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("TSVN_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
))
219 bool CStringUtils::ReadStringFromTextFile(const CString
& path
, CString
& text
)
221 if (!PathFileExists(path
))
226 // w/o typeBinary for some files \r gets dropped
227 if (!file
.Open(path
, CFile::typeBinary
| CFile::modeRead
| CFile::shareDenyWrite
))
230 CStringA filecontent
;
231 UINT filelength
= (UINT
)file
.GetLength();
232 int bytesread
= (int)file
.Read(filecontent
.GetBuffer(filelength
), filelength
);
233 filecontent
.ReleaseBuffer(bytesread
);
234 text
= CUnicodeUtils::GetUnicode(filecontent
);
237 catch (CFileException
* pE
)
245 #endif // #ifdef _MFC_VER
247 #if defined(CSTRING_AVAILABLE) || defined(_MFC_VER)
248 BOOL
CStringUtils::WildCardMatch(const CString
& wildcard
, const CString
& string
)
250 return _tcswildcmp(wildcard
, string
);
253 CString
CStringUtils::LinesWrap(const CString
& longstring
, int limit
/* = 80 */, bool bCompactPaths
/* = true */)
256 if ((longstring
.GetLength() < limit
) || (limit
== 0))
257 return longstring
; // no wrapping needed.
258 // now start breaking the string into lines
263 while ((linepos
= longstring
.Find('\n', linepos
)) >= 0)
265 temp
= longstring
.Mid(lineposold
, linepos
-lineposold
);
266 if ((linepos
+1)<longstring
.GetLength())
270 lineposold
= linepos
;
271 if (!retString
.IsEmpty())
272 retString
+= _T("\n");
273 retString
+= WordWrap(temp
, limit
, bCompactPaths
, false, 4);
275 temp
= longstring
.Mid(lineposold
);
277 retString
+= _T("\n");
278 retString
+= WordWrap(temp
, limit
, bCompactPaths
, false, 4);
283 CString
CStringUtils::WordWrap(const CString
& longstring
, int limit
, bool bCompactPaths
, bool bForceWrap
, int tabSize
)
285 int nLength
= longstring
.GetLength();
294 for (int i
= 0; i
< nLength
; ++i
)
296 if (i
-nLineStart
+tabOffset
>= limit
)
298 if (nLineEnd
== nLineStart
)
304 while ((i
< nLength
) && (longstring
[i
] != ' ') && (longstring
[i
] != '\t'))
311 CString longline
= longstring
.Mid(nLineStart
, nLineEnd
-nLineStart
).Left(MAX_PATH
-1);
312 if ((bCompactPaths
)&&(longline
.GetLength() < MAX_PATH
))
314 if (((!PathIsFileSpec(longline
))&&longline
.Find(':')<3)||(PathIsURL(longline
)))
316 TCHAR buf
[MAX_PATH
] = {0};
317 PathCompactPathEx(buf
, longline
, limit
+1, 0);
321 retString
+= longline
;
324 retString
+= longstring
.Mid(nLineStart
, nLineEnd
-nLineStart
);
327 nLineStart
= nLineEnd
;
329 if (longstring
[i
] == ' ')
331 if (longstring
[i
] == '\t')
333 tabOffset
+= (tabSize
- i
% tabSize
);
339 CString longline
= longstring
.Mid(nLineStart
).Left(MAX_PATH
-1);
340 if ((bCompactPaths
)&&(longline
.GetLength() < MAX_PATH
))
342 if (((!PathIsFileSpec(longline
))&&longline
.Find(':')<3)||(PathIsURL(longline
)))
344 TCHAR buf
[MAX_PATH
] = {0};
345 PathCompactPathEx(buf
, longline
, limit
+1, 0);
349 retString
+= longline
;
352 retString
+= longstring
.Mid(nLineStart
);
356 int CStringUtils::GetMatchingLength (const CString
& lhs
, const CString
& rhs
)
358 int lhsLength
= lhs
.GetLength();
359 int rhsLength
= rhs
.GetLength();
360 int maxResult
= min (lhsLength
, rhsLength
);
365 for (int i
= 0; i
< maxResult
; ++i
)
366 if (pLhs
[i
] != pRhs
[i
])
372 int CStringUtils::FastCompareNoCase (const CStringW
& lhs
, const CStringW
& rhs
)
374 // attempt latin-only comparison
376 INT_PTR count
= min (lhs
.GetLength(), rhs
.GetLength()+1);
377 const wchar_t* left
= lhs
;
378 const wchar_t* right
= rhs
;
379 for (const wchar_t* last
= left
+ count
+1; left
< last
; ++left
, ++right
)
381 int leftChar
= *left
;
382 int rightChar
= *right
;
384 int diff
= leftChar
- rightChar
;
387 // case-sensitive comparison found a difference
389 if ((leftChar
| rightChar
) >= 0x80)
391 // non-latin char -> fall back to CRT code
392 // (full comparison required as we might have
393 // skipped special chars / UTF plane selectors)
395 return _wcsicmp (lhs
, rhs
);
398 // normalize to lower case
400 if ((leftChar
>= 'A') && (leftChar
<= 'Z'))
401 leftChar
+= 'a' - 'A';
402 if ((rightChar
>= 'A') && (rightChar
<= 'Z'))
403 rightChar
+= 'a' - 'A';
407 diff
= leftChar
- rightChar
;
413 // must be equal (both ended with a 0)
417 #endif // #if defined(CSTRING_AVAILABLE) || defined(_MFC_VER)
419 bool CStringUtils::WriteStringToTextFile(const std::wstring
& path
, const std::wstring
& text
, bool bUTF8
/* = true */)
422 CAutoFile hFile
= CreateFile(path
.c_str(), GENERIC_WRITE
, FILE_SHARE_DELETE
, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
428 std::string buf
= CUnicodeUtils::StdGetUTF8(text
);
429 if (!WriteFile(hFile
, buf
.c_str(), (DWORD
)buf
.length(), &dwWritten
, NULL
))
436 if (!WriteFile(hFile
, text
.c_str(), (DWORD
)text
.length(), &dwWritten
, NULL
))
444 inline static void PipeToNull(TCHAR
* ptr
)
450 void CStringUtils::PipesToNulls(TCHAR
* buffer
, size_t length
)
452 TCHAR
* ptr
= buffer
+ length
;
453 while (ptr
!= buffer
)
460 void CStringUtils::PipesToNulls(TCHAR
* buffer
)