26
Classes, SysUtils, FileUtil, LazHelpIntf, HelpIntfs, LazConfigStorage,
27
PropEdits, LHelpControl, Controls;
25
Classes, SysUtils, FileUtil, LazLogger, LazFileUtils, LazHelpIntf, HelpIntfs,
26
LazConfigStorage, PropEdits, LazIDEIntf, LHelpControl, Controls, UTF8Process,
27
ChmLangRef, ChmLcl, ChmProg;
36
36
fHelpLabel: String;
37
37
fHelpConnection: TLHelpConnection;
38
fChmsFilePath: String;
39
function GetHelpEXE: String;
40
function DBFindViewer(HelpDB: THelpDatabase; const MimeType: string;
41
var ErrMsg: string; out Viewer: THelpViewer): TShowHelpResult;
38
fCHMSearchPath: String;
39
fHelpExeParams: String;
40
function DBFindViewer({%H-}HelpDB: THelpDatabase; {%H-}const MimeType: string;
41
var {%H-}ErrMsg: string; out Viewer: THelpViewer): TShowHelpResult;
42
42
function GetHelpLabel: String;
43
procedure SetChmsFilePath(const AValue: String);
44
procedure SetHelpEXE(AValue: String);
44
46
function GetFileNameAndURL(RawUrl: String; out FileName: String; out URL: String): Boolean;
45
procedure SetHelpEXE(AValue: String);
46
47
procedure SetHelpLabel(AValue: String);
47
48
function CheckBuildLHelp: Integer; // modal result
48
49
function GetLazBuildEXE(out ALazBuild: String): Boolean;
59
60
procedure Load(Storage: TConfigStorage); override;
60
61
procedure Save(Storage: TConfigStorage); override;
61
62
function GetLocalizedName: string; override;
63
function GetHelpEXE: String; // macros resolved, see property HelpEXE
64
function GetHelpFilesPath: String; // macros resolved, see property HelpFilesPath
63
property HelpEXE: String read GetHelpEXE write SetHelpEXE;
66
property HelpEXE: String read fHelpEXE write SetHelpEXE; // with macros, see GetHelpEXE
64
67
property HelpLabel: String read GetHelpLabel write SetHelpLabel;
65
property HelpFilesPath: String read fChmsFilePath write fChmsFilePath;
68
property HelpFilesPath: String read fCHMSearchPath write SetChmsFilePath; // directories separated with semicolon, with macros, see GetHelpFilesPath
69
property HelpExeParams: String read fHelpExeParams write fHelpExeParams;
69
72
procedure Register;
72
76
uses Process, MacroIntf, InterfaceBase, Forms, Dialogs, HelpFPDoc, IDEMsgIntf;
74
function FixSlash(AStr: String): String;
81
'/': WrongSlash := '\';
82
'\': WrongSlash := '/';
86
FP := Pos(WrongSlash, Result);
88
Result[FP] := PathDelim;
90
// fix double path delim
92
FP := Pos(PathDelim+PathDelim, Result);
94
Delete(Result, FP, 1);
100
80
function TChmHelpViewer.DBFindViewer(HelpDB: THelpDatabase;
112
92
Result := fHelpLabel;
95
procedure TChmHelpViewer.SetChmsFilePath(const AValue: String);
99
if fCHMSearchPath = AValue then Exit;
100
fCHMSearchPath := AppendPathDelim(AValue);
102
if Assigned(LangRefHelpDatabase) then
103
LangRefHelpDatabase.LoadKeywordList(p);
104
if Assigned(FPCDirectivesHelpDatabase) then
105
FPCDirectivesHelpDatabase.CHMSearchPath := p;
108
procedure TChmHelpViewer.SetHelpEXE(AValue: String);
110
if fHelpEXE=AValue then Exit;
115
114
function TChmHelpViewer.GetHelpEXE: String;
117
if fHelpExe <> '' then
119
Result := '$(LazarusDir)/components/chmhelp/lhelp/lhelp$(ExeExt)';
118
Result := SetDirSeparators('$(LazarusDir)/components/chmhelp/lhelp/lhelp$(ExeExt)');
120
119
if not IDEMacros.SubstituteMacros(Result) then
122
Result := FixSlash(Result);
123
function TChmHelpViewer.GetHelpFilesPath: String;
125
Result:=fCHMSearchPath;
127
Result:='$(LazarusDir)/docs/html;$(LazarusDir)/docs/html/lcl;$(LazarusDir)/docs/chm';
128
IDEMacros.SubstituteMacros(Result);
129
Result:=MinimizeSearchPath(SetDirSeparators(Result));
125
132
function TChmHelpViewer.GetFileNameAndURL(RawUrl:String; out FileName: String; out URL: String
154
156
function TChmHelpViewer.CheckBuildLHelp: Integer;
157
159
Lazbuild: String;
158
160
LHelpProject: String;
160
162
LastWasEOL: Boolean;
163
164
Buffer: array[0..511] of char;
166
168
Result := mrCancel;
168
if FileExistsUTF8(HelpExe) = True then
170
if FileExistsUTF8(GetHelpExe) then
171
173
if not GetLazBuildEXE(Lazbuild) then
174
LHelpProject := FixSlash('$(LazarusDir)/components/chmhelp/lhelp/lhelp.lpi');
176
if not (IDEMacros.SubstituteMacros(LHelpProject)
177
and FileExistsUTF8(LHelpProject))
181
WS := ' --ws='+LCLPlatformDirNames[WidgetSet.LCLPlatform]+' ';
175
debugln(['TChmHelpViewer.CheckBuildLHelp failed because lazbuild not found']);
179
LHelpProject := '$(LazarusDir)/components/chmhelp/lhelp/lhelp.lpi';
180
if not IDEMacros.SubstituteMacros(LHelpProject) then exit;
181
LHelpProject:=TrimFilename(SetDirSeparators(LHelpProject));
182
if not FileExistsUTF8(LHelpProject) then
184
debugln(['TChmHelpViewer.CheckBuildLHelp failed because lhelp.lpi not found']);
188
WS := '--ws='+LCLPlatformDirNames[WidgetSet.LCLPlatform];
189
PCP := '--pcp='+LazarusIDE.GetPrimaryConfigPath;
183
191
//Result := MessageDlg('The help viewer is not compiled yet. Try to compile it now?', mtConfirmation, mbYesNo ,0);
184
192
//if Result <> mrYes then
187
Proc := TProcess.Create(nil);
188
Proc.CommandLine := Lazbuild + WS + LHelpProject;
195
Proc := TProcessUTF8.Create(nil);
196
{$if (fpc_version=2) and (fpc_release<5)}
197
Proc.CommandLine := Lazbuild+' '+WS+' '+PCP+' '+LHelpProject;
199
Proc.Executable := Lazbuild;
200
Proc.Parameters.Add(WS);
201
Proc.Parameters.Add(PCP);
202
Proc.Parameters.Add(LHelpProject);
189
204
Proc.Options := [poUsePipes, poStderrToOutPut];
205
debugln(['TChmHelpViewer.CheckBuildLHelp running "',Lazbuild,' ',WS,' ',PCP,' ',LHelpProject,'" ...']);
247
265
function TChmHelpViewer.GetLazBuildEXE(out ALazBuild: String): Boolean;
249
LazBuildMacro: String;
252
LazBuildMacro:= '$(LazarusDir)/$MakeExe(lazbuild)';
253
Result := IDEMacros.SubstituteMacros(LazBuildMacro)
254
and FileExistsUTF8(LazBuildMacro);
256
ALazBuild := FixSlash(LazBuildMacro);
268
ALazBuild:= '$(LazarusDir)/$MakeExe(lazbuild)';
269
if not IDEMacros.SubstituteMacros(ALazBuild) then exit;
270
ALazBuild:=TrimFilename(SetDirSeparators(ALazBuild));
271
Result:=FileExistsUTF8(ALazBuild);
259
274
function TChmHelpViewer.PassTheBuck(Node: THelpNode; var ErrMsg: string
346
364
Exit(shrDatabaseNotFound);
349
if HelpFilesPath = '' then
367
SearchPath := GetHelpFilesPath;
368
FoundFileName:=SearchFileInPath(Filename,'',SearchPath,';',[]);
369
debugln(['TChmHelpViewer.ShowNode Filename="',Filename,'" SearchPath="',SearchPath,'" Found="',FoundFileName,'"']);
371
if FoundFileName='' then
351
DocsDir := FixSlash('$(LazarusDir)/docs/html/');
352
IDEMacros.SubstituteMacros(DocsDir);
353
if not FileExistsUTF8(DocsDir+FileName) then
373
Result := shrDatabaseNotFound;
374
ErrMsg := FileName +' not found. Please put the chm help files in '+ LineEnding
375
+SearchPath+ LineEnding
376
+' or set the path to lcl.chm rtl.chm fcl.chm with "HelpFilesPath" in '
377
+' Environment Options -> Help -> Help Options ->'+LineEnding
378
+' under HelpViewers - CHMHelpViewer';
382
FileName := CleanAndExpandFilename(FoundFileName);
384
if ExtractFileNameOnly(GetHelpExe) = 'lhelp' then begin
385
fHelpConnection.StartHelpServer(HelpLabel, GetHelpExe);
386
Res := fHelpConnection.OpenURL(FileName, Url);
388
if Trim(fHelpExeParams) = '' then
355
Result := shrDatabaseNotFound;
356
ErrMsg := FileName +' not found. Please put the chm help files in '+ LineEnding
358
+' or set the path to lcl.chm rtl.chm fcl.chm with "HelpFilesPath" in '
359
+' Environment Options -> Help -> Help Options ->'+LineEnding
360
+' under HelpViewers - CHMHelpViewer';
390
Result := shrViewerError;
391
ErrMsg := 'If you do not use "lhelp" as viewer you have to setup '
392
+ 'HelpExeParams correctly in' + sLineBreak
393
+ 'Tools -> Options -> Help -> Help Options -> '
394
+ 'under HelpViewers - CHM Help Viewer' + sLineBreak
395
+ 'e.g. for HH.EXE (HTML Help in Windows) it must be' + sLineBreak
396
+ ' "%s::%s"' + sLineBreak
397
+ 'where first %s will be replaced by CHM file name' + sLineBreak
398
+ 'and the second one will be replaced by URL';
366
DocsDir := fChmsFilePath;
368
FileName := IncludeTrailingPathDelimiter(DocsDir)+FileName;
370
fHelpConnection.StartHelpServer(HelpLabel, HelpExe);
371
Res := fHelpConnection.OpenURL(FileName, Url);
401
Proc := TProcessUTF8.Create(nil);
403
{$if (fpc_version=2) and (fpc_release<5)}
404
Proc.CommandLine := GetHelpExe + ' ' + Format(fHelpExeParams, [FileName, Url]);
406
LHelpPath:=GetHelpEXE;
407
Proc.Executable := LHelpPath;
409
debugln(['TChmHelpViewer.ShowNode LHelpPath=',LHelpPath]);
410
if DirectoryExistsUTF8(LHelpPath+'.app') then
412
if DirectoryExistsUTF8(LHelpPath) then begin
413
// application bundle
414
// to put lhelp into the foreground, use "open -n lhelp.app --args args"
415
Proc.Executable := '/usr/bin/open';
416
Proc.Parameters.Add('-n');
417
Proc.Parameters.Add(LHelpPath);
418
Proc.Parameters.Add('--args');
419
Proc.Parameters.Add(Format(fHelpExeParams, [FileName, Url]));
422
Proc.Parameters.Add(Format(fHelpExeParams, [FileName, Url]));
424
debugln(['TChmHelpViewer.ShowNode Executable=',Proc.Executable,' Params="',dbgstr(Proc.Parameters.Text),'"']);
374
434
srSuccess: Result := shrSuccess;
420
482
ChmHelp := TChmHelpViewer.Create(nil);
421
483
HelpViewers.RegisterViewer(ChmHelp);
484
RegisterLangRefHelpDatabase;
485
LangRefHelpDatabase.OnFindViewer := @ChmHelp.DBFindViewer;
486
RegisterLclHelpDatabase;
487
LCLHelpDatabase.OnFindViewer := @ChmHelp.DBFindViewer;
488
RegisterFPCDirectivesHelpDatabase;
489
FPCDirectivesHelpDatabase.OnFindViewer := @ChmHelp.DBFindViewer;
425
493
RegisterPropertyEditor(TypeInfo(AnsiString),
426
TCHmHelpViewer,'HelpEXE',TFileNamePropertyEditor);
494
TChmHelpViewer,'HelpEXE',TFileNamePropertyEditor);
427
495
RegisterPropertyEditor(TypeInfo(AnsiString),
428
TCHmHelpViewer,'HelpFilesPath',TFileNamePropertyEditor);
496
TChmHelpViewer,'HelpFilesPath',TDirectoryPropertyEditor);