All underline handling in [Tk] standard dialogs is now done with "magic ampersands". [[As of which version?]] [[What [TIP] discusses this?]] [[The [TCT] did not require a TIP because it is internal to Tk - seems like it might/would impact widget writers or people developing extensions or modifications to Tk though - so in some people's opinion, it ''SHOULD'' have been TIPed.]] The experts in this are [A/AK] and [DKF]. The latter has explained, "'Ampersand magic' is a way of encoding the character to underline in a button, label, menu etc. in the string. It is easiest to see how it works by looking at an example: If the string to show is 'Save As...' and the letter to underline is the 'A' in 'As...' then the ampersand-magic-ed string is 'Save &As...' If the string to show is 'Quit' and the letter to underline is 'Q', then the ampersand-magic-ed string is '&Quit'. IIRC, this sort of thing came originally from [Windows], and it is rather a good idea because it makes it much easier to set up underlines for labels (where real ampersands tend to be fairly rare), particularly compared with counting characters to get to the right spot. I don't remember the exact details of Tk's implementation but I think it is done through extra procedures and is just used for strings for Tk's standard dialogs coming from the message catalog." ---- [[Bring Anton's example code from "[msgcat and shortcut keys]" here.]] ---- [[But [Perl/Tk] uses '~' in place of '&'? What's going on?]] ''[DKF] writes:'' Tk went with '&' because it is the character used on Windows for this sort of thing. I've no idea why pTk uses '~' even though to me one character is as good as another. ---- [RS] thought the TCT had decided to use the Unicode "non-spacing underline" for this function? The advantage would have been that the hot key could be easily parsed out, while such a string would not have to be modified at all to display the underline - self fulfilling data prophecy... [A/AK]: Unicode "non-spacing underline" seems to be a very good choice. It doesn't matter now, as all this underline machinery is internal to tk. But it would be fine for application programmers; and if(when) non-spacing underline is handled at the [C] level, I will be glad to remove all these ugly ampersand kludges from the script level. ''[DKF]:'' At the moment, it only matters to people working on the core itself or its message catalogs. At such time as we add the unicode magic underline support to Tk (i.e. if it ever happens), we can easily convert the rest of the core to use it. ---- [Ro] coughs up some code: # ::whatUnderlined -- # # # Description # # Finds out what character index to underline from a given label. # The character after the "&" is the one to be underlined. # The first character has index 0. # Only one character can be underlined. # # e.g.: Given "Forma&t" it will return {5 Format} # Given "Edit" it will return {0 Edit} # # Note: If the "&" character is missing, 0 is the index returned. # # # Arguments # # s The label to parse for single character underlining. # # # Results # # Returns two elements in list format, the first is the index of the # character to be underlined, the other is the label to be displayed. # # If no character is to be underlined, the character index # returned is 0, and the label returned is the original given label. # # # Side Effects # # none # # proc ::whatUnderlined {s} { # # Get the index of the "&" character. # set i [string first & $s] # # If there is no "&" character in the label, then return the # index 0 and the original given label. # if {[string equal "-1" $i]} { return [list 0 $s] } # # If there is a "&" character, then return the index of the # explicitely determined character to underline and the display # formatted label. # set s [string replace $s $i $i] return [list $i $s] } ---- ''[MGS]'' [[2003/05/08]] - I think the above code should return -1 instead of 0, if no & is found. I humbly offer my own shortened version: proc amp {s} { set i [string first & $s] return [list $i [string replace $s $i $i]] } ---- [EKB] [[7 Aug 2005]] - Taking [MGS]'s code and extending it a bit so the result can easily be inserted into a menu item: proc menumsg {m} { set s [msgcat::mc $m] ;# Or import msgcat::mc and use [mc $m] set i [string first & $s] set retval "-label \{[string replace $s $i $i]\}" if {$i != -1} { set retval "$retval -underline $i" } return $retval ;# RS added a $'s worth of improvement :) } Thanks, [RS]! And I fixed up a couple of other things as well... Then if a string is in a [message catalog], it can be put into a call to menu as: eval menupath add command [menumsg mymsg] -command {...} ... ---- [MGS] [[2005/08/08]] I think this is slightly tidier (no worries about passing back -underline -1): proc menulabel {string {char &}} { set s [msgcat::mc $string] set i [string first $char $s] return [list -label [string replace $s $i $i] -underline $i] } Then you can do: menu .menu . configure -menu .menu set s "Save &As ..." eval [list .menu add command] [menulabel $s] ---- [Category Human Language] | [Category GUI] | [Category Word and Text Processing]