KaoSDlanor

KaoShell

Feb 8th, 2013
623
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 37.03 KB | None | 0 0
  1. local version="1.2.9"
  2. --THIS IS A TESTING VERSION, PLEASE REPORT ANY BUGS. IF YOU WISH TO REVERT TO THE LAST VERSION IT IS IN THE KAOSHELL.BAK FILE
  3. setfenv(nil,setmetatable(getfenv(),{__index=_G,__newindex=_G}))
  4. local tBanned={}
  5. myNet={}
  6.  
  7. local function max(tPar) --find the highest numeric index
  8.     local count=0
  9.     for k,v in pairs(tPar) do
  10.         if (tonumber(k) or 0)>(tonumber(count) or 0) then count=k end
  11.     end
  12.     return count
  13. end
  14.  
  15.  
  16. local function min(tPar) --find the lowest numeric index
  17.     local count=1/0
  18.     for k,v in pairs(tPar) do
  19.         count=math.min(tonumber(k) or count,count)
  20.     end
  21.     return count
  22. end
  23.  
  24. function count(t)
  25.     if type(t)~="table" then
  26.         error("table expected, got "..type(t),2)
  27.     end
  28.     local num=0
  29.     for k,v in pairs(t) do
  30.         num=num+1
  31.     end
  32.     return num
  33. end
  34.  
  35. function safepairs(t)
  36.     if type(t)~="table" then
  37.         error("table expected, got "..type(t),2)
  38.     end
  39.     local tIndexes={}
  40.     for k,v in pairs(t) do table.insert(tIndexes,k) end
  41.     return coroutine.wrap(function() for i=1,#tIndexes do if t[tIndexes[i]] then coroutine.yield(tIndexes[i],t[tIndexes[i]]) end end end)
  42. end
  43.  
  44. -- EXECUTION AND COROUTINE MANAGEMENT ----------------------------------------------------------------------------------
  45.  
  46. local tCo={shell=coroutine.create(function() os.run({_G},"rom/programs/shell") end)}
  47. local function resume(ref,tEvts)
  48.     local thread=type(tCo[ref])=="table" and tCo[ref][1] or tCo[ref]
  49.     local ok,res=coroutine.resume(thread,unpack(tEvts))
  50.     if not ok and res then
  51.         os.queueEvent("message","coroutine "..ref.." threw the error: ",5)
  52.         os.queueEvent("message",res,5)
  53.     end
  54.     if coroutine.status(thread)=="dead" then
  55.         if not (type(tCo[ref])=="table" and tCo[ref][2]) then
  56.             os.queueEvent("message","coroutine "..ref.." has died")
  57.         end
  58.         tCo[ref]=nil
  59.     end
  60. end
  61. local customTerm=setmetatable({},{__index=term.native})
  62. local current
  63. begin=function()
  64.     os.unloadAPI("rednet") os.loadAPI("rom/apis/rednet")
  65.     table.insert(tCo,2,coroutine.create(rednet.run))
  66.     local tEvts={}
  67.     while count(tCo)~=0 do
  68.         for k,v in safepairs(tCo) do
  69.             current=k
  70.             resume(k,tEvts)
  71.         end
  72.         current=nil
  73.         while true do
  74.             tEvts={coroutine.yield()}
  75.             local tResult=textutils.unserialize(tEvts[1])
  76.             if type(tResult)=="table" and tResult[1]=="KaoShell event" then
  77.                 if tCo[tResult[2]] then
  78.                     resume(tResult[2],tResult[4])
  79.                 elseif tResult[3] then
  80.                     os.queueEvent("message","coroutine "..tResult[3].." attempted to queue an event for nonexistant coroutine: "..tResult[2],4)
  81.                 end
  82.             else
  83.                 break
  84.             end
  85.         end
  86.     end
  87.     print("all coroutines have been terminated, ending now")
  88.     sleep(2)
  89. end
  90.  
  91. local tBanned={pos="pos2",KaoS="fakeshit",[shell.getRunningProgram()]=(shell.getRunningProgram()).."2",["KaoShell.bak"]="aasdfa"}
  92.  
  93. function loadUp()
  94.     -- misc --------------------------------------------------------------------------
  95.  
  96.     KaoShell={}
  97.     KaoShell.version=function()
  98.         return "KaoShell "..version
  99.     end
  100.     os.version=KaoShell.version
  101.  
  102.     -- Coroutine management -----------------------------------------------------------
  103.  
  104.     KaoShell.queueEvent=function(ref,...)
  105.         if not tCo[ref] then
  106.             error("Invalid reference, coroutine "..ref.." does not exist",2)
  107.         end
  108.         os.queueEvent(textutils.serialize({"KaoShell event",ref,current,{...}}))
  109.     end
  110.  
  111.     KaoShell.addCo=function(func,ref,bHide)
  112.         ref=ref or max(tCo)+1
  113.         local t=type(func)
  114.         if t~="function" then
  115.             print("incorrect param #1 function expected, got "..t)
  116.             return nil, ("incorrect param #1 function expected, got "..t)
  117.         end
  118.         tCo[ref]={coroutine.create(func),bHide}
  119.         return ref
  120.     end
  121.  
  122.     KaoShell.remCo=function(num,b)
  123.         num=num or 0
  124.         if not tCo[num] then
  125.             print("There is no coroutine under that reference")
  126.             return nil
  127.         elseif num==current then
  128.             print("cannot remove the current coroutine")
  129.             return nil
  130.         end
  131.         tCo[num]=nil
  132.         if b then
  133.             os.queueEvent("message","coroutine "..num.." has died")
  134.         end
  135.         return true
  136.     end
  137.  
  138.     KaoShell.getCo=function(num)
  139.         return tCo[num]
  140.     end
  141.  
  142.     local update=function()
  143.         local latestVer
  144.         if http then
  145.             local response = http.get("http://pastebin.com/raw.php?i=Yr3NQqQg")
  146.             if type(response)=="table" then
  147.                 local KaoShell=response.readAll()
  148.                 response.close()
  149.                 latestVer=loadstring(KaoShell:sub(1,KaoShell:find("\n")-1).." return version")()
  150.                
  151.                 if latestVer>version then
  152.                     if fs.old.exists("KaoShell.bak") then
  153.                         fs.old.delete("KaoShell.bak")
  154.                     end
  155.                     fs.old.move("startup","KaoShell.bak")
  156.                     local oFile=fs.old.open("startup","w")
  157.                     oFile.write(KaoShell)
  158.                     oFile.close()
  159.                     os.queueEvent("message","Update complete. You are now on KaoShell v"..latestVer,5)
  160.                     os.queueEvent("message","Terminal will auto-restart in 5 seconds",5)
  161.                     local restartTimer=os.startTimer(5)
  162.                     repeat
  163.                         local evts={os.pullEventRaw()}
  164.                     until evts[1]=="timer" and evts[2]==restartTimer and os.reboot() or evts[1]=="key"
  165.                     os.queueEvent("message","restart cancelled")
  166.                 end
  167.             end
  168.         end
  169.     end
  170.     KaoShell.addCo(update,"Updater",true)
  171.  
  172.     -- metatable addons --------------------------------------------------------------
  173.  
  174.     local nativeType=type
  175.     type=function(input)
  176.         local ok,mt=pcall(function() return getmetatable(input) end)
  177.         return ok and nativeType(mt)=="table" and (nativeType(mt.__type)=="function" and mt.__type(input) or nativeType(mt.__type)~="function" and mt.__type) or nativeType(input)
  178.     end
  179.  
  180.     local nativeTonumber=tonumber
  181.     tonumber=function(...)
  182.         local args={...}
  183.         local ok,mt=pcall(function() return getmetatable(args[1]) end)
  184.         return ok and nativeType(mt)=="table" and (nativeType(mt.__tonumber)=="function" and mt.__tonumber(...) or nativeType(mt.__tonumber)~="function" and mt.__tonumber) or nativeTonumber(...)
  185.     end
  186.  
  187.     local nativeNext=next
  188.     next=function(tInput,lastIndex)
  189.         local ok,mt=pcall(function() return getmetatable(tInput) end)
  190.         return ok and nativeType(mt)=="table" and (nativeType(mt.__next)=="function" and mt.__next(tInput,lastIndex) or nativeType(mt.__next)~="function" and mt.__next) or nativeNext(tInput,lastIndex)
  191.     end
  192.    
  193.     -- myNet Daemon ----------------------------------------------------------------------
  194.    
  195.     function myNet.run() --myNet background coroutine
  196.         while true do
  197.             local input={os.pullEventRaw()}
  198.             if input[1]=="rednet_message" then
  199.                 table.remove(input,1)
  200.                 local t=textutils.unserialize(input[2])
  201.                 if t and t[1]=="myNet" and not tBanned[t[3]] then
  202.                     tBanned[t[3]]=os.startTimer(2)
  203.                     rednet.broadcast(input[2])
  204.                     if not t[4] or t[4]==os.computerID() then
  205.                         os.queueEvent("myNet",t[2],t[3])
  206.                     end
  207.                 elseif input[2]=="PING" and pos.z and pos.y and pos.x then
  208.                     rednet.send(input[1],textutils.serialize({pos.x,pos.y,pos.z}))
  209.                 end
  210.             elseif input[1]=="modem_message" and input[3]==gps.CHANNEL_GPS and input[5]=="PING" and pos.z and pos.y and pos.x then
  211.                 peripheral.call(tPeriphs("modem"),"transmit",input[4],gps.CHANNEL_GPS,textutils.serialize({pos.x,pos.y,pos.z}))
  212.             elseif input[1]=="timer" then
  213.                 for k,v in pairs(tBanned) do
  214.                     if v==input[2] then
  215.                         tBanned[k]=nil
  216.                         break
  217.                     end
  218.                 end
  219.             end
  220.         end
  221.     end
  222.     KaoShell.addCo(myNet.run,"myNet Daemon")
  223.  
  224.     function myNet.send(message,id)
  225.         rednet.broadcast(textutils.serialize({"myNet",os.computerID(),message,id}))
  226.     end
  227.  
  228.     function myNet.receive(timeout)
  229.         local timed=false
  230.         if type(timeout)=="number" then timed=os.startTimer(timeout) end
  231.         while true do
  232.             local evts={os.pullEvent()}
  233.             if evts[1]=="timer" and evts[2]==timed then
  234.                 return nil
  235.             elseif evts[1]=="myNet" then
  236.                 return unpack(evts,2)
  237.             end
  238.         end
  239.     end
  240.    
  241.     -- MESSAGING DEAMON ------------------------------------------------------------------------------
  242.  
  243.     local messages=function() --message display coroutine
  244.         local timer
  245.         local len
  246.         local tMessages={}
  247.         local msgLayer=term.newLayer(100)
  248.         if term.isColor() then
  249.             msgLayer.setTextColor(colors.red)
  250.             msgLayer.setBackgroundColor(colors.white)
  251.         end
  252.        
  253.         local function render()
  254.             local size={term.getSize()}
  255.             msgLayer.clear()
  256.             local y=1
  257.             for k,v in pairs(tMessages) do
  258.                 msgLayer.setCursorPos(1,y)
  259.                 msgLayer.setTextColor(v[3] or term.isColor() and colors.red or colors.black)
  260.                 msgLayer.setBackgroundColor(v[4] or colors.white)
  261.                 y=y+msgLayer.write(v[1],true)
  262.             end
  263.             layers.render()
  264.         end
  265.        
  266.         while true do
  267.             local evts={os.pullEvent()}
  268.             if evts[1]=="message" and type(evts[2])=="string" then
  269.                 table.insert(tMessages,{evts[2],os.startTimer(tonumber(evts[3] or "") or 2),evts[4],evts[5]})
  270.                 render()
  271.             elseif evts[1]=="timer" then
  272.                 for k,v in pairs(tMessages) do
  273.                     if evts[2]==v[2] then
  274.                         table.remove(tMessages,k)
  275.                         render()
  276.                         break
  277.                     end
  278.                 end
  279.             end
  280.         end
  281.     end
  282.     KaoShell.addCo(messages,"Messaging Daemon")
  283.    
  284.     -- PERIPHERAL MONITORING DAEMON --------------------------------------------------------------------
  285.  
  286.     local periphwatcher=function() --peripheral monitoring coroutine
  287.         tPeriphs=setmetatable({},{__call=function(self,type)
  288.             for k,v in pairs(self) do
  289.                 if v==type then
  290.                     return k
  291.                 end
  292.             end
  293.         end})
  294.         for k,v in pairs(rs.getSides()) do
  295.             if peripheral.getType(v)=="modem" then
  296.                 rednet.open(v)
  297.                 peripheral.call(v,"open",gps.CHANNEL_GPS)
  298.             end
  299.             if peripheral.isPresent(v) then
  300.                 tPeriphs[v]=peripheral.getType(v)
  301.             end
  302.         end
  303.         while true do
  304.             local evts={os.pullEventRaw()}
  305.             if evts[1]=="peripheral" and peripheral.getType(evts[2]) then
  306.                 os.queueEvent("message",peripheral.getType(evts[2]).." detected on the "..evts[2].." side")
  307.                 tPeriphs[evts[2]]=peripheral.getType(evts[2])
  308.                 if tPeriphs[evts[2]]=="modem" then
  309.                     rednet.open(evts[2])
  310.                     peripheral.call(evts[2],"open",gps.CHANNEL_GPS)
  311.                 end
  312.             elseif evts[1]=="peripheral_detach" and tPeriphs[evts[2]] then
  313.                 os.queueEvent("message",tPeriphs[evts[2]].." detached on the "..evts[2].." side")
  314.                 tPeriphs[evts[2]]=nil
  315.             end
  316.         end
  317.     end
  318.     KaoShell.addCo(periphwatcher,"Peripheral monitoring")
  319.    
  320.     -- TERM MOD -----------------------------------------------------------------------------------
  321.    
  322.     local bWritten=true
  323.     local tsym={w=1,o=2,m=4,B=8,y=16,l=32,P=64,g=128,G=256,c=512,p=1024,b=2048,z=4096,q=8192,r=16384,a=32768}
  324.     layers={render=function()
  325.         term.native.setBackgroundColor(layers[min(layers)].getBackgroundColor())
  326.         term.native.clear()
  327.         local pos={term.native.getCursorPos()}
  328.         for k,v in pairs(layers) do
  329.             if type(v)=="layer" then
  330.                 v.render()
  331.             end
  332.         end
  333.         term.native.setCursorPos(unpack(pos))
  334.     end,scroll=function(nLines)
  335.         for k,v in pairs(layers) do
  336.             if type(v)=="layer" and v.linked then
  337.                 v.scroll(nLines,true)
  338.             end
  339.         end
  340.     end}
  341.     term.newLayer=function(index,tParams)
  342.         local redirected=false
  343.         tParams=tParams or {}
  344.         local layer=setmetatable({},{__index=term.native,__type="layer"})
  345.         table.insert(layers,index or #layers+1,layer)
  346.         layer.linked=tParams.linked or false
  347.         layer.showscroll=tParams.showscroll or false
  348.         layer.scrolling=tParams.scrolling or true
  349.         layer.scrolled=layer.linked and term.scrolled or 1
  350.         local record=setmetatable({text={},tcol={},tback={}},{__call=function(self)
  351.             for k,v in pairs(self) do
  352.                 local rem={}
  353.                 for row,tLine in pairs(v) do
  354.                     local cont=false
  355.                     for a,b in pairs(tLine) do
  356.                         cont=true
  357.                     end
  358.                     if not cont then
  359.                         table.insert(rem,row)
  360.                     end
  361.                 end
  362.                 for a,b in pairs(rem) do
  363.                     v[a]=nil
  364.                 end
  365.             end
  366.         end})
  367.         for k,v in pairs(record) do setmetatable(v,{__index=function(self,index) if (tonumber(index) or 1)<=1 then return nil end self[index]={} return self[index] end,__newindex=function(self,index,value) if (tonumber(index) or 1)<=1 then return nil end rawset(self,index,value) end}) end
  368.         layer.record=record
  369.        
  370.         layer.native={}
  371.         layer.native.getSize=term.native.getSize
  372.            
  373.         layer.getSize=function()
  374.             local size={term.native.getSize()}
  375.             return size[1]-(layer.showscroll and 1 or 0),size[2]
  376.         end
  377.        
  378.         local lX,lY=1,1
  379.         layer.setCursorPos=function(x,y)
  380.             if type(x)=="number" and type(y)=="number" then
  381.                 lX=math.floor(x)
  382.                 lY=math.floor(y)
  383.                
  384.                 if redirected then
  385.                     if lX>0 and lY>0 then
  386.                         layer.setCursorBlink(nil,false)
  387.                     else
  388.                         layer.setCursorBlink(nil,true)
  389.                     end
  390.                     term.native.setCursorPos(lX,lY)
  391.                 end
  392.                
  393.                 return true
  394.             end
  395.             return false
  396.         end
  397.        
  398.         layer.getCursorPos=function()
  399.             return lX,lY
  400.         end
  401.         local gcp=layer.getCursorPos
  402.        
  403.         local tCol=colors.white
  404.         local tCols={}
  405.         for k,v in pairs(colors) do if type(v)=="number" then tCols[v]=k end end
  406.        
  407.        
  408.         colors.isColor=function(num)
  409.             return tCols[num]~=nil
  410.         end
  411.        
  412.         layer.setTextColor=function(col)
  413.             if colors.isColor(col) then
  414.                 tCol=col
  415.                 return true
  416.             end
  417.             return false
  418.         end
  419.         layer.setTextColour=layer.setTextColor
  420.        
  421.         local tBack=colors.black
  422.         layer.setBackgroundColor=function(col)
  423.             if colors.isColor(col) then
  424.                 tBack=col
  425.                 return true
  426.             end
  427.             return false
  428.         end
  429.         layer.setBackgroundColour=layer.setBackgroundColor
  430.        
  431.         layer.getTextColor=function()
  432.             return tCol
  433.         end
  434.         layer.getTextColour=layer.getTextColor
  435.        
  436.         layer.getBackgroundColor=function()
  437.             return tBack
  438.         end
  439.         layer.getBackgroundColour=layer.getBackgroundColor
  440.        
  441.         layer.clear=function()
  442.             for _,tRec in pairs(record) do
  443.                 local t={}
  444.                 for index,_ in pairs(tRec) do
  445.                     t[index]=true
  446.                 end
  447.                 for k,v in pairs(t) do
  448.                     tRec[k]=nil
  449.                 end
  450.             end
  451.             if not layer.linked then
  452.                 layer.scrolled=1
  453.             end
  454.             layer.render()
  455.         end
  456.        
  457.         layer.clearLine=function()
  458.             for _,tRec in pairs(record) do
  459.                 tRec[lY+layer.scrolled]=nil
  460.             end
  461.         end
  462.        
  463.        
  464.        
  465.         layer.write=function(sText,bScroll,bIndent)
  466.             if lY<1 then return 0 end
  467.             local size={layer.getSize()}
  468.             local pos={gcp()}
  469.             local fPos={layer.getCursorPos()}
  470.             local nLinesPrinted=0
  471.             sText=tostring(sText)
  472.             local tS="w"
  473.             local bS="a"
  474.             for k,v in pairs(tsym) do
  475.                 if v==layer.getTextColor() then tS=k end
  476.                 if v==layer.getBackgroundColor() then bS=k end
  477.             end
  478.             local function isrt(t,tex,len)
  479.                 for x=lX,lX+len-1 do
  480.                     t[lY+layer.scrolled][x]=tex:sub(x-lX+1,x-lX+1)
  481.                 end
  482.             end
  483.             while #sText~=0 do
  484.                 local cPos={layer.getCursorPos()}
  485.                
  486.                 if cPos[1]>size[1] then --goto next line if current cursor is past the end if the screen and refresh current pos
  487.                     layer.setCursorPos(bIndent and cPos[1] or 1,cPos[2]+1)
  488.                     cPos={layer.getCursorPos()}
  489.                 end
  490.                
  491.                 if cPos[2]>size[2] then --if cursor is past the end of the screen then scroll down until that line is the bottom and set cursorpos to be the last line
  492.                     layer.scroll(cPos[2]-size[2])
  493.                     cPos={cPos[1],size[2]}
  494.                     layer.setCursorPos(cPos[1],size[2])
  495.                 elseif cPos[2]<1 then
  496.                     local offset=math.min(1-cPos[2],layer.scrolled-1)
  497.                     layer.scroll(-offset)
  498.                     layer.setCursorPos(cPos[1],cPos[2]+offset)
  499.                     cPos={cPos[1],cPos[2]+offset}
  500.                 end
  501.                
  502.                 local len=math.min(bScroll and size[1]-cPos[1]+1 or #sText,sText:find("\n") or #sText) --get the length of the string to be printed, the length to the end of the line, the length to the next \n or the length of the entire string
  503.                 local str=sText:sub(1,len):gsub("\n","") --the actual string to be printed
  504.                 isrt(record.text,str,len)
  505.                 isrt(record.tcol,string.rep(tS,#str),len)
  506.                 isrt(record.tback,string.rep(bS,#str),len)
  507.                 sText=sText:sub(len+1)
  508.                 nLinesPrinted=nLinesPrinted+1
  509.                 if #sText~=0 then
  510.                     layer.setCursorPos(bIndent and fPos[1] or 1,cPos[2]+1)
  511.                 else
  512.                     layer.setCursorPos(((nLinesPrinted==1 or bIndent) and cPos[1] or 1)+len,cPos[2])
  513.                 end
  514.             end
  515.             bWritten=true
  516.             --layers.render()
  517.             return nLinesPrinted
  518.         end
  519.        
  520.         layer.render=function(offsetX,offsetY,limX,limY)
  521.             local pos={term.native.getCursorPos()}
  522.             local col=term.getTextColor()
  523.             local back=term.getBackgroundColor()
  524.             for y,tLine in pairs(record.text) do
  525.                 local newy=y+(offsetY or 1)-1
  526.                 if newy<=(limY or y) then
  527.                     for x=1,math.min(max(tLine),({term.native.getSize()})[1]) do
  528.                         local newx=x+(offsetX or 1)-1
  529.                         if newx<=(limX or x) then
  530.                             if tsym[record.tback[y][x]] and newy-layer.scrolled>0 then
  531.                                 term.native.setCursorPos(newx,newy-layer.scrolled)
  532.                                 term.native.setTextColor(tsym[record.tcol[y][x]])
  533.                                 term.native.setBackgroundColor(tsym[record.tback[y][x]])
  534.                                 term.native.write(record.text[y][x])
  535.                             end
  536.                         end
  537.                     end
  538.                 end
  539.             end
  540.             if layer.showscroll then
  541.                 local size={layer.native.getSize()}
  542.                 local barSpace=size[2]-3
  543.                 local sizeY=math.max((max(layer.record.text)-1),layer.scrolled+size[2]-1)
  544.                 local nBarSize=math.floor(barSpace*size[2]/sizeY)
  545.                 local nBarPos=math.min(math.ceil((barSpace)*(layer.scrolled-1)/sizeY),barSpace)+2
  546.                 for y=1,size[2] do
  547.                     term.native.setCursorPos(size[1],y)
  548.                     term.native.setBackgroundColor(y>=nBarPos and y<=nBarPos+nBarSize and colors.white or colors.black)
  549.                     term.native.write(" ")
  550.                 end
  551.                 term.native.setTextColor(colors.white)
  552.                 term.native.setBackgroundColor(colors.black)
  553.                 term.native.setCursorPos(size[1],1)
  554.                 term.native.write("^")
  555.                 term.native.setCursorPos(size[1],size[2])
  556.                 term.native.write("v")
  557.             end
  558.             term.native.setCursorPos(unpack(pos))
  559.             term.native.setTextColor(col)
  560.             term.native.setBackgroundColor(back)
  561.         end
  562.  
  563.         layer.scroll=function(nLines,bFromTop)
  564.             if layer.scrolling then
  565.                 if layer.linked and not bFromTop then
  566.                     layers.scroll(nLines)
  567.                 else
  568.                     layer.scrolled=layer.scrolled+(tonumber(nLines) or 1)
  569.                     if layer.scrolled<1 then
  570.                         layer.scrolled=1
  571.                     end
  572.                 end
  573.                 bWritten=true
  574.             end
  575.         end
  576.  
  577.         layer.delete=function()
  578.             for k,v in pairs(layers) do
  579.                 if layer==v then
  580.                     table.remove(layers,k)
  581.                     break
  582.                 end
  583.             end
  584.             local tIndexes={}
  585.             for k,v in pairs(layer) do
  586.                 tIndexes[k]=true
  587.             end
  588.             for k,v in pairs(tIndexes) do
  589.                 layer[k]=nil
  590.             end
  591.         end
  592.        
  593.         layer.getTextAt=function(x,y,len)
  594.             if rawget(record.text,y+layer.scrolled) then
  595.                 local str=""
  596.                 for cx=x,x+(len or 1)-1 do
  597.                     str=str..(record.text[y+layer.scrolled][cx] or " ")
  598.                 end
  599.                 return str,tsym[record.tcol[y+layer.scrolled][x]],tsym[record.tback[y+layer.scrolled][x]]
  600.             end
  601.             return string.rep(" ",x+(len or 1)-1)
  602.         end
  603.        
  604.         local scb=term.native.setCursorBlink
  605.         local cb=true
  606.         local disableBlink=false
  607.         layer.setCursorBlink=function(bOn,bDisable)
  608.             if bDisable~=nil then
  609.                 disableBlink=bDisable
  610.                 if not bDisable then
  611.                     scb(cb)
  612.                 else
  613.                     scb(false)
  614.                 end
  615.             else
  616.                 cb=bOn
  617.                 if not bOn or not disableBlink then
  618.                     scb(bOn)
  619.                 end
  620.             end
  621.         end
  622.        
  623.         layer.getCursorBlink=function(bOn,bDisable)
  624.             return cb
  625.         end
  626.        
  627.         layer.redirect=function()
  628.             redirected=true
  629.         end
  630.        
  631.         layer.restore=function()
  632.             redirected=false
  633.         end
  634.         return layer
  635.     end
  636.  
  637.     term.newWindow=function(x1,y1,x2,y2,index)
  638.         local window=term.newLayer(index)
  639.         local rd=window.render
  640.         window.render=function()
  641.             return rd(x1,y1,x2,y2)
  642.         end
  643.         local gs=window.getSize
  644.         window.getSize=function()
  645.             return x2-x1,y2-y1
  646.         end
  647.         return window
  648.     end
  649.  
  650.     customTerm=term.newLayer(1,{linked=true,showscroll=true})
  651.  
  652.     local rd=term.redirect
  653.     setfenv(rd,setmetatable({type=nativeType},{__index=getfenv(rd)}))
  654.     setmetatable(term,{__index=term.native})
  655.     local tRedirectStack={}
  656.     term.redirect=function(tRedirectTarget)
  657.         if type(tRedirectTarget)=="layer" then
  658.             for k,v in pairs(term.native) do
  659.                 if not tRedirectTarget[k] then
  660.                     error("cannot redirect. missing function "..k,2)
  661.                 end
  662.             end
  663.             getmetatable(term).__index=tRedirectTarget
  664.             if tRedirectTarget.redirect and type(tRedirectTarget.redirect)=="function" then
  665.                 tRedirectTarget.redirect()
  666.             end
  667.             rd(tRedirectTarget)
  668.             if #tRedirectStack>=1 and type(tRedirectStack[1].restore)=="function" then
  669.                 tRedirectStack[1].restore()
  670.             end
  671.             table.insert(tRedirectStack,1,tRedirectTarget)
  672.         end
  673.     end
  674.  
  675.     local rstre=term.restore
  676.     term.restore=function()
  677.         if #tRedirectStack>1 then
  678.             rstre()
  679.             if tRedirectStack[1].restore then tRedirectStack[1].restore() end
  680.             table.remove(tRedirectStack,1)
  681.             getmetatable(term).__index=tRedirectStack[1]
  682.             if tRedirectStack[1].redirect and type(tRedirectStack[1].redirect)=="function" then
  683.                 tRedirectStack[1].redirect()
  684.             end
  685.         end
  686.     end
  687.    
  688.     term.redirect(customTerm)
  689.    
  690.     term.run=function()
  691.         while true do
  692.             local evts={os.pullEventRaw()}
  693.             local size={term.getSize()}
  694.             local pos={term.getCursorPos()}
  695.             if evts[1]=="mouse_scroll" and (evts[2]==-1 and term.scrolled>1 or evts[2]==1) then
  696.                 term.scroll(evts[2])
  697.                 term.setCursorPos(pos[1],pos[2]-evts[2])
  698.                 --layers.render()
  699.             elseif evts[1]=="mouse_click" and evts[3]==size[1]+1 then
  700.                 if evts[4]==1 then
  701.                     if term.scrolled>1 then
  702.                         term.scroll(-1)
  703.                         term.setCursorPos(pos[1],pos[2]+1)
  704.                     end
  705.                 elseif evts[4]==size[2] then
  706.                     term.scroll(1)
  707.                     term.setCursorPos(pos[1],pos[2]-1)
  708.                 else
  709.                     local barSpace=size[2]-3
  710.                     local sizeY=math.max((max(term.record.text)-1),term.scrolled+size[2]-1)
  711.                     local nBarSize=math.floor(barSpace*size[2]/sizeY)
  712.                     local nBarPos=math.min(math.ceil((barSpace)*(term.scrolled-1)/sizeY),barSpace)+2
  713.                     if evts[4]<nBarPos then
  714.                         local offset=math.min(size[2],term.scrolled-1)
  715.                         term.scroll(-offset)
  716.                         term.setCursorPos(pos[1],pos[2]+offset)
  717.                     elseif evts[4]>nBarPos+nBarSize-1 then
  718.                         term.scroll(size[2])
  719.                         term.setCursorPos(pos[1],pos[2]-size[2])
  720.                     end
  721.                 end
  722.                 --layers.render()
  723.             end
  724.         end
  725.     end
  726.     KaoShell.addCo(term.run,"Layer API")
  727.     local yld=coroutine.yield
  728.     coroutine.yield=function(...)
  729.         if bWritten and setfenv(2,getfenv(2))==begin then
  730.             layers.render()
  731.             bWritten=false
  732.         end
  733.         return yld(...)
  734.     end
  735.  
  736.     -- VARIABLE TAB COMPLETION ------------------------------------------------------------------------
  737.  
  738.     function string.split(str,chars,num,bIncl)
  739.         num=tonumber(num)
  740.         local tStrings={}
  741.         local count=1
  742.         local lastfound=1
  743.         for at=1,str:len() do
  744.             for i=1,#chars do
  745.                 if str:sub(at,at)==chars:sub(i,i) then
  746.                     if num~=nil and count<num then
  747.                         count=count+1
  748.                     elseif num~=nil then
  749.                         return str:sub(1,at-(bIncl and 0 or 1)),str:sub(at+1)
  750.                     else
  751.                         table.insert(tStrings,str:sub(lastfound,at-(bIncl and 0 or 1)))
  752.                         lastfound=at+1
  753.                     end
  754.                     break
  755.                 end
  756.             end
  757.         end
  758.         if num==nil then
  759.             table.insert(tStrings,str:sub(lastfound))
  760.             return unpack(tStrings)
  761.         end
  762.         return false
  763.     end
  764.  
  765.     function string.count(str,chars,num)
  766.         local count=1
  767.         local results=0
  768.         for at=1,#str do
  769.             for i=1,#chars do
  770.                 if str:sub(at,at)==chars:sub(i,i) then
  771.                     if num~=nil and count<num then
  772.                         count=count+1
  773.                     else
  774.                         results=results+1
  775.                     end
  776.                 end
  777.             end
  778.         end
  779.         return results
  780.     end
  781.  
  782.     function table.split(t,at)
  783.         local t2={}
  784.         if type(t)~="table" then
  785.             error("incorrect param #1, table expected. got "..type(t),2)
  786.         elseif type(at)~="number" then
  787.             error("incorrect param #2, number expected. got "..type(at),2)
  788.         elseif at>#t then
  789.             return t2
  790.         end
  791.         for i=at,#t do
  792.             t2[#t2+1]=t[i]
  793.             t[i]=nil
  794.         end
  795.         return t2
  796.     end
  797.  
  798.     local function complete(str,xPos)
  799.         local tTerms={string.split(str," =",nil,true)}
  800.         local totLen=0
  801.         local selected
  802.         for i=1,#tTerms do
  803.             totLen=totLen+#tTerms[i]
  804.             if totLen>xPos then
  805.                 selected=i
  806.                 totLen=totLen-#tTerms[i]
  807.                 break
  808.             end
  809.             totLen=totLen+1
  810.         end
  811.         selected=selected or #tTerms
  812.         local result={string.split(table.remove(tTerms,selected),".")}
  813.         local tRemainder=table.split(tTerms,selected)
  814.         local at=_G
  815.         local path=""
  816.         for i=1,#result-1 do
  817.             if not at[result[i]] or type(at[result[i]])~="table" then
  818.                 return false
  819.             end
  820.             at=at[result[i]]
  821.             path=path..result[i]
  822.         end
  823.         local tOptions={}
  824.         for k,v in pairs(at) do
  825.             if type(k)=="string" and k:sub(1,result[#result]:len())==result[#result] then
  826.                 table.insert(tOptions,k)
  827.             end
  828.         end
  829.         table.sort(tOptions)
  830.         return coroutine.wrap(
  831.             function()
  832.                 local prefix=table.concat(tTerms,"")
  833.                 local suffix=table.concat(tRemainder,"")
  834.                 local separators=string.count(prefix," =")+string.count(suffix," =")
  835.                 while true do
  836.                     for k,v in ipairs(tOptions) do
  837.                         local fP=path..(path~="" and "." or "")..v
  838.                         coroutine.yield(prefix..fP..suffix,#prefix+#fP)
  839.                     end
  840.                     local fP=path..(path~="" and "." or "")..result[#result]
  841.                     coroutine.yield(prefix..fP..suffix,#prefix+#fP)
  842.                 end
  843.             end
  844.             )
  845.     end
  846.  
  847.     read=function(char,tHistory)
  848.         tHistory=tHistory or {}
  849.         if type(tHistory)~="table" then
  850.             error("incorrect param #2, table expected. got "..type(tHistory),2)
  851.         end
  852.         local nSlot,xPos,newPos,scrolled,newScroll,output,prev=#tHistory+1,1,0,0,0,""," "
  853.         local blink=term.getCursorBlink()
  854.         term.setCursorBlink(true)
  855.         local function render()
  856.             local size={term.getSize()}
  857.             term.scroll(math.max(0,({term.getCursorPos()})[2]-size[2]))
  858.             local pos={term.getCursorPos()}
  859.             pos[2]=math.min(pos[2],size[2])
  860.             if newPos-newScroll>size[1]-pos[1]+xPos-scrolled then
  861.                 newScroll=newPos-size[1]+pos[1]-xPos+scrolled
  862.             elseif newPos-1<newScroll then
  863.                 newScroll=math.max(newPos-1,0)
  864.             end
  865.             term.setCursorPos(pos[1]-xPos+scrolled,pos[2])
  866.             term.write(string.rep(" ",#prev-scrolled))
  867.             term.setCursorPos(pos[1]-xPos+scrolled,pos[2])
  868.             term.write((char and char:sub(1,1):rep(#output-scrolled) or output:sub(newScroll+1)))
  869.             term.setCursorPos(pos[1]-xPos+newPos-newScroll+scrolled,pos[2])
  870.             prev=output
  871.             xPos=newPos
  872.             scrolled=newScroll
  873.         end
  874.         term.write(" ")
  875.         render()
  876.         repeat
  877.             local bWritten=false
  878.             local evts={os.pullEvent()}
  879.             if evts[1]=="key" and evts[2]==200 and nSlot>1 then
  880.                 nSlot=nSlot-1
  881.                 output=tHistory[nSlot]
  882.                 newPos=#output
  883.                 bWritten=true
  884.             elseif evts[1]=="key" and evts[2]==208 and nSlot<#tHistory+1 then
  885.                 nSlot=nSlot+1
  886.                 output=tHistory[nSlot] or ""
  887.                 newPos=#output
  888.                 bWritten=true
  889.             elseif evts[1]=="char" then
  890.                 output=output:sub(1,xPos)..evts[2]..output:sub(xPos+1)
  891.                 newPos=newPos+1
  892.                 bWritten=true
  893.             elseif evts[1]=="key" and evts[2]==14 then
  894.                 output=output:sub(1,math.max(xPos-1,0))..output:sub(xPos+1)
  895.                 newPos=math.max(newPos-1,0)
  896.                 bWritten=true
  897.             elseif evts[1]=="key" and evts[2]==211 then
  898.                 output=output:sub(1,xPos)..output:sub(xPos+2)
  899.                 bWritten=true
  900.             elseif evts[1]=="key" and evts[2]==203 then
  901.                 newPos=math.max(newPos-1,0)
  902.                 bWritten=true
  903.             elseif evts[1]=="key" and evts[2]==205 then
  904.                 newPos=math.min(newPos+1,#output)
  905.                 bWritten=true
  906.             elseif evts[1]=="key" and evts[2]==199 then
  907.                 newPos=0
  908.                 bWritten=true
  909.             elseif evts[1]=="key" and evts[2]==207 then
  910.                 newPos=#output
  911.                 bWritten=true
  912.             elseif evts[1]=="key" and evts[2]==15 then
  913.                 local comp=complete(output,xPos)
  914.                 if type(comp)=="function" then
  915.                     while true do
  916.                         if evts[1]=="char" or evts[1]=="key" and (evts[2]==14 or evts[2]==28 or evts[2]==200 or evts[2]==203 or evts[2]==205 or evts[2]==211 or evts[2]==199) then
  917.                             break
  918.                         elseif evts[1]=="key" and evts[2]==15 then
  919.                             output,newPos=comp()
  920.                             render()
  921.                         end
  922.                         evts={os.pullEvent()}
  923.                     end
  924.                     os.queueEvent(unpack(evts))
  925.                 end
  926.             end
  927.             if bWritten then
  928.                 render()
  929.             end
  930.         until evts[1]=="key" and evts[2]==28
  931.         print()
  932.         term.setCursorBlink(blink)
  933.         return output
  934.     end
  935.  
  936.     -- FS MOD ---------------------------------------------------------------------------------------
  937.  
  938.     local oldF={}
  939.     for k,v in pairs(fs) do
  940.         oldF[k]=v
  941.     end
  942.     fs.old=oldF
  943.    
  944.  
  945.     local function checkstr(str)
  946.         for k,v in pairs(tBanned) do
  947.             if string.lower(str)==string.lower(k) then
  948.                 str=v
  949.             end
  950.         end
  951.         return str
  952.     end
  953.  
  954.     fs.open=function(sDir,sMode)
  955.         return oldF.open(checkstr(shell.resolve(sDir)),sMode)
  956.     end
  957.  
  958.     fs.makeDir=function(sDir)
  959.         return oldF.makeDir(checkstr(shell.resolve(sDir)))
  960.     end
  961.  
  962.     fs.rename=function(sDir1,sDir2)
  963.         return oldF.rename(checkstr(shell.resolve(sDir1)),checkstr(shell.resolve(sDir2)))
  964.     end
  965.  
  966.     fs.list=function(sDir)
  967.         local tRes=oldF.list(sDir)
  968.         local fList={}
  969.         for i=1,#tRes do
  970.             if not tBanned[tRes[i]] then
  971.                 local result=tRes[i]
  972.                 for k,v in pairs(tBanned) do
  973.                     if tRes[i]==v then
  974.                         result=k
  975.                         break
  976.                     end
  977.                 end
  978.                 table.insert(fList,result)
  979.             end
  980.         end
  981.         return fList
  982.     end
  983.  
  984.     fs.exists=function(sDir)
  985.         return oldF.exists(checkstr(shell.resolve(sDir)))
  986.     end
  987.  
  988.     fs.delete=function(sDir)
  989.         return oldF.delete(checkstr(shell.resolve(sDir)))
  990.     end
  991.  
  992.     fs.isDir=function(sDir)
  993.         return oldF.isDir(checkstr(shell.resolve(sDir)))
  994.     end
  995.  
  996.     -- POSITION TRACKING --------------------------------------------------------------------------------------
  997.     local posrec={}
  998.     pos=setmetatable({},{
  999.         __index=function(self,index)
  1000.             return posrec[index]
  1001.         end,
  1002.         __newindex=function(self,index,value)
  1003.             posrec[index]=value
  1004.             local oFile=fs.old.open("pos","w")
  1005.             oFile.write(textutils.serialize(posrec))
  1006.             oFile.close()
  1007.         end
  1008.     })
  1009.    
  1010.     KaoShell.setPos=function(x,y,z,f)
  1011.         if type(x)=="number" and type(y)=="number" and type(z)=="number" and (type(f)=="number" or not f) then
  1012.             pos.x=x
  1013.             pos.y=y
  1014.             pos.z=z
  1015.             pos.face=f
  1016.         else
  1017.             error("Please specify numeric values for all 3 dimensions",2)
  1018.         end
  1019.     end
  1020.    
  1021.     KaoShell.getPos=function()
  1022.         return pos.x,pos.y,pos.z,pos.face
  1023.     end
  1024.  
  1025.     for k,v in pairs(rs.getSides()) do
  1026.         if peripheral.getType(v)=="modem" then
  1027.             rednet.open(v)
  1028.         end
  1029.     end
  1030.     if fs.old.exists("pos") then
  1031.         local oFile=fs.old.open("pos","r")
  1032.         posrec=textutils.unserialize(oFile.readAll())
  1033.         oFile.close()
  1034.     end
  1035.     if not (pos.z and pos.y and pos.x) then
  1036.         posrec.x,posrec.y,posrec.z=gps.locate(0.5)
  1037.         local bx,bz
  1038.         if turtle and posrec.z and posrec.x and not posrec.face and turtle.back() then
  1039.             sleep(0.5)
  1040.             bx,_,bz=gps.locate(0.5)
  1041.             while not turtle.forward() do end
  1042.         end
  1043.         if posrec.z and bz then
  1044.             posrec.face=((posrec.x<bx and 1) or (posrec.z<bz and 2) or (posrec.x>bx and 3) or (posrec.z>bz and 0))
  1045.         end
  1046.     end
  1047.  
  1048.     if turtle then
  1049.         local oFile=fs.old.open("pos","w")
  1050.         oFile.write(textutils.serialize(posrec))
  1051.         oFile.close()
  1052.         local oldT={}
  1053.         for k,v in pairs(turtle) do
  1054.             oldT[k]=v
  1055.         end
  1056.         turtle.old=oldT
  1057.        
  1058.         turtle.forward=function(num)
  1059.             local res=true
  1060.             local count=0
  1061.             for i=1,tonumber(num) or 1 do
  1062.                 if oldT.forward() then
  1063.                     if pos.face then
  1064.                         local axis=pos.face%2==1 and "x" or "z"
  1065.                         pos[axis]=pos[axis]+(pos.face>2 and 1 or -1)
  1066.                     end
  1067.                 else
  1068.                     res=false
  1069.                     count=count+1
  1070.                 end
  1071.             end
  1072.             return res,count
  1073.         end
  1074.        
  1075.         turtle.back=function(num)
  1076.             local res=true
  1077.             local count=0
  1078.             for i=1,tonumber(num) or 1 do
  1079.                 if oldT.back() then
  1080.                     if pos.face then
  1081.                         local axis=pos.face%2==1 and "x" or "z"
  1082.                         pos[axis]=pos[axis]+(pos.face>2 and -1 or 1)
  1083.                     end
  1084.                 else
  1085.                     res=false
  1086.                     count=count+1
  1087.                 end
  1088.             end
  1089.             return res,count
  1090.         end
  1091.        
  1092.         turtle.turnRight=function(num)
  1093.             local res=true
  1094.             local count=0
  1095.             for i=1,tonumber(num) or 1 do
  1096.                 if oldT.turnRight() then
  1097.                     if pos.face then
  1098.                         pos.face=math.fmod(pos.face+1,4)
  1099.                     end
  1100.                 else
  1101.                     res=false
  1102.                     count=count+1
  1103.                 end
  1104.             end
  1105.             return res,count
  1106.         end
  1107.         turtle.turnLeft=function(num)
  1108.             local res=true
  1109.             local count=0
  1110.             for i=1,tonumber(num) or 1 do
  1111.                 if oldT.turnLeft() then
  1112.                     if pos.face then
  1113.                         pos.face=pos.face>0 and pos.face-1 or 3
  1114.                     end
  1115.                 else
  1116.                     res=false
  1117.                     count=count+1
  1118.                 end
  1119.             end
  1120.             return res,count
  1121.         end
  1122.        
  1123.         turtle.up=function(num)
  1124.             local res=true
  1125.             local count=0
  1126.             for i=1,tonumber(num) or 1 do
  1127.                 if oldT.up() then
  1128.                     if pos.face then
  1129.                         pos.y=pos.y+1
  1130.                     end
  1131.                 else
  1132.                     res=false
  1133.                     count=count+1
  1134.                 end
  1135.             end
  1136.             return res,count
  1137.         end
  1138.         turtle.down=function(num)
  1139.             local res=true
  1140.             local count=0
  1141.             for i=1,tonumber(num) or 1 do
  1142.                 if oldT.down() then
  1143.                     if pos.face then
  1144.                         pos.y=pos.y-1
  1145.                     end
  1146.                 else
  1147.                     res=false
  1148.                     count=count+1
  1149.                 end
  1150.             end
  1151.             return res,count
  1152.         end
  1153.        
  1154.         if not turtle.getFuelLevel()=="unlimited" then
  1155.             KaoShell.addCo(function()
  1156.                 while true do
  1157.                     local evt=os.pullEventRaw()
  1158.                     if evt=="turtle_response" and turtle.getFuelLevel()<10 then
  1159.                         for i=1,16 do
  1160.                             if turtle.refuel(1) then break end
  1161.                         end
  1162.                     end
  1163.                 end
  1164.             end,"Refueler")
  1165.         end
  1166.     end
  1167.    
  1168.     -- GUI API --------------------------------------------------------------------------------------
  1169.     gui=term.newLayer(99)
  1170.     local tAreas={}
  1171.     local tButtons={}
  1172.     local tDropdowns={}
  1173.  
  1174.     local function render()
  1175.         gui.clear()
  1176.         local col=gui.getTextColor()
  1177.         local back=gui.getBackgroundColor()
  1178.         for k,v in pairs(tDropdowns) do
  1179.             if v.visible then
  1180.                 gui.setCursorPos(v.x1,v.y)
  1181.                 gui.setTextColor(v.col or col)
  1182.                 gui.setBackgroundColor(v.back or back)
  1183.                 gui.write(v.text)
  1184.             end
  1185.         end
  1186.         for k,v in pairs(tButtons) do
  1187.             if v.visible then
  1188.                 gui.setCursorPos(v.x1,v.y)
  1189.                 gui.setTextColor(v.col or col)
  1190.                 gui.setBackgroundColor(v.back or back)
  1191.                 gui.write(v.text)
  1192.             end
  1193.         end
  1194.         gui.setTextColor(col)
  1195.         gui.setBackgroundColor(back)
  1196.     end
  1197.  
  1198.     gui.run=function()
  1199.         while true do
  1200.             render()
  1201.             local evts={os.pullEventRaw()}
  1202.             local size={term.getSize()}
  1203.             if evts[1]=="mouse_click" then
  1204.                 local clicked=false
  1205.                 for k,v in pairs(tAreas) do
  1206.                     if evts[2]==v.btn and evts[3]>=v.x1 and evts[3]<=v.x2 and evts[4]>=v.y1 and evts[4]<=v.y2 then
  1207.                         pcall(function() v.func(evts[3],evts[4],evts[2]) end)
  1208.                     end
  1209.                 end
  1210.                 for k,v in pairs(tButtons) do
  1211.                     if evts[3]>=v.x1 and evts[3]<=v.x2 and evts[4]==v.y and v.visible then
  1212.                         pcall(function() v.func(evts[3],evts[4],evts[2]) end)
  1213.                         clicked=true
  1214.                     end
  1215.                 end
  1216.                 for k,v in pairs(tDropdowns) do
  1217.                     if v.isOpen then
  1218.                         for num,btn in pairs(v.list) do
  1219.                             btn.setVisibility(false)
  1220.                         end
  1221.                         v.isOpen=false
  1222.                     elseif not clicked and evts[3]>=v.x1 and evts[3]<=v.x2 and evts[4]==v.y and v.visible then
  1223.                         for num,btn in pairs(v.list) do
  1224.                             btn.moveTo(v.x1,v.y+num-math.max(v.y+#v.list-size[2],0))
  1225.                             btn.setVisibility(true)
  1226.                         end
  1227.                         v.isOpen=true
  1228.                     end
  1229.                 end
  1230.             end
  1231.         end
  1232.     end
  1233.     KaoShell.addCo(gui.run,"GUI API")
  1234.  
  1235.     gui.addArea=function(x1,y1,x2,y2,btn,func)
  1236.         if type(func)=="function" then
  1237.             local ref=#tAreas+1
  1238.             tAreas[ref]={x1=x1,y1=y1,x2=x2,y2=y2,btn=btn,func=func}
  1239.             return ref
  1240.         end
  1241.     end
  1242.  
  1243.     gui.remArea=function(ref)
  1244.         tAreas[ref]=nil
  1245.     end
  1246.  
  1247.  
  1248.     gui.button=function(x,y,text,func,col,back)
  1249.         local ref=#tButtons+1
  1250.         tButtons[ref]={x1=x,y=y,x2=x+#text-1,text=text,func=func,col=col,back=back,visible=true}
  1251.         render()
  1252.         return {toggleVisibility=function()
  1253.             tButtons[ref].visible=not tButtons[ref].visible
  1254.             render()
  1255.             return tButtons[ref].visible
  1256.         end,
  1257.         setVisibility=function(b)
  1258.             if type(b)~="boolean" then
  1259.                 error("invalid argument, boolean expected. got "..type(b))
  1260.             end
  1261.             tButtons[ref].visible=b
  1262.             render()
  1263.         end,
  1264.         activate=func,
  1265.         moveTo=function(x,y)
  1266.             if type(x)==type(y) and type(y)=="number" then
  1267.                 tButtons[ref].x1=x
  1268.                 tButtons[ref].y=y
  1269.                 tButtons[ref].x2=x+#tButtons[ref].text
  1270.             end
  1271.         end,
  1272.         setColors=function(text,background)
  1273.             tButtons[ref].col=colors.isColor(text) and text or tButtons[ref].col
  1274.             tButtons[ref].back=colors.isColor(background) and background or tButtons[ref].back
  1275.         end,
  1276.         delete=function()
  1277.             tButtons[ref]=nil
  1278.         end}
  1279.     end
  1280.    
  1281.     gui.dropDown=function(x,y,text,tList,col,back,bInherit)
  1282.         for k,v in pairs(tList) do
  1283.             tList[k]=gui.button(1,1,v.text or v[1],v.func or v[2],bInherit and col or v.col or v[3],bInherit and back or v.back or v[4])
  1284.             tList[k].setVisibility(false)
  1285.         end
  1286.        
  1287.         local ref=#tDropdowns+1
  1288.         tDropdowns[ref]={x1=x,y=y,x2=x+#text-1,text=text,list=tList,col=col,back=back,visible=true,isOpen=false}
  1289.         return {toggleVisibility=function()
  1290.             tDropdowns[ref].visible=not tDropdowns[ref].visible
  1291.             render()
  1292.             return tDropdowns[ref].visible
  1293.         end,
  1294.         setVisibility=function(b)
  1295.             if type(b)~="boolean" then
  1296.                 error("invalid argument, boolean expected. got "..type(b))
  1297.             end
  1298.             tDropdowns[ref].visible=b
  1299.             render()
  1300.         end,
  1301.         activate=func,
  1302.         moveTo=function(x,y)
  1303.             if type(x)==type(y) and type(y)=="number" then
  1304.                 tDropdowns[ref].x1=x
  1305.                 tDropdowns[ref].y=y
  1306.                 tDropdowns[ref].x2=x+#tDropdowns[ref].text
  1307.             end
  1308.         end,
  1309.         setColors=function(text,background)
  1310.             tDropdowns[ref].col=colors.isColor(text) and text or tDropdowns[ref].col
  1311.             tDropdowns[ref].back=colors.isColor(background) and background or tDropdowns[ref].back
  1312.         end,
  1313.         delete=function()
  1314.             tDropdowns[ref]=nil
  1315.         end}
  1316.     end
  1317. end
  1318.  
  1319.  
  1320.  
  1321. -- THE OVERRIDE ------------------------------------------------------------------------------------
  1322. if not os.override then
  1323.     local rp=shell.resolveProgram
  1324.     shell.resolveProgram=function()
  1325.         shell.resolveProgram=rp
  1326.         return nil
  1327.     end
  1328.  
  1329.     local pe=os.pullEvent
  1330.     os.pullEvent=function()
  1331.         os.pullEvent=pe
  1332.         return "key"
  1333.     end
  1334.  
  1335.     local count=0
  1336.     local sd=os.shutdown
  1337.     os.shutdown=function()
  1338.         count=count+1
  1339.         if count==2 then
  1340.             os.shutdown=sd
  1341.             os.override=true
  1342.             term.clear()
  1343.             term.setCursorPos(term.getSize()/2-5,1)
  1344.             term.native.write("Loading...")
  1345.             loadUp()
  1346.             term.clear()
  1347.             term.setCursorPos(1,1)
  1348.             begin()
  1349.         end
  1350.         return false
  1351.     end
  1352.     shell.exit()
  1353. end
Advertisement
Add Comment
Please, Sign In to add comment