local record ScreenContent x: integer y: integer width: integer height: integer blink: boolean fg: integer text: {string} fg_color: {string} bg_color: {string} palette: {integer} end local record Buffer target: term.Redirect serialize: function(): ScreenContent is_dirty: function(): boolean clear_dirty: function() end local COLOR_LOOKUP : {number: integer} = { [colors.white] = 0x0, [colors.orange] = 0x1, [colors.magenta] = 0x2, [colors.lightBlue] = 0x3, [colors.yellow] = 0x4, [colors.lime] = 0x5, [colors.pink] = 0x6, [colors.gray] = 0x7, [colors.lightGray] = 0x8, [colors.cyan] = 0x9, [colors.purple] = 0xA, [colors.blue] = 0xB, [colors.brown] = 0xC, [colors.green] = 0xD, [colors.red] = 0xE, [colors.black] = 0xF, } local function wrap(parent: term.Redirect): Buffer local x, y = parent.getCursorPos() local width, height = parent.getSize() local blink = parent.getCursorBlink() local fg = COLOR_LOOKUP[parent.getTextColor()] local palette: {number} = {} for c = 0, 15 do palette[c+1] = colors.packRGB(parent.getPaletteColor(2^c)) end local dirty: boolean = false local win = window.create(parent, 1, 1, width, height) local overrides: table = {} overrides.setCursorPos = function(new_x: integer, new_y: integer) win.setCursorPos(new_x, new_y) x = new_x y = new_y end overrides.setCursorBlink = function(new_blink: boolean) win.setCursorBlink(new_blink) blink = new_blink end overrides.setTextColor = function(new_color: number) local r = { pcall(win.setTextColor, new_color) } if not r[1] then error((r[2] as string):sub(8)) end fg = COLOR_LOOKUP[new_color] end overrides.setTextColour = overrides.setTextColor overrides.setPaletteColor = function(color: number, r_rgb: number, g: number | nil, b: number | nil) local r = { pcall(win.setPaletteColor, color, r_rgb, g, b) } if not r[1] then error((r[2] as string):sub(8)) end local index = COLOR_LOOKUP[color] if g == nil then palette[1 + index] = r_rgb else palette[1 + index] = colors.packRGB(r_rgb, g, b) end end overrides.setPaletteColour = overrides.setPaletteColor local target = setmetatable(overrides, { __index = function(_: table, k: any): any dirty = true return (win as table)[k] end }) as term.Redirect target.setTextColor(colors.white) target.setBackgroundColor(colors.black) target.setCursorPos(1,1) target.clear() local buffer: Buffer = { target = target } buffer.serialize = function(): ScreenContent local text: {string} = {} local fg_color: {string} = {} local bg_color: {string} = {} for i = 1, height do local t, f, b = win.getLine(i) table.insert(text, t) table.insert(fg_color, f) table.insert(bg_color, b) end return { x = x, y = y, width = width, height = height, blink = blink, fg = fg, text = text, fg_color = fg_color, bg_color = bg_color, palette = palette } end buffer.is_dirty = function(): boolean return dirty end buffer.clear_dirty = function() dirty = false end return buffer end return { wrap = wrap, Buffer = Buffer, ScreenContent = ScreenContent }