25 // This file is available under and governed by the GNU General Public |
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. |
26 // License version 2 only, as published by the Free Software Foundation. |
27 // However, the following notice accompanied the original version of this |
27 // However, the following notice accompanied the original version of this |
28 // file: |
28 // file: |
29 // |
29 // |
|
30 //--------------------------------------------------------------------------------- |
30 // |
31 // |
31 // Little cms |
32 // Little Color Management System |
32 // Copyright (C) 1998-2007 Marti Maria |
33 // Copyright (c) 1998-2010 Marti Maria Saguer |
33 // |
34 // |
34 // Permission is hereby granted, free of charge, to any person obtaining |
35 // Permission is hereby granted, free of charge, to any person obtaining |
35 // a copy of this software and associated documentation files (the "Software"), |
36 // a copy of this software and associated documentation files (the "Software"), |
36 // to deal in the Software without restriction, including without limitation |
37 // to deal in the Software without restriction, including without limitation |
37 // the rights to use, copy, modify, merge, publish, distribute, sublicense, |
38 // the rights to use, copy, modify, merge, publish, distribute, sublicense, |
47 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
48 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
49 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
50 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
51 // |
52 // |
52 // IT8.7 / CGATS.17-200x handling |
53 //--------------------------------------------------------------------------------- |
53 |
54 // |
54 #include "lcms.h" |
55 |
55 |
56 #include "lcms2_internal.h" |
56 |
57 |
57 LCMSAPI LCMSHANDLE LCMSEXPORT cmsIT8Alloc(void); |
58 |
58 LCMSAPI void LCMSEXPORT cmsIT8Free(LCMSHANDLE IT8); |
59 // IT8.7 / CGATS.17-200x handling ----------------------------------------------------------------------------- |
59 |
60 |
60 // Tables |
61 |
61 |
62 #define MAXID 128 // Max lenght of identifier |
62 LCMSAPI int LCMSEXPORT cmsIT8TableCount(LCMSHANDLE IT8); |
|
63 LCMSAPI int LCMSEXPORT cmsIT8SetTable(LCMSHANDLE IT8, int nTable); |
|
64 |
|
65 // Persistence |
|
66 LCMSAPI LCMSHANDLE LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName); |
|
67 LCMSAPI LCMSHANDLE LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len); |
|
68 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName); |
|
69 |
|
70 // Properties |
|
71 LCMSAPI const char* LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8); |
|
72 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type); |
|
73 |
|
74 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment); |
|
75 |
|
76 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str); |
|
77 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val); |
|
78 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val); |
|
79 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char* cSubProp, const char *Val); |
|
80 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer); |
|
81 |
|
82 LCMSAPI const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* cProp); |
|
83 LCMSAPI double LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp); |
|
84 LCMSAPI const char* LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char *cSubProp); |
|
85 LCMSAPI int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, const char ***PropertyNames); |
|
86 LCMSAPI int LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char*** SubpropertyNames); |
|
87 |
|
88 // Datasets |
|
89 |
|
90 LCMSAPI const char* LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buffer); |
|
91 |
|
92 LCMSAPI const char* LCMSEXPORT cmsIT8GetDataRowCol(LCMSHANDLE IT8, int row, int col); |
|
93 LCMSAPI double LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE IT8, int col, int row); |
|
94 |
|
95 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, |
|
96 const char* Val); |
|
97 |
|
98 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, |
|
99 double Val); |
|
100 |
|
101 LCMSAPI const char* LCMSEXPORT cmsIT8GetData(LCMSHANDLE IT8, const char* cPatch, const char* cSample); |
|
102 |
|
103 |
|
104 LCMSAPI double LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE IT8, const char* cPatch, const char* cSample); |
|
105 |
|
106 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch, |
|
107 const char* cSample, |
|
108 const char *Val); |
|
109 |
|
110 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch, |
|
111 const char* cSample, |
|
112 double Val); |
|
113 |
|
114 LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample); |
|
115 LCMSAPI int LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE IT8, char ***SampleNames); |
|
116 |
|
117 LCMSAPI void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE IT8, const char* Formatter); |
|
118 |
|
119 LCMSAPI int LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const char* cSet, |
|
120 const char* cField, |
|
121 const char* ExpectedType); |
|
122 |
|
123 // ------------------------------------------------------------- Implementation |
|
124 |
|
125 |
|
126 #define SIZEOFLONGMINUS1 (sizeof(long)-1) |
|
127 #define ALIGNLONG(x) (((x)+SIZEOFLONGMINUS1) & ~(SIZEOFLONGMINUS1)) |
|
128 |
|
129 // #define STRICT_CGATS 1 |
|
130 |
|
131 #define MAXID 128 // Max lenght of identifier |
|
132 #define MAXSTR 1024 // Max lenght of string |
63 #define MAXSTR 1024 // Max lenght of string |
133 #define MAXTABLES 255 // Max Number of tables in a single stream |
64 #define MAXTABLES 255 // Max Number of tables in a single stream |
134 #define MAXINCLUDE 20 // Max number of nested includes |
65 #define MAXINCLUDE 20 // Max number of nested includes |
135 |
66 |
136 #define DEFAULT_DBL_FORMAT "%.10g" // Double formatting |
67 #define DEFAULT_DBL_FORMAT "%.10g" // Double formatting |
137 |
68 |
138 #include <ctype.h> |
69 #ifdef CMS_IS_WINDOWS_ |
139 #include <limits.h> |
70 # include <io.h> |
140 |
71 # define DIR_CHAR '\\' |
141 #ifndef NON_WINDOWS |
|
142 #include <io.h> |
|
143 #define DIR_CHAR '\\' |
|
144 #else |
72 #else |
145 #define DIR_CHAR '/' |
73 # define DIR_CHAR '/' |
146 #endif |
74 #endif |
147 |
75 |
148 // Symbols |
76 // Symbols |
149 |
|
150 typedef enum { |
77 typedef enum { |
151 |
78 |
152 SNONE, |
79 SNONE, |
153 SINUM, // Integer |
80 SINUM, // Integer |
154 SDNUM, // Real |
81 SDNUM, // Real |
171 |
98 |
172 } SYMBOL; |
99 } SYMBOL; |
173 |
100 |
174 |
101 |
175 // How to write the value |
102 // How to write the value |
176 |
|
177 typedef enum { |
103 typedef enum { |
|
104 |
178 WRITE_UNCOOKED, |
105 WRITE_UNCOOKED, |
179 WRITE_STRINGIFY, |
106 WRITE_STRINGIFY, |
180 WRITE_HEXADECIMAL, |
107 WRITE_HEXADECIMAL, |
181 WRITE_BINARY, |
108 WRITE_BINARY, |
182 WRITE_PAIR |
109 WRITE_PAIR |
183 |
110 |
184 } WRITEMODE; |
111 } WRITEMODE; |
185 |
112 |
186 // Linked list of variable names |
113 // Linked list of variable names |
187 |
|
188 typedef struct _KeyVal { |
114 typedef struct _KeyVal { |
189 |
115 |
190 struct _KeyVal* Next; |
116 struct _KeyVal* Next; |
191 char* Keyword; // Name of variable |
117 char* Keyword; // Name of variable |
192 struct _KeyVal* NextSubkey; // If key is a dictionary, points to the next item |
118 struct _KeyVal* NextSubkey; // If key is a dictionary, points to the next item |
193 char* Subkey; // If key is a dictionary, points to the subkey name |
119 char* Subkey; // If key is a dictionary, points to the subkey name |
194 char* Value; // Points to value |
120 char* Value; // Points to value |
195 WRITEMODE WriteAs; // How to write the value |
121 WRITEMODE WriteAs; // How to write the value |
196 |
122 |
197 } KEYVALUE, *LPKEYVALUE; |
123 } KEYVALUE; |
198 |
124 |
199 |
125 |
200 // Linked list of memory chunks (Memory sink) |
126 // Linked list of memory chunks (Memory sink) |
201 |
|
202 typedef struct _OwnedMem { |
127 typedef struct _OwnedMem { |
203 |
128 |
204 struct _OwnedMem* Next; |
129 struct _OwnedMem* Next; |
205 void * Ptr; // Point to value |
130 void * Ptr; // Point to value |
206 |
131 |
207 } OWNEDMEM, *LPOWNEDMEM; |
132 } OWNEDMEM; |
208 |
133 |
209 // Suballocator |
134 // Suballocator |
210 |
|
211 typedef struct _SubAllocator { |
135 typedef struct _SubAllocator { |
212 |
136 |
213 LPBYTE Block; |
137 cmsUInt8Number* Block; |
214 size_t BlockSize; |
138 cmsUInt32Number BlockSize; |
215 size_t Used; |
139 cmsUInt32Number Used; |
216 |
140 |
217 } SUBALLOCATOR, *LPSUBALLOCATOR; |
141 } SUBALLOCATOR; |
218 |
142 |
219 // Table. Each individual table can hold properties and rows & cols |
143 // Table. Each individual table can hold properties and rows & cols |
220 |
|
221 typedef struct _Table { |
144 typedef struct _Table { |
222 |
145 |
223 int nSamples, nPatches; // Cols, Rows |
146 int nSamples, nPatches; // Cols, Rows |
224 int SampleID; // Pos of ID |
147 int SampleID; // Pos of ID |
225 |
148 |
226 LPKEYVALUE HeaderList; // The properties |
149 KEYVALUE* HeaderList; // The properties |
227 |
150 |
228 char** DataFormat; // The binary stream descriptor |
151 char** DataFormat; // The binary stream descriptor |
229 char** Data; // The binary stream |
152 char** Data; // The binary stream |
230 |
153 |
231 } TABLE, *LPTABLE; |
154 } TABLE; |
232 |
155 |
233 // File stream being parsed |
156 // File stream being parsed |
234 |
|
235 typedef struct _FileContext { |
157 typedef struct _FileContext { |
236 char FileName[MAX_PATH]; // File name if being readed from file |
158 char FileName[cmsMAX_PATH]; // File name if being readed from file |
237 FILE* Stream; // File stream or NULL if holded in memory |
159 FILE* Stream; // File stream or NULL if holded in memory |
238 } FILECTX, *LPFILECTX; |
160 } FILECTX; |
239 |
161 |
240 // This struct hold all information about an openened |
162 // This struct hold all information about an open IT8 handler. |
241 // IT8 handler. Only one dataset is allowed. |
|
242 |
|
243 typedef struct { |
163 typedef struct { |
244 |
164 |
245 char SheetType[MAXSTR]; |
165 char SheetType[MAXSTR]; // The first row of the IT8 (the type) |
246 |
166 |
247 int TablesCount; // How many tables in this stream |
167 cmsUInt32Number TablesCount; // How many tables in this stream |
248 int nTable; // The actual table |
168 cmsUInt32Number nTable; // The actual table |
249 |
169 |
250 TABLE Tab[MAXTABLES]; |
170 TABLE Tab[MAXTABLES]; |
251 |
171 |
252 // Memory management |
172 // Memory management |
253 |
173 OWNEDMEM* MemorySink; // The storage backend |
254 LPOWNEDMEM MemorySink; // The storage backend |
|
255 SUBALLOCATOR Allocator; // String suballocator -- just to keep it fast |
174 SUBALLOCATOR Allocator; // String suballocator -- just to keep it fast |
256 |
175 |
257 // Parser state machine |
176 // Parser state machine |
258 |
|
259 SYMBOL sy; // Current symbol |
177 SYMBOL sy; // Current symbol |
260 int ch; // Current character |
178 int ch; // Current character |
261 |
179 |
262 int inum; // integer value |
180 int inum; // integer value |
263 double dnum; // real value |
181 cmsFloat64Number dnum; // real value |
264 char id[MAXID]; // identifier |
182 char id[MAXID]; // identifier |
265 char str[MAXSTR]; // string |
183 char str[MAXSTR]; // string |
266 |
184 |
267 // Allowed keywords & datasets. They have visibility on whole stream |
185 // Allowed keywords & datasets. They have visibility on whole stream |
268 |
186 KEYVALUE* ValidKeywords; |
269 LPKEYVALUE ValidKeywords; |
187 KEYVALUE* ValidSampleID; |
270 LPKEYVALUE ValidSampleID; |
|
271 |
188 |
272 char* Source; // Points to loc. being parsed |
189 char* Source; // Points to loc. being parsed |
273 int lineno; // line counter for error reporting |
190 int lineno; // line counter for error reporting |
274 |
191 |
275 LPFILECTX FileStack[MAXINCLUDE]; // Stack of files being parsed |
192 FILECTX* FileStack[MAXINCLUDE]; // Stack of files being parsed |
276 int IncludeSP; // Include Stack Pointer |
193 int IncludeSP; // Include Stack Pointer |
277 |
194 |
278 char* MemoryBlock; // The stream if holded in memory |
195 char* MemoryBlock; // The stream if holded in memory |
279 |
196 |
280 char DoubleFormatter[MAXID]; // Printf-like 'double' formatter |
197 char DoubleFormatter[MAXID];// Printf-like 'cmsFloat64Number' formatter |
281 |
198 |
282 } IT8, *LPIT8; |
199 cmsContext ContextID; // The threading context |
283 |
200 |
284 |
201 } cmsIT8; |
285 |
202 |
|
203 |
|
204 // The stream for save operations |
286 typedef struct { |
205 typedef struct { |
287 |
206 |
288 FILE* stream; // For save-to-file behaviour |
207 FILE* stream; // For save-to-file behaviour |
289 |
208 |
290 LPBYTE Base; |
209 cmsUInt8Number* Base; |
291 LPBYTE Ptr; // For save-to-mem behaviour |
210 cmsUInt8Number* Ptr; // For save-to-mem behaviour |
292 size_t Used; |
211 cmsUInt32Number Used; |
293 size_t Max; |
212 cmsUInt32Number Max; |
294 |
213 |
295 } SAVESTREAM, FAR* LPSAVESTREAM; |
214 } SAVESTREAM; |
296 |
215 |
297 |
216 |
298 // ------------------------------------------------------ IT8 parsing routines |
217 // ------------------------------------------------------ cmsIT8 parsing routines |
299 |
218 |
300 |
219 |
301 // A keyword |
220 // A keyword |
302 typedef struct { |
221 typedef struct { |
303 |
222 |
307 } KEYWORD; |
226 } KEYWORD; |
308 |
227 |
309 // The keyword->symbol translation table. Sorting is required. |
228 // The keyword->symbol translation table. Sorting is required. |
310 static const KEYWORD TabKeys[] = { |
229 static const KEYWORD TabKeys[] = { |
311 |
230 |
312 {"$INCLUDE", SINCLUDE}, |
231 {"$INCLUDE", SINCLUDE}, // This is an extension! |
313 {".INCLUDE", SINCLUDE}, |
232 {".INCLUDE", SINCLUDE}, // This is an extension! |
314 {"BEGIN_DATA", SBEGIN_DATA }, |
233 |
315 {"BEGIN_DATA_FORMAT", SBEGIN_DATA_FORMAT }, |
234 {"BEGIN_DATA", SBEGIN_DATA }, |
|
235 {"BEGIN_DATA_FORMAT", SBEGIN_DATA_FORMAT }, |
316 {"DATA_FORMAT_IDENTIFIER", SDATA_FORMAT_ID}, |
236 {"DATA_FORMAT_IDENTIFIER", SDATA_FORMAT_ID}, |
317 {"END_DATA", SEND_DATA}, |
237 {"END_DATA", SEND_DATA}, |
318 {"END_DATA_FORMAT", SEND_DATA_FORMAT}, |
238 {"END_DATA_FORMAT", SEND_DATA_FORMAT}, |
319 {"KEYWORD", SKEYWORD} |
239 {"KEYWORD", SKEYWORD} |
320 }; |
240 }; |
321 |
241 |
322 #define NUMKEYS (sizeof(TabKeys)/sizeof(KEYWORD)) |
242 #define NUMKEYS (sizeof(TabKeys)/sizeof(KEYWORD)) |
323 |
243 |
324 // Predefined properties |
244 // Predefined properties |
325 |
245 |
326 // A property |
246 // A property |
327 typedef struct { |
247 typedef struct { |
328 const char *id; |
248 const char *id; // The identifier |
329 WRITEMODE as; |
249 WRITEMODE as; // How is supposed to be written |
330 } PROPERTY; |
250 } PROPERTY; |
331 |
251 |
332 static PROPERTY PredefinedProperties[] = { |
252 static PROPERTY PredefinedProperties[] = { |
333 |
253 |
334 {"NUMBER_OF_FIELDS", WRITE_UNCOOKED}, // Required - NUMBER OF FIELDS |
254 {"NUMBER_OF_FIELDS", WRITE_UNCOOKED}, // Required - NUMBER OF FIELDS |
364 {"SAMPLE_BACKING", WRITE_STRINGIFY}, // Identifies the backing material used behind the sample during |
284 {"SAMPLE_BACKING", WRITE_STRINGIFY}, // Identifies the backing material used behind the sample during |
365 // measurement. Allowed values are “black”, “white”, or {"na". |
285 // measurement. Allowed values are “black”, “white”, or {"na". |
366 |
286 |
367 {"CHISQ_DOF", WRITE_STRINGIFY}, // Degrees of freedom associated with the Chi squared statistic |
287 {"CHISQ_DOF", WRITE_STRINGIFY}, // Degrees of freedom associated with the Chi squared statistic |
368 |
288 |
369 // new in recent specs: |
289 // below properties are new in recent specs: |
|
290 |
370 {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated |
291 {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated |
371 // along with details of the geometry and the aperture size and shape. For example, |
292 // along with details of the geometry and the aperture size and shape. For example, |
372 // for transmission measurements it is important to identify 0/diffuse, diffuse/0, |
293 // for transmission measurements it is important to identify 0/diffuse, diffuse/0, |
373 // opal or integrating sphere, etc. For reflection it is important to identify 0/45, |
294 // opal or integrating sphere, etc. For reflection it is important to identify 0/45, |
374 // 45/0, sphere (specular included or excluded), etc. |
295 // 45/0, sphere (specular included or excluded), etc. |
436 "LAB_L", // L* component of Lab data |
357 "LAB_L", // L* component of Lab data |
437 "LAB_A", // a* component of Lab data |
358 "LAB_A", // a* component of Lab data |
438 "LAB_B", // b* component of Lab data |
359 "LAB_B", // b* component of Lab data |
439 "LAB_C", // C*ab component of Lab data |
360 "LAB_C", // C*ab component of Lab data |
440 "LAB_H", // hab component of Lab data |
361 "LAB_H", // hab component of Lab data |
441 "LAB_DE", // CIE dE |
362 "LAB_DE", // CIE dE |
442 "LAB_DE_94", // CIE dE using CIE 94 |
363 "LAB_DE_94", // CIE dE using CIE 94 |
443 "LAB_DE_CMC", // dE using CMC |
364 "LAB_DE_CMC", // dE using CMC |
444 "LAB_DE_2000", // CIE dE using CIE DE 2000 |
365 "LAB_DE_2000", // CIE dE using CIE DE 2000 |
445 "MEAN_DE", // Mean Delta E (LAB_DE) of samples compared to batch average |
366 "MEAN_DE", // Mean Delta E (LAB_DE) of samples compared to batch average |
446 // (Used for data files for ANSI IT8.7/1 and IT8.7/2 targets) |
367 // (Used for data files for ANSI IT8.7/1 and IT8.7/2 targets) |
447 "STDEV_X", // Standard deviation of X (tristimulus data) |
368 "STDEV_X", // Standard deviation of X (tristimulus data) |
448 "STDEV_Y", // Standard deviation of Y (tristimulus data) |
369 "STDEV_Y", // Standard deviation of Y (tristimulus data) |
456 // recommended as the predictor of the variability of dE |
377 // recommended as the predictor of the variability of dE |
457 |
378 |
458 #define NUMPREDEFINEDSAMPLEID (sizeof(PredefinedSampleID)/sizeof(char *)) |
379 #define NUMPREDEFINEDSAMPLEID (sizeof(PredefinedSampleID)/sizeof(char *)) |
459 |
380 |
460 //Forward declaration of some internal functions |
381 //Forward declaration of some internal functions |
461 static |
382 static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size); |
462 void* AllocChunk(LPIT8 it8, size_t size); |
|
463 |
383 |
464 // Checks if c is a separator |
384 // Checks if c is a separator |
465 static |
385 static |
466 LCMSBOOL isseparator(int c) |
386 cmsBool isseparator(int c) |
467 { |
387 { |
468 return (c == ' ') || (c == '\t') || (c == '\r'); |
388 return (c == ' ') || (c == '\t') || (c == '\r'); |
469 } |
389 } |
470 |
390 |
471 // Checks whatever if c is a valid identifier char |
391 // Checks whatever if c is a valid identifier char |
472 static |
392 static |
473 LCMSBOOL ismiddle(int c) |
393 cmsBool ismiddle(int c) |
474 { |
394 { |
475 return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127)); |
395 return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127)); |
476 } |
396 } |
477 |
397 |
478 // Checks whatsever if c is a valid identifier middle char. |
398 // Checks whatsever if c is a valid identifier middle char. |
479 static |
399 static |
480 LCMSBOOL isidchar(int c) |
400 cmsBool isidchar(int c) |
481 { |
401 { |
482 return isalnum(c) || ismiddle(c); |
402 return isalnum(c) || ismiddle(c); |
483 } |
403 } |
484 |
404 |
485 // Checks whatsever if c is a valid identifier first char. |
405 // Checks whatsever if c is a valid identifier first char. |
486 static |
406 static |
487 LCMSBOOL isfirstidchar(int c) |
407 cmsBool isfirstidchar(int c) |
488 { |
408 { |
489 return !isdigit(c) && ismiddle(c); |
409 return !isdigit(c) && ismiddle(c); |
490 } |
410 } |
491 |
411 |
492 // checks whether the supplied path looks like an absolute path |
412 // Guess whether the supplied path looks like an absolute path |
493 // NOTE: this function doesn't checks if the path exists or even if it's legal |
413 static |
494 static |
414 cmsBool isabsolutepath(const char *path) |
495 LCMSBOOL isabsolutepath(const char *path) |
415 { |
496 { |
416 char ThreeChars[4]; |
|
417 |
497 if(path == NULL) |
418 if(path == NULL) |
498 return FALSE; |
419 return FALSE; |
499 |
420 if (path[0] == 0) |
500 if(path[0] == DIR_CHAR) |
421 return FALSE; |
|
422 |
|
423 strncpy(ThreeChars, path, 3); |
|
424 ThreeChars[3] = 0; |
|
425 |
|
426 if(ThreeChars[0] == DIR_CHAR) |
501 return TRUE; |
427 return TRUE; |
502 |
428 |
503 #ifndef NON_WINDOWS |
429 #ifdef CMS_IS_WINDOWS_ |
504 if(isalpha(path[0]) && path[1] == ':') |
430 if (isalpha((int) ThreeChars[0]) && ThreeChars[1] == ':') |
505 return TRUE; |
431 return TRUE; |
506 #endif |
432 #endif |
507 return FALSE; |
433 return FALSE; |
508 } |
434 } |
509 |
435 |
510 // Makes a file path based on a given reference path |
436 // Makes a file path based on a given reference path |
511 // NOTE: buffer is assumed to point to at least MAX_PATH bytes |
|
512 // NOTE: both relPath and basePath are assumed to be no more than MAX_PATH characters long (including the null terminator!) |
|
513 // NOTE: this function doesn't check if the path exists or even if it's legal |
437 // NOTE: this function doesn't check if the path exists or even if it's legal |
514 static |
438 static |
515 LCMSBOOL _cmsMakePath(const char *relPath, const char *basePath, char *buffer) |
439 cmsBool BuildAbsolutePath(const char *relPath, const char *basePath, char *buffer, cmsUInt32Number MaxLen) |
516 { |
440 { |
517 if (!isabsolutepath(relPath)) { |
441 char *tail; |
518 |
442 cmsUInt32Number len; |
519 char *tail; |
443 |
520 |
444 // Already absolute? |
521 strncpy(buffer, basePath, MAX_PATH-1); |
445 if (isabsolutepath(relPath)) { |
522 tail = strrchr(buffer, DIR_CHAR); |
446 |
523 if (tail != NULL) { |
447 strncpy(buffer, relPath, MaxLen); |
524 |
448 buffer[MaxLen-1] = 0; |
525 size_t len = tail - buffer; |
449 return TRUE; |
526 strncpy(tail + 1, relPath, MAX_PATH - len -1); |
450 } |
527 // TODO: if combined path is longer than MAX_PATH, this should return FALSE! |
451 |
528 return TRUE; |
452 // No, search for last |
529 } |
453 strncpy(buffer, basePath, MaxLen); |
530 } |
454 buffer[MaxLen-1] = 0; |
531 strncpy(buffer, relPath, MAX_PATH - 1); |
455 |
532 buffer[MAX_PATH-1] = 0; |
456 tail = strrchr(buffer, DIR_CHAR); |
|
457 if (tail == NULL) return FALSE; // Is not absolute and has no separators?? |
|
458 |
|
459 len = (cmsUInt32Number) (tail - buffer); |
|
460 if (len >= MaxLen) return FALSE; |
|
461 |
|
462 // No need to assure zero terminator over here |
|
463 strncpy(tail + 1, relPath, MaxLen - len); |
|
464 |
533 return TRUE; |
465 return TRUE; |
534 } |
466 } |
535 |
467 |
536 |
468 |
537 // Make sure no exploit is being even tried |
469 // Make sure no exploit is being even tried |
538 |
|
539 static |
470 static |
540 const char* NoMeta(const char* str) |
471 const char* NoMeta(const char* str) |
541 { |
472 { |
542 if (strchr(str, '%') != NULL) |
473 if (strchr(str, '%') != NULL) |
543 return "**** CORRUPTED FORMAT STRING ***"; |
474 return "**** CORRUPTED FORMAT STRING ***"; |
544 |
475 |
545 return str; |
476 return str; |
546 } |
477 } |
547 |
478 |
548 |
|
549 // Syntax error |
479 // Syntax error |
550 static |
480 static |
551 LCMSBOOL SynError(LPIT8 it8, const char *Txt, ...) |
481 cmsBool SynError(cmsIT8* it8, const char *Txt, ...) |
552 { |
482 { |
553 char Buffer[256], ErrMsg[1024]; |
483 char Buffer[256], ErrMsg[1024]; |
554 va_list args; |
484 va_list args; |
555 |
485 |
556 va_start(args, Txt); |
486 va_start(args, Txt); |
557 vsnprintf(Buffer, 255, Txt, args); |
487 vsnprintf(Buffer, 255, Txt, args); |
558 Buffer[255] = 0; |
488 Buffer[255] = 0; |
559 va_end(args); |
489 va_end(args); |
560 |
490 |
561 snprintf(ErrMsg, 1023, "%s: Line %d, %s", it8->FileStack[it8 ->IncludeSP]->FileName, it8->lineno, Buffer); |
491 snprintf(ErrMsg, 1023, "%s: Line %d, %s", it8->FileStack[it8 ->IncludeSP]->FileName, it8->lineno, Buffer); |
562 ErrMsg[1023] = 0; |
492 ErrMsg[1023] = 0; |
563 it8->sy = SSYNERROR; |
493 it8->sy = SSYNERROR; |
564 cmsSignalError(LCMS_ERRC_ABORTED, "%s", ErrMsg); |
494 cmsSignalError(it8 ->ContextID, cmsERROR_CORRUPTION_DETECTED, "%s", ErrMsg); |
565 return FALSE; |
495 return FALSE; |
566 } |
496 } |
567 |
497 |
568 // Check if current symbol is same as specified. issue an error else. |
498 // Check if current symbol is same as specified. issue an error else. |
569 static |
499 static |
570 LCMSBOOL Check(LPIT8 it8, SYMBOL sy, const char* Err) |
500 cmsBool Check(cmsIT8* it8, SYMBOL sy, const char* Err) |
571 { |
501 { |
572 if (it8 -> sy != sy) |
502 if (it8 -> sy != sy) |
573 return SynError(it8, NoMeta(Err)); |
503 return SynError(it8, NoMeta(Err)); |
574 return TRUE; |
504 return TRUE; |
575 } |
505 } |
576 |
506 |
577 |
|
578 |
|
579 // Read Next character from stream |
507 // Read Next character from stream |
580 static |
508 static |
581 void NextCh(LPIT8 it8) |
509 void NextCh(cmsIT8* it8) |
582 { |
510 { |
583 if (it8 -> FileStack[it8 ->IncludeSP]->Stream) { |
511 if (it8 -> FileStack[it8 ->IncludeSP]->Stream) { |
584 |
512 |
585 it8 ->ch = fgetc(it8 ->FileStack[it8 ->IncludeSP]->Stream); |
513 it8 ->ch = fgetc(it8 ->FileStack[it8 ->IncludeSP]->Stream); |
586 |
514 |
607 |
532 |
608 // Try to see if current identifier is a keyword, if so return the referred symbol |
533 // Try to see if current identifier is a keyword, if so return the referred symbol |
609 static |
534 static |
610 SYMBOL BinSrchKey(const char *id) |
535 SYMBOL BinSrchKey(const char *id) |
611 { |
536 { |
612 int l = 1; |
537 int l = 1; |
613 int r = NUMKEYS; |
538 int r = NUMKEYS; |
614 int x, res; |
539 int x, res; |
615 |
540 |
616 while (r >= l) |
541 while (r >= l) |
617 { |
542 { |
618 x = (l+r)/2; |
543 x = (l+r)/2; |
619 res = stricmp(id, TabKeys[x-1].id); |
544 res = cmsstrcasecmp(id, TabKeys[x-1].id); |
620 if (res == 0) return TabKeys[x-1].sy; |
545 if (res == 0) return TabKeys[x-1].sy; |
621 if (res < 0) r = x - 1; |
546 if (res < 0) r = x - 1; |
622 else l = x + 1; |
547 else l = x + 1; |
623 } |
548 } |
624 |
549 |
625 return SNONE; |
550 return SNONE; |
626 } |
551 } |
627 |
552 |
628 |
553 |
629 // 10 ^n |
554 // 10 ^n |
630 static |
555 static |
631 double xpow10(int n) |
556 cmsFloat64Number xpow10(int n) |
632 { |
557 { |
633 return pow(10, (double) n); |
558 return pow(10, (cmsFloat64Number) n); |
634 } |
559 } |
635 |
560 |
636 |
561 |
637 // Reads a Real number, tries to follow from integer number |
562 // Reads a Real number, tries to follow from integer number |
638 static |
563 static |
639 void ReadReal(LPIT8 it8, int inum) |
564 void ReadReal(cmsIT8* it8, int inum) |
640 { |
565 { |
641 it8->dnum = (double) inum; |
566 it8->dnum = (cmsFloat64Number) inum; |
642 |
567 |
643 while (isdigit(it8->ch)) { |
568 while (isdigit(it8->ch)) { |
644 |
569 |
645 it8->dnum = it8->dnum * 10.0 + (it8->ch - '0'); |
570 it8->dnum = it8->dnum * 10.0 + (it8->ch - '0'); |
646 NextCh(it8); |
571 NextCh(it8); |
647 } |
572 } |
648 |
573 |
649 if (it8->ch == '.') { // Decimal point |
574 if (it8->ch == '.') { // Decimal point |
650 |
575 |
651 double frac = 0.0; // fraction |
576 cmsFloat64Number frac = 0.0; // fraction |
652 int prec = 0; // precission |
577 int prec = 0; // precision |
653 |
578 |
654 NextCh(it8); // Eats dec. point |
579 NextCh(it8); // Eats dec. point |
655 |
580 |
656 while (isdigit(it8->ch)) { |
581 while (isdigit(it8->ch)) { |
657 |
582 |
658 frac = frac * 10.0 + (it8->ch - '0'); |
583 frac = frac * 10.0 + (it8->ch - '0'); |
659 prec++; |
584 prec++; |
660 NextCh(it8); |
585 NextCh(it8); |
661 } |
586 } |
662 |
587 |
663 it8->dnum = it8->dnum + (frac / xpow10(prec)); |
588 it8->dnum = it8->dnum + (frac / xpow10(prec)); |
664 } |
589 } |
665 |
590 |
666 // Exponent, example 34.00E+20 |
591 // Exponent, example 34.00E+20 |
667 if (toupper(it8->ch) == 'E') { |
592 if (toupper(it8->ch) == 'E') { |
668 |
593 |
669 int e; |
594 int e; |
670 int sgn; |
595 int sgn; |
671 |
596 |
672 NextCh(it8); sgn = 1; |
597 NextCh(it8); sgn = 1; |
673 |
598 |
674 if (it8->ch == '-') { |
599 if (it8->ch == '-') { |
675 |
600 |
676 sgn = -1; NextCh(it8); |
601 sgn = -1; NextCh(it8); |
677 } |
602 } |
678 else |
603 else |
679 if (it8->ch == '+') { |
604 if (it8->ch == '+') { |
680 |
605 |
681 sgn = +1; |
606 sgn = +1; |
682 NextCh(it8); |
607 NextCh(it8); |
683 } |
608 } |
684 |
609 |
685 |
610 e = 0; |
686 e = 0; |
611 while (isdigit(it8->ch)) { |
687 while (isdigit(it8->ch)) { |
612 |
688 |
613 if ((cmsFloat64Number) e * 10L < INT_MAX) |
689 if ((double) e * 10L < INT_MAX) |
614 e = e * 10 + (it8->ch - '0'); |
690 e = e * 10 + (it8->ch - '0'); |
615 |
691 |
616 NextCh(it8); |
692 NextCh(it8); |
617 } |
693 } |
618 |
694 |
619 e = sgn*e; |
695 e = sgn*e; |
620 it8 -> dnum = it8 -> dnum * xpow10(e); |
696 |
621 } |
697 it8 -> dnum = it8 -> dnum * xpow10(e); |
|
698 } |
|
699 } |
622 } |
700 |
623 |
701 |
624 |
702 |
625 |
703 // Reads next symbol |
626 // Reads next symbol |
704 static |
627 static |
705 void InSymbol(LPIT8 it8) |
628 void InSymbol(cmsIT8* it8) |
706 { |
629 { |
707 register char *idptr; |
630 register char *idptr; |
708 register int k; |
631 register int k; |
709 SYMBOL key; |
632 SYMBOL key; |
710 int sng; |
633 int sng; |
919 |
836 |
920 // Handle the include special token |
837 // Handle the include special token |
921 |
838 |
922 if (it8 -> sy == SINCLUDE) { |
839 if (it8 -> sy == SINCLUDE) { |
923 |
840 |
924 LPFILECTX FileNest; |
841 FILECTX* FileNest; |
925 |
842 |
926 if(it8 -> IncludeSP >= (MAXINCLUDE-1)) |
843 if(it8 -> IncludeSP >= (MAXINCLUDE-1)) { |
927 { |
844 |
928 SynError(it8, "Too many recursion levels"); |
845 SynError(it8, "Too many recursion levels"); |
929 return; |
846 return; |
930 } |
847 } |
931 |
848 |
932 InSymbol(it8); |
849 InSymbol(it8); |
933 if (!Check(it8, SSTRING, "Filename expected")) return; |
850 if (!Check(it8, SSTRING, "Filename expected")) return; |
934 |
851 |
935 FileNest = it8 -> FileStack[it8 -> IncludeSP + 1]; |
852 FileNest = it8 -> FileStack[it8 -> IncludeSP + 1]; |
936 if(FileNest == NULL) |
853 if(FileNest == NULL) { |
937 { |
854 |
938 FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX)); |
855 FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX)); |
939 //if(FileNest == NULL) |
856 //if(FileNest == NULL) |
940 // TODO: how to manage out-of-memory conditions? |
857 // TODO: how to manage out-of-memory conditions? |
941 } |
858 } |
942 |
859 |
943 if(_cmsMakePath(it8->str, it8->FileStack[it8->IncludeSP]->FileName, FileNest->FileName) == FALSE) |
860 if (BuildAbsolutePath(it8->str, |
944 { |
861 it8->FileStack[it8->IncludeSP]->FileName, |
|
862 FileNest->FileName, cmsMAX_PATH-1) == FALSE) { |
945 SynError(it8, "File path too long"); |
863 SynError(it8, "File path too long"); |
946 return; |
864 return; |
947 } |
865 } |
948 |
866 |
949 FileNest->Stream = fopen(FileNest->FileName, "rt"); |
867 FileNest->Stream = fopen(FileNest->FileName, "rt"); |
1030 } |
948 } |
1031 |
949 |
1032 // ---------------------------------------------------------- Memory management |
950 // ---------------------------------------------------------- Memory management |
1033 |
951 |
1034 |
952 |
1035 |
|
1036 // Frees an allocator and owned memory |
953 // Frees an allocator and owned memory |
1037 void LCMSEXPORT cmsIT8Free(LCMSHANDLE hIT8) |
954 void CMSEXPORT cmsIT8Free(cmsHANDLE hIT8) |
1038 { |
955 { |
1039 LPIT8 it8 = (LPIT8) hIT8; |
956 cmsIT8* it8 = (cmsIT8*) hIT8; |
1040 |
957 |
1041 if (it8 == NULL) |
958 if (it8 == NULL) |
1042 return; |
959 return; |
1043 |
960 |
1044 |
|
1045 if (it8->MemorySink) { |
961 if (it8->MemorySink) { |
1046 |
962 |
1047 LPOWNEDMEM p; |
963 OWNEDMEM* p; |
1048 LPOWNEDMEM n; |
964 OWNEDMEM* n; |
1049 |
965 |
1050 for (p = it8->MemorySink; p != NULL; p = n) { |
966 for (p = it8->MemorySink; p != NULL; p = n) { |
1051 |
967 |
1052 n = p->Next; |
968 n = p->Next; |
1053 if (p->Ptr) _cmsFree(p->Ptr); |
969 if (p->Ptr) _cmsFree(it8 ->ContextID, p->Ptr); |
1054 _cmsFree(p); |
970 _cmsFree(it8 ->ContextID, p); |
1055 } |
971 } |
1056 } |
972 } |
1057 |
973 |
1058 if (it8->MemoryBlock) |
974 if (it8->MemoryBlock) |
1059 _cmsFree(it8->MemoryBlock); |
975 _cmsFree(it8 ->ContextID, it8->MemoryBlock); |
1060 |
976 |
1061 _cmsFree(it8); |
977 _cmsFree(it8 ->ContextID, it8); |
1062 } |
978 } |
1063 |
979 |
1064 |
980 |
1065 // Allocates a chunk of data, keep linked list |
981 // Allocates a chunk of data, keep linked list |
1066 static |
982 static |
1067 void* AllocBigBlock(LPIT8 it8, size_t size) |
983 void* AllocBigBlock(cmsIT8* it8, cmsUInt32Number size) |
1068 { |
984 { |
1069 LPOWNEDMEM ptr1; |
985 OWNEDMEM* ptr1; |
1070 void* ptr = _cmsMalloc(size); |
986 void* ptr = _cmsMallocZero(it8->ContextID, size); |
1071 |
987 |
1072 if (ptr) { |
988 if (ptr != NULL) { |
1073 |
989 |
1074 ZeroMemory(ptr, size); |
990 ptr1 = (OWNEDMEM*) _cmsMallocZero(it8 ->ContextID, sizeof(OWNEDMEM)); |
1075 ptr1 = (LPOWNEDMEM) _cmsMalloc(sizeof(OWNEDMEM)); |
991 |
1076 |
992 if (ptr1 == NULL) { |
1077 if (ptr1 == NULL) { |
993 |
1078 |
994 _cmsFree(it8 ->ContextID, ptr); |
1079 _cmsFree(ptr); |
995 return NULL; |
1080 return NULL; |
996 } |
1081 } |
997 |
1082 |
998 ptr1-> Ptr = ptr; |
1083 ZeroMemory(ptr1, sizeof(OWNEDMEM)); |
999 ptr1-> Next = it8 -> MemorySink; |
1084 |
1000 it8 -> MemorySink = ptr1; |
1085 ptr1-> Ptr = ptr; |
1001 } |
1086 ptr1-> Next = it8 -> MemorySink; |
1002 |
1087 it8 -> MemorySink = ptr1; |
1003 return ptr; |
1088 } |
|
1089 |
|
1090 return ptr; |
|
1091 } |
1004 } |
1092 |
1005 |
1093 |
1006 |
1094 // Suballocator. |
1007 // Suballocator. |
1095 static |
1008 static |
1096 void* AllocChunk(LPIT8 it8, size_t size) |
1009 void* AllocChunk(cmsIT8* it8, cmsUInt32Number size) |
1097 { |
1010 { |
1098 size_t free = it8 ->Allocator.BlockSize - it8 ->Allocator.Used; |
1011 cmsUInt32Number Free = it8 ->Allocator.BlockSize - it8 ->Allocator.Used; |
1099 LPBYTE ptr; |
1012 cmsUInt8Number* ptr; |
1100 |
1013 |
1101 size = ALIGNLONG(size); |
1014 size = _cmsALIGNLONG(size); |
1102 |
1015 |
1103 if (size > free) { |
1016 if (size > Free) { |
1104 |
1017 |
1105 if (it8 -> Allocator.BlockSize == 0) |
1018 if (it8 -> Allocator.BlockSize == 0) |
1106 |
1019 |
1107 it8 -> Allocator.BlockSize = 20*1024; |
1020 it8 -> Allocator.BlockSize = 20*1024; |
1108 else |
1021 else |
1163 |
1076 |
1164 for (; p != NULL; p = p->NextSubkey) { |
1077 for (; p != NULL; p = p->NextSubkey) { |
1165 |
1078 |
1166 if (LastPtr) *LastPtr = p; |
1079 if (LastPtr) *LastPtr = p; |
1167 |
1080 |
1168 if (stricmp(Subkey, p->Subkey) == 0) |
1081 if (cmsstrcasecmp(Subkey, p->Subkey) == 0) |
1169 return TRUE; |
1082 return TRUE; |
1170 } |
1083 } |
1171 |
1084 |
1172 return FALSE; |
1085 return FALSE; |
1173 } |
1086 } |
1174 |
1087 |
1175 |
1088 |
1176 |
1089 |
1177 // Add a property into a linked list |
1090 // Add a property into a linked list |
1178 static |
1091 static |
1179 LPKEYVALUE AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char *Subkey, const char* xValue, WRITEMODE WriteAs) |
1092 KEYVALUE* AddToList(cmsIT8* it8, KEYVALUE** Head, const char *Key, const char *Subkey, const char* xValue, WRITEMODE WriteAs) |
1180 { |
1093 { |
1181 LPKEYVALUE p; |
1094 KEYVALUE* p; |
1182 |
1095 KEYVALUE* last; |
1183 // Check if property is already in list (this is an error) |
1096 |
|
1097 |
|
1098 // Check if property is already in list |
1184 |
1099 |
1185 if (IsAvailableOnList(*Head, Key, Subkey, &p)) { |
1100 if (IsAvailableOnList(*Head, Key, Subkey, &p)) { |
1186 |
1101 |
1187 // This may work for editing properties |
1102 // This may work for editing properties |
1188 |
1103 |
1189 // return SynError(it8, "duplicate key <%s>", Key); |
1104 // return SynError(it8, "duplicate key <%s>", Key); |
1190 } |
1105 } |
1191 else { |
1106 else { |
1192 LPKEYVALUE last = p; |
1107 |
1193 |
1108 last = p; |
1194 // Allocate the container |
1109 |
1195 p = (LPKEYVALUE) AllocChunk(it8, sizeof(KEYVALUE)); |
1110 // Allocate the container |
1196 if (p == NULL) |
1111 p = (KEYVALUE*) AllocChunk(it8, sizeof(KEYVALUE)); |
1197 { |
1112 if (p == NULL) |
|
1113 { |
1198 SynError(it8, "AddToList: out of memory"); |
1114 SynError(it8, "AddToList: out of memory"); |
1199 return NULL; |
1115 return NULL; |
1200 } |
1116 } |
1201 |
1117 |
1202 // Store name and value |
1118 // Store name and value |
1203 p->Keyword = AllocString(it8, Key); |
1119 p->Keyword = AllocString(it8, Key); |
1204 p->Subkey = (Subkey == NULL) ? NULL : AllocString(it8, Subkey); |
1120 p->Subkey = (Subkey == NULL) ? NULL : AllocString(it8, Subkey); |
1205 |
1121 |
1206 // Keep the container in our list |
1122 // Keep the container in our list |
1207 if (*Head == NULL) |
1123 if (*Head == NULL) { |
1208 *Head = p; |
1124 *Head = p; |
|
1125 } |
1209 else |
1126 else |
1210 { |
1127 { |
1211 if(Subkey != 0 && last != 0) { |
1128 if (Subkey != NULL && last != NULL) { |
|
1129 |
1212 last->NextSubkey = p; |
1130 last->NextSubkey = p; |
1213 |
1131 |
1214 // If Subkey is not null, then last is the last property with the same key, |
1132 // If Subkey is not null, then last is the last property with the same key, |
1215 // but not necessarily is the last property in the list, so we need to move |
1133 // but not necessarily is the last property in the list, so we need to move |
1216 // to the actual list end |
1134 // to the actual list end |
1217 while(last->Next != 0) |
1135 while (last->Next != NULL) |
1218 last = last->Next; |
1136 last = last->Next; |
1219 } |
1137 } |
1220 last->Next = p; |
1138 |
1221 } |
1139 if (last != NULL) last->Next = p; |
1222 |
1140 } |
1223 p->Next = NULL; |
1141 |
|
1142 p->Next = NULL; |
1224 p->NextSubkey = NULL; |
1143 p->NextSubkey = NULL; |
1225 } |
1144 } |
1226 |
1145 |
1227 p->WriteAs = WriteAs; |
1146 p->WriteAs = WriteAs; |
|
1147 |
1228 if (xValue != NULL) { |
1148 if (xValue != NULL) { |
1229 |
1149 |
1230 p->Value = AllocString(it8, xValue); |
1150 p->Value = AllocString(it8, xValue); |
1231 } |
1151 } |
1232 else { |
1152 else { |
1333 |
1252 |
1334 for (i=0; i < NUMPREDEFINEDSAMPLEID; i++) |
1253 for (i=0; i < NUMPREDEFINEDSAMPLEID; i++) |
1335 AddAvailableSampleID(it8, PredefinedSampleID[i]); |
1254 AddAvailableSampleID(it8, PredefinedSampleID[i]); |
1336 |
1255 |
1337 |
1256 |
1338 return (LCMSHANDLE) it8; |
1257 return (cmsHANDLE) it8; |
1339 } |
1258 } |
1340 |
1259 |
1341 |
1260 |
1342 const char* LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8) |
1261 const char* CMSEXPORT cmsIT8GetSheetType(cmsHANDLE hIT8) |
1343 { |
1262 { |
1344 LPIT8 it8 = (LPIT8) hIT8; |
1263 cmsIT8* it8 = (cmsIT8*) hIT8; |
1345 |
1264 |
1346 return it8 ->SheetType; |
1265 return it8 ->SheetType; |
1347 |
1266 |
1348 } |
1267 } |
1349 |
1268 |
1350 LCMSBOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type) |
1269 cmsBool CMSEXPORT cmsIT8SetSheetType(cmsHANDLE hIT8, const char* Type) |
1351 { |
1270 { |
1352 LPIT8 it8 = (LPIT8) hIT8; |
1271 cmsIT8* it8 = (cmsIT8*) hIT8; |
1353 |
1272 |
1354 strncpy(it8 ->SheetType, Type, MAXSTR-1); |
1273 strncpy(it8 ->SheetType, Type, MAXSTR-1); |
1355 it8 ->SheetType[MAXSTR-1] = 0; |
1274 it8 ->SheetType[MAXSTR-1] = 0; |
1356 return TRUE; |
1275 return TRUE; |
1357 } |
1276 } |
1358 |
1277 |
1359 LCMSBOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* Val) |
1278 cmsBool CMSEXPORT cmsIT8SetComment(cmsHANDLE hIT8, const char* Val) |
1360 { |
1279 { |
1361 LPIT8 it8 = (LPIT8) hIT8; |
1280 cmsIT8* it8 = (cmsIT8*) hIT8; |
1362 |
1281 |
1363 if (!Val) return FALSE; |
1282 if (!Val) return FALSE; |
1364 if (!*Val) return FALSE; |
1283 if (!*Val) return FALSE; |
1365 |
1284 |
1366 return AddToList(it8, &GetTable(it8)->HeaderList, "# ", NULL, Val, WRITE_UNCOOKED) != NULL; |
1285 return AddToList(it8, &GetTable(it8)->HeaderList, "# ", NULL, Val, WRITE_UNCOOKED) != NULL; |
1367 } |
1286 } |
1368 |
1287 |
1369 |
1288 |
1370 |
1289 |
1371 // Sets a property |
1290 // Sets a property |
1372 LCMSBOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* Key, const char *Val) |
1291 cmsBool CMSEXPORT cmsIT8SetPropertyStr(cmsHANDLE hIT8, const char* Key, const char *Val) |
1373 { |
1292 { |
1374 LPIT8 it8 = (LPIT8) hIT8; |
1293 cmsIT8* it8 = (cmsIT8*) hIT8; |
1375 |
1294 |
1376 if (!Val) return FALSE; |
1295 if (!Val) return FALSE; |
1377 if (!*Val) return FALSE; |
1296 if (!*Val) return FALSE; |
1378 |
1297 |
1379 return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Val, WRITE_STRINGIFY) != NULL; |
1298 return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Val, WRITE_STRINGIFY) != NULL; |
1380 } |
1299 } |
1381 |
1300 |
1382 |
1301 |
1383 LCMSBOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val) |
1302 cmsBool CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFloat64Number Val) |
1384 { |
1303 { |
1385 LPIT8 it8 = (LPIT8) hIT8; |
1304 cmsIT8* it8 = (cmsIT8*) hIT8; |
1386 char Buffer[1024]; |
1305 char Buffer[1024]; |
1387 |
1306 |
1388 sprintf(Buffer, it8->DoubleFormatter, Val); |
1307 sprintf(Buffer, it8->DoubleFormatter, Val); |
1389 |
1308 |
1390 return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL; |
1309 return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL; |
1391 } |
1310 } |
1392 |
1311 |
1393 LCMSBOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val) |
1312 cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUInt32Number Val) |
1394 { |
1313 { |
1395 LPIT8 it8 = (LPIT8) hIT8; |
1314 cmsIT8* it8 = (cmsIT8*) hIT8; |
1396 char Buffer[1024]; |
1315 char Buffer[1024]; |
1397 |
1316 |
1398 sprintf(Buffer, "%d", Val); |
1317 sprintf(Buffer, "%d", Val); |
1399 |
1318 |
1400 return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL; |
1319 return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL; |
1401 } |
1320 } |
1402 |
1321 |
1403 LCMSBOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer) |
1322 cmsBool CMSEXPORT cmsIT8SetPropertyUncooked(cmsHANDLE hIT8, const char* Key, const char* Buffer) |
1404 { |
1323 { |
1405 LPIT8 it8 = (LPIT8) hIT8; |
1324 cmsIT8* it8 = (cmsIT8*) hIT8; |
1406 |
1325 |
1407 return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Buffer, WRITE_UNCOOKED) != NULL; |
1326 return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Buffer, WRITE_UNCOOKED) != NULL; |
1408 } |
1327 } |
1409 |
1328 |
1410 LCMSBOOL LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer) |
1329 cmsBool CMSEXPORT cmsIT8SetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer) |
1411 { |
1330 { |
1412 LPIT8 it8 = (LPIT8) hIT8; |
1331 cmsIT8* it8 = (cmsIT8*) hIT8; |
1413 |
1332 |
1414 return AddToList(it8, &GetTable(it8)->HeaderList, Key, SubKey, Buffer, WRITE_PAIR) != NULL; |
1333 return AddToList(it8, &GetTable(it8)->HeaderList, Key, SubKey, Buffer, WRITE_PAIR) != NULL; |
1415 } |
1334 } |
1416 |
1335 |
1417 // Gets a property |
1336 // Gets a property |
1418 const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* Key) |
1337 const char* CMSEXPORT cmsIT8GetProperty(cmsHANDLE hIT8, const char* Key) |
1419 { |
1338 { |
1420 LPIT8 it8 = (LPIT8) hIT8; |
1339 cmsIT8* it8 = (cmsIT8*) hIT8; |
1421 LPKEYVALUE p; |
1340 KEYVALUE* p; |
1422 |
1341 |
1423 if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, NULL, &p)) |
1342 if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, NULL, &p)) |
1424 { |
1343 { |
1425 return p -> Value; |
1344 return p -> Value; |
1426 } |
1345 } |
1427 return NULL; |
1346 return NULL; |
1428 } |
1347 } |
1429 |
1348 |
1430 |
1349 |
1431 double LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp) |
1350 cmsFloat64Number CMSEXPORT cmsIT8GetPropertyDbl(cmsHANDLE hIT8, const char* cProp) |
1432 { |
1351 { |
1433 const char *v = cmsIT8GetProperty(hIT8, cProp); |
1352 const char *v = cmsIT8GetProperty(hIT8, cProp); |
1434 |
1353 |
1435 if (v) return atof(v); |
1354 if (v) return atof(v); |
1436 else return 0.0; |
1355 else return 0.0; |
1437 } |
1356 } |
1438 |
1357 |
1439 const char* LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char *SubKey) |
1358 const char* CMSEXPORT cmsIT8GetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char *SubKey) |
1440 { |
1359 { |
1441 LPIT8 it8 = (LPIT8) hIT8; |
1360 cmsIT8* it8 = (cmsIT8*) hIT8; |
1442 LPKEYVALUE p; |
1361 KEYVALUE* p; |
1443 |
1362 |
1444 if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, SubKey, &p)) |
1363 if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, SubKey, &p)) { |
1445 { |
|
1446 return p -> Value; |
1364 return p -> Value; |
1447 } |
1365 } |
1448 return NULL; |
1366 return NULL; |
1449 } |
1367 } |
1450 |
1368 |
1451 // ----------------------------------------------------------------- Datasets |
1369 // ----------------------------------------------------------------- Datasets |
1452 |
1370 |
1453 |
1371 |
1454 static |
1372 static |
1455 void AllocateDataFormat(LPIT8 it8) |
1373 void AllocateDataFormat(cmsIT8* it8) |
1456 { |
1374 { |
1457 LPTABLE t = GetTable(it8); |
1375 TABLE* t = GetTable(it8); |
1458 |
1376 |
1459 if (t -> DataFormat) return; // Already allocated |
1377 if (t -> DataFormat) return; // Already allocated |
1460 |
1378 |
1461 t -> nSamples = (int) cmsIT8GetPropertyDbl(it8, "NUMBER_OF_FIELDS"); |
1379 t -> nSamples = (int) cmsIT8GetPropertyDbl(it8, "NUMBER_OF_FIELDS"); |
1462 |
1380 |
1465 SynError(it8, "AllocateDataFormat: Unknown NUMBER_OF_FIELDS"); |
1383 SynError(it8, "AllocateDataFormat: Unknown NUMBER_OF_FIELDS"); |
1466 t -> nSamples = 10; |
1384 t -> nSamples = 10; |
1467 } |
1385 } |
1468 |
1386 |
1469 t -> DataFormat = (char**) AllocChunk (it8, (t->nSamples + 1) * sizeof(char *)); |
1387 t -> DataFormat = (char**) AllocChunk (it8, (t->nSamples + 1) * sizeof(char *)); |
1470 if (t->DataFormat == NULL) |
1388 if (t->DataFormat == NULL) { |
1471 { |
1389 |
1472 SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array"); |
1390 SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array"); |
1473 } |
1391 } |
1474 |
1392 |
1475 } |
1393 } |
1476 |
1394 |
1477 static |
1395 static |
1478 const char *GetDataFormat(LPIT8 it8, int n) |
1396 const char *GetDataFormat(cmsIT8* it8, int n) |
1479 { |
1397 { |
1480 LPTABLE t = GetTable(it8); |
1398 TABLE* t = GetTable(it8); |
1481 |
1399 |
1482 if (t->DataFormat) |
1400 if (t->DataFormat) |
1483 return t->DataFormat[n]; |
1401 return t->DataFormat[n]; |
1484 |
1402 |
1485 return NULL; |
1403 return NULL; |
1486 } |
1404 } |
1487 |
1405 |
1488 static |
1406 static |
1489 LCMSBOOL SetDataFormat(LPIT8 it8, int n, const char *label) |
1407 cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label) |
1490 { |
1408 { |
1491 LPTABLE t = GetTable(it8); |
1409 TABLE* t = GetTable(it8); |
1492 |
|
1493 #ifdef STRICT_CGATS |
|
1494 if (!IsAvailableOnList(it8-> ValidSampleID, label, NULL, NULL)) { |
|
1495 SynError(it8, "Invalid data format '%s'.", label); |
|
1496 return FALSE; |
|
1497 } |
|
1498 #endif |
|
1499 |
1410 |
1500 if (!t->DataFormat) |
1411 if (!t->DataFormat) |
1501 AllocateDataFormat(it8); |
1412 AllocateDataFormat(it8); |
1502 |
1413 |
1503 if (n > t -> nSamples) { |
1414 if (n > t -> nSamples) { |
1504 SynError(it8, "More than NUMBER_OF_FIELDS fields."); |
1415 SynError(it8, "More than NUMBER_OF_FIELDS fields."); |
1505 return FALSE; |
1416 return FALSE; |
1506 } |
1417 } |
1507 |
1418 |
1508 |
|
1509 if (t->DataFormat) { |
1419 if (t->DataFormat) { |
1510 t->DataFormat[n] = AllocString(it8, label); |
1420 t->DataFormat[n] = AllocString(it8, label); |
1511 } |
1421 } |
1512 |
1422 |
1513 return TRUE; |
1423 return TRUE; |
1514 } |
1424 } |
1515 |
1425 |
1516 |
1426 |
1517 LCMSBOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE h, int n, const char *Sample) |
1427 cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE h, int n, const char *Sample) |
1518 { |
1428 { |
1519 LPIT8 it8 = (LPIT8) h; |
1429 cmsIT8* it8 = (cmsIT8*) h; |
1520 return SetDataFormat(it8, n, Sample); |
1430 return SetDataFormat(it8, n, Sample); |
1521 } |
1431 } |
1522 |
1432 |
1523 static |
1433 static |
1524 void AllocateDataSet(LPIT8 it8) |
1434 void AllocateDataSet(cmsIT8* it8) |
1525 { |
1435 { |
1526 LPTABLE t = GetTable(it8); |
1436 TABLE* t = GetTable(it8); |
1527 |
1437 |
1528 if (t -> Data) return; // Already allocated |
1438 if (t -> Data) return; // Already allocated |
1529 |
1439 |
1530 t-> nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS")); |
1440 t-> nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS")); |
1531 t-> nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS")); |
1441 t-> nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS")); |
1532 |
1442 |
1533 t-> Data = (char**)AllocChunk (it8, (t->nSamples + 1) * (t->nPatches + 1) *sizeof (char*)); |
1443 t-> Data = (char**)AllocChunk (it8, (t->nSamples + 1) * (t->nPatches + 1) *sizeof (char*)); |
1534 if (t->Data == NULL) |
1444 if (t->Data == NULL) { |
1535 { |
1445 |
1536 SynError(it8, "AllocateDataSet: Unable to allocate data array"); |
1446 SynError(it8, "AllocateDataSet: Unable to allocate data array"); |
1537 } |
1447 } |
1538 |
1448 |
1539 } |
1449 } |
1540 |
1450 |
1541 static |
1451 static |
1542 char* GetData(LPIT8 it8, int nSet, int nField) |
1452 char* GetData(cmsIT8* it8, int nSet, int nField) |
1543 { |
1453 { |
1544 LPTABLE t = GetTable(it8); |
1454 TABLE* t = GetTable(it8); |
1545 int nSamples = t -> nSamples; |
1455 int nSamples = t -> nSamples; |
1546 int nPatches = t -> nPatches; |
1456 int nPatches = t -> nPatches; |
1547 |
1457 |
1548 |
|
1549 if (nSet >= nPatches || nField >= nSamples) |
1458 if (nSet >= nPatches || nField >= nSamples) |
1550 return NULL; |
1459 return NULL; |
1551 |
1460 |
1552 if (!t->Data) return NULL; |
1461 if (!t->Data) return NULL; |
1553 return t->Data [nSet * nSamples + nField]; |
1462 return t->Data [nSet * nSamples + nField]; |
1554 } |
1463 } |
1555 |
1464 |
1556 static |
1465 static |
1557 LCMSBOOL SetData(LPIT8 it8, int nSet, int nField, const char *Val) |
1466 cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val) |
1558 { |
1467 { |
1559 LPTABLE t = GetTable(it8); |
1468 TABLE* t = GetTable(it8); |
1560 |
1469 |
1561 if (!t->Data) |
1470 if (!t->Data) |
1562 AllocateDataSet(it8); |
1471 AllocateDataSet(it8); |
1563 |
1472 |
1564 if (!t->Data) return FALSE; |
1473 if (!t->Data) return FALSE; |
1565 |
1474 |
1566 |
|
1567 |
|
1568 if (nSet > t -> nPatches || nSet < 0) { |
1475 if (nSet > t -> nPatches || nSet < 0) { |
1569 |
1476 |
1570 return SynError(it8, "Patch %d out of range, there are %d patches", nSet, t -> nPatches); |
1477 return SynError(it8, "Patch %d out of range, there are %d patches", nSet, t -> nPatches); |
1571 } |
1478 } |
1572 |
1479 |
1573 if (nField > t ->nSamples || nField < 0) { |
1480 if (nField > t ->nSamples || nField < 0) { |
1574 return SynError(it8, "Sample %d out of range, there are %d samples", nField, t ->nSamples); |
1481 return SynError(it8, "Sample %d out of range, there are %d samples", nField, t ->nSamples); |
1575 |
1482 |
1576 } |
1483 } |
1577 |
1484 |
1578 |
|
1579 t->Data [nSet * t -> nSamples + nField] = AllocString(it8, Val); |
1485 t->Data [nSet * t -> nSamples + nField] = AllocString(it8, Val); |
1580 return TRUE; |
1486 return TRUE; |
1581 } |
1487 } |
1582 |
1488 |
1583 |
1489 |
1584 // --------------------------------------------------------------- File I/O |
1490 // --------------------------------------------------------------- File I/O |
1585 |
1491 |
1586 |
1492 |
1587 // Writes a string to file |
1493 // Writes a string to file |
1588 static |
1494 static |
1589 void WriteStr(LPSAVESTREAM f, const char *str) |
1495 void WriteStr(SAVESTREAM* f, const char *str) |
1590 { |
1496 { |
1591 |
1497 cmsUInt32Number len; |
1592 size_t len; |
|
1593 |
1498 |
1594 if (str == NULL) |
1499 if (str == NULL) |
1595 str = " "; |
1500 str = " "; |
1596 |
1501 |
1597 // Lenghth to write |
1502 // Lenghth to write |
1598 len = strlen(str); |
1503 len = (cmsUInt32Number) strlen(str); |
1599 f ->Used += len; |
1504 f ->Used += len; |
1600 |
1505 |
1601 |
1506 |
1602 if (f ->stream) { // Should I write it to a file? |
1507 if (f ->stream) { // Should I write it to a file? |
1603 |
1508 |
1604 fwrite(str, 1, len, f->stream); |
1509 if (fwrite(str, 1, len, f->stream) != len) { |
|
1510 cmsSignalError(0, cmsERROR_WRITE, "Write to file error in CGATS parser"); |
|
1511 return; |
|
1512 } |
1605 |
1513 |
1606 } |
1514 } |
1607 else { // Or to a memory block? |
1515 else { // Or to a memory block? |
1608 |
1516 |
1609 |
|
1610 if (f ->Base) { // Am I just counting the bytes? |
1517 if (f ->Base) { // Am I just counting the bytes? |
1611 |
1518 |
1612 if (f ->Used > f ->Max) { |
1519 if (f ->Used > f ->Max) { |
1613 |
1520 |
1614 cmsSignalError(LCMS_ERRC_ABORTED, "Write to memory overflows in CGATS parser"); |
1521 cmsSignalError(0, cmsERROR_WRITE, "Write to memory overflows in CGATS parser"); |
1615 return; |
1522 return; |
1616 } |
1523 } |
1617 |
1524 |
1618 CopyMemory(f ->Ptr, str, len); |
1525 memmove(f ->Ptr, str, len); |
1619 f->Ptr += len; |
1526 f->Ptr += len; |
1620 |
|
1621 } |
1527 } |
1622 |
1528 |
1623 } |
1529 } |
1624 } |
1530 } |
1625 |
1531 |
1626 |
1532 |
1627 // Write formatted |
1533 // Write formatted |
1628 |
1534 |
1629 static |
1535 static |
1630 void Writef(LPSAVESTREAM f, const char* frm, ...) |
1536 void Writef(SAVESTREAM* f, const char* frm, ...) |
1631 { |
1537 { |
1632 char Buffer[4096]; |
1538 char Buffer[4096]; |
1633 va_list args; |
1539 va_list args; |
1634 |
1540 |
1635 va_start(args, frm); |
1541 va_start(args, frm); |
2259 |
2163 |
2260 } |
2164 } |
2261 |
2165 |
2262 |
2166 |
2263 static |
2167 static |
2264 int IsMyFile(const char* FileName) |
2168 cmsBool IsMyFile(const char* FileName) |
2265 { |
2169 { |
2266 FILE *fp; |
2170 FILE *fp; |
2267 size_t Size; |
2171 cmsUInt32Number Size; |
2268 BYTE Ptr[133]; |
2172 cmsUInt8Number Ptr[133]; |
2269 |
2173 |
2270 fp = fopen(FileName, "rt"); |
2174 fp = fopen(FileName, "rt"); |
2271 if (!fp) { |
2175 if (!fp) { |
2272 cmsSignalError(LCMS_ERRC_ABORTED, "File '%s' not found", FileName); |
2176 cmsSignalError(0, cmsERROR_FILE, "File '%s' not found", FileName); |
2273 return FALSE; |
2177 return FALSE; |
2274 } |
2178 } |
2275 |
2179 |
2276 Size = fread(Ptr, 1, 132, fp); |
2180 Size = (cmsUInt32Number) fread(Ptr, 1, 132, fp); |
2277 fclose(fp); |
2181 |
|
2182 if (fclose(fp) != 0) |
|
2183 return FALSE; |
2278 |
2184 |
2279 Ptr[Size] = '\0'; |
2185 Ptr[Size] = '\0'; |
2280 |
2186 |
2281 return IsMyBlock(Ptr, Size); |
2187 return IsMyBlock(Ptr, Size); |
2282 } |
2188 } |
2283 |
2189 |
2284 // ---------------------------------------------------------- Exported routines |
2190 // ---------------------------------------------------------- Exported routines |
2285 |
2191 |
2286 |
2192 |
2287 LCMSHANDLE LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len) |
2193 cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len) |
2288 { |
2194 { |
2289 LCMSHANDLE hIT8; |
2195 cmsHANDLE hIT8; |
2290 LPIT8 it8; |
2196 cmsIT8* it8; |
2291 |
2197 int type; |
2292 int type = IsMyBlock((LPBYTE) Ptr, len); |
2198 |
|
2199 _cmsAssert(Ptr != NULL); |
|
2200 _cmsAssert(len != 0); |
|
2201 |
|
2202 type = IsMyBlock((cmsUInt8Number*)Ptr, len); |
2293 if (type == 0) return NULL; |
2203 if (type == 0) return NULL; |
2294 |
2204 |
2295 hIT8 = cmsIT8Alloc(); |
2205 hIT8 = cmsIT8Alloc(ContextID); |
2296 if (!hIT8) return NULL; |
2206 if (!hIT8) return NULL; |
2297 |
2207 |
2298 it8 = (LPIT8) hIT8; |
2208 it8 = (cmsIT8*) hIT8; |
2299 it8 ->MemoryBlock = (char*) _cmsMalloc(len + 1); |
2209 it8 ->MemoryBlock = (char*) _cmsMalloc(ContextID, len + 1); |
2300 |
2210 |
2301 strncpy(it8 ->MemoryBlock, (const char*) Ptr, len); |
2211 strncpy(it8 ->MemoryBlock, (const char*) Ptr, len); |
2302 it8 ->MemoryBlock[len] = 0; |
2212 it8 ->MemoryBlock[len] = 0; |
2303 |
2213 |
2304 strncpy(it8->FileStack[0]->FileName, "", MAX_PATH-1); |
2214 strncpy(it8->FileStack[0]->FileName, "", cmsMAX_PATH-1); |
2305 it8-> Source = it8 -> MemoryBlock; |
2215 it8-> Source = it8 -> MemoryBlock; |
2306 |
2216 |
2307 if (!ParseIT8(it8, type-1)) { |
2217 if (!ParseIT8(it8, type-1)) { |
2308 |
2218 |
2309 cmsIT8Free(hIT8); |
2219 cmsIT8Free(hIT8); |
2355 } |
2268 } |
2356 |
2269 |
2357 CookPointers(it8); |
2270 CookPointers(it8); |
2358 it8 ->nTable = 0; |
2271 it8 ->nTable = 0; |
2359 |
2272 |
2360 fclose(it8 ->FileStack[0]->Stream); |
2273 if (fclose(it8 ->FileStack[0]->Stream)!= 0) { |
|
2274 cmsIT8Free(hIT8); |
|
2275 return NULL; |
|
2276 } |
|
2277 |
2361 return hIT8; |
2278 return hIT8; |
2362 |
2279 |
2363 } |
2280 } |
2364 |
2281 |
2365 int LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE hIT8, char ***SampleNames) |
2282 int CMSEXPORT cmsIT8EnumDataFormat(cmsHANDLE hIT8, char ***SampleNames) |
2366 { |
2283 { |
2367 LPIT8 it8 = (LPIT8) hIT8; |
2284 cmsIT8* it8 = (cmsIT8*) hIT8; |
2368 LPTABLE t = GetTable(it8); |
2285 TABLE* t; |
2369 |
2286 |
|
2287 _cmsAssert(hIT8 != NULL); |
|
2288 |
|
2289 t = GetTable(it8); |
|
2290 |
|
2291 if (SampleNames) |
2370 *SampleNames = t -> DataFormat; |
2292 *SampleNames = t -> DataFormat; |
2371 return t -> nSamples; |
2293 return t -> nSamples; |
2372 } |
2294 } |
2373 |
2295 |
2374 |
2296 |
2375 int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, const char ***PropertyNames) |
2297 cmsUInt32Number CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyNames) |
2376 { |
2298 { |
2377 LPIT8 it8 = (LPIT8) hIT8; |
2299 cmsIT8* it8 = (cmsIT8*) hIT8; |
2378 LPKEYVALUE p; |
2300 KEYVALUE* p; |
2379 int n; |
2301 cmsUInt32Number n; |
2380 const char **Props; |
2302 char **Props; |
2381 LPTABLE t = GetTable(it8); |
2303 TABLE* t; |
|
2304 |
|
2305 _cmsAssert(hIT8 != NULL); |
|
2306 |
|
2307 t = GetTable(it8); |
2382 |
2308 |
2383 // Pass#1 - count properties |
2309 // Pass#1 - count properties |
2384 |
2310 |
2385 n = 0; |
2311 n = 0; |
2386 for (p = t -> HeaderList; p != NULL; p = p->Next) { |
2312 for (p = t -> HeaderList; p != NULL; p = p->Next) { |
2387 n++; |
2313 n++; |
2388 } |
2314 } |
2389 |
2315 |
2390 |
2316 |
2391 Props = (const char **) AllocChunk(it8, sizeof(char *) * n); |
2317 Props = (char **) AllocChunk(it8, sizeof(char *) * n); |
2392 |
2318 |
2393 // Pass#2 - Fill pointers |
2319 // Pass#2 - Fill pointers |
2394 n = 0; |
2320 n = 0; |
2395 for (p = t -> HeaderList; p != NULL; p = p->Next) { |
2321 for (p = t -> HeaderList; p != NULL; p = p->Next) { |
2396 Props[n++] = p -> Keyword; |
2322 Props[n++] = p -> Keyword; |
2434 *SubpropertyNames = Props; |
2365 *SubpropertyNames = Props; |
2435 return n; |
2366 return n; |
2436 } |
2367 } |
2437 |
2368 |
2438 static |
2369 static |
2439 int LocatePatch(LPIT8 it8, const char* cPatch) |
2370 int LocatePatch(cmsIT8* it8, const char* cPatch) |
2440 { |
2371 { |
2441 int i; |
2372 int i; |
2442 const char *data; |
2373 const char *data; |
2443 LPTABLE t = GetTable(it8); |
2374 TABLE* t = GetTable(it8); |
2444 |
2375 |
2445 for (i=0; i < t-> nPatches; i++) { |
2376 for (i=0; i < t-> nPatches; i++) { |
2446 |
2377 |
2447 data = GetData(it8, i, t->SampleID); |
2378 data = GetData(it8, i, t->SampleID); |
2448 |
2379 |
2449 if (data != NULL) { |
2380 if (data != NULL) { |
2450 |
2381 |
2451 if (stricmp(data, cPatch) == 0) |
2382 if (cmsstrcasecmp(data, cPatch) == 0) |
2452 return i; |
2383 return i; |
2453 } |
2384 } |
2454 } |
2385 } |
2455 |
2386 |
2456 // SynError(it8, "Couldn't find patch '%s'\n", cPatch); |
2387 // SynError(it8, "Couldn't find patch '%s'\n", cPatch); |
2457 return -1; |
2388 return -1; |
2458 } |
2389 } |
2459 |
2390 |
2460 |
2391 |
2461 static |
2392 static |
2462 int LocateEmptyPatch(LPIT8 it8) |
2393 int LocateEmptyPatch(cmsIT8* it8) |
2463 { |
2394 { |
2464 int i; |
2395 int i; |
2465 const char *data; |
2396 const char *data; |
2466 LPTABLE t = GetTable(it8); |
2397 TABLE* t = GetTable(it8); |
2467 |
2398 |
2468 for (i=0; i < t-> nPatches; i++) { |
2399 for (i=0; i < t-> nPatches; i++) { |
2469 |
2400 |
2470 data = GetData(it8, i, t->SampleID); |
2401 data = GetData(it8, i, t->SampleID); |
2471 |
2402 |
2472 if (data == NULL) |
2403 if (data == NULL) |
2473 return i; |
2404 return i; |
2474 |
2405 |
2475 } |
2406 } |
2476 |
2407 |
2477 return -1; |
2408 return -1; |
2478 } |
2409 } |
2479 |
2410 |
2480 static |
2411 static |
2481 int LocateSample(LPIT8 it8, const char* cSample) |
2412 int LocateSample(cmsIT8* it8, const char* cSample) |
2482 { |
2413 { |
2483 int i; |
2414 int i; |
2484 const char *fld; |
2415 const char *fld; |
2485 LPTABLE t = GetTable(it8); |
2416 TABLE* t = GetTable(it8); |
2486 |
2417 |
2487 for (i=0; i < t->nSamples; i++) { |
2418 for (i=0; i < t->nSamples; i++) { |
2488 |
2419 |
2489 fld = GetDataFormat(it8, i); |
2420 fld = GetDataFormat(it8, i); |
2490 if (stricmp(fld, cSample) == 0) |
2421 if (cmsstrcasecmp(fld, cSample) == 0) |
2491 return i; |
2422 return i; |
2492 } |
2423 } |
2493 |
2424 |
2494 |
|
2495 // SynError(it8, "Couldn't find data field %s\n", cSample); |
|
2496 return -1; |
2425 return -1; |
2497 |
2426 |
2498 } |
2427 } |
2499 |
2428 |
2500 |
2429 |
2501 int LCMSEXPORT cmsIT8GetDataFormat(LCMSHANDLE hIT8, const char* cSample) |
2430 int CMSEXPORT cmsIT8FindDataFormat(cmsHANDLE hIT8, const char* cSample) |
2502 { |
2431 { |
2503 LPIT8 it8 = (LPIT8) hIT8; |
2432 cmsIT8* it8 = (cmsIT8*) hIT8; |
|
2433 |
|
2434 _cmsAssert(hIT8 != NULL); |
|
2435 |
2504 return LocateSample(it8, cSample); |
2436 return LocateSample(it8, cSample); |
2505 } |
2437 } |
2506 |
2438 |
2507 |
2439 |
2508 |
2440 |
2509 const char* LCMSEXPORT cmsIT8GetDataRowCol(LCMSHANDLE hIT8, int row, int col) |
2441 const char* CMSEXPORT cmsIT8GetDataRowCol(cmsHANDLE hIT8, int row, int col) |
2510 { |
2442 { |
2511 LPIT8 it8 = (LPIT8) hIT8; |
2443 cmsIT8* it8 = (cmsIT8*) hIT8; |
|
2444 |
|
2445 _cmsAssert(hIT8 != NULL); |
2512 |
2446 |
2513 return GetData(it8, row, col); |
2447 return GetData(it8, row, col); |
2514 } |
2448 } |
2515 |
2449 |
2516 |
2450 |
2517 double LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE hIT8, int row, int col) |
2451 cmsFloat64Number CMSEXPORT cmsIT8GetDataRowColDbl(cmsHANDLE hIT8, int row, int col) |
2518 { |
2452 { |
2519 const char* Buffer; |
2453 const char* Buffer; |
2520 |
2454 |
2521 Buffer = cmsIT8GetDataRowCol(hIT8, row, col); |
2455 Buffer = cmsIT8GetDataRowCol(hIT8, row, col); |
2522 |
2456 |
2528 return 0; |
2462 return 0; |
2529 |
2463 |
2530 } |
2464 } |
2531 |
2465 |
2532 |
2466 |
2533 LCMSBOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, const char* Val) |
2467 cmsBool CMSEXPORT cmsIT8SetDataRowCol(cmsHANDLE hIT8, int row, int col, const char* Val) |
2534 { |
2468 { |
2535 LPIT8 it8 = (LPIT8) hIT8; |
2469 cmsIT8* it8 = (cmsIT8*) hIT8; |
|
2470 |
|
2471 _cmsAssert(hIT8 != NULL); |
2536 |
2472 |
2537 return SetData(it8, row, col, Val); |
2473 return SetData(it8, row, col, Val); |
2538 } |
2474 } |
2539 |
2475 |
2540 |
2476 |
2541 LCMSBOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, double Val) |
2477 cmsBool CMSEXPORT cmsIT8SetDataRowColDbl(cmsHANDLE hIT8, int row, int col, cmsFloat64Number Val) |
2542 { |
2478 { |
2543 LPIT8 it8 = (LPIT8) hIT8; |
2479 cmsIT8* it8 = (cmsIT8*) hIT8; |
2544 char Buff[256]; |
2480 char Buff[256]; |
2545 |
2481 |
|
2482 _cmsAssert(hIT8 != NULL); |
|
2483 |
2546 sprintf(Buff, it8->DoubleFormatter, Val); |
2484 sprintf(Buff, it8->DoubleFormatter, Val); |
2547 |
2485 |
2548 return SetData(it8, row, col, Buff); |
2486 return SetData(it8, row, col, Buff); |
2549 } |
2487 } |
2550 |
2488 |
2551 |
2489 |
2552 |
2490 |
2553 const char* LCMSEXPORT cmsIT8GetData(LCMSHANDLE hIT8, const char* cPatch, const char* cSample) |
2491 const char* CMSEXPORT cmsIT8GetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample) |
2554 { |
2492 { |
2555 LPIT8 it8 = (LPIT8) hIT8; |
2493 cmsIT8* it8 = (cmsIT8*) hIT8; |
2556 int iField, iSet; |
2494 int iField, iSet; |
2557 |
2495 |
|
2496 _cmsAssert(hIT8 != NULL); |
2558 |
2497 |
2559 iField = LocateSample(it8, cSample); |
2498 iField = LocateSample(it8, cSample); |
2560 if (iField < 0) { |
2499 if (iField < 0) { |
2561 return NULL; |
2500 return NULL; |
2562 } |
2501 } |
2563 |
2502 |
2564 |
|
2565 iSet = LocatePatch(it8, cPatch); |
2503 iSet = LocatePatch(it8, cPatch); |
2566 if (iSet < 0) { |
2504 if (iSet < 0) { |
2567 return NULL; |
2505 return NULL; |
2568 } |
2506 } |
2569 |
2507 |
2570 return GetData(it8, iSet, iField); |
2508 return GetData(it8, iSet, iField); |
2571 } |
2509 } |
2572 |
2510 |
2573 |
2511 |
2574 double LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE it8, const char* cPatch, const char* cSample) |
2512 cmsFloat64Number CMSEXPORT cmsIT8GetDataDbl(cmsHANDLE it8, const char* cPatch, const char* cSample) |
2575 { |
2513 { |
2576 const char* Buffer; |
2514 const char* Buffer; |
2577 |
2515 |
2578 Buffer = cmsIT8GetData(it8, cPatch, cSample); |
2516 Buffer = cmsIT8GetData(it8, cPatch, cSample); |
2579 |
2517 |
2587 } |
2525 } |
2588 } |
2526 } |
2589 |
2527 |
2590 |
2528 |
2591 |
2529 |
2592 LCMSBOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE hIT8, const char* cPatch, |
2530 cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample, const char *Val) |
2593 const char* cSample, |
2531 { |
2594 const char *Val) |
2532 cmsIT8* it8 = (cmsIT8*) hIT8; |
2595 { |
|
2596 LPIT8 it8 = (LPIT8) hIT8; |
|
2597 int iField, iSet; |
2533 int iField, iSet; |
2598 LPTABLE t = GetTable(it8); |
2534 TABLE* t; |
2599 |
2535 |
|
2536 _cmsAssert(hIT8 != NULL); |
|
2537 |
|
2538 t = GetTable(it8); |
2600 |
2539 |
2601 iField = LocateSample(it8, cSample); |
2540 iField = LocateSample(it8, cSample); |
2602 |
2541 |
2603 if (iField < 0) |
2542 if (iField < 0) |
2604 return FALSE; |
2543 return FALSE; |
2605 |
2544 |
2606 |
2545 if (t-> nPatches == 0) { |
2607 |
2546 |
2608 if (t-> nPatches == 0) { |
2547 AllocateDataFormat(it8); |
2609 |
2548 AllocateDataSet(it8); |
2610 AllocateDataFormat(it8); |
2549 CookPointers(it8); |
2611 AllocateDataSet(it8); |
2550 } |
2612 CookPointers(it8); |
2551 |
2613 } |
2552 if (cmsstrcasecmp(cSample, "SAMPLE_ID") == 0) { |
2614 |
2553 |
2615 |
2554 iSet = LocateEmptyPatch(it8); |
2616 if (stricmp(cSample, "SAMPLE_ID") == 0) |
2555 if (iSet < 0) { |
2617 { |
2556 return SynError(it8, "Couldn't add more patches '%s'\n", cPatch); |
2618 |
2557 } |
2619 iSet = LocateEmptyPatch(it8); |
2558 |
2620 if (iSet < 0) { |
2559 iField = t -> SampleID; |
2621 return SynError(it8, "Couldn't add more patches '%s'\n", cPatch); |
2560 } |
2622 } |
2561 else { |
2623 |
2562 iSet = LocatePatch(it8, cPatch); |
2624 iField = t -> SampleID; |
2563 if (iSet < 0) { |
2625 } |
2564 return FALSE; |
2626 else { |
2565 } |
2627 iSet = LocatePatch(it8, cPatch); |
2566 } |
2628 if (iSet < 0) { |
2567 |
2629 return FALSE; |
2568 return SetData(it8, iSet, iField, Val); |
2630 } |
2569 } |
2631 } |
2570 |
2632 |
2571 |
2633 return SetData(it8, iSet, iField, Val); |
2572 cmsBool CMSEXPORT cmsIT8SetDataDbl(cmsHANDLE hIT8, const char* cPatch, |
2634 } |
2573 const char* cSample, |
2635 |
2574 cmsFloat64Number Val) |
2636 |
2575 { |
2637 LCMSBOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch, |
2576 cmsIT8* it8 = (cmsIT8*) hIT8; |
2638 const char* cSample, |
|
2639 double Val) |
|
2640 { |
|
2641 LPIT8 it8 = (LPIT8) hIT8; |
|
2642 char Buff[256]; |
2577 char Buff[256]; |
2643 |
2578 |
2644 snprintf(Buff, 255, it8->DoubleFormatter, Val); |
2579 _cmsAssert(hIT8 != NULL); |
2645 return cmsIT8SetData(hIT8, cPatch, cSample, Buff); |
2580 |
2646 |
2581 snprintf(Buff, 255, it8->DoubleFormatter, Val); |
|
2582 return cmsIT8SetData(hIT8, cPatch, cSample, Buff); |
2647 } |
2583 } |
2648 |
2584 |
2649 // Buffer should get MAXSTR at least |
2585 // Buffer should get MAXSTR at least |
2650 |
2586 |
2651 const char* LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buffer) |
2587 const char* CMSEXPORT cmsIT8GetPatchName(cmsHANDLE hIT8, int nPatch, char* buffer) |
2652 { |
2588 { |
2653 LPIT8 it8 = (LPIT8) hIT8; |
2589 cmsIT8* it8 = (cmsIT8*) hIT8; |
2654 LPTABLE t = GetTable(it8); |
2590 TABLE* t; |
2655 char* Data = GetData(it8, nPatch, t->SampleID); |
2591 char* Data; |
2656 |
2592 |
2657 if (!Data) return NULL; |
2593 _cmsAssert(hIT8 != NULL); |
2658 if (!buffer) return Data; |
2594 |
2659 |
2595 t = GetTable(it8); |
2660 strncpy(buffer, Data, MAXSTR-1); |
2596 Data = GetData(it8, nPatch, t->SampleID); |
2661 buffer[MAXSTR-1] = 0; |
2597 |
2662 return buffer; |
2598 if (!Data) return NULL; |
2663 } |
2599 if (!buffer) return Data; |
2664 |
2600 |
2665 int LCMSEXPORT cmsIT8GetPatchByName(LCMSHANDLE hIT8, const char *cPatch) |
2601 strncpy(buffer, Data, MAXSTR-1); |
2666 { |
2602 buffer[MAXSTR-1] = 0; |
2667 return LocatePatch((LPIT8)hIT8, cPatch); |
2603 return buffer; |
2668 } |
2604 } |
2669 |
2605 |
2670 int LCMSEXPORT cmsIT8TableCount(LCMSHANDLE hIT8) |
2606 int CMSEXPORT cmsIT8GetPatchByName(cmsHANDLE hIT8, const char *cPatch) |
2671 { |
2607 { |
2672 LPIT8 it8 = (LPIT8) hIT8; |
2608 _cmsAssert(hIT8 != NULL); |
2673 |
2609 |
2674 return it8 ->TablesCount; |
2610 return LocatePatch((cmsIT8*)hIT8, cPatch); |
|
2611 } |
|
2612 |
|
2613 cmsUInt32Number CMSEXPORT cmsIT8TableCount(cmsHANDLE hIT8) |
|
2614 { |
|
2615 cmsIT8* it8 = (cmsIT8*) hIT8; |
|
2616 |
|
2617 _cmsAssert(hIT8 != NULL); |
|
2618 |
|
2619 return it8 ->TablesCount; |
2675 } |
2620 } |
2676 |
2621 |
2677 // This handles the "LABEL" extension. |
2622 // This handles the "LABEL" extension. |
2678 // Label, nTable, Type |
2623 // Label, nTable, Type |
2679 |
2624 |
2680 int LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType) |
2625 int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType) |
2681 { |
2626 { |
2682 const char* cLabelFld; |
2627 const char* cLabelFld; |
2683 char Type[256], Label[256]; |
2628 char Type[256], Label[256]; |
2684 int nTable; |
2629 int nTable; |
2685 |
2630 |
|
2631 _cmsAssert(hIT8 != NULL); |
|
2632 |
2686 if (cField != NULL && *cField == 0) |
2633 if (cField != NULL && *cField == 0) |
2687 cField = "LABEL"; |
2634 cField = "LABEL"; |
2688 |
2635 |
2689 if (cField == NULL) |
2636 if (cField == NULL) |
2690 cField = "LABEL"; |
2637 cField = "LABEL"; |
2698 if (ExpectedType != NULL && *ExpectedType == 0) |
2645 if (ExpectedType != NULL && *ExpectedType == 0) |
2699 ExpectedType = NULL; |
2646 ExpectedType = NULL; |
2700 |
2647 |
2701 if (ExpectedType) { |
2648 if (ExpectedType) { |
2702 |
2649 |
2703 if (stricmp(Type, ExpectedType) != 0) return -1; |
2650 if (cmsstrcasecmp(Type, ExpectedType) != 0) return -1; |
2704 } |
2651 } |
2705 |
2652 |
2706 return cmsIT8SetTable(hIT8, nTable); |
2653 return cmsIT8SetTable(hIT8, nTable); |
2707 } |
2654 } |
2708 |
2655 |
2709 |
2656 |
2710 LCMSBOOL LCMSEXPORT cmsIT8SetIndexColumn(LCMSHANDLE hIT8, const char* cSample) |
2657 cmsBool CMSEXPORT cmsIT8SetIndexColumn(cmsHANDLE hIT8, const char* cSample) |
2711 { |
2658 { |
2712 LPIT8 it8 = (LPIT8) hIT8; |
2659 cmsIT8* it8 = (cmsIT8*) hIT8; |
2713 |
2660 int pos; |
2714 int pos = LocateSample(it8, cSample); |
2661 |
|
2662 _cmsAssert(hIT8 != NULL); |
|
2663 |
|
2664 pos = LocateSample(it8, cSample); |
2715 if(pos == -1) |
2665 if(pos == -1) |
2716 return FALSE; |
2666 return FALSE; |
2717 |
2667 |
2718 it8->Tab[it8->nTable].SampleID = pos; |
2668 it8->Tab[it8->nTable].SampleID = pos; |
2719 return TRUE; |
2669 return TRUE; |
2720 } |
2670 } |
2721 |
2671 |
2722 |
2672 |
2723 void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE hIT8, const char* Formatter) |
2673 void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter) |
2724 { |
2674 { |
2725 LPIT8 it8 = (LPIT8) hIT8; |
2675 cmsIT8* it8 = (cmsIT8*) hIT8; |
|
2676 |
|
2677 _cmsAssert(hIT8 != NULL); |
2726 |
2678 |
2727 if (Formatter == NULL) |
2679 if (Formatter == NULL) |
2728 strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT); |
2680 strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT); |
2729 else |
2681 else |
2730 strcpy(it8->DoubleFormatter, Formatter); |
2682 strcpy(it8->DoubleFormatter, Formatter); |