From c878f10d36508b82835ef74e48d3e0e8584e22f0 Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Wed, 29 Jul 2026 18:20:49 +0200 Subject: [PATCH 1/6] Open help in the default browser, on the new unified guide The engine replaced its 18 GUI help pages with a single html/guide.html whose deep links look like guide.html#win/opt-limits. That page needs , CSS custom properties, grid and prefers-color-scheme, and the embedded WebBrowser control renders none of it: without a FEATURE_BROWSER_EMULATION registration it falls back to IE7 document mode. Help now opens in the system default browser, which takes CDialogHtmlHelp, CHtmlCtrl, CHtmlFrame and CHTMLHelp with it, along with their dialog, menu, toolbar and eight icons. The old Go() glued the doc directory to the page name and passed the result to Navigate2 as a bare DOS path. '#' is a legal NTFS filename character, so an anchor was as likely to be read as part of a filename as a fragment. BuildDocUrl() builds a real file:/// URL instead, percent-encoding the path as UTF-8 so a non-ASCII install directory survives and keeping the fragment whole. --selftest checks it against a space, a literal '#', a UNC path and an accented directory. Every help button still named a retired page, and each now names its guide anchor. The eleven option tabs were mapped from the redirect stubs the engine left behind, not from the tab order, which runs differently. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_012gAp9x4L95B8DkeuHQpuqg Signed-off-by: Xavier Roche --- WinHTTrack/DialogHtmlHelp.cpp | 299 ---------------------------------- WinHTTrack/DialogHtmlHelp.h | 106 ------------ WinHTTrack/HTMLHelp.cpp | 87 ---------- WinHTTrack/HTMLHelp.h | 89 ---------- WinHTTrack/HtmlCtrl.cpp | 97 ----------- WinHTTrack/HtmlCtrl.h | 41 ----- WinHTTrack/HtmlFrm.cpp | 141 ---------------- WinHTTrack/HtmlFrm.h | 34 ---- WinHTTrack/Infoend.cpp | 2 +- WinHTTrack/LaunchHelp.cpp | 123 ++++++++------ WinHTTrack/LaunchHelp.h | 21 ++- WinHTTrack/MainTab.cpp | 22 +-- WinHTTrack/NewProj.cpp | 2 +- WinHTTrack/Wid1.cpp | 2 +- WinHTTrack/WinHTTrack.cpp | 35 +++- WinHTTrack/WinHTTrack.rc | 54 ------ WinHTTrack/WinHTTrack.vcxproj | 16 -- WinHTTrack/res/icon1.ico | Bin 3006 -> 0 bytes WinHTTrack/res/icon2.ico | Bin 3006 -> 0 bytes WinHTTrack/res/icon3.ico | Bin 3006 -> 0 bytes WinHTTrack/res/icon4.ico | Bin 3006 -> 0 bytes WinHTTrack/res/icon5.ico | Bin 3006 -> 0 bytes WinHTTrack/res/icon6.ico | Bin 3006 -> 0 bytes WinHTTrack/res/idr_main.ico | Bin 8166 -> 0 bytes WinHTTrack/res/mainfram.bmp | Bin 718 -> 0 bytes WinHTTrack/resource.h | 14 -- 26 files changed, 137 insertions(+), 1048 deletions(-) delete mode 100755 WinHTTrack/DialogHtmlHelp.cpp delete mode 100644 WinHTTrack/DialogHtmlHelp.h delete mode 100644 WinHTTrack/HTMLHelp.cpp delete mode 100644 WinHTTrack/HTMLHelp.h delete mode 100755 WinHTTrack/HtmlCtrl.cpp delete mode 100644 WinHTTrack/HtmlCtrl.h delete mode 100644 WinHTTrack/HtmlFrm.cpp delete mode 100644 WinHTTrack/HtmlFrm.h delete mode 100644 WinHTTrack/res/icon1.ico delete mode 100644 WinHTTrack/res/icon2.ico delete mode 100644 WinHTTrack/res/icon3.ico delete mode 100644 WinHTTrack/res/icon4.ico delete mode 100644 WinHTTrack/res/icon5.ico delete mode 100644 WinHTTrack/res/icon6.ico delete mode 100644 WinHTTrack/res/idr_main.ico delete mode 100755 WinHTTrack/res/mainfram.bmp diff --git a/WinHTTrack/DialogHtmlHelp.cpp b/WinHTTrack/DialogHtmlHelp.cpp deleted file mode 100755 index d365f6f..0000000 --- a/WinHTTrack/DialogHtmlHelp.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/* ------------------------------------------------------------ */ -/* -HTTrack Website Copier, Offline Browser for Windows and Unix -Copyright (C) 1998 Xavier Roche and other contributors - -SPDX-License-Identifier: GPL-3.0-or-later - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Ethical use: we kindly ask that you NOT use this software to harvest email -addresses or to collect any other private information about people. Doing so -would dishonor our work and waste the many hours we have spent on it. - -Please visit our Website: http://www.httrack.com -*/ -// DialogHtmlHelp.cpp : implementation file -// - -#include "stdafx.h" -#include "Shell.h" -#include "DialogHtmlHelp.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -extern "C" { - #include "HTTrackInterface.h" - //#include "htsbase.h" -}; - -extern HICON httrack_icon; - -///////////////////////////////////////////////////////////////////////////// -// CDialogHtmlHelp dialog - - -CDialogHtmlHelp::CDialogHtmlHelp(CWnd* pParent /*=NULL*/) - : CDialog(CDialogHtmlHelp::IDD, pParent) -{ - page=""; - //{{AFX_DATA_INIT(CDialogHtmlHelp) - //}}AFX_DATA_INIT -} - - -void CDialogHtmlHelp::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CDialogHtmlHelp) - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CDialogHtmlHelp, CDialog) - //{{AFX_MSG_MAP(CDialogHtmlHelp) - ON_WM_SIZE() - ON_WM_CREATE() - ON_BN_CLICKED(IDC_BACK, OnBack) - ON_BN_CLICKED(IDC_FORWARD, OnForward) - ON_BN_CLICKED(IDC_STOP, OnStop) - ON_BN_CLICKED(IDC_RELOAD, OnReload) - ON_BN_CLICKED(IDC_HOME, OnHome) - ON_BN_CLICKED(ID_FILE_PRINT, OnFilePrint) - ON_WM_CLOSE() - //}}AFX_MSG_MAP - ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify ) - ON_COMMAND(ID_HELP_FINDER,OnHelpInfo2) - ON_COMMAND(ID_HELP,OnHelpInfo2) - ON_COMMAND(ID_DEFAULT_HELP,OnHelpInfo2) - ON_COMMAND(ID_BUTTON_HOME,OnHome) -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CDialogHtmlHelp message handlers - -BOOL CDialogHtmlHelp::OnInitDialog() -{ - CDialog::OnInitDialog(); - SetIcon(httrack_icon,false); - SetIcon(httrack_icon,true); - EnableToolTips(true); // TOOL TIPS - SetForegroundWindow(); // yop en premier plan! - - strcpybuff(home,"file://"); - { - char* a=home+strlen(home); - ::GetModuleFileName(NULL, a, (DWORD) ( sizeof(home)/sizeof(TCHAR) - 1 - strlen(home) )); - // strcatbuff(home,AfxGetApp()->m_pszHelpFilePath); - a = home + strlen(home) -1; - while( (*a!='\\') && ( a > home ) ) a--; - if (*a=='\\') { - *(a+1)='\0'; - } - strcatbuff(home,"html\\"); - strcpybuff(home_dir,home); - strcatbuff(home,"index.html"); - } - - // créer - if (m_page.CreateFromStatic(IDC_HTMLVIEW, this)) { - m_page.SetToolBar(false); - m_page.SetMenuBar(false); - m_page.SetStatusBar(false); - m_page.SetRegisterAsBrowser(false); - m_page.SetFullScreen(false); - if (page.GetLength()==0) - OnHome(); - else - Go(page); - UpdateWindow(); - } else { - EndDialog(IDCANCEL); - if (!ShellOpen(home+strlen("file://"), SW_RESTORE)) - AfxMessageBox(LANG(LANG_DIAL1)); - } - return TRUE; -} - -// Resize -void CDialogHtmlHelp::OnSize(UINT nType, int cx, int cy) -{ - CDialog::OnSize(nType, cx, cy); - - HWND ip = ::GetDlgItem(this->m_hWnd,IDC_HTMLVIEW); - if (ip) { - int w,h; - RECT rect; - ::GetWindowRect(ip,&rect); - // screen coord -> client coord - POINT a,b; - a.x=rect.left; a.y=rect.top; b.x=rect.right; b.y=rect.bottom; - ::ScreenToClient(this->m_hWnd,&a); ::ScreenToClient(this->m_hWnd,&b); - rect.left=a.x; rect.top=a.y; rect.right=b.x; rect.bottom=b.y; - w = max(cx - rect.left,320); - h = max(cy - rect.top,200); - ::SetWindowPos(ip,NULL,0,0,w,h,SWP_NOZORDER|SWP_NOMOVE|SWP_NOOWNERZORDER); - //base.OnSizeCallback(this,nType,cx,cy); - } -} - -int CDialogHtmlHelp::OnCreate(LPCREATESTRUCT lpCreateStruct) -{ - if (CDialog::OnCreate(lpCreateStruct) == -1) - return -1; - - /* - if (!m_wndToolBar.Create(this)) - return -1; // fail to create - if (!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) - return -1; // fail to create - - // TODO: Remove this if you don't want tool tips or a resizeable toolbar - m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | - CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); - */ - - return 0; -} - -// help de l'help.. -// Appel aide -void CDialogHtmlHelp::OnHelpInfo2() { - (void)OnHelpInfo(NULL); -} - -BOOL CDialogHtmlHelp::OnHelpInfo(HELPINFO* dummy) -{ - return true; -} - - -// Home -void CDialogHtmlHelp::OnHome() { - m_page.Navigate2(home); - m_page.ShowWindow(SW_SHOW); - this->GetDlgItem(IDC_HTMLVIEW)->SetFocus(); -} - -void CDialogHtmlHelp::Go(CString st) { - if (st.Left(7)!="http://") { - char tempo[1024]; - strcpybuff(tempo,home_dir); - strcatbuff(tempo,st); - m_page.Navigate2(tempo); - } else - m_page.Navigate2(st); - m_page.ShowWindow(SW_SHOW); - this->GetDlgItem(IDC_HTMLVIEW)->SetFocus(); -} - -void CDialogHtmlHelp::OnBack() -{ - m_page.GoBack(); - this->GetDlgItem(IDC_HTMLVIEW)->SetFocus(); -} - -void CDialogHtmlHelp::OnForward() -{ - m_page.GoForward(); - this->GetDlgItem(IDC_HTMLVIEW)->SetFocus(); -} - -void CDialogHtmlHelp::OnStop() -{ - m_page.Stop(); - this->GetDlgItem(IDC_HTMLVIEW)->SetFocus(); -} - -void CDialogHtmlHelp::OnReload() -{ - m_page.Refresh(); - this->GetDlgItem(IDC_HTMLVIEW)->SetFocus(); -} - -void CDialogHtmlHelp::OnFilePrint() -{ - this->GetDlgItem(IDC_HTMLVIEW)->SendMessage(WM_COMMAND,ID_FILE_PRINT,NULL); - this->GetDlgItem(IDC_HTMLVIEW)->SetFocus(); -} - - -// ------------------------------------------------------------ -// TOOL TIPS -// -// ajouter dans le .cpp: -// remplacer les deux Wid1:: par le nom de la classe:: -// dans la message map, ajouter -// ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify ) -// dans initdialog ajouter -// EnableToolTips(true); // TOOL TIPS -// -// ajouter dans le .h: -// char* GetTip(int id); -// et en generated message map -// afx_msg BOOL OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult ); -BOOL CDialogHtmlHelp::OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult ) -{ - TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR; - UINT_PTR nID =pNMHDR->idFrom; - if (pTTT->uFlags & TTF_IDISHWND) - { - // idFrom is actually the HWND of the tool - nID = ::GetDlgCtrlID((HWND)nID); - if(nID) - { - const char* st=GetTip((int)nID); - if (st != NULL && *st) { - pTTT->lpszText = (LPSTR)st; - pTTT->hinst = AfxGetResourceHandle(); - return(TRUE); - } - } - } - return(FALSE); -} -const char* CDialogHtmlHelp::GetTip(int ID) -{ - switch(ID) { - case IDCANCEL: return LANG(LANG_B3); /*"Cancel","Annuler");*/ break; - case IDOK: return LANG(LANG_B4); /*"Add this filter","Ajouter cette règle");*/ break; - } - return ""; -} -// TOOL TIPS -// ------------------------------------------------------------ - - -BOOL CDialogHtmlHelp::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) -{ - // TODO: Add your specialized code here and/or call the base class - - dwStyle|=(WS_OVERLAPPEDWINDOW); - dwStyle&=~(WS_CHILD); - pParentWnd=NULL; - return CDialog::Create(IDD, pParentWnd); - //ModifyStyleEx(WS_EX_TOPMOST,0); - //SetWindowPos(&wndBottom,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); -} - -/* Auto-destruction! */ -void CDialogHtmlHelp::OnClose() -{ - ///CDialog::OnClose(); - int r=CDialog::DestroyWindow(); -} diff --git a/WinHTTrack/DialogHtmlHelp.h b/WinHTTrack/DialogHtmlHelp.h deleted file mode 100644 index c615e2e..0000000 --- a/WinHTTrack/DialogHtmlHelp.h +++ /dev/null @@ -1,106 +0,0 @@ -/* ------------------------------------------------------------ */ -/* -HTTrack Website Copier, Offline Browser for Windows and Unix -Copyright (C) 1998 Xavier Roche and other contributors - -SPDX-License-Identifier: GPL-3.0-or-later - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Ethical use: we kindly ask that you NOT use this software to harvest email -addresses or to collect any other private information about people. Doing so -would dishonor our work and waste the many hours we have spent on it. - -Please visit our Website: http://www.httrack.com -*/ -#if !defined(AFX_DIALOGHTMLHELP_H__FED0CE81_AB10_11D3_A2B3_0000E84E7CA1__INCLUDED_) -#define AFX_DIALOGHTMLHELP_H__FED0CE81_AB10_11D3_A2B3_0000E84E7CA1__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// DialogHtmlHelp.h : header file -// - -#include "resource.h" -//#include "LaunchHelpBase.h" -#include "HtmlCtrl.h" - -// type callback -typedef void (* Helper_CallBack ) (CWnd*); -typedef void (* OnSize_CallBack ) (CWnd*,UINT nType, int cx, int cy); - -///////////////////////////////////////////////////////////////////////////// -// CDialogHtmlHelp dialog - -class CDialogHtmlHelp : public CDialog -{ -// Construction -public: - void Go(CString st); - CDialogHtmlHelp(CWnd* pParent = NULL); // standard constructor - Helper_CallBack callback; - OnSize_CallBack callbackOnSize; - const char* GetTip(int id); - // - CString page; -protected: - CHtmlCtrl m_page; - CToolBar m_wndToolBar; - char home[1024]; - char home_dir[1024]; -//private: -// LaunchHelpBase base; - -// Dialog Data - //{{AFX_DATA(CDialogHtmlHelp) - enum { IDD = IDD_HtmlHelp }; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CDialogHtmlHelp) - public: - virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL); - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - afx_msg BOOL OnHelpInfo(HELPINFO* dummy); - afx_msg BOOL OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult ); - -// Implementation -protected: - void OnHelpInfo2(); - - // Generated message map functions - //{{AFX_MSG(CDialogHtmlHelp) - virtual BOOL OnInitDialog(); - afx_msg void OnSize(UINT nType, int cx, int cy); - afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); - afx_msg void OnBack(); - afx_msg void OnForward(); - afx_msg void OnStop(); - afx_msg void OnReload(); - afx_msg void OnHome(); - afx_msg void OnFilePrint(); - afx_msg void OnClose(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_DIALOGHTMLHELP_H__FED0CE81_AB10_11D3_A2B3_0000E84E7CA1__INCLUDED_) diff --git a/WinHTTrack/HTMLHelp.cpp b/WinHTTrack/HTMLHelp.cpp deleted file mode 100644 index ebdb6a5..0000000 --- a/WinHTTrack/HTMLHelp.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* ------------------------------------------------------------ */ -/* -HTTrack Website Copier, Offline Browser for Windows and Unix -Copyright (C) 1998 Xavier Roche and other contributors - -SPDX-License-Identifier: GPL-3.0-or-later - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Ethical use: we kindly ask that you NOT use this software to harvest email -addresses or to collect any other private information about people. Doing so -would dishonor our work and waste the many hours we have spent on it. - -Please visit our Website: http://www.httrack.com -*/ -// HTMLHelp.cpp : implementation file -// - -#include "stdafx.h" -#include "winhttrack.h" -#include "HTMLHelp.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// CHTMLHelp - -IMPLEMENT_DYNCREATE(CHTMLHelp, CHtmlView) - -CHTMLHelp::CHTMLHelp() -{ - //{{AFX_DATA_INIT(CHTMLHelp) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -CHTMLHelp::~CHTMLHelp() -{ -} - -void CHTMLHelp::DoDataExchange(CDataExchange* pDX) -{ - CHtmlView::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CHTMLHelp) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CHTMLHelp, CHtmlView) - //{{AFX_MSG_MAP(CHTMLHelp) - // NOTE - the ClassWizard will add and remove mapping macros here. - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CHTMLHelp diagnostics - -#ifdef _DEBUG -void CHTMLHelp::AssertValid() const -{ - CHtmlView::AssertValid(); -} - -void CHTMLHelp::Dump(CDumpContext& dc) const -{ - CHtmlView::Dump(dc); -} -#endif //_DEBUG - -///////////////////////////////////////////////////////////////////////////// -// CHTMLHelp message handlers diff --git a/WinHTTrack/HTMLHelp.h b/WinHTTrack/HTMLHelp.h deleted file mode 100644 index b4720b8..0000000 --- a/WinHTTrack/HTMLHelp.h +++ /dev/null @@ -1,89 +0,0 @@ -/* ------------------------------------------------------------ */ -/* -HTTrack Website Copier, Offline Browser for Windows and Unix -Copyright (C) 1998 Xavier Roche and other contributors - -SPDX-License-Identifier: GPL-3.0-or-later - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Ethical use: we kindly ask that you NOT use this software to harvest email -addresses or to collect any other private information about people. Doing so -would dishonor our work and waste the many hours we have spent on it. - -Please visit our Website: http://www.httrack.com -*/ -#if !defined(AFX_HTMLHELP_H__CA6ABCFD_0D37_4DC2_A214_AD0BB7AFBBD5__INCLUDED_) -#define AFX_HTMLHELP_H__CA6ABCFD_0D37_4DC2_A214_AD0BB7AFBBD5__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// HTMLHelp.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CHTMLHelp html view - -#ifndef __AFXEXT_H__ -#include -#endif -#include - -class CHTMLHelp : public CHtmlView -{ -public: - CHTMLHelp(); // protected constructor used by dynamic creation - DECLARE_DYNCREATE(CHTMLHelp) - -// html Data -public: - //{{AFX_DATA(CHTMLHelp) - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA - -// Attributes -public: - -// Operations -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CHTMLHelp) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -public: - virtual ~CHTMLHelp(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - - // Generated message map functions - //{{AFX_MSG(CHTMLHelp) - // NOTE - the ClassWizard will add and remove member functions here. - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_HTMLHELP_H__CA6ABCFD_0D37_4DC2_A214_AD0BB7AFBBD5__INCLUDED_) diff --git a/WinHTTrack/HtmlCtrl.cpp b/WinHTTrack/HtmlCtrl.cpp deleted file mode 100755 index 2214f54..0000000 --- a/WinHTTrack/HtmlCtrl.cpp +++ /dev/null @@ -1,97 +0,0 @@ -//////////////////////////////////////////////////////////////// -// Microsoft Systems Journal -- December 1999 -// If this code works, it was written by Paul DiLascia. -// If not, I don't know who wrote it. -// Compiles with Visual C++ 6.0, runs on Windows 98 and probably NT too. -// -#include "StdAfx.h" -#include "HtmlCtrl.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -IMPLEMENT_DYNAMIC(CHtmlCtrl, CHtmlView) -BEGIN_MESSAGE_MAP(CHtmlCtrl, CHtmlView) - ON_WM_DESTROY() - ON_WM_MOUSEACTIVATE() -END_MESSAGE_MAP() - -////////////////// -// Create control in same position as an existing static control with -// the same ID (could be any kind of control, really) -// -BOOL CHtmlCtrl::CreateFromStatic(UINT nID, CWnd* pParent) -{ - CStatic wndStatic; - if (!wndStatic.SubclassDlgItem(nID, pParent)) - return FALSE; - - // Get static control rect, convert to parent's client coords. - CRect rc; - wndStatic.GetWindowRect(&rc); - pParent->ScreenToClient(&rc); - wndStatic.DestroyWindow(); - - // create HTML control (CHtmlView) - return Create(NULL, // class name - NULL, // title - (WS_CHILD | WS_VISIBLE ), // style - rc, // rectangle - pParent, // parent - nID, // control ID - NULL); // frame/doc context not used -} - -//////////////// -// Override to avoid CView stuff that assumes a frame. -// -void CHtmlCtrl::OnDestroy() -{ - // This is probably unecessary since ~CHtmlView does it, but - // safer to mimic CHtmlView::OnDestroy. - if (m_pBrowserApp) { - m_pBrowserApp.Release(); - } - CWnd::OnDestroy(); // bypass CView doc/frame stuff -} - -//////////////// -// Override to avoid CView stuff that assumes a frame. -// -int CHtmlCtrl::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT msg) -{ - // bypass CView doc/frame stuff - return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, msg); -} - -////////////////// -// Override navigation handler to pass to "app:" links to virtual handler. -// Cancels the navigation in the browser, since app: is a pseudo-protocol. -// -void CHtmlCtrl::OnBeforeNavigate2( LPCTSTR lpszURL, - DWORD nFlags, - LPCTSTR lpszTargetFrameName, - CByteArray& baPostedData, - LPCTSTR lpszHeaders, - BOOL* pbCancel ) -{ - const char APP_PROTOCOL[] = "app:"; - int len = (int) _tcslen(APP_PROTOCOL); - if (_tcsnicmp(lpszURL, APP_PROTOCOL, len)==0) { - OnAppCmd(lpszURL + len); - *pbCancel = TRUE; - } -} - -////////////////// -// Called when the browser attempts to navigate to "app:foo" -// with "foo" as lpszWhere. Override to handle app commands. -// -void CHtmlCtrl::OnAppCmd(LPCTSTR lpszWhere) -{ - // default: do nothing -} - diff --git a/WinHTTrack/HtmlCtrl.h b/WinHTTrack/HtmlCtrl.h deleted file mode 100644 index afe0334..0000000 --- a/WinHTTrack/HtmlCtrl.h +++ /dev/null @@ -1,41 +0,0 @@ -//////////////////////////////////////////////////////////////// -// Microsoft Systems Journal -- December 1999 -// If this code works, it was written by Paul DiLascia. -// If not, I don't know who wrote it. -// Compiles with Visual C++ 6.0, runs on Windows 98 and probably NT too. -// - -#include - -class CHtmlCtrl : public CHtmlView { -public: - CHtmlCtrl() { } - ~CHtmlCtrl() { } - - BOOL CreateFromStatic(UINT nID, CWnd* pParent); - - // Normally, CHtmlView destroys itself in PostNcDestroy, - // but we don't want to do that for a control since a control - // is usually implemented as a stack object in a dialog. - // - virtual void PostNcDestroy() { } - - // overrides to bypass MFC doc/view frame dependencies - afx_msg void OnDestroy(); - afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT msg); - - // override to trap "app:" pseudo protocol - virtual void OnBeforeNavigate2( LPCTSTR lpszURL, - DWORD nFlags, - LPCTSTR lpszTargetFrameName, - CByteArray& baPostedData, - LPCTSTR lpszHeaders, - BOOL* pbCancel ); - - // override to handle links to "app:mumble...". lpszWhere will be "mumble" - virtual void OnAppCmd(LPCTSTR lpszWhere); - - DECLARE_MESSAGE_MAP(); - DECLARE_DYNAMIC(CHtmlCtrl) -}; - diff --git a/WinHTTrack/HtmlFrm.cpp b/WinHTTrack/HtmlFrm.cpp deleted file mode 100644 index ece6dab..0000000 --- a/WinHTTrack/HtmlFrm.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* ------------------------------------------------------------ */ -/* -HTTrack Website Copier, Offline Browser for Windows and Unix -Copyright (C) 1998 Xavier Roche and other contributors - -SPDX-License-Identifier: GPL-3.0-or-later - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Ethical use: we kindly ask that you NOT use this software to harvest email -addresses or to collect any other private information about people. Doing so -would dishonor our work and waste the many hours we have spent on it. - -Please visit our Website: http://www.httrack.com -*/ -// mainfrm.cpp : implementation of the CHtmlFrame class -// - - -#include "stdafx.h" -#include "htmlfrm.h" -#include "resource.h" - -#include "HTMLHelp.h" - - -IMPLEMENT_DYNCREATE(CHtmlFrame, CMDIFrameWnd) -BEGIN_MESSAGE_MAP(CHtmlFrame, CMDIFrameWnd) - //{{AFX_MSG_MAP(CHtmlFrame) - ON_WM_CREATE() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -static UINT BASED_CODE buttons[] = -{ - // same order as in the bitmap 'toolbar.bmp' - ID_FILE_NEW, ID_FILE_OPEN, ID_FILE_SAVE, 0, - ID_EDIT_CUT, ID_EDIT_COPY, ID_EDIT_PASTE, 0, - ID_FILE_PRINT, ID_APP_ABOUT, -}; - -static UINT BASED_CODE indicators[] = -{ - 0, ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_SCRL, -}; - -int CHtmlFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) -{ - if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) - return -1; - - /* - if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP - | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || - !m_wndToolBar.LoadToolBar(IDR_HELPFRM)) - { - TRACE0("Failed to create toolbar\n"); - return -1; // fail to create - } -*/ - - if (!m_wndStatusBar.Create(this) || - !m_wndStatusBar.SetIndicators(indicators, - sizeof(indicators)/sizeof(UINT))) - { - TRACE0("Failed to create status bar\n"); - return -1; // fail to create - } - - // TODO: Delete these three lines if you don't want the toolbar to - // be dockable -/* - m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); - EnableDocking(CBRS_ALIGN_ANY); - DockControlBar(&m_wndToolBar); - */ - - CHTMLHelp foo; - RECT toto; - toto.bottom=toto.right=0; - toto.top=toto.left=600; - foo.Create(NULL,NULL,WS_CHILD,toto,this,0); - //SetActiveView(&foo); - - return 0; -} - -///////////////////////////////////////////////////////////////////////////// -// Helpers for saving/restoring window state - -static TCHAR BASED_CODE szSection[] = _T("Settings"); -static TCHAR BASED_CODE szWindowPos[] = _T("WindowPos"); -static TCHAR szFormat[] = _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"); - -static BOOL PASCAL NEAR ReadWindowPlacement(LPWINDOWPLACEMENT pwp) -{ - CString strBuffer = AfxGetApp()->GetProfileString(szSection, szWindowPos); - if (strBuffer.IsEmpty()) - return FALSE; - - WINDOWPLACEMENT wp; - int nRead = _stscanf(strBuffer, szFormat, - &wp.flags, &wp.showCmd, - &wp.ptMinPosition.x, &wp.ptMinPosition.y, - &wp.ptMaxPosition.x, &wp.ptMaxPosition.y, - &wp.rcNormalPosition.left, &wp.rcNormalPosition.top, - &wp.rcNormalPosition.right, &wp.rcNormalPosition.bottom); - - if (nRead != 10) - return FALSE; - - wp.length = sizeof wp; - *pwp = wp; - return TRUE; -} - -static void PASCAL NEAR WriteWindowPlacement(LPWINDOWPLACEMENT pwp) - // write a window placement to settings section of app's ini file -{ - TCHAR szBuffer[sizeof("-32767")*8 + sizeof("65535")*2]; - - wsprintf(szBuffer, szFormat, - pwp->flags, pwp->showCmd, - pwp->ptMinPosition.x, pwp->ptMinPosition.y, - pwp->ptMaxPosition.x, pwp->ptMaxPosition.y, - pwp->rcNormalPosition.left, pwp->rcNormalPosition.top, - pwp->rcNormalPosition.right, pwp->rcNormalPosition.bottom); - AfxGetApp()->WriteProfileString(szSection, szWindowPos, szBuffer); -} - diff --git a/WinHTTrack/HtmlFrm.h b/WinHTTrack/HtmlFrm.h deleted file mode 100644 index 713f857..0000000 --- a/WinHTTrack/HtmlFrm.h +++ /dev/null @@ -1,34 +0,0 @@ -// mainfrm.h : interface of the CHtmlFrame class -// -// This is a part of the Microsoft Foundation Classes C++ library. -// Copyright (C) 1992-1998 Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Microsoft Foundation Classes Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Microsoft Foundation Classes product. - - - -#ifndef __AFXEXT_H__ -#include // for access to CToolBar and CStatusBar -#endif - -class CHtmlFrame : public CMDIFrameWnd -{ - DECLARE_DYNCREATE(CHtmlFrame) - -protected: - CStatusBar m_wndStatusBar; -// CToolBar m_wndToolBar; - -protected: - //{{AFX_MSG(CHtmlFrame) - afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -///////////////////////////////////////////////////////////////////////////// diff --git a/WinHTTrack/Infoend.cpp b/WinHTTrack/Infoend.cpp index 14954e5..8157ccd 100755 --- a/WinHTTrack/Infoend.cpp +++ b/WinHTTrack/Infoend.cpp @@ -247,7 +247,7 @@ void Cinfoend::OnHelpInfo2() { BOOL Cinfoend::OnHelpInfo(HELPINFO* dummy) { //return CPropertyPage::OnHelpInfo(pHelpInfo); - HtsHelper->Help("step5.html"); + HtsHelper->HelpTopic("step-done"); return true; //AfxGetApp()->WinHelp(0,HELP_FINDER); // Index du fichier Hlp //return true; diff --git a/WinHTTrack/LaunchHelp.cpp b/WinHTTrack/LaunchHelp.cpp index 1fe5749..7847824 100644 --- a/WinHTTrack/LaunchHelp.cpp +++ b/WinHTTrack/LaunchHelp.cpp @@ -28,63 +28,94 @@ Please visit our Website: http://www.httrack.com // #include "stdafx.h" - -/* Must follow the PCH include: anything before it is discarded, so defining - this above would silently do nothing. */ -#define VIEW_HELP 0 #include "LaunchHelp.h" -#include "DialogHtmlHelp.h" -#include "process.h" +#include "Shell.h" -#if VIEW_HELP -#include "htmlfrm.h" -#endif +/* The guide is shared with WebHTTrack and Android; the platform in the fragment is + what selects our screenshots. */ +#define DOC_GUIDE "guide.html#win" -LaunchHelp::LaunchHelp() { - page=""; +/* Unreserved, plus ':' and '/' so the drive letter and the separators survive. */ +static bool IsUrlSafe(unsigned char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') + || c == '-' || c == '_' || c == '.' || c == '~' || c == '/' || c == ':'; } -LaunchHelp::~LaunchHelp() { - if (b.m_hWnd) { - b.EndDialog(IDCANCEL); + +static void AppendEscaped(CString& url, const char* s) { + for(; *s != '\0' ; s++) { + const unsigned char c = (unsigned char) *s; + if (IsUrlSafe(c)) { + url += (char) c; + } else { + char hex[4]; + sprintfbuff(hex, "%%%02X", c); + url += hex; + } } } -void LaunchHelp::Help(CString page) { -#if VIEW_HELP -#else - if (!b) - this->page=page; - else { - if (b.m_hWnd) - this->b.Go(page); - else - this->page=page; +// Contract in LaunchHelp.h. +bool BuildDocUrl(const char* dir, const char* page, CString& url) { + const char* const frag = strchr(page, '#'); + CString path(dir); + path += (frag != NULL) ? CString(page, (int) (frag - page)) : CString(page); + path.Replace('\\', '/'); + + /* A browser reads a file: URL's escaped bytes as UTF-8, not as our ANSI codepage. */ + char* utf8 = strdupt_utf8(path); /* freet() nulls it, so not const */ + if (utf8 == NULL) + return false; + /* A UNC path is already rooted at "//server", so it takes two slashes, not three. */ + url = (utf8[0] == '/' && utf8[1] == '/') ? "file:" : "file:///"; + AppendEscaped(url, utf8); + freet(utf8); + + if (frag != NULL) { + url += '#'; + AppendEscaped(url, frag + 1); } -#endif - GoHelp(); + return true; } -void LaunchHelp::Help() { - Help("index.html"); +/* The doc tree sits beside the executable, where the installer stages it. */ +static bool DocDir(char* dir, size_t size) { + const DWORD n = ::GetModuleFileName(NULL, dir, (DWORD) size); + if (n == 0 || n >= size) /* n == size on truncation, which leaves dir unterminated */ + return false; + char* p = dir + n; + while(p > dir && p[-1] != '\\' && p[-1] != '/') + p--; + if ((size_t) (p - dir) + sizeof("html\\") > size) + return false; + memcpy(p, "html\\", sizeof("html\\")); + return true; } - -void LaunchHelp::GoHelp() { -#if VIEW_HELP - CHtmlFrame* frm=new CHtmlFrame; - if (!frm->LoadFrame(IDR_HELPFRM)) - return; - frm->ShowWindow(SW_SHOWNORMAL); - frm->UpdateWindow(); -#else - if (!b.m_hWnd) { - b.page=page; - RECT rect; - rect.bottom=rect.left=rect.right=rect.top=0; - b.Create(NULL,NULL,WS_OVERLAPPEDWINDOW,rect,NULL,0); - b.ShowWindow(SW_SHOWNORMAL); - } else { - b.SetForegroundWindow(); + +void LaunchHelp::Help(CString page) { + /* The update check hands us a real URL; everything else names a page in html/. */ + if (page.Left(7) == "http://" || page.Left(8) == "https://") { + if (!ShellOpen(page, SW_SHOWNORMAL)) + AfxMessageBox(LANG(LANG_DIAL1)); + return; } -#endif + + char dir[1024]; + CString url; + if (!DocDir(dir, sizeof(dir)) || !BuildDocUrl(dir, page, url) + || !ShellOpen(url, SW_SHOWNORMAL)) + AfxMessageBox(LANG(LANG_DIAL1)); +} + +void LaunchHelp::HelpTopic(const char* anchor) { + CString page(DOC_GUIDE); + if (anchor != NULL && *anchor != '\0') { + page += '/'; + page += anchor; + } + Help(page); +} + +void LaunchHelp::Help() { + HelpTopic(NULL); } diff --git a/WinHTTrack/LaunchHelp.h b/WinHTTrack/LaunchHelp.h index 773b807..83c5d93 100644 --- a/WinHTTrack/LaunchHelp.h +++ b/WinHTTrack/LaunchHelp.h @@ -29,20 +29,23 @@ Please visit our Website: http://www.httrack.com #define LAUNCHHELP_HGDHDGCJHHFIJKCHSOZIOJC5448545245451 #include "stdafx.h" -#include "DialogHtmlHelp.h" -//UINT RunBackHelp( LPVOID pP ); -// Lancer aide +// Build a browsable URL for a documentation page: dir is the ANSI directory holding it, +// page is "guide.html" or "guide.html#win/opt-limits". The path is percent-encoded as +// UTF-8 and the fragment kept whole, so '#' arrives as a fragment and not as the filename +// character NTFS also allows it to be. False if the path cannot be encoded. Help callers +// go through LaunchHelp; this is public for --selftest. +bool BuildDocUrl(const char* dir, const char* page, CString& url); + +// Opens the documentation in the system default browser. class LaunchHelp { public: - LaunchHelp(); - ~LaunchHelp(); + // The guide, at the top of the Windows walkthrough. void Help(); + // A page under html/, or an absolute http/https URL, which is opened untouched. void Help(CString page); - CDialogHtmlHelp b; - CString page; -private: - void GoHelp(); + // The guide, scrolled to one of its Windows sections, e.g. "opt-limits". + void HelpTopic(const char* anchor); }; #endif diff --git a/WinHTTrack/MainTab.cpp b/WinHTTrack/MainTab.cpp index c96c94b..7769130 100755 --- a/WinHTTrack/MainTab.cpp +++ b/WinHTTrack/MainTab.cpp @@ -242,27 +242,27 @@ BOOL CMainTab::OnHelpInfo(HELPINFO* dummy) //LaunchHelp(pHelpInfo); if (this->GetActivePage() == &m_option1) - HtsHelper->Help("step9_opt1.html"); + HtsHelper->HelpTopic("opt-links"); else if (this->GetActivePage() == &m_option5) - HtsHelper->Help("step9_opt2.html"); + HtsHelper->HelpTopic("opt-limits"); else if (this->GetActivePage() == &m_option4) - HtsHelper->Help("step9_opt3.html"); + HtsHelper->HelpTopic("opt-flow-control"); else if (this->GetActivePage() == &m_option7) - HtsHelper->Help("step9_opt4.html"); + HtsHelper->HelpTopic("opt-scan-rules"); else if (this->GetActivePage() == &m_option2) - HtsHelper->Help("step9_opt5.html"); + HtsHelper->HelpTopic("opt-build"); else if (this->GetActivePage() == &m_option8) - HtsHelper->Help("step9_opt6.html"); + HtsHelper->HelpTopic("opt-spider"); else if (this->GetActivePage() == &m_option10) - HtsHelper->Help("step9_opt7.html"); + HtsHelper->HelpTopic("opt-proxy"); else if (this->GetActivePage() == &m_option6) - HtsHelper->Help("step9_opt8.html"); + HtsHelper->HelpTopic("opt-browser-id"); else if (this->GetActivePage() == &m_option9) - HtsHelper->Help("step9_opt9.html"); + HtsHelper->HelpTopic("opt-log-index-cache"); else if (this->GetActivePage() == &m_option3) - HtsHelper->Help("step9_opt10.html"); + HtsHelper->HelpTopic("opt-experts-only"); else if (this->GetActivePage() == &m_option11) - HtsHelper->Help("step9_opt11.html"); + HtsHelper->HelpTopic("opt-mime-types"); else HtsHelper->Help(); return true; diff --git a/WinHTTrack/NewProj.cpp b/WinHTTrack/NewProj.cpp index c36e4bf..8ad8e4a 100755 --- a/WinHTTrack/NewProj.cpp +++ b/WinHTTrack/NewProj.cpp @@ -512,7 +512,7 @@ BOOL CNewProj::OnHelpInfo(HELPINFO* dummy) { //return CPropertyPage::OnHelpInfo(pHelpInfo); //AfxGetApp()->WinHelp(0,HELP_FINDER); // Index du fichier Hlp - HtsHelper->Help("step1.html"); + HtsHelper->HelpTopic("step-project"); //HtsHelper->Help(); return true; } diff --git a/WinHTTrack/Wid1.cpp b/WinHTTrack/Wid1.cpp index 4cd6d9d..f7861be 100755 --- a/WinHTTrack/Wid1.cpp +++ b/WinHTTrack/Wid1.cpp @@ -712,7 +712,7 @@ BOOL Wid1::OnHelpInfo(HELPINFO* dummy) //return CPropertyPage::OnHelpInfo(pHelpInfo); //AfxGetApp()->WinHelp(0,HELP_FINDER); // Index du fichier Hlp //LaunchHelp(pHelpInfo); - HtsHelper->Help("step2.html"); + HtsHelper->HelpTopic("step-address"); //HtsHelper->Help(); return true; } diff --git a/WinHTTrack/WinHTTrack.cpp b/WinHTTrack/WinHTTrack.cpp index 1529156..4233a72 100755 --- a/WinHTTrack/WinHTTrack.cpp +++ b/WinHTTrack/WinHTTrack.cpp @@ -330,7 +330,40 @@ BOOL CWinHTTrackApp::InitInstance() } freet(got); printf("MBCS->UTF-8 ok\n"); + /* The install path is where a non-ASCII byte reaches the help URL. */ + { + char dir[64]; + CString url; + sprintfbuff(dir, "C:\\%s\\html\\", ansi); + if (!BuildDocUrl(dir, "guide.html", url) || url != "file:///C:/caf%C3%A9/html/guide.html") { + fprintf(stderr, "FATAL: non-ASCII help path gave '%s'\n", (LPCSTR) url); + fflush(stderr); + ExitProcess(3); + } + } + } + } + /* An unescaped space truncates the path, and an unescaped '#' names a file rather + than a section, since NTFS allows one in a filename. */ + { + static const struct { const char* dir; const char* page; const char* want; } urls[] = { + { "C:\\Program Files\\WinHTTrack\\html\\", "guide.html#win/opt-limits", + "file:///C:/Program%20Files/WinHTTrack/html/guide.html#win/opt-limits" }, + { "C:\\h\\", "guide.html", "file:///C:/h/guide.html" }, + { "C:\\a#b\\", "guide.html#win", "file:///C:/a%23b/guide.html#win" }, + { "\\\\srv\\share\\html\\", "guide.html#win", "file://srv/share/html/guide.html#win" }, + { NULL, NULL, NULL } + }; + for(int k=0 ; urls[k].dir != NULL ; k++) { + CString url; + if (!BuildDocUrl(urls[k].dir, urls[k].page, url) || url != urls[k].want) { + fprintf(stderr, "FATAL: help URL for '%s%s' is '%s', expected '%s'\n", + urls[k].dir, urls[k].page, (LPCSTR) url, urls[k].want); + fflush(stderr); + ExitProcess(3); + } } + printf("help URLs ok\n"); } int nlangs = 0; /* Walk the languages as the About box does: losing LANG_LOAD()'s empty-name @@ -922,7 +955,7 @@ void CWinHTTrackApp::OnHelpInfo2() { BOOL CWinHTTrackApp::OnHelpInfo(HELPINFO* dummy) { - HtsHelper->Help("step2.html"); + HtsHelper->HelpTopic("step-address"); return true; } diff --git a/WinHTTrack/WinHTTrack.rc b/WinHTTrack/WinHTTrack.rc index deb132c..06918af 100755 --- a/WinHTTrack/WinHTTrack.rc +++ b/WinHTTrack/WinHTTrack.rc @@ -30,13 +30,6 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // remains consistent on all systems. IDR_MAINFRAME ICON "res\\Shell.ico" IDR_WINHTTTYPE ICON "res\\Shell.ico" -IDI_BACK ICON "res\\icon1.ico" -IDI_FORWARD ICON "res\\icon2.ico" -IDI_STOP ICON "res\\icon3.ico" -IDI_RELOAD ICON "res\\icon4.ico" -IDI_HOME ICON "res\\icon5.ico" -IDI_PRINT ICON "res\\icon6.ico" -IDR_HELPFRM ICON "res\\idr_main.ico" ///////////////////////////////////////////////////////////////////////////// // @@ -44,7 +37,6 @@ IDR_HELPFRM ICON "res\\idr_main.ico" // IDR_MAINFRAME BITMAP "res\\Toolbar.bmp" -IDR_HELPFRM BITMAP "res\\mainfram.bmp" ///////////////////////////////////////////////////////////////////////////// // @@ -61,16 +53,6 @@ BEGIN BUTTON ID_APP_ABOUT END -IDR_HELPFRM TOOLBAR 16, 15 -BEGIN - BUTTON ID_FILE_NEW - BUTTON ID_FILE_OPEN - BUTTON ID_FILE_SAVE - SEPARATOR - BUTTON ID_FILE_PRINT - BUTTON ID_APP_ABOUT -END - ///////////////////////////////////////////////////////////////////////////// // @@ -683,20 +665,6 @@ BEGIN CONTROL "Hide password",IDC_PWDHIDE,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_RIGHT | WS_TABSTOP,177,35,128,10 END -IDD_HtmlHelp DIALOGEX 0, 0, 381, 282 -STYLE DS_SETFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME -CAPTION "WinHTTrack Website Copier Help" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - LTEXT "",IDC_HTMLVIEW,0,25,381,257 - ICON IDI_BACK,IDC_BACK,0,0,20,20,SS_NOTIFY | SS_CENTERIMAGE | SS_REALSIZEIMAGE,WS_EX_DLGMODALFRAME - ICON IDI_FORWARD,IDC_FORWARD,20,0,20,20,SS_NOTIFY | SS_CENTERIMAGE | SS_REALSIZEIMAGE,WS_EX_DLGMODALFRAME - ICON IDI_STOP,IDC_STOP,40,0,20,20,SS_NOTIFY | SS_CENTERIMAGE | SS_REALSIZEIMAGE,WS_EX_DLGMODALFRAME - ICON IDI_RELOAD,IDC_RELOAD,60,0,20,20,SS_NOTIFY | SS_CENTERIMAGE | SS_REALSIZEIMAGE,WS_EX_DLGMODALFRAME - ICON IDI_HOME,IDC_HOME,80,0,20,20,SS_NOTIFY | SS_CENTERIMAGE | SS_REALSIZEIMAGE,WS_EX_DLGMODALFRAME - ICON IDI_PRINT,ID_FILE_PRINT,100,0,20,20,SS_NOTIFY | SS_CENTERIMAGE | SS_REALSIZEIMAGE,WS_EX_DLGMODALFRAME -END - IDD_InfoUrl DIALOG 0, 0, 347, 261 STYLE DS_SETFONT | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "File download information" @@ -2485,28 +2453,6 @@ LANGUAGE LANG_FRENCH, SUBLANG_FRENCH // remains consistent on all systems. IDI_SPLASH ICON "res\\ico00001.ico" -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_HELPFRM MENU -BEGIN - POPUP "&File" - BEGIN - MENUITEM "&Print...\tCtrl+P", ID_FILE_PRINT - MENUITEM "Print Pre&view", ID_FILE_PRINT_PREVIEW - MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP - MENUITEM SEPARATOR - MENUITEM "E&xit", ID_CLOSE - END - POPUP "Help" - BEGIN - MENUITEM "About WinHTTrack Website Copier...", ID_ABOUT - END -END - - ///////////////////////////////////////////////////////////////////////////// // // Dialog diff --git a/WinHTTrack/WinHTTrack.vcxproj b/WinHTTrack/WinHTTrack.vcxproj index 081074a..9c62500 100644 --- a/WinHTTrack/WinHTTrack.vcxproj +++ b/WinHTTrack/WinHTTrack.vcxproj @@ -127,13 +127,9 @@ - - - - @@ -195,13 +191,9 @@ - - - - @@ -259,15 +251,7 @@ - - - - - - - - diff --git a/WinHTTrack/res/icon1.ico b/WinHTTrack/res/icon1.ico deleted file mode 100644 index b9d25f3450b14ea73d65729f38152a0bc48aa56c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3006 zcmeH|u}d656vjV;gu@78b7^d1rS+@qg1um4Z8!gdO^T~*4FrVgERv8EY5WVWN)aDt zb0{3KPzylna6>qz|6>5K+?F4gUJ)&1Jl^_TaWo}N~#)za+jtmfzE)o!=7u&|)T#YHVI zFKc6CLu+emT3ub$%F2p5uR`nVp*K2Gd~4~G zwY;S|P~n}4s-?y|!;~@27-X0--kHTrl8kr8yKYDIM#n$npYbnSl=08hCc}_n$kd^1 z8&#=KkHSb_wvie*eh!<%;rP|9EgaOq;qb!2gVpWkCWpmgaUdMS`U=3}+~@>3g2Td( zMjrOWVewLr%2M8jvI}T11PlQ~zz{G54E1$_!C?p(0tSbHG&JI22p9r}fPvIBbQl7L zfFS?~{GDXMjX_W%M`E7fh?={^B)!l(ZEkLAYimo}+uPdR-POUtf%f1}->kl3j z*B=b}x5xedy|dH7-7zk22|R6%ad9&Qp3d|}$Nj#n5IA=IZn1ZEcRBu|H-34tI;p@v ztN`DT@+m3bl1Cn|n*4{&xYLYtqw%NaD#wpz9R4xCU5_R{Ztp*A@?16JV?W1l`JWG- F`~pnTtl|Iw diff --git a/WinHTTrack/res/icon2.ico b/WinHTTrack/res/icon2.ico deleted file mode 100644 index 20ae5b5ba13dab5620a7e55fa436e2a0658de02a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3006 zcmeH|u}d656vjV;gu@8I<|-k?O6ylyCD;o#)^_tR*aUKwbs!*2XOV=YNaJ5{Rf_ny zN|YS2h!%nf(e8r9%WvlHG={KTW2)P|nc4aF&HH})W{;I-IG2}IkB?8JHdkd@+6HY# zEqdwY<2wAK>qz|6=?n*YF4gUJ)&1Vp)z=T2ot;&y)zbX@ycQM~)NZ%6xVWgLr6sMb ztY~v{Q|s&NT3cJw>guXGuRtP89k#j$k83$(H+6jgLyCyug*qq_#26gMW#@-r!yD~27|$1 zs7Npv3E&hBsglR;7Bke7!nMnbP0|GLxREa3i?_?e1<3U zTHaC}sPN82)l%b~Vak|h3^Gg^@663il8kr8yKYDIM#n$npYbnSl=08hCc}_n$kd^1 z8&#=KkHSb_wvie*eh!<%;rP|9EgaOq;qb!2gVpV3k;CG!I1r9ueFb1~7CJ$W;IQzc zk%v8TSiIDuvXr->>;f7L0YktLFa!(%Lw%iKa2NuHfWcuP4UKph0)~JgU?4RO9fp7* zUZ*Oa7XGgocyE-^H(Ek3uj*pLZa&n@x zvol>>Ta73fXqbU0z)VZSl3 zcQ`)!je)(>{@u}#v3EK?`ak*&kJ1|-r;TB^8SuZoZo24A7B<)L2=~%Y8h3BebTX~L zT?P1tlut?dmOSuyGs^#KG!Dk&>*_zyi_!ROG(P=nKD-};VSJ3&kMoW5KlF3_kw3mY F`VE96vSa`N diff --git a/WinHTTrack/res/icon3.ico b/WinHTTrack/res/icon3.ico deleted file mode 100644 index 54419e16ace9668a5366c7be0cbb16e052d0d25c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3006 zcmeH|v1?R85Qiri^oRjTb5-D-sS-%HRVq#TgFr}~ZrhY;EUro|2!ZWVsAyr6zu+nh zGj*;pAY2g$f=PFvIDRwlPL2333MoYL-tF$~yx*JOx3hbk$PD-Lvc&c3zDS#IKJ~Uq zn~@g1$m6>){HE)P@R44x9_aZh{eEBi@B4D`?xoDm&PuD*lKJ_0Sy)(*cDpT$i;J?f zv?MDlE3&=4E!}QcHa0e7ZEa0@PfRv9O`ge#*hiJOC!gfx>`b1%euGh>Wm=(WJx#YA`a8C3I|3sq1OG!+^ zo-VSX2WH>S$Q7Skx3>k(DgO@JDkzvR% zC|*V%CB&z`nMZlOI#A(VP(`WnE-)2L3kC(If_LFzAxXiz;2ql$-o)`Q_!sJrPEF-$rVn_$h1(hvFAo>m1ZT;ZWybVX@u3q_8L~3WQ=9M*tS( zMMb0p6c#=-@~|fgi+VkR#ZQCp0x=j227|$1Fc=JmI8HDq3?<{1u)+^)&;P+rK+&W`Nu?aBWBz8oAJ$no*99336W zU@(x=(^DA^hjM;?E|-^=G8&EK;z#y?lEY3C|W_(RxW%iAPGI97I=(z$RK zWu0@H3?WLtrmNiP&(7%-rrSsVQUy4<{#WAvB{wwo>O5cNQRMw1Rg5Ef5aWg1yE1-| ZJ2C&;@z*?){1d;4zm0irY<*Yj^bJ?Aw+#RQ diff --git a/WinHTTrack/res/icon4.ico b/WinHTTrack/res/icon4.ico deleted file mode 100644 index 2f950f203e55ec697e0e1b29ba5dd2a5eee5052a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3006 zcmeH|F-RRj5QfJf$s-EE=2b$7l{T-L$|}KLu(7t=#>UPjkXKm;0>X9{Nl1z`))ucy z5vNuNv9b{4L9`Q6Oum^@F_1e`NI>xJ?e6W|fAfDkd&d)*;GCbAJU&f{^tp;@v=!Qf z^yo!iJA9RW=8t`zRb?f%G}(X zEG#U@>guX2FE7i|(vmDLF3Rw=%gTz&J2?;^n|wX^DF-Jf^7iu=jFeVrm1fOUi77E9 zrV;Z-QivDgg?J%eh{t1gU#SD{Bmo9gBlnd791=rx0{Cy7K6orFbwk*fW>&w5E%i3 zg&&PP?1{l*QIBMaw;^_c7z_@B!{9JD3=TuSPB0h@4uivBFp!3Z9tMZOVQ?5oO(PD2 z!{9JD0FJ+r%z4le6>=2j1rE>Lp(*l0KFHeInrv=v%GTDFY;SMN{{Ft~?(WLr;h`KI z9m(%nW%hQMB-dA9}_vg{Jpt1YT zjdQPE*T@EqxI>qM!Jv_M=t3}vBOd6`UFF+Y=c+?@&A0v!`9geqzR1*^9llMb+t*8> z*Ed*kX6(wxCzy2!;VrsQB4exD_l#*MfqaqjuZ63-7|-NM=K25QvrFISm*dOJ@lB4g(7RaQ%{)`zAN>ZJ2r-lZ diff --git a/WinHTTrack/res/icon5.ico b/WinHTTrack/res/icon5.ico deleted file mode 100644 index 6efbb4153e61852b66ba0d8c94f53095beb9e00b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3006 zcmeH|u}d6L5Qj&QL^eXOxk`{&>2~KdXO&bOANJ3JivA*Ie zi}-47A_Oc1kwm+LgiOAfyNeb%Pl!bV?)rB2{r0yr-u~@P|uVggVp*f4o5hhpbN_7A_w;pwTo`tXrL%1DgND1)h@ zDVn0GYc{YX^n{+!6M91T*D`uW&rC9UMkh!?FX#omAQW_CZp^JjW#y{WR}v{NshC80 zE((LfpfD&5fdqrXpfD&53PWJRpfD&53WLHB=rAY@3WLI+FsPxyp>U{km_-Lrh<;{9 zVW9hxVM!EE6iOsbutXbpn7B!>Bv_&?a3nYq90`sDN3;r#1Ve%$!Qib+a3mNK424?8 zHCjlW!O1+@>)nBh+8I~0n%WtrOwmk%3{$3d=3ypDrgo-wY)8~ar+%h>roL}crhcY3 z8HNl)rVqYtbR|}gLgeb(NDm723Ty?ALcQ2p=b#4#j^Z3FEVi4M3M>Vd0z{!;d;+i( zUM!djLV<-p26@<%0!#6J1dD$Sz6)qD7z_r3!C){L4DmU^P+%|^42A*&X&CrnFc=I5 zgMrixbQlZKBq3FB+yqj>J5{VUgQCNuJ1C+1lEY?d@&Z+1ZiZ-Ca32IFP-) zJvll$lH=oJIXO9zv$Hd~yu6ftzb_ZxP2O}m{Epjn*M9>Z$QLuu>r<2J{`lWJaNhN! zZq{`bcjMM`ZXM2grCC>g*B$Tk$8~F^S@{b$_#$7cwQ{R`omOj7K65^fiTT_(I>+;M z`M`hM#;>=kt{caut2@nW#%|SVjcMR@;|;c|x-#BqyE0C&jf@j*L!&R@`ItqFWM{;- zFv;hOp&^rf7|DGLUsbzrVFYp?|H%&cPi*k7<&NSPc^vuvHumIUthwOuR#sMId3jlumX@UP*kpCp3u$4DVwh!^68Kp}4UhHoX5l~vJK3MrdZOhTST zVNe(p28AJzU{Dwo28BUk2uv6h28BUkP#6Lo28BUkP#6>jHDYim9O@iq(E%b@zcRBh ziTf+Vk`PY_C5k3kq76Ju+$2~MEYTJ?5*!JR1V@4+S_MafA;FMf@YW?b5)283f|jvH z3(=`A{AjOt2P(8PS;IOFeIY}PK3t3-ZmyL}L+1%Wet*tHD-QAU)ogFzi zIFQ4`LpeG+l6Jc-y!aQt`#K|e;}eG~w8tb;uG0O=KzN*T#|DYF802+^%U^ipomcdCsdvUCc7_LeS0`5W zK=j@;ksXug1uhLwykHu+@sfjaU0S`tjy`wvRofj{B$R`13Q@AwMkpjhO9W8`y40{>|k(RY8W? diff --git a/WinHTTrack/res/idr_main.ico b/WinHTTrack/res/idr_main.ico deleted file mode 100644 index 5cc58fcae46fe53b3b8ba5ecd9b662806db26305..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8166 zcmeI1F^t>D6^6%w3~k<0lt__2AaJp9b?y#eL~3lAOR_uZ-!cXwbm-$#6ix7o!#MZ-uyG~ zn>Vx6ETz;9)lz$V%BDZ=DD?~OKKpD{ca{1c+umN!8vgMUrJjDGRIjP3uWu^#tDhB4SrdxFTbqSZ`BJ`mxcQ4i%Pxt?mP9H zKm8d;5m}Qna?w;HY!S8yTV!l?BhlD3c8y(Q*Vs+B410z>qmp6Iuv4f4dx5>cUSKG& z*VJq3bzwb6TqFEP3>48RQnj+~xkNBTFhnp!FjyoQA{ZhVA{ZhVEG7&Q3=s?w3=s?# z9fk;o2!;rT2!^P}21f)(WH{>DMgR+?`N_xy8M~P>EE?w;N18!3EH(@@YHl7z%vVTx|&P)BI4k;Wg2L3f~zj8)|%KFl9K+ zaFD^2;X9)-V~`Br8NTguSl`(3pW#2lzgeOT{~58#V8~#|h=W-+qGD%{g_5gTMq*Il zuYj$9qrjhCTEjsM3OEYG!Nlxx)2V=^fTaMUz@gm&uoQGG5EU2-SokF~4r@}tQkZyH z7PA}7Dqw@5hM|U`hM|U`hQV$p7z!9_7-|>_7#N0(9)=o*8ipDMh9+Z&p@yM`p$4GF zf5Bii9cx6IF*J1zM{UP88m)e=ey<)qdZZpdeypB6d7_>^eX5>6f3BWAd!}B#e5qc& zdZk{!eyt{xiJH&nYPnph**|ObyKlec?|49T&EJ427|+(sxTadG;V_pb4d13U(^{p` zteMs-*XS8lJ*DSRgJ5kof+KNLuS}ik#OTv5!yiEsRN}N7y%{?7Bs}(#nbYW}_-*tq`Y9j3$pjVt;i0i= zJCdY+nf9zcDaARoJgLzyxRgw=jN3t@Z!@d1zg#5!;IN8MPC`kW`7TUU793wnPh=S$ z&wFV+tAg2aER~y9@lkMk63p7tKMtDsoK!14Ol4RdEmMY@R1grn)GdS5@1qu-4daki_&4nwmur=xFT?yGtp5*4}(&fO?HMhfID3jq(i$5HW5yu$E?CyBn>5Oyf zY}1<)P!Iit(ldH3-Znk%N%_zmL#;j*e~W(1ezW?{nckIro4zCL7RkYi{SY4T$6NHK zdEBvj=8WE#-f*j)sL|d;4}BLVZAh~=$dxM#}DJ% zSb5@fI-L!Am(|=|&DXVh$FV$glMQ;=%{!uX6HgHAd}I7wrWdnqNcnhIy0KZ`34q)5 zXZyjdv(d9~tglV)?$53;0TIK@bEVloJ<(pX|KHVXF_U%8er6)ge!hHv=6YG$ne{CHsefUr1(rO#i8V%wM*2_>6RSDfETGsa_c0ZVwT^ zS)<^i(NDB_UTJ^qn`fKOSH%YYI5zQo?=;SHqvyY#?P+v_m%!U4S85&o^uvyKCFegp z@%sDpmIWN}?tOC_T>5|Nzk45dz)Ne>6JF z=4M0x(fR(S?-l!B&A&R>U*k6cYUW@;_f6gKf6-h_b&cOtO%vJ9-_%Y2v-zw21Ka-1 zs=xVSVikkY2cExr6aT*e(Hd}3P5jNBIrUYL@vjNa5g<=#9-_Q+@N zWA=HpY)*qq_xbhrM%V9ScoV^QGkmvm{k_qT?|UOo++q(gV{SOt{V(diNoL^H_}n$= SJ?ptmbouano1cg8Z~Yg(mK!Vp diff --git a/WinHTTrack/res/mainfram.bmp b/WinHTTrack/res/mainfram.bmp deleted file mode 100755 index fb2d933bebe265f4437ce28f73634903e5aebf79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 718 zcmbV~F;c`Z3`GTD#zl%;gK}qb1A1mCIfkn>Gc+kVPWlwd2{=po6ybfznwn4Fm)Gw{bGzc7nQzRF`Cw0Yv-f)Mhm#x37&Z*C;Mv-;EUdcNeb~Nh$Kd~9ei^T zx~?@M`uHlr7xh)$EeNw{DWK}A!1jcjXTJ)*-iherFK)wD%DAW)`c+m+qB{36W8)oH zIz5BaVU diff --git a/WinHTTrack/resource.h b/WinHTTrack/resource.h index ee208d4..57df912 100644 --- a/WinHTTrack/resource.h +++ b/WinHTTrack/resource.h @@ -81,18 +81,11 @@ Please visit our Website: http://www.httrack.com #define IDD_OPTION8 193 #define IDD_OPTION9 194 #define IDD_OPTION10 195 -#define IDD_HtmlHelp 197 #define IDB_COLDTOOLBAR 199 #define IDB_HOTTOOLBAR 200 -#define IDI_BACK 210 -#define IDI_FORWARD 211 -#define IDI_STOP 212 -#define IDI_RELOAD 213 #define IDB_ENSI 213 -#define IDI_HOME 214 #define IDD_Wait 214 #define IDB_ENSI_BACK 214 -#define IDI_PRINT 215 #define IDD_InfoUrl 215 #define IDD_CatchUrl 217 #define IDD_TESTFRAME 218 @@ -102,7 +95,6 @@ Please visit our Website: http://www.httrack.com #define IDR_WINHTTTYPE 222 #define IDD_OPTION11 222 #define IDD_BatchUpdate 223 -#define IDR_HELPFRM 229 #define IDB_SPLASH 236 #define IDC_CURSWWW 237 #define IDI_SPLASH 242 @@ -272,7 +264,6 @@ Please visit our Website: http://www.httrack.com #define IDC_sk0 1093 #define IDC_urls 1093 #define IDC_ADD2 1093 -#define IDC_BACK 1093 #define IDC_visit 1093 #define IDC_CTRL_log 1093 #define IDC_FIND 1093 @@ -281,20 +272,16 @@ Please visit our Website: http://www.httrack.com #define IDC_sk1 1094 #define IDC_br1 1094 #define IDC_ADD1 1094 -#define IDC_FORWARD 1094 #define IDC_up 1094 #define IDC_BUTTON3 1095 #define IDC_sk2 1095 -#define IDC_STOP 1095 #define IDC_down 1095 #define IDC_BUTTON4 1096 #define IDC_sk3 1096 #define IDC_br2 1096 -#define IDC_RELOAD 1096 #define IDC_RICHEDIT13 1097 #define IDC_sk4 1097 #define IDC_login 1097 -#define IDC_HOME 1097 #define IDC_RICHEDIT14 1098 #define IDC_sk5 1098 #define IDC_PRINT 1098 @@ -489,7 +476,6 @@ Please visit our Website: http://www.httrack.com #define IDC_updhack 1242 #define IDC_urlhack 1243 #define IDC_STATIC_checktype 1245 -#define IDC_HTMLVIEW 1247 #define IDC_textwait 1255 #define IDC_STATIC_spider 1256 #define IDC_STATIC_warning 1257 From 83232e8ccae8e4829a2f51d15c84ff400cba5b0a Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Wed, 29 Jul 2026 18:34:53 +0200 Subject: [PATCH 2/6] Keep the update check out of the help path, and pin the anchors in CI Review fallout. Help(CString) had grown a branch for absolute URLs, which only existed because OnUpdate borrowed the help class to reach httrack.com; a failed browser launch there reported "Unable to find Help files!". OnUpdate now calls ShellOpen() itself, as the other two httrack.com links already do, and LaunchHelp is back to documentation pages only. The no-argument Help() goes back to index.html. Repointing it at the guide was never asked for, and the nine generic F1 handlers had always landed on the doc index. The GUI deep-links into the engine's guide.html and CI follows engine master unpinned, so an anchor renamed upstream would arrive silently: the page still opens, it just never scrolls. CI now greps the anchors out of the sources and fails if one has no matching id, with a floor on the match count so a broken regex cannot pass the check vacuously. The same reasoning applies to --selftest's own output, which is now asserted rather than inferred from the exit code -- its accented-path case skips itself where the ANSI codepage cannot hold the accent, so a table entry escaping ',' pins the hex case unconditionally. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_012gAp9x4L95B8DkeuHQpuqg Signed-off-by: Xavier Roche --- .github/workflows/windows-build.yml | 25 +++++++++++++++++++++++++ WinHTTrack/LaunchHelp.cpp | 24 ++++++------------------ WinHTTrack/LaunchHelp.h | 14 ++++++-------- WinHTTrack/WinHTTrack.cpp | 6 +++++- 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index c309e98..4bf78f7 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -199,6 +199,25 @@ jobs: path: httrack submodules: recursive + - name: Help anchors resolve in the engine's guide + shell: pwsh + # The GUI deep-links into the engine's guide.html and the engine is unpinned, so a + # rename upstream lands here silently: the page still opens, it just never scrolls. + run: | + $guide = 'httrack\html\guide.html' + if (-not (Test-Path $guide)) { throw "$guide is missing: every help button would 404" } + $page = Get-Content $guide -Raw + $anchors = Select-String -Path 'httrack-windows\WinHTTrack\*.cpp' ` + -Pattern 'HelpTopic\("([^"]+)"\)' -AllMatches | + ForEach-Object { $_.Matches } | + ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique + # Guard the scan itself: a regex that matched nothing would pass the loop below. + if ($anchors.Count -lt 10) { throw "found only $($anchors.Count) anchors; the scan is broken" } + foreach ($a in $anchors) { + if (-not $page.Contains("id=""$a""")) { throw "guide.html has no id='$a'" } + } + Write-Host "$($anchors.Count) help anchors resolve in guide.html" + - name: Record engine provenance id: provenance shell: pwsh @@ -587,6 +606,12 @@ jobs: $p = Start-Process (Join-Path $bin 'WinHTTrack.exe') -ArgumentList '--selftest' -Wait -PassThru ` -RedirectStandardOutput "$PWD\crash-st.txt" -RedirectStandardError "$PWD\crash-st.err" if ($p.ExitCode -ne 0) { throw "--selftest exited $($p.ExitCode) from the staged tree" } + # Exit 0 also covers "every check skipped itself" -- the MBCS one bails out where + # the ANSI codepage cannot hold an accent. Make each say it ran. + $stdout = Get-Content "$PWD\crash-st.txt" -Raw + foreach ($m in @('MBCS->UTF-8 ok', 'help URLs ok')) { + if (-not $stdout.Contains($m)) { throw "--selftest never printed '$m': that check did not run" } + } if (-not (Test-Path $report)) { throw 'no crash report written: the first-chance hook never ran' } $trace = Get-Content $report -Raw Write-Host "--- crash report ---`n$trace" diff --git a/WinHTTrack/LaunchHelp.cpp b/WinHTTrack/LaunchHelp.cpp index 7847824..998d267 100644 --- a/WinHTTrack/LaunchHelp.cpp +++ b/WinHTTrack/LaunchHelp.cpp @@ -31,9 +31,8 @@ Please visit our Website: http://www.httrack.com #include "LaunchHelp.h" #include "Shell.h" -/* The guide is shared with WebHTTrack and Android; the platform in the fragment is - what selects our screenshots. */ -#define DOC_GUIDE "guide.html#win" +/* Shared with WebHTTrack and Android; #win picks our screenshots. */ +#define DOC_GUIDE "guide.html#win/" /* Unreserved, plus ':' and '/' so the drive letter and the separators survive. */ static bool IsUrlSafe(unsigned char c) { @@ -77,7 +76,8 @@ bool BuildDocUrl(const char* dir, const char* page, CString& url) { return true; } -/* The doc tree sits beside the executable, where the installer stages it. */ +/* The doc tree sits beside the executable, where the installer stages it. Not the + engine's hts_rootdir(): that is seeded late in InitInstance, after --selftest. */ static bool DocDir(char* dir, size_t size) { const DWORD n = ::GetModuleFileName(NULL, dir, (DWORD) size); if (n == 0 || n >= size) /* n == size on truncation, which leaves dir unterminated */ @@ -92,13 +92,6 @@ static bool DocDir(char* dir, size_t size) { } void LaunchHelp::Help(CString page) { - /* The update check hands us a real URL; everything else names a page in html/. */ - if (page.Left(7) == "http://" || page.Left(8) == "https://") { - if (!ShellOpen(page, SW_SHOWNORMAL)) - AfxMessageBox(LANG(LANG_DIAL1)); - return; - } - char dir[1024]; CString url; if (!DocDir(dir, sizeof(dir)) || !BuildDocUrl(dir, page, url) @@ -107,15 +100,10 @@ void LaunchHelp::Help(CString page) { } void LaunchHelp::HelpTopic(const char* anchor) { - CString page(DOC_GUIDE); - if (anchor != NULL && *anchor != '\0') { - page += '/'; - page += anchor; - } - Help(page); + Help(CString(DOC_GUIDE) + anchor); } void LaunchHelp::Help() { - HelpTopic(NULL); + Help("index.html"); } diff --git a/WinHTTrack/LaunchHelp.h b/WinHTTrack/LaunchHelp.h index 83c5d93..b0c5a41 100644 --- a/WinHTTrack/LaunchHelp.h +++ b/WinHTTrack/LaunchHelp.h @@ -30,21 +30,19 @@ Please visit our Website: http://www.httrack.com #include "stdafx.h" -// Build a browsable URL for a documentation page: dir is the ANSI directory holding it, -// page is "guide.html" or "guide.html#win/opt-limits". The path is percent-encoded as -// UTF-8 and the fragment kept whole, so '#' arrives as a fragment and not as the filename -// character NTFS also allows it to be. False if the path cannot be encoded. Help callers -// go through LaunchHelp; this is public for --selftest. +// Build a browsable file: URL for a doc page. dir is the ANSI directory holding it, page +// is "guide.html" or "guide.html#win/opt-limits". False if the path cannot be encoded. +// Public only for --selftest. bool BuildDocUrl(const char* dir, const char* page, CString& url); // Opens the documentation in the system default browser. class LaunchHelp { public: - // The guide, at the top of the Windows walkthrough. + // The documentation index. void Help(); - // A page under html/, or an absolute http/https URL, which is opened untouched. + // A page under html/, optionally with a #fragment. void Help(CString page); - // The guide, scrolled to one of its Windows sections, e.g. "opt-limits". + // The guide, at one of its Windows sections, e.g. "opt-limits". void HelpTopic(const char* anchor); }; diff --git a/WinHTTrack/WinHTTrack.cpp b/WinHTTrack/WinHTTrack.cpp index 4233a72..729f6b8 100755 --- a/WinHTTrack/WinHTTrack.cpp +++ b/WinHTTrack/WinHTTrack.cpp @@ -351,6 +351,9 @@ BOOL CWinHTTrackApp::InitInstance() "file:///C:/Program%20Files/WinHTTrack/html/guide.html#win/opt-limits" }, { "C:\\h\\", "guide.html", "file:///C:/h/guide.html" }, { "C:\\a#b\\", "guide.html#win", "file:///C:/a%23b/guide.html#win" }, + /* %2C, not %2c: the accented case below pins the hex case too, but it skips + where the ANSI codepage cannot hold the accent. */ + { "C:\\a,b\\", "guide.html", "file:///C:/a%2Cb/guide.html" }, { "\\\\srv\\share\\html\\", "guide.html#win", "file://srv/share/html/guide.html#win" }, { NULL, NULL, NULL } }; @@ -945,7 +948,8 @@ void CWinHTTrackApp::OnUpdate() { CString st; st.Format(HTS_UPDATE_WEBSITE,0,LANGUAGE_NAME); - HtsHelper->Help(st); + if (!ShellOpen(st, SW_SHOWNORMAL)) + AfxMessageBox("Cannot open a web browser for " + st); } // Appel aide From 9b4e7d2dbc71f830fb0699ba6c85cdaee9b0680b Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Wed, 29 Jul 2026 18:37:26 +0200 Subject: [PATCH 3/6] Name the engine pin when the guide is absent The guard fires today because HTTRACK_ENGINE_REF is pinned to an engine that predates html/guide.html, and "file is missing" does not say what to do about it. Point at the variable and the commit instead. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_012gAp9x4L95B8DkeuHQpuqg Signed-off-by: Xavier Roche --- .github/workflows/windows-build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 4bf78f7..ea4a194 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -205,7 +205,10 @@ jobs: # rename upstream lands here silently: the page still opens, it just never scrolls. run: | $guide = 'httrack\html\guide.html' - if (-not (Test-Path $guide)) { throw "$guide is missing: every help button would 404" } + if (-not (Test-Path $guide)) { + throw "$guide is missing, so every help button would open nothing. The engine " + + "predates the guide: move the HTTRACK_ENGINE_REF variable past xroche/httrack a21f84ee." + } $page = Get-Content $guide -Raw $anchors = Select-String -Path 'httrack-windows\WinHTTrack\*.cpp' ` -Pattern 'HelpTopic\("([^"]+)"\)' -AllMatches | From 25cf7794a38e4af4fb1ffd54a72e17480be0c2b8 Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Wed, 29 Jul 2026 18:54:06 +0200 Subject: [PATCH 4/6] Assert the help-URL check where the other selftest markers are asserted The staged-tree run grew its own copy of the marker loop; smoke-test/action.yml already does this for the installed binary, one assertion per marker with the reason written down, and it runs on every build. Add "help URLs ok" there and drop the duplicate, so the list cannot drift between two places. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_012gAp9x4L95B8DkeuHQpuqg Signed-off-by: Xavier Roche --- .github/actions/smoke-test/action.yml | 5 +++++ .github/workflows/windows-build.yml | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/actions/smoke-test/action.yml b/.github/actions/smoke-test/action.yml index 215d562..cf7dcfb 100644 --- a/.github/actions/smoke-test/action.yml +++ b/.github/actions/smoke-test/action.yml @@ -140,6 +140,11 @@ runs: if ("$so" -notmatch 'MBCS->UTF-8 ok') { throw "selftest did not exercise the MBCS->UTF-8 conversion" } + # Every help button hands one of these to the browser: an unescaped space truncates + # the path, an unescaped '#' names a file, since NTFS allows one in a filename. + if ("$so" -notmatch 'help URLs ok') { + throw "selftest did not check the help URLs" + } # Guards the empty-name terminator (newlang.h); losing it hangs the first-run About # box. [1-9] not \d: "after 0 entries" would pass while proving nothing. if ("$so" -notmatch 'language list ends after [1-9]\d* entries') { diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index ea4a194..97bdf53 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -609,12 +609,6 @@ jobs: $p = Start-Process (Join-Path $bin 'WinHTTrack.exe') -ArgumentList '--selftest' -Wait -PassThru ` -RedirectStandardOutput "$PWD\crash-st.txt" -RedirectStandardError "$PWD\crash-st.err" if ($p.ExitCode -ne 0) { throw "--selftest exited $($p.ExitCode) from the staged tree" } - # Exit 0 also covers "every check skipped itself" -- the MBCS one bails out where - # the ANSI codepage cannot hold an accent. Make each say it ran. - $stdout = Get-Content "$PWD\crash-st.txt" -Raw - foreach ($m in @('MBCS->UTF-8 ok', 'help URLs ok')) { - if (-not $stdout.Contains($m)) { throw "--selftest never printed '$m': that check did not run" } - } if (-not (Test-Path $report)) { throw 'no crash report written: the first-chance hook never ran' } $trace = Get-Content $report -Raw Write-Host "--- crash report ---`n$trace" From 9cbaa78e63a0eee4ce1b838a6020f868311409c7 Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Wed, 29 Jul 2026 18:57:57 +0200 Subject: [PATCH 5/6] Hand the URL to the browser, so the section anchor survives Verified on a VM: help opened the guide but always at the top, whatever button was pressed. ShellExecute() on a file: URL does not pass the URL on -- it resolves it to a filesystem path first, and that conversion stops at '#', so the fragment is gone before the browser is launched. Ask the shell which program opens http: and run it with the URL as an argument instead. A browser parses its argv as a URL and honours the fragment. Where no browser answers, fall back to the old ShellExecute: the page opens at the top, which is what happens today anyway, rather than an error box. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_012gAp9x4L95B8DkeuHQpuqg Signed-off-by: Xavier Roche --- WinHTTrack/LaunchHelp.cpp | 17 ++++++++++++++++- WinHTTrack/WinHTTrack.vcxproj | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/WinHTTrack/LaunchHelp.cpp b/WinHTTrack/LaunchHelp.cpp index 998d267..c2c61d6 100644 --- a/WinHTTrack/LaunchHelp.cpp +++ b/WinHTTrack/LaunchHelp.cpp @@ -30,6 +30,7 @@ Please visit our Website: http://www.httrack.com #include "stdafx.h" #include "LaunchHelp.h" #include "Shell.h" +#include /* Shared with WebHTTrack and Android; #win picks our screenshots. */ #define DOC_GUIDE "guide.html#win/" @@ -91,11 +92,25 @@ static bool DocDir(char* dir, size_t size) { return true; } +/* ShellExecute() on a file: URL hands the handler a PATH, and the conversion stops at + '#', so the section is lost and every button lands on the top of the guide. Ask which + program opens http: and pass the URL as its argument: a browser parses argv as a URL, + fragment and all. */ +static bool OpenInBrowser(const char* url) { + char browser[MAX_PATH]; + DWORD size = (DWORD) sizeof(browser); + if (AssocQueryStringA(ASSOCF_NONE, ASSOCSTR_EXECUTABLE, "http", "open", + browser, &size) != S_OK) + return false; + return (INT_PTR) ShellExecuteA(NULL, "open", browser, url, NULL, SW_SHOWNORMAL) > 32; +} + void LaunchHelp::Help(CString page) { char dir[1024]; CString url; + /* No browser registered: opening the page without its anchor still beats an error. */ if (!DocDir(dir, sizeof(dir)) || !BuildDocUrl(dir, page, url) - || !ShellOpen(url, SW_SHOWNORMAL)) + || !(OpenInBrowser(url) || ShellOpen(url, SW_SHOWNORMAL))) AfxMessageBox(LANG(LANG_DIAL1)); } diff --git a/WinHTTrack/WinHTTrack.vcxproj b/WinHTTrack/WinHTTrack.vcxproj index 9c62500..088abd7 100644 --- a/WinHTTrack/WinHTTrack.vcxproj +++ b/WinHTTrack/WinHTTrack.vcxproj @@ -79,7 +79,7 @@ Windows - Ws2_32.lib;Winmm.lib;%(AdditionalDependencies) + Ws2_32.lib;Winmm.lib;Shlwapi.lib;%(AdditionalDependencies) true From 305aa0d43e72d31c18922570f619dab3531e707d Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Wed, 29 Jul 2026 19:08:31 +0200 Subject: [PATCH 6/6] Let the staging check know shlwapi is Windows' AssocQueryString pulled in a new import, and the packaging check asserts every imported DLL is either staged or known to come from Windows. shlwapi.dll is the latter: an OS component since IE4, never redistributable. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_012gAp9x4L95B8DkeuHQpuqg Signed-off-by: Xavier Roche --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 97bdf53..ccceaa6 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -525,7 +525,7 @@ jobs: # Supplied by Windows itself. The CRT names are gone from this list on purpose: # they are ours to ship now, so the check below catches a staging regression. - $provided = '^(api-ms-win-(?!crt-)|kernel32|user32|advapi32|shell32|comctl32|ole32|oleaut32|ws2_32|winmm|gdi32)' + $provided = '^(api-ms-win-(?!crt-)|kernel32|user32|advapi32|shell32|comctl32|ole32|oleaut32|ws2_32|winmm|gdi32|shlwapi)' $needed = @(Deps "$bin\WinHTTrack.exe") + @(Deps "$bin\httrack.exe") + @(Deps "$bin\libhttrack.dll") | Where-Object { $_ -notmatch $provided } | Sort-Object -Unique Write-Host "--- must ship: $($needed -join ', ') ---"