2016-01-07 02:58:05 +11:00
local textgpu = { }
local mapping = {
[ " 0 " ] = 0x000000 ,
[ " 1 " ] = 0xFF0000 ,
[ " 2 " ] = 0x00FF00 ,
[ " 3 " ] = 0xFFFF00 ,
[ " 4 " ] = 0x0000FF ,
[ " 5 " ] = 0xFF00FF ,
[ " 6 " ] = 0x00FFFF ,
[ " 7 " ] = 0xFFFFFF ,
}
2016-01-14 11:10:04 +11:00
--[[local nw = io.write
io.write = function ( ... )
nw ( ... )
io.flush ( )
native.sleep ( 20000 )
end ] ] --
2016-01-19 05:42:32 +11:00
2016-01-18 06:07:51 +11:00
local write = io.write
local flush = io.flush
2016-01-14 11:10:04 +11:00
2016-01-07 02:58:05 +11:00
local background = " 0 "
local foreground = " 0 "
2016-01-14 11:10:04 +11:00
local tbuffer = { }
local bbuffer = { }
local fbuffer = { }
local function prepareBuffers ( w , h )
local tbline = ( " " ) : rep ( w )
local bbline = ( " 0 " ) : rep ( w )
local fbline = ( " 7 " ) : rep ( w )
for i = 1 , h do
tbuffer [ i ] = tbline
bbuffer [ i ] = bbline
fbuffer [ i ] = fbline
end
end
2016-01-21 09:18:02 +11:00
local usub
2016-01-14 11:10:04 +11:00
local function insertString ( main , sub , at )
2016-01-21 09:18:02 +11:00
checkArg ( 1 , main , " string " )
checkArg ( 2 , sub , " string " )
checkArg ( 3 , at , " number " )
2016-02-10 03:42:11 +11:00
return usub ( main , 1 , at - 1 )
.. sub .. usub ( main , at + ( utf8.len ( sub ) or 0 ) )
2016-01-14 11:10:04 +11:00
end
2016-01-07 02:58:05 +11:00
function textgpu . start ( )
2016-01-21 09:18:02 +11:00
usub = modules.sandbox . unicode.sub
2016-02-10 03:42:11 +11:00
local _height = 0
2016-01-07 02:58:05 +11:00
local gpu = { }
function gpu . bind ( ) return false , " This is static bound gpu " end
function gpu . setBackground ( color , isPaletteIndex )
checkArg ( 1 , color , " number " )
checkArg ( 2 , isPaletteIndex , " boolean " , " nil " )
if isPaletteIndex then
return --TODO: Maybe?
end
2016-01-16 05:58:26 +11:00
local old = background
2016-01-14 11:10:04 +11:00
background = tostring ( math.floor ( modules.color . nearest ( color , mapping ) ) )
2016-01-18 06:07:51 +11:00
write ( " \x1b [4 " .. background .. " m " )
flush ( )
2016-01-15 08:44:49 +11:00
return mapping [ old ]
2016-01-07 02:58:05 +11:00
end
function gpu . setForeground ( color , isPaletteIndex )
checkArg ( 1 , color , " number " )
checkArg ( 2 , isPaletteIndex , " boolean " , " nil " )
if isPaletteIndex then
return --TODO: Maybe?
end
2016-01-15 08:44:49 +11:00
local old = foreground
2016-01-14 11:10:04 +11:00
foreground = tostring ( math.floor ( modules.color . nearest ( color , mapping ) ) )
2016-01-18 06:07:51 +11:00
write ( " \x1b [3 " .. foreground .. " m " )
flush ( )
2016-01-15 08:44:49 +11:00
return mapping [ old ]
2016-01-07 02:58:05 +11:00
end
function gpu . getBackground ( )
return mapping [ background ] , false
end
function gpu . getForeground ( )
return mapping [ foreground ] , false
end
function gpu . getPaletteColor ( )
return nil
end
function gpu . setPaletteColor ( )
return nil
end
function gpu . maxDepth ( )
return 3
end
function gpu . setDepth ( )
return false
end
function gpu . getDepth ( )
return 3
end
function gpu . maxResolution ( )
return termutils.getSize ( )
end
function gpu . getResolution ( )
return termutils.getSize ( )
end
2016-01-15 08:44:49 +11:00
function gpu . getViewport ( )
return termutils.getSize ( )
end
function gpu . setViewport ( w , h )
checkArg ( 1 , w , " number " )
checkArg ( 2 , h , " number " )
return false , " Viewport not supported for this gpu "
end
2016-01-07 02:58:05 +11:00
function gpu . setResolution ( w , h )
checkArg ( 1 , w , " number " )
checkArg ( 2 , h , " number " )
return false , " Non resizeable gpu "
end
function gpu . get ( x , y )
checkArg ( 1 , x , " number " )
checkArg ( 2 , y , " number " )
--FIXME: ASAP: Implement
return " "
end
function gpu . set ( x , y , value , vertical )
checkArg ( 1 , x , " number " )
checkArg ( 2 , y , " number " )
checkArg ( 3 , value , " string " )
checkArg ( 4 , vertical , " boolean " , " nil " )
2016-01-10 05:39:48 +11:00
x = math.floor ( x )
y = math.floor ( y )
2016-01-07 02:58:05 +11:00
if not vertical then
2016-01-21 09:18:02 +11:00
if not tbuffer [ y ] then
2016-02-10 08:55:26 +11:00
native.log ( " GPU Set failed: under buffer " )
2016-01-21 09:18:02 +11:00
return false
end
2016-01-14 11:10:04 +11:00
tbuffer [ y ] = insertString ( tbuffer [ y ] , value , x )
bbuffer [ y ] = insertString ( bbuffer [ y ] , background : rep ( utf8.len ( value ) ) , x )
fbuffer [ y ] = insertString ( fbuffer [ y ] , foreground : rep ( utf8.len ( value ) ) , x )
2016-01-18 06:07:51 +11:00
write ( " \x1b [ " .. y .. " ; " .. x .. " H " .. value )
2016-01-07 02:58:05 +11:00
else
2016-01-21 09:18:02 +11:00
--TODO: Buffers!
2016-01-18 06:07:51 +11:00
write ( " \x1b [ " .. y .. " ; " .. x .. " H " )
2016-01-07 02:58:05 +11:00
value : gsub ( " . " , function ( c )
2016-01-18 06:07:51 +11:00
write ( c .. " \x1b [D \x1b [B " )
2016-01-07 02:58:05 +11:00
end )
end
2016-01-18 06:07:51 +11:00
flush ( )
2016-01-07 02:58:05 +11:00
return true
end
2016-01-14 11:10:04 +11:00
function gpu . copy ( x , y , w , h , tx , ty ) --TODO: Check(check X multiple times)
2016-01-07 02:58:05 +11:00
checkArg ( 1 , x , " number " )
checkArg ( 2 , y , " number " )
checkArg ( 3 , w , " number " )
checkArg ( 4 , h , " number " )
checkArg ( 5 , tx , " number " )
checkArg ( 6 , ty , " number " )
2016-01-14 11:10:04 +11:00
local ttbuf = { }
local btbuf = { }
local ftbuf = { }
for i = 1 , h do
2016-02-10 08:55:26 +11:00
if i + y - 2 <= _height and i + y > 1 then
2016-02-10 03:42:11 +11:00
ttbuf [ i ] = tbuffer [ y + i - 1 ] and usub ( tbuffer [ y + i - 1 ] , x , x + w - 1 ) or ( " " ) : rep ( w )
btbuf [ i ] = bbuffer [ y + i - 1 ] and bbuffer [ y + i - 1 ] : sub ( x , x + w - 1 ) or background : rep ( w )
ftbuf [ i ] = fbuffer [ y + i - 1 ] and fbuffer [ y + i - 1 ] : sub ( x , x + w - 1 ) or foreground : rep ( w )
else
ttbuf [ i ] = ( " " ) : rep ( w )
btbuf [ i ] = background : rep ( w )
ftbuf [ i ] = foreground : rep ( w )
end
2016-01-14 11:10:04 +11:00
end
local bg = background
local fg = foreground
for i = 1 , h do
local line , linex
2016-01-18 06:07:51 +11:00
local lwrite = false
2016-01-14 11:10:04 +11:00
for j = 1 , w do
if btbuf [ i ] : sub ( j , j ) ~= bg then
2016-01-18 06:07:51 +11:00
lwrite = true
2016-01-14 11:10:04 +11:00
end
if ftbuf [ i ] : sub ( j , j ) ~= fg then
2016-01-18 06:07:51 +11:00
lwrite = true
2016-01-14 11:10:04 +11:00
end
if not line then linex = j end
2016-01-16 22:42:09 +11:00
line = ( line or " " )
2016-01-18 06:07:51 +11:00
if lwrite then
2016-02-10 08:55:26 +11:00
local wx = ( tx + x + linex - 1 ) | 0
2016-01-14 11:10:04 +11:00
local wy = ( ty + y + i - 1 ) | 0
2016-02-10 08:55:26 +11:00
if tbuffer [ wy ] then
write ( " \x1b [4 " .. bg .. " m \x1b [3 " .. fg .. " m \x1b [ " .. wy .. " ; " .. wx .. " H " .. line )
tbuffer [ wy ] = insertString ( tbuffer [ wy ] , line , wx )
bbuffer [ wy ] = insertString ( bbuffer [ wy ] , bg : rep ( utf8.len ( line ) ) , wx )
fbuffer [ wy ] = insertString ( fbuffer [ wy ] , fg : rep ( utf8.len ( line ) ) , wx )
end
2016-02-10 03:42:11 +11:00
2016-01-16 22:42:09 +11:00
bg = btbuf [ i ] : sub ( j , j )
fg = ftbuf [ i ] : sub ( j , j )
2016-01-14 11:10:04 +11:00
line = nil
linex = nil
2016-01-18 06:07:51 +11:00
lwrite = false
2016-01-14 11:10:04 +11:00
end
2016-01-16 22:42:09 +11:00
if not line then linex = j end
2016-02-10 03:42:11 +11:00
line = ( line or " " ) .. usub ( ttbuf [ i ] , j , j )
2016-01-14 11:10:04 +11:00
end
if line then
2016-02-10 08:55:26 +11:00
local wx = ( tx + x + linex - 1 ) | 0
2016-01-14 11:10:04 +11:00
local wy = ( ty + y + i - 1 ) | 0
2016-02-10 08:55:26 +11:00
if tbuffer [ wy ] then
write ( " \x1b [4 " .. bg .. " m \x1b [3 " .. fg .. " m \x1b [ " .. wy .. " ; " .. wx .. " H " .. line )
tbuffer [ wy ] = insertString ( tbuffer [ wy ] , line , wx )
bbuffer [ wy ] = insertString ( bbuffer [ wy ] , bg : rep ( utf8.len ( line ) ) , wx )
fbuffer [ wy ] = insertString ( fbuffer [ wy ] , fg : rep ( utf8.len ( line ) ) , wx )
end
2016-01-14 11:10:04 +11:00
line = nil
linex = nil
2016-01-18 06:07:51 +11:00
lwrite = false
2016-01-14 11:10:04 +11:00
end
end
2016-01-18 06:07:51 +11:00
write ( " \x1b [4 " .. background .. " m " )
write ( " \x1b [3 " .. foreground .. " m " )
flush ( )
2016-01-14 11:10:04 +11:00
return true
2016-01-07 02:58:05 +11:00
end
function gpu . fill ( x , y , w , h , ch )
checkArg ( 1 , x , " number " )
checkArg ( 2 , y , " number " )
checkArg ( 3 , w , " number " )
checkArg ( 4 , h , " number " )
checkArg ( 5 , ch , " string " )
2016-02-10 03:42:11 +11:00
ch = usub ( ch , 1 , 1 ) : rep ( math.floor ( w ) )
2016-01-07 02:58:05 +11:00
for i = 1 , h do
2016-02-10 08:55:26 +11:00
if i + y - 1 <= _height and i + y > 1 then
2016-02-10 03:42:11 +11:00
gpu.set ( x , y + i - 1 , ch )
end
2016-01-07 02:58:05 +11:00
end
return true
end
2016-01-20 04:25:09 +11:00
local screenAddr
function gpu . getScreen ( )
return screenAddr
end
2016-02-28 01:30:34 +11:00
if not termutils.init ( ) then
return nil , " Cannot initialize terminal based gpu "
end
2016-01-18 06:07:51 +11:00
write ( " \x1b [?25l " ) --Disable cursor
2016-01-14 11:10:04 +11:00
local w , h = gpu.getResolution ( )
2016-02-10 03:42:11 +11:00
_height = h
2016-01-14 11:10:04 +11:00
prepareBuffers ( w , h )
2016-01-07 02:58:05 +11:00
gpu.setForeground ( 0xFFFFFF )
gpu.setBackground ( 0x000000 )
2016-02-28 01:30:34 +11:00
local gpuaddr = modules.component . api.register ( nil , " gpu " , gpu )
2016-01-20 04:25:09 +11:00
screenAddr = modules.component . api.register ( nil , " screen " , { getKeyboards = function ( ) return { " TODO:SetThisUuid " } end } ) --verry dummy screen, TODO: make it better, kbd uuid also in epoll.c
2016-01-16 22:42:09 +11:00
modules.component . api.register ( " TODO:SetThisUuid " , " keyboard " , { } )
2016-01-10 05:39:48 +11:00
deadhooks [ # deadhooks + 1 ] = function ( )
2016-02-10 03:42:11 +11:00
write ( " \x1b [?25h \x1b [ " .. ( ( h - 1 ) | 0 ) .. " ;1H " ) --Enable cursor on quit
io.flush ( )
termutils.restore ( )
2016-01-10 05:39:48 +11:00
end
2016-02-28 01:30:34 +11:00
return gpuaddr
2016-01-07 02:58:05 +11:00
end
2016-01-20 05:46:40 +11:00
return textgpu