1
// TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2018 - 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 // GitLogList.cpp : implementation file
24 #include "ResizableColumnsListCtrl.h"
26 #include "ProjectProperties.h"
30 #include "LogDlgHelper.h"
31 #include "GitRevLoglist.h"
33 #include "GitLogCache.h"
35 #include "GitStatusListCtrl.h"
37 #include <unordered_set>
39 template < typename Cont
, typename Pred
>
40 void for_each(Cont
& c
, Pred
&& p
)
42 std::for_each(cbegin(c
), cend(c
), p
);
45 template <typename Cont
, typename Pred
>
46 auto find_if(Cont
& c
, Pred
&& p
)
48 return std::find_if(cbegin(c
), cend(c
), p
);
52 #define ICONITEMBORDER 5
54 #define GITLOG_START 0
55 #define GITLOG_START_ALL 1
56 #define GITLOG_END 100
58 #define LOGFILTER_ALL 0xFFFF
59 #define LOGFILTER_TOGGLE 0x8000
60 #define LOGFILTER_MESSAGES 0x0001
61 #define LOGFILTER_PATHS 0x0002
62 #define LOGFILTER_AUTHORS 0x0004
63 #define LOGFILTER_REVS 0x0008
64 #define LOGFILTER_REGEX 0x0010
65 #define LOGFILTER_BUGID 0x0020
66 #define LOGFILTER_SUBJECT 0x0040
67 #define LOGFILTER_REFNAME 0x0080
68 #define LOGFILTER_EMAILS 0x0100
69 #define LOGFILTER_NOTES 0x0200
70 #define LOGFILTER_ANNOTATEDTAG 0x0400
71 #define LOGFILTER_CASE 0x0800
73 #define LOGLIST_SHOWNOTHING 0x0000
74 #define LOGLIST_SHOWLOCALBRANCHES 0x0001
75 #define LOGLIST_SHOWREMOTEBRANCHES 0x0002
76 #define LOGLIST_SHOWTAGS 0x0004
77 #define LOGLIST_SHOWSTASH 0x0008
78 #define LOGLIST_SHOWBISECT 0x0010
79 #define LOGLIST_SHOWOTHERREFS 0x0020
80 #define LOGLIST_SHOWALLREFS 0xFFFF
82 //typedef void CALLBACK_PROCESS(void * data, int progress);
83 #define MSG_LOADED (WM_USER+110)
84 #define MSG_LOAD_PERCENTAGE (WM_USER+111)
85 #define MSG_REFLOG_CHANGED (WM_USER+112)
86 #define MSG_FETCHED_DIFF (WM_USER+113)
87 #define MSG_COMMITS_REORDERED (WM_USER+114)
89 class SelectionHistory
91 #define HISTORYLENGTH 50
93 SelectionHistory(void)
96 lastselected
.reserve(HISTORYLENGTH
);
98 void Add(CGitHash
&hash
)
103 size_t size
= lastselected
.size();
105 // re-select last selected commit
106 if (size
> 0 && hash
== lastselected
[size
- 1])
109 if (location
!= size
- 1)
114 // go back and some commit was highlight
115 if (size
> 0 && location
!= size
- 1)
117 // Re-select current one, it may be a forked point.
118 if (hash
== lastselected
[location
])
120 // That is that discarding forward history when a forked entry is really coming.
121 // And user has the chance to Go Forward again in this situation.
122 // IOW, (hash != lastselected[location]) means user wants a forked history,
123 // and this change saves one step from old behavior.
126 // Discard forward history if any
127 while (lastselected
.size() - 1 > location
)
128 lastselected
.pop_back();
131 if (lastselected
.size() >= HISTORYLENGTH
)
132 lastselected
.erase(lastselected
.cbegin());
134 lastselected
.push_back(hash
);
135 location
= lastselected
.size() - 1;
137 BOOL
GoBack(CGitHash
& historyEntry
)
142 historyEntry
= lastselected
[--location
];
146 BOOL
GoForward(CGitHash
& historyEntry
)
148 if (location
>= lastselected
.size() - 1)
151 historyEntry
= lastselected
[++location
];
156 std::vector
<CGitHash
> lastselected
;
160 class CThreadSafePtrArray
: public std::vector
<GitRevLoglist
*>
162 typedef CComCritSecLock
<CComCriticalSection
> Locker
;
163 CComCriticalSection
*m_critSec
;
165 CThreadSafePtrArray(CComCriticalSection
* section
) : m_critSec(section
)
167 ATLASSERT(m_critSec
);
170 GitRevLoglist
* SafeGetAt(size_t i
)
172 Locker
lock(*m_critSec
);
179 void SafeAdd(GitRevLoglist
* newElement
)
181 Locker
lock(*m_critSec
);
182 push_back(newElement
);
185 void SafeRemoveAt(size_t i
)
187 Locker
lock(*m_critSec
);
194 void SafeAddFront(GitRevLoglist
* newElement
)
196 Locker
lock(*m_critSec
);
197 insert(cbegin(), newElement
);
202 Locker
lock(*m_critSec
);
211 class CGitLogListBase
: public CHintCtrl
<CResizableColumnsListCtrl
<CListCtrl
>>, public IAsyncDiffCB
213 DECLARE_DYNAMIC(CGitLogListBase
)
217 virtual ~CGitLogListBase();
218 ProjectProperties m_ProjectProperties
;
220 void UpdateProjectProperties()
222 m_ProjectProperties
.ReadProps();
224 if ((!m_ProjectProperties
.sUrl
.IsEmpty())||(!m_ProjectProperties
.sCheckRe
.IsEmpty()))
225 m_bShowBugtraqColumn
= true;
227 m_bShowBugtraqColumn
= false;
230 void ResetWcRev(bool refresh
= false)
234 CWnd
* pParent
= GetParent();
235 if (pParent
&& pParent
->GetSafeHwnd())
236 pParent
->SendMessage(LOGLIST_RESET_WCREV
);
239 m_wcRev
.GetSubject().LoadString(IDS_LOG_WORKINGDIRCHANGES
);
240 m_wcRev
.m_Mark
= L
'-';
241 m_wcRev
.GetBody().LoadString(IDS_LOG_FETCHINGSTATUS
);
242 m_wcRev
.GetBody() = L
'\n' + m_wcRev
.GetBody();
243 m_wcRev
.m_CallDiffAsync
= DiffAsync
;
244 InterlockedExchange(&m_wcRev
.m_IsDiffFiles
, FALSE
);
245 if (refresh
&& m_bShowWC
)
246 m_arShownList
[0] = &m_wcRev
;
249 volatile LONG m_bNoDispUpdates
;
250 BOOL m_IsIDReplaceAction
;
253 void hideFromContextMenu(unsigned __int64 hideMask
, bool exclusivelyShow
);
255 BOOL m_IsRebaseReplaceGraph
;
256 BOOL m_bNoHightlightHead
;
259 void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct
);
262 BOOL m_bShowBugtraqColumn
;
266 bool m_bIsCherryPick
;
267 unsigned __int64 m_ContextMenuMask
;
272 GitRevLoglist m_wcRev
;
274 volatile LONG m_bThreadRunning
;
276 CLogCache m_LogCache
;
280 // don't forget to bump BLAME_COLUMN_VERSION in GitStatusListCtrlHelpers.cpp if you change columns
293 LOGLIST_COMMIT_EMAIL
,
297 LOGLIST_MESSAGE_MAX
=300,
298 LOGLIST_MESSAGE_MIN
=200,
300 GIT_LOG_GRAPH
= 1<< LOGLIST_GRAPH
,
301 GIT_LOG_REBASE
= 1<< LOGLIST_REBASE
,
302 GIT_LOG_ID
= 1<< LOGLIST_ID
,
303 GIT_LOG_HASH
= 1<< LOGLIST_HASH
,
304 GIT_LOG_ACTIONS
= 1<< LOGLIST_ACTION
,
305 GIT_LOG_MESSAGE
= 1<< LOGLIST_MESSAGE
,
306 GIT_LOG_AUTHOR
= 1<< LOGLIST_AUTHOR
,
307 GIT_LOG_DATE
= 1<< LOGLIST_DATE
,
308 GIT_LOG_EMAIL
= 1<< LOGLIST_EMAIL
,
309 GIT_LOG_COMMIT_NAME
= 1<< LOGLIST_COMMIT_NAME
,
310 GIT_LOG_COMMIT_EMAIL
= 1<< LOGLIST_COMMIT_EMAIL
,
311 GIT_LOG_COMMIT_DATE
= 1<< LOGLIST_COMMIT_DATE
,
312 GIT_LOGLIST_BUG
= 1<< LOGLIST_BUG
,
313 GIT_LOGLIST_SVNREV
= 1<< LOGLIST_SVNREV
,
318 // needs to start with 1, since 0 is the return value if *nothing* is clicked on in the context menu
319 ID_COMPARE
= 1, // compare revision with WC
321 ID_COMPARETWO
, // compare two revisions
324 ID_GNUDIFF1
, // compare with WC, unified
325 ID_GNUDIFF2
, // compare two revisions, unified
341 ID_COMPAREWITHPREVIOUS
,
357 ID_REFLOG_STASH_APPLY
,
359 ID_REBASE_TO_VERSION
,
369 ID_LOG_VIEWRANGE_REACHABLEFROMONLYONE
,
378 ID_COMPARETWOCOMMITCHANGES
,
379 // the following can be >= 64 as those are not used for GetContextMenuBit(), all others must be < 64 in order to fit into __int64
380 ID_COPYCLIPBOARDFULL
,
381 ID_COPYCLIPBOARDFULLNOPATHS
,
382 ID_COPYCLIPBOARDHASH
,
383 ID_COPYCLIPBOARDAUTHORSFULL
,
384 ID_COPYCLIPBOARDAUTHORSNAME
,
385 ID_COPYCLIPBOARDAUTHORSEMAIL
,
386 ID_COPYCLIPBOARDSUBJECTS
,
387 ID_COPYCLIPBOARDMESSAGES
,
388 ID_COPYCLIPBOARDBRANCHTAG
,
393 FILTERSHOW_MERGEPOINTS
= 2,
394 FILTERSHOW_ANYCOMMIT
= 4,
395 FILTERSHOW_ALL
= FILTERSHOW_ANYCOMMIT
| FILTERSHOW_REFS
| FILTERSHOW_MERGEPOINTS
400 LOGACTIONS_REBASE_CURRENT
= 0x08000000,
401 LOGACTIONS_REBASE_PICK
= 0x04000000,
402 LOGACTIONS_REBASE_SQUASH
= 0x02000000,
403 LOGACTIONS_REBASE_EDIT
= 0x01000000,
404 LOGACTIONS_REBASE_DONE
= 0x00800000,
405 LOGACTIONS_REBASE_SKIP
= 0x00400000,
406 LOGACTIONS_REBASE_MASK
= 0x0FC00000,
407 LOGACTIONS_REBASE_MODE_MASK
= 0x07C00000,
409 static_assert(ID_COMPARETWOCOMMITCHANGES
< 64 && ID_COPYCLIPBOARDFULL
<= 64, "IDs must be <64 in order to be usable in a bitfield");
410 static inline unsigned __int64
GetContextMenuBit(int i
){ return ((unsigned __int64
)0x1)<<i
;}
411 static CString
GetRebaseActionName(int action
);
412 void InsertGitColumn();
413 void CopySelectionToClipBoard(int toCopy
= ID_COPYCLIPBOARDFULL
);
414 void DiffSelectedRevWithPrevious();
415 bool IsSelectionContinuous();
418 HWND
GetParentHWND();
420 int FillGitLog(CTGitPath
* path
, CString
* range
= nullptr, int infomask
= CGit::LOG_INFO_STAT
| CGit::LOG_INFO_FILESTATE
| CGit::LOG_INFO_SHOW_MERGEDFILE
);
421 int FillGitLog(std::unordered_set
<CGitHash
>& hashes
);
423 CString
MessageDisplayStr(GitRev
* pLogEntry
);
424 BOOL
IsMatchFilter(bool bRegex
, GitRevLoglist
* pRev
, std::wregex
& pat
);
425 bool ShouldShowFilter(GitRevLoglist
* pRev
, const std::unordered_map
<CGitHash
, std::unordered_set
<CGitHash
>>& commitChildren
);
427 void ShowGraphColumn(bool bShow
);
428 CString
GetTagInfo(GitRev
* pLogEntry
);
430 CFindDlg
*m_pFindDialog
;
431 static const UINT m_FindDialogMessage
;
435 static const UINT m_ScrollToMessage
;
437 static const UINT m_ScrollToRef
;
438 static const UINT m_RebaseActionMessage
;
439 static const UINT LOGLIST_RESET_WCREV
;
441 void FetchLogAsync(void* data
= nullptr);
442 CThreadSafePtrArray m_arShownList
;
443 void Refresh(BOOL IsCleanFilter
=TRUE
);
446 DWORD m_SelectedFilters
;
447 FilterShow m_ShowFilter
;
448 bool m_bFilterWithRegex
;
449 bool m_bFilterCaseSensitively
;
450 CLogDataVector m_logEntries
;
451 bool ValidateRegexp(LPCTSTR regexp_str
, std::wregex
& pat
, bool bMatchCase
= false );
452 CString m_sFilterText
;
454 CFilterData m_Filter
;
458 CGitHash m_lastSelectedHash
;
459 SelectionHistory m_selectionHistory
;
460 CGitHash m_highlight
;
464 CGitHash m_superProjectHash
;
467 void GetTimeRange(CTime
&oldest
,CTime
&latest
);
469 virtual void GetParentHashes(GitRev
* pRev
, GIT_REV_LIST
& parentHash
);
470 virtual void ContextMenuAction(int cmd
,int FirstSelect
, int LastSelect
, CMenu
* menu
)=0;
471 void UpdateSubmodulePointer()
473 m_superProjectHash
.Empty();
474 if (CRegDWORD(L
"Software\\TortoiseGit\\LogShowSuperProjectSubmodulePointer", TRUE
) != TRUE
)
476 if (GitAdminDir::IsBareRepo(g_Git
.m_CurrentDir
))
478 CString superprojectRoot
;
479 GitAdminDir::HasAdminDir(g_Git
.m_CurrentDir
, false, &superprojectRoot
);
480 if (superprojectRoot
.IsEmpty())
483 CAutoRepository
repo(superprojectRoot
);
487 if (git_repository_index(index
.GetPointer(), repo
))
490 CString submodulePath
;
491 if (superprojectRoot
[superprojectRoot
.GetLength() - 1] == L
'\\')
492 submodulePath
= g_Git
.m_CurrentDir
.Right(g_Git
.m_CurrentDir
.GetLength() - superprojectRoot
.GetLength());
494 submodulePath
= g_Git
.m_CurrentDir
.Right(g_Git
.m_CurrentDir
.GetLength() - superprojectRoot
.GetLength() - 1);
495 submodulePath
.Replace(L
'\\', L
'/');
496 const git_index_entry
* entry
= git_index_get_bypath(index
, CUnicodeUtils::GetUTF8(submodulePath
), 0);
500 m_superProjectHash
= entry
->id
;
504 m_RefLabelPosMap
.clear();
507 if (g_Git
.GetMapHashToFriendName(m_HashMap
))
508 MessageBox(g_Git
.GetGitLastErr(L
"Could not get all refs."), L
"TortoiseGit", MB_ICONERROR
);
510 m_CurrentBranch
=g_Git
.GetCurrentBranch();
512 if (g_Git
.GetHash(m_HeadHash
, L
"HEAD"))
514 MessageBox(g_Git
.GetGitLastErr(L
"Could not get HEAD hash. Quitting..."), L
"TortoiseGit", MB_ICONERROR
);
518 m_wcRev
.m_ParentHash
.clear();
519 m_wcRev
.m_ParentHash
.push_back(m_HeadHash
);
522 FetchTrackingBranchList();
524 UpdateSubmodulePointer();
526 void StartAsyncDiffThread();
527 void StartLoadingThread();
529 void SafeTerminateThread()
531 if (m_LoadingThread
&& InterlockedExchange(&m_bExitThread
, TRUE
) == FALSE
)
533 DWORD ret
= WAIT_TIMEOUT
;
534 for (int i
= 0; i
< 200 && m_bThreadRunning
; ++i
)
535 ret
=::WaitForSingleObject(m_LoadingThread
->m_hThread
, 100);
536 if (ret
== WAIT_TIMEOUT
&& m_bThreadRunning
)
537 ::TerminateThread(m_LoadingThread
, 0);
538 m_LoadingThread
= nullptr;
542 bool IsInWorkingThread()
544 return (AfxGetThread() == m_LoadingThread
);
547 void SetRange(const CString
& range
)
552 CString
GetRange() const { return m_sRange
; }
554 bool HasFilterText() const { return !m_sFilterText
.IsEmpty() && m_sFilterText
!= L
"!"; }
558 volatile LONG m_bExitThread
;
559 CWinThread
* m_LoadingThread
;
561 MAP_HASH_NAME m_HashMap
;
563 std::map
<CString
, std::pair
<CString
, CString
>> m_TrackingMap
;
568 CString m_ColumnRegKey
;
574 CString simplifiedName
;
579 CGit::REF_TYPE refType
;
582 DECLARE_MESSAGE_MAP()
583 afx_msg
void OnDestroy();
584 virtual afx_msg
void OnNMCustomdrawLoglist(NMHDR
* pNMHDR
, LRESULT
* pResult
);
585 virtual afx_msg
void OnLvnGetdispinfoLoglist(NMHDR
* pNMHDR
, LRESULT
* pResult
);
586 afx_msg LRESULT
OnFindDialogMessage(WPARAM wParam
, LPARAM lParam
);
587 afx_msg LRESULT
OnScrollToMessage(WPARAM wParam
, LPARAM lParam
);
588 afx_msg LRESULT
OnScrollToRef(WPARAM wParam
, LPARAM lParam
);
589 afx_msg
int OnCreate(LPCREATESTRUCT lpCreateStruct
);
590 afx_msg
void OnContextMenu(CWnd
* pWnd
, CPoint point
);
591 afx_msg LRESULT
OnLoad(WPARAM wParam
, LPARAM lParam
);
592 void OnNMDblclkLoglist(NMHDR
* /*pNMHDR*/, LRESULT
*pResult
);
593 afx_msg
void OnLvnOdfinditemLoglist(NMHDR
*pNMHDR
, LRESULT
*pResult
);
594 void PreSubclassWindow() override
;
595 virtual BOOL
PreTranslateMessage(MSG
* pMsg
) override
;
596 virtual ULONG
GetGestureStatus(CPoint ptTouch
) override
;
597 static UINT
LogThreadEntry(LPVOID pVoid
);
599 bool IsOnStash(int index
);
600 bool IsStash(const GitRev
* pSelLogEntry
);
601 bool IsBisect(const GitRev
* pSelLogEntry
);
602 void FetchRemoteList();
603 void FetchTrackingBranchList();
605 virtual afx_msg BOOL
OnToolTipText(UINT id
, NMHDR
* pNMHDR
, LRESULT
* pResult
);
606 virtual INT_PTR
OnToolHitTest(CPoint point
, TOOLINFO
* pTI
) const override
;
607 CString
GetToolTipText(int nItem
, int nSubItem
);
609 /** Checks whether a referenfe label is under pt and returns the index/type
610 * pLogEntry IN: the entry of commit
611 * pt IN: the mouse position in client coordinate
612 * type IN: give the specific reference type, then check if it is the same reference type.
613 * OUT: give CGit::REF_TYPE::UNKNOWN for getting the real type it is.
614 * pShortname OUT: the short name of that reference label
615 * pIndex OUT: the index value of label of that entry
617 bool IsMouseOnRefLabel(const GitRevLoglist
* pLogEntry
, const POINT
& pt
, CGit::REF_TYPE
& type
, CString
* pShortname
= nullptr, size_t* pIndex
= nullptr);
618 bool IsMouseOnRefLabelFromPopupMenu(const GitRevLoglist
* pLogEntry
, const CPoint
& pt
, CGit::REF_TYPE
& type
, CString
* pShortname
= nullptr, size_t* pIndex
= nullptr);
620 void FillBackGround(HDC hdc
, DWORD_PTR Index
, CRect
&rect
);
621 void DrawTagBranchMessage(HDC hdc
, CRect
&rect
, INT_PTR index
, std::vector
<REFLABEL
> &refList
);
622 void DrawTagBranch(HDC hdc
, CDC
& W_Dc
, HTHEME hTheme
, CRect
& rect
, CRect
& rt
, LVITEM
& rItem
, GitRevLoglist
* data
, std::vector
<REFLABEL
>& refList
);
623 void DrawGraph(HDC
,CRect
&rect
,INT_PTR index
);
625 void paintGraphLane(HDC hdc
,int laneHeight
, int type
, int x1
, int x2
,
626 const COLORREF
& col
,const COLORREF
& activeColor
, int top
) ;
627 void DrawLine(HDC hdc
, int x1
, int y1
, int x2
, int y2
){ ::MoveToEx(hdc
, x1
, y1
, nullptr); ::LineTo(hdc
, x2
, y2
); }
629 * Save column widths to the registry
631 void SaveColumnWidths(); // save col widths to the registry
635 std::vector
<GitRevLoglist
*> m_AsynDiffList
;
636 CComCriticalSection m_AsynDiffListLock
;
637 HANDLE m_AsyncDiffEvent
;
638 volatile LONG m_AsyncThreadExit
;
639 CWinThread
* m_DiffingThread
;
640 volatile LONG m_AsyncThreadRunning
;
642 static int DiffAsync(GitRevLoglist
* rev
, IAsyncDiffCB
* pdata
)
644 auto data
= static_cast<CGitLogListBase
*>(pdata
);
645 ULONGLONG offset
= data
->m_LogCache
.GetOffset(rev
->m_CommitHash
);
646 if (!offset
|| data
->m_LogCache
.LoadOneItem(*rev
, offset
))
648 data
->m_AsynDiffListLock
.Lock();
649 data
->m_AsynDiffList
.push_back(rev
);
650 data
->m_AsynDiffListLock
.Unlock();
651 ::SetEvent(data
->m_AsyncDiffEvent
);
655 InterlockedExchange(&rev
->m_IsDiffFiles
, TRUE
);
656 if (!rev
->m_IsCommitParsed
)
658 InterlockedExchange(&rev
->m_IsFull
, TRUE
);
659 // we might need to signal that the changed files are now available
660 if (data
->GetSelectedCount() == 1)
662 POSITION pos
= data
->GetFirstSelectedItemPosition();
663 int nItem
= data
->GetNextSelectedItem(pos
);
666 GitRevLoglist
* data2
= data
->m_arShownList
.SafeGetAt(nItem
);
667 if (data2
&& data2
->m_CommitHash
== rev
->m_CommitHash
)
668 data
->GetParent()->PostMessage(WM_COMMAND
, MSG_FETCHED_DIFF
, 0);
674 static UINT
AsyncThread(LPVOID data
)
676 return reinterpret_cast<CGitLogListBase
*>(data
)->AsyncDiffThread();
679 int AsyncDiffThread();
682 void SafeTerminateAsyncDiffThread()
684 if (m_DiffingThread
&& InterlockedExchange(&m_AsyncThreadExit
, TRUE
) == FALSE
)
686 ::SetEvent(m_AsyncDiffEvent
);
687 DWORD ret
= WAIT_TIMEOUT
;
688 // do not block here, but process messages and ask until the thread ends
689 while (ret
== WAIT_TIMEOUT
&& m_AsyncThreadRunning
)
692 if (::PeekMessage(&msg
, nullptr, 0,0, PM_NOREMOVE
))
693 AfxGetThread()->PumpMessage(); // process messages, so that GetTopIndex and so on in the thread work
694 ret
= ::WaitForSingleObject(m_DiffingThread
->m_hThread
, 100);
696 m_DiffingThread
= nullptr;
697 InterlockedExchange(&m_AsyncThreadExit
, FALSE
);
702 CComCriticalSection m_critSec
;
704 HICON m_hModifiedIcon
;
705 HICON m_hReplacedIcon
;
706 HICON m_hConflictedIcon
;
708 HICON m_hDeletedIcon
;
713 CFont m_boldItalicsFont
;
715 CRegDWORD m_regMaxBugIDColWidth
;
721 CString m_CurrentBranch
;
724 COLORREF m_LineColors
[Lanes::COLORS_NUM
];
727 DWORD m_DateFormat
; // DATE_SHORTDATE or DATE_LONGDATE
728 bool m_bRelativeTimes
; // Show relative times
730 CString m_SingleRemote
;
731 bool m_bTagsBranchesOnRightSide
;
732 bool m_bFullCommitMessageOnLogLine
;
733 bool m_bSymbolizeRefNames
;
734 bool m_bIncludeBoundaryCommits
;
736 DWORD m_dwDefaultColumns
;
737 TCHAR m_wszTip
[8192];
739 std::map
<CString
, CRect
> m_RefLabelPosMap
; // ref name vs. label position
742 GIT_MAILMAP m_pMailmap
;
744 bool m_bDragndropEnabled
;
747 int m_nDropMarkerLast
;
748 int m_nDropMarkerLastHot
;
749 afx_msg
void OnMouseMove(UINT nFlags
, CPoint point
);
750 afx_msg
void OnLButtonUp(UINT nFlags
, CPoint point
);
751 afx_msg
void OnBeginDrag(NMHDR
* pNMHDR
, LRESULT
* pResult
);
752 void DrawDropInsertMarker(int nIndex
);
753 void DrawDropInsertMarkerLine(int nIndex
);
756 void EnableDragnDrop(bool enable
) { m_bDragndropEnabled
= enable
; }