forked from AuroraMiddleware/gtk
composetable: Drop GtkComposeTableCompact
All tables use the compact format now, and we generate caches in that format too. Bump the cache version to 3 for this. Replace the python script for generating the builtin table by a small C program using the same code to generate the data for the builtin table. This drops the restriction on only generating a single character in the builtin sequences.
This commit is contained in:
parent
1cff4bb27a
commit
54dffa07f3
BIN
gtk/compose/chars
Normal file
BIN
gtk/compose/chars
Normal file
Binary file not shown.
63
gtk/compose/compose-parse.c
Normal file
63
gtk/compose/compose-parse.c
Normal file
@ -0,0 +1,63 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtk/gtkcomposetable.h"
|
||||
#include <locale.h>
|
||||
|
||||
/* This program reads a Compose file and generates files with sequences,
|
||||
* character data, and definitions for the builtin compose table of GTK.
|
||||
* Run it like this:
|
||||
*
|
||||
* compose-parse Compose sequences chars gtkcomposedata.h
|
||||
*
|
||||
* The GTK build expects the output files to be in the source tree, in
|
||||
* the gtk/compose directory.
|
||||
*/
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GtkComposeTable *table;
|
||||
GError *error = NULL;
|
||||
GString *str;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
if (argc < 5)
|
||||
{
|
||||
g_print ("Usage: compose-parse INPUT OUTPUT1 OUTPUT2 OUTPUT3\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
table = gtk_compose_table_parse (argv[1]);
|
||||
if (!table)
|
||||
g_error ("Failed to parse %s", argv[1]);
|
||||
|
||||
/* data_size is the size in guint16 */
|
||||
if (!g_file_set_contents (argv[2], (char *)table->data, 2 * table->data_size, &error))
|
||||
g_error ("%s", error->message);
|
||||
|
||||
if (!g_file_set_contents (argv[3], table->char_data, table->n_chars + 1, &error))
|
||||
g_error ("%s", error->message);
|
||||
|
||||
str = g_string_new ("");
|
||||
g_string_append (str,
|
||||
"#ifndef __GTK_COMPOSE_DATA__\n"
|
||||
"#define __GTK_COMPOSE_DATA__\n"
|
||||
"\n");
|
||||
g_string_append_printf (str,
|
||||
"#define MAX_SEQ_LEN %d\n", table->max_seq_len);
|
||||
g_string_append_printf (str,
|
||||
"#define N_INDEX_SIZE %d\n", table->n_index_size);
|
||||
g_string_append_printf (str,
|
||||
"#define DATA_SIZE %d\n", table->data_size);
|
||||
g_string_append_printf (str,
|
||||
"#define N_CHARS %d\n", table->n_chars);
|
||||
g_string_append (str,
|
||||
"\n"
|
||||
"#endif\n");
|
||||
|
||||
if (!g_file_set_contents (argv[4], str->str, str->len, &error))
|
||||
g_error ("%s", error->message);
|
||||
|
||||
g_string_free (str, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,984 +0,0 @@
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# compose-parse.py, version 1.4
|
||||
#
|
||||
# multifunction script that helps manage the compose sequence table in GTK+ (gtk/gtkimcontextsimple.c)
|
||||
# the script produces statistics and information about the whole process, run with --help for more.
|
||||
#
|
||||
# You may need to switch your python installation to utf-8, if you get 'ascii' codec errors.
|
||||
#
|
||||
# Complain to Simos Xenitellis (simos@gnome.org, http://simos.info/blog) for this craft.
|
||||
|
||||
from re import findall, match, split, sub
|
||||
from string import atoi
|
||||
from unicodedata import normalize
|
||||
from urllib import urlretrieve
|
||||
from os.path import isfile, getsize
|
||||
from copy import copy
|
||||
|
||||
import sys
|
||||
import getopt
|
||||
|
||||
# We grab files off the web, left and right.
|
||||
URL_COMPOSE = 'http://cgit.freedesktop.org/xorg/lib/libX11/plain/nls/en_US.UTF-8/Compose.pre'
|
||||
URL_KEYSYMSTXT = "http://www.cl.cam.ac.uk/~mgk25/ucs/keysyms.txt"
|
||||
URL_GDKKEYSYMSH = "http://git.gnome.org/browse/gtk%2B/plain/gdk/gdkkeysyms.h"
|
||||
URL_UNICODEDATATXT = 'http://www.unicode.org/Public/6.0.0/ucd/UnicodeData.txt'
|
||||
FILENAME_COMPOSE_SUPPLEMENTARY = 'gtk-compose-lookaside.txt'
|
||||
FILENAME_COMPOSE_NEGATIVE_SUPPLEMENTARY = 'gtk-compose-remove.txt'
|
||||
|
||||
# We currently support keysyms of size 2; once upstream xorg gets sorted,
|
||||
# we might produce some tables with size 2 and some with size 4.
|
||||
SIZEOFINT = 2
|
||||
|
||||
# Current max compose sequence length; in case it gets increased.
|
||||
WIDTHOFCOMPOSETABLE = 5
|
||||
|
||||
keysymdatabase = {}
|
||||
keysymunicodedatabase = {}
|
||||
unicodedatabase = {}
|
||||
|
||||
headerfile_start = """/* GTK - The GIMP Tool Kit
|
||||
* Copyright (C) 2007, 2008 GNOME Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File auto-generated from script found at http://bugzilla.gnome.org/show_bug.cgi?id=321896
|
||||
* using the input files
|
||||
* Input : http://cgit.freedesktop.org/xorg/lib/libX11/plain/nls/en_US.UTF-8/Compose.pre
|
||||
* Input : http://www.cl.cam.ac.uk/~mgk25/ucs/keysyms.txt
|
||||
* Input : http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
|
||||
*
|
||||
* This table is optimised for space and requires special handling to access the content.
|
||||
* This table is used solely by http://svn.gnome.org/viewcvs/gtk%2B/trunk/gtk/gtkimcontextsimple.c
|
||||
*
|
||||
* The resulting file is placed at http://svn.gnome.org/viewcvs/gtk%2B/trunk/gtk/gtkimcontextsimpleseqs.h
|
||||
* This file is described in bug report http://bugzilla.gnome.org/show_bug.cgi?id=321896
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 2007, 2008. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_IM_CONTEXT_SIMPLE_SEQS_H__
|
||||
#define __GTK_IM_CONTEXT_SIMPLE_SEQS_H__
|
||||
|
||||
/* === These are the original comments of the file; we keep for historical purposes ===
|
||||
*
|
||||
* The following table was generated from the X compose tables include with
|
||||
* XFree86 4.0 using a set of Perl scripts. Contact Owen Taylor <otaylor@redhat.com>
|
||||
* to obtain the relevant perl scripts.
|
||||
*
|
||||
* The following compose letter letter sequences conflicted
|
||||
* Dstroke/dstroke and ETH/eth; resolved to Dstroke (Croatian, Vietnamese, Lappish), over
|
||||
* ETH (Icelandic, Faroese, old English, IPA) [ D- -D d- -d ]
|
||||
* Amacron/amacron and ordfeminine; resolved to ordfeminine [ _A A_ a_ _a ]
|
||||
* Amacron/amacron and Atilde/atilde; resolved to atilde [ -A A- a- -a ]
|
||||
* Omacron/Omacron and masculine; resolved to masculine [ _O O_ o_ _o ]
|
||||
* Omacron/omacron and Otilde/atilde; resolved to otilde [ -O O- o- -o ]
|
||||
*
|
||||
* [ Amacron and Omacron are in Latin-4 (Baltic). ordfeminine and masculine are used for
|
||||
* spanish. atilde and otilde are used at least for Portuguese ]
|
||||
*
|
||||
* at and Aring; resolved to Aring [ AA ]
|
||||
* guillemotleft and caron; resolved to guillemotleft [ << ]
|
||||
* ogonek and cedilla; resolved to cedilla [ ,, ]
|
||||
*
|
||||
* This probably should be resolved by first checking an additional set of compose tables
|
||||
* that depend on the locale or selected input method.
|
||||
*/
|
||||
|
||||
static const guint16 gtk_compose_seqs_compact[] = {"""
|
||||
|
||||
headerfile_end = """};
|
||||
|
||||
#endif /* __GTK_IM_CONTEXT_SIMPLE_SEQS_H__ */
|
||||
"""
|
||||
|
||||
def stringtohex(str): return atoi(str, 16)
|
||||
|
||||
def factorial(n):
|
||||
if n <= 1:
|
||||
return 1
|
||||
else:
|
||||
return n * factorial(n-1)
|
||||
|
||||
def uniq(*args) :
|
||||
""" Performs a uniq operation on a list or lists """
|
||||
theInputList = []
|
||||
for theList in args:
|
||||
theInputList += theList
|
||||
theFinalList = []
|
||||
for elem in theInputList:
|
||||
if elem not in theFinalList:
|
||||
theFinalList.append(elem)
|
||||
return theFinalList
|
||||
|
||||
|
||||
|
||||
def all_permutations(seq):
|
||||
""" Borrowed from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252178 """
|
||||
""" Produces all permutations of the items of a list """
|
||||
if len(seq) <=1:
|
||||
yield seq
|
||||
else:
|
||||
for perm in all_permutations(seq[1:]):
|
||||
for i in range(len(perm)+1):
|
||||
#nb str[0:1] works in both string and list contexts
|
||||
yield perm[:i] + seq[0:1] + perm[i:]
|
||||
|
||||
def usage():
|
||||
print """compose-parse available parameters:
|
||||
-h, --help this craft
|
||||
-s, --statistics show overall statistics (both algorithmic, non-algorithmic)
|
||||
-a, --algorithmic show sequences saved with algorithmic optimisation
|
||||
-g, --gtk show entries that go to GTK+
|
||||
-u, --unicodedatatxt show compose sequences derived from UnicodeData.txt (from unicode.org)
|
||||
-v, --verbose show verbose output
|
||||
-p, --plane1 show plane1 compose sequences
|
||||
-n, --numeric when used with --gtk, create file with numeric values only
|
||||
-e, --gtk-expanded when used with --gtk, create file that repeats first column; not usable in GTK+
|
||||
|
||||
Default is to show statistics.
|
||||
"""
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "pvgashune", ["help", "algorithmic", "statistics", "unicodedatatxt",
|
||||
"stats", "gtk", "verbose", "plane1", "numeric", "gtk-expanded"])
|
||||
except:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
opt_statistics = False
|
||||
opt_algorithmic = False
|
||||
opt_gtk = False
|
||||
opt_unicodedatatxt = False
|
||||
opt_verbose = False
|
||||
opt_plane1 = False
|
||||
opt_numeric = False
|
||||
opt_gtkexpanded = False
|
||||
|
||||
for o, a in opts:
|
||||
if o in ("-h", "--help"):
|
||||
usage()
|
||||
sys.exit()
|
||||
if o in ("-s", "--statistics"):
|
||||
opt_statistics = True
|
||||
if o in ("-a", "--algorithmic"):
|
||||
opt_algorithmic = True
|
||||
if o in ("-g", "--gtk"):
|
||||
opt_gtk = True
|
||||
if o in ("-u", "--unicodedatatxt"):
|
||||
opt_unicodedatatxt = True
|
||||
if o in ("-v", "--verbose"):
|
||||
opt_verbose = True
|
||||
if o in ("-p", "--plane1"):
|
||||
opt_plane1 = True
|
||||
if o in ("-n", "--numeric"):
|
||||
opt_numeric = True
|
||||
if o in ("-e", "--gtk-expanded"):
|
||||
opt_gtkexpanded = True
|
||||
|
||||
if not opt_algorithmic and not opt_gtk and not opt_unicodedatatxt:
|
||||
opt_statistics = True
|
||||
|
||||
def download_hook(blocks_transferred, block_size, file_size):
|
||||
""" A download hook to provide some feedback when downloading """
|
||||
if blocks_transferred == 0:
|
||||
if file_size > 0:
|
||||
if opt_verbose:
|
||||
print "Downloading", file_size, "bytes: ",
|
||||
else:
|
||||
if opt_verbose:
|
||||
print "Downloading: ",
|
||||
sys.stdout.write('#')
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def download_file(url):
|
||||
""" Downloads a file provided a URL. Returns the filename. """
|
||||
""" Borks on failure """
|
||||
localfilename = url.split('/')[-1]
|
||||
if not isfile(localfilename) or getsize(localfilename) <= 0:
|
||||
if opt_verbose:
|
||||
print "Downloading ", url, "..."
|
||||
try:
|
||||
urlretrieve(url, localfilename, download_hook)
|
||||
except IOError, (errno, strerror):
|
||||
print "I/O error(%s): %s" % (errno, strerror)
|
||||
sys.exit(-1)
|
||||
except:
|
||||
print "Unexpected error: ", sys.exc_info()[0]
|
||||
sys.exit(-1)
|
||||
print " done."
|
||||
else:
|
||||
if opt_verbose:
|
||||
print "Using cached file for ", url
|
||||
return localfilename
|
||||
|
||||
def process_gdkkeysymsh():
|
||||
""" Opens the gdkkeysyms.h file from GTK+/gdk/gdkkeysyms.h """
|
||||
""" Fills up keysymdb with contents """
|
||||
filename_gdkkeysymsh = download_file(URL_GDKKEYSYMSH)
|
||||
try:
|
||||
gdkkeysymsh = open(filename_gdkkeysymsh, 'r')
|
||||
except IOError, (errno, strerror):
|
||||
print "I/O error(%s): %s" % (errno, strerror)
|
||||
sys.exit(-1)
|
||||
except:
|
||||
print "Unexpected error: ", sys.exc_info()[0]
|
||||
sys.exit(-1)
|
||||
|
||||
""" Parse the gdkkeysyms.h file and place contents in keysymdb """
|
||||
linenum_gdkkeysymsh = 0
|
||||
keysymdb = {}
|
||||
for line in gdkkeysymsh.readlines():
|
||||
linenum_gdkkeysymsh += 1
|
||||
line = line.strip()
|
||||
if line == "" or not match('^#define GDK_KEY_', line):
|
||||
continue
|
||||
components = split('\s+', line)
|
||||
if len(components) < 3:
|
||||
print "Invalid line %(linenum)d in %(filename)s: %(line)s"\
|
||||
% {'linenum': linenum_gdkkeysymsh, 'filename': filename_gdkkeysymsh, 'line': line}
|
||||
print "Was expecting 3 items in the line"
|
||||
sys.exit(-1)
|
||||
if not match('^GDK_KEY_', components[1]):
|
||||
print "Invalid line %(linenum)d in %(filename)s: %(line)s"\
|
||||
% {'linenum': linenum_gdkkeysymsh, 'filename': filename_gdkkeysymsh, 'line': line}
|
||||
print "Was expecting a keysym starting with GDK_KEY_"
|
||||
sys.exit(-1)
|
||||
if match('^0x[0-9a-fA-F]+$', components[2]):
|
||||
unival = long(components[2][2:], 16)
|
||||
if unival == 0:
|
||||
continue
|
||||
keysymdb[components[1][8:]] = unival
|
||||
else:
|
||||
print "Invalid line %(linenum)d in %(filename)s: %(line)s"\
|
||||
% {'linenum': linenum_gdkkeysymsh, 'filename': filename_gdkkeysymsh, 'line': line}
|
||||
print "Was expecting a hexadecimal number at the end of the line"
|
||||
sys.exit(-1)
|
||||
gdkkeysymsh.close()
|
||||
|
||||
""" Patch up the keysymdb with some of our own stuff """
|
||||
|
||||
""" 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 """
|
||||
#keysymdb['combining_tilde'] = 0x342
|
||||
|
||||
""" Fixing VoidSymbol """
|
||||
keysymdb['VoidSymbol'] = 0xFFFF
|
||||
|
||||
return keysymdb
|
||||
|
||||
def process_keysymstxt():
|
||||
""" Grabs and opens the keysyms.txt file that Markus Kuhn maintains """
|
||||
""" This file keeps a record between keysyms <-> unicode chars """
|
||||
filename_keysymstxt = download_file(URL_KEYSYMSTXT)
|
||||
try:
|
||||
keysymstxt = open(filename_keysymstxt, 'r')
|
||||
except IOError, (errno, strerror):
|
||||
print "I/O error(%s): %s" % (errno, strerror)
|
||||
sys.exit(-1)
|
||||
except:
|
||||
print "Unexpected error: ", sys.exc_info()[0]
|
||||
sys.exit(-1)
|
||||
|
||||
""" Parse the keysyms.txt file and place content in keysymdb """
|
||||
linenum_keysymstxt = 0
|
||||
keysymdb = {}
|
||||
for line in keysymstxt.readlines():
|
||||
linenum_keysymstxt += 1
|
||||
line = line.strip()
|
||||
if line == "" or match('^#', line):
|
||||
continue
|
||||
components = split('\s+', line)
|
||||
if len(components) < 5:
|
||||
print "Invalid line %(linenum)d in %(filename)s: %(line)s'"\
|
||||
% {'linenum': linenum_keysymstxt, 'filename': filename_keysymstxt, 'line': line}
|
||||
print "Was expecting 5 items in the line"
|
||||
sys.exit(-1)
|
||||
if match('^U[0-9a-fA-F]+$', components[1]):
|
||||
unival = long(components[1][1:], 16)
|
||||
if unival == 0:
|
||||
continue
|
||||
keysymdb[components[4]] = unival
|
||||
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 """
|
||||
# keysymdb['dead_tilde'] = 0x342
|
||||
""" This is preferential treatment for Greek """
|
||||
# keysymdb['combining_tilde'] = 0x342
|
||||
|
||||
""" 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
|
||||
""" This is for a missing keysym from Markus Kuhn's db """
|
||||
keysymdb['Ssharp'] = 0x1e9e
|
||||
|
||||
""" This is for a missing (recently added) keysym """
|
||||
keysymdb['dead_psili'] = 0x313
|
||||
""" This is for a missing (recently added) keysym """
|
||||
keysymdb['dead_dasia'] = 0x314
|
||||
|
||||
""" Allows to import Multi_key sequences """
|
||||
keysymdb['Multi_key'] = 0xff20
|
||||
|
||||
keysymdb['zerosubscript'] = 0x2080
|
||||
keysymdb['onesubscript'] = 0x2081
|
||||
keysymdb['twosubscript'] = 0x2082
|
||||
keysymdb['threesubscript'] = 0x2083
|
||||
keysymdb['foursubscript'] = 0x2084
|
||||
keysymdb['fivesubscript'] = 0x2085
|
||||
keysymdb['sixsubscript'] = 0x2086
|
||||
keysymdb['sevensubscript'] = 0x2087
|
||||
keysymdb['eightsubscript'] = 0x2088
|
||||
keysymdb['ninesubscript'] = 0x2089
|
||||
keysymdb['dead_doublegrave'] = 0x030F
|
||||
keysymdb['dead_invertedbreve'] = 0x0311
|
||||
keysymdb['dead_belowcomma'] = 0xfe6e
|
||||
keysymdb['dead_currency'] = 0xfe6f
|
||||
keysymdb['dead_greek'] = 0xfe8c
|
||||
|
||||
return keysymdb
|
||||
|
||||
def keysymvalue(keysym, file = "n/a", linenum = 0):
|
||||
""" Extracts a value from the keysym """
|
||||
""" Find the value of keysym, using the data from keysyms """
|
||||
""" Use file and linenum to when reporting errors """
|
||||
if keysym == "":
|
||||
return 0
|
||||
if keysymdatabase.has_key(keysym):
|
||||
return keysymdatabase[keysym]
|
||||
elif keysym[0] == 'U' and match('[0-9a-fA-F]+$', keysym[1:]):
|
||||
return atoi(keysym[1:], 16)
|
||||
elif keysym[:2] == '0x' and match('[0-9a-fA-F]+$', keysym[2:]):
|
||||
return atoi(keysym[2:], 16)
|
||||
else:
|
||||
print 'keysymvalue: UNKNOWN{%(keysym)s}' % { "keysym": keysym }
|
||||
#return -1
|
||||
sys.exit(-1)
|
||||
|
||||
def keysymunicodevalue(keysym, file = "n/a", linenum = 0):
|
||||
""" Extracts a value from the keysym """
|
||||
""" Find the value of keysym, using the data from keysyms """
|
||||
""" Use file and linenum to when reporting errors """
|
||||
if keysym == "":
|
||||
return 0
|
||||
if keysymunicodedatabase.has_key(keysym):
|
||||
return keysymunicodedatabase[keysym]
|
||||
elif keysym[0] == 'U' and match('[0-9a-fA-F]+$', keysym[1:]):
|
||||
return atoi(keysym[1:], 16)
|
||||
elif keysym[:2] == '0x' and match('[0-9a-fA-F]+$', keysym[2:]):
|
||||
return atoi(keysym[2:], 16)
|
||||
else:
|
||||
print 'keysymunicodevalue: UNKNOWN{%(keysym)s}' % { "keysym": keysym }
|
||||
sys.exit(-1)
|
||||
|
||||
def rename_combining(seq):
|
||||
filtered_sequence = []
|
||||
for ks in seq:
|
||||
if findall('^combining_', ks):
|
||||
ks = sub('^combining_', 'dead_', ks)
|
||||
if ks == 'dead_double_grave':
|
||||
ks = 'dead_doublegrave'
|
||||
if ks == 'dead_inverted_breve':
|
||||
ks = 'dead_invertedbreve'
|
||||
filtered_sequence.append(ks)
|
||||
return filtered_sequence
|
||||
|
||||
|
||||
keysymunicodedatabase = process_keysymstxt()
|
||||
keysymdatabase = process_gdkkeysymsh()
|
||||
|
||||
""" Grab and open the compose file from upstream """
|
||||
filename_compose = download_file(URL_COMPOSE)
|
||||
try:
|
||||
composefile = open(filename_compose, 'r')
|
||||
except IOError, (errno, strerror):
|
||||
print "I/O error(%s): %s" % (errno, strerror)
|
||||
sys.exit(-1)
|
||||
except:
|
||||
print "Unexpected error: ", sys.exc_info()[0]
|
||||
sys.exit(-1)
|
||||
|
||||
""" Look if there is a lookaside (supplementary) compose file in the current
|
||||
directory, and if so, open, then merge with upstream Compose file.
|
||||
"""
|
||||
xorg_compose_sequences_raw = []
|
||||
for seq in composefile.readlines():
|
||||
xorg_compose_sequences_raw.append(seq)
|
||||
|
||||
try:
|
||||
composefile_lookaside = open(FILENAME_COMPOSE_NEGATIVE_SUPPLEMENTARY, 'r')
|
||||
for seq in composefile_lookaside.readlines():
|
||||
xorg_compose_sequences_raw.remove(seq)
|
||||
except IOError, (errno, strerror):
|
||||
if opt_verbose:
|
||||
print "I/O error(%s): %s" % (errno, strerror)
|
||||
print "Did not find negative lookaside compose file. Continuing..."
|
||||
except:
|
||||
print "Unexpected error: ", sys.exc_info()[0]
|
||||
sys.exit(-1)
|
||||
|
||||
try:
|
||||
composefile_lookaside = open(FILENAME_COMPOSE_SUPPLEMENTARY, 'r')
|
||||
for seq in composefile_lookaside.readlines():
|
||||
xorg_compose_sequences_raw.append(seq)
|
||||
except IOError, (errno, strerror):
|
||||
if opt_verbose:
|
||||
print "I/O error(%s): %s" % (errno, strerror)
|
||||
print "Did not find lookaside compose file. Continuing..."
|
||||
except:
|
||||
print "Unexpected error: ", sys.exc_info()[0]
|
||||
sys.exit(-1)
|
||||
|
||||
""" Parse the compose file in xorg_compose_sequences"""
|
||||
xorg_compose_sequences = []
|
||||
xorg_compose_sequences_algorithmic = []
|
||||
linenum_compose = 0
|
||||
comment_nest_depth = 0
|
||||
for line in xorg_compose_sequences_raw:
|
||||
linenum_compose += 1
|
||||
line = line.strip()
|
||||
if match("^XCOMM", line) or match("^#", line):
|
||||
continue
|
||||
|
||||
line = sub(r"\/\*([^\*]*|[\*][^/])\*\/", "", line)
|
||||
|
||||
comment_start = line.find("/*")
|
||||
|
||||
if comment_start >= 0:
|
||||
if comment_nest_depth == 0:
|
||||
line = line[:comment_start]
|
||||
else:
|
||||
line = ""
|
||||
|
||||
comment_nest_depth += 1
|
||||
else:
|
||||
comment_end = line.find("*/")
|
||||
|
||||
if comment_end >= 0:
|
||||
comment_nest_depth -= 1
|
||||
|
||||
if comment_nest_depth < 0:
|
||||
print "Invalid comment %(linenum_compose)d in %(filename)s: \
|
||||
Closing '*/' without opening '/*'" % { "linenum_compose": linenum_compose, "filename": filename_compose }
|
||||
exit(-1)
|
||||
|
||||
if comment_nest_depth > 0:
|
||||
line = ""
|
||||
else:
|
||||
line = line[comment_end + 2:]
|
||||
|
||||
if line is "":
|
||||
continue
|
||||
|
||||
#line = line[:-1]
|
||||
components = split(':', line, 1)
|
||||
if len(components) != 2:
|
||||
print "Invalid line %(linenum_compose)d in %(filename)s: No sequence\
|
||||
/value pair found" % { "linenum_compose": linenum_compose, "filename": filename_compose }
|
||||
exit(-1)
|
||||
(seq, val ) = split(':', line, 1)
|
||||
seq = seq.strip()
|
||||
val = val.strip()
|
||||
raw_sequence = findall('\w+', seq)
|
||||
values = split('\s+', val)
|
||||
unichar_temp = split('"', values[0])
|
||||
unichar_utf8 = 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 match('^U[0-9a-fA-F]+$', codepointstr):
|
||||
codepoint = long(codepointstr[1:], 16)
|
||||
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:
|
||||
unichar = unicode(unichar_utf8, 'utf-8')
|
||||
codepoint = ord(unichar)
|
||||
sequence = rename_combining(raw_sequence)
|
||||
reject_this = False
|
||||
for i in sequence:
|
||||
if keysymvalue(i) > 0xFFFF:
|
||||
reject_this = True
|
||||
if opt_plane1:
|
||||
print sequence
|
||||
break
|
||||
if keysymvalue(i) < 0:
|
||||
reject_this = True
|
||||
break
|
||||
if reject_this:
|
||||
continue
|
||||
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
|
||||
if codepoint > 0xFFFF:
|
||||
if opt_verbose:
|
||||
print "Ignore the line greater than guint16:\n%s" % line
|
||||
continue
|
||||
#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:
|
||||
original_sequence = copy(sequence)
|
||||
stats_sequence = copy(sequence)
|
||||
base = sequence.pop()
|
||||
basechar = keysymvalue(base, filename_compose, linenum_compose)
|
||||
|
||||
if basechar < 0xFFFF:
|
||||
counter = 1
|
||||
unisequence = []
|
||||
not_normalised = True
|
||||
skipping_this = False
|
||||
for i in range(0, len(sequence)):
|
||||
""" If the sequence has dead_tilde and is for Greek, we don't do algorithmically
|
||||
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):
|
||||
skipping_this = True
|
||||
break
|
||||
if sequence[-1] == "dead_horn" and (bc >= 0x370 and bc <= 0x3ff) or (bc >= 0x1f00 and bc <= 0x1fff):
|
||||
skipping_this = True
|
||||
break
|
||||
if sequence[-1] == "dead_ogonek" and (bc >= 0x370 and bc <= 0x3ff) or (bc >= 0x1f00 and bc <= 0x1fff):
|
||||
skipping_this = True
|
||||
break
|
||||
if sequence[-1] == "dead_psili":
|
||||
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:
|
||||
unisequence = []
|
||||
for perm in all_permutations(unisequence):
|
||||
# print counter, original_sequence, unichr(basechar) + "".join(perm)
|
||||
# print counter, map(unichr, perm)
|
||||
normalized = normalize('NFC', unichr(basechar) + "".join(perm))
|
||||
if len(normalized) == 1:
|
||||
# print 'Base: %(base)s [%(basechar)s], produces [%(unichar)s] (0x%(codepoint)04X)' \
|
||||
# % { "base": base, "basechar": unichr(basechar), "unichar": unichar, "codepoint": codepoint },
|
||||
# print "Normalized: [%(normalized)s] SUCCESS %(c)d" % { "normalized": normalized, "c": counter }
|
||||
stats_sequence_data = map(keysymunicodevalue, stats_sequence)
|
||||
stats_sequence_data.append(normalized)
|
||||
xorg_compose_sequences_algorithmic.append(stats_sequence_data)
|
||||
not_normalised = False
|
||||
break;
|
||||
counter += 1
|
||||
if not_normalised:
|
||||
original_sequence.append(codepoint)
|
||||
xorg_compose_sequences.append(original_sequence)
|
||||
""" print xorg_compose_sequences[-1] """
|
||||
|
||||
else:
|
||||
print "Error in base char !?!"
|
||||
exit(-2)
|
||||
else:
|
||||
print "OVER", sequence
|
||||
exit(-1)
|
||||
else:
|
||||
sequence.append(codepoint)
|
||||
xorg_compose_sequences.append(sequence)
|
||||
""" print xorg_compose_sequences[-1] """
|
||||
|
||||
def sequence_cmp(x, y):
|
||||
if keysymvalue(x[0]) > keysymvalue(y[0]):
|
||||
return 1
|
||||
elif keysymvalue(x[0]) < keysymvalue(y[0]):
|
||||
return -1
|
||||
elif len(x) > len(y):
|
||||
return 1
|
||||
elif len(x) < len(y):
|
||||
return -1
|
||||
elif keysymvalue(x[1]) > keysymvalue(y[1]):
|
||||
return 1
|
||||
elif keysymvalue(x[1]) < keysymvalue(y[1]):
|
||||
return -1
|
||||
elif len(x) < 4:
|
||||
return 0
|
||||
elif keysymvalue(x[2]) > keysymvalue(y[2]):
|
||||
return 1
|
||||
elif keysymvalue(x[2]) < keysymvalue(y[2]):
|
||||
return -1
|
||||
elif len(x) < 5:
|
||||
return 0
|
||||
elif keysymvalue(x[3]) > keysymvalue(y[3]):
|
||||
return 1
|
||||
elif keysymvalue(x[3]) < keysymvalue(y[3]):
|
||||
return -1
|
||||
elif len(x) < 6:
|
||||
return 0
|
||||
elif keysymvalue(x[4]) > keysymvalue(y[4]):
|
||||
return 1
|
||||
elif keysymvalue(x[4]) < keysymvalue(y[4]):
|
||||
return -1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def sequence_unicode_cmp(x, y):
|
||||
if keysymunicodevalue(x[0]) > keysymunicodevalue(y[0]):
|
||||
return 1
|
||||
elif keysymunicodevalue(x[0]) < keysymunicodevalue(y[0]):
|
||||
return -1
|
||||
elif len(x) > len(y):
|
||||
return 1
|
||||
elif len(x) < len(y):
|
||||
return -1
|
||||
elif keysymunicodevalue(x[1]) > keysymunicodevalue(y[1]):
|
||||
return 1
|
||||
elif keysymunicodevalue(x[1]) < keysymunicodevalue(y[1]):
|
||||
return -1
|
||||
elif len(x) < 4:
|
||||
return 0
|
||||
elif keysymunicodevalue(x[2]) > keysymunicodevalue(y[2]):
|
||||
return 1
|
||||
elif keysymunicodevalue(x[2]) < keysymunicodevalue(y[2]):
|
||||
return -1
|
||||
elif len(x) < 5:
|
||||
return 0
|
||||
elif keysymunicodevalue(x[3]) > keysymunicodevalue(y[3]):
|
||||
return 1
|
||||
elif keysymunicodevalue(x[3]) < keysymunicodevalue(y[3]):
|
||||
return -1
|
||||
elif len(x) < 6:
|
||||
return 0
|
||||
elif keysymunicodevalue(x[4]) > keysymunicodevalue(y[4]):
|
||||
return 1
|
||||
elif keysymunicodevalue(x[4]) < keysymunicodevalue(y[4]):
|
||||
return -1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def sequence_algorithmic_cmp(x, y):
|
||||
if len(x) < len(y):
|
||||
return -1
|
||||
elif len(x) > len(y):
|
||||
return 1
|
||||
else:
|
||||
for i in range(len(x)):
|
||||
if x[i] < y[i]:
|
||||
return -1
|
||||
elif x[i] > y[i]:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
xorg_compose_sequences.sort(sequence_cmp)
|
||||
|
||||
xorg_compose_sequences_uniqued = []
|
||||
first_time = True
|
||||
item = None
|
||||
for next_item in xorg_compose_sequences:
|
||||
if first_time:
|
||||
first_time = False
|
||||
item = next_item
|
||||
if sequence_unicode_cmp(item, next_item) != 0:
|
||||
xorg_compose_sequences_uniqued.append(item)
|
||||
item = next_item
|
||||
|
||||
xorg_compose_sequences = copy(xorg_compose_sequences_uniqued)
|
||||
|
||||
counter_multikey = 0
|
||||
for item in xorg_compose_sequences:
|
||||
if findall('Multi_key', "".join(item[:-1])) != []:
|
||||
counter_multikey += 1
|
||||
|
||||
xorg_compose_sequences_algorithmic.sort(sequence_algorithmic_cmp)
|
||||
xorg_compose_sequences_algorithmic_uniqued = uniq(xorg_compose_sequences_algorithmic)
|
||||
|
||||
firstitem = ""
|
||||
num_first_keysyms = 0
|
||||
zeroes = 0
|
||||
num_entries = 0
|
||||
num_algorithmic_greek = 0
|
||||
for sequence in xorg_compose_sequences:
|
||||
if keysymvalue(firstitem) != keysymvalue(sequence[0]):
|
||||
firstitem = sequence[0]
|
||||
num_first_keysyms += 1
|
||||
zeroes += 6 - len(sequence) + 1
|
||||
num_entries += 1
|
||||
|
||||
for sequence in xorg_compose_sequences_algorithmic_uniqued:
|
||||
ch = ord(sequence[-1:][0])
|
||||
if ch >= 0x370 and ch <= 0x3ff or ch >= 0x1f00 and ch <= 0x1fff:
|
||||
num_algorithmic_greek += 1
|
||||
|
||||
|
||||
if opt_algorithmic:
|
||||
for sequence in xorg_compose_sequences_algorithmic_uniqued:
|
||||
letter = "".join(sequence[-1:])
|
||||
print '0x%(cp)04X, %(uni)s, seq: [ <0x%(base)04X>,' % { 'cp': ord(unicode(letter)), 'uni': letter.encode('utf-8'), 'base': sequence[-2] },
|
||||
for elem in sequence[:-2]:
|
||||
print "<0x%(keysym)04X>," % { 'keysym': elem },
|
||||
""" Yeah, verified... We just want to keep the output similar to -u, so we can compare/sort easily """
|
||||
print "], recomposed as", letter.encode('utf-8'), "verified"
|
||||
|
||||
def num_of_keysyms(seq):
|
||||
return len(seq) - 1
|
||||
|
||||
def convert_UnotationToHex(arg):
|
||||
if isinstance(arg, str):
|
||||
if match('^U[0-9A-F][0-9A-F][0-9A-F][0-9A-F]$', arg):
|
||||
return sub('^U', '0x', arg)
|
||||
return arg
|
||||
|
||||
def addprefix_GDK(arg):
|
||||
if match('^0x', arg):
|
||||
return '%(arg)s, ' % { 'arg': arg }
|
||||
elif match('^U[0-9A-F][0-9A-F][0-9A-F][0-9A-F]$', arg.upper()):
|
||||
keysym = ''
|
||||
for k, c in keysymunicodedatabase.items():
|
||||
if c == keysymvalue(arg):
|
||||
keysym = k
|
||||
break
|
||||
if keysym != '':
|
||||
return 'GDK_KEY_%(arg)s, ' % { 'arg': keysym }
|
||||
else:
|
||||
return '0x%(arg)04X, ' % { 'arg': keysymvalue(arg) }
|
||||
else:
|
||||
return 'GDK_KEY_%(arg)s, ' % { 'arg': arg }
|
||||
|
||||
if opt_gtk:
|
||||
first_keysym = ""
|
||||
sequence = []
|
||||
compose_table = []
|
||||
ct_second_part = []
|
||||
ct_sequence_width = 2
|
||||
start_offset = num_first_keysyms * (WIDTHOFCOMPOSETABLE+1)
|
||||
we_finished = False
|
||||
counter = 0
|
||||
|
||||
sequence_iterator = iter(xorg_compose_sequences)
|
||||
sequence = sequence_iterator.next()
|
||||
while True:
|
||||
first_keysym = sequence[0] # Set the first keysym
|
||||
compose_table.append([first_keysym, 0, 0, 0, 0, 0])
|
||||
while sequence[0] == first_keysym:
|
||||
compose_table[counter][num_of_keysyms(sequence)-1] += 1
|
||||
try:
|
||||
sequence = sequence_iterator.next()
|
||||
except StopIteration:
|
||||
we_finished = True
|
||||
break
|
||||
if we_finished:
|
||||
break
|
||||
counter += 1
|
||||
|
||||
ct_index = start_offset
|
||||
for line_num in range(len(compose_table)):
|
||||
for i in range(WIDTHOFCOMPOSETABLE):
|
||||
occurrences = compose_table[line_num][i+1]
|
||||
compose_table[line_num][i+1] = ct_index
|
||||
ct_index += occurrences * (i+2)
|
||||
|
||||
for sequence in xorg_compose_sequences:
|
||||
ct_second_part.append(map(convert_UnotationToHex, sequence))
|
||||
|
||||
print headerfile_start
|
||||
for i in compose_table:
|
||||
if opt_gtkexpanded:
|
||||
print "0x%(ks)04X," % { "ks": keysymvalue(i[0]) },
|
||||
print '%(str)s' % { 'str': "".join(map(lambda x : str(x) + ", ", i[1:])) }
|
||||
elif not match('^0x', i[0]):
|
||||
print 'GDK_KEY_%(str)s' % { 'str': "".join(map(lambda x : str(x) + ", ", i)) }
|
||||
else:
|
||||
print '%(str)s' % { 'str': "".join(map(lambda x : str(x) + ", ", i)) }
|
||||
for i in ct_second_part:
|
||||
if opt_numeric:
|
||||
for ks in i[1:][:-1]:
|
||||
print '0x%(seq)04X, ' % { 'seq': keysymvalue(ks) },
|
||||
print '0x%(cp)04X, ' % { 'cp':i[-1] }
|
||||
"""
|
||||
for ks in i[:-1]:
|
||||
print '0x%(seq)04X, ' % { 'seq': keysymvalue(ks) },
|
||||
print '0x%(cp)04X, ' % { 'cp':i[-1] }
|
||||
"""
|
||||
elif opt_gtkexpanded:
|
||||
print '%(seq)s0x%(cp)04X, ' % { 'seq': "".join(map(addprefix_GDK, i[:-1])), 'cp':i[-1] }
|
||||
else:
|
||||
print '%(seq)s0x%(cp)04X, ' % { 'seq': "".join(map(addprefix_GDK, i[:-1][1:])), 'cp':i[-1] }
|
||||
print headerfile_end
|
||||
|
||||
def redecompose(codepoint):
|
||||
(name, decomposition, combiningclass) = unicodedatabase[codepoint]
|
||||
if decomposition[0] == '' or decomposition[0] == '0':
|
||||
return [codepoint]
|
||||
if match('<\w+>', decomposition[0]):
|
||||
numdecomposition = map(stringtohex, decomposition[1:])
|
||||
return map(redecompose, numdecomposition)
|
||||
numdecomposition = map(stringtohex, decomposition)
|
||||
return map(redecompose, numdecomposition)
|
||||
|
||||
def process_unicodedata_file(verbose = False):
|
||||
""" Grab from wget http://www.unicode.org/Public/UNIDATA/UnicodeData.txt """
|
||||
filename_unicodedatatxt = download_file(URL_UNICODEDATATXT)
|
||||
try:
|
||||
unicodedatatxt = open(filename_unicodedatatxt, 'r')
|
||||
except IOError, (errno, strerror):
|
||||
print "I/O error(%s): %s" % (errno, strerror)
|
||||
sys.exit(-1)
|
||||
except:
|
||||
print "Unexpected error: ", sys.exc_info()[0]
|
||||
sys.exit(-1)
|
||||
for line in unicodedatatxt.readlines():
|
||||
if line[0] == "" or line[0] == '#':
|
||||
continue
|
||||
line = line[:-1]
|
||||
uniproperties = split(';', line)
|
||||
codepoint = stringtohex(uniproperties[0])
|
||||
""" We don't do Plane 1 or CJK blocks. The latter require reading additional files. """
|
||||
if codepoint > 0xFFFF or (codepoint >= 0x4E00 and codepoint <= 0x9FFF) or (codepoint >= 0xF900 and codepoint <= 0xFAFF):
|
||||
continue
|
||||
name = uniproperties[1]
|
||||
category = uniproperties[2]
|
||||
combiningclass = uniproperties[3]
|
||||
decomposition = uniproperties[5]
|
||||
unicodedatabase[codepoint] = [name, split('\s+', decomposition), combiningclass]
|
||||
|
||||
counter_combinations = 0
|
||||
counter_combinations_greek = 0
|
||||
counter_entries = 0
|
||||
counter_entries_greek = 0
|
||||
|
||||
for item in unicodedatabase.keys():
|
||||
(name, decomposition, combiningclass) = unicodedatabase[item]
|
||||
if decomposition[0] == '':
|
||||
continue
|
||||
print name, "is empty"
|
||||
elif match('<\w+>', decomposition[0]):
|
||||
continue
|
||||
print name, "has weird", decomposition[0]
|
||||
else:
|
||||
sequence = map(stringtohex, decomposition)
|
||||
chrsequence = map(unichr, sequence)
|
||||
normalized = normalize('NFC', "".join(chrsequence))
|
||||
|
||||
""" print name, sequence, "Combining: ", "".join(chrsequence), normalized, len(normalized), """
|
||||
decomposedsequence = []
|
||||
for subseq in map(redecompose, sequence):
|
||||
for seqitem in subseq:
|
||||
if isinstance(seqitem, list):
|
||||
for i in seqitem:
|
||||
if isinstance(i, list):
|
||||
for j in i:
|
||||
decomposedsequence.append(j)
|
||||
else:
|
||||
decomposedsequence.append(i)
|
||||
else:
|
||||
decomposedsequence.append(seqitem)
|
||||
recomposedchar = normalize('NFC', "".join(map(unichr, decomposedsequence)))
|
||||
if len(recomposedchar) == 1 and len(decomposedsequence) > 1:
|
||||
counter_entries += 1
|
||||
counter_combinations += factorial(len(decomposedsequence)-1)
|
||||
ch = item
|
||||
if ch >= 0x370 and ch <= 0x3ff or ch >= 0x1f00 and ch <= 0x1fff:
|
||||
counter_entries_greek += 1
|
||||
counter_combinations_greek += factorial(len(decomposedsequence)-1)
|
||||
if verbose:
|
||||
print "0x%(cp)04X, %(uni)c, seq:" % { 'cp':item, 'uni':unichr(item) },
|
||||
print "[",
|
||||
for elem in decomposedsequence:
|
||||
print '<0x%(hex)04X>,' % { 'hex': elem },
|
||||
print "], recomposed as", recomposedchar,
|
||||
if unichr(item) == recomposedchar:
|
||||
print "verified"
|
||||
|
||||
if verbose == False:
|
||||
print "Unicode statistics from UnicodeData.txt"
|
||||
print "Number of entries that can be algorithmically produced :", counter_entries
|
||||
print " of which are for Greek :", counter_entries_greek
|
||||
print "Number of compose sequence combinations requiring :", counter_combinations
|
||||
print " of which are for Greek :", counter_combinations_greek
|
||||
print "Note: We do not include partial compositions, "
|
||||
print "thus the slight discrepancy in the figures"
|
||||
print
|
||||
|
||||
if opt_unicodedatatxt:
|
||||
process_unicodedata_file(True)
|
||||
|
||||
if opt_statistics:
|
||||
print
|
||||
print "Total number of compose sequences (from file) :", len(xorg_compose_sequences) + len(xorg_compose_sequences_algorithmic)
|
||||
print " of which can be expressed algorithmically :", len(xorg_compose_sequences_algorithmic)
|
||||
print " of which cannot be expressed algorithmically :", len(xorg_compose_sequences)
|
||||
print " of which have Multi_key :", counter_multikey
|
||||
print
|
||||
print "Algorithmic (stats for Xorg Compose file)"
|
||||
print "Number of sequences off due to algo from file (len(array)) :", len(xorg_compose_sequences_algorithmic)
|
||||
print "Number of sequences off due to algo (uniq(sort(array))) :", len(xorg_compose_sequences_algorithmic_uniqued)
|
||||
print " of which are for Greek :", num_algorithmic_greek
|
||||
print
|
||||
process_unicodedata_file()
|
||||
print "Not algorithmic (stats from Xorg Compose file)"
|
||||
print "Number of sequences :", len(xorg_compose_sequences)
|
||||
print "Flat array looks like :", len(xorg_compose_sequences), "rows of 6 integers (2 bytes per int, or 12 bytes per row)"
|
||||
print "Flat array would have taken up (in bytes) :", num_entries * 2 * 6, "bytes from the GTK+ library"
|
||||
print "Number of items in flat array :", len(xorg_compose_sequences) * 6
|
||||
print " of which are zeroes :", zeroes, "or ", (100 * zeroes) / (len(xorg_compose_sequences) * 6), " per cent"
|
||||
print "Number of different first items :", num_first_keysyms
|
||||
print "Number of max bytes (if using flat array) :", num_entries * 2 * 6
|
||||
print "Number of savings :", zeroes * 2 - num_first_keysyms * 2 * 5
|
||||
print
|
||||
print "Memory needs if both algorithmic+optimised table in latest Xorg compose file"
|
||||
print " :", num_entries * 2 * 6 - zeroes * 2 + num_first_keysyms * 2 * 5
|
||||
print
|
||||
print "Existing (old) implementation in GTK+"
|
||||
print "Number of sequences in old gtkimcontextsimple.c :", 691
|
||||
print "The existing (old) implementation in GTK+ takes up :", 691 * 2 * 12, "bytes"
|
@ -1,405 +0,0 @@
|
||||
#
|
||||
# This file contains the compose sequences that GTK+ used to have until GTK+ 2.12
|
||||
# but are not found anymore at the upstream Compose file at X.Org.
|
||||
# When updating gtkimcontextsimpleseqs.h with compose-parse.py,
|
||||
# we include this file as well. There are 15 conflicts currently
|
||||
# in the compose sequences, and we currently favour the sequences from
|
||||
# this file (against the upstream X.Org file). For more, see
|
||||
# http://bugzilla.gnome.org/show_bug.cgi?id=557420
|
||||
#
|
||||
|
||||
<Greek_accentdieresis> <Greek_iota> : "ἴ" U0390
|
||||
<Greek_accentdieresis> <Greek_upsilon> : "ΐ" U03B0
|
||||
<Multi_key> <B> <period> : "Ḃ" U1E02
|
||||
<Multi_key> <b> <period> : "ḃ" U1E03
|
||||
<Multi_key> <D> <period> : "Ḋ" U1E0A
|
||||
<Multi_key> <d> <period> : "ḋ" U1E0B
|
||||
<Multi_key> <F> <period> : "Ḟ" U1E1E
|
||||
<Multi_key> <f> <period> : "ḟ" U1E1F
|
||||
<Multi_key> <M> <period> : "Ṁ" U1E40
|
||||
<Multi_key> <S> <period> : "Ṡ" U1E60
|
||||
<Multi_key> <P> <period> : "Ṗ" U1E56
|
||||
<Multi_key> <p> <period> : "ṗ" U1E57
|
||||
<Multi_key> <s> <period> : "ṡ" U1E61
|
||||
<Multi_key> <T> <period> : "Ṫ" U1E6A
|
||||
<Multi_key> <t> <period> : "ṫ" U1E6B
|
||||
<Multi_key> <e> <period> : "ė" U0117
|
||||
<Multi_key> <C> <bar> : "¢" U00A2
|
||||
<Multi_key> <bar> <C> : "¢" U00A2
|
||||
<Multi_key> <minus> <l> : "£" U00A3
|
||||
<Multi_key> <equal> <l> : "£" U00A3
|
||||
<Multi_key> <L> <equal> : "£" U00A3
|
||||
<Multi_key> <l> <minus> : "£" U00A3
|
||||
<Multi_key> <l> <equal> : "£" U00A3
|
||||
<Multi_key> <0> <X> : "¤" U00A4
|
||||
<Multi_key> <0> <x> : "¤" U00A4
|
||||
<Multi_key> <O> <X> : "¤" U00A4
|
||||
<Multi_key> <O> <x> : "¤" U00A4
|
||||
<Multi_key> <X> <0> : "¤" U00A4
|
||||
<Multi_key> <X> <O> : "¤" U00A4
|
||||
<Multi_key> <X> <o> : "¤" U00A4
|
||||
<Multi_key> <o> <X> : "¤" U00A4
|
||||
<Multi_key> <x> <0> : "¤" U00A4
|
||||
<Multi_key> <x> <O> : "¤" U00A4
|
||||
<Multi_key> <minus> <Y> : "¥" U00A5
|
||||
<Multi_key> <minus> <y> : "¥" U00A5
|
||||
<Multi_key> <equal> <y> : "¥" U00A5
|
||||
<Multi_key> <Y> <minus> : "¥" U00A5
|
||||
<Multi_key> <y> <minus> : "¥" U00A5
|
||||
<Multi_key> <y> <equal> : "¥" U00A5
|
||||
<Multi_key> <0> <S> : "§" U00A7
|
||||
<Multi_key> <0> <s> : "§" U00A7
|
||||
<Multi_key> <O> <S> : "§" U00A7
|
||||
<Multi_key> <S> <exclam> : "§" U00A7
|
||||
<Multi_key> <S> <0> : "§" U00A7
|
||||
<Multi_key> <S> <O> : "§" U00A7
|
||||
<Multi_key> <s> <exclam> : "§" U00A7
|
||||
<Multi_key> <s> <0> : "§" U00A7
|
||||
<Multi_key> <quotedbl> <quotedbl> : "¨" U00A8
|
||||
<Multi_key> <parenleft> <c> : "©" U00A9
|
||||
<Multi_key> <0> <C> : "©" U00A9
|
||||
<Multi_key> <0> <c> : "©" U00A9
|
||||
<Multi_key> <C> <0> : "©" U00A9
|
||||
<Multi_key> <C> <O> : "©" U00A9
|
||||
<Multi_key> <C> <o> : "©" U00A9
|
||||
<Multi_key> <c> <0> : "©" U00A9
|
||||
<Multi_key> <A> <underscore> : "ª" U00AA
|
||||
<Multi_key> <a> <underscore> : "ª" U00AA
|
||||
<Multi_key> <C> <comma> : "Ç" U00C7
|
||||
<Multi_key> <minus> <minus> <space> : "" U00AD
|
||||
<Multi_key> <parenleft> <r> : "®" U00AE
|
||||
<Multi_key> <R> <O> : "®" U00AE
|
||||
<Multi_key> <minus> <asciicircum> : "¯" U00AF
|
||||
<Multi_key> <asciicircum> <minus> : "¯" U00AF
|
||||
<Multi_key> <asciicircum> <underscore> : "¯" U00AF
|
||||
<Multi_key> <underscore> <asciicircum> : "¯" U00AF
|
||||
<Multi_key> <underscore> <underscore> : "¯" U00AF
|
||||
<Multi_key> <asterisk> <0> : "°" U00B0
|
||||
<Multi_key> <0> <asterisk> : "°" U00B0
|
||||
<Multi_key> <0> <asciicircum> : "°" U00B0
|
||||
<Multi_key> <minus> <plus> : "±" U00B1
|
||||
<Multi_key> <2> <S> : "²" U00B2
|
||||
<Multi_key> <2> <asciicircum> : "²" U00B2
|
||||
<Multi_key> <2> <s> : "²" U00B2
|
||||
<Multi_key> <S> <2> : "²" U00B2
|
||||
<Multi_key> <s> <2> : "²" U00B2
|
||||
<Multi_key> <3> <S> : "³" U00B3
|
||||
<Multi_key> <3> <asciicircum> : "³" U00B3
|
||||
<Multi_key> <3> <s> : "³" U00B3
|
||||
<Multi_key> <S> <3> : "³" U00B3
|
||||
<Multi_key> <s> <3> : "³" U00B3
|
||||
<Multi_key> <apostrophe> <apostrophe> : "´" U00B4
|
||||
<Multi_key> <slash> <U> : "µ" U00B5
|
||||
<Multi_key> <slash> <u> : "µ" U00B5
|
||||
<Multi_key> <U> <slash> : "µ" U00B5
|
||||
<Multi_key> <u> <slash> : "µ" U00B5
|
||||
<Multi_key> <exclam> <P> : "¶" U00B6
|
||||
<Multi_key> <exclam> <p> : "¶" U00B6
|
||||
<Multi_key> <period> <asciicircum> : "·" U00B7
|
||||
<Multi_key> <asciicircum> <period> : "·" U00B7
|
||||
<Multi_key> <comma> <comma> : "¸" U00B8
|
||||
<Multi_key> <1> <S> : "¹" U00B9
|
||||
<Multi_key> <1> <asciicircum> : "¹" U00B9
|
||||
<Multi_key> <1> <s> : "¹" U00B9
|
||||
<Multi_key> <S> <1> : "¹" U00B9
|
||||
<Multi_key> <s> <1> : "¹" U00B9
|
||||
<Multi_key> <O> <underscore> : "º" U00BA
|
||||
<Multi_key> <o> <underscore> : "º" U00BA
|
||||
<Multi_key> <A> <grave> : "À" U00C0
|
||||
<Multi_key> <A> <apostrophe> : "Á" U00C1
|
||||
<Multi_key> <A> <acute> : "Á" U00C1
|
||||
<Multi_key> <greater> <A> : "Â" U00C2
|
||||
<Multi_key> <A> <greater> : "Â" U00C2
|
||||
<Multi_key> <A> <asciicircum> : "Â" U00C2
|
||||
<Multi_key> <minus> <A> : "Ã" U00C3
|
||||
<Multi_key> <A> <minus> : "Ã" U00C3
|
||||
<Multi_key> <A> <asciitilde> : "Ã" U00C3
|
||||
<Multi_key> <A> <quotedbl> : "Ä" U00C4
|
||||
<Multi_key> <A> <diaeresis> : "Ä" U00C4
|
||||
<Multi_key> <diaeresis> <A> : "Ä" U00C4
|
||||
<Multi_key> <asterisk> <A> : "Å" U00C5
|
||||
<Multi_key> <A> <asterisk> : "Å" U00C5
|
||||
<Multi_key> <A> <A> : "Å" U00C5
|
||||
<Multi_key> <space> <less> : "ˇ" U02C7
|
||||
<Multi_key> <less> <space> : "ˇ" U02C7
|
||||
<Multi_key> <E> <grave> : "È" U00C8
|
||||
<Multi_key> <E> <apostrophe> : "É" U00C9
|
||||
<Multi_key> <E> <acute> : "É" U00C9
|
||||
<Multi_key> <greater> <E> : "Ê" U00CA
|
||||
<Multi_key> <E> <greater> : "Ê" U00CA
|
||||
<Multi_key> <E> <asciicircum> : "Ê" U00CA
|
||||
<Multi_key> <E> <quotedbl> : "Ë" U00CB
|
||||
<Multi_key> <E> <diaeresis> : "Ë" U00CB
|
||||
<Multi_key> <diaeresis> <E> : "Ë" U00CB
|
||||
<Multi_key> <I> <grave> : "Ì" U00CC
|
||||
<Multi_key> <I> <apostrophe> : "Í" U00CD
|
||||
<Multi_key> <I> <acute> : "Í" U00CD
|
||||
<Multi_key> <greater> <I> : "Î" U00CE
|
||||
<Multi_key> <I> <greater> : "Î" U00CE
|
||||
<Multi_key> <I> <asciicircum> : "Î" U00CE
|
||||
<Multi_key> <I> <quotedbl> : "Ï" U00CF
|
||||
<Multi_key> <I> <diaeresis> : "Ï" U00CF
|
||||
<Multi_key> <diaeresis> <I> : "Ï" U00CF
|
||||
<Multi_key> <minus> <N> : "Ñ" U00D1
|
||||
<Multi_key> <N> <minus> : "Ñ" U00D1
|
||||
<Multi_key> <N> <asciitilde> : "Ñ" U00D1
|
||||
<Multi_key> <O> <grave> : "Ò" U00D2
|
||||
<Multi_key> <O> <apostrophe> : "Ó" U00D3
|
||||
<Multi_key> <O> <acute> : "Ó" U00D3
|
||||
<Multi_key> <greater> <O> : "Ô" U00D4
|
||||
<Multi_key> <O> <greater> : "Ô" U00D4
|
||||
<Multi_key> <O> <asciicircum> : "Ô" U00D4
|
||||
<Multi_key> <minus> <O> : "Õ" U00D5
|
||||
<Multi_key> <O> <minus> : "Õ" U00D5
|
||||
<Multi_key> <O> <asciitilde> : "Õ" U00D5
|
||||
<Multi_key> <O> <quotedbl> : "Ö" U00D6
|
||||
<Multi_key> <O> <diaeresis> : "Ö" U00D6
|
||||
<Multi_key> <diaeresis> <O> : "Ö" U00D6
|
||||
<Multi_key> <space> <parenleft> : "˘" U02D8
|
||||
<Multi_key> <parenleft> <space> : "˘" U02D8
|
||||
<Multi_key> <U> <grave> : "Ù" U00D9
|
||||
<Multi_key> <U> <apostrophe> : "Ú" U00DA
|
||||
<Multi_key> <U> <acute> : "Ú" U00DA
|
||||
<Multi_key> <greater> <U> : "Û" U00DB
|
||||
<Multi_key> <U> <greater> : "Û" U00DB
|
||||
<Multi_key> <U> <asciicircum> : "Û" U00DB
|
||||
<Multi_key> <U> <quotedbl> : "Ü" U00DC
|
||||
<Multi_key> <U> <diaeresis> : "Ü" U00DC
|
||||
<Multi_key> <diaeresis> <U> : "Ü" U00DC
|
||||
<Multi_key> <Y> <apostrophe> : "Ý" U00DD
|
||||
<Multi_key> <Y> <acute> : "Ý" U00DD
|
||||
<Multi_key> <a> <grave> : "à" U00E0
|
||||
<Multi_key> <a> <apostrophe> : "á" U00E1
|
||||
<Multi_key> <a> <acute> : "á" U00E1
|
||||
<Multi_key> <greater> <a> : "â" U00E2
|
||||
<Multi_key> <a> <greater> : "â" U00E2
|
||||
<Multi_key> <a> <asciicircum> : "â" U00E2
|
||||
<Multi_key> <minus> <a> : "ā" U0101
|
||||
<Multi_key> <a> <minus> : "ā" U0101
|
||||
<Multi_key> <a> <asciitilde> : "ã" U00E3
|
||||
<Multi_key> <a> <quotedbl> : "ä" U00E4
|
||||
<Multi_key> <a> <diaeresis> : "ä" U00E4
|
||||
<Multi_key> <diaeresis> <a> : "ä" U00E4
|
||||
<Multi_key> <asterisk> <a> : "å" U00E5
|
||||
<Multi_key> <a> <asterisk> : "å" U00E5
|
||||
<Multi_key> <a> <a> : "å" U00E5
|
||||
<Multi_key> <c> <comma> : "ç" U00E7
|
||||
<Multi_key> <e> <grave> : "è" U00E8
|
||||
<Multi_key> <e> <apostrophe> : "é" U00E9
|
||||
<Multi_key> <e> <acute> : "é" U00E9
|
||||
<Multi_key> <greater> <e> : "ê" U00EA
|
||||
<Multi_key> <e> <greater> : "ê" U00EA
|
||||
<Multi_key> <e> <asciicircum> : "ê" U00EA
|
||||
<Multi_key> <e> <quotedbl> : "ë" U00EB
|
||||
<Multi_key> <e> <diaeresis> : "ë" U00EB
|
||||
<Multi_key> <diaeresis> <e> : "ë" U00EB
|
||||
<Multi_key> <i> <grave> : "ì" U00EC
|
||||
<Multi_key> <i> <apostrophe> : "í" U00ED
|
||||
<Multi_key> <i> <acute> : "í" U00ED
|
||||
<Multi_key> <greater> <i> : "î" U00EE
|
||||
<Multi_key> <i> <greater> : "î" U00EE
|
||||
<Multi_key> <i> <asciicircum> : "î" U00EE
|
||||
<Multi_key> <i> <quotedbl> : "ï" U00EF
|
||||
<Multi_key> <i> <diaeresis> : "ï" U00EF
|
||||
<Multi_key> <diaeresis> <i> : "ï" U00EF
|
||||
<Multi_key> <minus> <n> : "ñ" U00F1
|
||||
<Multi_key> <n> <minus> : "ñ" U00F1
|
||||
<Multi_key> <n> <asciitilde> : "ñ" U00F1
|
||||
<Multi_key> <o> <grave> : "ò" U00F2
|
||||
<Multi_key> <o> <apostrophe> : "ó" U00F3
|
||||
<Multi_key> <o> <acute> : "ó" U00F3
|
||||
<Multi_key> <greater> <o> : "ô" U00F4
|
||||
<Multi_key> <o> <greater> : "ô" U00F4
|
||||
<Multi_key> <o> <asciicircum> : "ô" U00F4
|
||||
<Multi_key> <minus> <o> : "ō" U014D
|
||||
<Multi_key> <o> <minus> : "ō" U014D
|
||||
<Multi_key> <o> <asciitilde> : "õ" U00F5
|
||||
<Multi_key> <o> <quotedbl> : "ö" U00F6
|
||||
<Multi_key> <o> <diaeresis> : "ö" U00F6
|
||||
<Multi_key> <diaeresis> <o> : "ö" U00F6
|
||||
<Multi_key> <o> <slash> : "ø" U00F8
|
||||
<Multi_key> <u> <grave> : "ù" U00F9
|
||||
<Multi_key> <u> <apostrophe> : "ú" U00FA
|
||||
<Multi_key> <u> <acute> : "ú" U00FA
|
||||
<Multi_key> <greater> <u> : "û" U00FB
|
||||
<Multi_key> <u> <greater> : "û" U00FB
|
||||
<Multi_key> <u> <asciicircum> : "û" U00FB
|
||||
<Multi_key> <u> <quotedbl> : "ü" U00FC
|
||||
<Multi_key> <u> <diaeresis> : "ü" U00FC
|
||||
<Multi_key> <diaeresis> <u> : "ü" U00FC
|
||||
<Multi_key> <y> <apostrophe> : "ý" U00FD
|
||||
<Multi_key> <y> <acute> : "ý" U00FD
|
||||
<Multi_key> <y> <quotedbl> : "ÿ" U00FF
|
||||
<Multi_key> <y> <diaeresis> : "ÿ" U00FF
|
||||
<Multi_key> <diaeresis> <y> : "ÿ" U00FF
|
||||
<Multi_key> <parenleft> <A> : "Ă" U0102
|
||||
<Multi_key> <A> <parenleft> : "Ă" U0102
|
||||
<Multi_key> <parenleft> <a> : "ă" U0103
|
||||
<Multi_key> <a> <parenleft> : "ă" U0103
|
||||
<Multi_key> <comma> <A> : "Ą" U0104
|
||||
<Multi_key> <A> <comma> : "Ą" U0104
|
||||
<Multi_key> <comma> <a> : "ą" U0105
|
||||
<Multi_key> <a> <comma> : "ą" U0105
|
||||
<Multi_key> <C> <apostrophe> : "Ć" U0106
|
||||
<Multi_key> <c> <apostrophe> : "ć" U0107
|
||||
<Multi_key> <C> <period> : "Ċ" U010A
|
||||
<Multi_key> <c> <period> : "ċ" U010B
|
||||
<Multi_key> <less> <C> : "Č" U010C
|
||||
<Multi_key> <C> <less> : "Č" U010C
|
||||
<Multi_key> <less> <c> : "č" U010D
|
||||
<Multi_key> <c> <less> : "č" U010D
|
||||
<Multi_key> <less> <D> : "Ď" U010E
|
||||
<Multi_key> <D> <less> : "Ď" U010E
|
||||
<Multi_key> <less> <d> : "ď" U010F
|
||||
<Multi_key> <d> <less> : "ď" U010F
|
||||
<Multi_key> <minus> <D> : "Đ" U0110
|
||||
<Multi_key> <D> <minus> : "Đ" U0110
|
||||
<Multi_key> <minus> <d> : "đ" U0111
|
||||
<Multi_key> <minus> <E> : "Ē" U0112
|
||||
<Multi_key> <E> <minus> : "Ē" U0112
|
||||
<Multi_key> <E> <underscore> : "Ē" U0112
|
||||
<Multi_key> <minus> <e> : "ē" U0113
|
||||
<Multi_key> <e> <minus> : "ē" U0113
|
||||
<Multi_key> <e> <underscore> : "ē" U0113
|
||||
<Multi_key> <E> <period> : "Ė" U0116
|
||||
<Multi_key> <E> <comma> : "Ę" U0118
|
||||
<Multi_key> <e> <comma> : "ę" U0119
|
||||
<Multi_key> <less> <E> : "Ě" U011A
|
||||
<Multi_key> <E> <less> : "Ě" U011A
|
||||
<Multi_key> <less> <e> : "ě" U011B
|
||||
<Multi_key> <e> <less> : "ě" U011B
|
||||
<Multi_key> <parenleft> <G> : "Ğ" U011E
|
||||
<Multi_key> <G> <parenleft> : "Ğ" U011E
|
||||
<Multi_key> <G> <U> : "Ğ" U011E
|
||||
<Multi_key> <G> <breve> : "Ğ" U011E
|
||||
<Multi_key> <breve> <G> : "Ğ" U011E
|
||||
<Multi_key> <parenleft> <g> : "ğ" U011F
|
||||
<Multi_key> <g> <parenleft> : "ğ" U011F
|
||||
<Multi_key> <g> <U> : "ğ" U011F
|
||||
<Multi_key> <g> <breve> : "ğ" U011F
|
||||
<Multi_key> <breve> <g> : "ğ" U011F
|
||||
<Multi_key> <G> <period> : "Ġ" U0120
|
||||
<Multi_key> <g> <period> : "ġ" U0121
|
||||
<Multi_key> <G> <comma> : "Ģ" U0122
|
||||
<Multi_key> <g> <comma> : "ģ" U0123
|
||||
<Multi_key> <I> <asciitilde> : "Ĩ" U0128
|
||||
<Multi_key> <i> <asciitilde> : "ĩ" U0129
|
||||
<Multi_key> <minus> <I> : "Ī" U012A
|
||||
<Multi_key> <I> <minus> : "Ī" U012A
|
||||
<Multi_key> <I> <underscore> : "Ī" U012A
|
||||
<Multi_key> <minus> <i> : "ī" U012B
|
||||
<Multi_key> <i> <minus> : "ī" U012B
|
||||
<Multi_key> <i> <underscore> : "ī" U012B
|
||||
<Multi_key> <comma> <I> : "Į" U012E
|
||||
<Multi_key> <I> <comma> : "Į" U012E
|
||||
<Multi_key> <I> <period> : "İ" U0130
|
||||
<Multi_key> <period> <i> : "ı" U0131
|
||||
<Multi_key> <K> <comma> : "Ķ" U0136
|
||||
<Multi_key> <k> <comma> : "ķ" U0137
|
||||
<Multi_key> <L> <apostrophe> : "Ĺ" U0139
|
||||
<Multi_key> <l> <apostrophe> : "ĺ" U013A
|
||||
<Multi_key> <L> <comma> : "Ļ" U013B
|
||||
<Multi_key> <l> <comma> : "ļ" U013C
|
||||
<Multi_key> <less> <L> : "Ľ" U013D
|
||||
<Multi_key> <L> <less> : "Ľ" U013D
|
||||
<Multi_key> <less> <l> : "ľ" U013E
|
||||
<Multi_key> <l> <less> : "ľ" U013E
|
||||
<Multi_key> <L> <slash> : "Ł" U0141
|
||||
<Multi_key> <l> <slash> : "ł" U0142
|
||||
<Multi_key> <N> <apostrophe> : "Ń" U0143
|
||||
<Multi_key> <n> <apostrophe> : "ń" U0144
|
||||
<Multi_key> <N> <comma> : "Ņ" U0145
|
||||
<Multi_key> <n> <comma> : "ņ" U0146
|
||||
<Multi_key> <less> <N> : "Ň" U0147
|
||||
<Multi_key> <N> <less> : "Ň" U0147
|
||||
<Multi_key> <less> <n> : "ň" U0148
|
||||
<Multi_key> <n> <less> : "ň" U0148
|
||||
<Multi_key> <R> <apostrophe> : "Ŕ" U0154
|
||||
<Multi_key> <r> <apostrophe> : "ŕ" U0155
|
||||
<Multi_key> <R> <comma> : "Ŗ" U0156
|
||||
<Multi_key> <r> <comma> : "ŗ" U0157
|
||||
<Multi_key> <less> <R> : "Ř" U0158
|
||||
<Multi_key> <R> <less> : "Ř" U0158
|
||||
<Multi_key> <less> <r> : "ř" U0159
|
||||
<Multi_key> <r> <less> : "ř" U0159
|
||||
<Multi_key> <S> <apostrophe> : "Ś" U015A
|
||||
<Multi_key> <s> <apostrophe> : "ś" U015B
|
||||
<Multi_key> <O> <slash> : "Ø" U00D8
|
||||
<Multi_key> <S> <comma> : "Ş" U015E
|
||||
<Multi_key> <S> <cedilla> : "Ş" U015E
|
||||
<Multi_key> <s> <comma> : "ş" U015F
|
||||
<Multi_key> <s> <cedilla> : "ş" U015F
|
||||
<Multi_key> <less> <S> : "Š" U0160
|
||||
<Multi_key> <S> <less> : "Š" U0160
|
||||
<Multi_key> <less> <s> : "š" U0161
|
||||
<Multi_key> <s> <less> : "š" U0161
|
||||
<Multi_key> <less> <T> : "Ť" U0164
|
||||
<Multi_key> <T> <less> : "Ť" U0164
|
||||
<Multi_key> <less> <t> : "ť" U0165
|
||||
<Multi_key> <t> <less> : "ť" U0165
|
||||
<Multi_key> <T> <minus> : "Ŧ" U0166
|
||||
<Multi_key> <T> <slash> : "Ŧ" U0166
|
||||
<Multi_key> <t> <minus> : "ŧ" U0167
|
||||
<Multi_key> <t> <slash> : "ŧ" U0167
|
||||
<Multi_key> <U> <asciitilde> : "Ũ" U0168
|
||||
<Multi_key> <u> <asciitilde> : "ũ" U0169
|
||||
<Multi_key> <minus> <U> : "Ū" U016A
|
||||
<Multi_key> <U> <minus> : "Ū" U016A
|
||||
<Multi_key> <U> <underscore> : "Ū" U016A
|
||||
<Multi_key> <minus> <u> : "ū" U016B
|
||||
<Multi_key> <u> <minus> : "ū" U016B
|
||||
<Multi_key> <u> <underscore> : "ū" U016B
|
||||
<Multi_key> <asterisk> <U> : "Ů" U016E
|
||||
<Multi_key> <U> <asterisk> : "Ů" U016E
|
||||
<Multi_key> <asterisk> <u> : "ů" U016F
|
||||
<Multi_key> <u> <asterisk> : "ů" U016F
|
||||
<Multi_key> <comma> <U> : "Ų" U0172
|
||||
<Multi_key> <U> <comma> : "Ų" U0172
|
||||
<Multi_key> <comma> <u> : "ų" U0173
|
||||
<Multi_key> <u> <comma> : "ų" U0173
|
||||
<Multi_key> <W> <asciicircum> : "Ŵ" U0174
|
||||
<Multi_key> <w> <asciicircum> : "ŵ" U0175
|
||||
<Multi_key> <Y> <asciicircum> : "Ŷ" U0176
|
||||
<Multi_key> <y> <asciicircum> : "ŷ" U0177
|
||||
<Multi_key> <Y> <quotedbl> : "Ÿ" U0178
|
||||
<Multi_key> <Y> <diaeresis> : "Ÿ" U0178
|
||||
<Multi_key> <diaeresis> <Y> : "Ÿ" U0178
|
||||
<Multi_key> <Z> <apostrophe> : "Ź" U0179
|
||||
<Multi_key> <z> <apostrophe> : "ź" U017A
|
||||
<Multi_key> <Z> <period> : "Ż" U017B
|
||||
<Multi_key> <z> <period> : "ż" U017C
|
||||
<Multi_key> <less> <Z> : "Ž" U017D
|
||||
<Multi_key> <Z> <less> : "Ž" U017D
|
||||
<Multi_key> <v> <Z> : "Ž" U017D
|
||||
<Multi_key> <less> <z> : "ž" U017E
|
||||
<Multi_key> <v> <z> : "ž" U017E
|
||||
<Multi_key> <z> <less> : "ž" U017E
|
||||
<dead_acute> <dead_diaeresis> <space> : "΅" U0385
|
||||
<dead_diaeresis> <dead_acute> <space> : "΅" U0385
|
||||
<Multi_key> <quotedbl> <apostrophe> <space> : "΅" U0385
|
||||
<Multi_key> <apostrophe> <quotedbl> <space> : "΅" U0385
|
||||
<Multi_key> <Greek_ALPHA> <apostrophe> : "Ά" U0386
|
||||
<Multi_key> <m> <period> : "ṁ" U1E41
|
||||
<Multi_key> <Greek_EPSILON> <apostrophe> : "Έ" U0388
|
||||
<Multi_key> <Greek_ETA> <apostrophe> : "Ή" U0389
|
||||
<Multi_key> <Greek_IOTA> <apostrophe> : "Ί" U038A
|
||||
<Multi_key> <Greek_OMICRON> <apostrophe> : "Ό" U038C
|
||||
<Multi_key> <Greek_UPSILON> <apostrophe> : "Ύ" U038E
|
||||
<Multi_key> <Greek_OMEGA> <apostrophe> : "Ώ" U038F
|
||||
<dead_diaeresis> <dead_acute> <Greek_iota> : "ΐ" U0390
|
||||
<Multi_key> <quotedbl> <apostrophe> <Greek_iota> : "ΐ" U0390
|
||||
<Multi_key> <comma> <i> : "į" U012F
|
||||
<Multi_key> <i> <comma> : "į" U012F
|
||||
<Multi_key> <Greek_IOTA> <quotedbl> : "Ϊ" U03AA
|
||||
<Multi_key> <Greek_UPSILON> <quotedbl> : "Ϋ" U03AB
|
||||
<Multi_key> <Greek_alpha> <apostrophe> : "ά" U03AC
|
||||
<Multi_key> <Greek_epsilon> <apostrophe> : "έ" U03AD
|
||||
<Multi_key> <Greek_eta> <apostrophe> : "ή" U03AE
|
||||
<Multi_key> <Greek_iota> <apostrophe> : "ί" U03AF
|
||||
<dead_diaeresis> <dead_acute> <Greek_upsilon> : "ΰ" U03B0
|
||||
<Multi_key> <quotedbl> <apostrophe> <Greek_upsilon> : "ΰ" U03B0
|
||||
<Multi_key> <Greek_iota> <quotedbl> : "ϊ" U03CA
|
||||
<Multi_key> <Greek_upsilon> <quotedbl> : "ϋ" U03CB
|
||||
<Multi_key> <Greek_omicron> <apostrophe> : "ό" U03CC
|
||||
<Multi_key> <Greek_upsilon> <apostrophe> : "ύ" U03CD
|
||||
<Multi_key> <Greek_omega> <apostrophe> : "ώ" U03CE
|
9
gtk/compose/gtkcomposedata.h
Normal file
9
gtk/compose/gtkcomposedata.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef __GTK_COMPOSE_DATA__
|
||||
#define __GTK_COMPOSE_DATA__
|
||||
|
||||
#define MAX_SEQ_LEN 5
|
||||
#define N_INDEX_SIZE 30
|
||||
#define DATA_SIZE 16521
|
||||
#define N_CHARS 1572
|
||||
|
||||
#endif
|
7
gtk/compose/meson.build
Normal file
7
gtk/compose/meson.build
Normal file
@ -0,0 +1,7 @@
|
||||
compose_parse = executable('compose-parse',
|
||||
sources: 'compose-parse.c',
|
||||
c_args: gtk_cargs + common_cflags,
|
||||
include_directories: [confinc, gtkinc],
|
||||
dependencies: libgtk_static_dep,
|
||||
install: false,
|
||||
)
|
BIN
gtk/compose/sequences
Normal file
BIN
gtk/compose/sequences
Normal file
Binary file not shown.
@ -84,6 +84,8 @@ for f in get_files('inspector', '.ui'):
|
||||
xml += '''
|
||||
<file>inspector/inspector.css</file>
|
||||
<file>emoji/en.data</file>
|
||||
<file>compose/sequences</file>
|
||||
<file>compose/chars</file>
|
||||
</gresource>
|
||||
</gresources>'''
|
||||
|
||||
|
@ -28,9 +28,9 @@
|
||||
|
||||
|
||||
#define GTK_COMPOSE_TABLE_MAGIC "GtkComposeTable"
|
||||
#define GTK_COMPOSE_TABLE_VERSION (2)
|
||||
#define GTK_COMPOSE_TABLE_VERSION (3)
|
||||
|
||||
extern const GtkComposeTableCompact gtk_compose_table_compact;
|
||||
extern const GtkComposeTable builtin_compose_table;
|
||||
|
||||
/* Maximum length of sequences we parse */
|
||||
|
||||
@ -326,36 +326,27 @@ handle_substitutions (const char *start,
|
||||
return g_string_free (s, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
add_sequence (gunichar *sequence,
|
||||
int len,
|
||||
const char *value,
|
||||
gpointer data)
|
||||
{
|
||||
GtkComposeParser *parser = data;
|
||||
gunichar *seq;
|
||||
|
||||
seq = g_new (gunichar, len + 1);
|
||||
memcpy (seq, sequence, (len + 1) * sizeof (gunichar));
|
||||
|
||||
g_hash_table_replace (parser->sequences, seq, g_strdup (value));
|
||||
}
|
||||
|
||||
static void
|
||||
parser_add_default_sequences (GtkComposeParser *parser)
|
||||
{
|
||||
const GtkComposeTableCompact *table = >k_compose_table_compact;
|
||||
const GtkComposeTable *table = &builtin_compose_table;
|
||||
|
||||
for (int idx = 0; idx < table->n_index_size; idx++)
|
||||
{
|
||||
const guint16 *seq_index = table->data + (idx * table->n_index_stride);
|
||||
|
||||
for (int i = 1; i < table->max_seq_len; i++)
|
||||
{
|
||||
int row_stride = i + 1;
|
||||
|
||||
for (int j = seq_index[i]; j < seq_index[i + 1]; j += row_stride)
|
||||
{
|
||||
char buf[8] = { 0, };
|
||||
gunichar *sequence;
|
||||
|
||||
sequence = g_new0 (gunichar, row_stride + 2);
|
||||
sequence[0] = seq_index[0];
|
||||
for (int k = 0; k < i; k++)
|
||||
sequence[1 + k] = table->data[j + k];
|
||||
sequence[1 + i] = 0;
|
||||
|
||||
g_unichar_to_utf8 (table->data[j + i], buf);
|
||||
|
||||
g_hash_table_replace (parser->sequences, sequence, g_strdup (buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
gtk_compose_table_foreach (table, add_sequence, parser);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -547,29 +538,54 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
parser_compute_max_compose_len (GtkComposeParser *parser)
|
||||
static void
|
||||
parser_compute_max_compose_len (GtkComposeParser *parser,
|
||||
int *max_compose_len,
|
||||
int *n_first,
|
||||
int *size)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
int max_compose_len = 0;
|
||||
gunichar *sequence;
|
||||
char *value;
|
||||
int max = 0;
|
||||
int count = 0;
|
||||
GHashTable *first;
|
||||
|
||||
first = g_hash_table_new (NULL, NULL);
|
||||
|
||||
g_hash_table_iter_init (&iter, parser->sequences);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&sequence, (gpointer *)&value))
|
||||
{
|
||||
g_hash_table_add (first, GUINT_TO_POINTER (sequence[0]));
|
||||
|
||||
for (int i = 0; i < MAX_COMPOSE_LEN + 1; i++)
|
||||
{
|
||||
if (sequence[i] == 0)
|
||||
{
|
||||
if (max_compose_len < i)
|
||||
max_compose_len = i;
|
||||
count += i;
|
||||
if (max < i)
|
||||
max = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return max_compose_len;
|
||||
*max_compose_len = max;
|
||||
*n_first = g_hash_table_size (first);
|
||||
*size = count;
|
||||
|
||||
g_hash_table_unref (first);
|
||||
}
|
||||
|
||||
static inline int
|
||||
sequence_length (gpointer a)
|
||||
{
|
||||
gunichar *seq = a;
|
||||
int i;
|
||||
|
||||
for (i = 0; seq[i]; i++) ;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -579,12 +595,26 @@ sequence_compare (gpointer a,
|
||||
{
|
||||
gunichar *seq_a = a;
|
||||
gunichar *seq_b = b;
|
||||
int max_compose_len = GPOINTER_TO_INT (data);
|
||||
int i;
|
||||
for (i = 0; i < max_compose_len; i++)
|
||||
gunichar code_a, code_b;
|
||||
int len_a, len_b;
|
||||
|
||||
code_a = seq_a[0];
|
||||
code_b = seq_b[0];
|
||||
|
||||
if (code_a != code_b)
|
||||
return code_a - code_b;
|
||||
|
||||
len_a = sequence_length (a);
|
||||
len_b = sequence_length (b);
|
||||
|
||||
if (len_a != len_b)
|
||||
return len_a - len_b;
|
||||
|
||||
for (i = 1; i < len_a; i++)
|
||||
{
|
||||
gunichar code_a = seq_a[i];
|
||||
gunichar code_b = seq_b[i];
|
||||
code_a = seq_a[i];
|
||||
code_b = seq_b[i];
|
||||
|
||||
if (code_a != code_b)
|
||||
return code_a - code_b;
|
||||
@ -640,29 +670,29 @@ gtk_compose_table_serialize (GtkComposeTable *compose_table,
|
||||
gsize *count)
|
||||
{
|
||||
char *p, *contents;
|
||||
gsize length, total_length;
|
||||
gsize header_length, total_length;
|
||||
guint16 bytes;
|
||||
const char *header = GTK_COMPOSE_TABLE_MAGIC;
|
||||
const guint16 version = GTK_COMPOSE_TABLE_VERSION;
|
||||
guint16 max_seq_len = compose_table->max_seq_len;
|
||||
guint16 index_stride = max_seq_len + 2;
|
||||
guint16 n_seqs = compose_table->n_seqs;
|
||||
guint16 n_index_size = compose_table->n_index_size;
|
||||
guint16 data_size = compose_table->data_size;
|
||||
guint16 n_chars = compose_table->n_chars;
|
||||
guint32 i;
|
||||
|
||||
g_return_val_if_fail (compose_table != NULL, NULL);
|
||||
g_return_val_if_fail (max_seq_len > 0, NULL);
|
||||
g_return_val_if_fail (index_stride > 0, NULL);
|
||||
g_return_val_if_fail (n_index_size > 0, NULL);
|
||||
|
||||
length = strlen (header);
|
||||
total_length = length + sizeof (guint16) * (4 + index_stride * n_seqs) + n_chars;
|
||||
header_length = strlen (header);
|
||||
total_length = header_length + sizeof (guint16) * (5 + data_size) + n_chars;
|
||||
if (count)
|
||||
*count = total_length;
|
||||
|
||||
p = contents = g_malloc (total_length);
|
||||
|
||||
memcpy (p, header, length);
|
||||
p += length;
|
||||
memcpy (p, header, header_length);
|
||||
p += header_length;
|
||||
|
||||
#define APPEND_GUINT16(elt) \
|
||||
bytes = GUINT16_TO_BE (elt); \
|
||||
@ -671,10 +701,11 @@ gtk_compose_table_serialize (GtkComposeTable *compose_table,
|
||||
|
||||
APPEND_GUINT16 (version);
|
||||
APPEND_GUINT16 (max_seq_len);
|
||||
APPEND_GUINT16 (n_seqs);
|
||||
APPEND_GUINT16 (n_index_size);
|
||||
APPEND_GUINT16 (data_size);
|
||||
APPEND_GUINT16 (n_chars);
|
||||
|
||||
for (i = 0; i < (guint32) index_stride * n_seqs; i++)
|
||||
for (i = 0; i < data_size; i++)
|
||||
{
|
||||
APPEND_GUINT16 (compose_table->data[i]);
|
||||
}
|
||||
@ -701,13 +732,13 @@ gtk_compose_table_load_cache (const char *compose_file)
|
||||
guint16 bytes;
|
||||
guint16 version;
|
||||
guint16 max_seq_len;
|
||||
guint16 index_stride;
|
||||
guint16 n_seqs;
|
||||
guint16 n_index_size;
|
||||
guint16 data_size;
|
||||
guint16 n_chars;
|
||||
guint32 i;
|
||||
guint16 *gtk_compose_seqs = NULL;
|
||||
GtkComposeTable *retval;
|
||||
guint16 *data = NULL;
|
||||
char *char_data = NULL;
|
||||
GtkComposeTable *retval;
|
||||
|
||||
hash = g_str_hash (compose_file);
|
||||
if ((path = gtk_compose_hash_get_cache_path (hash)) == NULL)
|
||||
@ -755,21 +786,21 @@ gtk_compose_table_load_cache (const char *compose_file)
|
||||
}
|
||||
|
||||
GET_GUINT16 (max_seq_len);
|
||||
GET_GUINT16 (n_seqs);
|
||||
GET_GUINT16 (n_index_size);
|
||||
GET_GUINT16 (data_size);
|
||||
GET_GUINT16 (n_chars);
|
||||
|
||||
if (max_seq_len == 0 || n_seqs == 0)
|
||||
if (max_seq_len == 0 || data_size == 0)
|
||||
{
|
||||
g_warning ("cache size is not correct %d %d", max_seq_len, n_seqs);
|
||||
g_warning ("cache size is not correct %d %d", max_seq_len, data_size);
|
||||
goto out_load_cache;
|
||||
}
|
||||
|
||||
index_stride = max_seq_len + 2;
|
||||
gtk_compose_seqs = g_new0 (guint16, n_seqs * index_stride);
|
||||
data = g_new0 (guint16, data_size);
|
||||
|
||||
for (i = 0; i < (guint32) index_stride * n_seqs; i++)
|
||||
for (i = 0; i < data_size; i++)
|
||||
{
|
||||
GET_GUINT16 (gtk_compose_seqs[i]);
|
||||
GET_GUINT16 (data[i]);
|
||||
}
|
||||
|
||||
if (n_chars > 0)
|
||||
@ -780,9 +811,10 @@ gtk_compose_table_load_cache (const char *compose_file)
|
||||
}
|
||||
|
||||
retval = g_new0 (GtkComposeTable, 1);
|
||||
retval->data = gtk_compose_seqs;
|
||||
retval->data = data;
|
||||
retval->max_seq_len = max_seq_len;
|
||||
retval->n_seqs = n_seqs;
|
||||
retval->n_index_size = n_index_size;
|
||||
retval->data_size = data_size;
|
||||
retval->char_data = char_data;
|
||||
retval->n_chars = n_chars;
|
||||
retval->id = hash;
|
||||
@ -795,7 +827,7 @@ gtk_compose_table_load_cache (const char *compose_file)
|
||||
#undef GET_GUINT16
|
||||
|
||||
out_load_cache:
|
||||
g_free (gtk_compose_seqs);
|
||||
g_free (data);
|
||||
g_free (char_data);
|
||||
g_free (contents);
|
||||
g_free (path);
|
||||
@ -834,94 +866,147 @@ out_save_cache:
|
||||
static GtkComposeTable *
|
||||
parser_get_compose_table (GtkComposeParser *parser)
|
||||
{
|
||||
guint length;
|
||||
guint n = 0;
|
||||
int i, j;
|
||||
guint16 *gtk_compose_seqs = NULL;
|
||||
GList *list;
|
||||
GtkComposeTable *retval = NULL;
|
||||
gunichar codepoint;
|
||||
guint16 *data;
|
||||
GtkComposeTable *table;
|
||||
guint16 encoded_value;
|
||||
GString *char_data;
|
||||
int max_compose_len = 0;
|
||||
int max_compose_len;
|
||||
GList *sequences;
|
||||
guint32 hash;
|
||||
GList *list;
|
||||
int i;
|
||||
int size;
|
||||
int n_first;
|
||||
int first_pos;
|
||||
int rest_pos;
|
||||
int index_rowstride;
|
||||
gunichar current_first;
|
||||
|
||||
parser_remove_duplicates (parser);
|
||||
|
||||
if (g_hash_table_size (parser->sequences) == 0)
|
||||
return NULL;
|
||||
|
||||
hash = g_str_hash (parser->compose_file);
|
||||
|
||||
max_compose_len = parser_compute_max_compose_len (parser);
|
||||
parser_compute_max_compose_len (parser, &max_compose_len, &n_first, &size);
|
||||
|
||||
sequences = g_hash_table_get_keys (parser->sequences);
|
||||
|
||||
sequences = g_list_sort_with_data (sequences,
|
||||
(GCompareDataFunc) sequence_compare,
|
||||
GINT_TO_POINTER (max_compose_len));
|
||||
NULL);
|
||||
|
||||
length = g_list_length (sequences);
|
||||
|
||||
gtk_compose_seqs = g_new0 (guint16, length * (max_compose_len + 2));
|
||||
index_rowstride = max_compose_len + 1;
|
||||
data = g_new0 (guint16, n_first * index_rowstride + size);
|
||||
|
||||
char_data = g_string_new ("");
|
||||
|
||||
current_first = 0;
|
||||
first_pos = 0;
|
||||
rest_pos = n_first * index_rowstride;
|
||||
|
||||
for (list = sequences; list != NULL; list = list->next)
|
||||
{
|
||||
gunichar *sequence = list->data;
|
||||
char *value = g_hash_table_lookup (parser->sequences, sequence);
|
||||
int len = sequence_length (sequence);
|
||||
|
||||
for (i = 0; i < max_compose_len; i++)
|
||||
g_assert (2 <= len && len <= max_compose_len);
|
||||
|
||||
/* Encode the value. If the value is a single
|
||||
* character with a value smaller than 1 << 15,
|
||||
* we just use it directly.
|
||||
* Otherwise, we store the value as string and
|
||||
* put the offset into the table, with the high
|
||||
* bit set.
|
||||
*/
|
||||
if (g_utf8_strlen (value, -1) == 1 &&
|
||||
g_utf8_get_char (value) < 0x8000)
|
||||
{
|
||||
if (sequence[i] == 0)
|
||||
{
|
||||
for (j = i; j < max_compose_len; j++)
|
||||
gtk_compose_seqs[n++] = 0;
|
||||
break;
|
||||
}
|
||||
gtk_compose_seqs[n++] = (guint16) sequence[i];
|
||||
}
|
||||
|
||||
if (g_utf8_strlen (value, -1) > 1)
|
||||
{
|
||||
if (char_data->len > 0)
|
||||
g_string_append_c (char_data, 0);
|
||||
|
||||
codepoint = char_data->len | (1 << 31);
|
||||
|
||||
g_string_append (char_data, value);
|
||||
encoded_value = (guint16) g_utf8_get_char (value);
|
||||
}
|
||||
else
|
||||
{
|
||||
codepoint = g_utf8_get_char (value);
|
||||
g_assert ((codepoint & (1 << 31)) == 0);
|
||||
g_assert (strlen (value) < 20);
|
||||
|
||||
if (char_data->len > 0)
|
||||
g_string_append_c (char_data, 0);
|
||||
|
||||
g_assert (char_data->len < 0x8000);
|
||||
|
||||
encoded_value = (guint16) (char_data->len | 0x8000);
|
||||
g_string_append (char_data, value);
|
||||
}
|
||||
|
||||
gtk_compose_seqs[n++] = (codepoint & 0xffff0000) >> 16;
|
||||
gtk_compose_seqs[n++] = codepoint & 0xffff;
|
||||
if (sequence[0] != current_first)
|
||||
{
|
||||
g_assert (sequence[0] <= 0xffff);
|
||||
if (current_first != 0)
|
||||
first_pos += index_rowstride;
|
||||
current_first = (guint16)sequence[0];
|
||||
|
||||
data[first_pos] = (guint16)sequence[0];
|
||||
for (i = 1; i < index_rowstride; i++)
|
||||
data[first_pos + i] = rest_pos;
|
||||
}
|
||||
|
||||
retval = g_new0 (GtkComposeTable, 1);
|
||||
retval->data = gtk_compose_seqs;
|
||||
retval->max_seq_len = max_compose_len;
|
||||
retval->n_seqs = length;
|
||||
retval->id = hash;
|
||||
retval->n_chars = char_data->len;
|
||||
retval->char_data = g_string_free (char_data, FALSE);
|
||||
for (i = 1; i < len; i++)
|
||||
{
|
||||
g_assert (sequence[i] != 0);
|
||||
g_assert (sequence[i] <= 0xffff);
|
||||
data[rest_pos + i - 1] = (guint16) sequence[i];
|
||||
}
|
||||
|
||||
g_assert (encoded_value != 0);
|
||||
data[rest_pos + len - 1] = encoded_value;
|
||||
|
||||
rest_pos += len;
|
||||
|
||||
for (i = len; i <= max_compose_len; i++)
|
||||
data[first_pos + i] = rest_pos;
|
||||
|
||||
for (i = 1; i < max_compose_len; i++)
|
||||
g_assert (data[first_pos + i] <= data[first_pos + i + 1]);
|
||||
}
|
||||
|
||||
g_assert (first_pos + index_rowstride == n_first * index_rowstride);
|
||||
g_assert (rest_pos == n_first * index_rowstride + size);
|
||||
|
||||
if (char_data->len > 0)
|
||||
g_string_append_c (char_data, 0);
|
||||
|
||||
table = g_new0 (GtkComposeTable, 1);
|
||||
table->data = data;
|
||||
table->data_size = n_first * index_rowstride + size;
|
||||
table->max_seq_len = max_compose_len;
|
||||
table->n_index_size = n_first;
|
||||
table->n_chars = char_data->len;
|
||||
table->char_data = g_string_free (char_data, FALSE);
|
||||
table->id = g_str_hash (parser->compose_file);
|
||||
|
||||
g_list_free (sequences);
|
||||
|
||||
return retval;
|
||||
return table;
|
||||
}
|
||||
|
||||
static char *
|
||||
canonicalize_filename (const char *path)
|
||||
canonicalize_filename (GtkComposeParser *parser,
|
||||
const char *path)
|
||||
{
|
||||
GFile *file;
|
||||
char *retval;
|
||||
|
||||
if (path[0] != '/' && parser->compose_file)
|
||||
{
|
||||
GFile *orig = g_file_new_for_path (parser->compose_file);
|
||||
GFile *parent = g_file_get_parent (orig);
|
||||
file = g_file_resolve_relative_path (parent, path);
|
||||
g_object_unref (parent);
|
||||
g_object_unref (orig);
|
||||
}
|
||||
else
|
||||
{
|
||||
file = g_file_new_for_path (path);
|
||||
}
|
||||
|
||||
retval = g_file_get_path (file);
|
||||
|
||||
g_object_unref (file);
|
||||
@ -939,7 +1024,7 @@ parser_parse_file (GtkComposeParser *parser,
|
||||
if (parser->compose_file == NULL)
|
||||
parser->compose_file = compose_file;
|
||||
|
||||
path = canonicalize_filename (compose_file);
|
||||
path = canonicalize_filename (parser, compose_file);
|
||||
|
||||
if (g_list_find_custom (parser->files, path, (GCompareFunc)strcmp))
|
||||
{
|
||||
@ -956,24 +1041,31 @@ parser_parse_file (GtkComposeParser *parser,
|
||||
}
|
||||
|
||||
GtkComposeTable *
|
||||
gtk_compose_table_new_with_file (const char *compose_file)
|
||||
gtk_compose_table_parse (const char *compose_file)
|
||||
{
|
||||
GtkComposeParser *parser;
|
||||
GtkComposeTable *compose_table;
|
||||
|
||||
parser = parser_new ();
|
||||
parser_parse_file (parser, compose_file);
|
||||
compose_table = parser_get_compose_table (parser);
|
||||
parser_free (parser);
|
||||
|
||||
return compose_table;
|
||||
}
|
||||
|
||||
GtkComposeTable *
|
||||
gtk_compose_table_new_with_file (const char *compose_file)
|
||||
{
|
||||
GtkComposeTable *compose_table;
|
||||
|
||||
g_assert (compose_file != NULL);
|
||||
|
||||
compose_table = gtk_compose_table_load_cache (compose_file);
|
||||
if (compose_table != NULL)
|
||||
return compose_table;
|
||||
|
||||
parser = parser_new ();
|
||||
|
||||
parser_parse_file (parser, compose_file);
|
||||
|
||||
compose_table = parser_get_compose_table (parser);
|
||||
|
||||
parser_free (parser);
|
||||
compose_table = gtk_compose_table_parse (compose_file);
|
||||
|
||||
if (compose_table != NULL)
|
||||
gtk_compose_table_save_cache (compose_table);
|
||||
@ -986,34 +1078,30 @@ gtk_compose_table_new_with_data (const guint16 *data,
|
||||
int max_seq_len,
|
||||
int n_seqs)
|
||||
{
|
||||
GtkComposeParser *parser;
|
||||
GtkComposeTable *compose_table;
|
||||
gsize n_index_stride;
|
||||
gsize length;
|
||||
int i;
|
||||
guint16 *gtk_compose_seqs = NULL;
|
||||
|
||||
g_return_val_if_fail (data != NULL, NULL);
|
||||
g_return_val_if_fail (max_seq_len >= 0, NULL);
|
||||
g_return_val_if_fail (n_seqs >= 0, NULL);
|
||||
parser = parser_new ();
|
||||
|
||||
n_index_stride = max_seq_len + 2;
|
||||
if (!g_size_checked_mul (&length, n_index_stride, n_seqs))
|
||||
for (i = 0; i < n_seqs; i++)
|
||||
{
|
||||
g_critical ("Overflow in the compose sequences");
|
||||
return NULL;
|
||||
const guint16 *seq = data + i * (max_seq_len + 2);
|
||||
guint16 *sequence;
|
||||
gunichar ch;
|
||||
char buf[8] = { 0, };
|
||||
|
||||
sequence = g_new0 (guint16, max_seq_len + 1);
|
||||
memcpy (sequence, seq, sizeof (guint16) * max_seq_len);
|
||||
|
||||
ch = ((gunichar)seq[max_seq_len]) << 16 | (gunichar)seq[max_seq_len + 1];
|
||||
g_unichar_to_utf8 (ch, buf);
|
||||
|
||||
g_hash_table_replace (parser->sequences, sequence, g_strdup (buf));
|
||||
}
|
||||
|
||||
gtk_compose_seqs = g_new0 (guint16, length);
|
||||
for (i = 0; i < length; i++)
|
||||
gtk_compose_seqs[i] = data[i];
|
||||
|
||||
compose_table = g_new (GtkComposeTable, 1);
|
||||
compose_table->data = gtk_compose_seqs;
|
||||
compose_table->max_seq_len = max_seq_len;
|
||||
compose_table->n_seqs = n_seqs;
|
||||
compose_table->id = data_hash (data, length);
|
||||
compose_table->char_data = NULL;
|
||||
compose_table->n_chars = 0;
|
||||
compose_table = parser_get_compose_table (parser);
|
||||
parser_free (parser);
|
||||
|
||||
return compose_table;
|
||||
}
|
||||
@ -1038,6 +1126,20 @@ compare_seq (const void *key, const void *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_seq_index (const void *key, const void *value)
|
||||
{
|
||||
const guint16 *keysyms = key;
|
||||
const guint16 *seq = value;
|
||||
|
||||
if (keysyms[0] < seq[0])
|
||||
return -1;
|
||||
else if (keysyms[0] > seq[0])
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* gtk_compose_table_check:
|
||||
* @table: the table to check
|
||||
@ -1058,97 +1160,6 @@ gtk_compose_table_check (const GtkComposeTable *table,
|
||||
gboolean *compose_finish,
|
||||
gboolean *compose_match,
|
||||
GString *output)
|
||||
{
|
||||
int row_stride = table->max_seq_len + 2;
|
||||
guint16 *seq;
|
||||
|
||||
*compose_finish = FALSE;
|
||||
*compose_match = FALSE;
|
||||
|
||||
g_string_set_size (output, 0);
|
||||
|
||||
/* Will never match, if the sequence in the compose buffer is longer
|
||||
* than the sequences in the table. Further, compare_seq (key, val)
|
||||
* will overrun val if key is longer than val.
|
||||
*/
|
||||
if (n_compose > table->max_seq_len)
|
||||
return FALSE;
|
||||
|
||||
seq = bsearch (compose_buffer,
|
||||
table->data, table->n_seqs,
|
||||
sizeof (guint16) * row_stride,
|
||||
compare_seq);
|
||||
|
||||
if (seq)
|
||||
{
|
||||
guint16 *prev_seq;
|
||||
|
||||
/* Back up to the first sequence that matches to make sure
|
||||
* we find the exact match if there is one.
|
||||
*/
|
||||
while (seq > table->data)
|
||||
{
|
||||
prev_seq = seq - row_stride;
|
||||
if (compare_seq (compose_buffer, prev_seq) != 0)
|
||||
break;
|
||||
seq = prev_seq;
|
||||
}
|
||||
|
||||
if (n_compose == table->max_seq_len ||
|
||||
seq[n_compose] == 0) /* complete sequence */
|
||||
{
|
||||
guint16 *next_seq;
|
||||
gunichar value;
|
||||
|
||||
value = (seq[table->max_seq_len] << 16) | seq[table->max_seq_len + 1];
|
||||
if ((value & (1 << 31)) != 0)
|
||||
g_string_append (output, &table->char_data[value & ~(1 << 31)]);
|
||||
else
|
||||
g_string_append_unichar (output, value);
|
||||
|
||||
*compose_match = TRUE;
|
||||
|
||||
/* We found a tentative match. See if there are any longer
|
||||
* sequences containing this subsequence
|
||||
*/
|
||||
next_seq = seq + row_stride;
|
||||
if (next_seq < table->data + row_stride * table->n_seqs)
|
||||
{
|
||||
if (compare_seq (compose_buffer, next_seq) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
*compose_finish = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_seq_index (const void *key, const void *value)
|
||||
{
|
||||
const guint16 *keysyms = key;
|
||||
const guint16 *seq = value;
|
||||
|
||||
if (keysyms[0] < seq[0])
|
||||
return -1;
|
||||
else if (keysyms[0] > seq[0])
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_compose_table_compact_check (const GtkComposeTableCompact *table,
|
||||
const guint16 *compose_buffer,
|
||||
int n_compose,
|
||||
gboolean *compose_finish,
|
||||
gboolean *compose_match,
|
||||
gunichar *output_char)
|
||||
{
|
||||
int row_stride;
|
||||
guint16 *seq_index;
|
||||
@ -1161,8 +1172,6 @@ gtk_compose_table_compact_check (const GtkComposeTableCompact *table,
|
||||
*compose_finish = FALSE;
|
||||
if (compose_match)
|
||||
*compose_match = FALSE;
|
||||
if (output_char)
|
||||
*output_char = 0;
|
||||
|
||||
/* Will never match, if the sequence in the compose buffer is longer
|
||||
* than the sequences in the table. Further, compare_seq (key, val)
|
||||
@ -1174,7 +1183,7 @@ gtk_compose_table_compact_check (const GtkComposeTableCompact *table,
|
||||
seq_index = bsearch (compose_buffer,
|
||||
table->data,
|
||||
table->n_index_size,
|
||||
sizeof (guint16) * table->n_index_stride,
|
||||
sizeof (guint16) * (table->max_seq_len + 1),
|
||||
compare_seq_index);
|
||||
|
||||
if (!seq_index)
|
||||
@ -1204,12 +1213,15 @@ gtk_compose_table_compact_check (const GtkComposeTableCompact *table,
|
||||
if (i == n_compose - 1)
|
||||
{
|
||||
value = seq[row_stride - 1];
|
||||
|
||||
if ((value & (1 << 15)) != 0)
|
||||
g_string_append (output, &table->char_data[value & ~(1 << 15)]);
|
||||
else
|
||||
g_string_append_unichar (output, value);
|
||||
match = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (output_char)
|
||||
*output_char = value;
|
||||
if (match)
|
||||
{
|
||||
if (compose_match)
|
||||
@ -1228,8 +1240,6 @@ gtk_compose_table_compact_check (const GtkComposeTableCompact *table,
|
||||
*compose_match = TRUE;
|
||||
if (compose_finish)
|
||||
*compose_finish = TRUE;
|
||||
if (output_char)
|
||||
*output_char = value;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -1237,6 +1247,65 @@ gtk_compose_table_compact_check (const GtkComposeTableCompact *table,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_compose_table_foreach (const GtkComposeTable *table,
|
||||
GtkComposeSequenceCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
int index_stride = table->max_seq_len + 1;
|
||||
gunichar *sequence;
|
||||
int seqno;
|
||||
|
||||
sequence = g_new0 (gunichar, table->max_seq_len + 1);
|
||||
|
||||
seqno = 0;
|
||||
for (int idx = 0; idx < table->n_index_size; idx++)
|
||||
{
|
||||
const guint16 *seq_index = table->data + (idx * index_stride);
|
||||
|
||||
for (int i = 1; i < table->max_seq_len; i++)
|
||||
{
|
||||
int len = i + 1;
|
||||
|
||||
g_assert (seq_index[i] <= seq_index[i + 1]);
|
||||
g_assert (seq_index[i + 1] <= table->data_size);
|
||||
g_assert ((seq_index[i + 1] - seq_index[i]) % len == 0);
|
||||
|
||||
for (int j = seq_index[i]; j < seq_index[i + 1]; j += len)
|
||||
{
|
||||
char buf[8] = { 0, };
|
||||
guint16 encoded_value;
|
||||
char *value;
|
||||
|
||||
sequence[0] = seq_index[0];
|
||||
for (int k = 0; k < len - 1; k++)
|
||||
sequence[k + 1] = (gunichar) table->data[j + k];
|
||||
sequence[len] = 0;
|
||||
|
||||
encoded_value = table->data[j + len - 1];
|
||||
g_assert (encoded_value != 0);
|
||||
if ((encoded_value & (1 << 15)) != 0)
|
||||
{
|
||||
int char_offset = encoded_value & ~(1 << 15);
|
||||
g_assert (char_offset < table->n_chars);
|
||||
value = &table->char_data[char_offset];
|
||||
g_assert (strlen (value) < 20);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_unichar_to_utf8 ((gunichar)encoded_value, buf);
|
||||
value = buf;
|
||||
}
|
||||
|
||||
callback (sequence, len, value, data);
|
||||
seqno++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_free (sequence);
|
||||
}
|
||||
|
||||
/* Checks if a keysym is a dead key.
|
||||
* Dead key keysym values are defined in ../gdk/gdkkeysyms.h and the
|
||||
* first is GDK_KEY_dead_grave. As X.Org is updated, more dead keys
|
||||
@ -1428,4 +1497,3 @@ gtk_check_algorithmically (const guint16 *compose_buffer,
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -26,29 +26,51 @@ G_BEGIN_DECLS
|
||||
typedef struct _GtkComposeTable GtkComposeTable;
|
||||
typedef struct _GtkComposeTableCompact GtkComposeTableCompact;
|
||||
|
||||
/* The layout of the data is as follows:
|
||||
*
|
||||
* The first part of the data contains rows of length max_seq_len + 1,
|
||||
* where the first element is the item of the sequence, and the
|
||||
* following elements are offsets to the data for sequences that
|
||||
* start with the first item of length 2, ..., max_seq_len.
|
||||
*
|
||||
* The second part of the data contains the rest of the sequence
|
||||
* data. It does not have a fixed stride. For each sequence, we
|
||||
* put seq[2], ..., seq[len - 1], followed by the encoded value
|
||||
* for this sequence.
|
||||
*
|
||||
* The values are encoded as follows:
|
||||
*
|
||||
* If the value is a single Unicode character smaler than 0x8000,
|
||||
* then we place it directly. Otherwise, we put the UTF8-encoded
|
||||
* value in the char_data array, and use offset | 0x8000 as the
|
||||
* encoded value.
|
||||
*/
|
||||
struct _GtkComposeTable
|
||||
{
|
||||
guint16 *data;
|
||||
char *char_data;
|
||||
int max_seq_len;
|
||||
int n_seqs;
|
||||
int n_index_size;
|
||||
int data_size;
|
||||
int n_chars;
|
||||
guint32 id;
|
||||
};
|
||||
|
||||
struct _GtkComposeTableCompact
|
||||
{
|
||||
const guint16 *data;
|
||||
int max_seq_len;
|
||||
int n_index_size;
|
||||
int n_index_stride;
|
||||
};
|
||||
|
||||
GtkComposeTable * gtk_compose_table_new_with_file (const char *compose_file);
|
||||
GtkComposeTable * gtk_compose_table_parse (const char *compose_file);
|
||||
GtkComposeTable * gtk_compose_table_new_with_data (const guint16 *data,
|
||||
int max_seq_len,
|
||||
int n_seqs);
|
||||
|
||||
typedef void (* GtkComposeSequenceCallback) (gunichar *sequence,
|
||||
int len,
|
||||
const char *value,
|
||||
gpointer data);
|
||||
|
||||
void gtk_compose_table_foreach (const GtkComposeTable *table,
|
||||
GtkComposeSequenceCallback callback,
|
||||
gpointer data);
|
||||
|
||||
gboolean gtk_compose_table_check (const GtkComposeTable *table,
|
||||
const guint16 *compose_buffer,
|
||||
int n_compose,
|
||||
@ -56,13 +78,6 @@ gboolean gtk_compose_table_check (const GtkComposeTable *table
|
||||
gboolean *compose_match,
|
||||
GString *output);
|
||||
|
||||
gboolean gtk_compose_table_compact_check (const GtkComposeTableCompact *table,
|
||||
const guint16 *compose_buffer,
|
||||
int n_compose,
|
||||
gboolean *compose_finish,
|
||||
gboolean *compose_match,
|
||||
gunichar *output_char);
|
||||
|
||||
gboolean gtk_check_algorithmically (const guint16 *compose_buffer,
|
||||
int n_compose,
|
||||
gunichar *output);
|
||||
|
@ -74,18 +74,32 @@ struct _GtkIMContextSimplePrivate
|
||||
guint modifiers_dropped : 1;
|
||||
};
|
||||
|
||||
/* From the values below, the value 30 means the number of different first keysyms
|
||||
* that exist in the Compose file (from Xorg). When running compose-parse.py without
|
||||
* parameters, you get the count that you can put here. Needed when updating the
|
||||
* gtkimcontextsimpleseqs.h header file (contains the compose sequences).
|
||||
*/
|
||||
const GtkComposeTableCompact gtk_compose_table_compact = {
|
||||
gtk_compose_seqs_compact,
|
||||
5,
|
||||
30,
|
||||
6
|
||||
#include "gtk/compose/gtkcomposedata.h"
|
||||
|
||||
GtkComposeTable builtin_compose_table = {
|
||||
NULL,
|
||||
NULL,
|
||||
MAX_SEQ_LEN,
|
||||
N_INDEX_SIZE,
|
||||
DATA_SIZE,
|
||||
N_CHARS,
|
||||
0
|
||||
};
|
||||
|
||||
static void
|
||||
init_builtin_table (void)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_resources_lookup_data ("/org/gtk/libgtk/compose/sequences", 0, NULL);
|
||||
builtin_compose_table.data = (guint16 *) g_bytes_get_data (bytes, NULL);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
bytes = g_resources_lookup_data ("/org/gtk/libgtk/compose/chars", 0, NULL);
|
||||
builtin_compose_table.char_data = (char *) g_bytes_get_data (bytes, NULL);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
G_LOCK_DEFINE_STATIC (global_tables);
|
||||
static GSList *global_tables;
|
||||
static gboolean omit_builtin_sequences;
|
||||
@ -147,6 +161,7 @@ gtk_im_context_simple_class_init (GtkIMContextSimpleClass *class)
|
||||
im_context_class->get_preedit_string = gtk_im_context_simple_get_preedit_string;
|
||||
gobject_class->finalize = gtk_im_context_simple_finalize;
|
||||
|
||||
init_builtin_table ();
|
||||
init_compose_table_async (NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
@ -200,7 +215,7 @@ add_compose_table_from_file (const char *compose_file,
|
||||
}
|
||||
|
||||
static void
|
||||
add_compose_table_from_data (const guint16 *data,
|
||||
add_compose_table_from_data (guint16 *data,
|
||||
int max_seq_len,
|
||||
int n_seqs)
|
||||
{
|
||||
@ -337,7 +352,7 @@ gtk_im_context_simple_init (GtkIMContextSimple *context_simple)
|
||||
|
||||
priv = context_simple->priv = gtk_im_context_simple_get_instance_private (context_simple);
|
||||
|
||||
priv->compose_buffer_len = gtk_compose_table_compact.max_seq_len + 1;
|
||||
priv->compose_buffer_len = builtin_compose_table.max_seq_len + 1;
|
||||
priv->compose_buffer = g_new0 (guint16, priv->compose_buffer_len);
|
||||
priv->tentative_match = g_string_new ("");
|
||||
priv->tentative_match_len = 0;
|
||||
@ -1069,18 +1084,19 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
|
||||
|
||||
G_UNLOCK (global_tables);
|
||||
|
||||
g_string_free (output, TRUE);
|
||||
|
||||
if (success)
|
||||
{
|
||||
g_string_free (output, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_LOCK (global_tables);
|
||||
|
||||
if (!omit_builtin_sequences &&
|
||||
gtk_compose_table_compact_check (>k_compose_table_compact,
|
||||
gtk_compose_table_check (&builtin_compose_table,
|
||||
priv->compose_buffer, n_compose,
|
||||
&compose_finish, &compose_match,
|
||||
&output_char))
|
||||
output))
|
||||
{
|
||||
if (!priv->in_compose_sequence)
|
||||
{
|
||||
@ -1091,24 +1107,28 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
|
||||
if (compose_finish)
|
||||
{
|
||||
if (compose_match)
|
||||
gtk_im_context_simple_commit_char (context_simple, output_char);
|
||||
gtk_im_context_simple_commit_string (context_simple, output->str);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (compose_match)
|
||||
{
|
||||
g_string_set_size (priv->tentative_match, 0);
|
||||
g_string_append_unichar (priv->tentative_match, output_char);
|
||||
g_string_assign (priv->tentative_match, output->str);
|
||||
priv->tentative_match_len = n_compose;
|
||||
}
|
||||
g_signal_emit_by_name (context_simple, "preedit-changed");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
success = TRUE;
|
||||
}
|
||||
|
||||
G_UNLOCK (global_tables);
|
||||
|
||||
g_string_free (output, TRUE);
|
||||
|
||||
if (success)
|
||||
return TRUE;
|
||||
|
||||
if (gtk_check_algorithmically (priv->compose_buffer, n_compose, &output_char))
|
||||
{
|
||||
if (!priv->in_compose_sequence)
|
||||
@ -1261,7 +1281,9 @@ gtk_im_context_simple_get_preedit_string (GtkIMContext *context,
|
||||
* The table must be sorted in dictionary order on the
|
||||
* numeric value of the key symbol fields. (Values beyond
|
||||
* the length of the sequence should be zero.)
|
||||
**/
|
||||
*
|
||||
* Deprecated: 4.4: Use gtk_im_context_simple_add_compose_file()
|
||||
*/
|
||||
void
|
||||
gtk_im_context_simple_add_table (GtkIMContextSimple *context_simple,
|
||||
guint16 *data,
|
||||
|
@ -63,7 +63,7 @@ GType gtk_im_context_simple_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkIMContext *gtk_im_context_simple_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_4_FOR(gtk_im_context_simple_add_compose_file)
|
||||
void gtk_im_context_simple_add_table (GtkIMContextSimple *context_simple,
|
||||
guint16 *data,
|
||||
int max_seq_len,
|
||||
|
@ -1276,3 +1276,5 @@ libgtk_static_dep = declare_dependency(sources: gtk_dep_sources,
|
||||
link_with: [libgtk_static, libgtk_css, libgdk, libgsk ],
|
||||
link_args: common_ldflags,
|
||||
)
|
||||
|
||||
subdir('compose')
|
||||
|
@ -1,3 +1,5 @@
|
||||
# n_seqs: 1
|
||||
# max_seq_len: 4
|
||||
# n_index_size: 1
|
||||
# data_size: 9
|
||||
# n_chars: 0
|
||||
<Uff20> <U73> <U65> <U71> : "!" # U21
|
||||
|
@ -1,3 +1,5 @@
|
||||
# n_seqs: 1
|
||||
# max_seq_len: 4
|
||||
# n_index_size: 1
|
||||
# data_size: 9
|
||||
# n_chars: 0
|
||||
<Uff20> <U73> <U6f> <U7a> : "!" # U21
|
||||
|
@ -1,5 +1,7 @@
|
||||
# n_seqs: 3
|
||||
# max_seq_len: 2
|
||||
# n_index_size: 1
|
||||
# data_size: 9
|
||||
# n_chars: 0
|
||||
<Uff20> <U61> : "a" # U61
|
||||
<Uff20> <U62> : "#" # U23
|
||||
<Uff20> <U63> : "a" # U61
|
||||
|
@ -1,3 +1,3 @@
|
||||
include "testsuite/gtk/compose/cycle" # create an include cycle
|
||||
include "cycle" # create an include cycle
|
||||
|
||||
<Multi_key> <s> <e> <q> : "!"
|
||||
|
@ -1,3 +1,5 @@
|
||||
# n_seqs: 1
|
||||
# max_seq_len: 4
|
||||
# n_index_size: 1
|
||||
# data_size: 9
|
||||
# n_chars: 7
|
||||
<Uff20> <U73> <U65> <U71> : "⏾⏳"
|
||||
|
@ -1,4 +1,4 @@
|
||||
include "testsuite/gtk/compose/included" # see if this works
|
||||
include "included" # see if this works
|
||||
|
||||
<Multi_key> <s> <s> <s> : "!" # replace this entry
|
||||
<Multi_key> <a> <a> <a> : "" # remove this entry
|
||||
|
@ -1,3 +1,5 @@
|
||||
# n_seqs: 1
|
||||
# max_seq_len: 4
|
||||
# n_index_size: 1
|
||||
# data_size: 9
|
||||
# n_chars: 0
|
||||
<Uff20> <U73> <U73> <U73> : "!" # U21
|
||||
|
@ -1,3 +1,5 @@
|
||||
# n_seqs: 1
|
||||
# max_seq_len: 11
|
||||
# n_index_size: 1
|
||||
# data_size: 23
|
||||
# n_chars: 5
|
||||
<Uff20> <U65> <U6d> <U6d> <U65> <U6e> <U74> <U61> <U6c> <U65> <U72> : "🧀" # U1f9c0
|
||||
|
@ -1,5 +1,7 @@
|
||||
# n_seqs: 3
|
||||
# max_seq_len: 7
|
||||
<Uff20> <U73> <U65> <U71> <U0> <U0> <U0> : "!" # U21
|
||||
<Uff20> <U73> <U65> <U71> <U75> <U0> <U0> : "?" # U3f
|
||||
<Uff20> <U7a> <U77> <U69> <U6e> <U65> <U73> : "🥂" # U1f942
|
||||
# n_index_size: 1
|
||||
# data_size: 24
|
||||
# n_chars: 4
|
||||
<Uff20> <U73> <U65> <U71> : "!" # U21
|
||||
<Uff20> <U73> <U65> <U71> <U75> : "?" # U3f
|
||||
<Uff20> <U7a> <U77> <U69> <U6e> <U65> <U73> : "🥂"
|
||||
|
@ -1,5 +1,7 @@
|
||||
# n_seqs: 3
|
||||
# max_seq_len: 5
|
||||
<Uff20> <U73> <U61> <U73> <U0> : "_" # U5f
|
||||
<Uff20> <U73> <U65> <U71> <U0> : "!" # U21
|
||||
# n_index_size: 1
|
||||
# data_size: 19
|
||||
# n_chars: 0
|
||||
<Uff20> <U73> <U61> <U73> : "_" # U5f
|
||||
<Uff20> <U73> <U65> <U71> : "!" # U21
|
||||
<Uff20> <U75> <U62> <U32> <U33> : "/" # U2f
|
||||
|
@ -1,3 +1,5 @@
|
||||
# n_seqs: 1
|
||||
# max_seq_len: 4
|
||||
# n_index_size: 1
|
||||
# data_size: 9
|
||||
# n_chars: 0
|
||||
<Uff20> <U73> <U65> <U71> : "!" # U21
|
||||
|
@ -1,6 +1,8 @@
|
||||
# n_seqs: 4
|
||||
# max_seq_len: 5
|
||||
<Uff20> <U73> <U61> <U73> <U0> : "\"\\"
|
||||
<Uff20> <U73> <U65> <U71> <U0> : "!a"
|
||||
# n_index_size: 1
|
||||
# data_size: 24
|
||||
# n_chars: 9
|
||||
<Uff20> <U73> <U61> <U73> : "\"\\"
|
||||
<Uff20> <U73> <U65> <U71> : "!a"
|
||||
<Uff20> <U73> <U65> <U71> <U75> : "?" # U3f
|
||||
<Uff20> <U75> <U62> <U32> <U33> : "QR"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,8 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "../gtk/gtkcomposetable.h"
|
||||
#include "../gtk/gtkimcontextsimpleseqs.h"
|
||||
#include "testsuite/testutils.h"
|
||||
@ -33,43 +35,59 @@ append_escaped (GString *str,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_sequence (gunichar *sequence,
|
||||
int len,
|
||||
const char *value,
|
||||
gpointer data)
|
||||
{
|
||||
GString *str = data;
|
||||
|
||||
for (int j = 0; j < len; j++)
|
||||
g_string_append_printf (str, "<U%x> ", sequence[j]);
|
||||
|
||||
g_string_append (str, ": \"");
|
||||
append_escaped (str, value);
|
||||
g_string_append (str, "\"");
|
||||
|
||||
if (g_utf8_strlen (value, -1) == 1)
|
||||
{
|
||||
gunichar ch = g_utf8_get_char (value);
|
||||
g_string_append_printf (str, " # U%x", ch);
|
||||
}
|
||||
|
||||
g_string_append_c (str, '\n');
|
||||
}
|
||||
|
||||
static char *
|
||||
gtk_compose_table_print (GtkComposeTable *table)
|
||||
{
|
||||
int i, j;
|
||||
guint16 *seq;
|
||||
GString *str;
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
g_string_append_printf (str, "# n_seqs: %d\n# max_seq_len: %d\n",
|
||||
table->n_seqs,
|
||||
table->max_seq_len);
|
||||
g_string_append_printf (str, "# max_seq_len: %d\n# n_index_size: %d\n# data_size: %d\n# n_chars: %d\n",
|
||||
table->max_seq_len,
|
||||
table->n_index_size,
|
||||
table->data_size,
|
||||
table->n_chars);
|
||||
|
||||
for (i = 0, seq = table->data; i < table->n_seqs; i++, seq += table->max_seq_len + 2)
|
||||
#if 0
|
||||
int index_stride = table->max_seq_len + 1;
|
||||
|
||||
for (int idx = 0; idx < table->n_index_size; idx++)
|
||||
{
|
||||
gunichar value;
|
||||
char buf[8] = { 0 };
|
||||
const guint16 *seq_index = table->data + (idx * index_stride);
|
||||
|
||||
for (j = 0; j < table->max_seq_len; j++)
|
||||
g_string_append_printf (str, "<U%x> ", seq[j]);
|
||||
g_print ("<U%x>", seq_index[0]);
|
||||
|
||||
value = (seq[table->max_seq_len] << 16) | seq[table->max_seq_len + 1];
|
||||
if ((value & (1 << 31)) != 0)
|
||||
{
|
||||
const char *out = &table->char_data[value & ~(1 << 31)];
|
||||
|
||||
g_string_append (str, ": \"");
|
||||
append_escaped (str, out);
|
||||
g_string_append (str, "\"\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_unichar_to_utf8 (value, buf);
|
||||
g_string_append_printf (str, ": \"%s\" # U%x\n", buf, value);
|
||||
for (int i = 1; i < index_stride; i++)
|
||||
g_print (" %d", seq_index[i]);
|
||||
g_print ("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
gtk_compose_table_foreach (table, print_sequence, str);
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
@ -80,7 +98,7 @@ generate_output (const char *file)
|
||||
GtkComposeTable *table;
|
||||
char *output;
|
||||
|
||||
table = gtk_compose_table_new_with_file (file);
|
||||
table = gtk_compose_table_parse (file);
|
||||
output = gtk_compose_table_print (table);
|
||||
|
||||
g_print ("%s", output);
|
||||
@ -97,12 +115,12 @@ compose_table_compare (gconstpointer data)
|
||||
char *diff;
|
||||
GError *error = NULL;
|
||||
|
||||
file = g_build_filename (g_test_get_dir (G_TEST_DIST), "compose", basename, NULL);
|
||||
file = g_test_build_filename (G_TEST_DIST, "compose", basename, NULL);
|
||||
expected = g_strconcat (file, ".expected", NULL);
|
||||
|
||||
table = gtk_compose_table_new_with_file (file);
|
||||
|
||||
table = gtk_compose_table_parse (file);
|
||||
output = gtk_compose_table_print (table);
|
||||
|
||||
diff = diff_with_file (expected, output, -1, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
@ -125,9 +143,9 @@ compose_table_cycle (void)
|
||||
char *file;
|
||||
GtkComposeTable *table;
|
||||
|
||||
file = g_build_filename (g_test_get_dir (G_TEST_DIST), "compose", "cycle", NULL);
|
||||
file = g_test_build_filename (G_TEST_DIST, "compose", "cycle", NULL);
|
||||
|
||||
table = gtk_compose_table_new_with_file (file);
|
||||
table = gtk_compose_table_parse (file);
|
||||
g_assert_nonnull (table);
|
||||
g_free (file);
|
||||
|
||||
@ -149,7 +167,7 @@ compose_table_nofile (void)
|
||||
|
||||
file = g_build_filename (g_test_get_dir (G_TEST_DIST), "compose", "nofile", NULL);
|
||||
|
||||
table = gtk_compose_table_new_with_file (file);
|
||||
table = gtk_compose_table_parse (file);
|
||||
g_assert_nonnull (table);
|
||||
g_free (file);
|
||||
|
||||
@ -175,7 +193,7 @@ compose_table_match (void)
|
||||
|
||||
file = g_build_filename (g_test_get_dir (G_TEST_DIST), "compose", "match", NULL);
|
||||
|
||||
table = gtk_compose_table_new_with_file (file);
|
||||
table = gtk_compose_table_parse (file);
|
||||
|
||||
buffer[0] = GDK_KEY_Multi_key;
|
||||
buffer[1] = 0;
|
||||
@ -229,39 +247,38 @@ compose_table_match (void)
|
||||
g_free (file);
|
||||
}
|
||||
|
||||
extern const GtkComposeTable builtin_compose_table;
|
||||
|
||||
/* just check some random sequences */
|
||||
static void
|
||||
compose_table_match_compact (void)
|
||||
compose_table_match_builtin (void)
|
||||
{
|
||||
const GtkComposeTableCompact table = {
|
||||
gtk_compose_seqs_compact,
|
||||
5,
|
||||
30,
|
||||
6
|
||||
};
|
||||
const GtkComposeTable *table = &builtin_compose_table;
|
||||
guint16 buffer[8] = { 0, };
|
||||
gboolean finish, match, ret;
|
||||
gunichar ch;
|
||||
GString *s;
|
||||
|
||||
buffer[0] = GDK_KEY_Multi_key;
|
||||
buffer[1] = 0;
|
||||
|
||||
ret = gtk_compose_table_compact_check (&table, buffer, 1, &finish, &match, &ch);
|
||||
s = g_string_new ("");
|
||||
|
||||
ret = gtk_compose_table_check (table, buffer, 1, &finish, &match, s);
|
||||
g_assert_true (ret);
|
||||
g_assert_false (finish);
|
||||
g_assert_false (match);
|
||||
g_assert_true (ch == 0);
|
||||
g_assert_true (s->len == 0);
|
||||
|
||||
buffer[0] = GDK_KEY_a;
|
||||
buffer[1] = GDK_KEY_b;
|
||||
buffer[2] = GDK_KEY_c;
|
||||
buffer[3] = 0;
|
||||
|
||||
ret = gtk_compose_table_compact_check (&table, buffer, 3, &finish, &match, &ch);
|
||||
ret = gtk_compose_table_check (table, buffer, 3, &finish, &match, s);
|
||||
g_assert_false (ret);
|
||||
g_assert_false (finish);
|
||||
g_assert_false (match);
|
||||
g_assert_true (ch == 0);
|
||||
g_assert_true (s->len == 0);
|
||||
|
||||
buffer[0] = GDK_KEY_Multi_key;
|
||||
buffer[1] = GDK_KEY_parenleft;
|
||||
@ -269,31 +286,37 @@ compose_table_match_compact (void)
|
||||
buffer[3] = GDK_KEY_parenright;
|
||||
buffer[4] = 0;
|
||||
|
||||
ret = gtk_compose_table_compact_check (&table, buffer, 4, &finish, &match, &ch);
|
||||
ret = gtk_compose_table_check (table, buffer, 4, &finish, &match, s);
|
||||
g_assert_true (ret);
|
||||
g_assert_true (finish);
|
||||
g_assert_true (match);
|
||||
g_assert_true (ch == 0x24d9); /* CIRCLED LATIN SMALL LETTER J */
|
||||
g_assert_cmpstr (s->str, ==, "ⓙ"); /* CIRCLED LATIN SMALL LETTER J */
|
||||
|
||||
buffer[0] = GDK_KEY_dead_acute;
|
||||
buffer[1] = GDK_KEY_space;
|
||||
buffer[2] = 0;
|
||||
|
||||
ret = gtk_compose_table_compact_check (&table, buffer, 2, &finish, &match, &ch);
|
||||
g_string_set_size (s, 0);
|
||||
|
||||
ret = gtk_compose_table_check (table, buffer, 2, &finish, &match, s);
|
||||
g_assert_true (ret);
|
||||
g_assert_true (finish);
|
||||
g_assert_true (match);
|
||||
g_assert_true (ch == 0x27);
|
||||
g_assert_cmpstr (s->str, ==, "'");
|
||||
|
||||
buffer[0] = GDK_KEY_dead_acute;
|
||||
buffer[1] = GDK_KEY_dead_acute;
|
||||
buffer[2] = 0;
|
||||
|
||||
ret = gtk_compose_table_compact_check (&table, buffer, 2, &finish, &match, &ch);
|
||||
g_string_set_size (s, 0);
|
||||
|
||||
ret = gtk_compose_table_check (table, buffer, 2, &finish, &match, s);
|
||||
g_assert_true (ret);
|
||||
g_assert_true (finish);
|
||||
g_assert_true (match);
|
||||
g_assert_true (ch == 0xb4);
|
||||
g_assert_cmpstr (s->str, ==, "´");
|
||||
|
||||
g_string_free (s, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -381,16 +404,16 @@ match_algorithmic (void)
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
char *dir;
|
||||
|
||||
g_setenv ("LC_ALL", "en_US.UTF-8", TRUE);
|
||||
dir = g_dir_make_tmp ("composetableXXXXXX", NULL);
|
||||
g_setenv ("XDG_CACHE_HOME", dir, TRUE);
|
||||
g_free (dir);
|
||||
|
||||
if (argc == 3 && strcmp (argv[1], "--generate") == 0)
|
||||
{
|
||||
setlocale (LC_ALL, "");
|
||||
gtk_disable_setlocale();
|
||||
setlocale (LC_ALL, "en_US.UTF-8");
|
||||
|
||||
gtk_init ();
|
||||
|
||||
/* Ensure that the builtin table is initialized */
|
||||
GtkIMContext *ctx = gtk_im_context_simple_new ();
|
||||
g_object_unref (ctx);
|
||||
|
||||
generate_output (argv[2]);
|
||||
return 0;
|
||||
@ -398,6 +421,10 @@ main (int argc, char *argv[])
|
||||
|
||||
gtk_test_init (&argc, &argv, NULL);
|
||||
|
||||
/* Ensure that the builtin table is initialized */
|
||||
GtkIMContext *ctx = gtk_im_context_simple_new ();
|
||||
g_object_unref (ctx);
|
||||
|
||||
g_test_add_data_func ("/compose-table/basic", "basic", compose_table_compare);
|
||||
g_test_add_data_func ("/compose-table/long", "long", compose_table_compare);
|
||||
g_test_add_data_func ("/compose-table/octal", "octal", compose_table_compare);
|
||||
@ -410,7 +437,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/compose-table/include-cycle", compose_table_cycle);
|
||||
g_test_add_func ("/compose-table/include-nofile", compose_table_nofile);
|
||||
g_test_add_func ("/compose-table/match", compose_table_match);
|
||||
g_test_add_func ("/compose-table/match-compact", compose_table_match_compact);
|
||||
g_test_add_func ("/compose-table/match-builtin", compose_table_match_builtin);
|
||||
g_test_add_func ("/compose-table/match-algorithmic", match_algorithmic);
|
||||
|
||||
return g_test_run ();
|
||||
|
Loading…
Reference in New Issue
Block a user