You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
asciinema.org/app/assets/javascripts/player/screen_buffer.js.coffee

319 lines
5.8 KiB
CoffeeScript

class AsciiIo.ScreenBuffer
constructor: (@cols, @lines, @scrollRegion, @tabStops) ->
@lineData = []
@dirtyLines = {}
@cursorX = 0
@cursorY = 0
@setBrush AsciiIo.Brush.create({})
@setCharset 'us'
topMargin: ->
@scrollRegion.getTop()
bottomMargin: ->
@scrollRegion.getBottom()
updateLine: (n = @cursorY) ->
@dirtyLines[n] = @lineData[n]
updateLines: (a, b) ->
n = a
while n <= b
@updateLine n
n++
updateScreen: ->
@updateLine n for n in [0...@lines]
changes: ->
@dirtyLines
clearChanges: ->
@dirtyLines = {}
clear: ->
@lineData.length = 0
getLine: (n = @cursorY) ->
throw "cant getLine " + n if n >= @lines
line = @lineData[n]
if typeof line is "undefined"
line = @lineData[n] = []
@fill n, 0, @cols, " "
line
_addEmptyLine: (l) ->
@lineData.splice l, 0, []
@clearLineData l
_removeLine: (l) ->
@lineData.splice l, 1
insertCharacters: (n) ->
line = @getLine()
@lineData[@cursorY] = line.slice(0, @cursorX).concat(" ".times(n).split(""), line.slice(@cursorX, @cols - n))
@updateLine()
fill: (line, col, n, char, brush=@brush) ->
lineArr = @getLine(line)
i = 0
while i < n
lineArr[col + i] = [char, brush]
i++
deleteCharacters: (n) ->
line = @getLine()
brush = line[line.length-1][1]
line.splice(@cursorX, n)
@fill(@cursorY, @cols - n, n, ' ', brush)
@updateLine()
print: (text) ->
text = Utf8.decode(text)
i = 0
while i < text.length
if @cursorX >= @cols
@cursorY += 1
@cursorX = 0
# TODO: updateLine?
13 years ago
@fill @cursorY, @cursorX, 1, @charsetModifier(text[i])
@cursorX += 1
i++
@updateLine()
clearLineData: (n) ->
@fill n, 0, @cols, " "
# ----- Cursor control
priorRow: (n = 1) ->
for i in [0...n]
if @cursorY > 0
@cursorY -= 1
@updateLine @cursorY
@updateLine @cursorY + 1
nextRow: (n = 1) ->
for i in [0...n]
if @cursorY + 1 < @lines
@cursorY += 1
@updateLine @cursorY - 1
@updateLine @cursorY
nextColumn: (n = 1) ->
@_cursorRight() for i in [0...n]
priorColumn: (n = 1) ->
@_cursorLeft() for i in [0...n]
_cursorLeft: ->
if @cursorX > 0
@cursorX -= 1
@updateLine()
_cursorRight: ->
if @cursorX < @cols - 1
@cursorX += 1
@updateLine()
priorRowFirstColumn: (n = 1) ->
@goToFirstColumn()
@priorRow n
nextRowFirstColumn: (n = 1) ->
@goToFirstColumn()
@nextRow n
goToColumn: (col = 1) ->
@cursorX = col - 1
@updateLine()
goToRow: (line = 1) ->
oldLine = @cursorY
@cursorY = line - 1
@updateLine oldLine
@updateLine()
goToRowAndColumn: (line = 1, col = 1) ->
@goToRow line
@goToColumn col
goToNextHorizontalTabStop: (n) ->
x = @tabStops.next(@cursorX)
@goToRowAndColumn(@cursorY + 1, x + 1)
@updateLine()
goToPriorHorizontalTabStop: (n) ->
x = @tabStops.prev(@cursorX)
@goToRowAndColumn(@cursorY + 1, x + 1)
@updateLine()
clearHorizontalTabStop: ->
console.log 'clearHorizontalTabStop'
clearAllHorizontalTabStops: ->
console.log 'clearAllHorizontalTabStops'
saveCursor: ->
@savedCol = @cursorX
@savedLine = @cursorY
restoreCursor: ->
oldLine = @cursorY
@cursorY = @savedLine
@cursorX = @savedCol
@updateLine oldLine
@updateLine()
goToFirstColumn: ->
@cursorX = 0
@updateLine()
# ----- Attribute control
setBrush: (brush) ->
@brush = brush
getBrush: ->
@brush
saveBrush: ->
@savedBrush = @brush
restoreBrush: ->
@brush = @savedBrush
repeatLastCharacter: (n = 1) ->
# ----- Scroll control
inScrollRegion: ->
@cursorY >= @topMargin() and @cursorY <= @bottomMargin()
scrollUp: (n = 1) ->
@insertLine n, @topMargin()
scrollDown: (n = 1) ->
@deleteLine n, @topMargin()
insertLine: (n, l = @cursorY) ->
return unless @inScrollRegion()
i = 0
while i < n
@_removeLine @bottomMargin()
@_addEmptyLine l
i++
@updateLines(l, @bottomMargin())
deleteLine: (n, l = @cursorY) ->
return unless @inScrollRegion()
i = 0
while i < n
@_removeLine l
@_addEmptyLine @bottomMargin()
i++
@updateLines(l, @bottomMargin())
goToPriorRow: ->
if @cursorY is @topMargin()
@scrollUp()
else
@priorRow()
goToNextRow: ->
if @cursorY is @bottomMargin()
@scrollDown()
else
@nextRow()
goToNextRowFirstColumn: ->
@goToFirstColumn()
@goToNextRow()
setLineWrap: (linewrap) ->
# ----- Erase control
eraseScreen: ->
l = 0
while l < @lines
@clearLineData l
@updateLine l
l++
eraseFromScreenStart: ->
l = 0
while l < @cursorY
@clearLineData l
@updateLine l
l++
@eraseFromRowStart()
eraseToScreenEnd: ->
@eraseToRowEnd()
l = @cursorY + 1
while l < @lines
@clearLineData l
@updateLine l
l++
eraseRow: ->
@fill @cursorY, 0, @cols, " "
@updateLine()
eraseFromRowStart: ->
@fill @cursorY, 0, @cursorX, " "
@updateLine()
eraseToRowEnd: ->
@fill @cursorY, @cursorX, @cols - @cursorX, " "
@updateLine()
eraseCharacters: (n = 1) ->
@fill @cursorY, @cursorX, n, " "
@updateLine()
# ------ Charset control
setCharset: (charset) ->
@charset = charset
switch charset
when 'uk'
@charsetModifier = @ukCharsetModifier
when 'us'
@charsetModifier = @usCharsetModifier
when 'special'
@charsetModifier = @specialCharsetModifier
getCharset: ->
@charset
usCharsetModifier: (char) ->
char
ukCharsetModifier: (char) ->
char
specialCharsetModifier: (char) ->
AsciiIo.SpecialCharset[char.charCodeAt(0)] or char