+CString CTortoiseGitBlameView::GetAppDirectory()\r
+{\r
+ CString path;\r
+ DWORD len = 0;\r
+ DWORD bufferlen = MAX_PATH; // MAX_PATH is not the limit here!\r
+ do \r
+ {\r
+ bufferlen += MAX_PATH; // MAX_PATH is not the limit here!\r
+ TCHAR * pBuf = new TCHAR[bufferlen];\r
+ len = GetModuleFileName(NULL, pBuf, bufferlen); \r
+ path = CString(pBuf, len);\r
+ delete [] pBuf;\r
+ } while(len == bufferlen);\r
+\r
+ path = path.Left(path.ReverseFind(_T('\\')));\r
+ //path = path.substr(0, path.rfind('\\') + 1);\r
+\r
+ return path;\r
+}\r
+\r
+// Return a color which is interpolated between c1 and c2.\r
+// Slider controls the relative proportions as a percentage:\r
+// Slider = 0 represents pure c1\r
+// Slider = 50 represents equal mixture\r
+// Slider = 100 represents pure c2\r
+COLORREF CTortoiseGitBlameView::InterColor(COLORREF c1, COLORREF c2, int Slider)\r
+{\r
+ int r, g, b;\r
+ \r
+ // Limit Slider to 0..100% range\r
+ if (Slider < 0)\r
+ Slider = 0;\r
+ if (Slider > 100)\r
+ Slider = 100;\r
+ \r
+ // The color components have to be treated individually.\r
+ r = (GetRValue(c2) * Slider + GetRValue(c1) * (100 - Slider)) / 100;\r
+ g = (GetGValue(c2) * Slider + GetGValue(c1) * (100 - Slider)) / 100;\r
+ b = (GetBValue(c2) * Slider + GetBValue(c1) * (100 - Slider)) / 100;\r
+ \r
+ return RGB(r, g, b);\r
+}\r
+\r
+LRESULT CTortoiseGitBlameView::SendEditor(UINT Msg, WPARAM wParam, LPARAM lParam)\r
+{\r
+ if (m_directFunction)\r
+ {\r
+ return ((SciFnDirect) m_directFunction)(m_directPointer, Msg, wParam, lParam);\r
+ }\r
+ return ::SendMessage(m_wEditor, Msg, wParam, lParam); \r
+}\r
+\r
+void CTortoiseGitBlameView::GetRange(int start, int end, char *text) \r
+{\r
+#if 0\r
+ TEXTRANGE tr;\r
+ tr.chrg.cpMin = start;\r
+ tr.chrg.cpMax = end;\r
+ tr.lpstrText = text;\r
+\r
+ SendMessage(m_wEditor, EM_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&tr));\r
+#endif\r
+}\r
+\r
+void CTortoiseGitBlameView::SetTitle() \r
+{\r
+#if 0\r
+ char title[MAX_PATH + 100];\r
+ strcpy_s(title, MAX_PATH + 100, szTitle);\r
+ strcat_s(title, MAX_PATH + 100, " - ");\r
+ strcat_s(title, MAX_PATH + 100, szViewtitle);\r
+ ::SetWindowText(wMain, title);\r
+#endif\r
+}\r
+\r
+BOOL CTortoiseGitBlameView::OpenLogFile(const char *fileName)\r
+{\r
+#if 0\r
+ char logmsgbuf[10000+1];\r
+ FILE * File;\r
+ fopen_s(&File, fileName, "rb");\r
+ if (File == 0)\r
+ {\r
+ return FALSE;\r
+ }\r
+ LONG rev = 0;\r
+ CString msg;\r
+ int slength = 0;\r
+ int reallength = 0;\r
+ size_t len = 0;\r
+ wchar_t wbuf[MAX_LOG_LENGTH+6];\r
+ for (;;)\r
+ {\r
+ len = fread(&rev, sizeof(LONG), 1, File);\r
+ if (len == 0)\r
+ {\r
+ fclose(File);\r
+ InitSize();\r
+ return TRUE;\r
+ }\r
+ len = fread(&slength, sizeof(int), 1, File);\r
+ if (len == 0)\r
+ {\r
+ fclose(File);\r
+ InitSize();\r
+ return FALSE;\r
+ }\r
+ if (slength > MAX_LOG_LENGTH)\r
+ {\r
+ reallength = slength;\r
+ slength = MAX_LOG_LENGTH;\r
+ }\r
+ else\r
+ reallength = 0;\r
+ len = fread(logmsgbuf, sizeof(char), slength, File);\r
+ if (len < (size_t)slength)\r
+ {\r
+ fclose(File);\r
+ InitSize();\r
+ return FALSE;\r
+ }\r
+ msg = CString(logmsgbuf, slength);\r
+ if (reallength)\r
+ {\r
+ fseek(File, reallength-MAX_LOG_LENGTH, SEEK_CUR);\r
+ msg = msg + _T("\n...");\r
+ }\r
+ int len2 = ::MultiByteToWideChar(CP_UTF8, NULL, msg.c_str(), min(msg.size(), MAX_LOG_LENGTH+5), wbuf, MAX_LOG_LENGTH+5);\r
+ wbuf[len2] = 0;\r
+ len2 = ::WideCharToMultiByte(CP_ACP, NULL, wbuf, len2, logmsgbuf, MAX_LOG_LENGTH+5, NULL, NULL);\r
+ logmsgbuf[len2] = 0;\r
+ msg = CString(logmsgbuf);\r
+ logmessages[rev] = msg;\r
+ }\r
+#endif\r
+ return TRUE;\r
+}\r
+\r
+BOOL CTortoiseGitBlameView::OpenFile(const char *fileName) \r
+{\r
+#if 0\r
+ SendEditor(SCI_SETREADONLY, FALSE);\r
+ SendEditor(SCI_CLEARALL);\r
+ SendEditor(EM_EMPTYUNDOBUFFER);\r
+ SetTitle();\r
+ SendEditor(SCI_SETSAVEPOINT);\r
+ SendEditor(SCI_CANCEL);\r
+ SendEditor(SCI_SETUNDOCOLLECTION, 0);\r
+ ::ShowWindow(m_wEditor, SW_HIDE);\r
+ std::ifstream File;\r
+ File.open(fileName);\r
+ if (!File.good())\r
+ {\r
+ return FALSE;\r
+ }\r
+ char line[100*1024];\r
+ char * lineptr = NULL;\r
+ char * trimptr = NULL;\r
+ //ignore the first two lines, they're of no interest to us\r
+ File.getline(line, sizeof(line)/sizeof(char));\r
+ File.getline(line, sizeof(line)/sizeof(char));\r
+ m_lowestrev = LONG_MAX;\r
+ m_highestrev = 0;\r
+ bool bUTF8 = true;\r
+ do\r
+ {\r
+ File.getline(line, sizeof(line)/sizeof(TCHAR));\r
+ if (File.gcount()>139)\r
+ {\r
+ mergelines.push_back((line[0] != ' '));\r
+ lineptr = &line[9];\r
+ long rev = _ttol(lineptr);\r
+ revs.push_back(rev);\r
+ m_lowestrev = min(m_lowestrev, rev);\r
+ m_highestrev = max(m_highestrev, rev);\r
+ lineptr += 7;\r
+ rev = _ttol(lineptr);\r
+ origrevs.push_back(rev);\r
+ lineptr += 7;\r
+ dates.push_back(CString(lineptr, 30));\r
+ lineptr += 31;\r
+ // unfortunately, the 'path' entry can be longer than the 60 chars\r
+ // we made the column. We therefore have to step through the path\r
+ // string until we find a space\r
+ trimptr = lineptr;\r
+ do \r
+ {\r
+ // TODO: how can we deal with the situation where the path has\r
+ // a space in it, but the space is after the 60 chars reserved\r
+ // for it?\r
+ // The only way to deal with that would be to use a custom\r
+ // binary format for the blame file.\r
+ trimptr++;\r
+ trimptr = _tcschr(trimptr, ' ');\r
+ } while ((trimptr)&&(trimptr+1 < lineptr+61));\r
+ if (trimptr)\r
+ *trimptr = 0;\r
+ else\r
+ trimptr = lineptr;\r
+ paths.push_back(CString(lineptr));\r
+ if (trimptr+1 < lineptr+61)\r
+ lineptr +=61;\r
+ else\r
+ lineptr = (trimptr+1);\r
+ trimptr = lineptr+30;\r
+ while ((*trimptr == ' ')&&(trimptr > lineptr))\r
+ trimptr--;\r
+ *(trimptr+1) = 0;\r
+ authors.push_back(CString(lineptr));\r
+ lineptr += 31;\r
+ // in case we find an UTF8 BOM at the beginning of the line, we remove it\r
+ if (((unsigned char)lineptr[0] == 0xEF)&&((unsigned char)lineptr[1] == 0xBB)&&((unsigned char)lineptr[2] == 0xBF))\r
+ {\r
+ lineptr += 3;\r
+ }\r
+ if (((unsigned char)lineptr[0] == 0xBB)&&((unsigned char)lineptr[1] == 0xEF)&&((unsigned char)lineptr[2] == 0xBF))\r
+ {\r
+ lineptr += 3;\r
+ }\r
+ // check each line for illegal utf8 sequences. If one is found, we treat\r
+ // the file as ASCII, otherwise we assume an UTF8 file.\r
+ char * utf8CheckBuf = lineptr;\r
+ while ((bUTF8)&&(*utf8CheckBuf))\r
+ {\r
+ if ((*utf8CheckBuf == 0xC0)||(*utf8CheckBuf == 0xC1)||(*utf8CheckBuf >= 0xF5))\r
+ {\r
+ bUTF8 = false;\r
+ break;\r
+ }\r
+ if ((*utf8CheckBuf & 0xE0)==0xC0)\r
+ {\r
+ utf8CheckBuf++;\r
+ if (*utf8CheckBuf == 0)\r
+ break;\r
+ if ((*utf8CheckBuf & 0xC0)!=0x80)\r
+ {\r
+ bUTF8 = false;\r
+ break;\r
+ }\r
+ }\r
+ if ((*utf8CheckBuf & 0xF0)==0xE0)\r
+ {\r
+ utf8CheckBuf++;\r
+ if (*utf8CheckBuf == 0)\r
+ break;\r
+ if ((*utf8CheckBuf & 0xC0)!=0x80)\r
+ {\r
+ bUTF8 = false;\r
+ break;\r
+ }\r
+ utf8CheckBuf++;\r
+ if (*utf8CheckBuf == 0)\r
+ break;\r
+ if ((*utf8CheckBuf & 0xC0)!=0x80)\r
+ {\r
+ bUTF8 = false;\r
+ break;\r
+ }\r
+ }\r
+ if ((*utf8CheckBuf & 0xF8)==0xF0)\r
+ {\r
+ utf8CheckBuf++;\r
+ if (*utf8CheckBuf == 0)\r
+ break;\r
+ if ((*utf8CheckBuf & 0xC0)!=0x80)\r
+ {\r
+ bUTF8 = false;\r
+ break;\r
+ }\r
+ utf8CheckBuf++;\r
+ if (*utf8CheckBuf == 0)\r
+ break;\r
+ if ((*utf8CheckBuf & 0xC0)!=0x80)\r
+ {\r
+ bUTF8 = false;\r
+ break;\r
+ }\r
+ utf8CheckBuf++;\r
+ if (*utf8CheckBuf == 0)\r
+ break;\r
+ if ((*utf8CheckBuf & 0xC0)!=0x80)\r
+ {\r
+ bUTF8 = false;\r
+ break;\r
+ }\r
+ }\r
+\r
+ utf8CheckBuf++;\r
+ }\r
+ SendEditor(SCI_ADDTEXT, _tcslen(lineptr), reinterpret_cast<LPARAM>(static_cast<char *>(lineptr)));\r
+ SendEditor(SCI_ADDTEXT, 2, (LPARAM)_T("\r\n"));\r
+ }\r
+ } while (File.gcount() > 0);\r
+\r
+ if (bUTF8)\r
+ SendEditor(SCI_SETCODEPAGE, SC_CP_UTF8);\r
+\r
+ SendEditor(SCI_SETUNDOCOLLECTION, 1);\r
+ ::SetFocus(m_wEditor);\r
+ SendEditor(EM_EMPTYUNDOBUFFER);\r
+ SendEditor(SCI_SETSAVEPOINT);\r
+ SendEditor(SCI_GOTOPOS, 0);\r
+ SendEditor(SCI_SETSCROLLWIDTHTRACKING, TRUE);\r
+ SendEditor(SCI_SETREADONLY, TRUE);\r
+\r
+ //check which lexer to use, depending on the filetype\r
+ SetupLexer(fileName);\r
+ ::ShowWindow(m_wEditor, SW_SHOW);\r
+ m_blamewidth = 0;\r
+ ::InvalidateRect(wMain, NULL, TRUE);\r
+ RECT rc;\r
+ GetWindowRect(wMain, &rc);\r
+ SetWindowPos(wMain, 0, rc.left, rc.top, rc.right-rc.left-1, rc.bottom - rc.top, 0);\r
+#endif\r
+ return TRUE;\r
+}\r
+\r
+void CTortoiseGitBlameView::SetAStyle(int style, COLORREF fore, COLORREF back, int size, CString *face) \r
+{\r
+ SendEditor(SCI_STYLESETFORE, style, fore);\r
+ SendEditor(SCI_STYLESETBACK, style, back);\r
+ if (size >= 1)\r
+ SendEditor(SCI_STYLESETSIZE, style, size);\r
+ if (face) \r
+ SendEditor(SCI_STYLESETFONT, style, reinterpret_cast<LPARAM>(this->m_TextView.StringForControl(*face).GetBuffer()));\r
+}\r
+\r
+void CTortoiseGitBlameView::InitialiseEditor() \r
+{\r
+\r
+ m_directFunction = ::SendMessage(m_wEditor, SCI_GETDIRECTFUNCTION, 0, 0);\r
+ m_directPointer = ::SendMessage(m_wEditor, SCI_GETDIRECTPOINTER, 0, 0);\r
+ // Set up the global default style. These attributes are used wherever no explicit choices are made.\r
+ SetAStyle(STYLE_DEFAULT, \r
+ black, \r
+ white, \r
+ (DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\BlameFontSize"), 10), \r
+ &CString(((stdstring)CRegStdString(_T("Software\\TortoiseGit\\BlameFontName"), _T("Courier New"))).c_str())\r
+ );\r
+ SendEditor(SCI_SETTABWIDTH, (DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\BlameTabSize"), 4));\r
+ SendEditor(SCI_SETREADONLY, TRUE);\r
+ LRESULT pix = SendEditor(SCI_TEXTWIDTH, STYLE_LINENUMBER, (LPARAM)this->m_TextView.StringForControl(_T("_99999")).GetBuffer());\r
+ if (m_bShowLine)\r
+ SendEditor(SCI_SETMARGINWIDTHN, 0, pix);\r
+ else\r
+ SendEditor(SCI_SETMARGINWIDTHN, 0);\r
+ SendEditor(SCI_SETMARGINWIDTHN, 1);\r
+ SendEditor(SCI_SETMARGINWIDTHN, 2);\r
+ //Set the default windows colors for edit controls\r
+ SendEditor(SCI_STYLESETFORE, STYLE_DEFAULT, ::GetSysColor(COLOR_WINDOWTEXT));\r
+ SendEditor(SCI_STYLESETBACK, STYLE_DEFAULT, ::GetSysColor(COLOR_WINDOW));\r
+ SendEditor(SCI_SETSELFORE, TRUE, ::GetSysColor(COLOR_HIGHLIGHTTEXT));\r
+ SendEditor(SCI_SETSELBACK, TRUE, ::GetSysColor(COLOR_HIGHLIGHT));\r
+ SendEditor(SCI_SETCARETFORE, ::GetSysColor(COLOR_WINDOWTEXT));\r
+ m_regOldLinesColor = CRegStdWORD(_T("Software\\TortoiseGit\\BlameOldColor"), RGB(230, 230, 255));\r
+ m_regNewLinesColor = CRegStdWORD(_T("Software\\TortoiseGit\\BlameNewColor"), RGB(255, 230, 230));\r
+ \r
+ this->m_TextView.Call(SCI_SETWRAPMODE, SC_WRAP_NONE);\r
+\r
+}\r
+\r
+void CTortoiseGitBlameView::StartSearch()\r
+{\r
+ if (m_pFindDialog)\r
+ return;\r
+ bool bCase = false;\r
+ // Initialize FINDREPLACE\r
+ if (fr.Flags & FR_MATCHCASE)\r
+ bCase = true;\r
+ SecureZeroMemory(&fr, sizeof(fr));\r
+ fr.lStructSize = sizeof(fr);\r
+ fr.hwndOwner = wMain;\r
+ fr.lpstrFindWhat = szFindWhat;\r
+ fr.wFindWhatLen = 80;\r
+ fr.Flags = FR_HIDEUPDOWN | FR_HIDEWHOLEWORD;\r
+ fr.Flags |= bCase ? FR_MATCHCASE : 0;\r
+\r
+ currentDialog = FindText(&fr);\r
+}\r
+\r
+bool CTortoiseGitBlameView::DoSearch(CString what, DWORD flags)\r
+{\r
+\r
+ //char szWhat[80];\r
+ int pos = SendEditor(SCI_GETCURRENTPOS);\r
+ int line = SendEditor(SCI_LINEFROMPOSITION, pos);\r
+ bool bFound = false;\r
+ bool bCaseSensitive = !!(flags & FR_MATCHCASE);\r
+\r
+ //strcpy_s(szWhat, sizeof(szWhat), what);\r
+\r
+ if(!bCaseSensitive)\r
+ {\r
+ what=what.MakeLower();\r
+ }\r
+\r
+ //CString sWhat = CString(szWhat);\r
+ \r
+ //char buf[20];\r
+ //int i=0;\r
+ int i=line;\r
+ do\r
+ {\r
+ int bufsize = SendEditor(SCI_GETLINE, i);\r
+ char * linebuf = new char[bufsize+1];\r
+ SecureZeroMemory(linebuf, bufsize+1);\r
+ SendEditor(SCI_GETLINE, i, (LPARAM)linebuf);\r
+ CString oneline=this->m_TextView.StringFromControl(linebuf);\r
+ if (!bCaseSensitive)\r
+ {\r
+ oneline=oneline.MakeLower();\r
+ }\r
+ //_stprintf_s(buf, 20, _T("%ld"), revs[i]);\r
+ if (this->m_Authors[i].Find(what)>=0)\r
+ bFound = true;\r
+ else if ((!bCaseSensitive)&&(this->m_Authors[i].MakeLower().Find(what)>=0))\r
+ bFound = true;\r
+ else if (oneline.Find(what) >=0)\r
+ bFound = true;\r
+ \r
+ delete [] linebuf;\r
+\r
+ i++;\r
+ if(i>=m_CommitHash.size())\r
+ i=0;\r
+ }while(i!=line &&(!bFound));\r
+\r
+ if (bFound)\r
+ {\r
+ GotoLine(i);\r
+ int selstart = SendEditor(SCI_GETCURRENTPOS);\r
+ int selend = SendEditor(SCI_POSITIONFROMLINE, i);\r
+ SendEditor(SCI_SETSELECTIONSTART, selstart);\r
+ SendEditor(SCI_SETSELECTIONEND, selend);\r
+ m_SelectedLine = i-1;\r
+ }\r
+ else\r
+ {\r
+ ::MessageBox(wMain, what+_T(" not found"), _T("CTortoiseGitBlameView"), MB_ICONINFORMATION);\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+bool CTortoiseGitBlameView::GotoLine(long line)\r
+{\r
+ --line;\r
+ if (line < 0)\r
+ return false;\r
+ if ((unsigned long)line >= m_CommitHash.size())\r
+ {\r
+ line = m_CommitHash.size()-1;\r
+ }\r
+\r
+ int nCurrentPos = SendEditor(SCI_GETCURRENTPOS);\r
+ int nCurrentLine = SendEditor(SCI_LINEFROMPOSITION,nCurrentPos);\r
+ int nFirstVisibleLine = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
+ int nLinesOnScreen = SendEditor(SCI_LINESONSCREEN);\r
+\r
+ if ( line>=nFirstVisibleLine && line<=nFirstVisibleLine+nLinesOnScreen)\r
+ {\r
+ // no need to scroll\r
+ SendEditor(SCI_GOTOLINE, line);\r
+ }\r
+ else\r
+ {\r
+ // Place the requested line one third from the top\r
+ if ( line > nCurrentLine )\r
+ {\r
+ SendEditor(SCI_GOTOLINE, (WPARAM)(line+(int)nLinesOnScreen*(2/3.0)));\r
+ }\r
+ else\r
+ {\r
+ SendEditor(SCI_GOTOLINE, (WPARAM)(line-(int)nLinesOnScreen*(1/3.0)));\r
+ }\r
+ }\r
+\r
+ // Highlight the line\r
+ int nPosStart = SendEditor(SCI_POSITIONFROMLINE,line);\r
+ int nPosEnd = SendEditor(SCI_GETLINEENDPOSITION,line);\r
+ SendEditor(SCI_SETSEL,nPosEnd,nPosStart);\r
+\r
+ return true;\r
+}\r
+\r
+bool CTortoiseGitBlameView::ScrollToLine(long line)\r
+{\r
+ if (line < 0)\r
+ return false;\r
+\r
+ int nCurrentLine = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
+\r
+ int scrolldelta = line - nCurrentLine;\r
+ SendEditor(SCI_LINESCROLL, 0, scrolldelta);\r
+\r
+ return true;\r
+}\r
+\r
+void CTortoiseGitBlameView::CopySelectedLogToClipboard()\r
+{\r
+#if 0\r
+ if (m_selectedrev <= 0)\r
+ return;\r
+ std::map<LONG, CString>::iterator iter;\r
+ if ((iter = app.logmessages.find(m_selectedrev)) != app.logmessages.end())\r
+ {\r
+ CString msg;\r
+ msg += m_selectedauthor;\r
+ msg += " ";\r
+ msg += app.m_selecteddate;\r
+ msg += '\n';\r
+ msg += iter->second;\r
+ msg += _T("\n");\r
+ if (OpenClipboard(app.wBlame))\r
+ {\r
+ EmptyClipboard();\r
+ HGLOBAL hClipboardData;\r
+ hClipboardData = GlobalAlloc(GMEM_DDESHARE, msg.size()+1);\r
+ char * pchData;\r
+ pchData = (char*)GlobalLock(hClipboardData);\r
+ strcpy_s(pchData, msg.size()+1, msg.c_str());\r
+ GlobalUnlock(hClipboardData);\r
+ SetClipboardData(CF_TEXT,hClipboardData);\r
+ CloseClipboard();\r
+ }\r
+ }\r
+#endif\r
+}\r
+\r
+void CTortoiseGitBlameView::BlamePreviousRevision()\r
+{\r
+#if 0\r
+ LONG nRevisionTo = m_selectedorigrev - 1;\r
+ if ( nRevisionTo<1 )\r
+ {\r
+ return;\r
+ }\r
+\r
+ // We now determine the smallest revision number in the blame file (but ignore "-1")\r
+ // We do this for two reasons:\r
+ // 1. we respect the "From revision" which the user entered\r
+ // 2. we speed up the call of "svn blame" because previous smaller revision numbers don't have any effect on the result\r
+ LONG nSmallestRevision = -1;\r
+ for (LONG line=0;line<(LONG)app.revs.size();line++)\r
+ {\r
+ const LONG nRevision = app.revs[line];\r
+ if ( nRevision > 0 )\r
+ {\r
+ if ( nSmallestRevision < 1 )\r
+ {\r
+ nSmallestRevision = nRevision;\r
+ }\r
+ else\r
+ {\r
+ nSmallestRevision = min(nSmallestRevision,nRevision);\r
+ }\r
+ }\r
+ }\r
+\r
+ char bufStartRev[20];\r
+ _stprintf_s(bufStartRev, 20, _T("%d"), nSmallestRevision);\r
+\r
+ char bufEndRev[20];\r
+ _stprintf_s(bufEndRev, 20, _T("%d"), nRevisionTo);\r
+\r
+ char bufLine[20];\r
+ _stprintf_s(bufLine, 20, _T("%d"), m_SelectedLine+1); //using the current line is a good guess.\r
+\r
+ STARTUPINFO startup;\r
+ PROCESS_INFORMATION process;\r
+ memset(&startup, 0, sizeof(startup));\r
+ startup.cb = sizeof(startup);\r
+ memset(&process, 0, sizeof(process));\r
+ stdstring tortoiseProcPath = GetAppDirectory() + _T("TortoiseProc.exe");\r
+ stdstring svnCmd = _T(" /command:blame ");\r
+ svnCmd += _T(" /path:\"");\r
+ svnCmd += szOrigPath;\r
+ svnCmd += _T("\"");\r
+ svnCmd += _T(" /startrev:");\r
+ svnCmd += bufStartRev;\r
+ svnCmd += _T(" /endrev:");\r
+ svnCmd += bufEndRev;\r
+ svnCmd += _T(" /line:");\r
+ svnCmd += bufLine;\r
+ if (bIgnoreEOL)\r
+ svnCmd += _T(" /ignoreeol");\r
+ if (bIgnoreSpaces)\r
+ svnCmd += _T(" /ignorespaces");\r
+ if (bIgnoreAllSpaces)\r
+ svnCmd += _T(" /ignoreallspaces");\r
+ if (CreateProcess(tortoiseProcPath.c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))\r
+ {\r
+ CloseHandle(process.hThread);\r
+ CloseHandle(process.hProcess);\r
+ }\r
+#endif\r
+}\r
+\r
+void CTortoiseGitBlameView::DiffPreviousRevision()\r
+{\r
+#if 0\r
+ LONG nRevisionTo = m_selectedorigrev;\r
+ if ( nRevisionTo<1 )\r
+ {\r
+ return;\r
+ }\r
+\r
+ LONG nRevisionFrom = nRevisionTo-1;\r
+\r
+ char bufStartRev[20];\r
+ _stprintf_s(bufStartRev, 20, _T("%d"), nRevisionFrom);\r
+\r
+ char bufEndRev[20];\r
+ _stprintf_s(bufEndRev, 20, _T("%d"), nRevisionTo);\r
+\r
+ STARTUPINFO startup;\r
+ PROCESS_INFORMATION process;\r
+ memset(&startup, 0, sizeof(startup));\r
+ startup.cb = sizeof(startup);\r
+ memset(&process, 0, sizeof(process));\r
+ stdstring tortoiseProcPath = GetAppDirectory() + _T("TortoiseProc.exe");\r
+ stdstring svnCmd = _T(" /command:diff ");\r
+ svnCmd += _T(" /path:\"");\r
+ svnCmd += szOrigPath;\r
+ svnCmd += _T("\"");\r
+ svnCmd += _T(" /startrev:");\r
+ svnCmd += bufStartRev;\r
+ svnCmd += _T(" /endrev:");\r
+ svnCmd += bufEndRev;\r
+ if (CreateProcess(tortoiseProcPath.c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))\r
+ {\r
+ CloseHandle(process.hThread);\r
+ CloseHandle(process.hProcess);\r
+ }\r
+#endif\r
+}\r
+\r
+void CTortoiseGitBlameView::ShowLog()\r
+{\r
+#if 0\r
+ char bufRev[20];\r
+ _stprintf_s(bufRev, 20, _T("%d"), m_selectedorigrev);\r
+\r
+ STARTUPINFO startup;\r
+ PROCESS_INFORMATION process;\r
+ memset(&startup, 0, sizeof(startup));\r
+ startup.cb = sizeof(startup);\r
+ memset(&process, 0, sizeof(process));\r
+ stdstring tortoiseProcPath = GetAppDirectory() + _T("TortoiseProc.exe");\r
+ stdstring svnCmd = _T(" /command:log ");\r
+ svnCmd += _T(" /path:\"");\r
+ svnCmd += szOrigPath;\r
+ svnCmd += _T("\"");\r
+ svnCmd += _T(" /startrev:");\r
+ svnCmd += bufRev;\r
+ svnCmd += _T(" /pegrev:");\r
+ svnCmd += bufRev;\r
+ if (CreateProcess(tortoiseProcPath.c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))\r
+ {\r
+ CloseHandle(process.hThread);\r
+ CloseHandle(process.hProcess);\r
+ }\r
+#endif\r
+}\r
+\r
+void CTortoiseGitBlameView::Notify(SCNotification *notification) \r
+{\r
+ switch (notification->nmhdr.code) \r
+ {\r
+ case SCN_SAVEPOINTREACHED:\r
+ break;\r
+\r
+ case SCN_SAVEPOINTLEFT:\r
+ break;\r
+ case SCN_PAINTED:\r
+// InvalidateRect(wBlame, NULL, FALSE);\r
+// InvalidateRect(wLocator, NULL, FALSE);\r
+ break;\r
+ case SCN_GETBKCOLOR:\r
+// if ((m_colorage)&&(notification->line < (int)revs.size()))\r
+// {\r
+// notification->lParam = InterColor(DWORD(m_regOldLinesColor), DWORD(m_regNewLinesColor), (revs[notification->line]-m_lowestrev)*100/((m_highestrev-m_lowestrev)+1));\r
+// }\r
+ break;\r
+ }\r
+}\r
+\r
+void CTortoiseGitBlameView::Command(int id)\r
+{\r
+#if 0\r
+ switch (id) \r
+ {\r
+// case IDM_EXIT:\r
+// ::PostQuitMessage(0);\r
+// break;\r
+ case ID_EDIT_FIND:\r
+ StartSearch();\r
+ break;\r
+ case ID_COPYTOCLIPBOARD:\r
+ CopySelectedLogToClipboard();\r
+ break;\r
+ case ID_BLAME_PREVIOUS_REVISION:\r
+ BlamePreviousRevision();\r
+ break;\r
+ case ID_DIFF_PREVIOUS_REVISION:\r
+ DiffPreviousRevision();\r
+ break;\r
+ case ID_SHOWLOG:\r
+ ShowLog();\r
+ break;\r
+ case ID_EDIT_GOTOLINE:\r
+ GotoLineDlg();\r
+ break;\r
+ case ID_VIEW_COLORAGEOFLINES:\r
+ {\r
+ m_colorage = !m_colorage;\r
+ HMENU hMenu = GetMenu(wMain);\r
+ UINT uCheck = MF_BYCOMMAND;\r
+ uCheck |= m_colorage ? MF_CHECKED : MF_UNCHECKED;\r
+ CheckMenuItem(hMenu, ID_VIEW_COLORAGEOFLINES, uCheck);\r
+ m_blamewidth = 0;\r
+ InitSize();\r
+ }\r
+ break;\r
+ case ID_VIEW_MERGEPATH:\r
+ {\r
+ ShowPath = !ShowPath;\r
+ HMENU hMenu = GetMenu(wMain);\r
+ UINT uCheck = MF_BYCOMMAND;\r
+ uCheck |= ShowPath ? MF_CHECKED : MF_UNCHECKED;\r
+ CheckMenuItem(hMenu, ID_VIEW_MERGEPATH, uCheck);\r
+ m_blamewidth = 0;\r
+ InitSize();\r
+ }\r
+ default:\r
+ break;\r
+ };\r
+#endif\r
+}\r
+\r
+void CTortoiseGitBlameView::GotoLineDlg()\r
+{\r
+#if 0\r
+ if (DialogBox(hResource, MAKEINTRESOURCE(IDD_GOTODLG), wMain, GotoDlgProc)==IDOK)\r
+ {\r
+ GotoLine(m_gotoline);\r
+ }\r
+#endif\r
+}\r
+\r
+LONG CTortoiseGitBlameView::GetBlameWidth()\r
+{\r
+ LONG blamewidth = 0;\r
+ SIZE width;\r
+ CreateFont();\r
+ HDC hDC = this->GetDC()->m_hDC;\r
+ HFONT oldfont = (HFONT)::SelectObject(hDC, m_font);\r
+ \r
+ TCHAR buf[MAX_PATH];\r
+ //_stprintf_s(buf, MAX_PATH, _T("%8ld "), 88888888);\r
+ //::GetTextExtentPoint(hDC, buf, _tcslen(buf), &width);\r
+ //m_revwidth = width.cx + BLAMESPACE;\r
+ //blamewidth += m_revwidth;\r
+\r
+ int maxnum=0;\r
+ for (int i=0;i<this->m_Authors.size();i++)\r
+ {\r
+ if(m_ID[i]>maxnum)\r
+ maxnum=m_ID[i];\r
+ }\r
+ _stprintf_s(buf, MAX_PATH, _T("%d."), maxnum);\r
+ ::GetTextExtentPoint(hDC, buf, _tcslen(buf), &width);\r
+ m_revwidth = width.cx + BLAMESPACE;\r
+ blamewidth += m_revwidth;\r
+\r
+#if 0\r
+ _stprintf_s(buf, MAX_PATH, _T("%d"), m_CommitHash.size());\r
+ ::GetTextExtentPoint(hDC, buf, _tcslen(buf), &width);\r
+ m_linewidth = width.cx + BLAMESPACE;\r
+ blamewidth += m_revwidth;\r
+#endif \r
+\r
+ if (m_bShowDate)\r
+ {\r
+ _stprintf_s(buf, MAX_PATH, _T("%30s"), _T("31.08.2001 06:24:14"));\r
+ ::GetTextExtentPoint32(hDC, buf, _tcslen(buf), &width);\r
+ m_datewidth = width.cx + BLAMESPACE;\r
+ blamewidth += m_datewidth;\r
+ }\r
+ if ( m_bShowAuthor)\r
+ {\r
+ SIZE maxwidth = {0};\r
+\r
+ for (int i=0;i<this->m_Authors.size();i++)\r
+ //for (std::vector<CString>::iterator I = authors.begin(); I != authors.end(); ++I)\r
+ {\r
+ ::GetTextExtentPoint32(hDC,m_Authors[i] , m_Authors[i].GetLength(), &width);\r
+ if (width.cx > maxwidth.cx)\r
+ maxwidth = width;\r
+ }\r
+ m_authorwidth = maxwidth.cx + BLAMESPACE;\r
+ blamewidth += m_authorwidth;\r
+ }\r
+#if 0\r
+ if (ShowPath)\r
+ {\r
+ SIZE maxwidth = {0};\r
+ for (std::vector<CString>::iterator I = paths.begin(); I != paths.end(); ++I)\r
+ {\r
+ ::GetTextExtentPoint32(hDC, I->c_str(), I->size(), &width);\r
+ if (width.cx > maxwidth.cx)\r
+ maxwidth = width;\r
+ }\r
+ m_pathwidth = maxwidth.cx + BLAMESPACE;\r
+ blamewidth += m_pathwidth;\r
+ }\r
+#endif\r
+ ::SelectObject(hDC, oldfont);\r
+ POINT pt = {blamewidth, 0};\r
+ LPtoDP(hDC, &pt, 1);\r
+ m_blamewidth = pt.x;\r
+ //::ReleaseDC(wBlame, hDC);\r
+\r
+ //return m_blamewidth;\r
+ return blamewidth;\r
+\r
+}\r
+\r
+void CTortoiseGitBlameView::CreateFont()\r
+{\r
+ if (m_font)\r
+ return;\r
+ LOGFONT lf = {0};\r
+ lf.lfWeight = 400;\r
+ HDC hDC = ::GetDC(wBlame);\r
+ lf.lfHeight = -MulDiv((DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\BlameFontSize"), 10), GetDeviceCaps(hDC, LOGPIXELSY), 72);\r
+ lf.lfCharSet = DEFAULT_CHARSET;\r
+ CRegStdString fontname = CRegStdString(_T("Software\\TortoiseGit\\BlameFontName"), _T("Courier New"));\r
+ _tcscpy_s(lf.lfFaceName, 32, ((stdstring)fontname).c_str());\r
+ m_font = ::CreateFontIndirect(&lf);\r
+\r
+ lf.lfItalic = TRUE;\r
+ m_italicfont = ::CreateFontIndirect(&lf);\r
+\r
+ ::ReleaseDC(wBlame, hDC);\r
+\r
+ //m_TextView.SetFont(lf.lfFaceName,((DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\BlameFontSize"), 10)));\r
+}\r
+\r
+void CTortoiseGitBlameView::DrawBlame(HDC hDC)\r
+{\r
+\r
+ if (hDC == NULL)\r
+ return;\r
+ if (m_font == NULL)\r
+ return;\r
+\r
+ HFONT oldfont = NULL;\r
+ LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
+ LONG_PTR linesonscreen = SendEditor(SCI_LINESONSCREEN);\r
+ LONG_PTR height = SendEditor(SCI_TEXTHEIGHT);\r
+ LONG_PTR Y = 0;\r
+ TCHAR buf[MAX_PATH];\r
+ RECT rc;\r
+ BOOL sel = FALSE;\r
+ //::GetClientRect(this->m_hWnd, &rc);\r
+ for (LRESULT i=line; i<(line+linesonscreen); ++i)\r
+ {\r
+ sel = FALSE;\r
+ if (i < (int)m_CommitHash.size())\r
+ {\r
+ // if (mergelines[i])\r
+ // oldfont = (HFONT)::SelectObject(hDC, m_italicfont);\r
+ // else\r
+ oldfont = (HFONT)::SelectObject(hDC, m_font);\r
+ ::SetBkColor(hDC, m_windowcolor);\r
+ ::SetTextColor(hDC, m_textcolor);\r
+ if (m_CommitHash[i].GetLength()>0)\r
+ {\r
+ //if (m_CommitHash[i].Compare(m_MouseHash)==0)\r
+ // ::SetBkColor(hDC, m_mouseauthorcolor);\r
+ if (m_CommitHash[i].Compare(m_SelectedHash)==0)\r
+ {\r
+ ::SetBkColor(hDC, m_selectedauthorcolor);\r
+ ::SetTextColor(hDC, m_texthighlightcolor);\r
+ sel = TRUE;\r
+ }\r
+ }\r
+\r
+ if(m_MouseLine == i)\r
+ ::SetBkColor(hDC, m_mouserevcolor);\r
+\r
+ //if ((revs[i] == m_mouserev)&&(!sel))\r
+ // ::SetBkColor(hDC, m_mouserevcolor);\r
+ //if (revs[i] == m_selectedrev)\r
+ //{\r
+ // ::SetBkColor(hDC, m_selectedrevcolor);\r
+ // ::SetTextColor(hDC, m_texthighlightcolor);\r
+ //}\r
+\r
+ CString str;\r
+ str.Format(_T("%d"),m_ID[i]);\r
+\r
+ //_stprintf_s(buf, MAX_PATH, _T("%8ld "), revs[i]);\r
+ rc.top=Y;\r
+ rc.left=LOCATOR_WIDTH; \r
+ rc.bottom=Y+height;\r
+ rc.right = rc.left + m_blamewidth;\r
+ ::ExtTextOut(hDC, LOCATOR_WIDTH, Y, ETO_CLIPPED, &rc, str, str.GetLength(), 0);\r
+ int Left = m_revwidth;\r
+ \r
+ if (m_bShowAuthor)\r
+ {\r
+ rc.right = rc.left + Left + m_authorwidth;\r
+ //_stprintf_s(buf, MAX_PATH, _T("%-30s "), authors[i].c_str());\r
+ ::ExtTextOut(hDC, Left, Y, ETO_CLIPPED, &rc, m_Authors[i], m_Authors[i].GetLength(), 0);\r
+ Left += m_authorwidth;\r
+ }\r
+#if 0\r
+ if (ShowDate)\r
+ {\r
+ rc.right = rc.left + Left + m_datewidth;\r
+ _stprintf_s(buf, MAX_PATH, _T("%30s "), dates[i].c_str());\r
+ ::ExtTextOut(hDC, Left, Y, ETO_CLIPPED, &rc, buf, _tcslen(buf), 0);\r
+ Left += m_datewidth;\r
+ }\r
+ \r
+#endif\r
+#if 0\r
+ if (ShowPath)\r
+ {\r
+ rc.right = rc.left + Left + m_pathwidth;\r
+ _stprintf_s(buf, MAX_PATH, _T("%-60s "), paths[i].c_str());\r
+ ::ExtTextOut(hDC, Left, Y, ETO_CLIPPED, &rc, buf, _tcslen(buf), 0);\r
+ Left += m_authorwidth;\r
+ }\r
+#endif\r
+ if ((i==m_SelectedLine)&&(m_pFindDialog))\r
+ {\r
+ LOGBRUSH brush;\r
+ brush.lbColor = m_textcolor;\r
+ brush.lbHatch = 0;\r
+ brush.lbStyle = BS_SOLID;\r
+ HPEN pen = ExtCreatePen(PS_SOLID | PS_GEOMETRIC, 2, &brush, 0, NULL);\r
+ HGDIOBJ hPenOld = SelectObject(hDC, pen);\r
+ RECT rc2 = rc;\r
+ rc2.top = Y;\r
+ rc2.bottom = Y + height;\r
+ ::MoveToEx(hDC, rc2.left, rc2.top, NULL);\r
+ ::LineTo(hDC, rc2.right, rc2.top);\r
+ ::LineTo(hDC, rc2.right, rc2.bottom);\r
+ ::LineTo(hDC, rc2.left, rc2.bottom);\r
+ ::LineTo(hDC, rc2.left, rc2.top);\r
+ SelectObject(hDC, hPenOld); \r
+ DeleteObject(pen); \r
+ }\r
+ Y += height;\r
+ ::SelectObject(hDC, oldfont);\r
+ }\r
+ else\r
+ {\r
+ ::SetBkColor(hDC, m_windowcolor);\r
+ for (int j=0; j< MAX_PATH; ++j)\r
+ buf[j]=' ';\r
+ ::ExtTextOut(hDC, 0, Y, ETO_CLIPPED, &rc, buf, MAX_PATH-1, 0);\r
+ Y += height;\r
+ }\r
+ }\r
+}\r
+\r
+void CTortoiseGitBlameView::DrawHeader(HDC hDC)\r
+{\r
+#if 0\r
+ if (hDC == NULL)\r
+ return;\r
+\r
+ RECT rc;\r
+ HFONT oldfont = (HFONT)::SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));\r
+ ::GetClientRect(wHeader, &rc);\r
+\r
+ ::SetBkColor(hDC, ::GetSysColor(COLOR_BTNFACE));\r
+\r
+ TCHAR szText[MAX_LOADSTRING];\r
+ LoadString(app.hResource, IDS_HEADER_REVISION, szText, MAX_LOADSTRING);\r
+ ::ExtTextOut(hDC, LOCATOR_WIDTH, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
+ int Left = m_revwidth+LOCATOR_WIDTH;\r
+ if (ShowDate)\r
+ {\r
+ LoadString(app.hResource, IDS_HEADER_DATE, szText, MAX_LOADSTRING);\r
+ ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
+ Left += m_datewidth;\r
+ }\r
+ if (ShowAuthor)\r
+ {\r
+ LoadString(app.hResource, IDS_HEADER_AUTHOR, szText, MAX_LOADSTRING);\r
+ ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
+ Left += m_authorwidth;\r
+ }\r
+ if (ShowPath)\r
+ {\r
+ LoadString(app.hResource, IDS_HEADER_PATH, szText, MAX_LOADSTRING);\r
+ ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
+ Left += m_pathwidth;\r
+ }\r
+ LoadString(app.hResource, IDS_HEADER_LINE, szText, MAX_LOADSTRING);\r
+ ::ExtTextOut(hDC, Left, 0, ETO_CLIPPED, &rc, szText, _tcslen(szText), 0);\r
+\r
+ ::SelectObject(hDC, oldfont);\r
+#endif\r
+}\r
+\r
+void CTortoiseGitBlameView::DrawLocatorBar(HDC hDC)\r
+{\r
+ if (hDC == NULL)\r
+ return;\r
+\r
+ LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
+ LONG_PTR linesonscreen = SendEditor(SCI_LINESONSCREEN);\r
+ LONG_PTR Y = 0;\r
+ COLORREF blackColor = GetSysColor(COLOR_WINDOWTEXT);\r
+\r
+ RECT rc;\r
+ //::GetClientRect(wLocator, &rc);\r
+ this->GetClientRect(&rc);\r
+\r
+ rc.right=LOCATOR_WIDTH;\r
+\r
+ RECT lineRect = rc;\r
+ LONG height = rc.bottom-rc.top;\r
+ LONG currentLine = 0;\r
+\r
+ // draw the colored bar\r
+ for (std::vector<LONG>::const_iterator it = m_ID.begin(); it != m_ID.end(); ++it)\r
+ {\r
+ currentLine++;\r
+ // get the line color\r
+ COLORREF cr = InterColor(DWORD(m_regOldLinesColor), DWORD(m_regNewLinesColor), (*it - m_lowestrev)*100/((m_highestrev-m_lowestrev)+1));\r
+ if ((currentLine > line)&&(currentLine <= (line + linesonscreen)))\r
+ {\r
+ cr = InterColor(cr, blackColor, 10);\r
+ }\r
+ SetBkColor(hDC, cr);\r
+ lineRect.top = Y;\r
+ lineRect.bottom = (currentLine * height / m_ID.size());\r
+ ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lineRect, NULL, 0, NULL);\r
+ Y = lineRect.bottom;\r
+ }\r
+\r
+ if (m_ID.size())\r
+ {\r
+ // now draw two lines indicating the scroll position of the source view\r
+ SetBkColor(hDC, blackColor);\r
+ lineRect.top = line * height / m_ID.size();\r
+ lineRect.bottom = lineRect.top+1;\r
+ ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lineRect, NULL, 0, NULL);\r
+ lineRect.top = (line + linesonscreen) * height / m_ID.size();\r
+ lineRect.bottom = lineRect.top+1;\r
+ ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lineRect, NULL, 0, NULL);\r
+ }\r
+\r
+}\r
+\r
+void CTortoiseGitBlameView::StringExpand(LPSTR str)\r
+{\r
+ char * cPos = str;\r
+ do\r
+ {\r
+ cPos = strchr(cPos, '\n');\r
+ if (cPos)\r
+ {\r
+ memmove(cPos+1, cPos, strlen(cPos)*sizeof(char));\r
+ *cPos = '\r';\r
+ cPos++;\r
+ cPos++;\r
+ }\r
+ } while (cPos != NULL);\r
+}\r
+void CTortoiseGitBlameView::StringExpand(LPWSTR str)\r
+{\r
+ wchar_t * cPos = str;\r
+ do\r
+ {\r
+ cPos = wcschr(cPos, '\n');\r
+ if (cPos)\r
+ {\r
+ memmove(cPos+1, cPos, wcslen(cPos)*sizeof(wchar_t));\r
+ *cPos = '\r';\r
+ cPos++;\r
+ cPos++;\r
+ }\r
+ } while (cPos != NULL);\r
+}\r
+\r
+// Forward declarations of functions included in this code module:\r
+ATOM MyRegisterClass(HINSTANCE hResource);\r
+ATOM MyRegisterBlameClass(HINSTANCE hResource);\r
+ATOM MyRegisterHeaderClass(HINSTANCE hResource);\r
+ATOM MyRegisterLocatorClass(HINSTANCE hResource);\r
+BOOL InitInstance(HINSTANCE, int);\r
+LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);\r
+LRESULT CALLBACK WndBlameProc(HWND, UINT, WPARAM, LPARAM);\r
+LRESULT CALLBACK WndHeaderProc(HWND, UINT, WPARAM, LPARAM);\r
+LRESULT CALLBACK WndLocatorProc(HWND, UINT, WPARAM, LPARAM);\r
+UINT uFindReplaceMsg;\r
+\r
+#if 0\r
+int APIENTRY _tWinMain(HINSTANCE hInstance,\r
+ HINSTANCE /*hPrevInstance*/,\r
+ LPTSTR lpCmdLine,\r
+ int nCmdShow)\r
+{\r
+ app.hInstance = hInstance;\r
+ MSG msg;\r
+ HACCEL hAccelTable;\r
+\r
+ if (::LoadLibrary("SciLexer.DLL") == NULL)\r
+ return FALSE;\r
+\r
+ CRegStdWORD loc = CRegStdWORD(_T("Software\\TortoiseGit\\LanguageID"), 1033);\r
+ long langId = loc;\r
+\r
+ CLangDll langDLL;\r
+ app.hResource = langDLL.Init(_T("CTortoiseGitBlameView"), langId);\r
+ if (app.hResource == NULL)\r
+ app.hResource = app.hInstance;\r
+\r
+ // Initialize global strings\r
+ LoadString(app.hResource, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);\r
+ LoadString(app.hResource, IDC_TortoiseGitBlameView, szWindowClass, MAX_LOADSTRING);\r
+ LoadString(app.hResource, IDS_SEARCHNOTFOUND, searchstringnotfound, MAX_LOADSTRING);\r
+ MyRegisterClass(app.hResource);\r
+ MyRegisterBlameClass(app.hResource);\r
+ MyRegisterHeaderClass(app.hResource);\r
+ MyRegisterLocatorClass(app.hResource);\r
+\r
+ // Perform application initialization:\r
+ if (!InitInstance (app.hResource, nCmdShow)) \r
+ {\r
+ langDLL.Close();\r
+ return FALSE;\r
+ }\r
+\r
+ SecureZeroMemory(szViewtitle, MAX_PATH);\r
+ SecureZeroMemory(szOrigPath, MAX_PATH);\r
+ char blamefile[MAX_PATH] = {0};\r
+ char logfile[MAX_PATH] = {0};\r
+\r
+ CCmdLineParser parser(lpCmdLine);\r
+\r
+\r
+ if (__argc > 1)\r
+ {\r
+ _tcscpy_s(blamefile, MAX_PATH, __argv[1]);\r
+ }\r
+ if (__argc > 2)\r
+ {\r
+ _tcscpy_s(logfile, MAX_PATH, __argv[2]);\r
+ }\r
+ if (__argc > 3)\r
+ {\r
+ _tcscpy_s(szViewtitle, MAX_PATH, __argv[3]);\r
+ if (parser.HasVal(_T("revrange")))\r
+ {\r
+ _tcscat_s(szViewtitle, MAX_PATH, _T(" : "));\r
+ _tcscat_s(szViewtitle, MAX_PATH, parser.GetVal(_T("revrange")));\r
+ }\r
+ }\r
+ if ((_tcslen(blamefile)==0) || parser.HasKey(_T("?")) || parser.HasKey(_T("help")))\r
+ {\r
+ TCHAR szInfo[MAX_LOADSTRING];\r
+ LoadString(app.hResource, IDS_COMMANDLINE_INFO, szInfo, MAX_LOADSTRING);\r
+ MessageBox(NULL, szInfo, _T("CTortoiseGitBlameView"), MB_ICONERROR);\r
+ langDLL.Close();\r
+ return 0;\r
+ }\r
+\r
+ if ( parser.HasKey(_T("path")) )\r
+ {\r
+ _tcscpy_s(szOrigPath, MAX_PATH, parser.GetVal(_T("path")));\r
+ }\r
+ app.bIgnoreEOL = parser.HasKey(_T("ignoreeol"));\r
+ app.bIgnoreSpaces = parser.HasKey(_T("ignorespaces"));\r
+ app.bIgnoreAllSpaces = parser.HasKey(_T("ignoreallspaces"));\r
+\r
+ app.SendEditor(SCI_SETCODEPAGE, GetACP());\r
+ app.OpenFile(blamefile);\r
+ if (_tcslen(logfile)>0)\r
+ app.OpenLogFile(logfile);\r
+\r
+ if (parser.HasKey(_T("line")))\r
+ {\r
+ app.GotoLine(parser.GetLongVal(_T("line")));\r
+ }\r
+\r
+ CheckMenuItem(GetMenu(app.wMain), ID_VIEW_COLORAGEOFLINES, MF_CHECKED|MF_BYCOMMAND);\r
+\r
+\r
+ hAccelTable = LoadAccelerators(app.hResource, (LPCTSTR)IDC_TortoiseGitBlameView);\r
+\r
+ BOOL going = TRUE;\r
+ msg.wParam = 0;\r
+ while (going) \r
+ {\r
+ going = GetMessage(&msg, NULL, 0, 0);\r
+ if (app.currentDialog && going) \r
+ {\r
+ if (!IsDialogMessage(app.currentDialog, &msg)) \r
+ {\r
+ if (TranslateAccelerator(msg.hwnd, hAccelTable, &msg) == 0) \r
+ {\r
+ TranslateMessage(&msg);\r
+ DispatchMessage(&msg);\r
+ }\r
+ }\r
+ } \r
+ else if (going) \r
+ {\r
+ if (TranslateAccelerator(app.wMain, hAccelTable, &msg) == 0) \r
+ {\r
+ TranslateMessage(&msg);\r
+ DispatchMessage(&msg);\r
+ }\r
+ }\r
+ }\r
+ langDLL.Close();\r
+ return msg.wParam;\r
+}\r
+\r
+ATOM MyRegisterClass(HINSTANCE hResource)\r
+{\r
+ WNDCLASSEX wcex;\r
+\r
+ wcex.cbSize = sizeof(WNDCLASSEX); \r
+\r
+ wcex.style = CS_HREDRAW | CS_VREDRAW;\r
+ wcex.lpfnWndProc = (WNDPROC)WndProc;\r
+ wcex.cbClsExtra = 0;\r
+ wcex.cbWndExtra = 0;\r
+ wcex.hInstance = hResource;\r
+ wcex.hIcon = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);\r
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);\r
+ wcex.lpszMenuName = (LPCTSTR)IDC_TortoiseGitBlameView;\r
+ wcex.lpszClassName = szWindowClass;\r
+ wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
+\r
+ return RegisterClassEx(&wcex);\r
+}\r
+\r
+ATOM MyRegisterBlameClass(HINSTANCE hResource)\r
+{\r
+ WNDCLASSEX wcex;\r
+\r
+ wcex.cbSize = sizeof(WNDCLASSEX); \r
+\r
+ wcex.style = CS_HREDRAW | CS_VREDRAW;\r
+ wcex.lpfnWndProc = (WNDPROC)WndBlameProc;\r
+ wcex.cbClsExtra = 0;\r
+ wcex.cbWndExtra = 0;\r
+ wcex.hInstance = hResource;\r
+ wcex.hIcon = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);\r
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);\r
+ wcex.lpszMenuName = 0;\r
+ wcex.lpszClassName = _T("TortoiseGitBlameViewBlame");\r
+ wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
+\r
+ return RegisterClassEx(&wcex);\r
+}\r
+\r
+ATOM MyRegisterHeaderClass(HINSTANCE hResource)\r
+{\r
+ WNDCLASSEX wcex;\r
+\r
+ wcex.cbSize = sizeof(WNDCLASSEX); \r
+\r
+ wcex.style = CS_HREDRAW | CS_VREDRAW;\r
+ wcex.lpfnWndProc = (WNDPROC)WndHeaderProc;\r
+ wcex.cbClsExtra = 0;\r
+ wcex.cbWndExtra = 0;\r
+ wcex.hInstance = hResource;\r
+ wcex.hIcon = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);\r
+ wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);\r
+ wcex.lpszMenuName = 0;\r
+ wcex.lpszClassName = _T("TortoiseGitBlameViewHeader");\r
+ wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
+\r
+ return RegisterClassEx(&wcex);\r
+}\r
+\r
+ATOM MyRegisterLocatorClass(HINSTANCE hResource)\r
+{\r
+ WNDCLASSEX wcex;\r
+\r
+ wcex.cbSize = sizeof(WNDCLASSEX); \r
+\r
+ wcex.style = CS_HREDRAW | CS_VREDRAW;\r
+ wcex.lpfnWndProc = (WNDPROC)WndLocatorProc;\r
+ wcex.cbClsExtra = 0;\r
+ wcex.cbWndExtra = 0;\r
+ wcex.hInstance = hResource;\r
+ wcex.hIcon = LoadIcon(hResource, (LPCTSTR)IDI_TortoiseGitBlameView);\r
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);\r
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);\r
+ wcex.lpszMenuName = 0;\r
+ wcex.lpszClassName = _T("TortoiseGitBlameViewLocator");\r
+ wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);\r
+\r
+ return RegisterClassEx(&wcex);\r
+}\r
+\r
+BOOL InitInstance(HINSTANCE hResource, int nCmdShow)\r
+{\r
+ app.wMain = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,\r
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hResource, NULL); \r
+\r
+ if (!app.wMain)\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ CRegStdWORD pos(_T("Software\\TortoiseGit\\TBlamePos"), 0);\r
+ CRegStdWORD width(_T("Software\\TortoiseGit\\TBlameSize"), 0);\r
+ CRegStdWORD state(_T("Software\\TortoiseGit\\TBlameState"), 0);\r
+ if (DWORD(pos) && DWORD(width))\r
+ {\r
+ RECT rc;\r
+ rc.left = LOWORD(DWORD(pos));\r
+ rc.top = HIWORD(DWORD(pos));\r
+ rc.right = rc.left + LOWORD(DWORD(width));\r
+ rc.bottom = rc.top + HIWORD(DWORD(width));\r
+ HMONITOR hMon = MonitorFromRect(&rc, MONITOR_DEFAULTTONULL);\r
+ if (hMon)\r
+ {\r
+ // only restore the window position if the monitor is valid\r
+ MoveWindow(app.wMain, LOWORD(DWORD(pos)), HIWORD(DWORD(pos)),\r
+ LOWORD(DWORD(width)), HIWORD(DWORD(width)), FALSE);\r
+ }\r
+ }\r
+ if (DWORD(state) == SW_MAXIMIZE)\r
+ ShowWindow(app.wMain, SW_MAXIMIZE);\r
+ else\r
+ ShowWindow(app.wMain, nCmdShow);\r
+ UpdateWindow(app.wMain);\r
+\r
+ //Create the tooltips\r
+\r
+ INITCOMMONCONTROLSEX iccex; \r
+ app.hwndTT; // handle to the ToolTip control\r
+ TOOLINFO ti;\r
+ RECT rect; // for client area coordinates\r
+ iccex.dwICC = ICC_WIN95_CLASSES;\r
+ iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);\r
+ InitCommonControlsEx(&iccex);\r
+\r
+ /* CREATE A TOOLTIP WINDOW */\r
+ app.hwndTT = CreateWindowEx(WS_EX_TOPMOST,\r
+ TOOLTIPS_CLASS,\r
+ NULL,\r
+ WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, \r
+ CW_USEDEFAULT,\r
+ CW_USEDEFAULT,\r
+ CW_USEDEFAULT,\r
+ CW_USEDEFAULT,\r
+ app.wBlame,\r
+ NULL,\r
+ app.hResource,\r
+ NULL\r
+ );\r
+\r
+ SetWindowPos(app.hwndTT,\r
+ HWND_TOPMOST,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);\r
+\r
+ /* GET COORDINATES OF THE MAIN CLIENT AREA */\r
+ GetClientRect (app.wBlame, &rect);\r
+\r
+ /* INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE */\r
+ ti.cbSize = sizeof(TOOLINFO);\r
+ ti.uFlags = TTF_TRACK | TTF_ABSOLUTE;//TTF_SUBCLASS | TTF_PARSELINKS;\r
+ ti.hwnd = app.wBlame;\r
+ ti.hinst = app.hResource;\r
+ ti.uId = 0;\r
+ ti.lpszText = LPSTR_TEXTCALLBACK;\r
+ // ToolTip control will cover the whole window\r
+ ti.rect.left = rect.left; \r
+ ti.rect.top = rect.top;\r
+ ti.rect.right = rect.right;\r
+ ti.rect.bottom = rect.bottom;\r
+\r
+ /* SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW */\r
+ SendMessage(app.hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti); \r
+ SendMessage(app.hwndTT, TTM_SETMAXTIPWIDTH, 0, 600);\r
+ //SendMessage(app.hwndTT, TTM_SETDELAYTIME, TTDT_AUTOPOP, MAKELONG(50000, 0));\r
+ //SendMessage(app.hwndTT, TTM_SETDELAYTIME, TTDT_RESHOW, MAKELONG(1000, 0));\r
+ \r
+ uFindReplaceMsg = RegisterWindowMessage(FINDMSGSTRING);\r
+ \r
+ return TRUE;\r
+}\r
+#endif\r
+void CTortoiseGitBlameView::InitSize()\r
+{\r
+ RECT rc;\r
+ RECT blamerc;\r
+ RECT sourcerc;\r
+ ::GetClientRect(wMain, &rc);\r
+ ::SetWindowPos(wHeader, 0, rc.left, rc.top, rc.right-rc.left, HEADER_HEIGHT, 0);\r
+ rc.top += HEADER_HEIGHT;\r
+ blamerc.left = rc.left;\r
+ blamerc.top = rc.top;\r
+ LONG w = GetBlameWidth();\r
+ blamerc.right = w > abs(rc.right - rc.left) ? rc.right : w + rc.left;\r
+ blamerc.bottom = rc.bottom;\r
+ sourcerc.left = blamerc.right;\r
+ sourcerc.top = rc.top;\r
+ sourcerc.bottom = rc.bottom;\r
+ sourcerc.right = rc.right;\r
+ if (m_colorage)\r
+ {\r
+ ::OffsetRect(&blamerc, LOCATOR_WIDTH, 0);\r
+ ::OffsetRect(&sourcerc, LOCATOR_WIDTH, 0);\r
+ sourcerc.right -= LOCATOR_WIDTH;\r
+ }\r
+ ::InvalidateRect(wMain, NULL, FALSE);\r
+ ::SetWindowPos(m_wEditor, 0, sourcerc.left, sourcerc.top, sourcerc.right - sourcerc.left, sourcerc.bottom - sourcerc.top, 0);\r
+ ::SetWindowPos(wBlame, 0, blamerc.left, blamerc.top, blamerc.right - blamerc.left, blamerc.bottom - blamerc.top, 0);\r
+ if (m_colorage)\r
+ ::SetWindowPos(wLocator, 0, 0, blamerc.top, LOCATOR_WIDTH, blamerc.bottom - blamerc.top, SWP_SHOWWINDOW);\r
+ else\r
+ ::ShowWindow(wLocator, SW_HIDE);\r
+}\r
+\r
+#if 0\r
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ if (message == uFindReplaceMsg)\r
+ {\r
+ LPFINDREPLACE lpfr = (LPFINDREPLACE)lParam;\r
+\r
+ // If the FR_DIALOGTERM flag is set, \r
+ // invalidate the handle identifying the dialog box. \r
+ if (lpfr->Flags & FR_DIALOGTERM)\r
+ {\r
+ app.currentDialog = NULL; \r
+ return 0; \r
+ } \r
+ if (lpfr->Flags & FR_FINDNEXT)\r
+ {\r
+ app.DoSearch(lpfr->lpstrFindWhat, lpfr->Flags);\r
+ }\r
+ return 0; \r
+ }\r
+ switch (message) \r
+ {\r
+ case WM_CREATE:\r
+ app.m_wEditor = ::CreateWindow(\r
+ "Scintilla",\r
+ "Source",\r
+ WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_CLIPCHILDREN,\r
+ 0, 0,\r
+ 100, 100,\r
+ hWnd,\r
+ 0,\r
+ app.hResource,\r
+ 0);\r
+ app.InitialiseEditor();\r
+ ::ShowWindow(app.m_wEditor, SW_SHOW);\r
+ ::SetFocus(app.m_wEditor);\r
+ app.wBlame = ::CreateWindow(\r
+ _T("TortoiseGitBlameViewBlame"), \r
+ _T("blame"), \r
+ WS_CHILD | WS_CLIPCHILDREN,\r
+ CW_USEDEFAULT, 0, \r
+ CW_USEDEFAULT, 0, \r
+ hWnd, \r
+ NULL, \r
+ app.hResource, \r
+ NULL);\r
+ ::ShowWindow(app.wBlame, SW_SHOW);\r
+ app.wHeader = ::CreateWindow(\r
+ _T("TortoiseGitBlameViewHeader"), \r
+ _T("header"), \r
+ WS_CHILD | WS_CLIPCHILDREN | WS_BORDER,\r
+ CW_USEDEFAULT, 0, \r
+ CW_USEDEFAULT, 0, \r
+ hWnd, \r
+ NULL, \r
+ app.hResource, \r
+ NULL);\r
+ ::ShowWindow(app.wHeader, SW_SHOW);\r
+ app.wLocator = ::CreateWindow(\r
+ _T("TortoiseGitBlameViewLocator"), \r
+ _T("locator"), \r
+ WS_CHILD | WS_CLIPCHILDREN | WS_BORDER,\r
+ CW_USEDEFAULT, 0, \r
+ CW_USEDEFAULT, 0, \r
+ hWnd, \r
+ NULL, \r
+ app.hResource, \r
+ NULL);\r
+ ::ShowWindow(app.wLocator, SW_SHOW);\r
+ return 0;\r
+\r
+ case WM_SIZE:\r
+ if (wParam != 1) \r
+ {\r
+ app.InitSize();\r
+ }\r
+ return 0;\r
+\r
+ case WM_COMMAND:\r
+ app.Command(LOWORD(wParam));\r
+ break;\r
+ case WM_NOTIFY:\r
+ app.Notify(reinterpret_cast<SCNotification *>(lParam));\r
+ return 0;\r
+ case WM_DESTROY:\r
+ PostQuitMessage(0);\r
+ break;\r
+ case WM_CLOSE:\r
+ {\r
+ CRegStdWORD pos(_T("Software\\TortoiseGit\\TBlamePos"), 0);\r
+ CRegStdWORD width(_T("Software\\TortoiseGit\\TBlameSize"), 0);\r
+ CRegStdWORD state(_T("Software\\TortoiseGit\\TBlameState"), 0);\r
+ RECT rc;\r
+ GetWindowRect(app.wMain, &rc);\r
+ if ((rc.left >= 0)&&(rc.top >= 0))\r
+ {\r
+ pos = MAKELONG(rc.left, rc.top);\r
+ width = MAKELONG(rc.right-rc.left, rc.bottom-rc.top);\r
+ }\r
+ WINDOWPLACEMENT wp = {0};\r
+ wp.length = sizeof(WINDOWPLACEMENT);\r
+ GetWindowPlacement(app.wMain, &wp);\r
+ state = wp.showCmd;\r
+ ::DestroyWindow(app.m_wEditor);\r
+ ::PostQuitMessage(0);\r
+ }\r
+ return 0;\r
+ case WM_SETFOCUS:\r
+ ::SetFocus(app.wBlame);\r
+ break;\r
+ default:\r
+ return DefWindowProc(hWnd, message, wParam, lParam);\r
+ }\r
+ return 0;\r
+}\r
+\r
+LRESULT CALLBACK WndBlameProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ PAINTSTRUCT ps;\r
+ TRACKMOUSEEVENT mevt;\r
+ HDC hDC;\r
+ switch (message) \r
+ {\r
+ case WM_CREATE:\r
+ return 0;\r
+ case WM_PAINT:\r
+ hDC = BeginPaint(app.wBlame, &ps);\r
+ app.DrawBlame(hDC);\r
+ EndPaint(app.wBlame, &ps);\r
+ break;\r
+ case WM_COMMAND:\r
+ app.Command(LOWORD(wParam));\r
+ break;\r
+ case WM_NOTIFY:\r
+ switch (((LPNMHDR)lParam)->code)\r
+ {\r
+ case TTN_GETDISPINFO:\r
+ {\r
+ LPNMHDR pNMHDR = (LPNMHDR)lParam;\r
+ NMTTDISPINFOA* pTTTA = (NMTTDISPINFOA*)pNMHDR;\r
+ NMTTDISPINFOW* pTTTW = (NMTTDISPINFOW*)pNMHDR;\r
+ POINT point;\r
+ DWORD ptW = GetMessagePos();\r
+ point.x = GET_X_LPARAM(ptW);\r
+ point.y = GET_Y_LPARAM(ptW);\r
+ ::ScreenToClient(app.wBlame, &point);\r
+ LONG_PTR line = app.SendEditor(SCI_GETFIRSTVISIBLELINE);\r
+ LONG_PTR height = app.SendEditor(SCI_TEXTHEIGHT);\r
+ line = line + (point.y/height);\r
+ if (line >= (LONG)app.revs.size())\r
+ break;\r
+ if (line < 0)\r
+ break;\r
+ LONG rev = app.revs[line];\r
+ if (line >= (LONG)app.revs.size())\r
+ break;\r
+\r
+ SecureZeroMemory(app.m_szTip, sizeof(app.m_szTip));\r
+ SecureZeroMemory(app.m_wszTip, sizeof(app.m_wszTip));\r
+ std::map<LONG, CString>::iterator iter;\r
+ if ((iter = app.logmessages.find(rev)) != app.logmessages.end())\r
+ {\r
+ CString msg;\r
+ if (!ShowAuthor)\r
+ {\r
+ msg += app.authors[line];\r
+ }\r
+ if (!ShowDate)\r
+ {\r
+ if (!ShowAuthor) msg += " ";\r
+ msg += app.dates[line];\r
+ }\r
+ if (!ShowAuthor || !ShowDate)\r
+ msg += '\n';\r
+ msg += iter->second;\r
+ // an empty tooltip string will deactivate the tooltips,\r
+ // which means we must make sure that the tooltip won't\r
+ // be empty.\r
+ if (msg.empty())\r
+ msg = _T(" ");\r
+ if (pNMHDR->code == TTN_NEEDTEXTA)\r
+ {\r
+ lstrcpyn(app.m_szTip, msg.c_str(), MAX_LOG_LENGTH*2);\r
+ app.StringExpand(app.m_szTip);\r
+ pTTTA->lpszText = app.m_szTip;\r
+ }\r
+ else\r
+ {\r
+ pTTTW->lpszText = app.m_wszTip;\r
+ ::MultiByteToWideChar( CP_ACP , 0, msg.c_str(), min(msg.size(), MAX_LOG_LENGTH*2), app.m_wszTip, MAX_LOG_LENGTH*2);\r
+ app.StringExpand(app.m_wszTip);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ return 0;\r
+ case WM_DESTROY:\r
+ break;\r
+ case WM_CLOSE:\r
+ return 0;\r
+ case WM_MOUSELEAVE:\r
+ app.m_mouserev = -2;\r
+ app.m_mouseauthor.clear();\r
+ app.ttVisible = FALSE;\r
+ SendMessage(app.hwndTT, TTM_TRACKACTIVATE, FALSE, 0);\r
+ ::InvalidateRect(app.wBlame, NULL, FALSE);\r
+ break;\r
+ case WM_MOUSEMOVE:\r
+ {\r
+ mevt.cbSize = sizeof(TRACKMOUSEEVENT);\r
+ mevt.dwFlags = TME_LEAVE;\r
+ mevt.dwHoverTime = HOVER_DEFAULT;\r
+ mevt.hwndTrack = app.wBlame;\r
+ ::TrackMouseEvent(&mevt);\r
+ POINT pt = {((int)(short)LOWORD(lParam)), ((int)(short)HIWORD(lParam))};\r
+ ClientToScreen(app.wBlame, &pt);\r
+ pt.x += 15;\r
+ pt.y += 15;\r
+ SendMessage(app.hwndTT, TTM_TRACKPOSITION, 0, MAKELONG(pt.x, pt.y));\r
+ if (!app.ttVisible)\r
+ {\r
+ TOOLINFO ti;\r
+ ti.cbSize = sizeof(TOOLINFO);\r
+ ti.hwnd = app.wBlame;\r
+ ti.uId = 0;\r
+ SendMessage(app.hwndTT, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti);\r
+ }\r
+ int y = ((int)(short)HIWORD(lParam));\r
+ LONG_PTR line = app.SendEditor(SCI_GETFIRSTVISIBLELINE);\r
+ LONG_PTR height = app.SendEditor(SCI_TEXTHEIGHT);\r
+ line = line + (y/height);\r
+ app.ttVisible = (line < (LONG)app.revs.size());\r
+ if ( app.ttVisible )\r
+ {\r
+ if (app.authors[line].compare(app.m_mouseauthor) != 0)\r
+ {\r
+ app.m_mouseauthor = app.authors[line];\r
+ }\r
+ if (app.revs[line] != app.m_mouserev)\r
+ {\r
+ app.m_mouserev = app.revs[line];\r
+ ::InvalidateRect(app.wBlame, NULL, FALSE);\r
+ SendMessage(app.hwndTT, TTM_UPDATE, 0, 0);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case WM_RBUTTONDOWN:\r
+ // fall through\r
+ case WM_LBUTTONDOWN:\r
+ {\r
+ break;\r
+ case WM_SETFOCUS:\r
+ ::SetFocus(app.wBlame);\r
+ app.SendEditor(SCI_GRABFOCUS);\r
+ break;\r
+ case WM_CONTEXTMENU:\r
+ {\r
+ if (app.m_selectedrev <= 0)\r
+ break;;\r
+ int xPos = GET_X_LPARAM(lParam);\r
+ int yPos = GET_Y_LPARAM(lParam);\r
+ if ((xPos < 0)||(yPos < 0))\r
+ {\r
+ // requested from keyboard, not mouse pointer\r
+ // use the center of the window\r
+ RECT rect;\r
+ GetClientRect(app.wBlame, &rect);\r
+ xPos = rect.right-rect.left;\r
+ yPos = rect.bottom-rect.top;\r
+ }\r
+ HMENU hMenu = LoadMenu(app.hResource, MAKEINTRESOURCE(IDR_BLAMEPOPUP));\r
+ HMENU hPopMenu = GetSubMenu(hMenu, 0);\r
+\r
+ if ( _tcslen(szOrigPath)==0 )\r
+ {\r
+ // Without knowing the original path we cannot blame the previous revision\r
+ // because we don't know which filename to pass to tortoiseproc.\r
+ EnableMenuItem(hPopMenu,ID_BLAME_PREVIOUS_REVISION, MF_DISABLED|MF_GRAYED);\r
+ }\r
+ \r
+ TrackPopupMenu(hPopMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, xPos, yPos, 0, app.wBlame, NULL); \r
+ DestroyMenu(hMenu);\r
+ }\r
+ break;\r
+ default:\r
+ return DefWindowProc(hWnd, message, wParam, lParam);\r
+ }\r
+ return 0;\r
+}\r
+\r
+LRESULT CALLBACK WndHeaderProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ PAINTSTRUCT ps;\r
+ HDC hDC;\r
+ switch (message) \r
+ {\r
+ case WM_CREATE:\r
+ return 0;\r
+ case WM_PAINT:\r
+ hDC = BeginPaint(app.wHeader, &ps);\r
+ app.DrawHeader(hDC);\r
+ EndPaint(app.wHeader, &ps);\r
+ break;\r
+ case WM_COMMAND:\r
+ break;\r
+ case WM_DESTROY:\r
+ break;\r
+ case WM_CLOSE:\r
+ return 0;\r
+ default:\r
+ return DefWindowProc(hWnd, message, wParam, lParam);\r
+ }\r
+ return 0;\r
+}\r
+\r
+LRESULT CALLBACK WndLocatorProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ PAINTSTRUCT ps;\r
+ HDC hDC;\r
+ switch (message) \r
+ {\r
+ case WM_PAINT:\r
+ hDC = BeginPaint(app.wLocator, &ps);\r
+ app.DrawLocatorBar(hDC);\r
+ EndPaint(app.wLocator, &ps);\r
+ break;\r
+ case WM_LBUTTONDOWN:\r
+ case WM_MOUSEMOVE:\r
+ if (wParam & MK_LBUTTON)\r
+ {\r
+ RECT rect;\r
+ ::GetClientRect(hWnd, &rect); \r
+ int nLine = HIWORD(lParam)*app.revs.size()/(rect.bottom-rect.top);\r
+\r
+ if (nLine < 0)\r
+ nLine = 0;\r
+ app.ScrollToLine(nLine);\r
+ }\r
+ break;\r
+ default:\r
+ return DefWindowProc(hWnd, message, wParam, lParam);\r
+ }\r
+ return 0;\r
+}\r
+#endif\r
+\r
+void CTortoiseGitBlameView::SetupLexer(CString filename)\r
+{\r
+\r
+ TCHAR *line;\r
+ //const char * lineptr = _tcsrchr(filename, '.');\r
+ int start=filename.ReverseFind(_T('.'));\r
+ if (start>0)\r
+ {\r
+ //_tcscpy_s(line, 20, lineptr+1);\r
+ //_tcslwr_s(line, 20);\r
+ CString ext=filename.Right(filename.GetLength()-start-1);\r
+ line=ext.GetBuffer();\r
+\r
+ if ((_tcscmp(line, _T("py"))==0)||\r
+ (_tcscmp(line, _T("pyw"))==0)||\r
+ (_tcscmp(line, _T("pyw"))==0))\r
+ {\r
+ SendEditor(SCI_SETLEXER, SCLEX_PYTHON);\r
+ SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("and assert break class continue def del elif \\r
+else except exec finally for from global if import in is lambda None \\r
+not or pass print raise return try while yield")).GetBuffer()));\r
+ SetAStyle(SCE_P_DEFAULT, black);\r
+ SetAStyle(SCE_P_COMMENTLINE, darkGreen);\r
+ SetAStyle(SCE_P_NUMBER, RGB(0, 0x80, 0x80));\r
+ SetAStyle(SCE_P_STRING, RGB(0, 0, 0x80));\r
+ SetAStyle(SCE_P_CHARACTER, RGB(0, 0, 0x80));\r
+ SetAStyle(SCE_P_WORD, RGB(0x80, 0, 0x80));\r
+ SetAStyle(SCE_P_TRIPLE, black);\r
+ SetAStyle(SCE_P_TRIPLEDOUBLE, black);\r
+ SetAStyle(SCE_P_CLASSNAME, darkBlue);\r
+ SetAStyle(SCE_P_DEFNAME, darkBlue);\r
+ SetAStyle(SCE_P_OPERATOR, darkBlue);\r
+ SetAStyle(SCE_P_IDENTIFIER, darkBlue);\r
+ SetAStyle(SCE_P_COMMENTBLOCK, darkGreen);\r
+ SetAStyle(SCE_P_STRINGEOL, red);\r
+ }\r
+ if ((_tcscmp(line, _T("c"))==0)||\r
+ (_tcscmp(line, _T("cc"))==0)||\r
+ (_tcscmp(line, _T("cpp"))==0)||\r
+ (_tcscmp(line, _T("cxx"))==0)||\r
+ (_tcscmp(line, _T("h"))==0)||\r
+ (_tcscmp(line, _T("hh"))==0)||\r
+ (_tcscmp(line, _T("hpp"))==0)||\r
+ (_tcscmp(line, _T("hxx"))==0)||\r
+ (_tcscmp(line, _T("dlg"))==0)||\r
+ (_tcscmp(line, _T("mak"))==0))\r
+ {\r
+ SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
+ SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("and and_eq asm auto bitand bitor bool break \\r
+case catch char class compl const const_cast continue \\r
+default delete do double dynamic_cast else enum explicit export extern false float for \\r
+friend goto if inline int long mutable namespace new not not_eq \\r
+operator or or_eq private protected public \\r
+register reinterpret_cast return short signed sizeof static static_cast struct switch \\r
+template this throw true try typedef typeid typename union unsigned using \\r
+virtual void volatile wchar_t while xor xor_eq")).GetBuffer()));\r
+ SendEditor(SCI_SETKEYWORDS, 3, (LPARAM)(m_TextView.StringForControl(_T("a addindex addtogroup anchor arg attention \\r
+author b brief bug c class code date def defgroup deprecated dontinclude \\r
+e em endcode endhtmlonly endif endlatexonly endlink endverbatim enum example exception \\r
+f$ f[ f] file fn hideinitializer htmlinclude htmlonly \\r
+if image include ingroup internal invariant interface latexonly li line link \\r
+mainpage name namespace nosubgrouping note overload \\r
+p page par param post pre ref relates remarks return retval \\r
+sa section see showinitializer since skip skipline struct subsection \\r
+test throw todo typedef union until \\r
+var verbatim verbinclude version warning weakgroup $ @ \\ & < > # { }")).GetBuffer()));\r
+ SetupCppLexer();\r
+ }\r
+ if (_tcscmp(line, _T("cs"))==0)\r
+ {\r
+ SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
+ SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("abstract as base bool break byte case catch char checked class \\r
+const continue decimal default delegate do double else enum \\r
+event explicit extern false finally fixed float for foreach goto if \\r
+implicit in int interface internal is lock long namespace new null \\r
+object operator out override params private protected public \\r
+readonly ref return sbyte sealed short sizeof stackalloc static \\r
+string struct switch this throw true try typeof uint ulong \\r
+unchecked unsafe ushort using virtual void while")).GetBuffer()));\r
+ SetupCppLexer();\r
+ }\r
+ if ((_tcscmp(line, _T("rc"))==0)||\r
+ (_tcscmp(line, _T("rc2"))==0))\r
+ {\r
+ SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
+ SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("ACCELERATORS ALT AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON \\r
+BEGIN BITMAP BLOCK BUTTON CAPTION CHARACTERISTICS CHECKBOX CLASS \\r
+COMBOBOX CONTROL CTEXT CURSOR DEFPUSHBUTTON DIALOG DIALOGEX DISCARDABLE \\r
+EDITTEXT END EXSTYLE FONT GROUPBOX ICON LANGUAGE LISTBOX LTEXT \\r
+MENU MENUEX MENUITEM MESSAGETABLE POPUP \\r
+PUSHBUTTON RADIOBUTTON RCDATA RTEXT SCROLLBAR SEPARATOR SHIFT STATE3 \\r
+STRINGTABLE STYLE TEXTINCLUDE VALUE VERSION VERSIONINFO VIRTKEY")).GetBuffer()));\r
+ SetupCppLexer();\r
+ }\r
+ if ((_tcscmp(line, _T("idl"))==0)||\r
+ (_tcscmp(line, _T("odl"))==0))\r
+ {\r
+ SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
+ SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("aggregatable allocate appobject arrays async async_uuid \\r
+auto_handle \\r
+bindable boolean broadcast byte byte_count \\r
+call_as callback char coclass code comm_status \\r
+const context_handle context_handle_noserialize \\r
+context_handle_serialize control cpp_quote custom \\r
+decode default defaultbind defaultcollelem \\r
+defaultvalue defaultvtable dispinterface displaybind dllname \\r
+double dual \\r
+enable_allocate encode endpoint entry enum error_status_t \\r
+explicit_handle \\r
+fault_status first_is float \\r
+handle_t heap helpcontext helpfile helpstring \\r
+helpstringcontext helpstringdll hidden hyper \\r
+id idempotent ignore iid_as iid_is immediatebind implicit_handle \\r
+import importlib in include in_line int __int64 __int3264 interface \\r
+last_is lcid length_is library licensed local long \\r
+max_is maybe message methods midl_pragma \\r
+midl_user_allocate midl_user_free min_is module ms_union \\r
+ncacn_at_dsp ncacn_dnet_nsp ncacn_http ncacn_ip_tcp \\r
+ncacn_nb_ipx ncacn_nb_nb ncacn_nb_tcp ncacn_np \\r
+ncacn_spx ncacn_vns_spp ncadg_ip_udp ncadg_ipx ncadg_mq \\r
+ncalrpc nocode nonbrowsable noncreatable nonextensible notify \\r
+object odl oleautomation optimize optional out out_of_line \\r
+pipe pointer_default pragma properties propget propput propputref \\r
+ptr public \\r
+range readonly ref represent_as requestedit restricted retval \\r
+shape short signed size_is small source strict_context_handle \\r
+string struct switch switch_is switch_type \\r
+transmit_as typedef \\r
+uidefault union unique unsigned user_marshal usesgetlasterror uuid \\r
+v1_enum vararg version void wchar_t wire_marshal")).GetBuffer()));\r
+ SetupCppLexer();\r
+ }\r
+ if (_tcscmp(line, _T("java"))==0)\r
+ {\r
+ SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
+ SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("abstract assert boolean break byte case catch char class \\r
+const continue default do double else extends final finally float for future \\r
+generic goto if implements import inner instanceof int interface long \\r
+native new null outer package private protected public rest \\r
+return short static super switch synchronized this throw throws \\r
+transient try var void volatile while")).GetBuffer()));\r
+ SetupCppLexer();\r
+ }\r
+ if (_tcscmp(line, _T("js"))==0)\r
+ {\r
+ SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
+ SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("abstract boolean break byte case catch char class \\r
+const continue debugger default delete do double else enum export extends \\r
+final finally float for function goto if implements import in instanceof \\r
+int interface long native new package private protected public \\r
+return short static super switch synchronized this throw throws \\r
+transient try typeof var void volatile while with")).GetBuffer()));\r
+ SetupCppLexer();\r
+ }\r
+ if ((_tcscmp(line, _T("pas"))==0)||\r
+ (_tcscmp(line, _T("dpr"))==0)||\r
+ (_tcscmp(line, _T("pp"))==0))\r
+ {\r
+ SendEditor(SCI_SETLEXER, SCLEX_PASCAL);\r
+ SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("and array as begin case class const constructor \\r
+destructor div do downto else end except file finally \\r
+for function goto if implementation in inherited \\r
+interface is mod not object of on or packed \\r
+procedure program property raise record repeat \\r
+set shl shr then threadvar to try type unit \\r
+until uses var while with xor")).GetBuffer()));\r
+ SetupCppLexer();\r
+ }\r
+ if ((_tcscmp(line, _T("as"))==0)||\r
+ (_tcscmp(line, _T("asc"))==0)||\r
+ (_tcscmp(line, _T("jsfl"))==0))\r
+ {\r
+ SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
+ SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("add and break case catch class continue default delete do \\r
+dynamic else eq extends false finally for function ge get gt if implements import in \\r
+instanceof interface intrinsic le lt ne new not null or private public return \\r
+set static super switch this throw true try typeof undefined var void while with")).GetBuffer()));\r
+ SendEditor(SCI_SETKEYWORDS, 1, (LPARAM)(m_TextView.StringForControl(_T("Array Arguments Accessibility Boolean Button Camera Color \\r
+ContextMenu ContextMenuItem Date Error Function Key LoadVars LocalConnection Math \\r
+Microphone Mouse MovieClip MovieClipLoader NetConnection NetStream Number Object \\r
+PrintJob Selection SharedObject Sound Stage String StyleSheet System TextField \\r
+TextFormat TextSnapshot Video Void XML XMLNode XMLSocket \\r
+_accProps _focusrect _global _highquality _parent _quality _root _soundbuftime \\r
+arguments asfunction call capabilities chr clearInterval duplicateMovieClip \\r
+escape eval fscommand getProperty getTimer getURL getVersion gotoAndPlay gotoAndStop \\r
+ifFrameLoaded Infinity -Infinity int isFinite isNaN length loadMovie loadMovieNum \\r
+loadVariables loadVariablesNum maxscroll mbchr mblength mbord mbsubstring MMExecute \\r
+NaN newline nextFrame nextScene on onClipEvent onUpdate ord parseFloat parseInt play \\r
+prevFrame prevScene print printAsBitmap printAsBitmapNum printNum random removeMovieClip \\r
+scroll set setInterval setProperty startDrag stop stopAllSounds stopDrag substring \\r
+targetPath tellTarget toggleHighQuality trace unescape unloadMovie unLoadMovieNum updateAfterEvent")).GetBuffer()));\r
+ SetupCppLexer();\r
+ }\r
+ if ((_tcscmp(line, _T("html"))==0)||\r
+ (_tcscmp(line, _T("htm"))==0)||\r
+ (_tcscmp(line, _T("shtml"))==0)||\r
+ (_tcscmp(line, _T("htt"))==0)||\r
+ (_tcscmp(line, _T("xml"))==0)||\r
+ (_tcscmp(line, _T("asp"))==0)||\r
+ (_tcscmp(line, _T("xsl"))==0)||\r
+ (_tcscmp(line, _T("php"))==0)||\r
+ (_tcscmp(line, _T("xhtml"))==0)||\r
+ (_tcscmp(line, _T("phtml"))==0)||\r
+ (_tcscmp(line, _T("cfm"))==0)||\r
+ (_tcscmp(line, _T("tpl"))==0)||\r
+ (_tcscmp(line, _T("dtd"))==0)||\r
+ (_tcscmp(line, _T("hta"))==0)||\r
+ (_tcscmp(line, _T("htd"))==0)||\r
+ (_tcscmp(line, _T("wxs"))==0))\r
+ {\r
+ SendEditor(SCI_SETLEXER, SCLEX_HTML);\r
+ SendEditor(SCI_SETSTYLEBITS, 7);\r
+ SendEditor(SCI_SETKEYWORDS, 0, (LPARAM)(m_TextView.StringForControl(_T("a abbr acronym address applet area b base basefont \\r
+bdo big blockquote body br button caption center \\r
+cite code col colgroup dd del dfn dir div dl dt em \\r
+fieldset font form frame frameset h1 h2 h3 h4 h5 h6 \\r
+head hr html i iframe img input ins isindex kbd label \\r
+legend li link map menu meta noframes noscript \\r
+object ol optgroup option p param pre q s samp \\r
+script select small span strike strong style sub sup \\r
+table tbody td textarea tfoot th thead title tr tt u ul \\r
+var xml xmlns abbr accept-charset accept accesskey action align alink \\r
+alt archive axis background bgcolor border \\r
+cellpadding cellspacing char charoff charset checked cite \\r
+class classid clear codebase codetype color cols colspan \\r
+compact content coords \\r
+data datafld dataformatas datapagesize datasrc datetime \\r
+declare defer dir disabled enctype event \\r
+face for frame frameborder \\r
+headers height href hreflang hspace http-equiv \\r
+id ismap label lang language leftmargin link longdesc \\r
+marginwidth marginheight maxlength media method multiple \\r
+name nohref noresize noshade nowrap \\r
+object onblur onchange onclick ondblclick onfocus \\r
+onkeydown onkeypress onkeyup onload onmousedown \\r
+onmousemove onmouseover onmouseout onmouseup \\r
+onreset onselect onsubmit onunload \\r
+profile prompt readonly rel rev rows rowspan rules \\r
+scheme scope selected shape size span src standby start style \\r
+summary tabindex target text title topmargin type usemap \\r
+valign value valuetype version vlink vspace width \\r
+text password checkbox radio submit reset \\r
+file hidden image")).GetBuffer()));\r
+ SendEditor(SCI_SETKEYWORDS, 1, (LPARAM)(m_TextView.StringForControl(_T("assign audio block break catch choice clear disconnect else elseif \\r
+emphasis enumerate error exit field filled form goto grammar help \\r
+if initial link log menu meta noinput nomatch object option p paragraph \\r
+param phoneme prompt property prosody record reprompt return s say-as \\r
+script sentence subdialog submit throw transfer value var voice vxml")).GetBuffer()));\r
+ SendEditor(SCI_SETKEYWORDS, 2, (LPARAM)(m_TextView.StringForControl(_T("accept age alphabet anchor application base beep bridge category charset \\r
+classid cond connecttimeout content contour count dest destexpr dtmf dtmfterm \\r
+duration enctype event eventexpr expr expritem fetchtimeout finalsilence \\r
+gender http-equiv id level maxage maxstale maxtime message messageexpr \\r
+method mime modal mode name namelist next nextitem ph pitch range rate \\r
+scope size sizeexpr skiplist slot src srcexpr sub time timeexpr timeout \\r
+transferaudio type value variant version volume xml:lang")).GetBuffer()));\r
+ SendEditor(SCI_SETKEYWORDS, 3, (LPARAM)(m_TextView.StringForControl(_T("and assert break class continue def del elif \\r
+else except exec finally for from global if import in is lambda None \\r
+not or pass print raise return try while yield")).GetBuffer()));\r
+ SendEditor(SCI_SETKEYWORDS, 4, (LPARAM)(m_TextView.StringForControl(_T("and argv as argc break case cfunction class continue declare default do \\r
+die echo else elseif empty enddeclare endfor endforeach endif endswitch \\r
+endwhile e_all e_parse e_error e_warning eval exit extends false for \\r
+foreach function global http_cookie_vars http_get_vars http_post_vars \\r
+http_post_files http_env_vars http_server_vars if include include_once \\r
+list new not null old_function or parent php_os php_self php_version \\r
+print require require_once return static switch stdclass this true var \\r
+xor virtual while __file__ __line__ __sleep __wakeup")).GetBuffer()));\r
+\r
+ SetAStyle(SCE_H_TAG, darkBlue);\r
+ SetAStyle(SCE_H_TAGUNKNOWN, red);\r
+ SetAStyle(SCE_H_ATTRIBUTE, darkBlue);\r
+ SetAStyle(SCE_H_ATTRIBUTEUNKNOWN, red);\r
+ SetAStyle(SCE_H_NUMBER, RGB(0x80,0,0x80));\r
+ SetAStyle(SCE_H_DOUBLESTRING, RGB(0,0x80,0));\r
+ SetAStyle(SCE_H_SINGLESTRING, RGB(0,0x80,0));\r
+ SetAStyle(SCE_H_OTHER, RGB(0x80,0,0x80));\r
+ SetAStyle(SCE_H_COMMENT, RGB(0x80,0x80,0));\r
+ SetAStyle(SCE_H_ENTITY, RGB(0x80,0,0x80));\r
+\r
+ SetAStyle(SCE_H_TAGEND, darkBlue);\r
+ SetAStyle(SCE_H_XMLSTART, darkBlue); // <?\r
+ SetAStyle(SCE_H_QUESTION, darkBlue); // <?\r
+ SetAStyle(SCE_H_XMLEND, darkBlue); // ?>\r
+ SetAStyle(SCE_H_SCRIPT, darkBlue); // <script\r
+ SetAStyle(SCE_H_ASP, RGB(0x4F, 0x4F, 0), RGB(0xFF, 0xFF, 0)); // <% ... %>\r
+ SetAStyle(SCE_H_ASPAT, RGB(0x4F, 0x4F, 0), RGB(0xFF, 0xFF, 0)); // <%@ ... %>\r
+\r
+ SetAStyle(SCE_HB_DEFAULT, black);\r
+ SetAStyle(SCE_HB_COMMENTLINE, darkGreen);\r
+ SetAStyle(SCE_HB_NUMBER, RGB(0,0x80,0x80));\r
+ SetAStyle(SCE_HB_WORD, darkBlue);\r
+ SendEditor(SCI_STYLESETBOLD, SCE_HB_WORD, 1);\r
+ SetAStyle(SCE_HB_STRING, RGB(0x80,0,0x80));\r
+ SetAStyle(SCE_HB_IDENTIFIER, black);\r
+\r
+ // This light blue is found in the windows system palette so is safe to use even in 256 colour modes.\r
+ // Show the whole section of VBScript with light blue background\r
+ for (int bstyle=SCE_HB_DEFAULT; bstyle<=SCE_HB_STRINGEOL; bstyle++) {\r
+ SendEditor(SCI_STYLESETFONT, bstyle, \r
+ reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
+ SendEditor(SCI_STYLESETBACK, bstyle, lightBlue);\r
+ // This call extends the backround colour of the last style on the line to the edge of the window\r
+ SendEditor(SCI_STYLESETEOLFILLED, bstyle, 1);\r
+ }\r
+ SendEditor(SCI_STYLESETBACK, SCE_HB_STRINGEOL, RGB(0x7F,0x7F,0xFF));\r
+ SendEditor(SCI_STYLESETFONT, SCE_HB_COMMENTLINE, \r
+ reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
+\r
+ SetAStyle(SCE_HBA_DEFAULT, black);\r
+ SetAStyle(SCE_HBA_COMMENTLINE, darkGreen);\r
+ SetAStyle(SCE_HBA_NUMBER, RGB(0,0x80,0x80));\r
+ SetAStyle(SCE_HBA_WORD, darkBlue);\r
+ SendEditor(SCI_STYLESETBOLD, SCE_HBA_WORD, 1);\r
+ SetAStyle(SCE_HBA_STRING, RGB(0x80,0,0x80));\r
+ SetAStyle(SCE_HBA_IDENTIFIER, black);\r
+\r
+ // Show the whole section of ASP VBScript with bright yellow background\r
+ for (int bastyle=SCE_HBA_DEFAULT; bastyle<=SCE_HBA_STRINGEOL; bastyle++) {\r
+ SendEditor(SCI_STYLESETFONT, bastyle, \r
+ reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
+ SendEditor(SCI_STYLESETBACK, bastyle, RGB(0xFF, 0xFF, 0));\r
+ // This call extends the backround colour of the last style on the line to the edge of the window\r
+ SendEditor(SCI_STYLESETEOLFILLED, bastyle, 1);\r
+ }\r
+ SendEditor(SCI_STYLESETBACK, SCE_HBA_STRINGEOL, RGB(0xCF,0xCF,0x7F));\r
+ SendEditor(SCI_STYLESETFONT, SCE_HBA_COMMENTLINE, \r
+ reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
+\r
+ // If there is no need to support embedded Javascript, the following code can be dropped.\r
+ // Javascript will still be correctly processed but will be displayed in just the default style.\r
+\r
+ SetAStyle(SCE_HJ_START, RGB(0x80,0x80,0));\r
+ SetAStyle(SCE_HJ_DEFAULT, black);\r
+ SetAStyle(SCE_HJ_COMMENT, darkGreen);\r
+ SetAStyle(SCE_HJ_COMMENTLINE, darkGreen);\r
+ SetAStyle(SCE_HJ_COMMENTDOC, darkGreen);\r
+ SetAStyle(SCE_HJ_NUMBER, RGB(0,0x80,0x80));\r
+ SetAStyle(SCE_HJ_WORD, black);\r
+ SetAStyle(SCE_HJ_KEYWORD, darkBlue);\r
+ SetAStyle(SCE_HJ_DOUBLESTRING, RGB(0x80,0,0x80));\r
+ SetAStyle(SCE_HJ_SINGLESTRING, RGB(0x80,0,0x80));\r
+ SetAStyle(SCE_HJ_SYMBOLS, black);\r
+\r
+ SetAStyle(SCE_HJA_START, RGB(0x80,0x80,0));\r
+ SetAStyle(SCE_HJA_DEFAULT, black);\r
+ SetAStyle(SCE_HJA_COMMENT, darkGreen);\r
+ SetAStyle(SCE_HJA_COMMENTLINE, darkGreen);\r
+ SetAStyle(SCE_HJA_COMMENTDOC, darkGreen);\r
+ SetAStyle(SCE_HJA_NUMBER, RGB(0,0x80,0x80));\r
+ SetAStyle(SCE_HJA_WORD, black);\r
+ SetAStyle(SCE_HJA_KEYWORD, darkBlue);\r
+ SetAStyle(SCE_HJA_DOUBLESTRING, RGB(0x80,0,0x80));\r
+ SetAStyle(SCE_HJA_SINGLESTRING, RGB(0x80,0,0x80));\r
+ SetAStyle(SCE_HJA_SYMBOLS, black);\r
+\r
+ SetAStyle(SCE_HPHP_DEFAULT, black);\r
+ SetAStyle(SCE_HPHP_HSTRING, RGB(0x80,0,0x80));\r
+ SetAStyle(SCE_HPHP_SIMPLESTRING, RGB(0x80,0,0x80));\r
+ SetAStyle(SCE_HPHP_WORD, darkBlue);\r
+ SetAStyle(SCE_HPHP_NUMBER, RGB(0,0x80,0x80));\r
+ SetAStyle(SCE_HPHP_VARIABLE, red);\r
+ SetAStyle(SCE_HPHP_HSTRING_VARIABLE, red);\r
+ SetAStyle(SCE_HPHP_COMPLEX_VARIABLE, red);\r
+ SetAStyle(SCE_HPHP_COMMENT, darkGreen);\r
+ SetAStyle(SCE_HPHP_COMMENTLINE, darkGreen);\r
+ SetAStyle(SCE_HPHP_OPERATOR, darkBlue);\r
+\r
+ // Show the whole section of Javascript with off white background\r
+ for (int jstyle=SCE_HJ_DEFAULT; jstyle<=SCE_HJ_SYMBOLS; jstyle++) {\r
+ SendEditor(SCI_STYLESETFONT, jstyle, \r
+ reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
+ SendEditor(SCI_STYLESETBACK, jstyle, offWhite);\r
+ SendEditor(SCI_STYLESETEOLFILLED, jstyle, 1);\r
+ }\r
+ SendEditor(SCI_STYLESETBACK, SCE_HJ_STRINGEOL, RGB(0xDF, 0xDF, 0x7F));\r
+ SendEditor(SCI_STYLESETEOLFILLED, SCE_HJ_STRINGEOL, 1);\r
+\r
+ // Show the whole section of Javascript with brown background\r
+ for (int jastyle=SCE_HJA_DEFAULT; jastyle<=SCE_HJA_SYMBOLS; jastyle++) {\r
+ SendEditor(SCI_STYLESETFONT, jastyle, \r
+ reinterpret_cast<LPARAM>(m_TextView.StringForControl(_T("Lucida Console")).GetBuffer()));\r
+ SendEditor(SCI_STYLESETBACK, jastyle, RGB(0xDF, 0xDF, 0x7F));\r
+ SendEditor(SCI_STYLESETEOLFILLED, jastyle, 1);\r
+ }\r
+ SendEditor(SCI_STYLESETBACK, SCE_HJA_STRINGEOL, RGB(0x0,0xAF,0x5F));\r
+ SendEditor(SCI_STYLESETEOLFILLED, SCE_HJA_STRINGEOL, 1);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ SendEditor(SCI_SETLEXER, SCLEX_CPP);\r
+ SetupCppLexer();\r
+ }\r
+ SendEditor(SCI_COLOURISE, 0, -1);\r
+\r
+}\r
+\r
+void CTortoiseGitBlameView::SetupCppLexer()\r
+{\r
+ SetAStyle(SCE_C_DEFAULT, RGB(0, 0, 0));\r
+ SetAStyle(SCE_C_COMMENT, RGB(0, 0x80, 0));\r
+ SetAStyle(SCE_C_COMMENTLINE, RGB(0, 0x80, 0));\r
+ SetAStyle(SCE_C_COMMENTDOC, RGB(0, 0x80, 0));\r
+ SetAStyle(SCE_C_COMMENTLINEDOC, RGB(0, 0x80, 0));\r
+ SetAStyle(SCE_C_COMMENTDOCKEYWORD, RGB(0, 0x80, 0));\r
+ SetAStyle(SCE_C_COMMENTDOCKEYWORDERROR, RGB(0, 0x80, 0));\r
+ SetAStyle(SCE_C_NUMBER, RGB(0, 0x80, 0x80));\r
+ SetAStyle(SCE_C_WORD, RGB(0, 0, 0x80));\r
+ SendEditor(SCE_C_WORD, 1);\r
+ SetAStyle(SCE_C_STRING, RGB(0x80, 0, 0x80));\r
+ SetAStyle(SCE_C_IDENTIFIER, RGB(0, 0, 0));\r
+ SetAStyle(SCE_C_PREPROCESSOR, RGB(0x80, 0, 0));\r
+ SetAStyle(SCE_C_OPERATOR, RGB(0x80, 0x80, 0));\r
+}\r
+\r
+\r
+void CTortoiseGitBlameView::UpdateInfo()\r
+{\r
+ CString &data = GetDocument()->m_BlameData;\r
+ CString one;\r
+ int pos=0;\r
+\r
+ CLogDataVector * pRevs= GetLogData();\r
+\r
+ this->m_CommitHash.clear();\r
+ this->m_Authors.clear();\r
+ this->m_ID.clear();\r
+ CString line;\r
+\r
+ CreateFont();\r
+\r
+ SendEditor(SCI_SETREADONLY, FALSE);\r
+ SendEditor(SCI_CLEARALL);\r
+ SendEditor(EM_EMPTYUNDOBUFFER);\r
+ SendEditor(SCI_SETSAVEPOINT);\r
+ SendEditor(SCI_CANCEL);\r
+ SendEditor(SCI_SETUNDOCOLLECTION, 0);\r
+\r
+ while( pos>=0 )\r
+ {\r
+ one=data.Tokenize(_T("\n"),pos);\r
+ if(one.IsEmpty())\r
+ continue;\r
+ m_CommitHash.push_back(one.Left(40));\r
+ int start=0;\r
+ start=one.Find(_T(')'),40);\r
+ if(start>0)\r
+ {\r
+ line=one.Right(one.GetLength()-start-2);\r
+ this->m_TextView.InsertText(line,true);\r
+ }\r
+ int id=pRevs->m_HashMap[one.Left(40)]; \r
+ if(id>=0 && id <GetLogData()->size())\r
+ {\r
+ m_ID.push_back(pRevs->size()-id);\r
+ m_Authors.push_back(pRevs->at(id).m_AuthorName);\r
+ }else\r
+ {\r
+ ASSERT(FALSE);\r
+ }\r
+ }\r
+\r
+ SetupLexer(GetDocument()->m_CurrentFileName);\r
+\r
+ SendEditor(SCI_SETUNDOCOLLECTION, 1);\r
+ SendEditor(EM_EMPTYUNDOBUFFER);\r
+ SendEditor(SCI_SETSAVEPOINT);\r
+ SendEditor(SCI_GOTOPOS, 0);\r
+ SendEditor(SCI_SETSCROLLWIDTHTRACKING, TRUE);\r
+ SendEditor(SCI_SETREADONLY, TRUE);\r
+\r
+ m_lowestrev=1;\r
+ m_highestrev=this->GetLogData()->size();\r
+\r
+ GetBlameWidth();\r
+ CRect rect;\r
+ this->GetClientRect(rect);\r
+ //this->m_TextView.GetWindowRect(rect);\r
+ //this->m_TextView.ScreenToClient(rect);\r
+ rect.left=this->m_blamewidth;\r
+ this->m_TextView.MoveWindow(rect);\r
+\r
+ this->Invalidate();\r
+}\r
+\r
+CGitBlameLogList * CTortoiseGitBlameView::GetLogList()\r
+{\r
+ return &(GetDocument()->GetMainFrame()->m_wndOutput.m_LogList);\r
+}\r
+\r
+\r
+CLogDataVector * CTortoiseGitBlameView::GetLogData()\r
+{\r
+ return &(GetDocument()->GetMainFrame()->m_wndOutput.m_LogList.m_logEntries);\r
+}\r
+\r
+void CTortoiseGitBlameView::OnSciPainted(NMHDR *,LRESULT *)\r
+{\r
+ this->Invalidate();\r
+}\r
+\r
+void CTortoiseGitBlameView::OnLButtonDown(UINT nFlags,CPoint point)\r
+{\r
+\r
+ LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
+ LONG_PTR height = SendEditor(SCI_TEXTHEIGHT);\r
+ line = line + (point.y/height);\r
+ \r
+ if (line < (LONG)m_CommitHash.size())\r
+ {\r
+ SetSelectedLine(line);\r
+ if (m_CommitHash[line] != m_SelectedHash)\r
+ {\r
+ m_SelectedHash = m_CommitHash[line];\r
+// app.m_selectedorigrev = app.origrevs[line];\r
+// app.m_selectedauthor = app.authors[line];\r
+// app.m_selecteddate = app.dates[line];\r
+ \r
+ \r
+ this->GetLogList()->SetItemState(this->GetLogList()->GetItemCount()-m_ID[line],\r
+ LVIS_SELECTED,\r
+ LVIS_SELECTED);\r
+\r
+ GitRev *pRev;\r
+ pRev=&this->GetLogData()->at(this->GetLogList()->GetItemCount()-m_ID[line]);\r
+ this->GetDocument()->GetMainFrame()->m_wndProperties.UpdateProperties(pRev);\r
+ }\r
+ else\r
+ {\r
+ m_SelectedHash.Empty();\r
+// app.m_selecteddate.clear();\r
+// app.m_selectedrev = -2;\r
+// app.m_selectedorigrev = -2;\r
+ }\r
+ //::InvalidateRect( NULL, FALSE);\r
+ this->Invalidate();\r
+ this->m_TextView.Invalidate();\r
+ \r
+ }\r
+ else\r
+ {\r
+ SetSelectedLine(-1);\r
+ }\r
+ \r
+ CView::OnLButtonDown(nFlags,point);\r
+}\r
+\r
+void CTortoiseGitBlameView::OnSciGetBkColor(NMHDR* hdr, LRESULT* result)\r
+{\r
+\r
+ SCNotification *notification=reinterpret_cast<SCNotification *>(hdr);\r
+\r
+ if ((m_colorage)&&(notification->line < (int)m_CommitHash.size()))\r
+ {\r
+ if(m_CommitHash[notification->line] == this->m_SelectedHash )\r
+ notification->lParam = m_selectedauthorcolor;\r
+ else\r
+ notification->lParam = InterColor(DWORD(m_regOldLinesColor), DWORD(m_regNewLinesColor), (m_ID[notification->line]-m_lowestrev)*100/((m_highestrev-m_lowestrev)+1));\r
+ }\r
+\r
+}\r
+\r
+void CTortoiseGitBlameView::FocusOn(GitRev *pRev)\r
+{\r
+ m_SelectedHash = pRev->m_CommitHash;\r
+\r
+ //GitRev *pRev;\r
+ //pRev=&this->GetLogData()->at(this->GetLogList()->GetItemCount()-m_ID[line]);\r
+ this->GetDocument()->GetMainFrame()->m_wndProperties.UpdateProperties(pRev);\r
+\r
+ this->Invalidate();\r
+ this->m_TextView.Invalidate();\r
+\r
+}\r
+\r
+void CTortoiseGitBlameView::OnMouseHover(UINT nFlags, CPoint point)\r
+{\r
+\r
+ LONG_PTR line = SendEditor(SCI_GETFIRSTVISIBLELINE);\r
+ LONG_PTR height = SendEditor(SCI_TEXTHEIGHT);\r
+ line = line + (point.y/height);\r
+ \r
+ if (line < (LONG)m_CommitHash.size())\r
+ {\r
+ if (line != m_MouseLine)\r
+ {\r
+ m_MouseLine = line;//m_CommitHash[line];\r
+// app.m_selectedorigrev = app.origrevs[line];\r
+// app.m_selectedauthor = app.authors[line];\r
+// app.m_selecteddate = app.dates[line];\r
+ \r
+ \r
+ GitRev *pRev;\r
+ pRev=&this->GetLogData()->at(this->GetLogList()->GetItemCount()-m_ID[line]);\r
+ //this->GetDocument()->GetMainFrame()->m_wndProperties.UpdateProperties(pRev);\r
+ this->ClientToScreen(&point);\r
+ //BALLOON_INFO bi;\r
+ //if(m_ToolTip.GetTool(this, bi))\r
+ //{\r
+ // bi.sBalloonTip=pRev->m_CommitHash;\r
+ CString str;\r
+ str.Format(_T("%s\n<b>%s</b>\n%s\n%s"),pRev->m_CommitHash,\r
+ pRev->m_Subject,\r
+ pRev->m_AuthorDate.Format(_T("%Y-%m-%d %H:%M")),\r
+ pRev->m_Body);\r
+ m_ToolTip.AddTool(this,str);\r
+ m_ToolTip.DisplayToolTip(&point);\r
+ //}\r
+ \r
+ CRect rect;\r
+ this->ScreenToClient(&point);\r
+ rect.left=LOCATOR_WIDTH;\r
+ rect.right=this->m_blamewidth+rect.left;\r
+ rect.top=point.y-height;\r
+ rect.bottom=point.y+height;\r
+ this->InvalidateRect(rect);\r
+\r
+ }\r
+ else\r
+ {\r
+ m_MouseLine=-1;\r
+// app.m_selecteddate.clear();\r
+// app.m_selectedrev = -2;\r
+// app.m_selectedorigrev = -2;\r
+ }\r
+ //::InvalidateRect( NULL, FALSE);\r
+ //this->Invalidate();\r
+ }\r
+ \r
+// const CString str=_T("this is a <b>Message Balloon</b>\n<hr=100%>\n<ct=0x0000FF>Warning! Warning!</ct>\nSomething unexpected happened");\r
+ //CBalloon::ShowBalloon(NULL, point, \r
+ // str,\r
+ // FALSE, (HICON)IDI_EXCLAMATION,\r
+ // (UINT)CBalloon ::BALLOON_RIGHT_TOP, (UINT)CBalloon ::BALLOON_EFFECT_SOLID,(COLORREF)NULL, (COLORREF)NULL, (COLORREF)NULL);\r
+}\r
+\r
+void CTortoiseGitBlameView::OnMouseMove(UINT nFlags, CPoint point)\r
+{\r
+ TRACKMOUSEEVENT tme;\r
+ tme.cbSize=sizeof(TRACKMOUSEEVENT);\r
+ tme.dwFlags=TME_HOVER|TME_LEAVE;\r
+ tme.hwndTrack=this->m_hWnd;\r
+ tme.dwHoverTime=1;\r
+ TrackMouseEvent(&tme);\r
+}\r
+\r
+\r
+BOOL CTortoiseGitBlameView::PreTranslateMessage(MSG* pMsg)\r
+{\r
+ m_ToolTip.RelayEvent(pMsg);\r
+ return CView::PreTranslateMessage(pMsg);\r
+}\r
+\r
+void CTortoiseGitBlameView::OnEditFind()\r
+{\r
+ m_pFindDialog=new CFindReplaceDialog();\r
+ \r
+ m_pFindDialog->Create(TRUE,_T(""),NULL,FR_DOWN,this); \r
+}\r
+\r
+void CTortoiseGitBlameView::OnEditGoto()\r
+{\r
+ CEditGotoDlg dlg;\r
+ if(dlg.DoModal()==IDOK)\r
+ {\r
+ this->GotoLine(dlg.m_LineNumber);\r
+ }\r
+}\r
+\r
+LRESULT CTortoiseGitBlameView::OnFindDialogMessage(WPARAM wParam, LPARAM lParam)//Õâ¸öÒ²ÊÇÕÒÄǸö³ÌÐò¸ÄµÄ£¬Ö»²»¹ý»»³ÉÁË×Ô¼ºµÄÀà \r
+{ \r
+ ASSERT(m_pFindDialog != NULL); \r
+ \r
+ // If the FR_DIALOGTERM flag is set, \r
+ // invalidate the handle identifying the dialog box. \r
+ if (m_pFindDialog->IsTerminating()) \r
+ { \r
+ m_pFindDialog = NULL; \r
+ return 0; \r
+ } \r
+\r
+ // If the FR_FINDNEXT flag is set, \r
+ // call the application-defined search routine \r
+ // to search for the requested string. \r
+ if(m_pFindDialog->FindNext()) \r
+ { \r
+ //read data from dialog \r
+ CString FindName = m_pFindDialog->GetFindString(); \r
+ bool bMatchCase = m_pFindDialog->MatchCase() == TRUE; \r
+ bool bMatchWholeWord = m_pFindDialog->MatchWholeWord() == TRUE; \r
+ bool bSearchDown = m_pFindDialog->SearchDown() == TRUE; \r
+ \r
+ DoSearch(FindName,m_pFindDialog->m_fr.Flags);\r
+ //with given name do search \r
+ // *FindWhatYouNeed(FindName, bMatchCase, bMatchWholeWord, bSearchDown); \r
+ } \r
+\r
+ return 0; \r
+} \r
+\r