@@ -1,141 +0,0 @@ | |||||
function vt100emu(gpu) -- takes GPU component proxy *gpu* and returns a function to write to it in a manner like an ANSI terminal | |||||
local colours = {0x0,0xFF0000,0x00FF00,0xFFFF00,0x0000FF,0xFF00FF,0x00B6FF,0xFFFFFF} | |||||
local mx, my = gpu.maxResolution() | |||||
local cx, cy = 1, 1 | |||||
local pc = " " | |||||
local lc = "" | |||||
local mode = 0 -- 0 normal, 1 escape, 2 command | |||||
local lw = true | |||||
local sx, sy = 1,1 | |||||
local cs = "" | |||||
local bg, fg = 0, 0xFFFFFF | |||||
-- setup | |||||
gpu.setResolution(mx,my) | |||||
gpu.fill(1,1,mx,my," ") | |||||
local function checkCursor() | |||||
if cx > mx and lw then | |||||
cx, cy = 1, cy+1 | |||||
end | |||||
if cy > my then | |||||
gpu.copy(1,2,mx,my-1,0,-1) | |||||
gpu.fill(1,my,mx,1," ") | |||||
cy=my | |||||
end | |||||
if cy < 1 then cy = 1 end | |||||
if cx < 1 then cx = 1 end | |||||
end | |||||
local function termwrite(s) | |||||
local wb = "" | |||||
local lb, ec = nil, nil | |||||
local function flushwb() | |||||
while wb:len() > 0 do | |||||
checkCursor() | |||||
local wl = wb:sub(1,mx-cx+1) | |||||
wb = wb:sub(wl:len()+1) | |||||
gpu.set(cx, cy, wl) | |||||
cx = cx + wl:len() | |||||
end | |||||
end | |||||
local rs = "" | |||||
s=s:gsub("\8","\27[D") | |||||
pc = gpu.get(cx,cy) | |||||
gpu.setForeground(fg) | |||||
gpu.setBackground(bg) | |||||
gpu.set(cx,cy,pc) | |||||
for cc in s:gmatch(".") do | |||||
if mode == 0 then | |||||
if cc == "\n" then | |||||
flushwb() | |||||
cx,cy = 1, cy+1 | |||||
elseif cc == "\t" then | |||||
wb=wb..(" "):rep(8*((cx+9)//8)) | |||||
elseif cc == "\27" then | |||||
flushwb() | |||||
mode = 1 | |||||
else | |||||
wb = wb .. cc | |||||
end | |||||
elseif mode == 1 then | |||||
if cc == "[" then | |||||
mode = 2 | |||||
else | |||||
mode = 0 | |||||
end | |||||
elseif mode == 2 then | |||||
if cc:match("[%d;]") then | |||||
cs = cs .. cc | |||||
else | |||||
mode = 0 | |||||
local tA = {} | |||||
for s in cs:gmatch("%d+") do | |||||
tA[#tA+1] = tonumber(s) | |||||
end | |||||
if cc == "H" then | |||||
cx, cy = tA[1] or 1, tA[2] or 1 | |||||
elseif cc == "A" then | |||||
cy = cy - (tA[1] or 1) | |||||
elseif cc == "B" then | |||||
cy = cy + (tA[1] or 1) | |||||
elseif cc == "C" then | |||||
cx = cx + (tA[1] or 1) | |||||
elseif cc == "D" then | |||||
cx = cx - (tA[1] or 1) | |||||
elseif cc == "s" then | |||||
sx, sy = cx, cy | |||||
elseif cc == "u" then | |||||
cx, cy = sx, sy | |||||
elseif cc == "n" and tA[1] == 6 then | |||||
rs = string.format("%s\27[%d;%dR",rs,cx,cy) | |||||
elseif cc == "K" and tA[1] == 1 then | |||||
gpu.fill(1,cy,cx,1," ") | |||||
elseif cc == "K" and tA[1] == 2 then | |||||
gpu.fill(cx,cy,mx,1," ") | |||||
elseif cc == "K" then | |||||
gpu.fill(1,cy,mx,1," ") | |||||
elseif cc == "J" and tA[1] == 1 then | |||||
gpu.fill(1,1,mx,cy," ") | |||||
elseif cc == "J" and tA[1] == 2 then | |||||
gpu.fill(1,1,mx,my," ") | |||||
cx, cy = 1, 1 | |||||
elseif cc == "J" then | |||||
gpu.fill(1,cy,mx,my," ") | |||||
elseif cc == "m" then | |||||
for _,num in ipairs(tA) do | |||||
if num == 0 then | |||||
fg,bg,ec,lb = 0xFFFFFF,0,true,true | |||||
elseif num == 7 then | |||||
local nfg,nbg = bg, fg | |||||
fg, bg = nfg, nbg | |||||
elseif num > 29 and num < 38 then | |||||
fg = colours[num-29] | |||||
elseif num > 39 and num < 48 then | |||||
bg = colours[num-39] | |||||
elseif num == 100 then -- disable local echo | |||||
ec = false | |||||
elseif num == 101 then -- disable line mode | |||||
lb = false | |||||
end | |||||
end | |||||
gpu.setForeground(fg) | |||||
gpu.setBackground(bg) | |||||
end | |||||
cs = "" | |||||
checkCursor() | |||||
end | |||||
end | |||||
end | |||||
flushwb() | |||||
checkCursor() | |||||
pc = gpu.get(cx,cy) | |||||
gpu.setForeground(bg) | |||||
gpu.setBackground(fg) | |||||
gpu.set(cx,cy,pc) | |||||
gpu.setForeground(fg) | |||||
gpu.setBackground(bg) | |||||
return rs, lb, ec | |||||
end | |||||
return termwrite | |||||
end |
@@ -1,5 +0,0 @@ | |||||
--#include "module/vt-task.lua" | |||||
do | |||||
local r,w = vtemu(component.list("gpu")(),component.list("screen")()) | |||||
devfs.register("tty0", function() return r,w,function() end end) | |||||
end |
@@ -1,58 +0,0 @@ | |||||
do | |||||
--#include "module/nvt100.lua" | |||||
function vtemu(gpua,scra) -- creates a process to handle the GPU and screen address combination *gpua*/*scra*. Returns read, write and "close" functions. | |||||
local gpu = component.proxy(gpua) | |||||
gpu.bind(scra) | |||||
local write = vt100emu(gpu) | |||||
local kba = {} | |||||
for k,v in ipairs(component.invoke(scra,"getKeyboards")) do | |||||
kba[v]=true | |||||
end | |||||
local buf, lbuf, echo = "", true, true | |||||
os.spawn(function() dprint(pcall(function() | |||||
while true do | |||||
local ty,ka,ch = coroutine.yield() | |||||
if ty == "key_down" and kba[ka] then | |||||
if ch == 13 then ch = 10 end | |||||
if ch == 8 then | |||||
if buf:len() > 0 then | |||||
if echo then write("\8 \8") end | |||||
buf = buf:sub(1,-2) | |||||
end | |||||
elseif ch > 0 then | |||||
if echo then write(string.char(ch)) end | |||||
buf=buf..string.char(ch) | |||||
end | |||||
end | |||||
end | |||||
end)) end,string.format("ttyd[%s:%s]",gpua:sub(1,8),scra:sub(1,8))) | |||||
local function bread(n) | |||||
local r | |||||
if lbuf then | |||||
while not buf:find("\n") do | |||||
coroutine.yield() | |||||
end | |||||
local n = buf:find("\n") | |||||
r, buf = buf:sub(1,n), buf:sub(n+1) | |||||
else | |||||
r = buf | |||||
buf = "" | |||||
coroutine.yield() | |||||
end | |||||
return r | |||||
end | |||||
local function bwrite(d) | |||||
local ba, lb, ec = write(d) | |||||
buf = buf .. ba | |||||
if lb ~= nil then | |||||
dprint("local buffer mode: "..tostring(lb)) | |||||
lbuf = lb | |||||
end | |||||
if ec ~= nil then | |||||
dprint("echo mode: "..tostring(ec)) | |||||
echo = ec | |||||
end | |||||
end | |||||
return bread, bwrite, function() io.write("\27[2J\27[H") end | |||||
end | |||||
end |
@@ -1,148 +0,0 @@ | |||||
function vt100emu(gpu) -- takes GPU component proxy *gpu* and returns a function to write to it in a manner like an ANSI terminal | |||||
local colours = {0x0,0xFF0000,0x00FF00,0xFFFF00,0x0000FF,0xFF00FF,0x00B6FF,0xFFFFFF} | |||||
local mx, my = gpu.maxResolution() | |||||
local cx, cy = 1, 1 | |||||
local pc = " " | |||||
local lc = "" | |||||
local mode = "n" | |||||
local lw = true | |||||
local sx, sy = 1,1 | |||||
local cs = "" | |||||
local bg, fg = 0, 0xFFFFFF | |||||
-- setup | |||||
gpu.setResolution(mx,my) | |||||
gpu.fill(1,1,mx,my," ") | |||||
local function termwrite(s) | |||||
local rs = "" | |||||
s=s:gsub("\8","\27[D") | |||||
pc = gpu.get(cx,cy) | |||||
gpu.setForeground(fg) | |||||
gpu.setBackground(bg) | |||||
gpu.set(cx,cy,pc) | |||||
for i = 1, s:len() do | |||||
local cc = s:sub(i,i) | |||||
if mode == "n" then | |||||
if cc == "\n" then -- line feed | |||||
cx, cy = 1, cy+1 | |||||
elseif cc == "\r" then -- cursor home | |||||
cx = 1 | |||||
elseif cc == "\27" then -- escape | |||||
mode = "e" | |||||
elseif cc == "\t" then | |||||
cx = 8*((cx+9)//8) | |||||
elseif string.byte(cc) > 31 and string.byte(cc) < 127 then -- printable, I guess | |||||
gpu.set(cx, cy, cc) | |||||
cx = cx + 1 | |||||
end | |||||
elseif mode == "e" then | |||||
if cc == "[" then | |||||
mode = "v" | |||||
cs = "" | |||||
elseif cc == "D" then -- scroll down | |||||
gpu.copy(1,2,mx,my-1,0,-1) | |||||
gpu.fill(1,my,mx,1," ") | |||||
cy=cy+1 | |||||
mode = "n" | |||||
elseif cc == "M" then -- scroll up | |||||
gpu.copy(1,1,mx,my-1,0,1) | |||||
gpu.fill(1,1,mx,1," ") | |||||
mode = "n" | |||||
else | |||||
mode = "n" | |||||
end | |||||
elseif mode == "v" then | |||||
mode = "n" | |||||
if cc == "s" then -- save cursor | |||||
sx, sy = cx, cy | |||||
elseif cc == "u" then -- restore cursor | |||||
cx, cy = sx, sy | |||||
elseif cc == "H" then -- cursor home or to | |||||
local tx, ty = cs:match("(%d+);(%d+)") | |||||
tx, ty = tx or "1", ty or "1" | |||||
cx, cy = tonumber(tx), tonumber(ty) | |||||
elseif cc == "A" then -- cursor up | |||||
cy = cy - (tonumber(cs) or 1) | |||||
elseif cc == "B" then -- cursor down | |||||
cy = cy + (tonumber(cs) or 1) | |||||
elseif cc == "C" then -- cursor right | |||||
cx = cx + (tonumber(cs) or 1) | |||||
elseif cc == "D" then -- cursor left | |||||
cx = cx - (tonumber(cs) or 1) | |||||
elseif cc == "h" and lc == "7" then -- enable line wrap | |||||
lw = true | |||||
elseif cc == "l" and lc == "7" then -- disable line wrap | |||||
lw = false | |||||
elseif cc == "c" then | |||||
rs = string.format("%s\27[%d;%d0c",rs,mx,my) | |||||
elseif cc == "n" and lc == "6" then | |||||
rs = string.format("%s\27[%d;%dR",rs,cx,cy) | |||||
elseif cc == "K" then | |||||
if lc == "1" then | |||||
gpu.fill(1,cy,cx,1," ") | |||||
elseif lc == "2" then | |||||
gpu.fill(cx,cy,mx,1," ") | |||||
else | |||||
gpu.fill(1,cy,mx,1," ") | |||||
end | |||||
elseif cc == "J" then | |||||
if lc == "1" then | |||||
gpu.fill(1,1,mx,cy," ") | |||||
elseif lc == "2" then | |||||
gpu.full(1,1,mx,my," ") | |||||
cx,cy = 1, 1 | |||||
else | |||||
gpu.fill(1,cy,mx,my," ") | |||||
end | |||||
elseif cc == "m" then | |||||
for num in cs:gmatch("%d+") do | |||||
num=tonumber(num) | |||||
if num == 0 then | |||||
fg,bg = 0xFFFFFF,0 | |||||
elseif num == 7 then | |||||
local nfg,nbg = bg, fg | |||||
fg, bg = nfg, nbg | |||||
elseif num > 29 and num < 38 then | |||||
fg = colours[num-29] | |||||
elseif num > 39 and num < 48 then | |||||
bg = colours[num-39] | |||||
end | |||||
end | |||||
gpu.setForeground(fg) | |||||
gpu.setBackground(bg) | |||||
else | |||||
cs = cs .. cc | |||||
if cc:match("[%d;]") then | |||||
mode = "v" | |||||
end | |||||
end | |||||
end | |||||
if cx > mx and lw then | |||||
cx, cy = 1, cy+1 | |||||
end | |||||
if cy > my then | |||||
gpu.copy(1,2,mx,my-1,0,-1) | |||||
gpu.fill(1,my,mx,1," ") | |||||
cy=my | |||||
end | |||||
if cy < 1 then cy = 1 end | |||||
if cx < 1 then cx = 1 end | |||||
lc = cc | |||||
end | |||||
pc = gpu.get(cx,cy) | |||||
gpu.setForeground(bg) | |||||
gpu.setBackground(fg) | |||||
gpu.set(cx,cy,pc) | |||||
gpu.setForeground(fg) | |||||
gpu.setBackground(bg) | |||||
return rs | |||||
end | |||||
return termwrite | |||||
end |