OSDN Git Service

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