From ceadc43c78b228b9e7d0acafff287b0403907759 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 24 Jan 2012 14:19:36 +0100 Subject: [PATCH] wrc: Add support for translating accelerators through po files. --- tools/wrc/genres.c | 68 ++++++++++++++++++++++++++++++++++++++++-- tools/wrc/parser.y | 1 + tools/wrc/po.c | 71 ++++++++++++++++++++++++++++++++++++++++++-- tools/wrc/wrctypes.h | 1 + 4 files changed, 136 insertions(+), 5 deletions(-) diff --git a/tools/wrc/genres.c b/tools/wrc/genres.c index 6b2d7ed9b2c..d6e641fc4f4 100644 --- a/tools/wrc/genres.c +++ b/tools/wrc/genres.c @@ -276,6 +276,66 @@ static void string_to_upper(string_t *str) } } +static int parse_accel_string( const string_t *key, int flags ) +{ + int keycode; + + if(key->type == str_char) + { + if((flags & WRC_AF_VIRTKEY) && + !((key->str.cstr[0] >= 'A' && key->str.cstr[0] <= 'Z') || + (key->str.cstr[0] >= '0' && key->str.cstr[0] <= '9'))) + { + print_location( &key->loc ); + error("VIRTKEY code is not equal to ascii value"); + } + + if(key->str.cstr[0] == '^' && (flags & WRC_AF_CONTROL) != 0) + { + print_location( &key->loc ); + error("Cannot use both '^' and CONTROL modifier"); + } + else if(key->str.cstr[0] == '^') + { + keycode = toupper((unsigned char)key->str.cstr[1]) - '@'; + if(keycode >= ' ') + { + print_location( &key->loc ); + error("Control-code out of range"); + } + } + else + keycode = key->str.cstr[0]; + } + else + { + if((flags & WRC_AF_VIRTKEY) && + !((key->str.wstr[0] >= 'A' && key->str.wstr[0] <= 'Z') || + (key->str.wstr[0] >= '0' && key->str.wstr[0] <= '9'))) + { + print_location( &key->loc ); + error("VIRTKEY code is not equal to ascii value"); + } + if(key->str.wstr[0] == '^' && (flags & WRC_AF_CONTROL) != 0) + { + print_location( &key->loc ); + error("Cannot use both '^' and CONTROL modifier"); + } + else if(key->str.wstr[0] == '^') + { + keycode = toupperW(key->str.wstr[1]) - '@'; + if(keycode >= ' ') + { + print_location( &key->loc ); + error("Control-code out of range"); + } + } + else + keycode = key->str.wstr[0]; + } + return keycode; +} + /* ***************************************************************************** * Function : put_string @@ -514,8 +574,10 @@ static res_t *accelerator2res(name_id_t *name, accelerator_t *acc) restag = put_res_header(res, WRC_RT_ACCELERATOR, NULL, name, acc->memopt, &(acc->lvc)); while(ev) { + int key = ev->key; + if (ev->str) key = parse_accel_string( ev->str, ev->flags ); put_word(res, ev->flags | (ev->next ? 0 : 0x80)); - put_word(res, ev->key); + put_word(res, key); put_word(res, ev->id); put_word(res, 0); /* Padding */ ev = ev->next; @@ -527,8 +589,10 @@ static res_t *accelerator2res(name_id_t *name, accelerator_t *acc) restag = put_res_header(res, WRC_RT_ACCELERATOR, NULL, name, acc->memopt, NULL); while(ev) { + int key = ev->key; + if (ev->str) key = parse_accel_string( ev->str, ev->flags ); put_byte(res, ev->flags | (ev->next ? 0 : 0x80)); - put_word(res, ev->key); + put_word(res, key); put_word(res, ev->id); ev = ev->next; } diff --git a/tools/wrc/parser.y b/tools/wrc/parser.y index e1a3c689be3..efcc050470c 100644 --- a/tools/wrc/parser.y +++ b/tools/wrc/parser.y @@ -2219,6 +2219,7 @@ static event_t *add_string_event(string_t *key, int id, int flags, event_t *prev keycode = key->str.wstr[0]; } + ev->str = key; ev->key = keycode; ev->id = id; ev->flags = flags & ~WRC_AF_ASCII; diff --git a/tools/wrc/po.c b/tools/wrc/po.c index ffb584f16c8..1d679bae0da 100644 --- a/tools/wrc/po.c +++ b/tools/wrc/po.c @@ -124,6 +124,16 @@ static char *get_message_context( char **msgid ) return context; } +static int string_has_context( const string_t *str ) +{ + char *id, *id_buffer, *context; + + id_buffer = id = convert_msgid_ascii( str, 1 ); + context = get_message_context( &id ); + free( id_buffer ); + return context != NULL; +} + static int control_has_title( const control_t *ctrl ) { if (!ctrl->title) return 0; @@ -155,6 +165,12 @@ static resource_t *dup_resource( resource_t *res, language_t *lang ) switch (res->type) { + case res_acc: + new->res.acc = xmalloc( sizeof(*(new)->res.acc) ); + *new->res.acc = *res->res.acc; + new->res.acc->lvc.language = lang; + new->res.acc->lvc.version = get_dup_version( lang ); + break; case res_dlg: new->res.dlg = xmalloc( sizeof(*(new)->res.dlg) ); *new->res.dlg = *res->res.dlg; @@ -803,6 +819,34 @@ static void add_po_menu( const resource_t *english, const resource_t *res ) add_po_menu_items( po, english_items, items, res->res.men->lvc.language ); } +static void add_pot_accel( po_file_t po, const resource_t *res ) +{ + event_t *event = res->res.acc->events; + + while (event) + { + /* accelerators without a context don't make sense in po files */ + if (event->str && string_has_context( event->str )) + add_po_string( po, event->str, NULL, NULL ); + event = event->next; + } +} + +static void add_po_accel( const resource_t *english, const resource_t *res ) +{ + event_t *english_event = english->res.acc->events; + event_t *event = res->res.acc->events; + po_file_t po = get_po_file( res->res.acc->lvc.language ); + + while (english_event && event) + { + if (english_event->str && event->str && string_has_context( english_event->str )) + add_po_string( po, english_event->str, event->str, res->res.acc->lvc.language ); + event = event->next; + english_event = english_event->next; + } +} + static resource_t *find_english_resource( resource_t *res ) { resource_t *ptr; @@ -829,7 +873,7 @@ void write_pot_file( const char *outname ) switch (res->type) { - case res_acc: break; /* FIXME */ + case res_acc: add_pot_accel( po, res ); break; case res_dlg: add_pot_dialog( po, res ); break; case res_men: add_pot_menu( po, res ); break; case res_stt: add_pot_stringtable( po, res ); break; @@ -850,7 +894,7 @@ void write_po_files( const char *outname ) if (!(english = find_english_resource( res ))) continue; switch (res->type) { - case res_acc: break; /* FIXME */ + case res_acc: add_po_accel( english, res ); break; case res_dlg: add_po_dialog( english, res ); break; case res_men: add_po_menu( english, res ); break; case res_stt: add_po_stringtable( english, res ); break; @@ -1089,6 +1133,26 @@ static void translate_dialog( dialog_t *dlg, dialog_t *new, int *found ) new->controls = translate_controls( dlg->controls, found ); } +static event_t *translate_accel( accelerator_t *acc, accelerator_t *new, int *found ) +{ + event_t *event, *new_ev, *head = NULL, *tail = NULL; + + event = acc->events; + while (event) + { + new_ev = new_event(); + *new_ev = *event; + if (event->str) new_ev->str = translate_string( event->str, found ); + if (tail) tail->next = new_ev; + else head = new_ev; + new_ev->next = NULL; + new_ev->prev = tail; + tail = new_ev; + event = event->next; + } + return head; +} + static void translate_resources( language_t *lang ) { resource_t *res; @@ -1103,7 +1167,8 @@ static void translate_resources( language_t *lang ) switch (res->type) { case res_acc: - /* FIXME */ + new = dup_resource( res, lang ); + new->res.acc->events = translate_accel( res->res.acc, new->res.acc, &found ); break; case res_dlg: new = dup_resource( res, lang ); diff --git a/tools/wrc/wrctypes.h b/tools/wrc/wrctypes.h index 4df92799fec..99699d72d0c 100644 --- a/tools/wrc/wrctypes.h +++ b/tools/wrc/wrctypes.h @@ -537,6 +537,7 @@ typedef struct versioninfo { typedef struct event { struct event *next; struct event *prev; + string_t *str; int flags; int key; int id;