OSDN Git Service

TortoiseMerge Basic Support Git patch created by format patch
[tortoisegit/TortoiseGitJp.git] / src / TortoiseMerge / TortoiseMerge.cpp
1 // TortoiseMerge - a Diff/Patch program\r
2 \r
3 // Copyright (C) 2006-2009 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "stdafx.h"\r
20 #include <dlgs.h>\r
21 #include "TortoiseMerge.h"\r
22 #include "MainFrm.h"\r
23 #include "AboutDlg.h"\r
24 #include "CmdLineParser.h"\r
25 #include "version.h"\r
26 #include "AppUtils.h"\r
27 #include "PathUtils.h"\r
28 #include "BrowseFolder.h"\r
29 #include "DirFileEnum.h"\r
30 \r
31 #ifdef _DEBUG\r
32 #define new DEBUG_NEW\r
33 #endif\r
34 \r
35 #pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")\r
36 \r
37 BEGIN_MESSAGE_MAP(CTortoiseMergeApp, CWinAppEx)\r
38         ON_COMMAND(ID_APP_ABOUT, OnAppAbout)\r
39 END_MESSAGE_MAP()\r
40 \r
41 \r
42 CTortoiseMergeApp::CTortoiseMergeApp()\r
43 {\r
44         EnableHtmlHelp();\r
45         m_bLoadUserToolbars = FALSE;\r
46         m_bSaveState = FALSE;\r
47 }\r
48 \r
49 // The one and only CTortoiseMergeApp object\r
50 CTortoiseMergeApp theApp;\r
51 CCrashReport g_crasher("tortoisesvn@gmail.com", "Crash Report for TortoiseMerge " APP_X64_STRING " : " STRPRODUCTVER, TRUE);\r
52 \r
53 // CTortoiseMergeApp initialization\r
54 BOOL CTortoiseMergeApp::InitInstance()\r
55 {\r
56         CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));\r
57         CMFCButton::EnableWindowsTheming();\r
58         //set the resource dll for the required language\r
59         CRegDWORD loc = CRegDWORD(_T("Software\\TortoiseSVN\\LanguageID"), 1033);\r
60         long langId = loc;\r
61         CString langDll;\r
62         HINSTANCE hInst = NULL;\r
63         do\r
64         {\r
65                 langDll.Format(_T("..\\Languages\\TortoiseMerge%d.dll"), langId);\r
66                 \r
67                 hInst = LoadLibrary(langDll);\r
68                 CString sVer = _T(STRPRODUCTVER);\r
69                 CString sFileVer = CPathUtils::GetVersionFromFile(langDll);\r
70                 if (sFileVer.Compare(sVer)!=0)\r
71                 {\r
72                         FreeLibrary(hInst);\r
73                         hInst = NULL;\r
74                 }\r
75                 if (hInst != NULL)\r
76                         AfxSetResourceHandle(hInst);\r
77                 else\r
78                 {\r
79                         DWORD lid = SUBLANGID(langId);\r
80                         lid--;\r
81                         if (lid > 0)\r
82                         {\r
83                                 langId = MAKELANGID(PRIMARYLANGID(langId), lid);\r
84                         }\r
85                         else\r
86                                 langId = 0;\r
87                 }\r
88         } while ((hInst == NULL) && (langId != 0));\r
89         TCHAR buf[6];\r
90         _tcscpy_s(buf, _T("en"));\r
91         langId = loc;\r
92         CString sHelppath;\r
93         sHelppath = this->m_pszHelpFilePath;\r
94         sHelppath = sHelppath.MakeLower();\r
95         sHelppath.Replace(_T(".chm"), _T("_en.chm"));\r
96         free((void*)m_pszHelpFilePath);\r
97         m_pszHelpFilePath=_tcsdup(sHelppath);\r
98         sHelppath = CPathUtils::GetAppParentDirectory() + _T("Languages\\TortoiseMerge_en.chm");\r
99         do\r
100         {\r
101                 GetLocaleInfo(MAKELCID(langId, SORT_DEFAULT), LOCALE_SISO639LANGNAME, buf, sizeof(buf)/sizeof(TCHAR));\r
102                 CString sLang = _T("_");\r
103                 sLang += buf;\r
104                 sHelppath.Replace(_T("_en"), sLang);\r
105                 if (PathFileExists(sHelppath))\r
106                 {\r
107                         free((void*)m_pszHelpFilePath);\r
108                         m_pszHelpFilePath=_tcsdup(sHelppath);\r
109                         break;\r
110                 }\r
111                 sHelppath.Replace(sLang, _T("_en"));\r
112                 GetLocaleInfo(MAKELCID(langId, SORT_DEFAULT), LOCALE_SISO3166CTRYNAME, buf, sizeof(buf)/sizeof(TCHAR));\r
113                 sLang += _T("_");\r
114                 sLang += buf;\r
115                 sHelppath.Replace(_T("_en"), sLang);\r
116                 if (PathFileExists(sHelppath))\r
117                 {\r
118                         free((void*)m_pszHelpFilePath);\r
119                         m_pszHelpFilePath=_tcsdup(sHelppath);\r
120                         break;\r
121                 }\r
122                 sHelppath.Replace(sLang, _T("_en"));\r
123 \r
124                 DWORD lid = SUBLANGID(langId);\r
125                 lid--;\r
126                 if (lid > 0)\r
127                 {\r
128                         langId = MAKELANGID(PRIMARYLANGID(langId), lid);\r
129                 }\r
130                 else\r
131                         langId = 0;\r
132         } while (langId);\r
133         setlocale(LC_ALL, ""); \r
134         // We need to explicitly set the thread locale to the system default one to avoid possible problems with saving files in its original codepage\r
135         // The problems occures when the language of OS differs from the regional settings\r
136         // See the details here: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100887\r
137         SetThreadLocale(LOCALE_SYSTEM_DEFAULT);\r
138 \r
139         // InitCommonControls() is required on Windows XP if an application\r
140         // manifest specifies use of ComCtl32.dll version 6 or later to enable\r
141         // visual styles.  Otherwise, any window creation will fail.\r
142         InitCommonControls();\r
143 \r
144         // Initialize all Managers for usage. They are automatically constructed\r
145         // if not yet present\r
146         InitContextMenuManager();\r
147         InitKeyboardManager();\r
148 \r
149         CCmdLineParser parser = CCmdLineParser(this->m_lpCmdLine);\r
150 \r
151         if (parser.HasKey(_T("?")) || parser.HasKey(_T("help")))\r
152         {\r
153                 CString sHelpText;\r
154                 sHelpText.LoadString(IDS_COMMANDLINEHELP);\r
155                 MessageBox(NULL, sHelpText, _T("TortoiseMerge"), MB_ICONINFORMATION);\r
156                 return FALSE;\r
157         }\r
158 \r
159         // Initialize OLE libraries\r
160         if (!AfxOleInit())\r
161         {\r
162                 AfxMessageBox(IDP_OLE_INIT_FAILED);\r
163                 return FALSE;\r
164         }\r
165         AfxEnableControlContainer();\r
166         // Standard initialization\r
167         // If you are not using these features and wish to reduce the size\r
168         // of your final executable, you should remove from the following\r
169         // the specific initialization routines you do not need\r
170         // Change the registry key under which our settings are stored\r
171         SetRegistryKey(_T("TortoiseMerge"));\r
172 \r
173         if (CRegDWORD(_T("Software\\TortoiseMerge\\Debug"), FALSE)==TRUE)\r
174                 AfxMessageBox(AfxGetApp()->m_lpCmdLine, MB_OK | MB_ICONINFORMATION);\r
175 \r
176         // To create the main window, this code creates a new frame window\r
177         // object and then sets it as the application's main window object\r
178         CMainFrame* pFrame = new CMainFrame;\r
179         if (pFrame == NULL)\r
180                 return FALSE;\r
181         m_pMainWnd = pFrame;\r
182 \r
183         // create and load the frame with its resources\r
184         pFrame->LoadFrame(IDR_MAINFRAME,\r
185                 WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,\r
186                 NULL);\r
187 \r
188         // Fill in the command line options\r
189         pFrame->m_Data.m_baseFile.SetFileName(parser.GetVal(_T("base")));\r
190         pFrame->m_Data.m_baseFile.SetDescriptiveName(parser.GetVal(_T("basename")));\r
191         pFrame->m_Data.m_theirFile.SetFileName(parser.GetVal(_T("theirs")));\r
192         pFrame->m_Data.m_theirFile.SetDescriptiveName(parser.GetVal(_T("theirsname")));\r
193         pFrame->m_Data.m_yourFile.SetFileName(parser.GetVal(_T("mine")));\r
194         pFrame->m_Data.m_yourFile.SetDescriptiveName(parser.GetVal(_T("minename")));\r
195         pFrame->m_Data.m_mergedFile.SetFileName(parser.GetVal(_T("merged")));\r
196         pFrame->m_Data.m_mergedFile.SetDescriptiveName(parser.GetVal(_T("mergedname")));\r
197         pFrame->m_Data.m_sPatchPath = parser.HasVal(_T("patchpath")) ? parser.GetVal(_T("patchpath")) : _T("");\r
198         pFrame->m_Data.m_sPatchPath.Replace('/', '\\');\r
199         if (parser.HasKey(_T("patchoriginal")))\r
200                 pFrame->m_Data.m_sPatchOriginal = parser.GetVal(_T("patchoriginal"));\r
201         if (parser.HasKey(_T("patchpatched")))\r
202                 pFrame->m_Data.m_sPatchPatched = parser.GetVal(_T("patchpatched"));\r
203         pFrame->m_Data.m_sDiffFile = parser.GetVal(_T("diff"));\r
204         pFrame->m_Data.m_sDiffFile.Replace('/', '\\');\r
205         if (parser.HasKey(_T("oneway")))\r
206         pFrame->m_bOneWay = TRUE;\r
207         if (parser.HasKey(_T("diff")))\r
208                 pFrame->m_bOneWay = FALSE;\r
209         if (parser.HasKey(_T("reversedpatch")))\r
210                 pFrame->m_bReversedPatch = TRUE;\r
211         if (pFrame->m_Data.IsBaseFileInUse() && !pFrame->m_Data.IsYourFileInUse() && pFrame->m_Data.IsTheirFileInUse())\r
212         {\r
213                 pFrame->m_Data.m_yourFile.TransferDetailsFrom(pFrame->m_Data.m_theirFile);\r
214         }\r
215 \r
216         if ((!parser.HasKey(_T("patchpath")))&&(parser.HasVal(_T("diff"))))\r
217         {\r
218                 // a patchfile was given, but not folder path to apply the patch to\r
219                 // If the patchfile is located inside a working copy, then use the parent directory\r
220                 // of the patchfile as the target directory, otherwise ask the user for a path.\r
221                 if (parser.HasKey(_T("wc")))\r
222                         pFrame->m_Data.m_sPatchPath = pFrame->m_Data.m_sDiffFile.Left(pFrame->m_Data.m_sDiffFile.ReverseFind('\\'));\r
223                 else\r
224                 {\r
225                         CBrowseFolder fbrowser;\r
226                         fbrowser.m_style = BIF_EDITBOX | BIF_NEWDIALOGSTYLE | BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS;\r
227                         if (fbrowser.Show(NULL, pFrame->m_Data.m_sPatchPath)==CBrowseFolder::CANCEL)\r
228                                 return FALSE;\r
229                 }\r
230         }\r
231 \r
232         if ((parser.HasKey(_T("patchpath")))&&(!parser.HasVal(_T("diff"))))\r
233         {\r
234                 // A path was given for applying a patchfile, but\r
235                 // the patchfile itself was not.\r
236                 // So ask the user for that patchfile\r
237 \r
238                 OPENFILENAME ofn = {0};                 // common dialog box structure\r
239                 TCHAR szFile[MAX_PATH] = {0};   // buffer for file name\r
240                 // Initialize OPENFILENAME\r
241                 ofn.lStructSize = sizeof(OPENFILENAME);\r
242                 ofn.hwndOwner = pFrame->m_hWnd;\r
243                 ofn.lpstrFile = szFile;\r
244                 ofn.nMaxFile = sizeof(szFile)/sizeof(TCHAR);\r
245                 CString temp;\r
246                 temp.LoadString(IDS_OPENDIFFFILETITLE);\r
247                 if (temp.IsEmpty())\r
248                         ofn.lpstrTitle = NULL;\r
249                 else\r
250                         ofn.lpstrTitle = temp;\r
251 \r
252                 ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_EXPLORER;\r
253                 // check if there's a patchfile in the clipboard\r
254                 UINT cFormat = RegisterClipboardFormat(_T("TSVN_UNIFIEDDIFF"));\r
255                 if (cFormat)\r
256                 {\r
257                         if (OpenClipboard(NULL))\r
258                         {\r
259                                 UINT enumFormat = 0;\r
260                                 do \r
261                                 {\r
262                                         if (enumFormat == cFormat)\r
263                                         {\r
264                                                 // yes, there's a patchfile in the clipboard\r
265                                                 ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER;\r
266 \r
267                                                 ofn.hInstance = AfxGetResourceHandle();\r
268                                                 ofn.lpTemplateName = MAKEINTRESOURCE(IDD_PATCH_FILE_OPEN_CUSTOM);\r
269                                                 ofn.lpfnHook = CreatePatchFileOpenHook;\r
270                                         }\r
271                                 } while((enumFormat = EnumClipboardFormats(enumFormat))!=0);\r
272                                 CloseClipboard();\r
273                         }\r
274                 }\r
275 \r
276                 CString sFilter;\r
277                 sFilter.LoadString(IDS_PATCHFILEFILTER);\r
278                 TCHAR * pszFilters = new TCHAR[sFilter.GetLength()+4];\r
279                 _tcscpy_s (pszFilters, sFilter.GetLength()+4, sFilter);\r
280                 // Replace '|' delimiters with '\0's\r
281                 TCHAR *ptr = pszFilters + _tcslen(pszFilters);  //set ptr at the NULL\r
282                 while (ptr != pszFilters)\r
283                 {\r
284                         if (*ptr == '|')\r
285                                 *ptr = '\0';\r
286                         ptr--;\r
287                 }\r
288                 ofn.lpstrFilter = pszFilters;\r
289                 ofn.nFilterIndex = 1;\r
290 \r
291                 // Display the Open dialog box. \r
292                 CString tempfile;\r
293                 if (GetOpenFileName(&ofn)==FALSE)\r
294                 {\r
295                         delete [] pszFilters;\r
296                         return FALSE;\r
297                 }\r
298                 delete [] pszFilters;\r
299                 pFrame->m_Data.m_sDiffFile = ofn.lpstrFile;\r
300         }\r
301 \r
302         if ( pFrame->m_Data.m_baseFile.GetFilename().IsEmpty() && pFrame->m_Data.m_yourFile.GetFilename().IsEmpty() )\r
303         {\r
304                 LPWSTR *szArglist;\r
305                 int nArgs;\r
306 \r
307                 szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);\r
308                 if( NULL == szArglist )\r
309                 {\r
310                         TRACE("CommandLineToArgvW failed\n");\r
311                 }\r
312                 else\r
313                 {\r
314                         if ( nArgs==3 || nArgs==4 )\r
315                         {\r
316                                 // Four parameters:\r
317                                 // [0]: Program name\r
318                                 // [1]: BASE file\r
319                                 // [2]: my file\r
320                                 // [3]: THEIR file (optional)\r
321                                 // This is the same format CAppUtils::StartExtDiff\r
322                                 // uses if %base and %mine are not set and most\r
323                                 // other diff tools use it too.\r
324                                 if ( PathFileExists(szArglist[1]) && PathFileExists(szArglist[2]) )\r
325                                 {\r
326                                         pFrame->m_Data.m_baseFile.SetFileName(szArglist[1]);\r
327                                         pFrame->m_Data.m_yourFile.SetFileName(szArglist[2]);\r
328                                         if ( nArgs == 4 && PathFileExists(szArglist[3]) )\r
329                                         {\r
330                                                 pFrame->m_Data.m_theirFile.SetFileName(szArglist[3]);\r
331                                         }\r
332                                 }\r
333                         }\r
334                 }\r
335 \r
336                 // Free memory allocated for CommandLineToArgvW arguments.\r
337                 LocalFree(szArglist);\r
338         }\r
339 \r
340         pFrame->m_bReadOnly = !!parser.HasKey(_T("readonly"));\r
341         if (GetFileAttributes(pFrame->m_Data.m_yourFile.GetFilename()) & FILE_ATTRIBUTE_READONLY)\r
342                 pFrame->m_bReadOnly = true;\r
343         pFrame->m_bBlame = !!parser.HasKey(_T("blame"));\r
344         // diffing a blame means no editing!\r
345         if (pFrame->m_bBlame)\r
346                 pFrame->m_bReadOnly = true;\r
347 \r
348         // try to find a suitable window title\r
349         CString sYour = pFrame->m_Data.m_yourFile.GetDescriptiveName();\r
350         if (sYour.Find(_T(" - "))>=0)\r
351                 sYour = sYour.Left(sYour.Find(_T(" - ")));\r
352         if (sYour.Find(_T(" : "))>=0)\r
353                 sYour = sYour.Left(sYour.Find(_T(" : ")));\r
354         CString sTheir = pFrame->m_Data.m_theirFile.GetDescriptiveName();\r
355         if (sTheir.Find(_T(" - "))>=0)\r
356                 sTheir = sTheir.Left(sTheir.Find(_T(" - ")));\r
357         if (sTheir.Find(_T(" : "))>=0)\r
358                 sTheir = sTheir.Left(sTheir.Find(_T(" : ")));\r
359 \r
360         if (!sYour.IsEmpty() && !sTheir.IsEmpty())\r
361         {\r
362                 if (sYour.CompareNoCase(sTheir)==0)\r
363                         pFrame->SetWindowText(sYour + _T(" - TortoiseMerge"));\r
364                 else if ((sYour.GetLength() < 10) &&\r
365                                 (sTheir.GetLength() < 10))\r
366                         pFrame->SetWindowText(sYour + _T(" - ") + sTheir + _T(" - TortoiseMerge"));\r
367                 else\r
368                 {\r
369                         // we have two very long descriptive texts here, which\r
370                         // means we have to find a way to use them as a window \r
371                         // title in a shorter way.\r
372                         // for simplicity, we just use the one from "yourfile"\r
373                         pFrame->SetWindowText(sYour + _T(" - TortoiseMerge"));\r
374                 }\r
375         }\r
376         else if (!sYour.IsEmpty())\r
377                 pFrame->SetWindowText(sYour + _T(" - TortoiseMerge"));\r
378         else if (!sTheir.IsEmpty())\r
379                 pFrame->SetWindowText(sTheir + _T(" - TortoiseMerge"));\r
380 \r
381         if (parser.HasKey(_T("createunifieddiff")))\r
382         {\r
383                 // user requested to create a unified diff file\r
384                 CString origFile = parser.GetVal(_T("origfile"));\r
385                 CString modifiedFile = parser.GetVal(_T("modifiedfile"));\r
386                 if (!origFile.IsEmpty() && !modifiedFile.IsEmpty())\r
387                 {\r
388                         CString outfile = parser.GetVal(_T("outfile"));\r
389                         if (outfile.IsEmpty())\r
390                         {\r
391                                 OPENFILENAME ofn = {0};                 // common dialog box structure\r
392                                 TCHAR szFile[MAX_PATH] = {0};   // buffer for file name\r
393                                 ofn.lStructSize = sizeof(OPENFILENAME);\r
394                                 ofn.lpstrFile = szFile;\r
395                                 ofn.nMaxFile = sizeof(szFile)/sizeof(TCHAR);\r
396                                 CString temp;\r
397                                 temp.LoadString(IDS_SAVEASTITLE);\r
398                                 if (!temp.IsEmpty())\r
399                                         ofn.lpstrTitle = temp;\r
400                                 ofn.Flags = OFN_OVERWRITEPROMPT;\r
401                                 CString sFilter;\r
402                                 sFilter.LoadString(IDS_COMMONFILEFILTER);\r
403                                 TCHAR * pszFilters = new TCHAR[sFilter.GetLength()+4];\r
404                                 _tcscpy_s (pszFilters, sFilter.GetLength()+4, sFilter);\r
405                                 // Replace '|' delimiters with '\0's\r
406                                 TCHAR *ptr = pszFilters + _tcslen(pszFilters);  //set ptr at the NULL\r
407                                 while (ptr != pszFilters)\r
408                                 {\r
409                                         if (*ptr == '|')\r
410                                                 *ptr = '\0';\r
411                                         ptr--;\r
412                                 }\r
413                                 ofn.lpstrFilter = pszFilters;\r
414                                 ofn.nFilterIndex = 1;\r
415 \r
416                                 // Display the Save dialog box. \r
417                                 CString sFile;\r
418                                 if (GetSaveFileName(&ofn)==TRUE)\r
419                                 {\r
420                                         outfile = CString(ofn.lpstrFile);\r
421                                 }\r
422                                 delete [] pszFilters;\r
423                         }\r
424                         if (!outfile.IsEmpty())\r
425                         {\r
426                                 CAppUtils::CreateUnifiedDiff(origFile, modifiedFile, outfile, false);\r
427                                 return FALSE;\r
428                         }\r
429                 }\r
430         }\r
431         // The one and only window has been initialized, so show and update it\r
432         pFrame->ActivateFrame();\r
433         pFrame->ShowWindow(SW_SHOW);\r
434         pFrame->UpdateWindow();\r
435         pFrame->ShowDiffBar(!pFrame->m_bOneWay);\r
436         if (!pFrame->m_Data.IsBaseFileInUse() && pFrame->m_Data.m_sPatchPath.IsEmpty() && pFrame->m_Data.m_sDiffFile.IsEmpty())\r
437         {\r
438                 pFrame->OnFileOpen();\r
439                 return TRUE;\r
440         }\r
441 \r
442         return pFrame->LoadViews();\r
443 }\r
444 \r
445 // CTortoiseMergeApp message handlers\r
446 \r
447 void CTortoiseMergeApp::OnAppAbout()\r
448 {\r
449         CAboutDlg aboutDlg;\r
450         aboutDlg.DoModal();\r
451 }\r
452 \r
453 UINT_PTR CALLBACK \r
454 CTortoiseMergeApp::CreatePatchFileOpenHook(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM /*lParam*/)\r
455 {\r
456         if(uiMsg ==     WM_COMMAND && LOWORD(wParam) == IDC_PATCH_TO_CLIPBOARD)\r
457         {\r
458                 HWND hFileDialog = GetParent(hDlg);\r
459 \r
460                 // if there's a patchfile in the clipboard, we save it\r
461                 // to a temporary file and tell TortoiseMerge to use that one\r
462                 UINT cFormat = RegisterClipboardFormat(_T("TSVN_UNIFIEDDIFF"));\r
463                 if ((cFormat)&&(OpenClipboard(NULL)))\r
464                 { \r
465                         HGLOBAL hglb = GetClipboardData(cFormat); \r
466                         LPCSTR lpstr = (LPCSTR)GlobalLock(hglb); \r
467 \r
468                         DWORD len = GetTempPath(0, NULL);\r
469                         TCHAR * path = new TCHAR[len+1];\r
470                         TCHAR * tempF = new TCHAR[len+100];\r
471                         GetTempPath (len+1, path);\r
472                         GetTempFileName (path, TEXT("tsm"), 0, tempF);\r
473                         std::wstring sTempFile = std::wstring(tempF);\r
474                         delete [] path;\r
475                         delete [] tempF;\r
476 \r
477                         FILE * outFile;\r
478                         size_t patchlen = strlen(lpstr);\r
479                         _tfopen_s(&outFile, sTempFile.c_str(), _T("wb"));\r
480                         if(outFile)\r
481                         {\r
482                                 size_t size = fwrite(lpstr, sizeof(char), patchlen, outFile);\r
483                                 if (size == patchlen)\r
484                                 {\r
485                                         CommDlg_OpenSave_SetControlText(hFileDialog, edt1, sTempFile.c_str());   \r
486                                         PostMessage(hFileDialog, WM_COMMAND, MAKEWPARAM(IDOK, BM_CLICK), (LPARAM)(GetDlgItem(hDlg, IDOK)));\r
487                                 }\r
488                                 fclose(outFile);\r
489                         }\r
490                         GlobalUnlock(hglb); \r
491                         CloseClipboard(); \r
492                 } \r
493         }\r
494         return 0;\r
495 }\r
496 \r
497 int CTortoiseMergeApp::ExitInstance()\r
498 {\r
499         // Look for temporary files left around by TortoiseMerge and\r
500         // remove them. But only delete 'old' files \r
501         DWORD len = ::GetTempPath(0, NULL);\r
502         TCHAR * path = new TCHAR[len + 100];\r
503         len = ::GetTempPath (len+100, path);\r
504         if (len != 0)\r
505         {\r
506                 CSimpleFileFind finder = CSimpleFileFind(path, _T("*tsm*.*"));\r
507                 FILETIME systime_;\r
508                 ::GetSystemTimeAsFileTime(&systime_);\r
509                 __int64 systime = (((_int64)systime_.dwHighDateTime)<<32) | ((__int64)systime_.dwLowDateTime);\r
510                 while (finder.FindNextFileNoDirectories())\r
511                 {\r
512                         CString filepath = finder.GetFilePath();\r
513                         HANDLE hFile = ::CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);\r
514                         if (hFile != INVALID_HANDLE_VALUE)\r
515                         {\r
516                                 FILETIME createtime_;\r
517                                 if (::GetFileTime(hFile, &createtime_, NULL, NULL))\r
518                                 {\r
519                                         ::CloseHandle(hFile);\r
520                                         __int64 createtime = (((_int64)createtime_.dwHighDateTime)<<32) | ((__int64)createtime_.dwLowDateTime);\r
521                                         if ((createtime + 864000000000) < systime)              //only delete files older than a day\r
522                                         {\r
523                                                 ::SetFileAttributes(filepath, FILE_ATTRIBUTE_NORMAL);\r
524                                                 ::DeleteFile(filepath);\r
525                                         }\r
526                                 }\r
527                                 else\r
528                                         ::CloseHandle(hFile);\r
529                         }\r
530                 }\r
531         }       \r
532         delete[] path;          \r
533 \r
534         return CWinAppEx::ExitInstance();\r
535 }\r