1
// TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2017, 2019-2023 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 // PatchViewDlg.cpp : implementation file
23 #include "TortoiseProc.h"
24 #include "MessageBox.h"
25 #include "PatchViewDlg.h"
26 #include "CommonAppUtils.h"
27 #include "StringUtils.h"
29 #include "StagingOperations.h"
31 #include "EnableStagingTypes.h"
33 #pragma comment(lib, "Dwmapi.lib")
35 // CPatchViewDlg dialog
37 UINT
CPatchViewDlg::WM_PARTIALSTAGINGREFRESHPATCHVIEW
= RegisterWindowMessage(L
"TORTOISEGIT_COMMIT_PARTIALSTAGINGREFRESHPATCHVIEW"); // same string in CommitDlg.cpp!!!
39 IMPLEMENT_DYNAMIC(CPatchViewDlg
, CStandAloneDialog
)
41 #define SEARCHBARHEIGHT 30
43 CPatchViewDlg::CPatchViewDlg(CWnd
* pParent
/*=nullptr*/)
44 : CStandAloneDialog(CPatchViewDlg::IDD
, pParent
)
48 CPatchViewDlg::~CPatchViewDlg()
52 void CPatchViewDlg::DoDataExchange(CDataExchange
* pDX
)
54 CStandAloneDialog::DoDataExchange(pDX
);
55 DDX_Control(pDX
, IDC_PATCH
, m_ctrlPatchView
);
58 BEGIN_MESSAGE_MAP(CPatchViewDlg
, CStandAloneDialog
)
63 ON_COMMAND(IDM_SHOWFINDBAR
, OnShowFindBar
)
64 ON_COMMAND(IDM_FINDEXIT
, OnEscape
)
65 ON_COMMAND(IDM_FINDNEXT
, OnFindNext
)
66 ON_COMMAND(IDM_FINDPREV
, OnFindPrev
)
67 ON_COMMAND(ID_STAGING_STAGESELECTEDLINES
, OnStageLines
)
68 ON_COMMAND(ID_STAGING_STAGESELECTEDHUNKS
, OnStageHunks
)
69 ON_COMMAND(ID_UNSTAGING_UNSTAGESELECTEDLINES
, OnUnstageLines
)
70 ON_COMMAND(ID_UNSTAGING_UNSTAGESELECTEDHUNKS
, OnUnstageHunks
)
71 ON_REGISTERED_MESSAGE(CFindBar::WM_FINDEXIT
, OnFindExitMessage
)
72 ON_REGISTERED_MESSAGE(CFindBar::WM_FINDNEXT
, OnFindNextMessage
)
73 ON_REGISTERED_MESSAGE(CFindBar::WM_FINDPREV
, OnFindPrevMessage
)
74 ON_REGISTERED_MESSAGE(CFindBar::WM_FINDRESET
, OnFindResetMessage
)
77 // CPatchViewDlg message handlers
79 BOOL
CPatchViewDlg::OnInitDialog()
81 CStandAloneDialog::OnInitDialog();
83 auto hIcon
= LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_PATCH
));
85 SetIcon(hIcon
, FALSE
);
87 m_ctrlPatchView
.Init(-1);
89 m_ctrlPatchView
.SetUDiffStyle();
91 m_ctrlPatchView
.Call(SCI_SETSCROLLWIDTH
, 1);
92 m_ctrlPatchView
.Call(SCI_SETSCROLLWIDTHTRACKING
, TRUE
);
94 m_ctrlPatchView
.RegisterContextMenuHandler(this);
96 m_hAccel
= LoadAccelerators(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_ACC_PATCHVIEW
));
98 m_FindBar
.Create(IDD_FINDBAR
, this);
100 return TRUE
; // return TRUE unless you set the focus to a control
101 // EXCEPTION: OCX Property Pages should return FALSE
104 // This is intended to be called by the commit window when staging support is enabled there and
105 // we were invoked becaused the user clicked on "Partial Staging>>" or "Partial Unstaging>>".
106 // We assume the commit window will later on pass us the output of "git diff" (for staging) or
107 // "git diff --cached" (for unstaging), of one file only.
108 // If we were invoked from somewhere else (e.g. the File Diff Dialog), this will never be called
109 // and all staging menu items will stay disabled.
110 void CPatchViewDlg::EnableStaging(EnableStagingTypes enableStagingType
)
112 EnableMenuItem(GetMenu()->GetSafeHmenu(), ID_STAGING_STAGESELECTEDHUNKS
, enableStagingType
== EnableStagingTypes::Staging
? MF_ENABLED
: MF_DISABLED
);
113 EnableMenuItem(GetMenu()->GetSafeHmenu(), ID_STAGING_STAGESELECTEDLINES
, enableStagingType
== EnableStagingTypes::Staging
? MF_ENABLED
: MF_DISABLED
);
114 EnableMenuItem(GetMenu()->GetSafeHmenu(), ID_UNSTAGING_UNSTAGESELECTEDHUNKS
, enableStagingType
== EnableStagingTypes::Unstaging
? MF_ENABLED
: MF_DISABLED
);
115 EnableMenuItem(GetMenu()->GetSafeHmenu(), ID_UNSTAGING_UNSTAGESELECTEDLINES
, enableStagingType
== EnableStagingTypes::Unstaging
? MF_ENABLED
: MF_DISABLED
);
117 switch (enableStagingType
)
119 case EnableStagingTypes::None
:
120 SetWindowText(CString(MAKEINTRESOURCE(IDS_VIEWPATCH
)));
122 case EnableStagingTypes::Staging
:
123 SetWindowText(CString(MAKEINTRESOURCE(IDS_VIEWPATCH_INDEX_WORKTREE
)));
125 case EnableStagingTypes::Unstaging
:
126 SetWindowText(CString(MAKEINTRESOURCE(IDS_VIEWPATCH_HEAD_INDEX
)));
130 m_nEnableStagingType
= enableStagingType
; // This will be used to determine which context menu items to show
133 void CPatchViewDlg::SetText(const CString
& text
)
135 m_ctrlPatchView
.SetText(text
);
138 m_ctrlPatchView
.Call(SCI_GOTOPOS
, 0);
140 m_ctrlPatchView
.GetClientRect(rect
);
144 void CPatchViewDlg::ClearView()
149 static int GetBorderAjustment(HWND parentHWND
, const RECT
& parentRect
)
151 CRect recta
{ 0, 0, 0, 0 };
152 if (SUCCEEDED(::DwmGetWindowAttribute(parentHWND
, DWMWA_EXTENDED_FRAME_BOUNDS
, &recta
, sizeof(recta
))))
153 return 2 * (recta
.left
- parentRect
.left
) + 1;
158 void CPatchViewDlg::OnSize(UINT nType
, int cx
, int cy
)
160 CStandAloneDialog::OnSize(nType
, cx
, cy
);
162 if (this->IsWindowVisible())
166 GetDlgItem(IDC_PATCH
)->MoveWindow(0, 0, cx
, cy
);
170 ::SetWindowPos(m_ctrlPatchView
.GetSafeHwnd(), HWND_TOP
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
- CDPIAware::Instance().ScaleX(GetSafeHwnd(), SEARCHBARHEIGHT
), SWP_SHOWWINDOW
);
171 ::SetWindowPos(m_FindBar
.GetSafeHwnd(), HWND_TOP
, rect
.left
, rect
.bottom
- CDPIAware::Instance().ScaleX(GetSafeHwnd(), SEARCHBARHEIGHT
+ 2), rect
.right
- rect
.left
, CDPIAware::Instance().ScaleX(GetSafeHwnd(), SEARCHBARHEIGHT
), SWP_SHOWWINDOW
);
175 ::SetWindowPos(m_ctrlPatchView
.GetSafeHwnd(), HWND_TOP
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, SWP_SHOWWINDOW
);
176 m_FindBar
.ShowWindow(SW_HIDE
);
181 void CPatchViewDlg::OnMoving(UINT fwSide
, LPRECT pRect
)
185 m_ParentDlg
->GetPatchViewParentWnd()->GetWindowRect(&parentRect
);
187 const int adjust
= GetBorderAjustment(m_ParentDlg
->GetPatchViewParentWnd()->GetSafeHwnd(), parentRect
);
188 if (abs(parentRect
.right
- pRect
->left
- adjust
) < STICKYSIZE
)
190 const int width
= pRect
->right
- pRect
->left
;
191 pRect
->left
= parentRect
.right
- adjust
;
192 pRect
->right
= pRect
->left
+ width
;
194 CStandAloneDialog::OnMoving(fwSide
, pRect
);
197 void CPatchViewDlg::ParentOnMoving(HWND parentHWND
, LPRECT pRect
)
199 if (!::IsWindow(m_hWnd
))
202 if (!::IsWindow(parentHWND
))
206 GetWindowRect(&patchrect
);
209 ::GetWindowRect(parentHWND
, &parentRect
);
211 const int adjust
= GetBorderAjustment(parentHWND
, parentRect
);
212 if (patchrect
.left
== parentRect
.right
- adjust
)
213 SetWindowPos(nullptr, patchrect
.left
- (parentRect
.left
- pRect
->left
), patchrect
.top
- (parentRect
.top
- pRect
->top
), 0, 0, SWP_NOACTIVATE
| SWP_NOOWNERZORDER
| SWP_NOSIZE
| SWP_NOZORDER
);
216 void CPatchViewDlg::ParentOnSizing(HWND parentHWND
, LPRECT pRect
)
218 if (!::IsWindow(m_hWnd
))
221 if (!::IsWindow(parentHWND
))
225 GetWindowRect(&patchrect
);
228 ::GetWindowRect(parentHWND
, &parentRect
);
230 const int adjust
= GetBorderAjustment(parentHWND
, parentRect
);
231 if (patchrect
.left
!= parentRect
.right
- adjust
)
234 if (patchrect
.bottom
== parentRect
.bottom
)
235 patchrect
.bottom
-= (parentRect
.bottom
- pRect
->bottom
);
236 if (patchrect
.top
== parentRect
.top
)
237 patchrect
.top
-= parentRect
.top
- pRect
->top
;
239 SetWindowPos(nullptr, patchrect
.left
- (parentRect
.right
- pRect
->right
), patchrect
.top
- (parentRect
.top
- pRect
->top
), patchrect
.right
- patchrect
.left
, patchrect
.bottom
- patchrect
.top
, SWP_NOACTIVATE
| SWP_NOOWNERZORDER
| SWP_NOZORDER
);
242 void CPatchViewDlg::ShowAndAlignToParent()
245 m_ParentDlg
->GetPatchViewParentWnd()->GetWindowRect(&rect
);
246 int adjust
= GetBorderAjustment(m_ParentDlg
->GetPatchViewParentWnd()->GetSafeHwnd(), rect
);
247 rect
.left
= rect
.right
- adjust
;
248 rect
.right
= rect
.left
;
249 int xPos
= CDPIAware::Instance().ScaleX(GetSafeHwnd(), static_cast<DWORD
>(CRegDWORD(L
"Software\\TortoiseGit\\TortoiseProc\\ResizableState\\PatchDlgWidth")));
253 rect
.right
+= rect
.Width();
256 m_ParentDlg
->GetPatchViewParentWnd()->GetWindowPlacement(&wp
);
257 if (wp
.showCmd
!= SW_MAXIMIZE
)
258 SetWindowPos(nullptr, rect
.left
, rect
.top
, rect
.Width(), rect
.Height(), SWP_SHOWWINDOW
| SWP_NOACTIVATE
| SWP_NOOWNERZORDER
| SWP_NOZORDER
);
259 else if (auto monitor
= MonitorFromRect(rect
, MONITOR_DEFAULTTONULL
); !monitor
)
263 SetWindowPos(nullptr, 0, 0, xPos
? xPos
: pos
.Width(), pos
.Height(), SWP_SHOWWINDOW
| SWP_NOACTIVATE
| SWP_NOOWNERZORDER
| SWP_NOZORDER
| SWP_NOMOVE
);
267 MONITORINFO monitorinfo
;
268 monitorinfo
.cbSize
= sizeof(MONITORINFO
);
269 GetMonitorInfo(monitor
, &monitorinfo
);
270 SetWindowPos(nullptr, monitorinfo
.rcWork
.left
, monitorinfo
.rcWork
.top
, min(rect
.Width(), static_cast<int>(monitorinfo
.rcWork
.right
- monitorinfo
.rcWork
.left
)), min(rect
.Height(), static_cast<int>(monitorinfo
.rcWork
.bottom
- monitorinfo
.rcWork
.top
)), SWP_SHOWWINDOW
| SWP_NOACTIVATE
| SWP_NOOWNERZORDER
| SWP_NOZORDER
);
274 void CPatchViewDlg::OnClose()
276 CStandAloneDialog::OnClose();
277 m_ParentDlg
->TogglePatchView();
280 BOOL
CPatchViewDlg::PreTranslateMessage(MSG
* pMsg
)
284 if (TranslateAccelerator(m_hWnd
, m_hAccel
, pMsg
))
287 return __super::PreTranslateMessage(pMsg
);
290 void CPatchViewDlg::OnEscape()
292 if (::IsWindowVisible(m_FindBar
))
297 SendMessage(WM_CLOSE
);
300 void CPatchViewDlg::OnShowFindBar()
302 m_bShowFindBar
= true;
304 GetClientRect(&rect
);
305 ::SetWindowPos(m_ctrlPatchView
.GetSafeHwnd(), HWND_TOP
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
- CDPIAware::Instance().ScaleX(GetSafeHwnd(), SEARCHBARHEIGHT
), SWP_SHOWWINDOW
);
306 ::SetWindowPos(m_FindBar
, HWND_TOP
, rect
.left
, rect
.bottom
- CDPIAware::Instance().ScaleX(GetSafeHwnd(), SEARCHBARHEIGHT
+ 2), rect
.right
- rect
.left
, CDPIAware::Instance().ScaleX(GetSafeHwnd(), SEARCHBARHEIGHT
), SWP_SHOWWINDOW
);
307 if (auto selstart
= static_cast<Sci_Position
>(m_ctrlPatchView
.Call(SCI_GETSELECTIONSTART
)), selend
= static_cast<Sci_Position
>(m_ctrlPatchView
.Call(SCI_GETSELECTIONEND
)); selstart
!= selend
&& selend
- selstart
< INT_MAX
)
310 Sci_TextRangeFull range
= { selstart
, selend
, selText
.GetBuffer(SafeSizeToInt(selend
- selstart
)) };
311 selText
.ReleaseBufferSetLength(SafeSizeToInt(m_ctrlPatchView
.Call(SCI_GETTEXTRANGEFULL
, 0, reinterpret_cast<LPARAM
>(&range
))));
312 if (!selText
.IsEmpty())
313 m_FindBar
.SetFindText(m_ctrlPatchView
.StringFromControl(selText
));
315 m_FindBar
.SetFocusTextBox();
318 void CPatchViewDlg::OnFindNext()
320 if (m_FindBar
.GetFindText().IsEmpty())
328 void CPatchViewDlg::DoSearch(bool reverse
)
330 Sci_Position lastcursor
= m_ctrlPatchView
.Call(SCI_GETSELECTIONEND
);
332 m_ctrlPatchView
.Call(SCI_SETTARGETRANGE
, lastcursor
, m_ctrlPatchView
.Call(SCI_GETLENGTH
));
335 lastcursor
= m_ctrlPatchView
.Call(SCI_GETSELECTIONSTART
);
336 m_ctrlPatchView
.Call(SCI_SETTARGETRANGE
, lastcursor
, 0);
339 auto searchText
= CUnicodeUtils::GetUTF8(m_FindBar
.GetFindText());
340 m_ctrlPatchView
.Call(SCI_SETSEARCHFLAGS
, m_FindBar
.IsMatchCase() ? SCFIND_MATCHCASE
: SCFIND_NONE
);
341 if (auto pos
= m_ctrlPatchView
.Call(SCI_SEARCHINTARGET
, searchText
.GetLength(), reinterpret_cast<LPARAM
>(static_cast<LPCSTR
>(searchText
))); pos
>= 0)
343 m_ctrlPatchView
.Call(SCI_SETSELECTION
, pos
, pos
+ searchText
.GetLength());
344 m_ctrlPatchView
.Call(SCI_SCROLLCARET
);
348 m_ctrlPatchView
.Call(SCI_SETSELECTION
, lastcursor
, lastcursor
);
349 FlashWindowEx(FLASHW_ALL
, 3, 100);
353 void CPatchViewDlg::OnFindPrev()
355 if (m_FindBar
.GetFindText().IsEmpty())
363 void CPatchViewDlg::OnFindExit()
365 if (!::IsWindowVisible(m_FindBar
))
369 GetClientRect(&rect
);
370 m_bShowFindBar
= false;
371 m_FindBar
.ShowWindow(SW_HIDE
);
372 ::SetWindowPos(m_ctrlPatchView
.GetSafeHwnd(), HWND_TOP
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, SWP_SHOWWINDOW
);
373 m_ctrlPatchView
.SetFocus();
376 void CPatchViewDlg::OnFindReset()
378 m_ctrlPatchView
.Call(SCI_SETSELECTIONSTART
, 0);
379 m_ctrlPatchView
.Call(SCI_SETSELECTIONEND
, 0);
382 LRESULT
CPatchViewDlg::OnFindNextMessage(WPARAM
, LPARAM
)
388 LRESULT
CPatchViewDlg::OnFindPrevMessage(WPARAM
, LPARAM
)
394 LRESULT
CPatchViewDlg::OnFindExitMessage(WPARAM
, LPARAM
)
400 LRESULT
CPatchViewDlg::OnFindResetMessage(WPARAM
, LPARAM
)
406 void CPatchViewDlg::OnStageHunks()
408 StageOrUnstageSelectedLinesOrHunks(StagingType::StageHunks
);
411 void CPatchViewDlg::OnStageLines()
413 StageOrUnstageSelectedLinesOrHunks(StagingType::StageLines
);
416 void CPatchViewDlg::OnUnstageHunks()
418 StageOrUnstageSelectedLinesOrHunks(StagingType::UnstageHunks
);
421 void CPatchViewDlg::OnUnstageLines()
423 StageOrUnstageSelectedLinesOrHunks(StagingType::UnstageLines
);
426 int CPatchViewDlg::GetFirstLineNumberSelected()
428 auto selstart
= m_ctrlPatchView
.Call(SCI_GETSELECTIONSTART
);
429 return static_cast<int>(m_ctrlPatchView
.Call(SCI_LINEFROMPOSITION
, selstart
));
432 int CPatchViewDlg::GetLastLineNumberSelected()
434 auto selend
= m_ctrlPatchView
.Call(SCI_GETSELECTIONEND
);
435 return static_cast<int>(m_ctrlPatchView
.Call(SCI_LINEFROMPOSITION
, selend
));
438 void CPatchViewDlg::StageOrUnstageSelectedLinesOrHunks(StagingType stagingType
)
440 auto documentLength
= static_cast<Sci_Position
>(m_ctrlPatchView
.Call(SCI_GETLENGTH
));
441 auto wholePatchBuf
= std::make_unique
<char[]>(documentLength
+ 1);
442 m_ctrlPatchView
.Call(SCI_GETTEXT
, documentLength
+ 1, reinterpret_cast<LPARAM
>(wholePatchBuf
.get()));
444 int lineCount
= static_cast<int>(m_ctrlPatchView
.Call(SCI_GETLINECOUNT
));
446 CDiffLinesForStaging
lines(wholePatchBuf
.get(), lineCount
, GetFirstLineNumberSelected(), GetLastLineNumberSelected());
447 auto op
= StagingOperations(&lines
);
448 std::string strPatch
;
449 if (stagingType
== StagingType::StageLines
|| stagingType
== StagingType::UnstageLines
)
450 strPatch
= op
.CreatePatchBufferToStageOrUnstageSelectedLines(stagingType
);
451 else if (stagingType
== StagingType::StageHunks
|| stagingType
== StagingType::UnstageHunks
)
452 strPatch
= op
.CreatePatchBufferToStageOrUnstageSelectedHunks();
454 return; // this should never happen
455 if (strPatch
.empty())
457 CMessageBox::Show(GetSafeHwnd(), IDS_ERROR_PARTIALSTAGING
, IDS_APPNAME
, MB_OK
| MB_ICONERROR
);
461 CTGitPath::StagingStatus newStatus
; // this will be sent to the commit dialog so that it can update the file checkbox/status
462 if (strcmp(wholePatchBuf
.get(), strPatch
.c_str()) == 0)
464 if (stagingType
== StagingType::StageLines
|| stagingType
== StagingType::StageHunks
)
465 newStatus
= CTGitPath::StagingStatus::TotallyStaged
;
466 else // stagingType == StagingType::UnstageLines || stagingType == StagingType::UnstageHunks
467 newStatus
= CTGitPath::StagingStatus::TotallyUnstaged
;
469 else // if the patch to be applied is different than the whole diff, the file is still partially staged or became partially staged
470 newStatus
= CTGitPath::StagingStatus::PartiallyStaged
;
472 CString tempPatch
= StagingOperations::WritePatchBufferToTemporaryFile(strPatch
);
473 if (tempPatch
.IsEmpty())
478 if (stagingType
== StagingType::StageHunks
|| stagingType
== StagingType::StageLines
)
479 ret
= g_Git
.ApplyPatchToIndex(tempPatch
, &out
);
480 else //if (stagingType == StagingType::UnstageHunks || stagingType == StagingType::UnstageLines)
481 ret
= g_Git
.ApplyPatchToIndexReverse(tempPatch
, &out
);
484 MessageBox(out
, L
"TortoiseGit", MB_OK
| MB_ICONERROR
);
488 // Tell the commit window we partially staged a file and ask it to update ourselves with the updated diff
489 m_ParentDlg
->GetPatchViewParentWnd()->SendMessage(WM_PARTIALSTAGINGREFRESHPATCHVIEW
, static_cast<WPARAM
>(newStatus
));
492 void CPatchViewDlg::OnDestroy()
494 __super::OnDestroy();
496 GetWindowRect(&rect
);
497 CRegStdDWORD(L
"Software\\TortoiseGit\\TortoiseProc\\ResizableState\\PatchDlgWidth") = CDPIAware::Instance().UnscaleX(GetSafeHwnd(), rect
.Width());
498 m_ctrlPatchView
.ClearContextMenuHandlers();
501 // CSciEditContextMenuInterface
502 void CPatchViewDlg::InsertMenuItems(CMenu
& mPopup
, int& nCmd
)
504 CString sMenuItemText
;
505 sMenuItemText
.LoadString(IDS_REPOBROWSE_SAVEAS
);
506 m_nPopupSave
= nCmd
++;
507 mPopup
.AppendMenu(MF_STRING
| MF_ENABLED
, m_nPopupSave
, sMenuItemText
);
508 // We need to reset those to 0:
513 if (m_nEnableStagingType
== EnableStagingTypes::Staging
|| m_nEnableStagingType
== EnableStagingTypes::Unstaging
)
514 mPopup
.AppendMenu(MF_SEPARATOR
);
515 if (m_nEnableStagingType
== EnableStagingTypes::Staging
)
517 sMenuItemText
.LoadString(IDS_PROC_STAGE_SELECTED_HUNKS
);
518 m_nStageHunks
= nCmd
++;
519 mPopup
.AppendMenu(MF_STRING
| MF_ENABLED
, m_nStageHunks
, sMenuItemText
);
521 sMenuItemText
.LoadString(IDS_PROC_STAGE_SELECTED_LINES
);
522 m_nStageLines
= nCmd
++;
523 mPopup
.AppendMenu(MF_STRING
| MF_ENABLED
, m_nStageLines
, sMenuItemText
);
525 if (m_nEnableStagingType
== EnableStagingTypes::Unstaging
)
527 sMenuItemText
.LoadString(IDS_PROC_UNSTAGE_SELECTED_HUNKS
);
528 m_nUnstageHunks
= nCmd
++;
529 mPopup
.AppendMenu(MF_STRING
| MF_ENABLED
, m_nUnstageHunks
, sMenuItemText
);
531 sMenuItemText
.LoadString(IDS_PROC_UNSTAGE_SELECTED_LINES
);
532 m_nUnstageLines
= nCmd
++;
533 mPopup
.AppendMenu(MF_STRING
| MF_ENABLED
, m_nUnstageLines
, sMenuItemText
);
537 bool CPatchViewDlg::HandleMenuItemClick(int cmd
, CSciEdit
*)
539 if (cmd
== m_nPopupSave
)
542 if (CCommonAppUtils::FileOpenSave(filename
, nullptr, 0, IDS_PATCHFILEFILTER
, false, GetSafeHwnd(), L
"diff"))
543 CStringUtils::WriteStringToTextFile(filename
, m_ctrlPatchView
.GetText());
546 else if (cmd
== m_nStageHunks
)
551 else if (cmd
== m_nStageLines
)
556 else if (cmd
== m_nUnstageHunks
)
561 else if (cmd
== m_nUnstageLines
)