OSDN Git Service

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