Version 2 of A tiny input manager

Updated 2002-03-19 09:51:24

Richard Suchenwirth - A Python user from Latvia asked how to make a Tk widget display Cyrillic (Russian) characters when typed into with a normal Latin (English) keyboard.

This is related to the more general problem of so-called "input managers", software that maps keyboard input to widget output in a not exactly trivial way. For each platform, there are existing solutions, but we don't have a generalized approach in Tk yet. So here comes my tiny "Tk input manager", or briefly tim, which does first steps into that direction.

As required, the first application is for Cyrillic; but the principle is clear enough to add other mappings with little effort (for a mapping foo, add a proc foo and a setupfoo). One problem is that the Cyrillic alphabet contains more than the 26 [A-Z] characters of the Latin one, so a sort-of "dead key" approach had to be taken. In the sketch below, I disable the exclamation mark, but use it in the beginning of two-character sequences that produce one Cyrillic character each (see Ruslish for a discussion of this approach). To get one real exclamation mark, add an extra space behind it (thanks to rmax for that tip!)

The widgets (text or entry - as both accept the insert insert method) created with the prefix tim::Russian get the Russian bindings prepended to their bindtags list; besides, they inherit everything from the original widgets.

A real input manager needs of course some more work. For example, allow toggling the keyboard encoding at runtime; display the current scheme, etc. Most challenging however is the extension to writing systems with a large character set: Chinese, Japanese, Korean... See taiku goes multilingual }

 namespace eval tim {
        proc Russian {type w args} {makeit Russian $type $w $args}

        proc makeit {name type w argl} {
                variable know
                if ![info exists know($name)] {setup$name} 
                eval $type $w $argl
                bindtags $w [concat $name [bindtags $w]]
                set w
        }
        proc setupRussian {} {
                variable know; set know(Russian) 1
                foreach {in out} {
                    ! "{}" !<space> !
            A  \u0410 B  \u0411 V  \u0412 G \u0413 D \u0414 E \u0415
            !Z \u0416 Z  \u0417 I  \u0418 J \u0419 K \u041A L \u041b
            M  \u041c N  \u041d O  \u041e P \u041f R \u0420 S \u0421
            T  \u0422 U  \u0423 F  \u0424 X \u0425 C \u0426 !C \u0427
            !S \u0428 !T \u0429 Q  \u042a Y \u042b H \u042c !E \u042d
            !U \u042e !A \u042F !O \u0401
            a  \u0430 b  \u0431 v  \u0432 g \u0433 d \u0434 e \u0435
            !z \u0436 z  \u0437 i  \u0438 j \u0439 k \u043a l \u043b
            m  \u043c n  \u043d o  \u043e p \u043f r \u0440 s \u0441
            t  \u0442 u  \u0443 f  \u0444 x \u0445 c \u0446 !c \u0447
            !s \u0448 !t \u0449 q  \u044a y \u044b h \u044c !e \u044d
            !u \u044e !a \u044f !o \u0451

                } {bind Russian $in "%W insert insert $out; break"}
        }
 }
 #------------------------------- demo and test code, usage examples
 # Hint: type in e.g. "Moskva i Leningrad - dva gorody Rossii".
 # or: "!A ne zna!u nicevo, a ne ponema!u nicevo."

 tim::Russian entry .e
 tim::Russian text .t
 eval pack [winfo children .] -fill x

i18n - writing for the world - Arts and crafts of Tcl-tk programming