source: trunk/tools/wrc/parser.y@ 3669

Last change on this file since 3669 was 3426, checked in by sandervl, 25 years ago

update with latest wine code

File size: 65.0 KB
Line 
1%{
2/*
3 * Copyright Martin von Loewis, 1994
4 * Copyright 1998 Bertho A. Stultiens (BS)
5 * 1999 Juergen Schmied (JS)
6 *
7 * 6-Nov-1999 JS - see CHANGES
8 *
9 * 29-Dec-1998 AdH - Grammar and function extensions.
10 * grammar: TOOLBAR resources, Named ICONs in
11 * DIALOGS
12 * functions: semantic actions for the grammar
13 * changes, resource files can now be anywhere
14 * on the include path instead of just in the
15 * current directory
16 *
17 * 20-Jun-1998 BS - Fixed a bug in load_file() where the name was not
18 * printed out correctly.
19 *
20 * 17-Jun-1998 BS - Fixed a bug in CLASS statement parsing which should
21 * also accept a tSTRING as argument.
22 *
23 * 25-May-1998 BS - Found out that I need to support language, version
24 * and characteristics in inline resources (bitmap,
25 * cursor, etc) but they can also be specified with
26 * a filename. This renders my filename-scanning scheme
27 * worthless. Need to build newline parsing to solve
28 * this one.
29 * It will come with version 1.1.0 (sigh).
30 *
31 * 19-May-1998 BS - Started to build a builtin preprocessor
32 *
33 * 30-Apr-1998 BS - Redid the stringtable parsing/handling. My previous
34 * ideas had some serious flaws.
35 *
36 * 27-Apr-1998 BS - Removed a lot of dead comments and put it in a doc
37 * file.
38 *
39 * 21-Apr-1998 BS - Added correct behavior for cursors and icons.
40 * - This file is growing too big. It is time to strip
41 * things and put it in a support file.
42 *
43 * 19-Apr-1998 BS - Tagged the stringtable resource so that only one
44 * resource will be created. This because the table
45 * has a different layout than other resources. The
46 * table has to be sorted, and divided into smaller
47 * resource entries (see comment in source).
48 *
49 * 17-Apr-1998 BS - Almost all strings, including identifiers, are parsed
50 * as string_t which include unicode strings upon
51 * input.
52 * - Parser now emits a warning when compiling win32
53 * extensions in win16 mode.
54 *
55 * 16-Apr-1998 BS - Raw data elements are now *optionally* seperated
56 * by commas. Read the comments in file sq2dq.l.
57 * - FIXME: there are instances in the source that rely
58 * on the fact that int==32bit and pointers are int size.
59 * - Fixed the conflict in menuex by changing a rule
60 * back into right recursion. See note in source.
61 * - UserType resources cannot have an expression as its
62 * typeclass. See note in source.
63 *
64 * 15-Apr-1998 BS - Changed all right recursion into left recursion to
65 * get reduction of the parsestack.
66 * This also helps communication between bison and flex.
67 * Main advantage is that the Empty rule gets reduced
68 * first, which is used to allocate/link things.
69 * It also added a shift/reduce conflict in the menuex
70 * handling, due to expression/option possibility,
71 * although not serious.
72 *
73 * 14-Apr-1998 BS - Redone almost the entire parser. We're not talking
74 * about making it more efficient, but readable (for me)
75 * and slightly easier to expand/change.
76 * This is done primarily by using more reduce states
77 * with many (intuitive) types for the various resource
78 * statements.
79 * - Added expression handling for all resources where a
80 * number is accepted (not only for win32). Also added
81 * multiply and division (not MS compatible, but handy).
82 * Unary minus introduced a shift/reduce conflict, but
83 * it is not serious.
84 *
85 * 13-Apr-1998 BS - Reordered a lot of things
86 * - Made the source more readable
87 * - Added Win32 resource definitions
88 * - Corrected syntax problems with an old yacc (;)
89 * - Added extra comment about grammar
90 */
91#include "config.h"
92
93#include <stdio.h>
94#include <stdlib.h>
95#include <stdarg.h>
96#include <assert.h>
97#include <ctype.h>
98#include <string.h>
99#ifdef HAVE_ALLOCA_H
100#include <alloca.h>
101#endif
102
103#include "wrc.h"
104#include "utils.h"
105#include "newstruc.h"
106#include "dumpres.h"
107#include "preproc.h"
108#include "parser.h"
109#include "windef.h"
110#include "wingdi.h"
111#include "winuser.h"
112
113#ifdef __BORLANDC__
114#pragma warn -sig
115#endif
116
117int indialog = 0; /* Signal flex that we're parsing a dialog */
118int want_rscname = 0; /* Set when a resource's name is required */
119stringtable_t *tagstt; /* Stringtable tag.
120 * It is set while parsing a stringtable to one of
121 * the stringtables in the sttres list or a new one
122 * if the language was not parsed before.
123 */
124stringtable_t *sttres; /* Stringtable resources. This holds the list of
125 * stringtables with different lanuages
126 */
127/* Set to the current options of the currently scanning stringtable */
128static int *tagstt_memopt;
129static characts_t *tagstt_characts;
130static version_t *tagstt_version;
131
132/* Prototypes of here defined functions */
133void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur);
134void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico);
135int alloc_cursor_id(language_t *);
136int alloc_icon_id(language_t *);
137void ins_stt_entry(stt_entry_t *ste);
138int check_stt_entry(stringtable_t *tabs, stt_entry_t *ste);
139event_t *get_event_head(event_t *p);
140control_t *get_control_head(control_t *p);
141ver_value_t *get_ver_value_head(ver_value_t *p);
142ver_block_t *get_ver_block_head(ver_block_t *p);
143resource_t *get_resource_head(resource_t *p);
144menuex_item_t *get_itemex_head(menuex_item_t *p);
145menu_item_t *get_item_head(menu_item_t *p);
146raw_data_t *merge_raw_data_str(raw_data_t *r1, string_t *str);
147raw_data_t *merge_raw_data_int(raw_data_t *r1, int i);
148raw_data_t *merge_raw_data_long(raw_data_t *r1, int i);
149raw_data_t *merge_raw_data(raw_data_t *r1, raw_data_t *r2);
150raw_data_t *str2raw_data(string_t *str);
151raw_data_t *int2raw_data(int i);
152raw_data_t *long2raw_data(int i);
153raw_data_t *load_file(string_t *name);
154itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid);
155event_t *add_string_event(string_t *key, int id, int flags, event_t *prev);
156event_t *add_event(int key, int id, int flags, event_t *prev);
157dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg);
158dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg);
159dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg);
160dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg);
161dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg);
162dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg);
163dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg);
164dialogex_t *dialogex_exstyle(style_t *st, dialogex_t *dlg);
165dialogex_t *dialogex_style(style_t *st, dialogex_t *dlg);
166name_id_t *convert_ctlclass(name_id_t *cls);
167control_t *ins_ctrl(int type, int special_style, control_t *ctrl, control_t *prev);
168dialog_t *dialog_version(version_t *v, dialog_t *dlg);
169dialog_t *dialog_characteristics(characts_t *c, dialog_t *dlg);
170dialog_t *dialog_language(language_t *l, dialog_t *dlg);
171dialog_t *dialog_menu(name_id_t *m, dialog_t *dlg);
172dialog_t *dialog_class(name_id_t *n, dialog_t *dlg);
173dialog_t *dialog_font(font_id_t *f, dialog_t *dlg);
174dialog_t *dialog_caption(string_t *s, dialog_t *dlg);
175dialog_t *dialog_exstyle(style_t * st, dialog_t *dlg);
176dialog_t *dialog_style(style_t * st, dialog_t *dlg);
177resource_t *build_stt_resources(stringtable_t *stthead);
178stringtable_t *find_stringtable(lvc_t *lvc);
179toolbar_item_t *ins_tlbr_button(toolbar_item_t *prev, toolbar_item_t *idrec);
180toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems);
181
182%}
183%union{
184 string_t *str;
185 int num;
186 int *iptr;
187 resource_t *res;
188 accelerator_t *acc;
189 bitmap_t *bmp;
190 cursor_t *cur;
191 cursor_group_t *curg;
192 dialog_t *dlg;
193 dialogex_t *dlgex;
194 font_t *fnt;
195 icon_t *ico;
196 icon_group_t *icog;
197 menu_t *men;
198 menuex_t *menex;
199 rcdata_t *rdt;
200 stringtable_t *stt;
201 stt_entry_t *stte;
202 user_t *usr;
203 messagetable_t *msg;
204 versioninfo_t *veri;
205 control_t *ctl;
206 name_id_t *nid;
207 font_id_t *fntid;
208 language_t *lan;
209 version_t *ver;
210 characts_t *chars;
211 event_t *event;
212 menu_item_t *menitm;
213 menuex_item_t *menexitm;
214 itemex_opt_t *exopt;
215 raw_data_t *raw;
216 lvc_t *lvc;
217 ver_value_t *val;
218 ver_block_t *blk;
219 ver_words_t *verw;
220 toolbar_t *tlbar;
221 toolbar_item_t *tlbarItems;
222 dlginit_t *dginit;
223 style_pair_t *styles;
224 style_t *style;
225}
226
227%token tIF tIFDEF tIFNDEF tELSE tELIF tENDIF tDEFINED tNL
228%token tTYPEDEF tEXTERN
229%token <num> NUMBER LNUMBER
230%token <str> tSTRING IDENT FILENAME
231%token <raw> RAWDATA
232%token ACCELERATORS tBITMAP CURSOR DIALOG DIALOGEX MENU MENUEX MESSAGETABLE
233%token RCDATA VERSIONINFO STRINGTABLE FONT ICON
234%token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX DEFPUSHBUTTON
235%token PUSHBUTTON RADIOBUTTON STATE3 /* PUSHBOX */
236%token GROUPBOX COMBOBOX LISTBOX SCROLLBAR
237%token CONTROL EDITTEXT
238%token RTEXT CTEXT LTEXT
239%token BLOCK VALUE
240%token SHIFT ALT ASCII VIRTKEY GRAYED CHECKED INACTIVE NOINVERT
241%token tPURE IMPURE DISCARDABLE LOADONCALL PRELOAD tFIXED MOVEABLE
242%token CLASS CAPTION CHARACTERISTICS EXSTYLE STYLE VERSION LANGUAGE
243%token FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEOS FILETYPE FILEFLAGS FILESUBTYPE
244%token MENUBARBREAK MENUBREAK MENUITEM POPUP SEPARATOR
245%token HELP
246%token tSTRING IDENT RAWDATA
247%token TOOLBAR BUTTON
248%token tBEGIN tEND
249%token DLGINIT
250%left LOGOR
251%left LOGAND
252%left '|'
253%left '^'
254%left '&'
255%left EQ NE
256%left '<' LTE '>' GTE
257%left '+' '-'
258%left '*' '/'
259%right '~' '!' NOT
260
261%type <res> resource_file resource resources resource_definition
262%type <stt> stringtable strings
263%type <fnt> font
264%type <icog> icon
265%type <acc> accelerators
266%type <event> events
267%type <bmp> bitmap
268%type <curg> cursor
269%type <dlg> dialog dlg_attributes
270%type <ctl> ctrls gen_ctrl lab_ctrl ctrl_desc iconinfo
271%type <iptr> helpid
272%type <dlgex> dialogex dlgex_attribs
273%type <ctl> exctrls gen_exctrl lab_exctrl exctrl_desc
274%type <rdt> rcdata
275%type <raw> raw_data raw_elements opt_data
276%type <veri> versioninfo fix_version
277%type <verw> ver_words
278%type <blk> ver_blocks ver_block
279%type <val> ver_values ver_value
280%type <men> menu
281%type <menitm> item_definitions menu_body
282%type <menex> menuex
283%type <menexitm> itemex_definitions menuex_body
284%type <exopt> itemex_p_options itemex_options
285%type <msg> messagetable
286%type <usr> userres
287%type <num> item_options
288%type <nid> nameid nameid_s ctlclass usertype
289%type <num> acc_opt
290%type <iptr> loadmemopts lamo lama
291%type <fntid> opt_font opt_exfont opt_expr
292%type <lvc> opt_lvc
293%type <lan> opt_language
294%type <chars> opt_characts
295%type <ver> opt_version
296%type <num> expr xpr
297%type <iptr> e_expr
298%type <iptr> pp_expr pp_constant
299%type <tlbar> toolbar
300%type <tlbarItems> toolbar_items
301%type <dginit> dlginit
302%type <styles> optional_style_pair
303%type <num> any_num
304%type <style> optional_style
305%type <style> style
306
307%%
308
309resource_file
310 : resources {
311 resource_t *rsc;
312 /* First add stringtables to the resource-list */
313 rsc = build_stt_resources(sttres);
314 /* 'build_stt_resources' returns a head and $1 is a tail */
315 if($1)
316 {
317 $1->next = rsc;
318 if(rsc)
319 rsc->prev = $1;
320 }
321 else
322 $1 = rsc;
323 /* Final statement before were done */
324 resource_top = get_resource_head($1);
325 }
326 ;
327
328/* Resources are put into a linked list */
329resources
330 : /* Empty */ { $$ = NULL; want_rscname = 1; }
331 | resources resource {
332 if($2)
333 {
334 resource_t *tail = $2;
335 resource_t *head = $2;
336 while(tail->next)
337 tail = tail->next;
338 while(head->prev)
339 head = head->prev;
340 head->prev = $1;
341 if($1)
342 $1->next = head;
343 $$ = tail;
344 }
345 else if($1)
346 {
347 resource_t *tail = $1;
348 while(tail->next)
349 tail = tail->next;
350 $$ = tail;
351 }
352 else
353 $$ = NULL;
354 want_rscname = 1;
355 }
356 | resources preprocessor { $$ = $1; want_rscname = 1; }
357 | resources cjunk { $$ = $1; want_rscname = 1; }
358 ;
359
360/* The buildin preprocessor */
361preprocessor
362 : tIF pp_expr tNL { pop_start(); push_if($2 ? *($2) : 0, 0, 0); if($2) free($2);}
363 | tIFDEF IDENT tNL { pop_start(); push_if(pp_lookup($2->str.cstr) != NULL, 0, 0); }
364 | tIFNDEF IDENT tNL { pop_start(); push_if(pp_lookup($2->str.cstr) == NULL, 0, 0); }
365 | tELIF pp_expr tNL { pop_start(); push_if($2 ? *($2) : 0, pop_if(), 0); if($2) free($2); }
366 | tELSE tNL { pop_start(); push_if(1, pop_if(), 0); }
367 | tENDIF tNL { pop_if(); }
368 ;
369
370pp_expr : pp_constant { $$ = $1; }
371 | pp_expr LOGOR pp_expr { $$ = new_int($1 && $3 ? (*$1 || *$3) : 0); if($1) free($1); if($3) free($3); }
372 | pp_expr LOGAND pp_expr { $$ = new_int($1 && $3 ? (*$1 && *$3) : 0); if($1) free($1); if($3) free($3); }
373 | pp_expr '+' pp_expr { $$ = new_int($1 && $3 ? (*$1 + *$3) : 0); if($1) free($1); if($3) free($3); }
374 | pp_expr '-' pp_expr { $$ = new_int($1 && $3 ? (*$1 - *$3) : 0); if($1) free($1); if($3) free($3); }
375 | pp_expr '^' pp_expr { $$ = new_int($1 && $3 ? (*$1 ^ *$3) : 0); if($1) free($1); if($3) free($3); }
376 | pp_expr EQ pp_expr { $$ = new_int($1 && $3 ? (*$1 == *$3) : 0); if($1) free($1); if($3) free($3); }
377 | pp_expr NE pp_expr { $$ = new_int($1 && $3 ? (*$1 != *$3) : 0); if($1) free($1); if($3) free($3); }
378 | pp_expr '<' pp_expr { $$ = new_int($1 && $3 ? (*$1 < *$3) : 0); if($1) free($1); if($3) free($3); }
379 | pp_expr '>' pp_expr { $$ = new_int($1 && $3 ? (*$1 > *$3) : 0); if($1) free($1); if($3) free($3); }
380 | pp_expr LTE pp_expr { $$ = new_int($1 && $3 ? (*$1 <= *$3) : 0); if($1) free($1); if($3) free($3); }
381 | pp_expr GTE pp_expr { $$ = new_int($1 && $3 ? (*$1 >= *$3) : 0); if($1) free($1); if($3) free($3); }
382 | '~' pp_expr { $$ = $2; if($2) *$2 = ~(*$2); }
383 | '+' pp_expr { $$ = $2; }
384 | '-' pp_expr { $$ = $2; if($2) *$2 = -(*$2); }
385 | '!' pp_expr { $$ = $2; if($2) *$2 = !(*$2); }
386 | '(' pp_expr ')' { $$ = $2; }
387 ;
388
389pp_constant
390 : any_num { $$ = new_int($1); }
391 | IDENT { $$ = NULL; }
392 | tDEFINED IDENT { $$ = new_int(pp_lookup($2->str.cstr) != NULL); }
393 | tDEFINED '(' IDENT ')' { $$ = new_int(pp_lookup($3->str.cstr) != NULL); }
394 ;
395
396/* C ignore stuff */
397cjunk : tTYPEDEF { strip_til_semicolon(); }
398 | tEXTERN { strip_extern(); }
399 | IDENT IDENT { strip_til_semicolon(); }
400 | IDENT '(' { strip_til_parenthesis(); }
401 | IDENT '*' { strip_til_semicolon(); }
402 ;
403
404/* Parse top level resource definitions etc. */
405resource
406 : nameid resource_definition {
407 $$ = $2;
408 if($$)
409 {
410 $$->name = $1;
411 if($1->type == name_ord)
412 {
413 chat("Got %s (%d)",get_typename($2),$1->name.i_name);
414 }
415 else if($1->type == name_str)
416 {
417 chat("Got %s (%s)",get_typename($2),$1->name.s_name->str.cstr);
418 }
419 }
420 }
421 | stringtable {
422 /* Don't do anything, stringtables are converted to
423 * resource_t structures when we are finished parsing and
424 * the final rule of the parser is reduced (see above)
425 */
426 $$ = NULL;
427 chat("Got STRINGTABLE");
428 }
429 | opt_language {
430 if(!win32)
431 yywarning("LANGUAGE not supported in 16-bit mode");
432 if(currentlanguage)
433 free(currentlanguage);
434 currentlanguage = $1;
435 $$ = NULL;
436 }
437 ;
438
439/*
440 * Get a valid name/id
441 */
442nameid : expr {
443 if($1 > 65535 || $1 < -32768)
444 yyerror("Resource's ID out of range (%d)", $1);
445 $$ = new_name_id();
446 $$->type = name_ord;
447 $$->name.i_name = $1;
448 want_rscname = 0;
449 }
450 | IDENT {
451 $$ = new_name_id();
452 $$->type = name_str;
453 $$->name.s_name = $1;
454 want_rscname = 0;
455 }
456 ;
457
458/*
459 * Extra string recognition for CLASS statement in dialogs
460 */
461nameid_s: nameid { $$ = $1; }
462 | tSTRING {
463 $$ = new_name_id();
464 $$->type = name_str;
465 $$->name.s_name = $1;
466 want_rscname = 0;
467 }
468 ;
469
470/* get the value for a single resource*/
471resource_definition
472 : accelerators { $$ = new_resource(res_acc, $1, $1->memopt, $1->lvc.language); }
473 | bitmap { $$ = new_resource(res_bmp, $1, $1->memopt, dup_language(currentlanguage)); }
474 | cursor {
475 resource_t *rsc;
476 cursor_t *cur;
477 $$ = rsc = new_resource(res_curg, $1, $1->memopt, dup_language(currentlanguage));
478 for(cur = $1->cursorlist; cur; cur = cur->next)
479 {
480 rsc->prev = new_resource(res_cur, cur, $1->memopt, dup_language(currentlanguage));
481 rsc->prev->next = rsc;
482 rsc = rsc->prev;
483 rsc->name = new_name_id();
484 rsc->name->type = name_ord;
485 rsc->name->name.i_name = cur->id;
486 }
487 }
488 | dialog { $$ = new_resource(res_dlg, $1, $1->memopt, $1->lvc.language); }
489 | dialogex {
490 if(win32)
491 $$ = new_resource(res_dlgex, $1, $1->memopt, $1->lvc.language);
492 else
493 $$ = NULL;
494 }
495 | dlginit { $$ = new_resource(res_dlginit, $1, $1->memopt, $1->lvc.language); }
496 | font { $$ = new_resource(res_fnt, $1, $1->memopt, dup_language(currentlanguage)); }
497 | icon {
498 resource_t *rsc;
499 icon_t *ico;
500 $$ = rsc = new_resource(res_icog, $1, $1->memopt, dup_language(currentlanguage));
501 for(ico = $1->iconlist; ico; ico = ico->next)
502 {
503 rsc->prev = new_resource(res_ico, ico, $1->memopt, dup_language(currentlanguage));
504 rsc->prev->next = rsc;
505 rsc = rsc->prev;
506 rsc->name = new_name_id();
507 rsc->name->type = name_ord;
508 rsc->name->name.i_name = ico->id;
509 }
510 }
511 | menu { $$ = new_resource(res_men, $1, $1->memopt, $1->lvc.language); }
512 | menuex {
513 if(win32)
514 $$ = new_resource(res_menex, $1, $1->memopt, $1->lvc.language);
515 else
516 $$ = NULL;
517 }
518 | messagetable { $$ = new_resource(res_msg, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, dup_language(currentlanguage)); }
519 | rcdata { $$ = new_resource(res_rdt, $1, $1->memopt, $1->lvc.language); }
520 | toolbar { $$ = new_resource(res_toolbar, $1, $1->memopt, $1->lvc.language); }
521 | userres { $$ = new_resource(res_usr, $1, $1->memopt, dup_language(currentlanguage)); }
522 | versioninfo { $$ = new_resource(res_ver, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, dup_language(currentlanguage)); }
523 ;
524
525/* ------------------------------ Bitmap ------------------------------ */
526bitmap : tBITMAP loadmemopts FILENAME { $$ = new_bitmap(load_file($3), $2); }
527 | tBITMAP loadmemopts raw_data { $$ = new_bitmap($3, $2); }
528 ;
529
530/* ------------------------------ Cursor ------------------------------ */
531cursor : CURSOR loadmemopts FILENAME { $$ = new_cursor_group(load_file($3), $2); }
532 | CURSOR loadmemopts raw_data { $$ = new_cursor_group($3, $2); }
533 ;
534
535/* ------------------------------ Font ------------------------------ */
536/* FIXME: Should we allow raw_data here? */
537font : FONT loadmemopts FILENAME { $$ = new_font(load_file($3), $2); }
538 ;
539
540/* ------------------------------ Icon ------------------------------ */
541icon : ICON loadmemopts FILENAME { $$ = new_icon_group(load_file($3), $2); }
542 | ICON loadmemopts raw_data { $$ = new_icon_group($3, $2); }
543 ;
544
545/* ------------------------------ MessageTable ------------------------------ */
546/* It might be interesting to implement the MS Message compiler here as well
547 * to get everything in one source. Might be a future project.
548 */
549messagetable
550 : MESSAGETABLE FILENAME {
551 if(!win32)
552 yywarning("MESSAGETABLE not supported in 16-bit mode");
553 $$ = new_messagetable(load_file($2));
554 }
555 ;
556
557/* ------------------------------ RCData ------------------------------ */
558rcdata : RCDATA loadmemopts opt_lvc raw_data {
559 $$ = new_rcdata($4, $2);
560 if($3)
561 {
562 $$->lvc = *($3);
563 free($3);
564 }
565 if(!$$->lvc.language)
566 $$->lvc.language = dup_language(currentlanguage);
567 }
568 ;
569
570/* ------------------------------ DLGINIT ------------------------------ */
571dlginit : DLGINIT loadmemopts opt_lvc raw_data {
572 $$ = new_dlginit($4, $2);
573 if($3)
574 {
575 $$->lvc = *($3);
576 free($3);
577 }
578 if(!$$->lvc.language)
579 $$->lvc.language = dup_language(currentlanguage);
580 }
581 ;
582
583/* ------------------------------ UserType ------------------------------ */
584userres : usertype loadmemopts FILENAME { $$ = new_user($1, load_file($3), $2); }
585 | usertype loadmemopts raw_data { $$ = new_user($1, $3, $2); }
586 ;
587
588/* NOTE: This here is an exception where I do not allow an expression.
589 * Reason for this is that it is not possible to set the 'yywf' condition
590 * for flex if loadmemopts is empty. Reading an expression requires a
591 * lookahead to determine its end. In this case here, that would mean that
592 * the filename has been read as IDENT or tSTRING, which is incorrect.
593 * Note also that IDENT cannot be used as a file-name because it is lacking
594 * the '.'.
595 */
596
597/* I also allow string identifiers as classtypes. Not MS implemented, but
598 * seems to be reasonable to implement.
599 */
600/* Allowing anything else than NUMBER makes it very hard to get rid of
601 * prototypes. So, I remove IDENT to be able to get prototypes out of the
602 * world.
603 */
604usertype: NUMBER {
605 $$ = new_name_id();
606 $$->type = name_ord;
607 $$->name.i_name = $1;
608 set_yywf();
609 }
610/* | IDENT {
611 $$ = new_name_id();
612 $$->type = name_str;
613 $$->name.s_name = $1;
614 set_yywf();
615 }
616*/ | tSTRING {
617 $$ = new_name_id();
618 $$->type = name_str;
619 $$->name.s_name = $1;
620 set_yywf();
621 }
622 ;
623
624/* ------------------------------ Accelerator ------------------------------ */
625accelerators
626 : ACCELERATORS loadmemopts opt_lvc tBEGIN events tEND {
627 $$ = new_accelerator();
628 if($2)
629 {
630 $$->memopt = *($2);
631 free($2);
632 }
633 else
634 {
635 $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
636 }
637 if(!$5)
638 yyerror("Accelerator table must have at least one entry");
639 $$->events = get_event_head($5);
640 if($3)
641 {
642 $$->lvc = *($3);
643 free($3);
644 }
645 if(!$$->lvc.language)
646 $$->lvc.language = dup_language(currentlanguage);
647 }
648 ;
649
650events : /* Empty */ { $$=NULL; }
651 | events tSTRING ',' expr acc_opt { $$=add_string_event($2, $4, $5, $1); }
652 | events expr ',' expr acc_opt { $$=add_event($2, $4, $5, $1); }
653 ;
654
655acc_opt : /* Empty */ { $$=0; }
656 | acc_opt ',' NOINVERT { $$=$1 | WRC_AF_NOINVERT; }
657 | acc_opt ',' SHIFT { $$=$1 | WRC_AF_SHIFT; }
658 | acc_opt ',' CONTROL { $$=$1 | WRC_AF_CONTROL; }
659 | acc_opt ',' ALT { $$=$1 | WRC_AF_ALT; }
660 | acc_opt ',' ASCII { $$=$1 | WRC_AF_ASCII; }
661 | acc_opt ',' VIRTKEY { $$=$1 | WRC_AF_VIRTKEY; }
662 ;
663
664/* ------------------------------ Dialog ------------------------------ */
665/* FIXME: Support EXSTYLE in the dialog line itself */
666dialog : DIALOG loadmemopts expr ',' expr ',' expr ',' expr dlg_attributes
667 tBEGIN ctrls tEND {
668 if($2)
669 {
670 $10->memopt = *($2);
671 free($2);
672 }
673 else
674 $10->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
675 $10->x = $3;
676 $10->y = $5;
677 $10->width = $7;
678 $10->height = $9;
679 $10->controls = get_control_head($12);
680 $$ = $10;
681 if(!$$->gotstyle)
682 {
683 $$->style->or_mask = WS_POPUP;
684 $$->gotstyle = TRUE;
685 }
686 if($$->title)
687 $$->style->or_mask |= WS_CAPTION;
688 if($$->font)
689 $$->style->or_mask |= DS_SETFONT;
690
691 $$->style->or_mask &= ~($$->style->and_mask);
692 $$->style->and_mask = 0;
693
694 indialog = FALSE;
695 if(!$$->lvc.language)
696 $$->lvc.language = dup_language(currentlanguage);
697 }
698 ;
699
700dlg_attributes
701 : /* Empty */ { $$=new_dialog(); }
702 | dlg_attributes STYLE style { $$=dialog_style($3,$1); }
703 | dlg_attributes EXSTYLE style { $$=dialog_exstyle($3,$1); }
704 | dlg_attributes CAPTION tSTRING { $$=dialog_caption($3,$1); }
705 | dlg_attributes opt_font { $$=dialog_font($2,$1); }
706 | dlg_attributes CLASS nameid_s { $$=dialog_class($3,$1); }
707 | dlg_attributes MENU nameid { $$=dialog_menu($3,$1); }
708 | dlg_attributes opt_language { $$=dialog_language($2,$1); }
709 | dlg_attributes opt_characts { $$=dialog_characteristics($2,$1); }
710 | dlg_attributes opt_version { $$=dialog_version($2,$1); }
711 ;
712
713ctrls : /* Empty */ { $$ = NULL; }
714 | ctrls CONTROL gen_ctrl { $$=ins_ctrl(-1, 0, $3, $1); }
715 | ctrls EDITTEXT ctrl_desc { $$=ins_ctrl(CT_EDIT, 0, $3, $1); }
716 | ctrls LISTBOX ctrl_desc { $$=ins_ctrl(CT_LISTBOX, 0, $3, $1); }
717 | ctrls COMBOBOX ctrl_desc { $$=ins_ctrl(CT_COMBOBOX, 0, $3, $1); }
718 | ctrls SCROLLBAR ctrl_desc { $$=ins_ctrl(CT_SCROLLBAR, 0, $3, $1); }
719 | ctrls CHECKBOX lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_CHECKBOX, $3, $1); }
720 | ctrls DEFPUSHBUTTON lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_DEFPUSHBUTTON, $3, $1); }
721 | ctrls GROUPBOX lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_GROUPBOX, $3, $1);}
722 | ctrls PUSHBUTTON lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_PUSHBUTTON, $3, $1); }
723/* | ctrls PUSHBOX lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_PUSHBOX, $3, $1); } */
724 | ctrls RADIOBUTTON lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_RADIOBUTTON, $3, $1); }
725 | ctrls AUTO3STATE lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTO3STATE, $3, $1); }
726 | ctrls STATE3 lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_3STATE, $3, $1); }
727 | ctrls AUTOCHECKBOX lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTOCHECKBOX, $3, $1); }
728 | ctrls AUTORADIOBUTTON lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTORADIOBUTTON, $3, $1); }
729 | ctrls LTEXT lab_ctrl { $$=ins_ctrl(CT_STATIC, SS_LEFT, $3, $1); }
730 | ctrls CTEXT lab_ctrl { $$=ins_ctrl(CT_STATIC, SS_CENTER, $3, $1); }
731 | ctrls RTEXT lab_ctrl { $$=ins_ctrl(CT_STATIC, SS_RIGHT, $3, $1); }
732 /* special treatment for icons, as the extent is optional */
733 | ctrls ICON nameid_s opt_comma expr ',' expr ',' expr iconinfo {
734 $10->title = $3;
735 $10->id = $5;
736 $10->x = $7;
737 $10->y = $9;
738 $$ = ins_ctrl(CT_STATIC, SS_ICON, $10, $1);
739 }
740 ;
741
742lab_ctrl
743 : tSTRING opt_comma expr ',' expr ',' expr ',' expr ',' expr optional_style {
744 $$=new_control();
745 $$->title = new_name_id();
746 $$->title->type = name_str;
747 $$->title->name.s_name = $1;
748 $$->id = $3;
749 $$->x = $5;
750 $$->y = $7;
751 $$->width = $9;
752 $$->height = $11;
753 if($12)
754 {
755 $$->style = $12;
756 $$->gotstyle = TRUE;
757 }
758 }
759 ;
760
761ctrl_desc
762 : expr ',' expr ',' expr ',' expr ',' expr optional_style {
763 $$ = new_control();
764 $$->id = $1;
765 $$->x = $3;
766 $$->y = $5;
767 $$->width = $7;
768 $$->height = $9;
769 if($10)
770 {
771 $$->style = $10;
772 $$->gotstyle = TRUE;
773 }
774 }
775 ;
776
777iconinfo: /* Empty */
778 { $$ = new_control(); }
779
780 | ',' expr ',' expr {
781 $$ = new_control();
782 $$->width = $2;
783 $$->height = $4;
784 }
785 | ',' expr ',' expr ',' style {
786 $$ = new_control();
787 $$->width = $2;
788 $$->height = $4;
789 $$->style = $6;
790 $$->gotstyle = TRUE;
791 }
792 | ',' expr ',' expr ',' style ',' style {
793 $$ = new_control();
794 $$->width = $2;
795 $$->height = $4;
796 $$->style = $6;
797 $$->gotstyle = TRUE;
798 $$->exstyle = $8;
799 $$->gotexstyle = TRUE;
800 }
801 ;
802
803gen_ctrl: nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ',' expr ',' style {
804 $$=new_control();
805 $$->title = $1;
806 $$->id = $3;
807 $$->ctlclass = convert_ctlclass($5);
808 $$->style = $7;
809 $$->gotstyle = TRUE;
810 $$->x = $9;
811 $$->y = $11;
812 $$->width = $13;
813 $$->height = $15;
814 $$->exstyle = $17;
815 $$->gotexstyle = TRUE;
816 }
817 | nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ',' expr {
818 $$=new_control();
819 $$->title = $1;
820 $$->id = $3;
821 $$->ctlclass = convert_ctlclass($5);
822 $$->style = $7;
823 $$->gotstyle = TRUE;
824 $$->x = $9;
825 $$->y = $11;
826 $$->width = $13;
827 $$->height = $15;
828 }
829 ;
830
831opt_font
832 : FONT expr ',' tSTRING { $$ = new_font_id($2, $4, 0, 0); }
833 ;
834
835/* ------------------------------ style flags ------------------------------ */
836optional_style /* Abbused once to get optional ExStyle */
837 : /* Empty */ { $$ = NULL; }
838 | ',' style { $$ = $2; }
839 ;
840
841optional_style_pair
842 : /* Empty */ { $$ = NULL; }
843 | ',' style { $$ = new_style_pair($2, 0); }
844 | ',' style ',' style { $$ = new_style_pair($2, $4); }
845 ;
846
847style
848 : style '|' style { $$ = new_style($1->or_mask | $3->or_mask, $1->and_mask | $3->and_mask); free($1); free($3);}
849 | '(' style ')' { $$ = $2; }
850 | any_num { $$ = new_style($1, 0); }
851 | NOT any_num { $$ = new_style(0, $2); }
852 ;
853
854ctlclass
855 : expr {
856 $$ = new_name_id();
857 $$->type = name_ord;
858 $$->name.i_name = $1;
859 }
860 | tSTRING {
861 $$ = new_name_id();
862 $$->type = name_str;
863 $$->name.s_name = $1;
864 }
865 ;
866
867/* ------------------------------ DialogEx ------------------------------ */
868dialogex: DIALOGEX loadmemopts expr ',' expr ',' expr ',' expr helpid dlgex_attribs
869 tBEGIN exctrls tEND {
870 if(!win32)
871 yywarning("DIALOGEX not supported in 16-bit mode");
872 if($2)
873 {
874 $11->memopt = *($2);
875 free($2);
876 }
877 else
878 $11->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
879 $11->x = $3;
880 $11->y = $5;
881 $11->width = $7;
882 $11->height = $9;
883 if($10)
884 {
885 $11->helpid = *($10);
886 $11->gothelpid = TRUE;
887 free($10);
888 }
889 $11->controls = get_control_head($13);
890 $$ = $11;
891
892 assert($$->style != NULL);
893 if(!$$->gotstyle)
894 {
895 $$->style->or_mask = WS_POPUP;
896 $$->gotstyle = TRUE;
897 }
898 if($$->title)
899 $$->style->or_mask |= WS_CAPTION;
900 if($$->font)
901 $$->style->or_mask |= DS_SETFONT;
902
903 $$->style->or_mask &= ~($$->style->and_mask);
904 $$->style->and_mask = 0;
905
906 indialog = FALSE;
907 if(!$$->lvc.language)
908 $$->lvc.language = dup_language(currentlanguage);
909 }
910 ;
911
912dlgex_attribs
913 : /* Empty */ { $$=new_dialogex(); }
914 | dlgex_attribs STYLE style { $$=dialogex_style($3,$1); }
915 | dlgex_attribs EXSTYLE style { $$=dialogex_exstyle($3,$1); }
916 | dlgex_attribs CAPTION tSTRING { $$=dialogex_caption($3,$1); }
917 | dlgex_attribs opt_font { $$=dialogex_font($2,$1); }
918 | dlgex_attribs opt_exfont { $$=dialogex_font($2,$1); }
919 | dlgex_attribs CLASS nameid_s { $$=dialogex_class($3,$1); }
920 | dlgex_attribs MENU nameid { $$=dialogex_menu($3,$1); }
921 | dlgex_attribs opt_language { $$=dialogex_language($2,$1); }
922 | dlgex_attribs opt_characts { $$=dialogex_characteristics($2,$1); }
923 | dlgex_attribs opt_version { $$=dialogex_version($2,$1); }
924 ;
925
926exctrls : /* Empty */ { $$ = NULL; }
927 | exctrls CONTROL gen_exctrl { $$=ins_ctrl(-1, 0, $3, $1); }
928 | exctrls EDITTEXT exctrl_desc { $$=ins_ctrl(CT_EDIT, 0, $3, $1); }
929 | exctrls LISTBOX exctrl_desc { $$=ins_ctrl(CT_LISTBOX, 0, $3, $1); }
930 | exctrls COMBOBOX exctrl_desc { $$=ins_ctrl(CT_COMBOBOX, 0, $3, $1); }
931 | exctrls SCROLLBAR exctrl_desc { $$=ins_ctrl(CT_SCROLLBAR, 0, $3, $1); }
932 | exctrls CHECKBOX lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_CHECKBOX, $3, $1); }
933 | exctrls DEFPUSHBUTTON lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_DEFPUSHBUTTON, $3, $1); }
934 | exctrls GROUPBOX lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_GROUPBOX, $3, $1);}
935 | exctrls PUSHBUTTON lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_PUSHBUTTON, $3, $1); }
936/* | exctrls PUSHBOX lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_PUSHBOX, $3, $1); } */
937 | exctrls RADIOBUTTON lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_RADIOBUTTON, $3, $1); }
938 | exctrls AUTO3STATE lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTO3STATE, $3, $1); }
939 | exctrls STATE3 lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_3STATE, $3, $1); }
940 | exctrls AUTOCHECKBOX lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTOCHECKBOX, $3, $1); }
941 | exctrls AUTORADIOBUTTON lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTORADIOBUTTON, $3, $1); }
942 | exctrls LTEXT lab_exctrl { $$=ins_ctrl(CT_STATIC, SS_LEFT, $3, $1); }
943 | exctrls CTEXT lab_exctrl { $$=ins_ctrl(CT_STATIC, SS_CENTER, $3, $1); }
944 | exctrls RTEXT lab_exctrl { $$=ins_ctrl(CT_STATIC, SS_RIGHT, $3, $1); }
945 /* special treatment for icons, as the extent is optional */
946 | exctrls ICON nameid_s opt_comma expr ',' expr ',' expr iconinfo {
947 $10->title = $3;
948 $10->id = $5;
949 $10->x = $7;
950 $10->y = $9;
951 $$ = ins_ctrl(CT_STATIC, SS_ICON, $10, $1);
952 }
953 ;
954
955gen_exctrl
956 : nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ','
957 expr ',' style helpid opt_data {
958 $$=new_control();
959 $$->title = $1;
960 $$->id = $3;
961 $$->ctlclass = convert_ctlclass($5);
962 $$->style = $7;
963 $$->gotstyle = TRUE;
964 $$->x = $9;
965 $$->y = $11;
966 $$->width = $13;
967 $$->height = $15;
968 if($17)
969 {
970 $$->exstyle = $17;
971 $$->gotexstyle = TRUE;
972 }
973 if($18)
974 {
975 $$->helpid = *($18);
976 $$->gothelpid = TRUE;
977 free($18);
978 }
979 $$->extra = $19;
980 }
981 | nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ',' expr opt_data {
982 $$=new_control();
983 $$->title = $1;
984 $$->id = $3;
985 $$->style = $7;
986 $$->gotstyle = TRUE;
987 $$->ctlclass = convert_ctlclass($5);
988 $$->x = $9;
989 $$->y = $11;
990 $$->width = $13;
991 $$->height = $15;
992 $$->extra = $16;
993 }
994 ;
995
996lab_exctrl
997 : tSTRING opt_comma expr ',' expr ',' expr ',' expr ',' expr optional_style_pair opt_data {
998 $$=new_control();
999 $$->title = new_name_id();
1000 $$->title->type = name_str;
1001 $$->title->name.s_name = $1;
1002 $$->id = $3;
1003 $$->x = $5;
1004 $$->y = $7;
1005 $$->width = $9;
1006 $$->height = $11;
1007 if($12)
1008 {
1009 $$->style = $12->style;
1010 $$->gotstyle = TRUE;
1011
1012 if ($12->exstyle)
1013 {
1014 $$->exstyle = $12->exstyle;
1015 $$->gotexstyle = TRUE;
1016 }
1017 free($12);
1018 }
1019
1020 $$->extra = $13;
1021 }
1022 ;
1023
1024exctrl_desc
1025 : expr ',' expr ',' expr ',' expr ',' expr optional_style_pair opt_data {
1026 $$ = new_control();
1027 $$->id = $1;
1028 $$->x = $3;
1029 $$->y = $5;
1030 $$->width = $7;
1031 $$->height = $9;
1032 if($10)
1033 {
1034 $$->style = $10->style;
1035 $$->gotstyle = TRUE;
1036
1037 if ($10->exstyle)
1038 {
1039 $$->exstyle = $10->exstyle;
1040 $$->gotexstyle = TRUE;
1041 }
1042 free($10);
1043 }
1044 $$->extra = $11;
1045 }
1046 ;
1047
1048opt_data: /* Empty */ { $$ = NULL; }
1049 | raw_data { $$ = $1; }
1050 ;
1051
1052helpid : /* Empty */ { $$ = NULL; }
1053 | ',' expr { $$ = new_int($2); }
1054 ;
1055
1056opt_exfont
1057 : FONT expr ',' tSTRING ',' expr ',' expr opt_expr { $$ = new_font_id($2, $4, $6, $8); }
1058 ;
1059
1060/*
1061 * FIXME: This odd expression is here to nullify an extra token found
1062 * in some appstudio produced resources which appear to do nothing.
1063 */
1064opt_expr: /* Empty */ { $$ = NULL; }
1065 | ',' expr { $$ = NULL; }
1066 ;
1067
1068/* ------------------------------ Menu ------------------------------ */
1069menu : MENU loadmemopts opt_lvc menu_body {
1070 if(!$4)
1071 yyerror("Menu must contain items");
1072 $$ = new_menu();
1073 if($2)
1074 {
1075 $$->memopt = *($2);
1076 free($2);
1077 }
1078 else
1079 $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
1080 $$->items = get_item_head($4);
1081 if($3)
1082 {
1083 $$->lvc = *($3);
1084 free($3);
1085 }
1086 if(!$$->lvc.language)
1087 $$->lvc.language = dup_language(currentlanguage);
1088 }
1089 ;
1090
1091menu_body
1092 : tBEGIN item_definitions tEND { $$ = $2; }
1093 ;
1094
1095item_definitions
1096 : /* Empty */ {$$ = NULL;}
1097 | item_definitions MENUITEM tSTRING opt_comma expr item_options {
1098 $$=new_menu_item();
1099 $$->prev = $1;
1100 if($1)
1101 $1->next = $$;
1102 $$->id = $5;
1103 $$->state = $6;
1104 $$->name = $3;
1105 }
1106 | item_definitions MENUITEM SEPARATOR {
1107 $$=new_menu_item();
1108 $$->prev = $1;
1109 if($1)
1110 $1->next = $$;
1111 }
1112 | item_definitions POPUP tSTRING item_options menu_body {
1113 $$ = new_menu_item();
1114 $$->prev = $1;
1115 if($1)
1116 $1->next = $$;
1117 $$->popup = get_item_head($5);
1118 $$->name = $3;
1119 }
1120 ;
1121
1122/* NOTE: item_options is right recursive because it would introduce
1123 * a shift/reduce conflict on ',' in itemex_options due to the
1124 * empty rule here. The parser is now forced to look beyond the ','
1125 * before reducing (force shift).
1126 * Right recursion here is not a problem because we cannot expect
1127 * more than 7 parserstack places to be occupied while parsing this
1128 * (who would want to specify a MF_x flag twice?).
1129 */
1130item_options
1131 : /* Empty */ { $$ = 0; }
1132 | ',' CHECKED item_options { $$ = $3 | MF_CHECKED; }
1133 | ',' GRAYED item_options { $$ = $3 | MF_GRAYED; }
1134 | ',' HELP item_options { $$ = $3 | MF_HELP; }
1135 | ',' INACTIVE item_options { $$ = $3 | MF_DISABLED; }
1136 | ',' MENUBARBREAK item_options { $$ = $3 | MF_MENUBARBREAK; }
1137 | ',' MENUBREAK item_options { $$ = $3 | MF_MENUBREAK; }
1138 ;
1139
1140/* ------------------------------ MenuEx ------------------------------ */
1141menuex : MENUEX loadmemopts opt_lvc menuex_body {
1142 if(!win32)
1143 yywarning("MENUEX not supported in 16-bit mode");
1144 if(!$4)
1145 yyerror("MenuEx must contain items");
1146 $$ = new_menuex();
1147 if($2)
1148 {
1149 $$->memopt = *($2);
1150 free($2);
1151 }
1152 else
1153 $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
1154 $$->items = get_itemex_head($4);
1155 if($3)
1156 {
1157 $$->lvc = *($3);
1158 free($3);
1159 }
1160 if(!$$->lvc.language)
1161 $$->lvc.language = dup_language(currentlanguage);
1162 }
1163 ;
1164
1165menuex_body
1166 : tBEGIN itemex_definitions tEND { $$ = $2; }
1167 ;
1168
1169itemex_definitions
1170 : /* Empty */ {$$ = NULL; }
1171 | itemex_definitions MENUITEM tSTRING itemex_options {
1172 $$ = new_menuex_item();
1173 $$->prev = $1;
1174 if($1)
1175 $1->next = $$;
1176 $$->name = $3;
1177 $$->id = $4->id;
1178 $$->type = $4->type;
1179 $$->state = $4->state;
1180 $$->helpid = $4->helpid;
1181 $$->gotid = $4->gotid;
1182 $$->gottype = $4->gottype;
1183 $$->gotstate = $4->gotstate;
1184 $$->gothelpid = $4->gothelpid;
1185 free($4);
1186 }
1187 | itemex_definitions MENUITEM SEPARATOR {
1188 $$ = new_menuex_item();
1189 $$->prev = $1;
1190 if($1)
1191 $1->next = $$;
1192 }
1193 | itemex_definitions POPUP tSTRING itemex_p_options menuex_body {
1194 $$ = new_menuex_item();
1195 $$->prev = $1;
1196 if($1)
1197 $1->next = $$;
1198 $$->popup = get_itemex_head($5);
1199 $$->name = $3;
1200 $$->id = $4->id;
1201 $$->type = $4->type;
1202 $$->state = $4->state;
1203 $$->helpid = $4->helpid;
1204 $$->gotid = $4->gotid;
1205 $$->gottype = $4->gottype;
1206 $$->gotstate = $4->gotstate;
1207 $$->gothelpid = $4->gothelpid;
1208 free($4);
1209 }
1210 ;
1211
1212itemex_options
1213 : /* Empty */ { $$ = new_itemex_opt(0, 0, 0, 0); }
1214 | ',' expr {
1215 $$ = new_itemex_opt($2, 0, 0, 0);
1216 $$->gotid = TRUE;
1217 }
1218 | ',' e_expr ',' e_expr item_options {
1219 $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $5, 0);
1220 $$->gotid = TRUE;
1221 $$->gottype = TRUE;
1222 $$->gotstate = TRUE;
1223 if($2) free($2);
1224 if($4) free($4);
1225 }
1226 | ',' e_expr ',' e_expr ',' expr {
1227 $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6, 0);
1228 $$->gotid = TRUE;
1229 $$->gottype = TRUE;
1230 $$->gotstate = TRUE;
1231 if($2) free($2);
1232 if($4) free($4);
1233 }
1234 ;
1235
1236itemex_p_options
1237 : /* Empty */ { $$ = new_itemex_opt(0, 0, 0, 0); }
1238 | ',' expr {
1239 $$ = new_itemex_opt($2, 0, 0, 0);
1240 $$->gotid = TRUE;
1241 }
1242 | ',' e_expr ',' expr {
1243 $$ = new_itemex_opt($2 ? *($2) : 0, $4, 0, 0);
1244 if($2) free($2);
1245 $$->gotid = TRUE;
1246 $$->gottype = TRUE;
1247 }
1248 | ',' e_expr ',' e_expr ',' expr {
1249 $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6, 0);
1250 if($2) free($2);
1251 if($4) free($4);
1252 $$->gotid = TRUE;
1253 $$->gottype = TRUE;
1254 $$->gotstate = TRUE;
1255 }
1256 | ',' e_expr ',' e_expr ',' e_expr ',' expr {
1257 $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6 ? *($6) : 0, $8);
1258 if($2) free($2);
1259 if($4) free($4);
1260 if($6) free($6);
1261 $$->gotid = TRUE;
1262 $$->gottype = TRUE;
1263 $$->gotstate = TRUE;
1264 $$->gothelpid = TRUE;
1265 }
1266 ;
1267
1268/* ------------------------------ StringTable ------------------------------ */
1269/* Stringtables are parsed differently than other resources because their
1270 * layout is substantially different from other resources.
1271 * The table is parsed through a _global_ variable 'tagstt' which holds the
1272 * current stringtable descriptor (stringtable_t *) and 'sttres' that holds a
1273 * list of stringtables of different languages.
1274 */
1275stringtable
1276 : stt_head tBEGIN strings tEND {
1277 if(!$3)
1278 {
1279 yyerror("Stringtable must have at least one entry");
1280 }
1281 else
1282 {
1283 stringtable_t *stt;
1284 /* Check if we added to a language table or created
1285 * a new one.
1286 */
1287 for(stt = sttres; stt; stt = stt->next)
1288 {
1289 if(stt == tagstt)
1290 break;
1291 }
1292 if(!stt)
1293 {
1294 /* It is a new one */
1295 if(sttres)
1296 {
1297 sttres->prev = tagstt;
1298 tagstt->next = sttres;
1299 sttres = tagstt;
1300 }
1301 else
1302 sttres = tagstt;
1303 }
1304 /* Else were done */
1305 }
1306 if(tagstt_memopt)
1307 {
1308 free(tagstt_memopt);
1309 tagstt_memopt = NULL;
1310 }
1311
1312 $$ = tagstt;
1313 }
1314 ;
1315
1316/* This is to get the language of the currently parsed stringtable */
1317stt_head: STRINGTABLE loadmemopts opt_lvc {
1318 if((tagstt = find_stringtable($3)) == NULL)
1319 tagstt = new_stringtable($3);
1320 tagstt_memopt = $2;
1321 tagstt_version = $3->version;
1322 tagstt_characts = $3->characts;
1323 if($3)
1324 free($3);
1325 }
1326 ;
1327
1328strings : /* Empty */ { $$ = NULL; }
1329 | strings expr opt_comma tSTRING {
1330 int i;
1331 assert(tagstt != NULL);
1332 if($2 > 65535 || $2 < -32768)
1333 yyerror("Stringtable entry's ID out of range (%d)", $2);
1334 /* Search for the ID */
1335 for(i = 0; i < tagstt->nentries; i++)
1336 {
1337 if(tagstt->entries[i].id == $2)
1338 yyerror("Stringtable ID %d already in use", $2);
1339 }
1340 /* If we get here, then we have a new unique entry */
1341 tagstt->nentries++;
1342 tagstt->entries = xrealloc(tagstt->entries, sizeof(tagstt->entries[0]) * tagstt->nentries);
1343 tagstt->entries[tagstt->nentries-1].id = $2;
1344 tagstt->entries[tagstt->nentries-1].str = $4;
1345 if(tagstt_memopt)
1346 tagstt->entries[tagstt->nentries-1].memopt = *tagstt_memopt;
1347 else
1348 tagstt->entries[tagstt->nentries-1].memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE | WRC_MO_PURE;
1349 tagstt->entries[tagstt->nentries-1].version = tagstt_version;
1350 tagstt->entries[tagstt->nentries-1].characts = tagstt_characts;
1351
1352 if(!win32 && $4->size > 254)
1353 yyerror("Stringtable entry more than 254 characters");
1354 if(win32 && $4->size > 65534) /* Hmm..., does this happen? */
1355 yyerror("Stringtable entry more than 65534 characters (probably something else that went wrong)");
1356 $$ = tagstt;
1357 }
1358 ;
1359
1360opt_comma /* There seem to be two ways to specify a stringtable... */
1361 : /* Empty */
1362 | ','
1363 ;
1364
1365/* ------------------------------ VersionInfo ------------------------------ */
1366versioninfo
1367 : VERSIONINFO fix_version tBEGIN ver_blocks tEND {
1368 $$ = $2;
1369 $2->blocks = get_ver_block_head($4);
1370 }
1371 ;
1372
1373fix_version
1374 : /* Empty */ { $$ = new_versioninfo(); }
1375 | fix_version FILEVERSION expr ',' expr ',' expr ',' expr {
1376 if($1->gotit.fv)
1377 yyerror("FILEVERSION already defined");
1378 $$ = $1;
1379 $$->filever_maj1 = $3;
1380 $$->filever_maj2 = $5;
1381 $$->filever_min1 = $7;
1382 $$->filever_min2 = $9;
1383 $$->gotit.fv = 1;
1384 }
1385 | fix_version PRODUCTVERSION expr ',' expr ',' expr ',' expr {
1386 if($1->gotit.pv)
1387 yyerror("PRODUCTVERSION already defined");
1388 $$ = $1;
1389 $$->prodver_maj1 = $3;
1390 $$->prodver_maj2 = $5;
1391 $$->prodver_min1 = $7;
1392 $$->prodver_min2 = $9;
1393 $$->gotit.pv = 1;
1394 }
1395 | fix_version FILEFLAGS expr {
1396 if($1->gotit.ff)
1397 yyerror("FILEFLAGS already defined");
1398 $$ = $1;
1399 $$->fileflags = $3;
1400 $$->gotit.ff = 1;
1401 }
1402 | fix_version FILEFLAGSMASK expr {
1403 if($1->gotit.ffm)
1404 yyerror("FILEFLAGSMASK already defined");
1405 $$ = $1;
1406 $$->fileflagsmask = $3;
1407 $$->gotit.ffm = 1;
1408 }
1409 | fix_version FILEOS expr {
1410 if($1->gotit.fo)
1411 yyerror("FILEOS already defined");
1412 $$ = $1;
1413 $$->fileos = $3;
1414 $$->gotit.fo = 1;
1415 }
1416 | fix_version FILETYPE expr {
1417 if($1->gotit.ft)
1418 yyerror("FILETYPE already defined");
1419 $$ = $1;
1420 $$->filetype = $3;
1421 $$->gotit.ft = 1;
1422 }
1423 | fix_version FILESUBTYPE expr {
1424 if($1->gotit.fst)
1425 yyerror("FILESUBTYPE already defined");
1426 $$ = $1;
1427 $$->filesubtype = $3;
1428 $$->gotit.fst = 1;
1429 }
1430 ;
1431
1432ver_blocks
1433 : /* Empty */ { $$ = NULL; }
1434 | ver_blocks ver_block {
1435 $$ = $2;
1436 $$->prev = $1;
1437 if($1)
1438 $1->next = $$;
1439 }
1440 ;
1441
1442ver_block
1443 : BLOCK tSTRING tBEGIN ver_values tEND {
1444 $$ = new_ver_block();
1445 $$->name = $2;
1446 $$->values = get_ver_value_head($4);
1447 }
1448 ;
1449
1450ver_values
1451 : /* Empty */ { $$ = NULL; }
1452 | ver_values ver_value {
1453 $$ = $2;
1454 $$->prev = $1;
1455 if($1)
1456 $1->next = $$;
1457 }
1458 ;
1459
1460ver_value
1461 : ver_block {
1462 $$ = new_ver_value();
1463 $$->type = val_block;
1464 $$->value.block = $1;
1465 }
1466 | VALUE tSTRING ',' tSTRING {
1467 $$ = new_ver_value();
1468 $$->type = val_str;
1469 $$->key = $2;
1470 $$->value.str = $4;
1471 }
1472 | VALUE tSTRING ',' ver_words {
1473 $$ = new_ver_value();
1474 $$->type = val_words;
1475 $$->key = $2;
1476 $$->value.words = $4;
1477 }
1478 ;
1479
1480ver_words
1481 : expr { $$ = new_ver_words($1); }
1482 | ver_words ',' expr { $$ = add_ver_words($1, $3); }
1483 ;
1484
1485/* ------------------------------ Toolbar ------------------------------ */
1486toolbar: TOOLBAR loadmemopts expr ',' expr opt_lvc tBEGIN toolbar_items tEND {
1487 int nitems;
1488 toolbar_item_t *items = get_tlbr_buttons_head($8, &nitems);
1489 $$ = new_toolbar($3, $5, items, nitems);
1490 if($2)
1491 {
1492 $$->memopt = *($2);
1493 free($2);
1494 }
1495 else
1496 {
1497 $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
1498 }
1499 if($6)
1500 {
1501 $$->lvc = *($6);
1502 free($6);
1503 }
1504 if(!$$->lvc.language)
1505 {
1506 $$->lvc.language = dup_language(currentlanguage);
1507 }
1508 }
1509 ;
1510
1511toolbar_items
1512 : /* Empty */ { $$ = NULL; }
1513 | toolbar_items BUTTON expr {
1514 toolbar_item_t *idrec = new_toolbar_item();
1515 idrec->id = $3;
1516 $$ = ins_tlbr_button($1, idrec);
1517 }
1518 | toolbar_items SEPARATOR {
1519 toolbar_item_t *idrec = new_toolbar_item();
1520 idrec->id = 0;
1521 $$ = ins_tlbr_button($1, idrec);
1522 }
1523 ;
1524
1525/* ------------------------------ Memory options ------------------------------ */
1526loadmemopts
1527 : /* Empty */ { $$ = NULL; }
1528 | loadmemopts lamo {
1529 if($1)
1530 {
1531 *($1) |= *($2);
1532 $$ = $1;
1533 free($2);
1534 }
1535 else
1536 $$ = $2;
1537 }
1538 | loadmemopts lama {
1539 if($1)
1540 {
1541 *($1) &= *($2);
1542 $$ = $1;
1543 free($2);
1544 }
1545 else
1546 {
1547 *$2 &= WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE | WRC_MO_PURE;
1548 $$ = $2;
1549 }
1550 }
1551 ;
1552
1553lamo : PRELOAD { $$ = new_int(WRC_MO_PRELOAD); }
1554 | MOVEABLE { $$ = new_int(WRC_MO_MOVEABLE); }
1555 | DISCARDABLE { $$ = new_int(WRC_MO_DISCARDABLE); }
1556 | tPURE { $$ = new_int(WRC_MO_PURE); }
1557 ;
1558
1559lama : LOADONCALL { $$ = new_int(~WRC_MO_PRELOAD); }
1560 | tFIXED { $$ = new_int(~WRC_MO_MOVEABLE); }
1561 | IMPURE { $$ = new_int(~WRC_MO_PURE); }
1562 ;
1563
1564/* ------------------------------ Win32 options ------------------------------ */
1565opt_lvc : /* Empty */ { $$ = new_lvc(); }
1566 | opt_lvc opt_language {
1567 if(!win32)
1568 yywarning("LANGUAGE not supported in 16-bit mode");
1569 if($1->language)
1570 yyerror("Language already defined");
1571 $$ = $1;
1572 $1->language = $2;
1573 }
1574 | opt_lvc opt_characts {
1575 if(!win32)
1576 yywarning("CHARACTERISTICS not supported in 16-bit mode");
1577 if($1->characts)
1578 yyerror("Characteristics already defined");
1579 $$ = $1;
1580 $1->characts = $2;
1581 }
1582 | opt_lvc opt_version {
1583 if(!win32)
1584 yywarning("VERSION not supported in 16-bit mode");
1585 if($1->version)
1586 yyerror("Version already defined");
1587 $$ = $1;
1588 $1->version = $2;
1589 }
1590 ;
1591
1592opt_language
1593 : LANGUAGE expr ',' expr { $$ = new_language($2, $4); }
1594 ;
1595
1596opt_characts
1597 : CHARACTERISTICS expr { $$ = new_characts($2); }
1598 ;
1599
1600opt_version
1601 : VERSION expr { $$ = new_version($2); }
1602 ;
1603
1604/* ------------------------------ Raw data handking ------------------------------ */
1605raw_data: tBEGIN raw_elements tEND { $$ = $2; }
1606 ;
1607
1608raw_elements
1609 : RAWDATA { $$ = $1; }
1610 | NUMBER { $$ = int2raw_data($1); }
1611 | LNUMBER { $$ = long2raw_data($1); }
1612 | tSTRING { $$ = str2raw_data($1); }
1613 | raw_elements opt_comma RAWDATA { $$ = merge_raw_data($1, $3); free($3->data); free($3); }
1614 | raw_elements opt_comma NUMBER { $$ = merge_raw_data_int($1, $3); }
1615 | raw_elements opt_comma LNUMBER { $$ = merge_raw_data_long($1, $3); }
1616 | raw_elements opt_comma tSTRING { $$ = merge_raw_data_str($1, $3); }
1617 ;
1618
1619/* ------------------------------ Win32 expressions ------------------------------ */
1620/* All win16 numbers are also handled here. This is inconsistent with MS'
1621 * resource compiler, but what the heck, its just handy to have.
1622 */
1623e_expr : /* Empty */ { $$ = 0; }
1624 | expr { $$ = new_int($1); }
1625 ;
1626expr : xpr { $$ = ($1); }
1627 ;
1628
1629xpr : xpr '+' xpr { $$ = ($1) + ($3); }
1630 | xpr '-' xpr { $$ = ($1) - ($3); }
1631 | xpr '|' xpr { $$ = ($1) | ($3); }
1632 | xpr '&' xpr { $$ = ($1) & ($3); }
1633 | xpr '*' xpr { $$ = ($1) * ($3); }
1634 | xpr '/' xpr { $$ = ($1) / ($3); }
1635 | '~' xpr { $$ = ~($2); }
1636 | '-' xpr { $$ = -($2); } /* FIXME: shift/reduce conflict */
1637/* | '+' xpr { $$ = $2; } */
1638 | '(' xpr ')' { $$ = $2; }
1639 | any_num { $$ = $1; want_rscname = 0; }
1640 | NOT any_num { $$ = ~($2); }
1641 ;
1642
1643any_num : NUMBER { $$ = $1; }
1644 | LNUMBER { $$ = $1; }
1645 ;
1646
1647%%
1648/* Dialog specific functions */
1649dialog_t *dialog_style(style_t * st, dialog_t *dlg)
1650{
1651 assert(dlg != NULL);
1652 if(dlg->style == NULL)
1653 {
1654 dlg->style = new_style(0,0);
1655 }
1656
1657 if(dlg->gotstyle)
1658 {
1659 yywarning("Style already defined, or-ing together");
1660 }
1661 else
1662 {
1663 dlg->style->or_mask = 0;
1664 dlg->style->and_mask = 0;
1665 }
1666 dlg->style->or_mask |= st->or_mask;
1667 dlg->style->and_mask |= st->and_mask;
1668 dlg->gotstyle = TRUE;
1669 free(st);
1670 return dlg;
1671}
1672
1673dialog_t *dialog_exstyle(style_t *st, dialog_t *dlg)
1674{
1675 assert(dlg != NULL);
1676 if(dlg->exstyle == NULL)
1677 {
1678 dlg->exstyle = new_style(0,0);
1679 }
1680
1681 if(dlg->gotexstyle)
1682 {
1683 yywarning("ExStyle already defined, or-ing together");
1684 }
1685 else
1686 {
1687 dlg->exstyle->or_mask = 0;
1688 dlg->exstyle->and_mask = 0;
1689 }
1690 dlg->exstyle->or_mask |= st->or_mask;
1691 dlg->exstyle->and_mask |= st->and_mask;
1692 dlg->gotexstyle = TRUE;
1693 free(st);
1694 return dlg;
1695}
1696
1697dialog_t *dialog_caption(string_t *s, dialog_t *dlg)
1698{
1699 assert(dlg != NULL);
1700 if(dlg->title)
1701 yyerror("Caption already defined");
1702 dlg->title = s;
1703 return dlg;
1704}
1705
1706dialog_t *dialog_font(font_id_t *f, dialog_t *dlg)
1707{
1708 assert(dlg != NULL);
1709 if(dlg->font)
1710 yyerror("Font already defined");
1711 dlg->font = f;
1712 return dlg;
1713}
1714
1715dialog_t *dialog_class(name_id_t *n, dialog_t *dlg)
1716{
1717 assert(dlg != NULL);
1718 if(dlg->dlgclass)
1719 yyerror("Class already defined");
1720 dlg->dlgclass = n;
1721 return dlg;
1722}
1723
1724dialog_t *dialog_menu(name_id_t *m, dialog_t *dlg)
1725{
1726 assert(dlg != NULL);
1727 if(dlg->menu)
1728 yyerror("Menu already defined");
1729 dlg->menu = m;
1730 return dlg;
1731}
1732
1733dialog_t *dialog_language(language_t *l, dialog_t *dlg)
1734{
1735 assert(dlg != NULL);
1736 if(dlg->lvc.language)
1737 yyerror("Language already defined");
1738 dlg->lvc.language = l;
1739 return dlg;
1740}
1741
1742dialog_t *dialog_characteristics(characts_t *c, dialog_t *dlg)
1743{
1744 assert(dlg != NULL);
1745 if(dlg->lvc.characts)
1746 yyerror("Characteristics already defined");
1747 dlg->lvc.characts = c;
1748 return dlg;
1749}
1750
1751dialog_t *dialog_version(version_t *v, dialog_t *dlg)
1752{
1753 assert(dlg != NULL);
1754 if(dlg->lvc.version)
1755 yyerror("Version already defined");
1756 dlg->lvc.version = v;
1757 return dlg;
1758}
1759
1760/* Controls specific functions */
1761control_t *ins_ctrl(int type, int special_style, control_t *ctrl, control_t *prev)
1762{
1763 /* Hm... this seems to be jammed in at all time... */
1764 int defaultstyle = WS_CHILD | WS_VISIBLE;
1765
1766 assert(ctrl != NULL);
1767 ctrl->prev = prev;
1768
1769 if(prev)
1770 prev->next = ctrl;
1771
1772 if(type != -1)
1773 {
1774 ctrl->ctlclass = new_name_id();
1775 ctrl->ctlclass->type = name_ord;
1776 ctrl->ctlclass->name.i_name = type;
1777 }
1778
1779 switch(type)
1780 {
1781 case CT_BUTTON:
1782 if(special_style != BS_GROUPBOX && special_style != BS_RADIOBUTTON)
1783 defaultstyle |= WS_TABSTOP;
1784 break;
1785 case CT_EDIT:
1786 defaultstyle |= WS_TABSTOP | WS_BORDER;
1787 break;
1788 case CT_LISTBOX:
1789 defaultstyle |= LBS_NOTIFY | WS_BORDER;
1790 break;
1791 case CT_COMBOBOX:
1792 defaultstyle |= CBS_SIMPLE;
1793 break;
1794 case CT_STATIC:
1795 if(special_style == SS_CENTER || special_style == SS_LEFT || special_style == SS_RIGHT)
1796 defaultstyle |= WS_GROUP;
1797 break;
1798 }
1799
1800 if(!ctrl->gotstyle) /* Handle default style setting */
1801 {
1802 switch(type)
1803 {
1804 case CT_EDIT:
1805 defaultstyle |= ES_LEFT;
1806 break;
1807 case CT_LISTBOX:
1808 defaultstyle |= LBS_NOTIFY;
1809 break;
1810 case CT_COMBOBOX:
1811 defaultstyle |= CBS_SIMPLE | WS_TABSTOP;
1812 break;
1813 case CT_SCROLLBAR:
1814 defaultstyle |= SBS_HORZ;
1815 break;
1816 case CT_BUTTON:
1817 switch(special_style)
1818 {
1819 case BS_CHECKBOX:
1820 case BS_DEFPUSHBUTTON:
1821 case BS_PUSHBUTTON:
1822 case BS_GROUPBOX:
1823/* case BS_PUSHBOX: */
1824 case BS_AUTORADIOBUTTON:
1825 case BS_AUTO3STATE:
1826 case BS_3STATE:
1827 case BS_AUTOCHECKBOX:
1828 defaultstyle |= WS_TABSTOP;
1829 break;
1830 default:
1831 yywarning("Unknown default button control-style 0x%08x", special_style);
1832 case BS_RADIOBUTTON:
1833 break;
1834 }
1835 break;
1836
1837 case CT_STATIC:
1838 switch(special_style)
1839 {
1840 case SS_LEFT:
1841 case SS_RIGHT:
1842 case SS_CENTER:
1843 defaultstyle |= WS_GROUP;
1844 break;
1845 case SS_ICON: /* Special case */
1846 break;
1847 default:
1848 yywarning("Unknown default static control-style 0x%08x", special_style);
1849 break;
1850 }
1851 break;
1852 case -1: /* Generic control */
1853 goto byebye;
1854
1855 default:
1856 yyerror("Internal error (report this): Got weird control type 0x%08x", type);
1857 }
1858 }
1859
1860 /* The SS_ICON flag is always forced in for icon controls */
1861 if(type == CT_STATIC && special_style == SS_ICON)
1862 defaultstyle |= SS_ICON;
1863
1864 if (!ctrl->gotstyle)
1865 ctrl->style = new_style(0,0);
1866
1867 /* combine all styles */
1868 ctrl->style->or_mask = ctrl->style->or_mask | defaultstyle | special_style;
1869 ctrl->gotstyle = TRUE;
1870byebye:
1871 /* combine with NOT mask */
1872 if (ctrl->gotstyle)
1873 {
1874 ctrl->style->or_mask &= ~(ctrl->style->and_mask);
1875 ctrl->style->and_mask = 0;
1876 }
1877 if (ctrl->gotexstyle)
1878 {
1879 ctrl->exstyle->or_mask &= ~(ctrl->exstyle->and_mask);
1880 ctrl->exstyle->and_mask = 0;
1881 }
1882 return ctrl;
1883}
1884
1885name_id_t *convert_ctlclass(name_id_t *cls)
1886{
1887 char *cc;
1888 int iclass;
1889
1890 if(cls->type == name_ord)
1891 return cls;
1892 assert(cls->type == name_str);
1893 if(cls->type == str_unicode)
1894 {
1895 yyerror("Don't yet support unicode class comparison");
1896 }
1897 else
1898 cc = cls->name.s_name->str.cstr;
1899
1900 if(!strcasecmp("BUTTON", cc))
1901 iclass = CT_BUTTON;
1902 else if(!strcasecmp("COMBOBOX", cc))
1903 iclass = CT_COMBOBOX;
1904 else if(!strcasecmp("LISTBOX", cc))
1905 iclass = CT_LISTBOX;
1906 else if(!strcasecmp("EDIT", cc))
1907 iclass = CT_EDIT;
1908 else if(!strcasecmp("STATIC", cc))
1909 iclass = CT_STATIC;
1910 else if(!strcasecmp("SCROLLBAR", cc))
1911 iclass = CT_SCROLLBAR;
1912 else
1913 return cls; /* No default, return user controlclass */
1914
1915 free(cls->name.s_name->str.cstr);
1916 free(cls->name.s_name);
1917 cls->type = name_ord;
1918 cls->name.i_name = iclass;
1919 return cls;
1920}
1921
1922/* DialogEx specific functions */
1923dialogex_t *dialogex_style(style_t * st, dialogex_t *dlg)
1924{
1925 assert(dlg != NULL);
1926 if(dlg->style == NULL)
1927 {
1928 dlg->style = new_style(0,0);
1929 }
1930
1931 if(dlg->gotstyle)
1932 {
1933 yywarning("Style already defined, or-ing together");
1934 }
1935 else
1936 {
1937 dlg->style->or_mask = 0;
1938 dlg->style->and_mask = 0;
1939 }
1940 dlg->style->or_mask |= st->or_mask;
1941 dlg->style->and_mask |= st->and_mask;
1942 dlg->gotstyle = TRUE;
1943 free(st);
1944 return dlg;
1945}
1946
1947dialogex_t *dialogex_exstyle(style_t * st, dialogex_t *dlg)
1948{
1949 assert(dlg != NULL);
1950 if(dlg->exstyle == NULL)
1951 {
1952 dlg->exstyle = new_style(0,0);
1953 }
1954
1955 if(dlg->gotexstyle)
1956 {
1957 yywarning("ExStyle already defined, or-ing together");
1958 }
1959 else
1960 {
1961 dlg->exstyle->or_mask = 0;
1962 dlg->exstyle->and_mask = 0;
1963 }
1964 dlg->exstyle->or_mask |= st->or_mask;
1965 dlg->exstyle->and_mask |= st->and_mask;
1966 dlg->gotexstyle = TRUE;
1967 free(st);
1968 return dlg;
1969}
1970
1971dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg)
1972{
1973 assert(dlg != NULL);
1974 if(dlg->title)
1975 yyerror("Caption already defined");
1976 dlg->title = s;
1977 return dlg;
1978}
1979
1980dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg)
1981{
1982 assert(dlg != NULL);
1983 if(dlg->font)
1984 yyerror("Font already defined");
1985 dlg->font = f;
1986 return dlg;
1987}
1988
1989dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg)
1990{
1991 assert(dlg != NULL);
1992 if(dlg->dlgclass)
1993 yyerror("Class already defined");
1994 dlg->dlgclass = n;
1995 return dlg;
1996}
1997
1998dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg)
1999{
2000 assert(dlg != NULL);
2001 if(dlg->menu)
2002 yyerror("Menu already defined");
2003 dlg->menu = m;
2004 return dlg;
2005}
2006
2007dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg)
2008{
2009 assert(dlg != NULL);
2010 if(dlg->lvc.language)
2011 yyerror("Language already defined");
2012 dlg->lvc.language = l;
2013 return dlg;
2014}
2015
2016dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg)
2017{
2018 assert(dlg != NULL);
2019 if(dlg->lvc.characts)
2020 yyerror("Characteristics already defined");
2021 dlg->lvc.characts = c;
2022 return dlg;
2023}
2024
2025dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg)
2026{
2027 assert(dlg != NULL);
2028 if(dlg->lvc.version)
2029 yyerror("Version already defined");
2030 dlg->lvc.version = v;
2031 return dlg;
2032}
2033
2034/* Accelerator specific functions */
2035event_t *add_event(int key, int id, int flags, event_t *prev)
2036{
2037 event_t *ev = new_event();
2038
2039 if((flags & (WRC_AF_VIRTKEY | WRC_AF_ASCII)) == (WRC_AF_VIRTKEY | WRC_AF_ASCII))
2040 yyerror("Cannot use both ASCII and VIRTKEY");
2041
2042 ev->key = key;
2043 ev->id = id;
2044 ev->flags = flags & ~WRC_AF_ASCII;
2045 ev->prev = prev;
2046 if(prev)
2047 prev->next = ev;
2048 return ev;
2049}
2050
2051event_t *add_string_event(string_t *key, int id, int flags, event_t *prev)
2052{
2053 int keycode = 0;
2054 event_t *ev = new_event();
2055
2056 if(key->type != str_char)
2057 yyerror("Key code must be an ascii string");
2058
2059 if((flags & WRC_AF_VIRTKEY) && (!isupper(key->str.cstr[0]) && !isdigit(key->str.cstr[0])))
2060 yyerror("VIRTKEY code is not equal to ascii value");
2061
2062 if(key->str.cstr[0] == '^' && (flags & WRC_AF_CONTROL) != 0)
2063 {
2064 yyerror("Cannot use both '^' and CONTROL modifier");
2065 }
2066 else if(key->str.cstr[0] == '^')
2067 {
2068 keycode = toupper(key->str.cstr[1]) - '@';
2069 if(keycode >= ' ')
2070 yyerror("Control-code out of range");
2071 }
2072 else
2073 keycode = key->str.cstr[0];
2074 ev->key = keycode;
2075 ev->id = id;
2076 ev->flags = flags & ~WRC_AF_ASCII;
2077 ev->prev = prev;
2078 if(prev)
2079 prev->next = ev;
2080 return ev;
2081}
2082
2083/* MenuEx specific functions */
2084itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid)
2085{
2086 itemex_opt_t *opt = (itemex_opt_t *)xmalloc(sizeof(itemex_opt_t));
2087 opt->id = id;
2088 opt->type = type;
2089 opt->state = state;
2090 opt->helpid = helpid;
2091 return opt;
2092}
2093
2094/* Raw data functions */
2095raw_data_t *load_file(string_t *name)
2096{
2097 FILE *fp;
2098 raw_data_t *rd;
2099 if(name->type != str_char)
2100 yyerror("Filename must be ASCII string");
2101
2102 fp = open_include(name->str.cstr, 1);
2103 if(!fp)
2104 yyerror("Cannot open file %s", name->str.cstr);
2105 rd = new_raw_data();
2106 fseek(fp, 0, SEEK_END);
2107 rd->size = ftell(fp);
2108 fseek(fp, 0, SEEK_SET);
2109 rd->data = (char *)xmalloc(rd->size);
2110 fread(rd->data, rd->size, 1, fp);
2111 fclose(fp);
2112 HEAPCHECK();
2113 return rd;
2114}
2115
2116raw_data_t *int2raw_data(int i)
2117{
2118 raw_data_t *rd;
2119
2120 if((int)((short)i) != i)
2121 yywarning("Integer constant out of 16bit range (%d), truncated to %d\n", i, (short)i);
2122
2123 rd = new_raw_data();
2124 rd->size = sizeof(short);
2125 rd->data = (char *)xmalloc(rd->size);
2126 *(short *)(rd->data) = (short)i;
2127 return rd;
2128}
2129
2130raw_data_t *long2raw_data(int i)
2131{
2132 raw_data_t *rd;
2133 rd = new_raw_data();
2134 rd->size = sizeof(int);
2135 rd->data = (char *)xmalloc(rd->size);
2136 *(int *)(rd->data) = i;
2137 return rd;
2138}
2139
2140raw_data_t *str2raw_data(string_t *str)
2141{
2142 raw_data_t *rd;
2143 rd = new_raw_data();
2144 rd->size = str->size * (str->type == str_char ? 1 : 2);
2145 rd->data = (char *)xmalloc(rd->size);
2146 memcpy(rd->data, str->str.cstr, rd->size);
2147 return rd;
2148}
2149
2150raw_data_t *merge_raw_data(raw_data_t *r1, raw_data_t *r2)
2151{
2152 r1->data = xrealloc(r1->data, r1->size + r2->size);
2153 memcpy(r1->data + r1->size, r2->data, r2->size);
2154 r1->size += r2->size;
2155 return r1;
2156}
2157
2158raw_data_t *merge_raw_data_int(raw_data_t *r1, int i)
2159{
2160 raw_data_t *t = int2raw_data(i);
2161 merge_raw_data(r1, t);
2162 free(t->data);
2163 free(t);
2164 return r1;
2165}
2166
2167raw_data_t *merge_raw_data_long(raw_data_t *r1, int i)
2168{
2169 raw_data_t *t = long2raw_data(i);
2170 merge_raw_data(r1, t);
2171 free(t->data);
2172 free(t);
2173 return r1;
2174}
2175
2176raw_data_t *merge_raw_data_str(raw_data_t *r1, string_t *str)
2177{
2178 raw_data_t *t = str2raw_data(str);
2179 merge_raw_data(r1, t);
2180 free(t->data);
2181 free(t);
2182 return r1;
2183}
2184
2185/* Function the go back in a list to get the head */
2186menu_item_t *get_item_head(menu_item_t *p)
2187{
2188 if(!p)
2189 return NULL;
2190 while(p->prev)
2191 p = p->prev;
2192 return p;
2193}
2194
2195menuex_item_t *get_itemex_head(menuex_item_t *p)
2196{
2197 if(!p)
2198 return NULL;
2199 while(p->prev)
2200 p = p->prev;
2201 return p;
2202}
2203
2204resource_t *get_resource_head(resource_t *p)
2205{
2206 if(!p)
2207 return NULL;
2208 while(p->prev)
2209 p = p->prev;
2210 return p;
2211}
2212
2213ver_block_t *get_ver_block_head(ver_block_t *p)
2214{
2215 if(!p)
2216 return NULL;
2217 while(p->prev)
2218 p = p->prev;
2219 return p;
2220}
2221
2222ver_value_t *get_ver_value_head(ver_value_t *p)
2223{
2224 if(!p)
2225 return NULL;
2226 while(p->prev)
2227 p = p->prev;
2228 return p;
2229}
2230
2231control_t *get_control_head(control_t *p)
2232{
2233 if(!p)
2234 return NULL;
2235 while(p->prev)
2236 p = p->prev;
2237 return p;
2238}
2239
2240event_t *get_event_head(event_t *p)
2241{
2242 if(!p)
2243 return NULL;
2244 while(p->prev)
2245 p = p->prev;
2246 return p;
2247}
2248
2249/* Find a stringtable with given language */
2250stringtable_t *find_stringtable(lvc_t *lvc)
2251{
2252 stringtable_t *stt;
2253
2254 assert(lvc != NULL);
2255
2256 if(!lvc->language)
2257 lvc->language = dup_language(currentlanguage);
2258
2259 for(stt = sttres; stt; stt = stt->next)
2260 {
2261 if(stt->lvc.language->id == lvc->language->id
2262 && stt->lvc.language->id == lvc->language->id)
2263 {
2264 /* Found a table with the same language */
2265 /* The version and characteristics are now handled
2266 * in the generation of the individual stringtables.
2267 * This enables localized analysis.
2268 if((stt->lvc.version && lvc->version && *(stt->lvc.version) != *(lvc->version))
2269 || (!stt->lvc.version && lvc->version)
2270 || (stt->lvc.version && !lvc->version))
2271 yywarning("Stringtable's versions are not the same, using first definition");
2272
2273 if((stt->lvc.characts && lvc->characts && *(stt->lvc.characts) != *(lvc->characts))
2274 || (!stt->lvc.characts && lvc->characts)
2275 || (stt->lvc.characts && !lvc->characts))
2276 yywarning("Stringtable's characteristics are not the same, using first definition");
2277 */
2278 return stt;
2279 }
2280 }
2281 return NULL;
2282}
2283
2284/* qsort sorting function for string table entries */
2285#define STE(p) ((stt_entry_t *)(p))
2286int sort_stt_entry(const void *e1, const void *e2)
2287{
2288 return STE(e1)->id - STE(e2)->id;
2289}
2290#undef STE
2291
2292resource_t *build_stt_resources(stringtable_t *stthead)
2293{
2294 stringtable_t *stt;
2295 stringtable_t *newstt;
2296 resource_t *rsc;
2297 resource_t *rsclist = NULL;
2298 resource_t *rsctail = NULL;
2299 int i;
2300 int j;
2301 DWORD andsum;
2302 DWORD orsum;
2303 characts_t *characts;
2304 version_t *version;
2305
2306 if(!stthead)
2307 return NULL;
2308
2309 /* For all languages defined */
2310 for(stt = stthead; stt; stt = stt->next)
2311 {
2312 assert(stt->nentries > 0);
2313
2314 /* Sort the entries */
2315 if(stt->nentries > 1)
2316 qsort(stt->entries, stt->nentries, sizeof(stt->entries[0]), sort_stt_entry);
2317
2318 for(i = 0; i < stt->nentries; )
2319 {
2320 newstt = new_stringtable(&stt->lvc);
2321 newstt->entries = (stt_entry_t *)xmalloc(16 * sizeof(stt_entry_t));
2322 newstt->nentries = 16;
2323 newstt->idbase = stt->entries[i].id & ~0xf;
2324 for(j = 0; j < 16 && i < stt->nentries; j++)
2325 {
2326 if(stt->entries[i].id - newstt->idbase == j)
2327 {
2328 newstt->entries[j] = stt->entries[i];
2329 i++;
2330 }
2331 }
2332 andsum = ~0;
2333 orsum = 0;
2334 characts = NULL;
2335 version = NULL;
2336 /* Check individual memory options and get
2337 * the first characteristics/version
2338 */
2339 for(j = 0; j < 16; j++)
2340 {
2341 if(!newstt->entries[j].str)
2342 continue;
2343 andsum &= newstt->entries[j].memopt;
2344 orsum |= newstt->entries[j].memopt;
2345 if(!characts)
2346 characts = newstt->entries[j].characts;
2347 if(!version)
2348 version = newstt->entries[j].version;
2349 }
2350 if(andsum != orsum)
2351 {
2352 warning("Stringtable's memory options are not equal (idbase: %d)", newstt->idbase);
2353 }
2354 /* Check version and characteristics */
2355 for(j = 0; j < 16; j++)
2356 {
2357 if(characts
2358 && newstt->entries[j].characts
2359 && *newstt->entries[j].characts != *characts)
2360 warning("Stringtable's characteristics are not the same (idbase: %d)", newstt->idbase);
2361 if(version
2362 && newstt->entries[j].version
2363 && *newstt->entries[j].version != *version)
2364 warning("Stringtable's versions are not the same (idbase: %d)", newstt->idbase);
2365 }
2366 rsc = new_resource(res_stt, newstt, newstt->memopt, newstt->lvc.language);
2367 rsc->name = new_name_id();
2368 rsc->name->type = name_ord;
2369 rsc->name->name.i_name = (newstt->idbase >> 4) + 1;
2370 rsc->memopt = andsum; /* Set to least common denominator */
2371 newstt->memopt = andsum;
2372 newstt->lvc.characts = characts;
2373 newstt->lvc.version = version;
2374 if(!rsclist)
2375 {
2376 rsclist = rsc;
2377 rsctail = rsc;
2378 }
2379 else
2380 {
2381 rsctail->next = rsc;
2382 rsc->prev = rsctail;
2383 rsctail = rsc;
2384 }
2385 }
2386 }
2387 return rsclist;
2388}
2389
2390/* Cursor and icon splitter functions */
2391typedef struct {
2392 language_t lan;
2393 int id;
2394} id_alloc_t;
2395
2396static int get_new_id(id_alloc_t **list, int *n, language_t *lan)
2397{
2398 int i;
2399 assert(lan != NULL);
2400 assert(list != NULL);
2401 assert(n != NULL);
2402
2403 if(!*list)
2404 {
2405 *list = (id_alloc_t *)xmalloc(sizeof(id_alloc_t));
2406 *n = 1;
2407 (*list)[0].lan = *lan;
2408 (*list)[0].id = 1;
2409 return 1;
2410 }
2411
2412 for(i = 0; i < *n; i++)
2413 {
2414 if((*list)[i].lan.id == lan->id && (*list)[i].lan.sub == lan->sub)
2415 return ++((*list)[i].id);
2416 }
2417
2418 *list = (id_alloc_t *)xrealloc(*list, sizeof(id_alloc_t) * (*n+1));
2419 (*list)[*n].lan = *lan;
2420 (*list)[*n].id = 1;
2421 *n += 1;
2422 return 1;
2423}
2424
2425int alloc_icon_id(language_t *lan)
2426{
2427 static id_alloc_t *idlist = NULL;
2428 static int nid = 0;
2429
2430 return get_new_id(&idlist, &nid, lan);
2431}
2432
2433int alloc_cursor_id(language_t *lan)
2434{
2435 static id_alloc_t *idlist = NULL;
2436 static int nid = 0;
2437
2438 return get_new_id(&idlist, &nid, lan);
2439}
2440
2441#define BPTR(base) ((char *)(rd->data + (base)))
2442#define WPTR(base) ((WORD *)(rd->data + (base)))
2443#define DPTR(base) ((DWORD *)(rd->data + (base)))
2444void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico)
2445{
2446 int cnt;
2447 int i;
2448 icon_dir_entry_t *ide;
2449 icon_t *ico;
2450 icon_t *list = NULL;
2451
2452 /* FIXME: Distinguish between normal and animated icons (RIFF format) */
2453 if(WPTR(0)[1] != 1)
2454 yyerror("Icon resource data has invalid type id %d", WPTR(0)[1]);
2455 cnt = WPTR(0)[2];
2456 ide = (icon_dir_entry_t *)&(WPTR(0)[3]);
2457 for(i = 0; i < cnt; i++)
2458 {
2459 ico = new_icon();
2460 ico->id = alloc_icon_id(icog->lvc.language);
2461 ico->lvc.language = dup_language(icog->lvc.language);
2462 if(ide[i].offset > rd->size
2463 || ide[i].offset + ide[i].ressize > rd->size)
2464 yyerror("Icon resource data corrupt");
2465 ico->width = ide[i].width;
2466 ico->height = ide[i].height;
2467 ico->nclr = ide[i].nclr;
2468 ico->planes = ide[i].planes;
2469 ico->bits = ide[i].bits;
2470 if(!ico->planes)
2471 {
2472 /* Argh! They did not fill out the resdir structure */
2473 ico->planes = ((BITMAPINFOHEADER *)BPTR(ide[i].offset))->biPlanes;
2474 }
2475 if(!ico->bits)
2476 {
2477 /* Argh! They did not fill out the resdir structure */
2478 ico->bits = ((BITMAPINFOHEADER *)BPTR(ide[i].offset))->biBitCount;
2479 }
2480 ico->data = new_raw_data();
2481 copy_raw_data(ico->data, rd, ide[i].offset, ide[i].ressize);
2482 if(!list)
2483 {
2484 list = ico;
2485 }
2486 else
2487 {
2488 ico->next = list;
2489 list->prev = ico;
2490 list = ico;
2491 }
2492 }
2493 icog->iconlist = list;
2494 *nico = cnt;
2495}
2496
2497void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur)
2498{
2499 int cnt;
2500 int i;
2501 cursor_dir_entry_t *cde;
2502 cursor_t *cur;
2503 cursor_t *list = NULL;
2504
2505 /* FIXME: Distinguish between normal and animated cursors (RIFF format)*/
2506 if(WPTR(0)[1] != 2)
2507 yyerror("Cursor resource data has invalid type id %d", WPTR(0)[1]);
2508 cnt = WPTR(0)[2];
2509 cde = (cursor_dir_entry_t *)&(WPTR(0)[3]);
2510 for(i = 0; i < cnt; i++)
2511 {
2512 cur = new_cursor();
2513 cur->id = alloc_cursor_id(curg->lvc.language);
2514 cur->lvc.language = dup_language(curg->lvc.language);
2515 if(cde[i].offset > rd->size
2516 || cde[i].offset + cde[i].ressize > rd->size)
2517 yyerror("Cursor resource data corrupt");
2518 cur->width = cde[i].width;
2519 cur->height = cde[i].height;
2520 cur->nclr = cde[i].nclr;
2521 /* The next two are to support color cursors */
2522 cur->planes = ((BITMAPINFOHEADER *)BPTR(cde[i].offset))->biPlanes;
2523 cur->bits = ((BITMAPINFOHEADER *)BPTR(cde[i].offset))->biBitCount;
2524 if(!win32 && (cur->planes != 1 || cur->bits != 1))
2525 yywarning("Win16 cursor contains colors");
2526 cur->xhot = cde[i].xhot;
2527 cur->yhot = cde[i].yhot;
2528 cur->data = new_raw_data();
2529 copy_raw_data(cur->data, rd, cde[i].offset, cde[i].ressize);
2530 if(!list)
2531 {
2532 list = cur;
2533 }
2534 else
2535 {
2536 cur->next = list;
2537 list->prev = cur;
2538 list = cur;
2539 }
2540 }
2541 curg->cursorlist = list;
2542 *ncur = cnt;
2543}
2544
2545#undef BPTR
2546#undef WPTR
2547#undef DPTR
2548
2549
2550toolbar_item_t *ins_tlbr_button(toolbar_item_t *prev, toolbar_item_t *idrec)
2551{
2552 idrec->prev = prev;
2553 if(prev)
2554 prev->next = idrec;
2555
2556 return idrec;
2557}
2558
2559toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems)
2560{
2561 if(!p)
2562 {
2563 *nitems = 0;
2564 return NULL;
2565 }
2566
2567 *nitems = 1;
2568
2569 while(p->prev)
2570 {
2571 (*nitems)++;
2572 p = p->prev;
2573 }
2574
2575 return p;
2576}
2577
Note: See TracBrowser for help on using the repository browser.