/* * Rufus: The Reliable USB Formatting Utility * Localization functions, a.k.a. "Everybody is doing it wrong but me!" * Copyright © 2013-2016 Pete Batard * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #pragma once // Number of concurrent localization messages (i.e. messages we can concurrently // reference at the same time). Must be a power of 2. #define LOC_MESSAGE_NB 32 #define LOC_MESSAGE_SIZE 2048 #define LOC_HTAB_SIZE 1031 // Using a prime speeds up the hash table init // Attributes that can be set by a translation #define LOC_RIGHT_TO_LEFT 0x00000001 #define LOC_NEEDS_UPDATE 0x00000002 #define MSG_RTF 0x10000000 #define MSG_MASK 0x0FFFFFFF #define luprint(msg) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr) #define luprintf(msg, ...) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr, __VA_ARGS__) /* * List handling functions (stolen from libusb) * NB: offsetof() requires '#include ' */ struct list_head { struct list_head *prev, *next; }; /* Get an entry from the list * ptr - the address of this list_head element in "type" * type - the data type that contains "member" * member - the list_head element in "type" */ #define list_entry(ptr, type, member) \ ((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member))) /* Get each entry from a list * pos - A structure pointer has a "member" element * head - list head * member - the list_head element in "pos" * type - the type of the first parameter */ #define list_for_each_entry(pos, head, type, member) \ for (pos = list_entry((head)->next, type, member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, type, member)) #define list_for_each_entry_safe(pos, n, head, type, member) \ for (pos = list_entry((head)->next, type, member), \ n = list_entry(pos->member.next, type, member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, type, member)) #define list_empty(entry) ((entry)->next == (entry)) static __inline void list_init(struct list_head *entry) { entry->prev = entry->next = entry; } static __inline void list_add(struct list_head *entry, struct list_head *head) { entry->next = head->next; entry->prev = head; head->next->prev = entry; head->next = entry; } static __inline void list_add_tail(struct list_head *entry, struct list_head *head) { entry->next = head; entry->prev = head->prev; head->prev->next = entry; head->prev = entry; } static __inline void list_del(struct list_head *entry) { entry->next->prev = entry->prev; entry->prev->next = entry->next; entry->next = entry->prev = NULL; } // Commands that take a control ID *MUST* be at the top // The last command with a control ID *MUST* be LC_TEXT enum loc_command_type { LC_GROUP, LC_TEXT, // Delimits commands that take a Control ID and commands that don't LC_VERSION, LC_LOCALE, LC_BASE, LC_FONT, LC_ATTRIBUTES, }; typedef struct loc_cmd_struct { uint8_t command; uint8_t unum_size; uint16_t line_nr; int ctrl_id; // Also used as the attributes mask int32_t num[2]; uint32_t* unum; char* txt[2]; struct list_head list; } loc_cmd; typedef struct loc_parse_struct { char c; enum loc_command_type cmd; char* arg_type; } loc_parse; typedef struct loc_control_id_struct { const char* name; const int id; } loc_control_id; typedef struct loc_dlg_list_struct { const int dlg_id; HWND hDlg; struct list_head list; } loc_dlg_list; extern const loc_parse parse_cmd[7]; extern struct list_head locale_list; extern char *default_msg_table[], *current_msg_table[], **msg_table; extern int loc_line_nr; extern char *loc_filename, *embedded_loc_filename; extern BOOL en_msg_mode; void free_loc_cmd(loc_cmd* lcmd); BOOL dispatch_loc_cmd(loc_cmd* lcmd); void _init_localization(BOOL reinit); void _exit_localization(BOOL reinit); #define init_localization() _init_localization(FALSE) #define exit_localization() _exit_localization(FALSE) #define reinit_localization() do {_exit_localization(TRUE); _init_localization(TRUE);} while(0) void apply_localization(int dlg_id, HWND hDlg); void reset_localization(int dlg_id); void free_dialog_list(void); char* lmprintf(uint32_t msg_id, ...); BOOL get_supported_locales(const char* filename); BOOL get_loc_data_file(const char* filename, loc_cmd* lcmd); void free_locale_list(void); loc_cmd* get_locale_from_lcid(int lcid, BOOL fallback); loc_cmd* get_locale_from_name(char* locale_name, BOOL fallback); void toggle_default_locale(void); const char* get_name_from_id(int id); WORD get_language_id(loc_cmd* lcmd);