OSDN Git Service

Update version number to 1.2.1.0
[tortoisegit/TortoiseGitJp.git] / src / TortoiseMerge / MainFrm.cpp
1 // TortoiseMerge - a Diff/Patch program\r
2 \r
3 // Copyright (C) 2004-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 "TortoiseMerge.h"\r
21 #include "OpenDlg.h"\r
22 #include "Patch.h"\r
23 #include "SysProgressDlg.h"\r
24 #include "Settings.h"\r
25 #include "MessageBox.h"\r
26 #include "AppUtils.h"\r
27 #include "PathUtils.h"\r
28 #include "MainFrm.h"\r
29 #include "LeftView.h"\r
30 #include "RightView.h"\r
31 #include "BottomView.h"\r
32 #include "DiffColors.h"\r
33 #include ".\mainfrm.h"\r
34 \r
35 #ifdef _DEBUG\r
36 #define new DEBUG_NEW\r
37 #endif                                           \r
38 \r
39 \r
40 // CMainFrame\r
41 const UINT CMainFrame::m_FindDialogMessage = RegisterWindowMessage(FINDMSGSTRING);\r
42 \r
43 IMPLEMENT_DYNCREATE(CMainFrame, CFrameWndEx)\r
44 \r
45 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)\r
46         ON_WM_CREATE()\r
47         ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_OFF_2007_AQUA, &CMainFrame::OnApplicationLook)\r
48         ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_OFF_2007_AQUA, &CMainFrame::OnUpdateApplicationLook)\r
49         // Global help commands\r
50         ON_COMMAND(ID_HELP_FINDER, CFrameWndEx::OnHelpFinder)\r
51         ON_COMMAND(ID_HELP, CFrameWndEx::OnHelp)\r
52         ON_COMMAND(ID_CONTEXT_HELP, CFrameWndEx::OnContextHelp)\r
53         ON_COMMAND(ID_DEFAULT_HELP, CFrameWndEx::OnHelpFinder)\r
54         ON_COMMAND(ID_FILE_OPEN, OnFileOpen)\r
55         ON_COMMAND(ID_VIEW_WHITESPACES, OnViewWhitespaces)\r
56         ON_WM_SIZE()\r
57         ON_COMMAND(ID_FILE_SAVE, OnFileSave)\r
58         ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs)\r
59         ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)\r
60         ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)\r
61         ON_COMMAND(ID_VIEW_ONEWAYDIFF, OnViewOnewaydiff)\r
62         ON_UPDATE_COMMAND_UI(ID_VIEW_ONEWAYDIFF, OnUpdateViewOnewaydiff)\r
63         ON_UPDATE_COMMAND_UI(ID_VIEW_WHITESPACES, OnUpdateViewWhitespaces)\r
64         ON_COMMAND(ID_VIEW_OPTIONS, OnViewOptions)\r
65         ON_WM_CLOSE()\r
66         ON_COMMAND(ID_EDIT_FIND, OnEditFind)\r
67         ON_REGISTERED_MESSAGE(m_FindDialogMessage, OnFindDialogMessage) \r
68         ON_COMMAND(ID_EDIT_FINDNEXT, OnEditFindnext)\r
69         ON_COMMAND(ID_EDIT_FINDPREV, OnEditFindprev)\r
70         ON_COMMAND(ID_FILE_RELOAD, OnFileReload)\r
71         ON_COMMAND(ID_VIEW_LINEDOWN, OnViewLinedown)\r
72         ON_COMMAND(ID_VIEW_LINEUP, OnViewLineup)\r
73         ON_UPDATE_COMMAND_UI(ID_EDIT_MARKASRESOLVED, OnUpdateMergeMarkasresolved)\r
74         ON_COMMAND(ID_EDIT_MARKASRESOLVED, OnMergeMarkasresolved)\r
75         ON_UPDATE_COMMAND_UI(ID_NAVIGATE_NEXTCONFLICT, OnUpdateMergeNextconflict)\r
76         ON_UPDATE_COMMAND_UI(ID_NAVIGATE_PREVIOUSCONFLICT, OnUpdateMergePreviousconflict)\r
77         ON_WM_MOVE()\r
78         ON_WM_MOVING()\r
79         ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)\r
80         ON_COMMAND(ID_VIEW_SWITCHLEFT, OnViewSwitchleft)\r
81         ON_UPDATE_COMMAND_UI(ID_VIEW_SWITCHLEFT, OnUpdateViewSwitchleft)\r
82         ON_COMMAND(ID_VIEW_LINELEFT, &CMainFrame::OnViewLineleft)\r
83         ON_COMMAND(ID_VIEW_LINERIGHT, &CMainFrame::OnViewLineright)\r
84         ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWFILELIST, &CMainFrame::OnUpdateViewShowfilelist)\r
85         ON_COMMAND(ID_VIEW_SHOWFILELIST, &CMainFrame::OnViewShowfilelist)\r
86         ON_COMMAND(ID_EDIT_USETHEIRBLOCK, &CMainFrame::OnEditUseTheirs)\r
87     ON_COMMAND(ID_EDIT_USEMYBLOCK, &CMainFrame::OnEditUseMine)\r
88     ON_COMMAND(ID_EDIT_USETHEIRTHENMYBLOCK, &CMainFrame::OnEditUseTheirsThenMine)\r
89     ON_COMMAND(ID_EDIT_USEMINETHENTHEIRBLOCK, &CMainFrame::OnEditUseMineThenTheirs)\r
90         ON_COMMAND(ID_EDIT_UNDO, &CMainFrame::OnEditUndo)\r
91         ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, &CMainFrame::OnUpdateEditUndo)\r
92         ON_UPDATE_COMMAND_UI(ID_EDIT_USEMINETHENTHEIRBLOCK, &CMainFrame::OnUpdateEditUseminethentheirblock)\r
93         ON_UPDATE_COMMAND_UI(ID_EDIT_USEMYBLOCK, &CMainFrame::OnUpdateEditUsemyblock)\r
94         ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRBLOCK, &CMainFrame::OnUpdateEditUsetheirblock)\r
95         ON_UPDATE_COMMAND_UI(ID_EDIT_USETHEIRTHENMYBLOCK, &CMainFrame::OnUpdateEditUsetheirthenmyblock)\r
96         ON_COMMAND(ID_VIEW_INLINEDIFFWORD, &CMainFrame::OnViewInlinediffword)\r
97         ON_UPDATE_COMMAND_UI(ID_VIEW_INLINEDIFFWORD, &CMainFrame::OnUpdateViewInlinediffword)\r
98         ON_UPDATE_COMMAND_UI(ID_EDIT_CREATEUNIFIEDDIFFFILE, &CMainFrame::OnUpdateEditCreateunifieddifffile)\r
99         ON_COMMAND(ID_EDIT_CREATEUNIFIEDDIFFFILE, &CMainFrame::OnEditCreateunifieddifffile)\r
100         ON_UPDATE_COMMAND_UI(ID_VIEW_LINEDIFFBAR, &CMainFrame::OnUpdateViewLinediffbar)\r
101         ON_COMMAND(ID_VIEW_LINEDIFFBAR, &CMainFrame::OnViewLinediffbar)\r
102         ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATORBAR, &CMainFrame::OnUpdateViewLocatorbar)\r
103         ON_COMMAND(ID_VIEW_LOCATORBAR, &CMainFrame::OnViewLocatorbar)\r
104         ON_COMMAND(ID_EDIT_USELEFTBLOCK, &CMainFrame::OnEditUseleftblock)\r
105         ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTBLOCK, &CMainFrame::OnUpdateEditUseleftblock)\r
106         ON_COMMAND(ID_EDIT_USELEFTFILE, &CMainFrame::OnEditUseleftfile)\r
107         ON_UPDATE_COMMAND_UI(ID_EDIT_USELEFTFILE, &CMainFrame::OnUpdateEditUseleftfile)\r
108         ON_COMMAND(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT, &CMainFrame::OnEditUseblockfromleftbeforeright)\r
109         ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMLEFTBEFORERIGHT, &CMainFrame::OnUpdateEditUseblockfromleftbeforeright)\r
110         ON_COMMAND(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT, &CMainFrame::OnEditUseblockfromrightbeforeleft)\r
111         ON_UPDATE_COMMAND_UI(ID_EDIT_USEBLOCKFROMRIGHTBEFORELEFT, &CMainFrame::OnUpdateEditUseblockfromrightbeforeleft)\r
112 END_MESSAGE_MAP()\r
113 \r
114 static UINT indicators[] =\r
115 {\r
116         ID_SEPARATOR,           // status line indicator\r
117         ID_INDICATOR_LEFTVIEW,\r
118         ID_INDICATOR_RIGHTVIEW,\r
119         ID_INDICATOR_BOTTOMVIEW,\r
120         ID_INDICATOR_CAPS,\r
121         ID_INDICATOR_NUM,\r
122         ID_INDICATOR_SCRL\r
123 };\r
124 \r
125 \r
126 // CMainFrame construction/destruction\r
127 \r
128 CMainFrame::CMainFrame()\r
129 {\r
130         m_pFindDialog = NULL;\r
131         m_nSearchIndex = 0;\r
132         m_bInitSplitter = FALSE;\r
133         m_bOneWay = (0 != ((DWORD)CRegDWORD(_T("Software\\TortoiseMerge\\OnePane"))));\r
134         m_bReversedPatch = FALSE;\r
135         m_bHasConflicts = false;\r
136         m_bInlineWordDiff = true;\r
137         m_bLineDiff = true;\r
138         m_bLocatorBar = true;\r
139         m_nMoveMovesToIgnore = 0;\r
140         theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_VS_2005);\r
141 }\r
142 \r
143 CMainFrame::~CMainFrame()\r
144 {\r
145 }\r
146 \r
147 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)\r
148 {\r
149         if (CFrameWndEx::OnCreate(lpCreateStruct) == -1)\r
150                 return -1;\r
151 \r
152         OnApplicationLook(theApp.m_nAppLook);\r
153 \r
154         if (!m_wndMenuBar.Create(this))\r
155         {\r
156                 TRACE0("Failed to create menubar\n");\r
157                 return -1;      // fail to create\r
158         }\r
159 \r
160         m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);\r
161 \r
162         // prevent the menu bar from taking the focus on activation\r
163         CMFCPopupMenu::SetForceMenuFocus(FALSE);\r
164 \r
165         if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY) ||\r
166                 !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))\r
167         {\r
168                 TRACE0("Failed to create toolbar\n");\r
169                 return -1;      // fail to create\r
170         }\r
171         m_wndToolBar.SetWindowText(_T("Main"));\r
172 \r
173         if (!m_wndStatusBar.Create(this) ||\r
174                 !m_wndStatusBar.SetIndicators(indicators,\r
175                   sizeof(indicators)/sizeof(UINT)))\r
176         {\r
177                 TRACE0("Failed to create status bar\n");\r
178                 return -1;      // fail to create\r
179         } \r
180 \r
181         if (!m_wndLocatorBar.Create(this, IDD_DIFFLOCATOR, \r
182                 CBRS_ALIGN_LEFT | CBRS_SIZE_FIXED, ID_VIEW_LOCATORBAR))\r
183         {\r
184                 TRACE0("Failed to create dialogbar\n");\r
185                 return -1;              // fail to create\r
186         }\r
187         if (!m_wndLineDiffBar.Create(this, IDD_LINEDIFF, \r
188                 CBRS_ALIGN_BOTTOM | CBRS_SIZE_FIXED, ID_VIEW_LINEDIFFBAR))\r
189         {\r
190                 TRACE0("Failed to create dialogbar\n");\r
191                 return -1;              // fail to create\r
192         }\r
193         m_wndLocatorBar.m_pMainFrm = this;\r
194         m_wndLineDiffBar.m_pMainFrm = this;\r
195 \r
196         EnableDocking(CBRS_ALIGN_ANY);\r
197         m_wndMenuBar.EnableDocking(CBRS_ALIGN_TOP);\r
198         m_wndToolBar.EnableDocking(CBRS_ALIGN_TOP);\r
199         DockPane(&m_wndMenuBar);\r
200         DockPane(&m_wndToolBar);\r
201         DockPane(&m_wndLocatorBar);\r
202         DockPane(&m_wndLineDiffBar);\r
203         ShowPane(&m_wndLocatorBar, true, false, true);\r
204         ShowPane(&m_wndLineDiffBar, true, false, true);\r
205 \r
206         m_wndLocatorBar.EnableGripper(FALSE);\r
207         m_wndLineDiffBar.EnableGripper(FALSE);\r
208 \r
209         return 0;\r
210 }\r
211 \r
212 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)\r
213 {\r
214         if( !CFrameWndEx::PreCreateWindow(cs) )\r
215                 return FALSE;\r
216         return TRUE;\r
217 }\r
218 \r
219 void CMainFrame::OnApplicationLook(UINT id)\r
220 {\r
221         CWaitCursor wait;\r
222 \r
223         theApp.m_nAppLook = id;\r
224 \r
225         switch (theApp.m_nAppLook)\r
226         {\r
227         case ID_VIEW_APPLOOK_WIN_2000:\r
228                 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager));\r
229                 break;\r
230 \r
231         case ID_VIEW_APPLOOK_OFF_XP:\r
232                 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP));\r
233                 break;\r
234 \r
235         case ID_VIEW_APPLOOK_WIN_XP:\r
236                 CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;\r
237                 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));\r
238                 break;\r
239 \r
240         case ID_VIEW_APPLOOK_OFF_2003:\r
241                 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003));\r
242                 CDockingManager::SetDockingMode(DT_SMART);\r
243                 break;\r
244 \r
245         case ID_VIEW_APPLOOK_VS_2005:\r
246                 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005));\r
247                 CDockingManager::SetDockingMode(DT_SMART);\r
248                 break;\r
249 \r
250         default:\r
251                 switch (theApp.m_nAppLook)\r
252                 {\r
253                 case ID_VIEW_APPLOOK_OFF_2007_BLUE:\r
254                         CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);\r
255                         break;\r
256 \r
257                 case ID_VIEW_APPLOOK_OFF_2007_BLACK:\r
258                         CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack);\r
259                         break;\r
260 \r
261                 case ID_VIEW_APPLOOK_OFF_2007_SILVER:\r
262                         CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver);\r
263                         break;\r
264 \r
265                 case ID_VIEW_APPLOOK_OFF_2007_AQUA:\r
266                         CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua);\r
267                         break;\r
268                 }\r
269 \r
270                 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));\r
271                 CDockingManager::SetDockingMode(DT_SMART);\r
272         }\r
273 \r
274         RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME | RDW_ERASE);\r
275 \r
276         theApp.WriteInt(_T("ApplicationLook"), theApp.m_nAppLook);\r
277 }\r
278 \r
279 void CMainFrame::OnUpdateApplicationLook(CCmdUI* pCmdUI)\r
280 {\r
281         pCmdUI->SetRadio(theApp.m_nAppLook == pCmdUI->m_nID);\r
282 }\r
283 \r
284 \r
285 // CMainFrame diagnostics\r
286 \r
287 #ifdef _DEBUG\r
288 void CMainFrame::AssertValid() const\r
289 {\r
290         CFrameWndEx::AssertValid();\r
291 }\r
292 \r
293 void CMainFrame::Dump(CDumpContext& dc) const\r
294 {\r
295         CFrameWndEx::Dump(dc);\r
296 }\r
297 \r
298 #endif //_DEBUG\r
299 \r
300 \r
301 // CMainFrame message handlers\r
302 \r
303 \r
304 BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)\r
305 {\r
306         CRect cr; \r
307         GetClientRect( &cr);\r
308 \r
309 \r
310         // split into three panes:\r
311         //        -------------\r
312         //        |     |     |\r
313         //        |     |     |\r
314         //        |------------\r
315         //        |           |\r
316         //        |           |\r
317         //        |------------\r
318 \r
319         // create a splitter with 2 rows, 1 column \r
320         if (!m_wndSplitter.CreateStatic(this, 2, 1))\r
321         { \r
322                 TRACE0("Failed to CreateStaticSplitter\n"); \r
323                 return FALSE; \r
324         }\r
325 \r
326         // add the second splitter pane - which is a nested splitter with 2 columns \r
327         if (!m_wndSplitter2.CreateStatic( \r
328                 &m_wndSplitter, // our parent window is the first splitter \r
329                 1, 2, // the new splitter is 1 row, 2 columns\r
330                 WS_CHILD | WS_VISIBLE | WS_BORDER, // style, WS_BORDER is needed \r
331                 m_wndSplitter.IdFromRowCol(0, 0) \r
332                 // new splitter is in the first row, 1st column of first splitter \r
333                 )) \r
334         { \r
335                 TRACE0("Failed to create nested splitter\n"); \r
336                 return FALSE; \r
337         }\r
338         // add the first splitter pane - the default view in row 0 \r
339         if (!m_wndSplitter.CreateView(1, 0, \r
340                 RUNTIME_CLASS(CBottomView), CSize(cr.Width(), cr.Height()), pContext)) \r
341         { \r
342                 TRACE0("Failed to create first pane\n"); \r
343                 return FALSE; \r
344         }\r
345         m_pwndBottomView = (CBottomView *)m_wndSplitter.GetPane(1,0);\r
346         m_pwndBottomView->m_pwndLocator = &m_wndLocatorBar;\r
347         m_pwndBottomView->m_pwndLineDiffBar = &m_wndLineDiffBar;\r
348         m_pwndBottomView->m_pwndStatusBar = &m_wndStatusBar;\r
349         m_pwndBottomView->m_pMainFrame = this;\r
350 \r
351         // now create the two views inside the nested splitter \r
352 \r
353         if (!m_wndSplitter2.CreateView(0, 0, \r
354                 RUNTIME_CLASS(CLeftView), CSize(cr.Width()/2, cr.Height()/2), pContext)) \r
355         { \r
356                 TRACE0("Failed to create second pane\n"); \r
357                 return FALSE; \r
358         }\r
359         m_pwndLeftView = (CLeftView *)m_wndSplitter2.GetPane(0,0);\r
360         m_pwndLeftView->m_pwndLocator = &m_wndLocatorBar;\r
361         m_pwndLeftView->m_pwndLineDiffBar = &m_wndLineDiffBar;\r
362         m_pwndLeftView->m_pwndStatusBar = &m_wndStatusBar;\r
363         m_pwndLeftView->m_pMainFrame = this;\r
364 \r
365         if (!m_wndSplitter2.CreateView(0, 1, \r
366                 RUNTIME_CLASS(CRightView), CSize(cr.Width()/2, cr.Height()/2), pContext)) \r
367         { \r
368                 TRACE0("Failed to create third pane\n"); \r
369                 return FALSE; \r
370         }\r
371         m_pwndRightView = (CRightView *)m_wndSplitter2.GetPane(0,1);\r
372         m_pwndRightView->m_pwndLocator = &m_wndLocatorBar;\r
373         m_pwndRightView->m_pwndLineDiffBar = &m_wndLineDiffBar;\r
374         m_pwndRightView->m_pwndStatusBar = &m_wndStatusBar;\r
375         m_pwndRightView->m_pMainFrame = this;\r
376         m_bInitSplitter = TRUE;\r
377 \r
378         m_dlgFilePatches.Create(IDD_FILEPATCHES, this);\r
379         UpdateLayout();\r
380         return TRUE;\r
381 }\r
382 \r
383 // Callback function\r
384 BOOL CMainFrame::PatchFile(CString sFilePath, CString sVersion, BOOL bAutoPatch,BOOL bIsReview)\r
385 {\r
386         //first, do a "dry run" of patching...\r
387         if (!m_Patch.PatchFile(sFilePath))\r
388         {\r
389                 //patching not successful, so retrieve the\r
390                 //base file from version control and try\r
391                 //again...\r
392                 CString sTemp;\r
393                 CSysProgressDlg progDlg;\r
394                 sTemp.Format(IDS_GETVERSIONOFFILE, (LPCTSTR)sVersion);\r
395                 progDlg.SetLine(1, sTemp, true);\r
396                 progDlg.SetLine(2, sFilePath, true);\r
397                 sTemp.LoadString(IDS_GETVERSIONOFFILETITLE);\r
398                 progDlg.SetTitle(sTemp);\r
399                 progDlg.SetShowProgressBar(false);\r
400                 progDlg.SetAnimation(IDR_DOWNLOAD);\r
401                 progDlg.SetTime(FALSE);\r
402 \r
403                 if(!m_Patch.m_IsGitPatch)\r
404                         progDlg.ShowModeless(this);\r
405 \r
406                 CString sBaseFile = m_TempFiles.GetTempFilePath();\r
407                 if (!CAppUtils::GetVersionedFile(sFilePath, sVersion, sBaseFile, &progDlg, m_hWnd))\r
408                 {\r
409                         progDlg.Stop();\r
410                         CString sErrMsg;\r
411                         sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sVersion, (LPCTSTR)sFilePath);\r
412                         MessageBox(sErrMsg, NULL, MB_ICONERROR);\r
413                         return FALSE;\r
414                 }\r
415                 progDlg.Stop();\r
416                 CString sTempFile = m_TempFiles.GetTempFilePath();\r
417                 if (!m_Patch.PatchFile(sFilePath, sTempFile, sBaseFile))\r
418                 {\r
419                         MessageBox(m_Patch.GetErrorMessage(), NULL, MB_ICONERROR);\r
420                         return FALSE;\r
421                 }\r
422                 \r
423                 CString temp;\r
424                 if(bIsReview)\r
425                 {\r
426                         \r
427                         temp.Format(_T("%s Revision %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)sVersion);\r
428                         m_Data.m_baseFile.SetFileName(sBaseFile);\r
429                         m_Data.m_baseFile.SetDescriptiveName(temp);\r
430                         temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchPatched);\r
431                         m_Data.m_yourFile.SetFileName(sTempFile);\r
432                         m_Data.m_yourFile.SetDescriptiveName(temp);\r
433                         m_Data.m_theirFile.SetOutOfUse();\r
434                         m_Data.m_mergedFile.SetOutOfUse();\r
435                 \r
436                 }else\r
437                 {\r
438                         temp.Format(_T("%s Revision %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)sVersion);\r
439                         m_Data.m_baseFile.SetFileName(sBaseFile);\r
440                         m_Data.m_baseFile.SetDescriptiveName(temp);\r
441                         temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchPatched);\r
442                         m_Data.m_theirFile.SetFileName(sTempFile);\r
443                         m_Data.m_theirFile.SetDescriptiveName(temp);\r
444                         m_Data.m_yourFile.SetFileName(sFilePath);\r
445                         m_Data.m_yourFile.SetDescriptiveName(CPathUtils::GetFileNameFromPath(sFilePath));\r
446                         m_Data.m_mergedFile.SetFileName(sFilePath);\r
447                         m_Data.m_mergedFile.SetDescriptiveName(CPathUtils::GetFileNameFromPath(sFilePath));\r
448                 }\r
449                 TRACE(_T("comparing %s and %s\nagainst the base file %s\n"), (LPCTSTR)sTempFile, (LPCTSTR)sFilePath, (LPCTSTR)sBaseFile);\r
450 \r
451         \r
452         }\r
453         else\r
454         {\r
455                 //"dry run" was successful, so save the patched file somewhere...\r
456                 CString sTempFile = m_TempFiles.GetTempFilePath();\r
457                 if (!m_Patch.PatchFile(sFilePath, sTempFile))\r
458                 {\r
459                         MessageBox(m_Patch.GetErrorMessage(), NULL, MB_ICONERROR);\r
460                         return FALSE;\r
461                 }\r
462                 if (m_bReversedPatch)\r
463                 {\r
464                         m_Data.m_baseFile.SetFileName(sTempFile);\r
465                         CString temp;\r
466                         temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchPatched);\r
467                         m_Data.m_baseFile.SetDescriptiveName(temp);\r
468                         m_Data.m_yourFile.SetFileName(sFilePath);\r
469                         temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchOriginal);\r
470                         m_Data.m_yourFile.SetDescriptiveName(temp);\r
471                         m_Data.m_theirFile.SetOutOfUse();\r
472                         m_Data.m_mergedFile.SetOutOfUse();\r
473                 }\r
474                 else\r
475                 {\r
476                         if (!PathFileExists(sFilePath))\r
477                         {\r
478                                 m_Data.m_baseFile.SetFileName(m_TempFiles.GetTempFilePath());\r
479                                 m_Data.m_baseFile.CreateEmptyFile();\r
480                         }\r
481                         else\r
482                         {\r
483                                 m_Data.m_baseFile.SetFileName(sFilePath);\r
484                         }\r
485                         CString sDescription;\r
486                         sDescription.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchOriginal);\r
487                         m_Data.m_baseFile.SetDescriptiveName(sDescription);\r
488                         m_Data.m_yourFile.SetFileName(sTempFile);\r
489                         CString temp;\r
490                         temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchPatched);\r
491                         m_Data.m_yourFile.SetDescriptiveName(temp);\r
492                         m_Data.m_theirFile.SetOutOfUse();\r
493                         m_Data.m_mergedFile.SetFileName(sFilePath);\r
494                 }\r
495                 TRACE(_T("comparing %s\nwith the patched result %s\n"), (LPCTSTR)sFilePath, (LPCTSTR)sTempFile);\r
496         }\r
497         LoadViews();\r
498         if (bAutoPatch)\r
499         {\r
500                 OnFileSave();\r
501         }\r
502         return TRUE;\r
503 }\r
504 \r
505 // Callback function\r
506 BOOL CMainFrame::DiffFiles(CString sURL1, CString sRev1, CString sURL2, CString sRev2)\r
507 {\r
508         CString tempfile1 = m_TempFiles.GetTempFilePath();\r
509         CString tempfile2 = m_TempFiles.GetTempFilePath();\r
510         \r
511         ASSERT(tempfile1.Compare(tempfile2));\r
512         \r
513         CString sTemp;\r
514         CSysProgressDlg progDlg;\r
515         sTemp.Format(IDS_GETVERSIONOFFILE, (LPCTSTR)sRev1);\r
516         progDlg.SetLine(1, sTemp, true);\r
517         progDlg.SetLine(2, sURL1, true);\r
518         sTemp.LoadString(IDS_GETVERSIONOFFILETITLE);\r
519         progDlg.SetTitle(sTemp);\r
520         progDlg.SetShowProgressBar(true);\r
521         progDlg.SetAnimation(IDR_DOWNLOAD);\r
522         progDlg.SetTime(FALSE);\r
523         progDlg.SetProgress(1,100);\r
524         progDlg.ShowModeless(this);\r
525         if (!CAppUtils::GetVersionedFile(sURL1, sRev1, tempfile1, &progDlg, m_hWnd))\r
526         {\r
527                 progDlg.Stop();\r
528                 CString sErrMsg;\r
529                 sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sRev1, (LPCTSTR)sURL1);\r
530                 MessageBox(sErrMsg, NULL, MB_ICONERROR);\r
531                 return FALSE;\r
532         }\r
533         sTemp.Format(IDS_GETVERSIONOFFILE, (LPCTSTR)sRev2);\r
534         progDlg.SetLine(1, sTemp, true);\r
535         progDlg.SetLine(2, sURL2, true);\r
536         progDlg.SetProgress(50, 100);\r
537         if (!CAppUtils::GetVersionedFile(sURL2, sRev2, tempfile2, &progDlg, m_hWnd))\r
538         {\r
539                 progDlg.Stop();\r
540                 CString sErrMsg;\r
541                 sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sRev2, (LPCTSTR)sURL2);\r
542                 MessageBox(sErrMsg, NULL, MB_ICONERROR);\r
543                 return FALSE;\r
544         }\r
545         progDlg.SetProgress(100,100);\r
546         progDlg.Stop();\r
547         CString temp;\r
548         temp.Format(_T("%s Revision %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sURL1), (LPCTSTR)sRev1);\r
549         m_Data.m_baseFile.SetFileName(tempfile1);\r
550         m_Data.m_baseFile.SetDescriptiveName(temp);\r
551         temp.Format(_T("%s Revision %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sURL2), (LPCTSTR)sRev2);\r
552         m_Data.m_yourFile.SetFileName(tempfile2);\r
553         m_Data.m_yourFile.SetDescriptiveName(temp);\r
554 \r
555         LoadViews();\r
556 \r
557         return TRUE;\r
558 }\r
559 \r
560 void CMainFrame::OnFileOpen()\r
561 {\r
562         if (CheckForSave()==IDCANCEL)\r
563                 return;\r
564         COpenDlg dlg;\r
565         if (dlg.DoModal()!=IDOK)\r
566         {\r
567                 return;\r
568         }\r
569         m_dlgFilePatches.ShowWindow(SW_HIDE);\r
570         m_dlgFilePatches.Init(NULL, NULL, CString(), NULL);\r
571         TRACE(_T("got the files:\n   %s\n   %s\n   %s\n   %s\n   %s\n"), (LPCTSTR)dlg.m_sBaseFile, (LPCTSTR)dlg.m_sTheirFile, (LPCTSTR)dlg.m_sYourFile, \r
572                 (LPCTSTR)dlg.m_sUnifiedDiffFile, (LPCTSTR)dlg.m_sPatchDirectory);\r
573         m_Data.m_baseFile.SetFileName(dlg.m_sBaseFile);\r
574         m_Data.m_theirFile.SetFileName(dlg.m_sTheirFile);\r
575         m_Data.m_yourFile.SetFileName(dlg.m_sYourFile);\r
576         m_Data.m_sDiffFile = dlg.m_sUnifiedDiffFile;\r
577         m_Data.m_sPatchPath = dlg.m_sPatchDirectory;\r
578         m_Data.m_mergedFile.SetOutOfUse();\r
579         g_crasher.AddFile((LPCSTR)(LPCTSTR)dlg.m_sBaseFile, (LPCSTR)(LPCTSTR)_T("Basefile"));\r
580         g_crasher.AddFile((LPCSTR)(LPCTSTR)dlg.m_sTheirFile, (LPCSTR)(LPCTSTR)_T("Theirfile"));\r
581         g_crasher.AddFile((LPCSTR)(LPCTSTR)dlg.m_sYourFile, (LPCSTR)(LPCTSTR)_T("Yourfile"));\r
582         g_crasher.AddFile((LPCSTR)(LPCTSTR)dlg.m_sUnifiedDiffFile, (LPCSTR)(LPCTSTR)_T("Difffile"));\r
583         \r
584         if (!m_Data.IsBaseFileInUse() && m_Data.IsTheirFileInUse() && m_Data.IsYourFileInUse())\r
585         {\r
586                 // a diff between two files means "Yours" against "Base", not "Theirs" against "Yours"\r
587                 m_Data.m_baseFile.TransferDetailsFrom(m_Data.m_theirFile);\r
588         }\r
589         if (m_Data.IsBaseFileInUse() && m_Data.IsTheirFileInUse() && !m_Data.IsYourFileInUse())\r
590         {\r
591                 // a diff between two files means "Yours" against "Base", not "Theirs" against "Base"\r
592                 m_Data.m_yourFile.TransferDetailsFrom(m_Data.m_theirFile);\r
593         }\r
594 \r
595         LoadViews();\r
596 }\r
597 \r
598 void CMainFrame::ClearViewNamesAndPaths() {\r
599         m_pwndLeftView->m_sWindowName.Empty();\r
600         m_pwndLeftView->m_sFullFilePath.Empty();\r
601         m_pwndRightView->m_sWindowName.Empty();\r
602         m_pwndRightView->m_sFullFilePath.Empty();\r
603         m_pwndBottomView->m_sWindowName.Empty();\r
604         m_pwndBottomView->m_sFullFilePath.Empty();\r
605 }\r
606 \r
607 bool CMainFrame::LoadViews(bool bRetainPosition)\r
608 {\r
609         m_Data.SetBlame(m_bBlame);\r
610         m_bHasConflicts = false;\r
611         CBaseView* pwndActiveView = m_pwndLeftView;\r
612         int nOldLine = m_pwndLeftView ? m_pwndLeftView->m_nTopLine : -1;\r
613         int nOldLineNumber =\r
614                 m_pwndLeftView && m_pwndLeftView->m_pViewData ?\r
615                 m_pwndLeftView->m_pViewData->GetLineNumber(m_pwndLeftView->m_nTopLine) : -1;\r
616         if (!m_Data.Load())\r
617         {\r
618                 ::MessageBox(NULL, m_Data.GetError(), _T("TortoiseMerge"), MB_ICONERROR);\r
619                 m_Data.m_mergedFile.SetOutOfUse();\r
620                 return false;\r
621         }\r
622 \r
623         m_pwndRightView->UseCaret(false);\r
624         m_pwndBottomView->UseCaret(false);\r
625 \r
626         if (!m_Data.IsBaseFileInUse())\r
627         {\r
628                 if (m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())\r
629                 {\r
630                         m_Data.m_baseFile.TransferDetailsFrom(m_Data.m_theirFile);\r
631                 }\r
632                 else if ((!m_Data.m_sDiffFile.IsEmpty())&&(!m_Patch.OpenUnifiedDiffFile(m_Data.m_sDiffFile)))\r
633                 {\r
634                         ClearViewNamesAndPaths();\r
635                         MessageBox(m_Patch.GetErrorMessage(), NULL, MB_ICONERROR);\r
636                         return false;\r
637                 }\r
638                 if (m_Patch.GetNumberOfFiles() > 0)\r
639                 {\r
640                         CString firstpath = m_Patch.GetFilename(0);\r
641                         CString path=firstpath;\r
642                         path.Replace('/','\\');\r
643                         if ( !PathIsRelative(path) && !PathFileExists(path) )\r
644                         {\r
645                                 // The absolute path mentioned in the patch does not exist. Lets\r
646                                 // try to find the correct relative path by stripping prefixes.\r
647                                 BOOL bFound = m_Patch.StripPrefixes(m_Data.m_sPatchPath);\r
648                                 CString strippedpath = m_Patch.GetFilename(0);\r
649                                 if (bFound)\r
650                                 {\r
651                                         CString msg;\r
652                                         msg.Format(IDS_WARNABSOLUTEPATHFOUND, (LPCTSTR)firstpath, (LPCTSTR)strippedpath);\r
653                                         if (CMessageBox::Show(m_hWnd, msg, _T("TortoiseMerge"), MB_ICONQUESTION | MB_YESNO)==IDNO)\r
654                                                 return false;\r
655                                 }\r
656                                 else\r
657                                 {\r
658                                         CString msg;\r
659                                         msg.Format(IDS_WARNABSOLUTEPATHNOTFOUND, (LPCTSTR)firstpath);\r
660                                         CMessageBox::Show(m_hWnd, msg, _T("TortoiseMerge"), MB_ICONEXCLAMATION);\r
661                                         return false;\r
662                                 }\r
663                         }\r
664                         CString betterpatchpath = m_Patch.CheckPatchPath(m_Data.m_sPatchPath);\r
665                         if (betterpatchpath.CompareNoCase(m_Data.m_sPatchPath)!=0)\r
666                         {\r
667                                 CString msg;\r
668                                 msg.Format(IDS_WARNBETTERPATCHPATHFOUND, (LPCTSTR)m_Data.m_sPatchPath, (LPCTSTR)betterpatchpath);\r
669                                 if (CMessageBox::Show(m_hWnd, msg, _T("TortoiseMerge"), MB_ICONQUESTION | MB_YESNO)==IDYES)\r
670                                         m_Data.m_sPatchPath = betterpatchpath;\r
671                         }\r
672                         m_dlgFilePatches.Init(&m_Patch, this, m_Data.m_sPatchPath, this);\r
673                         m_dlgFilePatches.ShowWindow(SW_SHOW);\r
674                         ClearViewNamesAndPaths();\r
675                         if (!m_wndSplitter.IsRowHidden(1))\r
676                                 m_wndSplitter.HideRow(1);\r
677                         m_pwndLeftView->SetHidden(FALSE);\r
678                         m_pwndRightView->SetHidden(FALSE);\r
679                         m_pwndBottomView->SetHidden(TRUE);\r
680                 }\r
681         }\r
682         if (m_Data.IsBaseFileInUse() && !m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())\r
683         {\r
684                 m_Data.m_yourFile.TransferDetailsFrom(m_Data.m_theirFile);\r
685         }\r
686         if (m_Data.IsBaseFileInUse() && m_Data.IsYourFileInUse() && !m_Data.IsTheirFileInUse())\r
687         {\r
688                 //diff between YOUR and BASE\r
689                 m_pwndRightView->UseCaret();\r
690                 if (m_bOneWay)\r
691                 {\r
692                         if (!m_wndSplitter2.IsColumnHidden(1))\r
693                                 m_wndSplitter2.HideColumn(1);\r
694 \r
695                         m_pwndLeftView->m_pViewData = &m_Data.m_YourBaseBoth;\r
696                         m_pwndLeftView->texttype = m_Data.m_arYourFile.GetUnicodeType();\r
697                         m_pwndLeftView->lineendings = m_Data.m_arYourFile.GetLineEndings();\r
698                         m_pwndLeftView->m_sWindowName = m_Data.m_baseFile.GetWindowName() + _T(" - ") + m_Data.m_yourFile.GetWindowName();\r
699                         m_pwndLeftView->m_sFullFilePath = m_Data.m_baseFile.GetFilename() + _T(" - ") + m_Data.m_yourFile.GetFilename();\r
700 \r
701                         m_pwndRightView->m_pViewData = NULL;\r
702                         m_pwndBottomView->m_pViewData = NULL;\r
703 \r
704                         if (!m_wndSplitter.IsRowHidden(1))\r
705                                 m_wndSplitter.HideRow(1);\r
706                         m_pwndLeftView->SetHidden(FALSE);\r
707                         m_pwndRightView->SetHidden(TRUE);\r
708                         m_pwndBottomView->SetHidden(TRUE);\r
709                         ::SetWindowPos(m_pwndLeftView->m_hWnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);\r
710                 }\r
711                 else\r
712                 {\r
713                         pwndActiveView = m_pwndRightView;\r
714                         if (m_wndSplitter2.IsColumnHidden(1))\r
715                                 m_wndSplitter2.ShowColumn();\r
716 \r
717                         m_pwndLeftView->m_pViewData = &m_Data.m_YourBaseLeft;\r
718                         m_pwndLeftView->texttype = m_Data.m_arBaseFile.GetUnicodeType();\r
719                         m_pwndLeftView->lineendings = m_Data.m_arBaseFile.GetLineEndings();\r
720                         m_pwndLeftView->m_sWindowName = m_Data.m_baseFile.GetWindowName();\r
721                         m_pwndLeftView->m_sFullFilePath = m_Data.m_baseFile.GetFilename();\r
722 \r
723                         m_pwndRightView->m_pViewData = &m_Data.m_YourBaseRight;\r
724                         m_pwndRightView->texttype = m_Data.m_arYourFile.GetUnicodeType();\r
725                         m_pwndRightView->lineendings = m_Data.m_arYourFile.GetLineEndings();\r
726                         m_pwndRightView->m_sWindowName = m_Data.m_yourFile.GetWindowName();\r
727                         m_pwndRightView->m_sFullFilePath = m_Data.m_yourFile.GetFilename();\r
728                 \r
729                         m_pwndBottomView->m_pViewData = NULL;\r
730 \r
731                 if (!m_wndSplitter.IsRowHidden(1))\r
732                                 m_wndSplitter.HideRow(1);\r
733                         m_pwndLeftView->SetHidden(FALSE);\r
734                         m_pwndRightView->SetHidden(FALSE);\r
735                         m_pwndBottomView->SetHidden(TRUE);\r
736                 }\r
737         }\r
738         else if (m_Data.IsBaseFileInUse() && m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())\r
739         {\r
740                 //diff between THEIR, YOUR and BASE\r
741                 m_pwndBottomView->UseCaret();\r
742                 pwndActiveView = m_pwndBottomView;\r
743 \r
744                 m_pwndLeftView->m_pViewData = &m_Data.m_TheirBaseBoth;\r
745                 m_pwndLeftView->texttype = m_Data.m_arTheirFile.GetUnicodeType();\r
746                 m_pwndLeftView->lineendings = m_Data.m_arTheirFile.GetLineEndings();\r
747                 m_pwndLeftView->m_sWindowName.LoadString(IDS_VIEWTITLE_THEIRS);\r
748                 m_pwndLeftView->m_sWindowName += _T(" - ") + m_Data.m_theirFile.GetWindowName();\r
749                 m_pwndLeftView->m_sFullFilePath = m_Data.m_theirFile.GetFilename();\r
750                 \r
751                 m_pwndRightView->m_pViewData = &m_Data.m_YourBaseBoth;\r
752                 m_pwndRightView->texttype = m_Data.m_arYourFile.GetUnicodeType();\r
753                 m_pwndRightView->lineendings = m_Data.m_arYourFile.GetLineEndings();\r
754                 m_pwndRightView->m_sWindowName.LoadString(IDS_VIEWTITLE_MINE);\r
755                 m_pwndRightView->m_sWindowName += _T(" - ") + m_Data.m_yourFile.GetWindowName();\r
756                 m_pwndRightView->m_sFullFilePath = m_Data.m_yourFile.GetFilename();\r
757                 \r
758                 m_pwndBottomView->m_pViewData = &m_Data.m_Diff3;\r
759                 m_pwndBottomView->texttype = m_Data.m_arTheirFile.GetUnicodeType();\r
760                 m_pwndBottomView->lineendings = m_Data.m_arTheirFile.GetLineEndings();\r
761                 m_pwndBottomView->m_sWindowName.LoadString(IDS_VIEWTITLE_MERGED);\r
762                 m_pwndBottomView->m_sWindowName += _T(" - ") + m_Data.m_mergedFile.GetWindowName();\r
763                 m_pwndBottomView->m_sFullFilePath = m_Data.m_mergedFile.GetFilename();\r
764                 \r
765                 if (m_wndSplitter2.IsColumnHidden(1))\r
766                         m_wndSplitter2.ShowColumn();\r
767                 if (m_wndSplitter.IsRowHidden(1))\r
768                         m_wndSplitter.ShowRow();\r
769                 m_pwndLeftView->SetHidden(FALSE);\r
770                 m_pwndRightView->SetHidden(FALSE);\r
771                 m_pwndBottomView->SetHidden(FALSE);\r
772                 // in three pane view, hide the line diff bar\r
773                 m_wndLineDiffBar.ShowPane(false, false, true);\r
774                 m_wndLineDiffBar.DocumentUpdated();\r
775         }\r
776         if (!m_Data.m_mergedFile.InUse())\r
777         {\r
778                 m_Data.m_mergedFile.SetFileName(m_Data.m_yourFile.GetFilename());\r
779         }\r
780         m_pwndLeftView->DocumentUpdated();\r
781         m_pwndRightView->DocumentUpdated();\r
782         m_pwndBottomView->DocumentUpdated();\r
783         m_wndLocatorBar.DocumentUpdated();\r
784         m_wndLineDiffBar.DocumentUpdated();\r
785         UpdateLayout();\r
786         SetActiveView(pwndActiveView);\r
787 \r
788         if (bRetainPosition && m_pwndLeftView->m_pViewData)\r
789         {\r
790                 int n = nOldLineNumber;\r
791                 if (n >= 0)\r
792                         n = m_pwndLeftView->m_pViewData->FindLineNumber(n);\r
793                 if (n < 0)\r
794                         n = nOldLine;\r
795 \r
796                 m_pwndLeftView->ScrollAllToLine(n);\r
797                 POINT p;\r
798                 p.x = 0;\r
799                 p.y = n;\r
800                 m_pwndLeftView->SetCaretPosition(p);\r
801         }\r
802         else\r
803         {\r
804                 bool bGoFirstDiff = (0 != (DWORD)CRegDWORD(_T("Software\\TortoiseMerge\\FirstDiffOnLoad"), TRUE));\r
805                 if (bGoFirstDiff) {\r
806                         pwndActiveView->GoToFirstDifference();\r
807                         // Ignore the first few Mouse Move messages, so that the line diff stays on\r
808                         // the first diff line until the user actually moves the mouse\r
809                         m_nMoveMovesToIgnore = 3; \r
810                 }\r
811 \r
812         }\r
813         // Avoid incorrect rendering of active pane.\r
814         m_pwndBottomView->ScrollToChar(0);\r
815         m_pwndLeftView->ScrollToChar(0);\r
816         m_pwndRightView->ScrollToChar(0);\r
817         CheckResolved();\r
818         CUndo::GetInstance().Clear();\r
819         return true;\r
820 }\r
821 \r
822 void CMainFrame::UpdateLayout()\r
823 {\r
824         if (m_bInitSplitter)\r
825         {\r
826                 CRect cr, rclocbar;\r
827                 GetWindowRect(&cr);\r
828                 int width = cr.Width();\r
829                 if (::IsWindow(m_wndLocatorBar) && m_wndLocatorBar.IsWindowVisible())\r
830                 {\r
831                         m_wndLocatorBar.GetWindowRect(&rclocbar);\r
832                         width -= rclocbar.Width();\r
833                 }\r
834                 m_wndSplitter.SetRowInfo(0, cr.Height()/2, 0);\r
835                 m_wndSplitter.SetRowInfo(1, cr.Height()/2, 0);\r
836                 m_wndSplitter.SetColumnInfo(0, width / 2, 50);\r
837                 m_wndSplitter2.SetRowInfo(0, cr.Height()/2, 0);\r
838                 m_wndSplitter2.SetColumnInfo(0, width / 2, 50);\r
839                 m_wndSplitter2.SetColumnInfo(1, width / 2, 50);\r
840 \r
841                 m_wndSplitter.RecalcLayout();\r
842         }\r
843 }\r
844 \r
845 void CMainFrame::OnSize(UINT nType, int cx, int cy)\r
846 {\r
847         if (m_bInitSplitter && nType != SIZE_MINIMIZED)\r
848         {\r
849                 UpdateLayout();\r
850         }\r
851         CFrameWndEx::OnSize(nType, cx, cy);\r
852 }\r
853 \r
854 void CMainFrame::OnViewWhitespaces()\r
855 {\r
856         CRegDWORD regViewWhitespaces = CRegDWORD(_T("Software\\TortoiseMerge\\ViewWhitespaces"), 1);\r
857         BOOL bViewWhitespaces = regViewWhitespaces;\r
858         if (m_pwndLeftView)\r
859                 bViewWhitespaces = m_pwndLeftView->m_bViewWhitespace;\r
860 \r
861         bViewWhitespaces = !bViewWhitespaces;\r
862         regViewWhitespaces = bViewWhitespaces;\r
863         if (m_pwndLeftView)\r
864         {\r
865                 m_pwndLeftView->m_bViewWhitespace = bViewWhitespaces;\r
866                 m_pwndLeftView->Invalidate();\r
867         }\r
868         if (m_pwndRightView)\r
869         {\r
870                 m_pwndRightView->m_bViewWhitespace = bViewWhitespaces;\r
871                 m_pwndRightView->Invalidate();\r
872         }\r
873         if (m_pwndBottomView)\r
874         {\r
875                 m_pwndBottomView->m_bViewWhitespace = bViewWhitespaces;\r
876                 m_pwndBottomView->Invalidate();\r
877         }\r
878 }\r
879 \r
880 void CMainFrame::OnUpdateViewWhitespaces(CCmdUI *pCmdUI)\r
881 {\r
882         if (m_pwndLeftView)\r
883                 pCmdUI->SetCheck(m_pwndLeftView->m_bViewWhitespace);\r
884 }\r
885 \r
886 void CMainFrame::OnViewOnewaydiff()\r
887 {\r
888         if (CheckForSave()==IDCANCEL)\r
889                 return;\r
890         m_bOneWay = !m_bOneWay;\r
891         if (m_bOneWay)\r
892         {\r
893                 // in one way view, hide the line diff bar\r
894                 m_wndLineDiffBar.ShowPane(false, false, true);\r
895                 m_wndLineDiffBar.DocumentUpdated();\r
896         }\r
897         else\r
898         {\r
899                 // restore the line diff bar\r
900                 m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);\r
901                 m_wndLineDiffBar.DocumentUpdated();\r
902                 m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);\r
903                 m_wndLocatorBar.DocumentUpdated();\r
904         }\r
905         LoadViews(true);\r
906 }\r
907 \r
908 void CMainFrame::ShowDiffBar(bool bShow)\r
909 {\r
910         if (bShow)\r
911         {\r
912                 // restore the line diff bar\r
913                 m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);\r
914                 m_wndLineDiffBar.DocumentUpdated();\r
915                 m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);\r
916                 m_wndLocatorBar.DocumentUpdated();\r
917         }\r
918         else\r
919         {\r
920                 // in one way view, hide the line diff bar\r
921                 m_wndLineDiffBar.ShowPane(false, false, true);\r
922                 m_wndLineDiffBar.DocumentUpdated();\r
923         }\r
924 }\r
925 \r
926 int CMainFrame::CheckResolved()\r
927 {\r
928         //only in three way diffs can be conflicts!\r
929         m_bHasConflicts = true;\r
930         if (m_pwndBottomView->IsWindowVisible())\r
931         {\r
932                 if (m_pwndBottomView->m_pViewData)\r
933                 {\r
934                         for (int i=0; i<m_pwndBottomView->m_pViewData->GetCount(); i++)\r
935                         {\r
936                                 if ((DIFFSTATE_CONFLICTED == m_pwndBottomView->m_pViewData->GetState(i))||\r
937                                         (DIFFSTATE_CONFLICTED_IGNORED == m_pwndBottomView->m_pViewData->GetState(i)))\r
938                                         return i;\r
939                         }\r
940                 }\r
941         }\r
942         m_bHasConflicts = false;\r
943         return -1;\r
944 }\r
945 \r
946 int CMainFrame::SaveFile(const CString& sFilePath)\r
947 {\r
948         CViewData * pViewData = NULL;\r
949         CFileTextLines * pOriginFile = &m_Data.m_arBaseFile;\r
950         if ((m_pwndBottomView)&&(m_pwndBottomView->IsWindowVisible()))\r
951         {\r
952                 pViewData = m_pwndBottomView->m_pViewData;\r
953                 Invalidate();\r
954         }\r
955         else if ((m_pwndRightView)&&(m_pwndRightView->IsWindowVisible()))\r
956         {\r
957                 pViewData = m_pwndRightView->m_pViewData;\r
958                 if (m_Data.IsYourFileInUse())\r
959                         pOriginFile = &m_Data.m_arYourFile;\r
960                 else if (m_Data.IsTheirFileInUse())\r
961                         pOriginFile = &m_Data.m_arTheirFile;\r
962                 Invalidate();\r
963         } \r
964         else\r
965         {\r
966                 // nothing to save!\r
967                 return -1;\r
968         }\r
969         if ((pViewData)&&(pOriginFile))\r
970         {\r
971                 CFileTextLines file;\r
972                 pOriginFile->CopySettings(&file);\r
973                 for (int i=0; i<pViewData->GetCount(); i++)\r
974                 {\r
975                         //only copy non-removed lines\r
976                         DiffStates state = pViewData->GetState(i);\r
977                         switch (state)\r
978                         {\r
979                         case DIFFSTATE_CONFLICTED:\r
980                         case DIFFSTATE_CONFLICTED_IGNORED:\r
981                                 {\r
982                                         int first = i;\r
983                                         int last = i;\r
984                                         do \r
985                                         {\r
986                                                 last++;\r
987                                         } while((last<pViewData->GetCount()) && ((pViewData->GetState(last)==DIFFSTATE_CONFLICTED)||(pViewData->GetState(last)==DIFFSTATE_CONFLICTED_IGNORED)));\r
988                                         file.Add(_T("<<<<<<< .mine"), EOL_NOENDING);\r
989                                         for (int j=first; j<last; j++)\r
990                                         {\r
991                                                 file.Add(m_pwndRightView->m_pViewData->GetLine(j), m_pwndRightView->m_pViewData->GetLineEnding(j));\r
992                                         }\r
993                                         file.Add(_T("======="), EOL_NOENDING);\r
994                                         for (int j=first; j<last; j++)\r
995                                         {\r
996                                                 file.Add(m_pwndLeftView->m_pViewData->GetLine(j), m_pwndLeftView->m_pViewData->GetLineEnding(j));\r
997                                         }\r
998                                         file.Add(_T(">>>>>>> .theirs"), EOL_NOENDING);\r
999                                         i = last-1;\r
1000                                 }\r
1001                                 break;\r
1002                         case DIFFSTATE_EMPTY:\r
1003                         case DIFFSTATE_CONFLICTEMPTY:\r
1004                         case DIFFSTATE_IDENTICALREMOVED:\r
1005                         case DIFFSTATE_REMOVED:\r
1006                         case DIFFSTATE_THEIRSREMOVED:\r
1007                         case DIFFSTATE_YOURSREMOVED:\r
1008                         case DIFFSTATE_CONFLICTRESOLVEDEMPTY:\r
1009                                 // do not save removed lines\r
1010                                 break;\r
1011                         default:\r
1012                                 file.Add(pViewData->GetLine(i), pViewData->GetLineEnding(i));\r
1013                                 break;\r
1014                         }\r
1015                 }\r
1016                 if (!file.Save(sFilePath, false))\r
1017                 {\r
1018                         CMessageBox::Show(m_hWnd, file.GetErrorString(), _T("TortoiseMerge"), MB_ICONERROR);\r
1019                         return -1;\r
1020                 }\r
1021                 m_dlgFilePatches.SetFileStatusAsPatched(sFilePath);\r
1022                 if (m_pwndBottomView)\r
1023                         m_pwndBottomView->SetModified(FALSE);\r
1024                 if (m_pwndRightView)\r
1025                         m_pwndRightView->SetModified(FALSE);\r
1026                 CUndo::GetInstance().MarkAsOriginalState();\r
1027                 return file.GetCount();\r
1028         }\r
1029         return -1;\r
1030 }\r
1031 \r
1032 void CMainFrame::OnFileSave()\r
1033 {\r
1034         FileSave();\r
1035 }\r
1036 \r
1037 bool CMainFrame::FileSave(bool bCheckResolved /*=true*/)\r
1038 {\r
1039         if (!m_Data.m_mergedFile.InUse())\r
1040                 return FileSaveAs(bCheckResolved);\r
1041         // check if the file has the readonly attribute set\r
1042         bool bDoesNotExist = false;\r
1043         DWORD fAttribs = GetFileAttributes(m_Data.m_mergedFile.GetFilename());\r
1044         if ((fAttribs != INVALID_FILE_ATTRIBUTES)&&(fAttribs & FILE_ATTRIBUTE_READONLY))\r
1045                 return FileSaveAs(bCheckResolved);\r
1046         if (fAttribs == INVALID_FILE_ATTRIBUTES)\r
1047         {\r
1048                 bDoesNotExist = (GetLastError() == ERROR_FILE_NOT_FOUND);\r
1049         }\r
1050         if (bCheckResolved)\r
1051         {\r
1052                 int nConflictLine = CheckResolved();\r
1053                 if (nConflictLine >= 0)\r
1054                 {\r
1055                         CString sTemp;\r
1056                         sTemp.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS, m_pwndBottomView->m_pViewData->GetLineNumber(nConflictLine)+1);\r
1057                         if (MessageBox(sTemp, 0, MB_ICONERROR | MB_YESNO)!=IDYES)\r
1058                         {\r
1059                                 if (m_pwndBottomView)\r
1060                                         m_pwndBottomView->GoToLine(nConflictLine);\r
1061                                 return false;\r
1062                         }\r
1063                 }\r
1064         }\r
1065         if (((DWORD)CRegDWORD(_T("Software\\TortoiseMerge\\Backup"))) != 0)\r
1066         {\r
1067                 MoveFileEx(m_Data.m_mergedFile.GetFilename(), m_Data.m_mergedFile.GetFilename() + _T(".bak"), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);\r
1068         }\r
1069         if (SaveFile(m_Data.m_mergedFile.GetFilename())==0)\r
1070         {\r
1071                 // file was saved with 0 lines!\r
1072                 // ask the user if the file should be deleted\r
1073                 CString sTemp;\r
1074                 sTemp.Format(IDS_DELETEWHENEMPTY, (LPCTSTR)m_Data.m_mergedFile.GetFilename());\r
1075                 if (CMessageBox::ShowCheck(m_hWnd, sTemp, _T("TortoiseMerge"), MB_YESNO, _T("DeleteFileWhenEmpty")) == IDYES)\r
1076                 {\r
1077                         DeleteFile(m_Data.m_mergedFile.GetFilename());\r
1078                 }\r
1079         }\r
1080         \r
1081         if (bDoesNotExist)\r
1082         {\r
1083                 // call TortoiseProc to add the new file to version control\r
1084                 CString cmd = _T("\"") + CPathUtils::GetAppDirectory();\r
1085                 cmd += _T("TortoiseProc.exe\" /command:add /noui /path:\"");\r
1086                 cmd += m_Data.m_mergedFile.GetFilename() + _T("\"");\r
1087                 TCHAR * buf = new TCHAR[cmd.GetLength()+1];\r
1088                 _tcscpy_s(buf, cmd.GetLength()+1, cmd);\r
1089                 STARTUPINFO startup;\r
1090                 PROCESS_INFORMATION process;\r
1091                 memset(&startup, 0, sizeof(startup));\r
1092                 startup.cb = sizeof(startup);\r
1093                 memset(&process, 0, sizeof(process));\r
1094                 if (CreateProcess(NULL, buf, NULL, NULL, FALSE, 0, 0, 0, &startup, &process)==0)\r
1095                 {\r
1096                         delete [] buf;\r
1097                         LPVOID lpMsgBuf;\r
1098                         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | \r
1099                                 FORMAT_MESSAGE_FROM_SYSTEM | \r
1100                                 FORMAT_MESSAGE_IGNORE_INSERTS,\r
1101                                 NULL,\r
1102                                 GetLastError(),\r
1103                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language\r
1104                                 (LPTSTR) &lpMsgBuf,\r
1105                                 0,\r
1106                                 NULL \r
1107                                 );\r
1108                         MessageBox((LPCTSTR)lpMsgBuf, _T("TortoiseMerge"), MB_OK | MB_ICONINFORMATION);\r
1109                         LocalFree( lpMsgBuf );\r
1110                         return FALSE;\r
1111                 }\r
1112                 delete [] buf;\r
1113                 CloseHandle(process.hThread);\r
1114                 CloseHandle(process.hProcess);\r
1115         }\r
1116         return true;\r
1117 }\r
1118 \r
1119 void CMainFrame::OnFileSaveAs()\r
1120 {\r
1121         FileSaveAs();\r
1122 }\r
1123 \r
1124 bool CMainFrame::FileSaveAs(bool bCheckResolved /*=true*/)\r
1125 {\r
1126         if (bCheckResolved)\r
1127         {\r
1128                 int nConflictLine = CheckResolved();\r
1129                 if (nConflictLine >= 0)\r
1130                 {\r
1131                         CString sTemp;\r
1132                         sTemp.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS, m_pwndBottomView->m_pViewData->GetLineNumber(nConflictLine)+1);\r
1133                         if (MessageBox(sTemp, 0, MB_ICONERROR | MB_YESNO)!=IDYES)\r
1134                         {\r
1135                                 if (m_pwndBottomView)\r
1136                                         m_pwndBottomView->GoToLine(nConflictLine);\r
1137                                 return false;\r
1138                         }\r
1139                 }\r
1140         }\r
1141         OPENFILENAME ofn = {0};                 // common dialog box structure\r
1142         TCHAR szFile[MAX_PATH] = {0};   // buffer for file name\r
1143         ofn.lStructSize = sizeof(OPENFILENAME);\r
1144         ofn.hwndOwner = m_hWnd;\r
1145         ofn.lpstrFile = szFile;\r
1146         ofn.nMaxFile = sizeof(szFile)/sizeof(TCHAR);\r
1147         CString temp;\r
1148         temp.LoadString(IDS_SAVEASTITLE);\r
1149         if (!temp.IsEmpty())\r
1150                 ofn.lpstrTitle = temp;\r
1151         ofn.Flags = OFN_OVERWRITEPROMPT;\r
1152         CString sFilter;\r
1153         sFilter.LoadString(IDS_COMMONFILEFILTER);\r
1154         TCHAR * pszFilters = new TCHAR[sFilter.GetLength()+4];\r
1155         _tcscpy_s (pszFilters, sFilter.GetLength()+4, sFilter);\r
1156         // Replace '|' delimiters with '\0's\r
1157         TCHAR *ptr = pszFilters + _tcslen(pszFilters);  //set ptr at the NULL\r
1158         while (ptr != pszFilters)\r
1159         {\r
1160                 if (*ptr == '|')\r
1161                         *ptr = '\0';\r
1162                 ptr--;\r
1163         }\r
1164         ofn.lpstrFilter = pszFilters;\r
1165         ofn.nFilterIndex = 1;\r
1166 \r
1167         // Display the Open dialog box. \r
1168         CString sFile;\r
1169         if (GetSaveFileName(&ofn)==TRUE)\r
1170         {\r
1171                 sFile = CString(ofn.lpstrFile);\r
1172                 SaveFile(sFile);\r
1173                 delete [] pszFilters;\r
1174                 return true;\r
1175         }\r
1176         delete [] pszFilters;\r
1177         return false;\r
1178 }\r
1179 \r
1180 void CMainFrame::OnUpdateFileSave(CCmdUI *pCmdUI)\r
1181 {\r
1182         BOOL bEnable = FALSE;\r
1183         if (m_Data.m_mergedFile.InUse())\r
1184         {\r
1185                 if (m_pwndBottomView)\r
1186                 {\r
1187                         if ((m_pwndBottomView->IsWindowVisible())&&(m_pwndBottomView->m_pViewData))\r
1188                         {\r
1189                                 bEnable = TRUE;\r
1190                         } \r
1191                 }\r
1192                 if (m_pwndRightView)\r
1193                 {\r
1194                         if ((m_pwndRightView->IsWindowVisible())&&(m_pwndRightView->m_pViewData))\r
1195                         {\r
1196                                 if (m_pwndRightView->IsModified() || (m_Data.m_yourFile.GetWindowName().Right(9).Compare(_T(": patched"))==0))\r
1197                                         bEnable = TRUE;\r
1198                         } \r
1199                 }\r
1200         }\r
1201         pCmdUI->Enable(bEnable);\r
1202 }\r
1203 \r
1204 void CMainFrame::OnUpdateFileSaveAs(CCmdUI *pCmdUI)\r
1205 {\r
1206         BOOL bEnable = FALSE;\r
1207         if (m_pwndBottomView)\r
1208         {\r
1209                 if ((m_pwndBottomView->IsWindowVisible())&&(m_pwndBottomView->m_pViewData))\r
1210                 {\r
1211                         bEnable = TRUE;\r
1212                 }\r
1213         }\r
1214         if (m_pwndRightView)\r
1215         {\r
1216                 if ((m_pwndRightView->IsWindowVisible())&&(m_pwndRightView->m_pViewData))\r
1217                 {\r
1218                         bEnable = TRUE;\r
1219                 }\r
1220         } \r
1221         pCmdUI->Enable(bEnable);\r
1222 }\r
1223 \r
1224 \r
1225 void CMainFrame::OnUpdateViewOnewaydiff(CCmdUI *pCmdUI)\r
1226 {\r
1227         pCmdUI->SetCheck(!m_bOneWay);\r
1228         BOOL bEnable = TRUE;\r
1229         if (m_pwndBottomView)\r
1230         {\r
1231                 if (m_pwndBottomView->IsWindowVisible())\r
1232                         bEnable = FALSE;\r
1233         }\r
1234         pCmdUI->Enable(bEnable);\r
1235 }\r
1236 \r
1237 void CMainFrame::OnViewOptions()\r
1238 {\r
1239         CString sTemp;\r
1240         sTemp.LoadString(IDS_SETTINGSTITLE);\r
1241         CSettings dlg(sTemp);\r
1242         dlg.DoModal();\r
1243         if (dlg.IsReloadNeeded())\r
1244         {\r
1245                 if (CheckForSave()==IDCANCEL)\r
1246                         return;\r
1247                 CDiffColors::GetInstance().LoadRegistry();\r
1248                 LoadViews();\r
1249                 return;\r
1250         }\r
1251         CDiffColors::GetInstance().LoadRegistry();\r
1252         if (m_pwndBottomView)\r
1253                 m_pwndBottomView->Invalidate();\r
1254         if (m_pwndLeftView)\r
1255                 m_pwndLeftView->Invalidate();\r
1256         if (m_pwndRightView)\r
1257                 m_pwndRightView->Invalidate();\r
1258 }\r
1259 \r
1260 void CMainFrame::OnClose()\r
1261 {\r
1262         if ((m_pFindDialog)&&(!m_pFindDialog->IsTerminating()))\r
1263         {\r
1264                 m_pFindDialog->SendMessage(WM_CLOSE);\r
1265                 return;\r
1266         }\r
1267         int ret = IDNO;\r
1268         if (((m_pwndBottomView)&&(m_pwndBottomView->IsModified())) ||\r
1269                 ((m_pwndRightView)&&(m_pwndRightView->IsModified())))\r
1270         {\r
1271                 CString sTemp;\r
1272                 sTemp.LoadString(IDS_ASKFORSAVE);\r
1273                 ret = MessageBox(sTemp, 0, MB_YESNOCANCEL | MB_ICONQUESTION);\r
1274                 if (ret == IDYES)\r
1275                 {\r
1276                         if (!FileSave())\r
1277                                 return;\r
1278                 }\r
1279         }\r
1280         if ((ret == IDNO)||(ret == IDYES))\r
1281         {\r
1282                 WINDOWPLACEMENT    wp;\r
1283 \r
1284                 // before it is destroyed, save the position of the window\r
1285                 wp.length = sizeof wp;\r
1286 \r
1287                 if (GetWindowPlacement(&wp))\r
1288                 {\r
1289 \r
1290                         if (IsIconic())\r
1291                                 // never restore to Iconic state\r
1292                                 wp.showCmd = SW_SHOW ;\r
1293 \r
1294                         if ((wp.flags & WPF_RESTORETOMAXIMIZED) != 0)\r
1295                                 // if maximized and maybe iconic restore maximized state\r
1296                                 wp.showCmd = SW_SHOWMAXIMIZED ;\r
1297 \r
1298                         // and write it to the .INI file\r
1299                         WriteWindowPlacement(&wp);\r
1300                 }\r
1301                 __super::OnClose();\r
1302         }\r
1303 }\r
1304 \r
1305 void CMainFrame::OnEditFind()\r
1306 {\r
1307         if (m_pFindDialog)\r
1308         {\r
1309                 return;\r
1310         }\r
1311         else\r
1312         {\r
1313                 // start searching from the start again\r
1314                 // if no line is selected, otherwise start from\r
1315                 // the selected line\r
1316                 m_nSearchIndex = FindSearchStart(0);\r
1317                 m_pFindDialog = new CFindDlg();\r
1318                 m_pFindDialog->Create(this);\r
1319         }\r
1320 }\r
1321 \r
1322 LRESULT CMainFrame::OnFindDialogMessage(WPARAM /*wParam*/, LPARAM /*lParam*/)\r
1323 {\r
1324     ASSERT(m_pFindDialog != NULL);\r
1325 \r
1326     if (m_pFindDialog->IsTerminating())\r
1327     {\r
1328             // invalidate the handle identifying the dialog box.\r
1329         m_pFindDialog = NULL;\r
1330         return 0;\r
1331     }\r
1332 \r
1333     if(m_pFindDialog->FindNext())\r
1334     {\r
1335         //read data from dialog\r
1336         m_sFindText = m_pFindDialog->GetFindString();\r
1337         m_bMatchCase = (m_pFindDialog->MatchCase() == TRUE);\r
1338                 m_bLimitToDiff = m_pFindDialog->LimitToDiffs();\r
1339                 m_bWholeWord = m_pFindDialog->WholeWord();\r
1340         \r
1341                 OnEditFindnext();\r
1342     }\r
1343 \r
1344     return 0;\r
1345 }\r
1346 \r
1347 bool CharIsDelimiter(const CString& ch)\r
1348 {\r
1349         CString delimiters(_T(" .,:;=+-*/\\\n\t()[]<>@"));\r
1350         return delimiters.Find(ch) >= 0;\r
1351 }\r
1352 \r
1353 bool CMainFrame::StringFound(const CString& str)const\r
1354 {\r
1355         int nSubStringStartIdx = str.Find(m_sFindText);\r
1356         bool bStringFound = (nSubStringStartIdx >= 0);\r
1357         if (bStringFound && m_bWholeWord)\r
1358         {\r
1359                 if (nSubStringStartIdx)\r
1360                         bStringFound = CharIsDelimiter(str.Mid(nSubStringStartIdx-1,1));\r
1361                 \r
1362                 if (bStringFound)\r
1363                 {\r
1364                         int nEndIndex = nSubStringStartIdx + m_sFindText.GetLength();\r
1365                         if (str.GetLength() > nEndIndex)\r
1366                                 bStringFound = CharIsDelimiter(str.Mid(nEndIndex, 1));\r
1367                 }\r
1368         }\r
1369         return bStringFound;\r
1370 }\r
1371 \r
1372 void CMainFrame::OnEditFindprev()\r
1373 {\r
1374         Search(SearchPrevious);\r
1375 }\r
1376 \r
1377 void CMainFrame::OnEditFindnext()\r
1378 {\r
1379         Search(SearchNext);\r
1380 }\r
1381 \r
1382 void CMainFrame::Search(SearchDirection srchDir)\r
1383 {\r
1384         if (m_sFindText.IsEmpty())\r
1385                 return;\r
1386 \r
1387         if ((m_pwndLeftView)&&(m_pwndLeftView->m_pViewData))\r
1388         {\r
1389                 bool bFound = FALSE;\r
1390 \r
1391                 CString left;\r
1392                 CString right;\r
1393                 CString bottom;\r
1394                 DiffStates leftstate = DIFFSTATE_NORMAL;\r
1395                 DiffStates rightstate = DIFFSTATE_NORMAL;\r
1396                 DiffStates bottomstate = DIFFSTATE_NORMAL;\r
1397                 int i = 0;\r
1398                 \r
1399                 m_nSearchIndex = FindSearchStart(m_nSearchIndex);\r
1400                 m_nSearchIndex++;\r
1401                 if (m_nSearchIndex >= m_pwndLeftView->m_pViewData->GetCount())\r
1402                         m_nSearchIndex = 0;\r
1403                 if (srchDir == SearchPrevious)\r
1404                 {\r
1405                         // SearchIndex points 1 past where we found the last match, \r
1406                         // so if we are searching backwards we need to adjust accordingly\r
1407                         m_nSearchIndex -= 2;\r
1408                         // if at the top, start again from the end\r
1409                         if (m_nSearchIndex < 0)\r
1410                                 m_nSearchIndex += m_pwndLeftView->m_pViewData->GetCount();\r
1411                 }\r
1412                 const int idxLimits[2][2][2]={{{m_nSearchIndex, m_pwndLeftView->m_pViewData->GetCount()},\r
1413                                                                            {0, m_nSearchIndex}},\r
1414                                                                           {{m_nSearchIndex, -1},\r
1415                                                                            {m_pwndLeftView->m_pViewData->GetCount()-1, m_nSearchIndex}}};\r
1416                 const int offsets[2]={+1, -1};\r
1417                 \r
1418                 for (int j=0; j != 2 && !bFound; ++j)\r
1419                 {\r
1420                         for (i=idxLimits[srchDir][j][0]; i != idxLimits[srchDir][j][1]; i += offsets[srchDir])\r
1421                         {\r
1422                                 left = m_pwndLeftView->m_pViewData->GetLine(i);\r
1423                                 leftstate = m_pwndLeftView->m_pViewData->GetState(i);\r
1424                                 if ((!m_bOneWay)&&(m_pwndRightView->m_pViewData))\r
1425                                 {\r
1426                                         right = m_pwndRightView->m_pViewData->GetLine(i);\r
1427                                         rightstate = m_pwndRightView->m_pViewData->GetState(i);\r
1428                                 }\r
1429                                 if ((m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))\r
1430                                 {\r
1431                                         bottom = m_pwndBottomView->m_pViewData->GetLine(i);\r
1432                                         bottomstate = m_pwndBottomView->m_pViewData->GetState(i);\r
1433                                 }\r
1434 \r
1435                                 if (!m_bMatchCase)\r
1436                                 {\r
1437                                         left = left.MakeLower();\r
1438                                         right = right.MakeLower();\r
1439                                         bottom = bottom.MakeLower();\r
1440                                         m_sFindText = m_sFindText.MakeLower();\r
1441                                 }\r
1442                                 if (StringFound(left))\r
1443                                 {\r
1444                                         if ((!m_bLimitToDiff)||(leftstate != DIFFSTATE_NORMAL))\r
1445                                         {\r
1446                                                 bFound = TRUE;\r
1447                                                 break;\r
1448                                         }\r
1449                                 } \r
1450                                 else if (StringFound(right))\r
1451                                 {\r
1452                                         if ((!m_bLimitToDiff)||(rightstate != DIFFSTATE_NORMAL))\r
1453                                         {\r
1454                                                 bFound = TRUE;\r
1455                                                 break;\r
1456                                         }\r
1457                                 } \r
1458                                 else if (StringFound(bottom))\r
1459                                 {\r
1460                                         if ((!m_bLimitToDiff)||(bottomstate != DIFFSTATE_NORMAL))\r
1461                                         {\r
1462                                                 bFound = TRUE;\r
1463                                                 break;\r
1464                                         }\r
1465                                 } \r
1466                         }\r
1467                 }\r
1468                 if (bFound)\r
1469                 {\r
1470                         m_nSearchIndex = i;\r
1471                         m_pwndLeftView->GoToLine(m_nSearchIndex);\r
1472                         if (StringFound(left))\r
1473                         {\r
1474                                 m_pwndLeftView->SetFocus();\r
1475                                 m_pwndLeftView->HiglightLines(m_nSearchIndex);\r
1476                         }\r
1477                         else if (StringFound(right))\r
1478                         {\r
1479                                 m_pwndRightView->SetFocus();\r
1480                                 m_pwndRightView->HiglightLines(m_nSearchIndex);\r
1481                         }\r
1482                         else if (StringFound(bottom))\r
1483                         {\r
1484                                 m_pwndBottomView->SetFocus();\r
1485                                 m_pwndBottomView->HiglightLines(m_nSearchIndex);\r
1486                         }\r
1487                 }\r
1488                 else\r
1489                 {\r
1490                         m_nSearchIndex = 0;\r
1491                 }\r
1492         }\r
1493 }\r
1494 \r
1495 int CMainFrame::FindSearchStart(int nDefault)\r
1496 {\r
1497         // TortoiseMerge doesn't have a cursor which we could use to\r
1498         // anchor the search on.\r
1499         // Instead we use a line that is selected.\r
1500         // If however no line is selected, use the default line (which could\r
1501         // be the top of the document for a new search, or the line where the\r
1502         // search was successful on)\r
1503         int nLine = nDefault;\r
1504         int nSelStart = 0;\r
1505         int nSelEnd = 0;\r
1506         if (m_pwndLeftView)\r
1507         {\r
1508                 if (m_pwndLeftView->GetSelection(nSelStart, nSelEnd))\r
1509                 {\r
1510                         if (nSelStart == nSelEnd)\r
1511                                 nLine = nSelStart;\r
1512                 }\r
1513         }\r
1514         else if ((nLine == nDefault)&&(m_pwndRightView))\r
1515         {\r
1516                 if (m_pwndRightView->GetSelection(nSelStart, nSelEnd))\r
1517                 {\r
1518                         if (nSelStart == nSelEnd)\r
1519                                 nLine = nSelStart;\r
1520                 }\r
1521         }\r
1522         else if ((nLine == nDefault)&&(m_pwndBottomView))\r
1523         {\r
1524                 if (m_pwndBottomView->GetSelection(nSelStart, nSelEnd))\r
1525                 {\r
1526                         if (nSelStart == nSelEnd)\r
1527                                 nLine = nSelStart;\r
1528                 }\r
1529         }\r
1530         return nLine;\r
1531 }\r
1532 \r
1533 void CMainFrame::OnViewLinedown()\r
1534 {\r
1535         if (m_pwndLeftView)\r
1536                 m_pwndLeftView->ScrollToLine(m_pwndLeftView->m_nTopLine+1);\r
1537         if (m_pwndRightView)\r
1538                 m_pwndRightView->ScrollToLine(m_pwndRightView->m_nTopLine+1);\r
1539         if (m_pwndBottomView)\r
1540                 m_pwndBottomView->ScrollToLine(m_pwndBottomView->m_nTopLine+1);\r
1541         m_wndLocatorBar.Invalidate();\r
1542 }\r
1543 \r
1544 void CMainFrame::OnViewLineup()\r
1545 {\r
1546         if (m_pwndLeftView)\r
1547                 m_pwndLeftView->ScrollToLine(m_pwndLeftView->m_nTopLine-1);\r
1548         if (m_pwndRightView)\r
1549                 m_pwndRightView->ScrollToLine(m_pwndRightView->m_nTopLine-1);\r
1550         if (m_pwndBottomView)\r
1551                 m_pwndBottomView->ScrollToLine(m_pwndBottomView->m_nTopLine-1);\r
1552         m_wndLocatorBar.Invalidate();\r
1553 }\r
1554 \r
1555 void CMainFrame::OnViewLineleft()\r
1556 {\r
1557         if (m_pwndLeftView)\r
1558                 m_pwndLeftView->ScrollSide(-1);\r
1559         if (m_pwndRightView)\r
1560                 m_pwndRightView->ScrollSide(-1);\r
1561         if (m_pwndBottomView)\r
1562                 m_pwndBottomView->ScrollSide(-1);\r
1563 }\r
1564 \r
1565 void CMainFrame::OnViewLineright()\r
1566 {\r
1567         if (m_pwndLeftView)\r
1568                 m_pwndLeftView->ScrollSide(1);\r
1569         if (m_pwndRightView)\r
1570                 m_pwndRightView->ScrollSide(1);\r
1571         if (m_pwndBottomView)\r
1572                 m_pwndBottomView->ScrollSide(1);\r
1573 }\r
1574 \r
1575 void CMainFrame::OnEditUseTheirs()\r
1576 {\r
1577         if (m_pwndBottomView)\r
1578                 m_pwndBottomView->UseTheirTextBlock();\r
1579 }\r
1580 void CMainFrame::OnUpdateEditUsetheirblock(CCmdUI *pCmdUI)\r
1581 {\r
1582         int nSelBlockStart = -1;\r
1583         int nSelBlockEnd = -1;\r
1584         if (m_pwndBottomView)\r
1585                 m_pwndBottomView->GetSelection(nSelBlockStart, nSelBlockEnd);\r
1586         pCmdUI->Enable((nSelBlockStart >= 0)&&(nSelBlockEnd >= 0));\r
1587 }\r
1588 \r
1589 \r
1590 void CMainFrame::OnEditUseMine()\r
1591 {\r
1592         if (m_pwndBottomView)\r
1593                 m_pwndBottomView->UseMyTextBlock();\r
1594 }\r
1595 void CMainFrame::OnUpdateEditUsemyblock(CCmdUI *pCmdUI)\r
1596 {\r
1597         int nSelBlockStart = -1;\r
1598         int nSelBlockEnd = -1;\r
1599         if (m_pwndBottomView)\r
1600                 m_pwndBottomView->GetSelection(nSelBlockStart, nSelBlockEnd);\r
1601         pCmdUI->Enable((nSelBlockStart >= 0)&&(nSelBlockEnd >= 0));\r
1602 }\r
1603 \r
1604 \r
1605 void CMainFrame::OnEditUseTheirsThenMine()\r
1606 {\r
1607         if (m_pwndBottomView)\r
1608                 m_pwndBottomView->UseTheirThenMyTextBlock();\r
1609 }\r
1610 void CMainFrame::OnUpdateEditUsetheirthenmyblock(CCmdUI *pCmdUI)\r
1611 {\r
1612         int nSelBlockStart = -1;\r
1613         int nSelBlockEnd = -1;\r
1614         if (m_pwndBottomView)\r
1615                 m_pwndBottomView->GetSelection(nSelBlockStart, nSelBlockEnd);\r
1616         pCmdUI->Enable((nSelBlockStart >= 0)&&(nSelBlockEnd >= 0));\r
1617 }\r
1618 \r
1619 \r
1620 void CMainFrame::OnEditUseMineThenTheirs()\r
1621 {\r
1622         if (m_pwndBottomView)\r
1623                 m_pwndBottomView->UseMyThenTheirTextBlock();\r
1624 }\r
1625 void CMainFrame::OnUpdateEditUseminethentheirblock(CCmdUI *pCmdUI)\r
1626 {\r
1627         int nSelBlockStart = -1;\r
1628         int nSelBlockEnd = -1;\r
1629         if (m_pwndBottomView)\r
1630                 m_pwndBottomView->GetSelection(nSelBlockStart, nSelBlockEnd);\r
1631         pCmdUI->Enable((nSelBlockStart >= 0)&&(nSelBlockEnd >= 0));\r
1632 }\r
1633 \r
1634 void CMainFrame::OnEditUseleftblock()\r
1635 {\r
1636         if (m_pwndRightView)\r
1637                 m_pwndRightView->UseBlock();\r
1638 }\r
1639 \r
1640 void CMainFrame::OnUpdateEditUseleftblock(CCmdUI *pCmdUI)\r
1641 {\r
1642         pCmdUI->Enable(m_pwndRightView && m_pwndRightView->IsWindowVisible() && m_pwndRightView->HasCaret() && m_pwndRightView->HasSelection());\r
1643 }\r
1644 \r
1645 void CMainFrame::OnEditUseleftfile()\r
1646 {\r
1647         if (m_pwndRightView)\r
1648                 m_pwndRightView->UseFile();\r
1649 }\r
1650 \r
1651 void CMainFrame::OnUpdateEditUseleftfile(CCmdUI *pCmdUI)\r
1652 {\r
1653         pCmdUI->Enable(m_pwndRightView && m_pwndRightView->IsWindowVisible() && m_pwndRightView->HasCaret());\r
1654 }\r
1655 \r
1656 void CMainFrame::OnEditUseblockfromleftbeforeright()\r
1657 {\r
1658         if (m_pwndRightView)\r
1659                 m_pwndRightView->UseLeftBeforeRight();\r
1660 }\r
1661 \r
1662 void CMainFrame::OnUpdateEditUseblockfromleftbeforeright(CCmdUI *pCmdUI)\r
1663 {\r
1664         pCmdUI->Enable(m_pwndRightView && m_pwndRightView->IsWindowVisible() && m_pwndRightView->HasCaret() && m_pwndRightView->HasSelection());\r
1665 }\r
1666 \r
1667 void CMainFrame::OnEditUseblockfromrightbeforeleft()\r
1668 {\r
1669         if (m_pwndRightView)\r
1670                 m_pwndRightView->UseRightBeforeLeft();\r
1671 }\r
1672 \r
1673 void CMainFrame::OnUpdateEditUseblockfromrightbeforeleft(CCmdUI *pCmdUI)\r
1674 {\r
1675         pCmdUI->Enable(m_pwndRightView && m_pwndRightView->IsWindowVisible() && m_pwndRightView->HasCaret() && m_pwndRightView->HasSelection());\r
1676 }\r
1677 \r
1678 \r
1679 void CMainFrame::OnFileReload()\r
1680 {\r
1681         if (CheckForSave()==IDCANCEL)\r
1682                 return;\r
1683         CDiffColors::GetInstance().LoadRegistry();\r
1684         LoadViews(true);\r
1685 }\r
1686 \r
1687 void CMainFrame::ActivateFrame(int nCmdShow)\r
1688 {\r
1689         // nCmdShow is the normal show mode this frame should be in\r
1690         // translate default nCmdShow (-1)\r
1691         if (nCmdShow == -1)\r
1692         {\r
1693                 if (!IsWindowVisible())\r
1694                         nCmdShow = SW_SHOWNORMAL;\r
1695                 else if (IsIconic())\r
1696                         nCmdShow = SW_RESTORE;\r
1697         }\r
1698 \r
1699         // bring to top before showing\r
1700         BringToTop(nCmdShow);\r
1701 \r
1702         if (nCmdShow != -1)\r
1703         {\r
1704                 // show the window as specified\r
1705                 WINDOWPLACEMENT wp;\r
1706 \r
1707                 if ( !ReadWindowPlacement(&wp) )\r
1708                 {\r
1709                         ShowWindow(nCmdShow);\r
1710                 }\r
1711                 else\r
1712                 {\r
1713                         if ( nCmdShow != SW_SHOWNORMAL )  \r
1714                                 wp.showCmd = nCmdShow;\r
1715 \r
1716                         SetWindowPlacement(&wp);\r
1717                 }\r
1718 \r
1719                 // and finally, bring to top after showing\r
1720                 BringToTop(nCmdShow);\r
1721         }\r
1722         return;\r
1723 }\r
1724 \r
1725 BOOL CMainFrame::ReadWindowPlacement(WINDOWPLACEMENT * pwp)\r
1726 {\r
1727         CRegString placement = CRegString(_T("Software\\TortoiseMerge\\WindowPos"));\r
1728         CString sPlacement = placement;\r
1729         if (sPlacement.IsEmpty())\r
1730                 return FALSE;\r
1731         int nRead = _stscanf_s(sPlacement, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),\r
1732                                 &pwp->flags, &pwp->showCmd,\r
1733                                 &pwp->ptMinPosition.x, &pwp->ptMinPosition.y,\r
1734                                 &pwp->ptMaxPosition.x, &pwp->ptMaxPosition.y,\r
1735                                 &pwp->rcNormalPosition.left,  &pwp->rcNormalPosition.top,\r
1736                                 &pwp->rcNormalPosition.right, &pwp->rcNormalPosition.bottom);\r
1737         if ( nRead != 10 )  \r
1738                 return FALSE;\r
1739         pwp->length = sizeof(WINDOWPLACEMENT);\r
1740 \r
1741         return TRUE;\r
1742 }\r
1743 \r
1744 void CMainFrame::WriteWindowPlacement(WINDOWPLACEMENT * pwp)\r
1745 {\r
1746         CRegString placement = CRegString(_T("Software\\TortoiseMerge\\WindowPos"));\r
1747         TCHAR szBuffer[sizeof("-32767")*8 + sizeof("65535")*2];\r
1748         CString s;\r
1749 \r
1750         _stprintf_s(szBuffer, sizeof("-32767")*8 + sizeof("65535")*2, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),\r
1751                         pwp->flags, pwp->showCmd,\r
1752                         pwp->ptMinPosition.x, pwp->ptMinPosition.y,\r
1753                         pwp->ptMaxPosition.x, pwp->ptMaxPosition.y,\r
1754                         pwp->rcNormalPosition.left, pwp->rcNormalPosition.top,\r
1755                         pwp->rcNormalPosition.right, pwp->rcNormalPosition.bottom);\r
1756         placement = szBuffer;\r
1757 }\r
1758 \r
1759 void CMainFrame::OnUpdateMergeMarkasresolved(CCmdUI *pCmdUI)\r
1760 {\r
1761         if (pCmdUI == NULL)\r
1762                 return;\r
1763         BOOL bEnable = FALSE;\r
1764         if ((!m_bReadOnly)&&(m_Data.m_mergedFile.InUse()))\r
1765         {\r
1766                 if (m_pwndBottomView)\r
1767                 {\r
1768                         if ((m_pwndBottomView->IsWindowVisible())&&(m_pwndBottomView->m_pViewData))\r
1769                         {\r
1770                                 bEnable = TRUE;\r
1771                         } \r
1772                 }\r
1773         }\r
1774         pCmdUI->Enable(bEnable);\r
1775 }\r
1776 \r
1777 void CMainFrame::OnMergeMarkasresolved()\r
1778 {\r
1779         int nConflictLine = CheckResolved();\r
1780         if (nConflictLine >= 0)\r
1781         {\r
1782                 CString sTemp;\r
1783                 sTemp.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS, m_pwndBottomView->m_pViewData->GetLineNumber(nConflictLine)+1);\r
1784                 if (MessageBox(sTemp, 0, MB_ICONERROR | MB_YESNO)!=IDYES)\r
1785                 {\r
1786                         if (m_pwndBottomView)\r
1787                                 m_pwndBottomView->GoToLine(nConflictLine);\r
1788                         return;\r
1789                 }\r
1790         }\r
1791         // now check if the file has already been saved and if not, save it.\r
1792         if (m_Data.m_mergedFile.InUse())\r
1793         {\r
1794                 if (m_pwndBottomView)\r
1795                 {\r
1796                         if ((m_pwndBottomView->IsWindowVisible())&&(m_pwndBottomView->m_pViewData))\r
1797                         {\r
1798                                 FileSave(false);\r
1799                         } \r
1800                 }\r
1801         }       \r
1802         MarkAsResolved();\r
1803 }\r
1804 \r
1805 BOOL CMainFrame::MarkAsResolved()\r
1806 {\r
1807         if (m_bReadOnly)\r
1808                 return FALSE;\r
1809         if ((m_pwndBottomView)&&(m_pwndBottomView->IsWindowVisible()))\r
1810         {\r
1811                 TCHAR buf[MAX_PATH*3];\r
1812                 GetModuleFileName(NULL, buf, MAX_PATH);\r
1813                 TCHAR * end = _tcsrchr(buf, '\\');\r
1814                 end++;\r
1815                 (*end) = 0;\r
1816                 _tcscat_s(buf, MAX_PATH*3, _T("TortoiseProc.exe /command:resolve /path:\""));\r
1817                 _tcscat_s(buf, MAX_PATH*3, m_Data.m_mergedFile.GetFilename());\r
1818                 _tcscat_s(buf, MAX_PATH*3, _T("\" /closeonend:1 /noquestion /skipcheck"));\r
1819                 STARTUPINFO startup;\r
1820                 PROCESS_INFORMATION process;\r
1821                 memset(&startup, 0, sizeof(startup));\r
1822                 startup.cb = sizeof(startup);\r
1823                 memset(&process, 0, sizeof(process));\r
1824                 if (CreateProcess(NULL, buf, NULL, NULL, FALSE, 0, 0, 0, &startup, &process)==0)\r
1825                 {\r
1826                         LPVOID lpMsgBuf;\r
1827                         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | \r
1828                                 FORMAT_MESSAGE_FROM_SYSTEM | \r
1829                                 FORMAT_MESSAGE_IGNORE_INSERTS,\r
1830                                 NULL,\r
1831                                 GetLastError(),\r
1832                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language\r
1833                                 (LPTSTR) &lpMsgBuf,\r
1834                                 0,\r
1835                                 NULL \r
1836                                 );\r
1837                         MessageBox((LPCTSTR)lpMsgBuf, _T("TortoiseMerge"), MB_OK | MB_ICONINFORMATION);\r
1838                         LocalFree( lpMsgBuf );\r
1839                         return FALSE;\r
1840                 }\r
1841                 CloseHandle(process.hThread);\r
1842                 CloseHandle(process.hProcess);\r
1843         }\r
1844         else\r
1845                 return FALSE;\r
1846         return TRUE;\r
1847 }\r
1848 \r
1849 void CMainFrame::OnUpdateMergeNextconflict(CCmdUI *pCmdUI)\r
1850 {\r
1851         pCmdUI->Enable(m_bHasConflicts);\r
1852 }\r
1853 \r
1854 void CMainFrame::OnUpdateMergePreviousconflict(CCmdUI *pCmdUI)\r
1855 {\r
1856         pCmdUI->Enable(m_bHasConflicts);\r
1857 }\r
1858 \r
1859 void CMainFrame::OnMoving(UINT fwSide, LPRECT pRect)\r
1860 {\r
1861         // if the pathfilelist dialog is attached to the mainframe,\r
1862         // move it along with the mainframe\r
1863         if (::IsWindow(m_dlgFilePatches.m_hWnd))\r
1864         {\r
1865                 RECT patchrect;\r
1866                 m_dlgFilePatches.GetWindowRect(&patchrect);\r
1867                 if (::IsWindow(m_hWnd))\r
1868                 {\r
1869                         RECT thisrect;\r
1870                         GetWindowRect(&thisrect);\r
1871                         if (patchrect.right == thisrect.left)\r
1872                         {\r
1873                                 m_dlgFilePatches.SetWindowPos(NULL, patchrect.left - (thisrect.left - pRect->left), patchrect.top - (thisrect.top - pRect->top), \r
1874                                         0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);\r
1875                         }\r
1876                 }\r
1877         }\r
1878         __super::OnMoving(fwSide, pRect);\r
1879 }\r
1880 \r
1881 void CMainFrame::OnUpdateEditCopy(CCmdUI *pCmdUI)\r
1882 {\r
1883         BOOL bShow = FALSE;\r
1884         if ((m_pwndBottomView)&&(m_pwndBottomView->HasSelection()))\r
1885                 bShow = TRUE;\r
1886         if ((m_pwndRightView)&&(m_pwndRightView->HasSelection()))\r
1887                 bShow = TRUE;\r
1888         if ((m_pwndLeftView)&&(m_pwndLeftView->HasSelection()))\r
1889                 bShow = TRUE;\r
1890         pCmdUI->Enable(bShow);\r
1891 }\r
1892 \r
1893 void CMainFrame::OnViewSwitchleft()\r
1894 {\r
1895         int ret = IDNO;\r
1896         if (((m_pwndBottomView)&&(m_pwndBottomView->IsModified())) ||\r
1897                 ((m_pwndRightView)&&(m_pwndRightView->IsModified())))\r
1898         {\r
1899                 CString sTemp;\r
1900                 sTemp.LoadString(IDS_ASKFORSAVE);\r
1901                 ret = MessageBox(sTemp, 0, MB_YESNOCANCEL | MB_ICONQUESTION);\r
1902                 if (ret == IDYES)\r
1903                 {\r
1904                         if (!FileSave())\r
1905                                 return;\r
1906                 }\r
1907         }\r
1908         if ((ret == IDNO)||(ret == IDYES))\r
1909         {\r
1910                 CWorkingFile file = m_Data.m_baseFile;\r
1911                 m_Data.m_baseFile = m_Data.m_yourFile;\r
1912                 m_Data.m_yourFile = file;\r
1913                 if (m_Data.m_mergedFile.GetFilename().CompareNoCase(m_Data.m_yourFile.GetFilename())==0)\r
1914                 {\r
1915                         m_Data.m_mergedFile = m_Data.m_baseFile;\r
1916                 }\r
1917                 else if (m_Data.m_mergedFile.GetFilename().CompareNoCase(m_Data.m_baseFile.GetFilename())==0)\r
1918                 {\r
1919                         m_Data.m_mergedFile = m_Data.m_yourFile;\r
1920                 }\r
1921                 LoadViews();\r
1922         }\r
1923 }\r
1924 \r
1925 void CMainFrame::OnUpdateViewSwitchleft(CCmdUI *pCmdUI)\r
1926 {\r
1927         BOOL bEnable = TRUE;\r
1928         if (m_pwndBottomView)\r
1929         {\r
1930                 if (m_pwndBottomView->IsWindowVisible())\r
1931                         bEnable = FALSE;\r
1932         }\r
1933         pCmdUI->Enable(bEnable);\r
1934 }\r
1935 \r
1936 \r
1937 void CMainFrame::OnUpdateViewShowfilelist(CCmdUI *pCmdUI)\r
1938 {\r
1939         if (m_dlgFilePatches.HasFiles())\r
1940         {\r
1941                 pCmdUI->Enable(true);\r
1942         }\r
1943         else\r
1944                 pCmdUI->Enable(false);\r
1945         pCmdUI->SetCheck(m_dlgFilePatches.IsWindowVisible());\r
1946 }\r
1947 \r
1948 void CMainFrame::OnViewShowfilelist()\r
1949 {\r
1950         m_dlgFilePatches.ShowWindow(m_dlgFilePatches.IsWindowVisible() ? SW_HIDE : SW_SHOW);\r
1951 }\r
1952 \r
1953 void CMainFrame::OnEditUndo()\r
1954 {\r
1955         if (CUndo::GetInstance().CanUndo())\r
1956         {\r
1957                 CUndo::GetInstance().Undo(m_pwndLeftView, m_pwndRightView, m_pwndBottomView);\r
1958 \r
1959         }\r
1960 }\r
1961 \r
1962 void CMainFrame::OnUpdateEditUndo(CCmdUI *pCmdUI)\r
1963 {\r
1964         pCmdUI->Enable(CUndo::GetInstance().CanUndo());\r
1965 }\r
1966 \r
1967 int CMainFrame::CheckForSave()\r
1968 {\r
1969         int ret = IDNO;\r
1970         if (((m_pwndBottomView)&&(m_pwndBottomView->IsModified())) ||\r
1971                 ((m_pwndRightView)&&(m_pwndRightView->IsModified())))\r
1972         {\r
1973                 CString sTemp;\r
1974                 sTemp.LoadString(IDS_WARNMODIFIEDLOOSECHANGES);\r
1975                 ret = MessageBox(sTemp, 0, MB_YESNOCANCEL | MB_ICONQUESTION);\r
1976 \r
1977                 if (ret == IDYES)\r
1978                 {\r
1979                         FileSave();\r
1980                 }\r
1981         }\r
1982         return ret;\r
1983 }\r
1984 \r
1985 void CMainFrame::OnViewInlinediffword()\r
1986 {\r
1987         m_bInlineWordDiff = !m_bInlineWordDiff;\r
1988         if (m_pwndLeftView)\r
1989         {\r
1990                 m_pwndLeftView->SetInlineWordDiff(m_bInlineWordDiff);\r
1991                 m_pwndLeftView->Invalidate();\r
1992         }\r
1993         if (m_pwndRightView)\r
1994         {\r
1995                 m_pwndRightView->SetInlineWordDiff(m_bInlineWordDiff);\r
1996                 m_pwndRightView->Invalidate();\r
1997         }\r
1998         if (m_pwndBottomView)\r
1999         {\r
2000                 m_pwndBottomView->SetInlineWordDiff(m_bInlineWordDiff);\r
2001                 m_pwndBottomView->Invalidate();\r
2002         }\r
2003         m_wndLineDiffBar.Invalidate();\r
2004 }\r
2005 \r
2006 void CMainFrame::OnUpdateViewInlinediffword(CCmdUI *pCmdUI)\r
2007 {\r
2008         pCmdUI->Enable(m_pwndLeftView && m_pwndLeftView->IsWindowVisible() &&\r
2009                 m_pwndRightView && m_pwndRightView->IsWindowVisible());\r
2010         pCmdUI->SetCheck(m_bInlineWordDiff);\r
2011 }\r
2012 \r
2013 void CMainFrame::OnUpdateEditCreateunifieddifffile(CCmdUI *pCmdUI)\r
2014 {\r
2015         // "create unified diff file" is only available if two files\r
2016         // are diffed, not three.\r
2017         bool bEnabled = true;\r
2018         if ((m_pwndLeftView == NULL)||(!m_pwndLeftView->IsWindowVisible()))\r
2019                 bEnabled = false;\r
2020         if ((m_pwndRightView == NULL)||(!m_pwndRightView->IsWindowVisible()))\r
2021                 bEnabled = false;\r
2022         if ((m_pwndBottomView)&&(m_pwndBottomView->IsWindowVisible()))\r
2023                 bEnabled = false;\r
2024         pCmdUI->Enable(bEnabled);\r
2025 }\r
2026 \r
2027 void CMainFrame::OnEditCreateunifieddifffile()\r
2028 {\r
2029         CString origFile, modifiedFile, outputFile;\r
2030         // the original file is the one on the left\r
2031         if (m_pwndLeftView)\r
2032                 origFile = m_pwndLeftView->m_sFullFilePath;\r
2033         if (m_pwndRightView)\r
2034                 modifiedFile = m_pwndRightView->m_sFullFilePath;\r
2035         if (!origFile.IsEmpty() && !modifiedFile.IsEmpty())\r
2036         {\r
2037                 // ask for the path to save the unified diff file to\r
2038                 OPENFILENAME ofn = {0};                 // common dialog box structure\r
2039                 TCHAR szFile[MAX_PATH] = {0};   // buffer for file name\r
2040                 ofn.lStructSize = sizeof(OPENFILENAME);\r
2041                 ofn.lpstrFile = szFile;\r
2042                 ofn.nMaxFile = sizeof(szFile)/sizeof(TCHAR);\r
2043                 CString temp;\r
2044                 temp.LoadString(IDS_SAVEASTITLE);\r
2045                 if (!temp.IsEmpty())\r
2046                         ofn.lpstrTitle = temp;\r
2047                 ofn.Flags = OFN_OVERWRITEPROMPT;\r
2048                 CString sFilter;\r
2049                 sFilter.LoadString(IDS_COMMONFILEFILTER);\r
2050                 TCHAR * pszFilters = new TCHAR[sFilter.GetLength()+4];\r
2051                 _tcscpy_s (pszFilters, sFilter.GetLength()+4, sFilter);\r
2052                 // Replace '|' delimiters with '\0's\r
2053                 TCHAR *ptr = pszFilters + _tcslen(pszFilters);  //set ptr at the NULL\r
2054                 while (ptr != pszFilters)\r
2055                 {\r
2056                         if (*ptr == '|')\r
2057                                 *ptr = '\0';\r
2058                         ptr--;\r
2059                 }\r
2060                 ofn.lpstrFilter = pszFilters;\r
2061                 ofn.nFilterIndex = 1;\r
2062 \r
2063                 // Display the Save dialog box. \r
2064                 CString sFile;\r
2065                 if (GetSaveFileName(&ofn)==TRUE)\r
2066                 {\r
2067                         outputFile = CString(ofn.lpstrFile);\r
2068                         CAppUtils::CreateUnifiedDiff(origFile, modifiedFile, outputFile, true);\r
2069                 }\r
2070                 delete [] pszFilters;\r
2071         }\r
2072 }\r
2073 \r
2074 void CMainFrame::OnUpdateViewLinediffbar(CCmdUI *pCmdUI)\r
2075 {\r
2076         pCmdUI->SetCheck(m_bLineDiff);\r
2077         pCmdUI->Enable();\r
2078 }\r
2079 \r
2080 void CMainFrame::OnViewLinediffbar()\r
2081 {\r
2082         m_bLineDiff = !m_bLineDiff;\r
2083         m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);\r
2084         m_wndLineDiffBar.DocumentUpdated();\r
2085         m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);\r
2086         m_wndLocatorBar.DocumentUpdated();\r
2087 }\r
2088 \r
2089 void CMainFrame::OnUpdateViewLocatorbar(CCmdUI *pCmdUI)\r
2090 {\r
2091         pCmdUI->SetCheck(m_bLocatorBar);\r
2092         pCmdUI->Enable();\r
2093 }\r
2094 \r
2095 void CMainFrame::OnViewLocatorbar()\r
2096 {\r
2097         m_bLocatorBar = !m_bLocatorBar;\r
2098         m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);\r
2099         m_wndLocatorBar.DocumentUpdated();\r
2100         m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);\r
2101         m_wndLineDiffBar.DocumentUpdated();\r
2102 }\r
2103 \r