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