OSDN Git Service

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