OSDN Git Service

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