- 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:
parent
6b4c347424
commit
997e0d782f
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
--------------------------
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
<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 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]* 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 */
|
||||
|
||||
<INITIAL>. return yytext[0];
|
||||
|
||||
|
|
|
@ -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 <str> tSTRING tIDENT tFILENAME
|
||||
%token <raw> 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 <res> resource_file resource resources resource_definition
|
||||
%type <stt> stringtable strings
|
||||
%type <fnt> font
|
||||
%type <icog> icon
|
||||
%type <fnd> fontdir
|
||||
%type <acc> accelerators
|
||||
%type <event> events
|
||||
%type <bmp> bitmap
|
||||
%type <curg> cursor
|
||||
%type <ani> cursor icon
|
||||
%type <dlg> dialog dlg_attributes
|
||||
%type <ctl> ctrls gen_ctrl lab_ctrl ctrl_desc iconinfo
|
||||
%type <iptr> helpid
|
||||
%type <dlgex> dialogex dlgex_attribs
|
||||
%type <ctl> exctrls gen_exctrl lab_exctrl exctrl_desc
|
||||
%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 <verw> ver_words
|
||||
%type <blk> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue