jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c
changeset 6482 0f6a4442b29e
parent 5506 202f599c92aa
child 14300 117dc9b98a7b
equal deleted inserted replaced
6481:78d56f33c3a7 6482:0f6a4442b29e
    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 
   592                 it8 -> ch = ' ';                            // Whitespace to be ignored
   520                 it8 -> ch = ' ';                            // Whitespace to be ignored
   593 
   521 
   594             } else
   522             } else
   595                 it8 ->ch = 0;   // EOF
   523                 it8 ->ch = 0;   // EOF
   596         }
   524         }
   597 
       
   598 
       
   599 
       
   600     }
   525     }
   601     else {
   526     else {
   602         it8->ch = *it8->Source;
   527         it8->ch = *it8->Source;
   603         if (it8->ch) it8->Source++;
   528         if (it8->ch) it8->Source++;
   604     }
   529     }
   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;
   713 
   636 
   714         while (isseparator(it8->ch))
   637         while (isseparator(it8->ch))
   715             NextCh(it8);
   638             NextCh(it8);
   716 
   639 
   717         if (isfirstidchar(it8->ch)) {          // Identifier
   640         if (isfirstidchar(it8->ch)) {          // Identifier
   718 
       
   719 
   641 
   720             k = 0;
   642             k = 0;
   721             idptr = it8->id;
   643             idptr = it8->id;
   722 
   644 
   723             do {
   645             do {
   843                         NextCh(it8);
   765                         NextCh(it8);
   844 
   766 
   845                     } while (isidchar(it8->ch));
   767                     } while (isidchar(it8->ch));
   846 
   768 
   847                     *idptr = '\0';
   769                     *idptr = '\0';
   848 
       
   849                     it8->sy = SIDENT;
   770                     it8->sy = SIDENT;
   850                 }
   771                 }
   851                 return;
   772                 return;
   852 
   773 
   853             }
   774             }
   858         case '\x1a':
   779         case '\x1a':
   859             NextCh(it8);
   780             NextCh(it8);
   860             break;
   781             break;
   861 
   782 
   862         // Eof stream markers
   783         // Eof stream markers
   863 
       
   864         case 0:
   784         case 0:
   865         case -1:
   785         case -1:
   866             it8->sy = SEOF;
   786             it8->sy = SEOF;
   867             break;
   787             break;
   868 
   788 
   869 
   789 
   870         // Next line
   790         // Next line
   871 
       
   872         case '\n':
   791         case '\n':
   873             NextCh(it8);
   792             NextCh(it8);
   874             it8->sy = SEOLN;
   793             it8->sy = SEOLN;
   875             it8->lineno++;
   794             it8->lineno++;
   876             break;
   795             break;
   877 
   796 
   878         // Comment
   797         // Comment
   879 
       
   880         case '#':
   798         case '#':
   881             NextCh(it8);
   799             NextCh(it8);
   882             while (it8->ch && it8->ch != '\n')
   800             while (it8->ch && it8->ch != '\n')
   883                 NextCh(it8);
   801                 NextCh(it8);
   884 
   802 
   885             it8->sy = SCOMMENT;
   803             it8->sy = SCOMMENT;
   886             break;
   804             break;
   887 
   805 
   888             // String.
   806         // String.
   889 
       
   890         case '\'':
   807         case '\'':
   891         case '\"':
   808         case '\"':
   892             idptr = it8->str;
   809             idptr = it8->str;
   893             sng = it8->ch;
   810             sng = it8->ch;
   894             k = 0;
   811             k = 0;
   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");
   960 
   878 
   961 }
   879 }
   962 
   880 
   963 // Checks end of line separator
   881 // Checks end of line separator
   964 static
   882 static
   965 LCMSBOOL CheckEOLN(LPIT8 it8)
   883 cmsBool CheckEOLN(cmsIT8* it8)
   966 {
   884 {
   967         if (!Check(it8, SEOLN, "Expected separator")) return FALSE;
   885         if (!Check(it8, SEOLN, "Expected separator")) return FALSE;
   968         while (it8 -> sy == SEOLN)
   886         while (it8 -> sy == SEOLN)
   969                         InSymbol(it8);
   887                         InSymbol(it8);
   970         return TRUE;
   888         return TRUE;
   972 }
   890 }
   973 
   891 
   974 // Skip a symbol
   892 // Skip a symbol
   975 
   893 
   976 static
   894 static
   977 void Skip(LPIT8 it8, SYMBOL sy)
   895 void Skip(cmsIT8* it8, SYMBOL sy)
   978 {
   896 {
   979         if (it8->sy == sy && it8->sy != SEOF)
   897         if (it8->sy == sy && it8->sy != SEOF)
   980                         InSymbol(it8);
   898                         InSymbol(it8);
   981 }
   899 }
   982 
   900 
   983 
   901 
   984 // Skip multiple EOLN
   902 // Skip multiple EOLN
   985 static
   903 static
   986 void SkipEOLN(LPIT8 it8)
   904 void SkipEOLN(cmsIT8* it8)
   987 {
   905 {
   988     while (it8->sy == SEOLN) {
   906     while (it8->sy == SEOLN) {
   989              InSymbol(it8);
   907              InSymbol(it8);
   990     }
   908     }
   991 }
   909 }
   992 
   910 
   993 
   911 
   994 // Returns a string holding current value
   912 // Returns a string holding current value
   995 static
   913 static
   996 LCMSBOOL GetVal(LPIT8 it8, char* Buffer, size_t max, const char* ErrorTitle)
   914 cmsBool GetVal(cmsIT8* it8, char* Buffer, cmsUInt32Number max, const char* ErrorTitle)
   997 {
   915 {
   998     switch (it8->sy) {
   916     switch (it8->sy) {
   999 
   917 
  1000     case SIDENT:  strncpy(Buffer, it8->id, max);
   918     case SIDENT:  strncpy(Buffer, it8->id, max);
  1001                   Buffer[max-1]=0;
   919                   Buffer[max-1]=0;
  1016 }
   934 }
  1017 
   935 
  1018 // ---------------------------------------------------------- Table
   936 // ---------------------------------------------------------- Table
  1019 
   937 
  1020 static
   938 static
  1021 LPTABLE GetTable(LPIT8 it8)
   939 TABLE* GetTable(cmsIT8* it8)
  1022 {
   940 {
  1023    if ((it8 -> nTable >= it8 ->TablesCount) || (it8 -> nTable < 0)) {
   941    if ((it8 -> nTable >= it8 ->TablesCount)) {
  1024 
   942 
  1025            SynError(it8, "Table %d out of sequence", it8 -> nTable);
   943            SynError(it8, "Table %d out of sequence", it8 -> nTable);
  1026            return it8 -> Tab;
   944            return it8 -> Tab;
  1027    }
   945    }
  1028 
   946 
  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
  1110 
  1023 
  1111         if (it8 ->Allocator.BlockSize < size)
  1024         if (it8 ->Allocator.BlockSize < size)
  1112                 it8 ->Allocator.BlockSize = size;
  1025                 it8 ->Allocator.BlockSize = size;
  1113 
  1026 
  1114         it8 ->Allocator.Used = 0;
  1027         it8 ->Allocator.Used = 0;
  1115         it8 ->Allocator.Block = (LPBYTE) AllocBigBlock(it8, it8 ->Allocator.BlockSize);
  1028         it8 ->Allocator.Block = (cmsUInt8Number*)  AllocBigBlock(it8, it8 ->Allocator.BlockSize);
  1116     }
  1029     }
  1117 
  1030 
  1118     ptr = it8 ->Allocator.Block + it8 ->Allocator.Used;
  1031     ptr = it8 ->Allocator.Block + it8 ->Allocator.Used;
  1119     it8 ->Allocator.Used += size;
  1032     it8 ->Allocator.Used += size;
  1120 
  1033 
  1123 }
  1036 }
  1124 
  1037 
  1125 
  1038 
  1126 // Allocates a string
  1039 // Allocates a string
  1127 static
  1040 static
  1128 char *AllocString(LPIT8 it8, const char* str)
  1041 char *AllocString(cmsIT8* it8, const char* str)
  1129 {
  1042 {
  1130     size_t Size = strlen(str)+1;
  1043     cmsUInt32Number Size = (cmsUInt32Number) strlen(str)+1;
  1131     char *ptr;
  1044     char *ptr;
  1132 
  1045 
  1133 
  1046 
  1134     ptr = (char *) AllocChunk(it8, Size);
  1047     ptr = (char *) AllocChunk(it8, Size);
  1135     if (ptr) strncpy (ptr, str, Size-1);
  1048     if (ptr) strncpy (ptr, str, Size-1);
  1138 }
  1051 }
  1139 
  1052 
  1140 // Searches through linked list
  1053 // Searches through linked list
  1141 
  1054 
  1142 static
  1055 static
  1143 LCMSBOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, const char* Subkey, LPKEYVALUE* LastPtr)
  1056 cmsBool IsAvailableOnList(KEYVALUE* p, const char* Key, const char* Subkey, KEYVALUE** LastPtr)
  1144 {
  1057 {
  1145     if (LastPtr) *LastPtr = p;
  1058     if (LastPtr) *LastPtr = p;
  1146 
  1059 
  1147     for (;  p != NULL; p = p->Next) {
  1060     for (;  p != NULL; p = p->Next) {
  1148 
  1061 
  1149         if (LastPtr) *LastPtr = p;
  1062         if (LastPtr) *LastPtr = p;
  1150 
  1063 
  1151         if (*Key != '#') { // Comments are ignored
  1064         if (*Key != '#') { // Comments are ignored
  1152 
  1065 
  1153             if (stricmp(Key, p->Keyword) == 0)
  1066             if (cmsstrcasecmp(Key, p->Keyword) == 0)
  1154                     break;
  1067                     break;
  1155         }
  1068         }
  1156         }
  1069         }
  1157 
  1070 
  1158     if (p == NULL)
  1071     if (p == NULL)
  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 {
  1235 
  1155 
  1236     return p;
  1156     return p;
  1237 }
  1157 }
  1238 
  1158 
  1239 static
  1159 static
  1240 LPKEYVALUE AddAvailableProperty(LPIT8 it8, const char* Key, WRITEMODE as)
  1160 KEYVALUE* AddAvailableProperty(cmsIT8* it8, const char* Key, WRITEMODE as)
  1241 {
  1161 {
  1242         return AddToList(it8, &it8->ValidKeywords, Key, NULL, NULL, as);
  1162     return AddToList(it8, &it8->ValidKeywords, Key, NULL, NULL, as);
  1243 }
  1163 }
  1244 
  1164 
  1245 
  1165 
  1246 static
  1166 static
  1247 LPKEYVALUE AddAvailableSampleID(LPIT8 it8, const char* Key)
  1167 KEYVALUE* AddAvailableSampleID(cmsIT8* it8, const char* Key)
  1248 {
  1168 {
  1249         return AddToList(it8, &it8->ValidSampleID, Key, NULL, NULL, WRITE_UNCOOKED);
  1169     return AddToList(it8, &it8->ValidSampleID, Key, NULL, NULL, WRITE_UNCOOKED);
  1250 }
  1170 }
  1251 
  1171 
  1252 
  1172 
  1253 static
  1173 static
  1254 void AllocTable(LPIT8 it8)
  1174 void AllocTable(cmsIT8* it8)
  1255 {
  1175 {
  1256     LPTABLE t;
  1176     TABLE* t;
  1257 
  1177 
  1258     t = it8 ->Tab + it8 ->TablesCount;
  1178     t = it8 ->Tab + it8 ->TablesCount;
  1259 
  1179 
  1260     t->HeaderList = NULL;
  1180     t->HeaderList = NULL;
  1261     t->DataFormat = NULL;
  1181     t->DataFormat = NULL;
  1263 
  1183 
  1264     it8 ->TablesCount++;
  1184     it8 ->TablesCount++;
  1265 }
  1185 }
  1266 
  1186 
  1267 
  1187 
  1268 int LCMSEXPORT cmsIT8SetTable(LCMSHANDLE IT8, int nTable)
  1188 cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE  IT8, cmsUInt32Number nTable)
  1269 {
  1189 {
  1270      LPIT8 it8 = (LPIT8) IT8;
  1190      cmsIT8* it8 = (cmsIT8*) IT8;
  1271 
  1191 
  1272      if (nTable >= it8 ->TablesCount) {
  1192      if (nTable >= it8 ->TablesCount) {
  1273 
  1193 
  1274          if (nTable == it8 ->TablesCount) {
  1194          if (nTable == it8 ->TablesCount) {
  1275 
  1195 
  1287 }
  1207 }
  1288 
  1208 
  1289 
  1209 
  1290 
  1210 
  1291 // Init an empty container
  1211 // Init an empty container
  1292 LCMSHANDLE LCMSEXPORT cmsIT8Alloc(void)
  1212 cmsHANDLE  CMSEXPORT cmsIT8Alloc(cmsContext ContextID)
  1293 {
  1213 {
  1294     LPIT8 it8;
  1214     cmsIT8* it8;
  1295     int i;
  1215     int i;
  1296 
  1216 
  1297     it8 = (LPIT8) malloc(sizeof(IT8));
  1217     it8 = (cmsIT8*) _cmsMallocZero(ContextID, sizeof(cmsIT8));
  1298     if (it8 == NULL) return NULL;
  1218     if (it8 == NULL) return NULL;
  1299 
       
  1300     ZeroMemory(it8, sizeof(IT8));
       
  1301 
  1219 
  1302     AllocTable(it8);
  1220     AllocTable(it8);
  1303 
  1221 
  1304     it8->MemoryBlock = NULL;
  1222     it8->MemoryBlock = NULL;
  1305     it8->MemorySink  = NULL;
  1223     it8->MemorySink  = NULL;
  1306 
  1224 
  1307     it8 ->nTable = 0;
  1225     it8 ->nTable = 0;
  1308 
  1226 
       
  1227     it8->ContextID = ContextID;
  1309     it8->Allocator.Used = 0;
  1228     it8->Allocator.Used = 0;
  1310     it8->Allocator.Block = NULL;
  1229     it8->Allocator.Block = NULL;
  1311     it8->Allocator.BlockSize = 0;
  1230     it8->Allocator.BlockSize = 0;
  1312 
  1231 
  1313     it8->ValidKeywords = NULL;
  1232     it8->ValidKeywords = NULL;
  1317     it8 -> ch = ' ';
  1236     it8 -> ch = ' ';
  1318     it8 -> Source = NULL;
  1237     it8 -> Source = NULL;
  1319     it8 -> inum = 0;
  1238     it8 -> inum = 0;
  1320     it8 -> dnum = 0.0;
  1239     it8 -> dnum = 0.0;
  1321 
  1240 
  1322     it8->FileStack[0] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX));
  1241     it8->FileStack[0] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX));
  1323     it8->IncludeSP   = 0;
  1242     it8->IncludeSP   = 0;
  1324     it8 -> lineno = 1;
  1243     it8 -> lineno = 1;
  1325 
  1244 
  1326     strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
  1245     strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
  1327     strcpy(it8->SheetType, "CGATS.17");
  1246     strcpy(it8->SheetType, "CGATS.17");
  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);
  1640 
  1546 
  1641 }
  1547 }
  1642 
  1548 
  1643 // Writes full header
  1549 // Writes full header
  1644 static
  1550 static
  1645 void WriteHeader(LPIT8 it8, LPSAVESTREAM fp)
  1551 void WriteHeader(cmsIT8* it8, SAVESTREAM* fp)
  1646 {
  1552 {
  1647     LPKEYVALUE p;
  1553     KEYVALUE* p;
  1648     LPTABLE t = GetTable(it8);
  1554     TABLE* t = GetTable(it8);
  1649 
  1555 
  1650 
  1556 
  1651     for (p = t->HeaderList; (p != NULL); p = p->Next)
  1557     for (p = t->HeaderList; (p != NULL); p = p->Next)
  1652     {
  1558     {
  1653         if (*p ->Keyword == '#') {
  1559         if (*p ->Keyword == '#') {
  1670         }
  1576         }
  1671 
  1577 
  1672 
  1578 
  1673         if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL, NULL)) {
  1579         if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL, NULL)) {
  1674 
  1580 
  1675 #ifdef STRICT_CGATS
  1581 #ifdef CMS_STRICT_CGATS
  1676             WriteStr(fp, "KEYWORD\t\"");
  1582             WriteStr(fp, "KEYWORD\t\"");
  1677             WriteStr(fp, p->Keyword);
  1583             WriteStr(fp, p->Keyword);
  1678             WriteStr(fp, "\"\n");
  1584             WriteStr(fp, "\"\n");
  1679 #endif
  1585 #endif
  1680 
  1586 
  1681             AddAvailableProperty(it8, p->Keyword, WRITE_UNCOOKED);
  1587             AddAvailableProperty(it8, p->Keyword, WRITE_UNCOOKED);
  1682 
       
  1683         }
  1588         }
  1684 
  1589 
  1685         WriteStr(fp, p->Keyword);
  1590         WriteStr(fp, p->Keyword);
  1686         if (p->Value) {
  1591         if (p->Value) {
  1687 
  1592 
  1718 }
  1623 }
  1719 
  1624 
  1720 
  1625 
  1721 // Writes the data format
  1626 // Writes the data format
  1722 static
  1627 static
  1723 void WriteDataFormat(LPSAVESTREAM fp, LPIT8 it8)
  1628 void WriteDataFormat(SAVESTREAM* fp, cmsIT8* it8)
  1724 {
  1629 {
  1725     int i, nSamples;
  1630     int i, nSamples;
  1726     LPTABLE t = GetTable(it8);
  1631     TABLE* t = GetTable(it8);
  1727 
  1632 
  1728     if (!t -> DataFormat) return;
  1633     if (!t -> DataFormat) return;
  1729 
  1634 
  1730        WriteStr(fp, "BEGIN_DATA_FORMAT\n");
  1635        WriteStr(fp, "BEGIN_DATA_FORMAT\n");
  1731        WriteStr(fp, " ");
  1636        WriteStr(fp, " ");
  1741 }
  1646 }
  1742 
  1647 
  1743 
  1648 
  1744 // Writes data array
  1649 // Writes data array
  1745 static
  1650 static
  1746 void WriteData(LPSAVESTREAM fp, LPIT8 it8)
  1651 void WriteData(SAVESTREAM* fp, cmsIT8* it8)
  1747 {
  1652 {
  1748        int  i, j;
  1653        int  i, j;
  1749        LPTABLE t = GetTable(it8);
  1654        TABLE* t = GetTable(it8);
  1750 
  1655 
  1751        if (!t->Data) return;
  1656        if (!t->Data) return;
  1752 
  1657 
  1753        WriteStr (fp, "BEGIN_DATA\n");
  1658        WriteStr (fp, "BEGIN_DATA\n");
  1754 
  1659 
  1783 }
  1688 }
  1784 
  1689 
  1785 
  1690 
  1786 
  1691 
  1787 // Saves whole file
  1692 // Saves whole file
  1788 LCMSBOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE hIT8, const char* cFileName)
  1693 cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName)
  1789 {
  1694 {
  1790     SAVESTREAM sd;
  1695     SAVESTREAM sd;
  1791     int i;
  1696     cmsUInt32Number i;
  1792     LPIT8 it8 = (LPIT8) hIT8;
  1697     cmsIT8* it8 = (cmsIT8*) hIT8;
  1793 
  1698 
  1794     ZeroMemory(&sd, sizeof(SAVESTREAM));
  1699     memset(&sd, 0, sizeof(sd));
  1795 
  1700 
  1796     sd.stream = fopen(cFileName, "wt");
  1701     sd.stream = fopen(cFileName, "wt");
  1797     if (!sd.stream) return FALSE;
  1702     if (!sd.stream) return FALSE;
  1798 
  1703 
  1799     WriteStr(&sd, it8->SheetType);
  1704     WriteStr(&sd, it8->SheetType);
  1804             WriteHeader(it8, &sd);
  1709             WriteHeader(it8, &sd);
  1805             WriteDataFormat(&sd, it8);
  1710             WriteDataFormat(&sd, it8);
  1806             WriteData(&sd, it8);
  1711             WriteData(&sd, it8);
  1807     }
  1712     }
  1808 
  1713 
  1809     fclose(sd.stream);
  1714     if (fclose(sd.stream) != 0) return FALSE;
  1810 
  1715 
  1811     return TRUE;
  1716     return TRUE;
  1812 }
  1717 }
  1813 
  1718 
  1814 
  1719 
  1815 // Saves to memory
  1720 // Saves to memory
  1816 LCMSBOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded)
  1721 cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* BytesNeeded)
  1817 {
  1722 {
  1818     SAVESTREAM sd;
  1723     SAVESTREAM sd;
  1819     int i;
  1724     cmsUInt32Number i;
  1820     LPIT8 it8 = (LPIT8) hIT8;
  1725     cmsIT8* it8 = (cmsIT8*) hIT8;
  1821 
  1726 
  1822     ZeroMemory(&sd, sizeof(SAVESTREAM));
  1727     memset(&sd, 0, sizeof(sd));
  1823 
  1728 
  1824     sd.stream = NULL;
  1729     sd.stream = NULL;
  1825     sd.Base   = (LPBYTE) MemPtr;
  1730     sd.Base   = (cmsUInt8Number*)  MemPtr;
  1826     sd.Ptr    = sd.Base;
  1731     sd.Ptr    = sd.Base;
  1827 
  1732 
  1828     sd.Used = 0;
  1733     sd.Used = 0;
  1829 
  1734 
  1830     if (sd.Base)
  1735     if (sd.Base)
  1854 
  1759 
  1855 
  1760 
  1856 // -------------------------------------------------------------- Higer level parsing
  1761 // -------------------------------------------------------------- Higer level parsing
  1857 
  1762 
  1858 static
  1763 static
  1859 LCMSBOOL DataFormatSection(LPIT8 it8)
  1764 cmsBool DataFormatSection(cmsIT8* it8)
  1860 {
  1765 {
  1861     int iField = 0;
  1766     int iField = 0;
  1862     LPTABLE t = GetTable(it8);
  1767     TABLE* t = GetTable(it8);
  1863 
  1768 
  1864     InSymbol(it8);   // Eats "BEGIN_DATA_FORMAT"
  1769     InSymbol(it8);   // Eats "BEGIN_DATA_FORMAT"
  1865     CheckEOLN(it8);
  1770     CheckEOLN(it8);
  1866 
  1771 
  1867     while (it8->sy != SEND_DATA_FORMAT &&
  1772     while (it8->sy != SEND_DATA_FORMAT &&
  1895 }
  1800 }
  1896 
  1801 
  1897 
  1802 
  1898 
  1803 
  1899 static
  1804 static
  1900 LCMSBOOL DataSection (LPIT8 it8)
  1805 cmsBool DataSection (cmsIT8* it8)
  1901 {
  1806 {
  1902     int  iField = 0;
  1807     int  iField = 0;
  1903     int  iSet   = 0;
  1808     int  iSet   = 0;
  1904     char Buffer[MAXSTR];
  1809     char Buffer[256];
  1905     LPTABLE t = GetTable(it8);
  1810     TABLE* t = GetTable(it8);
  1906 
  1811 
  1907     InSymbol(it8);   // Eats "BEGIN_DATA"
  1812     InSymbol(it8);   // Eats "BEGIN_DATA"
  1908     CheckEOLN(it8);
  1813     CheckEOLN(it8);
  1909 
  1814 
  1910     if (!t->Data)
  1815     if (!t->Data)
  1947 
  1852 
  1948 
  1853 
  1949 
  1854 
  1950 
  1855 
  1951 static
  1856 static
  1952 LCMSBOOL HeaderSection(LPIT8 it8)
  1857 cmsBool HeaderSection(cmsIT8* it8)
  1953 {
  1858 {
  1954     char VarName[MAXID];
  1859     char VarName[MAXID];
  1955     char Buffer[MAXSTR];
  1860     char Buffer[MAXSTR];
  1956     LPKEYVALUE Key;
  1861     KEYVALUE* Key;
  1957 
  1862 
  1958         while (it8->sy != SEOF &&
  1863         while (it8->sy != SEOF &&
  1959                it8->sy != SSYNERROR &&
  1864                it8->sy != SSYNERROR &&
  1960                it8->sy != SBEGIN_DATA_FORMAT &&
  1865                it8->sy != SBEGIN_DATA_FORMAT &&
  1961                it8->sy != SBEGIN_DATA) {
  1866                it8->sy != SBEGIN_DATA) {
  1983                 strncpy(VarName, it8->id, MAXID-1);
  1888                 strncpy(VarName, it8->id, MAXID-1);
  1984                 VarName[MAXID-1] = 0;
  1889                 VarName[MAXID-1] = 0;
  1985 
  1890 
  1986                 if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) {
  1891                 if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) {
  1987 
  1892 
  1988 #ifdef STRICT_CGATS
  1893 #ifdef CMS_STRICT_CGATS
  1989                  return SynError(it8, "Undefined keyword '%s'", VarName);
  1894                  return SynError(it8, "Undefined keyword '%s'", VarName);
  1990 #else
  1895 #else
  1991                     Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED);
  1896                     Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED);
  1992                     if (Key == NULL) return FALSE;
  1897                     if (Key == NULL) return FALSE;
  1993 #endif
  1898 #endif
  2005                     char *Nextkey;
  1910                     char *Nextkey;
  2006                     if (it8->sy != SSTRING)
  1911                     if (it8->sy != SSTRING)
  2007                         return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName);
  1912                         return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName);
  2008 
  1913 
  2009                     // chop the string as a list of "subkey, value" pairs, using ';' as a separator
  1914                     // chop the string as a list of "subkey, value" pairs, using ';' as a separator
  2010                     for(Subkey = Buffer; Subkey != NULL; Subkey = Nextkey)
  1915                     for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey)
  2011                     {
  1916                     {
  2012                         char *Value, *temp;
  1917                         char *Value, *temp;
  2013 
  1918 
  2014                         //  identify token pair boundary
  1919                         //  identify token pair boundary
  2015                         Nextkey = (char*) strchr(Subkey, ';');
  1920                         Nextkey = (char*) strchr(Subkey, ';');
  2056 
  1961 
  2057 }
  1962 }
  2058 
  1963 
  2059 
  1964 
  2060 static
  1965 static
  2061 LCMSBOOL ParseIT8(LPIT8 it8, LCMSBOOL nosheet)
  1966 cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
  2062 {
  1967 {
  2063     char* SheetTypePtr = it8 ->SheetType;
  1968     char* SheetTypePtr = it8 ->SheetType;
  2064 
  1969 
  2065     if (nosheet == 0) {
  1970     if (nosheet == 0) {
  2066 
  1971 
  2117 
  2022 
  2118 
  2023 
  2119 // Init usefull pointers
  2024 // Init usefull pointers
  2120 
  2025 
  2121 static
  2026 static
  2122 void CookPointers(LPIT8 it8)
  2027 void CookPointers(cmsIT8* it8)
  2123 {
  2028 {
  2124     int idField, i;
  2029     int idField, i;
  2125     char* Fld;
  2030     char* Fld;
  2126     int j;
  2031     cmsUInt32Number j;
  2127     int nOldTable = it8 ->nTable;
  2032     cmsUInt32Number nOldTable = it8 ->nTable;
  2128 
  2033 
  2129     for (j=0; j < it8 ->TablesCount; j++) {
  2034     for (j=0; j < it8 ->TablesCount; j++) {
  2130 
  2035 
  2131     LPTABLE t = it8 ->Tab + j;
  2036     TABLE* t = it8 ->Tab + j;
  2132 
  2037 
  2133     t -> SampleID = 0;
  2038     t -> SampleID = 0;
  2134     it8 ->nTable = j;
  2039     it8 ->nTable = j;
  2135 
  2040 
  2136     for (idField = 0; idField < t -> nSamples; idField++)
  2041     for (idField = 0; idField < t -> nSamples; idField++)
  2137     {
  2042     {
  2138         if (t ->DataFormat == NULL) {
  2043         if (t ->DataFormat == NULL){
  2139              SynError(it8, "Undefined DATA_FORMAT");
  2044             SynError(it8, "Undefined DATA_FORMAT");
  2140              return;
  2045             return;
  2141 
       
  2142         }
  2046         }
  2143 
  2047 
  2144         Fld = t->DataFormat[idField];
  2048         Fld = t->DataFormat[idField];
  2145         if (!Fld) continue;
  2049         if (!Fld) continue;
  2146 
  2050 
  2147 
  2051 
  2148         if (stricmp(Fld, "SAMPLE_ID") == 0) {
  2052         if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) {
  2149 
  2053 
  2150                     t -> SampleID = idField;
  2054                     t -> SampleID = idField;
  2151 
  2055 
  2152         for (i=0; i < t -> nPatches; i++) {
  2056         for (i=0; i < t -> nPatches; i++) {
  2153 
  2057 
  2168 
  2072 
  2169         }
  2073         }
  2170 
  2074 
  2171         // "LABEL" is an extension. It keeps references to forward tables
  2075         // "LABEL" is an extension. It keeps references to forward tables
  2172 
  2076 
  2173         if ((stricmp(Fld, "LABEL") == 0) || Fld[0] == '$' ) {
  2077         if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$' ) {
  2174 
  2078 
  2175                     // Search for table references...
  2079                     // Search for table references...
  2176                     for (i=0; i < t -> nPatches; i++) {
  2080                     for (i=0; i < t -> nPatches; i++) {
  2177 
  2081 
  2178                             char *Label = GetData(it8, i, idField);
  2082                             char *Label = GetData(it8, i, idField);
  2179 
  2083 
  2180                             if (Label) {
  2084                             if (Label) {
  2181 
  2085 
  2182                                 int k;
  2086                                 cmsUInt32Number k;
  2183 
  2087 
  2184                                 // This is the label, search for a table containing
  2088                                 // This is the label, search for a table containing
  2185                                 // this property
  2089                                 // this property
  2186 
  2090 
  2187                                 for (k=0; k < it8 ->TablesCount; k++) {
  2091                                 for (k=0; k < it8 ->TablesCount; k++) {
  2188 
  2092 
  2189                                     LPTABLE Table = it8 ->Tab + k;
  2093                                     TABLE* Table = it8 ->Tab + k;
  2190                                     LPKEYVALUE p;
  2094                                     KEYVALUE* p;
  2191 
  2095 
  2192                                     if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) {
  2096                                     if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) {
  2193 
  2097 
  2194                                         // Available, keep type and table
  2098                                         // Available, keep type and table
  2195                                         char Buffer[256];
  2099                                         char Buffer[256];
  2219 
  2123 
  2220 // Try to infere if the file is a CGATS/IT8 file at all. Read first line
  2124 // Try to infere if the file is a CGATS/IT8 file at all. Read first line
  2221 // that should be something like some printable characters plus a \n
  2125 // that should be something like some printable characters plus a \n
  2222 
  2126 
  2223 static
  2127 static
  2224 int IsMyBlock(LPBYTE Buffer, size_t n)
  2128 int IsMyBlock(cmsUInt8Number* Buffer, int n)
  2225 {
  2129 {
  2226     int cols = 1, space = 0, quot = 0;
  2130     int cols = 1, space = 0, quot = 0;
  2227     size_t i;
  2131     int i;
  2228 
  2132 
  2229     if (n < 10) return FALSE;   // Too small
  2133     if (n < 10) return FALSE;   // Too small
  2230 
  2134 
  2231     if (n > 132)
  2135     if (n > 132)
  2232         n = 132;
  2136         n = 132;
  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);
  2311     }
  2221     }
  2312 
  2222 
  2313     CookPointers(it8);
  2223     CookPointers(it8);
  2314     it8 ->nTable = 0;
  2224     it8 ->nTable = 0;
  2315 
  2225 
  2316      _cmsFree(it8->MemoryBlock);
  2226     _cmsFree(ContextID, it8->MemoryBlock);
  2317     it8 -> MemoryBlock = NULL;
  2227     it8 -> MemoryBlock = NULL;
  2318 
  2228 
  2319     return hIT8;
  2229     return hIT8;
  2320 
  2230 
  2321 
  2231 
  2322 }
  2232 }
  2323 
  2233 
  2324 
  2234 
  2325 LCMSHANDLE LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName)
  2235 cmsHANDLE  CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileName)
  2326 {
  2236 {
  2327 
  2237 
  2328      LCMSHANDLE hIT8;
  2238      cmsHANDLE hIT8;
  2329      LPIT8  it8;
  2239      cmsIT8*  it8;
  2330 
  2240      int type;
  2331      int type = IsMyFile(cFileName);
  2241 
       
  2242      _cmsAssert(cFileName != NULL);
       
  2243 
       
  2244      type = IsMyFile(cFileName);
  2332      if (type == 0) return NULL;
  2245      if (type == 0) return NULL;
  2333 
  2246 
  2334      hIT8 = cmsIT8Alloc();
  2247      hIT8 = cmsIT8Alloc(ContextID);
  2335      it8 = (LPIT8) hIT8;
  2248      it8 = (cmsIT8*) hIT8;
  2336      if (!hIT8) return NULL;
  2249      if (!hIT8) return NULL;
  2337 
  2250 
  2338 
  2251 
  2339      it8 ->FileStack[0]->Stream = fopen(cFileName, "rt");
  2252      it8 ->FileStack[0]->Stream = fopen(cFileName, "rt");
  2340 
  2253 
  2342          cmsIT8Free(hIT8);
  2255          cmsIT8Free(hIT8);
  2343          return NULL;
  2256          return NULL;
  2344      }
  2257      }
  2345 
  2258 
  2346 
  2259 
  2347     strncpy(it8->FileStack[0]->FileName, cFileName, MAX_PATH-1);
  2260     strncpy(it8->FileStack[0]->FileName, cFileName, cmsMAX_PATH-1);
  2348     it8->FileStack[0]->FileName[MAX_PATH-1] = 0;
  2261     it8->FileStack[0]->FileName[cmsMAX_PATH-1] = 0;
  2349 
  2262 
  2350     if (!ParseIT8(it8, type-1)) {
  2263     if (!ParseIT8(it8, type-1)) {
  2351 
  2264 
  2352             fclose(it8 ->FileStack[0]->Stream);
  2265             fclose(it8 ->FileStack[0]->Stream);
  2353             cmsIT8Free(hIT8);
  2266             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;
  2398 
  2324 
  2399     *PropertyNames = Props;
  2325     *PropertyNames = Props;
  2400     return n;
  2326     return n;
  2401 }
  2327 }
  2402 
  2328 
  2403 int LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char ***SubpropertyNames)
  2329 cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cProp, const char ***SubpropertyNames)
  2404 {
  2330 {
  2405     LPIT8 it8 = (LPIT8) hIT8;
  2331     cmsIT8* it8 = (cmsIT8*) hIT8;
  2406     LPKEYVALUE p, tmp;
  2332     KEYVALUE *p, *tmp;
  2407     int n;
  2333     cmsUInt32Number n;
  2408     const char **Props;
  2334     const char **Props;
  2409     LPTABLE t = GetTable(it8);
  2335     TABLE* t;
       
  2336 
       
  2337     _cmsAssert(hIT8 != NULL);
       
  2338 
       
  2339 
       
  2340     t = GetTable(it8);
  2410 
  2341 
  2411     if(!IsAvailableOnList(t->HeaderList, cProp, NULL, &p)) {
  2342     if(!IsAvailableOnList(t->HeaderList, cProp, NULL, &p)) {
  2412         *SubpropertyNames = 0;
  2343         *SubpropertyNames = 0;
  2413         return 0;
  2344         return 0;
  2414     }
  2345     }
  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);