From d47868ef1f0694a34efe01dcb75880c15bc5abbb Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sun, 23 Nov 2008 01:54:47 +0100 Subject: [PATCH] Fully parse KLC files Actually some sections are skipped altogether, but at least we know exactly where they begin and end. --- klc2xkb | 95 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 21 deletions(-) diff --git a/klc2xkb b/klc2xkb index 426f728..02343e3 100755 --- a/klc2xkb +++ b/klc2xkb @@ -117,46 +117,99 @@ class MSKLCFile(object): self.filename = filename self.mappings = [] self.deadkeys = [] + self.metadata = {} + self.shiftmap = [] self.parse() def parse(self): with codecs.open(self.filename, 'r', encoding='utf-16') as file: - in_deadkey_def = False + state = None for line in file: + line, sep, comment = line.partition('//') line = line.strip() + comment = comment.strip() - if in_deadkey_def: + if line == '': + continue + + if state == 'shiftstate': + try: + shift = int(line) + self.shiftmap.append([shift, shift in [0, 1, 6, 7]]) + continue + except ValueError: + state = None + elif state == 'layout': + pieces = line.split() + if len(pieces) == len(self.shiftmap)+3: + self.parse_layout_line(pieces) + continue + else: + state = None + elif state in ['keyname', 'keyname_ext', 'keyname_dead', 'descriptions', 'languagenames']: + try: + hex, key = line.split("\t", 1) + hex = int(hex, 16) + continue + except ValueError: + state = None + elif state == 'deadkey': match = re.match(r"""^([0-9a-fA-F]{4})\s+ - ([0-9a-fA-F]{4})\s+ - // - |\s?$""", + ([0-9a-fA-F]{4})$""", line, re.VERBOSE) if not match: - in_deadkey_def = False + state = None else: if match.group(1): self.deadkeys[-1].add_entry(match.group(1), match.group(2)) continue - - match = re.match(r'^DEADKEY\s+([0-9a-fA-F]{4})$', line) - if match: - in_deadkey_def = True - self.deadkeys.append(DeadKey(match.group(1))) - - match = re.match('(.*?)//', line) - if match: - pieces = match.group().split() - if len(pieces) == 9: - self.parse_layout_line(pieces) + elif state != None: + print line + raise KeyError + + key, sep, arg = line.partition("\t") + if not key.isupper(): + print line + raise KeyError + key = key.lower() + if key == 'kbd': + self.metadata['layout'], sep, quoted = arg.partition("\t") + self.metadata['name'] = quoted[1:-1] + elif key in ['copyright', 'company', 'version']: + self.metadata['key'] = arg[1:-1] + elif key in ['localename', 'localeid']: + continue + elif key in ['shiftstate', 'layout', 'keyname', 'keyname_ext', 'keyname_dead', 'descriptions', 'languagenames']: + state = key + elif key == 'deadkey': + state = key + self.deadkeys.append(DeadKey(arg)) + elif key == 'endkbd': + break + else: + print line + raise KeyError def parse_layout_line(self, pieces): - scancode, vk, cap, normal, shift, ctrl, altgr, shiftaltgr, junk = \ - pieces - scancode = int(scancode, 16) - mapping = KeyMapping(scancode, normal, shift, altgr, shiftaltgr) + scancode = int(pieces[0], 16) + vk = pieces[1] + cap = pieces[2] + valid = ['-1','-1','-1','-1'] + for i in range(3, len(pieces)): + shift, good = self.shiftmap[i-3] + if good: + valid[shift % 4] = pieces[i] + elif pieces[i] != '-1': + print >> sys.stderr, "skipping %(pc)s at position %(pos)u (shiftstate %(ss)u) for %(key)s" % { + 'pc': pieces[i], + 'pos': i, + 'ss': shift, + 'key': pieces[0] + } + mapping = KeyMapping(scancode, *valid) self.mappings.append(mapping) def main(args=None): -- 2.32.0.93.g670b81a890