- 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.
This commit is contained in:
Bertho Stultiens 2000-05-23 01:18:38 +00:00 committed by Alexandre Julliard
parent 6b4c347424
commit 997e0d782f
16 changed files with 1111 additions and 264 deletions

View File

@ -1,3 +1,28 @@
---------------------------------------------------------------------------
Version 1.1.3 (21-May-2000)
Bertho Stultiens <bertho@akhphd.au.dk>
- 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 <ps@leissner.se>
- Fixed byte order on Solaris and FreeBSD.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Version 1.1.2 (08-May-2000) Version 1.1.2 (08-May-2000)

View File

@ -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 See the file CHANGES for differences between the version and what has been
corrected in the current version. 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 specified. Both MS and Borland use the language of the system that the
compiler runs on. compiler runs on.
Not all resource-types can have local language keywords attached yet Language, version and characteristics can be bound to all resource types that
(notably: BITMAP, CURSOR, ICON and usertype). This is due to implementation have inline data, such as RCDATA. This is an extension to MS' resource
of filename-scanning and the complexity that it poses. This will be changed compiler, which lacks this support completely. Only VERSIONINFO cannot have
in the next release. You can work arround this problem by putting a LANGUAGE version and characteristics attached, but languages are propagated properly if
statement before (and evt. after) the code in the resource file. 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 Resource types supported
------------------------ ------------------------
All types are supported except for: All types are supported except for:
- FONT (RT_FONT, RT_FONTDIR)
- MESSAGETABLE (RT_MESSAGETABLE) - MESSAGETABLE (RT_MESSAGETABLE)
- Animated cursors/icons (RT_ANIICON, RT_ANICURSOR)
- RT_VXD - RT_VXD
- RT_PLUGPLAY - RT_PLUGPLAY
- RT_HTML
These types will be implemented as soon as I get a proper specification of These types will be implemented as soon as I get a proper specification of
the layout. 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 Expression capabilities and resource names
------------------------------------------ ------------------------------------------
@ -263,10 +277,12 @@ things that I noted in the above text (more lack of implementation than bug
though): though):
- No codepage translation - No codepage translation
- UNICODE translations are not/not correct implemented - 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 - grep for FIXME in the source
- Memory options are wrong under some conditions. There seems to be a - Memory options are wrong under some conditions. There seems to be a
different action for win32 and win16 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 Reporting bugs and patches
-------------------------- --------------------------

View File

