Commit 8c71a0d4 authored by Simos Xenitellis's avatar Simos Xenitellis

Closed Bug 550676 – Memory leak, update keyboard layout data table

svn path=/trunk/; revision=21339
parent 38417bf7
2008-09-10 Simos Xenitellis <simos@gnome.org>
Bug 550676 – Memory leak, update keyboard layout data structure
* gtk/gtkimcontextsimple.c (check_normalize_nfc): Added
function that checks if unicode sequence can be normalised (NFC)
to single character. Fixed memory leaks.
(check_algorithmically): Moved code to check_normalize_nfc,
updated switch statement for dead keys.
(gtk_im_context_simple_filter_keypress): Changed order; first
check_algorithmically() is attempted, then check_compact_table().
* gtk/gtkimcontextsimpleseqs.c: Updated compose sequence table
gtk_compose_seqs_compac[].
* gtk/compose-parse.py: Updated compose table generation script,
matches output to gtk/gtkimcontextsimpleseqs.c.
Wed Sep 10 06:18:25 2008 Søren Sandmann <sandmann@redhat.com>
* gdk/x11/gdkscreen-x11.c (init_multihead): Don't use
......
......@@ -279,9 +279,17 @@ def process_gdkkeysymsh():
""" Patch up the keysymdb with some of our own stuff """
""" This is for a missing keysym from the currently upstread file """
""" This is for a missing keysym from the currently upstream file """
keysymdb['dead_stroke'] = 0x338
""" This is for a missing keysym from the currently upstream file """
###keysymdb['dead_belowring'] = 0x323
###keysymdb['dead_belowmacron'] = 0x331
###keysymdb['dead_belowcircumflex'] = 0x32d
###keysymdb['dead_belowtilde'] = 0x330
###keysymdb['dead_belowbreve'] = 0x32e
###keysymdb['dead_belowdiaeresis'] = 0x324
""" This is^Wwas preferential treatment for Greek """
# keysymdb['dead_tilde'] = 0x342
""" This is^was preferential treatment for Greek """
......@@ -327,6 +335,13 @@ def process_keysymstxt():
keysymstxt.close()
""" Patch up the keysymdb with some of our own stuff """
""" This is for a missing keysym from the currently upstream file """
###keysymdb['dead_belowring'] = 0x323
###keysymdb['dead_belowmacron'] = 0x331
###keysymdb['dead_belowcircumflex'] = 0x32d
###keysymdb['dead_belowtilde'] = 0x330
###keysymdb['dead_belowbreve'] = 0x32e
###keysymdb['dead_belowdiaeresis'] = 0x324
""" This is preferential treatment for Greek """
""" => we get more savings if used for Greek """
......@@ -337,7 +352,7 @@ def process_keysymstxt():
""" This is for a missing keysym from Markus Kuhn's db """
keysymdb['dead_stroke'] = 0x338
""" This is for a missing keysym from Markus Kuhn's db """
# keysymdb['Oslash'] = 0x0d8
keysymdb['Oslash'] = 0x0d8
""" This is for a missing (recently added) keysym """
keysymdb['dead_psili'] = 0x313
......@@ -362,8 +377,9 @@ def keysymvalue(keysym, file = "n/a", linenum = 0):
elif keysym[:2] == '0x' and match('[0-9a-fA-F]+$', keysym[2:]):
return atoi(keysym[2:], 16)
else:
print 'UNKNOWN{%(keysym)s}' % { "keysym": keysym }
sys.exit(-1)
#print 'UNKNOWN{%(keysym)s}' % { "keysym": keysym }
return -1
#sys.exit(-1)
def keysymunicodevalue(keysym, file = "n/a", linenum = 0):
""" Extracts a value from the keysym """
......@@ -428,13 +444,21 @@ for line in composefile.readlines():
values = split('\s+', val)
unichar_temp = split('"', values[0])
unichar = unichar_temp[1]
if len(values) == 1:
continue
codepointstr = values[1]
if values[1] == '#':
# No codepoints that are >1 characters yet.
continue
if raw_sequence[0][0] == 'U' and match('[0-9a-fA-F]+$', raw_sequence[0][1:]):
raw_sequence[0] = '0x' + raw_sequence[0][1:]
if codepointstr[0] == 'U' and match('[0-9a-fA-F]+$', codepointstr[1:]):
codepoint = atoi(codepointstr[1:], 16)
elif keysymdatabase.has_key(codepointstr):
codepoint = keysymdatabase[codepointstr]
elif keysymunicodedatabase.has_key(codepointstr):
if keysymdatabase[codepointstr] != keysymunicodedatabase[codepointstr]:
print "DIFFERENCE: 0x%(a)X 0x%(b)X" % { "a": keysymdatabase[codepointstr], "b": keysymunicodedatabase[codepointstr]},
print raw_sequence, codepointstr
codepoint = keysymunicodedatabase[codepointstr]
else:
print
print "Invalid codepoint at line %(linenum_compose)d in %(filename)s:\
......@@ -448,13 +472,21 @@ for line in composefile.readlines():
if opt_plane1:
print sequence
break
if keysymvalue(i) < 0:
reject_this = True
break
if reject_this:
continue
if "U0313" in sequence or "U0314" in sequence or "0x0313" in sequence or "0x0314" in sequence:
if "U0342" in sequence or \
"U0313" in sequence or \
"U0314" in sequence or \
"0x0313" in sequence or \
"0x0342" in sequence or \
"0x0314" in sequence:
continue
for i in range(len(sequence)):
if sequence[i] == "0x0342":
sequence[i] = "dead_tilde"
#for i in range(len(sequence)):
# if sequence[i] == "0x0342":
# sequence[i] = "dead_tilde"
if "Multi_key" not in sequence:
""" Ignore for now >0xFFFF keysyms """
if codepoint < 0xFFFF:
......@@ -473,7 +505,7 @@ for line in composefile.readlines():
because of lack of dead_perispomeni (i.e. conflict)
"""
bc = basechar
if sequence[-1] == "dead_tilde" and (bc >= 0x370 and bc <= 0x3ff) or (bc >= 0x1f00 and bc <= 0x1fff):
"""if sequence[-1] == "dead_tilde" and (bc >= 0x370 and bc <= 0x3ff) or (bc >= 0x1f00 and bc <= 0x1fff):
skipping_this = True
break
if sequence[-1] == "dead_horn" and (bc >= 0x370 and bc <= 0x3ff) or (bc >= 0x1f00 and bc <= 0x1fff):
......@@ -486,6 +518,7 @@ for line in composefile.readlines():
sequence[i] = "dead_horn"
if sequence[-1] == "dead_dasia":
sequence[-1] = "dead_ogonek"
"""
unisequence.append(unichr(keysymunicodevalue(sequence.pop(), filename_compose, linenum_compose)))
if skipping_this:
......
......@@ -61,7 +61,7 @@ struct _GtkComposeTableCompact
static const GtkComposeTableCompact gtk_compose_table_compact = {
gtk_compose_seqs_compact,
5,
21,
22,
6
};
......@@ -340,10 +340,77 @@ check_compact_table (GtkIMContextSimple *context_simple,
return FALSE;
}
/* This function receives a sequence of Unicode characters and tries to
* normalize it (NFC). We check for the case the the resulting string
* has length 1 (single character).
* NFC normalisation normally rearranges diacritic marks, unless these
* belong to the same Canonical Combining Class.
* If they belong to the same canonical combining class, we produce all
* permutations of the diacritic marks, then attempt to normalize.
*/
static gboolean
check_normalize_nfc (gunichar* combination_buffer, gint n_compose)
{
gunichar combination_buffer_temp[GTK_MAX_COMPOSE_LEN];
gchar *combination_utf8_temp = NULL;
gchar *nfc_temp = NULL;
gint n_combinations;
gunichar temp_swap;
gint i;
n_combinations = 1;
for (i = 1; i < n_compose; i++ )
n_combinations *= i;
/* Xorg reuses dead_tilde for the perispomeni diacritic mark.
* We check if base character belongs to Greek Unicode block,
* and if so, we replace tilde with perispomeni. */
if (combination_buffer[0] >= 0x390 && combination_buffer[0] <= 0x3FF)
{
for (i = 1; i < n_compose; i++ )
if (combination_buffer[i] == 0x303)
combination_buffer[i] = 0x342;
}
memcpy (combination_buffer_temp, combination_buffer, GTK_MAX_COMPOSE_LEN * sizeof (gunichar) );
for (i = 0; i < n_combinations; i++ )
{
g_unicode_canonical_ordering (combination_buffer_temp, n_compose);
combination_utf8_temp = g_ucs4_to_utf8 (combination_buffer_temp, -1, NULL, NULL, NULL);
nfc_temp = g_utf8_normalize (combination_utf8_temp, -1, G_NORMALIZE_NFC);
if (g_utf8_strlen (nfc_temp, -1) == 1)
{
memcpy (combination_buffer, combination_buffer_temp, GTK_MAX_COMPOSE_LEN * sizeof (gunichar) );
g_free (combination_utf8_temp);
g_free (nfc_temp);
return TRUE;
}
g_free (combination_utf8_temp);
g_free (nfc_temp);
if (n_compose > 2)
{
temp_swap = combination_buffer_temp[i % (n_compose - 1) + 1];
combination_buffer_temp[i % (n_compose - 1) + 1] = combination_buffer_temp[(i+1) % (n_compose - 1) + 1];
combination_buffer_temp[(i+1) % (n_compose - 1) + 1] = temp_swap;
}
else
break;
}
return FALSE;
}
/* When updating the table of the compose sequences, also update here.
*/
#define IS_DEAD_KEY(k) \
(((k) >= GDK_dead_grave && (k) <= GDK_dead_stroke) || \
(((k) >= GDK_dead_grave && (k) <= (GDK_dead_dasia+1)) || \
g_unichar_type (gdk_keyval_to_unicode (k)) == G_UNICODE_NON_SPACING_MARK)
static gboolean
......@@ -351,12 +418,9 @@ check_algorithmically (GtkIMContextSimple *context_simple,
gint n_compose)
{
int i;
int k;
gint i;
gunichar combination_buffer[GTK_MAX_COMPOSE_LEN];
gunichar combination_buffer_temp[GTK_MAX_COMPOSE_LEN];
gchar *combination_utf8, *nfc;
gchar *combination_utf8_temp = NULL, *nfc_temp = NULL;
if (n_compose >= GTK_MAX_COMPOSE_LEN)
return FALSE;
......@@ -381,39 +445,33 @@ check_algorithmically (GtkIMContextSimple *context_simple,
CASE (grave, 0x0300);
CASE (acute, 0x0301);
CASE (circumflex, 0x0302);
CASE (tilde, 0x0303); /* Normally is 0x303; Greek Polytonic needs 0x342.
* We modified the compose sequences for now
* so that for Greek we don't apply algorithmic
* when perispomeni (0x342) is required
* Filed report; pending, bug 14013 (Freedesktop).
*/
CASE (tilde, 0x0303); /* Also used with perispomeni, 0x342. */
CASE (macron, 0x0304);
CASE (breve, 0x0306);
CASE (abovedot, 0x0307);
CASE (diaeresis, 0x0308);
CASE (hook, 0x0309);
CASE (abovering, 0x030A);
CASE (doubleacute, 0x030B);
CASE (caron, 0x030C);
CASE (abovecomma, 0x0313); /* Equivalent to psili */
CASE (abovereversedcomma, 0x0314); /* Equivalent to dasia */
CASE (horn, 0x031B); /* Legacy use for psili, 0x313 (or 0x343). */
CASE (belowdot, 0x0323);
CASE (cedilla, 0x0327);
CASE (ogonek, 0x0328); /* Normally is 0x328; Greek Polytonic needs 0x314.
* We modified the compose sequences for now to
* so that for Greek we don't apply algorithmic
* when dasia (0x314) is required
* Patch accepted in Xorg/GIT, may take a bit to propagate.
*/
CASE (dasia, 0x314);
CASE (iota, 0x0345); /* Used by Greek Polytonic layout only; "ypogegrammeni" */
CASE (ogonek, 0x0328); /* Legacy use for dasia, 0x314.*/
CASE (iota, 0x0345);
CASE (voiced_sound, 0x3099); /* Per Markus Kuhn keysyms.txt file. */
CASE (semivoiced_sound, 0x309a); /* Per Markus Kuhn keysyms.txt file. */
CASE (belowdot, 0x0323);
CASE (hook, 0x0309);
CASE (horn, 0x031b); /* Normally is 0x31b; Greek Polytonic needs 0x313 (or 0x343).
* We modified the compose sequences for now to
* so that for Greek we don't apply algorithmic
* when psili (0x343) is required
* Patch accepted in Xorg/GIT, may take a bit to propagate.
*/
CASE (psili, 0x343);
CASE (semivoiced_sound, 0x309A); /* Per Markus Kuhn keysyms.txt file. */
/* The following cases are to be removed once xkeyboard-config,
* xorg are fully updated.
*/
/* Workaround for typo in 1.4.x xserver-xorg */
case 0xfe66: combination_buffer[i+1] = 0x314; break;
/* CASE (dasia, 0x314); */
/* CASE (perispomeni, 0x342); */
/* CASE (psili, 0x343); */
#undef CASE
default:
combination_buffer[i+1] = gdk_keyval_to_unicode (context_simple->compose_buffer[i]);
......@@ -421,56 +479,24 @@ check_algorithmically (GtkIMContextSimple *context_simple,
i--;
}
if (n_compose > 2)
{
gint n_combinations;
gunichar temp_swap;
/* We calculate the number of permutations of the diacritic marks, factorial(n_compose-1).
* When diacritic marks belong to the same Canonical Combining Class,
* a normalisation does not attempt reorder them, thus we do this ourselves.
*/
n_combinations = 1;
for (k = 1; k < n_compose; k++ )
n_combinations *= k;
memcpy (combination_buffer_temp, combination_buffer, GTK_MAX_COMPOSE_LEN * sizeof (gunichar) );
for (k = 0; k < n_combinations; k++ )
{
g_unicode_canonical_ordering (combination_buffer_temp, n_compose);
combination_utf8_temp = g_ucs4_to_utf8 (combination_buffer_temp, -1, NULL, NULL, NULL);
nfc_temp = g_utf8_normalize (combination_utf8_temp, -1, G_NORMALIZE_NFC);
if (g_utf8_strlen (nfc_temp, -1) == 1)
{
memcpy (combination_buffer, combination_buffer_temp, GTK_MAX_COMPOSE_LEN * sizeof (gunichar) );
break;
}
temp_swap = combination_buffer_temp[k % (n_compose - 1) + 1];
combination_buffer_temp[k % (n_compose - 1) + 1] = combination_buffer_temp[(k+1) % (n_compose - 1) + 1];
combination_buffer_temp[(k+1) % (n_compose - 1) + 1] = temp_swap;
}
g_free (combination_utf8_temp);
g_free (nfc_temp);
}
/* If the buffer normalizes to a single character,
* then modify the order of combination_buffer accordingly, if necessary,
* and return TRUE.
*/
if (check_normalize_nfc (combination_buffer, n_compose))
{
combination_utf8 = g_ucs4_to_utf8 (combination_buffer, -1, NULL, NULL, NULL);
nfc = g_utf8_normalize (combination_utf8, -1, G_NORMALIZE_NFC);
combination_utf8 = g_ucs4_to_utf8 (combination_buffer, -1, NULL, NULL, NULL);
nfc = g_utf8_normalize (combination_utf8, -1, G_NORMALIZE_NFC);
if (g_utf8_strlen (nfc, -1) == 1)
{
gunichar value = g_utf8_get_char (nfc);
gtk_im_context_simple_commit_char (GTK_IM_CONTEXT (context_simple), value);
context_simple->compose_buffer[0] = 0;
gunichar value = g_utf8_get_char (nfc);
gtk_im_context_simple_commit_char (GTK_IM_CONTEXT (context_simple), value);
context_simple->compose_buffer[0] = 0;
g_free (combination_utf8);
g_free (nfc);
return TRUE;
}
g_free (combination_utf8);
g_free (nfc);
g_free (combination_utf8);
g_free (nfc);
return TRUE;
}
}
return FALSE;
......@@ -899,11 +925,11 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
tmp_list = tmp_list->next;
}
if (check_compact_table (context_simple, &gtk_compose_table_compact, n_compose))
return TRUE;
if (check_algorithmically (context_simple, n_compose))
return TRUE;
if (check_compact_table (context_simple, &gtk_compose_table_compact, n_compose))
return TRUE;
}
/* The current compose_buffer doesn't match anything */
......
This diff is collapsed.
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