OSDN Git Service

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