@ -46,6 +46,8 @@ char *get_typename(resource_t* r)
case res_ver: return "VERSIONINFO"; case res_ver: return "VERSIONINFO";
case res_dlginit: return "DLGINIT"; case res_dlginit: return "DLGINIT";
case res_toolbar: return "TOOLBAR"; case res_toolbar: return "TOOLBAR";
case res_anicur: return "CURSOR (animated)";
case res_aniico: return "ICON (animated)";
default: return "Unknown"; 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); 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 * Function : dump_font
@ -377,6 +397,7 @@ static void dump_icon_group(icon_group_t *icog)
static void dump_font(font_t *fnt) static void dump_font(font_t *fnt)
{ {
dump_memopt(fnt->memopt); dump_memopt(fnt->memopt);
dump_lvc(&(fnt->data->lvc));
dump_raw_data(fnt->data); dump_raw_data(fnt->data);
} }
@ -394,6 +415,7 @@ static void dump_font(font_t *fnt)
static void dump_bitmap(bitmap_t *bmp) static void dump_bitmap(bitmap_t *bmp)
{ {
dump_memopt(bmp->memopt); dump_memopt(bmp->memopt);
dump_lvc(&(bmp->data->lvc));
dump_raw_data(bmp->data); dump_raw_data(bmp->data);
} }
@ -411,6 +433,7 @@ static void dump_bitmap(bitmap_t *bmp)
static void dump_rcdata(rcdata_t *rdt) static void dump_rcdata(rcdata_t *rdt)
{ {
dump_memopt(rdt->memopt); dump_memopt(rdt->memopt);
dump_lvc(&(rdt->data->lvc));
dump_raw_data(rdt->data); dump_raw_data(rdt->data);
} }
@ -428,6 +451,7 @@ static void dump_rcdata(rcdata_t *rdt)
static void dump_user(user_t *usr) static void dump_user(user_t *usr)
{ {
dump_memopt(usr->memopt); dump_memopt(usr->memopt);
dump_lvc(&(usr->data->lvc));
printf("Class %s\n", get_nameid_str(usr->type)); printf("Class %s\n", get_nameid_str(usr->type));
dump_raw_data(usr->data); dump_raw_data(usr->data);
} }
@ -445,6 +469,7 @@ static void dump_user(user_t *usr)
*/ */
static void dump_messagetable(messagetable_t *msg) static void dump_messagetable(messagetable_t *msg)
{ {
dump_lvc(&(msg->data->lvc));
dump_raw_data(msg->data); dump_raw_data(msg->data);
} }
@ -821,6 +846,8 @@ static void dump_versioninfo(versioninfo_t *ver)
{ {
ver_block_t *blk = ver->blocks; ver_block_t *blk = ver->blocks;
dump_lvc(&(ver->lvc));
if(ver->gotit.fv) if(ver->gotit.fv)
printf("FILEVERSION %04x, %04x, %04x, %04x\n", printf("FILEVERSION %04x, %04x, %04x, %04x\n",
ver->filever_maj1, ver->filever_maj1,
@ -907,7 +934,7 @@ static void dump_toolbar(toolbar_t *toolbar)
static void dump_dlginit(dlginit_t *dit) static void dump_dlginit(dlginit_t *dit)
{ {
dump_memopt(dit->memopt); dump_memopt(dit->memopt);
dump_lvc(&(dit->lvc)); dump_lvc(&(dit->data->lvc));
dump_raw_data(dit->data); dump_raw_data(dit->data);
} }
@ -997,6 +1024,10 @@ void dump_resources(resource_t *top)
case res_toolbar: case res_toolbar:
dump_toolbar(top->res.tbt); dump_toolbar(top->res.tbt);
break; break;
case res_anicur:
case res_aniico:
dump_ani_curico(top->res.ani);
break;
default: default:
printf("Report this: Unknown resource type parsed %08x\n", top->type); printf("Report this: Unknown resource type parsed %08x\n", top->type);
} }

View File

@ -14,5 +14,6 @@
char *get_typename(resource_t* r); char *get_typename(resource_t* r);
void dump_resources(resource_t *top); void dump_resources(resource_t *top);
char *get_nameid_str(name_id_t *n);
#endif #endif

View File

@ -1190,6 +1190,40 @@ static res_t *icon2res(icon_t *ico)
return res; 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 * Function : bitmap2res
@ -1200,7 +1234,7 @@ static res_t *icon2res(icon_t *ico)
* Output : New .res format structure * Output : New .res format structure
* Description : * Description :
* Remarks : The endian of the bitmap structures have been converted * 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) 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); assert(bmp != NULL);
res = new_res(); 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' if(bmp->data->data[0] == 'B'
&& bmp->data->data[1] == 'M' && bmp->data->data[1] == 'M'
&& ((BITMAPFILEHEADER *)bmp->data->data)->bfSize == bmp->data->size && ((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 * fnt - The font descriptor
* Output : New .res format structure * Output : New .res format structure
* Description : * Description :
* Remarks : * Remarks : The data has been prepared just after parsing.
***************************************************************************** *****************************************************************************
*/ */
static res_t *font2res(name_id_t *name, font_t *fnt) static res_t *font2res(name_id_t *name, font_t *fnt)
{ {
int restag;
res_t *res;
assert(name != NULL); assert(name != NULL);
assert(fnt != 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); assert(rdt != NULL);
res = new_res(); 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); put_raw_data(res, rdt->data, 0);
/* Set ResourceSize */ /* Set ResourceSize */
SetResSize(res, restag); SetResSize(res, restag);
@ -1379,7 +1451,7 @@ static res_t *user2res(name_id_t *name, user_t *usr)
assert(usr != NULL); assert(usr != NULL);
res = new_res(); 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); put_raw_data(res, usr->data, 0);
/* Set ResourceSize */ /* Set ResourceSize */
SetResSize(res, restag); SetResSize(res, restag);
@ -1504,7 +1576,7 @@ static res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver)
vsvi.size = 15; /* Excl. termination */ vsvi.size = 15; /* Excl. termination */
res = new_res(); 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; rootblocksizetag = res->size;
put_word(res, 0); /* BlockSize filled in later */ put_word(res, 0); /* BlockSize filled in later */
valsizetag = res->size; valsizetag = res->size;
@ -1629,7 +1701,7 @@ static res_t *dlginit2res(name_id_t *name, dlginit_t *dit)
assert(dit != NULL); assert(dit != NULL);
res = new_res(); 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); put_raw_data(res, dit->data, 0);
/* Set ResourceSize */ /* Set ResourceSize */
SetResSize(res, restag); SetResSize(res, restag);
@ -1746,12 +1818,15 @@ char *get_c_typename(enum res_e type)
switch(type) switch(type)
{ {
case res_acc: return "Acc"; case res_acc: return "Acc";
case res_anicur:return "AniCur";
case res_aniico:return "AniIco";
case res_bmp: return "Bmp"; case res_bmp: return "Bmp";
case res_cur: return "Cur"; case res_cur: return "Cur";
case res_curg: return "CurGrp"; case res_curg: return "CurGrp";
case res_dlg: case res_dlg:
case res_dlgex: return "Dlg"; case res_dlgex: return "Dlg";
case res_fnt: return "Fnt"; case res_fnt: return "Fnt";
case res_fntdir:return "FntDir";
case res_ico: return "Ico"; case res_ico: return "Ico";
case res_icog: return "IcoGrp"; case res_icog: return "IcoGrp";
case res_men: case res_men:
@ -1812,6 +1887,10 @@ void resources2res(resource_t *top)
if(!top->binres) if(!top->binres)
top->binres = font2res(top->name, top->res.fnt); top->binres = font2res(top->name, top->res.fnt);
break; break;
case res_fntdir:
if(!top->binres)
top->binres = fontdir2res(top->name, top->res.fnd);
break;
case res_ico: case res_ico:
if(!top->binres) if(!top->binres)
top->binres = icon2res(top->res.ico); top->binres = icon2res(top->res.ico);
@ -1856,7 +1935,11 @@ void resources2res(resource_t *top)
if(!top->binres) if(!top->binres)
top->binres = dlginit2res(top->name, top->res.dlgi); top->binres = dlginit2res(top->name, top->res.dlgi);
break; break;
case res_anicur:
case res_aniico:
if(!top->binres)
top->binres = anicurico2res(top->name, top->res.ani, top->type);
break;
default: default:
internal_error(__FILE__, __LINE__, "Unknown resource type encountered %d in binary res generation", top->type); internal_error(__FILE__, __LINE__, "Unknown resource type encountered %d in binary res generation", top->type);
} }

View File

