1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /* loclibrary.c
19  * ----------------------------------------------------------------------
20  * Source for localization library
21  * Originally created by jsantamaria: 3 may 2004
22  * ----------------------------------------------------------------------
23  */
24 
25 #include "DebugServices.h"
26 #include <windows.h>
27 #include <stdio.h>
28 #include "isocode.h"
29 #include "loclibrary.h"
30 #include "Shlwapi.h"
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <wchar.h>
34 
35 
36 #ifdef __cplusplus
37 extern "c" {
38 #endif
39 
40 #ifdef _MSC_VER
41 #define swprintf _snwprintf
42 #define snprintf _snprintf
43 #endif
44 
45 
46 
47 #define DEFAULT_LANG_CODE "en"
48 
49 // gets the user language
_getUserLanguage(void)50 static LANGID _getUserLanguage( void ) {
51 
52 	return GetUserDefaultUILanguage();
53 
54 }
55 
56 
57 // gets the ISO mapping
_getISOCode(LANGID wLangID,char * isoLangCode,int codeLen)58 static int _getISOCode(LANGID wLangID, char *isoLangCode, int codeLen) {
59 	int i;
60 	unsigned short langCode;
61 
62 	for (i = 0; i < NUM_ISOCODES; i++) {
63 		int startIndex = i * MODULO_ISOCODES;
64 
65 		langCode = (ISOCODES[startIndex] << 8);
66 		langCode = langCode + ( (unsigned short) (ISOCODES[startIndex + 1]) );
67 
68 		if (langCode == wLangID) {
69 			char *langStr = (char *)&(ISOCODES[startIndex+2]);
70 			strncpy(isoLangCode, langStr, codeLen);
71 			return 0;
72 		}
73 	}
74 	return 1;
75 }
76 
77 static char isoLangCode[LANG_CODE_LEN + 1] = "";
78 static LANGID wLangID = (LANGID) -1;
79 
_setLanguageIfNeeded(void)80 static void _setLanguageIfNeeded(void) {
81 
82 	// get the language code if we don't have it cached
83 	if (!strncmp(isoLangCode,"",LANG_CODE_LEN + 1)) {
84 
85 		// if we haven't cached the language id, do the lookup
86 		if (wLangID == (LANGID) -1) {
87 			wLangID = _getUserLanguage();
88 		}
89 
90 		// if no ISOCode, set it to DEFAULT_LANG_CODE
91 		if (_getISOCode(wLangID, isoLangCode, LANG_CODE_LEN + 1)) {
92 			strncpy(isoLangCode, DEFAULT_LANG_CODE, LANG_CODE_LEN+1);
93 		}
94 	}
95 
96 }
97 
98 //// PathForResource
99 
100 // Gets the PathForResource for handle 0 for the current process
101 
102 
103 static char appPathNameA[MAX_PATH] = "";
104 
PathForResourceA(HMODULE module,const char * name,char * locFile,int locFileLen)105 int PathForResourceA ( HMODULE module, const char *name, char *locFile, int locFileLen)
106 {
107 	int ret = 0;
108 
109 	if ( !strcmp( appPathNameA, "" ) )
110 	{
111 		char   folder[MAX_PATH];
112 		char * ext;
113 		char * app;
114 
115 		GetModuleFileNameA( module, folder, MAX_PATH );
116 
117 		// Get folder string
118 
119 		app = strrchr( folder, '\\' );
120 		require_action( app, exit, ret = 0 );
121 		*app++ = '\0';
122 
123 		// Strip the extension
124 
125 		if ( ( ( ext = strstr( app, ".exe" ) ) != NULL ) || ( ( ext = strstr( app, ".dll" ) ) != NULL ) )
126 		{
127 			*ext = '\0';
128 		}
129 
130 		snprintf( appPathNameA, MAX_PATH, "%s\\%s", folder, app );
131 	}
132 
133 	ret = PathForResourceWithPathA (appPathNameA, name, locFile, locFileLen);
134 
135 exit:
136 
137 	return ret;
138 }
139 
140 static wchar_t appPathNameW[MAX_PATH] = L"";
141 
PathForResourceW(HMODULE module,const wchar_t * name,wchar_t * locFile,int locFileLen)142 int PathForResourceW ( HMODULE module, const wchar_t *name, wchar_t *locFile, int locFileLen)
143 {
144 	int ret = 0;
145 
146 	if ( !wcscmp( appPathNameW, L"" ) )
147 	{
148 		wchar_t   folder[MAX_PATH];
149 		wchar_t * app;
150 		wchar_t * ext;
151 
152 		GetModuleFileNameW( module, folder, MAX_PATH);
153 
154 		// Get folder string
155 
156 		app = wcsrchr( folder, '\\' );
157 		require_action( app, exit, ret = 0 );
158 		*app++ = '\0';
159 
160 		// Strip the extension
161 
162 		if ( ( ( ext = wcsstr( app, L".exe" ) ) != NULL ) || ( ( ext = wcsstr( app, L".dll" ) ) != NULL ) )
163 		{
164 			*ext = '\0';
165 		}
166 
167 		swprintf( appPathNameW, MAX_PATH, L"%ls\\%ls", folder, app );
168 	}
169 
170 	ret = PathForResourceWithPathW (appPathNameW, name, locFile, locFileLen);
171 
172 exit:
173 
174 	return ret;
175 }
176 
177 
178 //// PathForResourceWithPath
179 
180 #define TMP_BUF_SIZE MAX_PATH
181 
PathForResourceWithPathA(const char * path,const char * nm,char * locFile,int locFileLen)182 int PathForResourceWithPathA (const char *path, const char *nm,
183 									char *locFile, int locFileLen) {
184 	char tmpBuffer[TMP_BUF_SIZE];
185 
186 	// build the path to the executable in the generic
187 	// resources folder, check there first
188 	snprintf(tmpBuffer, MAX_PATH, "%s.Resources\\%s", path, nm);
189 
190 	if (!PathFileExistsA(tmpBuffer)) {
191 
192 		// didn't hit generic resource folder, so need to get language codes
193 		_setLanguageIfNeeded();
194 
195 		// test to see if localized directory exists,
196 		// if so, we don't fall back if we don't find the file.
197 		snprintf(tmpBuffer, TMP_BUF_SIZE,
198 				 "%s.Resources\\%s.lproj", path, isoLangCode);
199 
200 		if (PathFileExistsA(tmpBuffer)) {
201 			snprintf(tmpBuffer, TMP_BUF_SIZE, "%s\\%s", tmpBuffer, nm);
202 
203 			if (!PathFileExistsA(tmpBuffer)) return 0;
204 
205 			strncpy(locFile, tmpBuffer, locFileLen);
206 			return (int) strlen(locFile);
207 		}
208 
209 		// fall back on DEFAULT_LANG_CODE if still no good
210 		snprintf(tmpBuffer, TMP_BUF_SIZE, "%s.Resources\\%s.lproj\\%s",
211 				path, DEFAULT_LANG_CODE, nm);
212 
213 		// we can't find the resource, so return 0
214 		if (!PathFileExistsA(tmpBuffer)) return 0;
215 	}
216 
217 	strncpy(locFile, tmpBuffer, locFileLen);
218 	return (int) strlen(locFile);
219 
220 }
221 
222 
PathForResourceWithPathW(const wchar_t * path,const wchar_t * nm,wchar_t * locFile,int locFileLen)223 int PathForResourceWithPathW (const wchar_t *path, const wchar_t *nm,
224 								wchar_t *locFile, int locFileLen) {
225 
226 	wchar_t tmpBuffer[TMP_BUF_SIZE];
227 
228 	// build the path to the executable in the generic
229 	// resources folder, check there first
230 	swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls.Resources\\%ls", path, nm);
231 
232 	if (!PathFileExistsW(tmpBuffer)) {
233 		// didn't hit generic resource folder, so need to get language codes
234 		_setLanguageIfNeeded();
235 
236 		// test to see if localized directory exists,
237 		// if so, we don't fall back if we don't find the file.
238 		swprintf(tmpBuffer, TMP_BUF_SIZE,
239 				  L"%ls.Resources\\%S.lproj", path, isoLangCode);
240 
241 		if (PathFileExistsW(tmpBuffer)) {
242 			swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls\\%ls", tmpBuffer, nm);
243 
244 			if (!PathFileExistsW(tmpBuffer)) return 0;
245 
246 			wcsncpy(locFile, tmpBuffer, locFileLen);
247 			return (int) wcslen(locFile);
248 		}
249 
250 		// fall back on DEFAULT_LANG_CODE if still no good
251 		swprintf(tmpBuffer, TMP_BUF_SIZE, L"%ls.Resources\\%S.lproj\\%ls",
252 			path, DEFAULT_LANG_CODE, nm);
253 
254 		// we can't find the resource, so return 0
255 		if (!PathFileExistsW(tmpBuffer)) return 0;
256 	}
257 
258 	wcsncpy(locFile, tmpBuffer, locFileLen);
259 	return (int) wcslen(locFile);
260 
261 
262 }
263 
264 
265 
266 #ifdef __cplusplus
267 }
268 #endif
269