     bufferRow = e.oldRange.start.row
     oldRange.start.row = @firstScreenRowForBufferRow(e.oldRange.start.row)
     oldRange.end.row = @lastScreenRowForBufferRow(e.oldRange.end.row)
-    oldRange.end.column = _.last(@wrappedLines[e.oldRange.end.row].screenLines).text.length
+    oldRange.end.column = _.last(@index.at(e.oldRange.end.row).screenLines).text.length
 
-    @wrappedLines[e.oldRange.start.row..e.oldRange.end.row] = @buildWrappedLinesForBufferRows(e.newRange.start.row, e.newRange.end.row)
+    { start, end } = e.oldRange
+    wrappedLines = @buildWrappedLinesForBufferRows(e.newRange.start.row, e.newRange.end.row)
+    @index.splice start.row, end.row, @getSpans(wrappedLines), wrappedLines
 
     newRange = oldRange.copy()
     newRange.end.row = @lastScreenRowForBufferRow(e.newRange.end.row)
-    newRange.end.column = _.last(@wrappedLines[e.newRange.end.row].screenLines).text.length
+    newRange.end.column = _.last(@index.at(e.newRange.end.row).screenLines).text.length
 
     @trigger 'change', { oldRange, newRange }
 

  setMaxLength: (@maxLength) ->
    oldRange = new Range
    oldRange.end.row = @screenLineCount() - 1
    oldRange.end.column = _.last(_.last(@wrappedLines).screenLines).text.length
    @buildWrappedLines()
    newRange = new Range
    newRange.end.row = @screenLineCount() - 1
    newRange.end.column = _.last(_.last(@wrappedLines).screenLines).text.length
    @trigger 'change', { oldRange, newRange }

  buildWrappedLines: ->
    @wrappedLines = @buildWrappedLinesForBufferRows(0, @buffer.lastRow())

  handleChange: (e) ->
    oldRange = new Range


  screenPositionFromBufferPosition: (bufferPosition, allowEOL=false) ->
    bufferPosition = Point.fromObject(bufferPosition)
    row = @index.spanForIndex(bufferPosition.row)
    column = bufferPosition.column

    screenLines = @index.at(bufferPosition.row).screenLines
    for screenLine, index in screenLines
      break if index == screenLines.length - 1
      if allowEOL
