diff --git a/tools/wrc/CHANGES b/tools/wrc/CHANGES index ec35e5cfc97..08e9f2469f3 100644 --- a/tools/wrc/CHANGES +++ b/tools/wrc/CHANGES @@ -1,3 +1,28 @@ +--------------------------------------------------------------------------- +Version 1.1.3 (21-May-2000) + +Bertho Stultiens +- Implemented animated cursors and icons resource types. +- Added partial support for font resources (user supplied fontdir is + required). +- All resources with inline data (a la RCDATA) now support language, + version and characteristics data. +- Implemented resource name duplicate checks. It is now an error if + two resources of the same type have the same name. +- Bugfix: Language propagation was not correct when .res files were + generated. +- Bugfix: VERSIONINFO now handles memory options. +- Bugfix: resource names and the resource type may be equal (e.g. MENU + MENU {...}). This support was mistakingly deleted in the upgrade to + the builtin preprocessor. + The standalone LANGUAGE setting became context sensitive as a consequence + of this. Now it *must* end with a newline *after* both expressions and + no newlines are allowed within the line (the statement must fit on one + line). This is no practical problem though. + +Patrik Stridvall +- Fixed byte order on Solaris and FreeBSD. + --------------------------------------------------------------------------- Version 1.1.2 (08-May-2000) diff --git a/tools/wrc/README.wrc b/tools/wrc/README.wrc index 3b2d7aa282c..b0002779103 100644 --- a/tools/wrc/README.wrc +++ b/tools/wrc/README.wrc @@ -1,4 +1,4 @@ -Release 1.1.2 of wrc (08-May-2000), the wine resource compiler. +Release 1.1.3 of wrc (21-May-2000), the wine resource compiler. See the file CHANGES for differences between the version and what has been corrected in the current version. @@ -144,25 +144,39 @@ Borland's implementation. Wrc uses 0,0 as the default language if non is specified. Both MS and Borland use the language of the system that the compiler runs on. -Not all resource-types can have local language keywords attached yet -(notably: BITMAP, CURSOR, ICON and usertype). This is due to implementation -of filename-scanning and the complexity that it poses. This will be changed -in the next release. You can work arround this problem by putting a LANGUAGE -statement before (and evt. after) the code in the resource file. +Language, version and characteristics can be bound to all resource types that +have inline data, such as RCDATA. This is an extension to MS' resource +compiler, which lacks this support completely. Only VERSIONINFO cannot have +version and characteristics attached, but languages are propagated properly if +you declare it correctly before the VERSIONINFO resource starts. + +Example: + +1 RCDATA DISCARDABLE +LANGUAGE 1, 0 +VERSION 312 +CHARACTERISTICS 876 +{ + 1, 2, 3, 4, 5, "and whatever more data you want" + '00 01 02 03 04 05 06 07 08' +} Resource types supported ------------------------ All types are supported except for: -- FONT (RT_FONT, RT_FONTDIR) - MESSAGETABLE (RT_MESSAGETABLE) -- Animated cursors/icons (RT_ANIICON, RT_ANICURSOR) - RT_VXD - RT_PLUGPLAY +- RT_HTML These types will be implemented as soon as I get a proper specification of the layout. +Font type resources (RT_FONT, RT_FONTDIR) are partially supported and will +be enhanced when I have the complete spec. The font resources work only if +you supply the FONTDIR resource yourself. + Expression capabilities and resource names ------------------------------------------ @@ -263,10 +277,12 @@ things that I noted in the above text (more lack of implementation than bug though): - No codepage translation - UNICODE translations are not/not correct implemented -- No documentation ('wrc -?' gives command-line options though) +- No documentation ('wrc -?' gives command-line options and a manpage) - grep for FIXME in the source - Memory options are wrong under some conditions. There seems to be a different action for win32 and win16 +- PUSHBOX control is unsupported. The MS docs use it plenty, but neither + MS' nor Borland's compiler supports it. Reporting bugs and patches -------------------------- diff --git a/tools/wrc/dumpres.c b/tools/wrc/dumpres.c index 32b93e73e66..5a2b2310cf1 100644 --- a/tools/wrc/dumpres.c +++ b/tools/wrc/dumpres.c @@ -46,6 +46,8 @@ char *get_typename(resource_t* r) case res_ver: return "VERSIONINFO"; case res_dlginit: return "DLGINIT"; case res_toolbar: return "TOOLBAR"; + case res_anicur: return "CURSOR (animated)"; + case res_aniico: return "ICON (animated)"; default: return "Unknown"; } } @@ -363,6 +365,24 @@ static void dump_icon_group(icon_group_t *icog) printf("There are %d icons in this group\n", icog->nicon); } +/* + ***************************************************************************** + * Function : dump_ani_curico + * Syntax : void dump_ani_curico(ani_curico_t *ani) + * Input : + * ani - Animated object resource descriptor + * Output : nop + * Description : + * Remarks : + ***************************************************************************** +*/ +static void dump_ani_curico(ani_curico_t *ani) +{ + dump_memopt(ani->memopt); + dump_lvc(&ani->data->lvc); + dump_raw_data(ani->data); +} + /* ***************************************************************************** * Function : dump_font @@ -377,6 +397,7 @@ static void dump_icon_group(icon_group_t *icog) static void dump_font(font_t *fnt) { dump_memopt(fnt->memopt); + dump_lvc(&(fnt->data->lvc)); dump_raw_data(fnt->data); } @@ -394,6 +415,7 @@ static void dump_font(font_t *fnt) static void dump_bitmap(bitmap_t *bmp) { dump_memopt(bmp->memopt); + dump_lvc(&(bmp->data->lvc)); dump_raw_data(bmp->data); } @@ -411,6 +433,7 @@ static void dump_bitmap(bitmap_t *bmp) static void dump_rcdata(rcdata_t *rdt) { dump_memopt(rdt->memopt); + dump_lvc(&(rdt->data->lvc)); dump_raw_data(rdt->data); } @@ -428,6 +451,7 @@ static void dump_rcdata(rcdata_t *rdt) static void dump_user(user_t *usr) { dump_memopt(usr->memopt); + dump_lvc(&(usr->data->lvc)); printf("Class %s\n", get_nameid_str(usr->type)); dump_raw_data(usr->data); } @@ -445,6 +469,7 @@ static void dump_user(user_t *usr) */ static void dump_messagetable(messagetable_t *msg) { + dump_lvc(&(msg->data->lvc)); dump_raw_data(msg->data); } @@ -821,6 +846,8 @@ static void dump_versioninfo(versioninfo_t *ver) { ver_block_t *blk = ver->blocks; + dump_lvc(&(ver->lvc)); + if(ver->gotit.fv) printf("FILEVERSION %04x, %04x, %04x, %04x\n", ver->filever_maj1, @@ -907,7 +934,7 @@ static void dump_toolbar(toolbar_t *toolbar) static void dump_dlginit(dlginit_t *dit) { dump_memopt(dit->memopt); - dump_lvc(&(dit->lvc)); + dump_lvc(&(dit->data->lvc)); dump_raw_data(dit->data); } @@ -997,6 +1024,10 @@ void dump_resources(resource_t *top) case res_toolbar: dump_toolbar(top->res.tbt); break; + case res_anicur: + case res_aniico: + dump_ani_curico(top->res.ani); + break; default: printf("Report this: Unknown resource type parsed %08x\n", top->type); } diff --git a/tools/wrc/dumpres.h b/tools/wrc/dumpres.h index 75e965016b3..3c17cc007eb 100644 --- a/tools/wrc/dumpres.h +++ b/tools/wrc/dumpres.h @@ -14,5 +14,6 @@ char *get_typename(resource_t* r); void dump_resources(resource_t *top); +char *get_nameid_str(name_id_t *n); #endif diff --git a/tools/wrc/genres.c b/tools/wrc/genres.c index 72c1eac7700..40d20f1d16e 100644 --- a/tools/wrc/genres.c +++ b/tools/wrc/genres.c @@ -1190,6 +1190,40 @@ static res_t *icon2res(icon_t *ico) return res; } +/* + ***************************************************************************** + * Function : anicurico2res + * Syntax : res_t *anicurico2res(name_id_t *name, ani_curico_t *ani) + * Input : + * name - Name/ordinal of the resource + * ani - The animated object descriptor + * Output : New .res format structure + * Description : + * Remarks : The endian of the object's structures have been converted + * by the loader. + * There are rumors that win311 could handle animated stuff. + * That is why they are generated for both win16 and win32 + * compile. + ***************************************************************************** +*/ +static res_t *anicurico2res(name_id_t *name, ani_curico_t *ani, enum res_e type) +{ + int restag; + res_t *res; + assert(name != NULL); + assert(ani != NULL); + + res = new_res(); + restag = put_res_header(res, type == res_anicur ? WRC_RT_ANICURSOR : WRC_RT_ANIICON, + NULL, name, ani->memopt, NULL); + put_raw_data(res, ani->data, 0); + /* Set ResourceSize */ + SetResSize(res, restag); + if(win32) + put_pad(res); + return res; +} + /* ***************************************************************************** * Function : bitmap2res @@ -1200,7 +1234,7 @@ static res_t *icon2res(icon_t *ico) * Output : New .res format structure * Description : * Remarks : The endian of the bitmap structures have been converted - * to native by the loader. + * by the loader. ***************************************************************************** */ static res_t *bitmap2res(name_id_t *name, bitmap_t *bmp) @@ -1211,7 +1245,7 @@ static res_t *bitmap2res(name_id_t *name, bitmap_t *bmp) assert(bmp != NULL); res = new_res(); - restag = put_res_header(res, WRC_RT_BITMAP, NULL, name, bmp->memopt, NULL); + restag = put_res_header(res, WRC_RT_BITMAP, NULL, name, bmp->memopt, &(bmp->data->lvc)); if(bmp->data->data[0] == 'B' && bmp->data->data[1] == 'M' && ((BITMAPFILEHEADER *)bmp->data->data)->bfSize == bmp->data->size @@ -1240,15 +1274,53 @@ static res_t *bitmap2res(name_id_t *name, bitmap_t *bmp) * fnt - The font descriptor * Output : New .res format structure * Description : - * Remarks : + * Remarks : The data has been prepared just after parsing. ***************************************************************************** */ static res_t *font2res(name_id_t *name, font_t *fnt) { + int restag; + res_t *res; assert(name != NULL); assert(fnt != NULL); - warning("Fonts not yet implemented"); - return NULL; + + res = new_res(); + restag = put_res_header(res, WRC_RT_FONT, NULL, name, fnt->memopt, &(fnt->data->lvc)); + put_raw_data(res, fnt->data, 0); + /* Set ResourceSize */ + SetResSize(res, restag); + if(win32) + put_pad(res); + return res; +} + +/* + ***************************************************************************** + * Function : fontdir2res + * Syntax : res_t *fontdir2res(name_id_t *name, fontdir_t *fnd) + * Input : + * name - Name/ordinal of the resource + * fntdir - The fontdir descriptor + * Output : New .res format structure + * Description : + * Remarks : The data has been prepared just after parsing. + ***************************************************************************** +*/ +static res_t *fontdir2res(name_id_t *name, fontdir_t *fnd) +{ + int restag; + res_t *res; + assert(name != NULL); + assert(fnd != NULL); + + res = new_res(); + restag = put_res_header(res, WRC_RT_FONTDIR, NULL, name, fnd->memopt, &(fnd->data->lvc)); + put_raw_data(res, fnd->data, 0); + /* Set ResourceSize */ + SetResSize(res, restag); + if(win32) + put_pad(res); + return res; } /* @@ -1271,7 +1343,7 @@ static res_t *rcdata2res(name_id_t *name, rcdata_t *rdt) assert(rdt != NULL); res = new_res(); - restag = put_res_header(res, WRC_RT_RCDATA, NULL, name, rdt->memopt, NULL); + restag = put_res_header(res, WRC_RT_RCDATA, NULL, name, rdt->memopt, &(rdt->data->lvc)); put_raw_data(res, rdt->data, 0); /* Set ResourceSize */ SetResSize(res, restag); @@ -1379,7 +1451,7 @@ static res_t *user2res(name_id_t *name, user_t *usr) assert(usr != NULL); res = new_res(); - restag = put_res_header(res, 0, usr->type, name, usr->memopt, NULL); + restag = put_res_header(res, 0, usr->type, name, usr->memopt, &(usr->data->lvc)); put_raw_data(res, usr->data, 0); /* Set ResourceSize */ SetResSize(res, restag); @@ -1504,7 +1576,7 @@ static res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver) vsvi.size = 15; /* Excl. termination */ res = new_res(); - restag = put_res_header(res, WRC_RT_VERSION, NULL, name, WRC_MO_MOVEABLE | WRC_MO_PURE, NULL); + restag = put_res_header(res, WRC_RT_VERSION, NULL, name, ver->memopt, &(ver->lvc)); rootblocksizetag = res->size; put_word(res, 0); /* BlockSize filled in later */ valsizetag = res->size; @@ -1629,7 +1701,7 @@ static res_t *dlginit2res(name_id_t *name, dlginit_t *dit) assert(dit != NULL); res = new_res(); - restag = put_res_header(res, WRC_RT_DLGINIT, NULL, name, dit->memopt, &(dit->lvc)); + restag = put_res_header(res, WRC_RT_DLGINIT, NULL, name, dit->memopt, &(dit->data->lvc)); put_raw_data(res, dit->data, 0); /* Set ResourceSize */ SetResSize(res, restag); @@ -1746,12 +1818,15 @@ char *get_c_typename(enum res_e type) switch(type) { case res_acc: return "Acc"; + case res_anicur:return "AniCur"; + case res_aniico:return "AniIco"; case res_bmp: return "Bmp"; case res_cur: return "Cur"; case res_curg: return "CurGrp"; case res_dlg: case res_dlgex: return "Dlg"; case res_fnt: return "Fnt"; + case res_fntdir:return "FntDir"; case res_ico: return "Ico"; case res_icog: return "IcoGrp"; case res_men: @@ -1812,6 +1887,10 @@ void resources2res(resource_t *top) if(!top->binres) top->binres = font2res(top->name, top->res.fnt); break; + case res_fntdir: + if(!top->binres) + top->binres = fontdir2res(top->name, top->res.fnd); + break; case res_ico: if(!top->binres) top->binres = icon2res(top->res.ico); @@ -1856,7 +1935,11 @@ void resources2res(resource_t *top) if(!top->binres) top->binres = dlginit2res(top->name, top->res.dlgi); break; - + case res_anicur: + case res_aniico: + if(!top->binres) + top->binres = anicurico2res(top->name, top->res.ani, top->type); + break; default: internal_error(__FILE__, __LINE__, "Unknown resource type encountered %d in binary res generation", top->type); } diff --git a/tools/wrc/newstruc.c b/tools/wrc/newstruc.c index e4e65934bbd..79f7010386b 100644 --- a/tools/wrc/newstruc.c +++ b/tools/wrc/newstruc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "wrc.h" #include "newstruc.h" @@ -42,6 +43,7 @@ __NEW_STRUCT_FUNC(lvc) __NEW_STRUCT_FUNC(res_count) __NEW_STRUCT_FUNC(string) __NEW_STRUCT_FUNC(toolbar_item) +__NEW_STRUCT_FUNC(ani_any) /* New instances for all types of structures */ /* Very inefficient (in size), but very functional :-] @@ -146,10 +148,24 @@ font_t *new_font(raw_data_t *rd, int *memopt) free(memopt); } else - fnt->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE; + fnt->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE; return fnt; } +fontdir_t *new_fontdir(raw_data_t *rd, int *memopt) +{ + fontdir_t *fnd = (fontdir_t *)xmalloc(sizeof(fontdir_t)); + fnd->data = rd; + if(memopt) + { + fnd->memopt = *memopt; + free(memopt); + } + else + fnd->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE; + return fnd; +} + /* * Convert bitmaps to proper endian @@ -364,7 +380,6 @@ static void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico) icon_header_t *ih = (icon_header_t *)rd->data; int swap = 0; - /* FIXME: Distinguish between normal and animated icons (RIFF format) */ if(ih->type == 1) swap = 0; else if(BYTESWAP_WORD(ih->type) == 1) @@ -378,7 +393,7 @@ static void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico) { ico = new_icon(); ico->id = alloc_icon_id(icog->lvc.language); - ico->lvc.language = dup_language(icog->lvc.language); + ico->lvc = icog->lvc; if(swap) { ide[i].offset = BYTESWAP_DWORD(ide[i].offset); @@ -458,7 +473,6 @@ static void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur) cursor_header_t *ch = (cursor_header_t *)rd->data; int swap = 0; - /* FIXME: Distinguish between normal and animated cursors (RIFF format)*/ if(ch->type == 2) swap = 0; else if(BYTESWAP_WORD(ch->type) == 2) @@ -473,7 +487,7 @@ static void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur) WORD bits; cur = new_cursor(); cur->id = alloc_cursor_id(curg->lvc.language); - cur->lvc.language = dup_language(curg->lvc.language); + cur->lvc = curg->lvc; if(swap) { cde[i].offset = BYTESWAP_DWORD(cde[i].offset); @@ -536,7 +550,7 @@ icon_group_t *new_icon_group(raw_data_t *rd, int *memopt) } else icog->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE; - icog->lvc.language = dup_language(currentlanguage); + icog->lvc = rd->lvc; split_icons(rd, icog, &(icog->nicon)); free(rd->data); free(rd); @@ -553,13 +567,309 @@ cursor_group_t *new_cursor_group(raw_data_t *rd, int *memopt) } else curg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE; - curg->lvc.language = dup_language(currentlanguage); + curg->lvc = rd->lvc; split_cursors(rd, curg, &(curg->ncursor)); free(rd->data); free(rd); return curg; } +/* + * Animated cursors and icons + * + * The format of animated cursors and icons is yet another example + * of bad design by "The Company". The entire RIFF structure is + * flawed by design because it is inconsistent and single minded: + * - some tags have lengths attached, others don't. The use of these + * non-length tags is absolutely unclear; + * - the content of "icon" tags can be both icons and cursors; + * - tags lack proper alignment constraints. It seems that everything + * is 16bit aligned, but I could not find that in any docu. Just be + * prepared to eat anything; + * - there are no strict constraints on tag-nesting and the organization + * is highly illogical; + * + * Anyhow, here is the basic structure: + * "RIFF" { dword taglength } + * "ACON" // What does it do? + * "LIST" { dword taglength } + * "INFO" // And what does this do? + * "INAM" { dword taglength } // Icon/cursor name + * {inam data} + * "IART" { dword taglength } // The artist + * {iart data} + * "fram" // Is followed by "icon"s + * "icon" { dword taglength } // First frame + * { icon/cursor data } + * "icon" { dword taglength } // Second frame + * { icon/cursor data } + * ... // ... + * "anih" { dword taglength } // Header structure + * { aniheader_t structure } + * "rate" { dword taglength } // The rate for each frame + * { `steps' dwords } + * "seq " { dword taglength } // The frame blit-order + * { `steps' dwords } + * + * Tag length are bytelength without the header and length field (i.e. -8). + * The "LIST" tag may occur several times and may encapsulate different + * tags. The `steps' is the number of "icon" tags found (actually the + * number of steps specified in the aniheader_t structure). The "seq "uence + * tag can be ommitted, in which case the sequence is equal to the sequence + * of "icon"s found in the file. Also "rate" may be ommitted, in which case + * the deafult from the aniheader_t structure is used. + * + * A animated cursor puts `.cur' formatted files into each "icon" tag, whereas + * animated icons contain `.ico' formatted files. + * + * Note about the code: Yes, it can be shorter/compressed. Some tags can be + * dealt with in the same code. However, this version shows what is going on + * and is better debug-able. + */ +static const char riff[4] = "RIFF"; +static const char acon[4] = "ACON"; +static const char list[4] = "LIST"; +static const char info[4] = "INFO"; +static const char inam[4] = "INAM"; +static const char iart[4] = "IART"; +static const char fram[4] = "fram"; +static const char icon[4] = "icon"; +static const char anih[4] = "anih"; +static const char rate[4] = "rate"; +static const char seq[4] = "seq "; + +#define NEXT_TAG(p) ((riff_tag_t *)(((char *)p) + (isswapped ? BYTESWAP_DWORD(p->size) : p->size) + sizeof(*p))) + +static void handle_ani_icon(riff_tag_t *rtp, enum res_e type, int isswapped) +{ + cursor_dir_entry_t *cdp; + cursor_header_t *chp; + int count; + int ctype; + int i; + static int once = 0; /* This will trigger only once per file! */ + const char *anistr = type == res_aniico ? "icon" : "cursor"; + /* Notes: + * Both cursor and icon directories are similar + * Both cursor and icon headers are similar + */ + + chp = (cursor_header_t *)(rtp+1); + cdp = (cursor_dir_entry_t *)(chp+1); + count = isswapped ? BYTESWAP_WORD(chp->count) : chp->count; + ctype = isswapped ? BYTESWAP_WORD(chp->type) : chp->type; + chp->reserved = BYTESWAP_WORD(chp->reserved); + chp->type = BYTESWAP_WORD(chp->type); + chp->count = BYTESWAP_WORD(chp->count); + + if(type == res_anicur && ctype != 2 && !once) + { + yywarning("Animated cursor contains invalid \"icon\" tag cursor-file (%d->%s)", + ctype, + ctype == 1 ? "icontype" : "?"); + once++; + } + else if(type == res_aniico && ctype != 1 && !once) + { + yywarning("Animated icon contains invalid \"icon\" tag icon-file (%d->%s)", + ctype, + ctype == 2 ? "cursortype" : "?"); + once++; + } + else if(ctype != 1 && ctype != 2 && !once) + { + yywarning("Animated %s contains invalid \"icon\" tag file-type (%d; neither icon nor cursor)", anistr, ctype); + once++; + } + + for(i = 0; i < count; i++) + { + DWORD ofs = isswapped ? BYTESWAP_DWORD(cdp[i].offset) : cdp[i].offset; + DWORD sze = isswapped ? BYTESWAP_DWORD(cdp[i].ressize) : cdp[i].ressize; + if(ofs > rtp->size || ofs+sze > rtp->size) + yyerror("Animated %s's data corrupt", anistr); + convert_bitmap((char *)chp + ofs, 0); + cdp[i].xhot = BYTESWAP_WORD(cdp->xhot); + cdp[i].yhot = BYTESWAP_WORD(cdp->yhot); + cdp[i].ressize = BYTESWAP_DWORD(cdp->ressize); + cdp[i].offset = BYTESWAP_DWORD(cdp->offset); + } +} + +static void handle_ani_list(riff_tag_t *lst, enum res_e type, int isswapped) +{ + riff_tag_t *rtp = lst+1; /* Skip the "LIST" tag */ + + while((char *)rtp < (char *)lst + lst->size + sizeof(*lst)) + { + if(!memcmp(rtp->tag, info, sizeof(info))) + { + rtp = (riff_tag_t *)(((char *)rtp) + 4); + } + else if(!memcmp(rtp->tag, inam, sizeof(inam))) + { + /* Ignore the icon/cursor name; its a string */ + rtp = NEXT_TAG(rtp); + } + else if(!memcmp(rtp->tag, iart, sizeof(iart))) + { + /* Ignore the author's name; its a string */ + rtp = NEXT_TAG(rtp); + } + else if(!memcmp(rtp->tag, fram, sizeof(fram))) + { + /* This should be followed by "icon"s, but we + * simply ignore this because it is pure + * non-information. + */ + rtp = (riff_tag_t *)(((char *)rtp) + 4); + } + else if(!memcmp(rtp->tag, icon, sizeof(icon))) + { + handle_ani_icon(rtp, type, isswapped); + rtp = NEXT_TAG(rtp); + } + else + internal_error(__FILE__, __LINE__, "Unknown tag \"%c%c%c%c\" in RIFF file", + isprint(rtp->tag[0]) ? rtp->tag[0] : '.', + isprint(rtp->tag[1]) ? rtp->tag[1] : '.', + isprint(rtp->tag[2]) ? rtp->tag[2] : '.', + isprint(rtp->tag[3]) ? rtp->tag[3] : '.'); + + /* FIXME: This relies in sizeof(DWORD) == sizeof(pointer_type) */ + if((DWORD)rtp & 1) + ((char *)rtp)++; + } +} + +ani_curico_t *new_ani_curico(enum res_e type, raw_data_t *rd, int *memopt) +{ + ani_curico_t *ani = (ani_curico_t *)xmalloc(sizeof(ani_curico_t)); + riff_tag_t *rtp; + int isswapped = 0; + int doswap; + const char *anistr = type == res_aniico ? "icon" : "cursor"; + + assert(!memcmp(rd->data, riff, sizeof(riff))); + assert(type == res_anicur || type == res_aniico); + + rtp = (riff_tag_t *)rd->data; + + if(BYTESWAP_DWORD(rtp->size) + 2*sizeof(DWORD) == rd->size) + isswapped = 1; + else if(rtp->size + 2*sizeof(DWORD) == rd->size) + isswapped = 0; + else + yyerror("Animated %s has an invalid RIFF length", anistr); + + switch(byteorder) + { +#ifdef WORDS_BIGENDIAN + case WRC_BO_LITTLE: +#else + case WRC_BO_BIG: +#endif + doswap = !isswapped; + break; + default: + doswap = isswapped; + } + + /* + * When to swap what: + * isswapped | doswap | + * ----------+--------+--------------------------------- + * 0 | 0 | read native; don't convert + * 1 | 0 | read swapped size; don't convert + * 0 | 1 | read native; convert + * 1 | 1 | read swapped size; convert + * Reading swapped size if necessary to calculate in native + * format. E.g. a little-endian source on a big-endian + * processor. + */ + if(doswap) + { + /* We only go through the RIFF file if we need to swap + * bytes in words/dwords. Else we couldn't care less + * what the file contains. This is consistent with + * MS' rc.exe, which doesn't complain at all, eventhough + * the fileformat might not be entirely correct. + */ + rtp++; /* Skip the "RIFF" tag */ + + while((char *)rtp < (char *)rd->data + rd->size) + { + if(!memcmp(rtp->tag, acon, sizeof(acon))) + { + rtp = (riff_tag_t *)(((char *)rtp) + 4); + } + else if(!memcmp(rtp->tag, list, sizeof(list))) + { + handle_ani_list(rtp, type, isswapped); + rtp = NEXT_TAG(rtp); + } + else if(!memcmp(rtp->tag, anih, sizeof(anih))) + { + aniheader_t *ahp = (aniheader_t *)((char *)(rtp+1)); + ahp->structsize = BYTESWAP_DWORD(ahp->structsize); + ahp->frames = BYTESWAP_DWORD(ahp->frames); + ahp->steps = BYTESWAP_DWORD(ahp->steps); + ahp->cx = BYTESWAP_DWORD(ahp->cx); + ahp->cy = BYTESWAP_DWORD(ahp->cy); + ahp->bitcount = BYTESWAP_DWORD(ahp->bitcount); + ahp->planes = BYTESWAP_DWORD(ahp->planes); + ahp->rate = BYTESWAP_DWORD(ahp->rate); + ahp->flags = BYTESWAP_DWORD(ahp->flags); + rtp = NEXT_TAG(rtp); + } + else if(!memcmp(rtp->tag, rate, sizeof(rate))) + { + int cnt = rtp->size / sizeof(DWORD); + DWORD *dwp = (DWORD *)(rtp+1); + int i; + for(i = 0; i < cnt; i++) + dwp[i] = BYTESWAP_DWORD(dwp[i]); + rtp = NEXT_TAG(rtp); + } + else if(!memcmp(rtp->tag, seq, sizeof(seq))) + { + int cnt = rtp->size / sizeof(DWORD); + DWORD *dwp = (DWORD *)(rtp+1); + int i; + for(i = 0; i < cnt; i++) + dwp[i] = BYTESWAP_DWORD(dwp[i]); + rtp = NEXT_TAG(rtp); + } + else + internal_error(__FILE__, __LINE__, "Unknown tag \"%c%c%c%c\" in RIFF file", + isprint(rtp->tag[0]) ? rtp->tag[0] : '.', + isprint(rtp->tag[1]) ? rtp->tag[1] : '.', + isprint(rtp->tag[2]) ? rtp->tag[2] : '.', + isprint(rtp->tag[3]) ? rtp->tag[3] : '.'); + + /* FIXME: This relies in sizeof(DWORD) == sizeof(pointer_type) */ + if((DWORD)rtp & 1) + ((char *)rtp)++; + } + + /* We must end correctly here */ + if((char *)rtp != (char *)rd->data + rd->size) + yyerror("Animated %s contains invalid field size(s)", anistr); + } + + ani->data = rd; + if(memopt) + { + ani->memopt = *memopt; + free(memopt); + } + else + ani->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE; + return ani; +} +#undef NEXT_TAG + +/* Bitmaps */ bitmap_t *new_bitmap(raw_data_t *rd, int *memopt) { bitmap_t *bmp = (bitmap_t *)xmalloc(sizeof(bitmap_t)); diff --git a/tools/wrc/newstruc.h b/tools/wrc/newstruc.h index 354c4e4fa91..f30c30c92aa 100644 --- a/tools/wrc/newstruc.h +++ b/tools/wrc/newstruc.h @@ -41,6 +41,7 @@ __NEW_STRUCT_PROTO(lvc); __NEW_STRUCT_PROTO(res_count); __NEW_STRUCT_PROTO(string); __NEW_STRUCT_PROTO(toolbar_item); +__NEW_STRUCT_PROTO(ani_any); resource_t *new_resource(enum res_e t, void *res, int memopt, language_t *lan); version_t *new_version(DWORD v); @@ -53,8 +54,10 @@ rcdata_t *new_rcdata(raw_data_t *rd, int *memopt); font_id_t *new_font_id(int size, string_t *face, int weight, int italic); user_t *new_user(name_id_t *type, raw_data_t *rd, int *memopt); font_t *new_font(raw_data_t *rd, int *memopt); +fontdir_t *new_fontdir(raw_data_t *rd, int *memopt); icon_group_t *new_icon_group(raw_data_t *rd, int *memopt); cursor_group_t *new_cursor_group(raw_data_t *rd, int *memopt); +ani_curico_t *new_ani_curico(enum res_e type, raw_data_t *rd, int *memopt); bitmap_t *new_bitmap(raw_data_t *rd, int *memopt); ver_words_t *new_ver_words(int i); ver_words_t *add_ver_words(ver_words_t *w, int i); diff --git a/tools/wrc/parser.h b/tools/wrc/parser.h index 53de1318ed1..ce812f6ac97 100644 --- a/tools/wrc/parser.h +++ b/tools/wrc/parser.h @@ -10,6 +10,7 @@ /* From parser.y */ extern int yydebug; extern int want_nl; /* Set when getting line-numers */ +extern int want_id; /* Set when getting the resource name */ int yyparse(void); diff --git a/tools/wrc/parser.l b/tools/wrc/parser.l index b395330884f..932d7e05f62 100644 --- a/tools/wrc/parser.l +++ b/tools/wrc/parser.l @@ -2,6 +2,8 @@ * * Copyright 1998-2000 Bertho A. Stultiens (BS) * + * 21-May-2000 BS - Fixed the ident requirement of resource names + * which can be keywords. * 30-Apr-2000 BS - Reintegration into the wine-tree * 11-Jan-2000 BS - Very drastic cleanup because we don't have a * preprocessor in here anymore. @@ -96,7 +98,7 @@ cident [a-zA-Z_][0-9a-zA-Z_]* #define YY_NO_TOP_STATE /* Always update the current character position within a line */ -#define YY_USER_ACTION char_number+=yyleng; +#define YY_USER_ACTION char_number+=yyleng; wanted_id = want_id; want_id = 0; static void addcchar(char c); static void addwchar(short s); @@ -114,95 +116,116 @@ static int stripslevel = 0; /* Count {} during pp_strips/pp_stripe mode */ static int stripplevel = 0; /* Count () during pp_strips mode */ static int cjunk_tagline; /* Where did we start stripping (helps error tracking) */ +/* + * This one is a bit tricky. + * We set 'want_id' in the parser to get the first + * identifier we get across in the scanner, but we + * also want it to be reset at nearly any token we + * see. Exceptions are: + * - newlines + * - comments + * - whitespace + * + * The scanner will automatically reset 'want_id' + * after *each* scanner reduction and puts is value + * into the var below. In this way we can see the + * state after the YY_RULE_SETUP (i.e. the user action; + * see above) and don't have to worry too much when + * it needs to be reset. + */ +static int wanted_id = 0; +static int save_wanted_id; /* To save across comment reductions */ struct keyword { char *keyword; int token; int isextension; int needcase; + int alwayskw; }; static struct keyword keywords[] = { - { "ACCELERATORS", tACCELERATORS, 0, 0}, - { "ALT", tALT, 0, 0}, - { "ASCII", tASCII, 0, 0}, - { "AUTO3STATE", tAUTO3STATE, 1, 0}, - { "AUTOCHECKBOX", tAUTOCHECKBOX, 1, 0}, - { "AUTORADIOBUTTON", tAUTORADIOBUTTON, 1, 0}, - { "BEGIN", tBEGIN, 0, 0}, - { "BITMAP", tBITMAP, 0, 0}, - { "BLOCK", tBLOCK, 0, 0}, - { "BUTTON", tBUTTON, 1, 0}, - { "CAPTION", tCAPTION, 0, 0}, - { "CHARACTERISTICS", tCHARACTERISTICS, 1, 0}, - { "CHECKBOX", tCHECKBOX, 0, 0}, - { "CHECKED", tCHECKED, 0, 0}, - { "CLASS", tCLASS, 0, 0}, - { "COMBOBOX", tCOMBOBOX, 0, 0}, - { "CONTROL", tCONTROL, 0, 0}, - { "CTEXT", tCTEXT, 0, 0}, - { "CURSOR", tCURSOR, 0, 0}, - { "DEFPUSHBUTTON", tDEFPUSHBUTTON, 0, 0}, - { "DIALOG", tDIALOG, 0, 0}, - { "DIALOGEX", tDIALOGEX, 1, 0}, - { "DISCARDABLE", tDISCARDABLE, 0, 0}, - { "DLGINIT", tDLGINIT, 0, 0}, - { "EDITTEXT", tEDITTEXT, 0, 0}, - { "END", tEND, 0, 0}, - { "enum", tENUM, 0, 1}, - { "EXSTYLE", tEXSTYLE, 0, 0}, - { "extern", tEXTERN, 0, 1}, - { "FILEFLAGS", tFILEFLAGS, 0, 0}, - { "FILEFLAGSMASK", tFILEFLAGSMASK, 0, 0}, - { "FILEOS", tFILEOS, 0, 0}, - { "FILESUBTYPE", tFILESUBTYPE, 0, 0}, - { "FILETYPE", tFILETYPE, 0, 0}, - { "FILEVERSION", tFILEVERSION, 0, 0}, - { "FIXED", tFIXED, 0, 0}, - { "FONT", tFONT, 0, 0}, - { "GRAYED", tGRAYED, 0, 0}, - { "GROUPBOX", tGROUPBOX, 0, 0}, - { "HELP", tHELP, 0, 0}, - { "ICON", tICON, 0, 0}, - { "IMPURE", tIMPURE, 0, 0}, - { "INACTIVE", tINACTIVE, 0, 0}, - { "inline", tINLINE, 0, 1}, - { "LANGUAGE", tLANGUAGE, 1, 0}, - { "LISTBOX", tLISTBOX, 0, 0}, - { "LOADONCALL", tLOADONCALL, 0, 0}, - { "LTEXT", tLTEXT, 0, 0}, - { "MENU", tMENU, 0, 0}, - { "MENUBARBREAK", tMENUBARBREAK, 0, 0}, - { "MENUBREAK", tMENUBREAK, 0, 0}, - { "MENUEX", tMENUEX, 1, 0}, - { "MENUITEM", tMENUITEM, 0, 0}, - { "MESSAGETABLE", tMESSAGETABLE, 1, 0}, - { "MOVEABLE", tMOVEABLE, 0, 0}, - { "NOINVERT", tNOINVERT, 0, 0}, - { "NOT", tNOT, 0, 0}, - { "POPUP", tPOPUP, 0, 0}, - { "PRELOAD", tPRELOAD, 0, 0}, - { "PRODUCTVERSION", tPRODUCTVERSION, 0, 0}, - { "PURE", tPURE, 0, 0}, - { "PUSHBUTTON", tPUSHBUTTON, 0, 0}, - { "RADIOBUTTON", tRADIOBUTTON, 0, 0}, - { "RCDATA", tRCDATA, 0, 0}, - { "RTEXT", tRTEXT, 0, 0}, - { "SCROLLBAR", tSCROLLBAR, 0, 0}, - { "SEPARATOR", tSEPARATOR, 0, 0}, - { "SHIFT", tSHIFT, 0, 0}, - { "STATE3", tSTATE3, 1, 0}, - { "static", tSTATIC, 0, 1}, - { "STRING", tSTRING, 0, 0}, - { "STRINGTABLE", tSTRINGTABLE, 0, 0}, - { "struct", tSTRUCT, 0, 1}, - { "STYLE", tSTYLE, 0, 0}, - { "TOOLBAR", tTOOLBAR, 1, 0}, - { "typedef", tTYPEDEF, 0, 1}, - { "VALUE", tVALUE, 0, 0}, - { "VERSION", tVERSION, 1, 0}, - { "VERSIONINFO", tVERSIONINFO, 0, 0}, - { "VIRTKEY", tVIRTKEY, 0, 0} + { "ACCELERATORS", tACCELERATORS, 0, 0, 0}, + { "ALT", tALT, 0, 0, 0}, + { "ASCII", tASCII, 0, 0, 0}, + { "AUTO3STATE", tAUTO3STATE, 1, 0, 0}, + { "AUTOCHECKBOX", tAUTOCHECKBOX, 1, 0, 0}, + { "AUTORADIOBUTTON", tAUTORADIOBUTTON, 1, 0, 0}, + { "BEGIN", tBEGIN, 0, 0, 0}, + { "BITMAP", tBITMAP, 0, 0, 0}, + { "BLOCK", tBLOCK, 0, 0, 0}, + { "BUTTON", tBUTTON, 1, 0, 0}, + { "CAPTION", tCAPTION, 0, 0, 0}, + { "CHARACTERISTICS", tCHARACTERISTICS, 1, 0, 0}, + { "CHECKBOX", tCHECKBOX, 0, 0, 0}, + { "CHECKED", tCHECKED, 0, 0, 0}, + { "CLASS", tCLASS, 0, 0, 0}, + { "COMBOBOX", tCOMBOBOX, 0, 0, 0}, + { "CONTROL", tCONTROL, 0, 0, 0}, + { "CTEXT", tCTEXT, 0, 0, 0}, + { "CURSOR", tCURSOR, 0, 0, 0}, + { "DEFPUSHBUTTON", tDEFPUSHBUTTON, 0, 0, 0}, + { "DIALOG", tDIALOG, 0, 0, 0}, + { "DIALOGEX", tDIALOGEX, 1, 0, 0}, + { "DISCARDABLE", tDISCARDABLE, 0, 0, 0}, + { "DLGINIT", tDLGINIT, 0, 0, 0}, + { "EDITTEXT", tEDITTEXT, 0, 0, 0}, + { "END", tEND, 0, 0, 0}, + { "enum", tENUM, 0, 1, 1}, + { "EXSTYLE", tEXSTYLE, 0, 0, 0}, + { "extern", tEXTERN, 0, 1, 1}, + { "FILEFLAGS", tFILEFLAGS, 0, 0, 0}, + { "FILEFLAGSMASK", tFILEFLAGSMASK, 0, 0, 0}, + { "FILEOS", tFILEOS, 0, 0, 0}, + { "FILESUBTYPE", tFILESUBTYPE, 0, 0, 0}, + { "FILETYPE", tFILETYPE, 0, 0, 0}, + { "FILEVERSION", tFILEVERSION, 0, 0, 0}, + { "FIXED", tFIXED, 0, 0, 0}, + { "FONT", tFONT, 0, 0, 0}, + { "FONTDIR", tFONTDIR, 0, 0, 0}, /* This is a Borland BRC extension */ + { "GRAYED", tGRAYED, 0, 0, 0}, + { "GROUPBOX", tGROUPBOX, 0, 0, 0}, + { "HELP", tHELP, 0, 0, 0}, + { "ICON", tICON, 0, 0, 0}, + { "IMPURE", tIMPURE, 0, 0, 0}, + { "INACTIVE", tINACTIVE, 0, 0, 0}, + { "inline", tINLINE, 0, 1, 1}, + { "LANGUAGE", tLANGUAGE, 1, 0, 1}, + { "LISTBOX", tLISTBOX, 0, 0, 0}, + { "LOADONCALL", tLOADONCALL, 0, 0, 0}, + { "LTEXT", tLTEXT, 0, 0, 0}, + { "MENU", tMENU, 0, 0, 0}, + { "MENUBARBREAK", tMENUBARBREAK, 0, 0, 0}, + { "MENUBREAK", tMENUBREAK, 0, 0, 0}, + { "MENUEX", tMENUEX, 1, 0, 0}, + { "MENUITEM", tMENUITEM, 0, 0, 0}, + { "MESSAGETABLE", tMESSAGETABLE, 1, 0, 0}, + { "MOVEABLE", tMOVEABLE, 0, 0, 0}, + { "NOINVERT", tNOINVERT, 0, 0, 0}, + { "NOT", tNOT, 0, 0, 0}, + { "POPUP", tPOPUP, 0, 0, 0}, + { "PRELOAD", tPRELOAD, 0, 0, 0}, + { "PRODUCTVERSION", tPRODUCTVERSION, 0, 0, 0}, + { "PURE", tPURE, 0, 0, 0}, + { "PUSHBUTTON", tPUSHBUTTON, 0, 0, 0}, + { "RADIOBUTTON", tRADIOBUTTON, 0, 0, 0}, + { "RCDATA", tRCDATA, 0, 0, 0}, + { "RTEXT", tRTEXT, 0, 0, 0}, + { "SCROLLBAR", tSCROLLBAR, 0, 0, 0}, + { "SEPARATOR", tSEPARATOR, 0, 0, 0}, + { "SHIFT", tSHIFT, 0, 0, 0}, + { "STATE3", tSTATE3, 1, 0, 0}, + { "static", tSTATIC, 0, 1, 1}, + { "STRING", tSTRING, 0, 0, 0}, + { "STRINGTABLE", tSTRINGTABLE, 0, 0, 1}, + { "struct", tSTRUCT, 0, 1, 1}, + { "STYLE", tSTYLE, 0, 0, 0}, + { "TOOLBAR", tTOOLBAR, 1, 0, 0}, + { "typedef", tTYPEDEF, 0, 1, 1}, + { "VALUE", tVALUE, 0, 0, 0}, + { "VERSION", tVERSION, 1, 0, 0}, + { "VERSIONINFO", tVERSIONINFO, 0, 0, 0}, + { "VIRTKEY", tVIRTKEY, 0, 0, 0} }; #define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0])) @@ -318,6 +341,11 @@ static struct keyword *iskeyword(char *kw) { if(tok->token == tCLASS && !strcmp(yytext, "class")) return tCPPCLASS; + else if(wanted_id && !tok->alwayskw) + { + yylval.str = make_string(yytext); + return tIDENT; + } else return tok->token; } @@ -446,17 +474,21 @@ L\" { * Should never occur after preprocessing */ "/*" { - yy_push_state(comment); if(!no_preprocess) yywarning("Found comments after preprocessing, please report"); + yy_push_state(comment); + save_wanted_id = wanted_id; + if(!no_preprocess) + yywarning("Found comments after preprocessing, please report"); } [^*\n]* ; "*"+[^*/\n]* ; \n line_number++; char_number = 1; -"*"+"/" yy_pop_state(); +"*"+"/" yy_pop_state(); want_id = save_wanted_id; -;[^\n]* ; /* not really comment, but left-over c-junk */ -"//"[^\n]* if(!no_preprocess) yywarning("Found comments after preprocessing, please report"); +;[^\n]* want_id = wanted_id; /* not really comment, but left-over c-junk */ +"//"[^\n]* want_id = wanted_id; if(!no_preprocess) yywarning("Found comments after preprocessing, please report"); \n { + want_id = wanted_id; line_number++; char_number = 1; if(want_nl) @@ -465,7 +497,7 @@ L\" { return tNL; } } -{ws}+ ; /* Eat whitespace */ +{ws}+ want_id = wanted_id; /* Eat whitespace */ . return yytext[0]; diff --git a/tools/wrc/parser.y b/tools/wrc/parser.y index 379f44710db..3cd1d1ca5fb 100644 --- a/tools/wrc/parser.y +++ b/tools/wrc/parser.y @@ -4,6 +4,15 @@ * Copyright 1998-2000 Bertho A. Stultiens (BS) * 1999 Juergen Schmied (JS) * + * 21-May-2000 BS - Partial implementation of font resources. + * - Corrected language propagation for binary + * resources such as bitmaps, isons, cursors, + * userres and rcdata. The language is now + * correct in .res files. + * - Fixed reading the resource name as ident, + * so that it may overlap keywords. + * 20-May-2000 BS - Implemented animated cursors and icons + * resource types. * 30-Apr-2000 BS - Reintegration into the wine-tree * 14-Jan-2000 BS - Redid the usertype resources so that they * are compatible. @@ -117,6 +126,7 @@ #include "winuser.h" int want_nl = 0; /* Signal flex that we need the next newline */ +int want_id = 0; /* Signal flex that we need the next identifier */ stringtable_t *tagstt; /* Stringtable tag. * It is set while parsing a stringtable to one of * the stringtables in the sttres list or a new one @@ -130,6 +140,8 @@ static int *tagstt_memopt; static characts_t *tagstt_characts; static version_t *tagstt_version; +static const char riff[4] = "RIFF"; /* RIFF file magic for animated cursor/icon */ + /* Prototypes of here defined functions */ static event_t *get_event_head(event_t *p); static control_t *get_control_head(control_t *p); @@ -174,6 +186,8 @@ static stringtable_t *find_stringtable(lvc_t *lvc); static toolbar_item_t *ins_tlbr_button(toolbar_item_t *prev, toolbar_item_t *idrec); static toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems); static string_t *make_filename(string_t *s); +static resource_t *build_fontdirs(resource_t *tail); +static resource_t *build_fontdir(resource_t **fnt, int nfnt); %} %union{ @@ -184,13 +198,10 @@ static string_t *make_filename(string_t *s); resource_t *res; accelerator_t *acc; bitmap_t *bmp; - cursor_t *cur; - cursor_group_t *curg; dialog_t *dlg; dialogex_t *dlgex; font_t *fnt; - icon_t *ico; - icon_group_t *icog; + fontdir_t *fnd; menu_t *men; menuex_t *menex; rcdata_t *rdt; @@ -219,6 +230,7 @@ static string_t *make_filename(string_t *s); dlginit_t *dginit; style_pair_t *styles; style_t *style; + ani_any_t *ani; } %token tTYPEDEF tEXTERN tSTRUCT tENUM tCPPCLASS tINLINE tSTATIC tNL @@ -226,7 +238,7 @@ static string_t *make_filename(string_t *s); %token tSTRING tIDENT tFILENAME %token tRAWDATA %token tACCELERATORS tBITMAP tCURSOR tDIALOG tDIALOGEX tMENU tMENUEX tMESSAGETABLE -%token tRCDATA tVERSIONINFO tSTRINGTABLE tFONT tICON +%token tRCDATA tVERSIONINFO tSTRINGTABLE tFONT tFONTDIR tICON %token tAUTO3STATE tAUTOCHECKBOX tAUTORADIOBUTTON tCHECKBOX tDEFPUSHBUTTON %token tPUSHBUTTON tRADIOBUTTON tSTATE3 /* PUSHBOX */ %token tGROUPBOX tCOMBOBOX tLISTBOX tSCROLLBAR @@ -254,18 +266,18 @@ static string_t *make_filename(string_t *s); %type resource_file resource resources resource_definition %type stringtable strings %type font -%type icon +%type fontdir %type accelerators %type events %type bitmap -%type cursor +%type cursor icon %type dialog dlg_attributes %type ctrls gen_ctrl lab_ctrl ctrl_desc iconinfo %type helpid %type dialogex dlgex_attribs %type exctrls gen_exctrl lab_exctrl exctrl_desc %type rcdata -%type raw_data raw_elements opt_data +%type raw_data raw_elements opt_data file_raw %type versioninfo fix_version %type ver_words %type ver_blocks ver_block @@ -311,6 +323,20 @@ resource_file if(rsc) rsc->prev = $1; } + else + $1 = rsc; + /* Find the tail again */ + while($1 && $1->next) + $1 = $1->next; + /* Now add any fontdirecory */ + rsc = build_fontdirs($1); + /* 'build_fontdir' returns a head and $1 is a tail */ + if($1) + { + $1->next = rsc; + if(rsc) + rsc->prev = $1; + } else $1 = rsc; /* Final statement before were done */ @@ -320,7 +346,7 @@ resource_file /* Resources are put into a linked list */ resources - : /* Empty */ { $$ = NULL; } + : /* Empty */ { $$ = NULL; want_id = 1; } | resources resource { if($2) { @@ -334,6 +360,23 @@ resources if($1) $1->next = head; $$ = tail; + /* Check for duplicate identifiers */ + while($1 && head) + { + resource_t *rsc = $1; + while(rsc) + { + if(rsc->type == head->type + && rsc->lan->id == head->lan->id + && rsc->lan->sub == head->lan->sub + && !compare_name_id(rsc->name, head->name)) + { + yyerror("Duplicate resource name '%s'", get_nameid_str(rsc->name)); + } + rsc = rsc->prev; + } + head = head->next; + } } else if($1) { @@ -344,9 +387,10 @@ resources } else $$ = NULL; + want_id = 1; } - | resources preprocessor { $$ = $1; } - | resources cjunk { $$ = $1; } + | resources preprocessor { $$ = $1; want_id = 1; } + | resources cjunk { $$ = $1; want_id = 1; } ; /* @@ -416,12 +460,16 @@ resource $$ = NULL; chat("Got STRINGTABLE"); } - | opt_language { + | tLANGUAGE {want_nl = 1; } expr ',' expr tNL { + /* We *NEED* the newline to delimit the expression. + * Otherwise, we would not be able to set the next + * want_id anymore because of the token-lookahead. + */ if(!win32) yywarning("LANGUAGE not supported in 16-bit mode"); if(currentlanguage) free(currentlanguage); - currentlanguage = $1; + currentlanguage = new_language($3, $5); $$ = NULL; } ; @@ -457,20 +505,30 @@ nameid_s: nameid { $$ = $1; } /* get the value for a single resource*/ resource_definition : accelerators { $$ = new_resource(res_acc, $1, $1->memopt, $1->lvc.language); } - | bitmap { $$ = new_resource(res_bmp, $1, $1->memopt, dup_language(currentlanguage)); } + | bitmap { $$ = new_resource(res_bmp, $1, $1->memopt, $1->data->lvc.language); } | cursor { resource_t *rsc; - cursor_t *cur; - $$ = rsc = new_resource(res_curg, $1, $1->memopt, dup_language(currentlanguage)); - for(cur = $1->cursorlist; cur; cur = cur->next) + if($1->type == res_anicur) { - rsc->prev = new_resource(res_cur, cur, $1->memopt, dup_language(currentlanguage)); - rsc->prev->next = rsc; - rsc = rsc->prev; - rsc->name = new_name_id(); - rsc->name->type = name_ord; - rsc->name->name.i_name = cur->id; + $$ = rsc = new_resource(res_anicur, $1->u.ani, $1->u.ani->memopt, $1->u.ani->data->lvc.language); } + else if($1->type == res_curg) + { + cursor_t *cur; + $$ = rsc = new_resource(res_curg, $1->u.curg, $1->u.curg->memopt, $1->u.curg->lvc.language); + for(cur = $1->u.curg->cursorlist; cur; cur = cur->next) + { + rsc->prev = new_resource(res_cur, cur, $1->u.curg->memopt, $1->u.curg->lvc.language); + rsc->prev->next = rsc; + rsc = rsc->prev; + rsc->name = new_name_id(); + rsc->name->type = name_ord; + rsc->name->name.i_name = cur->id; + } + } + else + internal_error(__FILE__, __LINE__, "Invalid top-level type %d in cursor resource", $1->type); + free($1); } | dialog { $$ = new_resource(res_dlg, $1, $1->memopt, $1->lvc.language); } | dialogex { @@ -479,21 +537,32 @@ resource_definition else $$ = NULL; } - | dlginit { $$ = new_resource(res_dlginit, $1, $1->memopt, $1->lvc.language); } - | font { $$ = new_resource(res_fnt, $1, $1->memopt, dup_language(currentlanguage)); } + | dlginit { $$ = new_resource(res_dlginit, $1, $1->memopt, $1->data->lvc.language); } + | font { $$ = new_resource(res_fnt, $1, $1->memopt, $1->data->lvc.language); } + | fontdir { $$ = new_resource(res_fntdir, $1, $1->memopt, $1->data->lvc.language); } | icon { resource_t *rsc; - icon_t *ico; - $$ = rsc = new_resource(res_icog, $1, $1->memopt, dup_language(currentlanguage)); - for(ico = $1->iconlist; ico; ico = ico->next) + if($1->type == res_aniico) { - rsc->prev = new_resource(res_ico, ico, $1->memopt, dup_language(currentlanguage)); - rsc->prev->next = rsc; - rsc = rsc->prev; - rsc->name = new_name_id(); - rsc->name->type = name_ord; - rsc->name->name.i_name = ico->id; + $$ = rsc = new_resource(res_aniico, $1->u.ani, $1->u.ani->memopt, $1->u.ani->data->lvc.language); } + else if($1->type == res_icog) + { + icon_t *ico; + $$ = rsc = new_resource(res_icog, $1->u.icog, $1->u.icog->memopt, $1->u.icog->lvc.language); + for(ico = $1->u.icog->iconlist; ico; ico = ico->next) + { + rsc->prev = new_resource(res_ico, ico, $1->u.icog->memopt, $1->u.icog->lvc.language); + rsc->prev->next = rsc; + rsc = rsc->prev; + rsc->name = new_name_id(); + rsc->name->type = name_ord; + rsc->name->name.i_name = ico->id; + } + } + else + internal_error(__FILE__, __LINE__, "Invalid top-level type %d in icon resource", $1->type); + free($1); } | menu { $$ = new_resource(res_men, $1, $1->memopt, $1->lvc.language); } | menuex { @@ -503,10 +572,10 @@ resource_definition $$ = NULL; } | messagetable { $$ = new_resource(res_msg, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, dup_language(currentlanguage)); } - | rcdata { $$ = new_resource(res_rdt, $1, $1->memopt, $1->lvc.language); } + | rcdata { $$ = new_resource(res_rdt, $1, $1->memopt, $1->data->lvc.language); } | toolbar { $$ = new_resource(res_toolbar, $1, $1->memopt, $1->lvc.language); } - | userres { $$ = new_resource(res_usr, $1, $1->memopt, dup_language(currentlanguage)); } - | versioninfo { $$ = new_resource(res_ver, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, dup_language(currentlanguage)); } + | userres { $$ = new_resource(res_usr, $1, $1->memopt, $1->data->lvc.language); } + | versioninfo { $$ = new_resource(res_ver, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, $1->lvc.language); } ; @@ -516,23 +585,59 @@ filename: tFILENAME { $$ = make_filename($1); } ; /* ------------------------------ Bitmap ------------------------------ */ -bitmap : tBITMAP loadmemopts filename { $$ = new_bitmap(load_file($3), $2); } - | tBITMAP loadmemopts raw_data { $$ = new_bitmap($3, $2); } +bitmap : tBITMAP loadmemopts file_raw { $$ = new_bitmap($3, $2); } ; /* ------------------------------ Cursor ------------------------------ */ -cursor : tCURSOR loadmemopts filename { $$ = new_cursor_group(load_file($3), $2); } - | tCURSOR loadmemopts raw_data { $$ = new_cursor_group($3, $2); } - ; - -/* ------------------------------ Font ------------------------------ */ -/* FIXME: Should we allow raw_data here? */ -font : tFONT loadmemopts filename { $$ = new_font(load_file($3), $2); } +cursor : tCURSOR loadmemopts file_raw { + $$ = new_ani_any(); + if($3->size > 4 && !memcmp($3->data, riff, sizeof(riff))) + { + $$->type = res_anicur; + $$->u.ani = new_ani_curico(res_anicur, $3, $2); + } + else + { + $$->type = res_curg; + $$->u.curg = new_cursor_group($3, $2); + } + } ; /* ------------------------------ Icon ------------------------------ */ -icon : tICON loadmemopts filename { $$ = new_icon_group(load_file($3), $2); } - | tICON loadmemopts raw_data { $$ = new_icon_group($3, $2); } +icon : tICON loadmemopts file_raw { + $$ = new_ani_any(); + if($3->size > 4 && !memcmp($3->data, riff, sizeof(riff))) + { + $$->type = res_aniico; + $$->u.ani = new_ani_curico(res_aniico, $3, $2); + } + else + { + $$->type = res_icog; + $$->u.icog = new_icon_group($3, $2); + } + } + ; + +/* ------------------------------ Font ------------------------------ */ + /* + * The reading of raw_data for fonts is a Borland BRC + * extension. MS generates an error. However, it is + * most logical to support this, considering how wine + * enters things in CVS (ascii). + */ +font : tFONT loadmemopts file_raw { $$ = new_font($3, $2); } + ; + + /* + * The fontdir is a Borland BRC extension which only + * reads the data as 'raw_data' from the file. + * I don't know whether it is interpreted. + * The fontdir is generated if it was not present and + * fonts are defined in the source. + */ +fontdir : tFONTDIR loadmemopts raw_data { $$ = new_fontdir($3, $2); } ; /* ------------------------------ MessageTable ------------------------------ */ @@ -548,34 +653,15 @@ messagetable ; /* ------------------------------ RCData ------------------------------ */ -rcdata : tRCDATA loadmemopts opt_lvc raw_data { - $$ = new_rcdata($4, $2); - if($3) - { - $$->lvc = *($3); - free($3); - } - if(!$$->lvc.language) - $$->lvc.language = dup_language(currentlanguage); - } +rcdata : tRCDATA loadmemopts raw_data { $$ = new_rcdata($3, $2); } ; /* ------------------------------ DLGINIT ------------------------------ */ -dlginit : tDLGINIT loadmemopts opt_lvc raw_data { - $$ = new_dlginit($4, $2); - if($3) - { - $$->lvc = *($3); - free($3); - } - if(!$$->lvc.language) - $$->lvc.language = dup_language(currentlanguage); - } +dlginit : tDLGINIT loadmemopts raw_data { $$ = new_dlginit($3, $2); } ; /* ------------------------------ UserType ------------------------------ */ -userres : usertype loadmemopts filename { $$ = new_user($1, load_file($3), $2); } - | usertype loadmemopts raw_data { $$ = new_user($1, $3, $2); } +userres : usertype loadmemopts file_raw { $$ = new_user($1, $3, $2); } ; usertype: tNUMBER { @@ -1346,9 +1432,18 @@ opt_comma /* There seem to be two ways to specify a stringtable... */ /* ------------------------------ VersionInfo ------------------------------ */ versioninfo - : tVERSIONINFO fix_version tBEGIN ver_blocks tEND { - $$ = $2; - $2->blocks = get_ver_block_head($4); + : tVERSIONINFO loadmemopts fix_version tBEGIN ver_blocks tEND { + $$ = $3; + if($2) + { + $$->memopt = *($2); + free($2); + } + else + $$->memopt = WRC_MO_MOVEABLE | (win32 ? WRC_MO_PURE : 0); + $$->blocks = get_ver_block_head($5); + /* Set language; there is no version or characteristics */ + $$->lvc.language = dup_language(currentlanguage); } ; @@ -1590,8 +1685,19 @@ opt_version : tVERSION expr { $$ = new_version($2); } ; -/* ------------------------------ Raw data handking ------------------------------ */ -raw_data: tBEGIN raw_elements tEND { $$ = $2; } +/* ------------------------------ Raw data handling ------------------------------ */ +raw_data: opt_lvc tBEGIN raw_elements tEND { + if($1) + { + $3->lvc = *($1); + free($1); + } + + if(!$3->lvc.language) + $3->lvc.language = dup_language(currentlanguage); + + $$ = $3; + } ; raw_elements @@ -1605,6 +1711,14 @@ raw_elements | raw_elements opt_comma tSTRING { $$ = merge_raw_data_str($1, $3); } ; +/* File data or raw data */ +file_raw: filename { + $$ = load_file($1); + $$->lvc.language = dup_language(currentlanguage); + } + | raw_data { $$ = $1; } + ; + /* ------------------------------ Win32 expressions ------------------------------ */ /* All win16 numbers are also handled here. This is inconsistent with MS' * resource compiler, but what the heck, its just handy to have. @@ -2480,3 +2594,179 @@ static string_t *make_filename(string_t *str) return str; } +/* + * Process all resources to extract fonts and build + * a fontdir resource. + * + * Note: MS' resource compiler (build 1472) does not + * handle font resources with different languages. + * The fontdir is generated in the last active language + * and font identifiers must be unique across the entire + * source. + * This is not logical considering the localization + * constraints of all other resource types. MS has, + * most probably, never testet localized fonts. However, + * using fontresources is rare, so it might not occur + * in normal applications. + * Wine does require better localization because a lot + * of languages are coded into the same executable. + * Therefore, I will generate fontdirs for *each* + * localized set of fonts. + */ +static resource_t *build_fontdir(resource_t **fnt, int nfnt) +{ + static int once = 0; + if(!once) + { + warning("Need to parse fonts, not yet implemented"); + once++; + } + return NULL; +} + +static resource_t *build_fontdirs(resource_t *tail) +{ + resource_t *rsc; + resource_t *lst = NULL; + resource_t **fnt = NULL; /* List of all fonts */ + int nfnt = 0; + resource_t **fnd = NULL; /* List of all fontdirs */ + int nfnd = 0; + resource_t **lanfnt = NULL; + int nlanfnt = 0; + int i; + name_id_t nid; + string_t str; + int fntleft; + + nid.type = name_str; + nid.name.s_name = &str; + str.type = str_char; + str.str.cstr = "FONTDIR"; + str.size = 7; + + /* Extract all fonts and fontdirs */ + for(rsc = tail; rsc; rsc = rsc->prev) + { + if(rsc->type == res_fnt) + { + nfnt++; + fnt = xrealloc(fnt, nfnt * sizeof(*fnt)); + fnt[nfnt-1] = rsc; + } + else if(rsc->type == res_fntdir) + { + nfnd++; + fnd = xrealloc(fnd, nfnd * sizeof(*fnd)); + fnd[nfnd-1] = rsc; + } + } + + /* Verify the name of the present fontdirs */ + for(i = 0; i < nfnd; i++) + { + if(compare_name_id(&nid, fnd[i]->name)) + { + warning("User supplied FONTDIR entry has an invalid name '%s', ignored", + get_nameid_str(fnd[i]->name)); + fnd[i] = NULL; + } + } + + /* Sanity check */ + if(nfnt == 0) + { + if(nfnd != 0) + warning("Found %d FONTDIR entries without any fonts present", nfnd); + goto clean; + } + + /* Copy space */ + lanfnt = xmalloc(nfnt * sizeof(*lanfnt)); + + /* Get all fonts covered by fontdirs */ + for(i = 0; i < nfnd; i++) + { + int j; + WORD cnt; + int isswapped = 0; + + if(!fnd[i]) + continue; + for(j = 0; j < nfnt; j++) + { + if(!fnt[j]) + continue; + if(fnt[j]->lan->id == fnd[i]->lan->id && fnt[j]->lan->sub == fnd[i]->lan->sub) + { + lanfnt[nlanfnt] = fnt[j]; + nlanfnt++; + fnt[j] = NULL; + } + } + + cnt = *(WORD *)fnd[i]->res.fnd->data->data; + if(nlanfnt == cnt) + isswapped = 0; + else if(nlanfnt == BYTESWAP_WORD(cnt)) + isswapped = 1; + else + error("FONTDIR for language %d,%d has wrong count (%d, expected %d)", + fnd[i]->lan->id, fnd[i]->lan->sub, cnt, nlanfnt); +#ifdef WORDS_BIGENDIAN + if((byteorder == WRC_BO_LITTLE && !isswapped) || (byteorder != WRC_BO_LITTLE && isswapped)) +#else + if((byteorder == WRC_BO_BIG && !isswapped) || (byteorder != WRC_BO_BIG && isswapped)) +#endif + { + internal_error(__FILE__, __LINE__, "User supplied FONTDIR needs byteswapping"); + } + } + + /* We now have fonts left where we need to make a fontdir resource */ + for(i = fntleft = 0; i < nfnt; i++) + { + if(fnt[i]) + fntleft++; + } + while(fntleft) + { + /* Get fonts of same language in lanfnt[] */ + for(i = nlanfnt = 0; i < nfnt; i++) + { + if(fnt[i]) + { + if(!nlanfnt) + { + addlanfnt: + lanfnt[nlanfnt] = fnt[i]; + nlanfnt++; + fnt[i] = NULL; + fntleft--; + } + else if(fnt[i]->lan->id == lanfnt[0]->lan->id && fnt[i]->lan->sub == lanfnt[0]->lan->sub) + goto addlanfnt; + } + } + /* and build a fontdir */ + rsc = build_fontdir(lanfnt, nlanfnt); + if(rsc) + { + if(lst) + { + lst->next = rsc; + rsc->prev = lst; + } + lst = rsc; + } + } + + free(lanfnt); +clean: + if(fnt) + free(fnt); + if(fnd) + free(fnd); + return lst; +} + diff --git a/tools/wrc/utils.c b/tools/wrc/utils.c index 0845ed6f232..ec06da61c1f 100644 --- a/tools/wrc/utils.c +++ b/tools/wrc/utils.c @@ -276,3 +276,47 @@ char *dupwstr2cstr(const short *str) return cs; } +/* + ***************************************************************************** + * Function : compare_name_id + * Syntax : int compare_name_id(name_id_t *n1, name_id_t *n2) + * Input : + * Output : + * Description : + * Remarks : + ***************************************************************************** +*/ +int compare_name_id(name_id_t *n1, name_id_t *n2) +{ + if(n1->type == name_ord && n2->type == name_ord) + { + return n1->name.i_name - n2->name.i_name; + } + else if(n1->type == name_str && n2->type == name_str) + { + if(n1->name.s_name->type == str_char + && n2->name.s_name->type == str_char) + { + return strcasecmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr); + } + else if(n1->name.s_name->type == str_unicode + && n2->name.s_name->type == str_unicode) + { + return wstricmp(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr); + } + else + { + internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type"); + } + } + else if(n1->type == name_ord && n2->type == name_str) + return 1; + else if(n1->type == name_str && n2->type == name_ord) + return -1; + else + internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)", + n1->type, n2->type); + + return 0; /* Keep the compiler happy */ +} + diff --git a/tools/wrc/utils.h b/tools/wrc/utils.h index 96fa8a14fe7..1bb9e44cf0b 100644 --- a/tools/wrc/utils.h +++ b/tools/wrc/utils.h @@ -34,5 +34,6 @@ short *wstrcpy(short *dst, const short *src); int wstricmp(const short *s1, const short *s2); char *dupwstr2cstr(const short *str); short *dupcstr2wstr(const char *str); +int compare_name_id(name_id_t *n1, name_id_t *n2); #endif diff --git a/tools/wrc/wrc.h b/tools/wrc/wrc.h index 02979032a2f..41be299103e 100644 --- a/tools/wrc/wrc.h +++ b/tools/wrc/wrc.h @@ -16,8 +16,8 @@ #define WRC_MAJOR_VERSION 1 #define WRC_MINOR_VERSION 1 -#define WRC_MICRO_VERSION 2 -#define WRC_RELEASEDATE "(08-May-2000)" +#define WRC_MICRO_VERSION 3 +#define WRC_RELEASEDATE "(21-May-2000)" #define WRC_STRINGIZE(a) #a #define WRC_VERSIONIZE(a,b,c) WRC_STRINGIZE(a) "." WRC_STRINGIZE(b) "." WRC_STRINGIZE(c) diff --git a/tools/wrc/wrc.man b/tools/wrc/wrc.man index a15d5733dba..75c067a84b6 100644 --- a/tools/wrc/wrc.man +++ b/tools/wrc/wrc.man @@ -1,4 +1,4 @@ -.TH WRC 1 "May 8, 2000" "Version 1.1.2" "Wine Resource Compiler" +.TH WRC 1 "May 21, 2000" "Version 1.1.3" "Wine Resource Compiler" .SH NAME wrc \- Wine Resource Compiler .SH SYNOPSIS @@ -179,21 +179,26 @@ Additional resource\-types were contributed Ulrich Czekalla and Albert den Haan. Bugfixes have been contributed by many wine developpers. .SH BUGS \- The preprocessor recognizes variable argument macros, but does not -expanded them correctly. +expanded them correctly .br -\- Codepage/UNICODE translations are not/not correct implemented. +\- Codepage/UNICODE translations are not/not correct implemented .br \- Default memory options should differ between win16 and win32. .PP -\- There is no support for: +There is no support for: .br -\- MESSAGETABLE (parsed, but not generated). +\- MESSAGETABLE (parsed, but not generated) .br -\- FONT (parsed, but not generated). +\- RT_VXD, RT_PLUGPLAY and RT_HTML (unknown format) .br -\- RT_VXD and RT_PLUGPLAY (unknown format) -.br -\- Animated cursors and icons (RIFF format unknown). +\- PUSHBOX control is unsupported due to lack of original functionality. +.PP +Fonts are parsed and generated, but there is no support for the +generation of the FONTDIR yet. The user must supply the FONTDIR +resource in the source to match the FONT resources. +.PP +See the CHANGES and README.wrc files in the distribution for more +comments on bugs and fixes across the versions. .SH AVAILABILITY .B wrc is part of the wine distribution, which is available through diff --git a/tools/wrc/wrctypes.h b/tools/wrc/wrctypes.h index 53151ba0bc2..1cdd964175e 100644 --- a/tools/wrc/wrctypes.h +++ b/tools/wrc/wrctypes.h @@ -44,6 +44,7 @@ #define WRC_RT_VXD (20) #define WRC_RT_ANICURSOR (21) #define WRC_RT_ANIICON (22) +#define WRC_RT_HTML (23) #define WRC_RT_DLGINIT (240) #define WRC_RT_TOOLBAR (241) @@ -160,8 +161,9 @@ enum res_e { res_18, res_pnp, /* Not implemented, no layout available */ res_vxd, /* Not implemented, no layout available */ - res_anicur, /* Not implemented, no layout available */ - res_aniico, /* Not implemented, no layout available */ + res_anicur, + res_aniico, + res_html, /* Not implemented, no layout available */ res_dlginit = WRC_RT_DLGINIT, /* 240 */ res_toolbar = WRC_RT_TOOLBAR, /* 241 */ @@ -175,6 +177,7 @@ enum res_e { typedef struct raw_data { int size; char *data; + lvc_t lvc; /* Localized data */ } raw_data_t; /* Dialog structures */ @@ -286,12 +289,19 @@ typedef struct itemex_opt int gothelpid; } itemex_opt_t; -/* RC structures for types read from file or supplied binary */ +/* + * Font resources + */ typedef struct font { DWORD memopt; raw_data_t *data; } font_t; +typedef struct fontdir { + DWORD memopt; + raw_data_t *data; +} fontdir_t; + /* * Icon resources */ @@ -302,14 +312,14 @@ typedef struct icon_header { } icon_header_t; typedef struct icon_dir_entry { - BYTE width; /* From the SDK doc. */ - BYTE height; - BYTE nclr; - BYTE reserved; - WORD planes; - WORD bits; - DWORD ressize; - DWORD offset; + BYTE width; /* From the SDK doc. */ + BYTE height; + BYTE nclr; + BYTE reserved; + WORD planes; + WORD bits; + DWORD ressize; + DWORD offset; } icon_dir_entry_t; typedef struct icon { @@ -342,14 +352,14 @@ typedef struct cursor_header { } cursor_header_t; typedef struct cursor_dir_entry { - BYTE width; /* From the SDK doc. */ - BYTE height; - BYTE nclr; - BYTE reserved; - WORD xhot; - WORD yhot; - DWORD ressize; - DWORD offset; + BYTE width; /* From the SDK doc. */ + BYTE height; + BYTE nclr; + BYTE reserved; + WORD xhot; + WORD yhot; + DWORD ressize; + DWORD offset; } cursor_dir_entry_t; typedef struct cursor { @@ -374,6 +384,43 @@ typedef struct cursor_group { int ncursor; } cursor_group_t; +/* + * Animated cursors and icons + */ +typedef struct aniheader { + DWORD structsize; /* Header size (36 bytes) */ + DWORD frames; /* Number of unique icons in this cursor */ + DWORD steps; /* Number of blits before the animation cycles */ + DWORD cx; /* reserved, must be 0? */ + DWORD cy; /* reserved, must be 0? */ + DWORD bitcount; /* reserved, must be 0? */ + DWORD planes; /* reserved, must be 0? */ + DWORD rate; /* Default rate (1/60th of a second) if "rate" not present */ + DWORD flags; /* Animation flag (1==AF_ICON, although both icons and cursors set this) */ +} aniheader_t; + +typedef struct riff_tag { + BYTE tag[4]; + DWORD size; +} riff_tag_t; + +typedef struct ani_curico { + DWORD memopt; + raw_data_t *data; +} ani_curico_t; + +typedef struct ani_any { + enum res_e type; + union { + ani_curico_t *ani; + cursor_group_t *curg; + icon_group_t *icog; + } u; +} ani_any_t; + +/* + * Bitmaps + */ typedef struct bitmap { DWORD memopt; raw_data_t *data; @@ -381,7 +428,6 @@ typedef struct bitmap { typedef struct rcdata { DWORD memopt; - lvc_t lvc; raw_data_t *data; } rcdata_t; @@ -467,6 +513,8 @@ typedef struct versioninfo { int fst:1; } gotit; ver_block_t *blocks; + lvc_t lvc; + DWORD memopt; } versioninfo_t; /* Accelerator structures */ @@ -509,7 +557,6 @@ typedef struct toolbar { typedef struct dlginit { DWORD memopt; - lvc_t lvc; raw_data_t *data; } dlginit_t; @@ -523,6 +570,7 @@ typedef struct resource { language_t *lan; /* Only used as a sorting key and c-name creation*/ union { accelerator_t *acc; + ani_curico_t *ani; bitmap_t *bmp; cursor_t *cur; cursor_group_t *curg; @@ -530,6 +578,7 @@ typedef struct resource { dialogex_t *dlgex; dlginit_t *dlgi; font_t *fnt; + fontdir_t *fnd; icon_t *ico; icon_group_t *icog; menu_t *men; diff --git a/tools/wrc/writeres.c b/tools/wrc/writeres.c index 4ff255af769..1d83be5fb28 100644 --- a/tools/wrc/writeres.c +++ b/tools/wrc/writeres.c @@ -282,50 +282,6 @@ static void write_name_str(FILE *fp, name_id_t *nid) } } -/* - ***************************************************************************** - * Function : compare_name_id - * Syntax : int compare_name_id(name_id_t *n1, name_id_t *n2) - * Input : - * Output : - * Description : - * Remarks : - ***************************************************************************** -*/ -static int compare_name_id(name_id_t *n1, name_id_t *n2) -{ - if(n1->type == name_ord && n2->type == name_ord) - { - return n1->name.i_name - n2->name.i_name; - } - else if(n1->type == name_str && n2->type == name_str) - { - if(n1->name.s_name->type == str_char - && n2->name.s_name->type == str_char) - { - return strcasecmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr); - } - else if(n1->name.s_name->type == str_unicode - && n2->name.s_name->type == str_unicode) - { - return wstricmp(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr); - } - else - { - internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type"); - } - } - else if(n1->type == name_ord && n2->type == name_str) - return 1; - else if(n1->type == name_str && n2->type == name_ord) - return -1; - else - internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)", - n1->type, n2->type); - - return 0; /* Keep the compiler happy */ -} - /* ***************************************************************************** * Function : find_counter