1 // TortoiseSVN - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2011, 2015 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "UnicodeUtils.h"
21 #include "StringUtils.h"
22 #include "ClipboardHelper.h"
23 #include "SmartHandle.h"
25 int strwildcmp(const char *wild
, const char *string
)
27 const char *cp
= NULL
;
28 const char *mp
= NULL
;
29 while ((*string
) && (*wild
!= '*'))
31 if ((*wild
!= *string
) && (*wild
!= '?'))
49 else if ((*wild
== *string
) || (*wild
== '?'))
68 int wcswildcmp(const wchar_t *wild
, const wchar_t *string
)
70 const wchar_t *cp
= NULL
;
71 const wchar_t *mp
= NULL
;
72 while ((*string
) && (*wild
!= '*'))
74 if ((*wild
!= *string
) && (*wild
!= '?'))
92 else if ((*wild
== *string
) || (*wild
== '?'))
113 void CStringUtils::RemoveAccelerators(CString
& text
)
116 while ((pos
=text
.Find('&',pos
))>=0)
118 if (text
.GetLength() > (pos
-1))
120 if (text
.GetAt(pos
+1)!=' ')
127 bool CStringUtils::WriteAsciiStringToClipboard(const CStringA
& sClipdata
, LCID lcid
, HWND hOwningWnd
)
129 CClipboardHelper clipboardHelper
;
130 if (clipboardHelper
.Open(hOwningWnd
))
133 HGLOBAL hClipboardData
= CClipboardHelper::GlobalAlloc(sClipdata
.GetLength()+1);
136 char* pchData
= (char*)GlobalLock(hClipboardData
);
139 strcpy_s(pchData
, sClipdata
.GetLength()+1, (LPCSTR
)sClipdata
);
140 GlobalUnlock(hClipboardData
);
141 if (SetClipboardData(CF_TEXT
, hClipboardData
))
143 HANDLE hlocmem
= CClipboardHelper::GlobalAlloc(sizeof(LCID
));
146 PLCID plcid
= (PLCID
)GlobalLock(hlocmem
);
150 SetClipboardData(CF_LOCALE
, static_cast<HANDLE
>(plcid
));
152 GlobalUnlock(hlocmem
);
162 bool CStringUtils::WriteAsciiStringToClipboard(const CStringW
& sClipdata
, HWND hOwningWnd
)
164 CClipboardHelper clipboardHelper
;
165 if (clipboardHelper
.Open(hOwningWnd
))
168 HGLOBAL hClipboardData
= CClipboardHelper::GlobalAlloc((sClipdata
.GetLength()+1)*sizeof(WCHAR
));
171 WCHAR
* pchData
= (WCHAR
*)GlobalLock(hClipboardData
);
174 _tcscpy_s(pchData
, sClipdata
.GetLength()+1, (LPCWSTR
)sClipdata
);
175 GlobalUnlock(hClipboardData
);
176 if (SetClipboardData(CF_UNICODETEXT
, hClipboardData
))
178 // no need to also set CF_TEXT : the OS does this
188 bool CStringUtils::WriteDiffToClipboard(const CStringA
& sClipdata
, HWND hOwningWnd
)
190 UINT cFormat
= RegisterClipboardFormat(_T("TGIT_UNIFIEDDIFF"));
193 CClipboardHelper clipboardHelper
;
194 if (clipboardHelper
.Open(hOwningWnd
))
197 HGLOBAL hClipboardData
= CClipboardHelper::GlobalAlloc(sClipdata
.GetLength()+1);
200 char* pchData
= (char*)GlobalLock(hClipboardData
);
203 strcpy_s(pchData
, sClipdata
.GetLength()+1, (LPCSTR
)sClipdata
);
204 GlobalUnlock(hClipboardData
);
205 if (SetClipboardData(cFormat
,hClipboardData
)==NULL
)
209 if (SetClipboardData(CF_TEXT
, hClipboardData
) == NULL
)
213 CString sClipdataW
= CUnicodeUtils::GetUnicode(sClipdata
);
214 auto hClipboardDataW
= CClipboardHelper::GlobalAlloc(sClipdataW
.GetLength()*sizeof(wchar_t) + 1);
217 wchar_t* pchDataW
= (wchar_t*)GlobalLock(hClipboardDataW
);
220 wcscpy_s(pchDataW
, sClipdataW
.GetLength() + 1, (LPCWSTR
)sClipdataW
);
221 GlobalUnlock(hClipboardDataW
);
222 if (SetClipboardData(CF_UNICODETEXT
, hClipboardDataW
))
234 bool CStringUtils::ReadStringFromTextFile(const CString
& path
, CString
& text
)
236 if (!PathFileExists(path
))
241 // w/o typeBinary for some files \r gets dropped
242 if (!file
.Open(path
, CFile::typeBinary
| CFile::modeRead
| CFile::shareDenyWrite
))
245 CStringA filecontent
;
246 UINT filelength
= (UINT
)file
.GetLength();
247 int bytesread
= (int)file
.Read(filecontent
.GetBuffer(filelength
), filelength
);
248 filecontent
.ReleaseBuffer(bytesread
);
249 text
= CUnicodeUtils::GetUnicode(filecontent
);
252 catch (CFileException
* pE
)
260 #endif // #ifdef _MFC_VER
262 #if defined(CSTRING_AVAILABLE) || defined(_MFC_VER)
263 BOOL
CStringUtils::WildCardMatch(const CString
& wildcard
, const CString
& string
)
265 return _tcswildcmp(wildcard
, string
);
268 CString
CStringUtils::LinesWrap(const CString
& longstring
, int limit
/* = 80 */, bool bCompactPaths
/* = true */)
271 if ((longstring
.GetLength() < limit
) || (limit
== 0))
272 return longstring
; // no wrapping needed.
273 // now start breaking the string into lines
278 while ((linepos
= longstring
.Find('\n', linepos
)) >= 0)
280 temp
= longstring
.Mid(lineposold
, linepos
-lineposold
);
281 if ((linepos
+1)<longstring
.GetLength())
285 lineposold
= linepos
;
286 if (!retString
.IsEmpty())
287 retString
+= _T("\n");
288 retString
+= WordWrap(temp
, limit
, bCompactPaths
, false, 4);
290 temp
= longstring
.Mid(lineposold
);
292 retString
+= _T("\n");
293 retString
+= WordWrap(temp
, limit
, bCompactPaths
, false, 4);
298 CString
CStringUtils::WordWrap(const CString
& longstring
, int limit
, bool bCompactPaths
, bool bForceWrap
, int tabSize
)
300 int nLength
= longstring
.GetLength();
309 for (int i
= 0; i
< nLength
; ++i
)
311 if (i
-nLineStart
+tabOffset
>= limit
)
313 if (nLineEnd
== nLineStart
)
319 while ((i
< nLength
) && (longstring
[i
] != ' ') && (longstring
[i
] != '\t'))
326 CString longline
= longstring
.Mid(nLineStart
, nLineEnd
-nLineStart
).Left(MAX_PATH
-1);
327 if ((bCompactPaths
)&&(longline
.GetLength() < MAX_PATH
))
329 if (((!PathIsFileSpec(longline
))&&longline
.Find(':')<3)||(PathIsURL(longline
)))
331 TCHAR buf
[MAX_PATH
] = {0};
332 PathCompactPathEx(buf
, longline
, limit
+1, 0);
336 retString
+= longline
;
339 retString
+= longstring
.Mid(nLineStart
, nLineEnd
-nLineStart
);
342 nLineStart
= nLineEnd
;
344 if (longstring
[i
] == ' ')
346 if (longstring
[i
] == '\t')
348 tabOffset
+= (tabSize
- i
% tabSize
);
354 CString longline
= longstring
.Mid(nLineStart
).Left(MAX_PATH
-1);
355 if ((bCompactPaths
)&&(longline
.GetLength() < MAX_PATH
))
357 if (((!PathIsFileSpec(longline
))&&longline
.Find(':')<3)||(PathIsURL(longline
)))
359 TCHAR buf
[MAX_PATH
] = {0};
360 PathCompactPathEx(buf
, longline
, limit
+1, 0);
364 retString
+= longline
;
367 retString
+= longstring
.Mid(nLineStart
);
371 int CStringUtils::GetMatchingLength (const CString
& lhs
, const CString
& rhs
)
373 int lhsLength
= lhs
.GetLength();
374 int rhsLength
= rhs
.GetLength();
375 int maxResult
= min (lhsLength
, rhsLength
);
380 for (int i
= 0; i
< maxResult
; ++i
)
381 if (pLhs
[i
] != pRhs
[i
])
387 int CStringUtils::FastCompareNoCase (const CStringW
& lhs
, const CStringW
& rhs
)
389 // attempt latin-only comparison
391 INT_PTR count
= min (lhs
.GetLength(), rhs
.GetLength()+1);
392 const wchar_t* left
= lhs
;
393 const wchar_t* right
= rhs
;
394 for (const wchar_t* last
= left
+ count
+1; left
< last
; ++left
, ++right
)
396 int leftChar
= *left
;
397 int rightChar
= *right
;
399 int diff
= leftChar
- rightChar
;
402 // case-sensitive comparison found a difference
404 if ((leftChar
| rightChar
) >= 0x80)
406 // non-latin char -> fall back to CRT code
407 // (full comparison required as we might have
408 // skipped special chars / UTF plane selectors)
410 return _wcsicmp (lhs
, rhs
);
413 // normalize to lower case
415 if ((leftChar
>= 'A') && (leftChar
<= 'Z'))
416 leftChar
+= 'a' - 'A';
417 if ((rightChar
>= 'A') && (rightChar
<= 'Z'))
418 rightChar
+= 'a' - 'A';
422 diff
= leftChar
- rightChar
;
428 // must be equal (both ended with a 0)
432 #endif // #if defined(CSTRING_AVAILABLE) || defined(_MFC_VER)
434 bool CStringUtils::WriteStringToTextFile(const std::wstring
& path
, const std::wstring
& text
, bool bUTF8
/* = true */)
437 CAutoFile hFile
= CreateFile(path
.c_str(), GENERIC_WRITE
, FILE_SHARE_DELETE
, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
443 std::string buf
= CUnicodeUtils::StdGetUTF8(text
);
444 if (!WriteFile(hFile
, buf
.c_str(), (DWORD
)buf
.length(), &dwWritten
, NULL
))
451 if (!WriteFile(hFile
, text
.c_str(), (DWORD
)text
.length(), &dwWritten
, NULL
))
459 inline static void PipeToNull(TCHAR
* ptr
)
465 void CStringUtils::PipesToNulls(TCHAR
* buffer
, size_t length
)
467 TCHAR
* ptr
= buffer
+ length
;
468 while (ptr
!= buffer
)
475 void CStringUtils::PipesToNulls(TCHAR
* buffer
)