@ -12,6 +12,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <ctype.h>
#include "wrc.h" #include "wrc.h"
#include "newstruc.h" #include "newstruc.h"
@ -42,6 +43,7 @@ __NEW_STRUCT_FUNC(lvc)
__NEW_STRUCT_FUNC(res_count) __NEW_STRUCT_FUNC(res_count)
__NEW_STRUCT_FUNC(string) __NEW_STRUCT_FUNC(string)
__NEW_STRUCT_FUNC(toolbar_item) __NEW_STRUCT_FUNC(toolbar_item)
__NEW_STRUCT_FUNC(ani_any)
/* New instances for all types of structures */ /* New instances for all types of structures */
/* Very inefficient (in size), but very functional :-] /* Very inefficient (in size), but very functional :-]
@ -146,10 +148,24 @@ font_t *new_font(raw_data_t *rd, int *memopt)
free(memopt); free(memopt);
} }
else else
fnt->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE; fnt->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE;
return fnt; 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 * 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; icon_header_t *ih = (icon_header_t *)rd->data;
int swap = 0; int swap = 0;
/* FIXME: Distinguish between normal and animated icons (RIFF format) */
if(ih->type == 1) if(ih->type == 1)
swap = 0; swap = 0;
else if(BYTESWAP_WORD(ih->type) == 1) 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 = new_icon();
ico->id = alloc_icon_id(icog->lvc.language); ico->id = alloc_icon_id(icog->lvc.language);
ico->lvc.language = dup_language(icog->lvc.language); ico->lvc = icog->lvc;
if(swap) if(swap)
{ {
ide[i].offset = BYTESWAP_DWORD(ide[i].offset); 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; cursor_header_t *ch = (cursor_header_t *)rd->data;
int swap = 0; int swap = 0;
/* FIXME: Distinguish between normal and animated cursors (RIFF format)*/
if(ch->type == 2) if(ch->type == 2)
swap = 0; swap = 0;
else if(BYTESWAP_WORD(ch->type) == 2) 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; WORD bits;
cur = new_cursor(); cur = new_cursor();
cur->id = alloc_cursor_id(curg->lvc.language); cur->id = alloc_cursor_id(curg->lvc.language);
cur->lvc.language = dup_language(curg->lvc.language); cur->lvc = curg->lvc;
if(swap) if(swap)
{ {
cde[i].offset = BYTESWAP_DWORD(cde[i].offset); 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 else
icog->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE; 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)); split_icons(rd, icog, &(icog->nicon));
free(rd->data); free(rd->data);
free(rd); free(rd);
@ -553,13 +567,309 @@ cursor_group_t *new_cursor_group(raw_data_t *rd, int *memopt)
} }
else else
curg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE; 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)); split_cursors(rd, curg, &(curg->ncursor));
free(rd->data); free(rd->data);
free(rd); free(rd);
return curg; 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 *new_bitmap(raw_data_t *rd, int *memopt)
{ {
bitmap_t *bmp = (bitmap_t *)xmalloc(sizeof(bitmap_t)); bitmap_t *bmp = (bitmap_t *)xmalloc(sizeof(bitmap_t));

View File

@ -41,6 +41,7 @@ __NEW_STRUCT_PROTO(lvc);
__NEW_STRUCT_PROTO(res_count); __NEW_STRUCT_PROTO(res_count);
__NEW_STRUCT_PROTO(string); __NEW_STRUCT_PROTO(string);
__NEW_STRUCT_PROTO(toolbar_item); __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); resource_t *new_resource(enum res_e t, void *res, int memopt, language_t *lan);
version_t *new_version(DWORD v); 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); 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); user_t *new_user(name_id_t *type, raw_data_t *rd, int *memopt);
font_t *new_font(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); icon_group_t *new_icon_group(raw_data_t *rd, int *memopt);
cursor_group_t *new_cursor_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); bitmap_t *new_bitmap(raw_data_t *rd, int *memopt);
ver_words_t *new_ver_words(int i); ver_words_t *new_ver_words(int i);
ver_words_t *add_ver_words(ver_words_t *w, int i); ver_words_t *add_ver_words(ver_words_t *w, int i);

View File

@ -10,6 +10,7 @@
/* From parser.y */ /* From parser.y */
extern int yydebug; extern int yydebug;
extern int want_nl; /* Set when getting line-numers */ extern int want_nl; /* Set when getting line-numers */
extern int want_id; /* Set when getting the resource name */
int yyparse(void); int yyparse(void);

View File

