rufio 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78138156eb9ae86f5a57696e3b0170417da3c7b2c8a2d0dba4af3460efe69ddd
4
- data.tar.gz: b8c184800c8e26955663e0404654e50973407441ac61658511b15fc2bbf6c96f
3
+ metadata.gz: f6a5acef1da176c0bfb0c96f4dacc64e6ab519095b9e282a0c2558ca2594cd34
4
+ data.tar.gz: 5be4e0fe22abcd6d866842ab61436605e940d38d5c3b43f477fc3afea0323413
5
5
  SHA512:
6
- metadata.gz: 572569248e94a4456f20bcbf7a8235b26bbae55aadc24c911ae528ebcb23b08f2cd0ec1cb9f97c6781308b6856e676b4983e42728bd21ae4a21e0820b0eb0e28
7
- data.tar.gz: 65d4deb78ca48dc9e892b63e42bd98827a50d1b0168f7df198957c476696d67999268f4e2021bbc4beb6edad5be96e8acbac6a087bfe5855e25ac63bb23be102
6
+ metadata.gz: 40f7a8c8dc30211dd09ec1c047c2ca52f4f9854020e41e6a56d56d531f84e87dbf920c7f01df213d9d67c4085edf634e7e6b2c924b0b3a8fcb2da3ab56765d54
7
+ data.tar.gz: bc5b4458b71cdd85287f141ea8c8fff2cc66a6ba6a972cca558f1bf6bbd81c6a74a0e46fd1acaf413f2771e4170752fab4bb10838c45791d40c61e76c43c0f89
data/lib/rufio/screen.rb CHANGED
@@ -24,12 +24,16 @@ module Rufio
24
24
  # - Minimal ANSI stripping (only once in put_string)
25
25
  #
26
26
  class Screen
27
+ # Pre-allocated mutable cell. Struct supports [] access like Hash,
28
+ # so callers using cell[:char] etc. need no changes.
29
+ Cell = Struct.new(:char, :fg, :bg, :width)
30
+
27
31
  attr_reader :width, :height
28
32
 
29
33
  def initialize(width, height)
30
34
  @width = width
31
35
  @height = height
32
- @cells = Array.new(height) { Array.new(width) { default_cell } }
36
+ @cells = Array.new(height) { Array.new(width) { Cell.new(' ', nil, nil, 1) } }
33
37
  @overlay_cells = nil # オーバーレイレイヤー(ダイアログ用)
34
38
  @dirty_rows = Set.new # Phase1: Dirty row tracking
35
39
  end
@@ -47,12 +51,11 @@ module Rufio
47
51
 
48
52
  # Phase1: Width is calculated once here (not in rendering loop)
49
53
  char_width = width || TextUtils.display_width(char)
50
- @cells[y][x] = {
51
- char: char,
52
- fg: fg,
53
- bg: bg,
54
- width: char_width
55
- }
54
+ cell = @cells[y][x]
55
+ cell.char = char
56
+ cell.fg = fg
57
+ cell.bg = bg
58
+ cell.width = char_width
56
59
 
57
60
  # Phase1: Mark row as dirty
58
61
  @dirty_rows.add(y)
@@ -62,12 +65,11 @@ module Rufio
62
65
  (char_width - 1).times do |offset|
63
66
  next_x = x + 1 + offset
64
67
  break if next_x >= @width
65
- @cells[y][next_x] = {
66
- char: '',
67
- fg: nil,
68
- bg: nil,
69
- width: 0
70
- }
68
+ marker = @cells[y][next_x]
69
+ marker.char = ''
70
+ marker.fg = nil
71
+ marker.bg = nil
72
+ marker.width = 0
71
73
  end
72
74
  end
73
75
  end
@@ -156,7 +158,12 @@ module Rufio
156
158
  # Clear the entire screen
157
159
  def clear
158
160
  @cells.each do |row|
159
- row.fill { default_cell }
161
+ row.each do |cell|
162
+ cell.char = ' '
163
+ cell.fg = nil
164
+ cell.bg = nil
165
+ cell.width = 1
166
+ end
160
167
  end
