Help minor upd after #1700
[far2l.git] / WinPort / src / APIStringMap.cpp
blob7b0cd1c96ac9be72b278c88e203a145c38db6e38
1 #include <set>
2 #include <string>
3 #include <locale>
4 #include <algorithm>
5 #include <iostream>
6 #include <fstream>
7 #include <mutex>
8 #include <vector>
10 #include <cwctype>
12 #include "WinCompat.h"
13 #include "WinPort.h"
14 #include "wineguts.h"
15 #include "PathHelpers.h"
17 /*************************************************************************
18 * LCMapStringEx (KERNEL32.@)
20 * Map characters in a locale sensitive string.
22 * PARAMS
23 * name [I] Locale name for the conversion.
24 * flags [I] Flags controlling the mapping (LCMAP_ constants from "winnls.h")
25 * src [I] String to map
26 * srclen [I] Length of src in chars, or -1 if src is NUL terminated
27 * dst [O] Destination for mapped string
28 * dstlen [I] Length of dst in characters
29 * version [I] reserved, must be NULL
30 * reserved [I] reserved, must be NULL
31 * lparam [I] reserved, must be 0
33 * RETURNS
34 * Success: The length of the mapped string in dst, including the NUL terminator.
35 * Failure: 0. Use GetLastError() to determine the cause.
37 WINPORT_DECL(LCMapStringEx, INT, (LPCWSTR name, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen,
38 LPNLSVERSIONINFO version, LPVOID reserved, LPARAM lparam))
40 LPWSTR dst_ptr;
43 if (!src || !srclen || dstlen < 0)
45 WINPORT(SetLastError)(ERROR_INVALID_PARAMETER);
46 return 0;
49 /* mutually exclusive flags */
50 if ((flags & (LCMAP_LOWERCASE | LCMAP_UPPERCASE)) == (LCMAP_LOWERCASE | LCMAP_UPPERCASE) ||
51 (flags & (LCMAP_HIRAGANA | LCMAP_KATAKANA)) == (LCMAP_HIRAGANA | LCMAP_KATAKANA) ||
52 (flags & (LCMAP_HALFWIDTH | LCMAP_FULLWIDTH)) == (LCMAP_HALFWIDTH | LCMAP_FULLWIDTH) ||
53 (flags & (LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE)) == (LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE))
55 WINPORT(SetLastError)(ERROR_INVALID_FLAGS);
56 return 0;
59 if (!dstlen) dst = NULL;
61 if (flags & LCMAP_SORTKEY)
63 INT ret;
64 if (src == dst)
66 WINPORT(SetLastError)(ERROR_INVALID_FLAGS);
67 return 0;
70 if (srclen < 0) srclen = wcslen(src);
72 ret = wine_get_sortkey(flags, src, srclen, (char *)dst, dstlen);
73 if (ret == 0)
74 WINPORT(SetLastError)(ERROR_INSUFFICIENT_BUFFER);
75 else
76 ret++;
77 return ret;
80 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
81 if (flags & SORT_STRINGSORT)
83 WINPORT(SetLastError)(ERROR_INVALID_FLAGS);
84 return 0;
87 if (srclen < 0) srclen = wcslen(src) + 1;
90 if (!dst) /* return required string length */
92 INT len;
94 for (len = 0; srclen; src++, srclen--)
96 WCHAR wch = *src;
97 /* tests show that win2k just ignores NORM_IGNORENONSPACE,
98 * and skips white space and punctuation characters for
99 * NORM_IGNORESYMBOLS.
101 if ((flags & NORM_IGNORESYMBOLS) && (iswspace(wch) || iswpunct(wch)))
102 continue;
103 len++;
105 return len;
108 if (flags & LCMAP_UPPERCASE)
110 for (dst_ptr = dst; srclen && dstlen; src++, srclen--)
112 WCHAR wch = *src;
113 if ((flags & NORM_IGNORESYMBOLS) && (iswspace(wch) || iswpunct(wch)))
114 continue;
115 *dst_ptr++ = towupper(wch);
116 dstlen--;
119 else if (flags & LCMAP_LOWERCASE)
121 for (dst_ptr = dst; srclen && dstlen; src++, srclen--)
123 WCHAR wch = *src;
124 if ((flags & NORM_IGNORESYMBOLS) && (iswspace(wch) || iswpunct(wch)))
125 continue;
126 *dst_ptr++ = towlower(wch);
127 dstlen--;
130 else
132 if (src == dst)
134 WINPORT(SetLastError)(ERROR_INVALID_FLAGS);
135 return 0;
137 for (dst_ptr = dst; srclen && dstlen; src++, srclen--)
139 WCHAR wch = *src;
140 if ((flags & NORM_IGNORESYMBOLS) && (iswspace(wch) || iswpunct(wch)))
141 continue;
142 *dst_ptr++ = wch;
143 dstlen--;
147 if (srclen)
149 WINPORT(SetLastError)(ERROR_INSUFFICIENT_BUFFER);
150 return 0;
153 return dst_ptr - dst;
157 /******************************************************************************
158 * CompareStringEx (KERNEL32.@)
160 INT WINAPI WINPORT(CompareStringEx)(LPCWSTR locale, DWORD flags, LPCWSTR str1, INT len1,
161 LPCWSTR str2, INT len2, LPNLSVERSIONINFO version, LPVOID reserved, LPARAM lParam)
163 DWORD supported_flags = NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|SORT_STRINGSORT
164 |NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|LOCALE_USE_CP_ACP;
165 DWORD semistub_flags = NORM_LINGUISTIC_CASING|LINGUISTIC_IGNORECASE|0x10000000;
166 /* 0x10000000 is related to diacritics in Arabic, Japanese, and Hebrew */
167 INT ret;
169 if (!str1 || !str2)
171 WINPORT(SetLastError)(ERROR_INVALID_PARAMETER);
172 return 0;
175 if (flags & ~(supported_flags|semistub_flags))
177 WINPORT(SetLastError)(ERROR_INVALID_FLAGS);
178 return 0;
181 if (len1 < 0) len1 = wcslen(str1);
182 if (len2 < 0) len2 = wcslen(str2);
184 ret = wine_compare_string(flags, str1, len1, str2, len2);
186 if (ret) /* need to translate result */
187 return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
188 return CSTR_EQUAL;
191 WINPORT_DECL(CompareStringA, int, ( LCID Locale, DWORD dwCmpFlags,
192 LPCSTR lpString1, int cchCount1, LPCSTR lpString2, int cchCount2))
194 if (cchCount1==-1) cchCount1 = lpString1 ? strlen(lpString1) : 0;
195 if (cchCount2==-1) cchCount2 = lpString2 ? strlen(lpString2) : 0;
196 std::vector<WCHAR> wstr1(cchCount1 * 2 + 1);
197 std::vector<WCHAR> wstr2(cchCount2 * 2 + 1);
198 int l1 = WINPORT(MultiByteToWideChar)(CP_ACP, 0, lpString1, cchCount1, &wstr1[0], wstr1.size() - 1 );
199 int l2 = WINPORT(MultiByteToWideChar)(CP_ACP, 0, lpString2, cchCount2, &wstr2[0], wstr2.size() - 1);
200 return WINPORT(CompareString)( Locale, dwCmpFlags, &wstr1[0], l1, &wstr2[0], l2);
203 //////////////////////////
204 extern "C" {
205 WINPORT_DECL(LCMapString, INT, (LCID lcid, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen))
207 return WINPORT(LCMapStringEx)(NULL, flags, src, srclen, dst, dstlen, NULL, NULL, 0);
211 WINPORT_DECL(CharLowerBuff, DWORD , ( LPWSTR str, DWORD len ))
213 if (!str) return 0; /* YES */
214 return WINPORT(LCMapString)( LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, str, len, str, len );
217 WINPORT_DECL(CharUpperBuff, DWORD , ( LPWSTR str, DWORD len ))
219 if (!str) return 0; /* YES */
220 return WINPORT(LCMapString)( LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, str, len, str, len );
223 WINPORT_DECL(IsCharLower, BOOL, (WCHAR ch))
225 return iswlower(ch);
228 WINPORT_DECL(IsCharUpper, BOOL, (WCHAR ch))
230 return iswupper(ch);
233 WINPORT_DECL(IsCharAlphaNumeric, BOOL, (WCHAR ch))
235 return iswalnum(ch);
238 WINPORT_DECL(IsCharAlpha, BOOL, (WCHAR ch))
240 return iswalpha(ch);
244 WINPORT_DECL(CompareString, INT, (LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2))
246 return WINPORT(CompareStringEx)(NULL, flags, str1, len1, str2, len2, NULL, NULL, 0);
249 WINPORT_DECL(CharLower, LPWSTR, (LPWSTR str))
251 if (!IS_INTRESOURCE( str ))
253 WINPORT(CharLowerBuff)( str, wcslen( str ));
254 return str;
256 else
258 WCHAR ch = LOWORD( str );
259 WINPORT(CharLowerBuff)( &ch, 1 );
260 return (LPWSTR)(UINT_PTR)ch;
264 WINPORT_DECL(CharUpper, LPWSTR, (LPWSTR str))
266 if (!IS_INTRESOURCE( str ))
268 WINPORT(CharUpperBuff)( str, wcslen( str ));
269 return str;
271 else
273 WCHAR ch = LOWORD( str );
274 WINPORT(CharUpperBuff)( &ch, 1 );
275 return (LPWSTR)(UINT_PTR)ch;