mirror of
https://github.com/lihop/godot-xterm.git
synced 2024-09-20 08:26:20 +02:00
142 lines
3.5 KiB
GDScript3
142 lines
3.5 KiB
GDScript3
|
# Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
||
|
# Ported to GDScript by the GodotXterm authors.
|
||
|
# License MIT
|
||
|
extends Reference
|
||
|
|
||
|
|
||
|
const BufferLine = preload("res://addons/godot_xterm/buffer/buffer_line.gd")
|
||
|
const CellData = preload("res://addons/godot_xterm/buffer/cell_data.gd")
|
||
|
const Charsets = preload("res://addons/godot_xterm/data/charsets.gd")
|
||
|
const Constants = preload("res://addons/godot_xterm/buffer/constants.gd")
|
||
|
const CircularList = preload("res://addons/godot_xterm/circular_list.gd")
|
||
|
const AttributeData = preload("res://addons/godot_xterm/buffer/attribute_data.gd")
|
||
|
|
||
|
|
||
|
const MAX_BUFFER_SIZE = 4294967295 # 2^32 - 1
|
||
|
|
||
|
var lines
|
||
|
var ydisp: int = 0
|
||
|
var ybase: int = 0
|
||
|
var y: int = 0
|
||
|
var x: int = 0
|
||
|
var scroll_bottom: int
|
||
|
var scroll_top: int
|
||
|
var tabs = {}
|
||
|
var saved_y: int = 0
|
||
|
var saved_x: int = 0
|
||
|
var saved_cur_attr_data = AttributeData.new()
|
||
|
var saved_charset = Charsets.DEFAULT_CHARSET
|
||
|
var markers: Array = []
|
||
|
|
||
|
var _null_cell = CellData.from_char_data([0, Constants.NULL_CELL_CHAR,
|
||
|
Constants.NULL_CELL_WIDTH, Constants.NULL_CELL_CODE])
|
||
|
var _whitespace_cell = CellData.from_char_data([0, Constants.WHITESPACE_CELL_CHAR,
|
||
|
Constants.WHITESPACE_CELL_WIDTH, Constants.WHITESPACE_CELL_CODE])
|
||
|
var _cols: int
|
||
|
var _rows: int
|
||
|
var _has_scrollback
|
||
|
var _options_service
|
||
|
var _buffer_service
|
||
|
|
||
|
|
||
|
func _init(has_scrollback: bool, options_service, buffer_service):
|
||
|
_has_scrollback = has_scrollback
|
||
|
_options_service = options_service
|
||
|
_buffer_service = buffer_service
|
||
|
_cols = buffer_service.cols
|
||
|
_rows = buffer_service.rows
|
||
|
lines = CircularList.new(_get_correct_buffer_length(_rows))
|
||
|
scroll_top = 0
|
||
|
scroll_bottom = _rows - 1
|
||
|
setup_tab_stops()
|
||
|
|
||
|
|
||
|
func get_null_cell(attr = null):
|
||
|
if attr:
|
||
|
_null_cell.fg = attr.fg
|
||
|
_null_cell.bg = attr.bg
|
||
|
_null_cell.extended = attr.extended
|
||
|
else:
|
||
|
_null_cell.fg = 0
|
||
|
_null_cell.bg = 0
|
||
|
_null_cell.extended = AttributeData.ExtendedAttrs.new()
|
||
|
return _null_cell
|
||
|
|
||
|
|
||
|
func get_blank_line(attr, is_wrapped: bool = false):
|
||
|
return BufferLine.new(_buffer_service.cols, get_null_cell(attr), is_wrapped)
|
||
|
|
||
|
|
||
|
func _get_correct_buffer_length(rows: int) -> int:
|
||
|
if not _has_scrollback:
|
||
|
return rows
|
||
|
else:
|
||
|
var correct_buffer_length = rows + _options_service.options.scrollback
|
||
|
return correct_buffer_length if correct_buffer_length < MAX_BUFFER_SIZE else MAX_BUFFER_SIZE
|
||
|
|
||
|
|
||
|
# Fills the viewport with blank lines.
|
||
|
func fill_viewport_rows(fill_attr = null) -> void:
|
||
|
if lines.length == 0:
|
||
|
if not fill_attr:
|
||
|
fill_attr = AttributeData.new()
|
||
|
var i = _rows
|
||
|
while i:
|
||
|
lines.push(get_blank_line(fill_attr))
|
||
|
i -= 1
|
||
|
|
||
|
|
||
|
|
||
|
# Clears the buffer to it's initial state, discarding all previous data.
|
||
|
func clear() -> void:
|
||
|
ydisp = 0
|
||
|
ybase = 0
|
||
|
y = 0
|
||
|
x = 0
|
||
|
lines = CircularList.new(_get_correct_buffer_length(_rows))
|
||
|
scroll_top = 0
|
||
|
scroll_bottom = _rows - 1
|
||
|
setup_tab_stops()
|
||
|
|
||
|
|
||
|
func get_wrapped_range_for_line(y: int) -> Dictionary:
|
||
|
var first = y
|
||
|
var last = y
|
||
|
# Scan upwards for wrapped lines
|
||
|
while first > 0 and lines.get_el(first).is_wrapped:
|
||
|
first -= 1
|
||
|
# Scan downwards for wrapped lines
|
||
|
while last + 1 < lines.length and lines.get_el(last + 1).is_wrapped:
|
||
|
last += 1
|
||
|
return {"first": first, "last": last}
|
||
|
|
||
|
|
||
|
func setup_tab_stops(i = null) -> void:
|
||
|
if i == null:
|
||
|
return
|
||
|
|
||
|
if not tabs.get(i):
|
||
|
i = prev_stop(i)
|
||
|
else:
|
||
|
tabs = {}
|
||
|
i = 0
|
||
|
|
||
|
while i < _cols:
|
||
|
tabs[i] = true
|
||
|
i += _options_service.options.tab_stop_width
|
||
|
|
||
|
|
||
|
func prev_stop(x: int) -> int:
|
||
|
if x == null:
|
||
|
x = self.x
|
||
|
|
||
|
while not tabs.get(x - 1, false) and x - 1 > 0:
|
||
|
x - 1
|
||
|
|
||
|
return _cols - 1 if x > _cols else 0 if x < 0 else x
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|