Merged older cs.po file with newest pot file.
[gliv/czech_localization.git] / src / mnemonics.c
blob2406b19d64c2a057843ccf65abf19878a2050f56
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <guichaz@yahoo.fr>
21 /*****************************************
22 * Try to add unique mnemonics to labels *
23 *****************************************/
25 #include <string.h> /* strlen(), memcpy() */
27 #include "gliv.h"
28 #include "mnemonics.h"
29 #include "str_utils.h"
31 static GSList *stack = NULL;
32 static GHashTable *mnemonics = NULL;
34 static gint count_underscores(const gchar * str, gint len)
36 gint nb_underscores = 0;
37 const gulong *long_ptr;
39 while ((gulong) str & (sizeof(gulong) - 1))
40 switch (*str) {
41 case '\0':
42 return nb_underscores;
44 case '_':
45 nb_underscores++;
46 /* Fall through */
48 default:
49 str++;
50 len--;
53 long_ptr = (gulong *) str;
55 while (len >= sizeof(gulong)) {
56 gulong masked = *long_ptr ^ LONG_MASK(0x5F5F5F5FL, 0x5F5F5F5F5F5F5F5FL);
58 if (HAS_ZERO(masked)) {
59 /* A '_' has been detected. */
60 gchar *char_ptr = (gchar *) & masked;
61 gint i;
62 for (i = 0; i < sizeof(gulong); i++)
63 nb_underscores += (*char_ptr++ == 0);
66 long_ptr++;
67 len -= sizeof(gulong);
70 str = (const gchar *) long_ptr;
71 while (len > 0) {
72 nb_underscores += (*str == '_');
73 str++;
74 len--;
77 return nb_underscores;
80 static const gchar *find_mnemonic_position(const gchar * str)
82 const gchar *ptr;
84 for (ptr = str; *ptr != '\0'; ptr = g_utf8_next_char(ptr)) {
85 gunichar ch = g_unichar_tolower(g_utf8_get_char(ptr));
86 gpointer ch_key = GINT_TO_POINTER(ch);
88 if (g_unichar_isalnum(ch)) {
89 if (mnemonics == NULL) {
90 mnemonics = g_hash_table_new(g_direct_hash, g_direct_equal);
91 g_hash_table_insert(mnemonics, ch_key, mnemonics);
92 return ptr;
95 if (g_hash_table_lookup(mnemonics, ch_key) == NULL) {
96 g_hash_table_insert(mnemonics, ch_key, mnemonics);
97 return ptr;
102 /* No position found, add in front. */
103 return str;
107 * Underscores in labels are replaced with mnemonics, so we duplicate them.
108 * The caller has to determine whether the returned string has to be freed.
110 static gchar *duplicate_underscores(const gchar * orig)
112 gint nb_underscores, len;
113 const gchar *ptr_orig;
114 gchar *new, *ptr_new;
116 /* How many underscores? */
117 len = strlen(orig);
118 nb_underscores = count_underscores(orig, len);
119 len += nb_underscores;
121 if (nb_underscores == 0)
122 return (gchar *) orig;
124 ptr_new = new = g_new(gchar, len + 1);
126 for (ptr_orig = orig; *ptr_orig != '\0'; ptr_orig++) {
127 *ptr_new = *ptr_orig;
128 if (*ptr_orig == '_') {
129 /* Duplicate this one. */
130 ptr_new++;
131 *ptr_new = '_';
133 ptr_new++;
136 *ptr_new = '\0';
138 return new;
142 * The returned string should not be freed. We keep track of already used
143 * mnemonics to avoid giving twice the same letter.
145 const gchar *add_mnemonic(const gchar * str)
147 static gchar *result = NULL;
148 static gint size = 0;
149 const gchar *mnemonic_pos, *end;
150 gint new_size, offset;
151 gchar *work;
153 work = duplicate_underscores(str);
154 mnemonic_pos = find_mnemonic_position(work);
155 end = mnemonic_pos + strlen(mnemonic_pos);
157 /* + 2: '_' and '\0'. */
158 new_size = end - work + 2;
159 if (new_size > size) {
160 size = new_size;
161 g_free(result);
163 result = g_new(gchar, size);
166 offset = mnemonic_pos - work;
167 memcpy(result, work, offset);
168 result[offset] = '_';
169 memcpy(result + offset + 1, mnemonic_pos, end - mnemonic_pos + 1);
171 if (work != str)
172 g_free(work);
174 return result;
177 void reset_mnemonics(void)
179 if (mnemonics != NULL) {
180 g_hash_table_destroy(mnemonics);
181 mnemonics = NULL;
185 void push_mnemonics(void)
187 stack = g_slist_prepend(stack, mnemonics);
188 mnemonics = NULL;
191 void pop_mnemonics(void)
193 reset_mnemonics();
194 mnemonics = g_slist_nth_data(stack, 0);
195 stack = g_slist_delete_link(stack, stack);