File: | jdk/src/java.desktop/share/native/liblcms/cmsnamed.c |
Warning: | line 835, column 13 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |||
3 | * | |||
4 | * This code is free software; you can redistribute it and/or modify it | |||
5 | * under the terms of the GNU General Public License version 2 only, as | |||
6 | * published by the Free Software Foundation. Oracle designates this | |||
7 | * particular file as subject to the "Classpath" exception as provided | |||
8 | * by Oracle in the LICENSE file that accompanied this code. | |||
9 | * | |||
10 | * This code is distributed in the hope that it will be useful, but WITHOUT | |||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
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-2020 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 | //--------------------------------------------------------------------------------- | |||
54 | // | |||
55 | ||||
56 | #include "lcms2_internal.h" | |||
57 | ||||
58 | // Multilocalized unicode objects. That is an attempt to encapsulate i18n. | |||
59 | ||||
60 | ||||
61 | // Allocates an empty multi localizad unicode object | |||
62 | cmsMLU* CMSEXPORT cmsMLUalloc(cmsContext ContextID, cmsUInt32Number nItems) | |||
63 | { | |||
64 | cmsMLU* mlu; | |||
65 | ||||
66 | // nItems should be positive if given | |||
67 | if (nItems <= 0) nItems = 2; | |||
68 | ||||
69 | // Create the container | |||
70 | mlu = (cmsMLU*) _cmsMallocZero(ContextID, sizeof(cmsMLU)); | |||
71 | if (mlu == NULL((void*)0)) return NULL((void*)0); | |||
72 | ||||
73 | mlu ->ContextID = ContextID; | |||
74 | ||||
75 | // Create entry array | |||
76 | mlu ->Entries = (_cmsMLUentry*) _cmsCalloc(ContextID, nItems, sizeof(_cmsMLUentry)); | |||
77 | if (mlu ->Entries == NULL((void*)0)) { | |||
78 | _cmsFree(ContextID, mlu); | |||
79 | return NULL((void*)0); | |||
80 | } | |||
81 | ||||
82 | // Ok, keep indexes up to date | |||
83 | mlu ->AllocatedEntries = nItems; | |||
84 | mlu ->UsedEntries = 0; | |||
85 | ||||
86 | return mlu; | |||
87 | } | |||
88 | ||||
89 | ||||
90 | // Grows a mempool table for a MLU. Each time this function is called, mempool size is multiplied times two. | |||
91 | static | |||
92 | cmsBool GrowMLUpool(cmsMLU* mlu) | |||
93 | { | |||
94 | cmsUInt32Number size; | |||
95 | void *NewPtr; | |||
96 | ||||
97 | // Sanity check | |||
98 | if (mlu == NULL((void*)0)) return FALSE0; | |||
99 | ||||
100 | if (mlu ->PoolSize == 0) | |||
101 | size = 256; | |||
102 | else | |||
103 | size = mlu ->PoolSize * 2; | |||
104 | ||||
105 | // Check for overflow | |||
106 | if (size < mlu ->PoolSize) return FALSE0; | |||
107 | ||||
108 | // Reallocate the pool | |||
109 | NewPtr = _cmsRealloc(mlu ->ContextID, mlu ->MemPool, size); | |||
110 | if (NewPtr == NULL((void*)0)) return FALSE0; | |||
111 | ||||
112 | ||||
113 | mlu ->MemPool = NewPtr; | |||
114 | mlu ->PoolSize = size; | |||
115 | ||||
116 | return TRUE1; | |||
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((void*)0)) return FALSE0; | |||
129 | ||||
130 | AllocatedEntries = mlu ->AllocatedEntries * 2; | |||
131 | ||||
132 | // Check for overflow | |||
133 | if (AllocatedEntries / 2 != mlu ->AllocatedEntries) return FALSE0; | |||
134 | ||||
135 | // Reallocate the memory | |||
136 | NewPtr = (_cmsMLUentry*)_cmsRealloc(mlu ->ContextID, mlu ->Entries, AllocatedEntries*sizeof(_cmsMLUentry)); | |||
137 | if (NewPtr == NULL((void*)0)) return FALSE0; | |||
138 | ||||
139 | mlu ->Entries = NewPtr; | |||
140 | mlu ->AllocatedEntries = AllocatedEntries; | |||
141 | ||||
142 | return TRUE1; | |||
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((void*)0)) 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 (int) 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) | |||
171 | { | |||
172 | cmsUInt32Number Offset; | |||
173 | cmsUInt8Number* Ptr; | |||
174 | ||||
175 | // Sanity check | |||
176 | if (mlu == NULL((void*)0)) return FALSE0; | |||
177 | ||||
178 | // Is there any room available? | |||
179 | if (mlu ->UsedEntries >= mlu ->AllocatedEntries) { | |||
180 | if (!GrowMLUtable(mlu)) return FALSE0; | |||
181 | } | |||
182 | ||||
183 | // Only one ASCII string | |||
184 | if (SearchMLUEntry(mlu, LanguageCode, CountryCode) >= 0) return FALSE0; // Only one is allowed! | |||
185 | ||||
186 | // Check for size | |||
187 | while ((mlu ->PoolSize - mlu ->PoolUsed) < size) { | |||
188 | ||||
189 | if (!GrowMLUpool(mlu)) return FALSE0; | |||
190 | } | |||
191 | ||||
192 | Offset = mlu ->PoolUsed; | |||
193 | ||||
194 | Ptr = (cmsUInt8Number*) mlu ->MemPool; | |||
195 | if (Ptr == NULL((void*)0)) return FALSE0; | |||
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 TRUE1; | |||
208 | } | |||
209 | ||||
210 | // Convert from a 3-char code to a cmsUInt16Number. It is done in this way because some | |||
211 | // compilers don't properly align beginning of strings | |||
212 | static | |||
213 | cmsUInt16Number strTo16(const char str[3]) | |||
214 | { | |||
215 | const cmsUInt8Number* ptr8; | |||
216 | cmsUInt16Number n; | |||
217 | ||||
218 | // For non-existent strings | |||
219 | if (str == NULL((void*)0)) return 0; | |||
220 | ptr8 = (const cmsUInt8Number*)str; | |||
221 | n = (cmsUInt16Number)(((cmsUInt16Number)ptr8[0] << 8) | ptr8[1]); | |||
222 | ||||
223 | return n; | |||
224 | } | |||
225 | ||||
226 | static | |||
227 | void strFrom16(char str[3], cmsUInt16Number n) | |||
228 | { | |||
229 | str[0] = (char)(n >> 8); | |||
230 | str[1] = (char)n; | |||
231 | str[2] = (char)0; | |||
232 | ||||
233 | } | |||
234 | ||||
235 | // Add an ASCII entry. Do not add any \0 termination (ICC1v43_2010-12.pdf page 61) | |||
236 | // In the case the user explicitely sets an empty string, we force a \0 | |||
237 | cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString) | |||
238 | { | |||
239 | cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString); | |||
240 | wchar_t* WStr; | |||
241 | cmsBool rc; | |||
242 | cmsUInt16Number Lang = strTo16(LanguageCode); | |||
243 | cmsUInt16Number Cntry = strTo16(CountryCode); | |||
244 | ||||
245 | if (mlu == NULL((void*)0)) return FALSE0; | |||
246 | ||||
247 | // len == 0 would prevent operation, so we set a empty string pointing to zero | |||
248 | if (len == 0) | |||
249 | { | |||
250 | len = 1; | |||
251 | } | |||
252 | ||||
253 | WStr = (wchar_t*) _cmsCalloc(mlu ->ContextID, len, sizeof(wchar_t)); | |||
254 | if (WStr == NULL((void*)0)) return FALSE0; | |||
255 | ||||
256 | for (i=0; i < len; i++) | |||
257 | WStr[i] = (wchar_t) ASCIIString[i]; | |||
258 | ||||
259 | rc = AddMLUBlock(mlu, len * sizeof(wchar_t), WStr, Lang, Cntry); | |||
260 | ||||
261 | _cmsFree(mlu ->ContextID, WStr); | |||
262 | return rc; | |||
263 | ||||
264 | } | |||
265 | ||||
266 | // We don't need any wcs support library | |||
267 | static | |||
268 | cmsUInt32Number mywcslen(const wchar_t *s) | |||
269 | { | |||
270 | const wchar_t *p; | |||
271 | ||||
272 | p = s; | |||
273 | while (*p) | |||
274 | p++; | |||
275 | ||||
276 | return (cmsUInt32Number)(p - s); | |||
277 | } | |||
278 | ||||
279 | // Add a wide entry. Do not add any \0 terminator (ICC1v43_2010-12.pdf page 61) | |||
280 | cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char Country[3], const wchar_t* WideString) | |||
281 | { | |||
282 | cmsUInt16Number Lang = strTo16(Language); | |||
283 | cmsUInt16Number Cntry = strTo16(Country); | |||
284 | cmsUInt32Number len; | |||
285 | ||||
286 | if (mlu == NULL((void*)0)) return FALSE0; | |||
287 | if (WideString == NULL((void*)0)) return FALSE0; | |||
288 | ||||
289 | len = (cmsUInt32Number) (mywcslen(WideString)) * sizeof(wchar_t); | |||
290 | if (len == 0) | |||
291 | len = sizeof(wchar_t); | |||
292 | ||||
293 | return AddMLUBlock(mlu, len, WideString, Lang, Cntry); | |||
294 | } | |||
295 | ||||
296 | // Duplicating a MLU is as easy as copying all members | |||
297 | cmsMLU* CMSEXPORT cmsMLUdup(const cmsMLU* mlu) | |||
298 | { | |||
299 | cmsMLU* NewMlu = NULL((void*)0); | |||
300 | ||||
301 | // Duplicating a NULL obtains a NULL | |||
302 | if (mlu == NULL((void*)0)) return NULL((void*)0); | |||
303 | ||||
304 | NewMlu = cmsMLUalloc(mlu ->ContextID, mlu ->UsedEntries); | |||
305 | if (NewMlu == NULL((void*)0)) return NULL((void*)0); | |||
306 | ||||
307 | // Should never happen | |||
308 | if (NewMlu ->AllocatedEntries < mlu ->UsedEntries) | |||
309 | goto Error; | |||
310 | ||||
311 | // Sanitize... | |||
312 | if (NewMlu ->Entries == NULL((void*)0) || mlu ->Entries == NULL((void*)0)) goto Error; | |||
313 | ||||
314 | memmove(NewMlu ->Entries, mlu ->Entries, mlu ->UsedEntries * sizeof(_cmsMLUentry)); | |||
315 | NewMlu ->UsedEntries = mlu ->UsedEntries; | |||
316 | ||||
317 | // The MLU may be empty | |||
318 | if (mlu ->PoolUsed == 0) { | |||
319 | NewMlu ->MemPool = NULL((void*)0); | |||
320 | } | |||
321 | else { | |||
322 | // It is not empty | |||
323 | NewMlu ->MemPool = _cmsMalloc(mlu ->ContextID, mlu ->PoolUsed); | |||
324 | if (NewMlu ->MemPool == NULL((void*)0)) goto Error; | |||
325 | } | |||
326 | ||||
327 | NewMlu ->PoolSize = mlu ->PoolUsed; | |||
328 | ||||
329 | if (NewMlu ->MemPool == NULL((void*)0) || mlu ->MemPool == NULL((void*)0)) goto Error; | |||
330 | ||||
331 | memmove(NewMlu ->MemPool, mlu->MemPool, mlu ->PoolUsed); | |||
332 | NewMlu ->PoolUsed = mlu ->PoolUsed; | |||
333 | ||||
334 | return NewMlu; | |||
335 | ||||
336 | Error: | |||
337 | ||||
338 | if (NewMlu != NULL((void*)0)) cmsMLUfree(NewMlu); | |||
339 | return NULL((void*)0); | |||
340 | } | |||
341 | ||||
342 | // Free any used memory | |||
343 | void CMSEXPORT cmsMLUfree(cmsMLU* mlu) | |||
344 | { | |||
345 | if (mlu) { | |||
346 | ||||
347 | if (mlu -> Entries) _cmsFree(mlu ->ContextID, mlu->Entries); | |||
348 | if (mlu -> MemPool) _cmsFree(mlu ->ContextID, mlu->MemPool); | |||
349 | ||||
350 | _cmsFree(mlu ->ContextID, mlu); | |||
351 | } | |||
352 | } | |||
353 | ||||
354 | ||||
355 | // The algorithm first searches for an exact match of country and language, if not found it uses | |||
356 | // the Language. If none is found, first entry is used instead. | |||
357 | static | |||
358 | const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu, | |||
359 | cmsUInt32Number *len, | |||
360 | cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode, | |||
361 | cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode) | |||
362 | { | |||
363 | cmsUInt32Number i; | |||
364 | int Best = -1; | |||
365 | _cmsMLUentry* v; | |||
366 | ||||
367 | if (mlu == NULL((void*)0)) return NULL((void*)0); | |||
368 | ||||
369 | if (mlu -> AllocatedEntries <= 0) return NULL((void*)0); | |||
370 | ||||
371 | for (i=0; i < mlu ->UsedEntries; i++) { | |||
372 | ||||
373 | v = mlu ->Entries + i; | |||
374 | ||||
375 | if (v -> Language == LanguageCode) { | |||
376 | ||||
377 | if (Best == -1) Best = (int) i; | |||
378 | ||||
379 | if (v -> Country == CountryCode) { | |||
380 | ||||
381 | if (UsedLanguageCode != NULL((void*)0)) *UsedLanguageCode = v ->Language; | |||
382 | if (UsedCountryCode != NULL((void*)0)) *UsedCountryCode = v ->Country; | |||
383 | ||||
384 | if (len != NULL((void*)0)) *len = v ->Len; | |||
385 | ||||
386 | return (wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v -> StrW); // Found exact match | |||
387 | } | |||
388 | } | |||
389 | } | |||
390 | ||||
391 | // No string found. Return First one | |||
392 | if (Best == -1) | |||
393 | Best = 0; | |||
394 | ||||
395 | v = mlu ->Entries + Best; | |||
396 | ||||
397 | if (UsedLanguageCode != NULL((void*)0)) *UsedLanguageCode = v ->Language; | |||
398 | if (UsedCountryCode != NULL((void*)0)) *UsedCountryCode = v ->Country; | |||
399 | ||||
400 | if (len != NULL((void*)0)) *len = v ->Len; | |||
401 | ||||
402 | return(wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v ->StrW); | |||
403 | } | |||
404 | ||||
405 | ||||
406 | // Obtain an ASCII representation of the wide string. Setting buffer to NULL returns the len | |||
407 | cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu, | |||
408 | const char LanguageCode[3], const char CountryCode[3], | |||
409 | char* Buffer, cmsUInt32Number BufferSize) | |||
410 | { | |||
411 | const wchar_t *Wide; | |||
412 | cmsUInt32Number StrLen = 0; | |||
413 | cmsUInt32Number ASCIIlen, i; | |||
414 | ||||
415 | cmsUInt16Number Lang = strTo16(LanguageCode); | |||
416 | cmsUInt16Number Cntry = strTo16(CountryCode); | |||
417 | ||||
418 | // Sanitize | |||
419 | if (mlu == NULL((void*)0)) return 0; | |||
420 | ||||
421 | // Get WideChar | |||
422 | Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL((void*)0), NULL((void*)0)); | |||
423 | if (Wide == NULL((void*)0)) return 0; | |||
424 | ||||
425 | ASCIIlen = StrLen / sizeof(wchar_t); | |||
426 | ||||
427 | // Maybe we want only to know the len? | |||
428 | if (Buffer == NULL((void*)0)) return ASCIIlen + 1; // Note the zero at the end | |||
429 | ||||
430 | // No buffer size means no data | |||
431 | if (BufferSize <= 0) return 0; | |||
432 | ||||
433 | // Some clipping may be required | |||
434 | if (BufferSize < ASCIIlen + 1) | |||
435 | ASCIIlen = BufferSize - 1; | |||
436 | ||||
437 | // Precess each character | |||
438 | for (i=0; i < ASCIIlen; i++) { | |||
439 | ||||
440 | if (Wide[i] == 0) | |||
441 | Buffer[i] = 0; | |||
442 | else | |||
443 | Buffer[i] = (char) Wide[i]; | |||
444 | } | |||
445 | ||||
446 | // We put a termination "\0" | |||
447 | Buffer[ASCIIlen] = 0; | |||
448 | return ASCIIlen + 1; | |||
449 | } | |||
450 | ||||
451 | // Obtain a wide representation of the MLU, on depending on current locale settings | |||
452 | cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu, | |||
453 | const char LanguageCode[3], const char CountryCode[3], | |||
454 | wchar_t* Buffer, cmsUInt32Number BufferSize) | |||
455 | { | |||
456 | const wchar_t *Wide; | |||
457 | cmsUInt32Number StrLen = 0; | |||
458 | ||||
459 | cmsUInt16Number Lang = strTo16(LanguageCode); | |||
460 | cmsUInt16Number Cntry = strTo16(CountryCode); | |||
461 | ||||
462 | // Sanitize | |||
463 | if (mlu == NULL((void*)0)) return 0; | |||
464 | ||||
465 | Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL((void*)0), NULL((void*)0)); | |||
466 | if (Wide == NULL((void*)0)) return 0; | |||
467 | ||||
468 | // Maybe we want only to know the len? | |||
469 | if (Buffer == NULL((void*)0)) return StrLen + sizeof(wchar_t); | |||
470 | ||||
471 | // No buffer size means no data | |||
472 | if (BufferSize <= 0) return 0; | |||
473 | ||||
474 | // Some clipping may be required | |||
475 | if (BufferSize < StrLen + sizeof(wchar_t)) | |||
476 | StrLen = BufferSize - + sizeof(wchar_t); | |||
477 | ||||
478 | memmove(Buffer, Wide, StrLen); | |||
479 | Buffer[StrLen / sizeof(wchar_t)] = 0; | |||
480 | ||||
481 | return StrLen + sizeof(wchar_t); | |||
482 | } | |||
483 | ||||
484 | ||||
485 | // Get also the language and country | |||
486 | CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu, | |||
487 | const char LanguageCode[3], const char CountryCode[3], | |||
488 | char ObtainedLanguage[3], char ObtainedCountry[3]) | |||
489 | { | |||
490 | const wchar_t *Wide; | |||
491 | ||||
492 | cmsUInt16Number Lang = strTo16(LanguageCode); | |||
493 | cmsUInt16Number Cntry = strTo16(CountryCode); | |||
494 | cmsUInt16Number ObtLang, ObtCode; | |||
495 | ||||
496 | // Sanitize | |||
497 | if (mlu == NULL((void*)0)) return FALSE0; | |||
498 | ||||
499 | Wide = _cmsMLUgetWide(mlu, NULL((void*)0), Lang, Cntry, &ObtLang, &ObtCode); | |||
500 | if (Wide == NULL((void*)0)) return FALSE0; | |||
501 | ||||
502 | // Get used language and code | |||
503 | strFrom16(ObtainedLanguage, ObtLang); | |||
504 | strFrom16(ObtainedCountry, ObtCode); | |||
505 | ||||
506 | return TRUE1; | |||
507 | } | |||
508 | ||||
509 | ||||
510 | ||||
511 | // Get the number of translations in the MLU object | |||
512 | cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu) | |||
513 | { | |||
514 | if (mlu == NULL((void*)0)) return 0; | |||
515 | return mlu->UsedEntries; | |||
516 | } | |||
517 | ||||
518 | // Get the language and country codes for a specific MLU index | |||
519 | cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu, | |||
520 | cmsUInt32Number idx, | |||
521 | char LanguageCode[3], | |||
522 | char CountryCode[3]) | |||
523 | { | |||
524 | _cmsMLUentry *entry; | |||
525 | ||||
526 | if (mlu == NULL((void*)0)) return FALSE0; | |||
527 | ||||
528 | if (idx >= mlu->UsedEntries) return FALSE0; | |||
529 | ||||
530 | entry = &mlu->Entries[idx]; | |||
531 | ||||
532 | strFrom16(LanguageCode, entry->Language); | |||
533 | strFrom16(CountryCode, entry->Country); | |||
534 | ||||
535 | return TRUE1; | |||
536 | } | |||
537 | ||||
538 | ||||
539 | // Named color lists -------------------------------------------------------------------------------------------- | |||
540 | ||||
541 | // Grow the list to keep at least NumElements | |||
542 | static | |||
543 | cmsBool GrowNamedColorList(cmsNAMEDCOLORLIST* v) | |||
544 | { | |||
545 | cmsUInt32Number size; | |||
546 | _cmsNAMEDCOLOR * NewPtr; | |||
547 | ||||
548 | if (v == NULL((void*)0)) return FALSE0; | |||
549 | ||||
550 | if (v ->Allocated == 0) | |||
551 | size = 64; // Initial guess | |||
552 | else | |||
553 | size = v ->Allocated * 2; | |||
554 | ||||
555 | // Keep a maximum color lists can grow, 100K entries seems reasonable | |||
556 | if (size > 1024 * 100) { | |||
557 | _cmsFree(v->ContextID, (void*) v->List); | |||
558 | v->List = NULL((void*)0); | |||
559 | return FALSE0; | |||
560 | } | |||
561 | ||||
562 | NewPtr = (_cmsNAMEDCOLOR*) _cmsRealloc(v ->ContextID, v ->List, size * sizeof(_cmsNAMEDCOLOR)); | |||
563 | if (NewPtr == NULL((void*)0)) | |||
564 | return FALSE0; | |||
565 | ||||
566 | v ->List = NewPtr; | |||
567 | v ->Allocated = size; | |||
568 | return TRUE1; | |||
569 | } | |||
570 | ||||
571 | // Allocate a list for n elements | |||
572 | cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUInt32Number n, cmsUInt32Number ColorantCount, const char* Prefix, const char* Suffix) | |||
573 | { | |||
574 | cmsNAMEDCOLORLIST* v = (cmsNAMEDCOLORLIST*) _cmsMallocZero(ContextID, sizeof(cmsNAMEDCOLORLIST)); | |||
575 | ||||
576 | if (v == NULL((void*)0)) return NULL((void*)0); | |||
577 | ||||
578 | v ->List = NULL((void*)0); | |||
579 | v ->nColors = 0; | |||
580 | v ->ContextID = ContextID; | |||
581 | ||||
582 | while (v -> Allocated < n) { | |||
583 | if (!GrowNamedColorList(v)) { | |||
584 | cmsFreeNamedColorList(v); | |||
585 | return NULL((void*)0); | |||
586 | } | |||
587 | } | |||
588 | ||||
589 | strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1); | |||
590 | strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix)-1); | |||
591 | v->Prefix[32] = v->Suffix[32] = 0; | |||
592 | ||||
593 | v -> ColorantCount = ColorantCount; | |||
594 | ||||
595 | return v; | |||
596 | } | |||
597 | ||||
598 | // Free a list | |||
599 | void CMSEXPORT cmsFreeNamedColorList(cmsNAMEDCOLORLIST* v) | |||
600 | { | |||
601 | if (v == NULL((void*)0)) return; | |||
602 | if (v ->List) _cmsFree(v ->ContextID, v ->List); | |||
603 | _cmsFree(v ->ContextID, v); | |||
604 | } | |||
605 | ||||
606 | cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v) | |||
607 | { | |||
608 | cmsNAMEDCOLORLIST* NewNC; | |||
609 | ||||
610 | if (v == NULL((void*)0)) return NULL((void*)0); | |||
611 | ||||
612 | NewNC= cmsAllocNamedColorList(v ->ContextID, v -> nColors, v ->ColorantCount, v ->Prefix, v ->Suffix); | |||
613 | if (NewNC == NULL((void*)0)) return NULL((void*)0); | |||
614 | ||||
615 | // For really large tables we need this | |||
616 | while (NewNC ->Allocated < v ->Allocated){ | |||
617 | if (!GrowNamedColorList(NewNC)) | |||
618 | { | |||
619 | cmsFreeNamedColorList(NewNC); | |||
620 | return NULL((void*)0); | |||
621 | } | |||
622 | } | |||
623 | ||||
624 | memmove(NewNC ->Prefix, v ->Prefix, sizeof(v ->Prefix)); | |||
625 | memmove(NewNC ->Suffix, v ->Suffix, sizeof(v ->Suffix)); | |||
626 | NewNC ->ColorantCount = v ->ColorantCount; | |||
627 | memmove(NewNC->List, v ->List, v->nColors * sizeof(_cmsNAMEDCOLOR)); | |||
628 | NewNC ->nColors = v ->nColors; | |||
629 | return NewNC; | |||
630 | } | |||
631 | ||||
632 | ||||
633 | // Append a color to a list. List pointer may change if reallocated | |||
634 | cmsBool CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* NamedColorList, | |||
635 | const char* Name, | |||
636 | cmsUInt16Number PCS[3], cmsUInt16Number Colorant[cmsMAXCHANNELS16]) | |||
637 | { | |||
638 | cmsUInt32Number i; | |||
639 | ||||
640 | if (NamedColorList == NULL((void*)0)) return FALSE0; | |||
641 | ||||
642 | if (NamedColorList ->nColors + 1 > NamedColorList ->Allocated) { | |||
643 | if (!GrowNamedColorList(NamedColorList)) return FALSE0; | |||
644 | } | |||
645 | ||||
646 | for (i=0; i < NamedColorList ->ColorantCount; i++) | |||
647 | NamedColorList ->List[NamedColorList ->nColors].DeviceColorant[i] = Colorant == NULL((void*)0) ? (cmsUInt16Number)0 : Colorant[i]; | |||
648 | ||||
649 | for (i=0; i < 3; i++) | |||
650 | NamedColorList ->List[NamedColorList ->nColors].PCS[i] = PCS == NULL((void*)0) ? (cmsUInt16Number) 0 : PCS[i]; | |||
651 | ||||
652 | if (Name != NULL((void*)0)) { | |||
653 | ||||
654 | strncpy(NamedColorList ->List[NamedColorList ->nColors].Name, Name, cmsMAX_PATH256-1); | |||
655 | NamedColorList ->List[NamedColorList ->nColors].Name[cmsMAX_PATH256-1] = 0; | |||
656 | ||||
657 | } | |||
658 | else | |||
659 | NamedColorList ->List[NamedColorList ->nColors].Name[0] = 0; | |||
660 | ||||
661 | ||||
662 | NamedColorList ->nColors++; | |||
663 | return TRUE1; | |||
664 | } | |||
665 | ||||
666 | // Returns number of elements | |||
667 | cmsUInt32Number CMSEXPORT cmsNamedColorCount(const cmsNAMEDCOLORLIST* NamedColorList) | |||
668 | { | |||
669 | if (NamedColorList == NULL((void*)0)) return 0; | |||
670 | return NamedColorList ->nColors; | |||
671 | } | |||
672 | ||||
673 | // Info aboout a given color | |||
674 | cmsBool CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cmsUInt32Number nColor, | |||
675 | char* Name, | |||
676 | char* Prefix, | |||
677 | char* Suffix, | |||
678 | cmsUInt16Number* PCS, | |||
679 | cmsUInt16Number* Colorant) | |||
680 | { | |||
681 | if (NamedColorList == NULL((void*)0)) return FALSE0; | |||
682 | ||||
683 | if (nColor >= cmsNamedColorCount(NamedColorList)) return FALSE0; | |||
684 | ||||
685 | // strcpy instead of strncpy because many apps are using small buffers | |||
686 | if (Name) strcpy(Name, NamedColorList->List[nColor].Name); | |||
687 | if (Prefix) strcpy(Prefix, NamedColorList->Prefix); | |||
688 | if (Suffix) strcpy(Suffix, NamedColorList->Suffix); | |||
689 | if (PCS) | |||
690 | memmove(PCS, NamedColorList ->List[nColor].PCS, 3*sizeof(cmsUInt16Number)); | |||
691 | ||||
692 | if (Colorant) | |||
693 | memmove(Colorant, NamedColorList ->List[nColor].DeviceColorant, | |||
694 | sizeof(cmsUInt16Number) * NamedColorList ->ColorantCount); | |||
695 | ||||
696 | ||||
697 | return TRUE1; | |||
698 | } | |||
699 | ||||
700 | // Search for a given color name (no prefix or suffix) | |||
701 | cmsInt32Number CMSEXPORT cmsNamedColorIndex(const cmsNAMEDCOLORLIST* NamedColorList, const char* Name) | |||
702 | { | |||
703 | cmsUInt32Number i; | |||
704 | cmsUInt32Number n; | |||
705 | ||||
706 | if (NamedColorList == NULL((void*)0)) return -1; | |||
707 | n = cmsNamedColorCount(NamedColorList); | |||
708 | for (i=0; i < n; i++) { | |||
709 | if (cmsstrcasecmp(Name, NamedColorList->List[i].Name) == 0) | |||
710 | return (cmsInt32Number) i; | |||
711 | } | |||
712 | ||||
713 | return -1; | |||
714 | } | |||
715 | ||||
716 | // MPE support ----------------------------------------------------------------------------------------------------------------- | |||
717 | ||||
718 | static | |||
719 | void FreeNamedColorList(cmsStage* mpe) | |||
720 | { | |||
721 | cmsNAMEDCOLORLIST* List = (cmsNAMEDCOLORLIST*) mpe ->Data; | |||
722 | cmsFreeNamedColorList(List); | |||
723 | } | |||
724 | ||||
725 | static | |||
726 | void* DupNamedColorList(cmsStage* mpe) | |||
727 | { | |||
728 | cmsNAMEDCOLORLIST* List = (cmsNAMEDCOLORLIST*) mpe ->Data; | |||
729 | return cmsDupNamedColorList(List); | |||
730 | } | |||
731 | ||||
732 | static | |||
733 | void EvalNamedColorPCS(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) | |||
734 | { | |||
735 | cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) mpe ->Data; | |||
736 | cmsUInt16Number index = (cmsUInt16Number) _cmsQuickSaturateWord(In[0] * 65535.0); | |||
737 | ||||
738 | if (index >= NamedColorList-> nColors) { | |||
739 | cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE2, "Color %d out of range", index); | |||
740 | Out[0] = Out[1] = Out[2] = 0.0f; | |||
741 | } | |||
742 | else { | |||
743 | ||||
744 | // Named color always uses Lab | |||
745 | Out[0] = (cmsFloat32Number) (NamedColorList->List[index].PCS[0] / 65535.0); | |||
746 | Out[1] = (cmsFloat32Number) (NamedColorList->List[index].PCS[1] / 65535.0); | |||
747 | Out[2] = (cmsFloat32Number) (NamedColorList->List[index].PCS[2] / 65535.0); | |||
748 | } | |||
749 | } | |||
750 | ||||
751 | static | |||
752 | void EvalNamedColor(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) | |||
753 | { | |||
754 | cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) mpe ->Data; | |||
755 | cmsUInt16Number index = (cmsUInt16Number) _cmsQuickSaturateWord(In[0] * 65535.0); | |||
756 | cmsUInt32Number j; | |||
757 | ||||
758 | if (index >= NamedColorList-> nColors) { | |||
759 | cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE2, "Color %d out of range", index); | |||
760 | for (j = 0; j < NamedColorList->ColorantCount; j++) | |||
761 | Out[j] = 0.0f; | |||
762 | ||||
763 | } | |||
764 | else { | |||
765 | for (j=0; j < NamedColorList ->ColorantCount; j++) | |||
766 | Out[j] = (cmsFloat32Number) (NamedColorList->List[index].DeviceColorant[j] / 65535.0); | |||
767 | } | |||
768 | } | |||
769 | ||||
770 | ||||
771 | // Named color lookup element | |||
772 | cmsStage* CMSEXPORT _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS) | |||
773 | { | |||
774 | return _cmsStageAllocPlaceholder(NamedColorList ->ContextID, | |||
775 | cmsSigNamedColorElemType, | |||
776 | 1, UsePCS ? 3 : NamedColorList ->ColorantCount, | |||
777 | UsePCS ? EvalNamedColorPCS : EvalNamedColor, | |||
778 | DupNamedColorList, | |||
779 | FreeNamedColorList, | |||
780 | cmsDupNamedColorList(NamedColorList)); | |||
781 | ||||
782 | } | |||
783 | ||||
784 | ||||
785 | // Retrieve the named color list from a transform. Should be first element in the LUT | |||
786 | cmsNAMEDCOLORLIST* CMSEXPORT cmsGetNamedColorList(cmsHTRANSFORM xform) | |||
787 | { | |||
788 | _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform; | |||
789 | cmsStage* mpe = v ->Lut->Elements; | |||
790 | ||||
791 | if (mpe ->Type != cmsSigNamedColorElemType) return NULL((void*)0); | |||
792 | return (cmsNAMEDCOLORLIST*) mpe ->Data; | |||
793 | } | |||
794 | ||||
795 | ||||
796 | // Profile sequence description routines ------------------------------------------------------------------------------------- | |||
797 | ||||
798 | cmsSEQ* CMSEXPORT cmsAllocProfileSequenceDescription(cmsContext ContextID, cmsUInt32Number n) | |||
799 | { | |||
800 | cmsSEQ* Seq; | |||
801 | cmsUInt32Number i; | |||
802 | ||||
803 | if (n == 0) return NULL((void*)0); | |||
804 | ||||
805 | // In a absolutely arbitrary way, I hereby decide to allow a maxim of 255 profiles linked | |||
806 | // in a devicelink. It makes not sense anyway and may be used for exploits, so let's close the door! | |||
807 | if (n > 255) return NULL((void*)0); | |||
808 | ||||
809 | Seq = (cmsSEQ*) _cmsMallocZero(ContextID, sizeof(cmsSEQ)); | |||
810 | if (Seq == NULL((void*)0)) return NULL((void*)0); | |||
811 | ||||
812 | Seq -> ContextID = ContextID; | |||
813 | Seq -> seq = (cmsPSEQDESC*) _cmsCalloc(ContextID, n, sizeof(cmsPSEQDESC)); | |||
814 | Seq -> n = n; | |||
815 | ||||
816 | if (Seq -> seq == NULL((void*)0)) { | |||
817 | _cmsFree(ContextID, Seq); | |||
818 | return NULL((void*)0); | |||
819 | } | |||
820 | ||||
821 | for (i=0; i < n; i++) { | |||
822 | Seq -> seq[i].Manufacturer = NULL((void*)0); | |||
823 | Seq -> seq[i].Model = NULL((void*)0); | |||
824 | Seq -> seq[i].Description = NULL((void*)0); | |||
825 | } | |||
826 | ||||
827 | return Seq; | |||
828 | } | |||
829 | ||||
830 | void CMSEXPORT cmsFreeProfileSequenceDescription(cmsSEQ* pseq) | |||
831 | { | |||
832 | cmsUInt32Number i; | |||
833 | ||||
834 | for (i=0; i < pseq ->n; i++) { | |||
835 | if (pseq ->seq[i].Manufacturer != NULL((void*)0)) cmsMLUfree(pseq ->seq[i].Manufacturer); | |||
| ||||
836 | if (pseq ->seq[i].Model != NULL((void*)0)) cmsMLUfree(pseq ->seq[i].Model); | |||
837 | if (pseq ->seq[i].Description != NULL((void*)0)) cmsMLUfree(pseq ->seq[i].Description); | |||
838 | } | |||
839 | ||||
840 | if (pseq ->seq != NULL((void*)0)) _cmsFree(pseq ->ContextID, pseq ->seq); | |||
841 | _cmsFree(pseq -> ContextID, pseq); | |||
842 | } | |||
843 | ||||
844 | cmsSEQ* CMSEXPORT cmsDupProfileSequenceDescription(const cmsSEQ* pseq) | |||
845 | { | |||
846 | cmsSEQ *NewSeq; | |||
847 | cmsUInt32Number i; | |||
848 | ||||
849 | if (pseq == NULL((void*)0)) | |||
| ||||
850 | return NULL((void*)0); | |||
851 | ||||
852 | NewSeq = (cmsSEQ*) _cmsMalloc(pseq -> ContextID, sizeof(cmsSEQ)); | |||
853 | if (NewSeq == NULL((void*)0)) return NULL((void*)0); | |||
854 | ||||
855 | ||||
856 | NewSeq -> seq = (cmsPSEQDESC*) _cmsCalloc(pseq ->ContextID, pseq ->n, sizeof(cmsPSEQDESC)); | |||
857 | if (NewSeq ->seq == NULL((void*)0)) goto Error; | |||
858 | ||||
859 | NewSeq -> ContextID = pseq ->ContextID; | |||
860 | NewSeq -> n = pseq ->n; | |||
861 | ||||
862 | for (i=0; i < pseq->n; i++) { | |||
863 | ||||
864 | memmove(&NewSeq ->seq[i].attributes, &pseq ->seq[i].attributes, sizeof(cmsUInt64Number)); | |||
865 | ||||
866 | NewSeq ->seq[i].deviceMfg = pseq ->seq[i].deviceMfg; | |||
867 | NewSeq ->seq[i].deviceModel = pseq ->seq[i].deviceModel; | |||
868 | memmove(&NewSeq ->seq[i].ProfileID, &pseq ->seq[i].ProfileID, sizeof(cmsProfileID)); | |||
869 | NewSeq ->seq[i].technology = pseq ->seq[i].technology; | |||
870 | ||||
871 | NewSeq ->seq[i].Manufacturer = cmsMLUdup(pseq ->seq[i].Manufacturer); | |||
872 | NewSeq ->seq[i].Model = cmsMLUdup(pseq ->seq[i].Model); | |||
873 | NewSeq ->seq[i].Description = cmsMLUdup(pseq ->seq[i].Description); | |||
874 | ||||
875 | } | |||
876 | ||||
877 | return NewSeq; | |||
878 | ||||
879 | Error: | |||
880 | ||||
881 | cmsFreeProfileSequenceDescription(NewSeq); | |||
882 | return NULL((void*)0); | |||
883 | } | |||
884 | ||||
885 | // Dictionaries -------------------------------------------------------------------------------------------------------- | |||
886 | ||||
887 | // Dictionaries are just very simple linked lists | |||
888 | ||||
889 | ||||
890 | typedef struct _cmsDICT_struct { | |||
891 | cmsDICTentry* head; | |||
892 | cmsContext ContextID; | |||
893 | } _cmsDICT; | |||
894 | ||||
895 | ||||
896 | // Allocate an empty dictionary | |||
897 | cmsHANDLE CMSEXPORT cmsDictAlloc(cmsContext ContextID) | |||
898 | { | |||
899 | _cmsDICT* dict = (_cmsDICT*) _cmsMallocZero(ContextID, sizeof(_cmsDICT)); | |||
900 | if (dict == NULL((void*)0)) return NULL((void*)0); | |||
901 | ||||
902 | dict ->ContextID = ContextID; | |||
903 | return (cmsHANDLE) dict; | |||
904 | ||||
905 | } | |||
906 | ||||
907 | // Dispose resources | |||
908 | void CMSEXPORT cmsDictFree(cmsHANDLE hDict) | |||
909 | { | |||
910 | _cmsDICT* dict = (_cmsDICT*) hDict; | |||
911 | cmsDICTentry *entry, *next; | |||
912 | ||||
913 | _cmsAssert(dict != NULL)(((dict != ((void*)0))) ? (void) (0) : __assert_fail ("(dict != ((void*)0))" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmsnamed.c" , 913, __extension__ __PRETTY_FUNCTION__)); | |||
914 | ||||
915 | // Walk the list freeing all nodes | |||
916 | entry = dict ->head; | |||
917 | while (entry != NULL((void*)0)) { | |||
918 | ||||
919 | if (entry ->DisplayName != NULL((void*)0)) cmsMLUfree(entry ->DisplayName); | |||
920 | if (entry ->DisplayValue != NULL((void*)0)) cmsMLUfree(entry ->DisplayValue); | |||
921 | if (entry ->Name != NULL((void*)0)) _cmsFree(dict ->ContextID, entry -> Name); | |||
922 | if (entry ->Value != NULL((void*)0)) _cmsFree(dict ->ContextID, entry -> Value); | |||
923 | ||||
924 | // Don't fall in the habitual trap... | |||
925 | next = entry ->Next; | |||
926 | _cmsFree(dict ->ContextID, entry); | |||
927 | ||||
928 | entry = next; | |||
929 | } | |||
930 | ||||
931 | _cmsFree(dict ->ContextID, dict); | |||
932 | } | |||
933 | ||||
934 | ||||
935 | // Duplicate a wide char string | |||
936 | static | |||
937 | wchar_t* DupWcs(cmsContext ContextID, const wchar_t* ptr) | |||
938 | { | |||
939 | if (ptr == NULL((void*)0)) return NULL((void*)0); | |||
940 | return (wchar_t*) _cmsDupMem(ContextID, ptr, (mywcslen(ptr) + 1) * sizeof(wchar_t)); | |||
941 | } | |||
942 | ||||
943 | // Add a new entry to the linked list | |||
944 | cmsBool CMSEXPORT cmsDictAddEntry(cmsHANDLE hDict, const wchar_t* Name, const wchar_t* Value, const cmsMLU *DisplayName, const cmsMLU *DisplayValue) | |||
945 | { | |||
946 | _cmsDICT* dict = (_cmsDICT*) hDict; | |||
947 | cmsDICTentry *entry; | |||
948 | ||||
949 | _cmsAssert(dict != NULL)(((dict != ((void*)0))) ? (void) (0) : __assert_fail ("(dict != ((void*)0))" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmsnamed.c" , 949, __extension__ __PRETTY_FUNCTION__)); | |||
950 | _cmsAssert(Name != NULL)(((Name != ((void*)0))) ? (void) (0) : __assert_fail ("(Name != ((void*)0))" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmsnamed.c" , 950, __extension__ __PRETTY_FUNCTION__)); | |||
951 | ||||
952 | entry = (cmsDICTentry*) _cmsMallocZero(dict ->ContextID, sizeof(cmsDICTentry)); | |||
953 | if (entry == NULL((void*)0)) return FALSE0; | |||
954 | ||||
955 | entry ->DisplayName = cmsMLUdup(DisplayName); | |||
956 | entry ->DisplayValue = cmsMLUdup(DisplayValue); | |||
957 | entry ->Name = DupWcs(dict ->ContextID, Name); | |||
958 | entry ->Value = DupWcs(dict ->ContextID, Value); | |||
959 | ||||
960 | entry ->Next = dict ->head; | |||
961 | dict ->head = entry; | |||
962 | ||||
963 | return TRUE1; | |||
964 | } | |||
965 | ||||
966 | ||||
967 | // Duplicates an existing dictionary | |||
968 | cmsHANDLE CMSEXPORT cmsDictDup(cmsHANDLE hDict) | |||
969 | { | |||
970 | _cmsDICT* old_dict = (_cmsDICT*) hDict; | |||
971 | cmsHANDLE hNew; | |||
972 | cmsDICTentry *entry; | |||
973 | ||||
974 | _cmsAssert(old_dict != NULL)(((old_dict != ((void*)0))) ? (void) (0) : __assert_fail ("(old_dict != ((void*)0))" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmsnamed.c" , 974, __extension__ __PRETTY_FUNCTION__)); | |||
975 | ||||
976 | hNew = cmsDictAlloc(old_dict ->ContextID); | |||
977 | if (hNew == NULL((void*)0)) return NULL((void*)0); | |||
978 | ||||
979 | // Walk the list freeing all nodes | |||
980 | entry = old_dict ->head; | |||
981 | while (entry != NULL((void*)0)) { | |||
982 | ||||
983 | if (!cmsDictAddEntry(hNew, entry ->Name, entry ->Value, entry ->DisplayName, entry ->DisplayValue)) { | |||
984 | ||||
985 | cmsDictFree(hNew); | |||
986 | return NULL((void*)0); | |||
987 | } | |||
988 | ||||
989 | entry = entry -> Next; | |||
990 | } | |||
991 | ||||
992 | return hNew; | |||
993 | } | |||
994 | ||||
995 | // Get a pointer to the linked list | |||
996 | const cmsDICTentry* CMSEXPORT cmsDictGetEntryList(cmsHANDLE hDict) | |||
997 | { | |||
998 | _cmsDICT* dict = (_cmsDICT*) hDict; | |||
999 | ||||
1000 | if (dict == NULL((void*)0)) return NULL((void*)0); | |||
1001 | return dict ->head; | |||
1002 | } | |||
1003 | ||||
1004 | // Helper For external languages | |||
1005 | const cmsDICTentry* CMSEXPORT cmsDictNextEntry(const cmsDICTentry* e) | |||
1006 | { | |||
1007 | if (e == NULL((void*)0)) return NULL((void*)0); | |||
1008 | return e ->Next; | |||
1009 | } |