@@ -113,11 +113,13 @@ def click(x, y)
113113
114114 # Paint the boxes
115115 def repaint ( width : @con . winsize [ 1 ] , height : @con . winsize [ 0 ] )
116+ headroom = headline . size > 0 ? ( headline . size + width - 1 ) / width : 0 # roughly
116117 obw = ( width . to_f / @ncols ) . floor
117118 spw = obw - 4
118119 nrows = ( @boxes . size . to_f / @ncols ) . ceil
119- obh = ( height . to_f / nrows ) . floor
120+ obh = ( ( height - headroom ) . to_f / nrows ) . floor
120121 sph = obh - 2
122+ sph = 1 if sph < 1
121123 line = +""
122124 slines = [ [ ] ]
123125 nrows . times do |nrow |
@@ -140,6 +142,8 @@ def repaint(width: @con.winsize[1], height: @con.winsize[0])
140142 text_line ||= ""
141143 spl = ( spw - text_line . size ) / 2
142144 spr = spw - spl - text_line . size
145+ spl = 0 if spl < 0
146+ spr = 0 if spr < 0
143147 line += " #{ border [ 3 ] } " + " " * spl + text_line + " " * spr + "#{ border [ 5 ] } "
144148 slines . last . append ( *( [ box_idx ] * obw ) )
145149 end
@@ -157,7 +161,9 @@ def repaint(width: @con.winsize[1], height: @con.winsize[0])
157161 line += "\n "
158162 slines << [ ]
159163 end
160- print "\n #{ headline } \n " +line . chomp
164+ @con . write "\e [H" "\e [J"
165+ print "#{ headline } "
166+ print @con . cursor . last == 0 ? line . chomp : "\n #{ line . chomp } "
161167 @slines = slines
162168 end
163169 end
@@ -177,7 +183,9 @@ def initialize
177183 @GetConsoleMode = Win32API . new ( 'kernel32' , 'GetConsoleMode' , [ 'L' , 'P' ] , 'L' )
178184 @SetConsoleMode = Win32API . new ( 'kernel32' , 'SetConsoleMode' , [ 'L' , 'L' ] , 'L' )
179185
186+ @hConsoleHandle = @GetStdHandle . call ( STD_INPUT_HANDLE )
180187 @ev_r , @ev_w = IO . pipe . map ( &:binmode )
188+ @read_request_queue = Thread ::Queue . new
181189
182190 set_consolemode
183191
@@ -189,8 +197,11 @@ def initialize
189197 end
190198 end
191199
200+ def clear_screen
201+ IO . console . write "\e [H" "\e [2J"
202+ end
203+
192204 def set_consolemode
193- @hConsoleHandle = @GetStdHandle . call ( STD_INPUT_HANDLE )
194205 @base_console_input_mode = getconsolemode
195206 setconsolemode ( ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS | ENABLE_VIRTUAL_TERMINAL_INPUT )
196207 end
@@ -253,21 +264,27 @@ def unset_consolemode
253264 private def register_stdin
254265 Thread . new do
255266 str = +""
267+ @read_request_queue . shift
256268 c = IO . console
257269 while char = c . read ( 1 )
258270 str << char
259271 next if !str . valid_encoding? ||
260272 str == "\e " ||
261273 str == "\e [" ||
262274 str == "\xE0 " ||
263- str . match ( /\A \e \x5b <[^Mm ]*\z / )
275+ str . match ( /\A \e \x5b <[0-9; ]*\z / )
264276
265277 @ev_w . write [ 2 , str . size , str ] . pack ( "CCa*" )
266278 str = +""
279+ @read_request_queue . shift
267280 end
268281 end
269282 end
270283
284+ private def request_read
285+ @read_request_queue . push true
286+ end
287+
271288 private def handle_key_input ( str )
272289 case str
273290 when "\e [D" , "\xE0 K" . b # cursor left
@@ -289,12 +306,15 @@ def unset_consolemode
289306 widget . select
290307 end
291308 end
309+ when /\e \x5b <\d +;(\d +);(\d +)[Mm]/ # other mouse events
310+ return # no repaint
292311 end
293312 widget . repaint
294313 end
295314
296315 private def main_loop
297316 str = +""
317+ request_read
298318 while char = @ev_r . read ( 1 )
299319 case char
300320 when "\x01 "
@@ -304,10 +324,10 @@ def unset_consolemode
304324 str = @ev_r . read ( strlen )
305325
306326 handle_key_input ( str )
307- widget . repaint
308327 else
309328 raise "unexpected event: #{ char . inspect } "
310329 end
330+ request_read
311331 end
312332 end
313333
@@ -328,15 +348,19 @@ def run!
328348 end
329349 bm . add_button "text2" do
330350 p :button_2
351+ exit
331352 end
332353 bm . add_button "text3\n abc\n oollla\n text3\n abc\n oollla" do
333354 p :button_3
355+ exit
334356 end
335357 bm . add_button "text4\n def" do
336358 p :button_4
359+ exit
337360 end
338361 bm . add_button "text5\n abc" do
339362 p :button_5
363+ exit
340364 end
341365 app . widget = bm
342366 app . run!
0 commit comments