13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25 // This file is available under and governed by the GNU General Public
26 // License version 2 only, as published by the Free Software Foundation.
27 // However, the following notice accompanied the original version of this
28 // file:
29 //
30 //---------------------------------------------------------------------------------
31 //
32 // Little Color Management System
33 // Copyright (c) 1998-2012 Marti Maria Saguer
34 //
35 // Permission is hereby granted, free of charge, to any person obtaining
36 // a copy of this software and associated documentation files (the "Software"),
37 // to deal in the Software without restriction, including without limitation
38 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
39 // and/or sell copies of the Software, and to permit persons to whom the Software
40 // is furnished to do so, subject to the following conditions:
41 //
42 // The above copyright notice and this permission notice shall be included in
43 // all copies or substantial portions of the Software.
44 //
45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
52 //
53 //---------------------------------------------------------------------------------
104
105 // Check for overflow
106 if (size < mlu ->PoolSize) return FALSE;
107
108 // Reallocate the pool
109 NewPtr = _cmsRealloc(mlu ->ContextID, mlu ->MemPool, size);
110 if (NewPtr == NULL) return FALSE;
111
112
113 mlu ->MemPool = NewPtr;
114 mlu ->PoolSize = size;
115
116 return TRUE;
117 }
118
119
120 // Grows a entry table for a MLU. Each time this function is called, table size is multiplied times two.
121 static
122 cmsBool GrowMLUtable(cmsMLU* mlu)
123 {
124 int AllocatedEntries;
125 _cmsMLUentry *NewPtr;
126
127 // Sanity check
128 if (mlu == NULL) return FALSE;
129
130 AllocatedEntries = mlu ->AllocatedEntries * 2;
131
132 // Check for overflow
133 if (AllocatedEntries / 2 != mlu ->AllocatedEntries) return FALSE;
134
135 // Reallocate the memory
136 NewPtr = (_cmsMLUentry*)_cmsRealloc(mlu ->ContextID, mlu ->Entries, AllocatedEntries*sizeof(_cmsMLUentry));
137 if (NewPtr == NULL) return FALSE;
138
139 mlu ->Entries = NewPtr;
140 mlu ->AllocatedEntries = AllocatedEntries;
141
142 return TRUE;
143 }
144
145
146 // Search for a specific entry in the structure. Language and Country are used.
147 static
148 int SearchMLUEntry(cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode)
149 {
150 int i;
151
152 // Sanity check
153 if (mlu == NULL) return -1;
154
155 // Iterate whole table
156 for (i=0; i < mlu ->UsedEntries; i++) {
157
158 if (mlu ->Entries[i].Country == CountryCode &&
159 mlu ->Entries[i].Language == LanguageCode) return i;
160 }
161
162 // Not found
163 return -1;
164 }
165
166 // Add a block of characters to the intended MLU. Language and country are specified.
167 // Only one entry for Language/country pair is allowed.
168 static
169 cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
170 cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode)
190 }
191
192 Offset = mlu ->PoolUsed;
193
194 Ptr = (cmsUInt8Number*) mlu ->MemPool;
195 if (Ptr == NULL) return FALSE;
196
197 // Set the entry
198 memmove(Ptr + Offset, Block, size);
199 mlu ->PoolUsed += size;
200
201 mlu ->Entries[mlu ->UsedEntries].StrW = Offset;
202 mlu ->Entries[mlu ->UsedEntries].Len = size;
203 mlu ->Entries[mlu ->UsedEntries].Country = CountryCode;
204 mlu ->Entries[mlu ->UsedEntries].Language = LanguageCode;
205 mlu ->UsedEntries++;
206
207 return TRUE;
208 }
209
210
211 // Add an ASCII entry.
212 cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString)
213 {
214 cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString)+1;
215 wchar_t* WStr;
216 cmsBool rc;
217 cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
218 cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
219
220 if (mlu == NULL) return FALSE;
221
222 WStr = (wchar_t*) _cmsCalloc(mlu ->ContextID, len, sizeof(wchar_t));
223 if (WStr == NULL) return FALSE;
224
225 for (i=0; i < len; i++)
226 WStr[i] = (wchar_t) ASCIIString[i];
227
228 rc = AddMLUBlock(mlu, len * sizeof(wchar_t), WStr, Lang, Cntry);
229
230 _cmsFree(mlu ->ContextID, WStr);
231 return rc;
232
233 }
234
235 // We don't need any wcs support library
236 static
237 cmsUInt32Number mywcslen(const wchar_t *s)
238 {
239 const wchar_t *p;
240
241 p = s;
242 while (*p)
243 p++;
244
245 return (cmsUInt32Number)(p - s);
246 }
247
248
249 // Add a wide entry
250 cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char Country[3], const wchar_t* WideString)
251 {
252 cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) Language);
253 cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) Country);
254 cmsUInt32Number len;
255
256 if (mlu == NULL) return FALSE;
257 if (WideString == NULL) return FALSE;
258
259 len = (cmsUInt32Number) (mywcslen(WideString) + 1) * sizeof(wchar_t);
260 return AddMLUBlock(mlu, len, WideString, Lang, Cntry);
261 }
262
263 // Duplicating a MLU is as easy as copying all members
264 cmsMLU* CMSEXPORT cmsMLUdup(const cmsMLU* mlu)
265 {
266 cmsMLU* NewMlu = NULL;
267
268 // Duplicating a NULL obtains a NULL
269 if (mlu == NULL) return NULL;
270
271 NewMlu = cmsMLUalloc(mlu ->ContextID, mlu ->UsedEntries);
272 if (NewMlu == NULL) return NULL;
273
274 // Should never happen
275 if (NewMlu ->AllocatedEntries < mlu ->UsedEntries)
276 goto Error;
277
278 // Sanitize...
279 if (NewMlu ->Entries == NULL || mlu ->Entries == NULL) goto Error;
310 void CMSEXPORT cmsMLUfree(cmsMLU* mlu)
311 {
312 if (mlu) {
313
314 if (mlu -> Entries) _cmsFree(mlu ->ContextID, mlu->Entries);
315 if (mlu -> MemPool) _cmsFree(mlu ->ContextID, mlu->MemPool);
316
317 _cmsFree(mlu ->ContextID, mlu);
318 }
319 }
320
321
322 // The algorithm first searches for an exact match of country and language, if not found it uses
323 // the Language. If none is found, first entry is used instead.
324 static
325 const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
326 cmsUInt32Number *len,
327 cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode,
328 cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode)
329 {
330 int i;
331 int Best = -1;
332 _cmsMLUentry* v;
333
334 if (mlu == NULL) return NULL;
335
336 if (mlu -> AllocatedEntries <= 0) return NULL;
337
338 for (i=0; i < mlu ->UsedEntries; i++) {
339
340 v = mlu ->Entries + i;
341
342 if (v -> Language == LanguageCode) {
343
344 if (Best == -1) Best = i;
345
346 if (v -> Country == CountryCode) {
347
348 if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
349 if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
350
351 if (len != NULL) *len = v ->Len;
362 v = mlu ->Entries + Best;
363
364 if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
365 if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
366
367 if (len != NULL) *len = v ->Len;
368
369 return(wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v ->StrW);
370 }
371
372
373 // Obtain an ASCII representation of the wide string. Setting buffer to NULL returns the len
374 cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
375 const char LanguageCode[3], const char CountryCode[3],
376 char* Buffer, cmsUInt32Number BufferSize)
377 {
378 const wchar_t *Wide;
379 cmsUInt32Number StrLen = 0;
380 cmsUInt32Number ASCIIlen, i;
381
382 cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
383 cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
384
385 // Sanitize
386 if (mlu == NULL) return 0;
387
388 // Get WideChar
389 Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL, NULL);
390 if (Wide == NULL) return 0;
391
392 ASCIIlen = StrLen / sizeof(wchar_t);
393
394 // Maybe we want only to know the len?
395 if (Buffer == NULL) return ASCIIlen + 1; // Note the zero at the end
396
397 // No buffer size means no data
398 if (BufferSize <= 0) return 0;
399
400 // Some clipping may be required
401 if (BufferSize < ASCIIlen + 1)
402 ASCIIlen = BufferSize - 1;
403
406
407 if (Wide[i] == 0)
408 Buffer[i] = 0;
409 else
410 Buffer[i] = (char) Wide[i];
411 }
412
413 // We put a termination "\0"
414 Buffer[ASCIIlen] = 0;
415 return ASCIIlen + 1;
416 }
417
418 // Obtain a wide representation of the MLU, on depending on current locale settings
419 cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
420 const char LanguageCode[3], const char CountryCode[3],
421 wchar_t* Buffer, cmsUInt32Number BufferSize)
422 {
423 const wchar_t *Wide;
424 cmsUInt32Number StrLen = 0;
425
426 cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
427 cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
428
429 // Sanitize
430 if (mlu == NULL) return 0;
431
432 Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL, NULL);
433 if (Wide == NULL) return 0;
434
435 // Maybe we want only to know the len?
436 if (Buffer == NULL) return StrLen + sizeof(wchar_t);
437
438 // No buffer size means no data
439 if (BufferSize <= 0) return 0;
440
441 // Some clipping may be required
442 if (BufferSize < StrLen + sizeof(wchar_t))
443 StrLen = BufferSize - + sizeof(wchar_t);
444
445 memmove(Buffer, Wide, StrLen);
446 Buffer[StrLen / sizeof(wchar_t)] = 0;
447
448 return StrLen + sizeof(wchar_t);
449 }
450
451
452 // Get also the language and country
453 CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
454 const char LanguageCode[3], const char CountryCode[3],
455 char ObtainedLanguage[3], char ObtainedCountry[3])
456 {
457 const wchar_t *Wide;
458
459 cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
460 cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
461 cmsUInt16Number ObtLang, ObtCode;
462
463 // Sanitize
464 if (mlu == NULL) return FALSE;
465
466 Wide = _cmsMLUgetWide(mlu, NULL, Lang, Cntry, &ObtLang, &ObtCode);
467 if (Wide == NULL) return FALSE;
468
469 // Get used language and code
470 *(cmsUInt16Number *)ObtainedLanguage = _cmsAdjustEndianess16(ObtLang);
471 *(cmsUInt16Number *)ObtainedCountry = _cmsAdjustEndianess16(ObtCode);
472
473 ObtainedLanguage[2] = ObtainedCountry[2] = 0;
474 return TRUE;
475 }
476
477
478
479 // Get the number of translations in the MLU object
480 cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu)
481 {
482 if (mlu == NULL) return 0;
483 return mlu->UsedEntries;
484 }
485
486 // Get the language and country codes for a specific MLU index
487 cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu,
488 cmsUInt32Number idx,
489 char LanguageCode[3],
490 char CountryCode[3])
491 {
492 _cmsMLUentry *entry;
493
494 if (mlu == NULL) return FALSE;
495
496 if (idx >= (cmsUInt32Number) mlu->UsedEntries) return FALSE;
497
498 entry = &mlu->Entries[idx];
499
500 *(cmsUInt16Number *)LanguageCode = _cmsAdjustEndianess16(entry->Language);
501 *(cmsUInt16Number *)CountryCode = _cmsAdjustEndianess16(entry->Country);
502
503 return TRUE;
504 }
505
506
507 // Named color lists --------------------------------------------------------------------------------------------
508
509 // Grow the list to keep at least NumElements
510 static
511 cmsBool GrowNamedColorList(cmsNAMEDCOLORLIST* v)
512 {
513 cmsUInt32Number size;
514 _cmsNAMEDCOLOR * NewPtr;
515
516 if (v == NULL) return FALSE;
517
518 if (v ->Allocated == 0)
519 size = 64; // Initial guess
520 else
521 size = v ->Allocated * 2;
|
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25 // This file is available under and governed by the GNU General Public
26 // License version 2 only, as published by the Free Software Foundation.
27 // However, the following notice accompanied the original version of this
28 // file:
29 //
30 //---------------------------------------------------------------------------------
31 //
32 // Little Color Management System
33 // Copyright (c) 1998-2016 Marti Maria Saguer
34 //
35 // Permission is hereby granted, free of charge, to any person obtaining
36 // a copy of this software and associated documentation files (the "Software"),
37 // to deal in the Software without restriction, including without limitation
38 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
39 // and/or sell copies of the Software, and to permit persons to whom the Software
40 // is furnished to do so, subject to the following conditions:
41 //
42 // The above copyright notice and this permission notice shall be included in
43 // all copies or substantial portions of the Software.
44 //
45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
52 //
53 //---------------------------------------------------------------------------------
104
105 // Check for overflow
106 if (size < mlu ->PoolSize) return FALSE;
107
108 // Reallocate the pool
109 NewPtr = _cmsRealloc(mlu ->ContextID, mlu ->MemPool, size);
110 if (NewPtr == NULL) return FALSE;
111
112
113 mlu ->MemPool = NewPtr;
114 mlu ->PoolSize = size;
115
116 return TRUE;
117 }
118
119
120 // Grows a entry table for a MLU. Each time this function is called, table size is multiplied times two.
121 static
122 cmsBool GrowMLUtable(cmsMLU* mlu)
123 {
124 cmsUInt32Number AllocatedEntries;
125 _cmsMLUentry *NewPtr;
126
127 // Sanity check
128 if (mlu == NULL) return FALSE;
129
130 AllocatedEntries = mlu ->AllocatedEntries * 2;
131
132 // Check for overflow
133 if (AllocatedEntries / 2 != mlu ->AllocatedEntries) return FALSE;
134
135 // Reallocate the memory
136 NewPtr = (_cmsMLUentry*)_cmsRealloc(mlu ->ContextID, mlu ->Entries, AllocatedEntries*sizeof(_cmsMLUentry));
137 if (NewPtr == NULL) return FALSE;
138
139 mlu ->Entries = NewPtr;
140 mlu ->AllocatedEntries = AllocatedEntries;
141
142 return TRUE;
143 }
144
145
146 // Search for a specific entry in the structure. Language and Country are used.
147 static
148 int SearchMLUEntry(cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode)
149 {
150 cmsUInt32Number i;
151
152 // Sanity check
153 if (mlu == NULL) return -1;
154
155 // Iterate whole table
156 for (i=0; i < mlu ->UsedEntries; i++) {
157
158 if (mlu ->Entries[i].Country == CountryCode &&
159 mlu ->Entries[i].Language == LanguageCode) return i;
160 }
161
162 // Not found
163 return -1;
164 }
165
166 // Add a block of characters to the intended MLU. Language and country are specified.
167 // Only one entry for Language/country pair is allowed.
168 static
169 cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
170 cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode)
190 }
191
192 Offset = mlu ->PoolUsed;
193
194 Ptr = (cmsUInt8Number*) mlu ->MemPool;
195 if (Ptr == NULL) return FALSE;
196
197 // Set the entry
198 memmove(Ptr + Offset, Block, size);
199 mlu ->PoolUsed += size;
200
201 mlu ->Entries[mlu ->UsedEntries].StrW = Offset;
202 mlu ->Entries[mlu ->UsedEntries].Len = size;
203 mlu ->Entries[mlu ->UsedEntries].Country = CountryCode;
204 mlu ->Entries[mlu ->UsedEntries].Language = LanguageCode;
205 mlu ->UsedEntries++;
206
207 return TRUE;
208 }
209
210 // Convert from a 3-char code to a cmsUInt16Number. It is done inthis way because some
211 // compilers don't properly align beginning of strings
212
213 static
214 cmsUInt16Number strTo16(const char str[3])
215 {
216 cmsUInt16Number n = ((cmsUInt16Number) str[0] << 8) | str[1];
217
218 return n; // Always big endian in this case
219 }
220
221 static
222 void strFrom16(char str[3], cmsUInt16Number n)
223 {
224 // Assiming this would be aligned
225 union {
226
227 cmsUInt16Number n;
228 char str[2];
229
230 } c;
231
232 c.n = n; // Always big endian in this case
233
234 str[0] = c.str[0]; str[1] = c.str[1]; str[2] = 0;
235
236 }
237
238 // Add an ASCII entry. Do not add any \0 termination (ICC1v43_2010-12.pdf page 61)
239 cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString)
240 {
241 cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString);
242 wchar_t* WStr;
243 cmsBool rc;
244 cmsUInt16Number Lang = strTo16(LanguageCode);
245 cmsUInt16Number Cntry = strTo16(CountryCode);
246
247 if (mlu == NULL) return FALSE;
248
249 WStr = (wchar_t*) _cmsCalloc(mlu ->ContextID, len, sizeof(wchar_t));
250 if (WStr == NULL) return FALSE;
251
252 for (i=0; i < len; i++)
253 WStr[i] = (wchar_t) ASCIIString[i];
254
255 rc = AddMLUBlock(mlu, len * sizeof(wchar_t), WStr, Lang, Cntry);
256
257 _cmsFree(mlu ->ContextID, WStr);
258 return rc;
259
260 }
261
262 // We don't need any wcs support library
263 static
264 cmsUInt32Number mywcslen(const wchar_t *s)
265 {
266 const wchar_t *p;
267
268 p = s;
269 while (*p)
270 p++;
271
272 return (cmsUInt32Number)(p - s);
273 }
274
275 // Add a wide entry. Do not add any \0 terminator (ICC1v43_2010-12.pdf page 61)
276 cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char Country[3], const wchar_t* WideString)
277 {
278 cmsUInt16Number Lang = strTo16(Language);
279 cmsUInt16Number Cntry = strTo16(Country);
280 cmsUInt32Number len;
281
282 if (mlu == NULL) return FALSE;
283 if (WideString == NULL) return FALSE;
284
285 len = (cmsUInt32Number) (mywcslen(WideString)) * sizeof(wchar_t);
286 return AddMLUBlock(mlu, len, WideString, Lang, Cntry);
287 }
288
289 // Duplicating a MLU is as easy as copying all members
290 cmsMLU* CMSEXPORT cmsMLUdup(const cmsMLU* mlu)
291 {
292 cmsMLU* NewMlu = NULL;
293
294 // Duplicating a NULL obtains a NULL
295 if (mlu == NULL) return NULL;
296
297 NewMlu = cmsMLUalloc(mlu ->ContextID, mlu ->UsedEntries);
298 if (NewMlu == NULL) return NULL;
299
300 // Should never happen
301 if (NewMlu ->AllocatedEntries < mlu ->UsedEntries)
302 goto Error;
303
304 // Sanitize...
305 if (NewMlu ->Entries == NULL || mlu ->Entries == NULL) goto Error;
336 void CMSEXPORT cmsMLUfree(cmsMLU* mlu)
337 {
338 if (mlu) {
339
340 if (mlu -> Entries) _cmsFree(mlu ->ContextID, mlu->Entries);
341 if (mlu -> MemPool) _cmsFree(mlu ->ContextID, mlu->MemPool);
342
343 _cmsFree(mlu ->ContextID, mlu);
344 }
345 }
346
347
348 // The algorithm first searches for an exact match of country and language, if not found it uses
349 // the Language. If none is found, first entry is used instead.
350 static
351 const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
352 cmsUInt32Number *len,
353 cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode,
354 cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode)
355 {
356 cmsUInt32Number i;
357 cmsInt32Number Best = -1;
358 _cmsMLUentry* v;
359
360 if (mlu == NULL) return NULL;
361
362 if (mlu -> AllocatedEntries <= 0) return NULL;
363
364 for (i=0; i < mlu ->UsedEntries; i++) {
365
366 v = mlu ->Entries + i;
367
368 if (v -> Language == LanguageCode) {
369
370 if (Best == -1) Best = i;
371
372 if (v -> Country == CountryCode) {
373
374 if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
375 if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
376
377 if (len != NULL) *len = v ->Len;
388 v = mlu ->Entries + Best;
389
390 if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
391 if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
392
393 if (len != NULL) *len = v ->Len;
394
395 return(wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v ->StrW);
396 }
397
398
399 // Obtain an ASCII representation of the wide string. Setting buffer to NULL returns the len
400 cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
401 const char LanguageCode[3], const char CountryCode[3],
402 char* Buffer, cmsUInt32Number BufferSize)
403 {
404 const wchar_t *Wide;
405 cmsUInt32Number StrLen = 0;
406 cmsUInt32Number ASCIIlen, i;
407
408 cmsUInt16Number Lang = strTo16(LanguageCode);
409 cmsUInt16Number Cntry = strTo16(CountryCode);
410
411 // Sanitize
412 if (mlu == NULL) return 0;
413
414 // Get WideChar
415 Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL, NULL);
416 if (Wide == NULL) return 0;
417
418 ASCIIlen = StrLen / sizeof(wchar_t);
419
420 // Maybe we want only to know the len?
421 if (Buffer == NULL) return ASCIIlen + 1; // Note the zero at the end
422
423 // No buffer size means no data
424 if (BufferSize <= 0) return 0;
425
426 // Some clipping may be required
427 if (BufferSize < ASCIIlen + 1)
428 ASCIIlen = BufferSize - 1;
429
432
433 if (Wide[i] == 0)
434 Buffer[i] = 0;
435 else
436 Buffer[i] = (char) Wide[i];
437 }
438
439 // We put a termination "\0"
440 Buffer[ASCIIlen] = 0;
441 return ASCIIlen + 1;
442 }
443
444 // Obtain a wide representation of the MLU, on depending on current locale settings
445 cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
446 const char LanguageCode[3], const char CountryCode[3],
447 wchar_t* Buffer, cmsUInt32Number BufferSize)
448 {
449 const wchar_t *Wide;
450 cmsUInt32Number StrLen = 0;
451
452 cmsUInt16Number Lang = strTo16(LanguageCode);
453 cmsUInt16Number Cntry = strTo16(CountryCode);
454
455 // Sanitize
456 if (mlu == NULL) return 0;
457
458 Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL, NULL);
459 if (Wide == NULL) return 0;
460
461 // Maybe we want only to know the len?
462 if (Buffer == NULL) return StrLen + sizeof(wchar_t);
463
464 // No buffer size means no data
465 if (BufferSize <= 0) return 0;
466
467 // Some clipping may be required
468 if (BufferSize < StrLen + sizeof(wchar_t))
469 StrLen = BufferSize - + sizeof(wchar_t);
470
471 memmove(Buffer, Wide, StrLen);
472 Buffer[StrLen / sizeof(wchar_t)] = 0;
473
474 return StrLen + sizeof(wchar_t);
475 }
476
477
478 // Get also the language and country
479 CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
480 const char LanguageCode[3], const char CountryCode[3],
481 char ObtainedLanguage[3], char ObtainedCountry[3])
482 {
483 const wchar_t *Wide;
484
485 cmsUInt16Number Lang = strTo16(LanguageCode);
486 cmsUInt16Number Cntry = strTo16(CountryCode);
487 cmsUInt16Number ObtLang, ObtCode;
488
489 // Sanitize
490 if (mlu == NULL) return FALSE;
491
492 Wide = _cmsMLUgetWide(mlu, NULL, Lang, Cntry, &ObtLang, &ObtCode);
493 if (Wide == NULL) return FALSE;
494
495 // Get used language and code
496 strFrom16(ObtainedLanguage, ObtLang);
497 strFrom16(ObtainedCountry, ObtCode);
498
499 return TRUE;
500 }
501
502
503
504 // Get the number of translations in the MLU object
505 cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu)
506 {
507 if (mlu == NULL) return 0;
508 return mlu->UsedEntries;
509 }
510
511 // Get the language and country codes for a specific MLU index
512 cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu,
513 cmsUInt32Number idx,
514 char LanguageCode[3],
515 char CountryCode[3])
516 {
517 _cmsMLUentry *entry;
518
519 if (mlu == NULL) return FALSE;
520
521 if (idx >= mlu->UsedEntries) return FALSE;
522
523 entry = &mlu->Entries[idx];
524
525 strFrom16(LanguageCode, entry->Language);
526 strFrom16(CountryCode, entry->Country);
527
528 return TRUE;
529 }
530
531
532 // Named color lists --------------------------------------------------------------------------------------------
533
534 // Grow the list to keep at least NumElements
535 static
536 cmsBool GrowNamedColorList(cmsNAMEDCOLORLIST* v)
537 {
538 cmsUInt32Number size;
539 _cmsNAMEDCOLOR * NewPtr;
540
541 if (v == NULL) return FALSE;
542
543 if (v ->Allocated == 0)
544 size = 64; // Initial guess
545 else
546 size = v ->Allocated * 2;
|