Updated 2012-01-27 22:22:11 by RLE

Entering text with accented characters can be tedious, because normally under X (Linux) the keyboard uses so-called nodeadkeys. To be able to enter as many accented characters as possible, I developed a little package called deadkeys.

A global variable switch is used to show whether the state of the keyboard has changed, meaning that one of the dead keys has been pressed. You could use this as a textvariable for a label so that its content shows.

If you require this package in any Tk app, you can easily enter accented chars without affecting other programs. There are no side-effects (hopefully).

This package has not been tested on any other environment than Linux + X with a German keyboard.
  package provide deadkeys 1.0
  
  # list of classes to be applied to
  set classes [list Text Entry]
  
  foreach class $classes {
    bind $class <KeyPress-acute> {
      if {$switch == ""} {
        set switch "acute"
      } else {
        set switch ""
      } ;# if
      break
    } ;# bind
    
    bind $class <KeyPress-grave> {
      if {$switch == ""} {
        set switch "grave"
      } else {
        set switch ""
      } ;# if
      break
    } ;# bind
    
    bind $class <KeyPress-asciicircum> {
      if {$switch == ""} {
        set switch "circum"
      } else {
        set switch ""
      } ;# if
      break
    } ;# bind
    
    bind $class <KeyPress-degree> {
      if {$switch == ""} {
        set switch "degree"
      } else {
        set switch ""
      } ;# if
      break
    } ;# bind
    
    bind $class <KeyPress-plus> {
      if {"%A" == "~"} {
        if {$switch == ""} {
          set switch "tilde"
        } else {
          set switch ""
        } ;# if
      } ;# if
      break
    } ;# bind
    
    bind $class <Key> {
      if {$switch != "" && "%A" != "{}"} {
        set ch   "%A"
        set i_ch "%A"
        if {$switch == "acute"} {
          switch %A {
            " " {set i_ch "\u00b4"}
            a  {set i_ch "\u00e1"}
            A  {set i_ch "\u00c1"}
            e  {set i_ch "\u00e9"}
            E  {set i_ch "\u00c9"}
            i  {set i_ch "\u00ed"}
            I  {set i_ch "\u00cd"}
            o  {set i_ch "\u00f3"}
            O  {set i_ch "\u00d3"}
            u  {set i_ch "\u00fa"}
            U  {set i_ch "\u00da"}
            c  {set i_ch "\u0107"}
            C  {set i_ch "\u0106"}
            n  {set i_ch "\u0144"}
            N  {set i_ch "\u0143"}
            l  {set i_ch "\u013A"}
            L  {set i_ch "\u0139"}
            s  {set i_ch "\u015B"}
            S  {set i_ch "\u015A"}
            r  {set i_ch "\u0155"}
            R  {set i_ch "\u0154"}
            z  {set i_ch "\u017A"}
            Z  {set i_ch "\u0179"}
          } ;# switch
        } elseif {$switch == "grave"} {
          switch %A {
            " " {set i_ch "\u0060"}
            a  {set i_ch "\u00e0"}
            A  {set i_ch "\u00c0"}
            e  {set i_ch "\u00e8"}
            E  {set i_ch "\u00c8"}
            i  {set i_ch "\u00ec"}
            I  {set i_ch "\u00cc"}
            o  {set i_ch "\u00f2"}
            O  {set i_ch "\u00d2"}
            u  {set i_ch "\u00f9"}
            U  {set i_ch "\u00d9"}
          } ;# switch
        } elseif {$switch == "circum"} {
          switch %A {
            " " {set i_ch "^"}
            a  {set i_ch "\u00e2"}
            A  {set i_ch "\u00c2"}
            e  {set i_ch "\u00ea"}
            E  {set i_ch "\u00ca"}
            i  {set i_ch "\u00ee"}
            I  {set i_ch "\u00ce"}
            o  {set i_ch "\u00f4"}
            O  {set i_ch "\u00d4"}
            u  {set i_ch "\u00fb"}
            U  {set i_ch "\u00db"}
            w  {set i_ch "\u0175"}
            W  {set i_ch "\u0174"}
            z  {set i_ch "\u0177"}
            Z  {set i_ch "\u0176"}
            c  {set i_ch "\u00E7"}
            C  {set i_ch "\u00C7"}
            s  {set i_ch "\u015F"}
            S  {set i_ch "\u015E"}
            g  {set i_ch "\u011F"}
            G  {set i_ch "\u011E"}
          } ;# switch
        } elseif {$switch == "degree"} {
          switch %A {
            " " {set i_ch "\u00b0"}
            a  {set i_ch "\u00e5"}
            A  {set i_ch "\u00c5"}
            i  {set i_ch "\u0131"}
            I  {set i_ch "\u0130"}
            u  {set i_ch "\u016F"}
            U  {set i_ch "\u016E"}
          } ;# switch
        } elseif {$switch == "tilde"} {
          switch %A {
            " " {set i_ch "\u007e"}
            a  {set i_ch "\u00e3"}
            A  {set i_ch "\u00c3"}
            i  {set i_ch "\u0131"}
            I  {set i_ch "\u0130"}
            o  {set i_ch "\u00f5"}
            O  {set i_ch "\u00d5"}
            u  {set i_ch "\u0169"}
            U  {set i_ch "\u0168"}
            n  {set i_ch "\u00f1"}
            N  {set i_ch "\u00d1"}
          } ;# switch
        } ;# if
        if {$ch == " " || $ch >= {a} && $ch <= {z} || $ch >= {A} && $ch <= {Z}} {
          %W insert insert "$i_ch"
          set switch ""
          break
        } else {
          tk_messageBox -message "out of range"
        } ;# if
      } else {
        %W insert insert %A
      } ;# if
    } ;# bind
  } ;# foreach class

I added some bindings which can be very helpful especially for Turkish users. Using the ring accent on i gives a dotless i, ring accent on I gives a capital I with a dot, using the ring accent on a g/G gives the same character in its soft variation (yumusak g), using a circumflex on s/S gives the same character with a cedille unterneath.

LINKS

Hope this proves to be helpful.

HolgerJ