OSDN Git Service

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