OSDN Git Service

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