Removed old resource compiler.
This commit is contained in:
parent
87a2f8df86
commit
d1735c6198
|
@ -1,5 +0,0 @@
|
|||
Makefile
|
||||
lex.yy.c
|
||||
winerc
|
||||
y.tab.c
|
||||
y.tab.h
|
|
@ -1,28 +0,0 @@
|
|||
DEFS = -D__WINE__
|
||||
TOPSRCDIR = @top_srcdir@
|
||||
TOPOBJDIR = ..
|
||||
SRCDIR = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
PROGRAMS = winerc@PROGEXT@
|
||||
MODULE = none
|
||||
|
||||
C_SRCS = winerc.c
|
||||
EXTRA_SRCS = parser.y parser.l
|
||||
EXTRA_OBJS = y.tab.o lex.yy.o
|
||||
|
||||
all: $(PROGRAMS)
|
||||
|
||||
depend:: y.tab.h
|
||||
|
||||
@MAKE_RULES@
|
||||
|
||||
$(PROGRAMS): $(OBJS)
|
||||
$(CC) $(CFLAGS) -o winerc@PROGEXT@ $(OBJS) $(LEXLIB)
|
||||
|
||||
y.tab.c y.tab.h: parser.y
|
||||
$(YACC) -d -t $(SRCDIR)/parser.y
|
||||
|
||||
lex.yy.c: parser.l
|
||||
$(LEX) -8 -I $(SRCDIR)/parser.l
|
||||
|
||||
### Dependencies:
|
37
rc/README
37
rc/README
|
@ -1,37 +0,0 @@
|
|||
This is winerc, the resource compiler for the Wine project. It takes the
|
||||
same input as rc.exe, but generates C files as output. These C files can
|
||||
be linked together with the application, which can access the resource
|
||||
data directly instead of using FindResource/LoadResource/LockResource.
|
||||
The generated C code contains arrays, which represent the resource as if
|
||||
it was obtained from LoadResource. A table to map resource names to
|
||||
pointers is also available.
|
||||
Primary applications are the resources of sysres.dll and a future
|
||||
commdlg.dll, but the use in the library version is possible as well.
|
||||
The expected advantage of using winerc over sysres.dll is a speed
|
||||
improvement, however, actual data to support that claim are not
|
||||
available. The use of winerc might also simplify the source code. For
|
||||
example, the system menu is managed in the function CopySysMenu
|
||||
(controls/menu.c). A winerc-based implementation would just call
|
||||
return LoadMenuIndirect(_Sysres_SYSMENU);
|
||||
As the resources are already in the Wine image, they are loaded on
|
||||
demand as any other part of a Unix executable image.
|
||||
|
||||
Current State
|
||||
This is the first release of winerc. It is alpha software, as the rest
|
||||
of Wine is. If you use it for replacing sysres.dll, or if you write
|
||||
other parts of Wine which require resource (like commdlg), you will
|
||||
probably notice a loss in stability. This is especially true for cursor
|
||||
and icon resources, as they are unlikely to work at all. See the TODO
|
||||
file for details.
|
||||
|
||||
Copying
|
||||
The license for Wine applies for winerc as well. Read the files LICENSE
|
||||
and WARRANTY in the current or any future distribution for details. You
|
||||
can change any source files, and you can add your own copyright notice,
|
||||
as long as you leave the existing copyrights intact.
|
||||
|
||||
Bug Reports and Fixes
|
||||
If you find a bug in winerc, you can report it to me,
|
||||
martin@cs.csufresno.edu (Martin von Loewis) or to
|
||||
comp.emulators.ms-windows.wine. If you can fix the bug, send the diffs
|
||||
and ChangeLog entry to julliard@lrc.epfl.ch (Alexandre Julliard).
|
|
@ -1,19 +0,0 @@
|
|||
This release of winerc contains a resource script for sysres.dll,
|
||||
obtained by saving it as RC in Borland's Resource Workshop. Obsolete
|
||||
or duplicate resources where removed. If you find that I deleted to
|
||||
little or to much, drop me a note.
|
||||
You are encouraged to create sysres dumps using your favoured resource
|
||||
editor. If the output cannot be compiled, or the generated C code is
|
||||
different from mine, report this as a bug. When comparing the results,
|
||||
note that only the order might be different, which is not considered a
|
||||
bug.
|
||||
systest.c is a Windows program which shows how to use winerc generated
|
||||
resources. Compile it with your Windows compiler, and link it with
|
||||
sysres.c. It also shows how to prevent curious people from spying your
|
||||
bitmaps, dialogs, and menus :-)
|
||||
|
||||
Deleted resources:
|
||||
Bitmap: OBMCLOSE
|
||||
Menu: 1, 0xF140+2
|
||||
Dialog: 0XF140+3, EXCLAMATION_MSGBOX, QUESTION_MSGBOX, STOP_MSGBOX
|
||||
Icon: SYSIDI_STOPICON
|
63
rc/TODO
63
rc/TODO
|
@ -1,63 +0,0 @@
|
|||
1. User interface
|
||||
- use GNU's long_getopt
|
||||
- allow to pass input and output files via command line
|
||||
- add options for various not-yet-implemented features (Unicode, Win32
|
||||
format, non-native/native alignment and endianness, compact output
|
||||
format)
|
||||
|
||||
2. Input format
|
||||
- improve input file processing
|
||||
Currently, certain pre- and postprocessing is required. winerc
|
||||
should accept an arbitrary resource script and generate the C file
|
||||
with as little intermediate files as possible. I'm not sure how to
|
||||
handle the symbols from windows.h. There are certain options:
|
||||
* winerc predefines the symbols via the cpp command line
|
||||
* windows.h is #include'd, and the resulting C code is dropped
|
||||
(Should winerc do C parsing here?)
|
||||
* a stripped-down version of windows.h is included,
|
||||
generated by "grep '^#' windows.h"
|
||||
* windows.h #ifdef's every C code with _RC_INVOKED
|
||||
(commercial solution)
|
||||
- complete input syntax
|
||||
The goal here is to support every existing resource file which is
|
||||
accepted by another resource compiler, not to put as much fancy
|
||||
features into the compiler as possible. Every correct resource file
|
||||
which generates a parse error can be reported as a bug, a problem
|
||||
analysis and a fix would be appreciated.
|
||||
|
||||
3. Output file format
|
||||
- add missing resources (fonts, versioninfo, stringtables,rcdata)
|
||||
- check style handling
|
||||
The semantics of control and dialog styles is somewhat poorly
|
||||
documented. For example, I couldn't find a reference that every
|
||||
control has the WS_VISIBLE and WS_CHILD style, even if they are
|
||||
not specified. What other styles are considered default?
|
||||
The existance of default styles implies support for disabling these,
|
||||
unlike any other proper programming language,
|
||||
NOT WS_VISIBLE | WS_GROUP
|
||||
does *not* mean ~WS_VISIBLE, but WS_CHILD|WS_GROUP (in C semantics).
|
||||
What other strange semantics are there?
|
||||
- check cursor and icon handling
|
||||
At the moment, the .CUR and .ICO files are copied byte-by-byte into
|
||||
the C array. This is probably wrong, as there are things like cursor
|
||||
and icon groups. In which way should they be present in a Wine image?
|
||||
Should we have arrays for every cursor, as well as the cursor group?
|
||||
Is one cursor per group enough, in the context of X? If so, do we
|
||||
still need the group?
|
||||
- create a more compact output file
|
||||
The current format is well-suited for debugging, as one can easily
|
||||
match it with a resource' hex dump. A more compact format would use
|
||||
strings instead of integer lists. A clever algorithm for embedding
|
||||
values <32 and >127 is required.
|
||||
- platform independence
|
||||
Currently, the lay-out of the resources is just as it is in Win3.1 -
|
||||
packed structures, little endian. Although this format can be used
|
||||
on any architecture, aligned data and native endianness would speed-up
|
||||
the resource manipulation and simplify the code. OTOH, this would
|
||||
break applications that rely on the lay-out. All this is of interest
|
||||
for the library version only.
|
||||
- Win32 support
|
||||
|
||||
4. Programming Style
|
||||
- memory management
|
||||
No memory is freed in the current implementation.
|
108
rc/parser.h
108
rc/parser.h
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright Martin von Loewis, 1994
|
||||
*
|
||||
*/
|
||||
|
||||
/* resource types */
|
||||
enum rt {acc,bmp,cur,dlg,fnt,ico,men,rdt,str};
|
||||
/* generic resource
|
||||
Bytes can be inserted at arbitrary positions, the data field (res)
|
||||
grows as required. As the dialog header contains the number of
|
||||
controls, this number is generated in num_entries. If n_type if 0,
|
||||
the resource name is i_name, and s_name otherwise. Top level
|
||||
resources are linked via next. All gen_res objects are linked via
|
||||
g_prev, g_next for debugging purposes. space is the length of res,
|
||||
size is the used part of res.
|
||||
As most bison rules are right recursive, new items are usually
|
||||
inserted at the beginning
|
||||
*/
|
||||
typedef struct gen_res{
|
||||
int size,space;
|
||||
int num_entries;
|
||||
enum rt type;
|
||||
union{
|
||||
int i_name;
|
||||
char* s_name;
|
||||
}n;
|
||||
int n_type; /*0 - integer, 1 = string*/
|
||||
struct gen_res *next;
|
||||
struct gen_res *g_prev,*g_next;
|
||||
unsigned char res[0];
|
||||
} gen_res;
|
||||
|
||||
/* control/dialog style. or collects styles, and collects NOT styles */
|
||||
typedef struct rc_style{
|
||||
int and, or;
|
||||
}rc_style;
|
||||
|
||||
/* create a new resource */
|
||||
gen_res *new_res(void);
|
||||
/* double the space of the resource */
|
||||
gen_res* grow(gen_res*);
|
||||
/* insert byte array at the beginning, increase count */
|
||||
gen_res* insert_at_beginning(gen_res*,char*,int);
|
||||
/* insert byte array at offset */
|
||||
gen_res* insert_bytes(gen_res*,char*,int,int);
|
||||
/* delete bytes at offset */
|
||||
gen_res* delete_bytes(gen_res*,int,int);
|
||||
/* create a new style */
|
||||
rc_style* new_style(void);
|
||||
/* convert \t to tab etc. */
|
||||
char* parse_c_string(char*);
|
||||
/* get the resources type, convert dlg to "DIALOG" and so on */
|
||||
char* get_typename(gen_res*);
|
||||
|
||||
gen_res* add_accelerator(int,int,int,gen_res*);
|
||||
gen_res* add_string_accelerator(char*,int,int,gen_res*);
|
||||
gen_res* add_ascii_accelerator(int,int,int,gen_res*);
|
||||
gen_res* add_vk_accelerator(int,int,int,gen_res*);
|
||||
|
||||
gen_res* new_dialog(void);
|
||||
gen_res* dialog_style(rc_style*,gen_res*);
|
||||
int dialog_get_menu(gen_res*);
|
||||
int dialog_get_class(gen_res*);
|
||||
int dialog_get_caption(gen_res*);
|
||||
int dialog_get_fontsize(gen_res*);
|
||||
gen_res* dialog_caption(char*,gen_res*);
|
||||
gen_res* dialog_font(short,char*,gen_res*);
|
||||
gen_res* dialog_class(char*,gen_res*);
|
||||
gen_res* dialog_menu_id(short,gen_res*);
|
||||
gen_res* dialog_menu_str(char*,gen_res*);
|
||||
gen_res* create_control_desc(int,int,int,int,int,rc_style*);
|
||||
gen_res* label_control_desc(char*,gen_res*);
|
||||
gen_res* create_generic_control(char*,int,char*,rc_style*,int,int,int,int);
|
||||
gen_res* add_control(int,int,gen_res*,gen_res*);
|
||||
gen_res* add_icon(char*,int,int,int,gen_res*,gen_res*);
|
||||
gen_res* add_generic_control(gen_res*,gen_res*);
|
||||
gen_res* make_dialog(gen_res*,int,int,int,int,gen_res*);
|
||||
|
||||
gen_res *hex_to_raw(char*,gen_res*);
|
||||
gen_res *int_to_raw(int,gen_res*);
|
||||
gen_res *make_font(gen_res*);
|
||||
gen_res *make_raw(gen_res*);
|
||||
gen_res *make_bitmap(gen_res*);
|
||||
gen_res *make_icon(gen_res*);
|
||||
gen_res *make_cursor(gen_res*);
|
||||
gen_res *load_file(char*);
|
||||
|
||||
gen_res *add_menuitem(char*,int,int,gen_res*);
|
||||
gen_res *add_popup(char*,short,gen_res*,gen_res*);
|
||||
gen_res *make_menu(gen_res*);
|
||||
|
||||
gen_res *add_resource(gen_res*,gen_res*);
|
||||
|
||||
void add_str_tbl_elm(int,char*);
|
||||
|
||||
void create_output(gen_res*);
|
||||
void set_out_file(char*);
|
||||
|
||||
#define CT_BUTTON 0x80
|
||||
#define CT_EDIT 0x81
|
||||
#define CT_STATIC 0x82
|
||||
#define CT_LISTBOX 0x83
|
||||
#define CT_SCROLLBAR 0x84
|
||||
#define CT_COMBOBOX 0x85
|
||||
|
||||
extern int verbose;
|
||||
|
85
rc/parser.l
85
rc/parser.l
|
@ -1,85 +0,0 @@
|
|||
/* -*-C-*-
|
||||
*
|
||||
* Copyright Martin von Loewis, 1994
|
||||
*
|
||||
*/
|
||||
%{
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "parser.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
#define YY_NO_UNPUT
|
||||
|
||||
int line_number=1;
|
||||
%}
|
||||
%%
|
||||
ACCELERATORS return ACCELERATORS;
|
||||
ALT return ALT;
|
||||
ASCII return ASCII;
|
||||
BEGIN return tBEGIN;
|
||||
BITMAP return tBITMAP;
|
||||
CAPTION return CAPTION;
|
||||
CHECKBOX return CHECKBOX;
|
||||
CHECKED return CHECKED;
|
||||
CLASS return CLASS;
|
||||
COMBOBOX return COMBOBOX;
|
||||
CONTROL return CONTROL;
|
||||
CTEXT return CTEXT;
|
||||
CURSOR return CURSOR;
|
||||
DEFPUSHBUTTON return DEFPUSHBUTTON;
|
||||
DIALOG return DIALOG;
|
||||
DISCARDABLE return DISCARDABLE;
|
||||
EDITTEXT return EDITTEXT;
|
||||
END return tEND;
|
||||
FIXED return tFIXED;
|
||||
FONT return FONT;
|
||||
GRAYED return GRAYED;
|
||||
GROUPBOX return GROUPBOX;
|
||||
HELP return HELP;
|
||||
ICON return ICON;
|
||||
INACTIVE return INACTIVE;
|
||||
LISTBOX return LISTBOX;
|
||||
LTEXT return LTEXT;
|
||||
MENU return MENU;
|
||||
MENUBARBREAK return MENUBARBREAK;
|
||||
MENUBREAK return MENUBREAK;
|
||||
MENUITEM return MENUITEM;
|
||||
MOVEABLE return MOVEABLE;
|
||||
LOADONCALL return LOADONCALL;
|
||||
NOINVERT return NOINVERT;
|
||||
NOT return NOT;
|
||||
NUMBER return NUMBER;
|
||||
POPUP return POPUP;
|
||||
PRELOAD return PRELOAD;
|
||||
PUSHBUTTON return PUSHBUTTON;
|
||||
PURE return PURE;
|
||||
RADIOBUTTON return RADIOBUTTON;
|
||||
RCDATA return RCDATA;
|
||||
RTEXT return RTEXT;
|
||||
SCROLLBAR return SCROLLBAR;
|
||||
SHIFT return SHIFT;
|
||||
SEPARATOR return SEPARATOR;
|
||||
STRING return tSTRING;
|
||||
STRINGTABLE return STRINGTABLE;
|
||||
STYLE return STYLE;
|
||||
VERSIONINFO return VERSIONINFO;
|
||||
VIRTKEY return VIRTKEY;
|
||||
\{ return tBEGIN;
|
||||
\} return tEND;
|
||||
[+-]?[0-9]+ yylval.num=atoi(yytext);return NUMBER;
|
||||
0x[0-9A-Fa-f]+L? yylval.num=strtoul(yytext,0,16);return NUMBER;
|
||||
[A-Za-z][A-Za-z_0-9]* yylval.str=strdup(yytext);return IDENT;
|
||||
\"[^"]*\" yylval.str=parse_c_string(yytext);return tSTRING;
|
||||
\'[^']*\' yylval.str=strdup(yytext+1);return SINGLE_QUOTED;
|
||||
\n { line_number++; }
|
||||
[ \t\r] ;
|
||||
. return yytext[0];
|
||||
%%
|
||||
|
||||
#ifndef yywrap
|
||||
int yywrap(void) { return 1; }
|
||||
#endif
|
||||
|
228
rc/parser.y
228
rc/parser.y
|
@ -1,228 +0,0 @@
|
|||
%{
|
||||
/*
|
||||
*
|
||||
* Copyright Martin von Loewis, 1994
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "parser.h"
|
||||
#include "windows.h"
|
||||
|
||||
int yylex(void);
|
||||
int yyerror(const char *s);
|
||||
|
||||
%}
|
||||
%union{
|
||||
gen_res *res;
|
||||
char *str;
|
||||
int num;
|
||||
struct rc_style *style;
|
||||
}
|
||||
%token <num> NUMBER
|
||||
%token <str> tSTRING SINGLE_QUOTED IDENT
|
||||
%token ACCELERATORS ALT ASCII tBEGIN tBITMAP CAPTION CHECKBOX CHECKED
|
||||
%token CLASS COMBOBOX CONTROL CTEXT CURSOR DEFPUSHBUTTON DIALOG
|
||||
%token DISCARDABLE EDITTEXT tEND tFIXED FONT GRAYED GROUPBOX HELP ICON
|
||||
%token IDENT INACTIVE LISTBOX LTEXT MENU MENUBARBREAK MENUBREAK MENUITEM
|
||||
%token MOVEABLE LOADONCALL NOINVERT NOT NOT_SUPPORTED POPUP PRELOAD
|
||||
%token PURE PUSHBUTTON RADIOBUTTON RCDATA RTEXT SCROLLBAR SHIFT SEPARATOR
|
||||
%token SINGLE_QUOTED tSTRING STRINGTABLE STYLE VERSIONINFO VIRTKEY
|
||||
%type <res> resource_file resource resources resource_definition accelerators
|
||||
%type <res> events bitmap cursor dialog dlg_attributes controls
|
||||
%type <res> generic_control labeled_control control_desc font icon
|
||||
%type <res> iconinfo menu menu_body item_definitions rcdata raw_data raw_elements
|
||||
%type <res> stringtable strings versioninfo
|
||||
%type <num> acc_options item_options
|
||||
%type <style> style style_elm optional_style
|
||||
%%
|
||||
|
||||
resource_file: resources {create_output($1);}
|
||||
|
||||
/*resources are put into a linked list*/
|
||||
resources: {$$=0;}
|
||||
|resource resources {$$=add_resource($1,$2);}
|
||||
;
|
||||
|
||||
/* get the name for a single resource*/
|
||||
resource: NUMBER resource_definition
|
||||
{$$=$2;$$->n.i_name=$1;$$->n_type=0;
|
||||
if(verbose)fprintf(stderr,"Got %s %d\n",get_typename($2),$1);
|
||||
}
|
||||
| IDENT resource_definition
|
||||
{$$=$2;$$->n.s_name=$1;$$->n_type=1;
|
||||
if(verbose)fprintf(stderr,"Got %s %s\n",get_typename($2),$1);
|
||||
}
|
||||
| stringtable
|
||||
{$$=$1; /* <-- should be NULL */
|
||||
if(verbose)fprintf(stderr,"Got STRINGTABLE\n");
|
||||
}
|
||||
;
|
||||
|
||||
/* get the value for a single resource*/
|
||||
resource_definition: accelerators {$$=$1;}
|
||||
| bitmap {$$=$1;}
|
||||
| cursor {$$=$1;}
|
||||
| dialog {$$=$1;}
|
||||
| font {$$=$1;}
|
||||
| icon {$$=$1;}
|
||||
| menu {$$=$1;}
|
||||
| rcdata {$$=$1;}
|
||||
| versioninfo {$$=$1;}
|
||||
;
|
||||
|
||||
/* have to use tBEGIN because BEGIN is predefined */
|
||||
accelerators: ACCELERATORS load_and_memoption tBEGIN events tEND {$$=$4;$$->type=acc;}
|
||||
/* the events are collected in a gen_res, as the accelerator resource is just
|
||||
an array of events */
|
||||
events: {$$=new_res();}
|
||||
| tSTRING ',' NUMBER acc_options events
|
||||
{$$=add_string_accelerator($1,$3,$4,$5);}
|
||||
| NUMBER ',' NUMBER ',' ASCII acc_options events
|
||||
{$$=add_ascii_accelerator($1,$3,$6,$7);}
|
||||
| NUMBER ',' NUMBER ',' VIRTKEY acc_options events
|
||||
{$$=add_vk_accelerator($1,$3,$6,$7);}
|
||||
acc_options: {$$=0;}
|
||||
| ',' NOINVERT acc_options {$$=$3|2;}
|
||||
| ',' ALT acc_options {$$=$3|16;}
|
||||
| ',' SHIFT acc_options {$$=$3|4;}
|
||||
| ',' CONTROL acc_options {$$=$3|8;}
|
||||
|
||||
bitmap: tBITMAP load_and_memoption tSTRING {$$=make_bitmap(load_file($3));}
|
||||
| tBITMAP load_and_memoption raw_data {$$=make_bitmap($3);}
|
||||
|
||||
/* load and memory options are ignored */
|
||||
load_and_memoption: | lamo load_and_memoption
|
||||
lamo: PRELOAD | LOADONCALL | tFIXED | MOVEABLE | DISCARDABLE | PURE
|
||||
|
||||
cursor: CURSOR load_and_memoption tSTRING {$$=make_cursor(load_file($3));}
|
||||
|CURSOR load_and_memoption raw_data {$$=make_cursor($3);}
|
||||
|
||||
dialog: DIALOG load_and_memoption NUMBER ',' NUMBER ',' NUMBER ',' NUMBER
|
||||
dlg_attributes
|
||||
tBEGIN controls tEND
|
||||
{$$=make_dialog($10,$3,$5,$7,$9,$12);}
|
||||
|
||||
dlg_attributes: {$$=new_dialog();}
|
||||
| STYLE style dlg_attributes
|
||||
{$$=dialog_style($2,$3);}
|
||||
| CAPTION tSTRING dlg_attributes
|
||||
{$$=dialog_caption($2,$3);}
|
||||
| FONT NUMBER ',' tSTRING dlg_attributes
|
||||
{$$=dialog_font($2,$4,$5);}
|
||||
| CLASS tSTRING dlg_attributes
|
||||
{$$=dialog_class($2,$3);}
|
||||
| MENU tSTRING dlg_attributes
|
||||
{$$=dialog_menu_str($2,$3);}
|
||||
| MENU NUMBER dlg_attributes
|
||||
{$$=dialog_menu_id($2,$3);}
|
||||
|
||||
/* the controls are collected into a gen_res, and finally the dialog header
|
||||
is put at the beginning */
|
||||
controls: {$$=new_res();}
|
||||
| CHECKBOX labeled_control controls
|
||||
{$$=add_control(CT_BUTTON, BS_CHECKBOX, $2, $3);}
|
||||
| COMBOBOX control_desc controls
|
||||
{$$=add_control(CT_COMBOBOX, 0, $2, $3);}
|
||||
| CONTROL generic_control controls
|
||||
{$$=add_generic_control($2, $3);}
|
||||
| CTEXT labeled_control controls
|
||||
{$$=add_control(CT_STATIC, SS_CENTER, $2, $3);}
|
||||
| DEFPUSHBUTTON labeled_control controls
|
||||
{$$=add_control(CT_BUTTON, BS_DEFPUSHBUTTON, $2, $3);}
|
||||
| EDITTEXT control_desc controls
|
||||
{$$=add_control(CT_EDIT, 0, $2, $3);}
|
||||
| GROUPBOX labeled_control controls
|
||||
{$$=add_control(CT_BUTTON, BS_GROUPBOX, $2, $3);}
|
||||
/*special treatment for icons, as the extent is optional*/
|
||||
| ICON tSTRING ',' NUMBER ',' NUMBER ',' NUMBER iconinfo controls
|
||||
{$$=add_icon($2, $4, $6, $8, $9, $10);}
|
||||
| LISTBOX control_desc controls
|
||||
{$$=add_control(CT_LISTBOX, 0, $2, $3);}
|
||||
| LTEXT labeled_control controls
|
||||
{$$=add_control(CT_STATIC, SS_LEFT, $2, $3);}
|
||||
| PUSHBUTTON labeled_control controls
|
||||
{$$=add_control(CT_BUTTON, BS_PUSHBUTTON, $2, $3);}
|
||||
| RADIOBUTTON labeled_control controls
|
||||
{$$=add_control(CT_BUTTON, BS_RADIOBUTTON, $2, $3);}
|
||||
| RTEXT labeled_control controls
|
||||
{$$=add_control(CT_STATIC, SS_RIGHT, $2, $3);}
|
||||
| SCROLLBAR control_desc controls
|
||||
{$$=add_control(CT_SCROLLBAR, 0, $2, $3);}
|
||||
|
||||
|
||||
labeled_control: tSTRING ',' control_desc {$$=label_control_desc($1,$3);}
|
||||
control_desc: NUMBER ',' NUMBER ',' NUMBER ',' NUMBER ',' NUMBER optional_style
|
||||
{$$=create_control_desc($1,$3,$5,$7,$9,$10);}
|
||||
|
||||
optional_style: {$$=0;}|
|
||||
',' style {$$=$2;}
|
||||
|
||||
iconinfo: /*set extent and style to 0 if they are not provided */
|
||||
{$$=create_control_desc(0,0,0,0,0,0);}
|
||||
/* x and y are overwritten later */
|
||||
| ',' NUMBER ',' NUMBER optional_style
|
||||
{$$=create_control_desc(0,0,0,$2,$4,$5);}
|
||||
|
||||
generic_control: tSTRING ',' NUMBER ',' tSTRING ',' style ',' NUMBER
|
||||
',' NUMBER ',' NUMBER ',' NUMBER
|
||||
{$$=create_generic_control($1,$3,$5,$7,$9,$11,$13,$15);}
|
||||
|
||||
font: FONT load_and_memoption tSTRING {$$=make_font(load_file($3));}
|
||||
|
||||
icon: ICON load_and_memoption tSTRING {$$=make_icon(load_file($3));}
|
||||
| ICON load_and_memoption raw_data {$$=make_icon($3);}
|
||||
|
||||
menu: MENU load_and_memoption menu_body {$$=make_menu($3);}
|
||||
/* menu items are collected in a gen_res and prefixed with the menu header*/
|
||||
menu_body: tBEGIN item_definitions tEND {$$=$2;}
|
||||
item_definitions: {$$=new_res();}
|
||||
| MENUITEM tSTRING ',' NUMBER item_options item_definitions
|
||||
{$$=add_menuitem($2,$4,$5,$6);}
|
||||
| MENUITEM SEPARATOR item_definitions
|
||||
{$$=add_menuitem("",0,0,$3);}
|
||||
| POPUP tSTRING item_options menu_body item_definitions
|
||||
{$$=add_popup($2,$3,$4,$5);}
|
||||
item_options: {$$=0;}
|
||||
| ',' CHECKED item_options {$$=$3|MF_CHECKED;}
|
||||
| ',' GRAYED item_options {$$=$3|MF_GRAYED;}
|
||||
| ',' HELP item_options {$$=$3|MF_HELP;}
|
||||
| ',' INACTIVE item_options {$$=$3|MF_DISABLED;}
|
||||
| ',' MENUBARBREAK item_options {$$=$3|MF_MENUBARBREAK;}
|
||||
| ',' MENUBREAK item_options {$$=$3|MF_MENUBREAK;}
|
||||
|
||||
rcdata: RCDATA load_and_memoption raw_data {$$=make_raw($3);}
|
||||
|
||||
raw_data: tBEGIN raw_elements tEND {$$=$2;}
|
||||
raw_elements: SINGLE_QUOTED {$$=hex_to_raw($1,new_res());}
|
||||
| NUMBER {$$=int_to_raw($1,new_res());}
|
||||
| SINGLE_QUOTED raw_elements {$$=hex_to_raw($1,$2);}
|
||||
| NUMBER ',' raw_elements {$$=int_to_raw($1,$3);}
|
||||
|
||||
stringtable: STRINGTABLE load_and_memoption tBEGIN strings tEND
|
||||
{$$=$4;}
|
||||
strings: {$$=0;}|
|
||||
NUMBER tSTRING strings {$$=0;add_str_tbl_elm($1,$2);}
|
||||
|
||||
versioninfo: VERSIONINFO NOT_SUPPORTED {$$=0;}
|
||||
|
||||
/* NOT x | NOT y | a | b means (a|b)& ~x & ~y
|
||||
NOT is used to disable default styles */
|
||||
style: {$$=new_style();}
|
||||
| style_elm {$$=$1;}
|
||||
| style_elm '|' style
|
||||
{$$=$1;$$->or|=$3->or;$$->and&=$3->and;free($3);}
|
||||
|
||||
style_elm: NUMBER {$$=new_style();$$->or=$1;}
|
||||
| NOT NUMBER {$$=new_style();$$->and=~($2);}
|
||||
| '(' style ')' {$$=$2;}
|
||||
%%
|
||||
extern int line_number;
|
||||
extern char* yytext;
|
||||
|
||||
int yyerror( const char *s )
|
||||
{
|
||||
fprintf(stderr,"stdin:%d: %s before '%s'\n",line_number,s,yytext);
|
||||
return 0;
|
||||
}
|
||||
|
109
rc/systest.c
109
rc/systest.c
|
@ -1,109 +0,0 @@
|
|||
#include <windows.h>
|
||||
|
||||
LRESULT CALLBACK _export WndProc(HWND hWnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
|
||||
BOOL CALLBACK _export DlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
|
||||
|
||||
HINSTANCE hInst;
|
||||
HMENU hMenu,dummy;
|
||||
extern char sysres_MENU_SYSMENU[],sysres_BITMAP_WINELOGO[],sysres_DIALOG_2[];
|
||||
|
||||
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||
LPSTR lpszCmdLine, int cmdShow)
|
||||
{
|
||||
MSG msg;
|
||||
WNDCLASS wcHdumpClass;
|
||||
HWND hWndMain;
|
||||
|
||||
hInst=hInstance;
|
||||
|
||||
/* Define the window class for this application.
*/
|
||||
wcHdumpClass.lpszClassName = "WrcTestClass";
|
||||
wcHdumpClass.hInstance = hInstance;
|
||||
wcHdumpClass.lpfnWndProc = WndProc;
|
||||
wcHdumpClass.hCursor = 0;
|
||||
wcHdumpClass.hIcon = 0;
|
||||
wcHdumpClass.lpszMenuName = 0;
|
||||
wcHdumpClass.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||
wcHdumpClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wcHdumpClass.cbClsExtra = 0;
|
||||
wcHdumpClass.cbWndExtra = 0;
|
||||
RegisterClass(&wcHdumpClass);
|
||||
|
||||
hWndMain = CreateWindow("WrcTestClass","WrcTest",
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, /* x window location
*/
|
||||
CW_USEDEFAULT, /* y
*/
|
||||
CW_USEDEFAULT, /* cx and size
*/
|
||||
CW_USEDEFAULT, /* cy
*/
|
||||
NULL, /* no parent for this window
*/
|
||||
NULL, /* use the class menu
*/
|
||||
hInstance, /* who created this window
*/
|
||||
NULL /* no parms to pass on
*/
|
||||
);
|
||||
ShowWindow(hWndMain,SW_SHOW);
|
||||
UpdateWindow(hWndMain);
|
||||
hMenu=LoadMenuIndirect(sysres_MENU_SYSMENU);
|
||||
|
||||
/* see Q75254 on how to create a popup menu via LoadMenuIndirect */
|
||||
dummy=CreateMenu();
|
||||
InsertMenu(dummy,0,MF_POPUP,hMenu,NULL);
|
||||
hMenu=GetSubMenu(dummy,0);
|
||||
|
||||
while (GetMessage(&msg, NULL, NULL, NULL))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
return(msg.wParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK _export WndProc(HWND hWnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
POINT ptCurrent;
|
||||
switch(message)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
ptCurrent=MAKEPOINT(lParam);
|
||||
ClientToScreen(hWnd,&ptCurrent);
|
||||
TrackPopupMenu(hMenu,0,ptCurrent.x,ptCurrent.y,0,hWnd,0);
|
||||
break;
|
||||
case WM_PAINT:
|
||||
{ PAINTSTRUCT ps;
|
||||
BITMAPINFO *bm=sysres_BITMAP_WINELOGO;
|
||||
char *bits=bm;
|
||||
bits+=bm->bmiHeader.biSize;
|
||||
bits+=(1<<bm->bmiHeader.biBitCount)*sizeof(RGBQUAD);
|
||||
BeginPaint(hWnd,&ps);
|
||||
SetDIBitsToDevice(ps.hdc,0,0,bm->bmiHeader.biWidth,
|
||||
bm->bmiHeader.biHeight,0,0,0,bm->bmiHeader.biHeight,
|
||||
bits,bm,DIB_RGB_COLORS);
|
||||
EndPaint(hWnd,&ps);
|
||||
break;
|
||||
}
|
||||
case WM_COMMAND:
|
||||
CreateDialogIndirect(hInst,sysres_DIALOG_2,hWnd,DlgProc);
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
default:return DefWindowProc(hWnd,message,wParam,lParam);
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
BOOL CALLBACK _export DlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
return 1;
|
||||
case WM_COMMAND:
|
||||
DestroyWindow(hWnd);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
BIN
rc/winelogo.bmp
BIN
rc/winelogo.bmp
Binary file not shown.
Before Width: | Height: | Size: 64 KiB |
971
rc/winerc.c
971
rc/winerc.c
|
@ -1,971 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright Martin von Loewis, 1994
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "windows.h"
|
||||
#include "wine/winuser16.h"
|
||||
#include "parser.h"
|
||||
|
||||
char usage[]="winerc -bdvc -p prefix -o outfile < infile \n"
|
||||
" -b Create a C array from a binary .res file\n"
|
||||
" -c Add 'const' prefix to C constants\n"
|
||||
" -d Output debugging information\n"
|
||||
" -h Also generate a .h file\n"
|
||||
" -p prefix Give a prefix for the generated names\n"
|
||||
" -v Show each resource as it is processed\n"
|
||||
" -o file Output to file.c and file.h\n"
|
||||
" -w 16|32 Select win16 or win32 output\n";
|
||||
|
||||
/*might be overwritten by command line*/
|
||||
char *prefix="_Resource";
|
||||
int win32=1;
|
||||
int verbose,constant;
|
||||
gen_res* g_start;
|
||||
static FILE *header = NULL, *code = NULL;
|
||||
|
||||
int transform_binary_file(void);
|
||||
int yyparse(void);
|
||||
|
||||
static void *xmalloc (size_t size)
|
||||
{
|
||||
void *res;
|
||||
|
||||
res = malloc (size ? size : 1);
|
||||
if (res == NULL)
|
||||
{
|
||||
fprintf (stderr, "Virtual memory exhausted.\n");
|
||||
exit (1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
extern int yydebug;
|
||||
extern char* optarg;
|
||||
int optc,lose = 0, ret, binary = 0, output_header = 0;
|
||||
char output_name[256];
|
||||
|
||||
while((optc=getopt(argc,argv,"bcdhp:vo:w:"))!=EOF)
|
||||
switch(optc)
|
||||
{
|
||||
/* bison will print state transitions on stderr */
|
||||
case 'b':binary=1;
|
||||
break;
|
||||
case 'd':yydebug=1;
|
||||
setbuf(stdout,0);
|
||||
setbuf(stderr,0);
|
||||
break;
|
||||
case 'h':output_header=1; break;
|
||||
case 'p':prefix=strdup(optarg); break;
|
||||
case 'c':constant=1;break;
|
||||
case 'v':verbose=1;
|
||||
setbuf(stderr,0);
|
||||
break;
|
||||
case 'o':sprintf(output_name,"%s.c",optarg); break;
|
||||
case 'w':if(!strcmp(optarg,"16"))win32=0;
|
||||
else if(!strcmp(optarg,"32"))win32=1;
|
||||
else lose++;
|
||||
break;
|
||||
default: lose++;break;
|
||||
}
|
||||
if(lose)return fprintf(stderr,usage),1;
|
||||
|
||||
if (output_name[0])
|
||||
{
|
||||
code = fopen( output_name, "w" );
|
||||
if (output_header)
|
||||
{
|
||||
output_name[strlen(output_name)-1] = 'h';
|
||||
header = fopen( output_name, "w" );
|
||||
}
|
||||
}
|
||||
if (!code) code = stdout;
|
||||
if(binary)
|
||||
ret=transform_binary_file();
|
||||
else
|
||||
ret=yyparse();
|
||||
if (header) fclose(header);
|
||||
fclose(code);
|
||||
if (ret) /* There was an error */
|
||||
{
|
||||
if (header) unlink( output_name );
|
||||
output_name[strlen(output_name)-1] = 'c';
|
||||
unlink( output_name );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int transform_binary_file()
|
||||
{
|
||||
int i,c;
|
||||
if (header) fprintf(header,"#define APPLICATION_HAS_RESOURCES 1\n");
|
||||
fprintf(code,"char _Application_resources[]={");
|
||||
for(i=0;;i++)
|
||||
{
|
||||
c=getchar();
|
||||
if(c==-1)break;
|
||||
if(i%16==0)fputc('\n',code);
|
||||
fprintf(code,"%3d,",c);
|
||||
}
|
||||
fprintf(code,"\n 0};\nint _Application_resources_size=%d;\n",i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SunOS' memcpy is wrong for overlapping arrays */
|
||||
char *save_memcpy(char *d,char* s,int l)
|
||||
{
|
||||
if(d<s)
|
||||
for(;l;l--)*d++=*s++;
|
||||
else
|
||||
for(d+=l-1,s+=l-1;l;l--)*d--=*s--;
|
||||
return d;
|
||||
}
|
||||
|
||||
/*allow unaligned access*/
|
||||
void put_WORD(unsigned char* p,WORD w)
|
||||
{
|
||||
*p=w&0xFF;
|
||||
*(p+1)=w>>8;
|
||||
}
|
||||
|
||||
void put_DWORD(unsigned char* p,DWORD d)
|
||||
{
|
||||
put_WORD(p,d&0xFFFF);
|
||||
put_WORD(p+2,d>>16);
|
||||
}
|
||||
|
||||
WORD get_WORD(unsigned char* p)
|
||||
{
|
||||
return *p|(*(p+1)<<8);
|
||||
}
|
||||
|
||||
DWORD get_DWORD(unsigned char* p)
|
||||
{
|
||||
return get_WORD(p)|(get_WORD(p+2)<<16);
|
||||
}
|
||||
|
||||
|
||||
/*create a new gen_res, initial size 100*/
|
||||
gen_res *new_res()
|
||||
{ gen_res* ret=xmalloc(sizeof(gen_res)+100);
|
||||
int i;
|
||||
for(i=0;i<sizeof(gen_res)+100;i++)*((char*)ret+i)='\0';
|
||||
ret->g_next=g_start;
|
||||
ret->g_prev=0;
|
||||
g_start=ret;
|
||||
ret->space=100;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*double the space*/
|
||||
gen_res* grow(gen_res* res)
|
||||
{
|
||||
res=realloc(res,sizeof(gen_res)+2*res->space);
|
||||
if(!res)
|
||||
fprintf(stderr,"Out of memory\n"),exit(1);
|
||||
if(!res->g_prev)g_start=res;
|
||||
else res->g_prev->g_next=res;
|
||||
if(res->g_next)res->g_next->g_prev=res;
|
||||
res->space=2*res->space;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* insert bytes at offset 0, increase num_entries */
|
||||
gen_res* insert_at_beginning(gen_res* res,char* entry,int size)
|
||||
{
|
||||
while(res->size+size>res->space)res=grow(res);
|
||||
save_memcpy(res->res+size,res->res,res->size);
|
||||
save_memcpy(res->res,entry,size);
|
||||
res->size+=size;
|
||||
res->num_entries++;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* insert length characters from bytes into res, starting at start */
|
||||
gen_res* insert_bytes(gen_res* res,char* bytes,int start,int length)
|
||||
{
|
||||
while(res->size+length>res->space)res=grow(res);
|
||||
save_memcpy(res->res+start+length,res->res+start,res->size-start);
|
||||
save_memcpy(res->res+start,bytes,length);
|
||||
res->size+=length;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* insert string into res, starting at start */
|
||||
gen_res* insert_string(gen_res* res,unsigned char* string,int start,int terminating0)
|
||||
{
|
||||
unsigned char* p;
|
||||
int lengthA = strlen(string) + (terminating0 ? 1 : 0);
|
||||
int length = (win32 ? 2 : 1) * lengthA;
|
||||
while(res->size+length>res->space)res=grow(res);
|
||||
save_memcpy(res->res+start+length,res->res+start,res->size-start);
|
||||
p=res->res+start;
|
||||
while(lengthA--)
|
||||
if (win32)
|
||||
{
|
||||
put_WORD(p, *string++);
|
||||
p+=2;
|
||||
}
|
||||
else
|
||||
*p++=*string++;
|
||||
res->size+=length;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* insert string at offset 0, increase num_entries */
|
||||
gen_res* insert_string_at_beginning(gen_res* res,char* entry,int terminating0)
|
||||
{
|
||||
res=insert_string(res,entry,0,terminating0);
|
||||
res->num_entries++;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*delete len bytes from res, starting at start*/
|
||||
gen_res* delete_bytes(gen_res* res,int start,int len)
|
||||
{
|
||||
save_memcpy(res->res+start,res->res+start+len,res->size-start-len);
|
||||
res->size-=len;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*create a new style*/
|
||||
rc_style *new_style()
|
||||
{
|
||||
rc_style *ret=xmalloc(sizeof(rc_style));
|
||||
/*initially, no bits have to be reset*/
|
||||
ret->and=-1;
|
||||
/*initially, no bits are set*/
|
||||
ret->or=WS_CHILD | WS_VISIBLE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* entries are inserted at the beginning, starting from the last one */
|
||||
gen_res* add_accelerator(int ev, int id, int flags, gen_res* prev)
|
||||
{
|
||||
char accel_entry[5];
|
||||
if(prev->num_entries==0)flags|=0x80; /* last entry */
|
||||
accel_entry[0]=flags;
|
||||
put_WORD(accel_entry+1,ev);
|
||||
put_WORD(accel_entry+3,id);
|
||||
return insert_at_beginning(prev,accel_entry,5);
|
||||
}
|
||||
|
||||
|
||||
/* create an integer from the event, taking things as "^c" into account
|
||||
add this as new entry */
|
||||
gen_res* add_string_accelerator(char *ev, int id, int flags, gen_res* prev)
|
||||
{
|
||||
int event;
|
||||
if(*ev=='^')
|
||||
event=ev[1]-'a';
|
||||
else
|
||||
event=ev[0];
|
||||
return add_accelerator(event,id,flags,prev);
|
||||
}
|
||||
|
||||
/*is there a difference between ASCII and VIRTKEY accelerators? */
|
||||
|
||||
gen_res* add_ascii_accelerator(int ev, int id, int flags, gen_res* prev)
|
||||
{
|
||||
return add_accelerator(ev,id,flags,prev);
|
||||
}
|
||||
|
||||
gen_res* add_vk_accelerator(int ev, int id, int flags, gen_res* prev)
|
||||
{
|
||||
return add_accelerator(ev,id,flags,prev);
|
||||
}
|
||||
|
||||
/* create a new dialog header, set all items to 0 */
|
||||
gen_res* new_dialog()
|
||||
{ gen_res* ret=new_res();
|
||||
ret->size=win32?24:16; /*all strings "\0", no font*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* the STYLE option was specified */
|
||||
gen_res* dialog_style(rc_style* style, gen_res* attr)
|
||||
{
|
||||
/* default dialog styles? Do we need style->and? */
|
||||
/* DS_SETFONT might have been specified before */
|
||||
put_DWORD(attr->res,get_DWORD(attr->res)|style->or);
|
||||
return attr;
|
||||
}
|
||||
|
||||
/* menu name is at offset 13 (win32: 18) */
|
||||
int dialog_get_menu(gen_res* attr)
|
||||
{
|
||||
return win32?18:13;
|
||||
}
|
||||
|
||||
/* the class is after the menu name */
|
||||
int dialog_get_class(gen_res* attr)
|
||||
{
|
||||
int offs=dialog_get_menu(attr);
|
||||
while(attr->res[offs]||(win32&&attr->res[offs+1]))offs+=win32?2:1;
|
||||
offs+=win32?2:1;
|
||||
return offs;
|
||||
}
|
||||
|
||||
/* the caption is after the class */
|
||||
int dialog_get_caption(gen_res* attr)
|
||||
{
|
||||
int offs=dialog_get_class(attr);
|
||||
while(attr->res[offs]||(win32&&attr->res[offs+1]))offs+=win32?2:1;
|
||||
offs+=win32?2:1;
|
||||
return offs;
|
||||
}
|
||||
|
||||
/* the fontsize, if present, is after the caption, followed by the font name */
|
||||
int dialog_get_fontsize(gen_res* attr)
|
||||
{
|
||||
int offs=dialog_get_caption(attr);
|
||||
while(attr->res[offs]||(win32&&attr->res[offs+1]))offs+=win32?2:1;
|
||||
offs+=win32?2:1;
|
||||
return offs;
|
||||
}
|
||||
|
||||
|
||||
/* the CAPTION option was specified */
|
||||
gen_res* dialog_caption(char* cap, gen_res*attr)
|
||||
{
|
||||
/* we don't need the terminating 0 as it's already there */
|
||||
return insert_string(attr,cap,dialog_get_caption(attr),0);
|
||||
}
|
||||
|
||||
|
||||
/* the FONT option was specified, set the DS_SETFONT flag */
|
||||
gen_res* dialog_font(short size,char* font,gen_res *attr)
|
||||
{
|
||||
char c_size[2];
|
||||
int offs=dialog_get_fontsize(attr);
|
||||
put_DWORD(attr->res,get_DWORD(attr->res)|DS_SETFONT);
|
||||
put_WORD(c_size,size);
|
||||
attr=insert_bytes(attr,c_size,offs,2);
|
||||
offs+=2;
|
||||
/* as there is no font name by default, copy the '\0' */
|
||||
return insert_string(attr,font,offs,1);
|
||||
}
|
||||
|
||||
gen_res* dialog_class(char* cap, gen_res*attr)
|
||||
{
|
||||
return insert_string(attr,cap,dialog_get_class(attr),0);
|
||||
}
|
||||
|
||||
gen_res* dialog_menu_id(short nr, gen_res*attr)
|
||||
{
|
||||
char c_nr[2];
|
||||
int offs=dialog_get_menu(attr);
|
||||
attr->res[offs] = 0xff;
|
||||
if (win32) attr->res[offs+1] = 0xff;
|
||||
put_WORD(c_nr,nr);
|
||||
return insert_bytes(attr,c_nr,offs+(win32?2:1),2);
|
||||
}
|
||||
gen_res* dialog_menu_str(char* cap, gen_res*attr)
|
||||
{
|
||||
return insert_string(attr,cap,dialog_get_menu(attr),0);
|
||||
}
|
||||
|
||||
/* set the dialogs id, position, extent, and style */
|
||||
gen_res* create_control_desc(int id,int x,int y,int cx, int cy,rc_style *style)
|
||||
{ gen_res* ret=new_res();
|
||||
int s=WS_VISIBLE|WS_CHILD; /*defaults styles for any control*/
|
||||
if(win32)
|
||||
{
|
||||
if(style)s=(s|style->or)&style->and;
|
||||
put_DWORD(ret->res+0,s);
|
||||
/* FIXME */
|
||||
/* put_WORD(ret->res+4, exStyle); */
|
||||
put_WORD(ret->res+8,x);
|
||||
put_WORD(ret->res+10,y);
|
||||
put_WORD(ret->res+12,cx);
|
||||
put_WORD(ret->res+14,cy);
|
||||
put_WORD(ret->res+16,id);
|
||||
ret->size=24; /*empty strings, unused byte*/
|
||||
}
|
||||
else
|
||||
{
|
||||
put_WORD(ret->res+0,x);
|
||||
put_WORD(ret->res+2,y);
|
||||
put_WORD(ret->res+4,cx);
|
||||
put_WORD(ret->res+6,cy);
|
||||
put_WORD(ret->res+8,id);
|
||||
if(style)s=(s|style->or)&style->and;
|
||||
put_DWORD(ret->res+10,s);
|
||||
ret->size=17; /*empty strings, unused byte*/
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* insert the control's label */
|
||||
gen_res* label_control_desc(char* label,gen_res* cd)
|
||||
{
|
||||
int offs;
|
||||
if(win32) {
|
||||
if(get_WORD(cd->res+18)==0xffff)offs=20; /* one-character class */
|
||||
else {
|
||||
for(offs=18;get_WORD(cd->res+offs);offs+=2);
|
||||
offs+=2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(cd->res[14]&0x80)offs=15; /* one-character class */
|
||||
else {
|
||||
for(offs=14;cd->res[offs];offs++);
|
||||
offs++;
|
||||
}
|
||||
}
|
||||
return insert_string(cd,label,offs,0);
|
||||
}
|
||||
|
||||
/* a CONTROL was specified */
|
||||
gen_res* create_generic_control(char* label,int id,char* class,
|
||||
rc_style*style,int x,int y,int cx,int cy)
|
||||
{ gen_res* ret=new_res();
|
||||
int s=WS_VISIBLE|WS_CHILD; /*default styles for any control*/
|
||||
if(style)s=(s|style->or)&style->and;
|
||||
if(win32)
|
||||
{
|
||||
WORD cl;
|
||||
put_DWORD(ret->res+0,s);
|
||||
/* FIXME */
|
||||
/* put_DWORD(ret->res+4,exstyle->or); */
|
||||
put_WORD(ret->res+8,x);
|
||||
put_WORD(ret->res+10,y);
|
||||
put_WORD(ret->res+12,cx);
|
||||
put_WORD(ret->res+14,cy);
|
||||
put_WORD(ret->res+16,id);
|
||||
ret->size=24;
|
||||
ret=insert_string(ret,label,20,0);
|
||||
/* is it a predefined class? */
|
||||
cl=0;
|
||||
if(!strcasecmp(class,"BUTTON"))cl=CT_BUTTON;
|
||||
if(!strcasecmp(class,"EDIT"))cl=CT_EDIT;
|
||||
if(!strcasecmp(class,"STATIC"))cl=CT_STATIC;
|
||||
if(!strcasecmp(class,"LISTBOX"))cl=CT_LISTBOX;
|
||||
if(!strcasecmp(class,"SCROLLBAR"))cl=CT_SCROLLBAR;
|
||||
if(!strcasecmp(class,"COMBOBOX"))cl=CT_COMBOBOX;
|
||||
if(cl) {
|
||||
char ffff[2]={0xff, 0xff};
|
||||
ret=insert_bytes(ret,ffff,18,2);
|
||||
put_WORD(ret->res+20,cl);
|
||||
}
|
||||
else ret=insert_string(ret,class,18,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
char cl;
|
||||
put_WORD(ret->res+0,x);
|
||||
put_WORD(ret->res+2,y);
|
||||
put_WORD(ret->res+4,cx);
|
||||
put_WORD(ret->res+6,cy);
|
||||
put_WORD(ret->res+8,id);
|
||||
put_DWORD(ret->res+10,s);
|
||||
ret->size=17;
|
||||
ret=insert_string(ret,label,15,0);
|
||||
/* is it a predefined class? */
|
||||
cl=0;
|
||||
if(!strcasecmp(class,"BUTTON"))cl=CT_BUTTON;
|
||||
if(!strcasecmp(class,"EDIT"))cl=CT_EDIT;
|
||||
if(!strcasecmp(class,"STATIC"))cl=CT_STATIC;
|
||||
if(!strcasecmp(class,"LISTBOX"))cl=CT_LISTBOX;
|
||||
if(!strcasecmp(class,"SCROLLBAR"))cl=CT_SCROLLBAR;
|
||||
if(!strcasecmp(class,"COMBOBOX"))cl=CT_COMBOBOX;
|
||||
if(cl)ret->res[14]=cl;
|
||||
else ret=insert_string(ret,class,14,0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* insert cd into rest, set the type, add flags */
|
||||
gen_res* add_control(int type,int flags,gen_res*cd,gen_res* rest)
|
||||
{
|
||||
char zeros[4]={0,0,0,0};
|
||||
if(win32)
|
||||
{
|
||||
char ffff[2]={0xff, 0xff};
|
||||
put_DWORD(cd->res+0,get_DWORD(cd->res+0)|flags);
|
||||
cd=insert_bytes(cd,ffff,18,2);
|
||||
put_WORD(cd->res+20,type);
|
||||
}
|
||||
else
|
||||
{
|
||||
put_DWORD(cd->res+10,get_DWORD(cd->res+10)|flags);
|
||||
cd->res[14]=type;
|
||||
}
|
||||
/* WIN32: First control is on dword boundary */
|
||||
if(win32 && cd->size%4)
|
||||
cd=insert_bytes(cd,zeros,cd->size,4-cd->size%4);
|
||||
return insert_at_beginning(rest,cd->res,cd->size);
|
||||
}
|
||||
|
||||
/* an ICON control was specified, whf contains width, height, and flags */
|
||||
gen_res* add_icon(char* name,int id,int x,int y,gen_res* whf,gen_res* rest)
|
||||
{
|
||||
if (win32)
|
||||
{
|
||||
put_WORD(whf->res+8,x);
|
||||
put_WORD(whf->res+10,y);
|
||||
put_WORD(whf->res+16,id);
|
||||
}
|
||||
else
|
||||
{
|
||||
put_WORD(whf->res+0,x);
|
||||
put_WORD(whf->res+2,y);
|
||||
put_WORD(whf->res+8,id);
|
||||
}
|
||||
whf=label_control_desc(name,whf);
|
||||
return add_control(CT_STATIC,SS_ICON,whf,rest);
|
||||
}
|
||||
|
||||
/* insert the generic control into rest */
|
||||
gen_res* add_generic_control(gen_res* ctl, gen_res* rest)
|
||||
{
|
||||
char zeros[4]={0,0,0,0};
|
||||
/* WIN32: Control is on dword boundary */
|
||||
if(win32 && ctl->size%4)
|
||||
ctl=insert_bytes(ctl,zeros,ctl->size,4-ctl->size%4);
|
||||
return insert_at_beginning(rest,ctl->res,ctl->size);
|
||||
}
|
||||
|
||||
/* create a dialog resource by inserting the header into the controls.
|
||||
Set position and extent */
|
||||
gen_res* make_dialog(gen_res* header,int x,int y,int cx,int cy,gen_res* ctls)
|
||||
{
|
||||
char zeros[4]={0,0,0,0};
|
||||
if(win32)
|
||||
{
|
||||
put_WORD(header->res+8, ctls->num_entries);
|
||||
header->type=dlg;
|
||||
put_WORD(header->res+10,x);
|
||||
put_WORD(header->res+12,y);
|
||||
put_WORD(header->res+14,cx);
|
||||
put_WORD(header->res+16,cy);
|
||||
}
|
||||
else
|
||||
{
|
||||
header->res[4]=ctls->num_entries;
|
||||
header->type=dlg;
|
||||
put_WORD(header->res+5,x);
|
||||
put_WORD(header->res+7,y);
|
||||
put_WORD(header->res+9,cx);
|
||||
put_WORD(header->res+11,cy);
|
||||
}
|
||||
/* WIN32: First control is on dword boundary */
|
||||
if(win32 && header->size%4)
|
||||
header=insert_bytes(header,zeros,header->size,4-header->size%4);
|
||||
return insert_bytes(header,ctls->res,header->size,ctls->size);
|
||||
}
|
||||
|
||||
/* create {0x15,0x16,0xFF} from '15 16 FF' */
|
||||
gen_res *hex_to_raw(char *hex, gen_res*rest)
|
||||
{
|
||||
char r2[16];
|
||||
int i;
|
||||
for(i=0;*hex!='\'';i++)r2[i]=strtoul(hex,&hex,16);
|
||||
return insert_bytes(rest,r2,0,i);
|
||||
}
|
||||
|
||||
/* create a bitmap resource */
|
||||
gen_res *make_bitmap(gen_res* res)
|
||||
{
|
||||
res=delete_bytes(res,0,14); /* skip bitmap file header*/
|
||||
res->type=bmp;
|
||||
return res;
|
||||
}
|
||||
|
||||
gen_res *make_icon(gen_res* res)
|
||||
{
|
||||
res->type=ico;
|
||||
return res;
|
||||
}
|
||||
|
||||
gen_res *make_cursor(gen_res* res)
|
||||
{
|
||||
res->type=cur;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* load resource bytes from the file name */
|
||||
gen_res *load_file(char* name)
|
||||
{
|
||||
gen_res *res;
|
||||
struct stat st;
|
||||
int f=open(name,O_RDONLY);
|
||||
if(f<0)
|
||||
{
|
||||
perror(name);
|
||||
exit(1);
|
||||
}
|
||||
fstat(f,&st);
|
||||
res=new_res();
|
||||
while(res->space<st.st_size)res=grow(res);
|
||||
read(f,res->res,st.st_size);
|
||||
res->size=st.st_size;
|
||||
close(f);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* insert a normal menu item into res, starting from the last item */
|
||||
gen_res *add_menuitem(char* name,int id,int flags,gen_res *res)
|
||||
{
|
||||
char item[4];
|
||||
if(res->num_entries==0)flags|=MF_END;
|
||||
put_WORD(item,flags);
|
||||
put_WORD(item+2,id);
|
||||
res=insert_string_at_beginning(res,name,1);
|
||||
res=insert_bytes(res,item,0,4);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* insert a popup item into res */
|
||||
gen_res *add_popup(char *name,short flags, gen_res* body, gen_res*res)
|
||||
{
|
||||
char c_flags[2];
|
||||
flags|=MF_POPUP;
|
||||
if(res->num_entries==0)flags|=MF_END;
|
||||
put_WORD(c_flags,flags);
|
||||
res=insert_at_beginning(res,body->res,body->size);
|
||||
res=insert_string(res,name,0,1);
|
||||
res=insert_bytes(res,c_flags,0,2);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* prefix the menu header into res */
|
||||
gen_res *make_menu(gen_res* res)
|
||||
{
|
||||
static char header[4]={0,0,0,0};
|
||||
res=insert_at_beginning(res,header,4);
|
||||
res->type=men;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* link top-level resources */
|
||||
gen_res *add_resource(gen_res* first,gen_res *rest)
|
||||
{
|
||||
if(first)
|
||||
{
|
||||
first->next=rest;
|
||||
return first;
|
||||
}
|
||||
else
|
||||
return rest;
|
||||
}
|
||||
|
||||
typedef struct str_tbl_elm{
|
||||
int group;
|
||||
struct str_tbl_elm *next;
|
||||
char* strings[16];
|
||||
} str_tbl_elm;
|
||||
|
||||
str_tbl_elm* string_table=NULL; /* sorted by group */
|
||||
|
||||
void add_str_tbl_elm(int id,char* str)
|
||||
{
|
||||
int group=(id>>4)+1;
|
||||
int idx=id & 0x000f;
|
||||
|
||||
str_tbl_elm** elm=&string_table;
|
||||
while(*elm && (*elm)->group<group) elm=&(*elm)->next;
|
||||
if(!*elm || (*elm)->group!=group)
|
||||
{
|
||||
int i;
|
||||
str_tbl_elm* new=xmalloc(sizeof(str_tbl_elm));
|
||||
for(i=0; i<16; i++) new->strings[i] = NULL;
|
||||
new->group=group;
|
||||
new->next=*elm;
|
||||
*elm=new;
|
||||
}
|
||||
(*elm)->strings[idx]=str;
|
||||
}
|
||||
|
||||
gen_res* add_string_table(gen_res* t)
|
||||
{
|
||||
str_tbl_elm* ste;
|
||||
int size,i;
|
||||
gen_res* res;
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
||||
if(!string_table) return t;
|
||||
for(ste=string_table; ste; ste=ste->next)
|
||||
{
|
||||
for(size=0,i=0; i<16; i++)
|
||||
size += (win32 ? 2 : 1) * (ste->strings[i] ? strlen(ste->strings[i])+1 : 1);
|
||||
res=new_res();
|
||||
while(res->space<size)res=grow(res);
|
||||
res->type=str;
|
||||
res->n.i_name=ste->group;
|
||||
res->n_type=0;
|
||||
res->size=size;
|
||||
if (win32)
|
||||
for(p=res->res,i=0; i<16; i++)
|
||||
if((q=ste->strings[i])==NULL)
|
||||
{
|
||||
put_WORD(p, 0);
|
||||
p+=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
put_WORD(p, strlen(q));
|
||||
p+=2;
|
||||
while(*q)
|
||||
{
|
||||
put_WORD(p, *q++);
|
||||
p+=2;
|
||||
}
|
||||
}
|
||||
else
|
||||
for(p=res->res,i=0; i<16; i++)
|
||||
if((q=ste->strings[i])==NULL)
|
||||
*p++ = 0;
|
||||
else
|
||||
{
|
||||
*p++ = strlen(q);
|
||||
while(*q) *p++ = *q++;
|
||||
}
|
||||
t=add_resource(res,t);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
char *get_typename(gen_res* t)
|
||||
{
|
||||
switch(t->type){
|
||||
case acc:return "ACCELERATOR";
|
||||
case bmp:return "BITMAP";
|
||||
case cur:return "CURSOR";
|
||||
case dlg:return "DIALOG";
|
||||
case fnt:return "FONT";
|
||||
case ico:return "ICON";
|
||||
case men:return "MENU";
|
||||
case rdt:return "RCDATA";
|
||||
case str:return "STRINGTABLE";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
/* create strings like _Sysres_DIALOG_2 */
|
||||
char *get_resource_name(gen_res*it)
|
||||
{
|
||||
static char buf[1000];
|
||||
if(it->n_type)
|
||||
sprintf(buf,"%s_%s_%s",prefix,get_typename(it),it->n.s_name);
|
||||
else
|
||||
sprintf(buf,"%s_%s_%d",prefix,get_typename(it),it->n.i_name);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define ISCONSTANT (constant ? "const " : "")
|
||||
|
||||
/* create the final output */
|
||||
void create_output(gen_res* top)
|
||||
{
|
||||
gen_res *it;
|
||||
|
||||
top=add_string_table(top);
|
||||
|
||||
/* Generate the header */
|
||||
|
||||
if (header)
|
||||
{
|
||||
fprintf( header,
|
||||
"/*\n"
|
||||
" * This file is automatically generated. Do not edit!\n"
|
||||
" */\n\n"
|
||||
"#ifndef __%s_H\n"
|
||||
"#define __%s_H\n\n"
|
||||
"struct resource;\n\n",
|
||||
prefix, prefix );
|
||||
|
||||
/* Declare the resources */
|
||||
for (it=top;it;it=it->next)
|
||||
fprintf( header,"extern %sstruct resource %s;\n",
|
||||
ISCONSTANT, get_resource_name(it) );
|
||||
fprintf( header,"\nextern %sstruct resource * %s%s_Table[];\n\n",
|
||||
ISCONSTANT, ISCONSTANT, prefix );
|
||||
fprintf( header, "#endif /* __%s_H */\n", prefix );
|
||||
}
|
||||
|
||||
/* Print the resources bytes */
|
||||
|
||||
fprintf( code, "/*\n"
|
||||
" * This file is automatically generated. Do not edit!\n"
|
||||
" */\n\n"
|
||||
"struct resource {\n"
|
||||
"\tint id;\n"
|
||||
"\tint type;\n"
|
||||
"\tconst char *name;\n"
|
||||
"\tconst unsigned char* bytes;\n"
|
||||
"\tunsigned size;\n"
|
||||
"};\n\n" );
|
||||
|
||||
for(it=top;it;it=it->next)
|
||||
{
|
||||
int i;
|
||||
fprintf( code, "static %sunsigned char %s__bytes[]%s = {\n",
|
||||
ISCONSTANT, get_resource_name(it),
|
||||
win32?"\n__attribute__ ((aligned (4)))":"");
|
||||
for (i=0;i<it->size-1;i++)
|
||||
{
|
||||
fprintf(code,"0x%02x, ",it->res[i]);
|
||||
if ((i&7)==7)fputc('\n',code);
|
||||
}
|
||||
fprintf(code,"0x%02x };\n\n",it->res[i]);
|
||||
}
|
||||
|
||||
/* Print the resources names */
|
||||
|
||||
if (win32)
|
||||
for(it=top;it;it=it->next)
|
||||
{
|
||||
int i;
|
||||
char s_buffer[20], *s_name=s_buffer;
|
||||
if(it->n_type) s_name=it->n.s_name;
|
||||
else sprintf(s_name,"@%d",it->n.i_name);
|
||||
fprintf( code, "static %sunsigned char %s__name[] = {\n",
|
||||
ISCONSTANT, get_resource_name(it) );
|
||||
for (i=0;*s_name;i++,s_name++)
|
||||
{
|
||||
fprintf(code,"0x%02x, 0x00, ",*s_name);
|
||||
if ((i&3)==3)fputc('\n',code);
|
||||
}
|
||||
fprintf(code,"0x00, 0x00};\n\n");
|
||||
}
|
||||
|
||||
/* Print the resources */
|
||||
for (it=top;it;it=it->next)
|
||||
{
|
||||
int type;
|
||||
switch(it->type)
|
||||
{
|
||||
case acc:type=(int)RT_ACCELERATOR16;break;
|
||||
case bmp:type=(int)RT_BITMAP16;break;
|
||||
case cur:type=(int)RT_CURSOR16;break;
|
||||
case dlg:type=(int)RT_DIALOG16;break;
|
||||
case fnt:type=(int)RT_FONT16;break;
|
||||
case ico:type=(int)RT_ICON16;break;
|
||||
case men:type=(int)RT_MENU16;break;
|
||||
case rdt:type=(int)RT_RCDATA16;break;
|
||||
case str:type=(int)RT_STRING16;break;
|
||||
default:fprintf(stderr,"Unknown restype\n");type=-1;break;
|
||||
}
|
||||
if(win32)
|
||||
{
|
||||
if(it->n_type)
|
||||
fprintf(code,"%sstruct resource %s = {0,%d,%s__name,%s__bytes,%d};\n",
|
||||
ISCONSTANT, get_resource_name(it), type, get_resource_name(it),
|
||||
get_resource_name(it), it->size );
|
||||
else
|
||||
fprintf(code,"%sstruct resource %s = {%d,%d,%s__name,%s__bytes,%d};\n",
|
||||
ISCONSTANT, get_resource_name(it), it->n.i_name, type,
|
||||
get_resource_name(it), get_resource_name(it), it->size );
|
||||
}
|
||||
else
|
||||
{
|
||||
if(it->n_type)
|
||||
fprintf(code,"%sstruct resource %s = {0,%d,\"%s\",%s__bytes,%d};\n",
|
||||
ISCONSTANT, get_resource_name(it), type, it->n.s_name,
|
||||
get_resource_name(it), it->size );
|
||||
else
|
||||
fprintf(code,"%sstruct resource %s = {%d,%d,\"@%d\",%s__bytes,%d};\n",
|
||||
ISCONSTANT, get_resource_name(it), it->n.i_name, type,
|
||||
it->n.i_name, get_resource_name(it), it->size );
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the resource table (NULL terminated) */
|
||||
|
||||
fprintf(code,"\n%sstruct resource * %s%s_Table[] = {\n",
|
||||
ISCONSTANT, ISCONSTANT, prefix);
|
||||
for (it=top;it;it=it->next)
|
||||
fprintf( code, " &%s,\n", get_resource_name(it) );
|
||||
fprintf( code, " 0\n};\n\n\n" );
|
||||
|
||||
/* Perform autoregistration */
|
||||
fprintf( code,
|
||||
"#ifndef __WINE__\n"
|
||||
"#if defined(__GNUC__) && ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7)))\n"
|
||||
"static void DoIt(void) __attribute__((constructor));\n"
|
||||
"#else\n"
|
||||
"static void DoIt(void);\n"
|
||||
"void LIBWINE_Register_%s(void) { DoIt(); }\n"
|
||||
"#endif\n"
|
||||
"static void DoIt(void)\n"
|
||||
"{\n"
|
||||
"\textern void LIBRES_RegisterResources(const struct resource* const * Res);\n"
|
||||
"\tLIBRES_RegisterResources(%s_Table);\n"
|
||||
"}\n\n"
|
||||
"#endif /* __WINE__ */\n"
|
||||
,prefix,prefix);
|
||||
}
|
||||
|
||||
gen_res* make_font(gen_res* res)
|
||||
{
|
||||
fprintf(stderr,"Fonts not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gen_res* make_raw(gen_res* res)
|
||||
{
|
||||
fprintf(stderr,"RCData not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gen_res* int_to_raw(int i,gen_res* res)
|
||||
{
|
||||
fprintf(stderr,"IntToRaw not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* translate "Hello,\\tworld!\\10" to "Hello,\tworld!\n" */
|
||||
char *parse_c_string(char *in)
|
||||
{
|
||||
char *out=xmalloc(strlen(in)-1);
|
||||
char *it;
|
||||
char tmp[5],*tend;
|
||||
for(it=out,in++;*in;in++)
|
||||
if(*in=='\\')
|
||||
switch(*++in)
|
||||
{case 't':*it++='\t';break;
|
||||
case 'r':*it++='\r';break;
|
||||
case 'n':*it++='\n';break;
|
||||
case 'a':*it++='\a';break;
|
||||
case '0':
|
||||
memset(tmp,0,5);/*make sure it doesn't use more than 4 chars*/
|
||||
memcpy(tmp,in,4);
|
||||
*it++=strtoul(tmp,&tend,0);
|
||||
in+=tend-tmp-1;
|
||||
break;
|
||||
case '1':case '2':case '3':case '4':case '5':
|
||||
case '6':case '7':case '8':case '9':
|
||||
memset(tmp,0,5);
|
||||
memcpy(tmp,in,3);
|
||||
*it++=strtoul(tmp,&tend,10);
|
||||
in+=tend-tmp-1;
|
||||
break;
|
||||
case 'x':
|
||||
memset(tmp,0,5);
|
||||
memcpy(tmp,++in,2);
|
||||
*it++=strtoul(tmp,&tend,16);
|
||||
in+=tend-tmp-1;
|
||||
break;
|
||||
default:*it++=*in;
|
||||
}
|
||||
else
|
||||
*it++=*in;
|
||||
*(it-1)='\0';
|
||||
return out;
|
||||
}
|
Loading…
Reference in New Issue