1/*
2 * Copyright 2004-2007, Axel D��rfler, axeld@pinc-software.de
3 * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de
4 * All rights reserved. Distributed under the terms of the MIT License.
5 */
6
7
8#include <ctype.h>
9#include <locale.h>
10#include <strings.h>
11
12#include <ErrnoMaintainer.h>
13
14#include "LocaleBackend.h"
15#include "LocaleInternal.h"
16
17
18using BPrivate::Libroot::gGlobalLocaleBackend;
19using BPrivate::Libroot::GetLocalesFromEnvironment;
20using BPrivate::Libroot::LocaleBackend;
21
22
23extern "C" char*
24setlocale(int category, const char* locale)
25{
26	BPrivate::ErrnoMaintainer errnoMaintainer;
27
28	if (category < 0 || category > LC_LAST)
29		return NULL;
30
31	if (locale == NULL) {
32		// query the locale of the given category
33		if (gGlobalLocaleBackend != NULL)
34			return const_cast<char*>(gGlobalLocaleBackend->SetLocale(category, NULL));
35		else
36			return const_cast<char*>("POSIX");
37	}
38
39	// we may have to invoke SetLocale once for each category, so we use an
40	// array to collect the locale per category
41	const char* locales[LC_LAST + 1];
42	for (int lc = 0; lc <= LC_LAST; lc++)
43		locales[lc] = NULL;
44
45	if (*locale == '\0')
46		GetLocalesFromEnvironment(category, locales);
47	else
48		locales[category] = locale;
49
50	if (gGlobalLocaleBackend == NULL) {
51		// for any locale other than POSIX/C, we try to activate the ICU
52		// backend
53		bool needBackend = false;
54		for (int lc = 0; lc <= LC_LAST; lc++) {
55			if (locales[lc] != NULL && strcasecmp(locales[lc], "POSIX") != 0
56					&& strcasecmp(locales[lc], "C") != 0) {
57				needBackend = true;
58				break;
59			}
60		}
61		if (needBackend && LocaleBackend::LoadBackend() != B_OK)
62			return NULL;
63	}
64
65	if (gGlobalLocaleBackend != NULL) {
66		for (int lc = 0; lc <= LC_LAST; lc++) {
67			if (locales[lc] != NULL) {
68				locale = gGlobalLocaleBackend->SetLocale(lc, locales[lc]);
69				if (lc == LC_ALL) {
70					// skip the rest, LC_ALL overrides
71					return const_cast<char*>(locale);
72				}
73			}
74		}
75		return const_cast<char*>(gGlobalLocaleBackend->SetLocale(category, NULL));
76	}
77
78	return const_cast<char*>("POSIX");
79}
80