Ignore:
Timestamp:
Apr 16, 2001, 7:11:03 PM (25 years ago)
Author:
sandervl
Message:

updates

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/wrc/newstruc.c

    r3426 r5522  
    1313#include <string.h>
    1414#include <assert.h>
     15#include <ctype.h>
    1516
    1617#include "wrc.h"
     
    1819#include "utils.h"
    1920#include "parser.h"
     21
     22#include "wingdi.h"     /* for BITMAPINFOHEADER */
    2023
    2124/* Generate new_* functions that have no parameters (NOTE: no ';') */
     
    4144__NEW_STRUCT_FUNC(string)
    4245__NEW_STRUCT_FUNC(toolbar_item)
     46__NEW_STRUCT_FUNC(ani_any)
    4347
    4448/* New instances for all types of structures */
     
    145149        }
    146150        else
    147                 fnt->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
     151                fnt->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE;
    148152        return fnt;
    149153}
     154
     155fontdir_t *new_fontdir(raw_data_t *rd, int *memopt)
     156{
     157        fontdir_t *fnd = (fontdir_t *)xmalloc(sizeof(fontdir_t));
     158        fnd->data = rd;
     159        if(memopt)
     160        {
     161                fnd->memopt = *memopt;
     162                free(memopt);
     163        }
     164        else
     165                fnd->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE;
     166        return fnd;
     167}
     168
     169
     170/*
     171 * Convert bitmaps to proper endian
     172 */
     173static void convert_bitmap_swap_v3(BITMAPINFOHEADER *bih)
     174{
     175        bih->biSize             = BYTESWAP_DWORD(bih->biSize);
     176        bih->biWidth            = BYTESWAP_DWORD(bih->biWidth);
     177        bih->biHeight           = BYTESWAP_DWORD(bih->biHeight);
     178        bih->biPlanes           = BYTESWAP_WORD(bih->biPlanes);
     179        bih->biBitCount         = BYTESWAP_WORD(bih->biBitCount);
     180        bih->biCompression      = BYTESWAP_DWORD(bih->biCompression);
     181        bih->biSizeImage        = BYTESWAP_DWORD(bih->biSizeImage);
     182        bih->biXPelsPerMeter    = BYTESWAP_DWORD(bih->biXPelsPerMeter);
     183        bih->biYPelsPerMeter    = BYTESWAP_DWORD(bih->biYPelsPerMeter);
     184        bih->biClrUsed          = BYTESWAP_DWORD(bih->biClrUsed);
     185        bih->biClrImportant     = BYTESWAP_DWORD(bih->biClrImportant);
     186}
     187
     188static void convert_bitmap_swap_v4(BITMAPV4HEADER *b4h)
     189{
     190        convert_bitmap_swap_v3((BITMAPINFOHEADER *)b4h);
     191        b4h->bV4RedMask         = BYTESWAP_DWORD(b4h->bV4RedMask);
     192        b4h->bV4GreenMask       = BYTESWAP_DWORD(b4h->bV4GreenMask);
     193        b4h->bV4BlueMask        = BYTESWAP_DWORD(b4h->bV4BlueMask);
     194        b4h->bV4AlphaMask       = BYTESWAP_DWORD(b4h->bV4AlphaMask);
     195        b4h->bV4CSType          = BYTESWAP_DWORD(b4h->bV4CSType);
     196        b4h->bV4Endpoints.ciexyzRed.ciexyzX     = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzRed.ciexyzX);
     197        b4h->bV4Endpoints.ciexyzRed.ciexyzY     = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzRed.ciexyzY);
     198        b4h->bV4Endpoints.ciexyzRed.ciexyzZ     = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzRed.ciexyzZ);
     199        b4h->bV4Endpoints.ciexyzGreen.ciexyzX   = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzGreen.ciexyzX);
     200        b4h->bV4Endpoints.ciexyzGreen.ciexyzY   = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzGreen.ciexyzY);
     201        b4h->bV4Endpoints.ciexyzGreen.ciexyzZ   = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzGreen.ciexyzZ);
     202        b4h->bV4Endpoints.ciexyzBlue.ciexyzX    = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzBlue.ciexyzX);
     203        b4h->bV4Endpoints.ciexyzBlue.ciexyzY    = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzBlue.ciexyzY);
     204        b4h->bV4Endpoints.ciexyzBlue.ciexyzZ    = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzBlue.ciexyzZ);
     205        b4h->bV4GammaRed        = BYTESWAP_DWORD(b4h->bV4GammaRed);
     206        b4h->bV4GammaGreen      = BYTESWAP_DWORD(b4h->bV4GammaGreen);
     207        b4h->bV4GammaBlue       = BYTESWAP_DWORD(b4h->bV4GammaBlue);
     208}
     209
     210#define FL_SIGBE        0x01
     211#define FL_SIZEBE       0x02
     212#define FL_V4           0x04
     213static int convert_bitmap(char *data, int size)
     214{
     215        BITMAPINFOHEADER *bih = (BITMAPINFOHEADER *)data;
     216        BITMAPV4HEADER *b4h = (BITMAPV4HEADER *)data;
     217        int type = 0;
     218#ifdef WORDS_BIGENDIAN
     219        DWORD bisizel = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER));
     220        DWORD b4sizel = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER));
     221        DWORD bisizeb = sizeof(BITMAPINFOHEADER);
     222        DWORD b4sizeb = sizeof(BITMAPV4HEADER);
     223#else
     224        DWORD bisizel = sizeof(BITMAPINFOHEADER);
     225        DWORD b4sizel = sizeof(BITMAPV4HEADER);
     226        DWORD bisizeb = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER));
     227        DWORD b4sizeb = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER));
     228#endif
     229
     230        if(data[0] == 'B' && data[1] == 'M')
     231        {
     232                /* Little endian signature */
     233                bih = (BITMAPINFOHEADER *)(data + sizeof(BITMAPFILEHEADER));
     234                b4h = (BITMAPV4HEADER *)(data + sizeof(BITMAPFILEHEADER));
     235        }
     236        else if(data[0] == 'M' && data[1] == 'B')
     237        {
     238                type |= FL_SIGBE;       /* Big endian signature */
     239                bih = (BITMAPINFOHEADER *)(data + sizeof(BITMAPFILEHEADER));
     240                b4h = (BITMAPV4HEADER *)(data + sizeof(BITMAPFILEHEADER));
     241        }
     242
     243        if(bih->biSize == bisizel)
     244        {
     245                /* Little endian */
     246        }
     247        else if(bih->biSize == b4sizel)
     248        {
     249                type |= FL_V4;
     250        }
     251        else if(bih->biSize == bisizeb)
     252        {
     253                type |= FL_SIZEBE;
     254        }
     255        else if(bih->biSize == b4sizeb)
     256        {
     257                type |= FL_SIZEBE | FL_V4;
     258        }
     259#ifdef __EMX__
     260        else if(bih->biSize == sizeof(BITMAPCOREHEADER))
     261        {
     262                /* Little endian */
     263        }
     264#endif
     265        else
     266                type = -1;
     267
     268        switch(type)
     269        {
     270        default:
     271                break;
     272        case FL_SIZEBE:
     273        case FL_SIZEBE | FL_V4:
     274                yywarning("Bitmap v%c signature little-endian, but size big-endian", type & FL_V4 ? '4' : '3');
     275                break;
     276        case FL_SIGBE:
     277        case FL_SIGBE | FL_V4:
     278                yywarning("Bitmap v%c signature big-endian, but size little-endian", type & FL_V4 ? '4' : '3');
     279                break;
     280        case -1:
     281                yyerror("Invalid bitmap format");
     282                break;
     283        }
     284
     285        switch(byteorder)
     286        {
     287#ifdef WORDS_BIGENDIAN
     288        default:
     289#endif
     290        case WRC_BO_BIG:
     291                if(!(type & FL_SIZEBE))
     292                {
     293                        if(type & FL_V4)
     294                                convert_bitmap_swap_v4(b4h);
     295                        else
     296                                convert_bitmap_swap_v3(bih);
     297                }
     298                break;
     299#ifndef WORDS_BIGENDIAN
     300        default:
     301#endif
     302        case WRC_BO_LITTLE:
     303                if(type & FL_SIZEBE)
     304                {
     305                        if(type & FL_V4)
     306                                convert_bitmap_swap_v4(b4h);
     307                        else
     308                                convert_bitmap_swap_v3(bih);
     309                }
     310                break;
     311        }
     312
     313        if(size && (void *)data != (void *)bih)
     314        {
     315                /* We have the fileheader still attached, remove it */
     316                memmove(data, data+sizeof(BITMAPFILEHEADER), size - sizeof(BITMAPFILEHEADER));
     317                return sizeof(BITMAPFILEHEADER);
     318        }
     319        return 0;
     320}
     321#undef FL_SIGBE
     322#undef FL_SIZEBE
     323#undef FL_V4
     324
     325/*
     326 * Cursor and icon splitter functions used when allocating
     327 * cursor- and icon-groups.
     328 */
     329typedef struct {
     330        language_t      lan;
     331        int             id;
     332} id_alloc_t;
     333
     334static int get_new_id(id_alloc_t **list, int *n, language_t *lan)
     335{
     336        int i;
     337        assert(lan != NULL);
     338        assert(list != NULL);
     339        assert(n != NULL);
     340
     341        if(!*list)
     342        {
     343                *list = (id_alloc_t *)xmalloc(sizeof(id_alloc_t));
     344                *n = 1;
     345                (*list)[0].lan = *lan;
     346                (*list)[0].id = 1;
     347                return 1;
     348        }
     349
     350        for(i = 0; i < *n; i++)
     351        {
     352                if((*list)[i].lan.id == lan->id && (*list)[i].lan.sub == lan->sub)
     353                        return ++((*list)[i].id);
     354        }
     355
     356        *list = (id_alloc_t *)xrealloc(*list, sizeof(id_alloc_t) * (*n+1));
     357        (*list)[*n].lan = *lan;
     358        (*list)[*n].id = 1;
     359        *n += 1;
     360        return 1;
     361}
     362
     363static int alloc_icon_id(language_t *lan)
     364{
     365        static id_alloc_t *idlist = NULL;
     366        static int nid = 0;
     367
     368        return get_new_id(&idlist, &nid, lan);
     369}
     370
     371static int alloc_cursor_id(language_t *lan)
     372{
     373        static id_alloc_t *idlist = NULL;
     374        static int nid = 0;
     375
     376        return get_new_id(&idlist, &nid, lan);
     377}
     378
     379static void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico)
     380{
     381        int cnt;
     382        int i;
     383        icon_t *ico;
     384        icon_t *list = NULL;
     385        icon_header_t *ih = (icon_header_t *)rd->data;
     386        int swap = 0;
     387
     388        if(ih->type == 1)
     389                swap = 0;
     390        else if(BYTESWAP_WORD(ih->type) == 1)
     391                swap = 1;
     392        else
     393                yyerror("Icon resource data has invalid type id %d", ih->type);
     394
     395        cnt = swap ? BYTESWAP_WORD(ih->count) : ih->count;
     396        for(i = 0; i < cnt; i++)
     397        {
     398                icon_dir_entry_t ide;
     399                BITMAPINFOHEADER info;
     400                memcpy(&ide, rd->data + sizeof(icon_header_t)
     401                                      + i*sizeof(icon_dir_entry_t), sizeof(ide));
     402
     403                ico = new_icon();
     404                ico->id = alloc_icon_id(icog->lvc.language);
     405                ico->lvc = icog->lvc;
     406                if(swap)
     407                {
     408                        ide.offset = BYTESWAP_DWORD(ide.offset);
     409                        ide.ressize= BYTESWAP_DWORD(ide.ressize);
     410                }
     411                if(ide.offset > rd->size
     412                || ide.offset + ide.ressize > rd->size)
     413                        yyerror("Icon resource data corrupt");
     414                ico->width = ide.width;
     415                ico->height = ide.height;
     416                ico->nclr = ide.nclr;
     417                ico->planes = swap ? BYTESWAP_WORD(ide.planes) : ide.planes;
     418                ico->bits = swap ? BYTESWAP_WORD(ide.bits) : ide.bits;
     419                convert_bitmap((char *)rd->data + ide.offset, 0);
     420                memcpy(&info, rd->data + ide.offset, sizeof(info));
     421                if(!ico->planes)
     422                {
     423                        /* Argh! They did not fill out the resdir structure */
     424                        /* The bitmap is in destination byteorder. We want native for our structures */
     425                        switch(byteorder)
     426                        {
     427#ifdef WORDS_BIGENDIAN
     428                        case WRC_BO_LITTLE:
     429#else
     430                        case WRC_BO_BIG:
     431#endif
     432                                ico->planes = BYTESWAP_WORD(info.biPlanes);
     433                                break;
     434                        default:
     435                                ico->planes = info.biPlanes;
     436                        }
     437                }
     438                if(!ico->bits)
     439                {
     440                        /* Argh! They did not fill out the resdir structure */
     441                        /* The bitmap is in destination byteorder. We want native for our structures */
     442                        switch(byteorder)
     443                        {
     444#ifdef WORDS_BIGENDIAN
     445                        case WRC_BO_LITTLE:
     446#else
     447                        case WRC_BO_BIG:
     448#endif
     449                                ico->bits = BYTESWAP_WORD(info.biBitCount);
     450                                break;
     451                        default:
     452                                ico->bits = info.biBitCount;
     453                        }
     454                }
     455                ico->data = new_raw_data();
     456                copy_raw_data(ico->data, rd, ide.offset, ide.ressize);
     457                if(!list)
     458                {
     459                        list = ico;
     460                }
     461                else
     462                {
     463                        ico->next = list;
     464                        list->prev = ico;
     465                        list = ico;
     466                }
     467        }
     468        icog->iconlist = list;
     469        *nico = cnt;
     470}
     471
     472static void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur)
     473{
     474        int cnt;
     475        int i;
     476        cursor_t *cur;
     477        cursor_t *list = NULL;
     478        cursor_header_t *ch = (cursor_header_t *)rd->data;
     479        int swap = 0;
     480
     481        if(ch->type == 2)
     482                swap = 0;
     483        else if(BYTESWAP_WORD(ch->type) == 2)
     484                swap = 1;
     485        else
     486                yyerror("Cursor resource data has invalid type id %d", ch->type);
     487        cnt = swap ? BYTESWAP_WORD(ch->count) : ch->count;
     488        for(i = 0; i < cnt; i++)
     489        {
     490                cursor_dir_entry_t cde;
     491                BITMAPINFOHEADER info;
     492                memcpy(&cde, rd->data + sizeof(cursor_header_t)
     493                                      + i*sizeof(cursor_dir_entry_t), sizeof(cde));
     494
     495                cur = new_cursor();
     496                cur->id = alloc_cursor_id(curg->lvc.language);
     497                cur->lvc = curg->lvc;
     498                if(swap)
     499                {
     500                        cde.offset = BYTESWAP_DWORD(cde.offset);
     501                        cde.ressize= BYTESWAP_DWORD(cde.ressize);
     502                }
     503                if(cde.offset > rd->size
     504                || cde.offset + cde.ressize > rd->size)
     505                        yyerror("Cursor resource data corrupt");
     506                cur->width = cde.width;
     507                cur->height = cde.height;
     508                cur->nclr = cde.nclr;
     509                convert_bitmap((char *)rd->data + cde.offset, 0);
     510                memcpy(&info, rd->data + cde.offset, sizeof(info));
     511                /* The bitmap is in destination byteorder. We want native for our structures */
     512                switch(byteorder)
     513                {
     514#ifdef WORDS_BIGENDIAN
     515                case WRC_BO_LITTLE:
     516#else
     517                case WRC_BO_BIG:
     518#endif
     519                        cur->planes = BYTESWAP_WORD(info.biPlanes);
     520                        cur->bits = BYTESWAP_WORD(info.biBitCount);
     521                        break;
     522                default:
     523                        cur->planes = info.biPlanes;
     524                        cur->bits = info.biBitCount;
     525                }
     526                if(!win32 && (cur->planes != 1 || cur->bits != 1))
     527                        yywarning("Win16 cursor contains colors");
     528                cur->xhot = swap ? BYTESWAP_WORD(cde.xhot) : cde.xhot;
     529                cur->yhot = swap ? BYTESWAP_WORD(cde.yhot) : cde.yhot;
     530                cur->data = new_raw_data();
     531                copy_raw_data(cur->data, rd, cde.offset, cde.ressize);
     532                if(!list)
     533                {
     534                        list = cur;
     535                }
     536                else
     537                {
     538                        cur->next = list;
     539                        list->prev = cur;
     540                        list = cur;
     541                }
     542        }
     543        curg->cursorlist = list;
     544        *ncur = cnt;
     545}
     546
    150547
    151548icon_group_t *new_icon_group(raw_data_t *rd, int *memopt)
     
    159556        else
    160557                icog->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
    161         icog->lvc.language = dup_language(currentlanguage);
     558        icog->lvc = rd->lvc;
    162559        split_icons(rd, icog, &(icog->nicon));
    163560        free(rd->data);
     
    176573        else
    177574                curg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
    178         curg->lvc.language = dup_language(currentlanguage);
     575        curg->lvc = rd->lvc;
    179576        split_cursors(rd, curg, &(curg->ncursor));
    180577        free(rd->data);
     
    183580}
    184581
     582/*
     583 * Animated cursors and icons
     584 *
     585 * The format of animated cursors and icons is yet another example
     586 * of bad design by "The Company". The entire RIFF structure is
     587 * flawed by design because it is inconsistent and single minded:
     588 * - some tags have lengths attached, others don't. The use of these
     589 *   non-length tags is absolutely unclear;
     590 * - the content of "icon" tags can be both icons and cursors;
     591 * - tags lack proper alignment constraints. It seems that everything
     592 *   is 16bit aligned, but I could not find that in any docu. Just be
     593 *   prepared to eat anything;
     594 * - there are no strict constraints on tag-nesting and the organization
     595 *   is highly illogical;
     596 *
     597 * Anyhow, here is the basic structure:
     598 * "RIFF" { dword taglength }
     599 *      "ACON"                                  // What does it do?
     600 *      "LIST" { dword taglength }
     601 *              "INFO"                          // And what does this do?
     602 *              "INAM" { dword taglength }      // Icon/cursor name
     603 *                      {inam data}
     604 *              "IART" { dword taglength }      // The artist
     605 *                      {iart data}
     606 *              "fram"                          // Is followed by "icon"s
     607 *              "icon" { dword taglength }      // First frame
     608 *                      { icon/cursor data }
     609 *              "icon" { dword taglength }      // Second frame
     610 *                      { icon/cursor data }
     611 *                      ...                     // ...
     612 *      "anih" { dword taglength }              // Header structure
     613 *              { aniheader_t structure }
     614 *      "rate" { dword taglength }              // The rate for each frame
     615 *              { `steps' dwords }
     616 *      "seq " { dword taglength }              // The frame blit-order
     617 *              { `steps' dwords }
     618 *
     619 * Tag length are bytelength without the header and length field (i.e. -8).
     620 * The "LIST" tag may occur several times and may encapsulate different
     621 * tags. The `steps' is the number of "icon" tags found (actually the
     622 * number of steps specified in the aniheader_t structure). The "seq "uence
     623 * tag can be ommitted, in which case the sequence is equal to the sequence
     624 * of "icon"s found in the file. Also "rate" may be ommitted, in which case
     625 * the default from the aniheader_t structure is used.
     626 *
     627 * An animated cursor puts `.cur' formatted files into each "icon" tag,
     628 * whereas animated icons contain `.ico' formatted files.
     629 *
     630 * Note about the code: Yes, it can be shorter/compressed. Some tags can be
     631 * dealt with in the same code. However, this version shows what is going on
     632 * and is better debug-able.
     633 */
     634static const char riff[4] = "RIFF";
     635static const char acon[4] = "ACON";
     636static const char list[4] = "LIST";
     637static const char info[4] = "INFO";
     638static const char inam[4] = "INAM";
     639static const char iart[4] = "IART";
     640static const char fram[4] = "fram";
     641static const char icon[4] = "icon";
     642static const char anih[4] = "anih";
     643static const char rate[4] = "rate";
     644static const char seq[4]  = "seq ";
     645
     646#define NEXT_TAG(p)     ((riff_tag_t *)(((char *)p) + (isswapped ? BYTESWAP_DWORD(p->size) : p->size) + sizeof(*p)))
     647
     648static void handle_ani_icon(riff_tag_t *rtp, enum res_e type, int isswapped)
     649{
     650        cursor_dir_entry_t *cdp;
     651        cursor_header_t *chp;
     652        int count;
     653        int ctype;
     654        int i;
     655        static int once = 0;    /* This will trigger only once per file! */
     656        const char *anistr = type == res_aniico ? "icon" : "cursor";
     657        /* Notes:
     658         * Both cursor and icon directories are similar
     659         * Both cursor and icon headers are similar
     660         */
     661
     662        chp = (cursor_header_t *)(rtp+1);
     663        cdp = (cursor_dir_entry_t *)(chp+1);
     664        count = isswapped ? BYTESWAP_WORD(chp->count) : chp->count;
     665        ctype = isswapped ? BYTESWAP_WORD(chp->type) : chp->type;
     666        chp->reserved   = BYTESWAP_WORD(chp->reserved);
     667        chp->type       = BYTESWAP_WORD(chp->type);
     668        chp->count      = BYTESWAP_WORD(chp->count);
     669
     670        if(type == res_anicur && ctype != 2 && !once)
     671        {
     672                yywarning("Animated cursor contains invalid \"icon\" tag cursor-file (%d->%s)",
     673                                ctype,
     674                                ctype == 1 ? "icontype" : "?");
     675                once++;
     676        }
     677        else if(type == res_aniico && ctype != 1 && !once)
     678        {
     679                yywarning("Animated icon contains invalid \"icon\" tag icon-file (%d->%s)",
     680                                ctype,
     681                                ctype == 2 ? "cursortype" : "?");
     682                once++;
     683        }
     684        else if(ctype != 1 && ctype != 2 && !once)
     685        {
     686                yywarning("Animated %s contains invalid \"icon\" tag file-type (%d; neither icon nor cursor)", anistr, ctype);
     687                once++;
     688        }
     689
     690        for(i = 0; i < count; i++)
     691        {
     692                DWORD ofs = isswapped ? BYTESWAP_DWORD(cdp[i].offset) : cdp[i].offset;
     693                DWORD sze = isswapped ? BYTESWAP_DWORD(cdp[i].ressize) : cdp[i].ressize;
     694                if(ofs > rtp->size || ofs+sze > rtp->size)
     695                        yyerror("Animated %s's data corrupt", anistr);
     696                convert_bitmap((char *)chp + ofs, 0);
     697                cdp[i].xhot     = BYTESWAP_WORD(cdp->xhot);
     698                cdp[i].yhot     = BYTESWAP_WORD(cdp->yhot);
     699                cdp[i].ressize  = BYTESWAP_DWORD(cdp->ressize);
     700                cdp[i].offset   = BYTESWAP_DWORD(cdp->offset);
     701        }
     702}
     703
     704static void handle_ani_list(riff_tag_t *lst, enum res_e type, int isswapped)
     705{
     706        riff_tag_t *rtp = lst+1;        /* Skip the "LIST" tag */
     707       
     708        while((char *)rtp < (char *)lst + lst->size + sizeof(*lst))
     709        {
     710                if(!memcmp(rtp->tag, info, sizeof(info)))
     711                {
     712                        rtp = (riff_tag_t *)(((char *)rtp) + 4);
     713                }
     714                else if(!memcmp(rtp->tag, inam, sizeof(inam)))
     715                {
     716                        /* Ignore the icon/cursor name; its a string */
     717                        rtp = NEXT_TAG(rtp);
     718                }
     719                else if(!memcmp(rtp->tag, iart, sizeof(iart)))
     720                {
     721                        /* Ignore the author's name; its a string */
     722                        rtp = NEXT_TAG(rtp);
     723                }
     724                else if(!memcmp(rtp->tag, fram, sizeof(fram)))
     725                {
     726                        /* This should be followed by "icon"s, but we
     727                         * simply ignore this because it is pure
     728                         * non-information.
     729                         */
     730                        rtp = (riff_tag_t *)(((char *)rtp) + 4);
     731                }
     732                else if(!memcmp(rtp->tag, icon, sizeof(icon)))
     733                {
     734                        handle_ani_icon(rtp, type, isswapped);
     735                        rtp = NEXT_TAG(rtp);
     736                }
     737                else
     738                        internal_error(__FILE__, __LINE__, "Unknown tag \"%c%c%c%c\" in RIFF file",
     739                                       isprint(rtp->tag[0]) ? rtp->tag[0] : '.',
     740                                       isprint(rtp->tag[1]) ? rtp->tag[1] : '.',
     741                                       isprint(rtp->tag[2]) ? rtp->tag[2] : '.',
     742                                       isprint(rtp->tag[3]) ? rtp->tag[3] : '.');
     743
     744                /* FIXME: This relies in sizeof(DWORD) == sizeof(pointer_type) */
     745                if((DWORD)rtp & 1)
     746                        ((char *)rtp)++;
     747        }
     748}
     749
     750ani_curico_t *new_ani_curico(enum res_e type, raw_data_t *rd, int *memopt)
     751{
     752        ani_curico_t *ani = (ani_curico_t *)xmalloc(sizeof(ani_curico_t));
     753        riff_tag_t *rtp;
     754        int isswapped = 0;
     755        int doswap;
     756        const char *anistr = type == res_aniico ? "icon" : "cursor";
     757
     758        assert(!memcmp(rd->data, riff, sizeof(riff)));
     759        assert(type == res_anicur || type == res_aniico);
     760
     761        rtp = (riff_tag_t *)rd->data;
     762
     763        if(BYTESWAP_DWORD(rtp->size) + 2*sizeof(DWORD) == rd->size)
     764                isswapped = 1;
     765        else if(rtp->size + 2*sizeof(DWORD) == rd->size)
     766                isswapped = 0;
     767        else
     768                yyerror("Animated %s has an invalid RIFF length", anistr);
     769
     770        switch(byteorder)
     771        {
     772#ifdef WORDS_BIGENDIAN
     773        case WRC_BO_LITTLE:
     774#else
     775        case WRC_BO_BIG:
     776#endif
     777                doswap = !isswapped;
     778                break;
     779        default:
     780                doswap = isswapped;
     781        }
     782
     783        /*
     784         * When to swap what:
     785         * isswapped | doswap |
     786         * ----------+--------+---------------------------------
     787         *     0     |    0   | read native; don't convert
     788         *     1     |    0   | read swapped size; don't convert
     789         *     0     |    1   | read native; convert
     790         *     1     |    1   | read swapped size; convert
     791         * Reading swapped size if necessary to calculate in native
     792         * format. E.g. a little-endian source on a big-endian
     793         * processor.
     794         */
     795        if(doswap)
     796        {
     797                /* We only go through the RIFF file if we need to swap
     798                 * bytes in words/dwords. Else we couldn't care less
     799                 * what the file contains. This is consistent with
     800                 * MS' rc.exe, which doesn't complain at all, eventhough
     801                 * the fileformat might not be entirely correct.
     802                 */
     803                rtp++;  /* Skip the "RIFF" tag */
     804
     805                while((char *)rtp < (char *)rd->data + rd->size)
     806                {
     807                        if(!memcmp(rtp->tag, acon, sizeof(acon)))
     808                        {
     809                                rtp = (riff_tag_t *)(((char *)rtp) + 4);
     810                        }
     811                        else if(!memcmp(rtp->tag, list, sizeof(list)))
     812                        {
     813                                handle_ani_list(rtp, type, isswapped);
     814                                rtp = NEXT_TAG(rtp);
     815                        }
     816                        else if(!memcmp(rtp->tag, anih, sizeof(anih)))
     817                        {
     818                                aniheader_t *ahp = (aniheader_t *)((char *)(rtp+1));
     819                                ahp->structsize = BYTESWAP_DWORD(ahp->structsize);
     820                                ahp->frames     = BYTESWAP_DWORD(ahp->frames);
     821                                ahp->steps      = BYTESWAP_DWORD(ahp->steps);
     822                                ahp->cx         = BYTESWAP_DWORD(ahp->cx);
     823                                ahp->cy         = BYTESWAP_DWORD(ahp->cy);
     824                                ahp->bitcount   = BYTESWAP_DWORD(ahp->bitcount);
     825                                ahp->planes     = BYTESWAP_DWORD(ahp->planes);
     826                                ahp->rate       = BYTESWAP_DWORD(ahp->rate);
     827                                ahp->flags      = BYTESWAP_DWORD(ahp->flags);
     828                                rtp = NEXT_TAG(rtp);
     829                        }
     830                        else if(!memcmp(rtp->tag, rate, sizeof(rate)))
     831                        {
     832                                int cnt = rtp->size / sizeof(DWORD);
     833                                DWORD *dwp = (DWORD *)(rtp+1);
     834                                int i;
     835                                for(i = 0; i < cnt; i++)
     836                                        dwp[i] = BYTESWAP_DWORD(dwp[i]);
     837                                rtp = NEXT_TAG(rtp);
     838                        }
     839                        else if(!memcmp(rtp->tag, seq, sizeof(seq)))
     840                        {
     841                                int cnt = rtp->size / sizeof(DWORD);
     842                                DWORD *dwp = (DWORD *)(rtp+1);
     843                                int i;
     844                                for(i = 0; i < cnt; i++)
     845                                        dwp[i] = BYTESWAP_DWORD(dwp[i]);
     846                                rtp = NEXT_TAG(rtp);
     847                        }
     848                        else
     849                                internal_error(__FILE__, __LINE__, "Unknown tag \"%c%c%c%c\" in RIFF file",
     850                                       isprint(rtp->tag[0]) ? rtp->tag[0] : '.',
     851                                       isprint(rtp->tag[1]) ? rtp->tag[1] : '.',
     852                                       isprint(rtp->tag[2]) ? rtp->tag[2] : '.',
     853                                       isprint(rtp->tag[3]) ? rtp->tag[3] : '.');
     854
     855                        /* FIXME: This relies in sizeof(DWORD) == sizeof(pointer_type) */
     856                        if((DWORD)rtp & 1)
     857                                ((char *)rtp)++;
     858                }
     859
     860                /* We must end correctly here */
     861                if((char *)rtp != (char *)rd->data + rd->size)
     862                        yyerror("Animated %s contains invalid field size(s)", anistr);
     863        }
     864
     865        ani->data = rd;
     866        if(memopt)
     867        {
     868                ani->memopt = *memopt;
     869                free(memopt);
     870        }
     871        else
     872                ani->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE;
     873        return ani;
     874}
     875#undef NEXT_TAG
     876
     877/* Bitmaps */
    185878bitmap_t *new_bitmap(raw_data_t *rd, int *memopt)
    186879{
    187880        bitmap_t *bmp = (bitmap_t *)xmalloc(sizeof(bitmap_t));
     881
    188882        bmp->data = rd;
    189883        if(memopt)
     
    194888        else
    195889                bmp->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
     890        rd->size -= convert_bitmap(rd->data, rd->size);
    196891        return bmp;
    197892}
     
    214909}
    215910
    216 messagetable_t *new_messagetable(raw_data_t *rd)
     911#define MSGTAB_BAD_PTR(p, b, l, r)      (((l) - ((char *)(p) - (char *)(b))) > (r))
     912messagetable_t *new_messagetable(raw_data_t *rd, int *memopt)
    217913{
    218914        messagetable_t *msg = (messagetable_t *)xmalloc(sizeof(messagetable_t));
     915        msgtab_block_t *mbp;
     916        DWORD nblk;
     917        DWORD i;
     918        WORD lo;
     919        WORD hi;
     920
    219921        msg->data = rd;
     922        if(memopt)
     923        {
     924                msg->memopt = *memopt;
     925                free(memopt);
     926        }
     927        else
     928                msg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
     929
     930        if(rd->size < sizeof(DWORD))
     931                yyerror("Invalid messagetable, size too small");
     932
     933        nblk = *(DWORD *)rd->data;
     934        lo = WRC_LOWORD(nblk);
     935        hi = WRC_HIWORD(nblk);
     936
     937        /* FIXME:
     938         * This test will fail for all n*2^16 blocks in the messagetable.
     939         * However, no sane person would want to have so many blocks
     940         * and have a table of megabytes attached.
     941         * So, I will assume that we have less than 2^16 blocks in the table
     942         * and all will just work out fine. Otherwise, we would need to test
     943         * the ID, offset and length (and flag) fields to be very sure.
     944         */
     945        if(hi && lo)
     946                internal_error(__FILE__, __LINE__, "Messagetable contains more than 65535 blocks; cannot determine endian");
     947        if(!hi && !lo)
     948                yyerror("Invalid messagetable block count 0");
     949
     950        if(!hi && lo)  /* Messagetable byteorder == native byteorder */
     951        {
     952#ifdef WORDS_BIGENDIAN
     953                if(byteorder != WRC_BO_LITTLE) goto out;
     954#else
     955                if(byteorder != WRC_BO_BIG) goto out;
     956#endif
     957                /* Resource byteorder != native byteorder */
     958
     959                mbp = (msgtab_block_t *)&(((DWORD *)rd->data)[1]);
     960                if(MSGTAB_BAD_PTR(mbp, rd->data, rd->size, nblk * sizeof(*mbp)))
     961                        yyerror("Messagetable's blocks are outside of defined data");
     962                for(i = 0; i < nblk; i++)
     963                {
     964                        msgtab_entry_t *mep, *next_mep;
     965                        DWORD id;
     966
     967                        mep = (msgtab_entry_t *)(((char *)rd->data) + mbp[i].offset);
     968
     969                        for(id = mbp[i].idlo; id <= mbp[i].idhi; id++)
     970                        {
     971                                if(MSGTAB_BAD_PTR(mep, rd->data, rd->size, mep->length))
     972                                        yyerror("Messagetable's data for block %d, ID 0x%08lx is outside of defined data", (int)i, id);
     973                                if(mep->flags == 1)     /* Docu says 'flags == 0x0001' for unicode */
     974                                {
     975                                        WORD *wp = (WORD *)&mep[1];
     976                                        int l = mep->length/2 - 2; /* Length included header */
     977                                        int n;
     978
     979                                        if(mep->length & 1)
     980                                                yyerror("Message 0x%08lx is unicode (block %d), but has odd length (%d)", id, (int)i, mep->length);
     981                                        for(n = 0; n < l; n++)
     982                                                wp[n] = BYTESWAP_WORD(wp[n]);
     983                                               
     984                                }
     985                                next_mep = (msgtab_entry_t *)(((char *)mep) + mep->length);
     986                                mep->length = BYTESWAP_WORD(mep->length);
     987                                mep->flags  = BYTESWAP_WORD(mep->flags);
     988                                mep = next_mep;
     989                        }
     990
     991                        mbp[i].idlo   = BYTESWAP_DWORD(mbp[i].idlo);
     992                        mbp[i].idhi   = BYTESWAP_DWORD(mbp[i].idhi);
     993                        mbp[i].offset = BYTESWAP_DWORD(mbp[i].offset);
     994                }
     995        }
     996        if(hi && !lo)  /* Messagetable byteorder != native byteorder */
     997        {
     998#ifdef WORDS_BIGENDIAN
     999                if(byteorder == WRC_BO_LITTLE) goto out;
     1000#else
     1001                if(byteorder == WRC_BO_BIG) goto out;
     1002#endif
     1003                /* Resource byteorder == native byteorder */
     1004
     1005                mbp = (msgtab_block_t *)&(((DWORD *)rd->data)[1]);
     1006                nblk = BYTESWAP_DWORD(nblk);
     1007                if(MSGTAB_BAD_PTR(mbp, rd->data, rd->size, nblk * sizeof(*mbp)))
     1008                        yyerror("Messagetable's blocks are outside of defined data");
     1009                for(i = 0; i < nblk; i++)
     1010                {
     1011                        msgtab_entry_t *mep;
     1012                        DWORD id;
     1013
     1014                        mbp[i].idlo   = BYTESWAP_DWORD(mbp[i].idlo);
     1015                        mbp[i].idhi   = BYTESWAP_DWORD(mbp[i].idhi);
     1016                        mbp[i].offset = BYTESWAP_DWORD(mbp[i].offset);
     1017                        mep = (msgtab_entry_t *)(((char *)rd->data) + mbp[i].offset);
     1018
     1019                        for(id = mbp[i].idlo; id <= mbp[i].idhi; id++)
     1020                        {
     1021                                mep->length = BYTESWAP_WORD(mep->length);
     1022                                mep->flags  = BYTESWAP_WORD(mep->flags);
     1023
     1024                                if(MSGTAB_BAD_PTR(mep, rd->data, rd->size, mep->length))
     1025                                        yyerror("Messagetable's data for block %d, ID 0x%08lx is outside of defined data", (int)i, id);
     1026                                if(mep->flags == 1)     /* Docu says 'flags == 0x0001' for unicode */
     1027                                {
     1028                                        WORD *wp = (WORD *)&mep[1];
     1029                                        int l = mep->length/2 - 2; /* Length included header */
     1030                                        int n;
     1031
     1032                                        if(mep->length & 1)
     1033                                                yyerror("Message 0x%08lx is unicode (block %d), but has odd length (%d)", id, (int)i, mep->length);
     1034                                        for(n = 0; n < l; n++)
     1035                                                wp[n] = BYTESWAP_WORD(wp[n]);
     1036                                               
     1037                                }
     1038                                mep = (msgtab_entry_t *)(((char *)mep) + mep->length);
     1039                        }
     1040                }
     1041        }
     1042
     1043 out:
    2201044        return msg;
    2211045}
    222 
    223 void copy_raw_data(raw_data_t *dst, raw_data_t *src, int offs, int len)
     1046#undef MSGTAB_BAD_PTR
     1047
     1048void copy_raw_data(raw_data_t *dst, raw_data_t *src, unsigned int offs, int len)
    2241049{
    2251050        assert(offs <= src->size);
     
    2941119        return st;
    2951120}
     1121
Note: See TracChangeset for help on using the changeset viewer.