Class: WindowAdapter
- Inherits:
-
Object
- Object
- WindowAdapter
- Defined in:
- lib/windowadapter.rb
Overview
#Design change:
Terminal writes to the buffer. Buffer batches up updates to an output adapter (the window, but could be a terminal…)
But for now, the now stupidly misnamed TrackChanges class just bifurcates buffer changes and passes them to both the buffer and the screen, and “nothing” should talk to the window directly. Once all window updates are moved to TrackChanges/WindowAdapter We want to make it smarter.
Instance Method Summary collapse
- #brighten(col, bg) ⇒ Object
- #char_h ⇒ Object
- #char_w ⇒ Object
- #clear ⇒ Object
- #clear_area(x, y, w, h) ⇒ Object
- #clear_cells(x, y, w, h) ⇒ Object
- #clear_line(y, from_x, to_x = nil) ⇒ Object
- #delete_lines(y, num, maxy) ⇒ Object
-
#dim(col) ⇒ Object
FIXME.
- #draw(x, y, c, fg, bg, flags, lineattrs) ⇒ Object
-
#draw_flag_lines(flags, x, y, len, fg) ⇒ Object
# Migrating draw_flush.
-
#initialize(window, term) ⇒ WindowAdapter
constructor
A new instance of WindowAdapter.
- #insert_lines(y, num, maxy) ⇒ Object
-
#redraw_all ⇒ Object
Force a complete redraw of the window contents.
- #scroll_up(scroll_start, scroll_end) ⇒ Object
-
#scrollback_anchor ⇒ Object
A line has entered history while scrolled back: keep the same absolute lines in view (and the selection mapping consistent) by deepening the offset instead of letting the viewport drift.
-
#scrollback_mode ⇒ Object
True while the view is scrolled back into history.
-
#set_columns(cols) ⇒ Object
DECCOLM: the terminal asked to switch to
colscolumns (80/132).
Constructor Details
#initialize(window, term) ⇒ WindowAdapter
Returns a new instance of WindowAdapter.
14 15 16 17 |
# File 'lib/windowadapter.rb', line 14 def initialize window, term @window = window @term = term end |
Instance Method Details
#brighten(col, bg) ⇒ Object
45 46 47 48 |
# File 'lib/windowadapter.rb', line 45 def brighten(col, bg) # FIXME. Should bring it towards bg [col].pack("l").each_byte.map{|b| (b.ord+128).clamp(0,255) }.pack("C*").unpack("l")[0] end |
#char_h ⇒ Object
20 |
# File 'lib/windowadapter.rb', line 20 def char_h = @window.char_h |
#char_w ⇒ Object
19 |
# File 'lib/windowadapter.rb', line 19 def char_w = @window.char_w |
#clear ⇒ Object
21 |
# File 'lib/windowadapter.rb', line 21 def clear = @window.clear(0,0,@window.width,@window.height) |
#clear_area(x, y, w, h) ⇒ Object
50 |
# File 'lib/windowadapter.rb', line 50 def clear_area(x,y,w,h) = @window.clear(x*char_w,y*char_h,w,h) |
#clear_cells(x, y, w, h) ⇒ Object
51 |
# File 'lib/windowadapter.rb', line 51 def clear_cells(x,y,w,h) = clear_area(x,y, w * char_w, h * char_h) |
#clear_line(y, from_x, to_x = nil) ⇒ Object
53 54 55 56 57 58 59 60 61 62 |
# File 'lib/windowadapter.rb', line 53 def clear_line y, from_x, to_x = nil if to_x # to_x is an INCLUSIVE end column, matching TermBuffer#clear_line # (EL mode 1 clears [0..cursor] inclusive). Clearing to_x-from_x # cells left the cursor column itself stale on screen. clear_cells(from_x, y, to_x - from_x + 1, 1) else clear_cells(from_x, y, @term.term_width - from_x, 1) end end |
#delete_lines(y, num, maxy) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/windowadapter.rb', line 80 def delete_lines(y, num, maxy) # Deleting more lines than the region holds clears [y..maxy] entirely. # Without this clamp a large num gave Window#scroll_up a negative height # and a negative clear origin that clamped to row 0, wiping lines above # the scroll region. num = [num, maxy - y + 1].min return if num <= 0 # Move the rows below the deleted block - [y+num .. maxy] - up by num # rows, into [y .. maxy-num]; Window#scroll_up clears the vacated rows # at the bottom of the region. @window.scroll_up((y + num) * char_h, @term.term_width * char_w, (maxy - (y + num) + 1) * char_h, num * char_h) end |
#dim(col) ⇒ Object
FIXME
41 42 43 |
# File 'lib/windowadapter.rb', line 41 def dim(col) #FIXME [col].pack("l").each_byte.map{|b| b.ord*0.4 }.pack("C*").unpack("l")[0] end |
#draw(x, y, c, fg, bg, flags, lineattrs) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/windowadapter.rb', line 115 def draw(x,y,c,fg,bg,flags,lineattrs) inverse = flags.allbits?(INVERSE) if inverse fg,bg=bg,fg end if flags.allbits?(FAINT) fg = dim(fg) end if flags.anybits?(BLINK) && @term.blink_state fg = inverse ? brighten(fg,bg) : dim(fg) elsif flags.anybits?(RAPID_BLINK) && @term.rblink_state fg = inverse ? brighten(fg,bg) : dim(fg) end if x.nil? # @BUG STDERR.puts "\e[35m@BUG\[0m: x.nil? @windowadapter#draw" return end @window.draw(x*char_w, y*char_h, c, fg, bg, lineattrs) # FIXME: Take into account lineattrs draw_flag_lines(flags, x, y, c.length, fg) end |
#draw_flag_lines(flags, x, y, len, fg) ⇒ Object
# Migrating draw_flush
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/windowadapter.rb', line 97 def draw_flag_lines(flags, x,y, len, fg) x *= char_w y *= char_h w = len * char_w if flags.allbits?(OVERLINE) @window.draw_line(x,y,w,fg) end if flags.allbits?(CROSSED_OUT) @window.draw_line(x,y+char_h/2+2, w, fg) end if flags.anybits?(UNDERLINE | DBL_UNDERLINE) @window.draw_line(x,y+char_h-3, w, fg) if flags.allbits?(DBL_UNDERLINE) @window.draw_line(x,y+char_h-1, w, fg) end end end |
#insert_lines(y, num, maxy) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/windowadapter.rb', line 64 def insert_lines(y, num, maxy) # Inserting more lines than fit between y and the region bottom just # blanks the whole [y..maxy] span; clamp so the geometry below never # goes negative (which would clear rows above the region - see DL). num = [num, maxy - y + 1].min return if num <= 0 # Move the rows from the insertion point down to the region bottom - # [y .. maxy-num] - down by num rows, into [y+num .. maxy]; # Window#scroll_down clears the vacated rows at the top (the inserted # blanks). The old code scrolled from screen row 0 and ignored y, so an # IL anywhere below the top dragged every line above it (and outside the # scroll region) down, blanking row 0. @window.scroll_down(y * char_h, @term.term_width * char_w, (maxy - y - num + 1) * char_h, num * char_h) end |
#redraw_all ⇒ Object
Force a complete redraw of the window contents
143 144 145 146 147 148 149 150 |
# File 'lib/windowadapter.rb', line 143 def redraw_all # First clear the entire window @window.clear(0, 0, @window.width, @window.height) # Force the window to flush and update its display @window.dirty! @window.flush end |
#scroll_up(scroll_start, scroll_end) ⇒ Object
153 154 155 156 157 158 159 160 |
# File 'lib/windowadapter.rb', line 153 def scroll_up(scroll_start, scroll_end) @window.scroll_up( char_h*((scroll_start||0)+1), @window.width, (scroll_end-scroll_start)*char_h, char_h ) end |
#scrollback_anchor ⇒ Object
A line has entered history while scrolled back: keep the same absolute lines in view (and the selection mapping consistent) by deepening the offset instead of letting the viewport drift.
31 |
# File 'lib/windowadapter.rb', line 31 def scrollback_anchor = @window.scrollback_anchor |
#scrollback_mode ⇒ Object
True while the view is scrolled back into history. Live (pty-driven) screen writes are suppressed in this state so output doesn’t paint over the scrolled-back display; the buffer is still updated underneath.
26 |
# File 'lib/windowadapter.rb', line 26 def scrollback_mode = @window.scrollback_mode |
#set_columns(cols) ⇒ Object
DECCOLM: the terminal asked to switch to cols columns (80/132). The orchestrator (RubyTerm) owns the window pixels, font scale, config and the pty size report, so delegate to it. The headless harness “term” does not implement this (the virtual grid is fixed), so it no-ops.
37 38 39 |
# File 'lib/windowadapter.rb', line 37 def set_columns(cols) @term.set_columns(cols) if @term.respond_to?(:set_columns) end |