From 08eb6e34a97d86b6b22b91c69d265e3cdefa5a1d Mon Sep 17 00:00:00 2001 From: juha Date: Mon, 8 Feb 2021 20:53:44 +0000 Subject: [PATCH] LHelp: Revamp. Issue #38250, patch from Andrey Sobol. git-svn-id: trunk@64510 - --- components/chmhelp/lhelp/Makefile.fpc | 1 + .../chmhelp/lhelp/basecontentprovider.pas | 152 ++- .../chmhelp/lhelp/chmcontentprovider.pas | 874 +++++++++++------- components/chmhelp/lhelp/chmdataprovider.pas | 125 ++- components/chmhelp/lhelp/chmspecialparser.pas | 67 +- .../chmhelp/lhelp/filecontentprovider.pas | 60 +- .../chmhelp/lhelp/httpcontentprovider.pas | 33 +- .../chmhelp/lhelp/languages/lhelp.fi.po | 44 +- .../chmhelp/lhelp/languages/lhelp.fr.po | 44 +- .../chmhelp/lhelp/languages/lhelp.hu.po | 44 +- .../chmhelp/lhelp/languages/lhelp.lt.po | 44 +- .../chmhelp/lhelp/languages/lhelp.pl.po | 44 +- components/chmhelp/lhelp/languages/lhelp.pot | 42 +- .../chmhelp/lhelp/languages/lhelp.pt_BR.po | 44 +- .../chmhelp/lhelp/languages/lhelp.ru.po | 46 +- .../chmhelp/lhelp/languages/lhelp.uk.po | 44 +- .../chmhelp/lhelp/languages/lhelp.zh_CN.po | 44 +- components/chmhelp/lhelp/lhelp.lpi | 96 +- components/chmhelp/lhelp/lhelp.lpr | 5 +- components/chmhelp/lhelp/lhelpcore.lfm | 142 ++- components/chmhelp/lhelp/lhelpcore.pas | 540 +++++++---- components/chmhelp/lhelp/lhelpstrconsts.pas | 15 +- .../chmhelp/packages/help/lazhelpchm.pas | 9 +- .../chmhelp/packages/help/lhelpcontrol.pas | 4 +- .../chmhelp/packages/idehelp/lazchmhelp.pas | 2 +- 25 files changed, 1823 insertions(+), 742 deletions(-) diff --git a/components/chmhelp/lhelp/Makefile.fpc b/components/chmhelp/lhelp/Makefile.fpc index 00781e3330..6ae500b4a1 100644 --- a/components/chmhelp/lhelp/Makefile.fpc +++ b/components/chmhelp/lhelp/Makefile.fpc @@ -24,6 +24,7 @@ unitdir=. $(LAZDIR)/components/lazutils/lib/$(CPU_TARGET)-$(OS_TARGET) \ $(LAZDIR)/components/cairocanvas/lib/$(CPU_TARGET)-$(OS_TARGET)/$(LCL_PLATFORM) \ $(LAZDIR)/components/turbopower_ipro/units/$(CPU_TARGET)-$(OS_TARGET)/$(LCL_PLATFORM) \ $(LAZDIR)/components/printers/lib/$(CPU_TARGET)-$(OS_TARGET)/$(LCL_PLATFORM) \ + $(LAZDIR)/components/mouseandkeyinput/lib/$(CPU_TARGET)-$(OS_TARGET)/$(LCL_PLATFORM) \ ../packages/help/lib/$(CPU_TARGET)-$(OS_TARGET)/$(LCL_PLATFORM) targetdir=. diff --git a/components/chmhelp/lhelp/basecontentprovider.pas b/components/chmhelp/lhelp/basecontentprovider.pas index d068b59da8..425de27a26 100644 --- a/components/chmhelp/lhelp/basecontentprovider.pas +++ b/components/chmhelp/lhelp/basecontentprovider.pas @@ -5,7 +5,11 @@ unit BaseContentProvider; interface uses - Classes, SysUtils, Controls, Laz2_XMLCfg; + Classes, SysUtils, + // LCL + Controls, + // LazUtils + Laz2_XMLCfg, LazLoggerBase; type @@ -15,7 +19,8 @@ type TBaseContentProvider = class(TObject) private FOnTitleChange: TNotifyEvent; - fParent: TWinControl; + FOnContentComplete: TNotifyEvent; + FParent: TWinControl; FTitle: String; FConfig: TXMLConfig; FUpdateCount: Integer; @@ -23,37 +28,46 @@ type fImageList: TImageList; function GetTitle: String; virtual; procedure SetTitle(const AValue: String); virtual; - function IsUpdating: Boolean; + function isUpdate: Boolean; + function isUpdateLast: Boolean; public function CanGoBack: Boolean; virtual; abstract; function CanGoForward: Boolean; virtual; abstract; function GetHistory: TStrings; virtual; abstract; function LoadURL(const AURL: String; const AContext: THelpContext=-1): Boolean; virtual; abstract; + function HasLoadedData(const {%H-}AURL: String): Boolean; virtual; procedure GoHome; virtual; abstract; procedure GoBack; virtual; abstract; procedure GoForward; virtual; abstract; + procedure ActivateProvider; virtual; + procedure ActivateTOCControl; virtual; abstract; + procedure ActivateIndexControl; virtual; abstract; + procedure ActivateSearchControl; virtual; abstract; procedure BeginUpdate; virtual; procedure EndUpdate; virtual; procedure LoadPreferences(ACfg: TXMLConfig); virtual; procedure SavePreferences({%H-}ACfg: TXMLConfig); virtual; class function GetProperContentProvider(const AURL: String): TBaseContentProviderClass; virtual; abstract; - constructor Create(AParent: TWinControl; AImageList: TImageList); virtual; + constructor Create(AParent: TWinControl; AImageList: TImageList; AUpdateCount: Integer); virtual; destructor Destroy; override; property Parent: TWinControl read fParent; property Title: String read GetTitle write SetTitle; property OnTitleChange: TNotifyEvent read FOnTitleChange write FOnTitleChange; + property OnContentComplete: TNotifyEvent read FOnContentComplete write FOnContentComplete; end; - - + function GetUriPrefix( const AUri: String ):String; + function GetUrlFilePath ( const AUri: String ) : String; + function GetURIURL( const AURI: String): String; + function GetURIFileName( const AURI: String): String; + function GetUrlFile( const AUrl:String): String; + function GetUrlWoContext( const AUrl:String): String; // returns false if the protocol has already been registered - function RegisterContentProvider(const Protocol: String; ContentProvider: TBaseContentProviderClass): Boolean; - // example: RegisterContentProvider('chm://', TChmContentProvider); + function RegisterContentProviderClass(const Protocol: String; ContentProvider: TBaseContentProviderClass): Boolean; + // example: RegisterContentProvider('file://', TChmContentProvider); function GetContentProvider(const Protocol: String): TBaseContentProviderClass; - - // Result must be freed by caller function GetContentProviderList: TStringList; implementation @@ -61,12 +75,80 @@ implementation var ContentProviders: TStringList; -function RegisterContentProvider(const Protocol: String; +function GetUriPrefix ( const AUri: String ) : String; +var + fPos: Integer; +begin + Result := Trim(AUri); + fPos := Pos('://', Result); + if fPos >0 Then + Result := Copy(Result, 1, fPos+2); +end; + +function GetUrlFilePath ( const AUri: String ) : String; +var + fPos: Integer; +begin + Result := Copy(AUri,Length(GetUriPrefix(AUri))+1, Length(AUri)); + fPos := Pos('://', Result); + if fPos > 0 then + Result := Copy(Result, 1, fPos-1); + fPos := Pos('?', Result); + if fPos > 0 then + Result := Copy(Result, 1, fPos-1); +end; + +function GetURIFileName(Const AURI: String): String; +var + FileStart, + FileEnd: Integer; +begin + FileStart := Pos(':', AURI)+1; + FileEnd := Pos('::', AURI); + + Result := Copy(AURI, FileStart, FileEnd-FileStart); +end; + +function GetUrlFile(const AUrl: String): String; +var + fPos: Integer; +begin + Result := Copy(AUrl,Length(GetUriPrefix(AUrl)), Length(AUrl)); + fPos := Pos('://', Result); + if fPos > 0 then + Result := Copy(Result, fPos+3, Length(Result)) + else + Result:= ''; +end; + +function GetUrlWoContext(const AUrl: String): String; +var + fPos: Integer; +begin + Result:= AUrl; + fPos := Pos('?', Result); + if fPos > 0 then + Result := Copy(Result, 1, fPos-1); + fPos := Pos('#', Result); + if fPos > 0 then + Result := Copy(Result, 1, fPos-1); +end; + +function GetURIURL(Const AURI: String): String; +var + URLStart: Integer; +begin + URLStart := Pos('::', AURI) + 2; + Result := Copy(AURI, URLStart, Length(AURI)); +end; + +function RegisterContentProviderClass(const Protocol: String; ContentProvider: TBaseContentProviderClass): Boolean; begin Result := False; - if ContentProviders.IndexOf(Protocol) > -1 then exit; - ContentProviders.AddObject(Protocol, TObject(ContentProvider)); + if GetContentProviderList.IndexOf(Protocol) > -1 then exit; + GetContentProviderList.AddObject(Protocol, TObject(ContentProvider)); + Result := true; end; function GetContentProvider(const Protocol: String): TBaseContentProviderClass; @@ -74,20 +156,18 @@ var fIndex: Integer; begin Result := nil; - fIndex := ContentProviders.IndexOf(Protocol); + fIndex := GetContentProviderList.IndexOf(Protocol); if fIndex = -1 then Exit; - - Result := TBaseContentProviderClass(ContentProviders.Objects[fIndex]); + Result := TBaseContentProviderClass(GetContentProviderList.Objects[fIndex]); end; function GetContentProviderList: TStringList; begin - Result := TStringList.Create; - Result.AddStrings(ContentProviders); + if ContentProviders = nil then // Singleton + ContentProviders := TStringList.Create; + Result := ContentProviders; end; - - { TBaseContentProvider } function TBaseContentProvider.GetTitle: String; @@ -102,14 +182,32 @@ begin FOnTitleChange(Self); end; -function TBaseContentProvider.IsUpdating: Boolean; +function TBaseContentProvider.isUpdate: Boolean; begin Result := FUpdateCount <> 0; end; +function TBaseContentProvider.isUpdateLast: Boolean; +begin + Result := FUpdateCount <= 1; +end; + +function TBaseContentProvider.HasLoadedData ( const AURL: String ) : Boolean; +begin + Result:= false; +end; + +procedure TBaseContentProvider.ActivateProvider; +begin + // +end; + procedure TBaseContentProvider.BeginUpdate; begin Inc(FUpdateCount); + {$IFDEF UPDATE_CNT} + DebugLn('BeginUpdate() Cnt: ', IntToStr(FUpdateCount)); + {$ENDIF} end; procedure TBaseContentProvider.EndUpdate; @@ -117,6 +215,9 @@ begin Dec(FUpdateCount); if FUpdateCount < 0 then FUpdateCount:=0; + {$IFDEF UPDATE_CNT} + DebugLn('EndUpdate() Cnt: ', IntToStr(FUpdateCount)); + {$ENDIF} end; procedure TBaseContentProvider.LoadPreferences(ACfg: TXMLConfig); @@ -129,10 +230,12 @@ begin end; -constructor TBaseContentProvider.Create(AParent: TWinControl; AImageList: TImageList); +constructor TBaseContentProvider.Create(AParent: TWinControl; + AImageList: TImageList; AUpdateCount: Integer); begin - fParent:= AParent; - fImageList:= AImageList; + FParent:= AParent; + FImageList:= AImageList; + FUpdateCount:= AUpdateCount; end; destructor TBaseContentProvider.Destroy; @@ -142,7 +245,6 @@ begin end; initialization - ContentProviders := TStringList.Create; finalization diff --git a/components/chmhelp/lhelp/chmcontentprovider.pas b/components/chmhelp/lhelp/chmcontentprovider.pas index ada489f3fe..b612ee3ed4 100644 --- a/components/chmhelp/lhelp/chmcontentprovider.pas +++ b/components/chmhelp/lhelp/chmcontentprovider.pas @@ -1,10 +1,10 @@ -unit chmcontentprovider; - { Graphical CHM help content provider. Responsible for loading TOC, providing search etc. } +unit ChmContentProvider; + {$mode objfpc}{$H+} {$Note Compiling lhelp with search support} @@ -13,13 +13,11 @@ unit chmcontentprovider; {$IF FPC_FULLVERSION>=20400} {$Note Compiling lhelp *with* binary index and toc support} // CHMs can have both binary and text Table of Contents and index -{$DEFINE CHM_BINARY_INDEX_TOC} +{$DEFINE CHM_BINARY_INDEX_TOC} // internal chm index else external file`s indexes {$endif} - {off $DEFINE CHM_DEBUG_TIME} - interface uses @@ -27,27 +25,42 @@ uses // LCL LCLIntf, Forms, StdCtrls, ExtCtrls, ComCtrls, Controls, Menus, // LazUtils - LazFileUtils, LazUTF8, Laz2_XMLCfg, + LazFileUtils, LazUTF8, Laz2_XMLCfg, LazLoggerBase, + // Turbopower IPro + IpHtml, // ChmHelp - IpHtml, BaseContentProvider, FileContentProvider, ChmDataProvider, lhelpstrconsts; + BaseContentProvider, FileContentProvider, ChmDataProvider, lhelpstrconsts; const DefaultCHMContentTitle = '[unknown]'; type + TAsyncIndexData = record + CHMReader: TChmReader; + isUpdate: Boolean; + end; + PTAsyncIndexData = ^TAsyncIndexData; + + TAsyncUri = record + CHMReader: TChmReader; + Uri: String; + end; + PTAsyncUri = ^TAsyncUri; + { TChmContentProvider } TChmContentProvider = class(TFileContentProvider) private - fUpdateURI: String; + fUpdateURI: String; // last request + fLastURI: String; // last showed fTabsControl: TPageControl; fContentsTab: TTabSheet; fContentsPanel: TPanel; fContentsTree: TTreeView; fIndexTab: TTabSheet; fIndexEdit: TLabeledEdit; - fIndexView: TTreeView;//TListView; + fIndexView: TTreeView; fSearchTab: TTabSheet; fKeywordLabel: TLabel; fKeywordCombo: TComboBox; @@ -58,45 +71,52 @@ type fHtml: TIpHtmlPanel; fPopUp: TPopUpMenu; fStatusBar: TStatusBar; - fContext: THelpContext; + fFillTOCStack: TFPList; function GetShowStatusbar: Boolean; procedure SetShowStatusbar(AValue: Boolean); + procedure CompareIndexNodes(Sender: TObject; Node1, Node2: TTreeNode; + var Compare: Integer); + procedure ProcTreeKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); + procedure ProcKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); + procedure ProcTreeKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); protected fIsUsingHistory: Boolean; fChms: TChmFileList; + fChmDataProvider: TIpChmDataProvider; fHistory: TStringList; fHistoryIndex: Integer; fStopTimer: Boolean; - fFillingToc: Boolean; - fFillingIndex: Boolean; fActiveChmTitle: String; FLoadingSearchURL: Boolean; // use this to try to highlight search terms function MakeURI(Const AUrl: String; AChm: TChmReader): String; - procedure BeginUpdate; override; - procedure EndUpdate; override; procedure AddHistory(Const URL: String); procedure DoOpenChm(Const AFile: String; ACloseCurrent: Boolean = True); - procedure DoCloseChm; procedure DoLoadContext(Context: THelpContext); procedure DoLoadUri(Uri: String; AChm: TChmReader = nil); procedure DoError({%H-}Error: Integer); + function GetChmReader(Const AFile: String): TChmReader; procedure NewChmOpened(ChmFileList: TChmFileList; Index: Integer); - procedure LoadingHTMLStream(var AStream: TStream); - - // Queue TOC fill action for later processing + // Set to queue LoadUri processing + procedure QueueLoadUriAsync(Uri: String; AChm: TChmReader = nil); + // Set to queue a filling TOC Index for later processing procedure QueueFillToc(AChm: TChmReader); - // Fills table of contents (and index for main file) - procedure FillTOC(Data: PtrInt); + // Filling TOC and index for the chm file through Async process + procedure ProcFillTOC(AData: PtrInt); + // LoadURI through Async process + procedure ProcLoadUri(UriData: PtrInt); + procedure LoadingHTMLStream(var AStream: TStream); procedure IpHtmlPanelDocumentOpen(Sender: TObject); procedure IpHtmlPanelHotChange(Sender: TObject); + // text and image resource types procedure IpHtmlPanelHotClick(Sender: TObject); procedure PopupCopyClick(Sender: TObject); procedure PopupCopySourceClick(Sender: TObject); + procedure ContentsTreeSelectionChanged(Sender: TObject); - procedure IndexViewDblClick(Sender: TObject); procedure TreeViewStopCollapse(Sender: TObject; {%H-}Node: TTreeNode; var AllowCollapse: Boolean); + procedure TreeViewShowHint(Sender: TObject; HintInfo: PHintInfo); procedure ViewMenuContentsClick(Sender: TObject); procedure UpdateTitle; procedure SetTitle(const AValue: String); override; @@ -104,29 +124,38 @@ type procedure TOCExpand(Sender: TObject; Node: TTreeNode); procedure TOCCollapse(Sender: TObject; Node: TTreeNode); procedure SelectTreeItemFromURL(Const AUrl: String); + procedure GetTreeNodeClass(Sender: TCustomTreeView; var NodeClass: TTreeNodeClass); {$IFDEF CHM_SEARCH} procedure SearchButtonClick(Sender: TObject); - procedure SearchResultsDblClick(Sender: TObject); procedure SearchComboKeyDown(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState); - procedure GetTreeNodeClass(Sender: TCustomTreeView; var NodeClass: TTreeNodeClass); {$ENDIF} public + procedure ProcGlobalKeyUp(var {%H-}Key: Word; {%H-}Shift: TShiftState);overload; procedure LoadPreferences(ACfg: TXMLConfig); override; procedure SavePreferences(ACfg: TXMLConfig); override; - public + procedure BeginUpdate; override; + procedure EndUpdate; override; + function CanGoBack: Boolean; override; function CanGoForward: Boolean; override; function GetHistory: TStrings; override; function LoadURL(const AURL: String; const AContext: THelpContext=-1): Boolean; override; + function HasLoadedData(const AUrl: String): Boolean; override; procedure GoHome; override; procedure GoBack; override; procedure GoForward; override; + procedure ActivateProvider; override; + procedure ActivateTOCControl; override; + procedure ActivateIndexControl; override; + procedure ActivateSearchControl; override; + // property property TabsControl: TPageControl read fTabsControl; property Splitter: TSplitter read fSplitter; property ShowStatusbar: Boolean read GetShowStatusbar write SetShowStatusbar; + class function GetProperContentProvider(const {%H-}AURL: String): TBaseContentProviderClass; override; - constructor Create(AParent: TWinControl; AImageList: TImageList); override; + constructor Create(AParent: TWinControl; AImageList: TImageList; AUpdateCount: Integer); override; destructor Destroy; override; end; @@ -193,7 +222,9 @@ begin WordStart:= TDOMText(ATextNode).SplitText(fPos-1); After := WordStart.SplitText(Length(aword)); Span := doc.CreateElement('span'); - Span.SetAttribute('style', 'color:'+Color+';background-color:lightgray'); + // TODO: lHtml don`t perceive background color :( + Span.SetAttribute('style', DOMString('color:' + Color + + ';font-weight:bold;background:lightgray;padding:3px;')); Parent.InsertBefore(Span, After); Span.AppendChild(WordStart); @@ -222,25 +253,6 @@ begin end; -function GetURIFileName(Const AURI: String): String; -var - FileStart, - FileEnd: Integer; -begin - FileStart := Pos(':', AURI)+1; - FileEnd := Pos('::', AURI); - - Result := Copy(AURI, FileStart, FileEnd-FileStart); -end; - -function GetURIURL(Const AURI: String): String; -var - URLStart: Integer; -begin - URLStart := Pos('::', AURI) + 2; - Result := Copy(AURI, URLStart, Length(AURI)); -end; - function ChmURI(Const AUrl: String; Const AFileName: String): String; var FileNameNoPath: String; @@ -249,7 +261,6 @@ begin if Pos('ms-its:', Result) > 0 then Exit; FileNameNoPath := ExtractFileName(AFileName); - Result := 'ms-its:'+FileNameNoPath+'::'+AUrl; end; @@ -265,38 +276,102 @@ begin fStatusbar.Visible := AValue; end; -function TChmContentProvider.MakeURI (Const AUrl: String; AChm: TChmReader ) : String; +procedure TChmContentProvider.CompareIndexNodes(Sender: TObject; Node1, + Node2: TTreeNode; var Compare: Integer); +begin + Compare:= UTF8CompareStrCollated(LowerCase(Node1.Text), LowerCase(Node2.Text)); +end; + +procedure TChmContentProvider.ProcTreeKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + if Sender is TTreeView then + begin + if (Key = VK_RETURN) and (Shift = []) then + begin + ContentsTreeSelectionChanged(Sender); + key:= 0; + end + end; + if ((Sender is TTreeView) or (Sender is TIpHtmlPanel)) and (Shift = [ssAlt]) then + case Key of + VK_Left: begin + GoBack; key:= 0; + end; + VK_RIGHT: begin + GoForward; key:= 0; + end; + VK_Home: begin + GoHome; key:= 0; + end; + end; +end; + +procedure TChmContentProvider.ProcKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + if (Shift <> []) then Exit; + if (Sender is TLabeledEdit) and (Sender = fIndexEdit) then + begin + if ((Key = VK_DOWN) and ( fIndexView.Items.Count >0 )) then + begin + fIndexView.SetFocus(); + if (fIndexView.Selected = nil) then + begin + fIndexView.Items.GetFirstNode().MakeVisible; + fIndexView.Items.GetFirstNode().Selected:=True; + end; + Key:= 0; + end; + end; +end; + +procedure TChmContentProvider.ProcTreeKeyUp(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + if Sender is TTreeView then + begin + if ((Key = VK_DOWN) or (Key = VK_UP)) and (Shift = []) then + begin + ContentsTreeSelectionChanged(Sender); + Key:= 0; + end; + end; +end; + +function TChmContentProvider.MakeURI ( const AUrl: String; AChm: TChmReader + ) : String; var ChmIndex: Integer; begin ChmIndex := fChms.IndexOfObject(AChm); - Result := ChmURI(AUrl, fChms.FileName[ChmIndex]); end; procedure TChmContentProvider.BeginUpdate; begin + if not isUpdate then + begin + fContentsTree.BeginUpdate; + fIndexView.BeginUpdate; + end; inherited BeginUpdate; - fContentsTree.BeginUpdate; - fIndexView.BeginUpdate; end; procedure TChmContentProvider.EndUpdate; begin inherited EndUpdate; - fContentsTree.EndUpdate; - fIndexView.EndUpdate; - if not IsUpdating then + if not isUpdate then begin - if fUpdateURI <> '' then - DoLoadUri(fUpdateURI); - fUpdateURI:=''; - if Title=DefaultCHMContentTitle then - UpdateTitle; + fContentsTree.EndUpdate; + fIndexView.EndUpdate; + fContentsPanel.Caption := ''; + fContentsTree.Visible := True; + UpdateTitle; end; end; -procedure TChmContentProvider.AddHistory(Const URL: String); +procedure TChmContentProvider.AddHistory ( const URL: String ) ; begin if fHistoryIndex < fHistory.Count then begin @@ -308,63 +383,15 @@ begin Inc(fHistoryIndex); end; -type - TCHMHack = class(TChmFileList) - end; - -procedure TChmContentProvider.DoOpenChm(Const AFile: String; ACloseCurrent: Boolean = True); +procedure TChmContentProvider.DoOpenChm ( const AFile: String; + ACloseCurrent: Boolean ) ; begin - if (fChms <> nil) and fChms.IsAnOpenFile(AFile) then Exit; - if ACloseCurrent then DoCloseChm; - if not FileExistsUTF8(AFile) or DirectoryExistsUTF8(AFile) then - begin - Exit; - end; - if fChms = nil then - begin - try - fChms := TChmFileList.Create(Utf8ToSys(AFile)); - if Not(fChms.Chm[0].IsValidFile) then - begin - FreeAndNil(fChms); - //DoError(INVALID_FILE_TYPE); - Exit; - end; - TIpChmDataProvider(fHtml.DataProvider).Chm := fChms; - except - FreeAndNil(fChms); - //DoError(INVALID_FILE_TYPE); - Exit; - end; - end - else - begin - TCHMHack(fChms).OpenNewFile(AFile); - //WriteLn('Loading new chm: ', AFile); - end; - - if fChms = nil then Exit; - + fChmDataProvider.DoOpenChm(AFile, ACloseCurrent); + //DebugLn('CHP DoOpenChm() Chm file: ', AFile); fHistoryIndex := -1; fHistory.Clear; // Code here has been moved to the OpenFile handler - - UpdateTitle; -end; - -procedure TChmContentProvider.DoCloseChm; -var - i : integer; -begin - fStopTimer := True; - if assigned(fChms) then - begin - for i := 0 to fChms.Count -1 do - fChms.Chm[i].Free; - end; - FreeAndNil(fChms); - UpdateTitle; end; procedure TChmContentProvider.DoLoadContext(Context: THelpContext); @@ -376,6 +403,22 @@ begin if Str <> '' then DoLoadUri(Str, fChms.Chm[0]); end; +procedure TChmContentProvider.QueueLoadUriAsync(Uri: String; AChm: TChmReader = nil); +var + AUriData:PTAsyncUri; +begin + // https://www.freepascal.org/docs-html/rtl/system/initialize.html + {$IFDEF DEBUGASYNC} + DebugLn('CHP QueueLoadUriAsync() URI: ', Uri); + {$ENDIF} + GetMem(AUriData,SizeOf(TAsyncUri)); + Initialize(AUriData^); + AUriData^.CHMReader:= AChm; + AUriData^.Uri:= Uri; + Application.ProcessMessages; + Application.QueueAsyncCall(@ProcLoadUri, PtrInt(AUriData)); +end; + procedure TChmContentProvider.DoLoadUri(Uri: String; AChm: TChmReader = nil); var ChmIndex: Integer; @@ -388,7 +431,7 @@ var begin if (fChms = nil) and (AChm = nil) then exit; fStatusBar.SimpleText := Format(slhelp_Loading, [Uri]); - Application.ProcessMessages; + StartTime := Now; fPos := Pos('#', Uri); @@ -396,10 +439,15 @@ begin FilteredURL := Copy(Uri, 1, fPos -1) else FilteredURL := Uri; - + {$IFDEF LDEBUG} + DebugLn('CHP DoLoadUri() LastURI: '+ fLastURI); + {$ENDIF} if fChms.ObjectExists(FilteredURL, AChm) = 0 then begin fStatusBar.SimpleText := Format(slhelp_NotFound, [URI]); + {$IFDEF LDEBUG} + DebugLn('CHP ERR Chm object is not found - URI: '+ Uri); + {$ENDIF} Exit; end; if (Pos('ms-its', Uri) = 0) and (AChm <> nil) then @@ -409,13 +457,26 @@ begin NewUrl := 'ms-its:'+NewUrl+'::/'+Uri; Uri := NewUrl; end; + Application.ProcessMessages; + // Already showed - if not IsUpdating then + if fLastURI = Uri then Exit; + + if not isUpdate then begin fIsUsingHistory := True; + fChmDataProvider.CurrentPath := ExtractFileDir(URI)+'/'; + {$IFDEF LDEBUG} + DebugLn('CHP OpenURL URI: '+ Uri); + {$ENDIF} + fHtml.BeginUpdateBounds; + fLastURI:= ''; // TODO: for check it fHtml.OpenURL(Uri); - TIpChmDataProvider(fHtml.DataProvider).CurrentPath := ExtractFileDir(URI)+'/'; + fUpdateURI:= ''; + fHtml.EndUpdateBounds; + if Assigned(OnContentComplete) then + OnContentComplete(Self); AddHistory(Uri); EndTime := Now; @@ -424,11 +485,32 @@ begin fStatusBar.SimpleText := Format(slhelp_LoadedInMs, [Uri, Time]); end - else + else if isUpdateLast then begin - // We are updating. Save this to load at end of update. or if there is already a request overwrite it so only the last is loaded + // Do nothing, save URI and use Show for execute request fUpdateURI:= Uri; + // Used to async load URL before enable of Updating + // QueueLoadUriAsync(Uri, AChm); + {$IFDEF UPDATE_CNT} + DebugLn('Lastupdate URI: '+ Uri); + {$ENDIF} end; + +end; + +procedure TChmContentProvider.ProcLoadUri(UriData: PtrInt); +var + AUriData: PTAsyncUri; +begin + AUriData:= PTAsyncUri(UriData); + {$IFDEF DEBUGASYNC} + DebugLn('CHP ProcLoadUri() URI: ', AUriData^.Uri); + {$ENDIF} + fHtml.BeginUpdateBounds; + fHtml.OpenURL(AUriData^.Uri); + fHtml.EndUpdateBounds; + Finalize(AUriData^); + FreeMem(AUriData); end; @@ -438,27 +520,25 @@ begin //INVALID_FILE_TYPE; end; +function TChmContentProvider.GetChmReader ( const AFile: String ) : TChmReader; +var + FileIndex : Integer; +begin + Result := nil; + if fChms = nil then Exit; + FileIndex := fChms.IndexOf(AFile); + if (fChms <> nil) and (FileIndex >= 0) then + Result := fChms.Chm[fChms.IndexOf(AFile)]; +end; + procedure TChmContentProvider.NewChmOpened(ChmFileList: TChmFileList; Index: Integer); begin - if Index = 0 then - begin - if fContext > -1 then - begin - DoLoadContext(fContext); - fContext := -1; - end - else if ChmFileList.Chm[Index].DefaultPage <> '' then - begin - DoLoadUri(MakeURI(ChmFileList.Chm[Index].DefaultPage, ChmFileList.Chm[Index])); - end; - end; if ChmFileList.Chm[Index].Title = '' then ChmFileList.Chm[Index].Title := ExtractFileName(ChmFileList.FileName[Index]); // Fill the table of contents. - if Index <> 0 then - QueueFillToc(ChmFileList.Chm[Index]); + QueueFillToc(ChmFileList.Chm[Index]); end; procedure TChmContentProvider.LoadingHTMLStream(var AStream: TStream); @@ -510,87 +590,94 @@ begin end; procedure TChmContentProvider.QueueFillToc(AChm: TChmReader); +var + AData:PTAsyncIndexData; begin fContentsTree.Visible := False; fContentsPanel.Caption := slhelp_TableOfContentsLoadingPleaseWait; fStatusBar.SimpleText := slhelp_TableOfContentsLoading; + + AData:= New(PTAsyncIndexData); + AData^.CHMReader:= AChm; + AData^.isUpdate:= self.isUpdate; // save state for Async process + Application.ProcessMessages; - Application.QueueAsyncCall(@FillToc, PtrInt(AChm)); + Application.QueueAsyncCall(@ProcFillTOC, PtrInt(AData)); end; -procedure TChmContentProvider.FillTOC(Data: PtrInt); +procedure TChmContentProvider.ProcFillTOC(AData: PtrInt); var CHMReader: TChmReader; ParentNode: TTreeNode; i: Integer; + StackIdx: Integer; SM: TChmSiteMap; HasSearchIndex: Boolean = False; {$IFNDEF CHM_BINARY_INDEX_TOC} Stream: TMemoryStream; {$ENDIF} begin - if fFillingToc or fFillingIndex then - begin - Application.QueueAsyncCall(@FillToc, Data); - exit; - end; - fFillingToc := True; - fContentsTree.BeginUpdate; + SM := nil; + CHMReader := PTAsyncIndexData(AData)^.CHMReader; + try + BeginUpdate; + StackIdx := fFillTOCStack.IndexOf(CHMReader); + if StackIdx > 0 then Exit; - CHMReader := TChmReader(Data); - {$IFDEF CHM_DEBUG_TIME} - writeln('Start: ',FormatDateTime('hh:nn:ss.zzz', Now)); - {$ENDIF} - if CHMReader <> nil then - begin - ParentNode := fContentsTree.Items.AddChildObject(nil, CHMReader.Title, CHMReader); - ParentNode.ImageIndex := 0; - ParentNode.SelectedIndex := 0; - {$IFDEF CHM_BINARY_INDEX_TOC} - // GetTOCSitemap first tries binary TOC but falls back to text if needed - SM := CHMReader.GetTOCSitemap; - {$ELSE} - SM := nil; - fFillingIndex := True; - Stream := TMemoryStream(fchm.GetObject(fChm.TOCFile)); - if Stream <> nil then - begin - SM := TChmSiteMap.Create(stTOC); - SM.LoadFromStream(Stream); - Stream.Free; - end; + fFillTOCStack.Add(CHMReader); + {$IFDEF CHM_DEBUG_TIME} + DebugLn('CHT CHM Title: '+CHMReader.Title); + DebugLn('CHT Start of load: ',FormatDateTime('hh:nn:ss.zzz', Now)); {$ENDIF} - if SM <> nil then + if CHMReader <> nil then begin - {$IFDEF CHM_DEBUG_TIME} - writeln('Stream read: ',FormatDateTime('hh:nn:ss.zzz', Now)); + ParentNode := fContentsTree.Items.AddChildObject(nil, CHMReader.Title, CHMReader); + ParentNode.ImageIndex := 0; + ParentNode.SelectedIndex := 0; + {$IFDEF CHM_BINARY_INDEX_TOC} + // GetTOCSitemap first tries binary TOC but falls back to text if needed + {$IFDEF CHM_DEBUG_INDEX} + DebugLn('CHP GetTOCSitemap: ',FormatDateTime('hh:nn:ss.zzz', Now)); {$ENDIF} - with TContentsFiller.Create(fContentsTree, SM, @fStopTimer, CHMReader) do + {$IFDEF CHM_DEBUG_TIME} + DebugLn('CHT Load of TOC start: ',FormatDateTime('hh:nn:ss.zzz', Now)); + {$ENDIF} + SM := CHMReader.GetTOCSitemap; + {$ELSE} + SM := nil; + fFillingIndex := True; + Stream := TMemoryStream(fChms.GetObject(fChms.TOCFile)); + if Stream <> nil then begin - DoFill(ParentNode); - Free; + SM := TChmSiteMap.Create(stTOC); + SM.LoadFromStream(Stream); + Stream.Free; end; - SM.Free; - if (fContentsTree.Selected = nil) and (fHistory.Count > 0) then - SelectTreeItemFromURL(fHistory.Strings[fHistoryIndex]); - end; - if ParentNode.Index = 0 then ParentNode.Expanded := True; - fFillingToc := False; - fContentsTree.EndUpdate; - fContentsTree.Visible := True; - fContentsPanel.Caption := ''; - fContentsTab.TabVisible := fContentsTree.Items.Count > 1; - Application.ProcessMessages; - fFillingIndex := True; + {$ENDIF} + if SM <> nil then + begin + with TContentsFiller.Create(fContentsTree, SM, @fStopTimer, CHMReader) do + try + DoFill(ParentNode, false); + finally + Free; + end; + FreeAndNil(SM); + end; + if Assigned(ParentNode) and (ParentNode.Index = 0) then ParentNode.Expanded := True; + {$IFDEF CHM_DEBUG_TIME} + DebugLn('CHT Load of TOC end: ',FormatDateTime('hh:nn:ss.zzz', Now)); + {$ENDIF} - // we fill the index here too but only for the main file - if fChms.IndexOfObject(CHMReader) < 1 then - begin + // Now we fill the index for all files + {$IFDEF CHM_DEBUG_TIME} + DebugLn('CHT oad of INDEX start: ',FormatDateTime('hh:nn:ss.zzz', Now)); + {$ENDIF} {$IFDEF CHM_BINARY_INDEX_TOC} SM := CHMReader.GetIndexSitemap; {$ELSE} SM := nil; - Stream := TMemoryStream(fchm.GetObject(fChm.IndexFile)); + Stream := TMemoryStream(fChms.GetObject(fChms.IndexFile)); if Stream <> nil then begin SM := TChmSiteMap.Create(stTOC); @@ -601,46 +688,66 @@ begin if SM <> nil then begin fStatusBar.SimpleText := slhelp_IndexLoading; - Application.ProcessMessages; + {$IFDEF CHM_DEBUG_TIME} + DebugLn('CHT Load of INDEX start: ',FormatDateTime('hh:nn:ss.zzz', Now)); + {$ENDIF} with TContentsFiller.Create(fIndexView, SM, @fStopTimer, CHMReader) do - begin - DoFill(nil); + try + DoFill(nil, false); + if fChms.Count > 1 then // FpDoc have to sort an INDEX + fIndexView.Items.SortTopLevelNodes(@fIndexView.DefaultTreeViewSort); + finally Free; end; - SM.Free; + FreeAndNil(SM); + {$IFDEF CHM_DEBUG_TIME} + DebugLn('CHT Load of INDEX end: ',FormatDateTime('hh:nn:ss.zzz', Now)); + {$ENDIF} fIndexView.FullExpand; end; + {$IFDEF CHM_DEBUG_TIME} + DebugLn('CHT end of load: ',FormatDateTime('hh:nn:ss.zzz', Now)); + {$ENDIF} end; + + {$IFDEF CHM_DEBUG_TIME} + DebugLn('CHT CHM Title: '+CHMReader.Title); + DebugLn('CHT End: ',FormatDateTime('hh:nn:ss.zzz', Now)); + {$ENDIF} + + fContentsTab.TabVisible := fContentsTree.Items.Count > 0; + fIndexTab.TabVisible := fIndexTab.TabVisible or (fIndexView.Items.Count > 0); + fStatusBar.SimpleText:= ''; + + {$IFDEF CHM_SEARCH} + i := 0; + while (HasSearchIndex = False) and (i < fChms.Count) do + begin + // Look for binary full text search index in CHM file + HasSearchIndex := fChms.Chm[i].ObjectExists('/$FIftiMain') > 0; + inc(i); + end; + fSearchTab.TabVisible := fSearchTab.TabVisible or HasSearchIndex; + {$ENDIF} + + if Title=DefaultCHMContentTitle then + UpdateTitle; + fFillTOCStack.Remove(CHMReader); + finally + Dispose(PTAsyncIndexData(AData)); + EndUpdate; end; - fFillingIndex := False; - fIndexTab.TabVisible := fIndexView.Items.Count > 0; - - fStatusBar.SimpleText:= ''; - - {$IFDEF CHM_DEBUG_TIME} - writeln('End: ',FormatDateTime('hh:nn:ss.zzz', Now)); - {$ENDIF} - - {$IFDEF CHM_SEARCH} - i := 0; - while (HasSearchIndex = False) and (i < fChms.Count) do - begin - // Look for binary full text search index in CHM file - HasSearchIndex := fChms.Chm[i].ObjectExists('/$FIftiMain') > 0; - inc(i); - end; - - fSearchTab.TabVisible := HasSearchIndex; - {$ENDIF} end; procedure TChmContentProvider.IpHtmlPanelDocumentOpen(Sender: TObject); begin - // StatusBar1.Panels.Items[1] := fHtml.DataProvider.; - if fIsUsingHistory = False then - AddHistory(TIpChmDataProvider(fHtml.DataProvider).CurrentPage) - else fIsUsingHistory := False; - SelectTreeItemFromURL(TIpChmDataProvider(fHtml.DataProvider).CurrentPage); + if fIsUsingHistory = False then + AddHistory(fChmDataProvider.CurrentPage) + else + fIsUsingHistory := False; + fLastURI:= fChmDataProvider.CurrentPage; + SelectTreeItemFromURL(fLastURI); + // Debugln('CHP Ev IpHtmlPanelDocumentOpen() URL: '+fLastURI); end; procedure TChmContentProvider.IpHtmlPanelHotChange(Sender: TObject); @@ -672,8 +779,8 @@ begin if aPos>0 then HelpFile := Copy(fHtml.CurURL,1,aPos) + HelpFile; end; DoLoadUri(HelpFile); //open it in current iphtmlpanel. - end - else + end + else OpenURL(fHtml.HotURL); end; @@ -687,7 +794,7 @@ var rbs: rawbytestring; s: String; begin - rbs := TIpChmDataProvider(fHtml.DataProvider).GetHtmlText(fHtml.CurUrl); + rbs := fChmDataProvider.GetHtmlText(fHtml.CurUrl); s := ConvertEncoding(rbs, fHtml.MasterFrame.Html.DocCharset, encodingUTF8); Clipboard.SetAsHtml(rbs, s); end; @@ -697,54 +804,57 @@ var ATreeNode: TContentTreeNode; ARootNode: TTreeNode; fChm: TChmReader = nil; + ActiveTreeView: TTreeView; Uri: String; begin - if (fContentsTree.Selected = nil) then Exit; - if fContentsTree.Selected.Parent = nil then + // Check Active TreeView + ActiveTreeView:= nil; + if fTabsControl.ActivePage = fContentsTab then ActiveTreeView:= fContentsTree; + if fTabsControl.ActivePage = fIndexTab then ActiveTreeView:= fIndexView; + if fTabsControl.ActivePage = fSearchTab then ActiveTreeView:= fSearchResults; + + if not (Assigned(ActiveTreeView) and Assigned(ActiveTreeView.Selected)) then Exit; + // Load root pagefor TOC treeView + if (ActiveTreeView = fContentsTree) and (ActiveTreeView.Selected.Parent = nil) then begin - fChm := TChmReader(fContentsTree.Selected.Data); + fChm := TChmReader(ActiveTreeView.Selected.Data); fActiveChmTitle:= fChm.Title; - UpdateTitle; + //UpdateTitle; if fChm.DefaultPage <> '' then begin Uri := MakeURI(fChm.DefaultPage, fChm); +{$IFDEF TREE_DEBUG} + WriteLn('CHTR ContentTree changed1 URI: ', URI); +{$ENDIF} if ((fHtml.MasterFrame <> nil) and (MakeURI(fHtml.CurURL, fChm) = Uri)) = False then + begin + ActiveTreeView.Tag:=1; // status of request from treeview DoLoadUri(Uri); + ActiveTreeView.Tag:=0; + end; end; Exit; - end; - ATreeNode := TContentTreeNode(fContentsTree.Selected); - - //find the chm associated with this branch - ARootNode := ATreeNode.Parent; - while ARootNode.Parent <> nil do - ARootNode := ARootNode.Parent; + ATreeNode := TContentTreeNode(ActiveTreeView.Selected); + ArootNode:= ATreeNode; fChm := TChmReader(ARootNode.Data); - try - fContentsTree.OnSelectionChanged := nil; if ATreeNode.Url <> '' then begin Uri := MakeURI(ATreeNode.Url, fChm); +{$IFDEF TREE_DEBUG} + WriteLn('CHTR ContentTree changed1 URI: ', URI); +{$ENDIF} if ((fHtml.MasterFrame <> nil) and (MakeURI(fHtml.CurURL, fChm) = Uri)) = False then + begin + if ActiveTreeView = fSearchResults then FLoadingSearchURL:= True; + ActiveTreeView.Tag:=1; // status of request from treeview DoLoadUri(MakeURI(ATreeNode.Url, fChm)); + ActiveTreeView.Tag:=0; + if ActiveTreeView = fSearchResults then FLoadingSearchURL:= False; + end; end; - finally - fContentsTree.OnSelectionChanged := @ContentsTreeSelectionChanged; - end; -end; - -procedure TChmContentProvider.IndexViewDblClick(Sender: TObject); -var - ATreeNode: TContentTreeNode; -begin - if fIndexView.Selected = nil then Exit; - ATreeNode := TContentTreeNode(fIndexView.Selected); - - // Find the chm associated with this branch - DoLoadUri(MakeURI(ATreeNode.Url, TChmReader(ATreeNode.Data))); end; procedure TChmContentProvider.TreeViewStopCollapse(Sender: TObject; @@ -753,6 +863,19 @@ begin AllowCollapse:=False; end; +procedure TChmContentProvider.TreeViewShowHint ( Sender: TObject; + HintInfo: PHintInfo ) ; +var + Node: TContentTreeNode; +begin + if HintInfo^.HintControl is TTreeView then + begin + Node:= TContentTreeNode(TTreeView(HintInfo^.HintControl).Selected); + if Assigned(Node) and PtInRect(Node.DisplayRect(True), HintInfo^.CursorPos) then + HintInfo^.HintStr:= MakeURI(Node.Url, TChmReader(Node.Data)); + end; +end; + procedure TChmContentProvider.ViewMenuContentsClick(Sender: TObject); begin //TMenuItem(Sender).Checked := not TMenuItem(Sender).Checked; @@ -765,9 +888,11 @@ var Item: TTreeNode; NewTitle: String; begin - Item := fContentsTree.Items.GetFirstNode; + Item:=nil; + if fContentsTree.Items.Count > 0 then + Item := fContentsTree.Items.GetFirstNode; NewTitle := ''; - while Item <> nil do + while (Item <> nil) do begin if Item.Text <> fActiveChmTitle then begin @@ -789,7 +914,7 @@ end; procedure TChmContentProvider.SetTitle(const AValue: String); begin - if fHtml.Parent = nil then exit; + if (fHtml = nil) or (fHtml.Parent = nil) then exit; TTabSheet(fHtml.Parent).Caption := AValue; inherited SetTitle(AValue); end; @@ -812,11 +937,11 @@ begin fIndexView.Items.GetLastNode.MakeVisible; Node.MakeVisible; Node.Selected:=True; + //DebugLn('Search edit exit: %s', [SearchText]); Exit; end; Node := Node.GetNextSibling; end; - fIndexView.Selected:=nil; end; procedure TChmContentProvider.TOCExpand(Sender: TObject; Node: TTreeNode); @@ -837,7 +962,7 @@ begin end; end; -procedure TChmContentProvider.SelectTreeItemFromURL(Const AUrl: String); +procedure TChmContentProvider.SelectTreeItemFromURL ( const AUrl: String ) ; var FileName: String; URL: String; @@ -847,10 +972,18 @@ var TmpHolder: TNotifyEvent; i: integer; begin - if fContentsTree.OnSelectionChanged = nil then + RootNode:= nil; + if fContentsTree.Tag = 1 then Exit; // the change was a response to a click and should be ignored + {$IFDEF LDEBUG} + WriteLn('CHP >> SelectTreeItemFromURL()'); + DebugLn('Input AUrl: '+Aurl); + {$ENDIF} FileName := GetURIFileName(AUrl); URL := GetURIURL(AUrl); + {$IFDEF LDEBUG} + DebugLn('CHP Get Url: '+Url + ' Into filename: '+FileName); + {$ENDIF} FoundNode := nil; Node := nil; for i := 0 to fChms.Count-1 do @@ -858,18 +991,25 @@ begin if FileName = ExtractFileName(fChms.FileName[i]) then begin fActiveChmTitle:= fChms.Chm[i].Title; - UpdateTitle; + //UpdateTitle; RootNode := fContentsTree.Items.FindNodeWithData(fChms.Chm[i]); if URL = fChms.Chm[i].DefaultPage then begin FoundNode := RootNode; + {$IFDEF LDEBUG} + DebugLn('CHP RootNode: '+ RootNode.text); + {$ENDIF} Break; end; if RootNode <> nil then + begin Node := RootNode.GetFirstChild; - + {$IFDEF LDEBUG} + DebugLn('CHP RootNode Url : '+ TContentTreeNode(Node).Url); + {$ENDIF} + end; Break; end; @@ -878,17 +1018,25 @@ begin if RootNode = nil then Exit; - TmpHolder := fContentsTree.OnSelectionChanged; - fContentsTree.OnSelectionChanged := nil; - - while (Node<>nil) and (TContentTreeNode(Node).Url<>Url) do + TmpHolder := fContentsTree.OnClick; + fContentsTree.OnClick := nil; + // Todo: clear WoContext compare FIRST + while (Node<>nil) and (GetUrlWoContext(TContentTreeNode(Node).Url)<>GetUrlWoContext(Url)) do + begin Node:=Node.GetNext; - - if (Node <> nil) and (TContentTreeNode(Node).Url = Url) then + end; + // Todo: clear WoContext compare SECOND + if (Node <> nil) and (GetUrlWoContext(TContentTreeNode(Node).Url) = GetUrlWoContext(Url)) then + begin FoundNode := Node; + end; if FoundNode <> nil then begin + {$IFDEF LDEBUG} + DebugLn('CHP Found node: '+ FoundNode.Text); + DebugLn('CHP Found URL: '+ TContentTreeNode(FoundNode).Url); + {$ENDIF} fContentsTree.Selected := FoundNode; if not FoundNode.IsVisible then FoundNode.MakeVisible; @@ -896,17 +1044,10 @@ begin else fContentsTree.Selected := nil; - fContentsTree.OnSelectionChanged := TmpHolder; -end; - -{$IFDEF CHM_SEARCH} - -procedure TChmContentProvider.SearchComboKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); -begin - case key of - VK_RETURN: SearchButtonClick(nil); - - end; + fContentsTree.OnClick := TmpHolder; + {$IFDEF LDEBUG} + DebugLn('CHP << SelectTreeItemFromURL()'); + {$ENDIF} end; procedure TChmContentProvider.GetTreeNodeClass(Sender: TCustomTreeView; @@ -927,6 +1068,37 @@ begin ACfg.SetValue(ClassName+'/TabControlWidth/Value', fTabsControl.Width); end; +{$IFDEF CHM_SEARCH} + +procedure TChmContentProvider.SearchComboKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); +begin + if (Shift <> []) then Exit; + case key of + VK_RETURN: begin + SearchButtonClick(Sender); + Key:=0; + end; + VK_DOWN: + if fSearchResults.Items.Count > 0 then + begin + fSearchResults.SetFocus(); + if (fSearchResults.Selected = nil) then + begin + fSearchResults.Items.GetFirstNode().MakeVisible; + fSearchResults.Items.GetFirstNode().Selected:=True; + end; + Key:= 0; + end; + else // hide warning + end; +end; + +procedure TChmContentProvider.ProcGlobalKeyUp(var Key: Word; Shift: TShiftState + ); +begin + +end; + procedure TChmContentProvider.SearchButtonClick ( Sender: TObject ) ; type TTopicEntry = record @@ -943,7 +1115,7 @@ var var MoveSize: DWord; begin - //WriteLn('Deleting Topic'); + //DebugLn('Deleting Topic'); if ATopicIndex < High(FoundTopics) then begin MoveSize := SizeOf(TTopicEntry) * (High(FoundTopics) - (ATopicIndex+1)); @@ -968,7 +1140,7 @@ var var TopicIndex: Integer; begin - //WriteLn('Updating topic'); + //DebugLn('Updating topic'); TopicIndex := GetTopicIndex(TopicID); if TopicIndex = -1 then begin @@ -1008,7 +1180,7 @@ begin fKeywordCombo.Items.Add(fKeywordCombo.Text); fSearchResults.BeginUpdate; fSearchResults.Items.Clear; - //WriteLn('Search words: ', SearchWords.Text); + //DebugLn('Search words: ', SearchWords.Text); for i := 0 to fChms.Count-1 do begin for j := 0 to SearchWords.Count-1 do @@ -1061,11 +1233,12 @@ begin Item.Data:= fChms.Chm[i]; Item.Url:= DocURL; except - //WriteLn('Exception'); + //DebugLn('Exception'); // :) end; end; - + // Sort the result + fSearchResults.Items.SortTopLevelNodes(@fIndexView.DefaultTreeViewSort); SetLength(FoundTopics, 0); end; SetLength(FoundTopics, 0); @@ -1080,20 +1253,8 @@ begin fSearchResults.EndUpdate; end; -procedure TChmContentProvider.SearchResultsDblClick ( Sender: TObject ) ; -var - Item: TContentTreeNode; -begin - Item := TContentTreeNode(fSearchResults.Selected); - if (Item = nil) or (Item.Data = nil) then - Exit; - FLoadingSearchURL:= True; - DoLoadUri(MakeURI(Item.Url, TChmReader(Item.Data))); - FLoadingSearchURL:= False; -end; {$ENDIF} - function TChmContentProvider.CanGoBack: Boolean; begin Result := fHistoryIndex > 0; @@ -1113,36 +1274,22 @@ function TChmContentProvider.LoadURL(const AURL: String; const AContext: THelpCo var fFile: String; fURL: String = ''; - fPos: Integer; - FileIndex: Integer; - LoadTOC: Boolean; CurCHM: TChmReader; ContextURL: String; begin Result := False; - fFile := Copy(AUrl,8, Length(AURL)); - fPos := Pos('://', fFile); - if fPos > 0 then - begin - fURL := Copy(fFile, fPos+3, Length(fFIle)); - fFile := Copy(fFIle, 1, fPos-1); - end; + fFile := GetUrlFilePath(AUrl); + fURL := GetUrlFile(AUrl); - LoadTOC := (fChms = nil) or (fChms.IndexOf(fFile) < 0); - DoOpenChm(fFile, False); + fChmDataProvider.DoOpenChm(fFile, False); - // in case of exception fChms can be still = nil - if fChms <> nil then - FileIndex := fChms.IndexOf(fFile) - else - Exit; + fHistoryIndex := -1; + fHistory.Clear; - CurCHM := fChms.Chm[FileIndex]; + CurCHM := GetChmReader(fFile); + if CurCHM = nil then Exit; - if LoadTOC and (FileIndex = 0) then - begin - QueueFillToc(CurCHM); - end; + // Load TOC is executed by TChmContentProvider.NewChmOpened() now // AContext will override the URL if it is found if AContext <> -1 then @@ -1160,13 +1307,18 @@ begin DoLoadUri(MakeURI(CurCHM.DefaultPage, CurCHM)); Result := True; - fChms.OnOpenNewFile := @NewChmOpened; +end; + +function TChmContentProvider.HasLoadedData ( const AUrl: String ) : Boolean; +begin + Result:= (fChms <> nil) and fChms.IsAnOpenFile(GetUrlFilePath(AUrl)); end; procedure TChmContentProvider.GoHome; begin if (fChms <> nil) and (fChms.Chm[0].DefaultPage <> '') then begin + DebugLn('CHP GoHome() DefaultPage: ', fChms.Chm[0].DefaultPage); DoLoadUri(MakeURI(fChms.Chm[0].DefaultPage, fChms.Chm[0])); end; end; @@ -1195,19 +1347,58 @@ begin end; end; +procedure TChmContentProvider.ActivateProvider; +begin + //DebugLn('CHP FLastUri: '+fLastURI); + if (fChms.Count >0) and (fLastURI = '') then + GoHome; +end; + +procedure TChmContentProvider.ActivateTOCControl; +begin + if fContentsTab.TabVisible then + begin + fTabsControl.ActivePage:= fContentsTab; + if fContentsTree.Visible then + fContentsTree.SetFocus + else + fContentsTab.SetFocus; + end; +end; + +procedure TChmContentProvider.ActivateIndexControl; +begin + if fIndexTab.TabVisible then + begin + fTabsControl.ActivePage:= fIndexTab; + fIndexEdit.SetFocus; + end; +end; + +procedure TChmContentProvider.ActivateSearchControl; +begin + if fSearchTab.TabVisible then + begin + fTabsControl.ActivePage:= fSearchTab; + fKeywordCombo.SetFocus; + end; +end; + class function TChmContentProvider.GetProperContentProvider(const AURL: String ): TBaseContentProviderClass; begin Result:=TChmContentProvider; end; -constructor TChmContentProvider.Create(AParent: TWinControl; AImageList: TImageList); +constructor TChmContentProvider.Create(AParent: TWinControl; AImageList: TImageList; + AUpdateCount: Integer); const TAB_WIDTH = 215; begin - inherited Create(AParent, AImageList); + inherited Create(AParent, AImageList, AUpdateCount); fHistory := TStringList.Create; + fFillTOCStack := TFPList.Create; fTabsControl := TPageControl.Create(AParent); with fTabsControl do @@ -1223,7 +1414,6 @@ begin begin Caption := slhelp_Contents; Parent := fTabsControl; - //BorderSpacing.Around := 6; end; fContentsPanel := TPanel.Create(fContentsTab); with fContentsPanel do @@ -1242,10 +1432,14 @@ begin BorderSpacing.Around := 6; ReadOnly := True; Visible := True; - OnSelectionChanged := @ContentsTreeSelectionChanged; + ShowHint:=True; + OnShowHint:=@TreeViewShowHint; OnExpanded := @TOCExpand; OnCollapsed := @TOCCollapse; - OnCreateNodeClass:=@GetTreeNodeClass; + OnCreateNodeClass:= @GetTreeNodeClass; + OnClick:= @ContentsTreeSelectionChanged; + //OnKeyUp:= @ProcTreeKeyUp; + OnKeyDown:= @ProcTreeKeyDown; Images := fImageList; //StateImages := fImageList; end; @@ -1255,7 +1449,7 @@ begin begin Caption := slhelp_Index; Parent := fTabsControl; - //BorderSpacing.Around := 6; + TabVisible:= False; end; fIndexEdit := TLabeledEdit.Create(fIndexTab); @@ -1272,6 +1466,7 @@ begin EditLabel.AutoSize := True; LabelPosition := lpAbove; OnChange := @SearchEditChange; + OnKeyDown:= @ProcKeyDown; Visible := True; end; @@ -1294,18 +1489,23 @@ begin ShowButtons:=False; ShowLines:=False; ShowRoot:=False; + ShowHint:=True; + OnShowHint:=@TreeViewShowHint; OnCollapsing:=@TreeViewStopCollapse; - OnDblClick := @IndexViewDblClick; + OnClick:= @ContentsTreeSelectionChanged; + //OnKeyUp:= @ProcTreeKeyUp; + OnKeyDown:= @ProcTreeKeyDown; OnCreateNodeClass:=@GetTreeNodeClass; + OnCompare:=@CompareIndexNodes; end; - - // {$IFDEF CHM_SEARCH} + {$IFDEF CHM_SEARCH} fSearchTab := TTabSheet.Create(fTabsControl); with fSearchTab do begin Caption := slhelp_Search; Parent := fTabsControl; + TabVisible:= False; end; fKeywordLabel := TLabel.Create(fSearchTab); with fKeywordLabel do @@ -1373,26 +1573,34 @@ begin ShowButtons := False; ShowLines := False; ShowRoot:=False; - OnDblClick := @SearchResultsDblClick; + ShowHint:=True; + OnShowHint:=@TreeViewShowHint; + OnClick:= @ContentsTreeSelectionChanged; + OnKeyDown:= @ProcTreeKeyDown; OnCollapsing:=@TreeViewStopCollapse; OnCreateNodeClass:=@GetTreeNodeClass; + OnCompare:=@CompareIndexNodes; end; - // {$ENDIF} + {$ENDIF} - - fHtml := TIpHtmlPanel.Create(Parent); + fHtml := TIpHtmlPanel.Create(AParent); with fHtml do begin - DataProvider := TIpChmDataProvider.Create(fHtml, fChms); - TIpChmDataProvider(DataProvider).OnGetHtmlPage:=@LoadingHTMLStream; OnDocumentOpen := @IpHtmlPanelDocumentOpen; OnHotChange := @IpHtmlPanelHotChange; OnHotClick := @IpHtmlPanelHotClick; + //OnKeyDown:= @ProcTreeKeyDown; + DataProvider := TIpChmDataProvider.Create(fHtml); Parent := AParent; Align := alClient; end; - fSplitter := TSplitter.Create(Parent); + fChms:= TIpChmDataProvider(fHtml.DataProvider).Chms; // save only pointer for convenience + fChms.OnOpenNewFile:= @NewChmOpened; + fChmDataProvider:= TIpChmDataProvider(fHtml.DataProvider); // save only pointer for convenience + fChmDataProvider.OnGetHtmlPage:=@LoadingHTMLStream; + + fSplitter := TSplitter.Create(AParent); with fSplitter do begin //Align := alLeft; @@ -1404,7 +1612,6 @@ begin Parent := AParent; end; - fPopUp := TPopupMenu.Create(fHtml); fPopUp.Items.Add(TMenuItem.Create(fPopup)); with fPopUp.Items.Items[0] do @@ -1415,7 +1622,7 @@ begin fPopup.Items.Add(TMenuItem.Create(fPopup)); with fPopup.Items.Items[1] do begin - Caption := 'Copy source'; + Caption := slhelp_CopyHtmlSource; OnClick := @PopupCopySourceClick; end; fHtml.PopupMenu := fPopUp; @@ -1427,12 +1634,25 @@ begin Align := alBottom; SimplePanel := True; end; + + if isUpdate then + begin + fContentsTree.BeginUpdate; + fIndexView.BeginUpdate; + end; + end; destructor TChmContentProvider.Destroy; begin - DoCloseChm; + fChmDataProvider.DoCloseChms; fHistory.Free; + if fFillTOCStack.Count > 0 then + begin + Application.ProcessMessages; + Sleep(200); // waiting a stop of async TOC creating + end; + fFillTOCStack.Free; inherited Destroy; end; diff --git a/components/chmhelp/lhelp/chmdataprovider.pas b/components/chmhelp/lhelp/chmdataprovider.pas index 7f76f9f78a..ad4a07551b 100644 --- a/components/chmhelp/lhelp/chmdataprovider.pas +++ b/components/chmhelp/lhelp/chmdataprovider.pas @@ -14,36 +14,38 @@ unit ChmDataProvider; interface uses - Classes, SysUtils, IpHtml, iputils, IpMsg, Graphics, chmreader, - LCLType, Controls, - FPImage, - {$IF FPC_FULLVERSION>=20602} //fpreadgif exists since at least this version - FPReadgif, - {$ENDIF} - FPReadbmp, - FPReadxpm, - FPReadJPEG, - FPReadpng, - FPWritebmp, + Classes, SysUtils, chmreader, + FPImage, FPReadgif, FPReadbmp, FPReadxpm, FPReadJPEG, FPReadpng, FPWritebmp, FPWritePNG, - IntFGraphics, - lhelpstrconsts; - + // LCL + Graphics, LCLType, Controls, IntFGraphics, + // LazUtils + LazFileUtils, LazLoggerBase, + // Turbopower IPro + IpHtml, iputils, IpMsg, + // ChmHelp + LHelpStrConsts; type THelpPopupEvent = procedure(HelpFile: String; URL: String); THtmlPageLoadStreamEvent = procedure (var AStream: TStream) of object; + { TCHMFileListPublic } + + TCHMFileListPublic = class(TChmFileList) + end; + { TIpChmDataProvider } TIpChmDataProvider = class(TIpAbstractHtmlDataProvider) private - fChm: TChmFileList; + fChms: TCHMFileListPublic; fCurrentPage: String; fCurrentPath: String; FOnGetHtmlPage: THtmlPageLoadStreamEvent; fOnHelpPopup: THelpPopupEvent; + function GetChms: TChmFileList; function StripInPageLink(AURL: String): String; protected function DoGetHtmlStream(const URL: string; @@ -59,15 +61,16 @@ type function GetDirsParents(ADir: String): TStringList; function DoGetStream(const URL: string): TStream; override; public - constructor Create(AOwner: TComponent; AChm: TChmFileList); reintroduce; + constructor Create(AOwner: TComponent); override; destructor Destroy; override; function GetHtmlText(AURL: String): RawByteString; - property Chm: TChmFileList read fChm write fChm; + property Chms: TChmFileList read GetChms; + procedure DoOpenChm ( const AFile: String; ACloseCurrent: Boolean ); + procedure DoCloseChms; property OnHelpPopup: THelpPopupEvent read fOnHelpPopup write fOnHelpPopup; property CurrentPage: String read fCurrentPage; property CurrentPath: String read fCurrentPath write fCurrentPath; property OnGetHtmlPage: THtmlPageLoadStreamEvent read FOnGetHtmlPage write FOnGetHtmlPage; - end; implementation @@ -84,7 +87,12 @@ begin Result := Copy(Result, 1, i-1); end; -function TIpChmDataProvider.GetHtmlText(AURL: string): RawByteString; +function TIpChmDataProvider.GetChms: TChmFileList; +begin + Result:= fChms; +end; + +function TIpChmDataProvider.GetHtmlText ( AURL: String ) : RawByteString; var stream: TStream; ms: TMemoryStream; @@ -100,7 +108,7 @@ begin // --> buffer to memory stream ms := TMemoryStream.Create; try - ms.CopyFrom(stream, stream.Size); + ms.CopyFrom(stream, 0); SetLength(Result, ms.Size); Move(ms.Memory^, Result[1], ms.Size); finally @@ -112,20 +120,41 @@ begin end; end; +procedure TIpChmDataProvider.DoOpenChm ( const AFile: String; + ACloseCurrent: Boolean ) ; +begin + if fChms.IsAnOpenFile(AFile) then Exit; + if ACloseCurrent then DoCloseChms; + if not FileExistsUTF8(AFile) or DirectoryExistsUTF8(AFile) then + Exit; + TCHMFileListPublic(fChms).OpenNewFile(AFile); + // Code for Indexes has been moved to the OpenFile handler +end; + +procedure TIpChmDataProvider.DoCloseChms; +begin + if assigned(fChms) then + while Chms.Count > 0 do fChms.Delete(0); +end; + function TIpChmDataProvider.DoGetHtmlStream(const URL: string; PostData: TIpFormDataEntity): TStream; -var Tmp:string; +var + Msg:string; begin - Result := fChm.GetObject(StripInPageLink(URL)); + //WriteLn('DoGetHtmlStream() Url: ', URL); + Result := fChms.GetObject(StripInPageLink(URL)); // If for some reason we were not able to get the page return something so that // we don't cause an AV if Result = nil then begin Result := TMemoryStream.Create; - Tmp := '' + slhelp_PageCannotBeFound + ''; - Result.Write(Tmp,Length(tmp)); + Msg := '' + slhelp_PageCannotBeFound + ''; + Result.Write(Pointer(Msg)^, Length(Msg)); end; + Result.Position:= 0; if Assigned(FOnGetHtmlPage) then FOnGetHtmlPage(Result); + Result.Position:= 0; end; function TIpChmDataProvider.DoCheckURL(const URL: string; @@ -133,26 +162,27 @@ function TIpChmDataProvider.DoCheckURL(const URL: string; var Reader: TChmReader = nil; begin - //DebugLn('RequestedUrl: ',URL); - Result := fChm.ObjectExists(StripInPageLink(Url), Reader) > 0; + Result:= true; + //DebugLn('CD DoCheckURL() Url: ', URL); + Result := fChms.ObjectExists(StripInPageLink(Url), Reader) > 0; if Result then begin ContentType := 'text/html'; fCurrentPath := ExtractFilePath(Url); - Result := True; fCurrentPage := URL; + //DebugLn('CD checked url: ', URL); end; end; procedure TIpChmDataProvider.DoLeave(Html: TIpHtml); begin - // -// //DebugLn('Left: '); + // For free a data resources + //DebugLn('CD Left: '); end; procedure TIpChmDataProvider.DoReference(const URL: string); begin - // - ////DebugLn('Reference=',URL); + // For get all references from document + // DebugLn('CD Reference=',URL); end; procedure TIpChmDataProvider.DoGetImage(Sender: TIpHtmlNode; const URL: string; @@ -161,13 +191,11 @@ var Stream: TMemoryStream; FileExt: String; begin - //DebugLn('Getting Image ',(Url)); - Picture := nil; - + //DebugLn('CD Getting Image ',(Url)); FileExt := ExtractFileExt(URL); Picture := TPicture.Create; - Stream := fChm.GetObject('/'+URL); + Stream := fChms.GetObject('/'+URL); try if Assigned(Stream) then begin @@ -185,20 +213,19 @@ function TIpChmDataProvider.CanHandle(const URL: string): Boolean; var Reader: TChmReader = nil; begin - Result := True; + //DebugLn('CD CanHandle() Url: ', URL); + Result:=True; if Pos('Java', URL) = 1 then Result := False; - if (fChm.ObjectExists(StripInPageLink(url), Reader)= 0) and - (fChm.ObjectExists(StripInPageLink(BuildUrl(fCurrentPath,Url)), Reader) = 0) + // Here is opened the new chm file if required + if (fChms.ObjectExists(StripInPageLink(url), Reader)= 0) and + (fChms.ObjectExists(StripInPageLink(BuildUrl(fCurrentPath,Url)), Reader) = 0) then Result := False; - - //DebugLn('CanHandle ',Url,' = ', Result); - //if not Result then if fChm.ObjectExists(BuildURL('', URL)) > 0 Then result := true; - if (not Result) and (Pos('#', URL) = 1) then Result := True; + //DebugLn('CD CanHandle() ResultUrl: ', Result); end; function TIpChmDataProvider.BuildURL(const OldURL, NewURL: string): string; @@ -255,8 +282,8 @@ begin finally ParentDirs.Free; - //WriteLn('res = ', Result); end; + //DebugLn('CD BuildURL() Url: ', Result); end; function TIpChmDataProvider.GetDirsParents(ADir: String): TStringList; @@ -279,6 +306,7 @@ function TIpChmDataProvider.DoGetStream(const URL: string): TStream; var NewURL: String; begin + //DebugLn('CD DoGetStream() Url: ', URL); Result := nil; if Length(URL) = 0 then Exit; @@ -286,18 +314,21 @@ begin NewURL := BuildUrl(fCurrentPath,URL) else NewURL := URL; - - Result := fChm.GetObject(NewURL); + Result := fChms.GetObject(NewURL); + if Result <> nil then Result.Position:= 0; + //if Result = nil then DebugLn('CD Err DoGetStream URL: '+URL); end; -constructor TIpChmDataProvider.Create(AOwner: TComponent; AChm: TChmFileList); +constructor TIpChmDataProvider.Create ( AOwner: TComponent ) ; begin inherited Create(AOwner); - fChm := AChm; + fChms := TCHMFileListPublic.Create(''); end; destructor TIpChmDataProvider.Destroy; begin + DoCloseChms; + FreeAndnil(fChms); inherited Destroy; end; diff --git a/components/chmhelp/lhelp/chmspecialparser.pas b/components/chmhelp/lhelp/chmspecialparser.pas index 14013f1c74..dc2388190b 100644 --- a/components/chmhelp/lhelp/chmspecialparser.pas +++ b/components/chmhelp/lhelp/chmspecialparser.pas @@ -42,10 +42,11 @@ type fBranchCount: DWord; fStop: PBoolean; fLastNode: TTreeNode; - procedure AddItem(AItem: TChmSiteMapItem; AParentNode: TTreeNode); + procedure AddSiteMapItem(AItem: TChmSiteMapItem; AParentNode: TTreeNode; ANextNode: TTreeNode); public constructor Create(ATreeView: TTreeView; ASitemap: TChmSiteMap; StopBoolean: PBoolean; AChm: TObject); - procedure DoFill(ParentNode: TTreeNode); + destructor Destroy; override; + procedure DoFill(ParentNode: TTreeNode; ASortRoot: Boolean); end; implementation @@ -87,7 +88,7 @@ begin else begin // ';' was found, this may be an HTML entity like "&xxx;". AmpStr := Copy(AText, AmpPos+1, i-AmpPos-1); - ws := UTF8Encode(AmpStr); + ws := UTF8ToUTF16(UTF8Encode(AmpStr)); if ResolveHTMLEntityReference(ws, Entity) then Result := Result + UnicodeToUTF8(cardinal(Entity)) else @@ -120,7 +121,8 @@ end; { TContentsFiller } -procedure TContentsFiller.AddItem(AItem: TChmSiteMapItem; AParentNode: TTreeNode); +procedure TContentsFiller.AddSiteMapItem(AItem: TChmSiteMapItem; + AParentNode: TTreeNode; ANextNode: TTreeNode); var NewNode: TContentTreeNode; X: Integer; @@ -135,7 +137,10 @@ begin begin // Add new child node fLastNode := AParentNode; - NewNode := TContentTreeNode(fTreeView.Items.AddChild(AParentNode, txt)); + if Assigned(ANextNode) then + NewNode := TContentTreeNode(fTreeView.Items.Insert(ANextNode, txt)) + else + NewNode := TContentTreeNode(fTreeView.Items.AddChild(AParentNode, txt)); {$IF FPC_FULLVERSION>=30200} URL:=''; for x:=0 to AItem.SubItemcount-1 do @@ -173,7 +178,7 @@ begin Application.ProcessMessages; for X := 0 to AItem.Children.Count-1 do - AddItem(AItem.Children.Item[X], NewNode); + AddSiteMapItem(AItem.Children.Item[X], NewNode, nil); end; constructor TContentsFiller.Create(ATreeView: TTreeView; ASitemap: TChmSiteMap; StopBoolean: PBoolean; AChm: TObject); @@ -185,15 +190,53 @@ begin fChm := AChm; end; -procedure TContentsFiller.DoFill(ParentNode: TTreeNode); +destructor TContentsFiller.Destroy; +begin + inherited Destroy; +end; + +procedure TContentsFiller.DoFill(ParentNode: TTreeNode; ASortRoot: Boolean); var - X: Integer; + IdxSm, IdxSrc: Integer; begin fTreeView.BeginUpdate; - - for X := 0 to fSitemap.Items.Count-1 do - AddItem(fSitemap.Items.Item[X], ParentNode); - + fTreeView.Enabled:= False; + if ASortRoot and (fTreeView.Items.Count > 0) and not Assigned(ParentNode) then + begin; + // merge sorted TreeNodes + IdxSrc:=0; + IdxSm:=0; + while (IdxSrc <> fTreeView.Items.TopLvlCount-1 ) and (IdxSm <> fSitemap.Items.Count-1) do + begin + if (UTF8CompareStrCollated( + LowerCase(fSitemap.Items.Item[IdxSm].Text), + LowerCase(fTreeView.Items.TopLvlItems[IdxSrc].Text)) <= 0) then + begin + // insert sitemap before fTreeView Node + AddSiteMapItem(fSitemap.Items.Item[IdxSm], ParentNode, fTreeView.Items.TopLvlItems[IdxSrc]); + if IdxSm < fSitemap.Items.Count-1 then + Inc(IdxSm); + end + else + begin + if IdxSrc < fTreeView.Items.TopLvlCount-1 then + Inc(IdxSrc) + end; + // Add a rest of nodes from sitemap + if (IdxSrc = fTreeView.Items.TopLvlCount-1) then + begin + AddSiteMapItem(fSitemap.Items.Item[IdxSm], ParentNode, ParentNode); + Inc(IdxSm); + end; + end; + end + else + begin + // Simple add of nodes + for IdxSm := 0 to fSitemap.Items.Count-1 do + AddSiteMapItem(fSitemap.Items.Item[IdxSm], ParentNode, nil); + end; + fTreeView.Enabled:= True; fTreeView.EndUpdate; end; diff --git a/components/chmhelp/lhelp/filecontentprovider.pas b/components/chmhelp/lhelp/filecontentprovider.pas index 1c5f28d6c0..2fcb9dba32 100644 --- a/components/chmhelp/lhelp/filecontentprovider.pas +++ b/components/chmhelp/lhelp/filecontentprovider.pas @@ -10,6 +10,7 @@ uses type { TFileContentProvider } + TFileContentProviderClass = Class of TFileContentProvider; TFileContentProvider = class(TBaseContentProvider) private @@ -23,22 +24,42 @@ type procedure GoBack; override; procedure GoForward; override; class function GetProperContentProvider(const AURL: String): TBaseContentProviderClass; override; + class function GetRegisteredFileTypes(): TStringList; - constructor Create(AParent: TWinControl; AImageList: TImageList); override; + constructor Create(AParent: TWinControl; AImageList: TImageList; AUpdateCount: Integer); override; end; - function RegisterFileType(const FileType: String; ContentProvider: TBaseContentProviderClass): Boolean; - + + function RegisterFileType(const AFileType: String; ContentProvider: TBaseContentProviderClass): Boolean; + implementation var FileContentProviders: TStringList; -function RegisterFileType(const FileType: String; +function RegisteredFileTypes( ) : TStringList; +begin + if FileContentProviders = nil Then // Singleton + FileContentProviders := TStringList.Create; + Result := FileContentProviders; +end; + +function RegisterFileType(const AFileType: String; ContentProvider: TBaseContentProviderClass): Boolean; begin Result := False; - if FileContentProviders.IndexOf(FileType) > -1 then exit; - FileContentProviders.AddObject(FileType, TObject(ContentProvider)); + if RegisteredFileTypes.IndexOf(AFileType) > -1 then Exit; + RegisteredFileTypes.AddObject(AFileType, TObject(ContentProvider)); +end; + +function GetRegisteredFileType ( + const AProviderClass: TBaseContentProviderClass ) : String; +var + fIndex: Integer; +begin + Result := ''; + fIndex := RegisteredFileTypes.IndexOfObject(TObject(AProviderClass)); + if fIndex = -1 then Exit; + Result := RegisteredFileTypes[fIndex]; end; { TFileContentProvider } @@ -80,33 +101,30 @@ class function TFileContentProvider.GetProperContentProvider(const AURL: String var fIndex: Integer; fExt: String; - fFile: String; - fPos: Integer; begin Result := nil; - fFile := Copy(AUrl,8, Length(AURL)); - fPos := Pos('://', fFile); - if fPos > 0 then begin - fFile := Copy(fFIle, 1, fPos-1); - - end; - fExt := ExtractFileExt(fFile); + fExt := ExtractFileExt(GetUrlFilePath(AURL)); //WriteLn(fExt); - fIndex := FileContentProviders.IndexOf(fExt); + fIndex := RegisteredFileTypes.IndexOf(fExt); if fIndex = -1 then exit; - Result := TBaseContentProviderClass(FileContentProviders.Objects[fIndex]); + Result := TBaseContentProviderClass(RegisteredFileTypes.Objects[fIndex]); end; -constructor TFileContentProvider.Create(AParent: TWinControl; AImageList: TImageList); +class function TFileContentProvider.GetRegisteredFileTypes ( ) : TStringList; begin - inherited Create(AParent, AImageList); + Result:=RegisteredFileTypes(); +end; + +constructor TFileContentProvider.Create(AParent: TWinControl; + AImageList: TImageList; AUpdateCount: Integer); +begin + inherited Create(AParent, AImageList, AUpdateCount); end; initialization - FileContentProviders := TStringList.Create; - RegisterContentProvider('file://', TFileContentProvider); + RegisterContentProviderClass('file://', TFileContentProvider); finalization diff --git a/components/chmhelp/lhelp/httpcontentprovider.pas b/components/chmhelp/lhelp/httpcontentprovider.pas index 3a1d572663..2dca06ccc3 100644 --- a/components/chmhelp/lhelp/httpcontentprovider.pas +++ b/components/chmhelp/lhelp/httpcontentprovider.pas @@ -30,8 +30,11 @@ type procedure GoHome; override; procedure GoBack; override; procedure GoForward; override; + procedure ActivateTOCControl; override; + procedure ActivateIndexControl; override; + procedure ActivateSearchControl; override; class function GetProperContentProvider(const AURL: String): TBaseContentProviderClass; override; - constructor Create(AParent: TWinControl; AImageList: TImageList); override; + constructor Create(AParent: TWinControl; AImageList: TImageList; AUpdateCount:Integer); override; end; implementation @@ -98,15 +101,37 @@ begin fHtml.GoForward; end; +procedure THTTPContentProvider.ActivateTOCControl; +begin + // +end; + +procedure THTTPContentProvider.ActivateIndexControl; +begin + // +end; + +procedure THTTPContentProvider.ActivateSearchControl; +begin + // +end; + +procedure THTTPContentProvider.ProcGlobalKeyUp(var Key: Word; Shift: TShiftState + ); +begin + // +end; + class function THTTPContentProvider.GetProperContentProvider(const AURL: String ): TBaseContentProviderClass; begin Result := THTTPContentProvider; end; -constructor THTTPContentProvider.Create(AParent: TWinControl; AImageList: TImageList); +constructor THTTPContentProvider.Create(AParent: TWinControl; AImageList: TImageList; + AUpdateCount: Integer); begin - inherited Create(AParent, AImageList); + inherited Create(AParent, AImageList, ); fPopUp := TPopupMenu.Create(fHtml); fPopUp.Items.Add(TMenuItem.Create(fPopup)); with fPopUp.Items.Items[0] do begin @@ -118,7 +143,7 @@ begin fHtml := TIpHtmlPanel.Create(Parent); with fHtml do begin DataProvider := fHttpDataProvider; - //OnDocumentOpen := @IpHtmlPanelDocumentOpen; + OnDocumentOpen := @IpHtmlPanelDocumentOpen; OnHotChange := @IpHtmlPanelHotChange; PopupMenu := fPopUp; Parent := AParent; diff --git a/components/chmhelp/lhelp/languages/lhelp.fi.po b/components/chmhelp/lhelp/languages/lhelp.fi.po index 2bcb5e396a..9f74d16ce3 100644 --- a/components/chmhelp/lhelp/languages/lhelp.fi.po +++ b/components/chmhelp/lhelp/languages/lhelp.fi.po @@ -9,6 +9,34 @@ msgstr "Tietoja" msgid "&About ..." msgstr "Tietoja..." +#: lhelpstrconsts.slhelp_actions +msgid "&Actions" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoback +msgid "Go back" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoforward +msgid "Go forward" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgohome +msgid "Go home" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsindex +msgid "Search by &index" +msgstr "" + +#: lhelpstrconsts.slhelp_actionssearch +msgid "&Search by text" +msgstr "" + +#: lhelpstrconsts.slhelp_actionstoc +msgid "&TOC" +msgstr "" + #: lhelpstrconsts.slhelp_cannothandlethistypeofcontentforurl #, object-pascal-format msgid "Cannot handle this type of content. \"%s\" for url:%s%s" @@ -23,6 +51,10 @@ msgstr "Ei pysty hallitsemaan tämän tyyppistä sisältöä. \"%s\" url:%s%s" msgid "&Close" msgstr "&Sulje" +#: lhelpstrconsts.slhelp_closeconfirm +msgid "You can use the Esc to hide Help. Are you realy want to close lHelp?" +msgstr "" + #: lhelpstrconsts.slhelp_contents msgid "Contents" msgstr "Sisältö" @@ -35,6 +67,10 @@ msgstr " --context : Näytä tähän sisältöön liittyvät avusteet" msgid "Copy" msgstr "Kopio" +#: lhelpstrconsts.slhelp_copyhtmlsource +msgid "Copy html source" +msgstr "" + #: lhelpstrconsts.slhelp_exit msgid "E&xit" msgstr "&Poistu" @@ -59,6 +95,10 @@ msgstr "Avuste tiedostot (*.chm)|*.chm|Kaikki tiedostot (*.*)|*" msgid " --help : Show this information" msgstr " --help : Näytä tämä avuste" +#: lhelpstrconsts.slhelp_hide +msgid "&Hide" +msgstr "" + #: lhelpstrconsts.slhelp_hidestarthiddenbutacceptcommunicationsviaipc msgid " --hide : Start hidden but accept communications via IPC" msgstr " --hide : Käynnistä piilotettuna mutta salli yhteys IPC:n kautta" @@ -167,8 +207,8 @@ msgstr "Näytä sisältö" #: lhelpstrconsts.slhelp_supportedurltypes #, object-pascal-format -msgid "Supported URL type(s): (%s)" -msgstr "Tuetut URL tyyppi(/tyypit): (%s)" +msgid "Supported URL type(s): [ %s ]" +msgstr "Tuetut URL tyyppi(/tyypit): [ %s ]" #: lhelpstrconsts.slhelp_tableofcontentsloading msgid "Table of Contents Loading ..." diff --git a/components/chmhelp/lhelp/languages/lhelp.fr.po b/components/chmhelp/lhelp/languages/lhelp.fr.po index 5c93e4af31..4ba1a42f01 100644 --- a/components/chmhelp/lhelp/languages/lhelp.fr.po +++ b/components/chmhelp/lhelp/languages/lhelp.fr.po @@ -19,6 +19,34 @@ msgstr "À propos" msgid "&About ..." msgstr "&À propos..." +#: lhelpstrconsts.slhelp_actions +msgid "&Actions" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoback +msgid "Go back" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoforward +msgid "Go forward" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgohome +msgid "Go home" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsindex +msgid "Search by &index" +msgstr "" + +#: lhelpstrconsts.slhelp_actionssearch +msgid "&Search by text" +msgstr "" + +#: lhelpstrconsts.slhelp_actionstoc +msgid "&TOC" +msgstr "" + #: lhelpstrconsts.slhelp_cannothandlethistypeofcontentforurl #, object-pascal-format msgid "Cannot handle this type of content. \"%s\" for url:%s%s" @@ -33,6 +61,10 @@ msgstr "Impossible de prendre en charge ce type de contenu. \"%s\" pour l'URL :% msgid "&Close" msgstr "&Fermer" +#: lhelpstrconsts.slhelp_closeconfirm +msgid "You can use the Esc to hide Help. Are you realy want to close lHelp?" +msgstr "" + #: lhelpstrconsts.slhelp_contents msgid "Contents" msgstr "Contenu" @@ -45,6 +77,10 @@ msgstr " --context : Afficher l'information d'aide relative au contexte" msgid "Copy" msgstr "Copier" +#: lhelpstrconsts.slhelp_copyhtmlsource +msgid "Copy html source" +msgstr "" + #: lhelpstrconsts.slhelp_exit msgid "E&xit" msgstr "Q&uitter" @@ -69,6 +105,10 @@ msgstr "Fichiers d'aide (*.chm) | *. chm| Tous les fichiers (*. *) | *" msgid " --help : Show this information" msgstr " --help : Afficher cette information" +#: lhelpstrconsts.slhelp_hide +msgid "&Hide" +msgstr "" + #: lhelpstrconsts.slhelp_hidestarthiddenbutacceptcommunicationsviaipc msgid " --hide : Start hidden but accept communications via IPC" msgstr " --hide : Démarrer en mode caché mais accepter les communications via IPC" @@ -177,8 +217,8 @@ msgstr "Afficher le contenu" #: lhelpstrconsts.slhelp_supportedurltypes #, object-pascal-format -msgid "Supported URL type(s): (%s)" -msgstr "Type(s) d'URL pris en charge : (%s)" +msgid "Supported URL type(s): [ %s ]" +msgstr "Type(s) d'URL pris en charge : [ %s ]" #: lhelpstrconsts.slhelp_tableofcontentsloading msgid "Table of Contents Loading ..." diff --git a/components/chmhelp/lhelp/languages/lhelp.hu.po b/components/chmhelp/lhelp/languages/lhelp.hu.po index aa144c4145..f9c833649b 100644 --- a/components/chmhelp/lhelp/languages/lhelp.hu.po +++ b/components/chmhelp/lhelp/languages/lhelp.hu.po @@ -19,6 +19,34 @@ msgstr "Névjegy" msgid "&About ..." msgstr "&Névjegy ..." +#: lhelpstrconsts.slhelp_actions +msgid "&Actions" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoback +msgid "Go back" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoforward +msgid "Go forward" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgohome +msgid "Go home" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsindex +msgid "Search by &index" +msgstr "" + +#: lhelpstrconsts.slhelp_actionssearch +msgid "&Search by text" +msgstr "" + +#: lhelpstrconsts.slhelp_actionstoc +msgid "&TOC" +msgstr "" + #: lhelpstrconsts.slhelp_cannothandlethistypeofcontentforurl #, object-pascal-format msgid "Cannot handle this type of content. \"%s\" for url:%s%s" @@ -33,6 +61,10 @@ msgstr "Nem kezelhetők az ilyen típusú altartalmak. \"%s\" a következő url- msgid "&Close" msgstr "Be&zárás" +#: lhelpstrconsts.slhelp_closeconfirm +msgid "You can use the Esc to hide Help. Are you realy want to close lHelp?" +msgstr "" + #: lhelpstrconsts.slhelp_contents msgid "Contents" msgstr "Tartalom" @@ -45,6 +77,10 @@ msgstr " --context : Megjeleníti az azonosítóhoz tartozó súgót" msgid "Copy" msgstr "Másolás" +#: lhelpstrconsts.slhelp_copyhtmlsource +msgid "Copy html source" +msgstr "" + #: lhelpstrconsts.slhelp_exit msgid "E&xit" msgstr "Kilé&pés" @@ -69,6 +105,10 @@ msgstr "Súgó fájlok (*.chm)|*.chm|Minden fájl (*.*)|*" msgid " --help : Show this information" msgstr " --help : Megjeleníti ezt a súgót" +#: lhelpstrconsts.slhelp_hide +msgid "&Hide" +msgstr "" + #: lhelpstrconsts.slhelp_hidestarthiddenbutacceptcommunicationsviaipc msgid " --hide : Start hidden but accept communications via IPC" msgstr " --hide : Rejtve indul, de fogadja az IPC kéréseket" @@ -177,8 +217,8 @@ msgstr "Tartalom megjelenítése" #: lhelpstrconsts.slhelp_supportedurltypes #, object-pascal-format -msgid "Supported URL type(s): (%s)" -msgstr "Támogatott URL típus(ok): (%s)" +msgid "Supported URL type(s): [ %s ]" +msgstr "Támogatott URL típus(ok): [ %s ]" #: lhelpstrconsts.slhelp_tableofcontentsloading msgid "Table of Contents Loading ..." diff --git a/components/chmhelp/lhelp/languages/lhelp.lt.po b/components/chmhelp/lhelp/languages/lhelp.lt.po index 5a1cc908a2..acfaa523dc 100644 --- a/components/chmhelp/lhelp/languages/lhelp.lt.po +++ b/components/chmhelp/lhelp/languages/lhelp.lt.po @@ -20,6 +20,34 @@ msgstr "Apie" msgid "&About ..." msgstr "&Apie…" +#: lhelpstrconsts.slhelp_actions +msgid "&Actions" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoback +msgid "Go back" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoforward +msgid "Go forward" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgohome +msgid "Go home" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsindex +msgid "Search by &index" +msgstr "" + +#: lhelpstrconsts.slhelp_actionssearch +msgid "&Search by text" +msgstr "" + +#: lhelpstrconsts.slhelp_actionstoc +msgid "&TOC" +msgstr "" + #: lhelpstrconsts.slhelp_cannothandlethistypeofcontentforurl #, object-pascal-format msgid "Cannot handle this type of content. \"%s\" for url:%s%s" @@ -34,6 +62,10 @@ msgstr "Neįmanoma apdoroti šio tipo poturinio „%s“ adresui: %s%s" msgid "&Close" msgstr "Už&verti" +#: lhelpstrconsts.slhelp_closeconfirm +msgid "You can use the Esc to hide Help. Are you realy want to close lHelp?" +msgstr "" + #: lhelpstrconsts.slhelp_contents msgid "Contents" msgstr "Turiniai" @@ -46,6 +78,10 @@ msgstr " --context : Rodyti su šiuo turiniu sisijusią žinyno informacij msgid "Copy" msgstr "Kopijuoti" +#: lhelpstrconsts.slhelp_copyhtmlsource +msgid "Copy html source" +msgstr "" + #: lhelpstrconsts.slhelp_exit msgid "E&xit" msgstr "&Baigti darbą" @@ -70,6 +106,10 @@ msgstr "Žinyno failai (*.chm)|*.chm|Visi failai (*.*)|*" msgid " --help : Show this information" msgstr " --help : Rodyti šia informaciją" +#: lhelpstrconsts.slhelp_hide +msgid "&Hide" +msgstr "" + #: lhelpstrconsts.slhelp_hidestarthiddenbutacceptcommunicationsviaipc msgid " --hide : Start hidden but accept communications via IPC" msgstr " --hide : Darba pradėti pasislėpus, tačiau komunikuoti naudojant „IPC“" @@ -178,8 +218,8 @@ msgstr "Rodyti turinį" #: lhelpstrconsts.slhelp_supportedurltypes #, object-pascal-format -msgid "Supported URL type(s): (%s)" -msgstr "Palaikomas adreso tipas(-ai): (%s)" +msgid "Supported URL type(s): [ %s ]" +msgstr "Palaikomas adreso tipas(-ai): [ %s ]" #: lhelpstrconsts.slhelp_tableofcontentsloading msgid "Table of Contents Loading ..." diff --git a/components/chmhelp/lhelp/languages/lhelp.pl.po b/components/chmhelp/lhelp/languages/lhelp.pl.po index 67c985c640..ed30aedea7 100644 --- a/components/chmhelp/lhelp/languages/lhelp.pl.po +++ b/components/chmhelp/lhelp/languages/lhelp.pl.po @@ -20,6 +20,34 @@ msgstr "Informacja" msgid "&About ..." msgstr "&O..." +#: lhelpstrconsts.slhelp_actions +msgid "&Actions" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoback +msgid "Go back" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoforward +msgid "Go forward" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgohome +msgid "Go home" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsindex +msgid "Search by &index" +msgstr "" + +#: lhelpstrconsts.slhelp_actionssearch +msgid "&Search by text" +msgstr "" + +#: lhelpstrconsts.slhelp_actionstoc +msgid "&TOC" +msgstr "" + #: lhelpstrconsts.slhelp_cannothandlethistypeofcontentforurl #, object-pascal-format msgid "Cannot handle this type of content. \"%s\" for url:%s%s" @@ -34,6 +62,10 @@ msgstr "" msgid "&Close" msgstr "&Zamknij" +#: lhelpstrconsts.slhelp_closeconfirm +msgid "You can use the Esc to hide Help. Are you realy want to close lHelp?" +msgstr "" + #: lhelpstrconsts.slhelp_contents msgid "Contents" msgstr "Zawartość" @@ -46,6 +78,10 @@ msgstr "" msgid "Copy" msgstr "Kopiuj" +#: lhelpstrconsts.slhelp_copyhtmlsource +msgid "Copy html source" +msgstr "" + #: lhelpstrconsts.slhelp_exit msgid "E&xit" msgstr "&Wyjście" @@ -70,6 +106,10 @@ msgstr "Pliki pomocy (*.chm)|*.chm|Wszystkie pliki (*.*)|*" msgid " --help : Show this information" msgstr "" +#: lhelpstrconsts.slhelp_hide +msgid "&Hide" +msgstr "" + #: lhelpstrconsts.slhelp_hidestarthiddenbutacceptcommunicationsviaipc msgid " --hide : Start hidden but accept communications via IPC" msgstr "" @@ -178,8 +218,8 @@ msgstr "Pokaż zawartość" #: lhelpstrconsts.slhelp_supportedurltypes #, object-pascal-format -msgid "Supported URL type(s): (%s)" -msgstr "Obsługiwane typy URL: (%s)" +msgid "Supported URL type(s): [ %s ]" +msgstr "Obsługiwane typy URL: [ %s ]" #: lhelpstrconsts.slhelp_tableofcontentsloading msgid "Table of Contents Loading ..." diff --git a/components/chmhelp/lhelp/languages/lhelp.pot b/components/chmhelp/lhelp/languages/lhelp.pot index 547ffb9c83..014136f112 100644 --- a/components/chmhelp/lhelp/languages/lhelp.pot +++ b/components/chmhelp/lhelp/languages/lhelp.pot @@ -9,6 +9,34 @@ msgstr "" msgid "&About ..." msgstr "" +#: lhelpstrconsts.slhelp_actions +msgid "&Actions" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoback +msgid "Go back" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoforward +msgid "Go forward" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgohome +msgid "Go home" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsindex +msgid "Search by &index" +msgstr "" + +#: lhelpstrconsts.slhelp_actionssearch +msgid "&Search by text" +msgstr "" + +#: lhelpstrconsts.slhelp_actionstoc +msgid "&TOC" +msgstr "" + #: lhelpstrconsts.slhelp_cannothandlethistypeofcontentforurl #, object-pascal-format msgid "Cannot handle this type of content. \"%s\" for url:%s%s" @@ -23,6 +51,10 @@ msgstr "" msgid "&Close" msgstr "" +#: lhelpstrconsts.slhelp_closeconfirm +msgid "You can use the Esc to hide Help. Are you realy want to close lHelp?" +msgstr "" + #: lhelpstrconsts.slhelp_contents msgid "Contents" msgstr "" @@ -35,6 +67,10 @@ msgstr "" msgid "Copy" msgstr "" +#: lhelpstrconsts.slhelp_copyhtmlsource +msgid "Copy html source" +msgstr "" + #: lhelpstrconsts.slhelp_exit msgid "E&xit" msgstr "" @@ -59,6 +95,10 @@ msgstr "" msgid " --help : Show this information" msgstr "" +#: lhelpstrconsts.slhelp_hide +msgid "&Hide" +msgstr "" + #: lhelpstrconsts.slhelp_hidestarthiddenbutacceptcommunicationsviaipc msgid " --hide : Start hidden but accept communications via IPC" msgstr "" @@ -167,7 +207,7 @@ msgstr "" #: lhelpstrconsts.slhelp_supportedurltypes #, object-pascal-format -msgid "Supported URL type(s): (%s)" +msgid "Supported URL type(s): [ %s ]" msgstr "" #: lhelpstrconsts.slhelp_tableofcontentsloading diff --git a/components/chmhelp/lhelp/languages/lhelp.pt_BR.po b/components/chmhelp/lhelp/languages/lhelp.pt_BR.po index 7299766f60..b57ea21c6d 100644 --- a/components/chmhelp/lhelp/languages/lhelp.pt_BR.po +++ b/components/chmhelp/lhelp/languages/lhelp.pt_BR.po @@ -19,6 +19,34 @@ msgstr "Sobre" msgid "&About ..." msgstr "&Sobre ..." +#: lhelpstrconsts.slhelp_actions +msgid "&Actions" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoback +msgid "Go back" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoforward +msgid "Go forward" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgohome +msgid "Go home" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsindex +msgid "Search by &index" +msgstr "" + +#: lhelpstrconsts.slhelp_actionssearch +msgid "&Search by text" +msgstr "" + +#: lhelpstrconsts.slhelp_actionstoc +msgid "&TOC" +msgstr "" + #: lhelpstrconsts.slhelp_cannothandlethistypeofcontentforurl #, object-pascal-format msgid "Cannot handle this type of content. \"%s\" for url:%s%s" @@ -33,6 +61,10 @@ msgstr "Impossível lidar com este tipo de subconteúdo. \"%s\" para a url:%s%s" msgid "&Close" msgstr "&Fechar" +#: lhelpstrconsts.slhelp_closeconfirm +msgid "You can use the Esc to hide Help. Are you realy want to close lHelp?" +msgstr "" + #: lhelpstrconsts.slhelp_contents msgid "Contents" msgstr "Conteúdo" @@ -45,6 +77,10 @@ msgstr " --context : Exibe a informação de ajuda relacionada à este cont msgid "Copy" msgstr "Copiar" +#: lhelpstrconsts.slhelp_copyhtmlsource +msgid "Copy html source" +msgstr "" + #: lhelpstrconsts.slhelp_exit msgid "E&xit" msgstr "&Sair" @@ -69,6 +105,10 @@ msgstr "Arquivos de ajuda (*.chm)|*.chm|Todos (*.*)|*" msgid " --help : Show this information" msgstr " --help : Exibe esta informação" +#: lhelpstrconsts.slhelp_hide +msgid "&Hide" +msgstr "" + #: lhelpstrconsts.slhelp_hidestarthiddenbutacceptcommunicationsviaipc msgid " --hide : Start hidden but accept communications via IPC" msgstr " --hide : Inicia oculto mas aceita comunicação via IPC" @@ -177,8 +217,8 @@ msgstr "Exibir conteúdo" #: lhelpstrconsts.slhelp_supportedurltypes #, object-pascal-format -msgid "Supported URL type(s): (%s)" -msgstr "Tipo de URL suportado: (%s)" +msgid "Supported URL type(s): [ %s ]" +msgstr "Tipo de URL suportado: [ %s ]" #: lhelpstrconsts.slhelp_tableofcontentsloading msgid "Table of Contents Loading ..." diff --git a/components/chmhelp/lhelp/languages/lhelp.ru.po b/components/chmhelp/lhelp/languages/lhelp.ru.po index 4672a6ee91..0b5f0f6843 100644 --- a/components/chmhelp/lhelp/languages/lhelp.ru.po +++ b/components/chmhelp/lhelp/languages/lhelp.ru.po @@ -17,6 +17,36 @@ msgstr "О программе" msgid "&About ..." msgstr "&О программе ..." +#: lhelpstrconsts.slhelp_actions +#, fuzzy +#| msgid "Actions" +msgid "&Actions" +msgstr "Действия" + +#: lhelpstrconsts.slhelp_actionsgoback +msgid "Go back" +msgstr "Назад" + +#: lhelpstrconsts.slhelp_actionsgoforward +msgid "Go forward" +msgstr "Вперед" + +#: lhelpstrconsts.slhelp_actionsgohome +msgid "Go home" +msgstr "Домой" + +#: lhelpstrconsts.slhelp_actionsindex +msgid "Search by &index" +msgstr "Искать по индексу" + +#: lhelpstrconsts.slhelp_actionssearch +msgid "&Search by text" +msgstr "Полнотекстовый поиск" + +#: lhelpstrconsts.slhelp_actionstoc +msgid "&TOC" +msgstr "Содержание" + #: lhelpstrconsts.slhelp_cannothandlethistypeofcontentforurl #, object-pascal-format msgid "Cannot handle this type of content. \"%s\" for url:%s%s" @@ -31,6 +61,10 @@ msgstr "Невозможно обработать данный тип содер msgid "&Close" msgstr "&Закрыть" +#: lhelpstrconsts.slhelp_closeconfirm +msgid "You can use the Esc to hide Help. Are you realy want to close lHelp?" +msgstr "" + #: lhelpstrconsts.slhelp_contents msgid "Contents" msgstr "Содержание" @@ -43,6 +77,10 @@ msgstr " --context : Вывести справку по данному ко msgid "Copy" msgstr "Копировать" +#: lhelpstrconsts.slhelp_copyhtmlsource +msgid "Copy html source" +msgstr "Копировать HTML" + #: lhelpstrconsts.slhelp_exit msgid "E&xit" msgstr "В&ыход" @@ -67,6 +105,10 @@ msgstr "Файлы справки (*.chm)|*.chm|Все файлы (*.*)|*" msgid " --help : Show this information" msgstr " --help : Вывести данную информацию" +#: lhelpstrconsts.slhelp_hide +msgid "&Hide" +msgstr "Свернуть" + #: lhelpstrconsts.slhelp_hidestarthiddenbutacceptcommunicationsviaipc msgid " --hide : Start hidden but accept communications via IPC" msgstr " --hide : Запуститься скрыто, но взаимодействовать по IPC" @@ -176,8 +218,8 @@ msgstr "Показывать содержание" #: lhelpstrconsts.slhelp_supportedurltypes #, object-pascal-format -msgid "Supported URL type(s): (%s)" -msgstr "Поддерживаемые типы адресов: (%s)" +msgid "Supported URL type(s): [ %s ]" +msgstr "Поддерживаемые типы адресов: [ %s ]" #: lhelpstrconsts.slhelp_tableofcontentsloading msgid "Table of Contents Loading ..." diff --git a/components/chmhelp/lhelp/languages/lhelp.uk.po b/components/chmhelp/lhelp/languages/lhelp.uk.po index eb0a62b32f..01545f87fc 100644 --- a/components/chmhelp/lhelp/languages/lhelp.uk.po +++ b/components/chmhelp/lhelp/languages/lhelp.uk.po @@ -20,6 +20,34 @@ msgstr "Про програму" msgid "&About ..." msgstr "&Про програму ..." +#: lhelpstrconsts.slhelp_actions +msgid "&Actions" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoback +msgid "Go back" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoforward +msgid "Go forward" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgohome +msgid "Go home" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsindex +msgid "Search by &index" +msgstr "" + +#: lhelpstrconsts.slhelp_actionssearch +msgid "&Search by text" +msgstr "" + +#: lhelpstrconsts.slhelp_actionstoc +msgid "&TOC" +msgstr "" + #: lhelpstrconsts.slhelp_cannothandlethistypeofcontentforurl #, object-pascal-format msgid "Cannot handle this type of content. \"%s\" for url:%s%s" @@ -34,6 +62,10 @@ msgstr "Неможливо обробити вміст даного типу. \" msgid "&Close" msgstr "&Закрити" +#: lhelpstrconsts.slhelp_closeconfirm +msgid "You can use the Esc to hide Help. Are you realy want to close lHelp?" +msgstr "" + #: lhelpstrconsts.slhelp_contents msgid "Contents" msgstr "Зміст" @@ -46,6 +78,10 @@ msgstr " --context : Вивести довідку щодо даного к msgid "Copy" msgstr "Копіювати" +#: lhelpstrconsts.slhelp_copyhtmlsource +msgid "Copy html source" +msgstr "" + #: lhelpstrconsts.slhelp_exit msgid "E&xit" msgstr "В&ихід" @@ -70,6 +106,10 @@ msgstr "Файли довідки (*.chm)|*.chm|Всі файли (*.*)|*" msgid " --help : Show this information" msgstr " --help : Вивести дану інформацію" +#: lhelpstrconsts.slhelp_hide +msgid "&Hide" +msgstr "" + #: lhelpstrconsts.slhelp_hidestarthiddenbutacceptcommunicationsviaipc msgid " --hide : Start hidden but accept communications via IPC" msgstr " --hide : Запуститися приховано, але взаємодіяти через IPC" @@ -178,8 +218,8 @@ msgstr "Показувати зміст" #: lhelpstrconsts.slhelp_supportedurltypes #, object-pascal-format -msgid "Supported URL type(s): (%s)" -msgstr "Підтримувані типи адрес: (%s)" +msgid "Supported URL type(s): [ %s ]" +msgstr "Підтримувані типи адрес: [ %s ]" #: lhelpstrconsts.slhelp_tableofcontentsloading msgid "Table of Contents Loading ..." diff --git a/components/chmhelp/lhelp/languages/lhelp.zh_CN.po b/components/chmhelp/lhelp/languages/lhelp.zh_CN.po index 9d96739bff..ddca60c07d 100644 --- a/components/chmhelp/lhelp/languages/lhelp.zh_CN.po +++ b/components/chmhelp/lhelp/languages/lhelp.zh_CN.po @@ -20,6 +20,34 @@ msgstr "关于" msgid "&About ..." msgstr "关于...(&A)" +#: lhelpstrconsts.slhelp_actions +msgid "&Actions" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoback +msgid "Go back" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgoforward +msgid "Go forward" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsgohome +msgid "Go home" +msgstr "" + +#: lhelpstrconsts.slhelp_actionsindex +msgid "Search by &index" +msgstr "" + +#: lhelpstrconsts.slhelp_actionssearch +msgid "&Search by text" +msgstr "" + +#: lhelpstrconsts.slhelp_actionstoc +msgid "&TOC" +msgstr "" + #: lhelpstrconsts.slhelp_cannothandlethistypeofcontentforurl #, object-pascal-format msgid "Cannot handle this type of content. \"%s\" for url:%s%s" @@ -34,6 +62,10 @@ msgstr "不能处理这个子目录(subcontent)的类型.\"%s\"对于url:%s%s" msgid "&Close" msgstr "关闭(&C)" +#: lhelpstrconsts.slhelp_closeconfirm +msgid "You can use the Esc to hide Help. Are you realy want to close lHelp?" +msgstr "" + #: lhelpstrconsts.slhelp_contents msgid "Contents" msgstr "目录" @@ -46,6 +78,10 @@ msgstr " --context : 显示关于这个上下文的帮助信息" msgid "Copy" msgstr "复制" +#: lhelpstrconsts.slhelp_copyhtmlsource +msgid "Copy html source" +msgstr "" + #: lhelpstrconsts.slhelp_exit msgid "E&xit" msgstr "退出(&x)" @@ -70,6 +106,10 @@ msgstr "Help文件(*.chm)|*.chm|所有文件 (*.*)|*" msgid " --help : Show this information" msgstr " --help : 显示此信息" +#: lhelpstrconsts.slhelp_hide +msgid "&Hide" +msgstr "" + #: lhelpstrconsts.slhelp_hidestarthiddenbutacceptcommunicationsviaipc msgid " --hide : Start hidden but accept communications via IPC" msgstr " --hide :开始隐藏 但是通过IPC接受通讯" @@ -178,8 +218,8 @@ msgstr "显示目录(contents)" #: lhelpstrconsts.slhelp_supportedurltypes #, object-pascal-format -msgid "Supported URL type(s): (%s)" -msgstr "支持的URL类型:(%s)" +msgid "Supported URL type(s): [ %s ]" +msgstr "支持的URL类型:[ %s ]" #: lhelpstrconsts.slhelp_tableofcontentsloading msgid "Table of Contents Loading ..." diff --git a/components/chmhelp/lhelp/lhelp.lpi b/components/chmhelp/lhelp/lhelp.lpi index 571e381b89..77de05a9fb 100644 --- a/components/chmhelp/lhelp/lhelp.lpi +++ b/components/chmhelp/lhelp/lhelp.lpi @@ -15,43 +15,14 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + @@ -71,17 +42,20 @@ - + - - + - + + - + + + + @@ -99,38 +73,40 @@ - - - - - - - - + + + - - + + + - - + + - - + + + + + + + + - + @@ -150,8 +126,14 @@ + + + + + + - + diff --git a/components/chmhelp/lhelp/lhelp.lpr b/components/chmhelp/lhelp/lhelp.lpr index b1ba1337e7..f34524d94b 100644 --- a/components/chmhelp/lhelp/lhelp.lpr +++ b/components/chmhelp/lhelp/lhelp.lpr @@ -26,8 +26,8 @@ uses cthreads, {$ENDIF} Interfaces, // this includes the LCL widgetset - SysUtils, Classes, Controls, Dialogs, Forms, - SimpleIPC, TurboPowerIPro, chmpopup, lhelpcontrolpkg, lhelpcore, lhelpstrconsts; + SysUtils, Classes, Controls, Dialogs, Forms, lazmouseandkeyinput, + SimpleIPC, lhelpcontrolpkg, lhelpcore, lhelpstrconsts, filecontentprovider; var X: Integer; @@ -64,7 +64,6 @@ begin end; end; Application.CreateForm(THelpForm, HelpForm); - Application.CreateForm(THelpPopupForm, HelpPopupForm); try Application.Run; diff --git a/components/chmhelp/lhelp/lhelpcore.lfm b/components/chmhelp/lhelp/lhelpcore.lfm index 75155079a2..ffa23b4d8a 100644 --- a/components/chmhelp/lhelp/lhelpcore.lfm +++ b/components/chmhelp/lhelp/lhelpcore.lfm @@ -1,11 +1,12 @@ object HelpForm: THelpForm - Left = 582 - Height = 535 - Top = 318 - Width = 758 + Left = 413 + Height = 585 + Top = 199 + Width = 829 Caption = 'LHelp' - ClientHeight = 515 - ClientWidth = 758 + ClientHeight = 563 + ClientWidth = 829 + DesignTimePPI = 106 Icon.Data = { 7E04000000000100010010100000010020006804000016000000280000001000 0000200000000100200000000000000400006400000064000000000000000000 @@ -45,56 +46,73 @@ object HelpForm: THelpForm 0000000000000000000000000000000000000000000000000000000000000000 0000 } + KeyPreview = True Menu = MainMenu1 OnClose = FormClose OnCreate = FormCreate - OnKeyUp = FormKeyUp + OnKeyDown = FormKeyDown OnShow = FormShow + OnWindowStateChange = FormWindowStateChange Position = poScreenCenter - LCLVersion = '2.1.0.0' + LCLVersion = '2.0.11.0' Visible = True object PageControl: TPageControl Left = 0 - Height = 481 - Top = 34 - Width = 758 + Height = 525 + Top = 38 + Width = 829 Align = alClient + MultiLine = True + ParentFont = False + ParentShowHint = False + ShowHint = True TabOrder = 0 TabPosition = tpBottom OnChange = PageControlChange OnEnter = PageControlEnter + Options = [nboMultiLine] end object ToolBar1: TToolBar Left = 0 - Height = 34 + Height = 38 Top = 0 - Width = 758 - ButtonHeight = 32 - ButtonWidth = 32 + Width = 829 + ButtonHeight = 35 + ButtonWidth = 35 Caption = 'ToolBar1' EdgeBorders = [] Images = ImageListToolbar + ParentFont = False TabOrder = 1 object HomeBttn: TToolButton - Left = 41 + Left = 44 + Hint = 'Home' Top = 0 - Caption = 'HomeBttn' + Caption = 'Go Home' ImageIndex = 0 - OnClick = HomeToolBtnClick + OnClick = MiActionsGoHomeClick + ParentShowHint = False + ShowHint = True end object BackBttn: TToolButton - Left = 73 + Left = 79 + Hint = 'Go Back' Top = 0 - Caption = 'BackBttn' + Caption = 'Go back' ImageIndex = 1 - OnClick = BackToolBtnClick + OnClick = MiActionsGoBackClick + ParentShowHint = False + ShowHint = True end object ForwardBttn: TToolButton - Left = 105 + Left = 114 + Hint = 'Go forward' Top = 0 - Caption = 'ForwardBttn' + Caption = 'Go forward' ImageIndex = 2 - OnClick = ForwardToolBtnClick + OnClick = MiActionsGoForwardClick + ParentShowHint = False + ShowHint = True end object FileButton: TToolButton Left = 1 @@ -104,16 +122,16 @@ object HelpForm: THelpForm OnClick = FileMenuOpenItemClick end object ToolButton1: TToolButton - Left = 33 - Height = 32 + Left = 36 + Height = 35 Top = 0 Caption = 'ToolButton1' Style = tbsSeparator end end object MainMenu1: TMainMenu - left = 208 - top = 80 + Left = 230 + Top = 96 object FileMenuItem: TMenuItem Caption = '&File' object FileMenuOpenItem: TMenuItem @@ -134,13 +152,19 @@ object HelpForm: THelpForm ShortCut = 16471 OnClick = FileMenuCloseItemClick end + object MiHide: TMenuItem + Caption = 'Hide' + Hint = 'Hide' + ShortCut = 27 + OnClick = MiHideClick + end object FileSeperater: TMenuItem Caption = '-' end - object FileMenuExitItem: TMenuItem - Caption = 'E&xit' - ShortCut = 27 - OnClick = FileMenuExitItemClick + object MiQuit: TMenuItem + Caption = 'Quit' + ShortCut = 32883 + OnClick = MiQuitClick end end object ViewMenuItem: TMenuItem @@ -162,11 +186,47 @@ object HelpForm: THelpForm OnClick = ViewShowSepTabsClick end end + object MiActions: TMenuItem + Caption = '&Actions' + object MiActionsTOC: TMenuItem + Caption = 'TOC' + ShortCut = 16468 + OnClick = MiActionsTOCClick + end + object MiActionsIndex: TMenuItem + Caption = 'Search by index' + ShortCut = 16457 + OnClick = MiActionsIndexClick + end + object MiActionsSearch: TMenuItem + Caption = 'Search by text' + ShortCut = 16467 + OnClick = MiActionsSearchClick + end + object MenuItem2: TMenuItem + Caption = '-' + end + object MiActionsGoHome: TMenuItem + Caption = 'Go Home' + ShortCut = 32804 + OnClick = MiActionsGoHomeClick + end + object MiActionsGoBack: TMenuItem + Caption = 'Go Back' + ShortCut = 32805 + OnClick = MiActionsGoBackClick + end + object MiActionsGoForward: TMenuItem + Caption = 'Go Forward' + ShortCut = 32807 + OnClick = MiActionsGoForwardClick + end + end object HelpMenuItem: TMenuItem Caption = '&Help' + OnClick = HelpMenuItemClick object AboutItem: TMenuItem Caption = '&About...' - ShortCut = 112 OnClick = AboutItemClick end end @@ -174,12 +234,12 @@ object HelpForm: THelpForm object OpenDialog1: TOpenDialog Filter = 'Help files (*.chm)|*.chm|All files (*.*)|*' FilterIndex = 0 - left = 248 - top = 92 + Left = 232 + Top = 176 end object ImageList1: TImageList - left = 80 - top = 75 + Left = 48 + Top = 96 Bitmap = { 4C690400000010000000100000007001E300B0CE2A000000000000000000F609 0200E1281B00005959000090AF00329FCCFF75888800003A3A00000E0E00FA11 @@ -315,14 +375,14 @@ object HelpForm: THelpForm object ApplicationProperties1: TApplicationProperties ShowButtonGlyphs = sbgSystem ShowMenuGlyphs = sbgSystem - left = 80 - top = 136 + Left = 56 + Top = 176 end object ImageListToolbar: TImageList Height = 22 Width = 22 - left = 120 - top = 88 + Left = 144 + Top = 96 Bitmap = { 4C69040000001600000016000000000000000000000000000000000000000000 0000000000000000000000000000000000000000A4190000A4FF0000A4FF0000 diff --git a/components/chmhelp/lhelp/lhelpcore.pas b/components/chmhelp/lhelp/lhelpcore.pas index e1033b5115..9d474cf09a 100644 --- a/components/chmhelp/lhelp/lhelpcore.pas +++ b/components/chmhelp/lhelp/lhelpcore.pas @@ -22,7 +22,7 @@ Icons from Tango theme: http://tango.freedesktop.org/Tango_Icon_Library } -unit lhelpcore; +unit LHelpCore; {$IFDEF LNET_VISUAL} {$DEFINE USE_LNET} // you must manually add the lnetvisual.lpk package to the dependancy list @@ -40,10 +40,10 @@ uses Forms, Controls, Dialogs, Buttons, ComCtrls, ExtCtrls, Menus, StdCtrls, LCLProc, LCLType, LCLIntf, DefaultTranslator, // LazUtils - LazFileUtils, LazUTF8, LazLogger, + LazFileUtils, LazUTF8, LazLoggerBase, // ChmHelp {$IFDEF USE_LNET}HTTPContentProvider,{$ENDIF} - BaseContentProvider, ChmContentProvider, lhelpstrconsts; + BaseContentProvider, filecontentprovider, ChmContentProvider, lhelpstrconsts; type @@ -63,7 +63,7 @@ type THelpForm = class(TForm) ApplicationProperties1: TApplicationProperties; FileMenuCloseItem: TMenuItem; - FileMenuExitItem: TMenuItem; + MiQuit: TMenuItem; FileMenuItem: TMenuItem; FileMenuOpenItem: TMenuItem; FileSeperater: TMenuItem; @@ -74,6 +74,14 @@ type HelpMenuItem: TMenuItem; AboutItem: TMenuItem; FileMenuOpenRecentItem: TMenuItem; + MiHide: TMenuItem; + MiActionsGoBack: TMenuItem; + MiActionsGoForward: TMenuItem; + MiActionsGoHome: TMenuItem; + MiActions: TMenuItem; + MiActionsSearch: TMenuItem; + MiActionsIndex: TMenuItem; + MiActionsTOC: TMenuItem; ViewShowStatus: TMenuItem; ViewShowSepTabs: TMenuItem; PageControl: TPageControl; @@ -87,17 +95,24 @@ type ViewMenuContents: TMenuItem; ViewMenuItem: TMenuItem; procedure AboutItemClick(Sender: TObject); - procedure BackToolBtnClick(Sender: TObject); procedure FileMenuCloseItemClick(Sender: TObject); - procedure FileMenuExitItemClick(Sender: TObject); procedure FileMenuOpenItemClick(Sender: TObject); procedure FileMenuOpenURLItemClick(Sender: TObject); procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction); procedure FormCreate(Sender: TObject); - procedure FormKeyUp(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState); + procedure FormKeyDown ( Sender: TObject; var Key: Word; Shift: TShiftState + ) ; procedure FormShow(Sender: TObject); - procedure ForwardToolBtnClick(Sender: TObject); - procedure HomeToolBtnClick(Sender: TObject); + procedure FormWindowStateChange(Sender: TObject); + procedure MiActionsGoForwardClick ( Sender: TObject ) ; + procedure HelpMenuItemClick ( Sender: TObject ) ; + procedure MiHideClick ( Sender: TObject ) ; + procedure MiActionsGoBackClick ( Sender: TObject ) ; + procedure MiActionsGoHomeClick ( Sender: TObject ) ; + procedure MiActionsIndexClick ( Sender: TObject ) ; + procedure MiQuitClick ( Sender: TObject ) ; + procedure MiActionsSearchClick ( Sender: TObject ) ; + procedure MiActionsTOCClick ( Sender: TObject ) ; procedure PageControlChange(Sender: TObject); procedure PageControlEnter(Sender: TObject); procedure ViewMenuContentsClick(Sender: TObject); @@ -120,8 +135,12 @@ type fShowSepTabs: Boolean; fShowStatus: Boolean; fHasShowed: Boolean; + fMustClose: boolean; + fDefWinMax: Boolean; + fDefWinSize: TRect; fHide: boolean; //If yes, start with content hidden. Otherwise start normally fUpdateCount: Integer; + fLastHiddenRequest: String; // Keep track of whether size/position preferences were loaded and applied to form fLayoutApplied: boolean; // Applies layout (size/position/fullscreen) preferences once in lhelp lifetime @@ -133,6 +152,7 @@ type procedure SavePreferences; // Add filename to recent files (MRU) list procedure AddRecentFile(AFileName: String); + procedure DeleteRecentFile(AFileName: String); procedure ContentTitleChange({%H-}sender: TObject); procedure OpenRecentItemClick(Sender: TObject); // Send response back to server (IDE) @@ -156,16 +176,17 @@ type // Update UI visibility procedure RefreshState; procedure ShowError(AError: String); - // Set keyup handler for control (and any child controls) - procedure SetKeyUp(AControl: TControl); // BeginUpdate tells each content provider to possibly stop some events procedure BeginUpdate; // EndUpdate tells each content provider to resume normal behavior procedure EndUpdate; + // Bring App on Top and show + procedure ShowApp(); + // Event process + procedure DoShowContent(Sender:Tobject); public { public declarations } end; - var HelpForm: THelpForm; @@ -176,14 +197,14 @@ var const INVALID_FILE_TYPE = 1; - VERSION_STAMP = '2014-10-16'; //used in displaying version in about form etc + VERSION_STAMP = '2020-12-10'; //used in displaying version in about form etc implementation {$R *.lfm} uses - LHelpControl; + LHelpControl, MouseAndkeyInput; const DigitsInPID=5; // Number of digits in the formatted PID according to the Help Protocol @@ -196,12 +217,6 @@ type { THelpForm } - -procedure THelpForm.BackToolBtnClick(Sender: TObject); -begin - if Assigned(ActivePage) then ActivePage.ContentProvider.GoBack; -end; - procedure THelpForm.AboutItemClick(Sender: TObject); var f: TForm; @@ -218,6 +233,7 @@ begin l := TLabel.Create(f); l.Parent := f;; l.Align := alTop; + l.Alignment:=taCenter; l.BorderSpacing.Around := 6; l.Caption := Format(slhelp_LHelpCHMFileViewerVersionCopyrightCAndrewHainesLaz, [LineEnding, VERSION_STAMP, LineEnding + LineEnding, LineEnding]); @@ -241,7 +257,6 @@ begin end; end; - procedure THelpForm.FileMenuCloseItemClick(Sender: TObject); begin if Assigned(ActivePage) then @@ -252,11 +267,6 @@ begin end; end; -procedure THelpForm.FileMenuExitItemClick(Sender: TObject); -begin - Close; -end; - procedure THelpForm.FileMenuOpenItemClick(Sender: TObject); var TimerWasOn: boolean; @@ -291,21 +301,33 @@ procedure THelpForm.FileMenuOpenURLItemClick(Sender: TObject); var fRes: String; URLSAllowed: String; - Protocol: TStrings; - i: Integer; + FileExt: String; + Protocol: TStringList; + FileTypes: TStringList; + i, ii: Integer; begin Protocol := GetContentProviderList; - try - URLSAllowed:=''; - for i := 0 to Protocol.Count-1 do + URLSAllowed:=''; + for i := 0 to Protocol.Count-1 do + begin + FileExt := ''; + if i < 1 then + URLSAllowed := URLSAllowed + Protocol[i] + else + URLSAllowed := URLSAllowed + ', ' +Protocol[i]; + if TBaseContentProviderClass(Protocol.Objects[i]) = TFileContentProvider then begin - if i < 1 then - URLSAllowed := URLSAllowed + Protocol[i] - else - URLSAllowed := URLSAllowed + ', ' +Protocol[i] + FileTypes := TFileContentProviderClass(Protocol.Objects[i]).GetRegisteredFileTypes(); + for ii := 0 to Pred(FileTypes.Count) do + begin + if ii < 1 Then + FileExt:= FileTypes[ii] + else + FileExt:= FileExt + ', '+FileTypes[ii]; + end; + if FileExt<>'' then + URLSAllowed := URLSAllowed + '(*'+FileExt+')'; end; - finally - Protocol.Free; end; URLSAllowed := Trim(URLSAllowed); @@ -322,13 +344,20 @@ end; procedure THelpForm.FormClose(Sender: TObject; var CloseAction: TCloseAction); begin + if not fMustClose then + if MessageDlg(slhelp_LHelp, slhelp_CloseConfirm, mtConfirmation, mbYesNo, '') <> mrYes then + begin + CloseAction:= caNone; + Application.Minimize(); + Exit; + end; //close all tabs to avoid AV with many tabs - while Assigned(ActivePage) do + BeginUpdate; + PageControl.ShowTabs:= False; + while TContentTab(ActivePage) <>nil do ActivePage.Free; - ////was before: close tab - ////FileMenuCloseItemClick(Sender); - - Visible := false; + EndUpdate; + //Visible := false; Application.ProcessMessages; StopComms; SavePreferences; @@ -341,18 +370,34 @@ begin FileMenuOpenRecentItem.Caption := slhelp_OpenRecent; FileMenuOpenURLItem.Caption := slhelp_OpenURL; FileMenuCloseItem.Caption := slhelp_Close; - FileMenuExitItem.Caption := slhelp_EXit; + MiHide.Caption := slhelp_Hide; + MiQuit.Caption := slhelp_EXit; + MiActions.Caption:= slhelp_Actions; + MiActionsTOC.Caption:= slhelp_ActionsTOC; + MiActionsIndex.Caption:= slhelp_ActionsIndex; + MiActionsSearch.Caption:= slhelp_ActionsSearch; + MiActionsGoHome.Caption:= slhelp_ActionsGoHome; + MiActionsGoBack.Caption:= slhelp_ActionsGoBack; + MiActionsGoForward.Caption:= slhelp_ActionsGoForward; ViewMenuItem.Caption := slhelp_View; ViewMenuContents.Caption := slhelp_ShowContents; ViewShowStatus.Caption := slhelp_OpenNewTabWithStatusBar; ViewShowSepTabs.Caption := slhelp_OpenNewFileInSeparateTab; HelpMenuItem.Caption := slhelp_Help; + + BackBttn.Hint:= MiActionsGoBack.Caption; + ForwardBttn.Hint:= MiActionsGoForward.Caption; + HomeBttn.Hint:= MiActionsGoHome.Caption; + FileButton.Hint:= FileMenuOpenItem.Caption; + AboutItem.Caption := slhelp_About2; OpenDialog1.Title := slhelp_OpenExistingFile; OpenDialog1.Filter := slhelp_HelpFilesChmChmAllFiles; + fMustClose:= false; fContext := -1; + fUpdateCount:= 0; // Safe default: fHide := false; // ReadCommandLineOptions will set fHide if requested @@ -368,18 +413,26 @@ begin WindowState := wsMinimized else RefreshState; - SetKeyUp(Self); end; -procedure THelpForm.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); +procedure THelpForm.FormKeyDown ( Sender: TObject; var Key: Word; + Shift: TShiftState ) ; begin - if Key = VK_ESCAPE then - Close; - // Backspace: go to previous page (as if BackBttn were clicked) - if Key = VK_BACK then - if Assigned(ActivePage) then ActivePage.ContentProvider.GoBack; + //if (Shift = [ssAlt]) then + //case Key of + // VK_Left: begin + // MiActionsGoHomeClick(Sender); key:= 0; + // end; + // VK_RIGHT: begin + // MiActionsGoForwardClick(Sender); key:= 0; + // end; + // VK_Home: begin + // MiActionsGoBackClick(Sender); key:= 0; + // end; + //end; end; + procedure THelpForm.FormShow(Sender: TObject); begin if FHasShowed then @@ -387,16 +440,54 @@ begin FHasShowed := True; end; -procedure THelpForm.ForwardToolBtnClick(Sender: TObject); +procedure THelpForm.MiActionsGoForwardClick ( Sender: TObject ) ; begin if Assigned(ActivePage) then ActivePage.ContentProvider.GoForward; end; -procedure THelpForm.HomeToolBtnClick(Sender: TObject); +procedure THelpForm.HelpMenuItemClick ( Sender: TObject ) ; +begin + +end; + +procedure THelpForm.MiHideClick ( Sender: TObject ) ; +begin + if WindowState <> wsMinimized then + Application.Minimize(); + //Visible := False; +end; + +procedure THelpForm.MiActionsGoBackClick ( Sender: TObject ) ; +begin + if Assigned(ActivePage) then ActivePage.ContentProvider.GoBack; +end; + +procedure THelpForm.MiActionsGoHomeClick ( Sender: TObject ) ; begin if Assigned(ActivePage) then ActivePage.ContentProvider.GoHome; end; +procedure THelpForm.MiActionsIndexClick ( Sender: TObject ) ; +begin + if Assigned(ActivePage) then ActivePage.ContentProvider.ActivateIndexControl; +end; + +procedure THelpForm.MiQuitClick ( Sender: TObject ) ; +begin + fMustClose:= True; + Close(); +end; + +procedure THelpForm.MiActionsSearchClick ( Sender: TObject ) ; +begin + if Assigned(ActivePage) then ActivePage.ContentProvider.ActivateSearchControl; +end; + +procedure THelpForm.MiActionsTOCClick ( Sender: TObject ) ; +begin + if Assigned(ActivePage) then ActivePage.ContentProvider.ActivateTOCControl; +end; + procedure THelpForm.PageControlChange(Sender: TObject); begin RefreshState; @@ -407,21 +498,39 @@ begin RefreshState; end; +procedure THelpForm.FormWindowStateChange(Sender: TObject); +begin + if Windowstate = wsNormal then + begin + Left := fDefWinSize.Left; + Top := fDefWinSize.Top; + Width := fDefWinSize.Width; + Height := fDefWinSize.Height; + end; +end; + procedure THelpForm.ApplyLayoutPreferencesOnce; begin if not Assigned(fConfig) then exit; if (not fHide) and (not fLayoutApplied) then begin - if fConfig.GetValue('Position/Maximized', false) then + fDefWinSize.Left := fConfig.GetValue('Position/Left/Value', Left); + fDefWinSize.Top := fConfig.GetValue('Position/Top/Value', Top); + fDefWinSize.Width := fConfig.GetValue('Position/Width/Value', Width); + fDefWinSize.Height := fConfig.GetValue('Position/Height/Value', Height); + fDefWinMax:= fConfig.GetValue('Position/Maximized', false); + + if fDefWinMax then begin - Windowstate := wsMaximized + Windowstate := wsMaximized; end else begin - Left := fConfig.GetValue('Position/Left/Value', Left); - Top := fConfig.GetValue('Position/Top/Value', Top); - Width := fConfig.GetValue('Position/Width/Value', Width); - Height := fConfig.GetValue('Position/Height/Value', Height); + Windowstate := wsNormal; + Left := fDefWinSize.Left; + Top := fDefWinSize.Top; + Width := fDefWinSize.Width; + Height := fDefWinSize.Height; end; // Keep track so we do not reapply initial settings as user may have // changed size etc in the meantime. @@ -477,7 +586,10 @@ begin // server-dependent constant together with a process ID. // Strip out the formatted process ID to get fixed config file names for // one server - ServerPart := Copy(AIPCName, 1, length(AIPCName)-DigitsInPID); + if (AIPCName <> '') then + ServerPart := Copy(AIPCName, 1, length(AIPCName)-DigitsInPID) + else + ServerPart:= 'standalone'; PrefFile := Format('%slhelp-%s.conf',[IncludeTrailingPathDelimiter(PrefFile), ServerPart]); fConfig := TXMLConfig.Create(Self); @@ -557,6 +669,15 @@ begin FileMenuOpenRecentItem.Items[MaxHistory-1].Free; end; +procedure THelpForm.DeleteRecentFile ( AFileName: String ) ; +var + i: Integer; +begin + for i := FileMenuOpenRecentItem.Count-1 downto 0 do + if TRecentMenuItem(FileMenuOpenRecentItem.Items[i]).URL = AFileName then + FileMenuOpenRecentItem.Delete(i); +end; + procedure THelpForm.ContentTitleChange(sender: TObject); begin if ActivePage = nil then @@ -573,7 +694,10 @@ begin if res = Ord(srSuccess) then AddRecentFile(Item.URL) else + begin MessageDlg(Format(slhelp_NotFound, [Item.URL]), mtError, [mbOK], 0); + DeleteRecentFile(Item.URL); + end; end; procedure THelpForm.SendResponse(Response: DWord); @@ -596,7 +720,6 @@ var FileReq: TFileRequest; ConReq: TContextRequest; MiscReq: TMiscRequest; - MustClose: boolean=false; Stream: TStream; Res: LongWord; Url: String=''; @@ -612,34 +735,50 @@ begin rtFile: begin Url := 'file://'+FileReq.FileName; + DebugLn('got rtFile, filename '+filereq.filename); + {$IFDEF SHOW_ON_REQUEST} + fHide := false; + RefreshState; + ShowApp(); + {$ENDIF} Res := OpenURL(URL); - //debugln('got rtfile, filename '+filereq.filename); end; rtUrl: begin Stream.Position := 0; FillByte(UrlReq{%H-},SizeOf(UrlReq),0); Stream.Read(UrlReq, SizeOf(UrlReq)); + {$IFDEF SHOW_ON_REQUEST} + fHide := false; + RefreshState; + ShowApp(); + {$ENDIF} if UrlReq.FileRequest.FileName <> '' then begin Url := 'file://'+UrlReq.FileRequest.FileName; + DebugLn('got rturl, filename '+urlreq.filerequest.filename+', url '+urlreq.url); Res := OpenUrl(URL+'://'+UrlReq.Url); end else begin Url := UrlReq.Url; + DebugLn('got rturl, filename '+urlreq.filerequest.filename+', url '+urlreq.url); Res := OpenURL(Url); end; - //debugln('got rturl, filename '+urlreq.filerequest.filename+', url '+urlreq.url); end; rtContext: begin Stream.Position := 0; FillByte(ConReq{%H-},SizeOf(ConReq),0); Stream.Read(ConReq, SizeOf(ConReq)); - Url := 'file://'+FileReq.FileName; + Url := 'file://'+ConReq.FileRequest.FileName; + DebugLn('got rtcontext, filename '+ConReq.FileRequest.FileName+', context '+inttostr(ConReq.HelpContext)); + {$IFDEF SHOW_ON_REQUEST} + fHide := false; + RefreshState; + ShowApp(); + {$ENDIF} Res := OpenURL(Url, ConReq.HelpContext); - //debugln('got rtcontext, filename '+filereq.filename+', context '+inttostr(ConReq.HelpContext)); end; rtMisc: begin @@ -649,41 +788,47 @@ begin case MiscReq.RequestID of mrClose: begin - MustClose:=true; + fMustClose:=true; Res:= ord(srSuccess); - //debugln('got rtmisc/mrClose'); + //DebugLn('got rtmisc/mrClose'); end; mrShow: begin - fHide := false; - if WindowState = wsMinimized then - WindowState := wsNormal; - RefreshState; Res := ord(srSuccess); - //debugln('got rtmisc/mrShow'); + DebugLn('got rtmisc/mrShow'); + fHide := false; + if (fUpdateCount = 0) and (fLastHiddenRequest <> '')then + begin + DebugLn('mrShow OpenUrl '+fLastHiddenRequest); + Res := OpenURL(fLastHiddenRequest); + fLastHiddenRequest:= ''; + end; + RefreshState; + ShowApp(); end; mrVersion: begin // Protocol version encoded in the filename // Verify what we support - if strtointdef(FileReq.FileName,0)=strtointdef(PROTOCOL_VERSION,0) then + if strtointdef(MiscReq.FileRequest.FileName,0)=strtointdef(PROTOCOL_VERSION,0) then Res := ord(srSuccess) else Res := ord(srError); //version not supported - //debugln('got rtmisc/'); + DebugLn('got rtmisc/version ( ver=' + MiscReq.FileRequest.FileName + ' )' + + ' Success: ', BoolToStr((Res = ord(srSuccess)), true)); end; mrBeginUpdate: begin + DebugLn('got BeginUpdate'); BeginUpdate; Res := ord(srSuccess); end; mrEndUpdate: begin + DebugLn('got EndUpdate'); EndUpdate; Res := ord(srSuccess); - end - else {Unknown request} - Res := ord(srUnknown); + end; end; end; //rtMisc end; @@ -699,29 +844,25 @@ begin // Keep after SendResponse to avoid timing issues (e.g. writing to log file): //debugln('Just sent TLHelpResponse code: '+inttostr(Res)); - if MustClose then + // On received any command: + if (fMustClose = false) and (fHide = false) then begin - Application.ProcessMessages; - Sleep(10); - Application.Terminate; - end; - - // We received mrShow: - if (MustClose=false) and (fHide=false) then - begin - Self.SendToBack; - Self.BringToFront; - Self.ShowOnTop; // If lhelp was run with hidden parameter, we need to apply // layout preferences once: ApplyLayoutPreferencesOnce; end; + + if fMustClose then + begin + Close; + Application.Terminate; + end; end; end; procedure THelpForm.ReadCommandLineOptions; var - X: Integer; + X, S: Integer; IsHandled: array[0..50] of boolean; URL: String; StrItem: PStringItem; @@ -741,6 +882,7 @@ begin fServerName := ParamStrUTF8(X); IsHandled[X] := True; inc(X); + DebugLn('Start IPCNAME = ', fServerName); end; end else if LowerCase(ParamStrUTF8(X)) = '--context' then @@ -752,6 +894,7 @@ begin begin IsHandled[X] := True; inc(X); + DebugLn('Start CONTEXT = ', IntToStr(fContext)); end; end else if LowerCase(ParamStrUTF8(X)) = '--hide' then @@ -759,6 +902,7 @@ begin IsHandled[X] := True; inc(X); fHide:=true; + DebugLn('Start HIDE = True'); end else begin @@ -780,15 +924,20 @@ begin if pos('file://', FileName) = 1 then begin System.Delete(Filename,1,length('file://')); + S:= System.Pos('?', Filename); + if S > 0 then System.Delete(Filename, S, Length(FileName)); Filename := SetDirSeparators(Filename); if not FileExistsUTF8(Filename) then begin - debugln(['THelpForm.ReadCommandLineOptions file not found "',Filename,'"']); + DebugLn(['THelpForm.ReadCommandLineOptions file not found "',Filename,'"']); continue; end; end; - StrItem := New(PStringItem); + // https://www.freepascal.org/docs-html/rtl/system/initialize.html + GetMem(StrItem, SizeOf(TStringItem)); + Initialize(StrItem^); StrItem^.FString := URL; + DebugLn('Start URL = ', URL); Application.QueueAsyncCall(TDataEvent(@LateOpenURL), {%H-}PtrUInt(StrItem)); Break; end; @@ -848,88 +997,103 @@ begin end; function THelpForm.OpenURL(const AURL: String; AContext: THelpContext): DWord; - function GetURLPrefix: String; - var - fPos: Integer; - begin - fPos := Pos('://', AURL); - Result := Copy(AURL, 1, fPos+2); - end; + var fURLPrefix: String; fContentProvider: TBaseContentProviderClass; fRealContentProvider: TBaseContentProviderClass; fPage: TContentTab = nil; + fFirstSameTypePage: TContentTab = nil; I: Integer; fIsNewPage: Boolean = false; begin - Result := Ord(srInvalidURL); - fURLPrefix := GetURLPrefix; - fContentProvider := GetContentProvider(fURLPrefix); - - if fContentProvider = nil then - begin - ShowError(Format(slhelp_CannotHandleThisTypeOfContentForUrl, [fURLPrefix, LineEnding, AURL])); - Result := Ord(srInvalidURL); - Exit; - end; - fRealContentProvider := fContentProvider.GetProperContentProvider(AURL); - - if fRealContentProvider = nil then - begin - ShowError(Format(slhelp_CannotHandleThisTypeOfSubcontentForUrl, [fURLPrefix, LineEnding, AURL])); - Result := Ord(srInvalidURL); - Exit; - end; + Result := Ord(srInvalidURL); + fURLPrefix := GetUriPrefix(AURL); + fContentProvider := GetContentProvider(fURLPrefix); - if not fShowSepTabs then - for I := 0 to PageControl.PageCount-1 do - begin - if fRealContentProvider.ClassName = TContentTab(PageControl.Pages[I]).ContentProvider.ClassName then - begin - fPage := TContentTab(PageControl.Pages[I]); - if TContentTab(PageControl.Pages[I]).ContentProvider.LoadURL(AURL, AContext) then - begin - PageControl.ActivePage := PageControl.Pages[I]; - Result := Ord(srSuccess); - end - else - Result := Ord(srInvalidFile); - Exit; - end; - end; + if fContentProvider = nil then + begin + ShowError(Format(slhelp_CannotHandleThisTypeOfContentForUrl, [fURLPrefix, LineEnding, AURL])); + Result := Ord(srInvalidURL); + Exit; + end; - if fPage = nil then - begin - // no existing page that can handle this content, so create one - fIsNewPage := true; - fPage := TContentTab.Create(PageControl); - fPage.ContentProvider := fRealContentProvider.Create(fPage, ImageList1); - fPage.ContentProvider.OnTitleChange := @ContentTitleChange; - fPage.Parent := PageControl; - SetKeyUp(fPage); - fPage.ContentProvider.LoadPreferences(fConfig); - if fPage.ContentProvider is TChmContentProvider then + fRealContentProvider := fContentProvider.GetProperContentProvider(AURL); + if fRealContentProvider = nil then + begin + ShowError(Format(slhelp_CannotHandleThisTypeOfSubcontentForUrl, [fURLPrefix, LineEnding, AURL])); + Result := Ord(srInvalidURL); + Exit; + end; + + Result := Ord(srInvalidFile); + + if (fUpdateCount > 0) then + begin + fLastHiddenRequest:= AURL; + //DebugLn('set fLastHiddenRequest: ', AURL); + end; + + // Searching a page for loading or refreshing data + for I := 0 to PageControl.PageCount-1 do + begin + fPage := TContentTab(PageControl.Pages[I]); + if fRealContentProvider.ClassName = fPage.ContentProvider.ClassName then + begin + if fFirstSameTypePage = nil then fFirstSameTypePage:= fPage; + if fPage.ContentProvider.HasLoadedData(AURL) then // need to update data + break; + end; + fPage := nil; + end; + + if (fPage = nil) and (Assigned(fFirstSameTypePage) and (not fShowSepTabs)) then + begin // Page with data not found but exists the page with same type + fPage := fFirstSameTypePage; + end; + + if (fPage <> nil ) then // load or refresh a data within this page + begin + if fPage.ContentProvider.LoadURL(AURL, AContext) then + begin + PageControl.ActivePage := fPage; + Result := Ord(srSuccess); + end + else + begin + fPage := nil; + Result := Ord(srInvalidFile); + end; + end; + + if fPage = nil then + begin + // none existing page that can handle this content, so create one + fIsNewPage := true; + fPage := TContentTab.Create(PageControl); + fPage.ContentProvider := fRealContentProvider.Create(fPage, ImageList1, fUpdateCount); + fPage.ContentProvider.OnTitleChange := @ContentTitleChange; + //fPage.ContentProvider.OnContentComplete := @DoShowContent; + fPage.Parent := PageControl; + //SetKeyUp(fPage); + fPage.ContentProvider.LoadPreferences(fConfig); + if fPage.ContentProvider is TChmContentProvider then (fPage.ContentProvider as TChmContentProvider).ShowStatusbar := fShowStatus; - end; - if fUpdateCount > 0 then - fPage.ContentProvider.BeginUpdate; - - if fPage.ContentProvider.LoadURL(AURL, AContext) then - begin - PageControl.ActivePage := fPage; - RefreshState; - Result := Ord(srSuccess); - end - else begin - Result := Ord(srInvalidURL); - if fIsNewPage then - fPage.Free; - end; - - if not fHide then - ShowOnTop; + // BeginUpdate doing into Create + if fPage.ContentProvider.LoadURL(AURL, AContext) then + begin + PageControl.ActivePage := fPage; + RefreshState; + Result := Ord(srSuccess); + end + else + begin + Result := Ord(srInvalidURL); + if fIsNewPage then + fPage.Free; + end; + end; end; @@ -941,7 +1105,8 @@ begin // context shown fContext := -1; - Dispose(Url); + Finalize(Url^); + Freemem(Url); RefreshState; end; @@ -969,7 +1134,7 @@ begin end; end; end - else + else begin en := Assigned(ActivePage); // Show content page @@ -981,12 +1146,18 @@ begin Visible := true; TabsControl.Visible := true; Splitter.Visible := true; + ActivateProvider; end; end; end; - BackBttn.Enabled := en; - ForwardBttn.Enabled := en; + MiActionsGoBack.Enabled:= en; + MiActionsGoForward.Enabled:=en; + MiActionsGoHome.Enabled:=en; + MiActionsIndex.Enabled:=en; + MiActionsTOC.Enabled:=en; + MiActionsSearch.Enabled:=en; + HomeBttn.Enabled := en; FileMenuCloseItem.Enabled := en; ViewMenuContents.Enabled := en; @@ -1002,25 +1173,13 @@ begin ShowMessage(AError); end; -procedure THelpForm.SetKeyUp(AControl: TControl); -var - WCont: TWinControl absolute AControl; - i: Integer; -begin - if (AControl = nil) or not (AControl.InheritsFrom(TWinControl)) then - Exit; - for i := 0 to WCont.ControlCount-1 do - SetKeyUp(WCont.Controls[i]); - WCont.OnKeyUp:=@FormKeyUp; -end; - procedure THelpForm.BeginUpdate; var Tab: TContentTab; i: Integer; begin Inc(fUpdateCount); - if fUpdateCount = 1 then + //WriteLn(Format('>> fUpdateCount:=%d',[fUpdateCount])); begin for i := 0 to PageControl.PageCount-1 do begin @@ -1039,8 +1198,7 @@ begin Dec(fUpdateCount); if fUpdateCount < 0 then fUpdateCount:=0; - - if fUpdateCount = 0 then + //WriteLn(Format('<< fUpdateCount:=%d',[fUpdateCount ])); begin for i := 0 to PageControl.PageCount-1 do begin @@ -1050,6 +1208,28 @@ begin end; end; +procedure THelpForm.ShowApp(); +begin + if (fHide = false) then + begin + fMustClose:= false; + Application.Restore; + Application.BringToFront; +{$IFDEF WINDOWS} + // Go to TOC TreeView and to get focus on foreground window + KeyInput.Apply([ssCtrl]); + KeyInput.Press(VK_T); + KeyInput.UnApply([ssCtrl]); +{$ENDIF} + end; +end; + +procedure THelpForm.DoShowContent(Sender: Tobject); +begin + ShowApp(); +end; + + { TContentTab } constructor TContentTab.Create(AOwner: TComponent); diff --git a/components/chmhelp/lhelp/lhelpstrconsts.pas b/components/chmhelp/lhelp/lhelpstrconsts.pas index 64a60ca2a4..69007cbe3d 100644 --- a/components/chmhelp/lhelp/lhelpstrconsts.pas +++ b/components/chmhelp/lhelp/lhelpstrconsts.pas @@ -1,4 +1,4 @@ -unit lhelpstrconsts; +unit LHelpStrConsts; {$mode objfpc}{$H+} @@ -11,12 +11,13 @@ resourcestring slhelp_LHelpCHMFileViewerVersionCopyrightCAndrewHainesLaz = 'LHelp (CHM file viewer)%sVersion %s%sCopyright (C) Andrew Haines, %sLazarus contributors'; slhelp_Ok = 'Ok'; slhelp_PleaseEnterAURL = 'Please enter a URL'; - slhelp_SupportedURLTypeS = 'Supported URL type(s): (%s)'; + slhelp_SupportedURLTypeS = 'Supported URL type(s): [ %s ]'; slhelp_File = '&File'; slhelp_Open = '&Open ...'; slhelp_OpenRecent = 'Open Recent'; slhelp_OpenURL = 'Open &URL ...'; slhelp_Close = '&Close'; + slhelp_Hide = '&Hide'; slhelp_EXit = 'E&xit'; slhelp_View = '&View'; slhelp_ShowContents = 'Show contents'; @@ -46,6 +47,16 @@ resourcestring slhelp_SearchResults = 'Search Results:'; slhelp_Copy = 'Copy'; slhelp_PageCannotBeFound = 'Page cannot be found!'; + slhelp_CopyHtmlSource = 'Copy html source'; + slhelp_CloseConfirm = 'You can use the Esc to hide Help. Are you realy want to close lHelp?'; + + slhelp_Actions = '&Actions'; + slhelp_ActionsTOC = '&TOC'; + slhelp_ActionsIndex = 'Search by &index'; + slhelp_ActionsSearch = '&Search by text'; + slhelp_ActionsGoHome = 'Go home'; + slhelp_ActionsGoBack = 'Go back'; + slhelp_ActionsGoForward = 'Go forward'; // --help slhelp_LHelpOptions = ' LHelp options:'; diff --git a/components/chmhelp/packages/help/lazhelpchm.pas b/components/chmhelp/packages/help/lazhelpchm.pas index ebbaadb69f..0390100497 100644 --- a/components/chmhelp/packages/help/lazhelpchm.pas +++ b/components/chmhelp/packages/help/lazhelpchm.pas @@ -20,8 +20,13 @@ unit LazHelpCHM; interface uses - Classes, SysUtils, LazHelpIntf, LazConfigStorage, HelpIntfs, - Dialogs, Forms, LazLoggerBase, FileUtil, LazFileUtils, LHelpControl, LResources; + Classes, SysUtils, + // LCL + LazHelpIntf, HelpIntfs, LResources, Dialogs, Forms, + // LazUtils + LazConfigStorage, LazLoggerBase, FileUtil, LazFileUtils, + // ChmHelp + LHelpControl; const CHMMimeType = 'application/chm'; diff --git a/components/chmhelp/packages/help/lhelpcontrol.pas b/components/chmhelp/packages/help/lhelpcontrol.pas index 549eda48a8..00f4c2aaef 100644 --- a/components/chmhelp/packages/help/lhelpcontrol.pas +++ b/components/chmhelp/packages/help/lhelpcontrol.pas @@ -13,7 +13,9 @@ Currently, the only help viewer that supports this protocol is the lhelp CHM hel interface uses - Classes, SysUtils, LazFileUtils, LazLoggerBase, SimpleIPC, process, UTF8Process; + Classes, SysUtils, SimpleIPC, process, + // LazUtils + LazFileUtils, LazLoggerBase, UTF8Process; const PROTOCOL_VERSION='2'; //IDE<>LHelp communication protocol version. Please update when breaking compatibility diff --git a/components/chmhelp/packages/idehelp/lazchmhelp.pas b/components/chmhelp/packages/idehelp/lazchmhelp.pas index ab7a092dd4..e675adc8b7 100644 --- a/components/chmhelp/packages/idehelp/lazchmhelp.pas +++ b/components/chmhelp/packages/idehelp/lazchmhelp.pas @@ -29,7 +29,7 @@ interface uses Classes, SysUtils, // LazUtils - FileUtil, LazLogger, LazFileUtils, LazConfigStorage, UTF8Process, LazUTF8, + FileUtil, LazLoggerBase, LazFileUtils, LazConfigStorage, UTF8Process, LazUTF8, // LCL Controls, Forms, Dialogs, LazHelpIntf, HelpIntfs, LCLPlatformDef, InterfaceBase, // IdeIntf