161
168
  # Phase1: Clear dirty rows after full clear
162
169
  @dirty_rows.clear
@@ -266,7 +273,7 @@ module Rufio
266
273
  private
267
274
 
268
275
  def default_cell
269
- { char: ' ', fg: nil, bg: nil, width: 1 }
276
+ Cell.new(' ', nil, nil, 1)
270
277
  end
271
278
 
272
279
  def out_of_bounds?(x, y)
@@ -192,10 +192,12 @@ module Rufio
192
192
  # getch を使用し、受信した各バイトをキューに積む。
193
193
  if windows?
194
194
  @input_queue = Queue.new
195
+ @stop_input_thread = false
195
196
  @input_thread = Thread.new do
196
197
  loop do
198
+ break if @stop_input_thread
197
199
  ch = STDIN.getch(min: 1)
198
- break if ch.nil?
200
+ break if ch.nil? || @stop_input_thread
199
201
  ch.bytes.each { |b| @input_queue << b }
200
202
  end
201
203
  rescue
@@ -291,11 +293,22 @@ module Rufio
291
293
  end
292
294
 
293
295
  def cleanup_terminal
294
- # Windows 入力スレッドを停止(raw! 解除前に kill)
296
+ # マウスレポートを先に無効化して新しいイベントの流入を止める
297
+ if windows?
298
+ print "\e[?1000l\e[?1006l"
299
+ else
300
+ print "\e[?1003l\e[?1006l"
301
+ end
302
+ STDOUT.flush
303
+
304
+ # Windows 入力スレッドを停止
295
305
  if windows? && @input_thread
306
+ @stop_input_thread = true
296
307
  @input_thread.kill rescue nil
297
308
  @input_thread.join(0.5) rescue nil
298
309
  @input_thread = nil
310
+ # コンソール入力バッファをフラッシュして残留イベントによる不正出力を防ぐ
311
+ windows_flush_console_input_buffer
299
312
  end
300
313
 
301
314
  # rawモードを解除
@@ -303,20 +316,31 @@ module Rufio
303
316
  STDIN.cooked!
304
317
  end
305
318
 
306
- # マウスレポートを無効化(setup_terminal と対称)
307
- if windows?
308
- print "\e[?1000l\e[?1006l"
309
- else
310
- print "\e[?1003l\e[?1006l"
311
- end
312
- STDOUT.flush
313
-
314
319
  print "\e[?25h" # cursor visible
315
320
  print "\e[?1049l" # restore normal screen buffer
316
321
  STDOUT.flush
317
322
  puts ConfigLoader.message('app.terminated')
318
323
  end
319
324
 
325
+ def windows_flush_console_input_buffer
326
+ require 'fiddle'
327
+ kernel32 = Fiddle.dlopen('kernel32')
328
+ get_std_handle = Fiddle::Function.new(
329
+ kernel32['GetStdHandle'],
330
+ [Fiddle::TYPE_LONG],
331
+ Fiddle::TYPE_VOIDP
332
+ )
333
+ flush = Fiddle::Function.new(
334
+ kernel32['FlushConsoleInputBuffer'],
335
+ [Fiddle::TYPE_VOIDP],
336
+ Fiddle::TYPE_INT
337
+ )
338
+ handle = get_std_handle.call(-10) # STD_INPUT_HANDLE = -10
339
+ flush.call(handle)
340
+ rescue
341
+ # Windows API が使えない場合は無視して続行
342
+ end
343
+
320
344
  # ゲームループパターンのmain_loop(CPU最適化版:フレームスキップ対応)
321
345
  # UPDATE → DRAW → RENDER → SLEEP のサイクル
322
346
  # 変更がない場合は描画をスキップしてCPU使用率を削減
data/lib/rufio/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rufio
4
- VERSION = '1.0.0'
4
+ VERSION = '1.0.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufio
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - masisz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-29 00:00:00.000000000 Z
11
+ date: 2026-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console