chiark / gitweb /
wip show-thing rework
[ypp-sc-tools.web-live.git] / pctb / stuff / show-thing.tcl
1 #!/usr/bin/tk
2
3 proc manyset {list args} {
4     foreach val $list var $args {
5         upvar 1 $var my
6         set my $val
7     }
8 }
9
10 set mul 6
11 set inter 1
12 set rhsmost_max -1
13
14 proc read_xpm {f} {
15     set o {}
16     set y -3
17     while {[gets $f l] >= 0} {
18         if {![regexp {^"(.*)",$} $l dummy l]} {
19             append o "$l\n"
20             continue
21         }
22         if {$y==-3} {
23             manyset $l cols rows colours cpp
24             #assert {$colours==2}
25             #assert {$cpp==1}
26             set mulcols [expr {$cols*$mul+$inter}]
27             set mulrows [expr {$rows*$mul+$inter}]
28             append o "\"$mulcols $mulrows 9 1\",\n"
29             for {set x 0} {$x<$cols} {incr x} { set wordmap($x) 0 }
30         } elseif {$y==-2} { # first pixel
31             append o \
32 "\"+ c #111\",
33 \"a c #800\",
34 \"A c #fcc\",
35 \"b c #00c\",
36 \"B c #fff\",
37 \"u c #000\",
38 \"U c #ff0\",
39 \"q c #000\",
40 \"Q c #ff0\",\n"
41         } elseif {$y==-1} { # 2nd pixel but we've already printed ours
42         } else {
43             set ybit [expr {1<<$y}]
44             set x 0
45             set ol "\"+"
46             set olh $ol
47             foreach c [split $l ""] {
48                 set how "u"
49                 if {$x >= $unk_l && $x <= $unk_r} {
50                     set how q
51                 } else {
52                     set ab 0
53                     foreach {min max context got} $foolist {
54                         set rhsmost_max $max
55                         if {$x >= $min && $x <= $max} {
56                             set how [lindex {a b} $ab]
57                             break
58                         }
59                         set ab [expr {!$ab}]
60                     }
61                 }
62                 switch -exact $c {
63                     " " { set p $how }
64                     "o" {
65                         set p [string toupper $how]
66                         incr wordmap($x) $ybit
67                     }
68                     default { error "$c ?" }
69                 }
70                 append ol "[string repeat $p [expr {$mul-$inter}]][
71                          string repeat + $inter]"
72                 append olh [string repeat + $mul]
73                 incr x
74             }
75             set ole "\",\n"
76             append ol $ole
77             append olh $ole
78             set olhn [string repeat $olh $inter]
79             if {!$y} { append o $olhn }
80             append o [string repeat $ol [expr {$mul-1}]]
81             append o $olhn
82         }
83         incr y
84     }
85     set data [exec xpmtoppm << $o]
86     image create photo main_image -data $xpm
87 }
88
89 #puts $o
90
91 set gotsh 20
92 set csrh 20
93
94 frame .d -width $mulcols -height [expr {$csrh+$mulrows+$gotsh}]
95
96 set mi main_image
97 image create bitmap main_image
98 label .d.mi -image $mi -borderwidth 0
99
100 frame .d.csr -bg black -width $mulcols -height $csrh
101 frame .d.got -bg black -width $mulcols -height $gotsh
102
103 foreach {min max context got} $foolist {
104     frame .d.got.m$min -bd 0 -background \#888
105     label .d.got.m$min.l -text "$got" -fg white -bg black -bd 0
106     pack .d.got.m$min.l -padx 1 -pady 1
107     place .d.got.m$min -x [expr {$min*$mul+$inter}] -y 0
108 }
109
110 set imcsr [image create bitmap -data \
111 {#define csr_width 11
112 #define csr_height 11
113 static unsigned char csr_bits[] = {
114    0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x21, 0x04, 0x22, 0x02, 0x25, 0x05,
115    0xaa, 0x02, 0x74, 0x01, 0xa8, 0x00, 0x70, 0x00, 0x20, 0x00};
116 }]
117
118 frame .d.csr.csr
119 label .d.csr.csr.l -image $imcsr -compound left
120 entry .d.csr.csr.e -bd 0
121 pack .d.csr.csr.l -side left
122
123 frame .d.csr_0 -bg white -height $mulrows -width 1
124 frame .d.csr_1 -bg white -height $mulrows -width 1
125
126 place .d.csr -x 0 -y 0
127 place .d.mi -x 0 -y $csrh
128 place .d.got -x 0 -y [expr {$csrh+$mulrows}]
129 pack .d
130
131 frame .help
132 pack .help
133
134 set cur_already [expr {[llength $foolist]/4-1}]
135 set cur_mode 1 ;# one of:   0 1 already text
136
137 set cur_0 $unk_l
138 set cur_1 [expr {$unk_r+1}]
139 set last_ht {}
140
141 proc helptext {t} {
142     global last_ht
143     if {![string compare $t $last_ht]} return
144     eval destroy [grid slaves .help]
145     set y 0; foreach l $t {
146         set x 0; foreach c $l {
147             set w .help.at${x}x${y}
148             label $w -text $c
149             grid $w -row $y -column $x -padx 5
150             incr x
151         }
152         incr y
153     }
154     set last_ht $t
155 }
156
157 proc recursor/0 {} { recursor//01 0 }
158 proc recursor/1 {} { recursor//01 1 }
159 proc recursor//01 {z1} {
160     global mul rhsmost_max cols foolist
161     upvar #0 cur_$z1 cur
162     .d.csr.csr.l configure -text {adjust}
163     place .d.csr.csr -x [expr {$cur*$mul - 7}]
164     bind_key space { othercursor }
165     bind_leftright cur_$z1 0 [expr {$cols-1}]
166     if {[llength $foolist]} {
167         bind_key Tab { set cur_mode already; recursor }
168     } else {
169         bind_key Tab {}
170     }
171     bind_key Return {
172         if {$cur_0 != $cur_1} {
173             set cur_mode text
174             recursor
175         }
176     }
177     helptext {
178         {{<- ->}   {move cursor, adjusting area to define}}
179         {Space     {switch to moving other cursor}}
180         {Return    {confirm location, enter letter(s)}}
181         {Tab       {switch to correcting earlier ocr}}
182     }
183 }
184 proc othercursor {} {
185     global cur_mode
186     set cur_mode [expr {!$cur_mode}]
187     recursor
188 }
189
190 proc recursor/text {} {
191     helptext {
192         {Return   {confirm entry of new glyph}}
193         {Escape   {abandon entry}}
194     }
195     unbind_all_keys
196     .d.csr.csr.l configure -text {define:}
197     pack .d.csr.csr.e -side left
198     focus .d.csr.csr.e
199     bind_key Return {
200         binary scan [.d.csr.csr.e get] h* hex
201         if {[string length $hex]} {
202             RETURN_RESULT DEFINE "$cur_0 $cur_1 $hex"
203         }
204     }
205     bind_key Escape {
206         bind_key Escape {}
207         pack forget .d.csr.csr.e
208         set cur_mode 1
209         recursor
210     }
211 }
212
213 proc recursor/already {} {
214     global mul
215     global foolist
216     global cur_already mul
217     global foolist cur_already mul
218     .d.csr.csr.l configure -text {correct}
219     set rmax [lindex $foolist [expr {$cur_already*4}]]
220     place .d.csr.csr -x [expr {$rmax*$mul-3}]
221     bind_key Return {}
222     bind_key space {}
223     bind_leftright cur_already 0 [expr {[llength $foolist]/4-1}]
224     bind_key Tab { bind_key Delete {}; set cur_mode 1; recursor }
225     bind_key Delete {
226         RETURN_RESULT DELETE [lrange $foolist \
227                                   [expr $cur_already*4] \
228                                   [expr $cur_already*4+1]]
229     }
230     helptext {
231         {{<- ->}   {move cursor, selecting glyph to correct}}
232         {Del       {clear this glyph from the recognition database}}
233         {Tab       {switch to selecting area to define as new glyph}}
234     }
235 }
236
237 proc bind_key {k proc} {
238     global keybindings
239     bind . <Key-$k> $proc
240     set keybindings($k) [expr {!![string length $proc]}]
241 }
242 proc unbind_all_keys {} {
243     global keybindings
244     foreach k [array names keybindings] { bind_key $k {} }
245 }
246
247 proc bind_leftright {var min max} {
248     bind_key Left  [list leftright $var $min $max -1]
249     bind_key Right [list leftright $var $min $max +1]
250 }
251 proc leftright {var min max inc} {
252     upvar #0 $var v
253     set vnew $v
254     incr vnew $inc
255     if {$vnew < $min || $vnew > $max} return
256     set v $vnew
257     recursor
258 }
259
260 proc recursor {} {
261     global csrh cur_mode cur_0 cur_1 mul
262     foreach z1 {0 1} {
263         place .d.csr_$z1 -y $csrh -x [expr {[set cur_$z1] * $mul}]
264     }
265     recursor/$cur_mode
266 }
267
268
269 # database format:
270 # series of glyphs:
271 #   <context> <ncharacters> <hex>...
272 #   width
273 #   <hex-bitmap>
274
275 # $database($context 0x<bits> 0x<bits>...) = $hex
276
277 proc read_database {} {
278     global database
279     set f [open database r]
280     while {[gets $f l] >= 0} {
281         if {![regexp {^(\w+) (\d+) ([0-9a-f]{2}+)$} $l \
282                   dummy context strl strh]} {
283             error "bad syntax"
284         }
285         binary scan $strw h* strh
286         if {[string length $strh] != $strl*2} { error "$strh $strl" }
287         gets $f l; set width [format %d $l]
288         set bm $context
289         for {set x 0} {$x < $width} {incr x} {
290             gets $f l; lappend bm [format %x 0x$l]
291         }
292         set database($bm) $strh
293     }
294 }
295
296 proc write_database {} {
297     global database
298     set ol {}
299     foreach bm [array names database] {
300         set strh $database($bm)
301         set strs [binary format h* $strh]
302         set strdo [format "%d %s" [expr {[string length $strh]/2}] $strh]
303         set o "[lindex $bm 0] $strdo\n"
304         append o [format "%d\n" [expr {[llength $bm]-1}]]
305         foreach x [lrange $bm 1 end] { append o "$x\n" }
306         lappend ol $o
307     }
308     foreach o [lsort $ol] {
309         puts -nonewline $o
310     }
311 }
312
313 proc update_database/DEFINE {c0 c1 strh} {
314     global foolist unk_l unk_context wordmap database
315     if {$c0 > $c1} { manyset [list $c0 $c1] c1 c0 }
316     if {$c0 == $unk_l} {
317         set ncontext $unk_context
318     } else {
319         foreach {l r context got} $foolist {
320             if {$l==$c0} { set ncontext $context; break }
321         }
322         if {![exists ncontext]} {
323             puts stderr "must start at letter LHS!"
324             return
325         }
326     }
327     set bm $ncontext
328     for {set x $c0} {$x < $c1} {incr x} {
329         lappend bm [format %x $wordmap($x)]
330     }
331     set database($bm) $strh
332     write_database
333 }
334     
335
336 proc RETURN_RESULT {how what} {
337     place forget .d.csr.csr
338     pack forget .d.csr.csr.e
339     helptext {{{ Processing }}}
340     unbind_all_keys
341     update idletasks
342     puts "$how $what"
343     eval update_database/$how $what
344 }
345
346 #    bind . <Key-space> {}
347
348 proc test_main {} {
349     global foolist
350     
351     set foolist {
352         7 11 1 M
353         13 17 0 a
354         19 23 0 n
355     }
356     set unk_l 25
357     set unk_r 29
358     set unk_context 0
359
360     set f [open text.xpm]
361     read_xpm $f
362     close $f
363
364     read_database
365     recursor
366 }