OSDN Git Service

b29e9c04c59fdaea2798b269d9a2fd468d35317b
[tortoisegit/TortoiseGitJp.git] / TortoiseShell / SVNPropertyPage.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\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 #include "stdafx.h"\r
20 \r
21 #include "ShellExt.h"\r
22 #include "svnpropertypage.h"\r
23 #include "UnicodeUtils.h"\r
24 #include "PathUtils.h"\r
25 #include "SVNStatus.h"\r
26 \r
27 #define MAX_STRING_LENGTH               4096                    //should be big enough\r
28 \r
29 // Nonmember function prototypes\r
30 BOOL CALLBACK PageProc (HWND, UINT, WPARAM, LPARAM);\r
31 UINT CALLBACK PropPageCallbackProc ( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp );\r
32 \r
33 // CShellExt member functions (needed for IShellPropSheetExt)\r
34 STDMETHODIMP CShellExt::AddPages (LPFNADDPROPSHEETPAGE lpfnAddPage,\r
35                                   LPARAM lParam)\r
36 {\r
37         for (std::vector<stdstring>::iterator I = files_.begin(); I != files_.end(); ++I)\r
38         {\r
39                 SVNStatus svn = SVNStatus();\r
40                 if (svn.GetStatus(CTSVNPath(I->c_str())) == (-2))\r
41                         return NOERROR;                 // file/directory not under version control\r
42 \r
43                 if (svn.status->entry == NULL)\r
44                         return NOERROR;\r
45         }\r
46 \r
47         if (files_.size() == 0)\r
48                 return NOERROR;\r
49 \r
50         LoadLangDll();\r
51     PROPSHEETPAGE psp;\r
52         SecureZeroMemory(&psp, sizeof(PROPSHEETPAGE));\r
53         HPROPSHEETPAGE hPage;\r
54         CSVNPropertyPage *sheetpage = new CSVNPropertyPage(files_);\r
55 \r
56     psp.dwSize = sizeof (psp);\r
57     psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE | PSP_USEICONID | PSP_USECALLBACK;    \r
58         psp.hInstance = g_hResInst;\r
59         psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE);\r
60     psp.pszIcon = MAKEINTRESOURCE(IDI_APPSMALL);\r
61     psp.pszTitle = _T("Subversion");\r
62     psp.pfnDlgProc = (DLGPROC) PageProc;\r
63     psp.lParam = (LPARAM) sheetpage;\r
64     psp.pfnCallback = PropPageCallbackProc;\r
65     psp.pcRefParent = &g_cRefThisDll;\r
66 \r
67     hPage = CreatePropertySheetPage (&psp);\r
68 \r
69         if (hPage != NULL)\r
70         {\r
71         if (!lpfnAddPage (hPage, lParam))\r
72         {\r
73             delete sheetpage;\r
74             DestroyPropertySheetPage (hPage);\r
75         }\r
76         }\r
77 \r
78     return NOERROR;\r
79 }\r
80 \r
81 \r
82 \r
83 STDMETHODIMP CShellExt::ReplacePage (UINT /*uPageID*/, LPFNADDPROPSHEETPAGE /*lpfnReplaceWith*/, LPARAM /*lParam*/)\r
84 {\r
85     return E_FAIL;\r
86 }\r
87 \r
88 /////////////////////////////////////////////////////////////////////////////\r
89 // Dialog procedures and other callback functions\r
90 \r
91 BOOL CALLBACK PageProc (HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)\r
92 {\r
93     CSVNPropertyPage * sheetpage;\r
94 \r
95     if (uMessage == WM_INITDIALOG)\r
96     {\r
97         sheetpage = (CSVNPropertyPage*) ((LPPROPSHEETPAGE) lParam)->lParam;\r
98         SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) sheetpage);\r
99         sheetpage->SetHwnd(hwnd);\r
100     }\r
101     else\r
102     {\r
103         sheetpage = (CSVNPropertyPage*) GetWindowLongPtr (hwnd, GWLP_USERDATA);\r
104     }\r
105 \r
106     if (sheetpage != 0L)\r
107         return sheetpage->PageProc(hwnd, uMessage, wParam, lParam);\r
108     else\r
109         return FALSE;\r
110 }\r
111 \r
112 UINT CALLBACK PropPageCallbackProc ( HWND /*hwnd*/, UINT uMsg, LPPROPSHEETPAGE ppsp )\r
113 {\r
114     // Delete the page before closing.\r
115     if (PSPCB_RELEASE == uMsg)\r
116     {\r
117         CSVNPropertyPage* sheetpage = (CSVNPropertyPage*) ppsp->lParam;\r
118         if (sheetpage != NULL)\r
119             delete sheetpage;\r
120     }\r
121     return 1;\r
122 }\r
123 \r
124 // *********************** CSVNPropertyPage *************************\r
125 \r
126 CSVNPropertyPage::CSVNPropertyPage(const std::vector<stdstring> &newFilenames)\r
127         :filenames(newFilenames)\r
128 {\r
129 }\r
130 \r
131 CSVNPropertyPage::~CSVNPropertyPage(void)\r
132 {\r
133 }\r
134 \r
135 void CSVNPropertyPage::SetHwnd(HWND newHwnd)\r
136 {\r
137     m_hwnd = newHwnd;\r
138 }\r
139 \r
140 BOOL CSVNPropertyPage::PageProc (HWND /*hwnd*/, UINT uMessage, WPARAM wParam, LPARAM lParam)\r
141 {\r
142         switch (uMessage)\r
143         {\r
144         case WM_INITDIALOG:\r
145                 {\r
146                         InitWorkfileView();\r
147                         return TRUE;\r
148                 }\r
149         case WM_NOTIFY:\r
150                 {\r
151                         LPNMHDR point = (LPNMHDR)lParam;\r
152                         int code = point->code;\r
153                         //\r
154                         // Respond to notifications.\r
155                         //    \r
156                         if (code == PSN_APPLY)\r
157                         {\r
158                         }\r
159                         SetWindowLongPtr (m_hwnd, DWLP_MSGRESULT, FALSE);\r
160                         return TRUE;        \r
161 \r
162                         }\r
163                 case WM_DESTROY:\r
164                         return TRUE;\r
165 \r
166                 case WM_COMMAND:\r
167                         switch (HIWORD(wParam))\r
168                         {\r
169                                 case BN_CLICKED:\r
170                                         if (LOWORD(wParam) == IDC_SHOWLOG)\r
171                                         {\r
172                                                 STARTUPINFO startup;\r
173                                                 PROCESS_INFORMATION process;\r
174                                                 memset(&startup, 0, sizeof(startup));\r
175                                                 startup.cb = sizeof(startup);\r
176                                                 memset(&process, 0, sizeof(process));\r
177                                                 CRegStdString tortoiseProcPath(_T("Software\\TortoiseSVN\\ProcPath"), _T("TortoiseProc.exe"), false, HKEY_LOCAL_MACHINE);\r
178                                                 stdstring svnCmd = _T(" /command:");\r
179                                                 svnCmd += _T("log /path:\"");\r
180                                                 svnCmd += filenames.front().c_str();\r
181                                                 svnCmd += _T("\"");\r
182                                                 if (CreateProcess(((stdstring)tortoiseProcPath).c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))\r
183                                                 {\r
184                                                         CloseHandle(process.hThread);\r
185                                                         CloseHandle(process.hProcess);\r
186                                                 }\r
187                                         }\r
188                                         if (LOWORD(wParam) == IDC_EDITPROPERTIES)\r
189                                         {\r
190                                                 DWORD pathlength = GetTempPath(0, NULL);\r
191                                                 TCHAR * path = new TCHAR[pathlength+1];\r
192                                                 TCHAR * tempFile = new TCHAR[pathlength + 100];\r
193                                                 GetTempPath (pathlength+1, path);\r
194                                                 GetTempFileName (path, _T("svn"), 0, tempFile);\r
195                                                 stdstring retFilePath = stdstring(tempFile);\r
196 \r
197                                                 HANDLE file = ::CreateFile (tempFile,\r
198                                                         GENERIC_WRITE, \r
199                                                         FILE_SHARE_READ, \r
200                                                         0, \r
201                                                         CREATE_ALWAYS, \r
202                                                         FILE_ATTRIBUTE_TEMPORARY,\r
203                                                         0);\r
204 \r
205                                                 delete [] path;\r
206                                                 delete [] tempFile;\r
207                                                 if (file != INVALID_HANDLE_VALUE)\r
208                                                 {\r
209                                                         DWORD written = 0;\r
210                                                         for (std::vector<stdstring>::iterator I = filenames.begin(); I != filenames.end(); ++I)\r
211                                                         {\r
212                                                                 ::WriteFile (file, I->c_str(), I->size()*sizeof(TCHAR), &written, 0);\r
213                                                                 ::WriteFile (file, _T("\n"), 2, &written, 0);\r
214                                                         }\r
215                                                         ::CloseHandle(file);\r
216 \r
217                                                         STARTUPINFO startup;\r
218                                                         PROCESS_INFORMATION process;\r
219                                                         memset(&startup, 0, sizeof(startup));\r
220                                                         startup.cb = sizeof(startup);\r
221                                                         memset(&process, 0, sizeof(process));\r
222                                                         CRegStdString tortoiseProcPath(_T("Software\\TortoiseSVN\\ProcPath"), _T("TortoiseProc.exe"), false, HKEY_LOCAL_MACHINE);\r
223                                                         stdstring svnCmd = _T(" /command:");\r
224                                                         svnCmd += _T("properties /pathfile:\"");\r
225                                                         svnCmd += retFilePath.c_str();\r
226                                                         svnCmd += _T("\"");\r
227                                                         svnCmd += _T(" /deletepathfile");\r
228                                                         if (CreateProcess(((stdstring)tortoiseProcPath).c_str(), const_cast<TCHAR*>(svnCmd.c_str()), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))\r
229                                                         {\r
230                                                                 CloseHandle(process.hThread);\r
231                                                                 CloseHandle(process.hProcess);\r
232                                                         }\r
233                                                 }\r
234                                         }\r
235                                         break;\r
236                         } // switch (HIWORD(wParam)) \r
237         } // switch (uMessage) \r
238         return FALSE;\r
239 }\r
240 void CSVNPropertyPage::Time64ToTimeString(__time64_t time, TCHAR * buf, size_t buflen)\r
241 {\r
242         struct tm newtime;\r
243         SYSTEMTIME systime;\r
244         TCHAR timebuf[MAX_STRING_LENGTH];\r
245         TCHAR datebuf[MAX_STRING_LENGTH];\r
246 \r
247         LCID locale = (WORD)CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));\r
248         locale = MAKELCID(locale, SORT_DEFAULT);\r
249 \r
250         *buf = '\0';\r
251         if (time)\r
252         {\r
253                 _localtime64_s(&newtime, &time);\r
254 \r
255                 systime.wDay = (WORD)newtime.tm_mday;\r
256                 systime.wDayOfWeek = (WORD)newtime.tm_wday;\r
257                 systime.wHour = (WORD)newtime.tm_hour;\r
258                 systime.wMilliseconds = 0;\r
259                 systime.wMinute = (WORD)newtime.tm_min;\r
260                 systime.wMonth = (WORD)newtime.tm_mon+1;\r
261                 systime.wSecond = (WORD)newtime.tm_sec;\r
262                 systime.wYear = (WORD)newtime.tm_year+1900;\r
263                 if (CRegStdWORD(_T("Software\\TortoiseSVN\\LogDateFormat")) == 1)\r
264                         GetDateFormat(locale, DATE_SHORTDATE, &systime, NULL, datebuf, MAX_STRING_LENGTH);\r
265                 else\r
266                         GetDateFormat(locale, DATE_LONGDATE, &systime, NULL, datebuf, MAX_STRING_LENGTH);\r
267                 GetTimeFormat(locale, 0, &systime, NULL, timebuf, MAX_STRING_LENGTH);\r
268                 *buf = '\0';\r
269                 _tcsncat_s(buf, buflen, timebuf, MAX_STRING_LENGTH-1);\r
270                 _tcsncat_s(buf, buflen, _T(", "), MAX_STRING_LENGTH-1);\r
271                 _tcsncat_s(buf, buflen, datebuf, MAX_STRING_LENGTH-1);\r
272         }\r
273 }\r
274 \r
275 void CSVNPropertyPage::InitWorkfileView()\r
276 {\r
277         SVNStatus svn = SVNStatus();\r
278         TCHAR tbuf[MAX_STRING_LENGTH];\r
279         if (filenames.size() == 1)\r
280         {\r
281                 if (svn.GetStatus(CTSVNPath(filenames.front().c_str()))>(-2))\r
282                 {\r
283                         TCHAR buf[MAX_STRING_LENGTH];\r
284                         __time64_t      time;\r
285                         if (svn.status->entry != NULL)\r
286                         {\r
287                                 LoadLangDll();\r
288                                 if (svn.status->text_status == svn_wc_status_added)\r
289                                 {\r
290                                         // disable the "show log" button for added files\r
291                                         HWND showloghwnd = GetDlgItem(m_hwnd, IDC_SHOWLOG);\r
292                                         if (GetFocus() == showloghwnd)\r
293                                                 ::SendMessage(m_hwnd, WM_NEXTDLGCTL, 0, FALSE);\r
294                                         ::EnableWindow(showloghwnd, FALSE);\r
295                                 }\r
296                                 else\r
297                                 {\r
298                                         _stprintf_s(buf, MAX_STRING_LENGTH, _T("%d"), svn.status->entry->revision);\r
299                                         SetDlgItemText(m_hwnd, IDC_REVISION, buf);\r
300                                 }\r
301                                 if (svn.status->entry->url)\r
302                                 {\r
303                                         size_t len = strlen(svn.status->entry->url);\r
304                                         char * unescapedurl = new char[len+1];\r
305                                         strcpy_s(unescapedurl, len+1, svn.status->entry->url);\r
306                                         CPathUtils::Unescape(unescapedurl);\r
307                                         SetDlgItemText(m_hwnd, IDC_REPOURL, UTF8ToWide(unescapedurl).c_str());\r
308                                         if (strcmp(unescapedurl, svn.status->entry->url))\r
309                                         {\r
310                                                 ShowWindow(GetDlgItem(m_hwnd, IDC_ESCAPEDURLLABEL), SW_SHOW);\r
311                                                 ShowWindow(GetDlgItem(m_hwnd, IDC_REPOURLUNESCAPED), SW_SHOW);\r
312                                                 SetDlgItemText(m_hwnd, IDC_REPOURLUNESCAPED, UTF8ToWide(svn.status->entry->url).c_str());\r
313                                         }\r
314                                         else\r
315                                         {\r
316                                                 ShowWindow(GetDlgItem(m_hwnd, IDC_ESCAPEDURLLABEL), SW_HIDE);\r
317                                                 ShowWindow(GetDlgItem(m_hwnd, IDC_REPOURLUNESCAPED), SW_HIDE);\r
318                                         }\r
319                                         delete [] unescapedurl;\r
320                                 }\r
321                                 else\r
322                                 {\r
323                                         ShowWindow(GetDlgItem(m_hwnd, IDC_ESCAPEDURLLABEL), SW_HIDE);\r
324                                         ShowWindow(GetDlgItem(m_hwnd, IDC_REPOURLUNESCAPED), SW_HIDE);\r
325                                 }\r
326                                 if (svn.status->text_status != svn_wc_status_added)\r
327                                 {\r
328                                         _stprintf_s(buf, MAX_STRING_LENGTH, _T("%d"), svn.status->entry->cmt_rev);\r
329                                         SetDlgItemText(m_hwnd, IDC_CREVISION, buf);\r
330                                         time = (__time64_t)svn.status->entry->cmt_date/1000000L;\r
331                                         Time64ToTimeString(time, buf, MAX_STRING_LENGTH);\r
332                                         SetDlgItemText(m_hwnd, IDC_CDATE, buf);\r
333                                 }\r
334                                 if (svn.status->entry->cmt_author)\r
335                                         SetDlgItemText(m_hwnd, IDC_AUTHOR, UTF8ToWide(svn.status->entry->cmt_author).c_str());\r
336                                 SVNStatus::GetStatusString(g_hResInst, svn.status->text_status, buf, sizeof(buf)/sizeof(TCHAR), (WORD)CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)));\r
337                                 SetDlgItemText(m_hwnd, IDC_TEXTSTATUS, buf);\r
338                                 SVNStatus::GetStatusString(g_hResInst, svn.status->prop_status, buf, sizeof(buf)/sizeof(TCHAR), (WORD)CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)));\r
339                                 SetDlgItemText(m_hwnd, IDC_PROPSTATUS, buf);\r
340                                 time = (__time64_t)svn.status->entry->text_time/1000000L;\r
341                                 Time64ToTimeString(time, buf, MAX_STRING_LENGTH);\r
342                                 SetDlgItemText(m_hwnd, IDC_TEXTDATE, buf);\r
343                                 time = (__time64_t)svn.status->entry->prop_time/1000000L;\r
344                                 Time64ToTimeString(time, buf, MAX_STRING_LENGTH);\r
345                                 SetDlgItemText(m_hwnd, IDC_PROPDATE, buf);\r
346 \r
347                                 if (svn.status->entry->lock_owner)\r
348                                         SetDlgItemText(m_hwnd, IDC_LOCKOWNER, UTF8ToWide(svn.status->entry->lock_owner).c_str());\r
349                                 time = (__time64_t)svn.status->entry->lock_creation_date/1000000L;\r
350                                 Time64ToTimeString(time, buf, MAX_STRING_LENGTH);\r
351                                 SetDlgItemText(m_hwnd, IDC_LOCKDATE, buf);\r
352         \r
353                                 if (svn.status->entry->uuid)\r
354                                         SetDlgItemText(m_hwnd, IDC_REPOUUID, UTF8ToWide(svn.status->entry->uuid).c_str());\r
355                                 if (svn.status->entry->changelist)\r
356                                         SetDlgItemText(m_hwnd, IDC_CHANGELIST, UTF8ToWide(svn.status->entry->changelist).c_str());\r
357                                 SVNStatus::GetDepthString(g_hResInst, svn.status->entry->depth, buf, sizeof(buf)/sizeof(TCHAR), (WORD)CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)));\r
358                                 SetDlgItemText(m_hwnd, IDC_DEPTHEDIT, buf);\r
359 \r
360                                 if (svn.status->entry->checksum)\r
361                                         SetDlgItemText(m_hwnd, IDC_CHECKSUM, UTF8ToWide(svn.status->entry->checksum).c_str());\r
362 \r
363                                 if (svn.status->locked)\r
364                                         MAKESTRING(IDS_YES);\r
365                                 else\r
366                                         MAKESTRING(IDS_NO);\r
367                                 SetDlgItemText(m_hwnd, IDC_LOCKED, stringtablebuffer);\r
368 \r
369                                 if (svn.status->copied)\r
370                                         MAKESTRING(IDS_YES);\r
371                                 else\r
372                                         MAKESTRING(IDS_NO);\r
373                                 SetDlgItemText(m_hwnd, IDC_COPIED, stringtablebuffer);\r
374 \r
375                                 if (svn.status->switched)\r
376                                         MAKESTRING(IDS_YES);\r
377                                 else\r
378                                         MAKESTRING(IDS_NO);\r
379                                 SetDlgItemText(m_hwnd, IDC_SWITCHED, stringtablebuffer);\r
380                         } // if (svn.status->entry != NULL)\r
381                 } // if (svn.GetStatus(CTSVNPath(filenames.front().c_str()))>(-2))\r
382         } // if (filenames.size() == 1) \r
383         else if (filenames.size() != 0)\r
384         {\r
385                 //deactivate the show log button\r
386                 HWND logwnd = GetDlgItem(m_hwnd, IDC_SHOWLOG);\r
387                 if (GetFocus() == logwnd)\r
388                         ::SendMessage(m_hwnd, WM_NEXTDLGCTL, 0, FALSE);\r
389                 ::EnableWindow(logwnd, FALSE);\r
390                 //get the handle of the list view\r
391                 if (svn.GetStatus(CTSVNPath(filenames.front().c_str()))>(-2))\r
392                 {\r
393                         if (svn.status->entry != NULL)\r
394                         {\r
395                                 LoadLangDll();\r
396                                 if (svn.status->entry->url)\r
397                                 {\r
398                                         CPathUtils::Unescape((char*)svn.status->entry->url);\r
399                                         _tcsncpy_s(tbuf, MAX_STRING_LENGTH, UTF8ToWide(svn.status->entry->url).c_str(), 4095);\r
400                                         TCHAR * ptr = _tcsrchr(tbuf, '/');\r
401                                         if (ptr != 0)\r
402                                         {\r
403                                                 *ptr = 0;\r
404                                         }\r
405                                         SetDlgItemText(m_hwnd, IDC_REPOURL, tbuf);\r
406                                 }\r
407                                 SetDlgItemText(m_hwnd, IDC_LOCKED, _T(""));\r
408                                 SetDlgItemText(m_hwnd, IDC_COPIED, _T(""));\r
409                                 SetDlgItemText(m_hwnd, IDC_SWITCHED, _T(""));\r
410 \r
411                                 SetDlgItemText(m_hwnd, IDC_DEPTHEDIT, _T(""));\r
412                                 SetDlgItemText(m_hwnd, IDC_CHECKSUM, _T(""));\r
413                                 SetDlgItemText(m_hwnd, IDC_REPOUUID, _T(""));\r
414 \r
415                                 ShowWindow(GetDlgItem(m_hwnd, IDC_ESCAPEDURLLABEL), SW_HIDE);\r
416                                 ShowWindow(GetDlgItem(m_hwnd, IDC_REPOURLUNESCAPED), SW_HIDE);\r
417                         }\r
418                 }\r
419         } \r
420 }\r
421 \r
422 \r