OSDN Git Service

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