OSDN Git Service

Hover Balloon at gitblame view support
[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                         //if ((revs[i] == m_mouserev)&&(!sel))\r
1149                         //      ::SetBkColor(hDC, m_mouserevcolor);\r
1150                         //if (revs[i] == m_selectedrev)\r
1151                         //{\r
1152                         //      ::SetBkColor(hDC, m_selectedrevcolor);\r
1153                         //      ::SetTextColor(hDC, m_texthighlightcolor);\r
1154                         //}\r
1155 \r
1156                         CString str;\r
1157                         str.Format(_T("%d"),m_ID[i]);\r
1158 \r
1159                         //_stprintf_s(buf, MAX_PATH, _T("%8ld       "), revs[i]);\r
1160                         rc.top=Y;\r
1161                         rc.left=LOCATOR_WIDTH;          \r
1162                         rc.bottom=Y+height;\r
1163                         rc.right = rc.left + m_blamewidth;\r
1164                         ::ExtTextOut(hDC, LOCATOR_WIDTH, Y, ETO_CLIPPED, &rc, str, str.GetLength(), 0);\r
1165                         int Left = m_revwidth;\r
1166                         \r
1167                         if (m_bShowAuthor)\r
1168                         {\r
1169                                 rc.right = rc.left + Left + m_authorwidth;\r
1170                                 //_stprintf_s(buf, MAX_PATH, _T("%-30s            "), authors[i].c_str());\r
1171                                 ::ExtTextOut(hDC, Left, Y, ETO_CLIPPED, &rc, m_Authors[i], m_Authors[i].GetLength(), 0);\r
1172                                 Left += m_authorwidth;\r
1173                         }\r
1174 #if 0\r
1175                         if (ShowDate)\r
1176                         {\r
1177                                 rc.right = rc.left + Left + m_datewidth;\r
1178                                 _stprintf_s(buf, MAX_PATH, _T("%30s            "), dates[i].c_str());\r
1179                                 ::ExtTextOut(hDC, Left, Y, ETO_CLIPPED, &rc, buf, _tcslen(buf), 0);\r
1180                                 Left += m_datewidth;\r
1181                         }\r
1182                         \r
1183 #endif\r
1184 #if 0\r
1185                         if (ShowPath)\r
1186                         {\r
1187                                 rc.right = rc.left + Left + m_pathwidth;\r
1188                                 _stprintf_s(buf, MAX_PATH, _T("%-60s            "), paths[i].c_str());\r
1189                                 ::ExtTextOut(hDC, Left, Y, ETO_CLIPPED, &rc, buf, _tcslen(buf), 0);\r
1190                                 Left += m_authorwidth;\r
1191                         }\r
1192 #endif\r
1193                         if ((i==m_SelectedLine)&&(currentDialog))\r
1194                         {\r
1195                                 LOGBRUSH brush;\r
1196                                 brush.lbColor = m_textcolor;\r
1197                                 brush.lbHatch = 0;\r
1198                                 brush.lbStyle = BS_SOLID;\r
1199                                 HPEN pen = ExtCreatePen(PS_SOLID | PS_GEOMETRIC, 2, &brush, 0, NULL);\r
1200                                 HGDIOBJ hPenOld = SelectObject(hDC, pen);\r
1201                                 RECT rc2 = rc;\r
1202                                 rc2.top = Y;\r
1203                                 rc2.bottom = Y + height;\r
1204                                 ::MoveToEx(hDC, rc2.left, rc2.top, NULL);\r
1205                                 ::LineTo(hDC, rc2.right, rc2.top);\r
1206                                 ::LineTo(hDC, rc2.right, rc2.bottom);\r
1207                                 ::LineTo(hDC, rc2.left, rc2.bottom);\r
1208                                 ::LineTo(hDC, rc2.left, rc2.top);\r
1209                                 SelectObject(hDC, hPenOld); \r
1210                                 DeleteObject(pen); \r
1211                         }\r
1212                         Y += height;\r
1213                         ::SelectObject(hDC, oldfont);\r
1214                 }\r
1215                 else\r
1216                 {\r
1217                         ::SetBkColor(hDC, m_windowcolor);\r
1218                         for (int j=0; j< MAX_PATH; ++j)\r
1219                                 buf[j]=' ';\r
1220                         ::ExtTextOut(hDC, 0, Y, ETO_CLIPPED, &rc, buf, MAX_PATH-1, 0);\r
1221                         Y += height;\r
1222                 }\r
1223         }\r
1224 }\r
1225 \r
1226 void CTortoiseGitBlameView::DrawHeader(HDC hDC)\r
1227 {\r
1228 #if 0\r
1229         if (hDC == NULL)\r
1230                 return;\r
1231 \r
1232         RECT rc;\r
1233         HFONT oldfont = (HFONT)::SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));\r
1234         ::GetClientRect(wHeader, &rc);\r
1235 \r
1236         ::SetBkColor(hDC, ::GetSysColor(COLOR_BTNFACE));\r
1237 \r
1238         TCHAR szText[MAX_LOADSTRING];\r
1239         LoadString(app.hResource, IDS_HEADER_REVISION, szText, MAX_LOADSTRING);\r
1240         ::ExtTextOut(hDC, LOCATOR_WIDTH, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
1241         int Left = m_revwidth+LOCATOR_WIDTH;\r
1242         if (ShowDate)\r
1243         {\r
1244                 LoadString(app.hResource, IDS_HEADER_DATE, szText, MAX_LOADSTRING);\r
1245                 ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
1246                 Left += m_datewidth;\r
1247         }\r
1248         if (ShowAuthor)\r
1249         {\r
1250                 LoadString(app.hResource, IDS_HEADER_AUTHOR, szText, MAX_LOADSTRING);\r
1251                 ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
1252                 Left += m_authorwidth;\r
1253         }\r
1254         if (ShowPath)\r
1255         {\r
1256                 LoadString(app.hResource, IDS_HEADER_PATH, szText, MAX_LOADSTRING);\r
1257                 ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
1258                 Left += m_pathwidth;\r
1259         }\r
1260         LoadString(app.hResource, IDS_HEADER_LINE, szText, MAX_LOADSTRING);\r
1261         ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
1262 \r
1263         ::SelectObject(hDC, oldfont);\r
1264 #endif\r
1265 }\r
1266 \r
1267 void CTortoiseGitBlameView::DrawLocatorBar(HDC hDC)\r
1268 {\r
1269         if (hDC == NULL)\r
1270                 return;\r
1271 \r
1272         LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
1273         LONG_PTR linesonscreen = SendEditor(SCI_LINESONSCREEN);\r
1274         LONG_PTR Y = 0;\r
1275         COLORREF blackColor = GetSysColor(COLOR_WINDOWTEXT);\r
1276 \r
1277         RECT rc;\r
1278         //::GetClientRect(wLocator, &rc);\r
1279         this->GetClientRect(&rc);\r
1280 \r
1281         rc.right=LOCATOR_WIDTH;\r
1282 \r
1283         RECT lineRect = rc;\r
1284         LONG height = rc.bottom-rc.top;\r
1285         LONG currentLine = 0;\r
1286 \r
1287         // draw the colored bar\r
1288         for (std::vector<LONG>::const_iterator it = m_ID.begin(); it != m_ID.end(); ++it)\r
1289         {\r
1290                 currentLine++;\r
1291                 // get the line color\r
1292                 COLORREF cr = InterColor(DWORD(m_regOldLinesColor), DWORD(m_regNewLinesColor), (*it - m_lowestrev)*100/((m_highestrev-m_lowestrev)+1));\r
1293                 if ((currentLine > line)&&(currentLine <= (line + linesonscreen)))\r
1294                 {\r
1295                         cr = InterColor(cr, blackColor, 10);\r
1296                 }\r
1297                 SetBkColor(hDC, cr);\r
1298                 lineRect.top = Y;\r
1299                 lineRect.bottom = (currentLine * height / m_ID.size());\r
1300                 ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lineRect, NULL, 0, NULL);\r
1301                 Y = lineRect.bottom;\r
1302         }\r
1303 \r
1304         if (m_ID.size())\r
1305         {\r
1306                 // now draw two lines indicating the scroll position of the source view\r
1307                 SetBkColor(hDC, blackColor);\r
1308                 lineRect.top = line * height / m_ID.size();\r
1309                 lineRect.bottom = lineRect.top+1;\r
1310                 ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lineRect, NULL, 0, NULL);\r
1311                 lineRect.top = (line + linesonscreen) * height / m_ID.size();\r
1312                 lineRect.bottom = lineRect.top+1;\r
1313                 ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lineRect, NULL, 0, NULL);\r
1314         }\r
1315 \r
1316 }\r
1317 \r
1318 void CTortoiseGitBlameView::StringExpand(LPSTR str)\r
1319 {\r
1320         char * cPos = str;\r
1321         do\r
1322         {\r
1323                 cPos = strchr(cPos, '\n');\r
1324                 if (cPos)\r
1325                 {\r
1326                         memmove(cPos+1, cPos, strlen(cPos)*sizeof(char));\r
1327                         *cPos = '\r';\r
1328                         cPos++;\r
1329                         cPos++;\r
1330                 }\r
1331         } while (cPos != NULL);\r
1332 }\r
1333 void CTortoiseGitBlameView::StringExpand(LPWSTR str)\r
1334 {\r
1335         wchar_t * cPos = str;\r
1336         do\r
1337         {\r
1338                 cPos = wcschr(cPos, '\n');\r
1339                 if (cPos)\r
1340                 {\r
1341                         memmove(cPos+1, cPos, wcslen(cPos)*sizeof(wchar_t));\r
1342                         *cPos = '\r';\r
1343                         cPos++;\r
1344                         cPos++;\r
1345                 }\r
1346         } while (cPos != NULL);\r
1347 }\r
1348 \r
1349 // Forward declarations of functions included in this code module:\r
1350 ATOM                            MyRegisterClass(HINSTANCE hResource);\r
1351 ATOM                            MyRegisterBlameClass(HINSTANCE hResource);\r
1352 ATOM                            MyRegisterHeaderClass(HINSTANCE hResource);\r
1353 ATOM                            MyRegisterLocatorClass(HINSTANCE hResource);\r
1354 BOOL                            InitInstance(HINSTANCE, int);\r
1355 LRESULT CALLBACK        WndProc(HWND, UINT, WPARAM, LPARAM);\r
1356 LRESULT CALLBACK        WndBlameProc(HWND, UINT, WPARAM, LPARAM);\r
1357 LRESULT CALLBACK        WndHeaderProc(HWND, UINT, WPARAM, LPARAM);\r
1358 LRESULT CALLBACK        WndLocatorProc(HWND, UINT, WPARAM, LPARAM);\r
1359 UINT                            uFindReplaceMsg;\r
1360 \r
1361 #if 0\r
1362 int APIENTRY _tWinMain(HINSTANCE hInstance,\r
1363                      HINSTANCE /*hPrevInstance*/,\r
1364                      LPTSTR    lpCmdLine,\r
1365                      int       nCmdShow)\r
1366 {\r
1367         app.hInstance = hInstance;\r
1368         MSG msg;\r
1369         HACCEL hAccelTable;\r
1370 \r
1371         if (::LoadLibrary("SciLexer.DLL") == NULL)\r
1372                 return FALSE;\r
1373 \r
1374         CRegStdWORD loc = CRegStdWORD(_T("Software\\TortoiseGit\\LanguageID"), 1033);\r
1375         long langId = loc;\r
1376 \r
1377         CLangDll langDLL;\r
1378         app.hResource = langDLL.Init(_T("CTortoiseGitBlameView"), langId);\r
1379         if (app.hResource == NULL)\r
1380                 app.hResource = app.hInstance;\r
1381 \r
1382         // Initialize global strings\r
1383         LoadString(app.hResource, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);\r
1384         LoadString(app.hResource, IDC_TortoiseGitBlameView, szWindowClass, MAX_LOADSTRING);\r
1385         LoadString(app.hResource, IDS_SEARCHNOTFOUND, searchstringnotfound, MAX_LOADSTRING);\r
1386         MyRegisterClass(app.hResource);\r
1387         MyRegisterBlameClass(app.hResource);\r
1388         MyRegisterHeaderClass(app.hResource);\r
1389         MyRegisterLocatorClass(app.hResource);\r
1390 \r
1391         // Perform application initialization:\r
1392         if (!InitInstance (app.hResource, nCmdShow)) \r
1393         {\r
1394                 langDLL.Close();\r
1395                 return FALSE;\r
1396         }\r
1397 \r
1398         SecureZeroMemory(szViewtitle, MAX_PATH);\r
1399         SecureZeroMemory(szOrigPath, MAX_PATH);\r
1400         char blamefile[MAX_PATH] = {0};\r
1401         char logfile[MAX_PATH] = {0};\r
1402 \r
1403         CCmdLineParser parser(lpCmdLine);\r
1404 \r
1405 \r
1406         if (__argc > 1)\r
1407         {\r
1408                 _tcscpy_s(blamefile, MAX_PATH, __argv[1]);\r
1409         }\r
1410         if (__argc > 2)\r
1411         {\r
1412                 _tcscpy_s(logfile, MAX_PATH, __argv[2]);\r
1413         }\r
1414         if (__argc > 3)\r
1415         {\r
1416                 _tcscpy_s(szViewtitle, MAX_PATH, __argv[3]);\r
1417                 if (parser.HasVal(_T("revrange")))\r
1418                 {\r
1419                         _tcscat_s(szViewtitle, MAX_PATH, _T(" : "));\r
1420                         _tcscat_s(szViewtitle, MAX_PATH, parser.GetVal(_T("revrange")));\r
1421                 }\r
1422         }\r
1423         if ((_tcslen(blamefile)==0) || parser.HasKey(_T("?")) || parser.HasKey(_T("help")))\r
1424         {\r
1425                 TCHAR szInfo[MAX_LOADSTRING];\r
1426                 LoadString(app.hResource, IDS_COMMANDLINE_INFO, szInfo, MAX_LOADSTRING);\r
1427                 MessageBox(NULL, szInfo, _T("CTortoiseGitBlameView"), MB_ICONERROR);\r
1428                 langDLL.Close();\r
1429                 return 0;\r
1430         }\r
1431 \r
1432         if ( parser.HasKey(_T("path")) )\r
1433         {\r
1434                 _tcscpy_s(szOrigPath, MAX_PATH, parser.GetVal(_T("path")));\r
1435         }\r
1436         app.bIgnoreEOL = parser.HasKey(_T("ignoreeol"));\r
1437         app.bIgnoreSpaces = parser.HasKey(_T("ignorespaces"));\r
1438         app.bIgnoreAllSpaces = parser.HasKey(_T("ignoreallspaces"));\r
1439 \r
1440         app.SendEditor(SCI_SETCODEPAGE, GetACP());\r
1441         app.OpenFile(blamefile);\r
1442         if (_tcslen(logfile)>0)\r
1443                 app.OpenLogFile(logfile);\r
1444 \r
1445         if (parser.HasKey(_T("line")))\r
1446         {\r
1447                 app.GotoLine(parser.GetLongVal(_T("line")));\r
1448         }\r
1449 \r
1450         CheckMenuItem(GetMenu(app.wMain), ID_VIEW_COLORAGEOFLINES, MF_CHECKED|MF_BYCOMMAND);\r
1451 \r
1452 \r
1453         hAccelTable = LoadAccelerators(app.hResource, (LPCTSTR)IDC_TortoiseGitBlameView);\r
1454 \r
1455         BOOL going = TRUE;\r
1456         msg.wParam = 0;\r
1457         while (going) \r
1458         {\r
1459                 going = GetMessage(&msg, NULL, 0, 0);\r
1460                 if (app.currentDialog && going) \r
1461                 {\r
1462                         if (!IsDialogMessage(app.currentDialog, &msg)) \r
1463                         {\r
1464                                 if (TranslateAccelerator(msg.hwnd, hAccelTable, &msg) == 0) \r
1465                                 {\r
1466                                         TranslateMessage(&msg);\r
1467                                         DispatchMessage(&msg);\r
1468                                 }\r
1469                         }\r
1470                 } \r
1471                 else if (going) \r
1472                 {\r
1473                         if (TranslateAccelerator(app.wMain, hAccelTable, &msg) == 0) \r
1474                         {\r
1475                                 TranslateMessage(&msg);\r
1476                                 DispatchMessage(&msg);\r
1477                         }\r
1478                 }\r
1479         }\r
1480         langDLL.Close();\r
1481         return msg.wParam;\r
1482 }\r
1483 \r
1484 ATOM MyRegisterClass(HINSTANCE hResource)\r
1485 {\r
1486         WNDCLASSEX wcex;\r
1487 \r
1488         wcex.cbSize = sizeof(WNDCLASSEX); \r
1489 \r
1490         wcex.style                      = CS_HREDRAW | CS_VREDRAW;\r
1491         wcex.lpfnWndProc        = (WNDPROC)WndProc;\r
1492         wcex.cbClsExtra         = 0;\r
1493         wcex.cbWndExtra         = 0;\r
1494         wcex.hInstance          = hResource;\r
1495         wcex.hIcon                      = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
1496         wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);\r
1497         wcex.hbrBackground      = (HBRUSH)(COLOR_WINDOW+1);\r
1498         wcex.lpszMenuName       = (LPCTSTR)IDC_TortoiseGitBlameView;\r
1499         wcex.lpszClassName      = szWindowClass;\r
1500         wcex.hIconSm            = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
1501 \r
1502         return RegisterClassEx(&wcex);\r
1503 }\r
1504 \r
1505 ATOM MyRegisterBlameClass(HINSTANCE hResource)\r
1506 {\r
1507         WNDCLASSEX wcex;\r
1508 \r
1509         wcex.cbSize = sizeof(WNDCLASSEX); \r
1510 \r
1511         wcex.style                      = CS_HREDRAW | CS_VREDRAW;\r
1512         wcex.lpfnWndProc        = (WNDPROC)WndBlameProc;\r
1513         wcex.cbClsExtra         = 0;\r
1514         wcex.cbWndExtra         = 0;\r
1515         wcex.hInstance          = hResource;\r
1516         wcex.hIcon                      = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
1517         wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);\r
1518         wcex.hbrBackground      = (HBRUSH)(COLOR_WINDOW+1);\r
1519         wcex.lpszMenuName       = 0;\r
1520         wcex.lpszClassName      = _T("TortoiseGitBlameViewBlame");\r
1521         wcex.hIconSm            = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
1522 \r
1523         return RegisterClassEx(&wcex);\r
1524 }\r
1525 \r
1526 ATOM MyRegisterHeaderClass(HINSTANCE hResource)\r
1527 {\r
1528         WNDCLASSEX wcex;\r
1529 \r
1530         wcex.cbSize = sizeof(WNDCLASSEX); \r
1531 \r
1532         wcex.style                      = CS_HREDRAW | CS_VREDRAW;\r
1533         wcex.lpfnWndProc        = (WNDPROC)WndHeaderProc;\r
1534         wcex.cbClsExtra         = 0;\r
1535         wcex.cbWndExtra         = 0;\r
1536         wcex.hInstance          = hResource;\r
1537         wcex.hIcon                      = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
1538         wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);\r
1539         wcex.hbrBackground      = (HBRUSH)(COLOR_BTNFACE+1);\r
1540         wcex.lpszMenuName       = 0;\r
1541         wcex.lpszClassName      = _T("TortoiseGitBlameViewHeader");\r
1542         wcex.hIconSm            = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
1543 \r
1544         return RegisterClassEx(&wcex);\r
1545 }\r
1546 \r
1547 ATOM MyRegisterLocatorClass(HINSTANCE hResource)\r
1548 {\r
1549         WNDCLASSEX wcex;\r
1550 \r
1551         wcex.cbSize = sizeof(WNDCLASSEX); \r
1552 \r
1553         wcex.style                      = CS_HREDRAW | CS_VREDRAW;\r
1554         wcex.lpfnWndProc        = (WNDPROC)WndLocatorProc;\r
1555         wcex.cbClsExtra         = 0;\r
1556         wcex.cbWndExtra         = 0;\r
1557         wcex.hInstance          = hResource;\r
1558         wcex.hIcon                      = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
1559         wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);\r
1560         wcex.hbrBackground      = (HBRUSH)(COLOR_WINDOW+1);\r
1561         wcex.lpszMenuName       = 0;\r
1562         wcex.lpszClassName      = _T("TortoiseGitBlameViewLocator");\r
1563         wcex.hIconSm            = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
1564 \r
1565         return RegisterClassEx(&wcex);\r
1566 }\r
1567 \r
1568 BOOL InitInstance(HINSTANCE hResource, int nCmdShow)\r
1569 {\r
1570    app.wMain = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,\r
1571       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hResource, NULL);   \r
1572 \r
1573    if (!app.wMain)\r
1574    {\r
1575       return FALSE;\r
1576    }\r
1577 \r
1578    CRegStdWORD pos(_T("Software\\TortoiseGit\\TBlamePos"), 0);\r
1579    CRegStdWORD width(_T("Software\\TortoiseGit\\TBlameSize"), 0);\r
1580    CRegStdWORD state(_T("Software\\TortoiseGit\\TBlameState"), 0);\r
1581    if (DWORD(pos) && DWORD(width))\r
1582    {\r
1583            RECT rc;\r
1584            rc.left = LOWORD(DWORD(pos));\r
1585            rc.top = HIWORD(DWORD(pos));\r
1586            rc.right = rc.left + LOWORD(DWORD(width));\r
1587            rc.bottom = rc.top + HIWORD(DWORD(width));\r
1588            HMONITOR hMon = MonitorFromRect(&rc, MONITOR_DEFAULTTONULL);\r
1589            if (hMon)\r
1590            {\r
1591                    // only restore the window position if the monitor is valid\r
1592                    MoveWindow(app.wMain, LOWORD(DWORD(pos)), HIWORD(DWORD(pos)),\r
1593                            LOWORD(DWORD(width)), HIWORD(DWORD(width)), FALSE);\r
1594            }\r
1595    }\r
1596    if (DWORD(state) == SW_MAXIMIZE)\r
1597            ShowWindow(app.wMain, SW_MAXIMIZE);\r
1598    else\r
1599            ShowWindow(app.wMain, nCmdShow);\r
1600    UpdateWindow(app.wMain);\r
1601 \r
1602    //Create the tooltips\r
1603 \r
1604    INITCOMMONCONTROLSEX iccex; \r
1605    app.hwndTT;                 // handle to the ToolTip control\r
1606    TOOLINFO ti;\r
1607    RECT rect;                  // for client area coordinates\r
1608    iccex.dwICC = ICC_WIN95_CLASSES;\r
1609    iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);\r
1610    InitCommonControlsEx(&iccex);\r
1611 \r
1612    /* CREATE A TOOLTIP WINDOW */\r
1613    app.hwndTT = CreateWindowEx(WS_EX_TOPMOST,\r
1614            TOOLTIPS_CLASS,\r
1615            NULL,\r
1616            WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,             \r
1617            CW_USEDEFAULT,\r
1618            CW_USEDEFAULT,\r
1619            CW_USEDEFAULT,\r
1620            CW_USEDEFAULT,\r
1621            app.wBlame,\r
1622            NULL,\r
1623            app.hResource,\r
1624            NULL\r
1625            );\r
1626 \r
1627    SetWindowPos(app.hwndTT,\r
1628            HWND_TOPMOST,\r
1629            0,\r
1630            0,\r
1631            0,\r
1632            0,\r
1633            SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);\r
1634 \r
1635    /* GET COORDINATES OF THE MAIN CLIENT AREA */\r
1636    GetClientRect (app.wBlame, &rect);\r
1637 \r
1638    /* INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE */\r
1639    ti.cbSize = sizeof(TOOLINFO);\r
1640    ti.uFlags = TTF_TRACK | TTF_ABSOLUTE;//TTF_SUBCLASS | TTF_PARSELINKS;\r
1641    ti.hwnd = app.wBlame;\r
1642    ti.hinst = app.hResource;\r
1643    ti.uId = 0;\r
1644    ti.lpszText = LPSTR_TEXTCALLBACK;\r
1645    // ToolTip control will cover the whole window\r
1646    ti.rect.left = rect.left;    \r
1647    ti.rect.top = rect.top;\r
1648    ti.rect.right = rect.right;\r
1649    ti.rect.bottom = rect.bottom;\r
1650 \r
1651    /* SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW */\r
1652    SendMessage(app.hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);  \r
1653    SendMessage(app.hwndTT, TTM_SETMAXTIPWIDTH, 0, 600);\r
1654    //SendMessage(app.hwndTT, TTM_SETDELAYTIME, TTDT_AUTOPOP, MAKELONG(50000, 0));\r
1655    //SendMessage(app.hwndTT, TTM_SETDELAYTIME, TTDT_RESHOW, MAKELONG(1000, 0));\r
1656    \r
1657    uFindReplaceMsg = RegisterWindowMessage(FINDMSGSTRING);\r
1658    \r
1659    return TRUE;\r
1660 }\r
1661 #endif\r
1662 void CTortoiseGitBlameView::InitSize()\r
1663 {\r
1664     RECT rc;\r
1665     RECT blamerc;\r
1666     RECT sourcerc;\r
1667     ::GetClientRect(wMain, &rc);\r
1668     ::SetWindowPos(wHeader, 0, rc.left, rc.top, rc.right-rc.left, HEADER_HEIGHT, 0);\r
1669     rc.top += HEADER_HEIGHT;\r
1670     blamerc.left = rc.left;\r
1671     blamerc.top = rc.top;\r
1672         LONG w = GetBlameWidth();\r
1673     blamerc.right = w > abs(rc.right - rc.left) ? rc.right : w + rc.left;\r
1674     blamerc.bottom = rc.bottom;\r
1675     sourcerc.left = blamerc.right;\r
1676     sourcerc.top = rc.top;\r
1677     sourcerc.bottom = rc.bottom;\r
1678     sourcerc.right = rc.right;\r
1679         if (m_colorage)\r
1680         {\r
1681                 ::OffsetRect(&blamerc, LOCATOR_WIDTH, 0);\r
1682                 ::OffsetRect(&sourcerc, LOCATOR_WIDTH, 0);\r
1683                 sourcerc.right -= LOCATOR_WIDTH;\r
1684         }\r
1685         ::InvalidateRect(wMain, NULL, FALSE);\r
1686     ::SetWindowPos(m_wEditor, 0, sourcerc.left, sourcerc.top, sourcerc.right - sourcerc.left, sourcerc.bottom - sourcerc.top, 0);\r
1687         ::SetWindowPos(wBlame, 0, blamerc.left, blamerc.top, blamerc.right - blamerc.left, blamerc.bottom - blamerc.top, 0);\r
1688         if (m_colorage)\r
1689                 ::SetWindowPos(wLocator, 0, 0, blamerc.top, LOCATOR_WIDTH, blamerc.bottom - blamerc.top, SWP_SHOWWINDOW);\r
1690         else\r
1691                 ::ShowWindow(wLocator, SW_HIDE);\r
1692 }\r
1693 \r
1694 #if 0\r
1695 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
1696 {\r
1697         if (message == uFindReplaceMsg)\r
1698         {\r
1699                 LPFINDREPLACE lpfr = (LPFINDREPLACE)lParam;\r
1700 \r
1701                 // If the FR_DIALOGTERM flag is set, \r
1702                 // invalidate the handle identifying the dialog box. \r
1703                 if (lpfr->Flags & FR_DIALOGTERM)\r
1704                 {\r
1705                         app.currentDialog = NULL; \r
1706                         return 0; \r
1707                 } \r
1708                 if (lpfr->Flags & FR_FINDNEXT)\r
1709                 {\r
1710                         app.DoSearch(lpfr->lpstrFindWhat, lpfr->Flags);\r
1711                 }\r
1712                 return 0; \r
1713         }\r
1714         switch (message) \r
1715         {\r
1716         case WM_CREATE:\r
1717                 app.m_wEditor = ::CreateWindow(\r
1718                         "Scintilla",\r
1719                         "Source",\r
1720                         WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_CLIPCHILDREN,\r
1721                         0, 0,\r
1722                         100, 100,\r
1723                         hWnd,\r
1724                         0,\r
1725                         app.hResource,\r
1726                         0);\r
1727                 app.InitialiseEditor();\r
1728                 ::ShowWindow(app.m_wEditor, SW_SHOW);\r
1729                 ::SetFocus(app.m_wEditor);\r
1730                 app.wBlame = ::CreateWindow(\r
1731                         _T("TortoiseGitBlameViewBlame"), \r
1732                         _T("blame"), \r
1733                         WS_CHILD | WS_CLIPCHILDREN,\r
1734                         CW_USEDEFAULT, 0, \r
1735                         CW_USEDEFAULT, 0, \r
1736                         hWnd, \r
1737                         NULL, \r
1738                         app.hResource, \r
1739                         NULL);\r
1740                 ::ShowWindow(app.wBlame, SW_SHOW);\r
1741                 app.wHeader = ::CreateWindow(\r
1742                         _T("TortoiseGitBlameViewHeader"), \r
1743                         _T("header"), \r
1744                         WS_CHILD | WS_CLIPCHILDREN | WS_BORDER,\r
1745                         CW_USEDEFAULT, 0, \r
1746                         CW_USEDEFAULT, 0, \r
1747                         hWnd, \r
1748                         NULL, \r
1749                         app.hResource, \r
1750                         NULL);\r
1751                 ::ShowWindow(app.wHeader, SW_SHOW);\r
1752                 app.wLocator = ::CreateWindow(\r
1753                         _T("TortoiseGitBlameViewLocator"), \r
1754                         _T("locator"), \r
1755                         WS_CHILD | WS_CLIPCHILDREN | WS_BORDER,\r
1756                         CW_USEDEFAULT, 0, \r
1757                         CW_USEDEFAULT, 0, \r
1758                         hWnd, \r
1759                         NULL, \r
1760                         app.hResource, \r
1761                         NULL);\r
1762                 ::ShowWindow(app.wLocator, SW_SHOW);\r
1763                 return 0;\r
1764 \r
1765         case WM_SIZE:\r
1766                 if (wParam != 1) \r
1767                 {\r
1768             app.InitSize();\r
1769                 }\r
1770                 return 0;\r
1771 \r
1772         case WM_COMMAND:\r
1773                 app.Command(LOWORD(wParam));\r
1774                 break;\r
1775         case WM_NOTIFY:\r
1776                 app.Notify(reinterpret_cast<SCNotification *>(lParam));\r
1777                 return 0;\r
1778         case WM_DESTROY:\r
1779                 PostQuitMessage(0);\r
1780                 break;\r
1781         case WM_CLOSE:\r
1782                 {\r
1783                         CRegStdWORD pos(_T("Software\\TortoiseGit\\TBlamePos"), 0);\r
1784                         CRegStdWORD width(_T("Software\\TortoiseGit\\TBlameSize"), 0);\r
1785                         CRegStdWORD state(_T("Software\\TortoiseGit\\TBlameState"), 0);\r
1786                         RECT rc;\r
1787                         GetWindowRect(app.wMain, &rc);\r
1788                         if ((rc.left >= 0)&&(rc.top >= 0))\r
1789                         {\r
1790                                 pos = MAKELONG(rc.left, rc.top);\r
1791                                 width = MAKELONG(rc.right-rc.left, rc.bottom-rc.top);\r
1792                         }\r
1793                         WINDOWPLACEMENT wp = {0};\r
1794                         wp.length = sizeof(WINDOWPLACEMENT);\r
1795                         GetWindowPlacement(app.wMain, &wp);\r
1796                         state = wp.showCmd;\r
1797                         ::DestroyWindow(app.m_wEditor);\r
1798                         ::PostQuitMessage(0);\r
1799                 }\r
1800                 return 0;\r
1801         case WM_SETFOCUS:\r
1802                 ::SetFocus(app.wBlame);\r
1803                 break;\r
1804         default:\r
1805                 return DefWindowProc(hWnd, message, wParam, lParam);\r
1806         }\r
1807         return 0;\r
1808 }\r
1809 \r
1810 LRESULT CALLBACK WndBlameProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
1811 {\r
1812         PAINTSTRUCT ps;\r
1813         TRACKMOUSEEVENT mevt;\r
1814         HDC hDC;\r
1815         switch (message) \r
1816         {\r
1817         case WM_CREATE:\r
1818                 return 0;\r
1819         case WM_PAINT:\r
1820                 hDC = BeginPaint(app.wBlame, &ps);\r
1821                 app.DrawBlame(hDC);\r
1822                 EndPaint(app.wBlame, &ps);\r
1823                 break;\r
1824         case WM_COMMAND:\r
1825                 app.Command(LOWORD(wParam));\r
1826                 break;\r
1827         case WM_NOTIFY:\r
1828                 switch (((LPNMHDR)lParam)->code)\r
1829                 {\r
1830                 case TTN_GETDISPINFO:\r
1831                         {\r
1832                                 LPNMHDR pNMHDR = (LPNMHDR)lParam;\r
1833                                 NMTTDISPINFOA* pTTTA = (NMTTDISPINFOA*)pNMHDR;\r
1834                                 NMTTDISPINFOW* pTTTW = (NMTTDISPINFOW*)pNMHDR;\r
1835                                 POINT point;\r
1836                                 DWORD ptW = GetMessagePos();\r
1837                                 point.x = GET_X_LPARAM(ptW);\r
1838                                 point.y = GET_Y_LPARAM(ptW);\r
1839                                 ::ScreenToClient(app.wBlame, &point);\r
1840                                 LONG_PTR line = app.SendEditor(SCI_GETFIRSTVISIBLELINE);\r
1841                                 LONG_PTR height = app.SendEditor(SCI_TEXTHEIGHT);\r
1842                                 line = line + (point.y/height);\r
1843                                 if (line >= (LONG)app.revs.size())\r
1844                                         break;\r
1845                                 if (line < 0)\r
1846                                         break;\r
1847                                 LONG rev = app.revs[line];\r
1848                                 if (line >= (LONG)app.revs.size())\r
1849                                         break;\r
1850 \r
1851                                 SecureZeroMemory(app.m_szTip, sizeof(app.m_szTip));\r
1852                                 SecureZeroMemory(app.m_wszTip, sizeof(app.m_wszTip));\r
1853                                 std::map<LONG, CString>::iterator iter;\r
1854                                 if ((iter = app.logmessages.find(rev)) != app.logmessages.end())\r
1855                                 {\r
1856                                         CString msg;\r
1857                                         if (!ShowAuthor)\r
1858                                         {\r
1859                                                 msg += app.authors[line];\r
1860                                         }\r
1861                                         if (!ShowDate)\r
1862                                         {\r
1863                                                 if (!ShowAuthor) msg += "  ";\r
1864                                                 msg += app.dates[line];\r
1865                                         }\r
1866                                         if (!ShowAuthor || !ShowDate)\r
1867                                                 msg += '\n';\r
1868                                         msg += iter->second;\r
1869                                         // an empty tooltip string will deactivate the tooltips,\r
1870                                         // which means we must make sure that the tooltip won't\r
1871                                         // be empty.\r
1872                                         if (msg.empty())\r
1873                                                 msg = _T(" ");\r
1874                                         if (pNMHDR->code == TTN_NEEDTEXTA)\r
1875                                         {\r
1876                                                 lstrcpyn(app.m_szTip, msg.c_str(), MAX_LOG_LENGTH*2);\r
1877                                                 app.StringExpand(app.m_szTip);\r
1878                                                 pTTTA->lpszText = app.m_szTip;\r
1879                                         }\r
1880                                         else\r
1881                                         {\r
1882                                                 pTTTW->lpszText = app.m_wszTip;\r
1883                                                 ::MultiByteToWideChar( CP_ACP , 0, msg.c_str(), min(msg.size(), MAX_LOG_LENGTH*2), app.m_wszTip, MAX_LOG_LENGTH*2);\r
1884                                                 app.StringExpand(app.m_wszTip);\r
1885                                         }\r
1886                                 }\r
1887                         }\r
1888                         break;\r
1889                 }\r
1890                 return 0;\r
1891         case WM_DESTROY:\r
1892                 break;\r
1893         case WM_CLOSE:\r
1894                 return 0;\r
1895         case WM_MOUSELEAVE:\r
1896                 app.m_mouserev = -2;\r
1897                 app.m_mouseauthor.clear();\r
1898                 app.ttVisible = FALSE;\r
1899                 SendMessage(app.hwndTT, TTM_TRACKACTIVATE, FALSE, 0);\r
1900                 ::InvalidateRect(app.wBlame, NULL, FALSE);\r
1901                 break;\r
1902         case WM_MOUSEMOVE:\r
1903                 {\r
1904                         mevt.cbSize = sizeof(TRACKMOUSEEVENT);\r
1905                         mevt.dwFlags = TME_LEAVE;\r
1906                         mevt.dwHoverTime = HOVER_DEFAULT;\r
1907                         mevt.hwndTrack = app.wBlame;\r
1908                         ::TrackMouseEvent(&mevt);\r
1909                         POINT pt = {((int)(short)LOWORD(lParam)), ((int)(short)HIWORD(lParam))};\r
1910                         ClientToScreen(app.wBlame, &pt);\r
1911                         pt.x += 15;\r
1912                         pt.y += 15;\r
1913                         SendMessage(app.hwndTT, TTM_TRACKPOSITION, 0, MAKELONG(pt.x, pt.y));\r
1914                         if (!app.ttVisible)\r
1915                         {\r
1916                                 TOOLINFO ti;\r
1917                                 ti.cbSize = sizeof(TOOLINFO);\r
1918                                 ti.hwnd = app.wBlame;\r
1919                                 ti.uId = 0;\r
1920                                 SendMessage(app.hwndTT, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti);\r
1921                         }\r
1922                         int y = ((int)(short)HIWORD(lParam));\r
1923                         LONG_PTR line = app.SendEditor(SCI_GETFIRSTVISIBLELINE);\r
1924                         LONG_PTR height = app.SendEditor(SCI_TEXTHEIGHT);\r
1925                         line = line + (y/height);\r
1926                         app.ttVisible = (line < (LONG)app.revs.size());\r
1927                         if ( app.ttVisible )\r
1928                         {\r
1929                                 if (app.authors[line].compare(app.m_mouseauthor) != 0)\r
1930                                 {\r
1931                                         app.m_mouseauthor = app.authors[line];\r
1932                                 }\r
1933                                 if (app.revs[line] != app.m_mouserev)\r
1934                                 {\r
1935                                         app.m_mouserev = app.revs[line];\r
1936                                         ::InvalidateRect(app.wBlame, NULL, FALSE);\r
1937                                         SendMessage(app.hwndTT, TTM_UPDATE, 0, 0);\r
1938                                 }\r
1939                         }\r
1940                 }\r
1941                 break;\r
1942         case WM_RBUTTONDOWN:\r
1943                 // fall through\r
1944         case WM_LBUTTONDOWN:\r
1945                 {\r
1946                 break;\r
1947         case WM_SETFOCUS:\r
1948                 ::SetFocus(app.wBlame);\r
1949                 app.SendEditor(SCI_GRABFOCUS);\r
1950                 break;\r
1951         case WM_CONTEXTMENU:\r
1952                 {\r
1953                         if (app.m_selectedrev <= 0)\r
1954                                 break;;\r
1955                         int xPos = GET_X_LPARAM(lParam);\r
1956                         int yPos = GET_Y_LPARAM(lParam);\r
1957                         if ((xPos < 0)||(yPos < 0))\r
1958                         {\r
1959                                 // requested from keyboard, not mouse pointer\r
1960                                 // use the center of the window\r
1961                                 RECT rect;\r
1962                                 GetClientRect(app.wBlame, &rect);\r
1963                                 xPos = rect.right-rect.left;\r
1964                                 yPos = rect.bottom-rect.top;\r
1965                         }\r
1966                         HMENU hMenu = LoadMenu(app.hResource, MAKEINTRESOURCE(IDR_BLAMEPOPUP));\r
1967                         HMENU hPopMenu = GetSubMenu(hMenu, 0);\r
1968 \r
1969                         if ( _tcslen(szOrigPath)==0 )\r
1970                         {\r
1971                                 // Without knowing the original path we cannot blame the previous revision\r
1972                                 // because we don't know which filename to pass to tortoiseproc.\r
1973                                 EnableMenuItem(hPopMenu,ID_BLAME_PREVIOUS_REVISION, MF_DISABLED|MF_GRAYED);\r
1974                         }\r
1975                         \r
1976                         TrackPopupMenu(hPopMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, xPos, yPos, 0, app.wBlame, NULL); \r
1977                         DestroyMenu(hMenu);\r
1978                 }\r
1979                 break;\r
1980         default:\r
1981                 return DefWindowProc(hWnd, message, wParam, lParam);\r
1982         }\r
1983         return 0;\r
1984 }\r
1985 \r
1986 LRESULT CALLBACK WndHeaderProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
1987 {\r
1988         PAINTSTRUCT ps;\r
1989         HDC hDC;\r
1990         switch (message) \r
1991         {\r
1992         case WM_CREATE:\r
1993                 return 0;\r
1994         case WM_PAINT:\r
1995                 hDC = BeginPaint(app.wHeader, &ps);\r
1996                 app.DrawHeader(hDC);\r
1997                 EndPaint(app.wHeader, &ps);\r
1998                 break;\r
1999         case WM_COMMAND:\r
2000                 break;\r
2001         case WM_DESTROY:\r
2002                 break;\r
2003         case WM_CLOSE:\r
2004                 return 0;\r
2005         default:\r
2006                 return DefWindowProc(hWnd, message, wParam, lParam);\r
2007         }\r
2008         return 0;\r
2009 }\r
2010 \r
2011 LRESULT CALLBACK WndLocatorProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
2012 {\r
2013         PAINTSTRUCT ps;\r
2014         HDC hDC;\r
2015         switch (message) \r
2016         {\r
2017         case WM_PAINT:\r
2018                 hDC = BeginPaint(app.wLocator, &ps);\r
2019                 app.DrawLocatorBar(hDC);\r
2020                 EndPaint(app.wLocator, &ps);\r
2021                 break;\r
2022         case WM_LBUTTONDOWN:\r
2023         case WM_MOUSEMOVE:\r
2024                 if (wParam & MK_LBUTTON)\r
2025                 {\r
2026                         RECT rect;\r
2027                         ::GetClientRect(hWnd, &rect); \r
2028                         int nLine = HIWORD(lParam)*app.revs.size()/(rect.bottom-rect.top);\r
2029 \r
2030                         if (nLine < 0)\r
2031                                 nLine = 0;\r
2032                         app.ScrollToLine(nLine);\r
2033                 }\r
2034                 break;\r
2035         default:\r
2036                 return DefWindowProc(hWnd, message, wParam, lParam);\r
2037         }\r
2038         return 0;\r
2039 }\r
2040 #endif\r
2041 \r
2042 void CTortoiseGitBlameView::SetupLexer(CString filename)\r
2043 {\r
2044 \r
2045         TCHAR *line;\r
2046         //const char * lineptr = _tcsrchr(filename, '.');\r
2047         int start=filename.ReverseFind(_T('.'));\r
2048         if (start>0)\r
2049         {\r
2050                 //_tcscpy_s(line, 20, lineptr+1);\r
2051                 //_tcslwr_s(line, 20);\r
2052                 CString ext=filename.Right(filename.GetLength()-start-1);\r
2053                 line=ext.GetBuffer();\r
2054 \r
2055                 if ((_tcscmp(line, _T("py"))==0)||\r
2056                         (_tcscmp(line, _T("pyw"))==0)||\r
2057                         (_tcscmp(line, _T("pyw"))==0))\r
2058                 {\r
2059                         SendEditor(SCI_SETLEXER, SCLEX_PYTHON);\r
2060                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("and assert break class continue def del elif \\r
2061 else except exec finally for from global if import in is lambda None \\r
2062 not or pass print raise return try while yield")).GetBuffer()));\r
2063                         SetAStyle(SCE_P_DEFAULT, black);\r
2064                         SetAStyle(SCE_P_COMMENTLINE, darkGreen);\r
2065                         SetAStyle(SCE_P_NUMBER, RGB(0, 0x80, 0x80));\r
2066                         SetAStyle(SCE_P_STRING, RGB(0, 0, 0x80));\r
2067                         SetAStyle(SCE_P_CHARACTER, RGB(0, 0, 0x80));\r
2068                         SetAStyle(SCE_P_WORD, RGB(0x80, 0, 0x80));\r
2069                         SetAStyle(SCE_P_TRIPLE, black);\r
2070                         SetAStyle(SCE_P_TRIPLEDOUBLE, black);\r
2071                         SetAStyle(SCE_P_CLASSNAME, darkBlue);\r
2072                         SetAStyle(SCE_P_DEFNAME, darkBlue);\r
2073                         SetAStyle(SCE_P_OPERATOR, darkBlue);\r
2074                         SetAStyle(SCE_P_IDENTIFIER, darkBlue);\r
2075                         SetAStyle(SCE_P_COMMENTBLOCK, darkGreen);\r
2076                         SetAStyle(SCE_P_STRINGEOL, red);\r
2077                 }\r
2078                 if ((_tcscmp(line, _T("c"))==0)||\r
2079                         (_tcscmp(line, _T("cc"))==0)||\r
2080                         (_tcscmp(line, _T("cpp"))==0)||\r
2081                         (_tcscmp(line, _T("cxx"))==0)||\r
2082                         (_tcscmp(line, _T("h"))==0)||\r
2083                         (_tcscmp(line, _T("hh"))==0)||\r
2084                         (_tcscmp(line, _T("hpp"))==0)||\r
2085                         (_tcscmp(line, _T("hxx"))==0)||\r
2086                         (_tcscmp(line, _T("dlg"))==0)||\r
2087                         (_tcscmp(line, _T("mak"))==0))\r
2088                 {\r
2089                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2090                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("and and_eq asm auto bitand bitor bool break \\r
2091 case catch char class compl const const_cast continue \\r
2092 default delete do double dynamic_cast else enum explicit export extern false float for \\r
2093 friend goto if inline int long mutable namespace new not not_eq \\r
2094 operator or or_eq private protected public \\r
2095 register reinterpret_cast return short signed sizeof static static_cast struct switch \\r
2096 template this throw true try typedef typeid typename union unsigned using \\r
2097 virtual void volatile wchar_t while xor xor_eq")).GetBuffer()));\r
2098                         SendEditor(SCI_SETKEYWORDS, 3, (LPARAM)(m_TextView.StringForControl(_T("a addindex addtogroup anchor arg attention \\r
2099 author b brief bug c class code date def defgroup deprecated dontinclude \\r
2100 e em endcode endhtmlonly endif endlatexonly endlink endverbatim enum example exception \\r
2101 f$ f[ f] file fn hideinitializer htmlinclude htmlonly \\r
2102 if image include ingroup internal invariant interface latexonly li line link \\r
2103 mainpage name namespace nosubgrouping note overload \\r
2104 p page par param post pre ref relates remarks return retval \\r
2105 sa section see showinitializer since skip skipline struct subsection \\r
2106 test throw todo typedef union until \\r
2107 var verbatim verbinclude version warning weakgroup $ @ \\ & < > # { }")).GetBuffer()));\r
2108                         SetupCppLexer();\r
2109                 }\r
2110                 if (_tcscmp(line, _T("cs"))==0)\r
2111                 {\r
2112                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2113                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("abstract as base bool break byte case catch char checked class \\r
2114 const continue decimal default delegate do double else enum \\r
2115 event explicit extern false finally fixed float for foreach goto if \\r
2116 implicit in int interface internal is lock long namespace new null \\r
2117 object operator out override params private protected public \\r
2118 readonly ref return sbyte sealed short sizeof stackalloc static \\r
2119 string struct switch this throw true try typeof uint ulong \\r
2120 unchecked unsafe ushort using virtual void while")).GetBuffer()));\r
2121                         SetupCppLexer();\r
2122                 }\r
2123                 if ((_tcscmp(line, _T("rc"))==0)||\r
2124                         (_tcscmp(line, _T("rc2"))==0))\r
2125                 {\r
2126                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2127                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("ACCELERATORS ALT AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON \\r
2128 BEGIN BITMAP BLOCK BUTTON CAPTION CHARACTERISTICS CHECKBOX CLASS \\r
2129 COMBOBOX CONTROL CTEXT CURSOR DEFPUSHBUTTON DIALOG DIALOGEX DISCARDABLE \\r
2130 EDITTEXT END EXSTYLE FONT GROUPBOX ICON LANGUAGE LISTBOX LTEXT \\r
2131 MENU MENUEX MENUITEM MESSAGETABLE POPUP \\r
2132 PUSHBUTTON RADIOBUTTON RCDATA RTEXT SCROLLBAR SEPARATOR SHIFT STATE3 \\r
2133 STRINGTABLE STYLE TEXTINCLUDE VALUE VERSION VERSIONINFO VIRTKEY")).GetBuffer()));\r
2134                         SetupCppLexer();\r
2135                 }\r
2136                 if ((_tcscmp(line, _T("idl"))==0)||\r
2137                         (_tcscmp(line, _T("odl"))==0))\r
2138                 {\r
2139                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2140                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("aggregatable allocate appobject arrays async async_uuid \\r
2141 auto_handle \\r
2142 bindable boolean broadcast byte byte_count \\r
2143 call_as callback char coclass code comm_status \\r
2144 const context_handle context_handle_noserialize \\r
2145 context_handle_serialize control cpp_quote custom \\r
2146 decode default defaultbind defaultcollelem \\r
2147 defaultvalue defaultvtable dispinterface displaybind dllname \\r
2148 double dual \\r
2149 enable_allocate encode endpoint entry enum error_status_t \\r
2150 explicit_handle \\r
2151 fault_status first_is float \\r
2152 handle_t heap helpcontext helpfile helpstring \\r
2153 helpstringcontext helpstringdll hidden hyper \\r
2154 id idempotent ignore iid_as iid_is immediatebind implicit_handle \\r
2155 import importlib in include in_line int __int64 __int3264 interface \\r
2156 last_is lcid length_is library licensed local long \\r
2157 max_is maybe message methods midl_pragma \\r
2158 midl_user_allocate midl_user_free min_is module ms_union \\r
2159 ncacn_at_dsp ncacn_dnet_nsp ncacn_http ncacn_ip_tcp \\r
2160 ncacn_nb_ipx ncacn_nb_nb ncacn_nb_tcp ncacn_np \\r
2161 ncacn_spx ncacn_vns_spp ncadg_ip_udp ncadg_ipx ncadg_mq \\r
2162 ncalrpc nocode nonbrowsable noncreatable nonextensible notify \\r
2163 object odl oleautomation optimize optional out out_of_line \\r
2164 pipe pointer_default pragma properties propget propput propputref \\r
2165 ptr public \\r
2166 range readonly ref represent_as requestedit restricted retval \\r
2167 shape short signed size_is small source strict_context_handle \\r
2168 string struct switch switch_is switch_type \\r
2169 transmit_as typedef \\r
2170 uidefault union unique unsigned user_marshal usesgetlasterror uuid \\r
2171 v1_enum vararg version void wchar_t wire_marshal")).GetBuffer()));\r
2172                         SetupCppLexer();\r
2173                 }\r
2174                 if (_tcscmp(line, _T("java"))==0)\r
2175                 {\r
2176                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2177                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("abstract assert boolean break byte case catch char class \\r
2178 const continue default do double else extends final finally float for future \\r
2179 generic goto if implements import inner instanceof int interface long \\r
2180 native new null outer package private protected public rest \\r
2181 return short static super switch synchronized this throw throws \\r
2182 transient try var void volatile while")).GetBuffer()));\r
2183                         SetupCppLexer();\r
2184                 }\r
2185                 if (_tcscmp(line, _T("js"))==0)\r
2186                 {\r
2187                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2188                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("abstract boolean break byte case catch char class \\r
2189 const continue debugger default delete do double else enum export extends \\r
2190 final finally float for function goto if implements import in instanceof \\r
2191 int interface long native new package private protected public \\r
2192 return short static super switch synchronized this throw throws \\r
2193 transient try typeof var void volatile while with")).GetBuffer()));\r
2194                         SetupCppLexer();\r
2195                 }\r
2196                 if ((_tcscmp(line, _T("pas"))==0)||\r
2197                         (_tcscmp(line, _T("dpr"))==0)||\r
2198                         (_tcscmp(line, _T("pp"))==0))\r
2199                 {\r
2200                         SendEditor(SCI_SETLEXER, SCLEX_PASCAL);\r
2201                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("and array as begin case class const constructor \\r
2202 destructor div do downto else end except file finally \\r
2203 for function goto if implementation in inherited \\r
2204 interface is mod not object of on or packed \\r
2205 procedure program property raise record repeat \\r
2206 set shl shr then threadvar to try type unit \\r
2207 until uses var while with xor")).GetBuffer()));\r
2208                         SetupCppLexer();\r
2209                 }\r
2210                 if ((_tcscmp(line, _T("as"))==0)||\r
2211                         (_tcscmp(line, _T("asc"))==0)||\r
2212                         (_tcscmp(line, _T("jsfl"))==0))\r
2213                 {\r
2214                         SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2215                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("add and break case catch class continue default delete do \\r
2216 dynamic else eq extends false finally for function ge get gt if implements import in \\r
2217 instanceof interface intrinsic le lt ne new not null or private public return \\r
2218 set static super switch this throw true try typeof undefined var void while with")).GetBuffer()));\r
2219                         SendEditor(SCI_SETKEYWORDS, 1, (LPARAM)(m_TextView.StringForControl(_T("Array Arguments Accessibility Boolean Button Camera Color \\r
2220 ContextMenu ContextMenuItem Date Error Function Key LoadVars LocalConnection Math \\r
2221 Microphone Mouse MovieClip MovieClipLoader NetConnection NetStream Number Object \\r
2222 PrintJob Selection SharedObject Sound Stage String StyleSheet System TextField \\r
2223 TextFormat TextSnapshot Video Void XML XMLNode XMLSocket \\r
2224 _accProps _focusrect _global _highquality _parent _quality _root _soundbuftime \\r
2225 arguments asfunction call capabilities chr clearInterval duplicateMovieClip \\r
2226 escape eval fscommand getProperty getTimer getURL getVersion gotoAndPlay gotoAndStop \\r
2227 ifFrameLoaded Infinity -Infinity int isFinite isNaN length loadMovie loadMovieNum \\r
2228 loadVariables loadVariablesNum maxscroll mbchr mblength mbord mbsubstring MMExecute \\r
2229 NaN newline nextFrame nextScene on onClipEvent onUpdate ord parseFloat parseInt play \\r
2230 prevFrame prevScene print printAsBitmap printAsBitmapNum printNum random removeMovieClip \\r
2231 scroll set setInterval setProperty startDrag stop stopAllSounds stopDrag substring \\r
2232 targetPath tellTarget toggleHighQuality trace unescape unloadMovie unLoadMovieNum updateAfterEvent")).GetBuffer()));\r
2233                         SetupCppLexer();\r
2234                 }\r
2235                 if ((_tcscmp(line, _T("html"))==0)||\r
2236                         (_tcscmp(line, _T("htm"))==0)||\r
2237                         (_tcscmp(line, _T("shtml"))==0)||\r
2238                         (_tcscmp(line, _T("htt"))==0)||\r
2239                         (_tcscmp(line, _T("xml"))==0)||\r
2240                         (_tcscmp(line, _T("asp"))==0)||\r
2241                         (_tcscmp(line, _T("xsl"))==0)||\r
2242                         (_tcscmp(line, _T("php"))==0)||\r
2243                         (_tcscmp(line, _T("xhtml"))==0)||\r
2244                         (_tcscmp(line, _T("phtml"))==0)||\r
2245                         (_tcscmp(line, _T("cfm"))==0)||\r
2246                         (_tcscmp(line, _T("tpl"))==0)||\r
2247                         (_tcscmp(line, _T("dtd"))==0)||\r
2248                         (_tcscmp(line, _T("hta"))==0)||\r
2249                         (_tcscmp(line, _T("htd"))==0)||\r
2250                         (_tcscmp(line, _T("wxs"))==0))\r
2251                 {\r
2252                         SendEditor(SCI_SETLEXER, SCLEX_HTML);\r
2253                         SendEditor(SCI_SETSTYLEBITS, 7);\r
2254                         SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("a abbr acronym address applet area b base basefont \\r
2255 bdo big blockquote body br button caption center \\r
2256 cite code col colgroup dd del dfn dir div dl dt em \\r
2257 fieldset font form frame frameset h1 h2 h3 h4 h5 h6 \\r
2258 head hr html i iframe img input ins isindex kbd label \\r
2259 legend li link map menu meta noframes noscript \\r
2260 object ol optgroup option p param pre q s samp \\r
2261 script select small span strike strong style sub sup \\r
2262 table tbody td textarea tfoot th thead title tr tt u ul \\r
2263 var xml xmlns abbr accept-charset accept accesskey action align alink \\r
2264 alt archive axis background bgcolor border \\r
2265 cellpadding cellspacing char charoff charset checked cite \\r
2266 class classid clear codebase codetype color cols colspan \\r
2267 compact content coords \\r
2268 data datafld dataformatas datapagesize datasrc datetime \\r
2269 declare defer dir disabled enctype event \\r
2270 face for frame frameborder \\r
2271 headers height href hreflang hspace http-equiv \\r
2272 id ismap label lang language leftmargin link longdesc \\r
2273 marginwidth marginheight maxlength media method multiple \\r
2274 name nohref noresize noshade nowrap \\r
2275 object onblur onchange onclick ondblclick onfocus \\r
2276 onkeydown onkeypress onkeyup onload onmousedown \\r
2277 onmousemove onmouseover onmouseout onmouseup \\r
2278 onreset onselect onsubmit onunload \\r
2279 profile prompt readonly rel rev rows rowspan rules \\r
2280 scheme scope selected shape size span src standby start style \\r
2281 summary tabindex target text title topmargin type usemap \\r
2282 valign value valuetype version vlink vspace width \\r
2283 text password checkbox radio submit reset \\r
2284 file hidden image")).GetBuffer()));\r
2285                         SendEditor(SCI_SETKEYWORDS, 1, (LPARAM)(m_TextView.StringForControl(_T("assign audio block break catch choice clear disconnect else elseif \\r
2286 emphasis enumerate error exit field filled form goto grammar help \\r
2287 if initial link log menu meta noinput nomatch object option p paragraph \\r
2288 param phoneme prompt property prosody record reprompt return s say-as \\r
2289 script sentence subdialog submit throw transfer value var voice vxml")).GetBuffer()));\r
2290                         SendEditor(SCI_SETKEYWORDS, 2, (LPARAM)(m_TextView.StringForControl(_T("accept age alphabet anchor application base beep bridge category charset \\r
2291 classid cond connecttimeout content contour count dest destexpr dtmf dtmfterm \\r
2292 duration enctype event eventexpr expr expritem fetchtimeout finalsilence \\r
2293 gender http-equiv id level maxage maxstale maxtime message messageexpr \\r
2294 method mime modal mode name namelist next nextitem ph pitch range rate \\r
2295 scope size sizeexpr skiplist slot src srcexpr sub time timeexpr timeout \\r
2296 transferaudio type value variant version volume xml:lang")).GetBuffer()));\r
2297                         SendEditor(SCI_SETKEYWORDS, 3, (LPARAM)(m_TextView.StringForControl(_T("and assert break class continue def del elif \\r
2298 else except exec finally for from global if import in is lambda None \\r
2299 not or pass print raise return try while yield")).GetBuffer()));\r
2300                         SendEditor(SCI_SETKEYWORDS, 4, (LPARAM)(m_TextView.StringForControl(_T("and argv as argc break case cfunction class continue declare default do \\r
2301 die echo else elseif empty enddeclare endfor endforeach endif endswitch \\r
2302 endwhile e_all e_parse e_error e_warning eval exit extends false for \\r
2303 foreach function global http_cookie_vars http_get_vars http_post_vars \\r
2304 http_post_files http_env_vars http_server_vars if include include_once \\r
2305 list new not null old_function or parent php_os php_self php_version \\r
2306 print require require_once return static switch stdclass this true var \\r
2307 xor virtual while __file__ __line__ __sleep __wakeup")).GetBuffer()));\r
2308 \r
2309                         SetAStyle(SCE_H_TAG, darkBlue);\r
2310                         SetAStyle(SCE_H_TAGUNKNOWN, red);\r
2311                         SetAStyle(SCE_H_ATTRIBUTE, darkBlue);\r
2312                         SetAStyle(SCE_H_ATTRIBUTEUNKNOWN, red);\r
2313                         SetAStyle(SCE_H_NUMBER, RGB(0x80,0,0x80));\r
2314                         SetAStyle(SCE_H_DOUBLESTRING, RGB(0,0x80,0));\r
2315                         SetAStyle(SCE_H_SINGLESTRING, RGB(0,0x80,0));\r
2316                         SetAStyle(SCE_H_OTHER, RGB(0x80,0,0x80));\r
2317                         SetAStyle(SCE_H_COMMENT, RGB(0x80,0x80,0));\r
2318                         SetAStyle(SCE_H_ENTITY, RGB(0x80,0,0x80));\r
2319 \r
2320                         SetAStyle(SCE_H_TAGEND, darkBlue);\r
2321                         SetAStyle(SCE_H_XMLSTART, darkBlue);    // <?\r
2322                         SetAStyle(SCE_H_QUESTION, darkBlue);    // <?\r
2323                         SetAStyle(SCE_H_XMLEND, darkBlue);              // ?>\r
2324                         SetAStyle(SCE_H_SCRIPT, darkBlue);              // <script\r
2325                         SetAStyle(SCE_H_ASP, RGB(0x4F, 0x4F, 0), RGB(0xFF, 0xFF, 0));   // <% ... %>\r
2326                         SetAStyle(SCE_H_ASPAT, RGB(0x4F, 0x4F, 0), RGB(0xFF, 0xFF, 0)); // <%@ ... %>\r
2327 \r
2328                         SetAStyle(SCE_HB_DEFAULT, black);\r
2329                         SetAStyle(SCE_HB_COMMENTLINE, darkGreen);\r
2330                         SetAStyle(SCE_HB_NUMBER, RGB(0,0x80,0x80));\r
2331                         SetAStyle(SCE_HB_WORD, darkBlue);\r
2332                         SendEditor(SCI_STYLESETBOLD, SCE_HB_WORD, 1);\r
2333                         SetAStyle(SCE_HB_STRING, RGB(0x80,0,0x80));\r
2334                         SetAStyle(SCE_HB_IDENTIFIER, black);\r
2335 \r
2336                         // This light blue is found in the windows system palette so is safe to use even in 256 colour modes.\r
2337                         // Show the whole section of VBScript with light blue background\r
2338                         for (int bstyle=SCE_HB_DEFAULT; bstyle<=SCE_HB_STRINGEOL; bstyle++) {\r
2339                                 SendEditor(SCI_STYLESETFONT, bstyle, \r
2340                                         reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2341                                 SendEditor(SCI_STYLESETBACK, bstyle, lightBlue);\r
2342                                 // This call extends the backround colour of the last style on the line to the edge of the window\r
2343                                 SendEditor(SCI_STYLESETEOLFILLED, bstyle, 1);\r
2344                         }\r
2345                         SendEditor(SCI_STYLESETBACK, SCE_HB_STRINGEOL, RGB(0x7F,0x7F,0xFF));\r
2346                         SendEditor(SCI_STYLESETFONT, SCE_HB_COMMENTLINE, \r
2347                                 reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2348 \r
2349                         SetAStyle(SCE_HBA_DEFAULT, black);\r
2350                         SetAStyle(SCE_HBA_COMMENTLINE, darkGreen);\r
2351                         SetAStyle(SCE_HBA_NUMBER, RGB(0,0x80,0x80));\r
2352                         SetAStyle(SCE_HBA_WORD, darkBlue);\r
2353                         SendEditor(SCI_STYLESETBOLD, SCE_HBA_WORD, 1);\r
2354                         SetAStyle(SCE_HBA_STRING, RGB(0x80,0,0x80));\r
2355                         SetAStyle(SCE_HBA_IDENTIFIER, black);\r
2356 \r
2357                         // Show the whole section of ASP VBScript with bright yellow background\r
2358                         for (int bastyle=SCE_HBA_DEFAULT; bastyle<=SCE_HBA_STRINGEOL; bastyle++) {\r
2359                                 SendEditor(SCI_STYLESETFONT, bastyle, \r
2360                                         reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2361                                 SendEditor(SCI_STYLESETBACK, bastyle, RGB(0xFF, 0xFF, 0));\r
2362                                 // This call extends the backround colour of the last style on the line to the edge of the window\r
2363                                 SendEditor(SCI_STYLESETEOLFILLED, bastyle, 1);\r
2364                         }\r
2365                         SendEditor(SCI_STYLESETBACK, SCE_HBA_STRINGEOL, RGB(0xCF,0xCF,0x7F));\r
2366                         SendEditor(SCI_STYLESETFONT, SCE_HBA_COMMENTLINE, \r
2367                                 reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2368 \r
2369                         // If there is no need to support embedded Javascript, the following code can be dropped.\r
2370                         // Javascript will still be correctly processed but will be displayed in just the default style.\r
2371 \r
2372                         SetAStyle(SCE_HJ_START, RGB(0x80,0x80,0));\r
2373                         SetAStyle(SCE_HJ_DEFAULT, black);\r
2374                         SetAStyle(SCE_HJ_COMMENT, darkGreen);\r
2375                         SetAStyle(SCE_HJ_COMMENTLINE, darkGreen);\r
2376                         SetAStyle(SCE_HJ_COMMENTDOC, darkGreen);\r
2377                         SetAStyle(SCE_HJ_NUMBER, RGB(0,0x80,0x80));\r
2378                         SetAStyle(SCE_HJ_WORD, black);\r
2379                         SetAStyle(SCE_HJ_KEYWORD, darkBlue);\r
2380                         SetAStyle(SCE_HJ_DOUBLESTRING, RGB(0x80,0,0x80));\r
2381                         SetAStyle(SCE_HJ_SINGLESTRING, RGB(0x80,0,0x80));\r
2382                         SetAStyle(SCE_HJ_SYMBOLS, black);\r
2383 \r
2384                         SetAStyle(SCE_HJA_START, RGB(0x80,0x80,0));\r
2385                         SetAStyle(SCE_HJA_DEFAULT, black);\r
2386                         SetAStyle(SCE_HJA_COMMENT, darkGreen);\r
2387                         SetAStyle(SCE_HJA_COMMENTLINE, darkGreen);\r
2388                         SetAStyle(SCE_HJA_COMMENTDOC, darkGreen);\r
2389                         SetAStyle(SCE_HJA_NUMBER, RGB(0,0x80,0x80));\r
2390                         SetAStyle(SCE_HJA_WORD, black);\r
2391                         SetAStyle(SCE_HJA_KEYWORD, darkBlue);\r
2392                         SetAStyle(SCE_HJA_DOUBLESTRING, RGB(0x80,0,0x80));\r
2393                         SetAStyle(SCE_HJA_SINGLESTRING, RGB(0x80,0,0x80));\r
2394                         SetAStyle(SCE_HJA_SYMBOLS, black);\r
2395 \r
2396                         SetAStyle(SCE_HPHP_DEFAULT, black);\r
2397                         SetAStyle(SCE_HPHP_HSTRING,  RGB(0x80,0,0x80));\r
2398                         SetAStyle(SCE_HPHP_SIMPLESTRING,  RGB(0x80,0,0x80));\r
2399                         SetAStyle(SCE_HPHP_WORD, darkBlue);\r
2400                         SetAStyle(SCE_HPHP_NUMBER, RGB(0,0x80,0x80));\r
2401                         SetAStyle(SCE_HPHP_VARIABLE, red);\r
2402                         SetAStyle(SCE_HPHP_HSTRING_VARIABLE, red);\r
2403                         SetAStyle(SCE_HPHP_COMPLEX_VARIABLE, red);\r
2404                         SetAStyle(SCE_HPHP_COMMENT, darkGreen);\r
2405                         SetAStyle(SCE_HPHP_COMMENTLINE, darkGreen);\r
2406                         SetAStyle(SCE_HPHP_OPERATOR, darkBlue);\r
2407 \r
2408                         // Show the whole section of Javascript with off white background\r
2409                         for (int jstyle=SCE_HJ_DEFAULT; jstyle<=SCE_HJ_SYMBOLS; jstyle++) {\r
2410                                 SendEditor(SCI_STYLESETFONT, jstyle, \r
2411                                         reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2412                                 SendEditor(SCI_STYLESETBACK, jstyle, offWhite);\r
2413                                 SendEditor(SCI_STYLESETEOLFILLED, jstyle, 1);\r
2414                         }\r
2415                         SendEditor(SCI_STYLESETBACK, SCE_HJ_STRINGEOL, RGB(0xDF, 0xDF, 0x7F));\r
2416                         SendEditor(SCI_STYLESETEOLFILLED, SCE_HJ_STRINGEOL, 1);\r
2417 \r
2418                         // Show the whole section of Javascript with brown background\r
2419                         for (int jastyle=SCE_HJA_DEFAULT; jastyle<=SCE_HJA_SYMBOLS; jastyle++) {\r
2420                                 SendEditor(SCI_STYLESETFONT, jastyle, \r
2421                                         reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
2422                                 SendEditor(SCI_STYLESETBACK, jastyle, RGB(0xDF, 0xDF, 0x7F));\r
2423                                 SendEditor(SCI_STYLESETEOLFILLED, jastyle, 1);\r
2424                         }\r
2425                         SendEditor(SCI_STYLESETBACK, SCE_HJA_STRINGEOL, RGB(0x0,0xAF,0x5F));\r
2426                         SendEditor(SCI_STYLESETEOLFILLED, SCE_HJA_STRINGEOL, 1);\r
2427                 }\r
2428         }\r
2429         else\r
2430         {\r
2431                 SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
2432                 SetupCppLexer();\r
2433         }\r
2434         SendEditor(SCI_COLOURISE, 0, -1);\r
2435 \r
2436 }\r
2437 \r
2438 void CTortoiseGitBlameView::SetupCppLexer()\r
2439 {\r
2440         SetAStyle(SCE_C_DEFAULT, RGB(0, 0, 0));\r
2441         SetAStyle(SCE_C_COMMENT, RGB(0, 0x80, 0));\r
2442         SetAStyle(SCE_C_COMMENTLINE, RGB(0, 0x80, 0));\r
2443         SetAStyle(SCE_C_COMMENTDOC, RGB(0, 0x80, 0));\r
2444         SetAStyle(SCE_C_COMMENTLINEDOC, RGB(0, 0x80, 0));\r
2445         SetAStyle(SCE_C_COMMENTDOCKEYWORD, RGB(0, 0x80, 0));\r
2446         SetAStyle(SCE_C_COMMENTDOCKEYWORDERROR, RGB(0, 0x80, 0));\r
2447         SetAStyle(SCE_C_NUMBER, RGB(0, 0x80, 0x80));\r
2448         SetAStyle(SCE_C_WORD, RGB(0, 0, 0x80));\r
2449         SendEditor(SCE_C_WORD, 1);\r
2450         SetAStyle(SCE_C_STRING, RGB(0x80, 0, 0x80));\r
2451         SetAStyle(SCE_C_IDENTIFIER, RGB(0, 0, 0));\r
2452         SetAStyle(SCE_C_PREPROCESSOR, RGB(0x80, 0, 0));\r
2453         SetAStyle(SCE_C_OPERATOR, RGB(0x80, 0x80, 0));\r
2454 }\r
2455 \r
2456 \r
2457 void CTortoiseGitBlameView::UpdateInfo()\r
2458 {\r
2459         CString &data = GetDocument()->m_BlameData;\r
2460         CString one;\r
2461         int pos=0;\r
2462 \r
2463         CLogDataVector * pRevs= GetLogData();\r
2464 \r
2465         this->m_CommitHash.clear();\r
2466         this->m_Authors.clear();\r
2467         this->m_ID.clear();\r
2468         CString line;\r
2469 \r
2470         CreateFont();\r
2471 \r
2472         SendEditor(SCI_SETREADONLY, FALSE);\r
2473         SendEditor(SCI_CLEARALL);\r
2474         SendEditor(EM_EMPTYUNDOBUFFER);\r
2475         SendEditor(SCI_SETSAVEPOINT);\r
2476         SendEditor(SCI_CANCEL);\r
2477         SendEditor(SCI_SETUNDOCOLLECTION, 0);\r
2478 \r
2479         while( pos>=0 )\r
2480         {\r
2481                 one=data.Tokenize(_T("\n"),pos);\r
2482                 if(one.IsEmpty())\r
2483                         continue;\r
2484                 m_CommitHash.push_back(one.Left(40));\r
2485                 int start=0;\r
2486                 start=one.Find(_T(')'),40);\r
2487                 if(start>0)\r
2488                 {\r
2489                         line=one.Right(one.GetLength()-start-2);\r
2490                         this->m_TextView.InsertText(line,true);\r
2491                 }\r
2492                 int id=pRevs->m_HashMap[one.Left(40)];          \r
2493                 if(id>=0 && id <GetLogData()->size())\r
2494                 {\r
2495                         m_ID.push_back(pRevs->size()-id);\r
2496                         m_Authors.push_back(pRevs->at(id).m_AuthorName);\r
2497                 }else\r
2498                 {\r
2499                         ASSERT(FALSE);\r
2500                 }\r
2501         }\r
2502 \r
2503         SetupLexer(GetDocument()->m_CurrentFileName);\r
2504 \r
2505         SendEditor(SCI_SETUNDOCOLLECTION, 1);\r
2506         SendEditor(EM_EMPTYUNDOBUFFER);\r
2507         SendEditor(SCI_SETSAVEPOINT);\r
2508         SendEditor(SCI_GOTOPOS, 0);\r
2509         SendEditor(SCI_SETSCROLLWIDTHTRACKING, TRUE);\r
2510         SendEditor(SCI_SETREADONLY, TRUE);\r
2511 \r
2512         m_lowestrev=1;\r
2513         m_highestrev=this->GetLogData()->size();\r
2514 \r
2515         GetBlameWidth();\r
2516         CRect rect;\r
2517         this->GetClientRect(rect);\r
2518         //this->m_TextView.GetWindowRect(rect);\r
2519         //this->m_TextView.ScreenToClient(rect);\r
2520         rect.left=this->m_blamewidth;\r
2521         this->m_TextView.MoveWindow(rect);\r
2522 \r
2523         this->Invalidate();\r
2524 }\r
2525 \r
2526 CGitBlameLogList * CTortoiseGitBlameView::GetLogList()\r
2527 {\r
2528         return &(GetDocument()->GetMainFrame()->m_wndOutput.m_LogList);\r
2529 }\r
2530 \r
2531 \r
2532 CLogDataVector * CTortoiseGitBlameView::GetLogData()\r
2533 {\r
2534         return &(GetDocument()->GetMainFrame()->m_wndOutput.m_LogList.m_logEntries);\r
2535 }\r
2536 \r
2537 void CTortoiseGitBlameView::OnSciPainted(NMHDR *,LRESULT *)\r
2538 {\r
2539         this->Invalidate();\r
2540 }\r
2541 \r
2542 void CTortoiseGitBlameView::OnLButtonDown(UINT nFlags,CPoint point)\r
2543 {\r
2544 \r
2545         LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
2546         LONG_PTR height = SendEditor(SCI_TEXTHEIGHT);\r
2547         line = line + (point.y/height);\r
2548                         \r
2549         if (line < (LONG)m_CommitHash.size())\r
2550         {\r
2551                 SetSelectedLine(line);\r
2552                 if (m_CommitHash[line] != m_SelectedHash)\r
2553                 {\r
2554                         m_SelectedHash = m_CommitHash[line];\r
2555 //                      app.m_selectedorigrev = app.origrevs[line];\r
2556 //                      app.m_selectedauthor = app.authors[line];\r
2557 //                      app.m_selecteddate = app.dates[line];\r
2558                         \r
2559                         \r
2560                         this->GetLogList()->SetItemState(this->GetLogList()->GetItemCount()-m_ID[line],\r
2561                                                                                                                         LVIS_SELECTED,\r
2562                                                                                                                         LVIS_SELECTED);\r
2563 \r
2564                         GitRev *pRev;\r
2565                         pRev=&this->GetLogData()->at(this->GetLogList()->GetItemCount()-m_ID[line]);\r
2566                         this->GetDocument()->GetMainFrame()->m_wndProperties.UpdateProperties(pRev);\r
2567                 }\r
2568                 else\r
2569                 {\r
2570                         m_SelectedHash.Empty();\r
2571 //                      app.m_selecteddate.clear();\r
2572 //                      app.m_selectedrev = -2;\r
2573 //                      app.m_selectedorigrev = -2;\r
2574                 }\r
2575                 //::InvalidateRect( NULL, FALSE);\r
2576                 this->Invalidate();\r
2577                 this->m_TextView.Invalidate();\r
2578                 \r
2579         }\r
2580         else\r
2581         {\r
2582                 SetSelectedLine(-1);\r
2583         }\r
2584                 \r
2585         CView::OnLButtonDown(nFlags,point);\r
2586 }\r
2587 \r
2588 void CTortoiseGitBlameView::OnSciGetBkColor(NMHDR* hdr, LRESULT* result)\r
2589 {\r
2590 \r
2591         SCNotification *notification=reinterpret_cast<SCNotification *>(hdr);\r
2592 \r
2593         if ((m_colorage)&&(notification->line < (int)m_CommitHash.size()))\r
2594         {\r
2595                 if(m_CommitHash[notification->line] == this->m_SelectedHash )\r
2596                         notification->lParam = m_selectedauthorcolor;\r
2597                 else\r
2598                         notification->lParam = InterColor(DWORD(m_regOldLinesColor), DWORD(m_regNewLinesColor), (m_ID[notification->line]-m_lowestrev)*100/((m_highestrev-m_lowestrev)+1));\r
2599         }\r
2600 \r
2601 }\r
2602 \r
2603 void CTortoiseGitBlameView::FocusOn(GitRev *pRev)\r
2604 {\r
2605         m_SelectedHash = pRev->m_CommitHash;\r
2606 \r
2607         //GitRev *pRev;\r
2608         //pRev=&this->GetLogData()->at(this->GetLogList()->GetItemCount()-m_ID[line]);\r
2609         this->GetDocument()->GetMainFrame()->m_wndProperties.UpdateProperties(pRev);\r
2610 \r
2611         this->Invalidate();\r
2612         this->m_TextView.Invalidate();\r
2613 \r
2614 }\r
2615 \r
2616 void CTortoiseGitBlameView::OnMouseHover(UINT nFlags, CPoint point)\r
2617 {\r
2618 \r
2619         LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
2620         LONG_PTR height = SendEditor(SCI_TEXTHEIGHT);\r
2621         line = line + (point.y/height);\r
2622                         \r
2623         if (line < (LONG)m_CommitHash.size())\r
2624         {\r
2625                 if (line != m_MouseLine)\r
2626                 {\r
2627                         m_MouseLine = line;//m_CommitHash[line];\r
2628 //                      app.m_selectedorigrev = app.origrevs[line];\r
2629 //                      app.m_selectedauthor = app.authors[line];\r
2630 //                      app.m_selecteddate = app.dates[line];\r
2631                         \r
2632                         \r
2633                         GitRev *pRev;\r
2634                         pRev=&this->GetLogData()->at(this->GetLogList()->GetItemCount()-m_ID[line]);\r
2635                         //this->GetDocument()->GetMainFrame()->m_wndProperties.UpdateProperties(pRev);\r
2636                         this->ClientToScreen(&point);\r
2637                         //BALLOON_INFO bi;\r
2638                         //if(m_ToolTip.GetTool(this, bi))\r
2639                         //{\r
2640                         //      bi.sBalloonTip=pRev->m_CommitHash;\r
2641                                 CString str;\r
2642                                 str.Format(_T("%s\n<b>%s</b>\n%s"),pRev->m_CommitHash,pRev->m_Subject,pRev->m_AuthorDate.Format(_T("%Y-%m-%d %H:%M")));\r
2643                                 m_ToolTip.AddTool(this,str);\r
2644                                 m_ToolTip.DisplayToolTip(&point);\r
2645                         //}\r
2646 \r
2647                 }\r
2648                 else\r
2649                 {\r
2650                         m_MouseLine=-1;\r
2651 //                      app.m_selecteddate.clear();\r
2652 //                      app.m_selectedrev = -2;\r
2653 //                      app.m_selectedorigrev = -2;\r
2654                 }\r
2655                 //::InvalidateRect( NULL, FALSE);\r
2656                 //this->Invalidate();\r
2657         }\r
2658         \r
2659 //       const CString str=_T("this is a <b>Message Balloon</b>\n<hr=100%>\n<ct=0x0000FF>Warning! Warning!</ct>\nSomething unexpected happened");\r
2660          //CBalloon::ShowBalloon(NULL, point, \r
2661           //            str,\r
2662           //             FALSE, (HICON)IDI_EXCLAMATION,\r
2663                 //                 (UINT)CBalloon ::BALLOON_RIGHT_TOP, (UINT)CBalloon ::BALLOON_EFFECT_SOLID,(COLORREF)NULL,  (COLORREF)NULL,  (COLORREF)NULL);\r
2664 }\r
2665 \r
2666 void CTortoiseGitBlameView::OnMouseMove(UINT nFlags, CPoint point)\r
2667 {\r
2668         TRACKMOUSEEVENT tme;\r
2669         tme.cbSize=sizeof(TRACKMOUSEEVENT);\r
2670         tme.dwFlags=TME_HOVER|TME_LEAVE;\r
2671         tme.hwndTrack=this->m_hWnd;\r
2672         tme.dwHoverTime=1;\r
2673         TrackMouseEvent(&tme);\r
2674 }\r
2675 \r
2676 \r
2677 BOOL CTortoiseGitBlameView::PreTranslateMessage(MSG* pMsg)\r
2678 {\r
2679         m_ToolTip.RelayEvent(pMsg);\r
2680         return CView::PreTranslateMessage(pMsg);\r
2681 }