xref: /haiku/src/system/libroot/add-ons/icu/ICUTimeData.cpp (revision 3aeed6607cd07762c0e709633c012b3a632dbad9)
1560b10ffSOliver Tappe /*
2c894d186SOliver Tappe  * Copyright 2010-2011, Oliver Tappe, zooey@hirschkaefer.de.
3560b10ffSOliver Tappe  * Distributed under the terms of the MIT License.
4560b10ffSOliver Tappe  */
5560b10ffSOliver Tappe 
6560b10ffSOliver Tappe 
7560b10ffSOliver Tappe #include "ICUTimeData.h"
8560b10ffSOliver Tappe 
9560b10ffSOliver Tappe #include <langinfo.h>
10*3aeed660SJérôme Duval #include <string.h>
11560b10ffSOliver Tappe #include <strings.h>
12560b10ffSOliver Tappe 
13560b10ffSOliver Tappe #include <unicode/dtfmtsym.h>
14560b10ffSOliver Tappe #include <unicode/gregocal.h>
15560b10ffSOliver Tappe #include <unicode/smpdtfmt.h>
16560b10ffSOliver Tappe 
17560b10ffSOliver Tappe #include <AutoDeleter.h>
18560b10ffSOliver Tappe 
191e1278f4SOliver Tappe #include "ICUMessagesData.h"
20560b10ffSOliver Tappe 
21560b10ffSOliver Tappe namespace BPrivate {
2225dc253dSIngo Weinhold namespace Libroot {
23560b10ffSOliver Tappe 
24560b10ffSOliver Tappe 
251e1278f4SOliver Tappe ICUTimeData::ICUTimeData(pthread_key_t tlsKey, struct lc_time_t& lcTimeInfo,
261e1278f4SOliver Tappe 	const ICUMessagesData& messagesData)
27560b10ffSOliver Tappe 	:
28bf5ff480SOliver Tappe 	inherited(tlsKey),
29560b10ffSOliver Tappe 	fLCTimeInfo(lcTimeInfo),
301e1278f4SOliver Tappe 	fDataBridge(NULL),
311e1278f4SOliver Tappe 	fMessagesData(messagesData)
32560b10ffSOliver Tappe {
33560b10ffSOliver Tappe 	for (int i = 0; i < 12; ++i) {
34560b10ffSOliver Tappe 		fLCTimeInfo.mon[i] = fMon[i];
35560b10ffSOliver Tappe 		fLCTimeInfo.month[i] = fMonth[i];
36560b10ffSOliver Tappe 		fLCTimeInfo.alt_month[i] = fAltMonth[i];
37560b10ffSOliver Tappe 	}
38560b10ffSOliver Tappe 	for (int i = 0; i < 7; ++i) {
39560b10ffSOliver Tappe 		fLCTimeInfo.wday[i] = fWday[i];
40560b10ffSOliver Tappe 		fLCTimeInfo.weekday[i] = fWeekday[i];
41560b10ffSOliver Tappe 	}
42560b10ffSOliver Tappe 	fLCTimeInfo.X_fmt = fTimeFormat;
43560b10ffSOliver Tappe 	fLCTimeInfo.x_fmt = fDateFormat;
44560b10ffSOliver Tappe 	fLCTimeInfo.c_fmt = fDateTimeFormat;
45560b10ffSOliver Tappe 	fLCTimeInfo.am = fAm;
46560b10ffSOliver Tappe 	fLCTimeInfo.pm = fPm;
47560b10ffSOliver Tappe 	fLCTimeInfo.date_fmt = fDateTimeZoneFormat;
48560b10ffSOliver Tappe 	fLCTimeInfo.md_order = fMonthDayOrder;
49560b10ffSOliver Tappe 	fLCTimeInfo.ampm_fmt = fAmPmFormat;
50560b10ffSOliver Tappe }
51560b10ffSOliver Tappe 
52560b10ffSOliver Tappe 
53560b10ffSOliver Tappe ICUTimeData::~ICUTimeData()
54560b10ffSOliver Tappe {
55560b10ffSOliver Tappe }
56560b10ffSOliver Tappe 
57560b10ffSOliver Tappe 
58560b10ffSOliver Tappe void
59560b10ffSOliver Tappe ICUTimeData::Initialize(LocaleTimeDataBridge* dataBridge)
60560b10ffSOliver Tappe {
61560b10ffSOliver Tappe 	fDataBridge = dataBridge;
62560b10ffSOliver Tappe }
63560b10ffSOliver Tappe 
64560b10ffSOliver Tappe 
65560b10ffSOliver Tappe status_t
66560b10ffSOliver Tappe ICUTimeData::SetTo(const Locale& locale, const char* posixLocaleName)
67560b10ffSOliver Tappe {
68560b10ffSOliver Tappe 	status_t result = inherited::SetTo(locale, posixLocaleName);
69560b10ffSOliver Tappe 	if (result != B_OK)
70560b10ffSOliver Tappe 		return result;
71560b10ffSOliver Tappe 
72560b10ffSOliver Tappe 	UErrorCode icuStatus = U_ZERO_ERROR;
73ec17468fSOliver Tappe 	DateFormatSymbols formatSymbols(ICULocaleForStrings(), icuStatus);
74560b10ffSOliver Tappe 	if (!U_SUCCESS(icuStatus))
75560b10ffSOliver Tappe 		return B_UNSUPPORTED;
76560b10ffSOliver Tappe 
77560b10ffSOliver Tappe 	int count = 0;
78560b10ffSOliver Tappe 	const UnicodeString* strings = formatSymbols.getShortMonths(count);
79560b10ffSOliver Tappe 	result = _SetLCTimeEntries(strings, fMon[0], sizeof(fMon[0]), count, 12);
80560b10ffSOliver Tappe 
81560b10ffSOliver Tappe 	if (result == B_OK) {
82560b10ffSOliver Tappe 		strings = formatSymbols.getMonths(count);
83560b10ffSOliver Tappe 		result = _SetLCTimeEntries(strings, fMonth[0], sizeof(fMonth[0]), count,
84560b10ffSOliver Tappe 			12);
85560b10ffSOliver Tappe 	}
86560b10ffSOliver Tappe 
87560b10ffSOliver Tappe 	if (result == B_OK) {
88560b10ffSOliver Tappe 		strings = formatSymbols.getShortWeekdays(count);
89560b10ffSOliver Tappe 		if (count == 8 && strings[0].length() == 0) {
90560b10ffSOliver Tappe 			// ICUs weekday arrays are 1-based
91560b10ffSOliver Tappe 			strings++;
92560b10ffSOliver Tappe 			count = 7;
93560b10ffSOliver Tappe 		}
94560b10ffSOliver Tappe 		result
95560b10ffSOliver Tappe 			= _SetLCTimeEntries(strings, fWday[0], sizeof(fWday[0]), count, 7);
96560b10ffSOliver Tappe 	}
97560b10ffSOliver Tappe 
98560b10ffSOliver Tappe 	if (result == B_OK) {
99560b10ffSOliver Tappe 		strings = formatSymbols.getWeekdays(count);
100560b10ffSOliver Tappe 		if (count == 8 && strings[0].length() == 0) {
101560b10ffSOliver Tappe 			// ICUs weekday arrays are 1-based
102560b10ffSOliver Tappe 			strings++;
103560b10ffSOliver Tappe 			count = 7;
104560b10ffSOliver Tappe 		}
105560b10ffSOliver Tappe 		result = _SetLCTimeEntries(strings, fWeekday[0], sizeof(fWeekday[0]),
106560b10ffSOliver Tappe 			count, 7);
107560b10ffSOliver Tappe 	}
108560b10ffSOliver Tappe 
109560b10ffSOliver Tappe 	if (result == B_OK) {
110560b10ffSOliver Tappe 		try {
111560b10ffSOliver Tappe 			DateFormat* format = DateFormat::createTimeInstance(
112560b10ffSOliver Tappe 				DateFormat::kDefault, fLocale);
113560b10ffSOliver Tappe 			result = _SetLCTimePattern(format, fTimeFormat, sizeof(fTimeFormat));
114560b10ffSOliver Tappe 			delete format;
115560b10ffSOliver Tappe 		} catch(...) {
116560b10ffSOliver Tappe 			result = B_NO_MEMORY;
117560b10ffSOliver Tappe 		}
118560b10ffSOliver Tappe 	}
119560b10ffSOliver Tappe 
120560b10ffSOliver Tappe 	if (result == B_OK) {
121560b10ffSOliver Tappe 		try {
122560b10ffSOliver Tappe 			DateFormat* format = DateFormat::createDateInstance(
123560b10ffSOliver Tappe 				DateFormat::kDefault, fLocale);
124560b10ffSOliver Tappe 			result = _SetLCTimePattern(format, fDateFormat, sizeof(fDateFormat));
125560b10ffSOliver Tappe 			delete format;
126560b10ffSOliver Tappe 		} catch(...) {
127560b10ffSOliver Tappe 			result = B_NO_MEMORY;
128560b10ffSOliver Tappe 		}
129560b10ffSOliver Tappe 	}
130560b10ffSOliver Tappe 
131560b10ffSOliver Tappe 	if (result == B_OK) {
132560b10ffSOliver Tappe 		try {
133560b10ffSOliver Tappe 			DateFormat* format = DateFormat::createDateTimeInstance(
134560b10ffSOliver Tappe 				DateFormat::kFull, DateFormat::kFull, fLocale);
135560b10ffSOliver Tappe 			result = _SetLCTimePattern(format, fDateTimeFormat,
136560b10ffSOliver Tappe 				sizeof(fDateTimeFormat));
137560b10ffSOliver Tappe 			delete format;
138560b10ffSOliver Tappe 		} catch(...) {
139560b10ffSOliver Tappe 			result = B_NO_MEMORY;
140560b10ffSOliver Tappe 		}
141560b10ffSOliver Tappe 	}
142560b10ffSOliver Tappe 
143560b10ffSOliver Tappe 	if (result == B_OK) {
144560b10ffSOliver Tappe 		strings = formatSymbols.getAmPmStrings(count);
145560b10ffSOliver Tappe 		result = _SetLCTimeEntries(strings, fAm, sizeof(fAm), 1, 1);
146560b10ffSOliver Tappe 		if (result == B_OK)
147560b10ffSOliver Tappe 			result = _SetLCTimeEntries(&strings[1], fPm, sizeof(fPm), 1, 1);
148560b10ffSOliver Tappe 	}
149560b10ffSOliver Tappe 
150560b10ffSOliver Tappe 	if (result == B_OK) {
151560b10ffSOliver Tappe 		strings = formatSymbols.getMonths(count, DateFormatSymbols::STANDALONE,
152560b10ffSOliver Tappe 			DateFormatSymbols::WIDE);
153560b10ffSOliver Tappe 		result = _SetLCTimeEntries(strings, fAltMonth[0], sizeof(fAltMonth[0]),
154560b10ffSOliver Tappe 			count, 12);
155560b10ffSOliver Tappe 	}
156560b10ffSOliver Tappe 
157560b10ffSOliver Tappe 	strcpy(fAmPmFormat, fDataBridge->posixLCTimeInfo->ampm_fmt);
158560b10ffSOliver Tappe 		// ICU does not provide anything for this (and that makes sense, too)
159560b10ffSOliver Tappe 
160560b10ffSOliver Tappe 	return result;
161560b10ffSOliver Tappe }
162560b10ffSOliver Tappe 
163560b10ffSOliver Tappe 
164560b10ffSOliver Tappe status_t
165560b10ffSOliver Tappe ICUTimeData::SetToPosix()
166560b10ffSOliver Tappe {
167560b10ffSOliver Tappe 	status_t result = inherited::SetToPosix();
168560b10ffSOliver Tappe 
169560b10ffSOliver Tappe 	if (result == B_OK) {
170560b10ffSOliver Tappe 		for (int i = 0; i < 12; ++i) {
171560b10ffSOliver Tappe 			strcpy(fMon[i], fDataBridge->posixLCTimeInfo->mon[i]);
172560b10ffSOliver Tappe 			strcpy(fMonth[i], fDataBridge->posixLCTimeInfo->month[i]);
173560b10ffSOliver Tappe 			strcpy(fAltMonth[i], fDataBridge->posixLCTimeInfo->alt_month[i]);
174560b10ffSOliver Tappe 		}
175560b10ffSOliver Tappe 		for (int i = 0; i < 7; ++i) {
176560b10ffSOliver Tappe 			strcpy(fWday[i], fDataBridge->posixLCTimeInfo->wday[i]);
177560b10ffSOliver Tappe 			strcpy(fWeekday[i], fDataBridge->posixLCTimeInfo->weekday[i]);
178560b10ffSOliver Tappe 		}
179560b10ffSOliver Tappe 		strcpy(fTimeFormat, fDataBridge->posixLCTimeInfo->X_fmt);
180560b10ffSOliver Tappe 		strcpy(fDateFormat, fDataBridge->posixLCTimeInfo->x_fmt);
181560b10ffSOliver Tappe 		strcpy(fDateTimeFormat, fDataBridge->posixLCTimeInfo->c_fmt);
182560b10ffSOliver Tappe 		strcpy(fAm, fDataBridge->posixLCTimeInfo->am);
183560b10ffSOliver Tappe 		strcpy(fPm, fDataBridge->posixLCTimeInfo->pm);
184560b10ffSOliver Tappe 		strcpy(fDateTimeZoneFormat, fDataBridge->posixLCTimeInfo->date_fmt);
185560b10ffSOliver Tappe 		strcpy(fMonthDayOrder, fDataBridge->posixLCTimeInfo->md_order);
186560b10ffSOliver Tappe 		strcpy(fAmPmFormat, fDataBridge->posixLCTimeInfo->ampm_fmt);
187560b10ffSOliver Tappe 	}
188560b10ffSOliver Tappe 
189560b10ffSOliver Tappe 	return result;
190560b10ffSOliver Tappe }
191560b10ffSOliver Tappe 
192560b10ffSOliver Tappe 
193560b10ffSOliver Tappe const char*
194560b10ffSOliver Tappe ICUTimeData::GetLanginfo(int index)
195560b10ffSOliver Tappe {
196560b10ffSOliver Tappe 	switch(index) {
197560b10ffSOliver Tappe 		case D_T_FMT:
198560b10ffSOliver Tappe 			return fDateTimeFormat;
199560b10ffSOliver Tappe 		case D_FMT:
200560b10ffSOliver Tappe 			return fDateFormat;
201560b10ffSOliver Tappe 		case T_FMT:
202560b10ffSOliver Tappe 			return fTimeFormat;
203560b10ffSOliver Tappe 		case T_FMT_AMPM:
204560b10ffSOliver Tappe 			return fAmPmFormat;
205560b10ffSOliver Tappe 		case AM_STR:
206560b10ffSOliver Tappe 			return fAm;
207560b10ffSOliver Tappe 		case PM_STR:
208560b10ffSOliver Tappe 			return fPm;
209560b10ffSOliver Tappe 
210560b10ffSOliver Tappe 		case DAY_1:
211560b10ffSOliver Tappe 		case DAY_2:
212560b10ffSOliver Tappe 		case DAY_3:
213560b10ffSOliver Tappe 		case DAY_4:
214560b10ffSOliver Tappe 		case DAY_5:
215560b10ffSOliver Tappe 		case DAY_6:
216560b10ffSOliver Tappe 		case DAY_7:
217560b10ffSOliver Tappe 			return fWeekday[index - DAY_1];
218560b10ffSOliver Tappe 
219560b10ffSOliver Tappe 		case ABDAY_1:
220560b10ffSOliver Tappe 		case ABDAY_2:
221560b10ffSOliver Tappe 		case ABDAY_3:
222560b10ffSOliver Tappe 		case ABDAY_4:
223560b10ffSOliver Tappe 		case ABDAY_5:
224560b10ffSOliver Tappe 		case ABDAY_6:
225560b10ffSOliver Tappe 		case ABDAY_7:
226560b10ffSOliver Tappe 			return fWday[index - ABDAY_1];
227560b10ffSOliver Tappe 
228560b10ffSOliver Tappe 		case MON_1:
229560b10ffSOliver Tappe 		case MON_2:
230560b10ffSOliver Tappe 		case MON_3:
231560b10ffSOliver Tappe 		case MON_4:
232560b10ffSOliver Tappe 		case MON_5:
233560b10ffSOliver Tappe 		case MON_6:
234560b10ffSOliver Tappe 		case MON_7:
235560b10ffSOliver Tappe 		case MON_8:
236560b10ffSOliver Tappe 		case MON_9:
237560b10ffSOliver Tappe 		case MON_10:
238560b10ffSOliver Tappe 		case MON_11:
239560b10ffSOliver Tappe 		case MON_12:
240560b10ffSOliver Tappe 			return fMonth[index - MON_1];
241560b10ffSOliver Tappe 
242560b10ffSOliver Tappe 		case ABMON_1:
243560b10ffSOliver Tappe 		case ABMON_2:
244560b10ffSOliver Tappe 		case ABMON_3:
245560b10ffSOliver Tappe 		case ABMON_4:
246560b10ffSOliver Tappe 		case ABMON_5:
247560b10ffSOliver Tappe 		case ABMON_6:
248560b10ffSOliver Tappe 		case ABMON_7:
249560b10ffSOliver Tappe 		case ABMON_8:
250560b10ffSOliver Tappe 		case ABMON_9:
251560b10ffSOliver Tappe 		case ABMON_10:
252560b10ffSOliver Tappe 		case ABMON_11:
253560b10ffSOliver Tappe 		case ABMON_12:
254560b10ffSOliver Tappe 			return fMon[index - ABMON_1];
255560b10ffSOliver Tappe 
256560b10ffSOliver Tappe 		default:
257560b10ffSOliver Tappe 			return "";
258560b10ffSOliver Tappe 	}
259560b10ffSOliver Tappe }
260560b10ffSOliver Tappe 
261560b10ffSOliver Tappe 
262ec17468fSOliver Tappe const Locale&
263ec17468fSOliver Tappe ICUTimeData::ICULocaleForStrings() const
264ec17468fSOliver Tappe {
265ec17468fSOliver Tappe 	// check if the date strings should be taken from the messages-locale
266ec17468fSOliver Tappe 	// or from the time-locale (default)
267ec17468fSOliver Tappe 	UErrorCode icuStatus = U_ZERO_ERROR;
268ec17468fSOliver Tappe 	char stringsValue[16];
269ec17468fSOliver Tappe 	fLocale.getKeywordValue("strings", stringsValue, sizeof(stringsValue),
270ec17468fSOliver Tappe 		icuStatus);
271ec17468fSOliver Tappe 	if (U_SUCCESS(icuStatus) && strcasecmp(stringsValue, "messages") == 0)
272ec17468fSOliver Tappe 		return fMessagesData.ICULocale();
273ec17468fSOliver Tappe 	else
274ec17468fSOliver Tappe 		return fLocale;
275ec17468fSOliver Tappe }
276ec17468fSOliver Tappe 
277ec17468fSOliver Tappe 
278560b10ffSOliver Tappe status_t
279560b10ffSOliver Tappe ICUTimeData::_SetLCTimeEntries(const UnicodeString* strings, char* destination,
280560b10ffSOliver Tappe 	int entrySize, int count, int maxCount)
281560b10ffSOliver Tappe {
282560b10ffSOliver Tappe 	if (strings == NULL)
283560b10ffSOliver Tappe 		return B_ERROR;
284560b10ffSOliver Tappe 
285560b10ffSOliver Tappe 	status_t result = B_OK;
286560b10ffSOliver Tappe 	if (count > maxCount)
287560b10ffSOliver Tappe 		count = maxCount;
288560b10ffSOliver Tappe 	for (int32 i = 0; result == B_OK && i < count; ++i) {
289560b10ffSOliver Tappe 		result = _ConvertUnicodeStringToLocaleconvEntry(strings[i], destination,
290560b10ffSOliver Tappe 			entrySize);
291560b10ffSOliver Tappe 		destination += entrySize;
292560b10ffSOliver Tappe 	}
293560b10ffSOliver Tappe 
294560b10ffSOliver Tappe 	return result;
295560b10ffSOliver Tappe }
296560b10ffSOliver Tappe 
297560b10ffSOliver Tappe 
298560b10ffSOliver Tappe status_t
299560b10ffSOliver Tappe ICUTimeData::_SetLCTimePattern(DateFormat* format, char* destination,
300560b10ffSOliver Tappe 	int destinationSize)
301560b10ffSOliver Tappe {
302560b10ffSOliver Tappe 	SimpleDateFormat* simpleFormat = dynamic_cast<SimpleDateFormat*>(format);
303560b10ffSOliver Tappe 	if (!simpleFormat)
304560b10ffSOliver Tappe 		return B_BAD_TYPE;
305560b10ffSOliver Tappe 
306560b10ffSOliver Tappe 	// convert ICU-type pattern to posix (i.e. strftime()) format string
307560b10ffSOliver Tappe 	UnicodeString icuPattern;
308560b10ffSOliver Tappe 	simpleFormat->toPattern(icuPattern);
309560b10ffSOliver Tappe 	UnicodeString posixPattern;
310560b10ffSOliver Tappe 	if (icuPattern.length() > 0) {
311560b10ffSOliver Tappe 		UChar lastCharSeen = 0;
312560b10ffSOliver Tappe 		int lastCharCount = 1;
313560b10ffSOliver Tappe 		bool inSingleQuotes = false;
314560b10ffSOliver Tappe 		bool inDoubleQuotes = false;
315560b10ffSOliver Tappe 		// we loop one character past the end on purpose, which will result in a
316560b10ffSOliver Tappe 		// final -1 char to be processed, which in turn will let us handle the
317560b10ffSOliver Tappe 		// last character (via lastCharSeen)
318560b10ffSOliver Tappe 		for (int i = 0; i <= icuPattern.length(); ++i) {
319560b10ffSOliver Tappe 			UChar currChar = icuPattern.charAt(i);
320560b10ffSOliver Tappe 			if (lastCharSeen != 0 && currChar == lastCharSeen) {
321560b10ffSOliver Tappe 				lastCharCount++;
322560b10ffSOliver Tappe 				continue;
323560b10ffSOliver Tappe 			}
324560b10ffSOliver Tappe 
325560b10ffSOliver Tappe 			if (!inSingleQuotes && !inDoubleQuotes) {
326560b10ffSOliver Tappe 				switch (lastCharSeen) {
327560b10ffSOliver Tappe 					case L'a':
328560b10ffSOliver Tappe 						posixPattern.append(UnicodeString("%p", ""));
329560b10ffSOliver Tappe 						break;
330560b10ffSOliver Tappe 					case L'd':
331560b10ffSOliver Tappe 						if (lastCharCount == 2)
332560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%d", ""));
333560b10ffSOliver Tappe 						else
334560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%e", ""));
335560b10ffSOliver Tappe 						break;
336560b10ffSOliver Tappe 					case L'D':
337560b10ffSOliver Tappe 						posixPattern.append(UnicodeString("%j", ""));
338560b10ffSOliver Tappe 						break;
339560b10ffSOliver Tappe 					case L'c':
340560b10ffSOliver Tappe 						// fall through, to handle 'c' the same as 'e'
341560b10ffSOliver Tappe 					case L'e':
342560b10ffSOliver Tappe 						if (lastCharCount == 4)
343560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%A", ""));
344560b10ffSOliver Tappe 						else if (lastCharCount <= 2)
345560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%u", ""));
346560b10ffSOliver Tappe 						else
347560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%a", ""));
348560b10ffSOliver Tappe 						break;
349560b10ffSOliver Tappe 					case L'E':
350560b10ffSOliver Tappe 						if (lastCharCount == 4)
351560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%A", ""));
352560b10ffSOliver Tappe 						else
353560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%a", ""));
354560b10ffSOliver Tappe 						break;
355560b10ffSOliver Tappe 					case L'k':
356560b10ffSOliver Tappe 						// fall through, to handle 'k' the same as 'h'
357560b10ffSOliver Tappe 					case L'h':
358560b10ffSOliver Tappe 						if (lastCharCount == 2)
359560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%I", ""));
360560b10ffSOliver Tappe 						else
361560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%l", ""));
362560b10ffSOliver Tappe 						break;
363560b10ffSOliver Tappe 					case L'H':
364560b10ffSOliver Tappe 						if (lastCharCount == 2)
365560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%H", ""));
366560b10ffSOliver Tappe 						else
367560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%k", ""));
368560b10ffSOliver Tappe 						break;
369560b10ffSOliver Tappe 					case L'm':
370560b10ffSOliver Tappe 						posixPattern.append(UnicodeString("%M", ""));
371560b10ffSOliver Tappe 						break;
372560b10ffSOliver Tappe 					case L'L':
373560b10ffSOliver Tappe 						// fall through, to handle 'L' the same as 'M'
374560b10ffSOliver Tappe 					case L'M':
375560b10ffSOliver Tappe 						if (lastCharCount == 4)
376560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%B", ""));
377560b10ffSOliver Tappe 						else if (lastCharCount == 3)
378560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%b", ""));
379560b10ffSOliver Tappe 						else
380560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%m", ""));
381560b10ffSOliver Tappe 						break;
382560b10ffSOliver Tappe 					case L's':
383560b10ffSOliver Tappe 						posixPattern.append(UnicodeString("%S", ""));
384560b10ffSOliver Tappe 						break;
385560b10ffSOliver Tappe 					case L'w':
386560b10ffSOliver Tappe 						posixPattern.append(UnicodeString("%V", ""));
387560b10ffSOliver Tappe 						break;
388560b10ffSOliver Tappe 					case L'y':
389560b10ffSOliver Tappe 						if (lastCharCount == 2)
390560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%y", ""));
391560b10ffSOliver Tappe 						else
392560b10ffSOliver Tappe 							posixPattern.append(UnicodeString("%Y", ""));
393560b10ffSOliver Tappe 						break;
394560b10ffSOliver Tappe 					case L'Y':
395560b10ffSOliver Tappe 						posixPattern.append(UnicodeString("%G", ""));
396560b10ffSOliver Tappe 						break;
397560b10ffSOliver Tappe 					case L'z':
398560b10ffSOliver Tappe 						posixPattern.append(UnicodeString("%Z", ""));
399560b10ffSOliver Tappe 						break;
400560b10ffSOliver Tappe 					case L'Z':
401560b10ffSOliver Tappe 						posixPattern.append(UnicodeString("%z", ""));
402560b10ffSOliver Tappe 						break;
403560b10ffSOliver Tappe 					default:
404560b10ffSOliver Tappe 						if (lastCharSeen != 0)
405560b10ffSOliver Tappe 							posixPattern.append(lastCharSeen);
406560b10ffSOliver Tappe 				}
407560b10ffSOliver Tappe 			} else {
408560b10ffSOliver Tappe 				if (lastCharSeen != 0)
409560b10ffSOliver Tappe 					posixPattern.append(lastCharSeen);
410560b10ffSOliver Tappe 			}
411560b10ffSOliver Tappe 
412560b10ffSOliver Tappe 			if (currChar == L'"') {
413560b10ffSOliver Tappe 				inDoubleQuotes = !inDoubleQuotes;
414560b10ffSOliver Tappe 				lastCharSeen = 0;
415560b10ffSOliver Tappe 			} else if (currChar == L'\'') {
416560b10ffSOliver Tappe 				inSingleQuotes = !inSingleQuotes;
417560b10ffSOliver Tappe 				lastCharSeen = 0;
418560b10ffSOliver Tappe 			} else
419560b10ffSOliver Tappe 				lastCharSeen = currChar;
420560b10ffSOliver Tappe 
421560b10ffSOliver Tappe 			lastCharCount = 1;
422560b10ffSOliver Tappe 		}
423560b10ffSOliver Tappe 	}
424560b10ffSOliver Tappe 
425560b10ffSOliver Tappe 	return _ConvertUnicodeStringToLocaleconvEntry(posixPattern, destination,
426560b10ffSOliver Tappe 		destinationSize);
427560b10ffSOliver Tappe }
428560b10ffSOliver Tappe 
429560b10ffSOliver Tappe 
43025dc253dSIngo Weinhold }	// namespace Libroot
431560b10ffSOliver Tappe }	// namespace BPrivate
432