Commit 0fb82036 authored by Alexandre Julliard's avatar Alexandre Julliard

wrc: Merge the dialog and dialogex structures.

parent a756caac
......@@ -44,7 +44,6 @@ const char *get_typename(const resource_t* r)
case res_cur: return "CURSOR";
case res_curg: return "GROUP_CURSOR";
case res_dlg: return "DIALOG";
case res_dlgex: return "DIALOGEX";
case res_fnt: return "FONT";
case res_ico: return "ICON";
case res_icog: return "GROUP_ICON";
......@@ -607,57 +606,6 @@ static void dump_dialog(const dialog_t *dlg)
/*
*****************************************************************************
* Function : dump_dialogex
* Syntax : void dump_dialogex(const dialogex_t *dlgex)
* Input :
* dlgex - DialogEx resource descriptor
* Output :
* Description :
* Remarks :
*****************************************************************************
*/
static void dump_dialogex(const dialogex_t *dlgex)
{
const control_t *c = dlgex->controls;
dump_memopt(dlgex->memopt);
dump_lvc(&(dlgex->lvc));
printf("x, y, w, h: %d, %d, %d, %d\n", dlgex->x, dlgex->y, dlgex->width, dlgex->height);
if(dlgex->gotstyle)
{
assert(dlgex->style != NULL);
assert(dlgex->style->and_mask == 0);
printf("Style: %08x\n", dlgex->style->or_mask);
}
if(dlgex->gotexstyle)
{
assert(dlgex->exstyle != NULL);
assert(dlgex->exstyle->and_mask == 0);
printf("ExStyle: %08x\n", dlgex->exstyle->or_mask);
}
if(dlgex->gothelpid)
printf("Helpid: %d\n", dlgex->helpid);
printf("Menu: %s\n", get_nameid_str(dlgex->menu));
printf("Class: %s\n", get_nameid_str(dlgex->dlgclass));
printf("Title: "); print_string(dlgex->title); printf("\n");
printf("Font: ");
if(!dlgex->font)
printf("<none>\n");
else
{
printf("%d, ", dlgex->font->size);
print_string(dlgex->font->name);
printf(", %d, %d\n", dlgex->font->weight, dlgex->font->italic);
}
while(c)
{
dump_control(c);
c = c->next;
}
}
/*
*****************************************************************************
* Function : dump_menu_item
* Syntax : void dump_menu_item(const menu_item_t *item)
* Input :
......@@ -986,9 +934,6 @@ void dump_resources(const resource_t *top)
case res_dlg:
dump_dialog(top->res.dlg);
break;
case res_dlgex:
dump_dialogex(top->res.dlgex);
break;
case res_fnt:
dump_font(top->res.fnt);
break;
......
......@@ -560,8 +560,25 @@ static res_t *dialog2res(name_id_t *name, dialog_t *dlg)
{
restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlg->memopt, &(dlg->lvc));
put_dword(res, dlg->style->or_mask);
put_dword(res, dlg->gotexstyle ? dlg->exstyle->or_mask : 0);
if (dlg->is_ex)
{
/* FIXME: MS doc says that the first word must contain 0xffff
* and the second 0x0001 to signal a DLGTEMPLATEEX. Borland's
* compiler reverses the two words.
* I don't know which one to choose, but I write it as Mr. B
* writes it.
*/
put_word(res, 1); /* Signature */
put_word(res, 0xffff); /* DlgVer */
put_dword(res, dlg->gothelpid ? dlg->helpid : 0);
put_dword(res, dlg->gotexstyle ? dlg->exstyle->or_mask : 0);
put_dword(res, dlg->gotstyle ? dlg->style->or_mask : WS_POPUPWINDOW);
}
else
{
put_dword(res, dlg->style->or_mask);
put_dword(res, dlg->gotexstyle ? dlg->exstyle->or_mask : 0);
}
tag_nctrl = res->size;
put_word(res, 0); /* Number of controls */
put_word(res, dlg->x);
......@@ -583,20 +600,42 @@ static res_t *dialog2res(name_id_t *name, dialog_t *dlg)
if(dlg->font)
{
put_word(res, dlg->font->size);
if (dlg->is_ex)
{
put_word(res, dlg->font->weight);
/* FIXME: ? TRUE should be sufficient to say that it's
* italic, but Borland's compiler says it's 0x0101.
* I just copy it here, and hope for the best.
*/
put_word(res, dlg->font->italic ? 0x0101 : 0);
}
put_string(res, dlg->font->name, str_unicode, TRUE, dlg->lvc.language);
}
put_pad(res);
while(ctrl)
{
/* FIXME: what is default control style? */
put_dword(res, ctrl->gotstyle ? ctrl->style->or_mask: WS_CHILD);
put_dword(res, ctrl->gotexstyle ? ctrl->exstyle->or_mask : 0);
if (dlg->is_ex)
{
put_dword(res, ctrl->gothelpid ? ctrl->helpid : 0);
put_dword(res, ctrl->gotexstyle ? ctrl->exstyle->or_mask : 0);
/* FIXME: what is default control style? */
put_dword(res, ctrl->gotstyle ? ctrl->style->or_mask : WS_CHILD | WS_VISIBLE);
}
else
{
/* FIXME: what is default control style? */
put_dword(res, ctrl->gotstyle ? ctrl->style->or_mask: WS_CHILD);
put_dword(res, ctrl->gotexstyle ? ctrl->exstyle->or_mask : 0);
}
put_word(res, ctrl->x);
put_word(res, ctrl->y);
put_word(res, ctrl->width);
put_word(res, ctrl->height);
put_word(res, ctrl->id);
if (dlg->is_ex)
put_dword(res, ctrl->id);
else
put_word(res, ctrl->id);
if(ctrl->ctlclass)
put_name_id(res, ctrl->ctlclass, TRUE, dlg->lvc.language);
else
......@@ -693,124 +732,6 @@ static res_t *dialog2res(name_id_t *name, dialog_t *dlg)
/*
*****************************************************************************
* Function : dialogex2res
* Syntax : res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex)
* Input :
* name - Name/ordinal of the resource
* dlgex - The dialogex descriptor
* Output : New .res format structure
* Description :
* Remarks :
*****************************************************************************
*/
static res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex)
{
int restag;
res_t *res;
control_t *ctrl;
int tag_nctrl;
int nctrl = 0;
assert(name != NULL);
assert(dlgex != NULL);
ctrl = dlgex->controls;
res = new_res();
if(win32)
{
restag = put_res_header(res, WRC_RT_DIALOG, NULL, name, dlgex->memopt, &(dlgex->lvc));
/* FIXME: MS doc says that the first word must contain 0xffff
* and the second 0x0001 to signal a DLGTEMPLATEEX. Borland's
* compiler reverses the two words.
* I don't know which one to choose, but I write it as Mr. B
* writes it.
*/
put_word(res, 1); /* Signature */
put_word(res, 0xffff); /* DlgVer */
put_dword(res, dlgex->gothelpid ? dlgex->helpid : 0);
put_dword(res, dlgex->gotexstyle ? dlgex->exstyle->or_mask : 0);
put_dword(res, dlgex->gotstyle ? dlgex->style->or_mask : WS_POPUPWINDOW);
tag_nctrl = res->size;
put_word(res, 0); /* Number of controls */
put_word(res, dlgex->x);
put_word(res, dlgex->y);
put_word(res, dlgex->width);
put_word(res, dlgex->height);
if(dlgex->menu)
put_name_id(res, dlgex->menu, TRUE, dlgex->lvc.language);
else
put_word(res, 0);
if(dlgex->dlgclass)
put_name_id(res, dlgex->dlgclass, TRUE, dlgex->lvc.language);
else
put_word(res, 0);
if(dlgex->title)
put_string(res, dlgex->title, str_unicode, TRUE, dlgex->lvc.language);
else
put_word(res, 0);
if(dlgex->font)
{
put_word(res, dlgex->font->size);
put_word(res, dlgex->font->weight);
/* FIXME: ? TRUE should be sufficient to say that it's
* italic, but Borland's compiler says it's 0x0101.
* I just copy it here, and hope for the best.
*/
put_word(res, dlgex->font->italic ? 0x0101 : 0);
put_string(res, dlgex->font->name, str_unicode, TRUE, dlgex->lvc.language);
}
put_pad(res);
while(ctrl)
{
put_dword(res, ctrl->gothelpid ? ctrl->helpid : 0);
put_dword(res, ctrl->gotexstyle ? ctrl->exstyle->or_mask : 0);
/* FIXME: what is default control style? */
put_dword(res, ctrl->gotstyle ? ctrl->style->or_mask : WS_CHILD | WS_VISIBLE);
put_word(res, ctrl->x);
put_word(res, ctrl->y);
put_word(res, ctrl->width);
put_word(res, ctrl->height);
put_dword(res, ctrl->id);
if(ctrl->ctlclass)
put_name_id(res, ctrl->ctlclass, TRUE, dlgex->lvc.language);
else
internal_error(__FILE__, __LINE__, "Control has no control-class\n");
if(ctrl->title)
put_name_id(res, ctrl->title, FALSE, dlgex->lvc.language);
else
put_word(res, 0);
if(ctrl->extra)
{
put_pad(res);
put_word(res, ctrl->extra->size);
put_raw_data(res, ctrl->extra, 0);
}
else
put_word(res, 0);
put_pad(res);
nctrl++;
ctrl = ctrl->next;
}
/* Set number of controls */
set_word(res, tag_nctrl, (WORD)nctrl);
/* Set ResourceSize */
SetResSize(res, restag);
put_pad(res);
}
else /* win16 */
{
/* Do not generate anything in 16-bit mode */
free(res->data);
free(res);
return NULL;
}
return res;
}
/*
*****************************************************************************
* Function : menuitem2res
* Syntax : void menuitem2res(res_t *res, menu_item_t *item)
* Input :
......@@ -1881,8 +1802,7 @@ const char *get_c_typename(enum res_e type)
case res_bmp: return "Bmp";
case res_cur: return "Cur";
case res_curg: return "CurGrp";
case res_dlg:
case res_dlgex: return "Dlg";
case res_dlg: return "Dlg";
case res_fnt: return "Fnt";
case res_fntdir:return "FntDir";
case res_ico: return "Ico";
......@@ -1937,10 +1857,6 @@ void resources2res(resource_t *top)
if(!top->binres)
top->binres = dialog2res(top->name, top->res.dlg);
break;
case res_dlgex:
if(!top->binres)
top->binres = dialogex2res(top->name, top->res.dlgex);
break;
case res_fnt:
if(!top->binres)
top->binres = font2res(top->name, top->res.fnt);
......
......@@ -47,7 +47,6 @@ typedef struct
/* Generate new_* functions that have no parameters (NOTE: no ';') */
__NEW_STRUCT_FUNC(dialog)
__NEW_STRUCT_FUNC(dialogex)
__NEW_STRUCT_FUNC(name_id)
__NEW_STRUCT_FUNC(menu)
__NEW_STRUCT_FUNC(menuex)
......
......@@ -34,7 +34,6 @@
#define __NEW_STRUCT_PROTO(p) p##_t *new_##p(void)
__NEW_STRUCT_PROTO(dialog);
__NEW_STRUCT_PROTO(dialogex);
__NEW_STRUCT_PROTO(name_id);
__NEW_STRUCT_PROTO(menu);
__NEW_STRUCT_PROTO(menuex);
......
......@@ -205,15 +205,6 @@ static raw_data_t *load_file(string_t *name, language_t *lang);
static itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid);
static event_t *add_string_event(string_t *key, int id, int flags, event_t *prev);
static event_t *add_event(int key, int id, int flags, event_t *prev);
static dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg);
static dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg);
static dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg);
static dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg);
static dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg);
static dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg);
static dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg);
static dialogex_t *dialogex_exstyle(style_t *st, dialogex_t *dlg);
static dialogex_t *dialogex_style(style_t *st, dialogex_t *dlg);
static name_id_t *convert_ctlclass(name_id_t *cls);
static control_t *ins_ctrl(int type, int special_style, control_t *ctrl, control_t *prev);
static dialog_t *dialog_version(version_t *v, dialog_t *dlg);
......@@ -244,7 +235,6 @@ static int rsrcid_to_token(int lookahead);
accelerator_t *acc;
bitmap_t *bmp;
dialog_t *dlg;
dialogex_t *dlgex;
font_t *fnt;
fontdir_t *fnd;
menu_t *men;
......@@ -316,10 +306,9 @@ static int rsrcid_to_token(int lookahead);
%type <event> events
%type <bmp> bitmap
%type <ani> cursor icon
%type <dlg> dialog dlg_attributes
%type <dlg> dialog dlg_attributes dialogex dlgex_attribs
%type <ctl> ctrls gen_ctrl lab_ctrl ctrl_desc iconinfo
%type <iptr> helpid
%type <dlgex> dialogex dlgex_attribs
%type <ctl> exctrls gen_exctrl lab_exctrl exctrl_desc
%type <html> html
%type <rdt> rcdata
......@@ -616,7 +605,7 @@ resource_definition
| dialog { $$ = new_resource(res_dlg, $1, $1->memopt, $1->lvc.language); }
| dialogex {
if(win32)
$$ = new_resource(res_dlgex, $1, $1->memopt, $1->lvc.language);
$$ = new_resource(res_dlg, $1, $1->memopt, $1->lvc.language);
else
$$ = NULL;
}
......@@ -1078,17 +1067,17 @@ dialogex: tDIALOGEX loadmemopts expr ',' expr ',' expr ',' expr helpid dlgex_att
;
dlgex_attribs
: /* Empty */ { $$=new_dialogex(); }
| dlgex_attribs tSTYLE style { $$=dialogex_style($3,$1); }
| dlgex_attribs tEXSTYLE style { $$=dialogex_exstyle($3,$1); }
| dlgex_attribs tCAPTION tSTRING { $$=dialogex_caption($3,$1); }
| dlgex_attribs opt_font { $$=dialogex_font($2,$1); }
| dlgex_attribs opt_exfont { $$=dialogex_font($2,$1); }
| dlgex_attribs tCLASS nameid_s { $$=dialogex_class($3,$1); }
| dlgex_attribs tMENU nameid { $$=dialogex_menu($3,$1); }
| dlgex_attribs opt_language { $$=dialogex_language($2,$1); }
| dlgex_attribs opt_characts { $$=dialogex_characteristics($2,$1); }
| dlgex_attribs opt_version { $$=dialogex_version($2,$1); }
: /* Empty */ { $$=new_dialog(); $$->is_ex = TRUE; }
| dlgex_attribs tSTYLE style { $$=dialog_style($3,$1); }
| dlgex_attribs tEXSTYLE style { $$=dialog_exstyle($3,$1); }
| dlgex_attribs tCAPTION tSTRING { $$=dialog_caption($3,$1); }
| dlgex_attribs opt_font { $$=dialog_font($2,$1); }
| dlgex_attribs opt_exfont { $$=dialog_font($2,$1); }
| dlgex_attribs tCLASS nameid_s { $$=dialog_class($3,$1); }
| dlgex_attribs tMENU nameid { $$=dialog_menu($3,$1); }
| dlgex_attribs opt_language { $$=dialog_language($2,$1); }
| dlgex_attribs opt_characts { $$=dialog_characteristics($2,$1); }
| dlgex_attribs opt_version { $$=dialog_version($2,$1); }
;
exctrls : /* Empty */ { $$ = NULL; }
......@@ -2163,118 +2152,6 @@ static name_id_t *convert_ctlclass(name_id_t *cls)
return cls;
}
/* DialogEx specific functions */
static dialogex_t *dialogex_style(style_t * st, dialogex_t *dlg)
{
assert(dlg != NULL);
if(dlg->style == NULL)
{
dlg->style = new_style(0,0);
}
if(dlg->gotstyle)
{
parser_warning("Style already defined, or-ing together\n");
}
else
{
dlg->style->or_mask = 0;
dlg->style->and_mask = 0;
}
dlg->style->or_mask |= st->or_mask;
dlg->style->and_mask |= st->and_mask;
dlg->gotstyle = TRUE;
free(st);
return dlg;
}
static dialogex_t *dialogex_exstyle(style_t * st, dialogex_t *dlg)
{
assert(dlg != NULL);
if(dlg->exstyle == NULL)
{
dlg->exstyle = new_style(0,0);
}
if(dlg->gotexstyle)
{
parser_warning("ExStyle already defined, or-ing together\n");
}
else
{
dlg->exstyle->or_mask = 0;
dlg->exstyle->and_mask = 0;
}
dlg->exstyle->or_mask |= st->or_mask;
dlg->exstyle->and_mask |= st->and_mask;
dlg->gotexstyle = TRUE;
free(st);
return dlg;
}
static dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg)
{
assert(dlg != NULL);
if(dlg->title)
yyerror("Caption already defined");
dlg->title = s;
return dlg;
}
static dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg)
{
assert(dlg != NULL);
if(dlg->font)
yyerror("Font already defined");
dlg->font = f;
return dlg;
}
static dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg)
{
assert(dlg != NULL);
if(dlg->dlgclass)
yyerror("Class already defined");
dlg->dlgclass = n;
return dlg;
}
static dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg)
{
assert(dlg != NULL);
if(dlg->menu)
yyerror("Menu already defined");
dlg->menu = m;
return dlg;
}
static dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg)
{
assert(dlg != NULL);
if(dlg->lvc.language)
yyerror("Language already defined");
dlg->lvc.language = l;
return dlg;
}
static dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg)
{
assert(dlg != NULL);
if(dlg->lvc.characts)
yyerror("Characteristics already defined");
dlg->lvc.characts = c;
return dlg;
}
static dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg)
{
assert(dlg != NULL);
if(dlg->lvc.version)
yyerror("Version already defined");
dlg->lvc.version = v;
return dlg;
}
/* Accelerator specific functions */
static event_t *add_event(int key, int id, int flags, event_t *prev)
{
......
......@@ -47,8 +47,6 @@ static language_t get_language(resource_t *resource) {
return *resource->res.curg->lvc.language;
case res_dlg:
return *resource->res.dlg->lvc.language;
case res_dlgex:
return *resource->res.dlgex->lvc.language;
case res_fnt:
return *resource->res.fnt->data->lvc.language;
case res_fntdir:
......@@ -358,6 +356,13 @@ static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
((dialog1->gotexstyle && !dialog2->gotexstyle) ||
(!dialog1->gotexstyle && dialog2->gotexstyle)))
different = 1;
if(!different && dialog1->gothelpid && dialog2->gothelpid) {
if(dialog1->helpid != dialog2->helpid)
different = 1;
} else if(!different &&
((dialog1->gothelpid && !dialog2->gothelpid) ||
(!dialog1->gothelpid && dialog2->gothelpid)))
different = 1;
nameid = strdup(get_nameid_str(dialog1->menu));
if(!different && strcmp(nameid, get_nameid_str(dialog2->menu)))
different = 1;
......@@ -378,60 +383,6 @@ static int compare_dialog(dialog_t *dialog1, dialog_t *dialog2) {
return different;
}
static int compare_dialogex(dialogex_t *dialogex1, dialogex_t *dialogex2) {
int different = 0;
char *nameid = NULL;
control_t *ctrl1, *ctrl2;
if(!different &&
((dialogex1->memopt != dialogex2->memopt) ||
(dialogex1->lvc.version != dialogex2->lvc.version) ||
(dialogex1->lvc.characts != dialogex2->lvc.characts)))
different = 1;
if(!different && dialogex1->gotstyle && dialogex2->gotstyle) {
if((!dialogex1->style || !dialogex2->style) ||
(dialogex1->style->and_mask || dialogex2->style->and_mask) ||
(dialogex1->style->or_mask != dialogex2->style->or_mask))
different = 1;
} else if(!different &&
((dialogex1->gotstyle && !dialogex2->gotstyle) ||
(!dialogex1->gotstyle && dialogex2->gotstyle)))
different = 1;
if(!different && dialogex1->gotexstyle && dialogex2->gotexstyle) {
if((!dialogex1->exstyle || !dialogex2->exstyle) ||
(dialogex1->exstyle->and_mask || dialogex2->exstyle->and_mask) ||
(dialogex1->exstyle->or_mask != dialogex2->exstyle->or_mask))
different = 1;
} else if(!different &&
((dialogex1->gotexstyle && !dialogex2->gotexstyle) ||
(!dialogex1->gotexstyle && dialogex2->gotexstyle)))
different = 1;
if(!different && dialogex1->gothelpid && dialogex2->gothelpid) {
if(dialogex1->helpid != dialogex2->helpid)
different = 1;
} else if(!different &&
((dialogex1->gothelpid && !dialogex2->gothelpid) ||
(!dialogex1->gothelpid && dialogex2->gothelpid)))
different = 1;
nameid = strdup(get_nameid_str(dialogex1->menu));
if(!different && strcmp(nameid, get_nameid_str(dialogex2->menu)))
different = 1;
free(nameid);
nameid = strdup(get_nameid_str(dialogex1->dlgclass));
if(!different && strcmp(nameid, get_nameid_str(dialogex2->dlgclass)))
different = 1;
free(nameid);
ctrl1 = dialogex1->controls;
ctrl2 = dialogex2->controls;
while(!different && (ctrl1 || ctrl2))
{
different = compare_control(ctrl1, ctrl2);
if (ctrl1) ctrl1 = ctrl1->next;
if (ctrl2) ctrl2 = ctrl2->next;
}
return different;
}
static int compare_font(font_t *font1, font_t *font2) {
int different = 0;
if(!different &&
......@@ -924,8 +875,6 @@ static int compare(resource_t *resource1, resource_t *resource2) {
return compare_cursor_group(resource1->res.curg, resource2->res.curg);
case res_dlg:
return compare_dialog(resource1->res.dlg, resource2->res.dlg);
case res_dlgex:
return compare_dialogex(resource1->res.dlgex, resource2->res.dlgex);
case res_fnt:
return compare_font(resource1->res.fnt, resource2->res.fnt);
case res_fntdir:
......@@ -1034,7 +983,6 @@ static void setup_tabs(void)
case res_cur:
case res_curg:
case res_dlg:
case res_dlgex:
case res_fnt:
case res_fntdir:
case res_ico:
......
......@@ -184,7 +184,6 @@ enum res_e {
res_toolbar = WRC_RT_TOOLBAR, /* 241 */
res_menex = 256 + 4,
res_dlgex,
res_usr
};
......@@ -223,36 +222,18 @@ typedef struct dialog {
int height;
style_t *style; /* Style */
style_t *exstyle;
int gotstyle; /* Used to determine whether the default */
int gotexstyle; /* styles must be set */
name_id_t *menu;
name_id_t *dlgclass;
string_t *title;
font_id_t *font;
lvc_t lvc;
control_t *controls;
} dialog_t;
/* DialogEx structures */
typedef struct dialogex {
DWORD memopt;
int x; /* Position */
int y;
int width; /* Size */
int height;
style_t *style; /* Style */
style_t *exstyle;
DWORD helpid; /* EX: */
int gotstyle; /* Used to determine whether the default */
int gotexstyle; /* styles must be set */
int gothelpid;
int is_ex;
name_id_t *menu;
name_id_t *dlgclass;
string_t *title;
font_id_t *font;
lvc_t lvc;
control_t *controls;
} dialogex_t;
} dialog_t;
/* Menu structures */
typedef struct menu_item {
......@@ -611,7 +592,6 @@ typedef struct resource {
cursor_t *cur;
cursor_group_t *curg;
dialog_t *dlg;
dialogex_t *dlgex;
dlginit_t *dlgi;
font_t *fnt;
fontdir_t *fnd;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment