OSDN Git Service

Modify Git Clone Control Tab order
[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)\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                 progDlg.ShowModeless(this);\r
403                 CString sBaseFile = m_TempFiles.GetTempFilePath();\r
404                 if (!CAppUtils::GetVersionedFile(sFilePath, sVersion, sBaseFile, &progDlg, m_hWnd))\r
405                 {\r
406                         progDlg.Stop();\r
407                         CString sErrMsg;\r
408                         sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sVersion, (LPCTSTR)sFilePath);\r
409                         MessageBox(sErrMsg, NULL, MB_ICONERROR);\r
410                         return FALSE;\r
411                 }\r
412                 progDlg.Stop();\r
413                 CString sTempFile = m_TempFiles.GetTempFilePath();\r
414                 if (!m_Patch.PatchFile(sFilePath, sTempFile, sBaseFile))\r
415                 {\r
416                         MessageBox(m_Patch.GetErrorMessage(), NULL, MB_ICONERROR);\r
417                         return FALSE;\r
418                 }\r
419                 CString temp;\r
420                 temp.Format(_T("%s Revision %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)sVersion);\r
421                 m_Data.m_baseFile.SetFileName(sBaseFile);\r
422                 m_Data.m_baseFile.SetDescriptiveName(temp);\r
423                 temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchPatched);\r
424                 m_Data.m_theirFile.SetFileName(sTempFile);\r
425                 m_Data.m_theirFile.SetDescriptiveName(temp);\r
426                 m_Data.m_yourFile.SetFileName(sFilePath);\r
427                 m_Data.m_yourFile.SetDescriptiveName(CPathUtils::GetFileNameFromPath(sFilePath));\r
428                 m_Data.m_mergedFile.SetFileName(sFilePath);\r
429                 m_Data.m_mergedFile.SetDescriptiveName(CPathUtils::GetFileNameFromPath(sFilePath));\r
430                 TRACE(_T("comparing %s and %s\nagainst the base file %s\n"), (LPCTSTR)sTempFile, (LPCTSTR)sFilePath, (LPCTSTR)sBaseFile);\r
431         }\r
432         else\r
433         {\r
434                 //"dry run" was successful, so save the patched file somewhere...\r
435                 CString sTempFile = m_TempFiles.GetTempFilePath();\r
436                 if (!m_Patch.PatchFile(sFilePath, sTempFile))\r
437                 {\r
438                         MessageBox(m_Patch.GetErrorMessage(), NULL, MB_ICONERROR);\r
439                         return FALSE;\r
440                 }\r
441                 if (m_bReversedPatch)\r
442                 {\r
443                         m_Data.m_baseFile.SetFileName(sTempFile);\r
444                         CString temp;\r
445                         temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchPatched);\r
446                         m_Data.m_baseFile.SetDescriptiveName(temp);\r
447                         m_Data.m_yourFile.SetFileName(sFilePath);\r
448                         temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchOriginal);\r
449                         m_Data.m_yourFile.SetDescriptiveName(temp);\r
450                         m_Data.m_theirFile.SetOutOfUse();\r
451                         m_Data.m_mergedFile.SetOutOfUse();\r
452                 }\r
453                 else\r
454                 {\r
455                         if (!PathFileExists(sFilePath))\r
456                         {\r
457                                 m_Data.m_baseFile.SetFileName(m_TempFiles.GetTempFilePath());\r
458                                 m_Data.m_baseFile.CreateEmptyFile();\r
459                         }\r
460                         else\r
461                         {\r
462                                 m_Data.m_baseFile.SetFileName(sFilePath);\r
463                         }\r
464                         CString sDescription;\r
465                         sDescription.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchOriginal);\r
466                         m_Data.m_baseFile.SetDescriptiveName(sDescription);\r
467                         m_Data.m_yourFile.SetFileName(sTempFile);\r
468                         CString temp;\r
469                         temp.Format(_T("%s %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sFilePath), (LPCTSTR)m_Data.m_sPatchPatched);\r
470                         m_Data.m_yourFile.SetDescriptiveName(temp);\r
471                         m_Data.m_theirFile.SetOutOfUse();\r
472                         m_Data.m_mergedFile.SetFileName(sFilePath);\r
473                 }\r
474                 TRACE(_T("comparing %s\nwith the patched result %s\n"), (LPCTSTR)sFilePath, (LPCTSTR)sTempFile);\r
475         }\r
476         LoadViews();\r
477         if (bAutoPatch)\r
478         {\r
479                 OnFileSave();\r
480         }\r
481         return TRUE;\r
482 }\r
483 \r
484 // Callback function\r
485 BOOL CMainFrame::DiffFiles(CString sURL1, CString sRev1, CString sURL2, CString sRev2)\r
486 {\r
487         CString tempfile1 = m_TempFiles.GetTempFilePath();\r
488         CString tempfile2 = m_TempFiles.GetTempFilePath();\r
489         \r
490         ASSERT(tempfile1.Compare(tempfile2));\r
491         \r
492         CString sTemp;\r
493         CSysProgressDlg progDlg;\r
494         sTemp.Format(IDS_GETVERSIONOFFILE, (LPCTSTR)sRev1);\r
495         progDlg.SetLine(1, sTemp, true);\r
496         progDlg.SetLine(2, sURL1, true);\r
497         sTemp.LoadString(IDS_GETVERSIONOFFILETITLE);\r
498         progDlg.SetTitle(sTemp);\r
499         progDlg.SetShowProgressBar(true);\r
500         progDlg.SetAnimation(IDR_DOWNLOAD);\r
501         progDlg.SetTime(FALSE);\r
502         progDlg.SetProgress(1,100);\r
503         progDlg.ShowModeless(this);\r
504         if (!CAppUtils::GetVersionedFile(sURL1, sRev1, tempfile1, &progDlg, m_hWnd))\r
505         {\r
506                 progDlg.Stop();\r
507                 CString sErrMsg;\r
508                 sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sRev1, (LPCTSTR)sURL1);\r
509                 MessageBox(sErrMsg, NULL, MB_ICONERROR);\r
510                 return FALSE;\r
511         }\r
512         sTemp.Format(IDS_GETVERSIONOFFILE, (LPCTSTR)sRev2);\r
513         progDlg.SetLine(1, sTemp, true);\r
514         progDlg.SetLine(2, sURL2, true);\r
515         progDlg.SetProgress(50, 100);\r
516         if (!CAppUtils::GetVersionedFile(sURL2, sRev2, tempfile2, &progDlg, m_hWnd))\r
517         {\r
518                 progDlg.Stop();\r
519                 CString sErrMsg;\r
520                 sErrMsg.Format(IDS_ERR_MAINFRAME_FILEVERSIONNOTFOUND, (LPCTSTR)sRev2, (LPCTSTR)sURL2);\r
521                 MessageBox(sErrMsg, NULL, MB_ICONERROR);\r
522                 return FALSE;\r
523         }\r
524         progDlg.SetProgress(100,100);\r
525         progDlg.Stop();\r
526         CString temp;\r
527         temp.Format(_T("%s Revision %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sURL1), (LPCTSTR)sRev1);\r
528         m_Data.m_baseFile.SetFileName(tempfile1);\r
529         m_Data.m_baseFile.SetDescriptiveName(temp);\r
530         temp.Format(_T("%s Revision %s"), (LPCTSTR)CPathUtils::GetFileNameFromPath(sURL2), (LPCTSTR)sRev2);\r
531         m_Data.m_yourFile.SetFileName(tempfile2);\r
532         m_Data.m_yourFile.SetDescriptiveName(temp);\r
533 \r
534         LoadViews();\r
535 \r
536         return TRUE;\r
537 }\r
538 \r
539 void CMainFrame::OnFileOpen()\r
540 {\r
541         if (CheckForSave()==IDCANCEL)\r
542                 return;\r
543         COpenDlg dlg;\r
544         if (dlg.DoModal()!=IDOK)\r
545         {\r
546                 return;\r
547         }\r
548         m_dlgFilePatches.ShowWindow(SW_HIDE);\r
549         m_dlgFilePatches.Init(NULL, NULL, CString(), NULL);\r
550         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
551                 (LPCTSTR)dlg.m_sUnifiedDiffFile, (LPCTSTR)dlg.m_sPatchDirectory);\r
552         m_Data.m_baseFile.SetFileName(dlg.m_sBaseFile);\r
553         m_Data.m_theirFile.SetFileName(dlg.m_sTheirFile);\r
554         m_Data.m_yourFile.SetFileName(dlg.m_sYourFile);\r
555         m_Data.m_sDiffFile = dlg.m_sUnifiedDiffFile;\r
556         m_Data.m_sPatchPath = dlg.m_sPatchDirectory;\r
557         m_Data.m_mergedFile.SetOutOfUse();\r
558         g_crasher.AddFile((LPCSTR)(LPCTSTR)dlg.m_sBaseFile, (LPCSTR)(LPCTSTR)_T("Basefile"));\r
559         g_crasher.AddFile((LPCSTR)(LPCTSTR)dlg.m_sTheirFile, (LPCSTR)(LPCTSTR)_T("Theirfile"));\r
560         g_crasher.AddFile((LPCSTR)(LPCTSTR)dlg.m_sYourFile, (LPCSTR)(LPCTSTR)_T("Yourfile"));\r
561         g_crasher.AddFile((LPCSTR)(LPCTSTR)dlg.m_sUnifiedDiffFile, (LPCSTR)(LPCTSTR)_T("Difffile"));\r
562         \r
563         if (!m_Data.IsBaseFileInUse() && m_Data.IsTheirFileInUse() && m_Data.IsYourFileInUse())\r
564         {\r
565                 // a diff between two files means "Yours" against "Base", not "Theirs" against "Yours"\r
566                 m_Data.m_baseFile.TransferDetailsFrom(m_Data.m_theirFile);\r
567         }\r
568         if (m_Data.IsBaseFileInUse() && m_Data.IsTheirFileInUse() && !m_Data.IsYourFileInUse())\r
569         {\r
570                 // a diff between two files means "Yours" against "Base", not "Theirs" against "Base"\r
571                 m_Data.m_yourFile.TransferDetailsFrom(m_Data.m_theirFile);\r
572         }\r
573 \r
574         LoadViews();\r
575 }\r
576 \r
577 void CMainFrame::ClearViewNamesAndPaths() {\r
578         m_pwndLeftView->m_sWindowName.Empty();\r
579         m_pwndLeftView->m_sFullFilePath.Empty();\r
580         m_pwndRightView->m_sWindowName.Empty();\r
581         m_pwndRightView->m_sFullFilePath.Empty();\r
582         m_pwndBottomView->m_sWindowName.Empty();\r
583         m_pwndBottomView->m_sFullFilePath.Empty();\r
584 }\r
585 \r
586 bool CMainFrame::LoadViews(bool bRetainPosition)\r
587 {\r
588         m_Data.SetBlame(m_bBlame);\r
589         m_bHasConflicts = false;\r
590         CBaseView* pwndActiveView = m_pwndLeftView;\r
591         int nOldLine = m_pwndLeftView ? m_pwndLeftView->m_nTopLine : -1;\r
592         int nOldLineNumber =\r
593                 m_pwndLeftView && m_pwndLeftView->m_pViewData ?\r
594                 m_pwndLeftView->m_pViewData->GetLineNumber(m_pwndLeftView->m_nTopLine) : -1;\r
595         if (!m_Data.Load())\r
596         {\r
597                 ::MessageBox(NULL, m_Data.GetError(), _T("TortoiseMerge"), MB_ICONERROR);\r
598                 m_Data.m_mergedFile.SetOutOfUse();\r
599                 return false;\r
600         }\r
601 \r
602         m_pwndRightView->UseCaret(false);\r
603         m_pwndBottomView->UseCaret(false);\r
604 \r
605         if (!m_Data.IsBaseFileInUse())\r
606         {\r
607                 if (m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())\r
608                 {\r
609                         m_Data.m_baseFile.TransferDetailsFrom(m_Data.m_theirFile);\r
610                 }\r
611                 else if ((!m_Data.m_sDiffFile.IsEmpty())&&(!m_Patch.OpenUnifiedDiffFile(m_Data.m_sDiffFile)))\r
612                 {\r
613                         ClearViewNamesAndPaths();\r
614                         MessageBox(m_Patch.GetErrorMessage(), NULL, MB_ICONERROR);\r
615                         return false;\r
616                 }\r
617                 if (m_Patch.GetNumberOfFiles() > 0)\r
618                 {\r
619                         CString firstpath = m_Patch.GetFilename(0);\r
620                         CString path=firstpath;\r
621                         path.Replace('/','\\');\r
622                         if ( !PathIsRelative(path) && !PathFileExists(path) )\r
623                         {\r
624                                 // The absolute path mentioned in the patch does not exist. Lets\r
625                                 // try to find the correct relative path by stripping prefixes.\r
626                                 BOOL bFound = m_Patch.StripPrefixes(m_Data.m_sPatchPath);\r
627                                 CString strippedpath = m_Patch.GetFilename(0);\r
628                                 if (bFound)\r
629                                 {\r
630                                         CString msg;\r
631                                         msg.Format(IDS_WARNABSOLUTEPATHFOUND, (LPCTSTR)firstpath, (LPCTSTR)strippedpath);\r
632                                         if (CMessageBox::Show(m_hWnd, msg, _T("TortoiseMerge"), MB_ICONQUESTION | MB_YESNO)==IDNO)\r
633                                                 return false;\r
634                                 }\r
635                                 else\r
636                                 {\r
637                                         CString msg;\r
638                                         msg.Format(IDS_WARNABSOLUTEPATHNOTFOUND, (LPCTSTR)firstpath);\r
639                                         CMessageBox::Show(m_hWnd, msg, _T("TortoiseMerge"), MB_ICONEXCLAMATION);\r
640                                         return false;\r
641                                 }\r
642                         }\r
643                         CString betterpatchpath = m_Patch.CheckPatchPath(m_Data.m_sPatchPath);\r
644                         if (betterpatchpath.CompareNoCase(m_Data.m_sPatchPath)!=0)\r
645                         {\r
646                                 CString msg;\r
647                                 msg.Format(IDS_WARNBETTERPATCHPATHFOUND, (LPCTSTR)m_Data.m_sPatchPath, (LPCTSTR)betterpatchpath);\r
648                                 if (CMessageBox::Show(m_hWnd, msg, _T("TortoiseMerge"), MB_ICONQUESTION | MB_YESNO)==IDYES)\r
649                                         m_Data.m_sPatchPath = betterpatchpath;\r
650                         }\r
651                         m_dlgFilePatches.Init(&m_Patch, this, m_Data.m_sPatchPath, this);\r
652                         m_dlgFilePatches.ShowWindow(SW_SHOW);\r
653                         ClearViewNamesAndPaths();\r
654                         if (!m_wndSplitter.IsRowHidden(1))\r
655                                 m_wndSplitter.HideRow(1);\r
656                         m_pwndLeftView->SetHidden(FALSE);\r
657                         m_pwndRightView->SetHidden(FALSE);\r
658                         m_pwndBottomView->SetHidden(TRUE);\r
659                 }\r
660         }\r
661         if (m_Data.IsBaseFileInUse() && !m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())\r
662         {\r
663                 m_Data.m_yourFile.TransferDetailsFrom(m_Data.m_theirFile);\r
664         }\r
665         if (m_Data.IsBaseFileInUse() && m_Data.IsYourFileInUse() && !m_Data.IsTheirFileInUse())\r
666         {\r
667                 //diff between YOUR and BASE\r
668                 m_pwndRightView->UseCaret();\r
669                 if (m_bOneWay)\r
670                 {\r
671                         if (!m_wndSplitter2.IsColumnHidden(1))\r
672                                 m_wndSplitter2.HideColumn(1);\r
673 \r
674                         m_pwndLeftView->m_pViewData = &m_Data.m_YourBaseBoth;\r
675                         m_pwndLeftView->texttype = m_Data.m_arYourFile.GetUnicodeType();\r
676                         m_pwndLeftView->lineendings = m_Data.m_arYourFile.GetLineEndings();\r
677                         m_pwndLeftView->m_sWindowName = m_Data.m_baseFile.GetWindowName() + _T(" - ") + m_Data.m_yourFile.GetWindowName();\r
678                         m_pwndLeftView->m_sFullFilePath = m_Data.m_baseFile.GetFilename() + _T(" - ") + m_Data.m_yourFile.GetFilename();\r
679 \r
680                         m_pwndRightView->m_pViewData = NULL;\r
681                         m_pwndBottomView->m_pViewData = NULL;\r
682 \r
683                         if (!m_wndSplitter.IsRowHidden(1))\r
684                                 m_wndSplitter.HideRow(1);\r
685                         m_pwndLeftView->SetHidden(FALSE);\r
686                         m_pwndRightView->SetHidden(TRUE);\r
687                         m_pwndBottomView->SetHidden(TRUE);\r
688                         ::SetWindowPos(m_pwndLeftView->m_hWnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);\r
689                 }\r
690                 else\r
691                 {\r
692                         pwndActiveView = m_pwndRightView;\r
693                         if (m_wndSplitter2.IsColumnHidden(1))\r
694                                 m_wndSplitter2.ShowColumn();\r
695 \r
696                         m_pwndLeftView->m_pViewData = &m_Data.m_YourBaseLeft;\r
697                         m_pwndLeftView->texttype = m_Data.m_arBaseFile.GetUnicodeType();\r
698                         m_pwndLeftView->lineendings = m_Data.m_arBaseFile.GetLineEndings();\r
699                         m_pwndLeftView->m_sWindowName = m_Data.m_baseFile.GetWindowName();\r
700                         m_pwndLeftView->m_sFullFilePath = m_Data.m_baseFile.GetFilename();\r
701 \r
702                         m_pwndRightView->m_pViewData = &m_Data.m_YourBaseRight;\r
703                         m_pwndRightView->texttype = m_Data.m_arYourFile.GetUnicodeType();\r
704                         m_pwndRightView->lineendings = m_Data.m_arYourFile.GetLineEndings();\r
705                         m_pwndRightView->m_sWindowName = m_Data.m_yourFile.GetWindowName();\r
706                         m_pwndRightView->m_sFullFilePath = m_Data.m_yourFile.GetFilename();\r
707                 \r
708                         m_pwndBottomView->m_pViewData = NULL;\r
709 \r
710                 if (!m_wndSplitter.IsRowHidden(1))\r
711                                 m_wndSplitter.HideRow(1);\r
712                         m_pwndLeftView->SetHidden(FALSE);\r
713                         m_pwndRightView->SetHidden(FALSE);\r
714                         m_pwndBottomView->SetHidden(TRUE);\r
715                 }\r
716         }\r
717         else if (m_Data.IsBaseFileInUse() && m_Data.IsYourFileInUse() && m_Data.IsTheirFileInUse())\r
718         {\r
719                 //diff between THEIR, YOUR and BASE\r
720                 m_pwndBottomView->UseCaret();\r
721                 pwndActiveView = m_pwndBottomView;\r
722 \r
723                 m_pwndLeftView->m_pViewData = &m_Data.m_TheirBaseBoth;\r
724                 m_pwndLeftView->texttype = m_Data.m_arTheirFile.GetUnicodeType();\r
725                 m_pwndLeftView->lineendings = m_Data.m_arTheirFile.GetLineEndings();\r
726                 m_pwndLeftView->m_sWindowName.LoadString(IDS_VIEWTITLE_THEIRS);\r
727                 m_pwndLeftView->m_sWindowName += _T(" - ") + m_Data.m_theirFile.GetWindowName();\r
728                 m_pwndLeftView->m_sFullFilePath = m_Data.m_theirFile.GetFilename();\r
729                 \r
730                 m_pwndRightView->m_pViewData = &m_Data.m_YourBaseBoth;\r
731                 m_pwndRightView->texttype = m_Data.m_arYourFile.GetUnicodeType();\r
732                 m_pwndRightView->lineendings = m_Data.m_arYourFile.GetLineEndings();\r
733                 m_pwndRightView->m_sWindowName.LoadString(IDS_VIEWTITLE_MINE);\r
734                 m_pwndRightView->m_sWindowName += _T(" - ") + m_Data.m_yourFile.GetWindowName();\r
735                 m_pwndRightView->m_sFullFilePath = m_Data.m_yourFile.GetFilename();\r
736                 \r
737                 m_pwndBottomView->m_pViewData = &m_Data.m_Diff3;\r
738                 m_pwndBottomView->texttype = m_Data.m_arTheirFile.GetUnicodeType();\r
739                 m_pwndBottomView->lineendings = m_Data.m_arTheirFile.GetLineEndings();\r
740                 m_pwndBottomView->m_sWindowName.LoadString(IDS_VIEWTITLE_MERGED);\r
741                 m_pwndBottomView->m_sWindowName += _T(" - ") + m_Data.m_mergedFile.GetWindowName();\r
742                 m_pwndBottomView->m_sFullFilePath = m_Data.m_mergedFile.GetFilename();\r
743                 \r
744                 if (m_wndSplitter2.IsColumnHidden(1))\r
745                         m_wndSplitter2.ShowColumn();\r
746                 if (m_wndSplitter.IsRowHidden(1))\r
747                         m_wndSplitter.ShowRow();\r
748                 m_pwndLeftView->SetHidden(FALSE);\r
749                 m_pwndRightView->SetHidden(FALSE);\r
750                 m_pwndBottomView->SetHidden(FALSE);\r
751                 // in three pane view, hide the line diff bar\r
752                 m_wndLineDiffBar.ShowPane(false, false, true);\r
753                 m_wndLineDiffBar.DocumentUpdated();\r
754         }\r
755         if (!m_Data.m_mergedFile.InUse())\r
756         {\r
757                 m_Data.m_mergedFile.SetFileName(m_Data.m_yourFile.GetFilename());\r
758         }\r
759         m_pwndLeftView->DocumentUpdated();\r
760         m_pwndRightView->DocumentUpdated();\r
761         m_pwndBottomView->DocumentUpdated();\r
762         m_wndLocatorBar.DocumentUpdated();\r
763         m_wndLineDiffBar.DocumentUpdated();\r
764         UpdateLayout();\r
765         SetActiveView(pwndActiveView);\r
766 \r
767         if (bRetainPosition && m_pwndLeftView->m_pViewData)\r
768         {\r
769                 int n = nOldLineNumber;\r
770                 if (n >= 0)\r
771                         n = m_pwndLeftView->m_pViewData->FindLineNumber(n);\r
772                 if (n < 0)\r
773                         n = nOldLine;\r
774 \r
775                 m_pwndLeftView->ScrollAllToLine(n);\r
776                 POINT p;\r
777                 p.x = 0;\r
778                 p.y = n;\r
779                 m_pwndLeftView->SetCaretPosition(p);\r
780         }\r
781         else\r
782         {\r
783                 bool bGoFirstDiff = (0 != (DWORD)CRegDWORD(_T("Software\\TortoiseMerge\\FirstDiffOnLoad"), TRUE));\r
784                 if (bGoFirstDiff) {\r
785                         pwndActiveView->GoToFirstDifference();\r
786                         // Ignore the first few Mouse Move messages, so that the line diff stays on\r
787                         // the first diff line until the user actually moves the mouse\r
788                         m_nMoveMovesToIgnore = 3; \r
789                 }\r
790 \r
791         }\r
792         // Avoid incorrect rendering of active pane.\r
793         m_pwndBottomView->ScrollToChar(0);\r
794         m_pwndLeftView->ScrollToChar(0);\r
795         m_pwndRightView->ScrollToChar(0);\r
796         CheckResolved();\r
797         CUndo::GetInstance().Clear();\r
798         return true;\r
799 }\r
800 \r
801 void CMainFrame::UpdateLayout()\r
802 {\r
803         if (m_bInitSplitter)\r
804         {\r
805                 CRect cr, rclocbar;\r
806                 GetWindowRect(&cr);\r
807                 int width = cr.Width();\r
808                 if (::IsWindow(m_wndLocatorBar) && m_wndLocatorBar.IsWindowVisible())\r
809                 {\r
810                         m_wndLocatorBar.GetWindowRect(&rclocbar);\r
811                         width -= rclocbar.Width();\r
812                 }\r
813                 m_wndSplitter.SetRowInfo(0, cr.Height()/2, 0);\r
814                 m_wndSplitter.SetRowInfo(1, cr.Height()/2, 0);\r
815                 m_wndSplitter.SetColumnInfo(0, width / 2, 50);\r
816                 m_wndSplitter2.SetRowInfo(0, cr.Height()/2, 0);\r
817                 m_wndSplitter2.SetColumnInfo(0, width / 2, 50);\r
818                 m_wndSplitter2.SetColumnInfo(1, width / 2, 50);\r
819 \r
820                 m_wndSplitter.RecalcLayout();\r
821         }\r
822 }\r
823 \r
824 void CMainFrame::OnSize(UINT nType, int cx, int cy)\r
825 {\r
826         if (m_bInitSplitter && nType != SIZE_MINIMIZED)\r
827         {\r
828                 UpdateLayout();\r
829         }\r
830         CFrameWndEx::OnSize(nType, cx, cy);\r
831 }\r
832 \r
833 void CMainFrame::OnViewWhitespaces()\r
834 {\r
835         CRegDWORD regViewWhitespaces = CRegDWORD(_T("Software\\TortoiseMerge\\ViewWhitespaces"), 1);\r
836         BOOL bViewWhitespaces = regViewWhitespaces;\r
837         if (m_pwndLeftView)\r
838                 bViewWhitespaces = m_pwndLeftView->m_bViewWhitespace;\r
839 \r
840         bViewWhitespaces = !bViewWhitespaces;\r
841         regViewWhitespaces = bViewWhitespaces;\r
842         if (m_pwndLeftView)\r
843         {\r
844                 m_pwndLeftView->m_bViewWhitespace = bViewWhitespaces;\r
845                 m_pwndLeftView->Invalidate();\r
846         }\r
847         if (m_pwndRightView)\r
848         {\r
849                 m_pwndRightView->m_bViewWhitespace = bViewWhitespaces;\r
850                 m_pwndRightView->Invalidate();\r
851         }\r
852         if (m_pwndBottomView)\r
853         {\r
854                 m_pwndBottomView->m_bViewWhitespace = bViewWhitespaces;\r
855                 m_pwndBottomView->Invalidate();\r
856         }\r
857 }\r
858 \r
859 void CMainFrame::OnUpdateViewWhitespaces(CCmdUI *pCmdUI)\r
860 {\r
861         if (m_pwndLeftView)\r
862                 pCmdUI->SetCheck(m_pwndLeftView->m_bViewWhitespace);\r
863 }\r
864 \r
865 void CMainFrame::OnViewOnewaydiff()\r
866 {\r
867         if (CheckForSave()==IDCANCEL)\r
868                 return;\r
869         m_bOneWay = !m_bOneWay;\r
870         if (m_bOneWay)\r
871         {\r
872                 // in one way view, hide the line diff bar\r
873                 m_wndLineDiffBar.ShowPane(false, false, true);\r
874                 m_wndLineDiffBar.DocumentUpdated();\r
875         }\r
876         else\r
877         {\r
878                 // restore the line diff bar\r
879                 m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);\r
880                 m_wndLineDiffBar.DocumentUpdated();\r
881                 m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);\r
882                 m_wndLocatorBar.DocumentUpdated();\r
883         }\r
884         LoadViews(true);\r
885 }\r
886 \r
887 void CMainFrame::ShowDiffBar(bool bShow)\r
888 {\r
889         if (bShow)\r
890         {\r
891                 // restore the line diff bar\r
892                 m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);\r
893                 m_wndLineDiffBar.DocumentUpdated();\r
894                 m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);\r
895                 m_wndLocatorBar.DocumentUpdated();\r
896         }\r
897         else\r
898         {\r
899                 // in one way view, hide the line diff bar\r
900                 m_wndLineDiffBar.ShowPane(false, false, true);\r
901                 m_wndLineDiffBar.DocumentUpdated();\r
902         }\r
903 }\r
904 \r
905 int CMainFrame::CheckResolved()\r
906 {\r
907         //only in three way diffs can be conflicts!\r
908         m_bHasConflicts = true;\r
909         if (m_pwndBottomView->IsWindowVisible())\r
910         {\r
911                 if (m_pwndBottomView->m_pViewData)\r
912                 {\r
913                         for (int i=0; i<m_pwndBottomView->m_pViewData->GetCount(); i++)\r
914                         {\r
915                                 if ((DIFFSTATE_CONFLICTED == m_pwndBottomView->m_pViewData->GetState(i))||\r
916                                         (DIFFSTATE_CONFLICTED_IGNORED == m_pwndBottomView->m_pViewData->GetState(i)))\r
917                                         return i;\r
918                         }\r
919                 }\r
920         }\r
921         m_bHasConflicts = false;\r
922         return -1;\r
923 }\r
924 \r
925 int CMainFrame::SaveFile(const CString& sFilePath)\r
926 {\r
927         CViewData * pViewData = NULL;\r
928         CFileTextLines * pOriginFile = &m_Data.m_arBaseFile;\r
929         if ((m_pwndBottomView)&&(m_pwndBottomView->IsWindowVisible()))\r
930         {\r
931                 pViewData = m_pwndBottomView->m_pViewData;\r
932                 Invalidate();\r
933         }\r
934         else if ((m_pwndRightView)&&(m_pwndRightView->IsWindowVisible()))\r
935         {\r
936                 pViewData = m_pwndRightView->m_pViewData;\r
937                 if (m_Data.IsYourFileInUse())\r
938                         pOriginFile = &m_Data.m_arYourFile;\r
939                 else if (m_Data.IsTheirFileInUse())\r
940                         pOriginFile = &m_Data.m_arTheirFile;\r
941                 Invalidate();\r
942         } \r
943         else\r
944         {\r
945                 // nothing to save!\r
946                 return -1;\r
947         }\r
948         if ((pViewData)&&(pOriginFile))\r
949         {\r
950                 CFileTextLines file;\r
951                 pOriginFile->CopySettings(&file);\r
952                 for (int i=0; i<pViewData->GetCount(); i++)\r
953                 {\r
954                         //only copy non-removed lines\r
955                         DiffStates state = pViewData->GetState(i);\r
956                         switch (state)\r
957                         {\r
958                         case DIFFSTATE_CONFLICTED:\r
959                         case DIFFSTATE_CONFLICTED_IGNORED:\r
960                                 {\r
961                                         int first = i;\r
962                                         int last = i;\r
963                                         do \r
964                                         {\r
965                                                 last++;\r
966                                         } while((last<pViewData->GetCount()) && ((pViewData->GetState(last)==DIFFSTATE_CONFLICTED)||(pViewData->GetState(last)==DIFFSTATE_CONFLICTED_IGNORED)));\r
967                                         file.Add(_T("<<<<<<< .mine"), EOL_NOENDING);\r
968                                         for (int j=first; j<last; j++)\r
969                                         {\r
970                                                 file.Add(m_pwndRightView->m_pViewData->GetLine(j), m_pwndRightView->m_pViewData->GetLineEnding(j));\r
971                                         }\r
972                                         file.Add(_T("======="), EOL_NOENDING);\r
973                                         for (int j=first; j<last; j++)\r
974                                         {\r
975                                                 file.Add(m_pwndLeftView->m_pViewData->GetLine(j), m_pwndLeftView->m_pViewData->GetLineEnding(j));\r
976                                         }\r
977                                         file.Add(_T(">>>>>>> .theirs"), EOL_NOENDING);\r
978                                         i = last-1;\r
979                                 }\r
980                                 break;\r
981                         case DIFFSTATE_EMPTY:\r
982                         case DIFFSTATE_CONFLICTEMPTY:\r
983                         case DIFFSTATE_IDENTICALREMOVED:\r
984                         case DIFFSTATE_REMOVED:\r
985                         case DIFFSTATE_THEIRSREMOVED:\r
986                         case DIFFSTATE_YOURSREMOVED:\r
987                         case DIFFSTATE_CONFLICTRESOLVEDEMPTY:\r
988                                 // do not save removed lines\r
989                                 break;\r
990                         default:\r
991                                 file.Add(pViewData->GetLine(i), pViewData->GetLineEnding(i));\r
992                                 break;\r
993                         }\r
994                 }\r
995                 if (!file.Save(sFilePath, false))\r
996                 {\r
997                         CMessageBox::Show(m_hWnd, file.GetErrorString(), _T("TortoiseMerge"), MB_ICONERROR);\r
998                         return -1;\r
999                 }\r
1000                 m_dlgFilePatches.SetFileStatusAsPatched(sFilePath);\r
1001                 if (m_pwndBottomView)\r
1002                         m_pwndBottomView->SetModified(FALSE);\r
1003                 if (m_pwndRightView)\r
1004                         m_pwndRightView->SetModified(FALSE);\r
1005                 CUndo::GetInstance().MarkAsOriginalState();\r
1006                 return file.GetCount();\r
1007         }\r
1008         return -1;\r
1009 }\r
1010 \r
1011 void CMainFrame::OnFileSave()\r
1012 {\r
1013         FileSave();\r
1014 }\r
1015 \r
1016 bool CMainFrame::FileSave(bool bCheckResolved /*=true*/)\r
1017 {\r
1018         if (!m_Data.m_mergedFile.InUse())\r
1019                 return FileSaveAs(bCheckResolved);\r
1020         // check if the file has the readonly attribute set\r
1021         bool bDoesNotExist = false;\r
1022         DWORD fAttribs = GetFileAttributes(m_Data.m_mergedFile.GetFilename());\r
1023         if ((fAttribs != INVALID_FILE_ATTRIBUTES)&&(fAttribs & FILE_ATTRIBUTE_READONLY))\r
1024                 return FileSaveAs(bCheckResolved);\r
1025         if (fAttribs == INVALID_FILE_ATTRIBUTES)\r
1026         {\r
1027                 bDoesNotExist = (GetLastError() == ERROR_FILE_NOT_FOUND);\r
1028         }\r
1029         if (bCheckResolved)\r
1030         {\r
1031                 int nConflictLine = CheckResolved();\r
1032                 if (nConflictLine >= 0)\r
1033                 {\r
1034                         CString sTemp;\r
1035                         sTemp.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS, m_pwndBottomView->m_pViewData->GetLineNumber(nConflictLine)+1);\r
1036                         if (MessageBox(sTemp, 0, MB_ICONERROR | MB_YESNO)!=IDYES)\r
1037                         {\r
1038                                 if (m_pwndBottomView)\r
1039                                         m_pwndBottomView->GoToLine(nConflictLine);\r
1040                                 return false;\r
1041                         }\r
1042                 }\r
1043         }\r
1044         if (((DWORD)CRegDWORD(_T("Software\\TortoiseMerge\\Backup"))) != 0)\r
1045         {\r
1046                 MoveFileEx(m_Data.m_mergedFile.GetFilename(), m_Data.m_mergedFile.GetFilename() + _T(".bak"), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);\r
1047         }\r
1048         if (SaveFile(m_Data.m_mergedFile.GetFilename())==0)\r
1049         {\r
1050                 // file was saved with 0 lines!\r
1051                 // ask the user if the file should be deleted\r
1052                 CString sTemp;\r
1053                 sTemp.Format(IDS_DELETEWHENEMPTY, (LPCTSTR)m_Data.m_mergedFile.GetFilename());\r
1054                 if (CMessageBox::ShowCheck(m_hWnd, sTemp, _T("TortoiseMerge"), MB_YESNO, _T("DeleteFileWhenEmpty")) == IDYES)\r
1055                 {\r
1056                         DeleteFile(m_Data.m_mergedFile.GetFilename());\r
1057                 }\r
1058         }\r
1059         \r
1060         if (bDoesNotExist)\r
1061         {\r
1062                 // call TortoiseProc to add the new file to version control\r
1063                 CString cmd = _T("\"") + CPathUtils::GetAppDirectory();\r
1064                 cmd += _T("TortoiseProc.exe\" /command:add /noui /path:\"");\r
1065                 cmd += m_Data.m_mergedFile.GetFilename() + _T("\"");\r
1066                 TCHAR * buf = new TCHAR[cmd.GetLength()+1];\r
1067                 _tcscpy_s(buf, cmd.GetLength()+1, cmd);\r
1068                 STARTUPINFO startup;\r
1069                 PROCESS_INFORMATION process;\r
1070                 memset(&startup, 0, sizeof(startup));\r
1071                 startup.cb = sizeof(startup);\r
1072                 memset(&process, 0, sizeof(process));\r
1073                 if (CreateProcess(NULL, buf, NULL, NULL, FALSE, 0, 0, 0, &startup, &process)==0)\r
1074                 {\r
1075                         delete [] buf;\r
1076                         LPVOID lpMsgBuf;\r
1077                         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | \r
1078                                 FORMAT_MESSAGE_FROM_SYSTEM | \r
1079                                 FORMAT_MESSAGE_IGNORE_INSERTS,\r
1080                                 NULL,\r
1081                                 GetLastError(),\r
1082                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language\r
1083                                 (LPTSTR) &lpMsgBuf,\r
1084                                 0,\r
1085                                 NULL \r
1086                                 );\r
1087                         MessageBox((LPCTSTR)lpMsgBuf, _T("TortoiseMerge"), MB_OK | MB_ICONINFORMATION);\r
1088                         LocalFree( lpMsgBuf );\r
1089                         return FALSE;\r
1090                 }\r
1091                 delete [] buf;\r
1092                 CloseHandle(process.hThread);\r
1093                 CloseHandle(process.hProcess);\r
1094         }\r
1095         return true;\r
1096 }\r
1097 \r
1098 void CMainFrame::OnFileSaveAs()\r
1099 {\r
1100         FileSaveAs();\r
1101 }\r
1102 \r
1103 bool CMainFrame::FileSaveAs(bool bCheckResolved /*=true*/)\r
1104 {\r
1105         if (bCheckResolved)\r
1106         {\r
1107                 int nConflictLine = CheckResolved();\r
1108                 if (nConflictLine >= 0)\r
1109                 {\r
1110                         CString sTemp;\r
1111                         sTemp.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS, m_pwndBottomView->m_pViewData->GetLineNumber(nConflictLine)+1);\r
1112                         if (MessageBox(sTemp, 0, MB_ICONERROR | MB_YESNO)!=IDYES)\r
1113                         {\r
1114                                 if (m_pwndBottomView)\r
1115                                         m_pwndBottomView->GoToLine(nConflictLine);\r
1116                                 return false;\r
1117                         }\r
1118                 }\r
1119         }\r
1120         OPENFILENAME ofn = {0};                 // common dialog box structure\r
1121         TCHAR szFile[MAX_PATH] = {0};   // buffer for file name\r
1122         ofn.lStructSize = sizeof(OPENFILENAME);\r
1123         ofn.hwndOwner = m_hWnd;\r
1124         ofn.lpstrFile = szFile;\r
1125         ofn.nMaxFile = sizeof(szFile)/sizeof(TCHAR);\r
1126         CString temp;\r
1127         temp.LoadString(IDS_SAVEASTITLE);\r
1128         if (!temp.IsEmpty())\r
1129                 ofn.lpstrTitle = temp;\r
1130         ofn.Flags = OFN_OVERWRITEPROMPT;\r
1131         CString sFilter;\r
1132         sFilter.LoadString(IDS_COMMONFILEFILTER);\r
1133         TCHAR * pszFilters = new TCHAR[sFilter.GetLength()+4];\r
1134         _tcscpy_s (pszFilters, sFilter.GetLength()+4, sFilter);\r
1135         // Replace '|' delimiters with '\0's\r
1136         TCHAR *ptr = pszFilters + _tcslen(pszFilters);  //set ptr at the NULL\r
1137         while (ptr != pszFilters)\r
1138         {\r
1139                 if (*ptr == '|')\r
1140                         *ptr = '\0';\r
1141                 ptr--;\r
1142         }\r
1143         ofn.lpstrFilter = pszFilters;\r
1144         ofn.nFilterIndex = 1;\r
1145 \r
1146         // Display the Open dialog box. \r
1147         CString sFile;\r
1148         if (GetSaveFileName(&ofn)==TRUE)\r
1149         {\r
1150                 sFile = CString(ofn.lpstrFile);\r
1151                 SaveFile(sFile);\r
1152                 delete [] pszFilters;\r
1153                 return true;\r
1154         }\r
1155         delete [] pszFilters;\r
1156         return false;\r
1157 }\r
1158 \r
1159 void CMainFrame::OnUpdateFileSave(CCmdUI *pCmdUI)\r
1160 {\r
1161         BOOL bEnable = FALSE;\r
1162         if (m_Data.m_mergedFile.InUse())\r
1163         {\r
1164                 if (m_pwndBottomView)\r
1165                 {\r
1166                         if ((m_pwndBottomView->IsWindowVisible())&&(m_pwndBottomView->m_pViewData))\r
1167                         {\r
1168                                 bEnable = TRUE;\r
1169                         } \r
1170                 }\r
1171                 if (m_pwndRightView)\r
1172                 {\r
1173                         if ((m_pwndRightView->IsWindowVisible())&&(m_pwndRightView->m_pViewData))\r
1174                         {\r
1175                                 if (m_pwndRightView->IsModified() || (m_Data.m_yourFile.GetWindowName().Right(9).Compare(_T(": patched"))==0))\r
1176                                         bEnable = TRUE;\r
1177                         } \r
1178                 }\r
1179         }\r
1180         pCmdUI->Enable(bEnable);\r
1181 }\r
1182 \r
1183 void CMainFrame::OnUpdateFileSaveAs(CCmdUI *pCmdUI)\r
1184 {\r
1185         BOOL bEnable = FALSE;\r
1186         if (m_pwndBottomView)\r
1187         {\r
1188                 if ((m_pwndBottomView->IsWindowVisible())&&(m_pwndBottomView->m_pViewData))\r
1189                 {\r
1190                         bEnable = TRUE;\r
1191                 }\r
1192         }\r
1193         if (m_pwndRightView)\r
1194         {\r
1195                 if ((m_pwndRightView->IsWindowVisible())&&(m_pwndRightView->m_pViewData))\r
1196                 {\r
1197                         bEnable = TRUE;\r
1198                 }\r
1199         } \r
1200         pCmdUI->Enable(bEnable);\r
1201 }\r
1202 \r
1203 \r
1204 void CMainFrame::OnUpdateViewOnewaydiff(CCmdUI *pCmdUI)\r
1205 {\r
1206         pCmdUI->SetCheck(!m_bOneWay);\r
1207         BOOL bEnable = TRUE;\r
1208         if (m_pwndBottomView)\r
1209         {\r
1210                 if (m_pwndBottomView->IsWindowVisible())\r
1211                         bEnable = FALSE;\r
1212         }\r
1213         pCmdUI->Enable(bEnable);\r
1214 }\r
1215 \r
1216 void CMainFrame::OnViewOptions()\r
1217 {\r
1218         CString sTemp;\r
1219         sTemp.LoadString(IDS_SETTINGSTITLE);\r
1220         CSettings dlg(sTemp);\r
1221         dlg.DoModal();\r
1222         if (dlg.IsReloadNeeded())\r
1223         {\r
1224                 if (CheckForSave()==IDCANCEL)\r
1225                         return;\r
1226                 CDiffColors::GetInstance().LoadRegistry();\r
1227                 LoadViews();\r
1228                 return;\r
1229         }\r
1230         CDiffColors::GetInstance().LoadRegistry();\r
1231         if (m_pwndBottomView)\r
1232                 m_pwndBottomView->Invalidate();\r
1233         if (m_pwndLeftView)\r
1234                 m_pwndLeftView->Invalidate();\r
1235         if (m_pwndRightView)\r
1236                 m_pwndRightView->Invalidate();\r
1237 }\r
1238 \r
1239 void CMainFrame::OnClose()\r
1240 {\r
1241         if ((m_pFindDialog)&&(!m_pFindDialog->IsTerminating()))\r
1242         {\r
1243                 m_pFindDialog->SendMessage(WM_CLOSE);\r
1244                 return;\r
1245         }\r
1246         int ret = IDNO;\r
1247         if (((m_pwndBottomView)&&(m_pwndBottomView->IsModified())) ||\r
1248                 ((m_pwndRightView)&&(m_pwndRightView->IsModified())))\r
1249         {\r
1250                 CString sTemp;\r
1251                 sTemp.LoadString(IDS_ASKFORSAVE);\r
1252                 ret = MessageBox(sTemp, 0, MB_YESNOCANCEL | MB_ICONQUESTION);\r
1253                 if (ret == IDYES)\r
1254                 {\r
1255                         if (!FileSave())\r
1256                                 return;\r
1257                 }\r
1258         }\r
1259         if ((ret == IDNO)||(ret == IDYES))\r
1260         {\r
1261                 WINDOWPLACEMENT    wp;\r
1262 \r
1263                 // before it is destroyed, save the position of the window\r
1264                 wp.length = sizeof wp;\r
1265 \r
1266                 if (GetWindowPlacement(&wp))\r
1267                 {\r
1268 \r
1269                         if (IsIconic())\r
1270                                 // never restore to Iconic state\r
1271                                 wp.showCmd = SW_SHOW ;\r
1272 \r
1273                         if ((wp.flags & WPF_RESTORETOMAXIMIZED) != 0)\r
1274                                 // if maximized and maybe iconic restore maximized state\r
1275                                 wp.showCmd = SW_SHOWMAXIMIZED ;\r
1276 \r
1277                         // and write it to the .INI file\r
1278                         WriteWindowPlacement(&wp);\r
1279                 }\r
1280                 __super::OnClose();\r
1281         }\r
1282 }\r
1283 \r
1284 void CMainFrame::OnEditFind()\r
1285 {\r
1286         if (m_pFindDialog)\r
1287         {\r
1288                 return;\r
1289         }\r
1290         else\r
1291         {\r
1292                 // start searching from the start again\r
1293                 // if no line is selected, otherwise start from\r
1294                 // the selected line\r
1295                 m_nSearchIndex = FindSearchStart(0);\r
1296                 m_pFindDialog = new CFindDlg();\r
1297                 m_pFindDialog->Create(this);\r
1298         }\r
1299 }\r
1300 \r
1301 LRESULT CMainFrame::OnFindDialogMessage(WPARAM /*wParam*/, LPARAM /*lParam*/)\r
1302 {\r
1303     ASSERT(m_pFindDialog != NULL);\r
1304 \r
1305     if (m_pFindDialog->IsTerminating())\r
1306     {\r
1307             // invalidate the handle identifying the dialog box.\r
1308         m_pFindDialog = NULL;\r
1309         return 0;\r
1310     }\r
1311 \r
1312     if(m_pFindDialog->FindNext())\r
1313     {\r
1314         //read data from dialog\r
1315         m_sFindText = m_pFindDialog->GetFindString();\r
1316         m_bMatchCase = (m_pFindDialog->MatchCase() == TRUE);\r
1317                 m_bLimitToDiff = m_pFindDialog->LimitToDiffs();\r
1318                 m_bWholeWord = m_pFindDialog->WholeWord();\r
1319         \r
1320                 OnEditFindnext();\r
1321     }\r
1322 \r
1323     return 0;\r
1324 }\r
1325 \r
1326 bool CharIsDelimiter(const CString& ch)\r
1327 {\r
1328         CString delimiters(_T(" .,:;=+-*/\\\n\t()[]<>@"));\r
1329         return delimiters.Find(ch) >= 0;\r
1330 }\r
1331 \r
1332 bool CMainFrame::StringFound(const CString& str)const\r
1333 {\r
1334         int nSubStringStartIdx = str.Find(m_sFindText);\r
1335         bool bStringFound = (nSubStringStartIdx >= 0);\r
1336         if (bStringFound && m_bWholeWord)\r
1337         {\r
1338                 if (nSubStringStartIdx)\r
1339                         bStringFound = CharIsDelimiter(str.Mid(nSubStringStartIdx-1,1));\r
1340                 \r
1341                 if (bStringFound)\r
1342                 {\r
1343                         int nEndIndex = nSubStringStartIdx + m_sFindText.GetLength();\r
1344                         if (str.GetLength() > nEndIndex)\r
1345                                 bStringFound = CharIsDelimiter(str.Mid(nEndIndex, 1));\r
1346                 }\r
1347         }\r
1348         return bStringFound;\r
1349 }\r
1350 \r
1351 void CMainFrame::OnEditFindprev()\r
1352 {\r
1353         Search(SearchPrevious);\r
1354 }\r
1355 \r
1356 void CMainFrame::OnEditFindnext()\r
1357 {\r
1358         Search(SearchNext);\r
1359 }\r
1360 \r
1361 void CMainFrame::Search(SearchDirection srchDir)\r
1362 {\r
1363         if (m_sFindText.IsEmpty())\r
1364                 return;\r
1365 \r
1366         if ((m_pwndLeftView)&&(m_pwndLeftView->m_pViewData))\r
1367         {\r
1368                 bool bFound = FALSE;\r
1369 \r
1370                 CString left;\r
1371                 CString right;\r
1372                 CString bottom;\r
1373                 DiffStates leftstate = DIFFSTATE_NORMAL;\r
1374                 DiffStates rightstate = DIFFSTATE_NORMAL;\r
1375                 DiffStates bottomstate = DIFFSTATE_NORMAL;\r
1376                 int i = 0;\r
1377                 \r
1378                 m_nSearchIndex = FindSearchStart(m_nSearchIndex);\r
1379                 m_nSearchIndex++;\r
1380                 if (m_nSearchIndex >= m_pwndLeftView->m_pViewData->GetCount())\r
1381                         m_nSearchIndex = 0;\r
1382                 if (srchDir == SearchPrevious)\r
1383                 {\r
1384                         // SearchIndex points 1 past where we found the last match, \r
1385                         // so if we are searching backwards we need to adjust accordingly\r
1386                         m_nSearchIndex -= 2;\r
1387                         // if at the top, start again from the end\r
1388                         if (m_nSearchIndex < 0)\r
1389                                 m_nSearchIndex += m_pwndLeftView->m_pViewData->GetCount();\r
1390                 }\r
1391                 const int idxLimits[2][2][2]={{{m_nSearchIndex, m_pwndLeftView->m_pViewData->GetCount()},\r
1392                                                                            {0, m_nSearchIndex}},\r
1393                                                                           {{m_nSearchIndex, -1},\r
1394                                                                            {m_pwndLeftView->m_pViewData->GetCount()-1, m_nSearchIndex}}};\r
1395                 const int offsets[2]={+1, -1};\r
1396                 \r
1397                 for (int j=0; j != 2 && !bFound; ++j)\r
1398                 {\r
1399                         for (i=idxLimits[srchDir][j][0]; i != idxLimits[srchDir][j][1]; i += offsets[srchDir])\r
1400                         {\r
1401                                 left = m_pwndLeftView->m_pViewData->GetLine(i);\r
1402                                 leftstate = m_pwndLeftView->m_pViewData->GetState(i);\r
1403                                 if ((!m_bOneWay)&&(m_pwndRightView->m_pViewData))\r
1404                                 {\r
1405                                         right = m_pwndRightView->m_pViewData->GetLine(i);\r
1406                                         rightstate = m_pwndRightView->m_pViewData->GetState(i);\r
1407                                 }\r
1408                                 if ((m_pwndBottomView)&&(m_pwndBottomView->m_pViewData))\r
1409                                 {\r
1410                                         bottom = m_pwndBottomView->m_pViewData->GetLine(i);\r
1411                                         bottomstate = m_pwndBottomView->m_pViewData->GetState(i);\r
1412                                 }\r
1413 \r
1414                                 if (!m_bMatchCase)\r
1415                                 {\r
1416                                         left = left.MakeLower();\r
1417                                         right = right.MakeLower();\r
1418                                         bottom = bottom.MakeLower();\r
1419                                         m_sFindText = m_sFindText.MakeLower();\r
1420                                 }\r
1421                                 if (StringFound(left))\r
1422                                 {\r
1423                                         if ((!m_bLimitToDiff)||(leftstate != DIFFSTATE_NORMAL))\r
1424                                         {\r
1425                                                 bFound = TRUE;\r
1426                                                 break;\r
1427                                         }\r
1428                                 } \r
1429                                 else if (StringFound(right))\r
1430                                 {\r
1431                                         if ((!m_bLimitToDiff)||(rightstate != DIFFSTATE_NORMAL))\r
1432                                         {\r
1433                                                 bFound = TRUE;\r
1434                                                 break;\r
1435                                         }\r
1436                                 } \r
1437                                 else if (StringFound(bottom))\r
1438                                 {\r
1439                                         if ((!m_bLimitToDiff)||(bottomstate != DIFFSTATE_NORMAL))\r
1440                                         {\r
1441                                                 bFound = TRUE;\r
1442                                                 break;\r
1443                                         }\r
1444                                 } \r
1445                         }\r
1446                 }\r
1447                 if (bFound)\r
1448                 {\r
1449                         m_nSearchIndex = i;\r
1450                         m_pwndLeftView->GoToLine(m_nSearchIndex);\r
1451                         if (StringFound(left))\r
1452                         {\r
1453                                 m_pwndLeftView->SetFocus();\r
1454                                 m_pwndLeftView->HiglightLines(m_nSearchIndex);\r
1455                         }\r
1456                         else if (StringFound(right))\r
1457                         {\r
1458                                 m_pwndRightView->SetFocus();\r
1459                                 m_pwndRightView->HiglightLines(m_nSearchIndex);\r
1460                         }\r
1461                         else if (StringFound(bottom))\r
1462                         {\r
1463                                 m_pwndBottomView->SetFocus();\r
1464                                 m_pwndBottomView->HiglightLines(m_nSearchIndex);\r
1465                         }\r
1466                 }\r
1467                 else\r
1468                 {\r
1469                         m_nSearchIndex = 0;\r
1470                 }\r
1471         }\r
1472 }\r
1473 \r
1474 int CMainFrame::FindSearchStart(int nDefault)\r
1475 {\r
1476         // TortoiseMerge doesn't have a cursor which we could use to\r
1477         // anchor the search on.\r
1478         // Instead we use a line that is selected.\r
1479         // If however no line is selected, use the default line (which could\r
1480         // be the top of the document for a new search, or the line where the\r
1481         // search was successful on)\r
1482         int nLine = nDefault;\r
1483         int nSelStart = 0;\r
1484         int nSelEnd = 0;\r
1485         if (m_pwndLeftView)\r
1486         {\r
1487                 if (m_pwndLeftView->GetSelection(nSelStart, nSelEnd))\r
1488                 {\r
1489                         if (nSelStart == nSelEnd)\r
1490                                 nLine = nSelStart;\r
1491                 }\r
1492         }\r
1493         else if ((nLine == nDefault)&&(m_pwndRightView))\r
1494         {\r
1495                 if (m_pwndRightView->GetSelection(nSelStart, nSelEnd))\r
1496                 {\r
1497                         if (nSelStart == nSelEnd)\r
1498                                 nLine = nSelStart;\r
1499                 }\r
1500         }\r
1501         else if ((nLine == nDefault)&&(m_pwndBottomView))\r
1502         {\r
1503                 if (m_pwndBottomView->GetSelection(nSelStart, nSelEnd))\r
1504                 {\r
1505                         if (nSelStart == nSelEnd)\r
1506                                 nLine = nSelStart;\r
1507                 }\r
1508         }\r
1509         return nLine;\r
1510 }\r
1511 \r
1512 void CMainFrame::OnViewLinedown()\r
1513 {\r
1514         if (m_pwndLeftView)\r
1515                 m_pwndLeftView->ScrollToLine(m_pwndLeftView->m_nTopLine+1);\r
1516         if (m_pwndRightView)\r
1517                 m_pwndRightView->ScrollToLine(m_pwndRightView->m_nTopLine+1);\r
1518         if (m_pwndBottomView)\r
1519                 m_pwndBottomView->ScrollToLine(m_pwndBottomView->m_nTopLine+1);\r
1520         m_wndLocatorBar.Invalidate();\r
1521 }\r
1522 \r
1523 void CMainFrame::OnViewLineup()\r
1524 {\r
1525         if (m_pwndLeftView)\r
1526                 m_pwndLeftView->ScrollToLine(m_pwndLeftView->m_nTopLine-1);\r
1527         if (m_pwndRightView)\r
1528                 m_pwndRightView->ScrollToLine(m_pwndRightView->m_nTopLine-1);\r
1529         if (m_pwndBottomView)\r
1530                 m_pwndBottomView->ScrollToLine(m_pwndBottomView->m_nTopLine-1);\r
1531         m_wndLocatorBar.Invalidate();\r
1532 }\r
1533 \r
1534 void CMainFrame::OnViewLineleft()\r
1535 {\r
1536         if (m_pwndLeftView)\r
1537                 m_pwndLeftView->ScrollSide(-1);\r
1538         if (m_pwndRightView)\r
1539                 m_pwndRightView->ScrollSide(-1);\r
1540         if (m_pwndBottomView)\r
1541                 m_pwndBottomView->ScrollSide(-1);\r
1542 }\r
1543 \r
1544 void CMainFrame::OnViewLineright()\r
1545 {\r
1546         if (m_pwndLeftView)\r
1547                 m_pwndLeftView->ScrollSide(1);\r
1548         if (m_pwndRightView)\r
1549                 m_pwndRightView->ScrollSide(1);\r
1550         if (m_pwndBottomView)\r
1551                 m_pwndBottomView->ScrollSide(1);\r
1552 }\r
1553 \r
1554 void CMainFrame::OnEditUseTheirs()\r
1555 {\r
1556         if (m_pwndBottomView)\r
1557                 m_pwndBottomView->UseTheirTextBlock();\r
1558 }\r
1559 void CMainFrame::OnUpdateEditUsetheirblock(CCmdUI *pCmdUI)\r
1560 {\r
1561         int nSelBlockStart = -1;\r
1562         int nSelBlockEnd = -1;\r
1563         if (m_pwndBottomView)\r
1564                 m_pwndBottomView->GetSelection(nSelBlockStart, nSelBlockEnd);\r
1565         pCmdUI->Enable((nSelBlockStart >= 0)&&(nSelBlockEnd >= 0));\r
1566 }\r
1567 \r
1568 \r
1569 void CMainFrame::OnEditUseMine()\r
1570 {\r
1571         if (m_pwndBottomView)\r
1572                 m_pwndBottomView->UseMyTextBlock();\r
1573 }\r
1574 void CMainFrame::OnUpdateEditUsemyblock(CCmdUI *pCmdUI)\r
1575 {\r
1576         int nSelBlockStart = -1;\r
1577         int nSelBlockEnd = -1;\r
1578         if (m_pwndBottomView)\r
1579                 m_pwndBottomView->GetSelection(nSelBlockStart, nSelBlockEnd);\r
1580         pCmdUI->Enable((nSelBlockStart >= 0)&&(nSelBlockEnd >= 0));\r
1581 }\r
1582 \r
1583 \r
1584 void CMainFrame::OnEditUseTheirsThenMine()\r
1585 {\r
1586         if (m_pwndBottomView)\r
1587                 m_pwndBottomView->UseTheirThenMyTextBlock();\r
1588 }\r
1589 void CMainFrame::OnUpdateEditUsetheirthenmyblock(CCmdUI *pCmdUI)\r
1590 {\r
1591         int nSelBlockStart = -1;\r
1592         int nSelBlockEnd = -1;\r
1593         if (m_pwndBottomView)\r
1594                 m_pwndBottomView->GetSelection(nSelBlockStart, nSelBlockEnd);\r
1595         pCmdUI->Enable((nSelBlockStart >= 0)&&(nSelBlockEnd >= 0));\r
1596 }\r
1597 \r
1598 \r
1599 void CMainFrame::OnEditUseMineThenTheirs()\r
1600 {\r
1601         if (m_pwndBottomView)\r
1602                 m_pwndBottomView->UseMyThenTheirTextBlock();\r
1603 }\r
1604 void CMainFrame::OnUpdateEditUseminethentheirblock(CCmdUI *pCmdUI)\r
1605 {\r
1606         int nSelBlockStart = -1;\r
1607         int nSelBlockEnd = -1;\r
1608         if (m_pwndBottomView)\r
1609                 m_pwndBottomView->GetSelection(nSelBlockStart, nSelBlockEnd);\r
1610         pCmdUI->Enable((nSelBlockStart >= 0)&&(nSelBlockEnd >= 0));\r
1611 }\r
1612 \r
1613 void CMainFrame::OnEditUseleftblock()\r
1614 {\r
1615         if (m_pwndRightView)\r
1616                 m_pwndRightView->UseBlock();\r
1617 }\r
1618 \r
1619 void CMainFrame::OnUpdateEditUseleftblock(CCmdUI *pCmdUI)\r
1620 {\r
1621         pCmdUI->Enable(m_pwndRightView && m_pwndRightView->IsWindowVisible() && m_pwndRightView->HasCaret() && m_pwndRightView->HasSelection());\r
1622 }\r
1623 \r
1624 void CMainFrame::OnEditUseleftfile()\r
1625 {\r
1626         if (m_pwndRightView)\r
1627                 m_pwndRightView->UseFile();\r
1628 }\r
1629 \r
1630 void CMainFrame::OnUpdateEditUseleftfile(CCmdUI *pCmdUI)\r
1631 {\r
1632         pCmdUI->Enable(m_pwndRightView && m_pwndRightView->IsWindowVisible() && m_pwndRightView->HasCaret());\r
1633 }\r
1634 \r
1635 void CMainFrame::OnEditUseblockfromleftbeforeright()\r
1636 {\r
1637         if (m_pwndRightView)\r
1638                 m_pwndRightView->UseLeftBeforeRight();\r
1639 }\r
1640 \r
1641 void CMainFrame::OnUpdateEditUseblockfromleftbeforeright(CCmdUI *pCmdUI)\r
1642 {\r
1643         pCmdUI->Enable(m_pwndRightView && m_pwndRightView->IsWindowVisible() && m_pwndRightView->HasCaret() && m_pwndRightView->HasSelection());\r
1644 }\r
1645 \r
1646 void CMainFrame::OnEditUseblockfromrightbeforeleft()\r
1647 {\r
1648         if (m_pwndRightView)\r
1649                 m_pwndRightView->UseRightBeforeLeft();\r
1650 }\r
1651 \r
1652 void CMainFrame::OnUpdateEditUseblockfromrightbeforeleft(CCmdUI *pCmdUI)\r
1653 {\r
1654         pCmdUI->Enable(m_pwndRightView && m_pwndRightView->IsWindowVisible() && m_pwndRightView->HasCaret() && m_pwndRightView->HasSelection());\r
1655 }\r
1656 \r
1657 \r
1658 void CMainFrame::OnFileReload()\r
1659 {\r
1660         if (CheckForSave()==IDCANCEL)\r
1661                 return;\r
1662         CDiffColors::GetInstance().LoadRegistry();\r
1663         LoadViews(true);\r
1664 }\r
1665 \r
1666 void CMainFrame::ActivateFrame(int nCmdShow)\r
1667 {\r
1668         // nCmdShow is the normal show mode this frame should be in\r
1669         // translate default nCmdShow (-1)\r
1670         if (nCmdShow == -1)\r
1671         {\r
1672                 if (!IsWindowVisible())\r
1673                         nCmdShow = SW_SHOWNORMAL;\r
1674                 else if (IsIconic())\r
1675                         nCmdShow = SW_RESTORE;\r
1676         }\r
1677 \r
1678         // bring to top before showing\r
1679         BringToTop(nCmdShow);\r
1680 \r
1681         if (nCmdShow != -1)\r
1682         {\r
1683                 // show the window as specified\r
1684                 WINDOWPLACEMENT wp;\r
1685 \r
1686                 if ( !ReadWindowPlacement(&wp) )\r
1687                 {\r
1688                         ShowWindow(nCmdShow);\r
1689                 }\r
1690                 else\r
1691                 {\r
1692                         if ( nCmdShow != SW_SHOWNORMAL )  \r
1693                                 wp.showCmd = nCmdShow;\r
1694 \r
1695                         SetWindowPlacement(&wp);\r
1696                 }\r
1697 \r
1698                 // and finally, bring to top after showing\r
1699                 BringToTop(nCmdShow);\r
1700         }\r
1701         return;\r
1702 }\r
1703 \r
1704 BOOL CMainFrame::ReadWindowPlacement(WINDOWPLACEMENT * pwp)\r
1705 {\r
1706         CRegString placement = CRegString(_T("Software\\TortoiseMerge\\WindowPos"));\r
1707         CString sPlacement = placement;\r
1708         if (sPlacement.IsEmpty())\r
1709                 return FALSE;\r
1710         int nRead = _stscanf_s(sPlacement, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),\r
1711                                 &pwp->flags, &pwp->showCmd,\r
1712                                 &pwp->ptMinPosition.x, &pwp->ptMinPosition.y,\r
1713                                 &pwp->ptMaxPosition.x, &pwp->ptMaxPosition.y,\r
1714                                 &pwp->rcNormalPosition.left,  &pwp->rcNormalPosition.top,\r
1715                                 &pwp->rcNormalPosition.right, &pwp->rcNormalPosition.bottom);\r
1716         if ( nRead != 10 )  \r
1717                 return FALSE;\r
1718         pwp->length = sizeof(WINDOWPLACEMENT);\r
1719 \r
1720         return TRUE;\r
1721 }\r
1722 \r
1723 void CMainFrame::WriteWindowPlacement(WINDOWPLACEMENT * pwp)\r
1724 {\r
1725         CRegString placement = CRegString(_T("Software\\TortoiseMerge\\WindowPos"));\r
1726         TCHAR szBuffer[sizeof("-32767")*8 + sizeof("65535")*2];\r
1727         CString s;\r
1728 \r
1729         _stprintf_s(szBuffer, sizeof("-32767")*8 + sizeof("65535")*2, _T("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d"),\r
1730                         pwp->flags, pwp->showCmd,\r
1731                         pwp->ptMinPosition.x, pwp->ptMinPosition.y,\r
1732                         pwp->ptMaxPosition.x, pwp->ptMaxPosition.y,\r
1733                         pwp->rcNormalPosition.left, pwp->rcNormalPosition.top,\r
1734                         pwp->rcNormalPosition.right, pwp->rcNormalPosition.bottom);\r
1735         placement = szBuffer;\r
1736 }\r
1737 \r
1738 void CMainFrame::OnUpdateMergeMarkasresolved(CCmdUI *pCmdUI)\r
1739 {\r
1740         if (pCmdUI == NULL)\r
1741                 return;\r
1742         BOOL bEnable = FALSE;\r
1743         if ((!m_bReadOnly)&&(m_Data.m_mergedFile.InUse()))\r
1744         {\r
1745                 if (m_pwndBottomView)\r
1746                 {\r
1747                         if ((m_pwndBottomView->IsWindowVisible())&&(m_pwndBottomView->m_pViewData))\r
1748                         {\r
1749                                 bEnable = TRUE;\r
1750                         } \r
1751                 }\r
1752         }\r
1753         pCmdUI->Enable(bEnable);\r
1754 }\r
1755 \r
1756 void CMainFrame::OnMergeMarkasresolved()\r
1757 {\r
1758         int nConflictLine = CheckResolved();\r
1759         if (nConflictLine >= 0)\r
1760         {\r
1761                 CString sTemp;\r
1762                 sTemp.Format(IDS_ERR_MAINFRAME_FILEHASCONFLICTS, m_pwndBottomView->m_pViewData->GetLineNumber(nConflictLine)+1);\r
1763                 if (MessageBox(sTemp, 0, MB_ICONERROR | MB_YESNO)!=IDYES)\r
1764                 {\r
1765                         if (m_pwndBottomView)\r
1766                                 m_pwndBottomView->GoToLine(nConflictLine);\r
1767                         return;\r
1768                 }\r
1769         }\r
1770         // now check if the file has already been saved and if not, save it.\r
1771         if (m_Data.m_mergedFile.InUse())\r
1772         {\r
1773                 if (m_pwndBottomView)\r
1774                 {\r
1775                         if ((m_pwndBottomView->IsWindowVisible())&&(m_pwndBottomView->m_pViewData))\r
1776                         {\r
1777                                 FileSave(false);\r
1778                         } \r
1779                 }\r
1780         }       \r
1781         MarkAsResolved();\r
1782 }\r
1783 \r
1784 BOOL CMainFrame::MarkAsResolved()\r
1785 {\r
1786         if (m_bReadOnly)\r
1787                 return FALSE;\r
1788         if ((m_pwndBottomView)&&(m_pwndBottomView->IsWindowVisible()))\r
1789         {\r
1790                 TCHAR buf[MAX_PATH*3];\r
1791                 GetModuleFileName(NULL, buf, MAX_PATH);\r
1792                 TCHAR * end = _tcsrchr(buf, '\\');\r
1793                 end++;\r
1794                 (*end) = 0;\r
1795                 _tcscat_s(buf, MAX_PATH*3, _T("TortoiseProc.exe /command:resolve /path:\""));\r
1796                 _tcscat_s(buf, MAX_PATH*3, m_Data.m_mergedFile.GetFilename());\r
1797                 _tcscat_s(buf, MAX_PATH*3, _T("\" /closeonend:1 /noquestion /skipcheck"));\r
1798                 STARTUPINFO startup;\r
1799                 PROCESS_INFORMATION process;\r
1800                 memset(&startup, 0, sizeof(startup));\r
1801                 startup.cb = sizeof(startup);\r
1802                 memset(&process, 0, sizeof(process));\r
1803                 if (CreateProcess(NULL, buf, NULL, NULL, FALSE, 0, 0, 0, &startup, &process)==0)\r
1804                 {\r
1805                         LPVOID lpMsgBuf;\r
1806                         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | \r
1807                                 FORMAT_MESSAGE_FROM_SYSTEM | \r
1808                                 FORMAT_MESSAGE_IGNORE_INSERTS,\r
1809                                 NULL,\r
1810                                 GetLastError(),\r
1811                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language\r
1812                                 (LPTSTR) &lpMsgBuf,\r
1813                                 0,\r
1814                                 NULL \r
1815                                 );\r
1816                         MessageBox((LPCTSTR)lpMsgBuf, _T("TortoiseMerge"), MB_OK | MB_ICONINFORMATION);\r
1817                         LocalFree( lpMsgBuf );\r
1818                         return FALSE;\r
1819                 }\r
1820                 CloseHandle(process.hThread);\r
1821                 CloseHandle(process.hProcess);\r
1822         }\r
1823         else\r
1824                 return FALSE;\r
1825         return TRUE;\r
1826 }\r
1827 \r
1828 void CMainFrame::OnUpdateMergeNextconflict(CCmdUI *pCmdUI)\r
1829 {\r
1830         pCmdUI->Enable(m_bHasConflicts);\r
1831 }\r
1832 \r
1833 void CMainFrame::OnUpdateMergePreviousconflict(CCmdUI *pCmdUI)\r
1834 {\r
1835         pCmdUI->Enable(m_bHasConflicts);\r
1836 }\r
1837 \r
1838 void CMainFrame::OnMoving(UINT fwSide, LPRECT pRect)\r
1839 {\r
1840         // if the pathfilelist dialog is attached to the mainframe,\r
1841         // move it along with the mainframe\r
1842         if (::IsWindow(m_dlgFilePatches.m_hWnd))\r
1843         {\r
1844                 RECT patchrect;\r
1845                 m_dlgFilePatches.GetWindowRect(&patchrect);\r
1846                 if (::IsWindow(m_hWnd))\r
1847                 {\r
1848                         RECT thisrect;\r
1849                         GetWindowRect(&thisrect);\r
1850                         if (patchrect.right == thisrect.left)\r
1851                         {\r
1852                                 m_dlgFilePatches.SetWindowPos(NULL, patchrect.left - (thisrect.left - pRect->left), patchrect.top - (thisrect.top - pRect->top), \r
1853                                         0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);\r
1854                         }\r
1855                 }\r
1856         }\r
1857         __super::OnMoving(fwSide, pRect);\r
1858 }\r
1859 \r
1860 void CMainFrame::OnUpdateEditCopy(CCmdUI *pCmdUI)\r
1861 {\r
1862         BOOL bShow = FALSE;\r
1863         if ((m_pwndBottomView)&&(m_pwndBottomView->HasSelection()))\r
1864                 bShow = TRUE;\r
1865         if ((m_pwndRightView)&&(m_pwndRightView->HasSelection()))\r
1866                 bShow = TRUE;\r
1867         if ((m_pwndLeftView)&&(m_pwndLeftView->HasSelection()))\r
1868                 bShow = TRUE;\r
1869         pCmdUI->Enable(bShow);\r
1870 }\r
1871 \r
1872 void CMainFrame::OnViewSwitchleft()\r
1873 {\r
1874         int ret = IDNO;\r
1875         if (((m_pwndBottomView)&&(m_pwndBottomView->IsModified())) ||\r
1876                 ((m_pwndRightView)&&(m_pwndRightView->IsModified())))\r
1877         {\r
1878                 CString sTemp;\r
1879                 sTemp.LoadString(IDS_ASKFORSAVE);\r
1880                 ret = MessageBox(sTemp, 0, MB_YESNOCANCEL | MB_ICONQUESTION);\r
1881                 if (ret == IDYES)\r
1882                 {\r
1883                         if (!FileSave())\r
1884                                 return;\r
1885                 }\r
1886         }\r
1887         if ((ret == IDNO)||(ret == IDYES))\r
1888         {\r
1889                 CWorkingFile file = m_Data.m_baseFile;\r
1890                 m_Data.m_baseFile = m_Data.m_yourFile;\r
1891                 m_Data.m_yourFile = file;\r
1892                 if (m_Data.m_mergedFile.GetFilename().CompareNoCase(m_Data.m_yourFile.GetFilename())==0)\r
1893                 {\r
1894                         m_Data.m_mergedFile = m_Data.m_baseFile;\r
1895                 }\r
1896                 else if (m_Data.m_mergedFile.GetFilename().CompareNoCase(m_Data.m_baseFile.GetFilename())==0)\r
1897                 {\r
1898                         m_Data.m_mergedFile = m_Data.m_yourFile;\r
1899                 }\r
1900                 LoadViews();\r
1901         }\r
1902 }\r
1903 \r
1904 void CMainFrame::OnUpdateViewSwitchleft(CCmdUI *pCmdUI)\r
1905 {\r
1906         BOOL bEnable = TRUE;\r
1907         if (m_pwndBottomView)\r
1908         {\r
1909                 if (m_pwndBottomView->IsWindowVisible())\r
1910                         bEnable = FALSE;\r
1911         }\r
1912         pCmdUI->Enable(bEnable);\r
1913 }\r
1914 \r
1915 \r
1916 void CMainFrame::OnUpdateViewShowfilelist(CCmdUI *pCmdUI)\r
1917 {\r
1918         if (m_dlgFilePatches.HasFiles())\r
1919         {\r
1920                 pCmdUI->Enable(true);\r
1921         }\r
1922         else\r
1923                 pCmdUI->Enable(false);\r
1924         pCmdUI->SetCheck(m_dlgFilePatches.IsWindowVisible());\r
1925 }\r
1926 \r
1927 void CMainFrame::OnViewShowfilelist()\r
1928 {\r
1929         m_dlgFilePatches.ShowWindow(m_dlgFilePatches.IsWindowVisible() ? SW_HIDE : SW_SHOW);\r
1930 }\r
1931 \r
1932 void CMainFrame::OnEditUndo()\r
1933 {\r
1934         if (CUndo::GetInstance().CanUndo())\r
1935         {\r
1936                 CUndo::GetInstance().Undo(m_pwndLeftView, m_pwndRightView, m_pwndBottomView);\r
1937 \r
1938         }\r
1939 }\r
1940 \r
1941 void CMainFrame::OnUpdateEditUndo(CCmdUI *pCmdUI)\r
1942 {\r
1943         pCmdUI->Enable(CUndo::GetInstance().CanUndo());\r
1944 }\r
1945 \r
1946 int CMainFrame::CheckForSave()\r
1947 {\r
1948         int ret = IDNO;\r
1949         if (((m_pwndBottomView)&&(m_pwndBottomView->IsModified())) ||\r
1950                 ((m_pwndRightView)&&(m_pwndRightView->IsModified())))\r
1951         {\r
1952                 CString sTemp;\r
1953                 sTemp.LoadString(IDS_WARNMODIFIEDLOOSECHANGES);\r
1954                 ret = MessageBox(sTemp, 0, MB_YESNOCANCEL | MB_ICONQUESTION);\r
1955 \r
1956                 if (ret == IDYES)\r
1957                 {\r
1958                         FileSave();\r
1959                 }\r
1960         }\r
1961         return ret;\r
1962 }\r
1963 \r
1964 void CMainFrame::OnViewInlinediffword()\r
1965 {\r
1966         m_bInlineWordDiff = !m_bInlineWordDiff;\r
1967         if (m_pwndLeftView)\r
1968         {\r
1969                 m_pwndLeftView->SetInlineWordDiff(m_bInlineWordDiff);\r
1970                 m_pwndLeftView->Invalidate();\r
1971         }\r
1972         if (m_pwndRightView)\r
1973         {\r
1974                 m_pwndRightView->SetInlineWordDiff(m_bInlineWordDiff);\r
1975                 m_pwndRightView->Invalidate();\r
1976         }\r
1977         if (m_pwndBottomView)\r
1978         {\r
1979                 m_pwndBottomView->SetInlineWordDiff(m_bInlineWordDiff);\r
1980                 m_pwndBottomView->Invalidate();\r
1981         }\r
1982         m_wndLineDiffBar.Invalidate();\r
1983 }\r
1984 \r
1985 void CMainFrame::OnUpdateViewInlinediffword(CCmdUI *pCmdUI)\r
1986 {\r
1987         pCmdUI->Enable(m_pwndLeftView && m_pwndLeftView->IsWindowVisible() &&\r
1988                 m_pwndRightView && m_pwndRightView->IsWindowVisible());\r
1989         pCmdUI->SetCheck(m_bInlineWordDiff);\r
1990 }\r
1991 \r
1992 void CMainFrame::OnUpdateEditCreateunifieddifffile(CCmdUI *pCmdUI)\r
1993 {\r
1994         // "create unified diff file" is only available if two files\r
1995         // are diffed, not three.\r
1996         bool bEnabled = true;\r
1997         if ((m_pwndLeftView == NULL)||(!m_pwndLeftView->IsWindowVisible()))\r
1998                 bEnabled = false;\r
1999         if ((m_pwndRightView == NULL)||(!m_pwndRightView->IsWindowVisible()))\r
2000                 bEnabled = false;\r
2001         if ((m_pwndBottomView)&&(m_pwndBottomView->IsWindowVisible()))\r
2002                 bEnabled = false;\r
2003         pCmdUI->Enable(bEnabled);\r
2004 }\r
2005 \r
2006 void CMainFrame::OnEditCreateunifieddifffile()\r
2007 {\r
2008         CString origFile, modifiedFile, outputFile;\r
2009         // the original file is the one on the left\r
2010         if (m_pwndLeftView)\r
2011                 origFile = m_pwndLeftView->m_sFullFilePath;\r
2012         if (m_pwndRightView)\r
2013                 modifiedFile = m_pwndRightView->m_sFullFilePath;\r
2014         if (!origFile.IsEmpty() && !modifiedFile.IsEmpty())\r
2015         {\r
2016                 // ask for the path to save the unified diff file to\r
2017                 OPENFILENAME ofn = {0};                 // common dialog box structure\r
2018                 TCHAR szFile[MAX_PATH] = {0};   // buffer for file name\r
2019                 ofn.lStructSize = sizeof(OPENFILENAME);\r
2020                 ofn.lpstrFile = szFile;\r
2021                 ofn.nMaxFile = sizeof(szFile)/sizeof(TCHAR);\r
2022                 CString temp;\r
2023                 temp.LoadString(IDS_SAVEASTITLE);\r
2024                 if (!temp.IsEmpty())\r
2025                         ofn.lpstrTitle = temp;\r
2026                 ofn.Flags = OFN_OVERWRITEPROMPT;\r
2027                 CString sFilter;\r
2028                 sFilter.LoadString(IDS_COMMONFILEFILTER);\r
2029                 TCHAR * pszFilters = new TCHAR[sFilter.GetLength()+4];\r
2030                 _tcscpy_s (pszFilters, sFilter.GetLength()+4, sFilter);\r
2031                 // Replace '|' delimiters with '\0's\r
2032                 TCHAR *ptr = pszFilters + _tcslen(pszFilters);  //set ptr at the NULL\r
2033                 while (ptr != pszFilters)\r
2034                 {\r
2035                         if (*ptr == '|')\r
2036                                 *ptr = '\0';\r
2037                         ptr--;\r
2038                 }\r
2039                 ofn.lpstrFilter = pszFilters;\r
2040                 ofn.nFilterIndex = 1;\r
2041 \r
2042                 // Display the Save dialog box. \r
2043                 CString sFile;\r
2044                 if (GetSaveFileName(&ofn)==TRUE)\r
2045                 {\r
2046                         outputFile = CString(ofn.lpstrFile);\r
2047                         CAppUtils::CreateUnifiedDiff(origFile, modifiedFile, outputFile, true);\r
2048                 }\r
2049                 delete [] pszFilters;\r
2050         }\r
2051 }\r
2052 \r
2053 void CMainFrame::OnUpdateViewLinediffbar(CCmdUI *pCmdUI)\r
2054 {\r
2055         pCmdUI->SetCheck(m_bLineDiff);\r
2056         pCmdUI->Enable();\r
2057 }\r
2058 \r
2059 void CMainFrame::OnViewLinediffbar()\r
2060 {\r
2061         m_bLineDiff = !m_bLineDiff;\r
2062         m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);\r
2063         m_wndLineDiffBar.DocumentUpdated();\r
2064         m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);\r
2065         m_wndLocatorBar.DocumentUpdated();\r
2066 }\r
2067 \r
2068 void CMainFrame::OnUpdateViewLocatorbar(CCmdUI *pCmdUI)\r
2069 {\r
2070         pCmdUI->SetCheck(m_bLocatorBar);\r
2071         pCmdUI->Enable();\r
2072 }\r
2073 \r
2074 void CMainFrame::OnViewLocatorbar()\r
2075 {\r
2076         m_bLocatorBar = !m_bLocatorBar;\r
2077         m_wndLocatorBar.ShowPane(m_bLocatorBar, false, true);\r
2078         m_wndLocatorBar.DocumentUpdated();\r
2079         m_wndLineDiffBar.ShowPane(m_bLineDiff, false, true);\r
2080         m_wndLineDiffBar.DocumentUpdated();\r
2081 }\r
2082 \r