+}
+
+set last_ht {}
+
+proc helptext {t} {
+ global last_ht
+ if {![string compare $t $last_ht]} return
+ eval destroy [grid slaves .help]
+ set y 0; foreach l $t {
+ set x 0; foreach c $l {
+ set w .help.at${x}x${y}
+ label $w -text $c
+ grid $w -row $y -column $x -padx 5
+ incr x
+ }
+ incr y
+ }
+ set last_ht $t
+}
+
+proc bind_key {k proc} {
+ global keybindings
+ bind . <Key-$k> $proc
+ set keybindings($k) [expr {!![string length $proc]}]
+}
+proc unbind_all_keys {} {
+ global keybindings
+ foreach k [array names keybindings] { bind_key $k {} }
+}
+
+#---------- database read and write common wrapper ----------
+
+proc db_getsl {f} {
+ if {[gets $f l] < 0} { error "unexpected db eof" }
+ return $l
+}
+
+proc read_database {fn} {
+ global reqkind database database_fn
+ upvar #0 database_magic/$reqkind magic
+ catch { unset database }
+
+ set database_fn $fn
+ if {![file exists $database_fn]} return
+ set f [open $database_fn r]
+ if {[string compare [db_getsl $f] $magic]} { error "$l $reqkind ?" }
+
+ read_database_header/$reqkind $f
+ while 1 {
+ set l1 [db_getsl $f]
+
+ if {![string length $l1]} continue
+ if {[regexp {^\#} $l1]} continue
+ if {![string compare . $l1]} break
+
+ read_database_entry/$reqkind $f $l1
+ }
+ close $f
+}
+
+proc write_database {} {
+ global reqkind database_fn database
+ upvar #0 database_magic/$reqkind magic
+
+ set f [open $database_fn.new w]
+ puts $f $magic
+
+ write_database_header/$reqkind $f
+
+ set ol {}
+ foreach bm [array names database] {
+ lappend ol [format_database_entry/$reqkind $bm $database($bm)]
+ }
+ foreach o [lsort $ol] {
+ puts $f $o
+ }
+ puts $f "."
+ close $f
+ file rename -force $database_fn.new $database_fn
+}
+
+proc required/char {} {
+ global mulrows glyphsdone unk_l unk_r unk_contexts rows
+
+ must_gets stdin l
+
+ manyset [lrange $l 0 3] unk_l unk_r unk_contexts
+ set glyphsdone [lrange $l 3 end]
+ debug "GOT $l"