Prepare release and bump version numbers to 2.17.0.2
[TortoiseGit.git] / src / TortoiseGitBlame / TortoiseGitBlame.cpp
blob2ee1180b6a10a2c744bec80fe753fcf5f0ce676b
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2017, 2019-2023 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 // TortoiseGitBlame.cpp : Defines the class behaviors for the application.
23 #include "stdafx.h"
24 #include "afxwinappex.h"
25 #include "TortoiseGitBlame.h"
26 #include "MainFrm.h"
27 #include "../version.h"
28 #include "../Utils/CrashReport.h"
29 #include "I18NHelper.h"
30 #include "TortoiseGitBlameDoc.h"
31 #include "TortoiseGitBlameView.h"
32 #include "CmdLineParser.h"
33 #include "PathUtils.h"
34 #include "CommonAppUtils.h"
35 #include "TaskbarUUID.h"
36 #include "DPIAware.h"
38 #ifdef _DEBUG
39 #define new DEBUG_NEW
40 #endif
43 // CTortoiseGitBlameApp
45 BEGIN_MESSAGE_MAP(CTortoiseGitBlameApp, CWinAppEx)
46 ON_COMMAND(ID_APP_ABOUT, &CTortoiseGitBlameApp::OnAppAbout)
47 // Standard file based document commands
48 ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen)
49 ON_COMMAND(ID_FILE_SETTINGS, &CTortoiseGitBlameApp::OnFileSettings)
50 END_MESSAGE_MAP()
53 // CTortoiseGitBlameApp construction
55 CTortoiseGitBlameApp::CTortoiseGitBlameApp()
57 SetDllDirectory(L"");
58 SetTaskIDPerUUID();
59 #if ENABLE_CRASHHANLDER && !_M_ARM64
60 CCrashReportTGit crasher(L"TortoiseGitBlame " _T(APP_X64_STRING), TGIT_VERMAJOR, TGIT_VERMINOR, TGIT_VERMICRO, TGIT_VERBUILD, TGIT_VERDATE);
61 CCrashReport::Instance().AddUserInfoToReport(L"CommandLine", GetCommandLine());
62 #endif
63 EnableHtmlHelp();
64 git_libgit2_init();
67 CTortoiseGitBlameApp::~CTortoiseGitBlameApp()
69 git_libgit2_shutdown();
72 // The one and only CTortoiseGitBlameApp object
73 CTortoiseGitBlameApp theApp;
74 CString sOrigCWD;
75 CString g_sGroupingUUID;
76 CString g_sGroupingIcon;
77 bool g_bGroupingRemoveIcon = false;
79 // CTortoiseGitBlameApp initialization
81 BOOL CTortoiseGitBlameApp::InitInstance()
84 DWORD len = GetCurrentDirectory(0, nullptr);
85 if (len)
87 auto originalCurrentDirectory = std::make_unique<wchar_t[]>(len);
88 if (GetCurrentDirectory(len, originalCurrentDirectory.get()))
90 sOrigCWD = originalCurrentDirectory.get();
91 sOrigCWD = CPathUtils::GetLongPathname(sOrigCWD);
96 //set the resource dll for the required language
97 CRegDWORD loc = CRegDWORD(L"Software\\TortoiseGit\\LanguageID", 1033);
98 long langId = loc;
99 CString langDll;
100 HINSTANCE hInst = nullptr;
103 langDll.Format(L"%sLanguages\\TortoiseGitBlame%ld.dll", static_cast<LPCWSTR>(CPathUtils::GetAppParentDirectory()), langId);
105 hInst = LoadLibrary(langDll);
106 if (!CI18NHelper::DoVersionStringsMatch(CPathUtils::GetVersionFromFile(langDll), _T(STRPRODUCTVER)))
108 FreeLibrary(hInst);
109 hInst = nullptr;
111 if (hInst)
112 AfxSetResourceHandle(hInst);
113 else
115 DWORD lid = SUBLANGID(langId);
116 lid--;
117 if (lid > 0)
119 langId = MAKELANGID(PRIMARYLANGID(langId), lid);
121 else
122 langId = 0;
124 } while (!hInst && (langId != 0));
126 CString langStr;
127 langStr.Format(L"%ld", langId);
128 CCrashReport::Instance().AddUserInfoToReport(L"LanguageID", langStr);
130 setlocale(LC_ALL, "");
131 // We need to explicitly set the thread locale to the system default one to avoid possible problems with saving files in its original codepage
132 // The problems occures when the language of OS differs from the regional settings
133 // See the details here: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100887
134 SetThreadLocale(LOCALE_SYSTEM_DEFAULT);
136 // InitCommonControlsEx() is required on Windows XP if an application
137 // manifest specifies use of ComCtl32.dll version 6 or later to enable
138 // visual styles. Otherwise, any window creation will fail.
139 INITCOMMONCONTROLSEX InitCtrls;
140 InitCtrls.dwSize = sizeof(InitCtrls);
141 // Set this to include all the common control classes you want to use
142 // in your application.
143 InitCtrls.dwICC = ICC_WIN95_CLASSES;
144 InitCommonControlsEx(&InitCtrls);
146 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7));
148 CWinAppEx::InitInstance();
150 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
151 Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, nullptr);
153 // Initialize OLE libraries
154 if (!AfxOleInit())
156 AfxMessageBox(IDP_OLE_INIT_FAILED);
157 return FALSE;
159 AfxEnableControlContainer();
160 // Standard initialization
161 // If you are not using these features and wish to reduce the size
162 // of your final executable, you should remove from the following
163 // the specific initialization routines you do not need
164 // Change the registry key under which our settings are stored
166 SetRegistryKey(L"TortoiseGit");
167 LoadStdProfileSettings(4); // Load standard INI file options (including MRU)
169 InitContextMenuManager();
171 InitKeyboardManager();
173 InitTooltipManager();
174 CMFCToolTipInfo ttParams;
175 ttParams.m_bVislManagerTheme = TRUE;
176 theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
177 RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
179 // Register the application's document templates. Document templates
180 // serve as the connection between documents, frame windows and views
181 CSingleDocTemplate* pDocTemplate;
182 pDocTemplate = new CSingleDocTemplate(
183 IDR_TORTOISE_GIT_BLAME_MAINFRAME,
184 RUNTIME_CLASS(CTortoiseGitBlameDoc),
185 RUNTIME_CLASS(CMainFrame), // main SDI frame window
186 RUNTIME_CLASS(CTortoiseGitBlameView));
187 if (!pDocTemplate)
188 return FALSE;
189 AddDocTemplate(pDocTemplate);
191 CCmdLineParser parser(m_lpCmdLine);
192 g_sGroupingUUID = parser.GetVal(L"groupuuid");
194 // Parse command line for standard shell commands, DDE, file open
195 CCommandLineInfo cmdInfo;
196 ParseCommandLine(cmdInfo);
198 // Dispatch commands specified on the command line. Will return FALSE if
199 // app was launched with /RegServer, /Register, /Unregserver or /Unregister.
200 if (!ProcessShellCommand(cmdInfo))
201 return FALSE;
203 // The one and only window has been initialized, so show and update it
204 m_pMainWnd->ShowWindow(SW_SHOW);
205 m_pMainWnd->UpdateWindow();
206 // call DragAcceptFiles only if there's a suffix
207 // In an SDI app, this should occur after ProcessShellCommand
208 return TRUE;
211 BOOL CTortoiseGitBlameApp::LoadWindowPlacement(CRect& rectNormalPosition, int& nFlags, int& nShowCmd)
213 CRegString placement = CRegString(CString(L"Software\\TortoiseGitBlame\\WindowPos_") + GetMonitorSetupHash().c_str());
214 CString sPlacement = placement;
215 if (sPlacement.IsEmpty())
216 return FALSE;
217 WINDOWPLACEMENT wp = { 0 };
218 auto* pwp = &wp;
219 int nRead = swscanf_s(sPlacement, L"%u,%u,%d,%d,%d,%d,%d,%d,%d,%d",
220 &pwp->flags, &pwp->showCmd,
221 &pwp->ptMinPosition.x, &pwp->ptMinPosition.y,
222 &pwp->ptMaxPosition.x, &pwp->ptMaxPosition.y,
223 &pwp->rcNormalPosition.left, &pwp->rcNormalPosition.top,
224 &pwp->rcNormalPosition.right, &pwp->rcNormalPosition.bottom);
225 if (nRead != 10)
226 return FALSE;
227 pwp->length = sizeof(WINDOWPLACEMENT);
229 CDPIAware::Instance().ScaleWindowPlacement(m_pMainWnd->GetSafeHwnd(), pwp);
230 rectNormalPosition = wp.rcNormalPosition;
231 nFlags = wp.flags;
232 nShowCmd = wp.showCmd;
234 return TRUE;
237 BOOL CTortoiseGitBlameApp::StoreWindowPlacement(const CRect& rectNormalPosition, int nFlags, int nShowCmd)
239 CRegString placement(CString(L"Software\\TortoiseGitBlame\\WindowPos_") + GetMonitorSetupHash().c_str());
241 WINDOWPLACEMENT wp = { 0 };
242 wp.length = sizeof(wp);
243 wp.flags = nFlags;
244 wp.rcNormalPosition = rectNormalPosition;
245 wp.showCmd = nShowCmd;
247 CDPIAware::Instance().UnscaleWindowPlacement(m_pMainWnd->GetSafeHwnd(), &wp);
249 wchar_t szBuffer[_countof("-32767") * 8 + sizeof("65535") * 2];
250 swprintf_s(szBuffer, L"%u,%u,%d,%d,%d,%d,%d,%d,%d,%d",
251 wp.flags, wp.showCmd,
252 wp.ptMinPosition.x, wp.ptMinPosition.y,
253 wp.ptMaxPosition.x, wp.ptMaxPosition.y,
254 wp.rcNormalPosition.left, wp.rcNormalPosition.top,
255 wp.rcNormalPosition.right, wp.rcNormalPosition.bottom);
256 placement = szBuffer;
257 return TRUE;
260 // CAboutDlg dialog used for App About
262 class CAboutDlg : public CStandAloneDialog
264 public:
265 CAboutDlg();
267 // Dialog Data
268 enum { IDD = IDD_ABOUTBOX };
270 protected:
271 void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support
272 BOOL OnInitDialog() override;
274 // Implementation
275 DECLARE_MESSAGE_MAP()
278 CAboutDlg::CAboutDlg() : CStandAloneDialog(CAboutDlg::IDD)
282 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
284 CDialog::DoDataExchange(pDX);
287 BEGIN_MESSAGE_MAP(CAboutDlg, CStandAloneDialog)
288 END_MESSAGE_MAP()
290 BOOL CAboutDlg::OnInitDialog()
292 CStandAloneDialog::OnInitDialog();
294 wchar_t verbuf[1024] = { 0 };
295 wchar_t maskbuf[1024] = { 0 };
296 ::LoadString(GetModuleHandle(nullptr), IDS_VERSION, maskbuf, _countof(maskbuf));
297 swprintf_s(verbuf, maskbuf, TGIT_VERMAJOR, TGIT_VERMINOR, TGIT_VERMICRO, TGIT_VERBUILD);
298 SetDlgItemText(IDC_VERSION, verbuf);
300 SetDlgItemText(IDC_COPYRIGHT, CPathUtils::GetCopyrightForSelf());
301 SetDlgItemText(IDC_STATIC_AUTHORS, L"Sven Strickroth <email@cs-ware.de> (Current Maintainer), Sup Yut Sum <ch3cooli@gmail.com>, Frank Li <lznuaa@gmail.com> and Martin Strauß <MStrauss@MuellerBBM-vas.de>");
303 return FALSE;
306 // App command to run the dialog
307 void CTortoiseGitBlameApp::OnAppAbout()
309 CAboutDlg aboutDlg;
310 aboutDlg.DoModal();
313 void CTortoiseGitBlameApp::OnFileSettings()
315 CCommonAppUtils::RunTortoiseGitProc(L" /command:settings /page:blame");
318 // CTortoiseGitBlameApp message handlers
320 int CTortoiseGitBlameApp::ExitInstance()
322 Gdiplus::GdiplusShutdown(m_gdiplusToken);
323 return CWinAppEx::ExitInstance();