IMG_xpm.c
author Andreas Schiffler <aschiffler@ferzkopp.net>
Sun, 03 Feb 2013 08:37:28 -0800
changeset 343 5bf0f0d6a74e
parent 339 2e4f9d95a8c8
child 344 d59179e84a3b
permissions -rw-r--r--
Added VS2010 and VS2012 projects; updates for VS compile; fixes from VS code analysis and code review
     1 /*
     2   SDL_image:  An example image loading library for use with SDL
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 /*
    23  * XPM (X PixMap) image loader:
    24  *
    25  * Supports the XPMv3 format, EXCEPT:
    26  * - hotspot coordinates are ignored
    27  * - only colour ('c') colour symbols are used
    28  * - rgb.txt is not used (for portability), so only RGB colours
    29  *   are recognized (#rrggbb etc) - only a few basic colour names are
    30  *   handled
    31  *
    32  * The result is an 8bpp indexed surface if possible, otherwise 32bpp.
    33  * The colourkey is correctly set if transparency is used.
    34  * 
    35  * Besides the standard API, also provides
    36  *
    37  *     SDL_Surface *IMG_ReadXPMFromArray(char **xpm)
    38  *
    39  * that reads the image data from an XPM file included in the C source.
    40  *
    41  * TODO: include rgb.txt here. The full table (from solaris 2.6) only
    42  * requires about 13K in binary form.
    43  */
    44 
    45 #include <stdlib.h>
    46 #include <stdio.h>
    47 #include <string.h>
    48 #include <ctype.h>
    49 
    50 #include "SDL_image.h"
    51 
    52 #ifdef LOAD_XPM
    53 
    54 /* See if an image is contained in a data source */
    55 int IMG_isXPM(SDL_RWops *src)
    56 {
    57 	Sint64 start;
    58 	int is_XPM;
    59 	char magic[9];
    60 
    61 	if ( !src )
    62 		return 0;
    63 	start = SDL_RWtell(src);
    64 	is_XPM = 0;
    65 	if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
    66 		if ( SDL_memcmp(magic, "/* XPM */", sizeof(magic)) == 0 ) {
    67 			is_XPM = 1;
    68 		}
    69 	}
    70 	SDL_RWseek(src, start, RW_SEEK_SET);
    71 	return(is_XPM);
    72 }
    73 
    74 /* Hash table to look up colors from pixel strings */
    75 #define STARTING_HASH_SIZE 256
    76 
    77 struct hash_entry {
    78 	char *key;
    79 	Uint32 color;
    80 	struct hash_entry *next;
    81 };
    82 
    83 struct color_hash {
    84 	struct hash_entry **table;
    85 	struct hash_entry *entries; /* array of all entries */
    86 	struct hash_entry *next_free;
    87 	int size;
    88 	int maxnum;
    89 };
    90 
    91 static int hash_key(const char *key, int cpp, int size)
    92 {
    93 	int hash;
    94 
    95 	hash = 0;
    96 	while ( cpp-- > 0 ) {
    97 		hash = hash * 33 + *key++;
    98 	}
    99 	return hash & (size - 1);
   100 }
   101 
   102 static struct color_hash *create_colorhash(int maxnum)
   103 {
   104 	int bytes, s;
   105 	struct color_hash *hash;
   106 
   107 	/* we know how many entries we need, so we can allocate
   108 	   everything here */
   109 	hash = (struct color_hash *)SDL_malloc(sizeof *hash);
   110 	if(!hash)
   111 		return NULL;
   112 
   113 	/* use power-of-2 sized hash table for decoding speed */
   114 	for(s = STARTING_HASH_SIZE; s < maxnum; s <<= 1)
   115 		;
   116 	hash->size = s;
   117 	hash->maxnum = maxnum;
   118 	bytes = hash->size * sizeof(struct hash_entry **);
   119 	hash->entries = NULL;	/* in case malloc fails */
   120 	hash->table = (struct hash_entry **)SDL_malloc(bytes);
   121 	if(!hash->table)
   122 		return NULL;
   123 	memset(hash->table, 0, bytes);
   124 	hash->entries = (struct hash_entry *)SDL_malloc(maxnum * sizeof(struct hash_entry));
   125 	if(!hash->entries) {
   126 		SDL_free(hash->table);
   127 		return NULL;
   128 	}
   129 	hash->next_free = hash->entries;
   130 	return hash;
   131 }
   132 
   133 static int add_colorhash(struct color_hash *hash,
   134                          char *key, int cpp, Uint32 color)
   135 {
   136 	int index = hash_key(key, cpp, hash->size);
   137 	struct hash_entry *e = hash->next_free++;
   138 	e->color = color;
   139 	e->key = key;
   140 	e->next = hash->table[index];
   141 	hash->table[index] = e;
   142 	return 1;
   143 }
   144 
   145 /* fast lookup that works if cpp == 1 */
   146 #define QUICK_COLORHASH(hash, key) ((hash)->table[*(Uint8 *)(key)]->color)
   147 
   148 static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp)
   149 {
   150 	struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
   151 	while(entry) {
   152 		if(SDL_memcmp(key, entry->key, cpp) == 0)
   153 			return entry->color;
   154 		entry = entry->next;
   155 	}
   156 	return 0;		/* garbage in - garbage out */
   157 }
   158 
   159 static void free_colorhash(struct color_hash *hash)
   160 {
   161 	if(hash) {
   162 		if(hash->table)
   163 			SDL_free(hash->table);
   164 		if(hash->entries)
   165 			SDL_free(hash->entries);
   166 		SDL_free(hash);
   167 	}
   168 }
   169 
   170 /*
   171  * convert colour spec to RGB (in 0xrrggbb format).
   172  * return 1 if successful.
   173  */
   174 static int color_to_rgb(char *spec, int speclen, Uint32 *rgb)
   175 {
   176 	/* poor man's rgb.txt */
   177 	static struct { char *name; Uint32 rgb; } known[] = {
   178 		{ "none",                 0xFFFFFF },
   179 		{ "black",                0x000000 },
   180 		{ "white",                0xFFFFFF },
   181 		{ "red",                  0xFF0000 },
   182 		{ "green",                0x00FF00 },
   183 		{ "blue",                 0x0000FF },
   184 /* This table increases the size of the library by 40K, so it's disabled by default */
   185 #ifdef EXTENDED_XPM_COLORS
   186 		{ "aliceblue",            0xf0f8ff },
   187 		{ "antiquewhite",         0xfaebd7 },
   188 		{ "antiquewhite1",        0xffefdb },
   189 		{ "antiquewhite2",        0xeedfcc },
   190 		{ "antiquewhite3",        0xcdc0b0 },
   191 		{ "antiquewhite4",        0x8b8378 },
   192 		{ "aqua",                 0x00ffff },
   193 		{ "aquamarine",           0x7fffd4 },
   194 		{ "aquamarine1",          0x7fffd4 },
   195 		{ "aquamarine2",          0x76eec6 },
   196 		{ "aquamarine3",          0x66cdaa },
   197 		{ "aquamarine4",          0x458b74 },
   198 		{ "azure",                0xf0ffff },
   199 		{ "azure1",               0xf0ffff },
   200 		{ "azure2",               0xe0eeee },
   201 		{ "azure3",               0xc1cdcd },
   202 		{ "azure4",               0x838b8b },
   203 		{ "beige",                0xf5f5dc },
   204 		{ "bisque",               0xffe4c4 },
   205 		{ "bisque1",              0xffe4c4 },
   206 		{ "bisque2",              0xeed5b7 },
   207 		{ "bisque3",              0xcdb79e },
   208 		{ "bisque4",              0x8b7d6b },
   209 		{ "black",                0x000000 },
   210 		{ "blanchedalmond",       0xffebcd },
   211 		{ "blue",                 0x0000ff },
   212 		{ "blue1",                0x0000ff },
   213 		{ "blue2",                0x0000ee },
   214 		{ "blue3",                0x0000cd },
   215 		{ "blue4",                0x00008B },
   216 		{ "blueviolet",           0x8a2be2 },
   217 		{ "brown",                0xA52A2A },
   218 		{ "brown1",               0xFF4040 },
   219 		{ "brown2",               0xEE3B3B },
   220 		{ "brown3",               0xCD3333 },
   221 		{ "brown4",               0x8B2323 },
   222 		{ "burlywood",            0xDEB887 },
   223 		{ "burlywood1",           0xFFD39B },
   224 		{ "burlywood2",           0xEEC591 },
   225 		{ "burlywood3",           0xCDAA7D },
   226 		{ "burlywood4",           0x8B7355 },
   227 		{ "cadetblue",            0x5F9EA0 },
   228 		{ "cadetblue",            0x5f9ea0 },
   229 		{ "cadetblue1",           0x98f5ff },
   230 		{ "cadetblue2",           0x8ee5ee },
   231 		{ "cadetblue3",           0x7ac5cd },
   232 		{ "cadetblue4",           0x53868b },
   233 		{ "chartreuse",           0x7FFF00 },
   234 		{ "chartreuse1",          0x7FFF00 },
   235 		{ "chartreuse2",          0x76EE00 },
   236 		{ "chartreuse3",          0x66CD00 },
   237 		{ "chartreuse4",          0x458B00 },
   238 		{ "chocolate",            0xD2691E },
   239 		{ "chocolate1",           0xFF7F24 },
   240 		{ "chocolate2",           0xEE7621 },
   241 		{ "chocolate3",           0xCD661D },
   242 		{ "chocolate4",           0x8B4513 },
   243 		{ "coral",                0xFF7F50 },
   244 		{ "coral1",               0xFF7256 },
   245 		{ "coral2",               0xEE6A50 },
   246 		{ "coral3",               0xCD5B45 },
   247 		{ "coral4",               0x8B3E2F },
   248 		{ "cornflowerblue",       0x6495ed },
   249 		{ "cornsilk",             0xFFF8DC },
   250 		{ "cornsilk1",            0xFFF8DC },
   251 		{ "cornsilk2",            0xEEE8CD },
   252 		{ "cornsilk3",            0xCDC8B1 },
   253 		{ "cornsilk4",            0x8B8878 },
   254 		{ "crimson",              0xDC143C },
   255 		{ "cyan",                 0x00FFFF },
   256 		{ "cyan1",                0x00FFFF },
   257 		{ "cyan2",                0x00EEEE },
   258 		{ "cyan3",                0x00CDCD },
   259 		{ "cyan4",                0x008B8B },
   260 		{ "darkblue",             0x00008b },
   261 		{ "darkcyan",             0x008b8b },
   262 		{ "darkgoldenrod",        0xb8860b },
   263 		{ "darkgoldenrod1",       0xffb90f },
   264 		{ "darkgoldenrod2",       0xeead0e },
   265 		{ "darkgoldenrod3",       0xcd950c },
   266 		{ "darkgoldenrod4",       0x8b6508 },
   267 		{ "darkgray",             0xa9a9a9 },
   268 		{ "darkgreen",            0x006400 },
   269 		{ "darkgrey",             0xa9a9a9 },
   270 		{ "darkkhaki",            0xbdb76b },
   271 		{ "darkmagenta",          0x8b008b },
   272 		{ "darkolivegreen",       0x556b2f },
   273 		{ "darkolivegreen1",      0xcaff70 },
   274 		{ "darkolivegreen2",      0xbcee68 },
   275 		{ "darkolivegreen3",      0xa2cd5a },
   276 		{ "darkolivegreen4",      0x6e8b3d },
   277 		{ "darkorange",           0xff8c00 },
   278 		{ "darkorange1",          0xff7f00 },
   279 		{ "darkorange2",          0xee7600 },
   280 		{ "darkorange3",          0xcd6600 },
   281 		{ "darkorange4",          0x8b4500 },
   282 		{ "darkorchid",           0x9932cc },
   283 		{ "darkorchid1",          0xbf3eff },
   284 		{ "darkorchid2",          0xb23aee },
   285 		{ "darkorchid3",          0x9a32cd },
   286 		{ "darkorchid4",          0x68228b },
   287 		{ "darkred",              0x8b0000 },
   288 		{ "darksalmon",           0xe9967a },
   289 		{ "darkseagreen",         0x8fbc8f },
   290 		{ "darkseagreen1",        0xc1ffc1 },
   291 		{ "darkseagreen2",        0xb4eeb4 },
   292 		{ "darkseagreen3",        0x9bcd9b },
   293 		{ "darkseagreen4",        0x698b69 },
   294 		{ "darkslateblue",        0x483d8b },
   295 		{ "darkslategray",        0x2f4f4f },
   296 		{ "darkslategray1",       0x97ffff },
   297 		{ "darkslategray2",       0x8deeee },
   298 		{ "darkslategray3",       0x79cdcd },
   299 		{ "darkslategray4",       0x528b8b },
   300 		{ "darkslategrey",        0x2f4f4f },
   301 		{ "darkturquoise",        0x00ced1 },
   302 		{ "darkviolet",           0x9400D3 },
   303 		{ "darkviolet",           0x9400d3 },
   304 		{ "deeppink",             0xff1493 },
   305 		{ "deeppink1",            0xff1493 },
   306 		{ "deeppink2",            0xee1289 },
   307 		{ "deeppink3",            0xcd1076 },
   308 		{ "deeppink4",            0x8b0a50 },
   309 		{ "deepskyblue",          0x00bfff },
   310 		{ "deepskyblue1",         0x00bfff },
   311 		{ "deepskyblue2",         0x00b2ee },
   312 		{ "deepskyblue3",         0x009acd },
   313 		{ "deepskyblue4",         0x00688b },
   314 		{ "dimgray",              0x696969 },
   315 		{ "dimgrey",              0x696969 },
   316 		{ "dodgerblue",           0x1e90ff },
   317 		{ "dodgerblue1",          0x1e90ff },
   318 		{ "dodgerblue2",          0x1c86ee },
   319 		{ "dodgerblue3",          0x1874cd },
   320 		{ "dodgerblue4",          0x104e8b },
   321 		{ "firebrick",            0xB22222 },
   322 		{ "firebrick1",           0xFF3030 },
   323 		{ "firebrick2",           0xEE2C2C },
   324 		{ "firebrick3",           0xCD2626 },
   325 		{ "firebrick4",           0x8B1A1A },
   326 		{ "floralwhite",          0xfffaf0 },
   327 		{ "forestgreen",          0x228b22 },
   328 		{ "fractal",              0x808080 },
   329 		{ "fuchsia",              0xFF00FF },
   330 		{ "gainsboro",            0xDCDCDC },
   331 		{ "ghostwhite",           0xf8f8ff },
   332 		{ "gold",                 0xFFD700 },
   333 		{ "gold1",                0xFFD700 },
   334 		{ "gold2",                0xEEC900 },
   335 		{ "gold3",                0xCDAD00 },
   336 		{ "gold4",                0x8B7500 },
   337 		{ "goldenrod",            0xDAA520 },
   338 		{ "goldenrod1",           0xFFC125 },
   339 		{ "goldenrod2",           0xEEB422 },
   340 		{ "goldenrod3",           0xCD9B1D },
   341 		{ "goldenrod4",           0x8B6914 },
   342 		{ "gray",                 0x7E7E7E },
   343 		{ "gray",                 0xBEBEBE },
   344 		{ "gray0",                0x000000 },
   345 		{ "gray1",                0x030303 },
   346 		{ "gray10",               0x1A1A1A },
   347 		{ "gray100",              0xFFFFFF },
   348 		{ "gray11",               0x1C1C1C },
   349 		{ "gray12",               0x1F1F1F },
   350 		{ "gray13",               0x212121 },
   351 		{ "gray14",               0x242424 },
   352 		{ "gray15",               0x262626 },
   353 		{ "gray16",               0x292929 },
   354 		{ "gray17",               0x2B2B2B },
   355 		{ "gray18",               0x2E2E2E },
   356 		{ "gray19",               0x303030 },
   357 		{ "gray2",                0x050505 },
   358 		{ "gray20",               0x333333 },
   359 		{ "gray21",               0x363636 },
   360 		{ "gray22",               0x383838 },
   361 		{ "gray23",               0x3B3B3B },
   362 		{ "gray24",               0x3D3D3D },
   363 		{ "gray25",               0x404040 },
   364 		{ "gray26",               0x424242 },
   365 		{ "gray27",               0x454545 },
   366 		{ "gray28",               0x474747 },
   367 		{ "gray29",               0x4A4A4A },
   368 		{ "gray3",                0x080808 },
   369 		{ "gray30",               0x4D4D4D },
   370 		{ "gray31",               0x4F4F4F },
   371 		{ "gray32",               0x525252 },
   372 		{ "gray33",               0x545454 },
   373 		{ "gray34",               0x575757 },
   374 		{ "gray35",               0x595959 },
   375 		{ "gray36",               0x5C5C5C },
   376 		{ "gray37",               0x5E5E5E },
   377 		{ "gray38",               0x616161 },
   378 		{ "gray39",               0x636363 },
   379 		{ "gray4",                0x0A0A0A },
   380 		{ "gray40",               0x666666 },
   381 		{ "gray41",               0x696969 },
   382 		{ "gray42",               0x6B6B6B },
   383 		{ "gray43",               0x6E6E6E },
   384 		{ "gray44",               0x707070 },
   385 		{ "gray45",               0x737373 },
   386 		{ "gray46",               0x757575 },
   387 		{ "gray47",               0x787878 },
   388 		{ "gray48",               0x7A7A7A },
   389 		{ "gray49",               0x7D7D7D },
   390 		{ "gray5",                0x0D0D0D },
   391 		{ "gray50",               0x7F7F7F },
   392 		{ "gray51",               0x828282 },
   393 		{ "gray52",               0x858585 },
   394 		{ "gray53",               0x878787 },
   395 		{ "gray54",               0x8A8A8A },
   396 		{ "gray55",               0x8C8C8C },
   397 		{ "gray56",               0x8F8F8F },
   398 		{ "gray57",               0x919191 },
   399 		{ "gray58",               0x949494 },
   400 		{ "gray59",               0x969696 },
   401 		{ "gray6",                0x0F0F0F },
   402 		{ "gray60",               0x999999 },
   403 		{ "gray61",               0x9C9C9C },
   404 		{ "gray62",               0x9E9E9E },
   405 		{ "gray63",               0xA1A1A1 },
   406 		{ "gray64",               0xA3A3A3 },
   407 		{ "gray65",               0xA6A6A6 },
   408 		{ "gray66",               0xA8A8A8 },
   409 		{ "gray67",               0xABABAB },
   410 		{ "gray68",               0xADADAD },
   411 		{ "gray69",               0xB0B0B0 },
   412 		{ "gray7",                0x121212 },
   413 		{ "gray70",               0xB3B3B3 },
   414 		{ "gray71",               0xB5B5B5 },
   415 		{ "gray72",               0xB8B8B8 },
   416 		{ "gray73",               0xBABABA },
   417 		{ "gray74",               0xBDBDBD },
   418 		{ "gray75",               0xBFBFBF },
   419 		{ "gray76",               0xC2C2C2 },
   420 		{ "gray77",               0xC4C4C4 },
   421 		{ "gray78",               0xC7C7C7 },
   422 		{ "gray79",               0xC9C9C9 },
   423 		{ "gray8",                0x141414 },
   424 		{ "gray80",               0xCCCCCC },
   425 		{ "gray81",               0xCFCFCF },
   426 		{ "gray82",               0xD1D1D1 },
   427 		{ "gray83",               0xD4D4D4 },
   428 		{ "gray84",               0xD6D6D6 },
   429 		{ "gray85",               0xD9D9D9 },
   430 		{ "gray86",               0xDBDBDB },
   431 		{ "gray87",               0xDEDEDE },
   432 		{ "gray88",               0xE0E0E0 },
   433 		{ "gray89",               0xE3E3E3 },
   434 		{ "gray9",                0x171717 },
   435 		{ "gray90",               0xE5E5E5 },
   436 		{ "gray91",               0xE8E8E8 },
   437 		{ "gray92",               0xEBEBEB },
   438 		{ "gray93",               0xEDEDED },
   439 		{ "gray94",               0xF0F0F0 },
   440 		{ "gray95",               0xF2F2F2 },
   441 		{ "gray96",               0xF5F5F5 },
   442 		{ "gray97",               0xF7F7F7 },
   443 		{ "gray98",               0xFAFAFA },
   444 		{ "gray99",               0xFCFCFC },
   445 		{ "green",                0x008000 },
   446 		{ "green",                0x00FF00 },
   447 		{ "green1",               0x00FF00 },
   448 		{ "green2",               0x00EE00 },
   449 		{ "green3",               0x00CD00 },
   450 		{ "green4",               0x008B00 },
   451 		{ "greenyellow",          0xadff2f },
   452 		{ "grey",                 0xBEBEBE },
   453 		{ "grey0",                0x000000 },
   454 		{ "grey1",                0x030303 },
   455 		{ "grey10",               0x1A1A1A },
   456 		{ "grey100",              0xFFFFFF },
   457 		{ "grey11",               0x1C1C1C },
   458 		{ "grey12",               0x1F1F1F },
   459 		{ "grey13",               0x212121 },
   460 		{ "grey14",               0x242424 },
   461 		{ "grey15",               0x262626 },
   462 		{ "grey16",               0x292929 },
   463 		{ "grey17",               0x2B2B2B },
   464 		{ "grey18",               0x2E2E2E },
   465 		{ "grey19",               0x303030 },
   466 		{ "grey2",                0x050505 },
   467 		{ "grey20",               0x333333 },
   468 		{ "grey21",               0x363636 },
   469 		{ "grey22",               0x383838 },
   470 		{ "grey23",               0x3B3B3B },
   471 		{ "grey24",               0x3D3D3D },
   472 		{ "grey25",               0x404040 },
   473 		{ "grey26",               0x424242 },
   474 		{ "grey27",               0x454545 },
   475 		{ "grey28",               0x474747 },
   476 		{ "grey29",               0x4A4A4A },
   477 		{ "grey3",                0x080808 },
   478 		{ "grey30",               0x4D4D4D },
   479 		{ "grey31",               0x4F4F4F },
   480 		{ "grey32",               0x525252 },
   481 		{ "grey33",               0x545454 },
   482 		{ "grey34",               0x575757 },
   483 		{ "grey35",               0x595959 },
   484 		{ "grey36",               0x5C5C5C },
   485 		{ "grey37",               0x5E5E5E },
   486 		{ "grey38",               0x616161 },
   487 		{ "grey39",               0x636363 },
   488 		{ "grey4",                0x0A0A0A },
   489 		{ "grey40",               0x666666 },
   490 		{ "grey41",               0x696969 },
   491 		{ "grey42",               0x6B6B6B },
   492 		{ "grey43",               0x6E6E6E },
   493 		{ "grey44",               0x707070 },
   494 		{ "grey45",               0x737373 },
   495 		{ "grey46",               0x757575 },
   496 		{ "grey47",               0x787878 },
   497 		{ "grey48",               0x7A7A7A },
   498 		{ "grey49",               0x7D7D7D },
   499 		{ "grey5",                0x0D0D0D },
   500 		{ "grey50",               0x7F7F7F },
   501 		{ "grey51",               0x828282 },
   502 		{ "grey52",               0x858585 },
   503 		{ "grey53",               0x878787 },
   504 		{ "grey54",               0x8A8A8A },
   505 		{ "grey55",               0x8C8C8C },
   506 		{ "grey56",               0x8F8F8F },
   507 		{ "grey57",               0x919191 },
   508 		{ "grey58",               0x949494 },
   509 		{ "grey59",               0x969696 },
   510 		{ "grey6",                0x0F0F0F },
   511 		{ "grey60",               0x999999 },
   512 		{ "grey61",               0x9C9C9C },
   513 		{ "grey62",               0x9E9E9E },
   514 		{ "grey63",               0xA1A1A1 },
   515 		{ "grey64",               0xA3A3A3 },
   516 		{ "grey65",               0xA6A6A6 },
   517 		{ "grey66",               0xA8A8A8 },
   518 		{ "grey67",               0xABABAB },
   519 		{ "grey68",               0xADADAD },
   520 		{ "grey69",               0xB0B0B0 },
   521 		{ "grey7",                0x121212 },
   522 		{ "grey70",               0xB3B3B3 },
   523 		{ "grey71",               0xB5B5B5 },
   524 		{ "grey72",               0xB8B8B8 },
   525 		{ "grey73",               0xBABABA },
   526 		{ "grey74",               0xBDBDBD },
   527 		{ "grey75",               0xBFBFBF },
   528 		{ "grey76",               0xC2C2C2 },
   529 		{ "grey77",               0xC4C4C4 },
   530 		{ "grey78",               0xC7C7C7 },
   531 		{ "grey79",               0xC9C9C9 },
   532 		{ "grey8",                0x141414 },
   533 		{ "grey80",               0xCCCCCC },
   534 		{ "grey81",               0xCFCFCF },
   535 		{ "grey82",               0xD1D1D1 },
   536 		{ "grey83",               0xD4D4D4 },
   537 		{ "grey84",               0xD6D6D6 },
   538 		{ "grey85",               0xD9D9D9 },
   539 		{ "grey86",               0xDBDBDB },
   540 		{ "grey87",               0xDEDEDE },
   541 		{ "grey88",               0xE0E0E0 },
   542 		{ "grey89",               0xE3E3E3 },
   543 		{ "grey9",                0x171717 },
   544 		{ "grey90",               0xE5E5E5 },
   545 		{ "grey91",               0xE8E8E8 },
   546 		{ "grey92",               0xEBEBEB },
   547 		{ "grey93",               0xEDEDED },
   548 		{ "grey94",               0xF0F0F0 },
   549 		{ "grey95",               0xF2F2F2 },
   550 		{ "grey96",               0xF5F5F5 },
   551 		{ "grey97",               0xF7F7F7 },
   552 		{ "grey98",               0xFAFAFA },
   553 		{ "grey99",               0xFCFCFC },
   554 		{ "honeydew",             0xF0FFF0 },
   555 		{ "honeydew1",            0xF0FFF0 },
   556 		{ "honeydew2",            0xE0EEE0 },
   557 		{ "honeydew3",            0xC1CDC1 },
   558 		{ "honeydew4",            0x838B83 },
   559 		{ "hotpink",              0xff69b4 },
   560 		{ "hotpink1",             0xff6eb4 },
   561 		{ "hotpink2",             0xee6aa7 },
   562 		{ "hotpink3",             0xcd6090 },
   563 		{ "hotpink4",             0x8b3a62 },
   564 		{ "indianred",            0xcd5c5c },
   565 		{ "indianred1",           0xff6a6a },
   566 		{ "indianred2",           0xee6363 },
   567 		{ "indianred3",           0xcd5555 },
   568 		{ "indianred4",           0x8b3a3a },
   569 		{ "indigo",               0x4B0082 },
   570 		{ "ivory",                0xFFFFF0 },
   571 		{ "ivory1",               0xFFFFF0 },
   572 		{ "ivory2",               0xEEEEE0 },
   573 		{ "ivory3",               0xCDCDC1 },
   574 		{ "ivory4",               0x8B8B83 },
   575 		{ "khaki",                0xF0E68C },
   576 		{ "khaki1",               0xFFF68F },
   577 		{ "khaki2",               0xEEE685 },
   578 		{ "khaki3",               0xCDC673 },
   579 		{ "khaki4",               0x8B864E },
   580 		{ "lavender",             0xE6E6FA },
   581 		{ "lavenderblush",        0xfff0f5 },
   582 		{ "lavenderblush1",       0xfff0f5 },
   583 		{ "lavenderblush2",       0xeee0e5 },
   584 		{ "lavenderblush3",       0xcdc1c5 },
   585 		{ "lavenderblush4",       0x8b8386 },
   586 		{ "lawngreen",            0x7cfc00 },
   587 		{ "lemonchiffon",         0xfffacd },
   588 		{ "lemonchiffon1",        0xfffacd },
   589 		{ "lemonchiffon2",        0xeee9bf },
   590 		{ "lemonchiffon3",        0xcdc9a5 },
   591 		{ "lemonchiffon4",        0x8b8970 },
   592 		{ "lightblue",            0xadd8e6 },
   593 		{ "lightblue1",           0xbfefff },
   594 		{ "lightblue2",           0xb2dfee },
   595 		{ "lightblue3",           0x9ac0cd },
   596 		{ "lightblue4",           0x68838b },
   597 		{ "lightcoral",           0xf08080 },
   598 		{ "lightcyan",            0xe0ffff },
   599 		{ "lightcyan1",           0xe0ffff },
   600 		{ "lightcyan2",           0xd1eeee },
   601 		{ "lightcyan3",           0xb4cdcd },
   602 		{ "lightcyan4",           0x7a8b8b },
   603 		{ "lightgoldenrod",       0xeedd82 },
   604 		{ "lightgoldenrod1",      0xffec8b },
   605 		{ "lightgoldenrod2",      0xeedc82 },
   606 		{ "lightgoldenrod3",      0xcdbe70 },
   607 		{ "lightgoldenrod4",      0x8b814c },
   608 		{ "lightgoldenrodyellow", 0xfafad2 },
   609 		{ "lightgray",            0xd3d3d3 },
   610 		{ "lightgreen",           0x90ee90 },
   611 		{ "lightgrey",            0xd3d3d3 },
   612 		{ "lightpink",            0xffb6c1 },
   613 		{ "lightpink1",           0xffaeb9 },
   614 		{ "lightpink2",           0xeea2ad },
   615 		{ "lightpink3",           0xcd8c95 },
   616 		{ "lightpink4",           0x8b5f65 },
   617 		{ "lightsalmon",          0xffa07a },
   618 		{ "lightsalmon1",         0xffa07a },
   619 		{ "lightsalmon2",         0xee9572 },
   620 		{ "lightsalmon3",         0xcd8162 },
   621 		{ "lightsalmon4",         0x8b5742 },
   622 		{ "lightseagreen",        0x20b2aa },
   623 		{ "lightskyblue",         0x87cefa },
   624 		{ "lightskyblue1",        0xb0e2ff },
   625 		{ "lightskyblue2",        0xa4d3ee },
   626 		{ "lightskyblue3",        0x8db6cd },
   627 		{ "lightskyblue4",        0x607b8b },
   628 		{ "lightslateblue",       0x8470ff },
   629 		{ "lightslategray",       0x778899 },
   630 		{ "lightslategrey",       0x778899 },
   631 		{ "lightsteelblue",       0xb0c4de },
   632 		{ "lightsteelblue1",      0xcae1ff },
   633 		{ "lightsteelblue2",      0xbcd2ee },
   634 		{ "lightsteelblue3",      0xa2b5cd },
   635 		{ "lightsteelblue4",      0x6e7b8b },
   636 		{ "lightyellow",          0xffffe0 },
   637 		{ "lightyellow1",         0xffffe0 },
   638 		{ "lightyellow2",         0xeeeed1 },
   639 		{ "lightyellow3",         0xcdcdb4 },
   640 		{ "lightyellow4",         0x8b8b7a },
   641 		{ "lime",                 0x00FF00 },
   642 		{ "limegreen",            0x32cd32 },
   643 		{ "linen",                0xFAF0E6 },
   644 		{ "magenta",              0xFF00FF },
   645 		{ "magenta1",             0xFF00FF },
   646 		{ "magenta2",             0xEE00EE },
   647 		{ "magenta3",             0xCD00CD },
   648 		{ "magenta4",             0x8B008B },
   649 		{ "maroon",               0x800000 },
   650 		{ "maroon",               0xB03060 },
   651 		{ "maroon1",              0xFF34B3 },
   652 		{ "maroon2",              0xEE30A7 },
   653 		{ "maroon3",              0xCD2990 },
   654 		{ "maroon4",              0x8B1C62 },
   655 		{ "mediumaquamarine",     0x66cdaa },
   656 		{ "mediumblue",           0x0000cd },
   657 		{ "mediumforestgreen",    0x32814b },
   658 		{ "mediumgoldenrod",      0xd1c166 },
   659 		{ "mediumorchid",         0xba55d3 },
   660 		{ "mediumorchid1",        0xe066ff },
   661 		{ "mediumorchid2",        0xd15fee },
   662 		{ "mediumorchid3",        0xb452cd },
   663 		{ "mediumorchid4",        0x7a378b },
   664 		{ "mediumpurple",         0x9370db },
   665 		{ "mediumpurple1",        0xab82ff },
   666 		{ "mediumpurple2",        0x9f79ee },
   667 		{ "mediumpurple3",        0x8968cd },
   668 		{ "mediumpurple4",        0x5d478b },
   669 		{ "mediumseagreen",       0x3cb371 },
   670 		{ "mediumslateblue",      0x7b68ee },
   671 		{ "mediumspringgreen",    0x00fa9a },
   672 		{ "mediumturquoise",      0x48d1cc },
   673 		{ "mediumvioletred",      0xc71585 },
   674 		{ "midnightblue",         0x191970 },
   675 		{ "mintcream",            0xf5fffa },
   676 		{ "mistyrose",            0xffe4e1 },
   677 		{ "mistyrose1",           0xffe4e1 },
   678 		{ "mistyrose2",           0xeed5d2 },
   679 		{ "mistyrose3",           0xcdb7b5 },
   680 		{ "mistyrose4",           0x8b7d7b },
   681 		{ "moccasin",             0xFFE4B5 },
   682 		{ "navajowhite",          0xffdead },
   683 		{ "navajowhite1",         0xffdead },
   684 		{ "navajowhite2",         0xeecfa1 },
   685 		{ "navajowhite3",         0xcdb38b },
   686 		{ "navajowhite4",         0x8b795e },
   687 		{ "navy",                 0x000080 },
   688 		{ "navyblue",             0x000080 },
   689 		{ "none",                 0x0000FF },
   690 		{ "oldlace",              0xfdf5e6 },
   691 		{ "olive",                0x808000 },
   692 		{ "olivedrab",            0x6b8e23 },
   693 		{ "olivedrab1",           0xc0ff3e },
   694 		{ "olivedrab2",           0xb3ee3a },
   695 		{ "olivedrab3",           0x9acd32 },
   696 		{ "olivedrab4",           0x698b22 },
   697 		{ "opaque",               0x000000 },
   698 		{ "orange",               0xFFA500 },
   699 		{ "orange1",              0xFFA500 },
   700 		{ "orange2",              0xEE9A00 },
   701 		{ "orange3",              0xCD8500 },
   702 		{ "orange4",              0x8B5A00 },
   703 		{ "orangered",            0xff4500 },
   704 		{ "orangered1",           0xff4500 },
   705 		{ "orangered2",           0xee4000 },
   706 		{ "orangered3",           0xcd3700 },
   707 		{ "orangered4",           0x8b2500 },
   708 		{ "orchid",               0xDA70D6 },
   709 		{ "orchid1",              0xFF83FA },
   710 		{ "orchid2",              0xEE7AE9 },
   711 		{ "orchid3",              0xCD69C9 },
   712 		{ "orchid4",              0x8B4789 },
   713 		{ "palegoldenrod",        0xeee8aa },
   714 		{ "palegreen",            0x98fb98 },
   715 		{ "palegreen1",           0x9aff9a },
   716 		{ "palegreen2",           0x90ee90 },
   717 		{ "palegreen3",           0x7ccd7c },
   718 		{ "palegreen4",           0x548b54 },
   719 		{ "paleturquoise",        0xafeeee },
   720 		{ "paleturquoise1",       0xbbffff },
   721 		{ "paleturquoise2",       0xaeeeee },
   722 		{ "paleturquoise3",       0x96cdcd },
   723 		{ "paleturquoise4",       0x668b8b },
   724 		{ "palevioletred",        0xdb7093 },
   725 		{ "palevioletred1",       0xff82ab },
   726 		{ "palevioletred2",       0xee799f },
   727 		{ "palevioletred3",       0xcd6889 },
   728 		{ "palevioletred4",       0x8b475d },
   729 		{ "papayawhip",           0xffefd5 },
   730 		{ "peachpuff",            0xffdab9 },
   731 		{ "peachpuff1",           0xffdab9 },
   732 		{ "peachpuff2",           0xeecbad },
   733 		{ "peachpuff3",           0xcdaf95 },
   734 		{ "peachpuff4",           0x8b7765 },
   735 		{ "peru",                 0xCD853F },
   736 		{ "pink",                 0xFFC0CB },
   737 		{ "pink1",                0xFFB5C5 },
   738 		{ "pink2",                0xEEA9B8 },
   739 		{ "pink3",                0xCD919E },
   740 		{ "pink4",                0x8B636C },
   741 		{ "plum",                 0xDDA0DD },
   742 		{ "plum1",                0xFFBBFF },
   743 		{ "plum2",                0xEEAEEE },
   744 		{ "plum3",                0xCD96CD },
   745 		{ "plum4",                0x8B668B },
   746 		{ "powderblue",           0xb0e0e6 },
   747 		{ "purple",               0x800080 },
   748 		{ "purple",               0xA020F0 },
   749 		{ "purple1",              0x9B30FF },
   750 		{ "purple2",              0x912CEE },
   751 		{ "purple3",              0x7D26CD },
   752 		{ "purple4",              0x551A8B },
   753 		{ "red",                  0xFF0000 },
   754 		{ "red1",                 0xFF0000 },
   755 		{ "red2",                 0xEE0000 },
   756 		{ "red3",                 0xCD0000 },
   757 		{ "red4",                 0x8B0000 },
   758 		{ "rosybrown",            0xbc8f8f },
   759 		{ "rosybrown1",           0xffc1c1 },
   760 		{ "rosybrown2",           0xeeb4b4 },
   761 		{ "rosybrown3",           0xcd9b9b },
   762 		{ "rosybrown4",           0x8b6969 },
   763 		{ "royalblue",            0x4169e1 },
   764 		{ "royalblue1",           0x4876ff },
   765 		{ "royalblue2",           0x436eee },
   766 		{ "royalblue3",           0x3a5fcd },
   767 		{ "royalblue4",           0x27408b },
   768 		{ "saddlebrown",          0x8b4513 },
   769 		{ "salmon",               0xFA8072 },
   770 		{ "salmon1",              0xFF8C69 },
   771 		{ "salmon2",              0xEE8262 },
   772 		{ "salmon3",              0xCD7054 },
   773 		{ "salmon4",              0x8B4C39 },
   774 		{ "sandybrown",           0xf4a460 },
   775 		{ "seagreen",             0x2e8b57 },
   776 		{ "seagreen1",            0x54ff9f },
   777 		{ "seagreen2",            0x4eee94 },
   778 		{ "seagreen3",            0x43cd80 },
   779 		{ "seagreen4",            0x2e8b57 },
   780 		{ "seashell",             0xFFF5EE },
   781 		{ "seashell1",            0xFFF5EE },
   782 		{ "seashell2",            0xEEE5DE },
   783 		{ "seashell3",            0xCDC5BF },
   784 		{ "seashell4",            0x8B8682 },
   785 		{ "sienna",               0xA0522D },
   786 		{ "sienna1",              0xFF8247 },
   787 		{ "sienna2",              0xEE7942 },
   788 		{ "sienna3",              0xCD6839 },
   789 		{ "sienna4",              0x8B4726 },
   790 		{ "silver",               0xC0C0C0 },
   791 		{ "skyblue",              0x87ceeb },
   792 		{ "skyblue1",             0x87ceff },
   793 		{ "skyblue2",             0x7ec0ee },
   794 		{ "skyblue3",             0x6ca6cd },
   795 		{ "skyblue4",             0x4a708b },
   796 		{ "slateblue",            0x6a5acd },
   797 		{ "slateblue1",           0x836fff },
   798 		{ "slateblue2",           0x7a67ee },
   799 		{ "slateblue3",           0x6959cd },
   800 		{ "slateblue4",           0x473c8b },
   801 		{ "slategray",            0x708090 },
   802 		{ "slategray1",           0xc6e2ff },
   803 		{ "slategray2",           0xb9d3ee },
   804 		{ "slategray3",           0x9fb6cd },
   805 		{ "slategray4",           0x6c7b8b },
   806 		{ "slategrey",            0x708090 },
   807 		{ "snow",                 0xFFFAFA },
   808 		{ "snow1",                0xFFFAFA },
   809 		{ "snow2",                0xEEE9E9 },
   810 		{ "snow3",                0xCDC9C9 },
   811 		{ "snow4",                0x8B8989 },
   812 		{ "springgreen",          0x00ff7f },
   813 		{ "springgreen1",         0x00ff7f },
   814 		{ "springgreen2",         0x00ee76 },
   815 		{ "springgreen3",         0x00cd66 },
   816 		{ "springgreen4",         0x008b45 },
   817 		{ "steelblue",            0x4682b4 },
   818 		{ "steelblue1",           0x63b8ff },
   819 		{ "steelblue2",           0x5cacee },
   820 		{ "steelblue3",           0x4f94cd },
   821 		{ "steelblue4",           0x36648b },
   822 		{ "tan",                  0xD2B48C },
   823 		{ "tan1",                 0xFFA54F },
   824 		{ "tan2",                 0xEE9A49 },
   825 		{ "tan3",                 0xCD853F },
   826 		{ "tan4",                 0x8B5A2B },
   827 		{ "teal",                 0x008080 },
   828 		{ "thistle",              0xD8BFD8 },
   829 		{ "thistle1",             0xFFE1FF },
   830 		{ "thistle2",             0xEED2EE },
   831 		{ "thistle3",             0xCDB5CD },
   832 		{ "thistle4",             0x8B7B8B },
   833 		{ "tomato",               0xFF6347 },
   834 		{ "tomato1",              0xFF6347 },
   835 		{ "tomato2",              0xEE5C42 },
   836 		{ "tomato3",              0xCD4F39 },
   837 		{ "tomato4",              0x8B3626 },
   838 		{ "transparent",          0x0000FF },
   839 		{ "turquoise",            0x40E0D0 },
   840 		{ "turquoise1",           0x00F5FF },
   841 		{ "turquoise2",           0x00E5EE },
   842 		{ "turquoise3",           0x00C5CD },
   843 		{ "turquoise4",           0x00868B },
   844 		{ "violet",               0xEE82EE },
   845 		{ "violetred",            0xd02090 },
   846 		{ "violetred1",           0xff3e96 },
   847 		{ "violetred2",           0xee3a8c },
   848 		{ "violetred3",           0xcd3278 },
   849 		{ "violetred4",           0x8b2252 },
   850 		{ "wheat",                0xF5DEB3 },
   851 		{ "wheat1",               0xFFE7BA },
   852 		{ "wheat2",               0xEED8AE },
   853 		{ "wheat3",               0xCDBA96 },
   854 		{ "wheat4",               0x8B7E66 },
   855 		{ "white",                0xFFFFFF },
   856 		{ "whitesmoke",           0xf5f5f5 },
   857 		{ "yellow",               0xFFFF00 },
   858 		{ "yellow1",              0xFFFF00 },
   859 		{ "yellow2",              0xEEEE00 },
   860 		{ "yellow3",              0xCDCD00 },
   861 		{ "yellow4",              0x8B8B00 },
   862 		{ "yellowgreen",          0x9acd32 },
   863 #endif /* EXTENDED_XPM_COLORS */
   864 		{"none",                  0xFFFFFF}
   865 	};
   866 
   867 	if(spec[0] == '#') {
   868 		char buf[7];
   869 		switch(speclen) {
   870 		case 4:
   871 			buf[0] = buf[1] = spec[1];
   872 			buf[2] = buf[3] = spec[2];
   873 			buf[4] = buf[5] = spec[3];
   874 			break;
   875 		case 7:
   876 			SDL_memcpy(buf, spec + 1, 6);
   877 			break;
   878 		case 13:
   879 			buf[0] = spec[1];
   880 			buf[1] = spec[2];
   881 			buf[2] = spec[5];
   882 			buf[3] = spec[6];
   883 			buf[4] = spec[9];
   884 			buf[5] = spec[10];
   885 			break;
   886 		}
   887 		buf[6] = '\0';
   888 		*rgb = strtol(buf, NULL, 16);
   889 		return 1;
   890 	} else {
   891 		int i;
   892 		for(i = 0; i < SDL_arraysize(known); i++)
   893 			if(SDL_strncmp(known[i].name, spec, speclen) == 0) {
   894 				*rgb = known[i].rgb;
   895 				return 1;
   896 			}
   897 		return 0;
   898 	}
   899 }
   900 
   901 #ifndef MAX
   902 #define MAX(a, b) ((a) > (b) ? (a) : (b))
   903 #endif
   904 
   905 static char *linebuf;
   906 static int buflen;
   907 static char *error;
   908 
   909 /*
   910  * Read next line from the source.
   911  * If len > 0, it's assumed to be at least len chars (for efficiency).
   912  * Return NULL and set error upon EOF or parse error.
   913  */
   914 static char *get_next_line(char ***lines, SDL_RWops *src, int len)
   915 {
   916 	char *linebufnew;
   917 
   918 	if(lines) {
   919 		return *(*lines)++;
   920 	} else {
   921 		char c;
   922 		int n;
   923 		do {
   924 			if(SDL_RWread(src, &c, 1, 1) <= 0) {
   925 				error = "Premature end of data";
   926 				return NULL;
   927 			}
   928 		} while(c != '"');
   929 		if(len) {
   930 			len += 4;	/* "\",\n\0" */
   931 			if(len > buflen){
   932 				buflen = len;
   933 				linebufnew = (char *)SDL_realloc(linebuf, buflen);
   934 				if(!linebufnew) {
   935 					SDL_free(linebuf);
   936 					error = "Out of memory";
   937 					return NULL;
   938 				}
   939 				linebuf = linebufnew;
   940 			}
   941 			if(SDL_RWread(src, linebuf, len - 1, 1) <= 0) {
   942 				error = "Premature end of data";
   943 				return NULL;
   944 			}
   945 			n = len - 2;
   946 		} else {
   947 			n = 0;
   948 			do {
   949 				if(n >= buflen - 1) {
   950 					if(buflen == 0)
   951 						buflen = 16;
   952 					buflen *= 2;
   953 					linebufnew = (char *)SDL_realloc(linebuf, buflen);
   954 					if(!linebufnew) {
   955 						SDL_free(linebuf);
   956 						error = "Out of memory";
   957 						return NULL;
   958 					}
   959 					linebuf = linebufnew;
   960 				}
   961 				if(SDL_RWread(src, linebuf + n, 1, 1) <= 0) {
   962 					error = "Premature end of data";
   963 					return NULL;
   964 				}
   965 			} while(linebuf[n++] != '"');
   966 			n--;
   967 		}
   968 		linebuf[n] = '\0';
   969 		return linebuf;
   970 	}
   971 }
   972 
   973 #define SKIPSPACE(p)				\
   974 do {						\
   975 	while(SDL_isspace((unsigned char)*(p)))	\
   976 	      ++(p);				\
   977 } while(0)
   978 
   979 #define SKIPNONSPACE(p)					\
   980 do {							\
   981 	while(!SDL_isspace((unsigned char)*(p)) && *p)	\
   982 	      ++(p);					\
   983 } while(0)
   984 
   985 /* read XPM from either array or RWops */
   986 static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src)
   987 {
   988 	Sint64 start = 0;
   989 	SDL_Surface *image = NULL;
   990 	int index;
   991 	int x, y;
   992 	int w, h, ncolors, cpp;
   993 	int indexed;
   994 	Uint8 *dst;
   995 	struct color_hash *colors = NULL;
   996 	SDL_Color *im_colors = NULL;
   997 	char *keystrings = NULL, *nextkey;
   998 	char *line;
   999 	char ***xpmlines = NULL;
  1000 	int pixels_len;
  1001 
  1002 	error = NULL;
  1003 	linebuf = NULL;
  1004 	buflen = 0;
  1005 
  1006 	if ( src ) 
  1007 		start = SDL_RWtell(src);
  1008 
  1009 	if(xpm)
  1010 		xpmlines = &xpm;
  1011 
  1012 	line = get_next_line(xpmlines, src, 0);
  1013 	if(!line)
  1014 		goto done;
  1015 	/*
  1016 	 * The header string of an XPMv3 image has the format
  1017 	 *
  1018 	 * <width> <height> <ncolors> <cpp> [ <hotspot_x> <hotspot_y> ]
  1019 	 *
  1020 	 * where the hotspot coords are intended for mouse cursors.
  1021 	 * Right now we don't use the hotspots but it should be handled
  1022 	 * one day.
  1023 	 */
  1024 	if(SDL_sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4
  1025 	   || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) {
  1026 		error = "Invalid format description";
  1027 		goto done;
  1028 	}
  1029 
  1030 	keystrings = (char *)SDL_malloc(ncolors * cpp);
  1031 	if(!keystrings) {
  1032 		error = "Out of memory";
  1033 		goto done;
  1034 	}
  1035 	nextkey = keystrings;
  1036 
  1037 	/* Create the new surface */
  1038 	if(ncolors <= 256) {
  1039 		indexed = 1;
  1040 		image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8,
  1041 					     0, 0, 0, 0);
  1042 		im_colors = image->format->palette->colors;
  1043 		image->format->palette->ncolors = ncolors;
  1044 	} else {
  1045 		indexed = 0;
  1046 		image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
  1047 					     0xff0000, 0x00ff00, 0x0000ff, 0);
  1048 	}
  1049 	if(!image) {
  1050 		/* Hmm, some SDL error (out of memory?) */
  1051 		goto done;
  1052 	}
  1053 
  1054 	/* Read the colors */
  1055 	colors = create_colorhash(ncolors);
  1056 	if (!colors) {
  1057 		error = "Out of memory";
  1058 		goto done;
  1059 	}
  1060 	for(index = 0; index < ncolors; ++index ) {
  1061 		char *p;
  1062 		line = get_next_line(xpmlines, src, 0);
  1063 		if(!line)
  1064 			goto done;
  1065 
  1066 		p = line + cpp + 1;
  1067 
  1068 		/* parse a colour definition */
  1069 		for(;;) {
  1070 			char nametype;
  1071 			char *colname;
  1072 			Uint32 rgb, pixel;
  1073 
  1074 			SKIPSPACE(p);
  1075 			if(!*p) {
  1076 				error = "colour parse error";
  1077 				goto done;
  1078 			}
  1079 			nametype = *p;
  1080 			SKIPNONSPACE(p);
  1081 			SKIPSPACE(p);
  1082 			colname = p;
  1083 			SKIPNONSPACE(p);
  1084 			if(nametype == 's')
  1085 				continue;      /* skip symbolic colour names */
  1086 
  1087 			if(!color_to_rgb(colname, p - colname, &rgb))
  1088 				continue;
  1089 
  1090 			SDL_memcpy(nextkey, line, cpp);
  1091 			if(indexed) {
  1092 				SDL_Color *c = im_colors + index;
  1093 				c->r = (Uint8)(rgb >> 16);
  1094 				c->g = (Uint8)(rgb >> 8);
  1095 				c->b = (Uint8)(rgb);
  1096 				pixel = index;
  1097 			} else
  1098 				pixel = rgb;
  1099 			add_colorhash(colors, nextkey, cpp, pixel);
  1100 			nextkey += cpp;
  1101 			if(rgb == 0xffffffff)
  1102 				SDL_SetColorKey(image, SDL_TRUE, pixel);
  1103 			break;
  1104 		}
  1105 	}
  1106 
  1107 	/* Read the pixels */
  1108 	pixels_len = w * cpp;
  1109 	dst = (Uint8 *)image->pixels;
  1110 	for(y = 0; y < h; y++) {
  1111 		line = get_next_line(xpmlines, src, pixels_len);
  1112 		if(indexed) {
  1113 			/* optimization for some common cases */
  1114 			if(cpp == 1)
  1115 				for(x = 0; x < w; x++)
  1116 					dst[x] = (Uint8)QUICK_COLORHASH(colors,
  1117 								 line + x);
  1118 			else
  1119 				for(x = 0; x < w; x++)
  1120 					dst[x] = (Uint8)get_colorhash(colors,
  1121 							       line + x * cpp,
  1122 							       cpp);
  1123 		} else {
  1124 			for (x = 0; x < w; x++)
  1125 				((Uint32*)dst)[x] = get_colorhash(colors,
  1126 								line + x * cpp,
  1127 								  cpp);
  1128 		}
  1129 		dst += image->pitch;
  1130 	}
  1131 
  1132 done:
  1133 	if(error) {
  1134 		if ( src )
  1135 			SDL_RWseek(src, start, RW_SEEK_SET);
  1136 		if ( image ) {
  1137 			SDL_FreeSurface(image);
  1138 			image = NULL;
  1139 		}
  1140 		IMG_SetError(error);
  1141 	}
  1142 	if (keystrings)
  1143 		SDL_free(keystrings);
  1144 	free_colorhash(colors);
  1145 	if (linebuf)
  1146 		SDL_free(linebuf);
  1147 	return(image);
  1148 }
  1149 
  1150 /* Load a XPM type image from an RWops datasource */
  1151 SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src)
  1152 {
  1153 	if ( !src ) {
  1154 		/* The error message has been set in SDL_RWFromFile */
  1155 		return NULL;
  1156 	}
  1157 	return load_xpm(NULL, src);
  1158 }
  1159 
  1160 SDL_Surface *IMG_ReadXPMFromArray(char **xpm)
  1161 {
  1162 	return load_xpm(xpm, NULL);
  1163 }
  1164 
  1165 #else  /* not LOAD_XPM */
  1166 
  1167 /* See if an image is contained in a data source */
  1168 int IMG_isXPM(SDL_RWops *src)
  1169 {
  1170 	return(0);
  1171 }
  1172 
  1173 
  1174 /* Load a XPM type image from an SDL datasource */
  1175 SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src)
  1176 {
  1177 	return(NULL);
  1178 }
  1179 
  1180 SDL_Surface *IMG_ReadXPMFromArray(char **xpm)
  1181 {
  1182     return NULL;
  1183 }
  1184 #endif /* not LOAD_XPM */