@ -2,6 +2,8 @@
* *
* Copyright 1998-2000 Bertho A. Stultiens (BS) * 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 * 30-Apr-2000 BS - Reintegration into the wine-tree
* 11-Jan-2000 BS - Very drastic cleanup because we don't have a * 11-Jan-2000 BS - Very drastic cleanup because we don't have a
* preprocessor in here anymore. * preprocessor in here anymore.
@ -96,7 +98,7 @@ cident [a-zA-Z_][0-9a-zA-Z_]*
#define YY_NO_TOP_STATE #define YY_NO_TOP_STATE
/* Always update the current character position within a line */ /* 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 addcchar(char c);
static void addwchar(short s); 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 stripplevel = 0; /* Count () during pp_strips mode */
static int cjunk_tagline; /* Where did we start stripping (helps error tracking) */ 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 { struct keyword {
char *keyword; char *keyword;
int token; int token;
int isextension; int isextension;
int needcase; int needcase;
int alwayskw;
}; };
static struct keyword keywords[] = { static struct keyword keywords[] = {
{ "ACCELERATORS", tACCELERATORS, 0, 0}, { "ACCELERATORS", tACCELERATORS, 0, 0, 0},
{ "ALT", tALT, 0, 0}, { "ALT", tALT, 0, 0, 0},
{ "ASCII", tASCII, 0, 0}, { "ASCII", tASCII, 0, 0, 0},
{ "AUTO3STATE", tAUTO3STATE, 1, 0}, { "AUTO3STATE", tAUTO3STATE, 1, 0, 0},
{ "AUTOCHECKBOX", tAUTOCHECKBOX, 1, 0}, { "AUTOCHECKBOX", tAUTOCHECKBOX, 1, 0, 0},
{ "AUTORADIOBUTTON", tAUTORADIOBUTTON, 1, 0}, { "AUTORADIOBUTTON", tAUTORADIOBUTTON, 1, 0, 0},
{ "BEGIN", tBEGIN, 0, 0}, { "BEGIN", tBEGIN, 0, 0, 0},
{ "BITMAP", tBITMAP, 0, 0}, { "BITMAP", tBITMAP, 0, 0, 0},
{ "BLOCK", tBLOCK, 0, 0}, { "BLOCK", tBLOCK, 0, 0, 0},
{ "BUTTON", tBUTTON, 1, 0}, { "BUTTON", tBUTTON, 1, 0, 0},
{ "CAPTION", tCAPTION, 0, 0}, { "CAPTION", tCAPTION, 0, 0, 0},
{ "CHARACTERISTICS", tCHARACTERISTICS, 1, 0}, { "CHARACTERISTICS", tCHARACTERISTICS, 1, 0, 0},
{ "CHECKBOX", tCHECKBOX, 0, 0}, { "CHECKBOX", tCHECKBOX, 0, 0, 0},
{ "CHECKED", tCHECKED, 0, 0}, { "CHECKED", tCHECKED, 0, 0, 0},
{ "CLASS", tCLASS, 0, 0}, { "CLASS", tCLASS, 0, 0, 0},
{ "COMBOBOX", tCOMBOBOX, 0, 0}, { "COMBOBOX", tCOMBOBOX, 0, 0, 0},
{ "CONTROL", tCONTROL, 0, 0}, { "CONTROL", tCONTROL, 0, 0, 0},
{ "CTEXT", tCTEXT, 0, 0}, { "CTEXT", tCTEXT, 0, 0, 0},
{ "CURSOR", tCURSOR, 0, 0}, { "CURSOR", tCURSOR, 0, 0, 0},
{ "DEFPUSHBUTTON", tDEFPUSHBUTTON, 0, 0}, { "DEFPUSHBUTTON", tDEFPUSHBUTTON, 0, 0, 0},
{ "DIALOG", tDIALOG, 0, 0}, { "DIALOG", tDIALOG, 0, 0, 0},
{ "DIALOGEX", tDIALOGEX, 1, 0}, { "DIALOGEX", tDIALOGEX, 1, 0, 0},
{ "DISCARDABLE", tDISCARDABLE, 0, 0}, { "DISCARDABLE", tDISCARDABLE, 0, 0, 0},
{ "DLGINIT", tDLGINIT, 0, 0}, { "DLGINIT", tDLGINIT, 0, 0, 0},
{ "EDITTEXT", tEDITTEXT, 0, 0}, { "EDITTEXT", tEDITTEXT, 0, 0, 0},
{ "END", tEND, 0, 0}, { "END", tEND, 0, 0, 0},
{ "enum", tENUM, 0, 1}, { "enum", tENUM, 0, 1, 1},
{ "EXSTYLE", tEXSTYLE, 0, 0}, { "EXSTYLE", tEXSTYLE, 0, 0, 0},
{ "extern", tEXTERN, 0, 1}, { "extern", tEXTERN, 0, 1, 1},
{ "FILEFLAGS", tFILEFLAGS, 0, 0}, { "FILEFLAGS", tFILEFLAGS, 0, 0, 0},
{ "FILEFLAGSMASK", tFILEFLAGSMASK, 0, 0}, { "FILEFLAGSMASK", tFILEFLAGSMASK, 0, 0, 0},
{ "FILEOS", tFILEOS, 0, 0}, { "FILEOS", tFILEOS, 0, 0, 0},
{ "FILESUBTYPE", tFILESUBTYPE, 0, 0}, { "FILESUBTYPE", tFILESUBTYPE, 0, 0, 0},
{ "FILETYPE", tFILETYPE, 0, 0}, { "FILETYPE", tFILETYPE, 0, 0, 0},
{ "FILEVERSION", tFILEVERSION, 0, 0}, { "FILEVERSION", tFILEVERSION, 0, 0, 0},
{ "FIXED", tFIXED, 0, 0}, { "FIXED", tFIXED, 0, 0, 0},
{ "FONT", tFONT, 0, 0}, { "FONT", tFONT, 0, 0, 0},
{ "GRAYED", tGRAYED, 0, 0}, { "FONTDIR", tFONTDIR, 0, 0, 0}, /* This is a Borland BRC extension */
{ "GROUPBOX", tGROUPBOX, 0, 0}, { "GRAYED", tGRAYED, 0, 0, 0},
{ "HELP", tHELP, 0, 0}, { "GROUPBOX", tGROUPBOX, 0, 0, 0},
{ "ICON", tICON, 0, 0}, { "HELP", tHELP, 0, 0, 0},
{ "IMPURE", tIMPURE, 0, 0}, { "ICON", tICON, 0, 0, 0},
{ "INACTIVE", tINACTIVE, 0, 0}, { "IMPURE", tIMPURE, 0, 0, 0},
{ "inline", tINLINE, 0, 1}, { "INACTIVE", tINACTIVE, 0, 0, 0},
{ "LANGUAGE", tLANGUAGE, 1, 0}, { "inline", tINLINE, 0, 1, 1},
{ "LISTBOX", tLISTBOX, 0, 0}, { "LANGUAGE", tLANGUAGE, 1, 0, 1},
{ "LOADONCALL", tLOADONCALL, 0, 0}, { "LISTBOX", tLISTBOX, 0, 0, 0},
{ "LTEXT", tLTEXT, 0, 0}, { "LOADONCALL", tLOADONCALL, 0, 0, 0},
{ "MENU", tMENU, 0, 0}, { "LTEXT", tLTEXT, 0, 0, 0},
{ "MENUBARBREAK", tMENUBARBREAK, 0, 0}, { "MENU", tMENU, 0, 0, 0},
{ "MENUBREAK", tMENUBREAK, 0, 0}, { "MENUBARBREAK", tMENUBARBREAK, 0, 0, 0},
{ "MENUEX", tMENUEX, 1, 0}, { "MENUBREAK", tMENUBREAK, 0, 0, 0},
{ "MENUITEM", tMENUITEM, 0, 0}, { "MENUEX", tMENUEX, 1, 0, 0},
{ "MESSAGETABLE", tMESSAGETABLE, 1, 0}, { "MENUITEM", tMENUITEM, 0, 0, 0},
{ "MOVEABLE", tMOVEABLE, 0, 0}, { "MESSAGETABLE", tMESSAGETABLE, 1, 0, 0},
{ "NOINVERT", tNOINVERT, 0, 0}, { "MOVEABLE", tMOVEABLE, 0, 0, 0},
{ "NOT", tNOT, 0, 0}, { "NOINVERT", tNOINVERT, 0, 0, 0},
{ "POPUP", tPOPUP, 0, 0}, { "NOT", tNOT, 0, 0, 0},
{ "PRELOAD", tPRELOAD, 0, 0}, { "POPUP", tPOPUP, 0, 0, 0},
{ "PRODUCTVERSION", tPRODUCTVERSION, 0, 0}, { "PRELOAD", tPRELOAD, 0, 0, 0},
{ "PURE", tPURE, 0, 0}, { "PRODUCTVERSION", tPRODUCTVERSION, 0, 0, 0},
{ "PUSHBUTTON", tPUSHBUTTON, 0, 0}, { "PURE", tPURE, 0, 0, 0},
{ "RADIOBUTTON", tRADIOBUTTON, 0, 0}, { "PUSHBUTTON", tPUSHBUTTON, 0, 0, 0},
{ "RCDATA", tRCDATA, 0, 0}, { "RADIOBUTTON", tRADIOBUTTON, 0, 0, 0},
{ "RTEXT", tRTEXT, 0, 0}, { "RCDATA", tRCDATA, 0, 0, 0},
{ "SCROLLBAR", tSCROLLBAR, 0, 0}, { "RTEXT", tRTEXT, 0, 0, 0},
{ "SEPARATOR", tSEPARATOR, 0, 0}, { "SCROLLBAR", tSCROLLBAR, 0, 0, 0},
{ "SHIFT", tSHIFT, 0, 0}, { "SEPARATOR", tSEPARATOR, 0, 0, 0},
{ "STATE3", tSTATE3, 1, 0}, { "SHIFT", tSHIFT, 0, 0, 0},
{ "static", tSTATIC, 0, 1}, { "STATE3", tSTATE3, 1, 0, 0},
{ "STRING", tSTRING, 0, 0}, { "static", tSTATIC, 0, 1, 1},
{ "STRINGTABLE", tSTRINGTABLE, 0, 0}, { "STRING", tSTRING, 0, 0, 0},
{ "struct", tSTRUCT, 0, 1}, { "STRINGTABLE", tSTRINGTABLE, 0, 0, 1},
{ "STYLE", tSTYLE, 0, 0}, { "struct", tSTRUCT, 0, 1, 1},
{ "TOOLBAR", tTOOLBAR, 1, 0}, { "STYLE", tSTYLE, 0, 0, 0},
{ "typedef", tTYPEDEF, 0, 1}, { "TOOLBAR", tTOOLBAR, 1, 0, 0},
{ "VALUE", tVALUE, 0, 0}, { "typedef", tTYPEDEF, 0, 1, 1},
{ "VERSION", tVERSION, 1, 0}, { "VALUE", tVALUE, 0, 0, 0},
{ "VERSIONINFO", tVERSIONINFO, 0, 0}, { "VERSION", tVERSION, 1, 0, 0},
{ "VIRTKEY", tVIRTKEY, 0, 0} { "VERSIONINFO", tVERSIONINFO, 0, 0, 0},
{ "VIRTKEY", tVIRTKEY, 0, 0, 0}
}; };
#define NKEYWORDS (sizeof(keywords)/sizeof(keywords[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")) if(tok->token == tCLASS && !strcmp(yytext, "class"))
return tCPPCLASS; return tCPPCLASS;
else if(wanted_id && !tok->alwayskw)
{
yylval.str = make_string(yytext);
return tIDENT;
}
else else
return tok->token; return tok->token;
} }
@ -446,17 +474,21 @@ L\" {
* Should never occur after preprocessing * Should never occur after preprocessing
*/ */
<INITIAL,pp_stripp,pp_strips>"/*" { <INITIAL,pp_stripp,pp_strips>"/*" {
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");
} }
<comment>[^*\n]* ; <comment>[^*\n]* ;
<comment>"*"+[^*/\n]* ; <comment>"*"+[^*/\n]* ;
<comment>\n line_number++; char_number = 1; <comment>\n line_number++; char_number = 1;
<comment>"*"+"/" yy_pop_state(); <comment>"*"+"/" yy_pop_state(); want_id = save_wanted_id;
;[^\n]* ; /* not really comment, but left-over c-junk */ ;[^\n]* want_id = wanted_id; /* not really comment, but left-over c-junk */
"//"[^\n]* if(!no_preprocess) yywarning("Found comments after preprocessing, please report"); "//"[^\n]* want_id = wanted_id; if(!no_preprocess) yywarning("Found comments after preprocessing, please report");
\n { \n {
want_id = wanted_id;
line_number++; line_number++;
char_number = 1; char_number = 1;
if(want_nl) if(want_nl)
@ -465,7 +497,7 @@ L\" {
return tNL; return tNL;
} }
} }
{ws}+ ; /* Eat whitespace */ {ws}+ want_id = wanted_id; /* Eat whitespace */
<INITIAL>. return yytext[0]; <INITIAL>. return yytext[0];

