This is necessary to operate with many versions of the ruby ncurses library,
all of which block threads when getch is being called. But this means we can't
use getch to determine a sigwich, since we won't see it until an actual key is
pressed. so we handle sigwinch ourselves.
Index.load
trap("TERM") { |x| raise "so speaking as i think, i die, i die!" }
Index.load
trap("TERM") { |x| raise "so speaking as i think, i die, i die!" }
+ trap("WINCH") { |x| BufferManager.sigwinch_happened! }
if(s = Redwood::SourceManager.source_for DraftManager.source_name)
DraftManager.source = s
if(s = Redwood::SourceManager.source_for DraftManager.source_name)
DraftManager.source = s
+ if c.nil?
+ if BufferManager.sigwinch_happened?
+ Redwood::log "redrawing screen on sigwinch"
+ BufferManager.completely_redraw_screen
+ end
+ next
+ end
+
+ if c == 410
+ ## this is ncurses's way of telling us it's detected a refresh.
+ ## since we have our own sigwinch handler, we don't do anything.
+ next
+ end
+
bm.erase_flash
action = begin
bm.erase_flash
action = begin
def sync &b; mutex.synchronize(&b); end
def nonblocking_getch
def sync &b; mutex.synchronize(&b); end
def nonblocking_getch
- ## INSANITY
- ## it is NECESSARY to call nodelay EVERY TIME otherwise a single ctrl-c
- ## will turn a blocking call into a nonblocking one. hours of my life
- ## wasted on this trivial bullshit: 3.
- Ncurses.nodelay Ncurses.stdscr, false
- Ncurses.getch
+ ## INSANTIY
+ ## it is NECESSARY to wrap Ncurses.getch in a select() otherwise all
+ ## background threads will be BLOCKED. (except in very modern versions
+ ## of libncurses-ruby. the current one on ubuntu seems to work well.)
+ if IO.select([$stdin], nil, nil, 0.5)
+ c = Ncurses.getch
+ end
end
module_function :rows, :cols, :curx, :nonblocking_getch, :mutex, :sync
end
module_function :rows, :cols, :curx, :nonblocking_getch, :mutex, :sync
@flash = nil
@shelled = @asking = false
@in_x = ENV["TERM"] =~ /(xterm|rxvt|screen)/
@flash = nil
@shelled = @asking = false
@in_x = ENV["TERM"] =~ /(xterm|rxvt|screen)/
+ @sigwinch_happened = false
+ @sigwinch_mutex = Mutex.new
self.class.i_am_the_instance self
end
self.class.i_am_the_instance self
end
+ def sigwinch_happened!; @sigwinch_mutex.synchronize { @sigwinch_happened = true } end
+ def sigwinch_happened?; @sigwinch_mutex.synchronize { @sigwinch_happened } end
+
def buffers; @name_map.to_a; end
def focus_on buf
def buffers; @name_map.to_a; end
def focus_on buf
def completely_redraw_screen
return if @shelled
def completely_redraw_screen
return if @shelled
+ ## this magic makes Ncurses get the new size of the screen
+ Ncurses.endwin
+ Ncurses.refresh
+ @sigwinch_mutex.synchronize { @sigwinch_happened = false }
+ Redwood::log "new screen size is #{Ncurses.rows} x #{Ncurses.cols}"
+
status, title = get_status_and_title(@focus_buf) # must be called outside of the ncurses lock
Ncurses.sync do
status, title = get_status_and_title(@focus_buf) # must be called outside of the ncurses lock
Ncurses.sync do