OSDN Git Service

105f1ef69f034544bbf69c304a05fde270f180b7
[tortoisegit/TortoiseGitJp.git] / src / TortoiseGitBlame / TortoiseGitBlameView.cpp
1 // TortoiseGitBlame - a Viewer for Git Blames\r
2 \r
3 // Copyright (C) 2003-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 // CTortoiseGitBlameView.cpp : implementation of the CTortoiseGitBlameView class\r
20 //\r
21 \r
22 #include "stdafx.h"\r
23 #include "TortoiseGitBlame.h"\r
24 \r
25 #include "TortoiseGitBlameDoc.h"\r
26 #include "TortoiseGitBlameView.h"\r
27 #include "MainFrm.h"\r
28 #include "Balloon.h"\r
29 #include "EditGotoDlg.h"\r
30 #include "TortoiseGitBlameAppUtils.h"\r
31 \r
32 #ifdef _DEBUG\r
33 #define new DEBUG_NEW\r
34 #endif\r
35 \r
36 UINT CTortoiseGitBlameView::m_FindDialogMessage;\r
37 \r
38 // CTortoiseGitBlameView\r
39 \r
40 IMPLEMENT_DYNCREATE(CTortoiseGitBlameView, CView)\r
41 \r
42 BEGIN_MESSAGE_MAP(CTortoiseGitBlameView, CView)\r
43         // Standard printing commands\r
44         ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)\r
45         ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)\r
46         ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CTortoiseGitBlameView::OnFilePrintPreview)\r
47         ON_COMMAND(ID_EDIT_FIND,OnEditFind)\r
48         ON_COMMAND(ID_EDIT_GOTO,OnEditGoto)\r
49         ON_COMMAND(ID_EDIT_COPY,CopySelectedLogToClipboard)\r
50         ON_COMMAND(ID_VIEW_NEXT,OnViewNext)\r
51         ON_COMMAND(ID_VIEW_PREV,OnViewPrev)\r
52         ON_WM_CREATE()\r
53         ON_WM_SIZE()\r
54         ON_WM_MOUSEMOVE()\r
55         ON_WM_MOUSEHOVER()\r
56         ON_WM_MOUSELEAVE()\r
57         ON_WM_LBUTTONDOWN()\r
58         ON_WM_RBUTTONDOWN()\r
59         ON_NOTIFY(SCN_PAINTED,0,OnSciPainted)\r
60         ON_NOTIFY(SCN_GETBKCOLOR,0,OnSciGetBkColor)\r
61     ON_REGISTERED_MESSAGE(m_FindDialogMessage,   OnFindDialogMessage)  \r
62 END_MESSAGE_MAP()\r
63 \r
64 \r
65 // CTortoiseGitBlameView construction/destruction\r
66 \r
67 CTortoiseGitBlameView::CTortoiseGitBlameView()\r
68 {\r
69         // TODO: add construction code here\r
70         hInstance = 0;\r
71         hResource = 0;\r
72         currentDialog = 0;\r
73         wMain = 0;\r
74         m_wEditor = 0;\r
75         wLocator = 0;\r
76 \r
77         m_font = 0;\r
78         m_italicfont = 0;\r
79         m_blamewidth = 0;\r
80         m_revwidth = 0;\r
81         m_datewidth = 0;\r
82         m_authorwidth = 0;\r
83         m_pathwidth = 0;\r
84         m_linewidth = 0;\r
85 \r
86         m_windowcolor = ::GetSysColor(COLOR_WINDOW);\r
87         m_textcolor = ::GetSysColor(COLOR_WINDOWTEXT);\r
88         m_texthighlightcolor = ::GetSysColor(COLOR_HIGHLIGHTTEXT);\r
89         m_mouserevcolor = InterColor(m_windowcolor, m_textcolor, 20);\r
90         m_mouseauthorcolor = InterColor(m_windowcolor, m_textcolor, 10);\r
91         m_selectedrevcolor = ::GetSysColor(COLOR_HIGHLIGHT);\r
92         m_selectedauthorcolor = InterColor(m_selectedrevcolor, m_texthighlightcolor, 35);\r
93         m_mouserev = -2;\r
94 \r
95         m_selectedrev = -1;\r
96         m_selectedorigrev = -1;\r
97         m_SelectedLine = -1;\r
98         m_directPointer = 0;\r
99         m_directFunction = 0;\r
100 \r
101         m_lowestrev = LONG_MAX;\r
102         m_highestrev = 0;\r
103         m_colorage = true;\r
104 \r
105         m_bShowLine=true;\r
106 \r
107         m_bShowAuthor=true;\r
108         m_bShowDate=false;\r
109 \r
110     m_FindDialogMessage   =   ::RegisterWindowMessage(FINDMSGSTRING);   \r
111         m_pFindDialog = NULL;\r
112         // get short/long datetime setting from registry\r
113         DWORD RegUseShortDateFormat = CRegDWORD(_T("Software\\TortoiseGit\\LogDateFormat"), TRUE);\r
114         if ( RegUseShortDateFormat )\r
115         {\r
116                 m_DateFormat = DATE_SHORTDATE;\r
117         }\r
118         else\r
119         {\r
120                 m_DateFormat = DATE_LONGDATE;\r
121         }\r
122 }\r
123 \r
124 CTortoiseGitBlameView::~CTortoiseGitBlameView()\r
125 {\r
126         if (m_font)\r
127                 DeleteObject(m_font);\r
128         if (m_italicfont)\r
129                 DeleteObject(m_italicfont);\r
130 }\r
131 \r
132 \r
133 int CTortoiseGitBlameView::OnCreate(LPCREATESTRUCT lpcs)\r
134 {\r
135 \r
136         CRect rect,rect1;\r
137         this->GetWindowRect(&rect1);\r
138         rect.left=m_blamewidth+LOCATOR_WIDTH;\r
139         rect.right=rect.Width();\r
140         rect.top=0;\r
141         rect.bottom=rect.Height();\r
142         BOOL b=m_TextView.Create(_T("Scintilla"),_T("source"),0,rect,this,0,0);\r
143         m_TextView.Init(0);\r
144         m_TextView.ShowWindow( SW_SHOW);\r
145         //m_TextView.InsertText(_T("Abdadfasdf"));\r
146         m_wEditor = m_TextView.m_hWnd;\r
147         CreateFont();\r
148         InitialiseEditor();\r
149         m_ToolTip.Create(this->GetParent());    \r
150         m_ToolTip.AddTool(this,_T("Test"));\r
151         \r
152         ::AfxGetApp()->GetMainWnd();\r
153         return CView::OnCreate(lpcs);\r
154         \r
155 }\r
156 \r
157 void CTortoiseGitBlameView::OnSize(UINT nType,int cx, int cy)\r
158 {\r
159 \r
160         CRect rect;\r
161         rect.left=m_blamewidth;\r
162         rect.right=cx;\r
163         rect.top=0;\r
164         rect.bottom=cy;\r
165 \r
166         m_TextView.MoveWindow(&rect);\r
167 \r
168 }\r
169 BOOL CTortoiseGitBlameView::PreCreateWindow(CREATESTRUCT& cs)\r
170 {\r
171         // TODO: Modify the Window class or styles here by modifying\r
172         //  the CREATESTRUCT cs\r
173 \r
174         return CView::PreCreateWindow(cs);\r
175 }\r
176 \r
177 // CTortoiseGitBlameView drawing\r
178 \r
179 void CTortoiseGitBlameView::OnDraw(CDC* /*pDC*/)\r
180 {\r
181         CTortoiseGitBlameDoc* pDoc = GetDocument();\r
182         ASSERT_VALID(pDoc);\r
183         if (!pDoc)\r
184                 return;\r
185 \r
186         DrawBlame(this->GetDC()->m_hDC);\r
187         DrawLocatorBar(this->GetDC()->m_hDC);\r
188         // TODO: add draw code for native data here\r
189 }\r
190 \r
191 \r
192 // CTortoiseGitBlameView printing\r
193 \r
194 \r
195 void CTortoiseGitBlameView::OnFilePrintPreview()\r
196 {\r
197         AFXPrintPreview(this);\r
198 }\r
199 \r
200 BOOL CTortoiseGitBlameView::OnPreparePrinting(CPrintInfo* pInfo)\r
201 {\r
202         // default preparation\r
203         return DoPreparePrinting(pInfo);\r
204 }\r
205 \r
206 void CTortoiseGitBlameView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)\r
207 {\r
208         // TODO: add extra initialization before printing\r
209 }\r
210 \r
211 void CTortoiseGitBlameView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)\r
212 {\r
213         // TODO: add cleanup after printing\r
214 }\r
215 \r
216 void CTortoiseGitBlameView::OnRButtonUp(UINT nFlags, CPoint point)\r
217 {\r
218         ClientToScreen(&point);\r
219         OnContextMenu(this, point);\r
220 }\r
221 \r
222 void CTortoiseGitBlameView::OnContextMenu(CWnd* pWnd, CPoint point)\r
223 {\r
224         theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);\r
225 }\r
226 \r
227 \r
228 // CTortoiseGitBlameView diagnostics\r
229 \r
230 #ifdef _DEBUG\r
231 void CTortoiseGitBlameView::AssertValid() const\r
232 {\r
233         CView::AssertValid();\r
234 }\r
235 \r
236 void CTortoiseGitBlameView::Dump(CDumpContext& dc) const\r
237 {\r
238         CView::Dump(dc);\r
239 }\r
240 \r
241 CTortoiseGitBlameDoc* CTortoiseGitBlameView::GetDocument() const // non-debug version is inline\r
242 {\r
243         ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTortoiseGitBlameDoc)));\r
244         return (CTortoiseGitBlameDoc*)m_pDocument;\r
245 }\r
246 #endif //_DEBUG\r
247 \r
248 \r
249 // CTortoiseGitBlameView message handlers\r
250 CString CTortoiseGitBlameView::GetAppDirectory()\r
251 {\r
252         CString path;\r
253         DWORD len = 0;\r
254         DWORD bufferlen = MAX_PATH;             // MAX_PATH is not the limit here!\r
255         do \r
256         {\r
257                 bufferlen += MAX_PATH;          // MAX_PATH is not the limit here!\r
258                 TCHAR * pBuf = new TCHAR[bufferlen];\r
259                 len = GetModuleFileName(NULL, pBuf, bufferlen); \r
260                 path = CString(pBuf, len);\r
261                 delete [] pBuf;\r
262         } while(len == bufferlen);\r
263 \r
264         path = path.Left(path.ReverseFind(_T('\\')));\r
265         //path = path.substr(0, path.rfind('\\') + 1);\r
266 \r
267         return path;\r
268 }\r
269 \r
270 // Return a color which is interpolated between c1 and c2.\r
271 // Slider controls the relative proportions as a percentage:\r
272 // Slider = 0   represents pure c1\r
273 // Slider = 50  represents equal mixture\r
274 // Slider = 100 represents pure c2\r
275 COLORREF CTortoiseGitBlameView::InterColor(COLORREF c1, COLORREF c2, int Slider)\r
276 {\r
277         int r, g, b;\r
278         \r
279         // Limit Slider to 0..100% range\r
280         if (Slider < 0)\r
281                 Slider = 0;\r
282         if (Slider > 100)\r
283                 Slider = 100;\r
284         \r
285         // The color components have to be treated individually.\r
286         r = (GetRValue(c2) * Slider + GetRValue(c1) * (100 - Slider)) / 100;\r
287         g = (GetGValue(c2) * Slider + GetGValue(c1) * (100 - Slider)) / 100;\r
288         b = (GetBValue(c2) * Slider + GetBValue(c1) * (100 - Slider)) / 100;\r
289         \r
290         return RGB(r, g, b);\r
291 }\r
292 \r
293 LRESULT CTortoiseGitBlameView::SendEditor(UINT Msg, WPARAM wParam, LPARAM lParam)\r
294 {\r
295         if (m_directFunction)\r
296         {\r
297                 return ((SciFnDirect) m_directFunction)(m_directPointer, Msg, wParam, lParam);\r
298         }\r
299         return ::SendMessage(m_wEditor, Msg, wParam, lParam);   \r
300 }\r
301 \r
302 void CTortoiseGitBlameView::GetRange(int start, int end, char *text) \r
303 {\r
304 #if 0\r
305         TEXTRANGE tr;\r
306         tr.chrg.cpMin = start;\r
307         tr.chrg.cpMax = end;\r
308         tr.lpstrText = text;\r
309 \r
310         SendMessage(m_wEditor, EM_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&tr));\r
311 #endif\r
312 }\r
313 \r
314 void CTortoiseGitBlameView::SetTitle() \r
315 {\r
316 #if 0\r
317         char title[MAX_PATH + 100];\r
318         strcpy_s(title, MAX_PATH + 100, szTitle);\r
319         strcat_s(title, MAX_PATH + 100, " - ");\r
320         strcat_s(title, MAX_PATH + 100, szViewtitle);\r
321         ::SetWindowText(wMain, title);\r
322 #endif\r
323 }\r
324 \r
325 BOOL CTortoiseGitBlameView::OpenLogFile(const char *fileName)\r
326 {\r
327 #if 0\r
328         char logmsgbuf[10000+1];\r
329         FILE * File;\r
330         fopen_s(&File, fileName, "rb");\r
331         if (File == 0)\r
332         {\r
333                 return FALSE;\r
334         }\r
335         LONG rev = 0;\r
336         CString msg;\r
337         int slength = 0;\r
338         int reallength = 0;\r
339         size_t len = 0;\r
340         wchar_t wbuf[MAX_LOG_LENGTH+6];\r
341         for (;;)\r
342         {\r
343                 len = fread(&rev, sizeof(LONG), 1, File);\r
344                 if (len == 0)\r
345                 {\r
346                         fclose(File);\r
347             InitSize();\r
348                         return TRUE;\r
349                 }\r
350                 len = fread(&slength, sizeof(int), 1, File);\r
351                 if (len == 0)\r
352                 {\r
353                         fclose(File);\r
354             InitSize();\r
355                         return FALSE;\r
356                 }\r
357                 if (slength > MAX_LOG_LENGTH)\r
358                 {\r
359                         reallength = slength;\r
360                         slength = MAX_LOG_LENGTH;\r
361                 }\r
362                 else\r
363                         reallength = 0;\r
364                 len = fread(logmsgbuf, sizeof(char), slength, File);\r
365                 if (len < (size_t)slength)\r
366                 {\r
367                         fclose(File);\r
368             InitSize();\r
369                         return FALSE;\r
370                 }\r
371                 msg = CString(logmsgbuf, slength);\r
372                 if (reallength)\r
373                 {\r
374                         fseek(File, reallength-MAX_LOG_LENGTH, SEEK_CUR);\r
375                         msg = msg + _T("\n...");\r
376                 }\r
377                 int len2 = ::MultiByteToWideChar(CP_UTF8, NULL, msg.c_str(), min(msg.size(), MAX_LOG_LENGTH+5), wbuf, MAX_LOG_LENGTH+5);\r
378                 wbuf[len2] = 0;\r
379                 len2 = ::WideCharToMultiByte(CP_ACP, NULL, wbuf, len2, logmsgbuf, MAX_LOG_LENGTH+5, NULL, NULL);\r
380                 logmsgbuf[len2] = 0;\r
381                 msg = CString(logmsgbuf);\r
382                 logmessages[rev] = msg;\r
383         }\r
384 #endif\r
385         return TRUE;\r
386 }\r
387 \r
388 BOOL CTortoiseGitBlameView::OpenFile(const char *fileName) \r
389 {\r
390 #if 0\r
391         SendEditor(SCI_SETREADONLY, FALSE);\r
392         SendEditor(SCI_CLEARALL);\r
393         SendEditor(EM_EMPTYUNDOBUFFER);\r
394         SetTitle();\r
395         SendEditor(SCI_SETSAVEPOINT);\r
396         SendEditor(SCI_CANCEL);\r
397         SendEditor(SCI_SETUNDOCOLLECTION, 0);\r
398         ::ShowWindow(m_wEditor, SW_HIDE);\r
399         std::ifstream File;\r
400         File.open(fileName);\r
401         if (!File.good())\r
402         {\r
403                 return FALSE;\r
404         }\r
405         char line[100*1024];\r
406         char * lineptr = NULL;\r
407         char * trimptr = NULL;\r
408         //ignore the first two lines, they're of no interest to us\r
409         File.getline(line, sizeof(line)/sizeof(char));\r
410         File.getline(line, sizeof(line)/sizeof(char));\r
411         m_lowestrev = LONG_MAX;\r
412         m_highestrev = 0;\r
413         bool bUTF8 = true;\r
414         do\r
415         {\r
416                 File.getline(line, sizeof(line)/sizeof(TCHAR));\r
417                 if (File.gcount()>139)\r
418                 {\r
419                         mergelines.push_back((line[0] != ' '));\r
420                         lineptr = &line[9];\r
421                         long rev = _ttol(lineptr);\r
422                         revs.push_back(rev);\r
423                         m_lowestrev = min(m_lowestrev, rev);\r
424                         m_highestrev = max(m_highestrev, rev);\r
425                         lineptr += 7;\r
426                         rev = _ttol(lineptr);\r
427                         origrevs.push_back(rev);\r
428                         lineptr += 7;\r
429                         dates.push_back(CString(lineptr, 30));\r
430                         lineptr += 31;\r
431                         // unfortunately, the 'path' entry can be longer than the 60 chars\r
432                         // we made the column. We therefore have to step through the path\r
433                         // string until we find a space\r
434                         trimptr = lineptr;\r
435                         do \r
436                         {\r
437                                 // TODO: how can we deal with the situation where the path has\r
438                                 // a space in it, but the space is after the 60 chars reserved\r
439                                 // for it?\r
440                                 // The only way to deal with that would be to use a custom\r
441                                 // binary format for the blame file.\r
442                                 trimptr++;\r
443                                 trimptr = _tcschr(trimptr, ' ');\r
444                         } while ((trimptr)&&(trimptr+1 < lineptr+61));\r
445                         if (trimptr)\r
446                                 *trimptr = 0;\r
447                         else\r
448                                 trimptr = lineptr;\r
449                         paths.push_back(CString(lineptr));\r
450                         if (trimptr+1 < lineptr+61)\r
451                                 lineptr +=61;\r
452                         else\r
453                                 lineptr = (trimptr+1);\r
454                         trimptr = lineptr+30;\r
455                         while ((*trimptr == ' ')&&(trimptr > lineptr))\r
456                                 trimptr--;\r
457                         *(trimptr+1) = 0;\r
458                         authors.push_back(CString(lineptr));\r
459                         lineptr += 31;\r
460                         // in case we find an UTF8 BOM at the beginning of the line, we remove it\r
461                         if (((unsigned char)lineptr[0] == 0xEF)&&((unsigned char)lineptr[1] == 0xBB)&&((unsigned char)lineptr[2] == 0xBF))\r
462                         {\r
463                                 lineptr += 3;\r
464                         }\r
465                         if (((unsigned char)lineptr[0] == 0xBB)&&((unsigned char)lineptr[1] == 0xEF)&&((unsigned char)lineptr[2] == 0xBF))\r
466                         {\r
467                                 lineptr += 3;\r
468                         }\r
469                         // check each line for illegal utf8 sequences. If one is found, we treat\r
470                         // the file as ASCII, otherwise we assume an UTF8 file.\r
471                         char * utf8CheckBuf = lineptr;\r
472                         while ((bUTF8)&&(*utf8CheckBuf))\r
473                         {\r
474                                 if ((*utf8CheckBuf == 0xC0)||(*utf8CheckBuf == 0xC1)||(*utf8CheckBuf >= 0xF5))\r
475                                 {\r
476                                         bUTF8 = false;\r
477                                         break;\r
478                                 }\r
479                                 if ((*utf8CheckBuf & 0xE0)==0xC0)\r
480                                 {\r
481                                         utf8CheckBuf++;\r
482                                         if (*utf8CheckBuf == 0)\r
483                                                 break;\r
484                                         if ((*utf8CheckBuf & 0xC0)!=0x80)\r
485                                         {\r
486                                                 bUTF8 = false;\r
487                                                 break;\r
488                                         }\r
489                                 }\r
490                                 if ((*utf8CheckBuf & 0xF0)==0xE0)\r
491                                 {\r
492                                         utf8CheckBuf++;\r
493                                         if (*utf8CheckBuf == 0)\r
494                                                 break;\r
495                                         if ((*utf8CheckBuf & 0xC0)!=0x80)\r
496                                         {\r
497                                                 bUTF8 = false;\r
498                                                 break;\r
499                                         }\r
500                                         utf8CheckBuf++;\r
501                                         if (*utf8CheckBuf == 0)\r
502                                                 break;\r
503                                         if ((*utf8CheckBuf & 0xC0)!=0x80)\r
504                                         {\r
505                                                 bUTF8 = false;\r
506                                                 break;\r
507                                         }\r
508                                 }\r
509                                 if ((*utf8CheckBuf & 0xF8)==0xF0)\r
510                                 {\r
511                                         utf8CheckBuf++;\r
512                                         if (*utf8CheckBuf == 0)\r
513                                                 break;\r
514                                         if ((*utf8CheckBuf & 0xC0)!=0x80)\r
515                                         {\r
516                                                 bUTF8 = false;\r
517                                                 break;\r
518                                         }\r
519                                         utf8CheckBuf++;\r
520                                         if (*utf8CheckBuf == 0)\r
521                                                 break;\r
522                                         if ((*utf8CheckBuf & 0xC0)!=0x80)\r
523                                         {\r
524                                                 bUTF8 = false;\r
525                                                 break;\r
526                                         }\r
527                                         utf8CheckBuf++;\r
528                                         if (*utf8CheckBuf == 0)\r
529                                                 break;\r
530                                         if ((*utf8CheckBuf & 0xC0)!=0x80)\r
531                                         {\r
532                                                 bUTF8 = false;\r
533                                                 break;\r
534                                         }\r
535                                 }\r
536 \r
537                                 utf8CheckBuf++;\r
538                         }\r
539                         SendEditor(SCI_ADDTEXT, _tcslen(lineptr), reinterpret_cast<LPARAM>(static_cast<char *>(lineptr)));\r
540                         SendEditor(SCI_ADDTEXT, 2, (LPARAM)_T("\r\n"));\r
541                 }\r
542         } while (File.gcount() > 0);\r
543 \r
544         if (bUTF8)\r
545                 SendEditor(SCI_SETCODEPAGE, SC_CP_UTF8);\r
546 \r
547         SendEditor(SCI_SETUNDOCOLLECTION, 1);\r
548         ::SetFocus(m_wEditor);\r
549         SendEditor(EM_EMPTYUNDOBUFFER);\r
550         SendEditor(SCI_SETSAVEPOINT);\r
551         SendEditor(SCI_GOTOPOS, 0);\r
552         SendEditor(SCI_SETSCROLLWIDTHTRACKING, TRUE);\r
553         SendEditor(SCI_SETREADONLY, TRUE);\r
554 \r
555         //check which lexer to use, depending on the filetype\r
556         SetupLexer(fileName);\r
557         ::ShowWindow(m_wEditor, SW_SHOW);\r
558         m_blamewidth = 0;\r
559         ::InvalidateRect(wMain, NULL, TRUE);\r
560         RECT rc;\r
561         GetWindowRect(wMain, &rc);\r
562         SetWindowPos(wMain, 0, rc.left, rc.top, rc.right-rc.left-1, rc.bottom - rc.top, 0);\r
563 #endif\r
564         return TRUE;\r
565 }\r
566 \r
567 void CTortoiseGitBlameView::SetAStyle(int style, COLORREF fore, COLORREF back, int size, CString *face) \r
568 {\r
569         SendEditor(SCI_STYLESETFORE, style, fore);\r
570         SendEditor(SCI_STYLESETBACK, style, back);\r
571         if (size >= 1)\r
572                 SendEditor(SCI_STYLESETSIZE, style, size);\r
573         if (face) \r
574                 SendEditor(SCI_STYLESETFONT, style, reinterpret_cast<LPARAM>(this->m_TextView.StringForControl(*face).GetBuffer()));\r
575 }\r
576 \r
577 void CTortoiseGitBlameView::InitialiseEditor() \r
578 {\r
579 \r
580         m_directFunction = ::SendMessage(m_wEditor, SCI_GETDIRECTFUNCTION, 0, 0);\r
581         m_directPointer = ::SendMessage(m_wEditor, SCI_GETDIRECTPOINTER, 0, 0);\r
582         // Set up the global default style. These attributes are used wherever no explicit choices are made.\r
583         SetAStyle(STYLE_DEFAULT, \r
584                           black, \r
585                           white, \r
586                         (DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\BlameFontSize"), 10), \r
587                         &CString(((stdstring)CRegStdString(_T("Software\\TortoiseGit\\BlameFontName"), _T("Courier New"))).c_str())\r
588                         );\r
589         SendEditor(SCI_SETTABWIDTH, (DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\BlameTabSize"), 4));\r
590         SendEditor(SCI_SETREADONLY, TRUE);\r
591         LRESULT pix = SendEditor(SCI_TEXTWIDTH, STYLE_LINENUMBER, (LPARAM)this->m_TextView.StringForControl(_T("_99999")).GetBuffer());\r
592         if (m_bShowLine)\r
593                 SendEditor(SCI_SETMARGINWIDTHN, 0, pix);\r
594         else\r
595                 SendEditor(SCI_SETMARGINWIDTHN, 0);\r
596         SendEditor(SCI_SETMARGINWIDTHN, 1);\r
597         SendEditor(SCI_SETMARGINWIDTHN, 2);\r
598         //Set the default windows colors for edit controls\r
599         SendEditor(SCI_STYLESETFORE, STYLE_DEFAULT, ::GetSysColor(COLOR_WINDOWTEXT));\r
600         SendEditor(SCI_STYLESETBACK, STYLE_DEFAULT, ::GetSysColor(COLOR_WINDOW));\r
601         SendEditor(SCI_SETSELFORE, TRUE, ::GetSysColor(COLOR_HIGHLIGHTTEXT));\r
602         SendEditor(SCI_SETSELBACK, TRUE, ::GetSysColor(COLOR_HIGHLIGHT));\r
603         SendEditor(SCI_SETCARETFORE, ::GetSysColor(COLOR_WINDOWTEXT));\r
604         m_regOldLinesColor = CRegStdWORD(_T("Software\\TortoiseGit\\BlameOldColor"), RGB(230, 230, 255));\r
605         m_regNewLinesColor = CRegStdWORD(_T("Software\\TortoiseGit\\BlameNewColor"), RGB(255, 230, 230));\r
606         \r
607         this->m_TextView.Call(SCI_SETWRAPMODE, SC_WRAP_NONE);\r
608 \r
609 }\r
610 \r
611 void CTortoiseGitBlameView::StartSearch()\r
612 {\r
613         if (m_pFindDialog)\r
614                 return;\r
615         bool bCase = false;\r
616         // Initialize FINDREPLACE\r
617         if (fr.Flags & FR_MATCHCASE)\r
618                 bCase = true;\r
619         SecureZeroMemory(&fr, sizeof(fr));\r
620         fr.lStructSize = sizeof(fr);\r
621         fr.hwndOwner = wMain;\r
622         fr.lpstrFindWhat = szFindWhat;\r
623         fr.wFindWhatLen = 80;\r
624         fr.Flags = FR_HIDEUPDOWN | FR_HIDEWHOLEWORD;\r
625         fr.Flags |= bCase ? FR_MATCHCASE : 0;\r
626 \r
627         currentDialog = FindText(&fr);\r
628 }\r
629 \r
630 bool CTortoiseGitBlameView::DoSearch(CString what, DWORD flags)\r
631 {\r
632 \r
633         //char szWhat[80];\r
634         int pos = SendEditor(SCI_GETCURRENTPOS);\r
635         int line = SendEditor(SCI_LINEFROMPOSITION, pos);\r
636         bool bFound = false;\r
637         bool bCaseSensitive = !!(flags & FR_MATCHCASE);\r
638 \r
639         //strcpy_s(szWhat, sizeof(szWhat), what);\r
640 \r
641         if(!bCaseSensitive)\r
642         {\r
643                 what=what.MakeLower();\r
644         }\r
645 \r
646         //CString sWhat = CString(szWhat);\r
647         \r
648         //char buf[20];\r
649         //int i=0;\r
650         int i=line;\r
651         do\r
652         {\r
653                 int bufsize = SendEditor(SCI_GETLINE, i);\r
654                 char * linebuf = new char[bufsize+1];\r
655                 SecureZeroMemory(linebuf, bufsize+1);\r
656                 SendEditor(SCI_GETLINE, i, (LPARAM)linebuf);\r
657                 CString oneline=this->m_TextView.StringFromControl(linebuf);\r
658                 if (!bCaseSensitive)\r
659                 {\r
660                         oneline=oneline.MakeLower();\r
661                 }\r
662                 //_stprintf_s(buf, 20, _T("%ld"), revs[i]);\r
663                 if (this->m_Authors[i].Find(what)>=0)\r
664                         bFound = true;\r
665                 else if ((!bCaseSensitive)&&(this->m_Authors[i].MakeLower().Find(what)>=0))\r
666                         bFound = true;\r
667                 else if (oneline.Find(what) >=0)\r
668                         bFound = true;\r
669                 \r
670                 delete [] linebuf;\r
671 \r
672                 i++;\r
673                 if(i>=(signed int)m_CommitHash.size())\r
674                         i=0;\r
675         }while(i!=line &&(!bFound));\r
676 \r
677         if (bFound)\r
678         {\r
679                 GotoLine(i);\r
680                 int selstart = SendEditor(SCI_GETCURRENTPOS);\r
681                 int selend = SendEditor(SCI_POSITIONFROMLINE, i);\r
682                 SendEditor(SCI_SETSELECTIONSTART, selstart);\r
683                 SendEditor(SCI_SETSELECTIONEND, selend);\r
684                 m_SelectedLine = i-1;\r
685         }\r
686         else\r
687         {\r
688                 ::MessageBox(wMain, what+_T(" not found"), _T("CTortoiseGitBlameView"), MB_ICONINFORMATION);\r
689         }\r
690 \r
691         return true;\r
692 }\r
693 \r
694 bool CTortoiseGitBlameView::GotoLine(long line)\r
695 {\r
696         --line;\r
697         if (line < 0)\r
698                 return false;\r
699         if ((unsigned long)line >= m_CommitHash.size())\r
700         {\r
701                 line = m_CommitHash.size()-1;\r
702         }\r
703 \r
704         int nCurrentPos = SendEditor(SCI_GETCURRENTPOS);\r
705         int nCurrentLine = SendEditor(SCI_LINEFROMPOSITION,nCurrentPos);\r
706         int nFirstVisibleLine = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
707         int nLinesOnScreen = SendEditor(SCI_LINESONSCREEN);\r
708 \r
709         if ( line>=nFirstVisibleLine && line<=nFirstVisibleLine+nLinesOnScreen)\r
710         {\r
711                 // no need to scroll\r
712                 SendEditor(SCI_GOTOLINE, line);\r
713         }\r
714         else\r
715         {\r
716                 // Place the requested line one third from the top\r
717                 if ( line > nCurrentLine )\r
718                 {\r
719                         SendEditor(SCI_GOTOLINE, (WPARAM)(line+(int)nLinesOnScreen*(2/3.0)));\r
720                 }\r
721                 else\r
722                 {\r
723                         SendEditor(SCI_GOTOLINE, (WPARAM)(line-(int)nLinesOnScreen*(1/3.0)));\r
724                 }\r
725         }\r
726 \r
727         // Highlight the line\r
728         int nPosStart = SendEditor(SCI_POSITIONFROMLINE,line);\r
729         int nPosEnd = SendEditor(SCI_GETLINEENDPOSITION,line);\r
730         SendEditor(SCI_SETSEL,nPosEnd,nPosStart);\r
731 \r
732         return true;\r
733 }\r
734 \r
735 bool CTortoiseGitBlameView::ScrollToLine(long line)\r
736 {\r
737         if (line < 0)\r
738                 return false;\r
739 \r
740         int nCurrentLine = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
741 \r
742         int scrolldelta = line - nCurrentLine;\r
743         SendEditor(SCI_LINESCROLL, 0, scrolldelta);\r
744 \r
745         return true;\r
746 }\r
747 \r
748 void CTortoiseGitBlameView::CopySelectedLogToClipboard()\r
749 {\r
750         this->GetLogList()->CopySelectionToClipBoard(FALSE);\r
751 }\r
752 \r
753 void CTortoiseGitBlameView::BlamePreviousRevision()\r
754 {\r
755 #if 0\r
756         LONG nRevisionTo = m_selectedorigrev - 1;\r
757         if ( nRevisionTo<1 )\r
758         {\r
759                 return;\r
760         }\r
761 \r
762         // We now determine the smallest revision number in the blame file (but ignore "-1")\r
763         // We do this for two reasons:\r
764         // 1. we respect the "From revision" which the user entered\r
765         // 2. we speed up the call of "svn blame" because previous smaller revision numbers don't have any effect on the result\r
766         LONG nSmallestRevision = -1;\r
767         for (LONG line=0;line<(LONG)app.revs.size();line++)\r
768         {\r
769                 const LONG nRevision = app.revs[line];\r
770                 if ( nRevision > 0 )\r
771                 {\r
772                         if ( nSmallestRevision < 1 )\r
773                         {\r
774                                 nSmallestRevision = nRevision;\r
775                         }\r
776                         else\r
777                         {\r
778                                 nSmallestRevision = min(nSmallestRevision,nRevision);\r
779                         }\r
780                 }\r
781         }\r
782 \r
783         char bufStartRev[20];\r
784         _stprintf_s(bufStartRev, 20, _T("%d"), nSmallestRevision);\r
785 \r
786         char bufEndRev[20];\r
787         _stprintf_s(bufEndRev, 20, _T("%d"), nRevisionTo);\r
788 \r
789         char bufLine[20];\r
790         _stprintf_s(bufLine, 20, _T("%d"), m_SelectedLine+1); //using the current line is a good guess.\r
791 \r
792         STARTUPINFO startup;\r
793         PROCESS_INFORMATION process;\r
794         memset(&startup, 0, sizeof(startup));\r
795         startup.cb = sizeof(startup);\r
796         memset(&process, 0, sizeof(process));\r
797         stdstring tortoiseProcPath = GetAppDirectory() + _T("TortoiseProc.exe");\r
798         stdstring svnCmd = _T(" /command:blame ");\r
799         svnCmd += _T(" /path:\"");\r
800         svnCmd += szOrigPath;\r
801         svnCmd += _T("\"");\r
802         svnCmd += _T(" /startrev:");\r
803         svnCmd += bufStartRev;\r
804         svnCmd += _T(" /endrev:");\r
805         svnCmd += bufEndRev;\r
806         svnCmd += _T(" /line:");\r
807         svnCmd += bufLine;\r
808         if (bIgnoreEOL)\r
809                 svnCmd += _T(" /ignoreeol");\r
810         if (bIgnoreSpaces)\r
811                 svnCmd += _T(" /ignorespaces");\r
812         if (bIgnoreAllSpaces)\r
813                 svnCmd += _T(" /ignoreallspaces");\r
814     if (CreateProcess(tortoiseProcPath.c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))\r
815         {\r
816                 CloseHandle(process.hThread);\r
817                 CloseHandle(process.hProcess);\r
818         }\r
819 #endif\r
820 }\r
821 \r
822 void CTortoiseGitBlameView::DiffPreviousRevision()\r
823 {\r
824 #if 0\r
825         LONG nRevisionTo = m_selectedorigrev;\r
826         if ( nRevisionTo<1 )\r
827         {\r
828                 return;\r
829         }\r
830 \r
831         LONG nRevisionFrom = nRevisionTo-1;\r
832 \r
833         char bufStartRev[20];\r
834         _stprintf_s(bufStartRev, 20, _T("%d"), nRevisionFrom);\r
835 \r
836         char bufEndRev[20];\r
837         _stprintf_s(bufEndRev, 20, _T("%d"), nRevisionTo);\r
838 \r
839         STARTUPINFO startup;\r
840         PROCESS_INFORMATION process;\r
841         memset(&startup, 0, sizeof(startup));\r
842         startup.cb = sizeof(startup);\r
843         memset(&process, 0, sizeof(process));\r
844         stdstring tortoiseProcPath = GetAppDirectory() + _T("TortoiseProc.exe");\r
845         stdstring svnCmd = _T(" /command:diff ");\r
846         svnCmd += _T(" /path:\"");\r
847         svnCmd += szOrigPath;\r
848         svnCmd += _T("\"");\r
849         svnCmd += _T(" /startrev:");\r
850         svnCmd += bufStartRev;\r
851         svnCmd += _T(" /endrev:");\r
852         svnCmd += bufEndRev;\r
853         if (CreateProcess(tortoiseProcPath.c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))\r
854         {\r
855                 CloseHandle(process.hThread);\r
856                 CloseHandle(process.hProcess);\r
857         }\r
858 #endif\r
859 }\r
860 \r
861 void CTortoiseGitBlameView::ShowLog()\r
862 {\r
863 #if 0\r
864         char bufRev[20];\r
865         _stprintf_s(bufRev, 20, _T("%d"), m_selectedorigrev);\r
866 \r
867         STARTUPINFO startup;\r
868         PROCESS_INFORMATION process;\r
869         memset(&startup, 0, sizeof(startup));\r
870         startup.cb = sizeof(startup);\r
871         memset(&process, 0, sizeof(process));\r
872         stdstring tortoiseProcPath = GetAppDirectory() + _T("TortoiseProc.exe");\r
873         stdstring svnCmd = _T(" /command:log ");\r
874         svnCmd += _T(" /path:\"");\r
875         svnCmd += szOrigPath;\r
876         svnCmd += _T("\"");\r
877         svnCmd += _T(" /startrev:");\r
878         svnCmd += bufRev;\r
879         svnCmd += _T(" /pegrev:");\r
880         svnCmd += bufRev;\r
881         if (CreateProcess(tortoiseProcPath.c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))\r
882         {\r
883                 CloseHandle(process.hThread);\r
884                 CloseHandle(process.hProcess);\r
885         }\r
886 #endif\r
887 }\r
888 \r
889 void CTortoiseGitBlameView::Notify(SCNotification *notification) \r
890 {\r
891         switch (notification->nmhdr.code) \r
892         {\r
893         case SCN_SAVEPOINTREACHED:\r
894                 break;\r
895 \r
896         case SCN_SAVEPOINTLEFT:\r
897                 break;\r
898         case SCN_PAINTED:\r
899 //              InvalidateRect(wBlame, NULL, FALSE);\r
900 //              InvalidateRect(wLocator, NULL, FALSE);\r
901                 break;\r
902         case SCN_GETBKCOLOR:\r
903 //              if ((m_colorage)&&(notification->line < (int)revs.size()))\r
904 //              {\r
905 //                      notification->lParam = InterColor(DWORD(m_regOldLinesColor), DWORD(m_regNewLinesColor), (revs[notification->line]-m_lowestrev)*100/((m_highestrev-m_lowestrev)+1));\r
906 //              }\r
907                 break;\r
908         }\r
909 }\r
910 \r
911 void CTortoiseGitBlameView::Command(int id)\r
912 {\r
913 #if 0\r
914         switch (id) \r
915         {\r
916 //      case IDM_EXIT:\r
917 //              ::PostQuitMessage(0);\r
918 //              break;\r
919         case ID_EDIT_FIND:\r
920                 StartSearch();\r
921                 break;\r
922         case ID_COPYTOCLIPBOARD:\r
923                 CopySelectedLogToClipboard();\r
924                 break;\r
925         case ID_BLAME_PREVIOUS_REVISION:\r
926                 BlamePreviousRevision();\r
927                 break;\r
928         case ID_DIFF_PREVIOUS_REVISION:\r
929                 DiffPreviousRevision();\r
930                 break;\r
931         case ID_SHOWLOG:\r
932                 ShowLog();\r
933                 break;\r
934         case ID_EDIT_GOTOLINE:\r
935                 GotoLineDlg();\r
936                 break;\r
937         case ID_VIEW_COLORAGEOFLINES:\r
938                 {\r
939                         m_colorage = !m_colorage;\r
940                         HMENU hMenu = GetMenu(wMain);\r
941                         UINT uCheck = MF_BYCOMMAND;\r
942                         uCheck |= m_colorage ? MF_CHECKED : MF_UNCHECKED;\r
943                         CheckMenuItem(hMenu, ID_VIEW_COLORAGEOFLINES, uCheck);\r
944                         m_blamewidth = 0;\r
945                         InitSize();\r
946                 }\r
947                 break;\r
948         case ID_VIEW_MERGEPATH:\r
949                 {\r
950                         ShowPath = !ShowPath;\r
951                         HMENU hMenu = GetMenu(wMain);\r
952                         UINT uCheck = MF_BYCOMMAND;\r
953                         uCheck |= ShowPath ? MF_CHECKED : MF_UNCHECKED;\r
954                         CheckMenuItem(hMenu, ID_VIEW_MERGEPATH, uCheck);\r
955                         m_blamewidth = 0;\r
956                         InitSize();\r
957                 }\r
958         default:\r
959                 break;\r
960         };\r
961 #endif\r
962 }\r
963 \r
964 \r
965 LONG CTortoiseGitBlameView::GetBlameWidth()\r
966 {\r
967         LONG blamewidth = 0;\r
968         SIZE width;\r
969         CreateFont();\r
970         HDC hDC = this->GetDC()->m_hDC;\r
971         HFONT oldfont = (HFONT)::SelectObject(hDC, m_font);\r
972         \r
973         TCHAR buf[MAX_PATH];\r
974 \r
975         int maxnum=0;\r
976         for (unsigned int i=0;i<this->m_ID.size();i++)\r
977         {\r
978                 if(m_ID[i]>maxnum)\r
979                         maxnum=m_ID[i];\r
980         }\r
981         _stprintf_s(buf, MAX_PATH, _T("%d."), maxnum);\r
982         ::GetTextExtentPoint(hDC, buf, _tcslen(buf), &width);\r
983         m_revwidth = width.cx + BLAMESPACE;\r
984         blamewidth += m_revwidth;\r
985 \r
986 #if 0\r
987         _stprintf_s(buf, MAX_PATH, _T("%d"), m_CommitHash.size());\r
988         ::GetTextExtentPoint(hDC, buf, _tcslen(buf), &width);\r
989         m_linewidth = width.cx + BLAMESPACE;\r
990         blamewidth += m_revwidth;\r
991 #endif \r
992 \r
993         if (m_bShowDate)\r
994         {\r
995                 _stprintf_s(buf, MAX_PATH, _T("%30s"), _T("31.08.2001 06:24:14"));\r
996                 ::GetTextExtentPoint32(hDC, buf, _tcslen(buf), &width);\r
997                 m_datewidth = width.cx + BLAMESPACE;\r
998                 blamewidth += m_datewidth;\r
999         }\r
1000         if ( m_bShowAuthor)\r
1001         {\r
1002                 SIZE maxwidth = {0};\r
1003 \r
1004                 for (unsigned int i=0;i<this->m_Authors.size();i++)\r
1005                 //for (std::vector<CString>::iterator I = authors.begin(); I != authors.end(); ++I)\r
1006                 {\r
1007                         ::GetTextExtentPoint32(hDC,m_Authors[i] , m_Authors[i].GetLength(), &width);\r
1008                         if (width.cx > maxwidth.cx)\r
1009                                 maxwidth = width;\r
1010                 }\r
1011                 m_authorwidth = maxwidth.cx + BLAMESPACE;\r
1012                 blamewidth += m_authorwidth;\r
1013         }\r
1014 #if 0\r
1015         if (ShowPath)\r
1016         {\r
1017                 SIZE maxwidth = {0};\r
1018                 for (std::vector<CString>::iterator I = paths.begin(); I != paths.end(); ++I)\r
1019                 {\r
1020                         ::GetTextExtentPoint32(hDC, I->c_str(), I->size(), &width);\r
1021                         if (width.cx > maxwidth.cx)\r
1022                                 maxwidth = width;\r
1023                 }\r
1024                 m_pathwidth = maxwidth.cx + BLAMESPACE;\r
1025                 blamewidth += m_pathwidth;\r
1026         }\r
1027 #endif\r
1028         ::SelectObject(hDC, oldfont);\r
1029         POINT pt = {blamewidth, 0};\r
1030         LPtoDP(hDC, &pt, 1);\r
1031         m_blamewidth = pt.x;\r
1032         //::ReleaseDC(wBlame, hDC);\r
1033 \r
1034         //return m_blamewidth;\r
1035         return blamewidth;\r
1036 \r
1037 }\r
1038 \r
1039 void CTortoiseGitBlameView::CreateFont()\r
1040 {\r
1041         if (m_font)\r
1042                 return;\r
1043         LOGFONT lf = {0};\r
1044         lf.lfWeight = 400;\r
1045         HDC hDC = ::GetDC(wBlame);\r
1046         lf.lfHeight = -MulDiv((DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\BlameFontSize"), 10), GetDeviceCaps(hDC, LOGPIXELSY), 72);\r
1047         lf.lfCharSet = DEFAULT_CHARSET;\r
1048         CRegStdString fontname = CRegStdString(_T("Software\\TortoiseGit\\BlameFontName"), _T("Courier New"));\r
1049         _tcscpy_s(lf.lfFaceName, 32, ((stdstring)fontname).c_str());\r
1050         m_font = ::CreateFontIndirect(&lf);\r
1051 \r
1052         lf.lfItalic = TRUE;\r
1053         m_italicfont = ::CreateFontIndirect(&lf);\r
1054 \r
1055         ::ReleaseDC(wBlame, hDC);\r
1056 \r
1057         //m_TextView.SetFont(lf.lfFaceName,((DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\BlameFontSize"), 10)));\r
1058 }\r
1059 \r
1060 void CTortoiseGitBlameView::DrawBlame(HDC hDC)\r
1061 {\r
1062 \r
1063         if (hDC == NULL)\r
1064                 return;\r
1065         if (m_font == NULL)\r
1066                 return;\r
1067 \r
1068         HFONT oldfont = NULL;\r
1069         LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
1070         LONG_PTR linesonscreen = SendEditor(SCI_LINESONSCREEN);\r
1071         LONG_PTR height = SendEditor(SCI_TEXTHEIGHT);\r
1072         LONG_PTR Y = 0;\r
1073         TCHAR buf[MAX_PATH];\r
1074         RECT rc;\r
1075         BOOL sel = FALSE;\r
1076         //::GetClientRect(this->m_hWnd, &rc);\r
1077         for (LRESULT i=line; i<(line+linesonscreen); ++i)\r
1078         {\r
1079                 sel = FALSE;\r
1080                 if (i < (int)m_CommitHash.size())\r
1081                 {\r
1082                 //      if (mergelines[i])\r
1083                 //              oldfont = (HFONT)::SelectObject(hDC, m_italicfont);\r
1084                 //      else\r
1085                                 oldfont = (HFONT)::SelectObject(hDC, m_font);\r
1086                         ::SetBkColor(hDC, m_windowcolor);\r
1087                         ::SetTextColor(hDC, m_textcolor);\r
1088                         if (m_CommitHash[i].GetLength()>0)\r
1089                         {\r
1090                                 //if (m_CommitHash[i].Compare(m_MouseHash)==0)\r
1091                                 //      ::SetBkColor(hDC, m_mouseauthorcolor);\r
1092                                 if (m_CommitHash[i].Compare(m_SelectedHash)==0)\r
1093                                 {\r
1094                                         ::SetBkColor(hDC, m_selectedauthorcolor);\r
1095                                         ::SetTextColor(hDC, m_texthighlightcolor);\r
1096                                         sel = TRUE;\r
1097                                 }\r
1098                         }\r
1099 \r
1100                         if(m_MouseLine == i)\r
1101                                 ::SetBkColor(hDC, m_mouserevcolor);\r
1102 \r
1103                         //if ((revs[i] == m_mouserev)&&(!sel))\r
1104                         //      ::SetBkColor(hDC, m_mouserevcolor);\r
1105                         //if (revs[i] == m_selectedrev)\r
1106                         //{\r
1107                         //      ::SetBkColor(hDC, m_selectedrevcolor);\r
1108                         //      ::SetTextColor(hDC, m_texthighlightcolor);\r
1109                         //}\r
1110 \r
1111                         CString str;\r
1112                         if(m_ID[i]>=0)\r
1113                                 str.Format(_T("%d"),m_ID[i]);\r
1114 \r
1115                         //_stprintf_s(buf, MAX_PATH, _T("%8ld       "), revs[i]);\r
1116                         rc.top=Y;\r
1117                         rc.left=LOCATOR_WIDTH;          \r
1118                         rc.bottom=Y+height;\r
1119                         rc.right = rc.left + m_blamewidth;\r
1120                         ::ExtTextOut(hDC, LOCATOR_WIDTH, Y, ETO_CLIPPED, &rc, str, str.GetLength(), 0);\r
1121                         int Left = m_revwidth;\r
1122                         \r
1123                         if (m_bShowAuthor)\r
1124                         {\r
1125                                 rc.right = rc.left + Left + m_authorwidth;\r
1126                                 //_stprintf_s(buf, MAX_PATH, _T("%-30s            "), authors[i].c_str());\r
1127                                 ::ExtTextOut(hDC, Left, Y, ETO_CLIPPED, &rc, m_Authors[i], m_Authors[i].GetLength(), 0);\r
1128                                 Left += m_authorwidth;\r
1129                         }\r
1130 #if 0\r
1131                         if (ShowDate)\r
1132                         {\r
1133                                 rc.right = rc.left + Left + m_datewidth;\r
1134                                 _stprintf_s(buf, MAX_PATH, _T("%30s            "), dates[i].c_str());\r
1135                                 ::ExtTextOut(hDC, Left, Y, ETO_CLIPPED, &rc, buf, _tcslen(buf), 0);\r
1136                                 Left += m_datewidth;\r
1137                         }\r
1138                         \r
1139 #endif\r
1140 #if 0\r
1141                         if (ShowPath)\r
1142                         {\r
1143                                 rc.right = rc.left + Left + m_pathwidth;\r
1144                                 _stprintf_s(buf, MAX_PATH, _T("%-60s            "), paths[i].c_str());\r
1145                                 ::ExtTextOut(hDC, Left, Y, ETO_CLIPPED, &rc, buf, _tcslen(buf), 0);\r
1146                                 Left += m_authorwidth;\r
1147                         }\r
1148 #endif\r
1149                         if ((i==m_SelectedLine)&&(m_pFindDialog))\r
1150                         {\r
1151                                 LOGBRUSH brush;\r
1152                                 brush.lbColor = m_textcolor;\r
1153                                 brush.lbHatch = 0;\r
1154                                 brush.lbStyle = BS_SOLID;\r
1155                                 HPEN pen = ExtCreatePen(PS_SOLID | PS_GEOMETRIC, 2, &brush, 0, NULL);\r
1156                                 HGDIOBJ hPenOld = SelectObject(hDC, pen);\r
1157                                 RECT rc2 = rc;\r
1158                                 rc2.top = Y;\r
1159                                 rc2.bottom = Y + height;\r
1160                                 ::MoveToEx(hDC, rc2.left, rc2.top, NULL);\r
1161                                 ::LineTo(hDC, rc2.right, rc2.top);\r
1162                                 ::LineTo(hDC, rc2.right, rc2.bottom);\r
1163                                 ::LineTo(hDC, rc2.left, rc2.bottom);\r
1164                                 ::LineTo(hDC, rc2.left, rc2.top);\r
1165                                 SelectObject(hDC, hPenOld); \r
1166                                 DeleteObject(pen); \r
1167                         }\r
1168                         Y += height;\r
1169                         ::SelectObject(hDC, oldfont);\r
1170                 }\r
1171                 else\r
1172                 {\r
1173                         ::SetBkColor(hDC, m_windowcolor);\r
1174                         for (int j=0; j< MAX_PATH; ++j)\r
1175                                 buf[j]=' ';\r
1176                         ::ExtTextOut(hDC, 0, Y, ETO_CLIPPED, &rc, buf, MAX_PATH-1, 0);\r
1177                         Y += height;\r
1178                 }\r
1179         }\r
1180 }\r
1181 \r
1182 void CTortoiseGitBlameView::DrawHeader(HDC hDC)\r
1183 {\r
1184 #if 0\r
1185         if (hDC == NULL)\r
1186                 return;\r
1187 \r
1188         RECT rc;\r
1189         HFONT oldfont = (HFONT)::SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));\r
1190         ::GetClientRect(wHeader, &rc);\r
1191 \r
1192         ::SetBkColor(hDC, ::GetSysColor(COLOR_BTNFACE));\r
1193 \r
1194         TCHAR szText[MAX_LOADSTRING];\r
1195         LoadString(app.hResource, IDS_HEADER_REVISION, szText, MAX_LOADSTRING);\r
1196         ::ExtTextOut(hDC, LOCATOR_WIDTH, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
1197         int Left = m_revwidth+LOCATOR_WIDTH;\r
1198         if (ShowDate)\r
1199         {\r
1200                 LoadString(app.hResource, IDS_HEADER_DATE, szText, MAX_LOADSTRING);\r
1201                 ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
1202                 Left += m_datewidth;\r
1203         }\r
1204         if (ShowAuthor)\r
1205         {\r
1206                 LoadString(app.hResource, IDS_HEADER_AUTHOR, szText, MAX_LOADSTRING);\r
1207                 ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
1208                 Left += m_authorwidth;\r
1209         }\r
1210         if (ShowPath)\r
1211         {\r
1212                 LoadString(app.hResource, IDS_HEADER_PATH, szText, MAX_LOADSTRING);\r
1213                 ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
1214                 Left += m_pathwidth;\r
1215         }\r
1216         LoadString(app.hResource, IDS_HEADER_LINE, szText, MAX_LOADSTRING);\r
1217         ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
1218 \r
1219         ::SelectObject(hDC, oldfont);\r
1220 #endif\r
1221 }\r
1222 \r
1223 void CTortoiseGitBlameView::DrawLocatorBar(HDC hDC)\r
1224 {\r
1225         if (hDC == NULL)\r
1226                 return;\r
1227 \r
1228         LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
1229         LONG_PTR linesonscreen = SendEditor(SCI_LINESONSCREEN);\r
1230         LONG_PTR Y = 0;\r
1231         COLORREF blackColor = GetSysColor(COLOR_WINDOWTEXT);\r
1232 \r
1233         RECT rc;\r
1234         //::GetClientRect(wLocator, &rc);\r
1235         this->GetClientRect(&rc);\r
1236 \r
1237         rc.right=LOCATOR_WIDTH;\r
1238 \r
1239         RECT lineRect = rc;\r
1240         LONG height = rc.bottom-rc.top;\r
1241         LONG currentLine = 0;\r
1242 \r
1243         // draw the colored bar\r
1244         for (std::vector<LONG>::const_iterator it = m_ID.begin(); it != m_ID.end(); ++it)\r
1245         {\r
1246                 currentLine++;\r
1247                 // get the line color\r
1248                 COLORREF cr = InterColor(DWORD(m_regOldLinesColor), DWORD(m_regNewLinesColor), (*it - m_lowestrev)*100/((m_highestrev-m_lowestrev)+1));\r
1249                 if ((currentLine > line)&&(currentLine <= (line + linesonscreen)))\r
1250                 {\r
1251                         cr = InterColor(cr, blackColor, 10);\r
1252                 }\r
1253                 SetBkColor(hDC, cr);\r
1254                 lineRect.top = Y;\r
1255                 lineRect.bottom = (currentLine * height / m_ID.size());\r
1256                 ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lineRect, NULL, 0, NULL);\r
1257                 Y = lineRect.bottom;\r
1258         }\r
1259 \r
1260         if (m_ID.size())\r
1261         {\r
1262                 // now draw two lines indicating the scroll position of the source view\r
1263                 SetBkColor(hDC, blackColor);\r
1264                 lineRect.top = line * height / m_ID.size();\r
1265                 lineRect.bottom = lineRect.top+1;\r
1266                 ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lineRect, NULL, 0, NULL);\r
1267                 lineRect.top = (line + linesonscreen) * height / m_ID.size();\r
1268                 lineRect.bottom = lineRect.top+1;\r
1269                 ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lineRect, NULL, 0, NULL);\r
1270         }\r
1271 \r
1272 }\r
1273 \r
1274 void CTortoiseGitBlameView::StringExpand(LPSTR str)\r
1275 {\r
1276         char * cPos = str;\r
1277         do\r
1278         {\r
1279                 cPos = strchr(cPos, '\n');\r
1280                 if (cPos)\r
1281                 {\r
1282                         memmove(cPos+1, cPos, strlen(cPos)*sizeof(char));\r
1283                         *cPos = '\r';\r
1284                         cPos++;\r
1285                         cPos++;\r
1286                 }\r
1287         } while (cPos != NULL);\r
1288 }\r
1289 void CTortoiseGitBlameView::StringExpand(LPWSTR str)\r
1290 {\r
1291         wchar_t * cPos = str;\r
1292         do\r
1293         {\r
1294                 cPos = wcschr(cPos, '\n');\r
1295                 if (cPos)\r
1296                 {\r
1297                         memmove(cPos+1, cPos, wcslen(cPos)*sizeof(wchar_t));\r
1298                         *cPos = '\r';\r
1299                         cPos++;\r
1300                         cPos++;\r
1301                 }\r
1302         } while (cPos != NULL);\r
1303 }\r
1304 \r
1305 // Forward declarations of functions included in this code module:\r
1306 ATOM                            MyRegisterClass(HINSTANCE hResource);\r
1307 ATOM                            MyRegisterBlameClass(HINSTANCE hResource);\r
1308 ATOM                            MyRegisterHeaderClass(HINSTANCE hResource);\r
1309 ATOM                            MyRegisterLocatorClass(HINSTANCE hResource);\r
1310 BOOL                            InitInstance(HINSTANCE, int);\r
1311 LRESULT CALLBACK        WndProc(HWND, UINT, WPARAM, LPARAM);\r
1312 LRESULT CALLBACK        WndBlameProc(HWND, UINT, WPARAM, LPARAM);\r
1313 LRESULT CALLBACK        WndHeaderProc(HWND, UINT, WPARAM, LPARAM);\r
1314 LRESULT CALLBACK        WndLocatorProc(HWND, UINT, WPARAM, LPARAM);\r
1315 UINT                            uFindReplaceMsg;\r
1316 \r
1317 #if 0\r
1318 int APIENTRY _tWinMain(HINSTANCE hInstance,\r
1319                      HINSTANCE /*hPrevInstance*/,\r
1320                      LPTSTR    lpCmdLine,\r
1321                      int       nCmdShow)\r
1322 {\r
1323         app.hInstance = hInstance;\r
1324         MSG msg;\r
1325         HACCEL hAccelTable;\r
1326 \r
1327         if (::LoadLibrary("SciLexer.DLL") == NULL)\r
1328                 return FALSE;\r
1329 \r
1330         CRegStdWORD loc = CRegStdWORD(_T("Software\\TortoiseGit\\LanguageID"), 1033);\r
1331         long langId = loc;\r
1332 \r
1333         CLangDll langDLL;\r
1334         app.hResource = langDLL.Init(_T("CTortoiseGitBlameView"), langId);\r
1335         if (app.hResource == NULL)\r
1336                 app.hResource = app.hInstance;\r
1337 \r
1338         // Initialize global strings\r
1339         LoadString(app.hResource, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);\r
1340         LoadString(app.hResource, IDC_TortoiseGitBlameView, szWindowClass, MAX_LOADSTRING);\r
1341         LoadString(app.hResource, IDS_SEARCHNOTFOUND, searchstringnotfound, MAX_LOADSTRING);\r
1342         MyRegisterClass(app.hResource);\r
1343         MyRegisterBlameClass(app.hResource);\r
1344         MyRegisterHeaderClass(app.hResource);\r
1345         MyRegisterLocatorClass(app.hResource);\r
1346 \r
1347         // Perform application initialization:\r
1348         if (!InitInstance (app.hResource, nCmdShow)) \r
1349         {\r
1350                 langDLL.Close();\r
1351                 return FALSE;\r
1352         }\r
1353 \r
1354         SecureZeroMemory(szViewtitle, MAX_PATH);\r
1355         SecureZeroMemory(szOrigPath, MAX_PATH);\r
1356         char blamefile[MAX_PATH] = {0};\r
1357         char logfile[MAX_PATH] = {0};\r
1358 \r
1359         CCmdLineParser parser(lpCmdLine);\r
1360 \r
1361 \r
1362         if (__argc > 1)\r
1363         {\r
1364                 _tcscpy_s(blamefile, MAX_PATH, __argv[1]);\r
1365         }\r
1366         if (__argc > 2)\r
1367         {\r
1368                 _tcscpy_s(logfile, MAX_PATH, __argv[2]);\r
1369         }\r
1370         if (__argc > 3)\r
1371         {\r
1372                 _tcscpy_s(szViewtitle, MAX_PATH, __argv[3]);\r
1373                 if (parser.HasVal(_T("revrange")))\r
1374                 {\r
1375                         _tcscat_s(szViewtitle, MAX_PATH, _T(" : "));\r
1376                         _tcscat_s(szViewtitle, MAX_PATH, parser.GetVal(_T("revrange")));\r
1377                 }\r
1378         }\r
1379         if ((_tcslen(blamefile)==0) || parser.HasKey(_T("?")) || parser.HasKey(_T("help")))\r
1380         {\r
1381                 TCHAR szInfo[MAX_LOADSTRING];\r
1382                 LoadString(app.hResource, IDS_COMMANDLINE_INFO, szInfo, MAX_LOADSTRING);\r
1383                 MessageBox(NULL, szInfo, _T("CTortoiseGitBlameView"), MB_ICONERROR);\r
1384                 langDLL.Close();\r
1385                 return 0;\r
1386         }\r
1387 \r
1388         if ( parser.HasKey(_T("path")) )\r
1389         {\r
1390                 _tcscpy_s(szOrigPath, MAX_PATH, parser.GetVal(_T("path")));\r
1391         }\r
1392         app.bIgnoreEOL = parser.HasKey(_T("ignoreeol"));\r
1393         app.bIgnoreSpaces = parser.HasKey(_T("ignorespaces"));\r
1394         app.bIgnoreAllSpaces = parser.HasKey(_T("ignoreallspaces"));\r
1395 \r
1396         app.SendEditor(SCI_SETCODEPAGE, GetACP());\r
1397         app.OpenFile(blamefile);\r
1398         if (_tcslen(logfile)>0)\r
1399                 app.OpenLogFile(logfile);\r
1400 \r
1401         if (parser.HasKey(_T("line")))\r
1402         {\r
1403                 app.GotoLine(parser.GetLongVal(_T("line")));\r
1404         }\r
1405 \r
1406         CheckMenuItem(GetMenu(app.wMain), ID_VIEW_COLORAGEOFLINES, MF_CHECKED|MF_BYCOMMAND);\r
1407 \r
1408 \r
1409         hAccelTable = LoadAccelerators(app.hResource, (LPCTSTR)IDC_TortoiseGitBlameView);\r
1410 \r
1411         BOOL going = TRUE;\r
1412         msg.wParam = 0;\r
1413         while (going) \r
1414         {\r
1415                 going = GetMessage(&msg, NULL, 0, 0);\r
1416                 if (app.currentDialog && going) \r
1417                 {\r
1418                         if (!IsDialogMessage(app.currentDialog, &msg)) \r
1419                         {\r
1420                                 if (TranslateAccelerator(msg.hwnd, hAccelTable, &msg) == 0) \r
1421                                 {\r
1422                                         TranslateMessage(&msg);\r
1423                                         DispatchMessage(&msg);\r
1424                                 }\r
1425                         }\r
1426                 } \r
1427                 else if (going) \r
1428                 {\r
1429                         if (TranslateAccelerator(app.wMain, hAccelTable, &msg) == 0) \r
1430                         {\r
1431                                 TranslateMessage(&msg);\r
1432                                 DispatchMessage(&msg);\r
1433                         }\r
1434                 }\r
1435         }\r
1436         langDLL.Close();\r
1437         return msg.wParam;\r
1438 }\r
1439 \r
1440 ATOM MyRegisterClass(HINSTANCE hResource)\r
1441 {\r
1442         WNDCLASSEX wcex;\r
1443 \r
1444         wcex.cbSize = sizeof(WNDCLASSEX); \r
1445 \r
1446         wcex.style                      = CS_HREDRAW | CS_VREDRAW;\r
1447         wcex.lpfnWndProc        = (WNDPROC)WndProc;\r
1448         wcex.cbClsExtra         = 0;\r
1449         wcex.cbWndExtra         = 0;\r
1450         wcex.hInstance          = hResource;\r
1451         wcex.hIcon                      = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
1452         wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);\r
1453         wcex.hbrBackground      = (HBRUSH)(COLOR_WINDOW+1);\r
1454         wcex.lpszMenuName       = (LPCTSTR)IDC_TortoiseGitBlameView;\r
1455         wcex.lpszClassName      = szWindowClass;\r
1456         wcex.hIconSm            = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
1457 \r
1458         return RegisterClassEx(&wcex);\r
1459 }\r
1460 \r
1461 ATOM MyRegisterBlameClass(HINSTANCE hResource)\r
1462 {\r
1463         WNDCLASSEX wcex;\r
1464 \r
1465         wcex.cbSize = sizeof(WNDCLASSEX); \r
1466 \r
1467         wcex.style                      = CS_HREDRAW | CS_VREDRAW;\r
1468         wcex.lpfnWndProc        = (WNDPROC)WndBlameProc;\r
1469         wcex.cbClsExtra         = 0;\r
1470         wcex.cbWndExtra         = 0;\r
1471         wcex.hInstance          = hResource;\r
1472         wcex.hIcon                      = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
1473         wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);\r
1474         wcex.hbrBackground      = (HBRUSH)(COLOR_WINDOW+1);\r
1475         wcex.lpszMenuName       = 0;\r
1476         wcex.lpszClassName      = _T("TortoiseGitBlameViewBlame");\r
1477         wcex.hIconSm            = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
1478 \r
1479         return RegisterClassEx(&wcex);\r
1480 }\r
1481 \r
1482 ATOM MyRegisterHeaderClass(HINSTANCE hResource)\r
1483 {\r
1484         WNDCLASSEX wcex;\r
1485 \r
1486         wcex.cbSize = sizeof(WNDCLASSEX); \r
1487 \r
1488         wcex.style                      = CS_HREDRAW | CS_VREDRAW;\r
1489         wcex.lpfnWndProc        = (WNDPROC)WndHeaderProc;\r
1490         wcex.cbClsExtra         = 0;\r
1491         wcex.cbWndExtra         = 0;\r
1492         wcex.hInstance          = hResource;\r
1493         wcex.hIcon                      = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
1494         wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);\r
1495         wcex.hbrBackground      = (HBRUSH)(COLOR_BTNFACE+1);\r
1496         wcex.lpszMenuName       = 0;\r
1497         wcex.lpszClassName      = _T("TortoiseGitBlameViewHeader");\r
1498         wcex.hIconSm            = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
1499 \r
1500         return RegisterClassEx(&wcex);\r
1501 }\r
1502 \r
1503 ATOM MyRegisterLocatorClass(HINSTANCE hResource)\r
1504 {\r
1505         WNDCLASSEX wcex;\r
1506 \r
1507         wcex.cbSize = sizeof(WNDCLASSEX); \r
1508 \r
1509         wcex.style                      = CS_HREDRAW | CS_VREDRAW;\r
1510         wcex.lpfnWndProc        = (WNDPROC)WndLocatorProc;\r
1511         wcex.cbClsExtra         = 0;\r
1512         wcex.cbWndExtra         = 0;\r
1513         wcex.hInstance          = hResource;\r
1514         wcex.hIcon                      = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
1515         wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);\r
1516         wcex.hbrBackground      = (HBRUSH)(COLOR_WINDOW+1);\r
1517         wcex.lpszMenuName       = 0;\r
1518         wcex.lpszClassName      = _T("TortoiseGitBlameViewLocator");\r
1519         wcex.hIconSm            = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
1520 \r
1521         return RegisterClassEx(&wcex);\r
1522 }\r
1523 \r
1524 BOOL InitInstance(HINSTANCE hResource, int nCmdShow)\r
1525 {\r
1526    app.wMain = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,\r
1527       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hResource, NULL);   \r
1528 \r
1529    if (!app.wMain)\r
1530    {\r
1531       return FALSE;\r
1532    }\r
1533 \r
1534    CRegStdWORD pos(_T("Software\\TortoiseGit\\TBlamePos"), 0);\r
1535    CRegStdWORD width(_T("Software\\TortoiseGit\\TBlameSize"), 0);\r
1536    CRegStdWORD state(_T("Software\\TortoiseGit\\TBlameState"), 0);\r
1537    if (DWORD(pos) && DWORD(width))\r
1538    {\r
1539            RECT rc;\r
1540            rc.left = LOWORD(DWORD(pos));\r
1541            rc.top = HIWORD(DWORD(pos));\r
1542            rc.right = rc.left + LOWORD(DWORD(width));\r
1543            rc.bottom = rc.top + HIWORD(DWORD(width));\r
1544            HMONITOR hMon = MonitorFromRect(&rc, MONITOR_DEFAULTTONULL);\r
1545            if (hMon)\r
1546            {\r
1547                    // only restore the window position if the monitor is valid\r
1548                    MoveWindow(app.wMain, LOWORD(DWORD(pos)), HIWORD(DWORD(pos)),\r
1549                            LOWORD(DWORD(width)), HIWORD(DWORD(width)), FALSE);\r
1550            }\r
1551    }\r
1552    if (DWORD(state) == SW_MAXIMIZE)\r
1553            ShowWindow(app.wMain, SW_MAXIMIZE);\r
1554    else\r
1555            ShowWindow(app.wMain, nCmdShow);\r
1556    UpdateWindow(app.wMain);\r
1557 \r
1558    //Create the tooltips\r
1559 \r
1560    INITCOMMONCONTROLSEX iccex; \r
1561    app.hwndTT;                 // handle to the ToolTip control\r
1562    TOOLINFO ti;\r
1563    RECT rect;                  // for client area coordinates\r
1564    iccex.dwICC = ICC_WIN95_CLASSES;\r
1565    iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);\r
1566    InitCommonControlsEx(&iccex);\r
1567 \r
1568    /* CREATE A TOOLTIP WINDOW */\r
1569    app.hwndTT = CreateWindowEx(WS_EX_TOPMOST,\r
1570            TOOLTIPS_CLASS,\r
1571            NULL,\r
1572            WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,             \r
1573            CW_USEDEFAULT,\r
1574            CW_USEDEFAULT,\r
1575            CW_USEDEFAULT,\r
1576            CW_USEDEFAULT,\r
1577            app.wBlame,\r
1578            NULL,\r
1579            app.hResource,\r
1580            NULL\r
1581            );\r
1582 \r
1583    SetWindowPos(app.hwndTT,\r
1584            HWND_TOPMOST,\r
1585            0,\r
1586            0,\r
1587            0,\r
1588            0,\r
1589            SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);\r
1590 \r
1591    /* GET COORDINATES OF THE MAIN CLIENT AREA */\r
1592    GetClientRect (app.wBlame, &rect);\r
1593 \r
1594    /* INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE */\r
1595    ti.cbSize = sizeof(TOOLINFO);\r
1596    ti.uFlags = TTF_TRACK | TTF_ABSOLUTE;//TTF_SUBCLASS | TTF_PARSELINKS;\r
1597    ti.hwnd = app.wBlame;\r
1598    ti.hinst = app.hResource;\r
1599    ti.uId = 0;\r
1600    ti.lpszText = LPSTR_TEXTCALLBACK;\r
1601    // ToolTip control will cover the whole window\r
1602    ti.rect.left = rect.left;    \r
1603    ti.rect.top = rect.top;\r
1604    ti.rect.right = rect.right;\r
1605    ti.rect.bottom = rect.bottom;\r
1606 \r
1607    /* SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW */\r
1608    SendMessage(app.hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);  \r
1609    SendMessage(app.hwndTT, TTM_SETMAXTIPWIDTH, 0, 600);\r
1610    //SendMessage(app.hwndTT, TTM_SETDELAYTIME, TTDT_AUTOPOP, MAKELONG(50000, 0));\r
1611    //SendMessage(app.hwndTT, TTM_SETDELAYTIME, TTDT_RESHOW, MAKELONG(1000, 0));\r
1612    \r
1613    uFindReplaceMsg = RegisterWindowMessage(FINDMSGSTRING);\r
1614    \r
1615    return TRUE;\r
1616 }\r
1617 #endif\r
1618 void CTortoiseGitBlameView::InitSize()\r
1619 {\r
1620     RECT rc;\r
1621     RECT blamerc;\r
1622     RECT sourcerc;\r
1623     ::GetClientRect(wMain, &rc);\r
1624     ::SetWindowPos(wHeader, 0, rc.left, rc.top, rc.right-rc.left, HEADER_HEIGHT, 0);\r
1625     rc.top += HEADER_HEIGHT;\r
1626     blamerc.left = rc.left;\r
1627     blamerc.top = rc.top;\r
1628         LONG w = GetBlameWidth();\r
1629     blamerc.right = w > abs(rc.right - rc.left) ? rc.right : w + rc.left;\r
1630     blamerc.bottom = rc.bottom;\r
1631     sourcerc.left = blamerc.right;\r
1632     sourcerc.top = rc.top;\r
1633     sourcerc.bottom = rc.bottom;\r
1634     sourcerc.right = rc.right;\r
1635         if (m_colorage)\r
1636         {\r
1637                 ::OffsetRect(&blamerc, LOCATOR_WIDTH, 0);\r
1638                 ::OffsetRect(&sourcerc, LOCATOR_WIDTH, 0);\r
1639                 sourcerc.right -= LOCATOR_WIDTH;\r
1640         }\r
1641         ::InvalidateRect(wMain, NULL, FALSE);\r
1642     ::SetWindowPos(m_wEditor, 0, sourcerc.left, sourcerc.top, sourcerc.right - sourcerc.left, sourcerc.bottom - sourcerc.top, 0);\r
1643         ::SetWindowPos(wBlame, 0, blamerc.left, blamerc.top, blamerc.right - blamerc.left, blamerc.bottom - blamerc.top, 0);\r
1644         if (m_colorage)\r
1645                 ::SetWindowPos(wLocator, 0, 0, blamerc.top, LOCATOR_WIDTH, blamerc.bottom - blamerc.top, SWP_SHOWWINDOW);\r
1646         else\r
1647                 ::ShowWindow(wLocator, SW_HIDE);\r
1648 }\r
1649 \r
1650 #if 0\r
1651 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
1652 {\r
1653         if (message == uFindReplaceMsg)\r
1654         {\r
1655                 LPFINDREPLACE lpfr = (LPFINDREPLACE)lParam;\r
1656 \r
1657                 // If the FR_DIALOGTERM flag is set, \r
1658                 // invalidate the handle identifying the dialog box. \r
1659                 if (lpfr->Flags & FR_DIALOGTERM)\r
1660                 {\r
1661                         app.currentDialog = NULL; \r
1662                         return 0; \r
1663                 } \r
1664                 if (lpfr->Flags & FR_FINDNEXT)\r
1665                 {\r
1666                         app.DoSearch(lpfr->lpstrFindWhat, lpfr->Flags);\r
1667                 }\r
1668                 return 0; \r
1669         }\r
1670         switch (message) \r
1671         {\r
1672         case WM_CREATE:\r
1673                 app.m_wEditor = ::CreateWindow(\r
1674                         "Scintilla",\r
1675                         "Source",\r
1676                         WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_CLIPCHILDREN,\r
1677                         0, 0,\r
1678                         100, 100,\r
1679                         hWnd,\r
1680                         0,\r
1681                         app.hResource,\r
1682                         0);\r
1683                 app.InitialiseEditor();\r
1684                 ::ShowWindow(app.m_wEditor, SW_SHOW);\r
1685                 ::SetFocus(app.m_wEditor);\r
1686                 app.wBlame = ::CreateWindow(\r
1687                         _T("TortoiseGitBlameViewBlame"), \r
1688                         _T("blame"), \r
1689                         WS_CHILD | WS_CLIPCHILDREN,\r
1690                         CW_USEDEFAULT, 0, \r
1691                         CW_USEDEFAULT, 0, \r
1692                         hWnd, \r
1693                         NULL, \r
1694                         app.hResource, \r
1695                         NULL);\r
1696                 ::ShowWindow(app.wBlame, SW_SHOW);\r
1697                 app.wHeader = ::CreateWindow(\r
1698                         _T("TortoiseGitBlameViewHeader"), \r
1699                         _T("header"), \r
1700                         WS_CHILD | WS_CLIPCHILDREN | WS_BORDER,\r
1701                         CW_USEDEFAULT, 0, \r
1702                         CW_USEDEFAULT, 0, \r
1703                         hWnd, \r
1704                         NULL, \r
1705                         app.hResource, \r
1706                         NULL);\r
1707                 ::ShowWindow(app.wHeader, SW_SHOW);\r
1708                 app.wLocator = ::CreateWindow(\r
1709                         _T("TortoiseGitBlameViewLocator"), \r
1710                         _T("locator"), \r
1711                         WS_CHILD | WS_CLIPCHILDREN | WS_BORDER,\r
1712                         CW_USEDEFAULT, 0, \r
1713                         CW_USEDEFAULT, 0, \r
1714                         hWnd, \r
1715                         NULL, \r
1716                         app.hResource, \r
1717                         NULL);\r
1718                 ::ShowWindow(app.wLocator, SW_SHOW);\r
1719                 return 0;\r
1720 \r
1721         case WM_SIZE:\r
1722                 if (wParam != 1) \r
1723                 {\r
1724             app.InitSize();\r
1725                 }\r
1726                 return 0;\r
1727 \r
1728         case WM_COMMAND:\r
1729                 app.Command(LOWORD(wParam));\r
1730                 break;\r
1731         case WM_NOTIFY:\r
1732                 app.Notify(reinterpret_cast<SCNotification *>(lParam));\r
1733                 return 0;\r
1734         case WM_DESTROY:\r
1735                 PostQuitMessage(0);\r
1736                 break;\r
1737         case WM_CLOSE:\r
1738                 {\r
1739                         CRegStdWORD pos(_T("Software\\TortoiseGit\\TBlamePos"), 0);\r
1740                         CRegStdWORD width(_T("Software\\TortoiseGit\\TBlameSize"), 0);\r
1741                         CRegStdWORD state(_T("Software\\TortoiseGit\\TBlameState"), 0);\r
1742                         RECT rc;\r
1743                         GetWindowRect(app.wMain, &rc);\r
1744                         if ((rc.left >= 0)&&(rc.top >= 0))\r
1745                         {\r
1746                                 pos = MAKELONG(rc.left, rc.top);\r
1747                                 width = MAKELONG(rc.right-rc.left, rc.bottom-rc.top);\r
1748                         }\r
1749                         WINDOWPLACEMENT wp = {0};\r
1750                         wp.length = sizeof(WINDOWPLACEMENT);\r
1751                         GetWindowPlacement(app.wMain, &wp);\r
1752                         state = wp.showCmd;\r
1753                         ::DestroyWindow(app.m_wEditor);\r
1754                         ::PostQuitMessage(0);\r
1755                 }\r
1756                 return 0;\r
1757         case WM_SETFOCUS:\r
1758                 ::SetFocus(app.wBlame);\r
1759                 break;\r
1760         default:\r
1761                 return DefWindowProc(hWnd, message, wParam, lParam);\r
1762         }\r
1763         return 0;\r
1764 }\r
1765 \r
1766 LRESULT CALLBACK WndBlameProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
1767 {\r
1768         PAINTSTRUCT ps;\r
1769         TRACKMOUSEEVENT mevt;\r
1770         HDC hDC;\r
1771         switch (message) \r
1772         {\r
1773         case WM_CREATE:\r
1774                 return 0;\r
1775         case WM_PAINT:\r
1776                 hDC = BeginPaint(app.wBlame, &ps);\r
1777                 app.DrawBlame(hDC);\r
1778                 EndPaint(app.wBlame, &ps);\r
1779                 break;\r
1780         case WM_COMMAND:\r
1781                 app.Command(LOWORD(wParam));\r
1782                 break;\r
1783         case WM_NOTIFY:\r
1784                 switch (((LPNMHDR)lParam)->code)\r
1785                 {\r
1786                 case TTN_GETDISPINFO:\r
1787                         {\r
1788                                 LPNMHDR pNMHDR = (LPNMHDR)lParam;\r
1789                                 NMTTDISPINFOA* pTTTA = (NMTTDISPINFOA*)pNMHDR;\r
1790                                 NMTTDISPINFOW* pTTTW = (NMTTDISPINFOW*)pNMHDR;\r
1791                                 POINT point;\r
1792                                 DWORD ptW = GetMessagePos();\r
1793                                 point.x = GET_X_LPARAM(ptW);\r
1794                                 point.y = GET_Y_LPARAM(ptW);\r
1795                                 ::ScreenToClient(app.wBlame, &point);\r
1796                                 LONG_PTR line = app.SendEditor(SCI_GETFIRSTVISIBLELINE);\r
1797                                 LONG_PTR height = app.SendEditor(SCI_TEXTHEIGHT);\r
1798                                 line = line + (point.y/height);\r
1799                                 if (line >= (LONG)app.revs.size())\r
1800                                         break;\r
1801                                 if (line < 0)\r
1802                                         break;\r
1803                                 LONG rev = app.revs[line];\r
1804                                 if (line >= (LONG)app.revs.size())\r
1805                                         break;\r
1806 \r
1807                                 SecureZeroMemory(app.m_szTip, sizeof(app.m_szTip));\r
1808                                 SecureZeroMemory(app.m_wszTip, sizeof(app.m_wszTip));\r
1809                                 std::map<LONG, CString>::iterator iter;\r
1810                                 if ((iter = app.logmessages.find(rev)) != app.logmessages.end())\r
1811                                 {\r
1812                                         CString msg;\r
1813                                         if (!ShowAuthor)\r
1814                                         {\r
1815                                                 msg += app.authors[line];\r
1816                                         }\r
1817                                         if (!ShowDate)\r
1818                                         {\r
1819                                                 if (!ShowAuthor) msg += "  ";\r
1820                                                 msg += app.dates[line];\r
1821                                         }\r
1822                                         if (!ShowAuthor || !ShowDate)\r
1823                                                 msg += '\n';\r
1824                                         msg += iter->second;\r
1825                                         // an empty tooltip string will deactivate the tooltips,\r
1826                                         // which means we must make sure that the tooltip won't\r
1827                                         // be empty.\r
1828                                         if (msg.empty())\r
1829                                                 msg = _T(" ");\r
1830                                         if (pNMHDR->code == TTN_NEEDTEXTA)\r
1831                                         {\r
1832                                                 lstrcpyn(app.m_szTip, msg.c_str(), MAX_LOG_LENGTH*2);\r
1833                                                 app.StringExpand(app.m_szTip);\r
1834                                                 pTTTA->lpszText = app.m_szTip;\r
1835                                         }\r
1836                                         else\r
1837                                         {\r
1838                                                 pTTTW->lpszText = app.m_wszTip;\r
1839                                                 ::MultiByteToWideChar( CP_ACP , 0, msg.c_str(), min(msg.size(), MAX_LOG_LENGTH*2), app.m_wszTip, MAX_LOG_LENGTH*2);\r
1840                                                 app.StringExpand(app.m_wszTip);\r
1841                                         }\r
1842                                 }\r
1843                         }\r
1844                         break;\r
1845                 }\r
1846                 return 0;\r
1847         case WM_DESTROY:\r
1848                 break;\r
1849         case WM_CLOSE:\r
1850                 return 0;\r
1851         case WM_MOUSELEAVE:\r
1852                 app.m_mouserev = -2;\r
1853                 app.m_mouseauthor.clear();\r
1854                 app.ttVisible = FALSE;\r
1855                 SendMessage(app.hwndTT, TTM_TRACKACTIVATE, FALSE, 0);\r
1856                 ::InvalidateRect(app.wBlame, NULL, FALSE);\r
1857                 break;\r
1858         case WM_MOUSEMOVE:\r
1859                 {\r
1860                         mevt.cbSize = sizeof(TRACKMOUSEEVENT);\r
1861                         mevt.dwFlags = TME_LEAVE;\r
1862                         mevt.dwHoverTime = HOVER_DEFAULT;\r
1863                         mevt.hwndTrack = app.wBlame;\r
1864                         ::TrackMouseEvent(&mevt);\r
1865                         POINT pt = {((int)(short)LOWORD(lParam)), ((int)(short)HIWORD(lParam))};\r
1866                         ClientToScreen(app.wBlame, &pt);\r
1867                         pt.x += 15;\r
1868                         pt.y += 15;\r
1869                         SendMessage(app.hwndTT, TTM_TRACKPOSITION, 0, MAKELONG(pt.x, pt.y));\r
1870                         if (!app.ttVisible)\r
1871                         {\r
1872                                 TOOLINFO ti;\r
1873                                 ti.cbSize = sizeof(TOOLINFO);\r
1874                                 ti.hwnd = app.wBlame;\r
1875                                 ti.uId = 0;\r
1876                                 SendMessage(app.hwndTT, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti);\r
1877                         }\r
1878                         int y = ((int)(short)HIWORD(lParam));\r
1879                         LONG_PTR line = app.SendEditor(SCI_GETFIRSTVISIBLELINE);\r
1880                         LONG_PTR height = app.SendEditor(SCI_TEXTHEIGHT);\r
1881                         line = line + (y/height);\r
1882                         app.ttVisible = (line < (LONG)app.revs.size());\r
1883                         if ( app.ttVisible )\r
1884                         {\r
1885                                 if (app.authors[line].compare(app.m_mouseauthor) != 0)\r
1886                                 {\r
1887                                         app.m_mouseauthor = app.authors[line];\r
1888                                 }\r
1889                                 if (app.revs[line] != app.m_mouserev)\r
1890                                 {\r
1891                                         app.m_mouserev = app.revs[line];\r
1892                                         ::InvalidateRect(app.wBlame, NULL, FALSE);\r
1893                                         SendMessage(app.hwndTT, TTM_UPDATE, 0, 0);\r
1894                                 }\r
1895                         }\r
1896                 }\r
1897                 break;\r
1898         case WM_RBUTTONDOWN:\r
1899                 // fall through\r
1900         case WM_LBUTTONDOWN:\r
1901                 {\r
1902                 break;\r
1903         case WM_SETFOCUS:\r
1904                 ::SetFocus(app.wBlame);\r
1905                 app.SendEditor(SCI_GRABFOCUS);\r
1906                 break;\r
1907         case WM_CONTEXTMENU:\r
1908                 {\r
1909                         if (app.m_selectedrev <= 0)\r
1910                                 break;;\r
1911                         int xPos = GET_X_LPARAM(lParam);\r
1912                         int yPos = GET_Y_LPARAM(lParam);\r
1913                         if ((xPos < 0)||(yPos < 0))\r
1914                         {\r
1915                                 // requested from keyboard, not mouse pointer\r
1916                                 // use the center of the window\r
1917                                 RECT rect;\r
1918                                 GetClientRect(app.wBlame, &rect);\r
1919                                 xPos = rect.right-rect.left;\r
1920                                 yPos = rect.bottom-rect.top;\r
1921                         }\r
1922                         HMENU hMenu = LoadMenu(app.hResource, MAKEINTRESOURCE(IDR_BLAMEPOPUP));\r
1923                         HMENU hPopMenu = GetSubMenu(hMenu, 0);\r
1924 \r
1925                         if ( _tcslen(szOrigPath)==0 )\r
1926                         {\r
1927                                 // Without knowing the original path we cannot blame the previous revision\r
1928                                 // because we don't know which filename to pass to tortoiseproc.\r
1929                                 EnableMenuItem(hPopMenu,ID_BLAME_PREVIOUS_REVISION, MF_DISABLED|MF_GRAYED);\r
1930                         }\r
1931                         \r
1932                         TrackPopupMenu(hPopMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, xPos, yPos, 0, app.wBlame, NULL); \r
1933                         DestroyMenu(hMenu);\r
1934                 }\r
1935                 break;\r
1936         default:\r
1937                 return DefWindowProc(hWnd, message, wParam, lParam);\r
1938         }\r
1939         return 0;\r
1940 }\r
1941 \r
1942 LRESULT CALLBACK WndHeaderProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
1943 {\r
1944         PAINTSTRUCT ps;\r
1945         HDC hDC;\r
1946         switch (message) \r
1947         {\r
1948         case WM_CREATE:\r
1949                 return 0;\r
1950         case WM_PAINT:\r
1951                 hDC = BeginPaint(app.wHeader, &ps);\r
1952                 app.DrawHeader(hDC);\r
1953                 EndPaint(app.wHeader, &ps);\r
1954                 break;\r
1955         case WM_COMMAND:\r
1956                 break;\r
1957         case WM_DESTROY:\r
1958                 break;\r
1959         case WM_CLOSE:\r
1960                 return 0;\r
1961         default:\r
1962                 return DefWindowProc(hWnd, message, wParam, lParam);\r
1963         }\r
1964         return 0;\r
1965 }\r
1966 \r
1967 LRESULT CALLBACK WndLocatorProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
1968 {\r
1969         PAINTSTRUCT ps;\r
1970         HDC hDC;\r
1971         switch (message) \r
1972         {\r
1973         case WM_PAINT:\r
1974                 hDC = BeginPaint(app.wLocator, &ps);\r
1975                 app.DrawLocatorBar(hDC);\r
1976                 EndPaint(app.wLocator, &ps);\r
1977                 break;\r
1978         case WM_LBUTTONDOWN:\r
1979         case WM_MOUSEMOVE:\r
1980                 if (wParam & MK_LBUTTON)\r
1981                 {\r
1982                         RECT rect;\r
1983                         ::GetClientRect(hWnd, &rect); \r
1984                         int nLine = HIWORD(lParam)*app.revs.size()/(rect.bottom-rect.top);\r
1985 \r
1986                         if (nLine < 0)\r
1987                                 nLine = 0;\r
1988                         app.ScrollToLine(nLine);\r
1989                 }\r
1990                 break;\r
1991         default:\r
1992                 return DefWindowProc(hWnd, message, wParam, lParam);\r
1993         }\r
1994         return 0;\r
1995 }\r
1996 #endif\r
1997 \r
1998 void CTortoiseGitBlameView::SetupLexer(CString filename)\r
1999 {\r
2000 \r
2001         TCHAR *line;\r
2002         //const char * lineptr = _tcsrchr(filename, '.');\r
2003         int start=filename.ReverseFind(_T('.'));\r
2004         if (start>0)\r
2005         {\r
2006                 //_tcscpy_s(line, 20, lineptr+1);\r
2007                 //_tcslwr_s(line, 20);\r
2008                 CString ext=filename.Right(filename.GetLength()-start-1);\r
2009                 line=ext.GetBuffer();\r
2010 \r
2011                 if ((_tcscmp(line, _T("py"))==0)||\r
2012                         (_tcscmp(line, _T("pyw"))==0)||\r
2013                         (_tcscmp(line, _T("pyw"))==0))\r
2014                 {\r
2015                         SendEditor(SCI_SETLEXER, SCLEX_PYTHON);\r
2016                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("and assert break class continue def del elif \\r
2017 else except exec finally for from global if import in is lambda None \\r
2018 not or pass print raise return try while yield")).GetBuffer()));\r
2019                         SetAStyle(SCE_P_DEFAULT, black);\r
2020                         SetAStyle(SCE_P_COMMENTLINE, darkGreen);\r
2021                         SetAStyle(SCE_P_NUMBER, RGB(0, 0x80, 0x80));\r
2022                         SetAStyle(SCE_P_STRING, RGB(0, 0, 0x80));\r
2023                         SetAStyle(SCE_P_CHARACTER, RGB(0, 0, 0x80));\r
2024                         SetAStyle(SCE_P_WORD, RGB(0x80, 0, 0x80));\r
2025                         SetAStyle(SCE_P_TRIPLE, black);\r
2026                         SetAStyle(SCE_P_TRIPLEDOUBLE, black);\r
2027                         SetAStyle(SCE_P_CLASSNAME, darkBlue);\r
2028                         SetAStyle(SCE_P_DEFNAME, darkBlue);\r
2029                         SetAStyle(SCE_P_OPERATOR, darkBlue);\r
2030                         SetAStyle(SCE_P_IDENTIFIER, darkBlue);\r
2031                         SetAStyle(SCE_P_COMMENTBLOCK, darkGreen);\r
2032                         SetAStyle(SCE_P_STRINGEOL, red);\r
2033                 }\r
2034                 if ((_tcscmp(line, _T("c"))==0)||\r
2035                         (_tcscmp(line, _T("cc"))==0)||\r
2036                         (_tcscmp(line, _T("cpp"))==0)||\r
2037                         (_tcscmp(line, _T("cxx"))==0)||\r
2038                         (_tcscmp(line, _T("h"))==0)||\r
2039                         (_tcscmp(line, _T("hh"))==0)||\r
2040                         (_tcscmp(line, _T("hpp"))==0)||\r
2041                         (_tcscmp(line, _T("hxx"))==0)||\r
2042                         (_tcscmp(line, _T("dlg"))==0)||\r
2043                         (_tcscmp(line, _T("mak"))==0))\r
2044                 {\r
2045                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2046                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("and and_eq asm auto bitand bitor bool break \\r
2047 case catch char class compl const const_cast continue \\r
2048 default delete do double dynamic_cast else enum explicit export extern false float for \\r
2049 friend goto if inline int long mutable namespace new not not_eq \\r
2050 operator or or_eq private protected public \\r
2051 register reinterpret_cast return short signed sizeof static static_cast struct switch \\r
2052 template this throw true try typedef typeid typename union unsigned using \\r
2053 virtual void volatile wchar_t while xor xor_eq")).GetBuffer()));\r
2054                         SendEditor(SCI_SETKEYWORDS, 3, (LPARAM)(m_TextView.StringForControl(_T("a addindex addtogroup anchor arg attention \\r
2055 author b brief bug c class code date def defgroup deprecated dontinclude \\r
2056 e em endcode endhtmlonly endif endlatexonly endlink endverbatim enum example exception \\r
2057 f$ f[ f] file fn hideinitializer htmlinclude htmlonly \\r
2058 if image include ingroup internal invariant interface latexonly li line link \\r
2059 mainpage name namespace nosubgrouping note overload \\r
2060 p page par param post pre ref relates remarks return retval \\r
2061 sa section see showinitializer since skip skipline struct subsection \\r
2062 test throw todo typedef union until \\r
2063 var verbatim verbinclude version warning weakgroup $ @ \\ & < > # { }")).GetBuffer()));\r
2064                         SetupCppLexer();\r
2065                 }\r
2066                 if (_tcscmp(line, _T("cs"))==0)\r
2067                 {\r
2068                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2069                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("abstract as base bool break byte case catch char checked class \\r
2070 const continue decimal default delegate do double else enum \\r
2071 event explicit extern false finally fixed float for foreach goto if \\r
2072 implicit in int interface internal is lock long namespace new null \\r
2073 object operator out override params private protected public \\r
2074 readonly ref return sbyte sealed short sizeof stackalloc static \\r
2075 string struct switch this throw true try typeof uint ulong \\r
2076 unchecked unsafe ushort using virtual void while")).GetBuffer()));\r
2077                         SetupCppLexer();\r
2078                 }\r
2079                 if ((_tcscmp(line, _T("rc"))==0)||\r
2080                         (_tcscmp(line, _T("rc2"))==0))\r
2081                 {\r
2082                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2083                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("ACCELERATORS ALT AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON \\r
2084 BEGIN BITMAP BLOCK BUTTON CAPTION CHARACTERISTICS CHECKBOX CLASS \\r
2085 COMBOBOX CONTROL CTEXT CURSOR DEFPUSHBUTTON DIALOG DIALOGEX DISCARDABLE \\r
2086 EDITTEXT END EXSTYLE FONT GROUPBOX ICON LANGUAGE LISTBOX LTEXT \\r
2087 MENU MENUEX MENUITEM MESSAGETABLE POPUP \\r
2088 PUSHBUTTON RADIOBUTTON RCDATA RTEXT SCROLLBAR SEPARATOR SHIFT STATE3 \\r
2089 STRINGTABLE STYLE TEXTINCLUDE VALUE VERSION VERSIONINFO VIRTKEY")).GetBuffer()));\r
2090                         SetupCppLexer();\r
2091                 }\r
2092                 if ((_tcscmp(line, _T("idl"))==0)||\r
2093                         (_tcscmp(line, _T("odl"))==0))\r
2094                 {\r
2095                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2096                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("aggregatable allocate appobject arrays async async_uuid \\r
2097 auto_handle \\r
2098 bindable boolean broadcast byte byte_count \\r
2099 call_as callback char coclass code comm_status \\r
2100 const context_handle context_handle_noserialize \\r
2101 context_handle_serialize control cpp_quote custom \\r
2102 decode default defaultbind defaultcollelem \\r
2103 defaultvalue defaultvtable dispinterface displaybind dllname \\r
2104 double dual \\r
2105 enable_allocate encode endpoint entry enum error_status_t \\r
2106 explicit_handle \\r
2107 fault_status first_is float \\r
2108 handle_t heap helpcontext helpfile helpstring \\r
2109 helpstringcontext helpstringdll hidden hyper \\r
2110 id idempotent ignore iid_as iid_is immediatebind implicit_handle \\r
2111 import importlib in include in_line int __int64 __int3264 interface \\r
2112 last_is lcid length_is library licensed local long \\r
2113 max_is maybe message methods midl_pragma \\r
2114 midl_user_allocate midl_user_free min_is module ms_union \\r
2115 ncacn_at_dsp ncacn_dnet_nsp ncacn_http ncacn_ip_tcp \\r
2116 ncacn_nb_ipx ncacn_nb_nb ncacn_nb_tcp ncacn_np \\r
2117 ncacn_spx ncacn_vns_spp ncadg_ip_udp ncadg_ipx ncadg_mq \\r
2118 ncalrpc nocode nonbrowsable noncreatable nonextensible notify \\r
2119 object odl oleautomation optimize optional out out_of_line \\r
2120 pipe pointer_default pragma properties propget propput propputref \\r
2121 ptr public \\r
2122 range readonly ref represent_as requestedit restricted retval \\r
2123 shape short signed size_is small source strict_context_handle \\r
2124 string struct switch switch_is switch_type \\r
2125 transmit_as typedef \\r
2126 uidefault union unique unsigned user_marshal usesgetlasterror uuid \\r
2127 v1_enum vararg version void wchar_t wire_marshal")).GetBuffer()));\r
2128                         SetupCppLexer();\r
2129                 }\r
2130                 if (_tcscmp(line, _T("java"))==0)\r
2131                 {\r
2132                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2133                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("abstract assert boolean break byte case catch char class \\r
2134 const continue default do double else extends final finally float for future \\r
2135 generic goto if implements import inner instanceof int interface long \\r
2136 native new null outer package private protected public rest \\r
2137 return short static super switch synchronized this throw throws \\r
2138 transient try var void volatile while")).GetBuffer()));\r
2139                         SetupCppLexer();\r
2140                 }\r
2141                 if (_tcscmp(line, _T("js"))==0)\r
2142                 {\r
2143                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2144                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("abstract boolean break byte case catch char class \\r
2145 const continue debugger default delete do double else enum export extends \\r
2146 final finally float for function goto if implements import in instanceof \\r
2147 int interface long native new package private protected public \\r
2148 return short static super switch synchronized this throw throws \\r
2149 transient try typeof var void volatile while with")).GetBuffer()));\r
2150                         SetupCppLexer();\r
2151                 }\r
2152                 if ((_tcscmp(line, _T("pas"))==0)||\r
2153                         (_tcscmp(line, _T("dpr"))==0)||\r
2154                         (_tcscmp(line, _T("pp"))==0))\r
2155                 {\r
2156                         SendEditor(SCI_SETLEXER, SCLEX_PASCAL);\r
2157                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("and array as begin case class const constructor \\r
2158 destructor div do downto else end except file finally \\r
2159 for function goto if implementation in inherited \\r
2160 interface is mod not object of on or packed \\r
2161 procedure program property raise record repeat \\r
2162 set shl shr then threadvar to try type unit \\r
2163 until uses var while with xor")).GetBuffer()));\r
2164                         SetupCppLexer();\r
2165                 }\r
2166                 if ((_tcscmp(line, _T("as"))==0)||\r
2167                         (_tcscmp(line, _T("asc"))==0)||\r
2168                         (_tcscmp(line, _T("jsfl"))==0))\r
2169                 {\r
2170                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2171                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("add and break case catch class continue default delete do \\r
2172 dynamic else eq extends false finally for function ge get gt if implements import in \\r
2173 instanceof interface intrinsic le lt ne new not null or private public return \\r
2174 set static super switch this throw true try typeof undefined var void while with")).GetBuffer()));\r
2175                         SendEditor(SCI_SETKEYWORDS, 1, (LPARAM)(m_TextView.StringForControl(_T("Array Arguments Accessibility Boolean Button Camera Color \\r
2176 ContextMenu ContextMenuItem Date Error Function Key LoadVars LocalConnection Math \\r
2177 Microphone Mouse MovieClip MovieClipLoader NetConnection NetStream Number Object \\r
2178 PrintJob Selection SharedObject Sound Stage String StyleSheet System TextField \\r
2179 TextFormat TextSnapshot Video Void XML XMLNode XMLSocket \\r
2180 _accProps _focusrect _global _highquality _parent _quality _root _soundbuftime \\r
2181 arguments asfunction call capabilities chr clearInterval duplicateMovieClip \\r
2182 escape eval fscommand getProperty getTimer getURL getVersion gotoAndPlay gotoAndStop \\r
2183 ifFrameLoaded Infinity -Infinity int isFinite isNaN length loadMovie loadMovieNum \\r
2184 loadVariables loadVariablesNum maxscroll mbchr mblength mbord mbsubstring MMExecute \\r
2185 NaN newline nextFrame nextScene on onClipEvent onUpdate ord parseFloat parseInt play \\r
2186 prevFrame prevScene print printAsBitmap printAsBitmapNum printNum random removeMovieClip \\r
2187 scroll set setInterval setProperty startDrag stop stopAllSounds stopDrag substring \\r
2188 targetPath tellTarget toggleHighQuality trace unescape unloadMovie unLoadMovieNum updateAfterEvent")).GetBuffer()));\r
2189                         SetupCppLexer();\r
2190                 }\r
2191                 if ((_tcscmp(line, _T("html"))==0)||\r
2192                         (_tcscmp(line, _T("htm"))==0)||\r
2193                         (_tcscmp(line, _T("shtml"))==0)||\r
2194                         (_tcscmp(line, _T("htt"))==0)||\r
2195                         (_tcscmp(line, _T("xml"))==0)||\r
2196                         (_tcscmp(line, _T("asp"))==0)||\r
2197                         (_tcscmp(line, _T("xsl"))==0)||\r
2198                         (_tcscmp(line, _T("php"))==0)||\r
2199                         (_tcscmp(line, _T("xhtml"))==0)||\r
2200                         (_tcscmp(line, _T("phtml"))==0)||\r
2201                         (_tcscmp(line, _T("cfm"))==0)||\r
2202                         (_tcscmp(line, _T("tpl"))==0)||\r
2203                         (_tcscmp(line, _T("dtd"))==0)||\r
2204                         (_tcscmp(line, _T("hta"))==0)||\r
2205                         (_tcscmp(line, _T("htd"))==0)||\r
2206                         (_tcscmp(line, _T("wxs"))==0))\r
2207                 {\r
2208                         SendEditor(SCI_SETLEXER, SCLEX_HTML);\r
2209                         SendEditor(SCI_SETSTYLEBITS, 7);\r
2210                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("a abbr acronym address applet area b base basefont \\r
2211 bdo big blockquote body br button caption center \\r
2212 cite code col colgroup dd del dfn dir div dl dt em \\r
2213 fieldset font form frame frameset h1 h2 h3 h4 h5 h6 \\r
2214 head hr html i iframe img input ins isindex kbd label \\r
2215 legend li link map menu meta noframes noscript \\r
2216 object ol optgroup option p param pre q s samp \\r
2217 script select small span strike strong style sub sup \\r
2218 table tbody td textarea tfoot th thead title tr tt u ul \\r
2219 var xml xmlns abbr accept-charset accept accesskey action align alink \\r
2220 alt archive axis background bgcolor border \\r
2221 cellpadding cellspacing char charoff charset checked cite \\r
2222 class classid clear codebase codetype color cols colspan \\r
2223 compact content coords \\r
2224 data datafld dataformatas datapagesize datasrc datetime \\r
2225 declare defer dir disabled enctype event \\r
2226 face for frame frameborder \\r
2227 headers height href hreflang hspace http-equiv \\r
2228 id ismap label lang language leftmargin link longdesc \\r
2229 marginwidth marginheight maxlength media method multiple \\r
2230 name nohref noresize noshade nowrap \\r
2231 object onblur onchange onclick ondblclick onfocus \\r
2232 onkeydown onkeypress onkeyup onload onmousedown \\r
2233 onmousemove onmouseover onmouseout onmouseup \\r
2234 onreset onselect onsubmit onunload \\r
2235 profile prompt readonly rel rev rows rowspan rules \\r
2236 scheme scope selected shape size span src standby start style \\r
2237 summary tabindex target text title topmargin type usemap \\r
2238 valign value valuetype version vlink vspace width \\r
2239 text password checkbox radio submit reset \\r
2240 file hidden image")).GetBuffer()));\r
2241                         SendEditor(SCI_SETKEYWORDS, 1, (LPARAM)(m_TextView.StringForControl(_T("assign audio block break catch choice clear disconnect else elseif \\r
2242 emphasis enumerate error exit field filled form goto grammar help \\r
2243 if initial link log menu meta noinput nomatch object option p paragraph \\r
2244 param phoneme prompt property prosody record reprompt return s say-as \\r
2245 script sentence subdialog submit throw transfer value var voice vxml")).GetBuffer()));\r
2246                         SendEditor(SCI_SETKEYWORDS, 2, (LPARAM)(m_TextView.StringForControl(_T("accept age alphabet anchor application base beep bridge category charset \\r
2247 classid cond connecttimeout content contour count dest destexpr dtmf dtmfterm \\r
2248 duration enctype event eventexpr expr expritem fetchtimeout finalsilence \\r
2249 gender http-equiv id level maxage maxstale maxtime message messageexpr \\r
2250 method mime modal mode name namelist next nextitem ph pitch range rate \\r
2251 scope size sizeexpr skiplist slot src srcexpr sub time timeexpr timeout \\r
2252 transferaudio type value variant version volume xml:lang")).GetBuffer()));\r
2253                         SendEditor(SCI_SETKEYWORDS, 3, (LPARAM)(m_TextView.StringForControl(_T("and assert break class continue def del elif \\r
2254 else except exec finally for from global if import in is lambda None \\r
2255 not or pass print raise return try while yield")).GetBuffer()));\r
2256                         SendEditor(SCI_SETKEYWORDS, 4, (LPARAM)(m_TextView.StringForControl(_T("and argv as argc break case cfunction class continue declare default do \\r
2257 die echo else elseif empty enddeclare endfor endforeach endif endswitch \\r
2258 endwhile e_all e_parse e_error e_warning eval exit extends false for \\r
2259 foreach function global http_cookie_vars http_get_vars http_post_vars \\r
2260 http_post_files http_env_vars http_server_vars if include include_once \\r
2261 list new not null old_function or parent php_os php_self php_version \\r
2262 print require require_once return static switch stdclass this true var \\r
2263 xor virtual while __file__ __line__ __sleep __wakeup")).GetBuffer()));\r
2264 \r
2265                         SetAStyle(SCE_H_TAG, darkBlue);\r
2266                         SetAStyle(SCE_H_TAGUNKNOWN, red);\r
2267                         SetAStyle(SCE_H_ATTRIBUTE, darkBlue);\r
2268                         SetAStyle(SCE_H_ATTRIBUTEUNKNOWN, red);\r
2269                         SetAStyle(SCE_H_NUMBER, RGB(0x80,0,0x80));\r
2270                         SetAStyle(SCE_H_DOUBLESTRING, RGB(0,0x80,0));\r
2271                         SetAStyle(SCE_H_SINGLESTRING, RGB(0,0x80,0));\r
2272                         SetAStyle(SCE_H_OTHER, RGB(0x80,0,0x80));\r
2273                         SetAStyle(SCE_H_COMMENT, RGB(0x80,0x80,0));\r
2274                         SetAStyle(SCE_H_ENTITY, RGB(0x80,0,0x80));\r
2275 \r
2276                         SetAStyle(SCE_H_TAGEND, darkBlue);\r
2277                         SetAStyle(SCE_H_XMLSTART, darkBlue);    // <?\r
2278                         SetAStyle(SCE_H_QUESTION, darkBlue);    // <?\r
2279                         SetAStyle(SCE_H_XMLEND, darkBlue);              // ?>\r
2280                         SetAStyle(SCE_H_SCRIPT, darkBlue);              // <script\r
2281                         SetAStyle(SCE_H_ASP, RGB(0x4F, 0x4F, 0), RGB(0xFF, 0xFF, 0));   // <% ... %>\r
2282                         SetAStyle(SCE_H_ASPAT, RGB(0x4F, 0x4F, 0), RGB(0xFF, 0xFF, 0)); // <%@ ... %>\r
2283 \r
2284                         SetAStyle(SCE_HB_DEFAULT, black);\r
2285                         SetAStyle(SCE_HB_COMMENTLINE, darkGreen);\r
2286                         SetAStyle(SCE_HB_NUMBER, RGB(0,0x80,0x80));\r
2287                         SetAStyle(SCE_HB_WORD, darkBlue);\r
2288                         SendEditor(SCI_STYLESETBOLD, SCE_HB_WORD, 1);\r
2289                         SetAStyle(SCE_HB_STRING, RGB(0x80,0,0x80));\r
2290                         SetAStyle(SCE_HB_IDENTIFIER, black);\r
2291 \r
2292                         // This light blue is found in the windows system palette so is safe to use even in 256 colour modes.\r
2293                         // Show the whole section of VBScript with light blue background\r
2294                         for (int bstyle=SCE_HB_DEFAULT; bstyle<=SCE_HB_STRINGEOL; bstyle++) {\r
2295                                 SendEditor(SCI_STYLESETFONT, bstyle, \r
2296                                         reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2297                                 SendEditor(SCI_STYLESETBACK, bstyle, lightBlue);\r
2298                                 // This call extends the backround colour of the last style on the line to the edge of the window\r
2299                                 SendEditor(SCI_STYLESETEOLFILLED, bstyle, 1);\r
2300                         }\r
2301                         SendEditor(SCI_STYLESETBACK, SCE_HB_STRINGEOL, RGB(0x7F,0x7F,0xFF));\r
2302                         SendEditor(SCI_STYLESETFONT, SCE_HB_COMMENTLINE, \r
2303                                 reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2304 \r
2305                         SetAStyle(SCE_HBA_DEFAULT, black);\r
2306                         SetAStyle(SCE_HBA_COMMENTLINE, darkGreen);\r
2307                         SetAStyle(SCE_HBA_NUMBER, RGB(0,0x80,0x80));\r
2308                         SetAStyle(SCE_HBA_WORD, darkBlue);\r
2309                         SendEditor(SCI_STYLESETBOLD, SCE_HBA_WORD, 1);\r
2310                         SetAStyle(SCE_HBA_STRING, RGB(0x80,0,0x80));\r
2311                         SetAStyle(SCE_HBA_IDENTIFIER, black);\r
2312 \r
2313                         // Show the whole section of ASP VBScript with bright yellow background\r
2314                         for (int bastyle=SCE_HBA_DEFAULT; bastyle<=SCE_HBA_STRINGEOL; bastyle++) {\r
2315                                 SendEditor(SCI_STYLESETFONT, bastyle, \r
2316                                         reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2317                                 SendEditor(SCI_STYLESETBACK, bastyle, RGB(0xFF, 0xFF, 0));\r
2318                                 // This call extends the backround colour of the last style on the line to the edge of the window\r
2319                                 SendEditor(SCI_STYLESETEOLFILLED, bastyle, 1);\r
2320                         }\r
2321                         SendEditor(SCI_STYLESETBACK, SCE_HBA_STRINGEOL, RGB(0xCF,0xCF,0x7F));\r
2322                         SendEditor(SCI_STYLESETFONT, SCE_HBA_COMMENTLINE, \r
2323                                 reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2324 \r
2325                         // If there is no need to support embedded Javascript, the following code can be dropped.\r
2326                         // Javascript will still be correctly processed but will be displayed in just the default style.\r
2327 \r
2328                         SetAStyle(SCE_HJ_START, RGB(0x80,0x80,0));\r
2329                         SetAStyle(SCE_HJ_DEFAULT, black);\r
2330                         SetAStyle(SCE_HJ_COMMENT, darkGreen);\r
2331                         SetAStyle(SCE_HJ_COMMENTLINE, darkGreen);\r
2332                         SetAStyle(SCE_HJ_COMMENTDOC, darkGreen);\r
2333                         SetAStyle(SCE_HJ_NUMBER, RGB(0,0x80,0x80));\r
2334                         SetAStyle(SCE_HJ_WORD, black);\r
2335                         SetAStyle(SCE_HJ_KEYWORD, darkBlue);\r
2336                         SetAStyle(SCE_HJ_DOUBLESTRING, RGB(0x80,0,0x80));\r
2337                         SetAStyle(SCE_HJ_SINGLESTRING, RGB(0x80,0,0x80));\r
2338                         SetAStyle(SCE_HJ_SYMBOLS, black);\r
2339 \r
2340                         SetAStyle(SCE_HJA_START, RGB(0x80,0x80,0));\r
2341                         SetAStyle(SCE_HJA_DEFAULT, black);\r
2342                         SetAStyle(SCE_HJA_COMMENT, darkGreen);\r
2343                         SetAStyle(SCE_HJA_COMMENTLINE, darkGreen);\r
2344                         SetAStyle(SCE_HJA_COMMENTDOC, darkGreen);\r
2345                         SetAStyle(SCE_HJA_NUMBER, RGB(0,0x80,0x80));\r
2346                         SetAStyle(SCE_HJA_WORD, black);\r
2347                         SetAStyle(SCE_HJA_KEYWORD, darkBlue);\r
2348                         SetAStyle(SCE_HJA_DOUBLESTRING, RGB(0x80,0,0x80));\r
2349                         SetAStyle(SCE_HJA_SINGLESTRING, RGB(0x80,0,0x80));\r
2350                         SetAStyle(SCE_HJA_SYMBOLS, black);\r
2351 \r
2352                         SetAStyle(SCE_HPHP_DEFAULT, black);\r
2353                         SetAStyle(SCE_HPHP_HSTRING,  RGB(0x80,0,0x80));\r
2354                         SetAStyle(SCE_HPHP_SIMPLESTRING,  RGB(0x80,0,0x80));\r
2355                         SetAStyle(SCE_HPHP_WORD, darkBlue);\r
2356                         SetAStyle(SCE_HPHP_NUMBER, RGB(0,0x80,0x80));\r
2357                         SetAStyle(SCE_HPHP_VARIABLE, red);\r
2358                         SetAStyle(SCE_HPHP_HSTRING_VARIABLE, red);\r
2359                         SetAStyle(SCE_HPHP_COMPLEX_VARIABLE, red);\r
2360                         SetAStyle(SCE_HPHP_COMMENT, darkGreen);\r
2361                         SetAStyle(SCE_HPHP_COMMENTLINE, darkGreen);\r
2362                         SetAStyle(SCE_HPHP_OPERATOR, darkBlue);\r
2363 \r
2364                         // Show the whole section of Javascript with off white background\r
2365                         for (int jstyle=SCE_HJ_DEFAULT; jstyle<=SCE_HJ_SYMBOLS; jstyle++) {\r
2366                                 SendEditor(SCI_STYLESETFONT, jstyle, \r
2367                                         reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2368                                 SendEditor(SCI_STYLESETBACK, jstyle, offWhite);\r
2369                                 SendEditor(SCI_STYLESETEOLFILLED, jstyle, 1);\r
2370                         }\r
2371                         SendEditor(SCI_STYLESETBACK, SCE_HJ_STRINGEOL, RGB(0xDF, 0xDF, 0x7F));\r
2372                         SendEditor(SCI_STYLESETEOLFILLED, SCE_HJ_STRINGEOL, 1);\r
2373 \r
2374                         // Show the whole section of Javascript with brown background\r
2375                         for (int jastyle=SCE_HJA_DEFAULT; jastyle<=SCE_HJA_SYMBOLS; jastyle++) {\r
2376                                 SendEditor(SCI_STYLESETFONT, jastyle, \r
2377                                         reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2378                                 SendEditor(SCI_STYLESETBACK, jastyle, RGB(0xDF, 0xDF, 0x7F));\r
2379                                 SendEditor(SCI_STYLESETEOLFILLED, jastyle, 1);\r
2380                         }\r
2381                         SendEditor(SCI_STYLESETBACK, SCE_HJA_STRINGEOL, RGB(0x0,0xAF,0x5F));\r
2382                         SendEditor(SCI_STYLESETEOLFILLED, SCE_HJA_STRINGEOL, 1);\r
2383                 }\r
2384         }\r
2385         else\r
2386         {\r
2387                 SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2388                 SetupCppLexer();\r
2389         }\r
2390         SendEditor(SCI_COLOURISE, 0, -1);\r
2391 \r
2392 }\r
2393 \r
2394 void CTortoiseGitBlameView::SetupCppLexer()\r
2395 {\r
2396         SetAStyle(SCE_C_DEFAULT, RGB(0, 0, 0));\r
2397         SetAStyle(SCE_C_COMMENT, RGB(0, 0x80, 0));\r
2398         SetAStyle(SCE_C_COMMENTLINE, RGB(0, 0x80, 0));\r
2399         SetAStyle(SCE_C_COMMENTDOC, RGB(0, 0x80, 0));\r
2400         SetAStyle(SCE_C_COMMENTLINEDOC, RGB(0, 0x80, 0));\r
2401         SetAStyle(SCE_C_COMMENTDOCKEYWORD, RGB(0, 0x80, 0));\r
2402         SetAStyle(SCE_C_COMMENTDOCKEYWORDERROR, RGB(0, 0x80, 0));\r
2403         SetAStyle(SCE_C_NUMBER, RGB(0, 0x80, 0x80));\r
2404         SetAStyle(SCE_C_WORD, RGB(0, 0, 0x80));\r
2405         SendEditor(SCE_C_WORD, 1);\r
2406         SetAStyle(SCE_C_STRING, RGB(0x80, 0, 0x80));\r
2407         SetAStyle(SCE_C_IDENTIFIER, RGB(0, 0, 0));\r
2408         SetAStyle(SCE_C_PREPROCESSOR, RGB(0x80, 0, 0));\r
2409         SetAStyle(SCE_C_OPERATOR, RGB(0x80, 0x80, 0));\r
2410 }\r
2411 \r
2412 \r
2413 void CTortoiseGitBlameView::UpdateInfo()\r
2414 {\r
2415         CString &data = GetDocument()->m_BlameData;\r
2416         CString one;\r
2417         int pos=0;\r
2418         \r
2419         BYTE_VECTOR vector;\r
2420 \r
2421         CLogDataVector * pRevs= GetLogData();\r
2422 \r
2423         this->m_CommitHash.clear();\r
2424         this->m_Authors.clear();\r
2425         this->m_ID.clear();\r
2426         CString line;\r
2427 \r
2428         CreateFont();\r
2429 \r
2430         SendEditor(SCI_SETREADONLY, FALSE);\r
2431         SendEditor(SCI_CLEARALL);\r
2432         SendEditor(EM_EMPTYUNDOBUFFER);\r
2433         SendEditor(SCI_SETSAVEPOINT);\r
2434         SendEditor(SCI_CANCEL);\r
2435         SendEditor(SCI_SETUNDOCOLLECTION, 0);\r
2436 \r
2437         while( pos>=0 )\r
2438         {\r
2439                 one=data.Tokenize(_T("\n"),pos);\r
2440                 if(one.IsEmpty())\r
2441                         continue;\r
2442                 m_CommitHash.push_back(one.Left(40));\r
2443                 int start=0;\r
2444                 start=one.Find(_T(')'),40);\r
2445                 if(start>0)\r
2446                 {\r
2447                         line=one.Right(one.GetLength()-start-2);\r
2448                         this->m_TextView.InsertText(line,true);\r
2449                 }\r
2450                 int id;\r
2451                 if(pRevs->m_HashMap.find(one.Left(40))!=pRevs->m_HashMap.end())\r
2452                 {\r
2453                         id=pRevs->m_HashMap[one.Left(40)];      \r
2454                 }\r
2455                 else\r
2456                 {\r
2457                         id=-1;\r
2458                         if(this->m_NoListCommit.find(one.Left(40)) == m_NoListCommit.end() )\r
2459                         {\r
2460                                 g_Git.GetLog(vector,one.Left(40),NULL,1);\r
2461                                 this->m_NoListCommit[one.Left(40)].ParserFromLog(vector);\r
2462                         }\r
2463                         \r
2464                 }\r
2465 \r
2466                 if(id>=0 && id <(int)GetLogData()->size())\r
2467                 {\r
2468                         m_ID.push_back(pRevs->size()-id);\r
2469                         m_Authors.push_back(pRevs->at(id).m_AuthorName);\r
2470                 }else\r
2471                 {\r
2472                         m_ID.push_back(id);\r
2473                         m_Authors.push_back(one.Left(6));\r
2474                 }\r
2475         }\r
2476 \r
2477         SetupLexer(GetDocument()->m_CurrentFileName);\r
2478 \r
2479         SendEditor(SCI_SETUNDOCOLLECTION, 1);\r
2480         SendEditor(EM_EMPTYUNDOBUFFER);\r
2481         SendEditor(SCI_SETSAVEPOINT);\r
2482         SendEditor(SCI_GOTOPOS, 0);\r
2483         SendEditor(SCI_SETSCROLLWIDTHTRACKING, TRUE);\r
2484         SendEditor(SCI_SETREADONLY, TRUE);\r
2485 \r
2486         m_lowestrev=1;\r
2487         m_highestrev=this->GetLogData()->size();\r
2488 \r
2489         GetBlameWidth();\r
2490         CRect rect;\r
2491         this->GetClientRect(rect);\r
2492         //this->m_TextView.GetWindowRect(rect);\r
2493         //this->m_TextView.ScreenToClient(rect);\r
2494         rect.left=this->m_blamewidth;\r
2495         this->m_TextView.MoveWindow(rect);\r
2496 \r
2497         this->Invalidate();\r
2498 }\r
2499 \r
2500 CGitBlameLogList * CTortoiseGitBlameView::GetLogList()\r
2501 {\r
2502         return &(GetDocument()->GetMainFrame()->m_wndOutput.m_LogList);\r
2503 }\r
2504 \r
2505 \r
2506 CLogDataVector * CTortoiseGitBlameView::GetLogData()\r
2507 {\r
2508         return &(GetDocument()->GetMainFrame()->m_wndOutput.m_LogList.m_logEntries);\r
2509 }\r
2510 \r
2511 void CTortoiseGitBlameView::OnSciPainted(NMHDR *,LRESULT *)\r
2512 {\r
2513         this->Invalidate();\r
2514 }\r
2515 \r
2516 void CTortoiseGitBlameView::OnLButtonDown(UINT nFlags,CPoint point)\r
2517 {\r
2518 \r
2519         LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
2520         LONG_PTR height = SendEditor(SCI_TEXTHEIGHT);\r
2521         line = line + (point.y/height);\r
2522                         \r
2523         if (line < (LONG)m_CommitHash.size())\r
2524         {\r
2525                 SetSelectedLine(line);\r
2526                 if (m_CommitHash[line] != m_SelectedHash)\r
2527                 {\r
2528                         m_SelectedHash = m_CommitHash[line];\r
2529                         \r
2530                         if(m_ID[line]>=0)\r
2531                         {\r
2532                                 this->GetLogList()->SetItemState(this->GetLogList()->GetItemCount()-m_ID[line],\r
2533                                                                                                                         LVIS_SELECTED,\r
2534                                                                                                                         LVIS_SELECTED);\r
2535 \r
2536                                 GitRev *pRev;\r
2537                                 pRev=&this->GetLogData()->at(this->GetLogList()->GetItemCount()-m_ID[line]);\r
2538                                 this->GetDocument()->GetMainFrame()->m_wndProperties.UpdateProperties(pRev);\r
2539                         }else\r
2540                         {\r
2541                                 this->GetDocument()->GetMainFrame()->m_wndProperties.UpdateProperties(&m_NoListCommit[m_CommitHash[line]]);\r
2542                         }\r
2543                 }\r
2544                 else\r
2545                 {\r
2546                         m_SelectedHash.Empty();\r
2547                 }\r
2548                 //::InvalidateRect( NULL, FALSE);\r
2549                 this->Invalidate();\r
2550                 this->m_TextView.Invalidate();\r
2551                 \r
2552         }\r
2553         else\r
2554         {\r
2555                 SetSelectedLine(-1);\r
2556         }\r
2557                 \r
2558         CView::OnLButtonDown(nFlags,point);\r
2559 }\r
2560 \r
2561 void CTortoiseGitBlameView::OnSciGetBkColor(NMHDR* hdr, LRESULT* result)\r
2562 {\r
2563 \r
2564         SCNotification *notification=reinterpret_cast<SCNotification *>(hdr);\r
2565 \r
2566         if ((m_colorage)&&(notification->line < (int)m_CommitHash.size()))\r
2567         {\r
2568                 if(m_CommitHash[notification->line] == this->m_SelectedHash )\r
2569                         notification->lParam = m_selectedauthorcolor;\r
2570                 else\r
2571                         notification->lParam = InterColor(DWORD(m_regOldLinesColor), DWORD(m_regNewLinesColor), (m_ID[notification->line]-m_lowestrev)*100/((m_highestrev-m_lowestrev)+1));\r
2572         }\r
2573 \r
2574 }\r
2575 \r
2576 void CTortoiseGitBlameView::FocusOn(GitRev *pRev)\r
2577 {\r
2578         m_SelectedHash = pRev->m_CommitHash;\r
2579 \r
2580         //GitRev *pRev;\r
2581         //pRev=&this->GetLogData()->at(this->GetLogList()->GetItemCount()-m_ID[line]);\r
2582         this->GetDocument()->GetMainFrame()->m_wndProperties.UpdateProperties(pRev);\r
2583 \r
2584         this->Invalidate();\r
2585 \r
2586         int i;\r
2587         for(i=0;i<m_CommitHash.size();i++)\r
2588         {\r
2589                 if( pRev->m_CommitHash == m_CommitHash[i] )\r
2590                         break;\r
2591         }\r
2592         this->GotoLine(i);\r
2593         this->m_TextView.Invalidate();\r
2594 \r
2595 }\r
2596 \r
2597 void CTortoiseGitBlameView::OnMouseHover(UINT nFlags, CPoint point)\r
2598 {\r
2599 \r
2600         LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
2601         LONG_PTR height = SendEditor(SCI_TEXTHEIGHT);\r
2602         line = line + (point.y/height);\r
2603                         \r
2604         if (line < (LONG)m_CommitHash.size())\r
2605         {\r
2606                 if (line != m_MouseLine)\r
2607                 {\r
2608                         m_MouseLine = line;//m_CommitHash[line];\r
2609                         GitRev *pRev;\r
2610                         if(m_ID[line]<0)\r
2611                         {\r
2612                                 pRev=&this->m_NoListCommit[m_CommitHash[line]];\r
2613 \r
2614                         }else\r
2615                         {\r
2616                                 pRev=&this->GetLogData()->at(this->GetLogList()->GetItemCount()-m_ID[line]);\r
2617                         }\r
2618 \r
2619                         this->ClientToScreen(&point);\r
2620 \r
2621                         CString str;\r
2622                         str.Format(_T("%s\n<b>%s</b>\n%s %s\n%s"),pRev->m_CommitHash,\r
2623                                                                                                            pRev->m_Subject,\r
2624                                                                                                            pRev->m_AuthorName,\r
2625                                                                                                            CAppUtils::FormatDateAndTime( pRev->m_AuthorDate, m_DateFormat ), \r
2626                                                                                                            pRev->m_Body);\r
2627                         m_ToolTip.AddTool(this,str);\r
2628                         m_ToolTip.DisplayToolTip(&point);\r
2629         \r
2630                         CRect rect;\r
2631                         this->ScreenToClient(&point);\r
2632                         rect.left=LOCATOR_WIDTH;\r
2633                         rect.right=this->m_blamewidth+rect.left;\r
2634                         rect.top=point.y-height;\r
2635                         rect.bottom=point.y+height;\r
2636                         this->InvalidateRect(rect);\r
2637 \r
2638                 }\r
2639                 else\r
2640                 {\r
2641                         m_MouseLine=-1;\r
2642                 }\r
2643         }\r
2644 }\r
2645 \r
2646 void CTortoiseGitBlameView::OnMouseMove(UINT nFlags, CPoint point)\r
2647 {\r
2648         TRACKMOUSEEVENT tme;\r
2649         tme.cbSize=sizeof(TRACKMOUSEEVENT);\r
2650         tme.dwFlags=TME_HOVER|TME_LEAVE;\r
2651         tme.hwndTrack=this->m_hWnd;\r
2652         tme.dwHoverTime=1;\r
2653         TrackMouseEvent(&tme);\r
2654 }\r
2655 \r
2656 \r
2657 BOOL CTortoiseGitBlameView::PreTranslateMessage(MSG* pMsg)\r
2658 {\r
2659         m_ToolTip.RelayEvent(pMsg);\r
2660         return CView::PreTranslateMessage(pMsg);\r
2661 }\r
2662 \r
2663 void CTortoiseGitBlameView::OnEditFind()\r
2664 {\r
2665     m_pFindDialog=new CFindReplaceDialog();\r
2666         \r
2667     m_pFindDialog->Create(TRUE,_T(""),NULL,FR_DOWN,this);  \r
2668 }\r
2669 \r
2670 void CTortoiseGitBlameView::OnEditGoto()\r
2671 {\r
2672     CEditGotoDlg dlg;\r
2673     if(dlg.DoModal()==IDOK)\r
2674     {\r
2675         this->GotoLine(dlg.m_LineNumber);\r
2676     }\r
2677 }\r
2678 \r
2679 LRESULT CTortoiseGitBlameView::OnFindDialogMessage(WPARAM   wParam,   LPARAM   lParam)//Õâ¸öÒ²ÊÇÕÒÄǸö³ÌÐò¸ÄµÄ£¬Ö»²»¹ý»»³ÉÁË×Ô¼ºµÄÀà   \r
2680 {   \r
2681     ASSERT(m_pFindDialog   !=   NULL);   \r
2682     \r
2683     //   If   the   FR_DIALOGTERM   flag   is   set,   \r
2684           //   invalidate   the   handle   identifying   the   dialog   box.   \r
2685     if   (m_pFindDialog->IsTerminating())   \r
2686     {   \r
2687             m_pFindDialog   =   NULL;   \r
2688             return   0;   \r
2689     }   \r
2690 \r
2691     //   If   the   FR_FINDNEXT   flag   is   set,   \r
2692     //   call   the   application-defined   search   routine   \r
2693     //   to   search   for   the   requested   string.   \r
2694     if(m_pFindDialog->FindNext())   \r
2695     {   \r
2696             //read   data   from   dialog   \r
2697         CString   FindName   =   m_pFindDialog->GetFindString();   \r
2698         bool   bMatchCase   =   m_pFindDialog->MatchCase()   ==   TRUE;   \r
2699         bool   bMatchWholeWord   =   m_pFindDialog->MatchWholeWord()   ==   TRUE;   \r
2700         bool   bSearchDown   =   m_pFindDialog->SearchDown()   ==   TRUE;   \r
2701                 \r
2702                 DoSearch(FindName,m_pFindDialog->m_fr.Flags);\r
2703             //with   given   name   do   search   \r
2704     //        *FindWhatYouNeed(FindName,   bMatchCase,   bMatchWholeWord,   bSearchDown);   \r
2705     }   \r
2706 \r
2707     return   0;   \r
2708 }   \r
2709 \r
2710 void CTortoiseGitBlameView::OnViewNext()\r
2711 {\r
2712         FindNextLine(this->m_SelectedHash,false);\r
2713 }\r
2714 void CTortoiseGitBlameView::OnViewPrev()\r
2715 {\r
2716         FindNextLine(this->m_SelectedHash,true);\r
2717 }\r
2718 \r
2719 int CTortoiseGitBlameView::FindNextLine(CString CommitHash,bool bUpOrDown)\r
2720 {\r
2721         LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
2722         LONG_PTR startline =line;\r
2723         bool findNoMatch =false;\r
2724         while(line>=0 && line<m_CommitHash.size())\r
2725         {\r
2726                 if(m_CommitHash[line]!=CommitHash)\r
2727                 {\r
2728                         findNoMatch=true;\r
2729                 }\r
2730 \r
2731                 if(m_CommitHash[line] == CommitHash && findNoMatch)\r
2732                 {\r
2733                         if( line == startline+2 )\r
2734                         {\r
2735                                 findNoMatch=false;\r
2736                         }\r
2737                         else\r
2738                         {\r
2739                                 if( bUpOrDown )\r
2740                                 {\r
2741                                         line=FindFirstLine(CommitHash,line);\r
2742                                 }\r
2743                                 SendEditor(SCI_LINESCROLL,0,line-startline-2);\r
2744                                 return line;\r
2745                         }\r
2746                 }\r
2747                 if(bUpOrDown)\r
2748                         line--;\r
2749                 else\r
2750                         line++;\r
2751         }\r
2752         return -1;\r
2753 }