View File

@ -4,6 +4,15 @@
* Copyright 1998-2000 Bertho A. Stultiens (BS) * Copyright 1998-2000 Bertho A. Stultiens (BS)
* 1999 Juergen Schmied (JS) * 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 * 30-Apr-2000 BS - Reintegration into the wine-tree
* 14-Jan-2000 BS - Redid the usertype resources so that they * 14-Jan-2000 BS - Redid the usertype resources so that they
* are compatible. * are compatible.
@ -117,6 +126,7 @@
#include "winuser.h" #include "winuser.h"
int want_nl = 0; /* Signal flex that we need the next newline */ 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. stringtable_t *tagstt; /* Stringtable tag.
* It is set while parsing a stringtable to one of * It is set while parsing a stringtable to one of
* the stringtables in the sttres list or a new one * the stringtables in the sttres list or a new one
@ -130,6 +140,8 @@ static int *tagstt_memopt;
static characts_t *tagstt_characts; static characts_t *tagstt_characts;
static version_t *tagstt_version; static version_t *tagstt_version;
static const char riff[4] = "RIFF"; /* RIFF file magic for animated cursor/icon */
/* Prototypes of here defined functions */ /* Prototypes of here defined functions */
static event_t *get_event_head(event_t *p); static event_t *get_event_head(event_t *p);
static control_t *get_control_head(control_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 *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 toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems);
static string_t *make_filename(string_t *s); 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{ %union{
@ -184,13 +198,10 @@ static string_t *make_filename(string_t *s);
resource_t *res; resource_t *res;
accelerator_t *acc; accelerator_t *acc;
bitmap_t *bmp; bitmap_t *bmp;
cursor_t *cur;
cursor_group_t *curg;
dialog_t *dlg; dialog_t *dlg;
dialogex_t *dlgex; dialogex_t *dlgex;
font_t *fnt; font_t *fnt;
icon_t *ico; fontdir_t *fnd;
icon_group_t *icog;
menu_t *men; menu_t *men;
menuex_t *menex; menuex_t *menex;
rcdata_t *rdt; rcdata_t *rdt;
@ -219,6 +230,7 @@ static string_t *make_filename(string_t *s);
dlginit_t *dginit; dlginit_t *dginit;
style_pair_t *styles; style_pair_t *styles;
style_t *style; style_t *style;
ani_any_t *ani;
} }
%token tTYPEDEF tEXTERN tSTRUCT tENUM tCPPCLASS tINLINE tSTATIC tNL %token tTYPEDEF tEXTERN tSTRUCT tENUM tCPPCLASS tINLINE tSTATIC tNL
@ -226,7 +238,7 @@ static string_t *make_filename(string_t *s);
%token <str> tSTRING tIDENT tFILENAME %token <str> tSTRING tIDENT tFILENAME
%token <raw> tRAWDATA %token <raw> tRAWDATA
%token tACCELERATORS tBITMAP tCURSOR tDIALOG tDIALOGEX tMENU tMENUEX tMESSAGETABLE %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 tAUTO3STATE tAUTOCHECKBOX tAUTORADIOBUTTON tCHECKBOX tDEFPUSHBUTTON
%token tPUSHBUTTON tRADIOBUTTON tSTATE3 /* PUSHBOX */ %token tPUSHBUTTON tRADIOBUTTON tSTATE3 /* PUSHBOX */
%token tGROUPBOX tCOMBOBOX tLISTBOX tSCROLLBAR %token tGROUPBOX tCOMBOBOX tLISTBOX tSCROLLBAR
@ -254,18 +266,18 @@ static string_t *make_filename(string_t *s);
%type <res> resource_file resource resources resource_definition %type <res> resource_file resource resources resource_definition
%type <stt> stringtable strings %type <stt> stringtable strings
%type <fnt> font %type <fnt> font
%type <icog> icon %type <fnd> fontdir
%type <acc> accelerators %type <acc> accelerators
%type <event> events %type <event> events
%type <bmp> bitmap %type <bmp> bitmap
%type <curg> cursor %type <ani> cursor icon
%type <dlg> dialog dlg_attributes %type <dlg> dialog dlg_attributes
%type <ctl> ctrls gen_ctrl lab_ctrl ctrl_desc iconinfo %type <ctl> ctrls gen_ctrl lab_ctrl ctrl_desc iconinfo
%type <iptr> helpid %type <iptr> helpid
%type <dlgex> dialogex dlgex_attribs %type <dlgex> dialogex dlgex_attribs
%type <ctl> exctrls gen_exctrl lab_exctrl exctrl_desc %type <ctl> exctrls gen_exctrl lab_exctrl exctrl_desc
%type <rdt> rcdata %type <rdt> rcdata
%type <raw> raw_data raw_elements opt_data %type <raw> raw_data raw_elements opt_data file_raw
%type <veri> versioninfo fix_version %type <veri> versioninfo fix_version
%type <verw> ver_words %type <verw> ver_words
%type <blk> ver_blocks ver_block %type <blk> ver_blocks ver_block
@ -311,6 +323,20 @@ resource_file
if(rsc) if(rsc)
rsc->prev = $1; 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 else
$1 = rsc; $1 = rsc;
/* Final statement before were done */ /* Final statement before were done */
@ -320,7 +346,7 @@ resource_file
/* Resources are put into a linked list */ /* Resources are put into a linked list */
resources resources
: /* Empty */ { $$ = NULL; } : /* Empty */ { $$ = NULL; want_id = 1; }
| resources resource { | resources resource {
if($2) if($2)
{ {
@ -334,6 +360,23 @@ resources
if($1) if($1)
$1->next = head; $1->next = head;
$$ = tail; $$ = 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) else if($1)
{ {
@ -344,9 +387,10 @@ resources
} }
else else
$$ = NULL; $$ = NULL;
want_id = 1;
} }
| resources preprocessor { $$ = $1; } | resources preprocessor { $$ = $1; want_id = 1; }
| resources cjunk { $$ = $1; } | resources cjunk { $$ = $1; want_id = 1; }
; ;
/* /*
@ -416,12 +460,16 @@ resource
$$ = NULL; $$ = NULL;
chat("Got STRINGTABLE"); 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) if(!win32)
yywarning("LANGUAGE not supported in 16-bit mode"); yywarning("LANGUAGE not supported in 16-bit mode");
if(currentlanguage) if(currentlanguage)
free(currentlanguage); free(currentlanguage);
currentlanguage = $1; currentlanguage = new_language($3, $5);
$$ = NULL; $$ = NULL;
} }
; ;
@ -457,20 +505,30 @@ nameid_s: nameid { $$ = $1; }
/* get the value for a single resource*/ /* get the value for a single resource*/
resource_definition resource_definition
: accelerators { $$ = new_resource(res_acc, $1, $1->memopt, $1->lvc.language); } : 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 { | cursor {
resource_t *rsc; resource_t *rsc;
cursor_t *cur; if($1->type == res_anicur)
$$ = rsc = new_resource(res_curg, $1, $1->memopt, dup_language(currentlanguage));
for(cur = $1->cursorlist; cur; cur = cur->next)
{ {
rsc->prev = new_resource(res_cur, cur, $1->memopt, dup_language(currentlanguage)); $$ = rsc = new_resource(res_anicur, $1->u.ani, $1->u.ani->memopt, $1->u.ani->data->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 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); } | dialog { $$ = new_resource(res_dlg, $1, $1->memopt, $1->lvc.language); }
| dialogex { | dialogex {
@ -479,21 +537,32 @@ resource_definition
else else
$$ = NULL; $$ = NULL;
} }
| dlginit { $$ = new_resource(res_dlginit, $1, $1->memopt, $1->lvc.language); } | dlginit { $$ = new_resource(res_dlginit, $1, $1->memopt, $1->data->lvc.language); }
| font { $$ = new_resource(res_fnt, $1, $1->memopt, dup_language(currentlanguage)); } | 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 { | icon {
resource_t *rsc; resource_t *rsc;
icon_t *ico; if($1->type == res_aniico)
$$ = rsc = new_resource(res_icog, $1, $1->memopt, dup_language(currentlanguage));
for(ico = $1->iconlist; ico; ico = ico->next)
{ {
rsc->prev = new_resource(res_ico, ico, $1->memopt, dup_language(currentlanguage)); $$ = rsc = new_resource(res_aniico, $1->u.ani, $1->u.ani->memopt, $1->u.ani->data->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 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); } | menu { $$ = new_resource(res_men, $1, $1->memopt, $1->lvc.language); }
| menuex { | menuex {
@ -503,10 +572,10 @@ resource_definition
$$ = NULL; $$ = NULL;
} }
| messagetable { $$ = new_resource(res_msg, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, dup_language(currentlanguage)); } | 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); } | toolbar { $$ = new_resource(res_toolbar, $1, $1->memopt, $1->lvc.language); }
| userres { $$ = new_resource(res_usr, $1, $1->memopt, 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, dup_language(currentlanguage)); } | 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 ------------------------------ */
bitmap : tBITMAP loadmemopts filename { $$ = new_bitmap(load_file($3), $2); } bitmap : tBITMAP loadmemopts file_raw { $$ = new_bitmap($3, $2); }
| tBITMAP loadmemopts raw_data { $$ = new_bitmap($3, $2); }
; ;
/* ------------------------------ Cursor ------------------------------ */ /* ------------------------------ Cursor ------------------------------ */
cursor : tCURSOR loadmemopts filename { $$ = new_cursor_group(load_file($3), $2); } cursor : tCURSOR loadmemopts file_raw {
| tCURSOR loadmemopts raw_data { $$ = new_cursor_group($3, $2); } $$ = new_ani_any();
; if($3->size > 4 && !memcmp($3->data, riff, sizeof(riff)))
{
/* ------------------------------ Font ------------------------------ */ $$->type = res_anicur;
/* FIXME: Should we allow raw_data here? */ $$->u.ani = new_ani_curico(res_anicur, $3, $2);
font : tFONT loadmemopts filename { $$ = new_font(load_file($3), $2); } }
else
{
$$->type = res_curg;
$$->u.curg = new_cursor_group($3, $2);
}
}
; ;
/* ------------------------------ Icon ------------------------------ */ /* ------------------------------ Icon ------------------------------ */
icon : tICON loadmemopts filename { $$ = new_icon_group(load_file($3), $2); } icon : tICON loadmemopts file_raw {
| tICON loadmemopts raw_data { $$ = new_icon_group($3, $2); } $$ = 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 ------------------------------ */ /* ------------------------------ MessageTable ------------------------------ */
@ -548,34 +653,15 @@ messagetable
; ;
/* ------------------------------ RCData ------------------------------ */ /* ------------------------------ RCData ------------------------------ */
rcdata : tRCDATA loadmemopts opt_lvc raw_data { rcdata : tRCDATA loadmemopts raw_data { $$ = new_rcdata($3, $2); }
$$ = new_rcdata($4, $2);
if($3)
{
$$->lvc = *($3);
free($3);
}
if(!$$->lvc.language)
$$->lvc.language = dup_language(currentlanguage);
}
; ;
/* ------------------------------ DLGINIT ------------------------------ */ /* ------------------------------ DLGINIT ------------------------------ */
dlginit : tDLGINIT loadmemopts opt_lvc raw_data { dlginit : tDLGINIT loadmemopts raw_data { $$ = new_dlginit($3, $2); }
$$ = new_dlginit($4, $2);
if($3)
{
$$->lvc = *($3);
free($3);
}
if(!$$->lvc.language)
$$->lvc.language = dup_language(currentlanguage);
}
; ;
/* ------------------------------ UserType ------------------------------ */ /* ------------------------------ UserType ------------------------------ */
userres : usertype loadmemopts filename { $$ = new_user($1, load_file($3), $2); } userres : usertype loadmemopts file_raw { $$ = new_user($1, $3, $2); }
| usertype loadmemopts raw_data { $$ = new_user($1, $3, $2); }
; ;
usertype: tNUMBER { usertype: tNUMBER {
@ -1346,9 +1432,18 @@ opt_comma /* There seem to be two ways to specify a stringtable... */
/* ------------------------------ VersionInfo ------------------------------ */ /* ------------------------------ VersionInfo ------------------------------ */
versioninfo versioninfo
: tVERSIONINFO fix_version tBEGIN ver_blocks tEND { : tVERSIONINFO loadmemopts fix_version tBEGIN ver_blocks tEND {
$$ = $2; $$ = $3;
$2->blocks = get_ver_block_head($4); 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); } : tVERSION expr { $$ = new_version($2); }
; ;
/* ------------------------------ Raw data handking ------------------------------ */ /* ------------------------------ Raw data handling ------------------------------ */
raw_data: tBEGIN raw_elements tEND { $$ = $2; } 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 raw_elements
@ -1605,6 +1711,14 @@ raw_elements
| raw_elements opt_comma tSTRING { $$ = merge_raw_data_str($1, $3); } | 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 ------------------------------ */ /* ------------------------------ Win32 expressions ------------------------------ */
/* All win16 numbers are also handled here. This is inconsistent with MS' /* All win16 numbers are also handled here. This is inconsistent with MS'
* resource compiler, but what the heck, its just handy to have. * 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; 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;
}

View File

@ -276,3 +276,47 @@ char *dupwstr2cstr(const short *str)
return cs; 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 */
}

View File

@ -34,5 +34,6 @@ short *wstrcpy(short *dst, const short *src);
int wstricmp(const short *s1, const short *s2); int wstricmp(const short *s1, const short *s2);
char *dupwstr2cstr(const short *str); char *dupwstr2cstr(const short *str);
short *dupcstr2wstr(const char *str); short *dupcstr2wstr(const char *str);
int compare_name_id(name_id_t *n1, name_id_t *n2);
#endif #endif

View File

@ -16,8 +16,8 @@
#define WRC_MAJOR_VERSION 1 #define WRC_MAJOR_VERSION 1
#define WRC_MINOR_VERSION 1 #define WRC_MINOR_VERSION 1
#define WRC_MICRO_VERSION 2 #define WRC_MICRO_VERSION 3
#define WRC_RELEASEDATE "(08-May-2000)" #define WRC_RELEASEDATE "(21-May-2000)"
#define WRC_STRINGIZE(a) #a #define WRC_STRINGIZE(a) #a
#define WRC_VERSIONIZE(a,b,c) WRC_STRINGIZE(a) "." WRC_STRINGIZE(b) "." WRC_STRINGIZE(c) #define WRC_VERSIONIZE(a,b,c) WRC_STRINGIZE(a) "." WRC_STRINGIZE(b) "." WRC_STRINGIZE(c)

View File

@ -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 .SH NAME
wrc \- Wine Resource Compiler wrc \- Wine Resource Compiler
.SH SYNOPSIS .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. den Haan. Bugfixes have been contributed by many wine developpers.
.SH BUGS .SH BUGS
\- The preprocessor recognizes variable argument macros, but does not \- The preprocessor recognizes variable argument macros, but does not
expanded them correctly. expanded them correctly
.br .br
\- Codepage/UNICODE translations are not/not correct implemented. \- Codepage/UNICODE translations are not/not correct implemented
.br .br
\- Default memory options should differ between win16 and win32. \- Default memory options should differ between win16 and win32.
.PP .PP
\- There is no support for: There is no support for:
.br .br
\- MESSAGETABLE (parsed, but not generated). \- MESSAGETABLE (parsed, but not generated)
.br .br
\- FONT (parsed, but not generated). \- RT_VXD, RT_PLUGPLAY and RT_HTML (unknown format)
.br .br
\- RT_VXD and RT_PLUGPLAY (unknown format) \- PUSHBOX control is unsupported due to lack of original functionality.
.br .PP
\- Animated cursors and icons (RIFF format unknown). 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 .SH AVAILABILITY
.B wrc .B wrc
is part of the wine distribution, which is available through is part of the wine distribution, which is available through

View File

@ -44,6 +44,7 @@
#define WRC_RT_VXD (20) #define WRC_RT_VXD (20)
#define WRC_RT_ANICURSOR (21) #define WRC_RT_ANICURSOR (21)
#define WRC_RT_ANIICON (22) #define WRC_RT_ANIICON (22)
#define WRC_RT_HTML (23)
#define WRC_RT_DLGINIT (240) #define WRC_RT_DLGINIT (240)
#define WRC_RT_TOOLBAR (241) #define WRC_RT_TOOLBAR (241)
@ -160,8 +161,9 @@ enum res_e {
res_18, res_18,
res_pnp, /* Not implemented, no layout available */ res_pnp, /* Not implemented, no layout available */
res_vxd, /* Not implemented, no layout available */ res_vxd, /* Not implemented, no layout available */
res_anicur, /* Not implemented, no layout available */ res_anicur,
res_aniico, /* Not implemented, no layout available */ res_aniico,
res_html, /* Not implemented, no layout available */
res_dlginit = WRC_RT_DLGINIT, /* 240 */ res_dlginit = WRC_RT_DLGINIT, /* 240 */
res_toolbar = WRC_RT_TOOLBAR, /* 241 */ res_toolbar = WRC_RT_TOOLBAR, /* 241 */
@ -175,6 +177,7 @@ enum res_e {
typedef struct raw_data { typedef struct raw_data {
int size; int size;
char *data; char *data;
lvc_t lvc; /* Localized data */
} raw_data_t; } raw_data_t;
/* Dialog structures */ /* Dialog structures */
@ -286,12 +289,19 @@ typedef struct itemex_opt
int gothelpid; int gothelpid;
} itemex_opt_t; } itemex_opt_t;
/* RC structures for types read from file or supplied binary */ /*
* Font resources
*/
typedef struct font { typedef struct font {
DWORD memopt; DWORD memopt;
raw_data_t *data; raw_data_t *data;
} font_t; } font_t;
typedef struct fontdir {
DWORD memopt;
raw_data_t *data;
} fontdir_t;
/* /*
* Icon resources * Icon resources
*/ */
@ -302,14 +312,14 @@ typedef struct icon_header {
} icon_header_t; } icon_header_t;
typedef struct icon_dir_entry { typedef struct icon_dir_entry {
BYTE width; /* From the SDK doc. */ BYTE width; /* From the SDK doc. */
BYTE height; BYTE height;
BYTE nclr; BYTE nclr;
BYTE reserved; BYTE reserved;
WORD planes; WORD planes;
WORD bits; WORD bits;
DWORD ressize; DWORD ressize;
DWORD offset; DWORD offset;
} icon_dir_entry_t; } icon_dir_entry_t;
typedef struct icon { typedef struct icon {
@ -342,14 +352,14 @@ typedef struct cursor_header {
} cursor_header_t; } cursor_header_t;
typedef struct cursor_dir_entry { typedef struct cursor_dir_entry {
BYTE width; /* From the SDK doc. */ BYTE width; /* From the SDK doc. */
BYTE height; BYTE height;
BYTE nclr; BYTE nclr;
BYTE reserved; BYTE reserved;
WORD xhot; WORD xhot;
WORD yhot; WORD yhot;
DWORD ressize; DWORD ressize;
DWORD offset; DWORD offset;
} cursor_dir_entry_t; } cursor_dir_entry_t;
typedef struct cursor { typedef struct cursor {
@ -374,6 +384,43 @@ typedef struct cursor_group {
int ncursor; int ncursor;
} cursor_group_t; } 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 { typedef struct bitmap {
DWORD memopt; DWORD memopt;
raw_data_t *data; raw_data_t *data;
@ -381,7 +428,6 @@ typedef struct bitmap {
typedef struct rcdata { typedef struct rcdata {
DWORD memopt; DWORD memopt;
lvc_t lvc;
raw_data_t *data; raw_data_t *data;
} rcdata_t; } rcdata_t;
@ -467,6 +513,8 @@ typedef struct versioninfo {
int fst:1; int fst:1;
} gotit; } gotit;
ver_block_t *blocks; ver_block_t *blocks;
lvc_t lvc;
DWORD memopt;
} versioninfo_t; } versioninfo_t;
/* Accelerator structures */ /* Accelerator structures */
@ -509,7 +557,6 @@ typedef struct toolbar {
typedef struct dlginit { typedef struct dlginit {
DWORD memopt; DWORD memopt;
lvc_t lvc;
raw_data_t *data; raw_data_t *data;
} dlginit_t; } dlginit_t;
@ -523,6 +570,7 @@ typedef struct resource {
language_t *lan; /* Only used as a sorting key and c-name creation*/ language_t *lan; /* Only used as a sorting key and c-name creation*/
union { union {
accelerator_t *acc; accelerator_t *acc;
ani_curico_t *ani;
bitmap_t *bmp; bitmap_t *bmp;
cursor_t *cur; cursor_t *cur;
cursor_group_t *curg; cursor_group_t *curg;
@ -530,6 +578,7 @@ typedef struct resource {
dialogex_t *dlgex; dialogex_t *dlgex;
dlginit_t *dlgi; dlginit_t *dlgi;
font_t *fnt; font_t *fnt;
fontdir_t *fnd;
icon_t *ico; icon_t *ico;
icon_group_t *icog; icon_group_t *icog;
menu_t *men; menu_t *men;

View File

@ -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 * Function : find_counter