dannysmc95

Verinian Desktop Environment - Version 3.0.1

Nov 6th, 2014
1,347
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 453.60 KB | None | 0 0
  1. -- Verinian Desktop Environment: 3.0.1
  2. -- Created By DannySMc
  3.  
  4. -- Configuration File Protocols
  5. function saveConfig(table, file)
  6.   fConfig = fs.open(file, "w") or error("Cannot open file "..file, 2)
  7.   fConfig.write(textutils.serialize(table))
  8.   fConfig.close()
  9. end
  10.  
  11. function loadConfig(file)
  12.   fConfig = fs.open(file, "r")
  13.   ret = textutils.unserialize(fConfig.readAll())
  14.   return ret
  15. end
  16.  
  17. -- Peripheral Functions
  18. function findPeripheral(Perihp) --Returns side of first matching peripheral matching passed string  
  19.   for _,s in ipairs(rs.getSides()) do
  20.     if peripheral.isPresent(s) and peripheral.getType(s) == Perihp then
  21.       return s  
  22.     end
  23.   end
  24.   return false
  25. end
  26.  
  27. -- Common Draw Functions
  28. function cs()
  29.     term.clear()
  30.     term.setCursorPos(1,1)
  31.     return
  32. end
  33.  
  34. function setCol(textColour, backgroundColour)
  35.     if textColour and backgroundColour then
  36.         if term.isColour() then
  37.             term.setTextColour(colours[textColour])
  38.             term.setBackgroundColour(colours[backgroundColour])
  39.             return true
  40.         else
  41.             return false
  42.         end
  43.     else
  44.         return false
  45.     end
  46. end
  47.  
  48. function resetCol()
  49.     if term.isColour then
  50.         term.setTextColour(colours.white)
  51.         term.setBackgroundColour(colours.black)
  52.         return true
  53.     else
  54.         return false
  55.     end
  56. end
  57.  
  58. -- Print Functions
  59. function printC(Text, Line, NextLine, Color, BkgColor) -- print centered
  60.   local x, y = term.getSize()
  61.   x = x/2 - #Text/2
  62.   term.setCursorPos(x, Line)
  63.   if Color then setCol(Color, BkgColor) end
  64.   term.write(Text)
  65.   if NextLine then
  66.     term.setCursorPos(1, NextLine)
  67.   end
  68.   if Color then resetCol(Color, BkgColor) end
  69.   return true  
  70. end
  71.  
  72. function printL(Text, Line, NextLine, Color, BkgColor) -- print line
  73.  
  74.  
  75.   local x, y = term.getSize()
  76.   if ((term.isColor) and (term.isColor() == false) and (Text == " ")) then Text = "-" end
  77.   for i = 1, x do
  78.     term.setCursorPos(i, Line)
  79.     if Color then setCol(Color, BkgColor) end
  80.     term.write(Text)
  81.   end
  82.   if NextLine then  
  83.     term.setCursorPos(1, NextLine)
  84.   end
  85.   if Color then resetCol(Color, BkgColor) end
  86.   return true  
  87. end
  88.  
  89. function printA(Text, xx, yy, NextLine, Color, BkgColor) -- print anywhere
  90.   term.setCursorPos(xx,yy)
  91.   if Color then setCol(Color, BkgColor) end
  92.   term.write(Text)
  93.   if NextLine then  
  94.     term.setCursorPos(1, NextLine)
  95.   end
  96.   if Color then resetCol(Color, BkgColor) end
  97.   return true  
  98. end
  99.  
  100. function clearLine(Line, NextLine) -- May seem a bit odd, but it may be usefull sometimes
  101.   local x, y = term.getSize()
  102.   for i = 1, x do
  103.     term.setCursorPos(i, Line)
  104.     term.write(" ")
  105.   end  
  106.   if not NextLine then  
  107.     x, y = term.getCursorPos()
  108.     term.setCursorPos(1, y+1)
  109.   end
  110.   return true  
  111. end
  112.  
  113. function drawBox(StartX, lengthX, StartY, lengthY, Text, Color, BkgColor) -- does what is says on the tin.
  114.   local x, y = term.getSize()
  115.   if Color then setCol(Color, BkgColor) end
  116.   if not Text then Text = "*" end
  117.   lengthX = lengthX - 1
  118.   lengthY = lengthY - 1
  119.   EndX = StartX + lengthX  
  120.   EndY = StartY + lengthY
  121.   term.setCursorPos(StartX, StartY)
  122.   term.write(string.rep(Text, lengthX))
  123.   term.setCursorPos(StartX, EndY)
  124.   term.write(string.rep(Text, lengthX))
  125.   for i = StartY, EndY do
  126.     term.setCursorPos(StartX, i)
  127.     term.write(Text)
  128.     term.setCursorPos(EndX, i)    
  129.     term.write(Text)
  130.   end
  131.   resetCol(Color, BkgColor)
  132.   return true  
  133. end
  134.  
  135.  -- Download Functions
  136. function getPBFile(PBCode, uPath) -- pastebin code of the file, and path to save
  137.     local temp = http.get("http://pastebin.com/raw.php?i="..textutils.urlEncode(PBCode))
  138.     if temp then
  139.         tempTo = temp.readAll()
  140.         temp.close()
  141.         local file = fs.open( uPath, "w" )
  142.         file.write(temp)
  143.         file.close()
  144.         return true
  145.     else
  146.         return false
  147.     end
  148. end
  149.  
  150. -- Database Functions
  151. db = {}
  152. db.__index = db
  153.  
  154. function db.delete(Filename)
  155.   if fs.exists(Filename) then
  156.     fs.delete(Filename)
  157.     return true
  158.   end
  159.   return false
  160. end
  161.  
  162. function db.load(Filename)
  163.   if not fs.exists(Filename) then
  164.     local F = fs.open(Filename, "w")
  165.     F.write("{}")
  166.     F.close()
  167.   end
  168.   local F = fs.open(Filename, "r")
  169.   local Data = F.readAll()
  170.   F.close()
  171.   Data = textutils.unserialize(Data)
  172.   return Data
  173. end
  174.  
  175. function db.save(Filename, ATable)
  176.   local Data = textutils.serialize(ATable)
  177.   local F = fs.open(Filename, "w")
  178.   F.write(Data)
  179.   F.close()
  180.   return true
  181. end
  182.  
  183. function db.search(searchstring, ATable)
  184.   for i, V in pairs(ATable) do
  185.     if tostring(ATable[i]) == tostring(searchstring) then
  186.       return i
  187.     end
  188.   end
  189.   return 0
  190. end
  191.  
  192. function db.removeString(Filename, AString)
  193.   local TempT = db.load(Filename)
  194.   if type(TempT) ~= "table" then return false end
  195.   local Pos = db.search(AString, TempT)
  196.   if Pos > 0 then
  197.     table.remove(TempT, Pos)
  198.     db.save(Filename, TempT)
  199.     return true
  200.   else
  201.     return false
  202.   end
  203. end
  204.  
  205. function db.insertString(Filename, AString)
  206.   local TempT = db.load(Filename)
  207.   if type(TempT) ~= "table" then TempT = {} end
  208.   table.insert(TempT, AString)
  209.   db.save(Filename, TempT)
  210.   return true
  211. end
  212.  
  213. -- Serial Generator
  214. function serialGen(digits) -- seems to become unstable above 18 digits long
  215.  
  216.   local serial
  217.   for i = 1, digits do
  218.     if i == 1 then
  219.       serial = math.random(9)
  220.     else
  221.       serial = serial.. math.random(9)
  222.     end
  223.   end
  224.   serial = tonumber(serial)
  225.   return serial
  226. end
  227.  
  228. -- Encryption & Checksum!
  229. local function zfill(N)
  230.     N=string.format("%X",N)
  231.     Zs=""
  232.     if #N==1 then
  233.         Zs="0"
  234.     end
  235.     return Zs..N
  236. end
  237.  
  238. local function serializeImpl(t)
  239.     local sType = type(t)
  240.     if sType == "table" then
  241.         local lstcnt=0
  242.         for k,v in pairs(t) do
  243.             lstcnt = lstcnt + 1
  244.         end
  245.         local result = "{"
  246.         local aset=1
  247.         for k,v in pairs(t) do
  248.             if k==aset then
  249.                 result = result..serializeImpl(v)..","
  250.                 aset=aset+1
  251.             else
  252.                 result = result..("["..serializeImpl(k).."]="..serializeImpl(v)..",")
  253.             end
  254.         end
  255.         result = result.."}"
  256.         return result
  257.     elseif sType == "string" then
  258.         return string.format("%q",t)
  259.     elseif sType == "number" or sType == "boolean" or sType == "nil" then
  260.         return tostring(t)
  261.     elseif sType == "function" then
  262.         local status,data=pcall(string.dump,t)
  263.         if status then
  264.             return 'func('..string.format("%q",data)..')'
  265.         else
  266.             error()
  267.         end
  268.     else
  269.         error()
  270.     end
  271. end
  272.  
  273. local function split(T,func)
  274.     if func then
  275.         T=func(T)
  276.     end
  277.     local Out={}
  278.     if type(T)=="table" then
  279.         for k,v in pairs(T) do
  280.             Out[split(k)]=split(v)
  281.         end
  282.     else
  283.         Out=T
  284.     end
  285.     return Out
  286. end
  287.  
  288. local function serialize( t )
  289.     t=split(t)
  290.     return serializeImpl( t, tTracking )
  291. end
  292.  
  293. local function unserialize( s )
  294.     local func, e = loadstring( "return "..s, "serialize" )
  295.     local funcs={}
  296.     if not func then
  297.         return e
  298.     end
  299.     setfenv( func, {
  300.         func=function(S)
  301.             local new={}
  302.             funcs[new]=S
  303.             return new
  304.         end,
  305.     })
  306.     return split(func(),function(val)
  307.         if funcs[val] then
  308.             return loadstring(funcs[val])
  309.         else
  310.             return val
  311.         end
  312.     end)
  313. end
  314.  
  315. local function sure(N,n)
  316.     if (l2-n)<1 then N="0" end
  317.     return N
  318. end
  319.  
  320. local function splitnum(S)
  321.     Out=""
  322.     for l1=1,#S,2 do
  323.         l2=(#S-l1)+1
  324.         CNum=tonumber("0x"..sure(string.sub(S,l2-1,l2-1),1) .. sure(string.sub(S,l2,l2),0))
  325.         Out=string.char(CNum)..Out
  326.     end
  327.     return Out
  328. end
  329.  
  330. local function wrap(N)
  331.     return N-(math.floor(N/256)*256)
  332. end
  333.  
  334. function checksum(S,num) -- args strInput and intPassNumber
  335.     local sum=0
  336.     for char in string.gmatch(S,".") do
  337.         for l1=1,(num or 1) do
  338.             math.randomseed(string.byte(char)+sum)
  339.             sum=sum+math.random(0,9999)
  340.         end
  341.     end
  342.     math.randomseed(sum)
  343.     return sum
  344. end
  345.  
  346. local function genkey(len,psw)
  347.     checksum(psw)
  348.     local key={}
  349.     local tKeys={}
  350.     for l1=1,len do
  351.         local num=math.random(1,len)
  352.         while tKeys[num] do
  353.             num=math.random(1,len)
  354.         end
  355.         tKeys[num]=true
  356.         key[l1]={num,math.random(0,255)}
  357.     end
  358.     return key
  359. end
  360.  
  361. function encrypt(data,psw) -- args strInput and strPassword
  362.     data=serialize(data)
  363.     local chs=checksum(data)
  364.     local key=genkey(#data,psw)
  365.     local out={}
  366.     local cnt=1
  367.     for char in string.gmatch(data,".") do
  368.         table.insert(out,key[cnt][1],zfill(wrap(string.byte(char)+key[cnt][2])),chars)
  369.         cnt=cnt+1
  370.     end
  371.     return string.sub(serialize({chs,table.concat(out)}),2,-3)
  372. end
  373.  
  374. function decrypt(data,psw) -- args strInput and strPassword
  375.     local oData=data
  376.     data=unserialize("{"..data.."}")
  377.     if type(data)~="table" then
  378.         return oData
  379.     end
  380.     local chs=data[1]
  381.     data=data[2]
  382.     local key=genkey((#data)/2,psw)
  383.     local sKey={}
  384.     for k,v in pairs(key) do
  385.         sKey[v[1]]={k,v[2]}
  386.     end
  387.     local str=splitnum(data)
  388.     local cnt=1
  389.     local out={}
  390.     for char in string.gmatch(str,".") do
  391.         table.insert(out,sKey[cnt][1],string.char(wrap(string.byte(char)-sKey[cnt][2])))
  392.         cnt=cnt+1
  393.     end
  394.     out=table.concat(out)
  395.     if checksum(out or "")==chs then
  396.         return unserialize(out)
  397.     end
  398.     return oData,out,chs
  399. end
  400.  
  401. function wordwrap(str, limit)
  402.   limit = limit or 72
  403.   local here = 1
  404.   local buf = ""
  405.   local t = {}
  406.   str:gsub("(%s*)()(%S+)()",
  407.   function(sp, st, word, fi)
  408.         if fi-here > limit then
  409.            --# Break the line
  410.            here = st
  411.            table.insert(t, buf)
  412.            buf = word
  413.         else
  414.            buf = buf..sp..word  --# Append
  415.         end
  416.   end)
  417.   --# Tack on any leftovers
  418.   if(buf ~= "") then
  419.         table.insert(t, buf)
  420.   end
  421.   return t
  422. end
  423.  
  424. function time()
  425.     local nTime = textutils.formatTime(os.time(), true)
  426.     if string.len(nTime) == 4 then
  427.         nTime = "0"..nTime
  428.     end
  429.     os.startTimer(1)
  430.     return nTime
  431. end
  432.  
  433. function CalculateLineWrapping(self)
  434.     local limit = self.PageSize.Width
  435.     local text = self.TextInput.Value
  436.     local lines = {''}
  437.     local words = {}
  438.  
  439.     for word, space in text:gmatch('(%S+)(%s*)') do
  440.         for i = 1, math.ceil(#word/limit) do
  441.             local _space = ''
  442.             if i == math.ceil(#word/limit) then
  443.                 _space = space
  444.             end
  445.             table.insert(words, {word:sub(1+limit*(i-1), limit*i), _space})
  446.         end
  447.     end
  448.  
  449.     for i, ws in ipairs(words) do
  450.         local word = ws[1]
  451.         local space = ws[2]
  452.         local temp = lines[#lines] .. word .. space:gsub('\n','')
  453.         if #temp > limit then
  454.             table.insert(lines, '')
  455.         end
  456.         if space:find('\n') then
  457.             lines[#lines] = lines[#lines] .. word
  458.                          
  459.             space = space:gsub('\n', function()
  460.             table.insert(lines, '')
  461.             return ''
  462.         end)
  463.     else
  464.         lines[#lines] = lines[#lines] .. word .. space
  465.     end
  466.     end
  467.         return lines
  468. end
  469.  
  470. -- SHA256 Hashing Algorithm:
  471. local MOD = 2^32
  472. local MODM = MOD-1
  473. local function memoize(f)
  474.     local mt = {}
  475.     local t = setmetatable({}, mt)
  476.     function mt:__index(k)
  477.         local v = f(k)
  478.         t[k] = v
  479.         return v
  480.     end
  481.     return t
  482. end
  483. local function make_bitop_uncached(t, m)
  484.     local function bitop(a, b)
  485.         local res,p = 0,1
  486.         while a ~= 0 and b ~= 0 do
  487.             local am, bm = a % m, b % m
  488.             res = res + t[am][bm] * p
  489.             a = (a - am) / m
  490.             b = (b - bm) / m
  491.             p = p*m
  492.         end
  493.         res = res + (a + b) * p
  494.         return res
  495.     end
  496.     return bitop
  497. end
  498. local function make_bitop(t)
  499.     local op1 = make_bitop_uncached(t,2^1)
  500.     local op2 = memoize(function(a) return memoize(function(b) return op1(a, b) end) end)
  501.     return make_bitop_uncached(op2, 2 ^ (t.n or 1))
  502. end
  503. local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})
  504. local function bxor(a, b, c, ...)
  505.     local z = nil
  506.     if b then
  507.         a = a % MOD
  508.         b = b % MOD
  509.         z = bxor1(a, b)
  510.         if c then z = bxor(z, c, ...) end
  511.         return z
  512.     elseif a then return a % MOD
  513.     else return 0 end
  514. end
  515. local function band(a, b, c, ...)
  516.     local z
  517.     if b then
  518.         a = a % MOD
  519.         b = b % MOD
  520.         z = ((a + b) - bxor1(a,b)) / 2
  521.         if c then z = bit32_band(z, c, ...) end
  522.         return z
  523.     elseif a then return a % MOD
  524.     else return MODM end
  525. end
  526. local function bnot(x) return (-1 - x) % MOD end
  527. local function rshift1(a, disp)
  528.     if disp < 0 then return lshift(a,-disp) end
  529.     return math.floor(a % 2 ^ 32 / 2 ^ disp)
  530. end
  531. local function rshift(x, disp)
  532.     if disp > 31 or disp < -31 then return 0 end
  533.     return rshift1(x % MOD, disp)
  534. end
  535. local function lshift(a, disp)
  536.     if disp < 0 then return rshift(a,-disp) end
  537.     return (a * 2 ^ disp) % 2 ^ 32
  538. end
  539. local function rrotate(x, disp)
  540.     x = x % MOD
  541.     disp = disp % 32
  542.     local low = band(x, 2 ^ disp - 1)
  543.     return rshift(x, disp) + lshift(low, 32 - disp)
  544. end
  545. local k = {
  546.     0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
  547.     0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  548.     0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
  549.     0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  550.     0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
  551.     0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  552.     0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
  553.     0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  554.     0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
  555.     0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  556.     0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
  557.     0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  558.     0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
  559.     0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  560.     0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
  561.     0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
  562. }
  563. local function str2hexa(s)
  564.     return (string.gsub(s, ".", function(c) return string.format("%02x", string.byte(c)) end))
  565. end
  566. local function num2s(l, n)
  567.     local s = ""
  568.     for i = 1, n do
  569.         local rem = l % 256
  570.         s = string.char(rem) .. s
  571.         l = (l - rem) / 256
  572.     end
  573.     return s
  574. end
  575. local function s232num(s, i)
  576.     local n = 0
  577.     for i = i, i + 3 do n = n*256 + string.byte(s, i) end
  578.     return n
  579. end
  580. local function preproc(msg, len)
  581.     local extra = 64 - ((len + 9) % 64)
  582.     len = num2s(8 * len, 8)
  583.     msg = msg .. "\128" .. string.rep("\0", extra) .. len
  584.     assert(#msg % 64 == 0)
  585.     return msg
  586. end
  587. local function initH256(H)
  588.     H[1] = 0x6a09e667
  589.     H[2] = 0xbb67ae85
  590.     H[3] = 0x3c6ef372
  591.     H[4] = 0xa54ff53a
  592.     H[5] = 0x510e527f
  593.     H[6] = 0x9b05688c
  594.     H[7] = 0x1f83d9ab
  595.     H[8] = 0x5be0cd19
  596.     return H
  597. end
  598. local function digestblock(msg, i, H)
  599.     local w = {}
  600.     for j = 1, 16 do w[j] = s232num(msg, i + (j - 1)*4) end
  601.     for j = 17, 64 do
  602.         local v = w[j - 15]
  603.         local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3))
  604.         v = w[j - 2]
  605.         w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10))
  606.     end
  607.     local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
  608.     for i = 1, 64 do
  609.         local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))
  610.         local maj = bxor(band(a, b), band(a, c), band(b, c))
  611.         local t2 = s0 + maj
  612.         local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))
  613.         local ch = bxor (band(e, f), band(bnot(e), g))
  614.         local t1 = h + s1 + ch + k[i] + w[i]
  615.         h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2
  616.     end
  617.     H[1] = band(H[1] + a)
  618.     H[2] = band(H[2] + b)
  619.     H[3] = band(H[3] + c)
  620.     H[4] = band(H[4] + d)
  621.     H[5] = band(H[5] + e)
  622.     H[6] = band(H[6] + f)
  623.     H[7] = band(H[7] + g)
  624.     H[8] = band(H[8] + h)
  625. end
  626. function sha256(msg)
  627.     msg = preproc(msg, #msg)
  628.     local H = initH256({})
  629.     for i = 1, #msg, 64 do digestblock(msg, i, H) end
  630.     return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) ..
  631.         num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4))
  632. end
  633. -- End API Functions
  634.  
  635.  
  636.  
  637.  
  638.  
  639. --[[ Program Help:
  640.     + Desktop Computer (51 x 19)
  641.     + Tablet PC (26 x 20)
  642. ]]
  643.  
  644. -- Main Program Code Start:
  645.  
  646. vdeArguments = {...}
  647. for _, v in ipairs(vdeArguments) do
  648.     if v == "update" then
  649.         VDEControl("runUpdate")
  650.     elseif v == "bypass" then
  651.         cs()
  652.         print("> You are running VDE in bypass mode...")
  653.         platformType = UnknownOK
  654.     else
  655.         break
  656.     end
  657. end
  658.  
  659. -- Get Type:
  660. local intX, intY = term.getSize()
  661. if intX == 51 and intY == 19 then
  662.     platformType = Desktop
  663. elseif intX == 26 and intY == 2 then
  664.     platformType = Tablet
  665. else
  666.     platformType = Unknown
  667. end
  668.  
  669. -- Variables:
  670. nVersion = "3.0.0"
  671.  
  672. mainTC = "white"
  673. MainBC = "cyan"
  674. errorTC = "lime"
  675. errorBC = "red"
  676. loginTC = "blue"
  677. loginBC = "lightGrey"
  678. loginfieldTC = "black"
  679. loginfieldBC = "white"
  680. homeTC = "white"
  681. homeBC = "lightGrey"
  682. homeLogoTC = "blue"
  683. homeLogoBC = "grey"
  684. tMSides = {"top", "bottom", "right", "left", "back", "front",}
  685. recentTasks = {}
  686. processes = {
  687.     {
  688.         -- Name
  689.     },
  690.     {
  691.         -- Path of File
  692.     },
  693. }
  694.  
  695. -- Run Rednet Open
  696. for _, v in ipairs(tMSides) do
  697.     if peripheral.isPresent(v) then
  698.         if peripheral.getType(v) == "modem" then
  699.             modemSide = v
  700.         end
  701.     end
  702. end
  703.  
  704.  
  705.  
  706. -- DISABLED VDE TERMINATION FOR TESTING PURPOSES
  707.  
  708.  
  709. -- os.pullEvent = os.pullEventRaw
  710. defUser = "admin"
  711. defPass = "login"
  712. sUrl = "https://dannysmc.com/files/php/mysqldb.php"
  713.  
  714. function DBControl(sMode, sUser, sPass)
  715.     local nPass = sha256(sPass)
  716.     if sMode == "login" then
  717.         local req = http.post(sUrl, "cmd="..textutils.urlEncode(tostring(sMode)).."&".."username="..textutils.urlEncode(tostring(sUser)).."&".."password="..textutils.urlEncode(tostring(nPass)))
  718.         local status = req.readAll()
  719.         if status == '"true"' then
  720.             return true
  721.         else
  722.             return false
  723.         end
  724.     elseif sMode == "insert" then
  725.         local req = http.post(sUrl, "cmd="..textutils.urlEncode(tostring(sMode)).."&".."username="..textutils.urlEncode(tostring(sUser)).."&".."password="..textutils.urlEncode(tostring(nPass)))
  726.         local status = req.readAll()
  727.         if status == "true" then
  728.             return true
  729.         else
  730.             return false
  731.         end
  732.     elseif sMode == "delete" then
  733.         local req = http.post(sUrl, "cmd="..textutils.urlEncode(tostring(sMode)).."&".."username="..textutils.urlEncode(tostring(sUser)).."&".."password="..textutils.urlEncode(tostring(nPass)))
  734.         local status = req.readAll()
  735.         if status == "true" then
  736.             return true
  737.         else
  738.             return false
  739.         end
  740.     end
  741. end
  742.  
  743. function drawPopup(sText)
  744.     drawBox(1, 51, 8, 1, " ", errorTC, errorBC)
  745.     printC(sText, 8, false, errorTC, errorBC)
  746. end
  747.  
  748. -- Main Code:
  749.  
  750. function VDE_Error(errordata)
  751.     -- displays errors
  752.     if errordata == "Unknown" then
  753.         cs()
  754.         error1 = "Verinian encountered an error that was caused from VDE being unable to figure out what platform you are using... Computer, Pocket, etc. VDE detects the user platform using the screen characters, if you have changed the screen size then please run VDE in unknown mode by typing: vde.lua bypass, this will allow you to bypass the screen detection phase."
  755.     end
  756. end
  757.  
  758. function VDEControl(sMode)
  759.     if sMode == "run" then
  760.         -- Run program
  761.         login()
  762.     elseif sMode == "install" then
  763.         -- Install VDE
  764.         local tDirs = {"/core/", "/core/config/", "/core/addons/", "/core/libs/", "/core/apps/", "/core/themes/", "/core/users/", "/core/users/default",}
  765.         for _,v in ipairs(tDirs) do
  766.             fs.makeDir(v)
  767.         end
  768.         if not platformType == "UnknownOK" then
  769.             if platformType == "Desktop" then
  770.                 home()
  771.             elseif platformType == "Tablet" then
  772.                 tab_home()
  773.             elseif platformType == "Unknown" then
  774.                 VDE_Error("Unknown")
  775.             elseif platformType == "Monitor" then
  776.                 VDEMonitor()
  777.             else
  778.                 VDE_Error("Unknown")
  779.             end
  780.         end
  781.         drawPopup("Downloading Files, Please Wait...")
  782.        
  783.  
  784.         local ConfigUser = {
  785.             {
  786.                 "No Options Available",
  787.             },
  788.             {  
  789.                 false,
  790.             },
  791.         }
  792.  
  793.         local ConfigRednet = {
  794.             {
  795.                 "No Options Available",
  796.             },
  797.             {
  798.                 false,
  799.                 false,
  800.             },
  801.         }
  802.  
  803.         local ConfigOS = {
  804.             {  
  805.                 "Uninstall VerinianDE",
  806.                 "Initialise File System",
  807.             },
  808.             {
  809.                 false,
  810.                 false,       
  811.             },
  812.         }
  813.  
  814.         local ConfigMisc = {
  815.             {
  816.                 "No Options Available",
  817.             },
  818.             {
  819.                 false,
  820.             },
  821.         }
  822.  
  823.         local tempFile = fs.open("/core/config/Config_MISC", "w")
  824.         tempFile.write(textutils.serialize(ConfigMisc))
  825.         tempFile.close()
  826.  
  827.         local tempFile = fs.open("/core/config/Config_OS", "w")
  828.         tempFile.write(textutils.serialize(ConfigOS))
  829.         tempFile.close()
  830.  
  831.         local tempFile = fs.open("/core/config/Config_REDNET", "w")
  832.         tempFile.write(textutils.serialize(ConfigRednet))
  833.         tempFile.close()
  834.  
  835.         local tempFile = fs.open("/core/config/Config_USER", "w")
  836.         tempFile.write(textutils.serialize(ConfigUser))
  837.         tempFile.close()
  838.  
  839.         shell.run("pastebin get HC1MjHVq /core/apps/Stacker")
  840.         shell.run("pastebin get 0uygJmhJ /core/apps/Lasers")
  841.  
  842.         local tempFile = fs.open("/core/config/install", "w")
  843.         tempFile.write("Installed")
  844.         tempFile.close()
  845.  
  846.         local tStartFile = fs.open("startup", "w")
  847.         tStartFile.write("shell.run('vde.lua')")
  848.         tStartFile.close()
  849.  
  850.         login()
  851.     elseif sMode == "uninstall" then
  852.         -- Uninstall VDE
  853.         cs()
  854.         local texttc, textbc = "black", "white"
  855.         drawBox(1, 51, 1, 1, " ", texttc, textbc)
  856.         colourScreen()
  857.         term.setCursorPos(1,1)
  858.         local content = "Sorry to see you go... This will uninstall Verinian Desktop Environment from your computer, by deleting all files associated and created by VDE. These are the following folders: core/, core/addons/, core/apps/, core/libs, core/users/, core/config and core/themes. All files that aren't created will be left. If you wish to keep apps, I would move them now. Press 'y' to continue with the uninstall process or press 'c' to cancel."
  859.         setCol(texttc, textbc)
  860.         for _,v in ipairs(wordwrap(content)) do
  861.             print(v)
  862.         end
  863.  
  864.         while true do
  865.             local args = { os.pullEvent("char") }
  866.             if args[2] == "y" then
  867.                 cs()
  868.                 colourScreen()
  869.                 setCol(texttc, textbc)
  870.                 print("> Starting to uninstall VDE...")
  871.                 local toDelFiles = {"core/addons/", "core/apps/", "core/config/", "core/libs/", "core/themes/", "core/users/","core/"}
  872.                 for _,v in ipairs(toDelFiles) do
  873.                     fs.delete(v)
  874.                 end
  875.                 print("> Folders deleted, deleting startup...")
  876.                 fs.delete("startup")
  877.                 sleep(1)
  878.                 print("> VDE is left in-case you wish to reinstall...")
  879.                 sleep(1)
  880.                 os.reboot()
  881.             elseif args[2] == "n" then
  882.                 home()
  883.             end
  884.         end
  885.  
  886.     elseif sMode == "update" then
  887.         -- Update VDE
  888.         drawPopup("Attempting Update, Halting System...")
  889.         sleep(1)
  890.         cs()
  891.         colourScreen()
  892.         term.setCursorPos(1,1)
  893.         setCol("black", "white")
  894.         print("> Starting Update Process...")
  895.         print("> System Halted, while updating...")
  896.         setCol("lime", "white")
  897.         print("> Do not turn off the computer, or access the file")
  898.         print("  system, while this process is active...")
  899.         setCol("black", "white")
  900.         print("> Attempting to grab update data...")
  901.         local newReq = http.get("https://dannysmc.com/programs/vde/update.txt")
  902.         if not newReq then
  903.             print("> Couldn't obtain file...")
  904.             print("> Error: VDE_UPD_DAT_FALSE")
  905.             sleep(2)
  906.             home()
  907.         end
  908.         print("> File obtained...")
  909.         print("> Attempting to get new update...")
  910.         local updData = http.get(newReq.readAll())
  911.         local tempFile = fs.open("vdeUpd", "w")
  912.         tempFile.write(updData.readAll())
  913.         tempFile.close()
  914.         print("> Attempting to update, please wait...")
  915.         local stat, err = pcall(shell.run("vdeUpd update"))
  916.         if not stat then
  917.             print("An error occured, VDE can't obtain error code.")
  918.             print("> Error: "..err)
  919.             sleep(4)
  920.             home()
  921.         end
  922.     elseif sMode == "shutdown" then
  923.         -- Shutdown VDE
  924.         drawPopup("Shutting Down...")
  925.         sleep(1.5)
  926.         os.shutdown()
  927.     elseif sMode == "restart" then
  928.         -- Restart VDE
  929.         drawPopup("Restarting...")
  930.         sleep(1.5)
  931.         os.reboot()
  932.     elseif sMode == "runUpdate" then
  933.         fs.delete("vde.lua")
  934.         fs.move("vdeUpd", "vde.lua")
  935.         os.reboot()
  936.     end
  937. end
  938.  
  939. function tab_home()
  940.     -- Not done yet
  941.     cs()
  942.     colourScreen()
  943.     term.setCursorPos(1,1)
  944.     print("> Tablet version isn't completed yet...")
  945.     sleep(2)
  946.     os.shutdown()
  947. end
  948.  
  949. function tab_programs()
  950.     -- Not done yet
  951. end
  952.  
  953. function tab_settings()
  954.     -- Not done yet
  955. end
  956.  
  957. function tab_connect()
  958.     -- Not done yet
  959. end
  960.  
  961. function VDEMonitor()
  962.     -- This function isn't available just yet
  963.     cs()
  964.     print("> This function isn't available yet.")
  965.     sleep(1.5)
  966.     print("> Will attempt to redirect to a monitor...")
  967.     sleep(1)
  968.     local mon = findPeripheral("monitor")
  969.     if mon then
  970.         term.redirect(mon)
  971.     end
  972. end
  973.  
  974. function login()
  975.   -- Start Login
  976.   home()
  977.  
  978.   local tInfo = {"Welcome to the new Verinian Desktop Environment", "The pocket, turtle editions are on their way!",}
  979.   cs()
  980.   colourScreen()
  981.   drawBox(1, 51, 1, 2, " ", tc, bc)
  982.   printA("Verinian Desktop Environment", 1, 1, false, tc, bc)
  983.   printA(time(), 47, 1, false, tc, bc)
  984.   printC(">> Login <<", 2, false, tc, bc)
  985.   -- Login Boxes
  986.   drawBox(1, 51, 3, 1, " ", tc, "grey")
  987.   printC("       REGISTER        < - >         [ LOGIN ]     ", 3, false, "white", "grey")
  988.   drawBox(8, 35, 5, 3, " ", tc, bc)
  989.   drawBox(8, 35, 9, 3, " ", tc, bc)
  990.   printC(">> Username <<", 5, false, tc, bc)
  991.   printC(">> Password <<", 9, false, tc, bc)
  992.   term.setCursorPos(1, 17)
  993.   setCol("black", "white")
  994.   printA("Please use your username and password to login to", 1, 17, false, "black", "white")
  995.   printA("the desktop environment. Don't have an account?", 1, 18, false, "black", "white")
  996.   printA("press 'REGISTER' to get an email account!", 1, 19, false, "black", "white")
  997.   term.setCursorPos(1,1)
  998.   drawBox(1, 51, 16, 1, " ", tc, bc)
  999.   printC(">> Help <<", 16, false, tc, bc)
  1000.   drawBox(19, 13, 13, 1, " ", tc, bc)
  1001.   printC(">> LOGIN <<", 13, false, tc, bc)
  1002.  
  1003.  
  1004.  
  1005.   while true do
  1006.     local args = { os.pullEvent() }
  1007.     if args[1] == "timer" then
  1008.       clearLine(1, false)
  1009.       drawBox(1, 51, 1, 2, " ", tc, bc)
  1010.       printA("Verinian Desktop Environment", 1, 1, false, tc, bc)
  1011.       printA(time(), 47, 1, false, tc, bc)
  1012.       printC(">> Login <<", 2, false, tc, bc)
  1013.     elseif args[1] == "mouse_click" then
  1014.       if (args[3] >= 9 and args[3] <= 42) and (args[4] == 6) then
  1015.         term.setCursorPos(9, 6)
  1016.         setCol("lime", "white")
  1017.         write(": ")
  1018.         username = tostring(read())
  1019.       elseif (args[3] >= 9 and args[3] <= 42) and (args[4] == 10) then
  1020.         term.setCursorPos(9, 10)
  1021.         setCol("lime", "white")
  1022.         write(": ")
  1023.         password = tostring(read("*"))
  1024.         password = sha256(password)
  1025.       elseif (args[3] >= 20 and args[3] <= 31) and (args[4] == 13) then
  1026.         local status = BlazeLogin(username, password)
  1027.         if status.readAll() == '"true"' then
  1028.           drawPopup("This action was successful")
  1029.           sleep(1.5)
  1030.           home()
  1031.         else
  1032.           drawPopup("Login Failed!")
  1033.           sleep(1.5)
  1034.           login()
  1035.         end
  1036.       elseif (args[3] >= 1 and args[3] <= 25) and (args[4] == 3) then
  1037.         register()
  1038.       end
  1039.     elseif args[1] == "char" then
  1040.       if args[2] == "u" then
  1041.         term.setCursorPos(9, 6)
  1042.         setCol("lime", "white")
  1043.         write(": ")
  1044.         username = tostring(read())
  1045.       elseif args[2] == "p" then
  1046.         term.setCursorPos(9, 10)
  1047.         setCol("lime", "white")
  1048.         write(": ")
  1049.         password = tostring(read("*"))
  1050.         password = sha256(password)
  1051.       elseif args[2] == "r" then
  1052.         register()
  1053.         break
  1054.       elseif args[2] == "l" then
  1055.         local status = BlazeLogin(username, password)
  1056.         if status.readAll() == '"true"' then
  1057.           drawPopup("This action was successful")
  1058.           sleep(1.5)
  1059.           home()
  1060.         else
  1061.           drawPopup("Login Failed!")
  1062.           sleep(1.5)
  1063.           login()
  1064.         end
  1065.       end
  1066.     end
  1067.   end
  1068. end
  1069.  
  1070. -- Set Vars:
  1071. scroll = 1
  1072. histFold = {}
  1073. table.insert(histFold, "/")
  1074.  
  1075. function fb_getClick(sButton, nX, nY, scroll, sDir)
  1076.     if sButton == 1 then
  1077.         local tFilesClean = tFilesClean
  1078.         tFilesCount = #tFilesClean
  1079.         local count = nY - 2 - scroll
  1080.         oldDir = sDir
  1081.         if sDir == "/" then
  1082.             newDir = sDir..""..(tFilesClean[count])
  1083.         else
  1084.             newDir = sDir.."/"..tFilesClean[count]
  1085.         end
  1086.         sDir = newDir
  1087.  
  1088.         if fs.isDir(newDir) then
  1089.             table.insert(histFold, sDir)
  1090.             fb_finder(newDir)
  1091.         else
  1092.             fb_runFile(newDir, sDir)
  1093.         end
  1094.     elseif sButton == 2 then
  1095.         -- Do delete or edit
  1096.         if sOption == "delete" then
  1097.             local tFilesClean = tFilesClean
  1098.             tFilesCount = #tFilesClean
  1099.             local count = nY - 2 - scroll
  1100.             oldDir = sDir
  1101.             if sDir == "/" then
  1102.                 newDir = sDir..""..(tFilesClean[count])
  1103.             else
  1104.                 newDir = sDir.."/"..tFilesClean[count]
  1105.             end
  1106.             fs.delete(newDir)
  1107.             fb_finder(sDir)
  1108.         elseif sOption == "edit" then
  1109.             -- Empty
  1110.         else
  1111.             fb_drawOptions(nX, nY, sDir)
  1112.         end
  1113.     end
  1114. end
  1115.  
  1116. function fb_drawOptions(tempX, tempY, sDir)
  1117.     drawBox(tempX, 8, tempY, 2, " ", "black", "lightGrey")
  1118.     printA("Delete", tempX, tempY, false, "black", "lightGrey")
  1119.     printA("Edit", tempX, tempY + 1, false, "black", "lightGrey")
  1120.  
  1121.     while true do
  1122.         local args = { os.pullEvent() }
  1123.         if args[1] == "mouse_click" then
  1124.             if args[2] == 1 then
  1125.                 if args[3] >= tempX and args[3] <= tempX + 8 then
  1126.                     if args[4] == tempY then
  1127.                         local tFilesClean = tFilesClean
  1128.                         tFilesCount = #tFilesClean
  1129.                         local count = tempY - 2 - scroll
  1130.                         oldDir = sDir
  1131.                         if sDir == "/" then
  1132.                             newDir = sDir..""..(tFilesClean[count])
  1133.                         else
  1134.                             newDir = sDir.."/"..tFilesClean[count]
  1135.                         end
  1136.                         fs.delete(newDir)
  1137.                         fb_finder(sDir)
  1138.                     elseif args[4] == tempY + 1 then
  1139.                         local tFilesClean = tFilesClean
  1140.                         tFilesCount = #tFilesClean
  1141.                         local count = tempY - 2 - scroll
  1142.                         oldDir = sDir
  1143.                         if sDir == "/" then
  1144.                             newDir = sDir..""..(tFilesClean[count])
  1145.                         else
  1146.                             newDir = sDir.."/"..tFilesClean[count]
  1147.                         end
  1148.                         shell.run("edit "..newDir)
  1149.                         fb_finder(sDir)
  1150.                     else
  1151.                         fb_finder(sDir)
  1152.                     end
  1153.                 else
  1154.                     fb_finder(sDir)
  1155.                 end
  1156.             else
  1157.                 fb_finder(sDir)
  1158.             end
  1159.         end
  1160.     end
  1161. end
  1162.  
  1163. function fb_runFile(path, sDir)
  1164.     cs()
  1165.     setCol("black", "white")
  1166.     shell.run(path)
  1167.     fb_finder(sDir)
  1168. end
  1169.  
  1170. function fb_drawMenu(sDir)
  1171.     -- Get files
  1172.     maintc = "blue"
  1173.     mainbc = "grey"
  1174.     mainbc2 = "lightGrey"
  1175.     texttc = "black"
  1176.     textbc = "white"
  1177.     dirtc = "red"
  1178.     xtc = "lime"
  1179.     sidetc = "white"
  1180.     sidebc = "cyan"
  1181.     sidetc1 = "lime"
  1182.     setCol("white", "white")
  1183.     cs()
  1184.     drawBox(1, 51, 1, 1, " ", maintc, mainbc)
  1185.     printA(" "..time().." ", 44, 1, false, maintc, mainbc2)
  1186.     printA("X", 1, 1, false, xtc, dirtc)
  1187.     printA(" Path: ", 3, 1, false, texttc, mainbc2)
  1188.     printA(sDir.." ", 10, 1, false, dirtc, mainbc2)
  1189.     drawBox(40, 12, 2, 18, " ", sidetc, sidebc)
  1190.     drawBox(41, 10, 3, 16, " ", sidetc, sidebc)
  1191.     drawBox(42, 8, 4, 14, " ", sidetc, sidebc)
  1192.     drawBox(43, 6, 5, 12, " ", sidetc, sidebc)
  1193.     drawBox(44, 4, 6, 10, " ", sidetc, sidebc)
  1194.     drawBox(45, 2, 7, 8, " ", sidetc, sidebc)
  1195.     printA("< ..", 2, 3, false, "blue", "white")
  1196.  
  1197.     printA("Create", 41, 3, false, sidetc1, sidebc)
  1198.     printA("File", 43, 4, false, sidetc, sidebc)
  1199.     printA("Folder", 43, 5, false, sidetc, sidebc)
  1200.  
  1201.     printA("LuaIDE", 41, 7, false, sidetc1, sidebc)
  1202.     printA("New", 43, 8, false, sidetc, sidebc)
  1203.     printA("Open", 43, 9, false, sidetc, sidebc)
  1204.  
  1205.     printA("Sketch", 41, 11, false, sidetc1, sidebc)
  1206.     printA("New", 43, 12, false, sidetc, sidebc)
  1207.     printA("Open", 43, 13, false, sidetc, sidebc)
  1208.     setCol(texttc, textbc)
  1209. end
  1210.  
  1211. function fb_finder(sDir)
  1212.     -- Get files
  1213.     fb_drawMenu(sDir)
  1214.     fb_drawDir(sDir, scroll)
  1215.  
  1216.     while true do
  1217.         local args = { os.pullEvent() }
  1218.         if args[1] == "timer" then
  1219.             fb_drawMenu(sDir)
  1220.             fb_drawDir(sDir, scroll)
  1221.         elseif args[1] == "mouse_scroll" then
  1222.             if args[2] == 1 then
  1223.                 scroll = scroll + 1
  1224.                 fb_drawMenu(sDir)
  1225.                 fb_drawDir(sDir, scroll)
  1226.             elseif args[2] == -1 then
  1227.                 scroll = scroll - 1
  1228.                 fb_drawMenu(sDir)
  1229.                 fb_drawDir(sDir, scroll)
  1230.             end
  1231.         elseif args[1] == "mouse_click" then
  1232.             if args[3] == 1 and args[4] == 1 then
  1233.                 if RunningUnder == "Verinian" then
  1234.                     home()
  1235.                 else
  1236.                     setCol("white", "black")
  1237.                     break
  1238.                 end
  1239.             elseif (args[3] >= 2 and args[3] <= 40) and (args[4] == 3) then
  1240.                 table.remove(histFold)
  1241.                 historyCount = #histFold
  1242.                 sDir = histFold[historyCount]
  1243.                 fb_finder(sDir)
  1244.             elseif (args[3] >= 2 and args[3] <= 40) and (args[4] >= 4 and args[4] <= 18) then
  1245.                 fb_getClick(args[2], args[3], args[4], scroll, sDir)
  1246.             elseif (args[3] >= 43 and args[3] <= 50) then
  1247.                 if args[4] == 4 then
  1248.                     fb_drawInput("file", sDir)
  1249.                 elseif args[4] == 5 then
  1250.                     fb_drawInput("folder", sDir)
  1251.                 elseif args[4] == 8 then
  1252.                     luaide()
  1253.                 elseif args[4] == 9 then
  1254.                     luaide()
  1255.                 elseif args[4] == 12 then
  1256.                     sketch()
  1257.                 elseif args[4] == 13 then
  1258.                     sketch()
  1259.                 end
  1260.             end
  1261.         end
  1262.     end
  1263. end
  1264.  
  1265. function fb_drawInput(object, sDir)
  1266.     poptc1 = "white"
  1267.     popbc1 = "red"
  1268.     poptc2 = "black"
  1269.     popbc2 = "white"
  1270.     if object == "file" then
  1271.         drawBox(6, 39, 6, 3, " ", poptc1, popbc1)
  1272.         drawBox(6, 39, 7, 1, " ", poptc1, popbc1)
  1273.         drawBox(7, 37, 7, 1, " ", poptc2, popbc2)
  1274.         printC("Name For File:", 6, false, poptc1, popbc1)
  1275.         setCol(poptc2, popbc2)
  1276.         term.setCursorPos(7,7)
  1277.         write(": ")
  1278.         local newFileName = tostring(read())
  1279.         if sDir == "/" then
  1280.             fileDirName = "/"..newFileName
  1281.         else
  1282.             fileDirName = sDir.."/"..newFileName
  1283.         end
  1284.         shell.run("edit "..fileDirName)
  1285.         fb_finder(sDir)
  1286.     elseif object == "folder" then
  1287.         drawBox(6, 39, 6, 3, " ", poptc1, popbc1)
  1288.         drawBox(6, 39, 7, 1, " ", poptc1, popbc1)
  1289.         drawBox(7, 37, 7, 1, " ", poptc2, popbc2)
  1290.         printC("Name For Folder:", 6, false, poptc1, popbc1)
  1291.         setCol(poptc2, popbc2)
  1292.         term.setCursorPos(7,7)
  1293.         write(": ")
  1294.         local newFolderName = tostring(read())
  1295.         if sDir == "/" then
  1296.             fileDirName = "/"..newFolderName
  1297.         else
  1298.             fileDirName = sDir.."/"..newFolderName
  1299.         end
  1300.         fs.makeDir(fileDirName)
  1301.         fb_finder(sDir)
  1302.     end
  1303. end
  1304.  
  1305. -- Code by: wieselkatze (Modified by dannysmc95)
  1306.  
  1307. local function fb_getDir( sDir )
  1308.     sDir = ( "/" .. sDir .. "/" ):gsub( "\\+", "/" ):gsub( "/+", "/" )
  1309.     local folder, list = sDir:match( ".*/" ), {}
  1310.  
  1311.     tFilesClean = {}
  1312.  
  1313.     if not fs.isDir( sDir ) then
  1314.         return {}
  1315.     end
  1316.  
  1317.     for k, v in pairs( fs.list( sDir ) ) do
  1318.         if fs.isDir( folder .. v ) then
  1319.             table.insert( list, 1, "+ " .. v )
  1320.             table.insert( tFilesClean, 1, v)
  1321.         else
  1322.             list[ #list+1 ] = "- " .. v
  1323.             tFilesClean[ #tFilesClean + 1 ] = v
  1324.         end
  1325.     end
  1326.  
  1327.     return list
  1328. end
  1329.  
  1330. function fb_drawDir(sDir, scroll)
  1331.     local intX = 2
  1332.     local intY = 4
  1333.  
  1334.     tFiles = fb_getDir(sDir)
  1335.  
  1336.     for k, v in ipairs(tFiles) do
  1337.         if k >= scroll and k <= 15 then
  1338.             term.setCursorPos(intX, intY)
  1339.             if v:find("+") then
  1340.                 setCol("blue", "white")
  1341.                 print(v)
  1342.             else
  1343.                 setCol("red", "white")
  1344.                 print(v)
  1345.             end
  1346.             intY = intY + 1
  1347.         end
  1348.     end
  1349. end
  1350.  
  1351. function fb_main()
  1352.     if fs.exists("vde.lua") then
  1353.         RunningUnder = "Verinian"
  1354.     else
  1355.         RunningUnder = "Unknown"
  1356.     end
  1357.     fb_finder("/")
  1358. end
  1359.  
  1360.  
  1361. function register()
  1362.   -- Draws register menu
  1363.   cs()
  1364.   colourScreen()
  1365.   drawBox(1, 51, 1, 2, " ", tc, bc)
  1366.   printA("Verinian Desktop Environment", 1, 1, false, tc, bc)
  1367.   printA(time(), 47, 1, false, tc, bc)
  1368.   printC(">> Register <<", 2, false, tc, bc)
  1369.   -- Login Boxes
  1370.   drawBox(1, 51, 3, 1, " ", tc, "grey")
  1371.   printC("     [ REGISTER ]      < - >           LOGIN       ", 3, false, "white", "grey")
  1372.   drawBox(8, 35, 5, 7, " ", tc, bc)
  1373.   printC(">> Username <<", 5, false, tc, bc)
  1374.   drawBox(8, 35, 7, 1, " ", tc, bc)
  1375.   printC(">> Password <<", 7, false, tc, bc)
  1376.   drawBox(8, 35, 9, 1, " ", tc, bc)
  1377.   printC(">> Email Address <<", 9, false, tc, bc)
  1378.   drawBox(15, 21, 13, 1, " ", tc, bc)
  1379.   printC(" >> REGISTER <<", 13, false, tc, bc)
  1380.   drawBox(1, 51, 17, 1, " ", tc, bc)
  1381.   printC(">> Information <<", 17, false, tc, bc)
  1382.   printA("Your email address is stored so you can recover", 1, 18, false, tc, "white")
  1383.   printA("your account!", 1, 19, false, tc, "white")
  1384.  
  1385.   while true do
  1386.     local args = { os.pullEvent() }
  1387.     if args[1] == "timer" then
  1388.       drawBox(1, 51, 1, 2, " ", tc, bc)
  1389.       printA("Verinian Desktop Environment", 1, 1, false, tc, bc)
  1390.       printA(time(), 47, 1, false, tc, bc)
  1391.       printC(">> Register <<", 2, false, tc, bc)
  1392.     elseif args[1] == "mouse_click" then
  1393.       if (args[3] >= 9 and args[3] <= 42) and (args[4] == 6) then
  1394.         setCol("lime", "white")
  1395.         term.setCursorPos(9, 6)
  1396.         write(": ")
  1397.         username = tostring(read())
  1398.       elseif (args[3] >= 9 and args[3] <= 42) and (args[4] == 8) then
  1399.         setCol("lime", "white")
  1400.         term.setCursorPos(9, 8)
  1401.         write(": ")
  1402.         password = tostring(read("*"))
  1403.         password = sha256(password)
  1404.       elseif (args[3] >= 9 and args[3] <= 42) and (args[4] == 10) then
  1405.         setCol("lime", "white")
  1406.         term.setCursorPos(9, 10)
  1407.         write(": ")
  1408.         email = tostring(read())
  1409.       elseif (args[3] >= 18 and args[3] <= 33) and (args[4] == 13) then
  1410.         local status = BlazeRegister(username, password, email)
  1411.         if status.readAll() == '"true"' then
  1412.           drawPopup("This action was successful")
  1413.           sleep(1.5)
  1414.           _BLAZEUSER = username
  1415.           _BLAZEPASS = password
  1416.           login()
  1417.         else
  1418.           drawPopup("Login Failed!")
  1419.           sleep(1.5)
  1420.           login()
  1421.         end
  1422.       elseif (args[3] >= 28 and args[3] <= 51) and (args[4] == 3) then
  1423.         login()
  1424.       end
  1425.     elseif args[1] == "char" then
  1426.       if args[2] == "l" then
  1427.         login()
  1428.         break
  1429.       elseif args[2] == "u" then
  1430.         setCol("lime", "white")
  1431.         term.setCursorPos(9, 6)
  1432.         write(": ")
  1433.         username = tostring(read())
  1434.       elseif args[2] == "p" then
  1435.         setCol("lime", "white")
  1436.         term.setCursorPos(9, 8)
  1437.         write(": ")
  1438.         password = tostring(read("*"))
  1439.         password = sha256(password)
  1440.       elseif args[2] == "e" then
  1441.         setCol("lime", "white")
  1442.         term.setCursorPos(9, 10)
  1443.         write(": ")
  1444.         email = tostring(read())
  1445.       elseif args[2] == "r" then
  1446.         local status = BlazeRegister(username, password, email)
  1447.         if status.readAll() == '"true"' then
  1448.           drawPopup("This action was successful")
  1449.           sleep(1.5)
  1450.           username = username
  1451.           password = password
  1452.           login()
  1453.         else
  1454.           drawPopup("Login Failed!")
  1455.           sleep(1.5)
  1456.           login()
  1457.         end
  1458.       end
  1459.     end
  1460.   end
  1461. end
  1462. --[[function login()
  1463.     loginTC = "blue"
  1464.     loginBC = "lightGrey"
  1465.     colourScreen()
  1466.     cs()
  1467.     drawBox(1, 51, 2, 3, " ", loginTC, loginBC)
  1468.     drawBox(1, 51, 3, 1, " ", loginTC, loginBC)
  1469.     drawBox(11, 30, 7, 5, " ", loginTC, loginBC)
  1470.     drawBox(11, 30, 7, 2, " ", loginTC, loginBC)
  1471.     drawBox(11, 30, 9, 2, " ", loginTC, loginBC)
  1472.     drawBox(11, 30, 13, 3, " ", loginTC, loginBC)
  1473.     drawBox(11, 30, 14, 1, " ", loginTC, loginBC)
  1474.     drawBox(1, 51, 17, 3, " ", loginTC, loginBC)
  1475.     drawBox(1, 51, 18, 1, " ", loginTC, loginBC)
  1476.     drawBox(12, 28, 8, 1 , " ", loginfieldTC, loginfieldBC)
  1477.     drawBox(12, 28, 10, 1, " ", loginfieldTC, loginfieldBC)
  1478.     drawBox(1, 51, 17, 3, " ", loginTC, loginBC)
  1479.     drawBox(2, 49, 18, 1, " ", loginfieldTC, loginfieldBC)
  1480.     printA("VDE: Login Screen", 2, 3, false, loginTC, loginBC)
  1481.     printA(time(), 47, 2, false, loginTC, loginBC)
  1482.     printA("Username:", 12, 7, false, loginTC, loginBC)
  1483.     printA("Password:", 12, 9, false, loginTC, loginBC)
  1484.     printA("> LOGIN <", 13 ,14, false, loginfieldTC, loginfieldBC)
  1485.     printA("> CLEAR <", 30, 14, false, loginfieldTC, loginfieldBC)
  1486.     printA("Console Log:", 2, 17, false, loginTC, loginBC)
  1487.  
  1488.     while true do
  1489.         local args = { os.pullEvent() }
  1490.         if args[1] == "timer" then
  1491.             drawBox(1, 51, 2, 3, " ", loginTC, loginBC)
  1492.             printA(time(), 47, 2, false, loginTC, loginBC)
  1493.         elseif args[1] == "char" then
  1494.             if args[2] == "u" then
  1495.                 term.setCursorPos(12, 8)
  1496.                 setCol(loginfieldTC, loginfieldBC)
  1497.                 write(": ")
  1498.                 sUsername = tostring(read())
  1499.             elseif args[2] == "p" then
  1500.                 term.setCursorPos(12, 10)
  1501.                 setCol(loginfieldTC, loginfieldBC)
  1502.                 write(": ")
  1503.                 sPassword = tostring(read("*"))
  1504.             elseif args[2] == "c" then
  1505.                 login()
  1506.             elseif args[2] == "l" then
  1507.                 if sUsername and sPassword then
  1508.                     printC("Sending Data To Server", 18, false, loginfieldTC, loginfieldBC)
  1509.                     sleep(0.5)
  1510.                     local status = DBControl("login", sUsername, sPassword)
  1511.                     if status then
  1512.                         printC("Login Correct, Loading Settings", 18, false, loginfieldTC, loginfieldBC)
  1513.                         sleep(0.5)
  1514.                         home()
  1515.                         break
  1516.                     else
  1517.                         printC("Incorrect Login, Please try again", 18, false, loginfieldTC, loginfieldBC)
  1518.                         sleep(2.5)
  1519.                         login()
  1520.                         break
  1521.                     end
  1522.                 else
  1523.                     printC("Both Username and Password are required", 18, false, loginfieldTC, loginfieldBC)
  1524.                     sleep(2.5)
  1525.                     login()
  1526.                     break
  1527.                 end
  1528.             end
  1529.         end
  1530.     end
  1531. end]]
  1532.  
  1533. function drawTaskbar()
  1534.     drawBox(1, 51, 19, 1, " ", "white", "grey")
  1535.     -- drawBox(47, 7, 19, 1, " ", "white", "lightGrey")
  1536.     printA("GO!", 1, 19, false, "blue", "lightGrey")
  1537.     printA(" "..time().." ", 45, 19, false, "blue", homeBC)
  1538.     -- drawBox(16, 19, 19, 1, " ", homeTC, homeBC)
  1539.     -- printA("Recent Tasks: ["..tostring(#recentTasks).."] ", 17, 19, false, "blue", "lightGrey")
  1540. end
  1541.  
  1542. function colourScreen()
  1543.     intX = 1
  1544.     intY = 1
  1545.     setCol("white", "white")
  1546.     repeat
  1547.         intX = 1
  1548.         repeat
  1549.             term.setCursorPos(intX, intY)
  1550.             write(" ")
  1551.             intX = intX + 1
  1552.         until intX == 52
  1553.         intY = intY + 1
  1554.     until intY == 20
  1555. end
  1556.  
  1557. function deskMenu(sObject, obj1)
  1558.     if sObject == "go" then
  1559.         drawBox(1, 11, 13, 6, " ", homeTC, homeBC)
  1560.         drawBox(1, 11, 14, 4 , " ", homeTC, homeBC)
  1561.         drawBox(1, 11, 15, 2 , " ", homeTC, homeBC)
  1562.         drawBox(1, 11, 13, 1, " ", "grey", "grey")
  1563.         printA("  GO MENU  ", 1, 13, false, "blue", "grey")
  1564.         printA("Programs  >", 1, 18, false, homeTC, homeBC)
  1565.         printA("Games     >", 1, 17, false, homeTC, homeBC)
  1566.         printA("Explorer  +", 1, 16, false, homeTC, homeBC)
  1567.         printA("C.Panel   +", 1, 15, false, homeTC, homeBC)
  1568.         printA("Add-Ons   +", 1, 14, false, homeTC, homeBC)
  1569.     elseif sObject == "programs" then
  1570.         drawBox(12, 11, 11, 8, " ", homeTC, homeBC)
  1571.         drawBox(12, 11, 12, 6, " ", homeTC, homeBC)
  1572.         drawBox(12, 11, 13, 4, " ", homeTC, homeBC)
  1573.         drawBox(12, 11, 14, 2, " ", homeTC, homeBC)
  1574.         drawBox(12, 11, 11, 1, " ", "blue", "grey")
  1575.         printA("ProgramMenu", 12, 11, false, "blue", "grey")
  1576.         printA("Blaze EC  +", 12, 12, false, homeTC, homeBC)
  1577.         printA("L2P Email +", 12, 13, false, homeTC, homeBC)
  1578.         printA("SHA256    +", 12, 14, false, homeTC, homeBC)
  1579.         printA("Transmit  +", 12, 15, false, homeTC, homeBC)
  1580.         printA("INK       +", 12, 16, false, homeTC, homeBC)
  1581.         printA("Sketch    +", 12, 17, false, homeTC, homeBC)
  1582.         printA("LuaIDE    +", 12, 18, false, homeTC, homeBC)
  1583.     elseif sObject == "games" then
  1584.         drawBox(12, 11, 14, 4, " ", homeTC, homeBC)
  1585.         drawBox(12, 11, 16, 2, " ", homeTC, homeBC)
  1586.         printA("Games Menu ", 12, 14, false, "blue", "grey")
  1587.         printA("Lazers    +", 12, 15, false, homeTC, homeBC)
  1588.         printA("Stacker   +", 12, 16, false, homeTC, homeBC)
  1589.         printA("P.Alpha   +", 12, 17, false, "lightGrey", homeBC)
  1590.     elseif sObject == "time" then
  1591.         drawBox(43, 9, 17, 2, " ", homeTC, homeBC)
  1592.         printA("Time Info", 43, 17, false, "blue", "grey")
  1593.         printA("Day: "..tostring(os.day()), 43, 18, false, homeTC, homeBC)
  1594.     elseif sObject == "clear" then
  1595.         if obj1 == "cpanel" then
  1596.             cpanel()
  1597.         elseif obj1 == "cpanelos" then
  1598.             cpanel("OS")
  1599.         elseif obj1 == "cpaneluser" then
  1600.             cpanel("USER")
  1601.         elseif obj1 == "cpanelred" then
  1602.             cpanel("REDNET")
  1603.         elseif obj1 == "cpanelmisc" then
  1604.             cpanel("MISC")
  1605.         else
  1606.             home()
  1607.         end
  1608.     elseif sObject == "new" then
  1609.         drawBox(2, 10, 2, 2, " ", homeTC, homeBC)
  1610.         printA("Program  +", 2, 2, false, homeTC, homeBC)
  1611.         printA("Download +", 2, 3, false, homeTC, homeBC)
  1612.     elseif sObject == "run" then
  1613.         drawBox(8, 10, 2, 2, " ", homeTC, homeBC)
  1614.         printA("Shell    +", 8, 2, false, homeTC, homeBC)
  1615.         printA("External +", 8, 3, false, homeTC, homeBC)
  1616.     elseif sObject == "red" then
  1617.         drawBox(14, 9, 2, 2, " ", homeTC, homeBC)
  1618.         printA("Send    +", 14, 2, false, homeTC, homeBC)
  1619.         printA("Receive +", 14, 3, false, homeTC, homeBC)
  1620.     elseif sObject == "app" then
  1621.         drawBox(20, 8, 2, 4, " ", homeTC, homeBC)
  1622.         drawBox(20, 8, 3, 2, " ", homeTC, homeBC)
  1623.         printA("Ink    +", 20, 2, false, homeTC, homeBC)
  1624.         printA("Sketch +", 20, 3, false, homeTC, homeBC)
  1625.         printA("Flow   +", 20, 4, false, homeTC, homeBC)
  1626.         printA("LuaIDE +", 20, 5, false, homeTC, homeBC)
  1627.     elseif sObject == "verinian" then
  1628.         drawBox(41, 10, 2, 3, " ", homeTC, homeBC)
  1629.         drawBox(41, 10, 3, 1, " ", homeTC, homeBC)
  1630.         printA("Shutdown +", 41, 2, false, homeTC, homeBC)
  1631.         printA("Restart  +", 41, 3, false, homeTC, homeBC)
  1632.         printA("Update   +", 41, 4, false, homeTC, homeBC)
  1633.         drawBox(41, 10, 5, 2, " ", homeTC, "cyan")
  1634.         printA(" Version: ", 41, 5, false, homeTC, "cyan")
  1635.         printA("  "..tostring(nVersion), 41, 6, false, homeTC, "cyan")
  1636.     end
  1637. end
  1638.  
  1639. function drawShortcuts()
  1640.     -- // Shortcut #1: Explorer/File Manager
  1641.     paintutils.drawPixel(3, 3, colours.yellow)
  1642.     paintutils.drawPixel(4, 3, colours.yellow)
  1643.     paintutils.drawPixel(5, 3, colours.yellow)
  1644.     paintutils.drawPixel(3, 4, colours.yellow)
  1645.     paintutils.drawPixel(4, 4, colours.yellow)
  1646.     paintutils.drawPixel(5, 4, colours.yellow)
  1647.     paintutils.drawPixel(6, 4, colours.yellow)
  1648.     paintutils.drawPixel(3, 5, colours.yellow)
  1649.     paintutils.drawPixel(4, 5, colours.yellow)
  1650.     paintutils.drawPixel(5, 5, colours.yellow)
  1651.     paintutils.drawPixel(6, 5, colours.yellow)
  1652.     printA("//", 3, 5, false, "white", "yellow")
  1653.     printA("FILE", 3, 6, false, "blue", "lightGrey")
  1654.  
  1655.     -- // Shortcut #2: LuaIDE
  1656.     paintutils.drawPixel(3, 8, colours.lime)
  1657.     paintutils.drawPixel(4, 8, colours.lime)
  1658.     paintutils.drawPixel(5, 8, colours.lime)
  1659.     paintutils.drawPixel(6, 8, colours.lime)
  1660.     paintutils.drawPixel(3, 9, colours.black)
  1661.     paintutils.drawPixel(6, 9, colours.black)
  1662.     paintutils.drawPixel(3, 10, colours.black)
  1663.     paintutils.drawPixel(4, 10, colours.black)
  1664.     paintutils.drawPixel(5, 10, colours.black)
  1665.     paintutils.drawPixel(6, 10, colours.black)
  1666.     paintutils.drawPixel(4, 9, colours.black)
  1667.     paintutils.drawPixel(5, 9, colours.black)
  1668.     printA(">_", 3, 9, false, "white", "black")
  1669.     printA("LUAI", 3, 11, false, "blue", "lightGrey")
  1670.  
  1671.     -- // Shortcut #3: Sketch
  1672.     paintutils.drawPixel(3, 13, colours.blue)
  1673.     paintutils.drawPixel(4, 13, colours.yellow)
  1674.     paintutils.drawPixel(5, 13, colours.lime)
  1675.     paintutils.drawPixel(6, 13, colours.pink)
  1676.     paintutils.drawPixel(3, 14, colours.purple)
  1677.     paintutils.drawPixel(4, 14, colours.white)
  1678.     paintutils.drawPixel(5, 14, colours.grey)
  1679.     paintutils.drawPixel(6, 14, colours.lightGrey)
  1680.     paintutils.drawPixel(3, 15, colours.magenta)
  1681.     paintutils.drawPixel(4, 15, colours.brown)
  1682.     paintutils.drawPixel(5, 15, colours.black)
  1683.     paintutils.drawPixel(6, 15, colours.red)
  1684.     printA("#", 3, 15, false, "white", "magenta")
  1685.     printA("DRAW", 3, 16, false, "blue", "lightGrey")
  1686.  
  1687.     -- // Shortcut #4: Blaze Email Client
  1688.     paintutils.drawPixel(9, 3, colours.red)
  1689.     paintutils.drawPixel(10, 3, colours.red)
  1690.     paintutils.drawPixel(11, 3, colours.red)
  1691.     paintutils.drawPixel(12, 3, colours.red)
  1692.     paintutils.drawPixel(9, 4, colours.red)
  1693.     paintutils.drawPixel(10, 4, colours.lightGrey)
  1694.     paintutils.drawPixel(11, 4, colours.lightGrey)
  1695.     paintutils.drawPixel(12, 4, colours.red)
  1696.     paintutils.drawPixel(9, 5, colours.red)
  1697.     paintutils.drawPixel(10, 5, colours.red)
  1698.     paintutils.drawPixel(11, 5, colours.red)
  1699.     paintutils.drawPixel(12, 5, colours.red)
  1700.     printA("@", 10, 4, false, "black", "lightGrey")
  1701.     printA("BLZE", 9, 6, false, "blue", "lightGrey")
  1702.  
  1703.     -- // Shortcut #4: Blaze File Finder
  1704.     paintutils.drawPixel(9, 8, colours.blue)
  1705.     paintutils.drawPixel(10, 8, colours.blue)
  1706.     paintutils.drawPixel(11, 8, colours.blue)
  1707.     paintutils.drawPixel(12, 8, colours.white)
  1708.     paintutils.drawPixel(9, 9, colours.blue)
  1709.     paintutils.drawPixel(10, 9, colours.blue)
  1710.     paintutils.drawPixel(11, 9, colours.blue)
  1711.     paintutils.drawPixel(12, 9, colours.blue)
  1712.     paintutils.drawPixel(9, 10, colours.blue)
  1713.     paintutils.drawPixel(10, 10, colours.blue)
  1714.     paintutils.drawPixel(11, 10, colours.blue)
  1715.     paintutils.drawPixel(12, 10, colours.blue)
  1716.     printA("//", 9, 10, false, "lime", "blue")
  1717.     printA("FIND", 9, 11, false, "blue", "lightGrey")
  1718.  
  1719.     --[[ // Draw Statistics
  1720.     drawBox(40, 12, 4, 1, " ", "white", "lightGrey")
  1721.     printA(" Statistics ", 40, 4, false, "white", "lightGrey")
  1722.     printA(" Libs: "..tostring(#fs.list("/core/libs")), 40, 5, false, "blue", "white")
  1723.     printA(" Add-Ons: "..tostring(#fs.list("/core/addons")), 40, 6, false, "blue", "white")
  1724.     printA(" Configs: "..tostring(#fs.list("/core/config")), 40, 7, false, "blue", "white")
  1725.     printA(" Help: "..tostring(#fs.list("/core/help")), 40, 8, false, "blue", "white")
  1726.     printA(" Apps: "..tostring(#fs.list("/core/apps")), 40, 9, false, "blue", "white")
  1727.     printA(" Themes: "..tostring(#fs.list("/core/themes")), 40, 10, false, "blue", "white")
  1728.     printA(" Users: "..tostring(#fs.list("/core/users")), 40, 11, false, "blue", "white")]]
  1729. end
  1730. function home()
  1731.     recentTasks = {}
  1732.     desktc = "blue"
  1733.     deskbc = "lightGrey"
  1734.     -- desktop
  1735.     cs()
  1736.     colourScreen()
  1737.     drawTaskbar(false)
  1738.     drawShortcuts()
  1739.     drawBox(1, 51, 1, 1, " ", "blue", "grey")
  1740.     drawBox(2, 5, 1, 1, " ", desktc, deskbc)
  1741.     drawBox(8, 5, 1, 1, " ", desktc, deskbc)
  1742.     drawBox(14, 5, 1, 1, " ", desktc, deskbc)
  1743.     drawBox(20, 5, 1, 1, " ", desktc, deskbc)
  1744.     drawBox(41, 10, 1, 1, " ", desktc, deskbc)
  1745.     printA("NEW", 3, 1, false, desktc, deskbc)
  1746.     printA("RUN", 9, 1, false, desktc, deskbc)
  1747.     printA("RED", 15, 1, false, desktc, deskbc)
  1748.     printA("APP", 21, 1, false, desktc, deskbc)
  1749.     printA("Verinian", 42, 1, false, desktc, deskbc)
  1750.  
  1751.     while true do
  1752.         local args = { os.pullEvent() }
  1753.         if args[1] == "timer" then
  1754.             drawTaskbar()
  1755.         elseif args[1] == "mouse_click" then
  1756.             if args[2] == 1 then
  1757.                 if (args[3] >= 1 and args[3] <= 3) and (args[4] == 19) then
  1758.                     deskMenu("go")
  1759.                     local args1 = { os.pullEvent("mouse_click") }
  1760.                     if args[2] == 1 then
  1761.                         if (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 14) then
  1762.                             addons("view")
  1763.                             break
  1764.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 15) then
  1765.                             cpanel()
  1766.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 16) then
  1767.                             filebrowser()
  1768.                             table.insert(recentTasks, "File Browser")
  1769.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 17) then
  1770.                             deskMenu("games")
  1771.                             local args2 = { os.pullEvent("mouse_click") }
  1772.                             if args2[2] == 1 then
  1773.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  1774.                                     table.insert(recentTasks, "Lazers")
  1775.                                     game_laser()
  1776.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  1777.                                     table.insert(recentTasks, "Stacker")
  1778.                                     game_stacker()
  1779.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  1780.                                     table.insert(recentTasks, "Project Alpha")
  1781.                                     game_alpha()
  1782.                                 else
  1783.                                     deskMenu("clear")
  1784.                                 end
  1785.                             end
  1786.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 18) then
  1787.                             deskMenu("programs")
  1788.                             local args2 = { os.pullEvent("mouse_click") }
  1789.                             if args2[2] == 1 then
  1790.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 12) then
  1791.                                     table.insert(recentTasks, "Blaze Email Client")
  1792.                                     blaze_main()
  1793.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 13) then
  1794.                                     table.insert(recentTasks, "L2P Live Email Client")
  1795.                                     liveemail()
  1796.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 14) then
  1797.                                     table.insert(recentTasks, "SHA256 Test")
  1798.                                     sha256test()
  1799.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  1800.                                     table.insert(recentTasks, "Trasmit")
  1801.                                     transmit("display")
  1802.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  1803.                                     table.insert(recentTasks, "Ink")
  1804.                                     ink()
  1805.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  1806.                                     table.insert(recentTasks, "Sketch")
  1807.                                     sketch()
  1808.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 18) then
  1809.                                     table.insert(recentTasks, "LuaIDE")
  1810.                                     luaide()
  1811.                                 else
  1812.                                     deskMenu("clear")
  1813.                                 end
  1814.                             end
  1815.                         else
  1816.                             deskMenu("clear")
  1817.                         end
  1818.                     end
  1819.                 elseif (args[3] >= 3 and args[3] <= 6) and (args[4] >= 3 and args[4] <= 6) then
  1820.                     filebrowser()
  1821.                 elseif (args[3] >= 3 and args[3] <= 6) and (args[4] >= 8 and args[4] <= 11) then
  1822.                     luaide()
  1823.                 elseif (args[3] >= 3 and args[3] <= 6) and (args[4] >= 13 and args[4] <= 17) then
  1824.                     sketch()
  1825.                 elseif (args[3] >= 8 and args[3] <= 12) and (args[4] >= 3 and args[4] <= 6) then
  1826.                     blaze_inbox(1)
  1827.                 elseif (args[3] >=8 and args[3] <= 12) and (args[4] >= 8 and args[4] <= 11) then
  1828.                     fb_main()
  1829.                 elseif (args[3] >= 41 and args[3] <= 50) and (args[4] == 1) then
  1830.                     deskMenu("verinian")
  1831.                     local args1 = { os.pullEvent("mouse_click") }
  1832.                     if args1[2] == 1 then
  1833.                         if (args1[3] >= 41 and args1[3] <= 50) and (args1[4] == 2) then
  1834.                             VDEControl("shutdown")
  1835.                         elseif (args1[3] >= 41 and args1[3] <= 50) and (args1[4] == 3) then
  1836.                             VDEControl("restart")
  1837.                         elseif (args1[3] >= 41 and args1[3] <= 50) and (args1[4] == 4) then
  1838.                             VDEControl("update")
  1839.                         else
  1840.                             deskMenu("clear")
  1841.                         end
  1842.                     end
  1843.                 elseif (args[3] >= 46 and args[3] <= 51) and (args[4] == 19) then
  1844.                     deskMenu("time")
  1845.                     local args = { os.pullEvent("mouse_click") }
  1846.                     if (args[3] >= 1 and args[3] <= 51) and (args[4] >= 1 and args[4] <= 19) then
  1847.                         deskMenu("clear")
  1848.                     end
  1849.                 elseif (args[3] >= 2 and args[3] <= 6) and (args[4] == 1) then
  1850.                     deskMenu("new")
  1851.                     local args1 = { os.pullEvent("mouse_click") }
  1852.                     if args[2] == 1 then
  1853.                         if (args1[3] >= 2 and args1[3] <= 13) and (args1[4] == 2) then
  1854.                             table.insert(recentTasks, "LuaIDE (GravityScore")
  1855.                             luaide()
  1856.                             break
  1857.                         elseif (args1[3] >= 2 and args1[3] <= 13) and (args1[4] == 3) then
  1858.                             table.insert(recentTasks, "URL Downloader")
  1859.                             URLDownload()
  1860.                         else
  1861.                             deskMenu("clear")
  1862.                         end
  1863.                     end
  1864.                 elseif (args[3] >= 8 and args[3] <= 12) and (args[4] == 1) then
  1865.                     deskMenu("run")
  1866.                     local args1 = {os.pullEvent("mouse_click")}
  1867.                     if args[2] == 1 then
  1868.                         if (args1[3] >= 2 and args1[3] <= 13) and (args1[4] == 2) then
  1869.                             table.insert(recentTasks, "Shell")
  1870.                             vdeShell()
  1871.                             break
  1872.                         elseif (args1[3] >= 2 and args1[3] <= 13) and (args1[4] == 3) then
  1873.                             table.insert(recentTasks, "External Launcher")                         
  1874.                             launcher()
  1875.                         else
  1876.                             deskMenu("clear")
  1877.                         end
  1878.                     end
  1879.                 elseif (args[3] >= 14 and args[3] <= 18) and (args[4] == 1) then
  1880.                     deskMenu("red")
  1881.                     local args1 = {os.pullEvent("mouse_click")}
  1882.                     if args[2] == 1 then
  1883.                         if (args1[3] >= 14 and args1[3] <= 18) and (args1[4] == 2) then
  1884.                             table.insert(recentTasks, "Transmit")
  1885.                             transmit("send")
  1886.                         elseif (args1[3] >= 14 and args1[3] <= 18) and (args1[4] == 3) then
  1887.                             table.insert(recentTasks, "Transmit")
  1888.                             transmit("receive")
  1889.                         else
  1890.                             deskMenu("clear")
  1891.                         end
  1892.                     end
  1893.                 elseif (args[3] >= 20 and args[3] <= 24) and (args[4] == 1) then
  1894.                     deskMenu("app")
  1895.                    
  1896.                     local args1 = {os.pullEvent("mouse_click")}
  1897.                     if args1[2] == 1 then
  1898.                         if (args1[3] >= 20 and args1[3] <= 24) and (args1[4] == 2) then
  1899.                             table.insert(recentTasks, "Ink (OEED)")
  1900.                             ink()
  1901.                             break
  1902.                         elseif (args1[3] >= 20 and args1[3] <= 24) and (args1[4] == 3) then
  1903.                             table.insert(recentTasks, "Sketch (OEED)")
  1904.                             sketch()
  1905.                             break
  1906.                         elseif (args1[3] >= 20 and args1[3] <= 24) and (args1[4] == 4) then
  1907.                             table.insert(recentTasks, "FlowOffice (Konnichen)")
  1908.                             flowoffice()
  1909.                             break
  1910.                         elseif (args1[3] >= 20 and args1[3] <= 24) and (args1[4] == 5) then
  1911.                             table.insert(recentTasks, "LuaIDE (GravityScore)")
  1912.                             luaide()
  1913.                             break
  1914.                         else
  1915.                             deskMenu("clear")
  1916.                         end
  1917.                     end
  1918.                 end
  1919.             end
  1920.         end
  1921.     end
  1922. end
  1923.  
  1924. function game_stacker()
  1925.     drawPopup("Attempting to run...")
  1926.     sleep(1)
  1927.     shell.run("/core/apps/Stacker")
  1928.     home()
  1929. end
  1930.  
  1931. function game_laser()
  1932.     drawPopup("Attempting to run...")
  1933.     sleep(1)
  1934.     shell.run("/core/apps/Lazers")
  1935.     home()
  1936. end
  1937.  
  1938. function game_alpha()
  1939.     drawPopup("Game isn't installed")
  1940. end
  1941. --[[ Window API
  1942.  
  1943.     window.create(parent, x, y, width, height, visible)
  1944.  
  1945.     write()
  1946.     clear()
  1947.     clearLine()
  1948.     getCursorPos()
  1949.     setCursorPos(x, y)
  1950.     SetCursorBlink(blink)
  1951.     isColour()
  1952.     setTextColour(colour)
  1953.     setBackgroundColour(colour)
  1954.     getSize()
  1955.     scroll(n)
  1956.     setVisible(boolean)
  1957.     redraw()
  1958.     restoreCursor()
  1959.     getPosition()
  1960.     reposition(x,y)
  1961. ]]
  1962.  
  1963. function runExtGame(gameName)
  1964.     -- Runs an external game
  1965.     drawPopup("Executing: "..tostring(gameName))
  1966.     sleep(1)
  1967.     shell.run("/core/apps/"..gameName)
  1968.     home()
  1969. end
  1970.  
  1971. function liveemail()
  1972.     -- Live Email Client
  1973.     -- Vars
  1974.     tc = "white"
  1975.     bc = "cyan"
  1976.     text1 = "> Username: "
  1977.     text2 = "> Recipient: "
  1978.     text3 = "> Subject: "
  1979.     text4 = "> Message: "
  1980.     a = {}
  1981.  
  1982.     -- New Code:
  1983.     function le_drawScreen(strPage, strInstructions)
  1984.         cs()
  1985.         drawBox(1, 51, 1, 2, " ", tc, bc)
  1986.         printC("Lua to PHP Email Client - Created By DannySMc", 1, false, tc, bc)
  1987.         printC(">> "..strPage.." <<", 2, false, tc, bc)
  1988.         drawBox(1, 51, 19, 1, " ", tc, bc)
  1989.         printC(strInstructions, 19, 5, tc, bc)
  1990.     end
  1991.  
  1992.     function le_main()
  1993.         cs()
  1994.         le_drawScreen("Add Recepient Emails", "1 = Add | 2 = Remove | 3 = Accept")
  1995.         drawBox(1,51,7,1, " ", tc, bc)
  1996.         setCol("white", "cyan")
  1997.         term.setCursorPos(1,7)
  1998.         print("> Added Recipients:")
  1999.         resetCol()
  2000.  
  2001.         while true do
  2002.             if #a > 0  then
  2003.                 term.setCursorPos(1, 8)
  2004.                 for k, v in ipairs(a) do
  2005.                     print(k..": "..v)
  2006.                 end
  2007.             end
  2008.             local args = { os.pullEvent("char") }
  2009.             if args[2] == "1" then
  2010.                 term.setCursorPos(1,4)
  2011.                 print("> Add a recipient:")
  2012.                 write(": ")
  2013.                 local recipient = tostring(read())
  2014.                 if #recipient > 9 then
  2015.                     printC(">> Recipient Added! <<", 18, false, "lime", "black")
  2016.                     sleep(1.5)
  2017.                     table.insert(a, recipient)
  2018.                     le_main()
  2019.                 else
  2020.                     printC(">> Needs to be more than 10 characters <<", 18, false, "lime", "black")
  2021.                     sleep(2.5)
  2022.                     le_main()
  2023.                 end
  2024.             elseif args[2] == "2" then
  2025.                 table.remove(a)
  2026.                 le_main()
  2027.             elseif args[2] == "3" then
  2028.                 if #a < 1 then
  2029.                     printC(">> Please add more than 1 recipient <<", 18, false, "lime", "black")
  2030.                     sleep(2.5)
  2031.                     le_main()
  2032.                 else
  2033.                     lecreate(a)
  2034.                 end
  2035.             end
  2036.         end
  2037.     end
  2038.  
  2039.  
  2040.     function le_create(tRecipients)
  2041.         cs()
  2042.         le_drawScreen("Create email", "Fill out information")
  2043.         drawBox(1, 51, 4, 1, " ", tc, bc)
  2044.         drawBox(1, 51, 6, 1, " ", tc, bc)
  2045.         printC("Message:", 6, false, tc, bc)
  2046.         printC("Subject:", 4, 5, tc, bc)
  2047.         write(": ")
  2048.         local subject = tostring(read())
  2049.         if #subject < 5 then
  2050.             printC(">> Subject length needs to be more than 5 <<", 18, false, "lime", "black")
  2051.             sleep(2.5)
  2052.             le_create(tRecipients)
  2053.         end
  2054.         term.setCursorPos(1,7)
  2055.         write(": ")
  2056.         local message1 = tostring(read())
  2057.         message = wrap(message1, 51)
  2058.         printC(">> Working please wait... <<", 18, false, "lime", "black")
  2059.         sleep(1)
  2060.         le_check(tRecipients, subject, message, message1)
  2061.     end
  2062.  
  2063.     function le_check(tRecipients, sSubject, tMessage, sMessage)
  2064.         le_drawScreen("Check your subject and message", "1 = Send | 2 = Restart")
  2065.         drawBox(1,51,4,3," ", tc, bc)
  2066.         printC("Subject:", 4, 5, tc, bc)
  2067.         term.setCursorPos(2,5)
  2068.         print("Subject: "..sSubject)
  2069.         printC("Message:",6, 7, tc, bc)
  2070.         for _,v in ipairs(tMessage) do
  2071.             print(v)
  2072.         end
  2073.         sMessage = sMessage
  2074.         if #tMessage > 12 then
  2075.             print(" ")
  2076.             drawBox(1,51,19,1," ", tc, bc)
  2077.             printC("1 = Send | 2 = Restart", 4, 5, tc, bc)
  2078.         end
  2079.         while true do
  2080.             local args = { os.pullEvent("char") }
  2081.             if args[2] == "1" then
  2082.                 le_send(tRecipients, sSubject, tMessage, sMessage)
  2083.             elseif args[2] == "2" then
  2084.                 le_create(tRecipients)
  2085.             end
  2086.         end
  2087.     end
  2088.  
  2089.     function le_send(tRecipients, sSubject, tMessage, sMessage)
  2090.         cs()
  2091.         le_drawScreen("Send Message", "Add a username and press enter to send")
  2092.         drawBox(1, 51, 4, 3, " ", tc, bc)
  2093.         printC("Your username:", 4, 5, tc, bc)
  2094.         write(": ")
  2095.         local sUsername = tostring(read())
  2096.  
  2097.         sMessage = sMessage
  2098.  
  2099.         term.setCursorPos(1,8)
  2100.         print("> We are sending your email")
  2101.  
  2102.         url = "http://dannysmc.com/ccdb/email.php"
  2103.  
  2104.         if #tRecipients > 1 then
  2105.             for _,v in ipairs(tRecipients) do
  2106.                 http.post(url, "username="..textutils.urlEncode(tostring(sUsername)).."&".."emailto="..textutils.urlEncode(tostring(v)).."&".."emailsubject="..textutils.urlEncode(tostring(sSubject)).."&".."emailmessage="..textutils.urlEncode(tostring(sMessage)))
  2107.             end
  2108.         else
  2109.             http.post(url, "username="..textutils.urlEncode(tostring(sUsername)).."&".."emailto="..textutils.urlEncode(tostring(tRecipients[1])).."&".."emailsubject="..textutils.urlEncode(tostring(sSubject)).."&".."emailmessage="..textutils.urlEncode(tostring(sMessage)))
  2110.         end
  2111.  
  2112.         sleep(0.5)
  2113.         print("> Done!")
  2114.         a = {}
  2115.         sleep(2)
  2116.         le_main()
  2117.     end
  2118.  
  2119.     le_main()
  2120. end
  2121.  
  2122. function sha256test()
  2123.     -- SHA256 Hashing Test
  2124.     local maintc = "white"
  2125.     local mainbc = "cyan"
  2126.     local texttc = "black"
  2127.     local textbc = "white"
  2128.     drawBox(1, 51, 6, 6, " ", maintc, mainbc)
  2129.     drawBox(1, 51, 7, 4, " ", maintc, mainbc)
  2130.     drawBox(1, 51, 8, 2, " ", maintc, mainbc)
  2131.     printC("SHA256 Hashing Algorithm Test", 6, false, maintc, mainbc)
  2132.     drawBox(1, 51, 7, 1, " ", texttc, textbc)
  2133.     drawBox(1, 51, 9, 2, " ", texttc, textbc)
  2134.     setCol(texttc, textbc)
  2135.     term.setCursorPos(1,7)
  2136.     write(": ")
  2137.     local toHash = tostring(read())
  2138.     local hashed = sha256(toHash)
  2139.     local count = 8
  2140.     for _,v in ipairs(wordwrap(hashed, 49)) do
  2141.         term.setCursorPos(1, count)
  2142.         print(v)
  2143.         count = count + 1
  2144.     end
  2145.     sleep(2.5)
  2146.     home()
  2147. end
  2148.  
  2149. function cpanel(cmd)
  2150.     local checkSystem = {}
  2151.     local sPath = "/core/config"
  2152.     local tFiles = {"Config_OS", "Config_USER", "Config_REDNET", "Config_MISC",}
  2153.  
  2154.     for _, v in ipairs(tFiles) do
  2155.         if fs.exists(sPath.."/"..v) == false then
  2156.             drawPopup("An error occured while loading cpanel...")
  2157.             sleep(2.5)
  2158.             drawPopup("Configuration files are missing...")
  2159.             sleep(2.5)
  2160.             drawPopup("Please re-install VDE to initiliase files!")
  2161.             sleep(2.5)
  2162.             home()
  2163.         end
  2164.     end
  2165.    
  2166.     local tConfigOS = loadConfig(sPath.."/Config_OS")
  2167.     local tConfigUSER = loadConfig(sPath.."/Config_USER")
  2168.     local tConfigREDNET = loadConfig(sPath.."/Config_REDNET")
  2169.     local tConfigMISC = loadConfig(sPath.."/Config_MISC")
  2170.  
  2171.     if cmd == "OS" then
  2172.         local menutc = "blue"
  2173.         local menubc = "lightGrey"
  2174.         local menubc2 = "grey"
  2175.         local texttc = "black"
  2176.         local textbc = "white"
  2177.         local optiontc = "white"
  2178.         local optionbc = "cyan"
  2179.         local menubc3 = "blue"
  2180.  
  2181.         cs()
  2182.         colourScreen()
  2183.         drawTaskbar(false)
  2184.         drawBox(1, 51, 1, 1, " ", menutc, menubc2)
  2185.         printA(" HOME ", 45, 1, false, menutc, menubc)
  2186.         printA(" OS ", 2, 1, false, "lime", menubc)
  2187.         printA(" USER ", 7, 1, false, menutc, menubc)
  2188.         printA(" REDNET ", 14, 1, false, menutc, menubc)
  2189.         printA(" MISC ", 23, 1, false, menutc, menubc)
  2190.         setCol(texttc, textbc)
  2191.         term.setCursorPos(1,2)
  2192.  
  2193.         drawBox(48, 3, 2, 17, " ", "pink", "pink")
  2194.         drawBox(49, 1, 2, 17, " ", "pink", "pink")
  2195.         drawBox(1, 51, 2, 17, " ", optiontc, optionbc)
  2196.         drawBox(47, 1, 2, 17, " ", optiontc, optionbc)
  2197.         drawBox(44, 1, 2, 17, " ", optiontc, optionbc)
  2198.         drawBox(1, 51, 16, 1, " ", optiontc, optionbc)
  2199.         drawBox(1, 51, 17, 2, " ", texttc, textbc)
  2200.         printC("Toggle options by pressing 'RUN' for that option", 17, false, "lime", "white")
  2201.         printC("Yellow = On/True & Red = Off/False", 18, false, "lime", "white")
  2202.  
  2203.         local count = 3
  2204.         for k1, v1 in ipairs(tConfigOS[1]) do
  2205.             printA(k1..": "..v1, 2, count, false, texttc, textbc)
  2206.             printA("RUN", 48, count, false, "red", "pink")
  2207.             drawBox(45, 2, count+1, 1, " ", optiontc, optionbc)
  2208.             count = count + 2
  2209.         end
  2210.         count = 3
  2211.         for _, v in ipairs(tConfigOS[2]) do
  2212.             if v then
  2213.                 drawBox(45, 2, count, 1, " ", "yellow", "yellow")
  2214.             else
  2215.                 drawBox(45, 2, count, 1, " ", "red", "red")
  2216.             end
  2217.             count = count + 2
  2218.         end
  2219.  
  2220.         while true do
  2221.             local args = { os.pullEvent() }
  2222.             if args[1] == "timer" then
  2223.                 drawTaskbar()
  2224.             elseif args[1] == "mouse_click" then
  2225.                 if (args[3] >= 1 and args[3] <= 3) and (args[4] == 19) then
  2226.                     deskMenu("go")
  2227.                     local args1 = { os.pullEvent("mouse_click") }
  2228.                     if args[2] == 1 then
  2229.                         if (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 14) then
  2230.                             addons("view")
  2231.                             break
  2232.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 15) then
  2233.                             cpanel()
  2234.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 16) then
  2235.                             filebrowser()
  2236.                             table.insert(recentTasks, "File Browser")
  2237.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 17) then
  2238.                             deskMenu("games")
  2239.                             local args2 = { os.pullEvent("mouse_click") }
  2240.                             if args2[2] == 1 then
  2241.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  2242.                                     table.insert(recentTasks, "Lazers")
  2243.                                     game_lazers()
  2244.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  2245.                                     table.insert(recentTasks, "Stacker")
  2246.                                     game_stacker()
  2247.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  2248.                                     table.insert(recentTasks, "Project Alpha")
  2249.                                     game_alpha()
  2250.                                 else
  2251.                                     deskMenu("clear", "cpanelos")
  2252.                                 end
  2253.                             end
  2254.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 18) then
  2255.                             deskMenu("programs")
  2256.                             local args2 = { os.pullEvent("mouse_click") }
  2257.                             if args2[2] == 1 then
  2258.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 12) then
  2259.                                     table.insert(recentTasks, "Blaze Email Client")
  2260.                                     blaze_main()
  2261.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 13) then
  2262.                                     table.insert(recentTasks, "L2P Live Email Client")
  2263.                                     liveemail()
  2264.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 14) then
  2265.                                     table.insert(recentTasks, "SHA256 Test")
  2266.                                     sha256test()
  2267.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  2268.                                     table.insert(recentTasks, "Trasmit")
  2269.                                     transmit("display")
  2270.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  2271.                                     table.insert(recentTasks, "Ink")
  2272.                                     ink()
  2273.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  2274.                                     table.insert(recentTasks, "Sketch")
  2275.                                     sketch()
  2276.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 18) then
  2277.                                     table.insert(recentTasks, "LuaIDE")
  2278.                                     luaide()
  2279.                                 else
  2280.                                     deskMenu("clear", "cpanelos")
  2281.                                 end
  2282.                             end
  2283.                         else
  2284.                             deskMenu("clear", "cpanelos")
  2285.                         end
  2286.                     end
  2287.                 elseif (args[3] >= 2 and args[3] <= 5) and (args[4] == 1) then
  2288.                     -- OS
  2289.                     cpanel("OS")
  2290.                     break
  2291.                 elseif (args[3] >= 7 and args[3] <= 12) and (args[4] == 1) then
  2292.                     -- User
  2293.                     cpanel("USER")
  2294.                     break
  2295.                 elseif (args[3] >= 14 and args[3] <= 21) and (args[4] == 1) then
  2296.                     -- Rednet
  2297.                     cpanel("REDNET")
  2298.                     break
  2299.                 elseif (args[3] >= 23 and args[3] <= 28) and (args[4] == 1) then
  2300.                     -- Misc
  2301.                     cpanel("MISC")
  2302.                     break
  2303.                 elseif (args[3] >= 45 and args[3] <= 50) and (args[4] == 1) then
  2304.                     home()
  2305.                 elseif args[3] >= 48 and args[3] <= 50 then
  2306.                     -- Logic For Options
  2307.                     if args[4] == 3 then
  2308.                         if #tConfigOS[1] >= 1 then
  2309.                             -- Option 1
  2310.                             if tConfigOS[2][1] == true then
  2311.                                 tConfigOS[2][1] = false
  2312.                             else
  2313.                                 tConfigOS[2][1] = true
  2314.                             end
  2315.                             saveConfig(tConfigOS, sPath.."/"..tFiles[1])
  2316.                             VDEControl("uninstall")
  2317.                             break
  2318.                         end
  2319.                     elseif args[4] == 5 then
  2320.                         -- Option 2
  2321.                         if #tConfigOS[1] >= 2 then
  2322.                             if tConfigOS[2][2] == true then
  2323.                                 tConfigOS[2][2] = false
  2324.                             else
  2325.                                 tConfigOS[2][2] = true
  2326.                             end
  2327.                             saveConfig(tConfigOS, sPath.."/"..tFiles[1])
  2328.                             VDEControl("install")
  2329.                             cpanel("OS")
  2330.                         end
  2331.                     elseif args[4] == 7 then
  2332.                         -- Option 3
  2333.                         if #tConfigOS[1] >= 3 then
  2334.                             if tConfigOS[2][3] == true then
  2335.                                 tConfigOS[2][3] = false
  2336.                             else
  2337.                                 tConfigOS[2][3] = true
  2338.                             end
  2339.                             saveConfig(tConfigOS, sPath.."/"..tFiles[1])
  2340.                             cpanel("OS")
  2341.                         end
  2342.                     elseif args[4] == 9 then
  2343.                         -- Option 4
  2344.                         if #tConfigOS[1] >= 4 then
  2345.                             if tConfigOS[2][4] == true then
  2346.                                 tConfigOS[2][4] = false
  2347.                             else
  2348.                                 tConfigOS[2][4] = true
  2349.                             end
  2350.                             saveConfig(tConfigOS, sPath.."/"..tFiles[1])
  2351.                             cpanel("OS")
  2352.                         end
  2353.                     elseif args[4] == 11 then
  2354.                         -- Option 5
  2355.                         if #tConfigOS[1] >= 5 then
  2356.                             if tConfigOS[2][5] == true then
  2357.                                 tConfigOS[2][5] = false
  2358.                             else
  2359.                                 tConfigOS[2][5] = true
  2360.                             end
  2361.                             saveConfig(tConfigOS, sPath.."/"..tFiles[1])
  2362.                             cpanel("OS")
  2363.                         end
  2364.                     elseif args[4] == 13 then
  2365.                         -- Option 6
  2366.                         if #tConfigOS[1] >= 6 then
  2367.                             if tConfigOS[2][6] == true then
  2368.                                 tConfigOS[2][6] = false
  2369.                             else
  2370.                                 tConfigOS[2][6] = true
  2371.                             end
  2372.                             saveConfig(tConfigOS, sPath.."/"..tFiles[1])
  2373.                             cpanel("OS")
  2374.                         end
  2375.                     elseif args[4] == 15 then
  2376.                         -- Option 7
  2377.                         if #tConfigOS[1] >= 7 then
  2378.                             if tConfigOS[2][7] == true then
  2379.                                 tConfigOS[2][7] = false
  2380.                             else
  2381.                                 tConfigOS[2][7] = true
  2382.                             end
  2383.                             saveConfig(tConfigOS, sPath.."/"..tFiles[1])
  2384.                             cpanel("OS")
  2385.                         end
  2386.                     end
  2387.                 end
  2388.             end
  2389.         end
  2390.     elseif cmd == "USER" then
  2391.         local menutc = "blue"
  2392.         local menubc = "lightGrey"
  2393.         local menubc2 = "grey"
  2394.         local texttc = "black"
  2395.         local textbc = "white"
  2396.         local optiontc = "white"
  2397.         local optionbc = "cyan"
  2398.         local menubc3 = "blue"
  2399.  
  2400.         cs()
  2401.         colourScreen()
  2402.         drawTaskbar(false)
  2403.         drawBox(1, 51, 1, 1, " ", menutc, menubc2)
  2404.         printA(" HOME ", 45, 1, false, menutc, menubc)
  2405.         printA(" OS ", 2, 1, false, menutc, menubc)
  2406.         printA(" USER ", 7, 1, false, "lime", menubc)
  2407.         printA(" REDNET ", 14, 1, false, menutc, menubc)
  2408.         printA(" MISC ", 23, 1, false, menutc, menubc)
  2409.         setCol(texttc, textbc)
  2410.         term.setCursorPos(1,2)
  2411.  
  2412.         drawBox(48, 3, 2, 17, " ", "pink", "pink")
  2413.         drawBox(49, 1, 2, 17, " ", "pink", "pink")
  2414.         drawBox(1, 51, 2, 17, " ", optiontc, optionbc)
  2415.         drawBox(47, 1, 2, 17, " ", optiontc, optionbc)
  2416.         drawBox(44, 1, 2, 17, " ", optiontc, optionbc)
  2417.         drawBox(1, 51, 16, 1, " ", optiontc, optionbc)
  2418.         drawBox(1, 51, 17, 2, " ", texttc, textbc)
  2419.         printC("Toggle options by pressing 'RUN' for that option", 17, false, "lime", "white")
  2420.         printC("Yellow = On/True & Red = Off/False", 18, false, "lime", "white")
  2421.  
  2422.         local count = 3
  2423.         for k1, v1 in ipairs(tConfigUSER[1]) do
  2424.             printA(k1..": "..v1, 2, count, false, texttc, textbc)
  2425.             printA("RUN", 48, count, false, "red", "pink")
  2426.             drawBox(45, 2, count+1, 1, " ", optiontc, optionbc)
  2427.             count = count + 2
  2428.         end
  2429.         count = 3
  2430.         for _, v in ipairs(tConfigUSER[2]) do
  2431.             if v then
  2432.                 drawBox(45, 2, count, 1, " ", "yellow", "yellow")
  2433.             else
  2434.                 drawBox(45, 2, count, 1, " ", "red", "red")
  2435.             end
  2436.             count = count + 2
  2437.         end
  2438.  
  2439.         while true do
  2440.             local args = { os.pullEvent() }
  2441.             if args[1] == "timer" then
  2442.                 drawTaskbar()
  2443.             elseif args[1] == "mouse_click" then
  2444.                 if (args[3] >= 1 and args[3] <= 3) and (args[4] == 19) then
  2445.                     deskMenu("go")
  2446.                     local args1 = { os.pullEvent("mouse_click") }
  2447.                     if args[2] == 1 then
  2448.                         if (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 14) then
  2449.                             addons("view")
  2450.                             break
  2451.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 15) then
  2452.                             cpanel()
  2453.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 16) then
  2454.                             filebrowser()
  2455.                             table.insert(recentTasks, "File Browser")
  2456.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 17) then
  2457.                             deskMenu("games")
  2458.                             local args2 = { os.pullEvent("mouse_click") }
  2459.                             if args2[2] == 1 then
  2460.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  2461.                                     table.insert(recentTasks, "Lazers")
  2462.                                     game_lazers()
  2463.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  2464.                                     table.insert(recentTasks, "Stacker")
  2465.                                     game_stacker()
  2466.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  2467.                                     table.insert(recentTasks, "Project Alpha")
  2468.                                     game_alpha()
  2469.                                 else
  2470.                                     deskMenu("clear", "cpaneluser")
  2471.                                 end
  2472.                             end
  2473.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 18) then
  2474.                             deskMenu("programs")
  2475.                             local args2 = { os.pullEvent("mouse_click") }
  2476.                             if args2[2] == 1 then
  2477.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 12) then
  2478.                                     table.insert(recentTasks, "Blaze Email Client")
  2479.                                     blaze_main()
  2480.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 13) then
  2481.                                     table.insert(recentTasks, "L2P Live Email Client")
  2482.                                     liveemail()
  2483.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 14) then
  2484.                                     table.insert(recentTasks, "SHA256 Test")
  2485.                                     sha256test()
  2486.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  2487.                                     table.insert(recentTasks, "Trasmit")
  2488.                                     transmit("display")
  2489.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  2490.                                     table.insert(recentTasks, "Ink")
  2491.                                     ink()
  2492.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  2493.                                     table.insert(recentTasks, "Sketch")
  2494.                                     sketch()
  2495.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 18) then
  2496.                                     table.insert(recentTasks, "LuaIDE")
  2497.                                     luaide()
  2498.                                 else
  2499.                                     deskMenu("clear", "cpaneluser")
  2500.                                 end
  2501.                             end
  2502.                         else
  2503.                             deskMenu("clear", "cpaneluser")
  2504.                         end
  2505.                     end
  2506.                 elseif (args[3] >= 2 and args[3] <= 5) and (args[4] == 1) then
  2507.                     -- OS
  2508.                     cpanel("OS")
  2509.                     break
  2510.                 elseif (args[3] >= 7 and args[3] <= 12) and (args[4] == 1) then
  2511.                     -- User
  2512.                     cpanel("USER")
  2513.                     break
  2514.                 elseif (args[3] >= 14 and args[3] <= 21) and (args[4] == 1) then
  2515.                     -- Rednet
  2516.                     cpanel("REDNET")
  2517.                     break
  2518.                 elseif (args[3] >= 23 and args[3] <= 28) and (args[4] == 1) then
  2519.                     -- Misc
  2520.                     cpanel("MISC")
  2521.                     break
  2522.                 elseif (args[3] >= 45 and args[3] <= 50) and (args[4] == 1) then
  2523.                     home()
  2524.                 elseif args[3] >= 48 and args[3] <= 50 then
  2525.                 -- Logic For Options
  2526.                     if args[4] == 3 then
  2527.                         if #tConfigUSER[1] >= 1 then
  2528.                             -- Option 1
  2529.                             if tConfigUSER[2][1] == true then
  2530.                                 tConfigUSER[2][1] = false
  2531.                             else
  2532.                                 tConfigUSER[2][1] = true
  2533.                             end
  2534.                             saveConfig(tConfigUSER, sPath.."/"..tFiles[2])
  2535.                             cpanel("USER")
  2536.                         end
  2537.                     elseif args[4] == 5 then
  2538.                         -- Option 2
  2539.                         if #tConfigUSER[1] >= 2 then
  2540.                             if tConfigUSER[2][2] == true then
  2541.                                 tConfigUSER[2][2] = false
  2542.                             else
  2543.                                 tConfigUSER[2][2] = true
  2544.                             end
  2545.                             saveConfig(tConfigUSER, sPath.."/"..tFiles[2])
  2546.                             cpanel("USER")
  2547.                         end
  2548.                     elseif args[4] == 7 then
  2549.                         -- Option 3
  2550.                         if #tConfigUSER[1] >= 3 then
  2551.                             if tConfigUSER[2][3] == true then
  2552.                                 tConfigUSER[2][3] = false
  2553.                             else
  2554.                                 tConfigUSER[2][3] = true
  2555.                             end
  2556.                             saveConfig(tConfigUSER, sPath.."/"..tFiles[2])
  2557.                             cpanel("USER")
  2558.                         end
  2559.                     elseif args[4] == 9 then
  2560.                         -- Option 4
  2561.                         if #tConfigUSER[1] >= 4 then
  2562.                             if tConfigUSER[2][4] == true then
  2563.                                 tConfigUSER[2][4] = false
  2564.                             else
  2565.                                 tConfigUSER[2][4] = true
  2566.                             end
  2567.                             saveConfig(tConfigUSER, sPath.."/"..tFiles[2])
  2568.                             cpanel("USER")
  2569.                         end
  2570.                     elseif args[4] == 11 then
  2571.                         -- Option 5
  2572.                         if #tConfigUSER[1] >= 5 then
  2573.                             if tConfigUSER[2][5] == true then
  2574.                                 tConfigUSER[2][5] = false
  2575.                             else
  2576.                                 tConfigUSER[2][5] = true
  2577.                             end
  2578.                             saveConfig(tConfigUSER, sPath.."/"..tFiles[2])
  2579.                             cpanel("USER")
  2580.                         end
  2581.                     elseif args[4] == 13 then
  2582.                         -- Option 6
  2583.                         if #tConfigUSER[1] >= 6 then
  2584.                             if tConfigUSER[2][6] == true then
  2585.                                 tConfigUSER[2][6] = false
  2586.                             else
  2587.                                 tConfigUSER[2][6] = true
  2588.                             end
  2589.                             saveConfig(tConfigUSER, sPath.."/"..tFiles[2])
  2590.                             cpanel("USER")
  2591.                         end
  2592.                     elseif args[4] == 15 then
  2593.                         -- Option 7
  2594.                         if #tConfigUSER[1] >= 7 then
  2595.                             if tConfigUSER[2][7] == true then
  2596.                                 tConfigUSER[2][7] = false
  2597.                             else
  2598.                                 tConfigUSER[2][7] = true
  2599.                             end
  2600.                             saveConfig(tConfigUSER, sPath.."/"..tFiles[2])
  2601.                             cpanel("USER")
  2602.                         end
  2603.                     end
  2604.                 end
  2605.             end
  2606.         end
  2607.     elseif cmd == "REDNET" then
  2608.         local menutc = "blue"
  2609.         local menubc = "lightGrey"
  2610.         local menubc2 = "grey"
  2611.         local texttc = "black"
  2612.         local textbc = "white"
  2613.         local optiontc = "white"
  2614.         local optionbc = "cyan"
  2615.         local menubc3 = "blue"
  2616.  
  2617.         cs()
  2618.         colourScreen()
  2619.         drawTaskbar(false)
  2620.         drawBox(1, 51, 1, 1, " ", menutc, menubc2)
  2621.         printA(" HOME ", 45, 1, false, menutc, menubc)
  2622.         printA(" OS ", 2, 1, false, menutc, menubc)
  2623.         printA(" USER ", 7, 1, false, menutc, menubc)
  2624.         printA(" REDNET ", 14, 1, false, "lime", menubc)
  2625.         printA(" MISC ", 23, 1, false, menutc, menubc)
  2626.         setCol(texttc, textbc)
  2627.         term.setCursorPos(1,2)
  2628.  
  2629.         drawBox(48, 3, 2, 17, " ", "pink", "pink")
  2630.         drawBox(49, 1, 2, 17, " ", "pink", "pink")
  2631.         drawBox(1, 51, 2, 17, " ", optiontc, optionbc)
  2632.         drawBox(47, 1, 2, 17, " ", optiontc, optionbc)
  2633.         drawBox(44, 1, 2, 17, " ", optiontc, optionbc)
  2634.         drawBox(1, 51, 16, 1, " ", optiontc, optionbc)
  2635.         drawBox(1, 51, 17, 2, " ", texttc, textbc)
  2636.         printC("Toggle options by pressing 'RUN' for that option", 17, false, "lime", "white")
  2637.         printC("Yellow = On/True & Red = Off/False", 18, false, "lime", "white")
  2638.  
  2639.         local count = 3
  2640.         for k1, v1 in ipairs(tConfigREDNET[1]) do
  2641.             printA(k1..": "..v1, 2, count, false, texttc, textbc)
  2642.             printA("RUN", 48, count, false, "red", "pink")
  2643.             drawBox(45, 2, count+1, 1, " ", optiontc, optionbc)
  2644.             count = count + 2
  2645.         end
  2646.         count = 3
  2647.         for _, v in ipairs(tConfigREDNET[2]) do
  2648.             if v then
  2649.                 drawBox(45, 2, count, 1, " ", "yellow", "yellow")
  2650.             else
  2651.                 drawBox(45, 2, count, 1, " ", "red", "red")
  2652.             end
  2653.             count = count + 2
  2654.         end
  2655.  
  2656.         while true do
  2657.             local args = { os.pullEvent() }
  2658.             if args[1] == "timer" then
  2659.                 drawTaskbar()
  2660.             elseif args[1] == "mouse_click" then
  2661.                 if (args[3] >= 1 and args[3] <= 3) and (args[4] == 19) then
  2662.                     deskMenu("go")
  2663.                     local args1 = { os.pullEvent("mouse_click") }
  2664.                     if args[2] == 1 then
  2665.                         if (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 14) then
  2666.                             addons("view")
  2667.                             break
  2668.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 15) then
  2669.                             cpanel()
  2670.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 16) then
  2671.                             filebrowser()
  2672.                             table.insert(recentTasks, "File Browser")
  2673.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 17) then
  2674.                             deskMenu("games")
  2675.                             local args2 = { os.pullEvent("mouse_click") }
  2676.                             if args2[2] == 1 then
  2677.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  2678.                                     table.insert(recentTasks, "Lazers")
  2679.                                     game_lazers()
  2680.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  2681.                                     table.insert(recentTasks, "Stacker")
  2682.                                     game_stacker()
  2683.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  2684.                                     table.insert(recentTasks, "Project Alpha")
  2685.                                     game_alpha()
  2686.                                 else
  2687.                                     deskMenu("clear", "cpanelred")
  2688.                                 end
  2689.                             end
  2690.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 18) then
  2691.                             deskMenu("programs")
  2692.                             local args2 = { os.pullEvent("mouse_click") }
  2693.                             if args2[2] == 1 then
  2694.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 12) then
  2695.                                     table.insert(recentTasks, "Blaze Email Client")
  2696.                                     blaze_main()
  2697.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 13) then
  2698.                                     table.insert(recentTasks, "L2P Live Email Client")
  2699.                                     liveemail()
  2700.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 14) then
  2701.                                     table.insert(recentTasks, "SHA256 Test")
  2702.                                     sha256test()
  2703.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  2704.                                     table.insert(recentTasks, "Trasmit")
  2705.                                     transmit("display")
  2706.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  2707.                                     table.insert(recentTasks, "Ink")
  2708.                                     ink()
  2709.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  2710.                                     table.insert(recentTasks, "Sketch")
  2711.                                     sketch()
  2712.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 18) then
  2713.                                     table.insert(recentTasks, "LuaIDE")
  2714.                                     luaide()
  2715.                                 else
  2716.                                     deskMenu("clear", "cpanelred")
  2717.                                 end
  2718.                             end
  2719.                         else
  2720.                             deskMenu("clear", "cpanelred")
  2721.                         end
  2722.                     end
  2723.                 elseif (args[3] >= 2 and args[3] <= 5) and (args[4] == 1) then
  2724.                     -- OS
  2725.                     cpanel("OS")
  2726.                     break
  2727.                 elseif (args[3] >= 7 and args[3] <= 12) and (args[4] == 1) then
  2728.                     -- User
  2729.                     cpanel("USER")
  2730.                     break
  2731.                 elseif (args[3] >= 14 and args[3] <= 21) and (args[4] == 1) then
  2732.                     -- Rednet
  2733.                     cpanel("REDNET")
  2734.                     break
  2735.                 elseif (args[3] >= 23 and args[3] <= 28) and (args[4] == 1) then
  2736.                     -- Misc
  2737.                     cpanel("MISC")
  2738.                     break
  2739.                 elseif (args[3] >= 45 and args[3] <= 50) and (args[4] == 1) then
  2740.                     home()
  2741.                 elseif args[3] >= 48 and args[3] <= 50 then
  2742.                 -- Logic For Options
  2743.                     if args[4] == 3 then
  2744.                         if #tConfigREDNET[1] >= 1 then
  2745.                             -- Option 1
  2746.                             if tConfigREDNET[2][1] == true then
  2747.                                 tConfigREDNET[2][1] = false
  2748.                             else
  2749.                                 tConfigREDNET[2][1] = true
  2750.                             end
  2751.                             saveConfig(tConfigREDNET, sPath.."/"..tFiles[3])
  2752.                             cpanel("REDNET")
  2753.                         end
  2754.                     elseif args[4] == 5 then
  2755.                         -- Option 2
  2756.                         if #tConfigREDNET[1] >= 2 then
  2757.                             if tConfigREDNET[2][2] == true then
  2758.                                 tConfigREDNET[2][2] = false
  2759.                             else
  2760.                                 tConfigREDNET[2][2] = true
  2761.                             end
  2762.                             saveConfig(tConfigREDNET, sPath.."/"..tFiles[3])
  2763.                             cpanel("REDNET")
  2764.                         end
  2765.                     elseif args[4] == 7 then
  2766.                         -- Option 3
  2767.                         if #tConfigREDNET[1] >= 3 then
  2768.                             if tConfigREDNET[2][3] == true then
  2769.                                 tConfigREDNET[2][3] = false
  2770.                             else
  2771.                                 tConfigREDNET[2][3] = true
  2772.                             end
  2773.                             saveConfig(tConfigREDNET, sPath.."/"..tFiles[3])
  2774.                             cpanel("REDNET")
  2775.                         end
  2776.                     elseif args[4] == 9 then
  2777.                         -- Option 4
  2778.                         if #tConfigREDNET[1] >= 4 then
  2779.                             if tConfigREDNET[2][4] == true then
  2780.                                 tConfigREDNET[2][4] = false
  2781.                             else
  2782.                                 tConfigREDNET[2][4] = true
  2783.                             end
  2784.                             saveConfig(tConfigREDNET, sPath.."/"..tFiles[3])
  2785.                             cpanel("REDNET")
  2786.                         end
  2787.                     elseif args[4] == 11 then
  2788.                         -- Option 5
  2789.                         if #tConfigREDNET[1] >= 5 then
  2790.                             if tConfigREDNET[2][5] == true then
  2791.                                 tConfigREDNET[2][5] = false
  2792.                             else
  2793.                                 tConfigREDNET[2][5] = true
  2794.                             end
  2795.                             saveConfig(tConfigREDNET, sPath.."/"..tFiles[3])
  2796.                             cpanel("REDNET")
  2797.                         end
  2798.                     elseif args[4] == 13 then
  2799.                         -- Option 6
  2800.                         if #tConfigREDNET[1] >= 6 then
  2801.                             if tConfigREDNET[2][6] == true then
  2802.                                 tConfigREDNET[2][6] = false
  2803.                             else
  2804.                                 tConfigREDNET[2][6] = true
  2805.                             end
  2806.                             saveConfig(tConfigREDNET, sPath.."/"..tFiles[3])
  2807.                             cpanel("REDNET")
  2808.                         end
  2809.                     elseif args[4] == 15 then
  2810.                         -- Option 7
  2811.                         if #tConfigREDNET[1] >= 7 then
  2812.                             if tConfigREDNET[2][7] == true then
  2813.                                 tConfigREDNET[2][7] = false
  2814.                             else
  2815.                                 tConfigREDNET[2][7] = true
  2816.                             end
  2817.                             saveConfig(tConfigREDNET, sPath.."/"..tFiles[3])
  2818.                             cpanel("REDNET")
  2819.                         end
  2820.                     end
  2821.                 end
  2822.             end
  2823.         end    
  2824.     elseif cmd == "MISC" then
  2825.         local menutc = "blue"
  2826.         local menubc = "lightGrey"
  2827.         local menubc2 = "grey"
  2828.         local texttc = "black"
  2829.         local textbc = "white"
  2830.         local optiontc = "white"
  2831.         local optionbc = "cyan"
  2832.         local menubc3 = "blue"
  2833.  
  2834.         cs()
  2835.         colourScreen()
  2836.         drawTaskbar(false)
  2837.         drawBox(1, 51, 1, 1, " ", menutc, menubc2)
  2838.         printA(" HOME ", 45, 1, false, menutc, menubc)
  2839.         printA(" OS ", 2, 1, false, menutc, menubc)
  2840.         printA(" USER ", 7, 1, false, menutc, menubc)
  2841.         printA(" REDNET ", 14, 1, false, menutc, menubc)
  2842.         printA(" MISC ", 23, 1, false, "lime", menubc)
  2843.         setCol(texttc, textbc)
  2844.         term.setCursorPos(1,2)
  2845.  
  2846.         drawBox(48, 3, 2, 17, " ", "pink", "pink")
  2847.         drawBox(49, 1, 2, 17, " ", "pink", "pink")
  2848.         drawBox(1, 51, 2, 17, " ", optiontc, optionbc)
  2849.         drawBox(47, 1, 2, 17, " ", optiontc, optionbc)
  2850.         drawBox(44, 1, 2, 17, " ", optiontc, optionbc)
  2851.         drawBox(1, 51, 16, 1, " ", optiontc, optionbc)
  2852.         drawBox(1, 51, 17, 2, " ", texttc, textbc)
  2853.         printC("Toggle options by pressing 'RUN' for that option", 17, false, "lime", "white")
  2854.         printC("Yellow = On/True & Red = Off/False", 18, false, "lime", "white")
  2855.  
  2856.         local count = 3
  2857.         for k1, v1 in ipairs(tConfigMISC[1]) do
  2858.             printA(k1..": "..v1, 2, count, false, texttc, textbc)
  2859.             printA("RUN", 48, count, false, "red", "pink")
  2860.             drawBox(45, 2, count+1, 1, " ", optiontc, optionbc)
  2861.             count = count + 2
  2862.         end
  2863.         count = 3
  2864.         for _, v in ipairs(tConfigMISC[2]) do
  2865.             if v then
  2866.                 drawBox(45, 2, count, 1, " ", "yellow", "yellow")
  2867.             else
  2868.                 drawBox(45, 2, count, 1, " ", "red", "red")
  2869.             end
  2870.             count = count + 2
  2871.         end
  2872.  
  2873.         while true do
  2874.             local args = { os.pullEvent() }
  2875.             if args[1] == "timer" then
  2876.                 drawTaskbar()
  2877.             elseif args[1] == "mouse_click" then
  2878.                 if (args[3] >= 1 and args[3] <= 3) and (args[4] == 19) then
  2879.                     deskMenu("go")
  2880.                     local args1 = { os.pullEvent("mouse_click") }
  2881.                     if args[2] == 1 then
  2882.                         if (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 14) then
  2883.                             addons("view")
  2884.                             break
  2885.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 15) then
  2886.                             cpanel()
  2887.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 16) then
  2888.                             filebrowser()
  2889.                             table.insert(recentTasks, "File Browser")
  2890.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 17) then
  2891.                             deskMenu("games")
  2892.                             local args2 = { os.pullEvent("mouse_click") }
  2893.                             if args2[2] == 1 then
  2894.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  2895.                                     table.insert(recentTasks, "Lazers")
  2896.                                     game_lazers()
  2897.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  2898.                                     table.insert(recentTasks, "Stacker")
  2899.                                     game_stacker()
  2900.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  2901.                                     table.insert(recentTasks, "Project Alpha")
  2902.                                     game_alpha()
  2903.                                 else
  2904.                                     deskMenu("clear", "cpanelmisc")
  2905.                                 end
  2906.                             end
  2907.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 18) then
  2908.                             deskMenu("programs")
  2909.                             local args2 = { os.pullEvent("mouse_click") }
  2910.                             if args2[2] == 1 then
  2911.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 12) then
  2912.                                     table.insert(recentTasks, "Blaze Email Client")
  2913.                                     blaze_main()
  2914.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 13) then
  2915.                                     table.insert(recentTasks, "L2P Live Email Client")
  2916.                                     liveemail()
  2917.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 14) then
  2918.                                     table.insert(recentTasks, "SHA256 Test")
  2919.                                     sha256test()
  2920.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  2921.                                     table.insert(recentTasks, "Trasmit")
  2922.                                     transmit("display")
  2923.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  2924.                                     table.insert(recentTasks, "Ink")
  2925.                                     ink()
  2926.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  2927.                                     table.insert(recentTasks, "Sketch")
  2928.                                     sketch()
  2929.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 18) then
  2930.                                     table.insert(recentTasks, "LuaIDE")
  2931.                                     luaide()
  2932.                                 else
  2933.                                     deskMenu("clear", "cpanelmisc")
  2934.                                 end
  2935.                             end
  2936.                         else
  2937.                             deskMenu("clear", "cpanelmisc")
  2938.                         end
  2939.                     end
  2940.                 elseif (args[3] >= 2 and args[3] <= 5) and (args[4] == 1) then
  2941.                     -- OS
  2942.                     cpanel("OS")
  2943.                     break
  2944.                 elseif (args[3] >= 7 and args[3] <= 12) and (args[4] == 1) then
  2945.                     -- User
  2946.                     cpanel("USER")
  2947.                     break
  2948.                 elseif (args[3] >= 14 and args[3] <= 21) and (args[4] == 1) then
  2949.                     -- Rednet
  2950.                     cpanel("REDNET")
  2951.                     break
  2952.                 elseif (args[3] >= 23 and args[3] <= 28) and (args[4] == 1) then
  2953.                     -- Misc
  2954.                     cpanel("MISC")
  2955.                     break
  2956.                 elseif (args[3] >= 45 and args[3] <= 50) and (args[4] == 1) then
  2957.                     home()
  2958.                 elseif args[3] >= 48 and args[3] <= 50 then
  2959.                 -- Logic For Options
  2960.                     if args[4] == 3 then
  2961.                         if #tConfigMISC[1] >= 1 then
  2962.                             -- Option 1
  2963.                             if tConfigMISC[2][1] == true then
  2964.                                 tConfigMISC[2][1] = false
  2965.                             else
  2966.                                 tConfigMISC[2][1] = true
  2967.                             end
  2968.                             saveConfig(tConfigMISC, sPath.."/"..tFiles[4])
  2969.                             cpanel("MISC")
  2970.                         end
  2971.                     elseif args[4] == 5 then
  2972.                         -- Option 2
  2973.                         if #tConfigMISC[1] >= 2 then
  2974.                             if tConfigMISC[2][2] == true then
  2975.                                 tConfigMISC[2][2] = false
  2976.                             else
  2977.                                 tConfigMISC[2][2] = true
  2978.                             end
  2979.                             saveConfig(tConfigMISC, sPath.."/"..tFiles[4])
  2980.                             cpanel("MISC")
  2981.                         end
  2982.                     elseif args[4] == 7 then
  2983.                         -- Option 3
  2984.                         if #tConfigMISC[1] >= 3 then
  2985.                             if tConfigMISC[2][3] == true then
  2986.                                 tConfigMISC[2][3] = false
  2987.                             else
  2988.                                 tConfigMISC[2][3] = true
  2989.                             end
  2990.                             saveConfig(tConfigMISC, sPath.."/"..tFiles[4])
  2991.                             cpanel("MISC")
  2992.                         end
  2993.                     elseif args[4] == 9 then
  2994.                         -- Option 4
  2995.                         if #tConfigMISC[1] >= 4 then
  2996.                             if tConfigMISC[2][4] == true then
  2997.                                 tConfigMISC[2][4] = false
  2998.                             else
  2999.                                 tConfigMISC[2][4] = true
  3000.                             end
  3001.                             saveConfig(tConfigMISC, sPath.."/"..tFiles[4])
  3002.                             cpanel("MISC")
  3003.                         end
  3004.                     elseif args[4] == 11 then
  3005.                         -- Option 5
  3006.                         if #tConfigMISC[1] >= 5 then
  3007.                             if tConfigMISC[2][5] == true then
  3008.                                 tConfigMISC[2][5] = false
  3009.                             else
  3010.                                 tConfigMISC[2][5] = true
  3011.                             end
  3012.                             saveConfig(tConfigMISC, sPath.."/"..tFiles[4])
  3013.                             cpanel("MISC")
  3014.                         end
  3015.                     elseif args[4] == 13 then
  3016.                         -- Option 6
  3017.                         if #tConfigMISC[1] >= 6 then
  3018.                             if tConfigMISC[2][6] == true then
  3019.                                 tConfigMISC[2][6] = false
  3020.                             else
  3021.                                 tConfigMISC[2][6] = true
  3022.                             end
  3023.                             saveConfig(tConfigMISC, sPath.."/"..tFiles[4])
  3024.                             cpanel("MISC")
  3025.                         end
  3026.                     elseif args[4] == 15 then
  3027.                         -- Option 7
  3028.                         if #tConfigMISC[1] >= 7 then
  3029.                             if tConfigMISC[2][7] == true then
  3030.                                 tConfigMISC[2][7] = false
  3031.                             else
  3032.                                 tConfigMISC[2][7] = true
  3033.                             end
  3034.                             saveConfig(tConfigMISC, sPath.."/"..tFiles[4])
  3035.                             cpanel("MISC")
  3036.                         end
  3037.                     end
  3038.                 end
  3039.             end
  3040.         end
  3041.     else
  3042.         local menutc = "blue"
  3043.         local menubc = "lightGrey"
  3044.         local menubc2 = "grey"
  3045.         local texttc = "black"
  3046.         local textbc = "white"
  3047.         local optiontc = "white"
  3048.         local optionbc = "cyan"
  3049.         local menubc3 = "blue"
  3050.  
  3051.         cs()
  3052.         colourScreen()
  3053.         drawTaskbar(false)
  3054.         drawBox(1, 51, 1, 1, " ", menutc, menubc2)
  3055.         printA(" HOME ", 45, 1, false, menutc, menubc)
  3056.         printA(" OS ", 2, 1, false, menutc, menubc)
  3057.         printA(" USER ", 7, 1, false, menutc, menubc)
  3058.         printA(" REDNET ", 14, 1, false, menutc, menubc)
  3059.         printA(" MISC ", 23, 1, false, menutc, menubc)
  3060.         setCol(texttc, textbc)
  3061.  
  3062.         printC("Please select a category", 4, false, texttc, textbc)
  3063.         printC("to view the available options.", 5, false, texttc, textbc)
  3064.         printA("Press 'RUN' next to each option to toggle it. Each", 1, 12, false, "blue", textbc)
  3065.         printA("box next to run will display either yellow or red,", 1, 13, false, "blue", textbc)
  3066.         printA("this defines the current state of that option, for", 1, 14, false, "blue", textbc)
  3067.         printA("example: a yellow box indicates the option is true", 1, 15, false, "blue", textbc)
  3068.         printA("or on, as for the red box means off or false.", 1, 16, false, "blue", textbc)
  3069.         printA("All options are in beta and may or may not work!", 2, 18, false, "lime", textbc)
  3070.         term.setCursorPos(1,2)
  3071.  
  3072.         while true do
  3073.             local args = { os.pullEvent() }
  3074.             if args[1] == "timer" then
  3075.                 drawTaskbar()
  3076.             elseif args[1] == "mouse_click" then
  3077.                 if (args[3] >= 1 and args[3] <= 3) and (args[4] == 19) then
  3078.                     deskMenu("go")
  3079.                     local args1 = { os.pullEvent("mouse_click") }
  3080.                     if args[2] == 1 then
  3081.                         if (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 14) then
  3082.                             addons("view")
  3083.                             break
  3084.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 15) then
  3085.                             cpanel()
  3086.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 16) then
  3087.                             filebrowser()
  3088.                             table.insert(recentTasks, "File Browser")
  3089.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 17) then
  3090.                             deskMenu("games")
  3091.                             local args2 = { os.pullEvent("mouse_click") }
  3092.                             if args2[2] == 1 then
  3093.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  3094.                                     table.insert(recentTasks, "Lazers")
  3095.                                     game_lazers()
  3096.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  3097.                                     table.insert(recentTasks, "Stacker")
  3098.                                     game_stacker()
  3099.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  3100.                                     table.insert(recentTasks, "Project Alpha")
  3101.                                     game_alpha()
  3102.                                 else
  3103.                                     deskMenu("clear", "cpanel")
  3104.                                 end
  3105.                             end
  3106.                         elseif (args1[3] >= 1 and args1[3] <= 11) and (args1[4] == 18) then
  3107.                             deskMenu("programs")
  3108.                             local args2 = { os.pullEvent("mouse_click") }
  3109.                             if args2[2] == 1 then
  3110.                                 if (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 12) then
  3111.                                     table.insert(recentTasks, "Blaze Email Client")
  3112.                                     blaze_main()
  3113.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 13) then
  3114.                                     table.insert(recentTasks, "L2P Live Email Client")
  3115.                                     liveemail()
  3116.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 14) then
  3117.                                     table.insert(recentTasks, "SHA256 Test")
  3118.                                     sha256test()
  3119.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 15) then
  3120.                                     table.insert(recentTasks, "Trasmit")
  3121.                                     transmit("display")
  3122.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 16) then
  3123.                                     table.insert(recentTasks, "Ink")
  3124.                                     ink()
  3125.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 17) then
  3126.                                     table.insert(recentTasks, "Sketch")
  3127.                                     sketch()
  3128.                                 elseif (args2[3] >= 12 and args2[3] <= 23) and (args2[4] == 18) then
  3129.                                     table.insert(recentTasks, "LuaIDE")
  3130.                                     luaide()
  3131.                                 else
  3132.                                     deskMenu("clear", "cpanel")
  3133.                                 end
  3134.                             end
  3135.                         else
  3136.                             deskMenu("clear", "cpanel")
  3137.                         end
  3138.                     end
  3139.                 elseif (args[3] >= 2 and args[3] <= 5) and (args[4] == 1) then
  3140.                     -- OS
  3141.                     cpanel("OS")
  3142.                     break
  3143.                 elseif (args[3] >= 7 and args[3] <= 12) and (args[4] == 1) then
  3144.                     -- User
  3145.                     cpanel("USER")
  3146.                     break
  3147.                 elseif (args[3] >= 14 and args[3] <= 21) and (args[4] == 1) then
  3148.                     -- Rednet
  3149.                     cpanel("REDNET")
  3150.                     break
  3151.                 elseif (args[3] >= 23 and args[3] <= 28) and (args[4] == 1) then
  3152.                     -- Misc
  3153.                     cpanel("MISC")
  3154.                     break
  3155.                 elseif (args[3] >= 45 and args[3] <= 50) and (args[4] == 1) then
  3156.                     home()
  3157.                 end
  3158.             end
  3159.         end
  3160.     end
  3161. end
  3162.  
  3163. function test256()
  3164.     -- Test the SHA256 hashing algorithm
  3165. end
  3166.  
  3167. function vdeShell()
  3168.     -- Runs VDE's Own Shell
  3169.     tHelpTopics = {"move", "copy", "delete", "help", "vde", "time", "addUser", "shell", "dir", "mkdir", "redraw", "addons", "apps", "fsCore", "fsLibs", "users", "themes", "fsConfig", "loginHTTP", "loginLOCAL", "lua",}
  3170.     -- Help Topics Content
  3171.     sHelp = {
  3172.         move = "This allows you to move files from one place to another, the usage is as follows: #move <old_path> <new_path>.",
  3173.         copy = "This will copy a file by specifying two paths, the old file path and the copied file path, usage: #copy <old_path> <copied_path>.",
  3174.         delete = "This will delete a file, make sure to use the file path, usage: #delete <file_path>.",
  3175.         help = "This is the help menu, to see available help topics type: #help, to see a certain help topic use the following: #help <topic>.",
  3176.         vde = "This will return you to the home desktop of VDE.",
  3177.         time = "This will print the current Minecraft time.",
  3178.         addUser = "This will add a new user to the database, usage: #addUser <username> <password>.",
  3179.         shell = "This will run a craftos shell command, usage: #shell <command>.",
  3180.         dir = "This will print the contents of a directory, usage: #dir <directory_path>.",
  3181.         mkdir = "This will create a new directory, usage: #mkdir <new_directory_path>.",
  3182.         redraw = "This will redraw the shell as it may end up running into a problem while executing commands.",
  3183.         addons = "These are small programs that are loaded upon system boot, which in turn will allow users to add extras to the environment, making it more productive.",
  3184.         apps = "Apps are programs that are installed to the system. So if you take the LuaIDE app, this is a program made by someone but has been edited the slightest to allow it to run completely in a function of the environment.",
  3185.         fsCore = "FileSystem - Core: This is simple just a folder in the root directory, this will be installed on OS intilisation, it is accessed most of the time, for configuration files, or for caching for the environment.",
  3186.         fsLibs = "FileSystem - Libs: This is the libraries folder, this will contain API's or other programs that will give the console more functionality, so the OS could run the program with an argument and it will load the desired library allowing the OS to use more API's and functions to control more things, at the moment, the OS uses libs to connect to SGCraft and/or LanteaCraft.",
  3187.         users = "Users: A user is just a security method to allow users to login to all the applications on the environment. For example included with the OS is Blaze Email Client, this will auto-log you in when the app is run because the User Database is the same database for all of my HTTP based programs!",
  3188.         themes = "These are themes that can be run on the OS, that allows you to retexture the whole OS or give it a completely new UI. The OS is loadable via API, so you can run the functions contained in it.",
  3189.         fsConfig = "These are the config files, these of course are accessed and edited by VDE a lot so if you change one, make sure to reboot the OS, straight after, otherwise it may overwrite the file in the next process.",
  3190.         loginHTTP = "This is a login based on the User Database on my web server, this is all done via a small internal API that will connect.",
  3191.         loginLOCAL = "This is a login based on a local table, allowing you to still have multiple local users, this won't use the HTTP based login, but is good to have as a backup in-case you don't have internet access.",
  3192.         lua = "This is a prompt lua execution script, allowing you to input code and it will be executed on the fly, it has two usages and expects one argument, the following arguments are: 'prompt' = Run Lua on the fly, or 'ide' = to start LuaIDE. Usage: lua <argument1>.",
  3193.     }
  3194.  
  3195.     cs()
  3196.     colourScreen()
  3197.     drawBox(1, 51, 1, 1, " ", "blue", "grey")
  3198.     printC(" VDE Shell -> Version 1.1 ", 1, false, "blue", "lightGrey")
  3199.     printC("Use the prefix: # for commands", 2, false, "lime", "white")
  3200.     term.setCursorPos(1,3)
  3201.     setCol("black", "white")
  3202.     while true do
  3203.         write("> ")
  3204.         local cmd = tostring(read())
  3205.         tempX, tempY = term.getCursorPos()
  3206.         tCmd = {}
  3207.         for id in cmd:gmatch("%S+") do
  3208.             table.insert(tCmd, id)
  3209.         end
  3210.         if tCmd[1] == "#copy" then
  3211.             -- Copy file
  3212.             if #tCmd == 3 then
  3213.                 fs.copy(tCmds[2], tCmds[3])
  3214.             else
  3215.                 print("> Wrong Usage - Use '#help' for more info!")
  3216.             end
  3217.         elseif tCmd[1] == "#move" then
  3218.             -- Move file
  3219.             if #tCmd[1] == 3 then
  3220.                 fs.move(tCmds[2], tCmds[3])
  3221.             else
  3222.                 print("> Wrong Usage - Use '#help' for more info!")
  3223.             end
  3224.         elseif tCmd[1] == "#delete" then
  3225.             if #tCmd == 2 then
  3226.                 fs.delete(tCmds[2])
  3227.             else
  3228.                 print("> Wrong Usage - Use '#help' for more info!")
  3229.             end
  3230.         elseif tCmd[1] == "#help" then
  3231.             -- Display help
  3232.             if #tCmd == 1 then
  3233.                 print("> Available Help Topics:")
  3234.                 tData1 = {}
  3235.                 for _,v in ipairs(tHelpTopics) do
  3236.                     table.insert(tData1, v)
  3237.                 end
  3238.                 setCol("red", "white")
  3239.                 print(table.concat(tData1, ", "))
  3240.                 setCol("black", "white")
  3241.             elseif #tCmd >= 2 then
  3242.                 for _, v in ipairs(wordwrap(sHelp[tCmd[2]], 51)) do
  3243.                     print(v)
  3244.                 end
  3245.             end
  3246.  
  3247.         elseif tCmd[1] == "#vde" then
  3248.             home()
  3249.             break
  3250.         elseif tCmd[1] == "#time" then
  3251.             print("Current Time: "..textutils.formatTime(os.time()))
  3252.             print("Current Day: "..tostring(os.day()))
  3253.         elseif tCmd[1] == "#shell" then
  3254.             -- Run craftos shell command
  3255.             if #tCmd >= 2 then
  3256.                 newCmd = string.gsub(cmd, "#shell", "fg")
  3257.                 shell.run(newCmd)
  3258.                 vdeShell()
  3259.             else
  3260.                 print("> Wrong Usage: Use '#help' for more info!")
  3261.             end
  3262.         elseif tCmd[1] == "#addUser" then
  3263.             -- Show controls for users
  3264.             if tCmd >= 3 then
  3265.                 local status = DBControl("insert", args[2], args[3])
  3266.                 if status then
  3267.                     print("> Successfully added user")
  3268.                 else
  3269.                     print("> Error occured while adding user")
  3270.                 end
  3271.             else
  3272.                 print("> Wrong Usage - Use '#help' for more info!")
  3273.             end
  3274.         elseif tCmd[1] == "#dir" then
  3275.             if #tCmd >= 2 then
  3276.                 local tFiles = fs.list(tCmd[2])
  3277.                 for _,v in ipairs(tFiles) do
  3278.                     if fs.isDir(v) then
  3279.                         setCol("green", "white")
  3280.                         print(v)
  3281.                     else
  3282.                         setCol("blue", "white")
  3283.                         print(v)
  3284.                     end
  3285.                     setCol("black", "white")
  3286.                 end
  3287.             else
  3288.                 print("> Wrong Usage - Use '#help' for more info!")
  3289.             end
  3290.         elseif tCmd[1] == "#mkdir" then
  3291.             if #tCmd >= 2 then
  3292.                 fs.makeDir(tCmd[2])
  3293.             else
  3294.                 print("> Wrong Usage - Use '#help' for more info!")
  3295.             end
  3296.         elseif tCmd[1] == "#redraw" then
  3297.             vdeShell()
  3298.         elseif tCmd[1] == "#lua" then
  3299.             if #tCmd >= 2 then
  3300.                 if tCmd[2] == "prompt" then
  3301.                     VDELua("prompt")
  3302.                     break
  3303.                 elseif tCmd[2] == "ide" then
  3304.                     luaide()
  3305.                     break
  3306.                 end
  3307.             else
  3308.                 print("> Wrong Usage - Use '#help' for more info!")
  3309.             end
  3310.         end
  3311.     end
  3312. end
  3313.  
  3314. function launcher()
  3315.     drawBox(6, 39, 7, 4, " ", "blue", "grey")
  3316.     drawBox(6, 39, 8, 2, " ", "blue", "grey")
  3317.     drawBox(8, 35, 9, 1, " ", "white", "white")
  3318.     printC(" Specify Program's Full Path: ", 7, false, "red", "lightGrey")
  3319.     setCol("black", "white")
  3320.     term.setCursorPos(8,9)
  3321.     write("> ")
  3322.     local cmd = tostring(read())
  3323.     shell.run("fg "..cmd)
  3324.     sleep(1)
  3325.     home()
  3326. end
  3327.  
  3328. function addons(cmd, name)
  3329.     addonsPath = "/core/addons"
  3330.     addonsList = {"bluetooth", "calculator", "local_login", "external_login", "cloud_storage",}
  3331.  
  3332.     if cmd == "view" then
  3333.         local menutc = "blue"
  3334.         local menubc = "grey"
  3335.         local menuex = "lightGrey"
  3336.         local backbc = "white"
  3337.         local backtc = "black"
  3338.         cs()
  3339.         drawTaskbar(false)
  3340.         drawBox(1, 51, 1, 1, " ", menutc, menubc)
  3341.         drawBox(2, 5, 1, 1, " ", menutc, menuex)
  3342.         printA("ADD", 3, 1, false, menutc, menuex)
  3343.         drawBox(8, 5, 1, 1, " ", menutc, menuex)
  3344.         printA("RUN", 9, 1, false, menutc, menuex)
  3345.         drawBox(14, 5, 1, 1, " ", menutc, menuex)
  3346.         printA("DEL", 15, 1, false, menutc, menuex)
  3347.         drawBox(20, 6, 1, 1, " ", menutc, menuex)
  3348.         printA("HOME", 21, 1, false, menutc, menuex)
  3349.  
  3350.         -- Draw Table
  3351.         drawBox(1, 51, 2, 17, " ", menutc, "cyan")
  3352.         drawBox(26, 1, 2, 17, " ", menutc, "cyan")
  3353.         printA("ID: NAME", 2, 2, false, "lime", "cyan")
  3354.         printA("ID: NAME", 27, 2, false, "lime", "cyan")
  3355.         printC("Only First 30 Displayed", 18, false, "lime", "cyan")
  3356.  
  3357.         -- Draw Background
  3358.         drawBox(2, 24, 3, 2, " ", backtc, backbc)
  3359.         drawBox(2, 24, 5, 2, " ", backtc, backbc)
  3360.         drawBox(2, 24, 7, 2, " ", backtc, backbc)
  3361.         drawBox(2, 24, 9, 2, " ", backtc, backbc)
  3362.         drawBox(2, 24, 11, 2, " ", backtc, backbc)
  3363.         drawBox(2, 24, 13, 2, " ", backtc, backbc)
  3364.         drawBox(2, 24, 15, 2, " ", backtc, backbc)
  3365.         drawBox(2, 24, 17, 1, " ", backtc, backbc)
  3366.         drawBox(27, 24, 3, 2, " ", backtc, backbc)
  3367.         drawBox(27, 24, 5, 2, " ", backtc, backbc)
  3368.         drawBox(27, 24, 7, 2, " ", backtc, backbc)
  3369.         drawBox(27, 24, 9, 2, " ", backtc, backbc)
  3370.         drawBox(27, 24, 11, 2, " ", backtc, backbc)
  3371.         drawBox(27, 24, 13, 2, " ", backtc, backbc)
  3372.         drawBox(27, 24, 15, 2, " ", backtc, backbc)
  3373.         drawBox(27, 24, 17, 1, " ", backtc, backbc)
  3374.         setCol(backtc, backbc)
  3375.  
  3376.         -- Addons Data List
  3377.         local addonsList = fs.list(addonsPath)
  3378.  
  3379.         -- Draw Addon View
  3380.         intX = 2
  3381.         intY = 3
  3382.  
  3383.         for k, v in ipairs(addonsList) do
  3384.             term.setCursorPos(intX, intY)
  3385.             print(k..": "..v)
  3386.             intY = intY + 1
  3387.             if intY == 18 then
  3388.                 intX = 27
  3389.                 intY = 3
  3390.                 if intX == 27 and intY == 18 then
  3391.                     break
  3392.                 end
  3393.             end
  3394.         end
  3395.  
  3396.         while true do
  3397.             local args = { os.pullEvent() }
  3398.             if args[1] == "timer" then
  3399.                 drawTaskbar(false)
  3400.             elseif args[1] == "mouse_click" then
  3401.                 if (args[3] >= 2 and args[3] <= 6) and (args[4] == 1) then
  3402.                     addons("get")
  3403.                     break
  3404.                 elseif (args[3] >= 8 and args[3] <= 12) and (args[4] == 1) then
  3405.                     addons("load")
  3406.                     break
  3407.                 elseif (args[3] >= 14 and args[3] <= 18) and (args[4] == 1) then
  3408.                     addons("delete")
  3409.                     break
  3410.                 elseif (args[3] >= 20 and args[3] <= 26) and (args[4] == 1) then
  3411.                     home()
  3412.                     break
  3413.                 end
  3414.             end
  3415.         end
  3416.     elseif cmd == "load" then
  3417.         local menutc = "blue"
  3418.         local menubc = "grey"
  3419.         local menuex = "lightGrey"
  3420.         local backbc = "white"
  3421.         local backtc = "black"
  3422.         cs()
  3423.         drawTaskbar(false)
  3424.         drawBox(1, 51, 1, 18, " ", "lime", "cyan")
  3425.         printC(">> Run Addon <<", 1, false, "lime", "cyan")
  3426.         drawBox(1, 51, 2, 1, " ", backtc, backbc)
  3427.         drawBox(1, 51, 3, 2, " ", backtc, backbc)
  3428.         drawBox(1, 51, 5, 2, " ", backtc, backbc)
  3429.         drawBox(1, 51, 7, 2, " ", backtc, backbc)
  3430.         drawBox(1, 51, 9, 2, " ", backtc, backbc)
  3431.         drawBox(1, 51, 11, 2, " ", backtc, backbc)
  3432.         drawBox(1, 51, 13, 2, " ", backtc, backbc)
  3433.         drawBox(1, 51, 15, 2, " ", backtc, backbc)
  3434.         drawBox(1, 51, 17, 2, " ", backtc, backbc)
  3435.         term.setCursorPos(1,3)
  3436.         setCol(backtc, backbc)
  3437.         print("> File name of addon to run:")
  3438.         write(": ")
  3439.         local fileName = tostring(read())
  3440.         print(" ")
  3441.         if fs.exists(addonsPath.."/"..fileName) then
  3442.             print("> File exists, attempting to run...")
  3443.             shell.run("bg "..addonsPath.."/"..fileName)
  3444.         else
  3445.             print("> File doesn't exists, return to addons...")
  3446.             sleep(1.5)
  3447.             addons("view")
  3448.         end
  3449.     elseif cmd == "get" then
  3450.         local menutc = "blue"
  3451.         local menubc = "grey"
  3452.         local menuex = "lightGrey"
  3453.         local backbc = "white"
  3454.         local backtc = "black"
  3455.         cs()
  3456.         drawTaskbar(false)
  3457.         drawBox(1, 51, 1, 18, " ", "lime", "cyan")
  3458.         printC(">> Download Addon <<", 1, false, "lime", "cyan")
  3459.         drawBox(1, 51, 2, 1, " ", backtc, backbc)
  3460.         drawBox(1, 51, 3, 2, " ", backtc, backbc)
  3461.         drawBox(1, 51, 5, 2, " ", backtc, backbc)
  3462.         drawBox(1, 51, 7, 2, " ", backtc, backbc)
  3463.         drawBox(1, 51, 9, 2, " ", backtc, backbc)
  3464.         drawBox(1, 51, 11, 2, " ", backtc, backbc)
  3465.         drawBox(1, 51, 13, 2, " ", backtc, backbc)
  3466.         drawBox(1, 51, 15, 2, " ", backtc, backbc)
  3467.         drawBox(1, 51, 17, 2, " ", backtc, backbc)
  3468.         term.setCursorPos(1,3)
  3469.         setCol(backtc, backbc)
  3470.         print("> Please enter pastebin code:")
  3471.         write(": ")
  3472.         local pastebinLink = tostring(read())
  3473.         print("> Please enter addon name:")
  3474.         write(": ")
  3475.         local fileName = tostring(read())
  3476.         print(" ")
  3477.         print("> Attempting to download file...")
  3478.         shell.run("pastebin get "..pastebinLink.." "..addonsPath.."/"..fileName)
  3479.         print(" ")
  3480.         print("> Addon saved as: "..fileName)
  3481.         sleep(1.5)
  3482.         home()
  3483.     elseif cmd == "delete" then
  3484.         local menutc = "blue"
  3485.         local menubc = "grey"
  3486.         local menuex = "lightGrey"
  3487.         local backbc = "white"
  3488.         local backtc = "black"
  3489.         cs()
  3490.         drawTaskbar(false)
  3491.         drawBox(1, 51, 1, 18, " ", "lime", "cyan")
  3492.         printC(">> Delete Addon <<", 1, false, "lime", "cyan")
  3493.         drawBox(1, 51, 2, 1, " ", backtc, backbc)
  3494.         drawBox(1, 51, 3, 2, " ", backtc, backbc)
  3495.         drawBox(1, 51, 5, 2, " ", backtc, backbc)
  3496.         drawBox(1, 51, 7, 2, " ", backtc, backbc)
  3497.         drawBox(1, 51, 9, 2, " ", backtc, backbc)
  3498.         drawBox(1, 51, 11, 2, " ", backtc, backbc)
  3499.         drawBox(1, 51, 13, 2, " ", backtc, backbc)
  3500.         drawBox(1, 51, 15, 2, " ", backtc, backbc)
  3501.         drawBox(1, 51, 17, 2, " ", backtc, backbc)
  3502.         term.setCursorPos(1,3)
  3503.         setCol(backtc, backbc)
  3504.         print("> File name of addon to delete:")
  3505.         write(": ")
  3506.         local fileName = tostring(read())
  3507.         print(" ")
  3508.         if fs.exists(addonsPath.."/"..fileName) then
  3509.             print("> File exists, attempting to delete...")
  3510.             fs.delete(addonsPath.."/"..fileName)
  3511.             sleep(1)
  3512.             addons("view")
  3513.         else
  3514.             print("> File doesn't exists, return to addons...")
  3515.             sleep(1.5)
  3516.             addons("view")
  3517.         end
  3518.     elseif cmd == "autorun" then
  3519.         -- Runs specific addons when loaded
  3520.         if name then
  3521.             shell.run("bg "..addonsPath.."/"..name)
  3522.         end
  3523.     end
  3524. end
  3525.  
  3526. function URLDownload()
  3527.     local poptc = "lime"
  3528.     local popbc = "cyan"
  3529.     local input1tc = "black"
  3530.     local input1bc = "white"
  3531.     drawBox(1, 51, 7, 4, " ", poptc, popbc)
  3532.     drawBox(1, 51, 8, 2, " ", poptc, popbc)
  3533.     drawBox(2, 49, 9, 1, " ", input1tc, input1bc)
  3534.     printC("URL Downloader - File Path:", 7, false, poptc, popbc)
  3535.     setCol(input1tc, input1bc)
  3536.     term.setCursorPos(2,9)
  3537.     write(": ")
  3538.     local input1 = tostring(read())
  3539.     printC("URL Downloader - File URL/Pastebin Code:", 7, false, poptc, popbc)
  3540.     drawBox(2, 49, 9, 1, " ", input1tc, input1bc)
  3541.     setCol(input1tc, input1bc)
  3542.     term.setCursorPos(2,9)
  3543.     write(": ")
  3544.     local input2 = tostring(read())
  3545.     if string.len(input2) == 8 then
  3546.         -- Pastebin Download
  3547.         cs()
  3548.         colourScreen()
  3549.         term.setCursorPos(1,1)
  3550.         setCol(input1tc, input1bc)
  3551.         shell.run("pastebin get "..input2.." "..input1)
  3552.         sleep(1)
  3553.         home()
  3554.     else
  3555.         -- URL Downloader
  3556.         local req = http.post(input2)
  3557.         if req then
  3558.             local tempFile = fs.open(input1, "w")
  3559.             tempFile.write(req.readAll())
  3560.             tempFile.close()
  3561.             drawPopup("Download Completed!")
  3562.             sleep(1)
  3563.             home()
  3564.         else
  3565.             drawPopup("File was empty...")
  3566.             sleep(1.5)
  3567.             home()
  3568.         end
  3569.     end
  3570. end
  3571.  
  3572. function transmit(command)
  3573.     tc = "white"
  3574.     bc = "black"
  3575.     bc2 = "cyan"
  3576.     if command == "send" then
  3577.         -- Start File Sending
  3578.         drawBox(30, 22, 2, 17, " ", tc, bc2)
  3579.         drawBox(31, 20, 3, 2, " ", tc, bc)
  3580.         drawBox(31, 20, 5, 2, " ", tc, bc)
  3581.         drawBox(31, 20, 7, 2, " ", tc, bc)
  3582.         drawBox(31, 20, 9, 2, " ", tc, bc)
  3583.         drawBox(31, 20, 11, 2, " ", tc, bc)
  3584.         drawBox(31, 20, 13, 2, " ", tc, bc)
  3585.         drawBox(31, 20, 15, 2, " ", tc, bc)
  3586.         drawBox(31, 20, 17, 1, " ", tc, bc)
  3587.         printA("Transmit: Send", 34, 2, false, tc, bc2)
  3588.         objwin1 = window.create(term.current(), 31, 3, 20, 15, true)
  3589.         objwin1.setTextColour(colours.lime)
  3590.         objwin1.setCursorPos(1,1)
  3591.         objwin1.write("File Path:")
  3592.         objwin1.setCursorPos(1,2)
  3593.         objwin1.setTextColour(colours.white)
  3594.         write(": ")
  3595.         local fPath = tostring(read())
  3596.         objwin1.setCursorPos(1,3)
  3597.         objwin1.setTextColour(colours.lime)
  3598.         if fs.exists(fPath) then
  3599.             objwin1.write("File Selected!")
  3600.             objwin1.setCursorPos(1,4)
  3601.             objwin1.write("Receiving PC ID:")
  3602.             objwin1.setCursorPos(1,5)
  3603.             objwin1.setTextColour(colours.white)
  3604.             write(": ")
  3605.             local nCompID = tostring(read())
  3606.             objwin1.setCursorPos(1,6)
  3607.             objwin1.setTextColour(colours.lime)
  3608.             objwin1.write("Attempting to send:")
  3609.             objwin1.setCursorPos(1,7)
  3610.             objwin1.setTextColour(colours.lime)
  3611.             objwin1.write(fPath)
  3612.             objwin1.setCursorPos(1,8)
  3613.             objwin1.setTextColour(colours.lime)
  3614.             objwin1.write("to: "..nCompID)
  3615.             local tempfile = fs.open(fPath, "r")
  3616.             tempfile = textutils.unserialize(tempfile.readAll())
  3617.             if rednet.isOpen(modemSide) then
  3618.                 rednet.send(nCompID, tempfile)
  3619.                 objwin1.setCursorPos(1,9)
  3620.                 objwin1.setTextColour(colours.lime)
  3621.                 objwin1.write("Sent!")
  3622.                 sleep(1.5)
  3623.                 home()
  3624.             else
  3625.                 objwin1.setCursorPos(1,9)
  3626.                 objwin1.setTextColour(colours.lime)
  3627.                 objwin1.write("Rednet not open")
  3628.                 sleep(1.5)
  3629.                 home()
  3630.             end
  3631.         else
  3632.             objwin1.write("File Not Found!")
  3633.             objwin1.setCursorPos(1,4)
  3634.             objwin1.write("Restarting Home!")
  3635.             sleep(1)
  3636.             home(1.5)
  3637.         end
  3638.     elseif command == "receive" then
  3639.         -- Start File Receiving
  3640.         drawBox(30, 22, 2, 17, " ", tc, bc2)
  3641.         drawBox(31, 20, 3, 2, " ", tc, bc)
  3642.         drawBox(31, 20, 5, 2, " ", tc, bc)
  3643.         drawBox(31, 20, 7, 2, " ", tc, bc)
  3644.         drawBox(31, 20, 9, 2, " ", tc, bc)
  3645.         drawBox(31, 20, 11, 2, " ", tc, bc)
  3646.         drawBox(31, 20, 13, 2, " ", tc, bc)
  3647.         drawBox(31, 20, 15, 2, " ", tc, bc)
  3648.         drawBox(31, 20, 17, 1, " ", tc, bc)
  3649.         printA("Transmit: Receive", 32, 2, false, tc, bc2)
  3650.         win1 = window.create(term.current(), 31, 3, 20, 15, true)
  3651.         win1.setTextColour(colours.lime)
  3652.         win1.setCursorPos(1,1)
  3653.         win1.write("File Path:")
  3654.         win1.setCursorPos(1,2)
  3655.         win1.setTextColour(colours.white)
  3656.         write(": ")
  3657.         local sName = tostring(read())
  3658.         win1.setCursorPos(1,3)
  3659.         win1.setTextColour(colours.lime)
  3660.         win1.write("Waiting for file...")
  3661.         win1.setCursorPos(1,4)
  3662.         win1.write("Press 'x' to exit.")
  3663.  
  3664.         -- Run Halt
  3665.         while true do
  3666.             local args = { os.pullEvent() }
  3667.             if args[1] == "char" then
  3668.                 if args[2] == "x" then
  3669.                     home()
  3670.                 end
  3671.             elseif args[1] == "rednet_message" then
  3672.                 win1.setCursorPos(1,5)
  3673.                 win1.write("Received...")
  3674.                 local tempfile = fs.open(sName, "w")
  3675.                 tempfile.write(textutils.unserialize(args[3].readAll()))
  3676.                 tempfile.close()
  3677.                 win1.setCursorPos(1,6)
  3678.                 win1.write("Saved to:")
  3679.                 win1.setCursorPos(1,7)
  3680.                 win1.write(sName)
  3681.                 sleep(1.5)
  3682.                 home()
  3683.             end
  3684.         end
  3685.     end
  3686. end
  3687.  
  3688. function main()
  3689.     if fs.exists("/core/config/install") then
  3690.         VDEControl("run")
  3691.     else
  3692.         VDEControl("install")
  3693.         login()
  3694.     end
  3695. end
  3696.  
  3697. -- Set Globals, Variables and Placeholders
  3698. _BLAZEUSER = nil
  3699. _BLAZEPASS = nil
  3700. _BLAZECMDS = {"login", "getInbox", "register", "delete", "send",}
  3701. _BLAZEURLS = {"http://dannysmc.com/files/php/emailsystem.php",}
  3702.  
  3703. -- Set Defaults
  3704. tc = "black"
  3705. bc = "lightGrey"
  3706. nVer = 1.1
  3707.  
  3708. -- BLAZE API
  3709. function BlazeLogin(username, password)
  3710.   local req = http.post(_BLAZEURLS[1], "command="..textutils.urlEncode(tostring(_BLAZECMDS[1])).."&".."username="..textutils.urlEncode(tostring(username)).."&".."password="..textutils.urlEncode(tostring(password)))
  3711.   return req
  3712. end
  3713.  
  3714. function BlazeInbox(username, password)
  3715.   local req = http.post(_BLAZEURLS[1], "command="..textutils.urlEncode(tostring(_BLAZECMDS[2])).."&".."username="..textutils.urlEncode(tostring(username)).."&".."password="..textutils.urlEncode(tostring(password)))
  3716.   return req
  3717. end
  3718.  
  3719. function BlazeSend(username, password, recipient, subject, message)
  3720.   local req = http.post(_BLAZEURLS[1], "command="..textutils.urlEncode(tostring(_BLAZECMDS[5])).."&".."username="..textutils.urlEncode(tostring(username)).."&".."password="..textutils.urlEncode(tostring(password)).."&".."recipient="..textutils.urlEncode(tostring(recipient)).."&".."subject="..textutils.urlEncode(tostring(subject)).."&".."message="..textutils.urlEncode(tostring(message)))
  3721.   return req
  3722. end
  3723.  
  3724. function BlazeDelete(username, password, msgid)
  3725.   local req = http.post(_BLAZEURLS[1], "command="..textutils.urlEncode(tostring(_BLAZECMDS[4])).."&".."username="..textutils.urlEncode(tostring(username)).."&".."password="..textutils.urlEncode(tostring(password)).."&".."messageid="..textutils.urlEncode(tostring(msgid)))
  3726.   return req
  3727. end
  3728.  
  3729. function BlazeRegister(username, password, email)
  3730.   local req = http.post(_BLAZEURLS[1], "command="..textutils.urlEncode(tostring(_BLAZECMDS[3])).."&".."username="..textutils.urlEncode(tostring(username)).."&".."password="..textutils.urlEncode(tostring(password)).."&".."email="..textutils.urlEncode(tostring(email)))
  3731.   return req
  3732. end
  3733.  
  3734. -- Main Code
  3735. function blaze_main()
  3736.   if term.isColor() then
  3737.     blaze_login()
  3738.   end
  3739. end
  3740.  
  3741. function drawPopup(sText)
  3742.   drawBox(1, 51, 7, 1, " ", "lime", "red")
  3743.   printC(">> "..sText.." <<", 7, false, "lime", "red")
  3744. end
  3745.  
  3746. function addressBook(pageNumber)
  3747.   local texttc = "black"
  3748.   local textbc = "white"
  3749.   local gridtc = "white"
  3750.   local gridbc = "grey"
  3751.   local menutc = "blue"
  3752.   local menubc = "lightGrey"
  3753.   fs.makeDir("blazeCore/")
  3754.   abPath = "blazeCore/addresses"
  3755.   if fs.exists(abPath) then
  3756.     addresses = db.load(abPath)
  3757.   else
  3758.     aTable = {
  3759.       {
  3760.         "Creator",
  3761.       },
  3762.       {
  3763.         "dannysmc95",
  3764.       }
  3765.     }
  3766.     saveConfig(aTable, abPath)
  3767.     addresses = loadConfig(abPath)
  3768.   end
  3769.   cs()
  3770.   colourScreen()
  3771.   drawMenuBar()
  3772.   -- Views all users on the database
  3773.   drawBox(1, 51, 2, 18, " ", "black", "black")
  3774.   drawBox(2, 49, 3, 16, " ", gridtc, gridbc)
  3775.   drawBox(2, 49, 5, 1, " ", gridtc, gridbc)
  3776.   drawBox(26, 1, 3, 16, " ", gridtc, gridbc)
  3777.   drawBox(3, 23, 4, 1, " ", menutc, menubc)
  3778.   drawBox(27, 23, 4, 1, " ", menutc, menubc)
  3779.   printA("Custom Name", 4, 4, false, menutc, menubc)
  3780.   printA("Username Address", 28, 4, false, menutc, menubc)
  3781.   drawBox(4, 5, 18, 1, " ", menutc, menubc)
  3782.   printA("ADD", 5, 18, false, menutc, menubc)
  3783.   drawBox(28, 21, 18, 1, " ", menutc, menubc)
  3784.   printA("Right-Click Deletes", 29, 18, false, menutc, menubc)
  3785.   countY = 6
  3786.  
  3787.   for k, v in ipairs(addresses[1]) do
  3788.     printA(v, 3, countY, false, texttc, textbc)
  3789.     countY = countY + 1
  3790.   end
  3791.  
  3792.   countY = 6
  3793.   for k, v in ipairs(addresses[2]) do
  3794.     printA(v, 27, countY, false, texttc, textbc)
  3795.     countY = countY + 1
  3796.   end
  3797.  
  3798.   while true do
  3799.     local args = { os.pullEvent() }
  3800.     if args[1] == "timer" then
  3801.       drawMenuBar()
  3802.     end
  3803.     if args[1] == "mouse_click" then
  3804.       if (args[3] >= 2 and args[3] <= 6) and (args[4] == 1) then
  3805.         drawDropdown("new")
  3806.       elseif (args[3] >= 2 and args[3] <= 11) and (args[4] == 2) then
  3807.         blaze_send()
  3808.         break
  3809.       elseif (args[3] >= 2 and args[3] <= 11) and (args[4] == 3) then
  3810.         addressBook("view")
  3811.         break
  3812.       elseif (args[3] >= 8 and args[3] <= 14) and (args[4] == 1) then
  3813.         blaze_inbox(1)
  3814.         break
  3815.       elseif (args[3] >= 16 and args[3] <= 25) and (args[4] == 1) then
  3816.         blaze_options()
  3817.         break
  3818.       elseif (args[3] >= 27 and args[3] <= 32) and (args[4] == 1) then
  3819.         blaze_help()
  3820.         break
  3821.       end
  3822.       if args[2] == 1 then
  3823.         -- Do touch buttons here
  3824.         if (args[3] >= 3 and args[3] <= 49) and (args[4] >= 6 and args[4] <= 17) then
  3825.           -- Option 1
  3826.           intPos = args[4] - 5
  3827.           if #addresses[2] == intPos then
  3828.             sendRecipient = addresses[2][intPos]
  3829.             blaze_send()
  3830.             break
  3831.           end
  3832.         elseif (args[3] >= 4 and args[3] <= 9) and (args[4] == 18) then
  3833.           cs()
  3834.           colourScreen()
  3835.           term.setCursorPos(1,1)
  3836.           setCol(texttc, textbc)
  3837.           print("Address Book -> Add User")
  3838.           print(" ")
  3839.           print("> Custom Name: ")
  3840.           write(": ")
  3841.           local customName = tostring(read())
  3842.           print("> Address Name: ")
  3843.           write(": ")
  3844.           local addressName = tostring(read())
  3845.           table.insert(addresses[1], customName)
  3846.           table.insert(addresses[2], addressName)
  3847.           saveConfig(addresses, abPath)
  3848.           addressBook()
  3849.         end
  3850.       elseif args[2] == 2 then
  3851.         if (args[3] >= 4 and args[3] <= 8) and (args[4] >= 6 and args[4] <= 17) then
  3852.          intPos = args[4] - 5
  3853.          if #addresses[2] == intPos then
  3854.             table.remove(addresses[1], intPos)
  3855.             table.remove(addresses[2], intPos)
  3856.             saveConfig(addresses, abPath)
  3857.             addressBook()
  3858.           end
  3859.         end
  3860.       end
  3861.     end
  3862.   end
  3863. end
  3864.  
  3865. function drawMenuBar()
  3866.   menutc = "blue"
  3867.   menubc = "lightGrey"
  3868.   selectedtc = "lime"
  3869.   inboxbc = "white"
  3870.   gridbc = "grey"
  3871.   drawBox(1, 51, 1, 1, " ", tc, gridbc)
  3872.   drawBox(2, 5, 1, 1, " ", menutc, menubc)
  3873.   printA("NEW", 3, 1, false, menutc, menubc)
  3874.   drawBox(8, 7, 1, 1, " ", menutc, menubc)
  3875.   printA("INBOX", 9, 1, false, menutc, menubc)
  3876.   drawBox(16, 10, 1, 1, " ", menutc, menubc)
  3877.   printA("SETTINGS", 17, 1, false, menutc, menubc)
  3878.   drawBox(27, 6, 1, 1, " ", menutc, menubc)
  3879.   printA("HELP", 28, 1, false, menutc, menubc)
  3880.   drawBox(44, 7, 1, 1, " ", menutc, menubc)
  3881.   printA(time(), 45, 1, false, menutc, menubc)
  3882. end
  3883.  
  3884. function blaze_inbox(inboxNumber)
  3885.   refreshCount = 300
  3886.   menutc = "blue"
  3887.   menubc = "lightGrey"
  3888.   selectedtc = "lime"
  3889.   inboxbc = "white"
  3890.   gridbc = "grey"
  3891.   cs()
  3892.   colourScreen()
  3893.   printA("No Message Selected!", 28, 11, false, "black", "white")
  3894.   drawMenuBar()
  3895.   drawBox(8, 7, 1, 1, " ", menutc, menubc)
  3896.   printA("INBOX", 9, 1, false, selectedtc, menubc)
  3897.  
  3898.   -- Attempt to grab the users inbox:
  3899.   local tData = BlazeInbox(username, password)
  3900.   inbox = tData
  3901.   inbox = inbox.readAll()
  3902.   inbox = textutils.unserialize(inbox)
  3903.   local status, err = pcall(function() test123 = #inbox end)
  3904.   if status then
  3905.     inboxEmpty = false
  3906.   else
  3907.     inboxEmpty = true
  3908.   end
  3909.  
  3910.   -- Draw Inbox Grid
  3911.   drawBox(20, 1, 2, 18, " ", tc, gridbc)
  3912.   drawBox(1, 20, 2, 1, " ", tc, gridbc)
  3913.   drawBox(1, 20, 6, 1, " ", tc, gridbc)
  3914.   drawBox(1, 20, 10, 1, " ", tc, gridbc)
  3915.   drawBox(1, 20, 14, 1, " ", tc, gridbc)
  3916.   drawBox(1, 20, 18, 1, " ", tc, gridbc)
  3917.   drawBox(1, 20, 19, 1, " ", tc, gridbc)
  3918.   drawBox(2, 4, 19, 1, " ", menutc, menubc)
  3919.   drawBox(16, 4, 19, 1, " ", menutc, menubc)
  3920.   printA("<-", 3, 19, false, menutc, menubc)
  3921.   printA("->", 17, 19, false, menutc, menubc)
  3922.  
  3923.   -- Draw refresh timer
  3924.   drawBox(34, 5, 1, 1, " ", menutc, menubc)
  3925.   printA(tostring(refreshCount), 35, 1, false, menutc, menubc)
  3926.  
  3927.   -- Page Logic Counter
  3928.   if inboxEmpty == false then
  3929.     inboxCount = #inbox
  3930.     if inboxCount >= 1 then
  3931.       inboxPages = 1
  3932.     elseif inboxCount > 4 and inboxCount <= 8 then
  3933.       inboxPages = 2
  3934.     elseif inboxCount > 8 and inboxCount <= 12 then
  3935.       inboxPages = 3
  3936.     elseif inboxCount > 12 and inboxCount <= 16 then
  3937.       inboxPages = 4
  3938.     elseif inboxCount > 16 and inboxCount <= 20 then
  3939.       inboxPages = 5
  3940.     end
  3941.  
  3942.     if inboxNumber == 1 then
  3943.       if inboxCount >= 1 then
  3944.         printA(inbox[1][1], 1, 3, false, selectedtc, inboxbc)
  3945.         printA(inbox[1][3], 1, 4, false, menutc, inboxbc)
  3946.         printA(inbox[1][4], 1, 5, false, menutc, inboxbc)
  3947.       end
  3948.       if inboxCount >= 2 then
  3949.         printA(inbox[2][1], 1, 7, false, selectedtc, inboxbc)
  3950.         printA(inbox[2][3], 1, 8, false, menutc, inboxbc)
  3951.         printA(inbox[2][4], 1, 9, false, menutc, inboxbc)
  3952.       end
  3953.       if inboxCount >= 3 then
  3954.         printA(inbox[3][1], 1, 11, false, selectedtc, inboxbc)
  3955.         printA(inbox[3][3], 1, 12, false, menutc, inboxbc)
  3956.         printA(inbox[3][4], 1, 13, false, menutc, inboxbc)
  3957.       end
  3958.       if inboxCount >= 4 then
  3959.         printA(inbox[4][1], 1, 15, false, selectedtc, inboxbc)
  3960.         printA(inbox[4][3], 1, 16, false, menutc, inboxbc)
  3961.         printA(inbox[4][4], 1, 17, false, menutc, inboxbc)
  3962.       end
  3963.     elseif inboxNumber == 2 then
  3964.       -- Draw Page 1
  3965.       if inboxCount >= 5 then
  3966.         printA(inbox[5][1], 1, 3, false, selectedtc, inboxbc)
  3967.         printA(inbox[5][3], 5, 4, false, menutc, inboxbc)
  3968.         printA(inbox[5][4], 5, 5, false, menutc, inboxbc)
  3969.       end
  3970.       if inboxCount >= 6 then
  3971.         printA(inbox[6][1], 1, 7, false, selectedtc, inboxbc)
  3972.         printA(inbox[6][3], 1, 8, false, menutc, inboxbc)
  3973.         printA(inbox[6][4], 1, 9, false, menutc, inboxbc)
  3974.       end
  3975.       if inboxCount >= 7 then
  3976.         printA(inbox[7][1], 1, 11, false, selectedtc, inboxbc)
  3977.         printA(inbox[7][3], 1, 12, false, menutc, inboxbc)
  3978.         printA(inbox[7][4], 1, 13, false, menutc, inboxbc)
  3979.       end
  3980.       if inboxCount >= 8 then
  3981.         printA(inbox[8][1], 1, 15, false, selectedtc, inboxbc)
  3982.         printA(inbox[8][3], 1, 16, false, menutc, inboxbc)
  3983.         printA(inbox[8][4], 1, 17, false, menutc, inboxbc)
  3984.       end
  3985.     elseif inboxNumber == 3 then
  3986.       -- Draw Page 1
  3987.       if inboxCount >= 9 then
  3988.         printA(inbox[9][1], 1, 3, false, selectedtc, inboxbc)
  3989.         printA(inbox[9][3], 5, 4, false, menutc, inboxbc)
  3990.         printA(inbox[9][4], 5, 5, false, menutc, inboxbc)
  3991.       end
  3992.       if inboxCount >= 10 then
  3993.         printA(inbox[10][1], 1, 7, false, selectedtc, inboxbc)
  3994.         printA(inbox[10][3], 1, 8, false, menutc, inboxbc)
  3995.         printA(inbox[10][4], 1, 9, false, menutc, inboxbc)
  3996.       end
  3997.       if inboxCount >= 11 then
  3998.         printA(inbox[11][1], 1, 11, false, selectedtc, inboxbc)
  3999.         printA(inbox[11][3], 1, 12, false, menutc, inboxbc)
  4000.         printA(inbox[11][4], 1, 13, false, menutc, inboxbc)
  4001.       end
  4002.       if inboxCount >= 12 then
  4003.         printA(inbox[12][1], 1, 15, false, selectedtc, inboxbc)
  4004.         printA(inbox[12][3], 1, 16, false, menutc, inboxbc)
  4005.         printA(inbox[12][4], 1, 17, false, menutc, inboxbc)
  4006.       end
  4007.     elseif inboxNumber == 4 then
  4008.       -- Draw Page 1
  4009.       if inboxCount >= 13 then
  4010.         printA(inbox[13][1], 1, 3, false, selectedtc, inboxbc)
  4011.         printA(inbox[13][3], 5, 4, false, menutc, inboxbc)
  4012.         printA(inbox[13][4], 5, 5, false, menutc, inboxbc)
  4013.       end
  4014.       if inboxCount >= 14 then
  4015.         printA(inbox[14][1], 1, 7, false, selectedtc, inboxbc)
  4016.         printA(inbox[14][3], 1, 8, false, menutc, inboxbc)
  4017.         printA(inbox[14][4], 1, 9, false, menutc, inboxbc)
  4018.       end
  4019.       if inboxCount >= 15 then
  4020.         printA(inbox[15][1], 1, 11, false, selectedtc, inboxbc)
  4021.         printA(inbox[15][3], 1, 12, false, menutc, inboxbc)
  4022.         printA(inbox[15][4], 1, 13, false, menutc, inboxbc)
  4023.       end
  4024.       if inboxCount >= 16 then
  4025.         printA(inbox[16][1], 1, 15, false, selectedtc, inboxbc)
  4026.         printA(inbox[16][3], 1, 16, false, menutc, inboxbc)
  4027.         printA(inbox[16][4], 1, 17, false, menutc, inboxbc)
  4028.       end
  4029.     elseif inboxNumber == 5 then
  4030.       -- Draw Page 1
  4031.       if inboxCount >= 17 then
  4032.         printA(inbox[17][1], 1, 3, false, selectedtc, inboxbc)
  4033.         printA(inbox[17][3], 5, 4, false, menutc, inboxbc)
  4034.         printA(inbox[17][4], 5, 5, false, menutc, inboxbc)
  4035.       end
  4036.       if inboxCount >= 18 then
  4037.         printA(inbox[18][1], 1, 7, false, selectedtc, inboxbc)
  4038.         printA(inbox[18][3], 1, 8, false, menutc, inboxbc)
  4039.         printA(inbox[18][4], 1, 9, false, menutc, inboxbc)
  4040.       end
  4041.       if inboxCount >= 19 then
  4042.         printA(inbox[19][1], 1, 11, false, selectedtc, inboxbc)
  4043.         printA(inbox[19][3], 1, 12, false, menutc, inboxbc)
  4044.         printA(inbox[19][4], 1, 13, false, menutc, inboxbc)
  4045.       end
  4046.       if inboxCount >= 20 then
  4047.         printA(inbox[20][1], 1, 15, false, selectedtc, inboxbc)
  4048.         printA(inbox[20][3], 1, 16, false, menutc, inboxbc)
  4049.         printA(inbox[20][4], 1, 17, false, menutc, inboxbc)
  4050.       end
  4051.     end
  4052.   end
  4053.   drawBox(8, 6, 19, 1, " ", menutc, menubc)
  4054.   printA(inboxNumber.."/5", 9, 19, false, menutc, menubc)
  4055.   while true do
  4056.     local args = { os.pullEvent() }
  4057.     if args[1] == "timer" then
  4058.       drawBox(44, 7, 1, 1, " ", menutc, menubc)
  4059.       printA(time(), 45, 1, false, menutc, menubc)
  4060.       drawBox(34, 5, 1, 1, " ", menutc, menubc)
  4061.       printA(tostring(refreshCount), 35, 1, false, menutc, menubc)
  4062.       refreshCount = refreshCount - 1
  4063.       if refreshCount == 0 then
  4064.         refreshCount = 300
  4065.         blaze_inbox(1)
  4066.       end
  4067.     elseif args[1] == "mouse_click" then
  4068.       if (args[3] >= 2 and args[3] <= 6) and (args[4] == 1) then
  4069.         drawDropdown("new")
  4070.       elseif (args[3] >= 2 and args[3] <= 11) and (args[4] == 2) then
  4071.         blaze_send()
  4072.         break
  4073.       elseif (args[3] >= 2 and args[3] <= 11) and (args[4] == 3) then
  4074.         addressBook("view")
  4075.         break
  4076.       elseif (args[3] >= 8 and args[3] <= 14) and (args[4] == 1) then
  4077.         blaze_inbox(1)
  4078.         break
  4079.       elseif (args[3] >= 16 and args[3] <= 25) and (args[4] == 1) then
  4080.         blaze_options()
  4081.         break
  4082.       elseif (args[3] >= 27 and args[3] <= 32) and (args[4] == 1) then
  4083.         blaze_help()
  4084.         break
  4085.       elseif (args[3] >= 3 and args[3] <= 48) and (args[4] == 7) then
  4086.         -- Do Update
  4087.         blaze_update()
  4088.         break
  4089.       elseif (args[3] >= 16 and args[3] <= 19) and (args[4] == 19) then
  4090.         if inboxNumber <= 4 then
  4091.           blaze_inbox(inboxNumber + 1)
  4092.         end
  4093.       elseif (args[3] >= 2 and args[3] <= 5) and (args[4] == 19) then
  4094.         if inboxNumber >= 2 then
  4095.           blaze_inbox(inboxNumber - 1)
  4096.         end
  4097.       elseif (args[3] >= 23 and args[3] <= 29) and (args[4] == 18) then
  4098.         sendRecipient = inbox[msgID1][3]
  4099.         blaze_send()
  4100.         break
  4101.       elseif (args[3] >= 42 and args[3] <= 48) and (args[4] == 18) then
  4102.         BlazeDelete(username, password, msgID)
  4103.         blaze_inbox(1)
  4104.         break
  4105.       end  
  4106.       -- Do Inbox Logic
  4107.       if inboxNumber == 1 then
  4108.         if (args[3] >= 1 and args[3] <= 19) and (args[4] >= 3 and args[4] <= 5) then
  4109.           openMessage(1)
  4110.           msgID = inbox[1][1]
  4111.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 7 and args[4] <= 9) then
  4112.           openMessage(2)
  4113.           msgID = inbox[2][1]
  4114.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 11 and args[4] <= 13) then
  4115.           openMessage(3)
  4116.           msgID = inbox[3][1]
  4117.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 15 and args[4] <= 17) then
  4118.           openMessage(4)
  4119.           msgID = inbox[4][1]
  4120.         end
  4121.       elseif inboxNumber == 2 then
  4122.         -- Allow Message Choosing for Page 2
  4123.         if (args[3] >= 1 and args[3] <= 19) and (args[4] >= 3 and args[4] <= 5) then
  4124.           openMessage(5)
  4125.           msgID = inbox[5][1]
  4126.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 7 and args[4] <= 9) then
  4127.           openMessage(6)
  4128.           msgID = inbox[6][1]
  4129.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 11 and args[4] <= 13) then
  4130.           openMessage(7)
  4131.           msgID = inbox[7][1]
  4132.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 15 and args[4] <= 17) then
  4133.           openMessage(8)
  4134.           msgID = inbox[8][1]
  4135.         end
  4136.       elseif inboxNumber == 3 then
  4137.         -- Allow Message Choosing for Page 3
  4138.         if (args[3] >= 1 and args[3] <= 19) and (args[4] >= 3 and args[4] <= 5) then
  4139.           openMessage(9)
  4140.           msgID = inbox[9][1]
  4141.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 7 and args[4] <= 9) then
  4142.           openMessage(10)
  4143.           msgID = inbox[10][1]
  4144.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 11 and args[4] <= 13) then
  4145.           openMessage(11)
  4146.           msgID = inbox[11][1]
  4147.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 15 and args[4] <= 17) then
  4148.           openMessage(12)
  4149.           msgID = inbox[12][1]
  4150.         end
  4151.       elseif inboxNumber == 4 then
  4152.         -- Allow Message Choosing for Page 4
  4153.         if (args[3] >= 1 and args[3] <= 19) and (args[4] >= 3 and args[4] <= 5) then
  4154.           openMessage(13)
  4155.           msgID = inbox[13][1]
  4156.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 7 and args[4] <= 9) then
  4157.           openMessage(14)
  4158.           msgID = inbox[14][1]
  4159.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 11 and args[4] <= 13) then
  4160.           openMessage(15)
  4161.           msgID = inbox[15][1]
  4162.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 15 and args[4] <= 17) then
  4163.           openMessage(16)
  4164.           msgID = inbox[16][1]
  4165.         end
  4166.       elseif inboxNumber == 5 then
  4167.         -- Allow Message Choosing for Page 5
  4168.         if (args[3] >= 1 and args[3] <= 19) and (args[4] >= 3 and args[4] <= 5) then
  4169.           openMessage(17)
  4170.           msgID = inbox[17][1]
  4171.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 7 and args[4] <= 9) then
  4172.           openMessage(18)
  4173.           msgID = inbox[18][1]
  4174.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 11 and args[4] <= 13) then
  4175.           openMessage(19)
  4176.           msgID = inbox[19][1]
  4177.         elseif (args[3] >= 1 and args[3] <= 19) and (args[4] >= 15 and args[4] <= 17) then
  4178.           openMessage(20)
  4179.           msgID = inbox[20][1]
  4180.         end
  4181.       end
  4182.     end
  4183.   end
  4184. end
  4185.  
  4186. function openMessage(intID)
  4187.   msgID1 = intID
  4188.   local texttc = "black"
  4189.   local textbc = "white"
  4190.   local gridtc = "white"
  4191.   local gridbc = "grey"
  4192.   local menutc = "blue"
  4193.   local menubc = "lightGrey"
  4194.   setCol(texttc, textbc)
  4195.   local count1 = 2
  4196.   repeat
  4197.     term.setCursorPos(21, count1)
  4198.     write("                               ")
  4199.     count1 = count1 + 1
  4200.   until count1 == 19
  4201.   drawBox(21, 31, 2, 18, " ", "black", "black")
  4202.   drawBox(22, 29, 3, 16, " ", gridtc, gridbc)
  4203.   drawBox(22, 29, 7, 1, " ", gridtc, gridbc)
  4204.   drawBox(22, 29, 18, 1, " ", gridtc, gridbc)
  4205.   drawBox(23, 7, 18, 1, " ", menutc, menubc)
  4206.   drawBox(42, 8, 18, 1, " ", menutc, menubc)
  4207.   drawBox(31, 1, 4, 3, " ", gridtc, gridbc)
  4208.   printA("REPLY", 24, 18, false, menutc, menubc)
  4209.   printA("DELETE", 43, 18, false, menutc, menubc)
  4210.   printA("Sender:", 23, 4, false, texttc, textbc)
  4211.   printA("Subject:", 23, 5, false, texttc, textbc)
  4212.   printA(inbox[intID][3], 32, 4, false, texttc, textbc)
  4213.   local count1 = 5
  4214.   local tSubject = wordwrap(inbox[intID][4], 18)
  4215.   for _, v in ipairs(tSubject) do
  4216.     term.setCursorPos(32, count1)
  4217.     write(v)
  4218.     count1 = count1 + 1
  4219.   end
  4220.   printA(inbox[intID][4], 32, 5, false, texttc, textbc)
  4221.   setCol(texttc, textbc)
  4222.   local count1 = 8
  4223.   local tMessage = wordwrap(inbox[intID][5], 27)
  4224.   for _,v in ipairs(tMessage) do
  4225.     term.setCursorPos(23, count1)
  4226.     write(v)
  4227.     count1 = count1 + 1
  4228.   end
  4229.   printA("Message ID: "..inbox[intID][1], 23, 3, false, "lime", gridbc)
  4230. end
  4231.  
  4232. function drawDropdown(sMenu, intY)
  4233.   if sMenu == "new" then
  4234.     drawBox(2, 9, 2, 2, " ", menutc, menubc)
  4235.     printA("Message", 3, 2, false, menutc, menubc)
  4236.     printA("Contact", 3, 3, false, menutc, menubc)
  4237.   end
  4238. end
  4239.  
  4240. function blaze_send()
  4241.   gridtc = "white"
  4242.   gridbc = "grey"
  4243.   texttc = "black"
  4244.   textbc = "white"
  4245.   menutc = "blue"
  4246.   menubc = "lightgrey"
  4247.   cs()
  4248.   colourScreen()
  4249.   drawMenuBar()
  4250.   printA("NEW", 3, 1, false, selectedtc, menubc)
  4251.   drawBox(1, 51, 4, 1, " ", gridtc, gridbc)
  4252.   drawBox(12, 1, 2, 3, " ", gridtc, gridbc)
  4253.   printA("To:", 1, 2, false, texttc, textbc)
  4254.   if sendRecipient then
  4255.     printA(sendRecipient, 14, 2, false, texttc, textbc)
  4256.   end
  4257.   sendSubject = nil
  4258.   printA("Subject:", 1, 3, false, texttc, textbc)
  4259.   printC("Message Contents (MAX 200 CHARS)", 4, false, gridtc, gridbc)
  4260.   drawBox(46, 1, 2, 3, " ", gridtc, gridbc)
  4261.   printA("MAX:1", 47, 2, false, texttc, textbc)
  4262.   printA("<= 16", 47, 3, false, texttc, textbc)
  4263.  
  4264.   drawBox(1, 51, 19, 1, " ", gridtc, gridbc)
  4265.   drawBox(2, 6, 19, 1, " ", menutc, menubc)
  4266.   printA("SEND", 3, 19, false, menutc, menubc)
  4267.   drawBox(10, 7, 19, 1, " ", menutc, menubc)
  4268.   printA("CLEAR", 11, 19, false, menutc, menubc)
  4269.   drawBox(42, 8, 19, 1, " ", menutc, menubc)
  4270.   printA("CANCEL", 43, 19, false, menutc, menubc)
  4271.  
  4272.   while true do
  4273.     local args = { os.pullEvent() }
  4274.     if args[1] == "timer" then
  4275.       drawMenuBar()
  4276.       printA("NEW", 3, 1, false, selectedtc, menubc)
  4277.     elseif args[1] == "mouse_click" then
  4278.       if (args[3] >= 42 and args[3] <= 50) and (args[4] == 19) then
  4279.         blaze_inbox(1)
  4280.         break
  4281.       elseif (args[3] >= 2 and args[3] <= 8) and (args[4] == 19) then
  4282.         BlazeSend(username, password, sendRecipient, sendSubject, sendMessage)
  4283.         drawPopup("Message Sent")
  4284.         sleep(1.5)
  4285.         blaze_inbox(1)
  4286.         break
  4287.       elseif args[1] == "mouse_click" then
  4288.         if (args[3] >= 2 and args[3] <= 6) and (args[4] == 1) then
  4289.         drawDropdown("new")
  4290.       elseif (args[3] >= 2 and args[3] <= 11) and (args[4] == 2) then
  4291.         blaze_send()
  4292.         break
  4293.       elseif (args[3] >= 2 and args[3] <= 11) and (args[4] == 3) then
  4294.         addressBook("view")
  4295.         break
  4296.       elseif (args[3] >= 8 and args[3] <= 14) and (args[4] == 1) then
  4297.         blaze_inbox(1)
  4298.         break
  4299.       elseif (args[3] >= 16 and args[3] <= 25) and (args[4] == 1) then
  4300.         blaze_options()
  4301.         break
  4302.       elseif (args[3] >= 27 and args[3] <= 32) and (args[4] == 1) then
  4303.         blaze_help()
  4304.         break
  4305.       elseif (args[3] >= 3 and args[3] <= 48) and (args[4] == 7) then
  4306.         -- Do Update
  4307.         blaze_update()
  4308.         break
  4309.       elseif (args[3] >= 23 and args[3] <= 29) and (args[4] == 18) then
  4310.         -- Do Back button
  4311.         blaze_inbox(1)
  4312.         break
  4313.         elseif (args[3] >= 13 and args[3] <= 45) and (args[4] == 2) then
  4314.           -- Start Recipient Input
  4315.           if sendRecipientExist then
  4316.             setCol(texttc, textbc)
  4317.             term.setCursorPos(13,2)
  4318.             write("                                 ")
  4319.           end
  4320.           setCol(texttc, textbc)
  4321.           term.setCursorPos(14,2)
  4322.           sendRecipient = read()
  4323.           sendRecipientExist = true        
  4324.         elseif (args[3] >= 13 and args[3] <= 45) and (args[4] == 3) then
  4325.           -- Start Subject Input
  4326.           if sendSubjectExist then
  4327.             setCol(texttc, textbc)
  4328.             term.setCursorPos(13,3)
  4329.             write("                                 ")
  4330.           end
  4331.           setCol(texttc, textbc)
  4332.           term.setCursorPos(14,3)
  4333.           sendSubject = read()
  4334.           sendSubjectExist = true  
  4335.         elseif (args[3] >= 1 and args[3] <= 51) and (args[4] >= 5 and args[4] <= 18) then
  4336.           -- Start Message Input
  4337.           if sendMessageExist then
  4338.             count2 = 5
  4339.             repeat
  4340.               term.setCursorPos(1, count2)
  4341.               setCol("white", "white")
  4342.               write("                                                   ")
  4343.               count2 = count2 + 1
  4344.             until count2 == 19
  4345.           end
  4346.           setCol("black", "white")
  4347.           term.setCursorPos(1, 5)
  4348.           sendMessage = read()
  4349.           sendMessageExist = true
  4350.           term.setCursorPos(1, 5)
  4351.           for _, v in ipairs(wordwrap(sendMessage)) do
  4352.             print(v)
  4353.           end
  4354.         end
  4355.       end
  4356.     end
  4357.   end
  4358. end
  4359.  
  4360. function blaze_options()
  4361.   texttc = "black"
  4362.   textbc = "white"
  4363.   selectedtc = "lime"
  4364.   gridtc = "white"
  4365.   gridbc = "grey"
  4366.   menutc = "blue"
  4367.   menubc = "lightGrey"
  4368.   cs()
  4369.   colourScreen()
  4370.   drawMenuBar()
  4371.   drawBox(16, 10, 1, 1, " ", menutc, menubc)
  4372.   printA("SETTINGS", 17, 1, false, selectedtc, menubc)
  4373.   local tOptions = {"1. Register New User", "2. Update Blaze"}
  4374.   drawBox(1, 51, 2, 18, " ", "black", "black")
  4375.   drawBox(2, 49, 3, 16, " ", gridtc, gridbc)
  4376.   drawBox(35, 1, 3, 13, " ", gridtc, gridbc)
  4377.   drawBox(2, 49, 15, 1, " ", gridtc, gridbc)
  4378.   drawBox(2, 49, 5, 1, " ", gridtc, gridbc)
  4379.   drawBox(3, 32, 4, 1, " ", menutc, menubc)
  4380.   drawBox(36, 14, 4, 1, " ", menutc, menubc)
  4381.   printA("OPTION/FUNCTION NAME", 4, 4, false, menutc, menubc)
  4382.   printA("VALUE", 37, 4, false, menutc, menubc)
  4383.   printA(tOptions[1], 4, 6, false, menubc, textbc)
  4384.   printA(tOptions[2], 4, 7, false, texttc, textbc)
  4385.   printA("N/A", 37, 6, false, texttc, textbc)
  4386.   printA("N/A", 37, 7, false, texttc, textbc)
  4387.   printA("Greyed out options are not yet functional.", 3, 16, false, texttc, textbc)
  4388.   printA("N/A applies to functions that can't be changed.", 3, 17, false, texttc, textbc)
  4389.   printA(" BACK ", 23, 18, false, menutc, menubc)
  4390.  
  4391.   while true do
  4392.     local args = { os.pullEvent() }
  4393.     if args[1] == "timer" then
  4394.       drawMenuBar()
  4395.       drawBox(16, 10, 1, 1, " ", menutc, menubc)
  4396.       printA("SETTINGS", 17, 1, false, selectedtc, menubc)
  4397.       settings1 = true
  4398.     elseif args[1] == "mouse_click" then
  4399.       if (args[3] >= 2 and args[3] <= 6) and (args[4] == 1) then
  4400.         if settings1 then
  4401.           settings1 = false
  4402.           drawDropdown("new")
  4403.         end
  4404.       elseif (args[3] >= 2 and args[3] <= 11) and (args[4] == 2) then
  4405.         if settings1 then
  4406.           settings1 = false
  4407.           blaze_send()
  4408.           break
  4409.         end
  4410.       elseif (args[3] >= 2 and args[3] <= 11) and (args[4] == 3) then
  4411.         if settings1 then
  4412.           settings1 = false
  4413.           addressBook("view")
  4414.           break
  4415.         end
  4416.       elseif (args[3] >= 8 and args[3] <= 14) and (args[4] == 1) then
  4417.         if settings1 then
  4418.           settings1 = false
  4419.           blaze_inbox(1)
  4420.           break
  4421.         end
  4422.       elseif (args[3] >= 16 and args[3] <= 25) and (args[4] == 1) then
  4423.         if settings1 then
  4424.           settings1 = false
  4425.           blaze_options()
  4426.           break
  4427.         end
  4428.       elseif (args[3] >= 27 and args[3] <= 32) and (args[4] == 1) then
  4429.         if settings1 then
  4430.           settings1 = false
  4431.           blaze_help()
  4432.           break
  4433.         end
  4434.       elseif (args[3] >= 3 and args[3] <= 48) and (args[4] == 7) then
  4435.         -- Do Update
  4436.         if settings1 then
  4437.           settings1 = false
  4438.           blaze_update()
  4439.           break
  4440.         end
  4441.       elseif (args[3] >= 23 and args[3] <= 29) and (args[4] == 18) then
  4442.         -- Do Back button
  4443.         if settings1 then
  4444.           settings1 = false
  4445.           blaze_inbox(1)
  4446.           break
  4447.         end
  4448.       end
  4449.     end
  4450.   end
  4451. end
  4452.  
  4453. function blaze_update()
  4454.   cs()
  4455.   colourScreen()
  4456.   -- Do Update Stuff Here
  4457.   bartc = "blue"
  4458.   barbc = "lightGrey"
  4459.   texttc = "black"
  4460.   textbc = "white"
  4461.   drawBox(1, 51, 1, 2, " ", bartc, barbc)
  4462.   printA("Blaze Email Client", 1, 1, false, bartc, barbc)
  4463.   printC("UPDATING BLAZE", 2, false, bartc, barbc)
  4464.   term.setCursorPos(1,4)
  4465.   setCol(texttc, textbc)
  4466.   print("> Update in progress, please wait")
  4467.   sleep(1)
  4468.   print("> Grabbing Blaze")
  4469.   shell.run("pastebin get VehDCxwR updateBlaze")
  4470.   print("> Deleting old file")
  4471.   fs.delete("blaze")
  4472.   print("> Saving new file")
  4473.   shell.run("mv updateBlaze blaze")
  4474.   print("> Restarting...")
  4475.   sleep(1.5)
  4476.   os.reboot()
  4477. end
  4478.  
  4479. function blaze_help()
  4480.   texttc = "black"
  4481.   textbc = "white"
  4482.   selectedtc = "lime"
  4483.   gridtc = "white"
  4484.   gridbc = "grey"
  4485.   menutc = "blue"
  4486.   menubc = "lightGrey"
  4487.   cs()
  4488.   colourScreen()
  4489.   drawMenuBar()
  4490.   drawBox(27, 6, 1, 1, " ", menutc, menubc)
  4491.   printA("HELP", 28, 1, false, selectedtc, menubc)
  4492.   drawBox(1, 51, 2, 18, " ", "black", "black")
  4493.   drawBox(2, 49, 3, 16, " ", gridtc, gridbc)
  4494.   local sHelp1 = "Created and hosted by DannySMc, Contacts: danny.smc95@gmail.com, Website: http://dannysmc.com. Questions? Contact Danny! Want to use the API? Check on my blog to when it is published. Passwords are secured with SHA265 Hashing algorithm for extra security. This is a beta, so there will likely be many bugs! Please submit them on the ComputerCraft Forums post in the comments."
  4495.   local tHelp1 = wordwrap(sHelp1, 47)
  4496.   drawBox(22, 6, 3, 1, " ", menutc, menubc)
  4497.   printA("HELP", 23, 3, false, menutc, menubc)
  4498.   setCol(texttc, textbc)
  4499.   local count1 = 4
  4500.   for _,v in ipairs(tHelp1) do
  4501.     term.setCursorPos(3, count1)
  4502.     write(v)
  4503.     count1 = count1 + 1
  4504.   end
  4505.  
  4506.   while true do
  4507.     local args = { os.pullEvent() }
  4508.     if args[1] == "timer" then
  4509.       drawMenuBar()
  4510.       drawBox(27, 6, 1, 1, " ", menutc, menubc)
  4511.       printA("HELP", 28, 1, false, selectedtc, menubc)
  4512.     elseif args[1] == "mouse_click" then
  4513.       if (args[3] >= 2 and args[3] <= 6) and (args[4] == 1) then
  4514.         drawDropdown("new")
  4515.       elseif (args[3] >= 2 and args[3] <= 11) and (args[4] == 2) then
  4516.         blaze_send()
  4517.         break
  4518.       elseif (args[3] >= 2 and args[3] <= 11) and (args[4] == 3) then
  4519.         addressBook("view")
  4520.         break
  4521.       elseif (args[3] >= 8 and args[3] <= 14) and (args[4] == 1) then
  4522.         blaze_inbox(1)
  4523.         break
  4524.       elseif (args[3] >= 16 and args[3] <= 25) and (args[4] == 1) then
  4525.         blaze_options()
  4526.         break
  4527.       elseif (args[3] >= 27 and args[3] <= 32) and (args[4] == 1) then
  4528.         blaze_help()
  4529.         break
  4530.       elseif (args[3] >= 3 and args[3] <= 48) and (args[4] == 7) then
  4531.         -- Do Update
  4532.         blaze_update()
  4533.         break
  4534.       elseif (args[3] >= 23 and args[3] <= 29) and (args[4] == 18) then
  4535.         -- Do Back button
  4536.         blaze_inbox(1)
  4537.         break
  4538.       end
  4539.     end
  4540.   end
  4541. end
  4542.  
  4543. function filebrowser()
  4544.     local tArgs = {}
  4545.     local ver = "1.4"
  4546.     local sTitle = "File Browser"
  4547.     local bugTest, norun, dir, showAll
  4548.     local _tArgs = {}
  4549.     local config = "config/mouse.cfg"
  4550.  
  4551.     local temp
  4552.     if shell and shell.getRunningProgram then
  4553.         temp = shell.getRunningProgram()
  4554.     end
  4555.  
  4556.     temp = temp or "/bla"
  4557.     local localPath = string.sub(temp,1,#temp-string.len(fs.getName(temp)))
  4558.     temp = nil -- just because not needed
  4559.  
  4560.     -- load config file
  4561.  
  4562.     local configSet = {}
  4563.     local cnf = {}
  4564.  
  4565.     if fs.exists(localPath.."/"..config) then
  4566.         local file = fs.open(localPath.."/"..config,"r")
  4567.         if file then
  4568.             local item = file.readLine()
  4569.             while item do
  4570.                 table.insert(cnf,item)
  4571.                 item = file.readLine()
  4572.             end
  4573.             file.close()
  4574.         end
  4575.     end
  4576.  
  4577.     for i = 1,10 do
  4578.         local test,data = pcall(textutils.unserialize,cnf[i])
  4579.         if test then
  4580.             configSet[i] = data
  4581.         else
  4582.             configSet[i] = nil
  4583.         end
  4584.     end
  4585.     cnf = nil
  4586.  
  4587.     -- color configuration work in progress
  4588.     local titleBar = configSet[1] or {txt = colors.black,back = colors.blue}
  4589.     local addressBar = configSet[2] or {txt = colors.black,back = colors.lightGray}
  4590.     local itemWindo = configSet[3] or {txt = colors.black,back = colors.cyan}
  4591.     local rcmList = configSet[4] or {txt = colors.black,back = colors.lightGray} -- rcm = Right Click Menu List
  4592.     local rcmTitle = configSet[5] or {txt = colors.black,back = colors.blue}
  4593.     local dialogTitle = configSet[6] or {txt = colors.black,back = colors.blue}
  4594.     local dialogWindo = configSet[7] or {txt = colors.black,back = colors.white}
  4595.     local scrollCol = configSet[8] or {off = colors.gray, button = colors.gray,back = colors.lightGray}
  4596.  
  4597.     local tIcons = configSet[9] or {
  4598.         back = {tCol = "lightGray",bCol = "blue",txt = " < "},
  4599.         disk = {tCol = "lime",bCol = "green",txt = "[*]"},
  4600.         audio = {tCol = "yellow",bCol = "red",txt = "(o)"},
  4601.         folder = {tCol = "lightGray",bCol = "blue",txt = "[=]"},
  4602.         file = {tCol = nil ,bCol = nil ,txt = nil}
  4603.     }
  4604.  
  4605.     local customLaunch = configSet[10] or {
  4606.         ["Edit"] = "rom/programs/edit",
  4607.         ["Paint"] = "rom/programs/color/paint"
  4608.     }
  4609.  
  4610.     local function saveCFG(overWrite)
  4611.         if not fs.exists(localPath.."/"..config) or overWrite then
  4612.             local cnf = {}
  4613.             local file = fs.open(localPath.."/"..config,"w")
  4614.             if file then
  4615.                 file.write(textutils.serialize(titleBar).."\n")
  4616.                 file.write(textutils.serialize(addressBar).."\n")
  4617.                 file.write(textutils.serialize(itemWindo).."\n")
  4618.                 file.write(textutils.serialize(rcmList).."\n")
  4619.                 file.write(textutils.serialize(rcmTitle).."\n")
  4620.                 file.write(textutils.serialize(dialogTitle).."\n")
  4621.                 file.write(textutils.serialize(dialogWindo).."\n")
  4622.                 file.write(textutils.serialize(scrollCol).."\n")
  4623.                 file.write(textutils.serialize(tIcons).."\n")
  4624.                 file.write(textutils.serialize(customLaunch).."\n")
  4625.                 file.close()
  4626.             elseif overWrite then
  4627.             end
  4628.         end
  4629.     end
  4630.  
  4631.     saveCFG()
  4632.  
  4633.     -- end configuration
  4634.  
  4635.     local function help()
  4636.         print([[Usage: browser [-d] [-h] [-a] [-u] [--debug] [--help] [--dir <dir>] [--all] [--update]
  4637.     --debug or -d: enable debug mode
  4638.     --help or -h: display this screen
  4639.     --dir: define initial directory
  4640.     --all or -a: show hidden files
  4641.     --update -u: update]])
  4642.     end
  4643.  
  4644.     local function inBouwndry(clickX,clickY,boxX,boxY,width,hight)
  4645.         return ( clickX >= boxX and clickX < boxX + width and clickY >= boxY and clickY < boxY + hight )
  4646.     end
  4647.  
  4648.     local function update()
  4649.         print("Checking for Updates")
  4650.         local isHTTP = false
  4651.         local response
  4652.         if http then
  4653.             isHTTP = true
  4654.             print("http on")
  4655.             response = http.get("http://pastebin.com/raw.php?i=rLbnyM1U")
  4656.         end
  4657.         local flag = false
  4658.         local isNewFlag = false
  4659.         local newVerID
  4660.         if response and isHTTP then
  4661.             print("recived")
  4662.             local sInfo = response.readLine()
  4663.             print(sInfo)
  4664.             while sInfo do
  4665.                 print(sInfo)
  4666.                 if flag then
  4667.                     if sInfo == ver then
  4668.                         print("Mouse File Browser is up to date")
  4669.                         break
  4670.                     else
  4671.                         newVerID = sInfo
  4672.                         flag = false
  4673.                         isNewFlag = true
  4674.                     end
  4675.                 elseif sInfo == sTitle then
  4676.                     flag = true
  4677.                 elseif isNewFlag then
  4678.                     isNewFlag = sInfo
  4679.                     response.close()
  4680.                     break
  4681.                 end
  4682.                 sInfo = response.readLine()
  4683.             end
  4684.             if isNewFlag then
  4685.                 print("New vershion avalible "..newVerID)
  4686.                 print('downloading to Browser')
  4687.                 if fs.exists("Browser") then
  4688.                     write("Browser exists OverWrite Browser Y/N : ")
  4689.                     local input = string.lower(read())
  4690.                     while input ~= "y" and input ~= "n" do
  4691.                         print("y or n required")
  4692.                         input = string.lower(read())
  4693.                     end
  4694.                     if input == "y" then
  4695.                         print("Over Writeing Browser")
  4696.                         print("Downloading new File")
  4697.                         local response = http.get("http://pastebin.com/raw.php?i="..isNewFlag)
  4698.                         if response then
  4699.                             print("file downloaded")
  4700.                             print("installing")
  4701.                             fs.delete("Browser")
  4702.                             local handel = fs.open("Browser","w")
  4703.                             if handel then
  4704.                                 handel.write(response.readAll())
  4705.                                 handel.close()
  4706.                                 print("Update Complete")
  4707.                             end
  4708.                             response.close()
  4709.                         end
  4710.                     else
  4711.                         print("Update aborted")
  4712.                     end
  4713.                 else
  4714.                     print("Downloading new File")
  4715.                     local response = http.get("http://pastebin.com/raw.php?i="..isNewFlag)
  4716.                     if response then
  4717.                         print("file downloaded")
  4718.                         print("installing")
  4719.                         local handel = fs.open("Browser","w")
  4720.                         if handel then
  4721.                             handel.write(response.readAll())
  4722.                             handel.close()
  4723.                             print("Update Complete")
  4724.                         end
  4725.                         response.close()
  4726.                     end
  4727.                 end
  4728.             end
  4729.         elseif isHTTP then
  4730.             print("Error downloading update file Please contact BigSHinyToys on the CC forums")
  4731.             print("http://www.computercraft.info/forums2/index.php?/topic/5509-advanced-computer-mouse-file-browser/")
  4732.         elseif not isHTTP then
  4733.             print("HTTP API is turned off")
  4734.             print("Access Computer Craft Configer and change line")
  4735.             print([[enableapi_http {
  4736.     # Enable the "http" API on Computers
  4737.     general=false
  4738.     }
  4739.     TO THIS :
  4740.     enableapi_http {
  4741.     # Enable the "http" API on Computers
  4742.     general=true
  4743.     }]])
  4744.         end
  4745.         notCMD = false
  4746.         norun = true
  4747.     end
  4748.  
  4749.     for a = 1, #tArgs do
  4750.         if tArgs[a]:sub(1,2) == "--" then
  4751.             local cmd = tArgs[a]:sub(3):lower()
  4752.             if cmd == "debug" then
  4753.                 bugTest = true
  4754.             elseif cmd == "help" then
  4755.                 help()
  4756.                 norun = true
  4757.             elseif cmd == "dir" then
  4758.                 dir = tArgs[a+1]
  4759.                 a = a + 1
  4760.             elseif cmd == "all" then
  4761.                 showAll = true
  4762.             elseif cmd == "update" then
  4763.                 update()
  4764.             end
  4765.         elseif tArgs[a]:sub(1,1) == "-" then
  4766.             for b = 2, #tArgs[a] do
  4767.                 cmd = tArgs[a]:sub(b, b)
  4768.                 if cmd == "d" then
  4769.                     bugTest = true
  4770.                 elseif cmd == "h" then
  4771.                     help()
  4772.                     norun = true
  4773.                 elseif cmd == "p" then
  4774.                     dir = tArgs[a+1]
  4775.                     a = a + 1
  4776.                 elseif cmd == "a" then
  4777.                     showAll = true
  4778.                 elseif cmd == "u" then
  4779.                     update()
  4780.                 end
  4781.             end
  4782.         else
  4783.             table.insert(_tArgs, tArgs[a])
  4784.         end
  4785.     end
  4786.  
  4787.     if (not dir) and shell and shell.dir then
  4788.         dir = shell.dir()
  4789.     end
  4790.  
  4791.     if dir and shell and shell.resolve then
  4792.         dir = shell.resolve(dir)
  4793.     end
  4794.  
  4795.     dir = dir or "/"
  4796.  
  4797.     if bugTest then -- this is that the var is for testing
  4798.         print("Dir: "..dir)
  4799.         os.startTimer(4)
  4800.         os.pullEvent()
  4801.     end
  4802.  
  4803.     local function clear()
  4804.         term.setBackgroundColor(colors.black)
  4805.         term.setTextColor(colors.white)
  4806.         term.clear()
  4807.         term.setCursorBlink(false)
  4808.         term.setCursorPos(1,1)
  4809.     end
  4810.  
  4811.     --[[
  4812.             Code thanks to Cruor
  4813.             http://www.computercraft.info/forums2/index.php?/topic/5802-support-for-shell/
  4814.     ]]--
  4815.  
  4816.     local function fixArgs(...)
  4817.         local tReturn={}
  4818.         local str=table.concat({...}," ")
  4819.         local sMatch
  4820.         while str and #str>0 do
  4821.             if string.sub(str,1,1)=="\"" then
  4822.                 sMatch, str=string.match(str, "\"(.-)\"%s*(.*)")
  4823.             else
  4824.                 sMatch, str=string.match(str, "(%S+)%s*(.*)")
  4825.             end
  4826.             table.insert(tReturn,sMatch)
  4827.         end
  4828.         return tReturn
  4829.     end
  4830.  
  4831.     --[[ end Cruor function ]]--
  4832.  
  4833.  
  4834.     -- modified read made to play nice with coroutines
  4835.  
  4836.     local function readMOD( _sReplaceChar, _tHistory,_wdth)
  4837.         local sLine = ""
  4838.         term.setCursorBlink( true )
  4839.  
  4840.         local nHistoryPos = nil
  4841.         local nPos = 0
  4842.         if _sReplaceChar then
  4843.             _sReplaceChar = string.sub( _sReplaceChar, 1, 1 )
  4844.         end
  4845.        
  4846.         local sx, sy = term.getCursorPos() 
  4847.  
  4848.         local w, h = term.getSize()
  4849.         if _wdth and type(_wdth) == "number" then
  4850.             w = sx + _wdth - 1
  4851.         end
  4852.        
  4853.         local function redraw( _sCustomReplaceChar )
  4854.             local nScroll = 0
  4855.             if sx + nPos >= w then
  4856.                 nScroll = (sx + nPos) - w
  4857.             end
  4858.                
  4859.             term.setCursorPos( sx + _wdth - 1, sy )
  4860.             term.write(" ")
  4861.             term.setCursorPos( sx, sy )
  4862.             local sReplace = _sCustomReplaceChar or _sReplaceChar
  4863.             if sReplace then
  4864.                 term.write( string.rep(sReplace,_wdth) )
  4865.             else
  4866.                 term.write( string.sub( sLine, nScroll + 1 ,nScroll + _wdth) )
  4867.             end
  4868.             term.setCursorPos( sx + nPos - nScroll, sy )
  4869.         end
  4870.        
  4871.         while true do
  4872.             local sEvent, param = os.pullEvent()
  4873.             if sEvent == "char" then
  4874.                 sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
  4875.                 nPos = nPos + 1
  4876.                 redraw()
  4877.                
  4878.             elseif sEvent == "key" then
  4879.                
  4880.                 if param == keys.left then
  4881.                     -- Left
  4882.                     if nPos > 0 then
  4883.                         nPos = nPos - 1
  4884.                         redraw()
  4885.                     end
  4886.                    
  4887.                 elseif param == keys.right then
  4888.                     -- Right               
  4889.                     if nPos < string.len(sLine) then
  4890.                         nPos = nPos + 1
  4891.                         redraw()
  4892.                     end
  4893.                
  4894.                 elseif param == keys.up or param == keys.down then
  4895.                     -- Up or down
  4896.                     if _tHistory then
  4897.                         redraw(" ");
  4898.                         if param == keys.up then
  4899.                             -- Up
  4900.                             if nHistoryPos == nil then
  4901.                                 if #_tHistory > 0 then
  4902.                                     nHistoryPos = #_tHistory
  4903.                                 end
  4904.                             elseif nHistoryPos > 1 then
  4905.                                 nHistoryPos = nHistoryPos - 1
  4906.                             end
  4907.                         else
  4908.                             -- Down
  4909.                             if nHistoryPos == #_tHistory then
  4910.                                 nHistoryPos = nil
  4911.                             elseif nHistoryPos ~= nil then
  4912.                                 nHistoryPos = nHistoryPos + 1
  4913.                             end                    
  4914.                         end
  4915.                        
  4916.                         if nHistoryPos then
  4917.                             sLine = _tHistory[nHistoryPos]
  4918.                             nPos = string.len( sLine )
  4919.                         else
  4920.                             sLine = ""
  4921.                             nPos = 0
  4922.                         end
  4923.                         redraw()
  4924.                     end
  4925.                 elseif param == keys.backspace then
  4926.                     -- Backspace
  4927.                     if nPos > 0 then
  4928.                         redraw(" ");
  4929.                         sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
  4930.                         nPos = nPos - 1                
  4931.                         redraw()
  4932.                     end
  4933.                 elseif param == keys.home then
  4934.                     -- Home
  4935.                     nPos = 0
  4936.                     redraw()       
  4937.                 elseif param == keys.delete then
  4938.                     if nPos < string.len(sLine) then
  4939.                         redraw(" ");
  4940.                         sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )              
  4941.                         redraw()
  4942.                     end
  4943.                 elseif param == keys["end"] then
  4944.                     -- End
  4945.                     nPos = string.len(sLine)
  4946.                     redraw()
  4947.                 end
  4948.             elseif sEvent == "redraw" then
  4949.                 redraw()
  4950.             elseif sEvent == "return" then
  4951.                 term.setCursorBlink( false )
  4952.                 return sLine
  4953.             end
  4954.         end
  4955.        
  4956.         term.setCursorBlink( false )
  4957.        
  4958.         return sLine
  4959.     end
  4960.  
  4961.     -- end modified read
  4962.  
  4963.  
  4964.     local function printC(posX,posY,textCol,backCol,text)
  4965.         term.setCursorPos(posX,posY)
  4966.         term.setTextColor(colors[textCol] or textCol)
  4967.         term.setBackgroundColor(colors[backCol] or backCol)
  4968.         term.write(text)
  4969.     end
  4970.  
  4971.     local function InputBox(title)
  4972.         local boxW,boxH = 26,3
  4973.         local termX,termY = term.getSize()
  4974.         local ofsX,ofsY = math.ceil((termX/2) - (boxW/2)) , math.ceil((termY/2) - (boxH/2)) -- offset from top left
  4975.         local options = {"ok","cancel"}
  4976.        
  4977.         local selected = 1
  4978.         local space = 0
  4979.         local range = {}
  4980.         for i = 1,#options do
  4981.             range[i] = {s = space,f = space + string.len(options[i])}
  4982.             space = space + string.len(options[i])+3
  4983.         end
  4984.         local ofC = (boxW/2) - (space/2)
  4985.        
  4986.         local function drawBox()
  4987.             printC(ofsX,ofsY,colors.black,colors.blue,string.rep(" ",boxW))
  4988.             printC(ofsX+1,ofsY,colors.black,colors.blue,(title or "User Input"))
  4989.             printC(ofsX,ofsY+1,colors.black,colors.white,string.rep(" ",boxW))
  4990.             printC(ofsX,ofsY+2,colors.black,colors.white,string.rep(" ",boxW))
  4991.             printC(ofsX,ofsY+3,colors.black,colors.white,string.rep(" ",boxW))
  4992.            
  4993.             for i = 1,#options do
  4994.                 if i == selected then
  4995.                     term.setBackgroundColor(colors.lightGray)
  4996.                     term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)
  4997.                     term.write("["..options[i].."]")
  4998.                     term.setBackgroundColor(colors.white)
  4999.                     term.write(" ")
  5000.                 else
  5001.                     term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)
  5002.                     term.write(" "..options[i].." ")
  5003.                 end
  5004.             end
  5005.            
  5006.             printC(ofsX+2,ofsY+2,colors.black,colors.lightGray,string.rep(" ",boxW-4))
  5007.         end
  5008.         drawBox()
  5009.         term.setCursorPos(ofsX+2,ofsY+2)
  5010.         local co = coroutine.create(function() return readMOD(nil,nil,boxW - 4) end)
  5011.         while true do
  5012.             local event = {os.pullEvent()}
  5013.             if event[1] == "key" or event[1] == "char" then
  5014.                 if event[2] == 28 then
  5015.                     local test,data = coroutine.resume(co,"return")
  5016.                     return data
  5017.                 else
  5018.                     coroutine.resume(co,unpack(event))
  5019.                 end
  5020.             elseif event[1] == "mouse_click" then
  5021.                 if event[4] == ofsY + 3 then
  5022.                     for i = 1,#options do
  5023.                         if event[3] >= range[i].s + ofC + ofsX - 1 and event[3] <= range[i].f + ofC + ofsX then
  5024.                             if options[i] == "ok" then
  5025.                                 local test,data = coroutine.resume(co,"return")
  5026.                                 return data
  5027.                             elseif options[i] == "cancel" then
  5028.                                 return false
  5029.                             end
  5030.                         end
  5031.                     end
  5032.                 end
  5033.             end
  5034.         end
  5035.     end
  5036.  
  5037.     local function dialogBox(title,message,options, h, w)
  5038.         term.setCursorBlink(false)
  5039.         local selected = 1
  5040.         title = title or ""
  5041.         message = message or ""
  5042.         options = options or {}
  5043.         local boxW,boxH = (w or 26), (h or 3)
  5044.         local termX,termY = term.getSize()
  5045.         local ofsX,ofsY = math.ceil((termX/2) - (boxW/2)) , math.ceil((termY/2) - (boxH/2)) -- offset from top left
  5046.        
  5047.         local space = 0
  5048.         local range = {}
  5049.         for i = 1,#options do
  5050.             range[i] = {s = space,f = space + string.len(options[i])}
  5051.             space = space + string.len(options[i])+3
  5052.         end
  5053.         local ofC = math.ceil((boxW/2)) - math.ceil((space/2))
  5054.        
  5055.         local function drawBox()
  5056.             printC(ofsX,ofsY,dialogTitle.txt,dialogTitle.back," "..title..string.rep(" ",boxW-#title-5).."_[]")
  5057.             term.setBackgroundColor(colors.red)
  5058.             term.setTextColor(colors.white)
  5059.             term.write("X")
  5060.             printC(ofsX,ofsY+1,dialogWindo.txt,dialogWindo.back,string.sub(" "..message..string.rep(" ",boxW),1,boxW))
  5061.             term.setCursorPos(ofsX,ofsY+2)
  5062.             term.write(string.rep(" ",boxW))
  5063.             term.setCursorPos(ofsX,ofsY+3)
  5064.             term.write(string.rep(" ",boxW))
  5065.             for i = 1,#options do
  5066.                 if i == selected then
  5067.                     printC(range[i].s + ofC + ofsX - 1,ofsY + 3,"black","lightGray","["..options[i].."]")
  5068.                     term.setBackgroundColor(dialogWindo.back)
  5069.                     term.setTextColor(dialogWindo.txt)
  5070.                     term.write(" ")
  5071.                 else
  5072.                     term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)
  5073.                     term.write(" "..options[i].." ")
  5074.                 end
  5075.             end
  5076.             term.setCursorPos(ofsX + ofC + space,ofsY + 3)
  5077.             term.write(string.rep(" ",boxW - (ofC + space)))
  5078.             term.setBackgroundColor(colors.black)
  5079.             term.setTextColor(colors.white)        
  5080.         end
  5081.         while true do
  5082.             drawBox()
  5083.             event = {os.pullEvent()}
  5084.             if event[1] == "key" then
  5085.                 if event[2] == 203 then -- left
  5086.                     selected = selected - 1
  5087.                     if selected < 1 then
  5088.                         selected = #options
  5089.                     end
  5090.                 elseif event[2] == 205 then -- right
  5091.                     selected = selected + 1
  5092.                     if selected > #options then
  5093.                         selected = 1
  5094.                     end
  5095.                 elseif event[2] == 28 then -- enter
  5096.                     return selected , options[selected]
  5097.                 end
  5098.             elseif event[1] == "mouse_click" then
  5099.                
  5100.                 if bugTest then term.write("M "..event[2].." X "..event[3].." Y "..event[4].."    ") end
  5101.                
  5102.                 if event[2] == 1 then
  5103.                     if event[4] == ofsY + 3 then
  5104.                         for i = 1,#options do
  5105.                             if event[3] >= range[i].s + ofC + ofsX - 1 and event[3] <= range[i].f + ofC + ofsX then
  5106.                                 return i , options[i]
  5107.                             end
  5108.                         end
  5109.                     end
  5110.                 end
  5111.             end
  5112.         end
  5113.     end
  5114.  
  5115.     local flag = true
  5116.     local fSlash = "/"
  5117.     local path = {dir:match("[^/]+")}
  5118.     local function stringPath() -- compacted this a lot
  5119.         return fSlash..table.concat(path,fSlash)
  5120.     end
  5121.  
  5122.     local function osRunSpaces(sFileLocation,...) -- getRunningProgram() ["shell"] = shell
  5123.         clear()
  5124.         if os.newThread then
  5125.             os.newThread(false,...)
  5126.         else
  5127.         local fProg,probblem = loadfile(sFileLocation)
  5128.             if fProg then
  5129.                 local tEnv = {["shell"] = {}}
  5130.                 setmetatable(tEnv.shell,{ __index = shell})
  5131.                 tEnv.shell.getRunningProgram = function()
  5132.                     return sFileLocation
  5133.                 end
  5134.                 setmetatable(tEnv,{ __index = _G})
  5135.                 setfenv(fProg,tEnv)
  5136.                 local test,probblem = pcall(fProg,...)
  5137.                 if not test then
  5138.                     print(probblem)
  5139.                     dialogBox("ERROR",tostring(probblem),{"ok"},3,30)
  5140.                 else
  5141.                     return true
  5142.                 end
  5143.             else
  5144.                 print(probblem)
  5145.                 dialogBox("ERROR",tostring(probblem),{"ok"},3,30)
  5146.             end
  5147.         end
  5148.     end
  5149.  
  5150.     local function rClickMenu(title,tList,tItem,posX,posY)
  5151.  
  5152.         term.setCursorBlink(false)
  5153.         local BoxTitle = title
  5154.         local choices = {}
  5155.         local termX,termY = term.getSize()
  5156.         local offX,offY
  5157.        
  5158.         local width = #BoxTitle + 2
  5159.         local hight
  5160.        
  5161.         for k,v in pairs(tList) do
  5162.             if v ~= nil then
  5163.                 table.insert(choices,k)
  5164.             end
  5165.             if width < #k + 2 then
  5166.                 width = #k + 2
  5167.             end
  5168.         end
  5169.        
  5170.         if #choices == 0 then
  5171.             return
  5172.         end
  5173.        
  5174.         hight = #choices + 1
  5175.         table.sort(choices)
  5176.        
  5177.         offX,offY = math.ceil((termX/2) - (width/2)),math.ceil((termY/2) - (hight/2))
  5178.        
  5179.         if posX and posY then -- offX,offY = posX,posY
  5180.             if posX >= termX - width - 1 then
  5181.                 offX = termX - width - 1
  5182.             else
  5183.                 offX = posX
  5184.             end
  5185.             if posY >= termY - hight then
  5186.                 offY = termY - hight
  5187.             else
  5188.                 offY = posY
  5189.             end
  5190.         end
  5191.        
  5192.         local function reDrawer()
  5193.             printC(offX,offY,rcmTitle.txt,rcmTitle.back," "..BoxTitle..string.rep(" ",width - #BoxTitle - 1))
  5194.             for i = 1,#choices do
  5195.                 printC(offX,offY + i,rcmList.txt,rcmList.back," "..choices[i]..string.rep(" ",width - #choices[i] - 1))
  5196.             end
  5197.         end
  5198.        
  5199.         while true do
  5200.             reDrawer()
  5201.             local event = {os.pullEvent()}
  5202.             if event[1] == "mouse_click" then
  5203.                 if event[2] == 1 then -- event[3] = x event[4] = y
  5204.                     if event[4] > offY and event[4] < hight + offY and event[3] >= offX and event[3] < width + offX then
  5205.                         --dialogBox("ERROR:",type(tList[choices[event[4] - offY]]),{"ok"})
  5206.                         if type(tList[choices[event[4] - offY]]) == "function" then
  5207.                             return tList[choices[event[4] - offY]](tItem)
  5208.                         elseif type(tList[choices[event[4] - offY]]) == "table" then
  5209.                             return rClickMenu("Options",tList[choices[event[4] - offY]],tItem,event[3],event[4])
  5210.                         elseif type(tList[choices[event[4] - offY]]) == "string" then
  5211.                             return osRunSpaces(
  5212.                                     unpack(
  5213.                                         fixArgs(
  5214.                                             tList[choices[event[4] - offY]].." \""..stringPath()..fSlash..tItem.n.."\""
  5215.                                         )
  5216.                                     )
  5217.                                 )
  5218.                         else
  5219.                             dialogBox("ERROR:","somthing up with new rMenu",{"ok"})
  5220.                         end
  5221.                     else
  5222.                         return
  5223.                     end
  5224.                 elseif event[2] == 2 then
  5225.                     return
  5226.                 end
  5227.             end
  5228.         end
  5229.        
  5230.     end
  5231.  
  5232.     local function preferences()
  5233.         local tItem = {
  5234.             {txt = "Title Bar",it = titleBar},
  5235.             {txt = "Address Bar",it = addressBar},
  5236.             {txt = "Item Windo", it = itemWindo},
  5237.             {txt = "Title Right Click Title",it = rcmTitle},
  5238.             {txt = "Right Click Menu",it = rcmList},
  5239.             {txt = "Title Dialog Box",it = dialogTitle},
  5240.             {txt = "Dialog Box",it = dialogWindo},
  5241.             {txt = "Scroll Bar",it = scrollCol}
  5242.         }
  5243.         local topL,topR = 13,5
  5244.         local width,hight = 23,6
  5245.         local bottomL,bottomR = topL + width,topR + hight
  5246.        
  5247.         local listOffset = 0
  5248.         local sel = 1
  5249.         local otherSel = 1
  5250.         local otherItems = {}
  5251.        
  5252.         if tItem[sel] then
  5253.             for k,v in pairs(tItem[sel].it) do
  5254.                 table.insert(otherItems,{txt = k,it = v})
  5255.             end
  5256.         end
  5257.        
  5258.         local function draw()
  5259.             printC(topL,topR,titleBar.txt,titleBar.back,string.sub(" Preferences "..string.rep(" ",width),1,width))
  5260.             for i = 0,12,4 do
  5261.                 for a = 1,4 do
  5262.                     --printC(topL + (a*12)-12 ,topR + ((i+4)/4),4,2^(a+i-1)," "..tostring(2^(a+i-1)))
  5263.                     printC(topL + a-1 ,topR + ((i+4)/4),4,2^(a+i-1)," ")
  5264.                 end
  5265.             end
  5266.             local sSel = " "
  5267.             for i = 1,hight - 2 do
  5268.                 if i == sel - listOffset then
  5269.                     sSel = ">"
  5270.                 end
  5271.                 if tItem[i+listOffset] then
  5272.                     printC(topL + 4 ,topR + i,colors.black,colors.white,string.sub(sSel..tItem[i+listOffset].txt..string.rep(" ",width),1,width - 4))
  5273.                 else
  5274.                     printC(topL + 4 ,topR + i,colors.black,colors.white,sSel..string.rep(" ",width-5))
  5275.                 end
  5276.                 if i == sel - listOffset then
  5277.                     sSel = " "
  5278.                 end
  5279.             end
  5280.             term.setCursorPos(topL,topR + hight - 1)
  5281.             local loop = 1
  5282.             local length = 0
  5283.                 for i = 1,#otherItems do
  5284.                     if otherSel == i then
  5285.                         sSel = ">"
  5286.                     end
  5287.                     if colors.black == otherItems[i].it or colors.gray == otherItems[i].it then
  5288.                         term.setTextColor(colors.white)
  5289.                     else
  5290.                         term.setTextColor(colors.black)
  5291.                     end
  5292.                     term.setBackgroundColor(otherItems[i].it)
  5293.                     term.write(sSel..tostring(otherItems[i].txt).." ")
  5294.                     length = length + #otherItems[i].txt + 2
  5295.                     if otherSel == i then
  5296.                         sSel = " "
  5297.                     end
  5298.                     loop = loop+1
  5299.                 end
  5300.             term.setBackgroundColor(colors.white)
  5301.             term.write(string.rep(" ",width - length))
  5302.         end
  5303.         while true do
  5304.             draw()
  5305.             local event = {os.pullEvent()}
  5306.             if event[1] == "mouse_click" and event[2] == 1 then
  5307.                 if inBouwndry(event[3],event[4],topL,topR,width,hight) then
  5308.                     local inSideX,inSideY = event[3] - topL,event[4] - topR
  5309.                     if inBouwndry(inSideX+1,inSideY,1,1,4,4) and tItem[sel] then
  5310.                         --[[
  5311.                         term.setCursorPos(1,1)
  5312.                         term.setBackgroundColor(2^(inSideX + ((inSideY*4)-4)))
  5313.                         print(2^(inSideX + ((inSideY*4)-4))," ",inSideX + ((inSideY*4)-4),"     ")
  5314.                         ]]--
  5315.                         tItem[sel]["it"][otherItems[otherSel].txt] = (2^(inSideX + ((inSideY*4)-4)))
  5316.                     end
  5317.                 end
  5318.             elseif event[1] == "key" then
  5319.                 if event[2] == 200 then
  5320.                     sel = sel - 1
  5321.                 elseif event[2] == 208 then
  5322.                     sel = sel + 1
  5323.                 elseif event[2] == 203 then
  5324.                     otherSel = otherSel - 1
  5325.                 elseif event[2] == 205 then
  5326.                     otherSel = otherSel + 1
  5327.                 elseif event[2] == 28 then
  5328.                     if dialogBox("Confirm","Save prefrences?",{"Yes","No"}) == 1 then
  5329.                         saveCFG(true)
  5330.                     end
  5331.                     return
  5332.                 end
  5333.             end
  5334.             if sel < 1 then
  5335.                 sel = 1
  5336.             elseif sel > #tItem then
  5337.                 sel = #tItem
  5338.             end
  5339.             if sel > listOffset + hight - 2 then
  5340.                 listOffset = listOffset + 1
  5341.             elseif sel - listOffset < 1 then
  5342.                 listOffset = listOffset - 1
  5343.             end
  5344.            
  5345.             otherItems = {}
  5346.             if tItem[sel] then
  5347.                 for k,v in pairs(tItem[sel].it) do
  5348.                     table.insert(otherItems,{txt = k,it = v})
  5349.                 end
  5350.             end
  5351.            
  5352.             if otherSel < 1 then
  5353.                 otherSel = 1
  5354.             elseif otherSel > #otherItems then
  5355.                 otherSel = #otherItems
  5356.             end
  5357.            
  5358.             if bugTest then
  5359.                 term.setBackgroundColor(colors.black)
  5360.                 term.setTextColor(colors.white)
  5361.                 term.setCursorPos(1,1)
  5362.                 term.clearLine()
  5363.                 term.write("sel "..sel.." offset "..listOffset)
  5364.             end
  5365.         end
  5366.     end
  5367.  
  5368.     local function fileSelect(mode) -- save_file open_file browse < not yet implemented
  5369.        
  5370.         local title = sTitle.." "..ver
  5371.         local bRun = true
  5372.         local clipboard = nil
  5373.         local cut = false
  5374.        
  5375.         local termX,termY = term.getSize()
  5376.         local offsetX,offsetY = 1,1
  5377.         local hight,width = math.ceil(termY-2),math.ceil(termX-2)
  5378.         local oldHight,oldWidth
  5379.        
  5380.         -- offsets
  5381.         local boxOffX,boxOffY = offsetX,offsetY + 2
  5382.         local boxH,boxW = hight - 2 ,width - 2
  5383.        
  5384.         local barX,barY = offsetX + 1,offsetY + 2
  5385.         local barH,barW = 1,width - 1
  5386.        
  5387.         local tbarX,tbarY = offsetX + 1,offsetY + 1
  5388.         local tbarH,tbarW = 1,width - 1
  5389.        
  5390.         local exitX,exitY = offsetX + width - 1 ,offsetY + 1
  5391.        
  5392.         local pading = string.rep(" ",boxW)
  5393.         local list
  5394.        
  5395.         local listOff = 0
  5396.        
  5397.         local sPath
  5398.         local tItemList = {}
  5399.        
  5400.         local function newList()
  5401.             listOff = 0
  5402.             flag = true
  5403.             tItemList = {{n = "..", id = "back"}} -- adds a back item at top of list
  5404.             sPath = stringPath()
  5405.             local folders = {}
  5406.             local files = {}
  5407.             local disks = {}
  5408.             if not fs.exists(sPath) then
  5409.                 path = {}
  5410.                 sPath = stringPath()
  5411.                 dialogBox("ERROR:","Path no longer exists",{"ok"})
  5412.             end
  5413.             local test,list = pcall(fs.list,sPath) -- stopes fs.list crash
  5414.             if list == nil then
  5415.                 list = {}
  5416.                 dialogBox("ERROR : ","fs.list crashed",{"ok"})
  5417.             end
  5418.             if #path == 0 then
  5419.                 for i,v in pairs(rs.getSides()) do
  5420.                     if disk.isPresent(v) then
  5421.                         if disk.hasData(v) then
  5422.                             table.insert(tItemList,{n = disk.getMountPath(v), id = "disk",s = v})
  5423.                             disks[disk.getMountPath(v)] = true
  5424.                         elseif disk.hasAudio(v) then
  5425.                             table.insert(tItemList,{n = disk.getAudioTitle(v), id = "audio",s = v})
  5426.                         end
  5427.                     end
  5428.                 end
  5429.             end
  5430.             for i,v in pairs(list) do
  5431.                 if fs.isDir(sPath..fSlash..v) then
  5432.                     table.insert(folders,v)
  5433.                 else
  5434.                     table.insert(files,v)
  5435.                 end
  5436.             end
  5437.             table.sort(folders)
  5438.             table.sort(files)
  5439.             for i,v in pairs(folders) do
  5440.                 if disks[v] == nil then
  5441.                     table.insert(tItemList,{n = v, id = "folder"})
  5442.                 end
  5443.             end
  5444.             for i,v in pairs(files) do
  5445.                 table.insert(tItemList,{n = v, id = "file"})
  5446.             end
  5447.         end
  5448.        
  5449.         local function paste()
  5450.             if cut then
  5451.                 local s, m = pcall(
  5452.                     function()
  5453.                         fs.move(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash..clipboard[2])
  5454.                         cut = false
  5455.                         clipboard = nil
  5456.                     end)
  5457.                 if not s then
  5458.                     dialogBox("Error", (m or "Couldn't move"), {"ok"}, 4, 30)
  5459.                 end
  5460.                 if bugTest then
  5461.                     local x, y = term.getCursorPos()
  5462.                     term.setCursorPos(1, ({term.getSize()})[2])
  5463.                     write("from "..clipboard[1]..fSlash..clipboard[2].." to "..stringPath()..fSlash..clipboard[2])
  5464.                 end
  5465.             else
  5466.                 local s, m = pcall(function()
  5467.                     if fs.exists(stringPath()..fSlash..clipboard[2]) then
  5468.                         fs.copy(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash.."copy-"..clipboard[2])
  5469.                     else
  5470.                         fs.copy(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash..clipboard[2])
  5471.                     end
  5472.                 end)
  5473.                 if not s then
  5474.                     dialogBox("Error", (m or "Couldn't copy"), {"ok"}, 4, 30)
  5475.                 end
  5476.                 if bugTest then
  5477.                     local x, y = term.getCursorPos()
  5478.                     term.setCursorPos(1, ({term.getSize()})[2])
  5479.                     write("from "..clipboard[1]..fSlash..clipboard[2].." to "..stringPath()..fSlash..clipboard[2])
  5480.                 end
  5481.             end
  5482.             newList()
  5483.         end
  5484.        
  5485.         -- this section bellow handles the right click menu
  5486.        
  5487.         local tmenu = {
  5488.             disk = {
  5489.                 ["Open"] = function(tItem)
  5490.                     table.insert(path,tItem.n)
  5491.                     newList()
  5492.                 end,
  5493.                 ["Copy"] = function(tItem)
  5494.                     clipboard = {stringPath(), tItem.n}
  5495.                     cut = false
  5496.                 end,
  5497.                 ["Eject"] = function(tItem)
  5498.                     if dialogBox("Confirm","Eject "..fSlash..tItem.n.." "..tItem.s,{"yes","no"}) == 1 then
  5499.                         disk.eject(tItem.s)
  5500.                         newList()
  5501.                     end
  5502.                 end,
  5503.                 ["ID label"] = function(tItem)
  5504.                     dialogBox("ID label",disk.getDiskID(tItem.s).." "..tostring(disk.getLabel(tItem.s)),{"ok"})
  5505.                 end,
  5506.                 ["Set label"] = function(tItem)
  5507.                     local name = InputBox("Label?")
  5508.                     if name then
  5509.                         disk.setLabel(tItem.s,name)
  5510.                     end
  5511.                 end,
  5512.                 ["Clear label"] = function(tItem)
  5513.                     if dialogBox("Confirm","Cleal Label from "..tItem.s,{"yes","no"}) == 1 then
  5514.                         disk.setLabel(tItem.s)
  5515.                     end
  5516.                 end
  5517.             },
  5518.             folder = {
  5519.                 ["Open"] = function(temp)
  5520.                     table.insert(path,temp.n)
  5521.                     newList()
  5522.                 end,
  5523.                 ["Copy"] = function(tItem)
  5524.                     clipboard = {stringPath(), tItem.n}
  5525.                     cut = false
  5526.                 end,
  5527.                 ["Cut"] = function(tItem)
  5528.                     clipboard = {stringPath(), tItem.n}
  5529.                     cut = true
  5530.                 end,
  5531.                 ["Delete"] = function(tItem)
  5532.                     if dialogBox("Confirm","Delete "..tItem.id.." "..tItem.n,{"yes","no"}) == 1 then
  5533.                         if fs.isReadOnly(stringPath()..fSlash..tItem.n) then
  5534.                             dialogBox("ERROR",tItem.id.." Is read Only",{"ok"})
  5535.                         else
  5536.                             fs.delete(stringPath()..fSlash..tItem.n)
  5537.                             newList()
  5538.                         end
  5539.                     end
  5540.                 end,
  5541.                 ["Rename"] = function(tItem)
  5542.                     local sName = InputBox("New Name")
  5543.                     if type(sName) == "string" and sName ~= "" then
  5544.                         local s, m = pcall(function()
  5545.                             fs.move(stringPath()..fSlash..tItem.n,stringPath()..fSlash..sName)
  5546.                         end)
  5547.                         if not s then
  5548.                             dialogBox("Error", (m or "Rename failed"), {"ok"})
  5549.                         end
  5550.                     end
  5551.                     newList()
  5552.                 end
  5553.             },
  5554.             file = {
  5555.                 ["Run"] = {
  5556.                     ["Run"] = function(tItem)
  5557.                         osRunSpaces(stringPath()..fSlash..tItem.n)
  5558.                     end,
  5559.                     ["Run CMD"] = function(tItem)
  5560.                         local cmd = InputBox("Commands")
  5561.                         if cmd then
  5562.                             osRunSpaces(stringPath()..fSlash..tItem.n,unpack(fixArgs(cmd)))
  5563.                         end
  5564.                     end,
  5565.                 },
  5566.                 ["Open With"] = customLaunch,
  5567.                 ["Rename"] = function(tItem)
  5568.                     local sName = InputBox("New Name")
  5569.                     if type(sName) == "string" and sName ~= "" then
  5570.                         local s, m = pcall(function()
  5571.                             fs.move(stringPath()..fSlash..tItem.n,stringPath()..fSlash..sName)
  5572.                         end)
  5573.                         if not s then
  5574.                             dialogBox("Error", (m or "Rename failed"), {"ok"})
  5575.                         end
  5576.                     end
  5577.                     newList()
  5578.                 end,
  5579.                 ["Delete"] = function(tItem)
  5580.                     if dialogBox("Confirm","Delete "..tItem.id.." "..tItem.n,{"yes","no"}) == 1 then
  5581.                         if fs.isReadOnly(stringPath()..fSlash..tItem.n) then
  5582.                             dialogBox("ERROR",tItem.id.." Is read Only",{"ok"})
  5583.                         else
  5584.                             fs.delete(stringPath()..fSlash..tItem.n)
  5585.                             newList()
  5586.                         end
  5587.                     end
  5588.                 end,
  5589.                 ["Cut"] = function(tItem)
  5590.                     clipboard = {stringPath(), tItem.n}
  5591.                     cut = true
  5592.                 end,
  5593.                 ["Copy"] = function(tItem)
  5594.                     clipboard = {stringPath(), tItem.n}
  5595.                     cut = false
  5596.                 end
  5597.             },
  5598.             audio = {
  5599.                 ["Play"] = 1,
  5600.                 ["Eject"] = 1
  5601.             },
  5602.             back = {
  5603.             },
  5604.             blank = { -- tmenu.blank.Paste =
  5605.                 ["Paste"] = nil,
  5606.                 ["New File"] = function()
  5607.                     local name = InputBox()
  5608.                     if name then
  5609.                         if fs.exists(stringPath()..fSlash..name) then
  5610.                             dialogBox("ERROR","Name exists",{"ok"})
  5611.                         else
  5612.                             local file = fs.open(stringPath()..fSlash..name,"w")
  5613.                             if file then
  5614.                                 file.write("")
  5615.                                 file.close()
  5616.                                 newList()
  5617.                             else
  5618.                                 dialogBox("ERROR","File not created",{"ok"})
  5619.                             end
  5620.                         end
  5621.                     end
  5622.                 end,
  5623.                 ["New Folder"] = function()
  5624.                     local name = InputBox()
  5625.                     if name then
  5626.                         if fs.exists(stringPath()..fSlash..name) then
  5627.                             dialogBox("ERROR","Name exists",{"ok"})
  5628.                         else
  5629.                             if pcall(fs.makeDir,stringPath()..fSlash..name) then
  5630.                                 newList()
  5631.                             else
  5632.                                 dialogBox("ERROR","Access Denied",{"ok"})
  5633.                             end
  5634.                         end
  5635.                     end
  5636.                 end,
  5637.                 ["Preferences"] = preferences
  5638.             },
  5639.         }
  5640.        
  5641.         -- end right click menu
  5642.        
  5643.         local function scrollBar(posX,posY)
  5644.             if posX == boxOffX+boxW+1 and posY > boxOffY and posY <= boxOffY+boxH then
  5645.                 if #tItemList > boxH then
  5646.                     if posY == boxOffY + 1 then
  5647.                         listOff = 0
  5648.                     elseif posY == boxOffY+boxH then
  5649.                         listOff = #tItemList + 1 - boxH
  5650.                     else
  5651.                         listOff = math.ceil((posY - boxOffY - 1 )*(((#tItemList - boxH+2)/boxH)))
  5652.                     end
  5653.                     flag = true
  5654.                 end
  5655.             end
  5656.         end
  5657.        
  5658.         newList()
  5659.        
  5660.         while bRun do
  5661.             if flag then
  5662.                 flag = false
  5663.                 -- clear
  5664.                 if oldHight ~= hight and oldWidth ~= width then
  5665.                     term.setBackgroundColor(colors.black)
  5666.                     term.clear()
  5667.                     oldHight,oldWidth = hight,width
  5668.                 end
  5669.                 -- draw top title bar
  5670.                 local b = tbarW - #title -2
  5671.                 if b < 0 then
  5672.                     b = 0
  5673.                 end
  5674.                 printC(tbarX,tbarY,titleBar.txt,titleBar.back,string.sub(" "..title,1,tbarW)..string.rep(" ",b))
  5675.                 term.setTextColor(colors.white)
  5676.                 term.setBackgroundColor(colors.red)
  5677.                 term.write("X")
  5678.                
  5679.                 -- draw location bar
  5680.                 local a = barW - #sPath - 1
  5681.                 if a < 0 then
  5682.                     a = 0
  5683.                 end
  5684.                 local tmppath = sPath
  5685.                 if shell and shell.getDisplayName then
  5686.                     tmppath = shell.getDisplayName(sPath)
  5687.                     --dialogBox("yay")
  5688.                 else
  5689.                     --dialogBox("moop")
  5690.                 end
  5691.                 tmppath = tmppath or sPath
  5692.                 local a = barW - #tmppath - 1
  5693.                 if a < 0 then
  5694.                     a = 0
  5695.                 end
  5696.                 printC(barX,barY,addressBar.txt,addressBar.back,string.sub(" "..tmppath,1,barW)..string.rep(" ",a))
  5697.                
  5698.                 -- draw scroll bar
  5699.                 if #tItemList > boxH then
  5700.                     term.setBackgroundColor(scrollCol.back)
  5701.                     for i = 1,boxH do
  5702.                         term.setCursorPos(boxOffX+boxW+1,i + boxOffY)
  5703.                         local scroll = math.floor( boxH* (listOff/(#tItemList-boxH+2)) )+1
  5704.                         if i == scroll then
  5705.                             term.setBackgroundColor(scrollCol.button)
  5706.                             term.write(" ")
  5707.                             term.setBackgroundColor(scrollCol.back)
  5708.                         else
  5709.                             term.write(" ")
  5710.                         end
  5711.                     end
  5712.                 else
  5713.                     term.setBackgroundColor(scrollCol.off)
  5714.                     for i = 1,boxH do
  5715.                         term.setCursorPos(boxOffX+boxW+1,i + boxOffY)
  5716.                         term.write(" ")
  5717.                     end
  5718.                 end
  5719.                
  5720.                 -- draw main section
  5721.  
  5722.                 for i = 1,boxH do -- listOff
  5723.                     local sel = i+listOff
  5724.                     if tItemList[sel] then
  5725.                         printC(1+boxOffX,i+boxOffY,(tIcons[tItemList[sel].id].tCol or itemWindo.txt),(tIcons[tItemList[sel].id].bCol or itemWindo.back),( tIcons[tItemList[sel].id].txt or "   "))
  5726.                         printC(4+boxOffX,i+boxOffY,itemWindo.txt,itemWindo.back,string.sub(" "..tItemList[sel].n..pading,1,boxW-3))
  5727.                     else
  5728.                         printC(1+boxOffX,i+boxOffY,itemWindo.txt,itemWindo.back,pading)
  5729.                     end
  5730.                 end
  5731.                
  5732.                 if bugTest then
  5733.                     printC(1,1,"black","white",listOff.." "..boxOffY.." "..boxH)
  5734.                 end
  5735.                
  5736.             end
  5737.            
  5738.             -- react to events
  5739.             local event = {os.pullEvent()}
  5740.            
  5741.             if event[1] == "mouse_click" then
  5742.                 if inBouwndry(event[3],event[4],boxOffX+1,boxOffY+1,boxW,boxH) then
  5743.                     local selected = tItemList[event[4]+listOff-boxOffY]
  5744.                     if selected and inBouwndry(event[3],event[4],boxOffX+1,event[4],#selected.n + 4,1) then
  5745.                         if event[2] == 1 then -- left mouse
  5746.                             if selected.id == "back" then
  5747.                                 table.remove(path,#path)
  5748.                                 newList()
  5749.                             elseif selected.id == "folder" or selected.id == "disk" then
  5750.                                 table.insert(path,selected.n)
  5751.                                 newList()
  5752.                             elseif selected.id == "file" then
  5753.                                 if dialogBox("Run file ?",selected.n,{"yes","no"}) == 1 then
  5754.                                     osRunSpaces(stringPath()..fSlash..selected.n)
  5755.                                 end
  5756.                             flag = true
  5757.                             end
  5758.                         elseif event[2] == 2 then -- right mouse
  5759.                             rClickMenu("Options",tmenu[selected.id],selected,event[3],event[4])
  5760.                             flag = true
  5761.                         end
  5762.                     elseif event[2] == 2 then -- right clicking not on object
  5763.                         if clipboard then
  5764.                             tmenu.blank.Paste = paste
  5765.                         else
  5766.                             tmenu.blank.Paste = nil
  5767.                         end
  5768.                         rClickMenu("Options",tmenu["blank"],selected,event[3],event[4])
  5769.                         flag = true
  5770.                     end
  5771.                 elseif event[2] == 1 and event[3] == exitX and event[4] == exitY then
  5772.                     if dialogBox("Confirm","Exit application",{"yes","no"}) == 1 then
  5773.                         bRun = false
  5774.                     end
  5775.                     flag = true
  5776.                 elseif event[2] == 1 then
  5777.                     scrollBar(event[3],event[4])
  5778.                 end
  5779.             elseif event[1] == "mouse_scroll" then -- flag this needs new math
  5780.                 local old = listOff
  5781.                 listOff = listOff + event[2]
  5782.                 if listOff < 0 then
  5783.                     listOff = 0
  5784.                 end
  5785.                 if #tItemList + 1 - boxH > 0 and listOff > #tItemList + 1 - boxH then
  5786.                     listOff = #tItemList + 1 - boxH
  5787.                 elseif listOff > 0 and #tItemList + 1 - boxH < 0 then
  5788.                     listOff = 0
  5789.                 end
  5790.                 if listOff ~= old then
  5791.                     flag = true
  5792.                 end
  5793.            
  5794.             elseif event[1] == "mouse_drag" then -- scroll bar
  5795.                 scrollBar(event[3],event[4])
  5796.             elseif event[1] == "disk" or event[1] == "disk_eject" then
  5797.                 newList()
  5798.             elseif event[1] == "window_resize" then
  5799.                 termX,termY = term.getSize()
  5800.                 offsetX,offsetY = 1,1
  5801.                 hight,width = math.ceil(termY-2),math.ceil(termX-2)
  5802.                
  5803.                 boxOffX,boxOffY = offsetX,offsetY + 2
  5804.                 boxH,boxW = hight - 2 ,width - 2
  5805.                
  5806.                 barX,barY = offsetX + 1,offsetY + 2
  5807.                 barH,barW = 1,width - 1
  5808.                
  5809.                 tbarX,tbarY = offsetX + 1,offsetY + 1
  5810.                 tbarH,tbarW = 1,width - 1
  5811.                
  5812.                 exitX,exitY = offsetX + width - 1 ,offsetY + 1
  5813.                 pading = string.rep(" ",boxW)
  5814.                
  5815.                 flag = true
  5816.             elseif event[1] == "redraw" then
  5817.                 flag = true
  5818.             end
  5819.         end
  5820.     end
  5821.  
  5822.     local function main()
  5823.         if term.isColor() then
  5824.             clear()
  5825.             fileSelect()
  5826.             clear()
  5827.         else
  5828.             error("Not an Advanced Computer (gold) ")
  5829.         end
  5830.     end
  5831.  
  5832.     local trash = (norun or main())
  5833.     home()
  5834. end
  5835.  
  5836. function chat()
  5837.     local chatTable = { [1] = "Welcome to uChat V1.2 (/help for commands)" }
  5838.     local chatLine = 1
  5839.     local message = ""
  5840.     local compID = os.computerID()
  5841.     local toID = ""
  5842.     local msgMessage = ""
  5843.     local msgSent = ""
  5844.  
  5845.     function drawLine()
  5846.     term.setCursorPos( 1, 17 )
  5847.     term.clearLine()
  5848.     for n=1,49 do
  5849.     io.write("=")
  5850.     end
  5851.     term.setCursorPos(1,18)
  5852.     term.clearLine()
  5853.     write(username)
  5854.     write(": ")
  5855.     write(message)
  5856.     end
  5857.     function addChat(str)
  5858.     if chatLine < 16 then
  5859.       table.insert(chatTable, str)
  5860.       chatLine = chatLine + 1
  5861.     else
  5862.       for n=1,15 do
  5863.        chatTable[n] = chatTable[n+1]
  5864.       end
  5865.        chatTable[16] = str
  5866.       end
  5867.     end
  5868.     function quit()
  5869.     os.exit()
  5870.     end
  5871.     function showChat()
  5872.     term.setCursorPos( 1, 1 )
  5873.     for n=1,chatLine do
  5874.       term.clearLine()
  5875.       print(chatTable[n])
  5876.     end
  5877.     end
  5878.  
  5879.     -- Opens rednet
  5880.         username = user
  5881.  
  5882.         print("Starting chat...")
  5883.         sleep(1)
  5884.  
  5885.         term.clear()
  5886.         drawLine()
  5887.         rednet.broadcast("")
  5888.         rednet.broadcast(username .. " enters the room!")
  5889.  
  5890.         repeat
  5891.         term.setCursorPos(1,1)
  5892.         write(chatTable[chatLine] or "")
  5893.         drawLine()
  5894.         showChat()
  5895.         term.setCursorPos((3 + string.len(username) + string.len(message)),18)
  5896.         term.setCursorBlink( true )
  5897.  
  5898.         event, param = os.pullEventRaw()
  5899.         if event == "key" then
  5900.           if param == 28 then
  5901.            if string.sub(message,1,1) == "/" then
  5902.                 if string.sub(message,1,6) == "/name " then
  5903.                  if string.len(message) > 6 then
  5904.                   if string.len(message) < 16 then
  5905.                    user = username
  5906.                    username = string.sub(message,7,string.len(message))
  5907.                    message = "User '" .. user .. "' is now called '" .. username .. "'!"
  5908.                    rednet.broadcast("")
  5909.                    rednet.broadcast(message)
  5910.                    addChat(message)
  5911.                    message = ""
  5912.                    drawLine()
  5913.                   else
  5914.                    addChat("<SYS> Name too long! Maximum 9 characters.")
  5915.                    message = ""
  5916.                   end
  5917.                  end
  5918.                 elseif string.sub(message,1,4) == "/me " then
  5919.                  local meMessage = string.sub(message,4,string.len(message))
  5920.                  message = "*" .. username .. meMessage
  5921.                  rednet.broadcast("")
  5922.                  rednet.broadcast(message)
  5923.                  addChat(message)
  5924.                  message = ""
  5925.                  drawLine()
  5926.                 elseif string.sub(message,1,5) == "/list" then
  5927.                  rednet.broadcast("")
  5928.                  rednet.broadcast(message)
  5929.                  message = ""
  5930.                 elseif string.sub(message,1,5) == "/exit" then
  5931.                  addChat("<SYS> Goodbye!")
  5932.                  rednet.broadcast("")
  5933.                  rednet.broadcast("User '" .. username .. "' exits the room.")
  5934.                  sleep(1.0)
  5935.                  term.clear()
  5936.                  term.setCursorPos(1,1)
  5937.                  programs()
  5938.                  break
  5939.                 elseif string.sub(message,1,5) == "/quit" then
  5940.                  addChat("<SYS> Goodbye!")
  5941.                  rednet.broadcast("")
  5942.                  rednet.broadcast("User '" .. username .. "' exits the room.")
  5943.                  sleep(1.0)
  5944.                  term.clear()
  5945.                  term.setCursorPos(1,1)
  5946.                  programs()
  5947.                  break
  5948.                 elseif string.sub(message,1,5) == "/help" then
  5949.                  addChat("/help - lists programs")
  5950.                  addChat("/name <name> - changes username")
  5951.                  addChat("/list - lists connected users, and console IDs")
  5952.                  addChat("/me - used as emote")
  5953.                  addChat("/clear - clears the screen")
  5954.                  addChat("/msg <ID> <message> - sends a private message")
  5955.                  addChat("/exit - exits the program")
  5956.                  message = ""
  5957.                 elseif string.sub(message,1,5) == "/msg " then
  5958.                  if string.len(message) > 5 then
  5959.                   if string.sub(message,7,7) == " " then
  5960.                    toID = string.sub(message,6,6)
  5961.                    msgMessage = string.sub(message,8,string.len(message))
  5962.                    addChat("You whisper to #" .. toID .. ": " .. msgMessage)
  5963.                    message = username .. " whispers to you: " .. msgMessage
  5964.                    toID = tonumber(toID)
  5965.                    rednet.send(toID,"")
  5966.                    rednet.send(toID,message)
  5967.                    message = ""
  5968.                   elseif string.sub(message, 8,8) == " " then
  5969.                    toID = string.sub(message,6,7)
  5970.                    msgMessage = string.sub(message,9,string.len(message))
  5971.                    addChat("You whisper to #" .. toID .. ": " .. msgMessage)
  5972.                    message = username .. " whispers to you: " .. msgMessage
  5973.                    toID = tonumber(toID)
  5974.                    rednet.send(toID,"")
  5975.                    rednet.send(toID,message)
  5976.                    message = ""
  5977.                   elseif string.sub(message, 9,9) == " " then
  5978.                    toID = string.sub(message,6,8)
  5979.                    msgMessage = string.sub(message,10,string.len(message))
  5980.                    addChat("You whisper to #" .. toID .. ": " .. msgMessage)
  5981.                    message = username .. " whispers to you: " .. msgMessage
  5982.                    toID = tonumber(toID)
  5983.                    rednet.send(toID,"")
  5984.                    rednet.send(toID,message)
  5985.                    message = ""
  5986.                   elseif string.sub(message,10,10) == " " then
  5987.                    toID = string.sub(message,6,9)
  5988.                    msgMessage = string.sub(message,11,string.len(message))
  5989.                    addChat("You whisper to #" .. toID .. ": " .. msgMessage)
  5990.                    message = username .. " whispers to you: " .. msgMessage
  5991.                    toID = tonumber(toID)
  5992.                    rednet.send(toID,"")
  5993.                    rednet.send(toID,message)
  5994.                    message = ""
  5995.                   end
  5996.                  end
  5997.                 elseif string.sub(message,1,3) == "/m " then
  5998.                  if string.len(message) > 3 then
  5999.                   if string.sub(message,5,5) == " " then
  6000.                    toID = string.sub(message,4,4)
  6001.                    msgMessage = string.sub(message,6,string.len(message))
  6002.                    addChat("You whisper to #" .. toID .. ": " .. msgMessage)
  6003.                    message = username .. " whispers to you: " .. msgMessage
  6004.                    toID = tonumber(toID)
  6005.                    rednet.send(toID,"")
  6006.                    rednet.send(toID,message)
  6007.                    message = ""
  6008.                   elseif string.sub(message, 6,6) == " " then
  6009.                    toID = string.sub(message,4,5)
  6010.                    msgMessage = string.sub(message,7,string.len(message))
  6011.                    addChat("You whisper to #" .. toID .. ": " .. msgMessage)
  6012.                    message = username .. " whispers to you: " .. msgMessage
  6013.                    toID = tonumber(toID)
  6014.                    rednet.send(toID,"")
  6015.                    rednet.send(toID,message)
  6016.                    message = ""
  6017.                   elseif string.sub(message, 7,7) == " " then
  6018.                    toID = string.sub(message,4,6)
  6019.                    msgMessage = string.sub(message,8,string.len(message))
  6020.                    addChat("You whisper to #" .. toID .. ": " .. msgMessage)
  6021.                    message = username .. " whispers to you: " .. msgMessage
  6022.                    toID = tonumber(toID)
  6023.                    rednet.send(toID,"")
  6024.                    rednet.send(toID,message)
  6025.                    message = ""
  6026.                   elseif string.sub(message,8,8) == " " then
  6027.                    toID = string.sub(message,4,7)
  6028.                    msgMessage = string.sub(message,9,string.len(message))
  6029.                    addChat("You whisper to #" .. toID .. ": " .. msgMessage)
  6030.                    message = username .. " whispers to you: " .. msgMessage
  6031.                    toID = tonumber(toID)
  6032.                    rednet.send(toID,"")
  6033.                    rednet.send(toID,message)
  6034.                    message = ""
  6035.                   end
  6036.                  end
  6037.                 elseif string.sub(message,1,6) == "/clear" then
  6038.                  term.clear()
  6039.                  for n=1,16 do
  6040.                   addChat(" ")
  6041.                  end
  6042.                  chatTable = {}
  6043.                  chatLine = 1
  6044.                  message = ""
  6045.                 else
  6046.                  message = ""
  6047.                 end  
  6048.            else
  6049.                 if string.len(message) > 0 then
  6050.                   username = tostring(username)
  6051.                   message = tostring(message)
  6052.                   message = "<" .. username .. "> " .. message
  6053.                   rednet.broadcast("")
  6054.                   rednet.broadcast(message)
  6055.                   addChat(message)
  6056.                   message = ""
  6057.                   drawLine()
  6058.                 end
  6059.            end
  6060.           elseif param == 14 then
  6061.            message = string.sub(message,1,string.len(message)-1)
  6062.            drawLine()
  6063.           end
  6064.         end
  6065.  
  6066.         if event == "char" then
  6067.           if string.len(message) < 40 then
  6068.                 message = message .. param
  6069.           end
  6070.           drawLine()
  6071.         end
  6072.  
  6073.         if event == "rednet_message" then
  6074.           id, incoming = rednet.receive(0.5)
  6075.  
  6076.           if incoming == "/list" then
  6077.            rednet.send(id,"")
  6078.            rednet.send(id,"User '" .. username .. "' is connected at terminal #" .. compID)
  6079.           else
  6080.            addChat(incoming)
  6081.           end
  6082.         end
  6083.  
  6084.         until message == "override"
  6085. end
  6086.  
  6087. -- Ink (OEED)
  6088. function ink()
  6089.         tArgs = {}
  6090.  
  6091.     if OneOS then
  6092.         --running under OneOS
  6093.         OneOS.ToolBarColour = colours.grey
  6094.         OneOS.ToolBarTextColour = colours.white
  6095.     end
  6096.  
  6097.     local _w, _h = term.getSize()
  6098.  
  6099.     local round = function(num, idp)
  6100.         local mult = 10^(idp or 0)
  6101.         return math.floor(num * mult + 0.5) / mult
  6102.     end
  6103.  
  6104.     UIColours = {
  6105.         Toolbar = colours.grey,
  6106.         ToolbarText = colours.lightGrey,
  6107.         ToolbarSelected = colours.lightBlue,
  6108.         ControlText = colours.white,
  6109.         ToolbarItemTitle = colours.black,
  6110.         Background = colours.lightGrey,
  6111.         MenuBackground = colours.white,
  6112.         MenuText = colours.black,
  6113.         MenuSeparatorText = colours.grey,
  6114.         MenuDisabledText = colours.lightGrey,
  6115.         Shadow = colours.grey,
  6116.         TransparentBackgroundOne = colours.white,
  6117.         TransparentBackgroundTwo = colours.lightGrey,
  6118.         MenuBarActive = colours.white
  6119.     }
  6120.  
  6121.     local getNames = peripheral.getNames or function()
  6122.         local tResults = {}
  6123.         for n,sSide in ipairs( rs.getSides() ) do
  6124.             if peripheral.isPresent( sSide ) then
  6125.                 table.insert( tResults, sSide )
  6126.                 local isWireless = false
  6127.                 if not pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then
  6128.                     isWireless = true
  6129.                 end    
  6130.                 if peripheral.getType( sSide ) == "modem" and not isWireless then
  6131.                     local tRemote = peripheral.call( sSide, "getNamesRemote" )
  6132.                     for n,sName in ipairs( tRemote ) do
  6133.                         table.insert( tResults, sName )
  6134.                     end
  6135.                 end
  6136.             end
  6137.         end
  6138.         return tResults
  6139.     end
  6140.  
  6141.     Peripheral = {
  6142.         GetPeripheral = function(_type)
  6143.             for i, p in ipairs(Peripheral.GetPeripherals()) do
  6144.                 if p.Type == _type then
  6145.                     return p
  6146.                 end
  6147.             end
  6148.         end,
  6149.  
  6150.         Call = function(type, ...)
  6151.             local tArgs = {...}
  6152.             local p = Peripheral.GetPeripheral(type)
  6153.             peripheral.call(p.Side, unpack(tArgs))
  6154.         end,
  6155.  
  6156.         GetPeripherals = function(filterType)
  6157.             local peripherals = {}
  6158.             for i, side in ipairs(getNames()) do
  6159.                 local name = peripheral.getType(side):gsub("^%l", string.upper)
  6160.                 local code = string.upper(side:sub(1,1))
  6161.                 if side:find('_') then
  6162.                     code = side:sub(side:find('_')+1)
  6163.                 end
  6164.  
  6165.                 local dupe = false
  6166.                 for i, v in ipairs(peripherals) do
  6167.                     if v[1] == name .. ' ' .. code then
  6168.                         dupe = true
  6169.                     end
  6170.                 end
  6171.  
  6172.                 if not dupe then
  6173.                     local _type = peripheral.getType(side)
  6174.                     local isWireless = false
  6175.                     if _type == 'modem' then
  6176.                         if not pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then
  6177.                             isWireless = true
  6178.                         end    
  6179.                         if isWireless then
  6180.                             _type = 'wireless_modem'
  6181.                             name = 'W '..name
  6182.                         end
  6183.                     end
  6184.                     if not filterType or _type == filterType then
  6185.                         table.insert(peripherals, {Name = name:sub(1,8) .. ' '..code, Fullname = name .. ' ('..side:sub(1, 1):upper() .. side:sub(2, -1)..')', Side = side, Type = _type, Wireless = isWireless})
  6186.                     end
  6187.                 end
  6188.             end
  6189.             return peripherals
  6190.         end,
  6191.  
  6192.         PresentNamed = function(name)
  6193.             return peripheral.isPresent(name)
  6194.         end,
  6195.  
  6196.         CallType = function(type, ...)
  6197.             local tArgs = {...}
  6198.             local p = GetPeripheral(type)
  6199.             return peripheral.call(p.Side, unpack(tArgs))
  6200.         end,
  6201.  
  6202.         CallNamed = function(name, ...)
  6203.             local tArgs = {...}
  6204.             return peripheral.call(name, unpack(tArgs))
  6205.         end
  6206.     }
  6207.  
  6208.     TextLine = {
  6209.         Text = "",
  6210.         Alignment = AlignmentLeft,
  6211.  
  6212.         Initialise = function(self, text, alignment)
  6213.             local new = {}    -- the new instance
  6214.             setmetatable( new, {__index = self} )
  6215.             new.Text = text
  6216.             new.Alignment = alignment or AlignmentLeft
  6217.             return new
  6218.         end
  6219.     }
  6220.  
  6221.     local StripColours = function(str)
  6222.         return str:gsub('['..string.char(14)..'-'..string.char(29)..']','')
  6223.     end
  6224.  
  6225.     Printer = {
  6226.         Name = nil,
  6227.         PeripheralType = 'printer',
  6228.  
  6229.         paperLevel = function(self)
  6230.             return Peripheral.CallNamed(self.Name, 'getPaperLevel')
  6231.         end,
  6232.  
  6233.         newPage = function(self)
  6234.             return Peripheral.CallNamed(self.Name, 'newPage')
  6235.         end,
  6236.  
  6237.         endPage = function(self)
  6238.             return Peripheral.CallNamed(self.Name, 'endPage')
  6239.         end,
  6240.  
  6241.         pageWrite = function(self, text)
  6242.             return Peripheral.CallNamed(self.Name, 'write', text)
  6243.         end,
  6244.  
  6245.         setPageTitle = function(self, title)
  6246.             return Peripheral.CallNamed(self.Name, 'setPageTitle', title)
  6247.         end,
  6248.  
  6249.         inkLevel = function(self)
  6250.             return Peripheral.CallNamed(self.Name, 'getInkLevel')
  6251.         end,
  6252.  
  6253.         getCursorPos = function(self)
  6254.             return Peripheral.CallNamed(self.Name, 'getCursorPos')
  6255.         end,
  6256.  
  6257.         setCursorPos = function(self, x, y)
  6258.             return Peripheral.CallNamed(self.Name, 'setCursorPos', x, y)
  6259.         end,
  6260.  
  6261.         pageSize = function(self)
  6262.             return Peripheral.CallNamed(self.Name, 'getPageSize')
  6263.         end,
  6264.  
  6265.         Present = function()
  6266.             if Peripheral.GetPeripheral(Printer.PeripheralType) == nil then
  6267.                 return false
  6268.             else
  6269.                 return true
  6270.             end
  6271.         end,
  6272.  
  6273.         PrintLines = function(self, lines, title, copies)
  6274.             local pages = {}
  6275.             local pageLines = {}
  6276.             for i, line in ipairs(lines) do
  6277.                 table.insert(pageLines, TextLine:Initialise(StripColours(line)))
  6278.                 if i % 25 == 0 then
  6279.                     table.insert(pages, pageLines)
  6280.                     pageLines = {}
  6281.                 end
  6282.             end
  6283.             if #pageLines ~= 0 then
  6284.                     table.insert(pages, pageLines)
  6285.             end
  6286.             return self:PrintPages(pages, title, copies)
  6287.         end,
  6288.  
  6289.         PrintPages = function(self, pages, title, copies)
  6290.             copies = copies or 1
  6291.             for c = 1, copies do
  6292.                 for p, page in ipairs(pages) do
  6293.                     if self:paperLevel() < #pages * copies then
  6294.                         return 'Add more paper to the printer'
  6295.                     end
  6296.                     if self:inkLevel() < #pages * copies then
  6297.                         return 'Add more ink to the printer'
  6298.                     end
  6299.                     self:newPage()
  6300.                     for i, line in ipairs(page) do
  6301.                         self:setCursorPos(1, i)
  6302.                         self:pageWrite(StripColours(line.Text))
  6303.                     end
  6304.                     if title then
  6305.                         self:setPageTitle(title)
  6306.                     end
  6307.                     self:endPage()
  6308.                 end
  6309.             end
  6310.         end,
  6311.  
  6312.         Initialise = function(self, name)
  6313.             if Printer.Present() then --fix
  6314.                 local new = {}    -- the new instance
  6315.                 setmetatable( new, {__index = self} )
  6316.                 if name and Peripheral.PresentNamed(name) then
  6317.                     new.Name = name
  6318.                 else
  6319.                     new.Name = Peripheral.GetPeripheral(Printer.PeripheralType).Side
  6320.                 end
  6321.                 return new
  6322.             end
  6323.         end
  6324.     }
  6325.  
  6326.     Clipboard = {
  6327.         Content = nil,
  6328.         Type = nil,
  6329.         IsCut = false,
  6330.  
  6331.         Empty = function()
  6332.             Clipboard.Content = nil
  6333.             Clipboard.Type = nil
  6334.             Clipboard.IsCut = false
  6335.         end,
  6336.  
  6337.         isEmpty = function()
  6338.             return Clipboard.Content == nil
  6339.         end,
  6340.  
  6341.         Copy = function(content, _type)
  6342.             Clipboard.Content = content
  6343.             Clipboard.Type = _type or 'generic'
  6344.             Clipboard.IsCut = false
  6345.         end,
  6346.  
  6347.         Cut = function(content, _type)
  6348.             Clipboard.Content = content
  6349.             Clipboard.Type = _type or 'generic'
  6350.             Clipboard.IsCut = true
  6351.         end,
  6352.  
  6353.         Paste = function()
  6354.             local c, t = Clipboard.Content, Clipboard.Type
  6355.             if Clipboard.IsCut then
  6356.                 Clipboard.Empty()
  6357.             end
  6358.             return c, t
  6359.         end
  6360.     }
  6361.  
  6362.     if OneOS and OneOS.Clipboard then
  6363.         Clipboard = OneOS.Clipboard
  6364.     end
  6365.  
  6366.     Drawing = {
  6367.        
  6368.         Screen = {
  6369.             Width = _w,
  6370.             Height = _h
  6371.         },
  6372.  
  6373.         DrawCharacters = function (x, y, characters, textColour,bgColour)
  6374.             Drawing.WriteStringToBuffer(x, y, characters, textColour, bgColour)
  6375.         end,
  6376.        
  6377.         DrawBlankArea = function (x, y, w, h, colour)
  6378.             Drawing.DrawArea (x, y, w, h, " ", 1, colour)
  6379.         end,
  6380.  
  6381.         DrawArea = function (x, y, w, h, character, textColour, bgColour)
  6382.             --width must be greater than 1, other wise we get a stack overflow
  6383.             if w < 0 then
  6384.                 w = w * -1
  6385.             elseif w == 0 then
  6386.                 w = 1
  6387.             end
  6388.  
  6389.             for ix = 1, w do
  6390.                 local currX = x + ix - 1
  6391.                 for iy = 1, h do
  6392.                     local currY = y + iy - 1
  6393.                     Drawing.WriteToBuffer(currX, currY, character, textColour, bgColour)
  6394.                 end
  6395.             end
  6396.         end,
  6397.  
  6398.         DrawImage = function(_x,_y,tImage, w, h)
  6399.             if tImage then
  6400.                 for y = 1, h do
  6401.                     if not tImage[y] then
  6402.                         break
  6403.                     end
  6404.                     for x = 1, w do
  6405.                         if not tImage[y][x] then
  6406.                             break
  6407.                         end
  6408.                         local bgColour = tImage[y][x]
  6409.                         local textColour = tImage.textcol[y][x] or colours.white
  6410.                         local char = tImage.text[y][x]
  6411.                         Drawing.WriteToBuffer(x+_x-1, y+_y-1, char, textColour, bgColour)
  6412.                     end
  6413.                 end
  6414.             elseif w and h then
  6415.                 Drawing.DrawBlankArea(x, y, w, h, colours.green)
  6416.             end
  6417.         end,
  6418.         --using .nft
  6419.         LoadImage = function(path)
  6420.             local image = {
  6421.                 text = {},
  6422.                 textcol = {}
  6423.             }
  6424.             local fs = fs
  6425.             if OneOS then
  6426.                 fs = OneOS.FS
  6427.             end
  6428.             if fs.exists(path) then
  6429.                 local _open = io.open
  6430.                 if OneOS then
  6431.                     _open = OneOS.IO.open
  6432.                 end
  6433.                 local file = _open(path, "r")
  6434.                 local sLine = file:read()
  6435.                 local num = 1
  6436.                 while sLine do  
  6437.                         table.insert(image, num, {})
  6438.                         table.insert(image.text, num, {})
  6439.                         table.insert(image.textcol, num, {})
  6440.                                                    
  6441.                         --As we're no longer 1-1, we keep track of what index to write to
  6442.                         local writeIndex = 1
  6443.                         --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour
  6444.                         local bgNext, fgNext = false, false
  6445.                         --The current background and foreground colours
  6446.                         local currBG, currFG = nil,nil
  6447.                         for i=1,#sLine do
  6448.                                 local nextChar = string.sub(sLine, i, i)
  6449.                                 if nextChar:byte() == 30 then
  6450.                                     bgNext = true
  6451.                                 elseif nextChar:byte() == 31 then
  6452.                                     fgNext = true
  6453.                                 elseif bgNext then
  6454.                                     currBG = Drawing.GetColour(nextChar)
  6455.                                     bgNext = false
  6456.                                 elseif fgNext then
  6457.                                     currFG = Drawing.GetColour(nextChar)
  6458.                                     fgNext = false
  6459.                                 else
  6460.                                     if nextChar ~= " " and currFG == nil then
  6461.                                            currFG = colours.white
  6462.                                     end
  6463.                                     image[num][writeIndex] = currBG
  6464.                                     image.textcol[num][writeIndex] = currFG
  6465.                                     image.text[num][writeIndex] = nextChar
  6466.                                     writeIndex = writeIndex + 1
  6467.                                 end
  6468.                         end
  6469.                         num = num+1
  6470.                         sLine = file:read()
  6471.                 end
  6472.                 file:close()
  6473.             end
  6474.             return image
  6475.         end,
  6476.  
  6477.         DrawCharactersCenter = function(x, y, w, h, characters, textColour,bgColour)
  6478.             w = w or Drawing.Screen.Width
  6479.             h = h or Drawing.Screen.Height
  6480.             x = x or 0
  6481.             y = y or 0
  6482.             x = math.ceil((w - #characters) / 2) + x
  6483.             y = math.floor(h / 2) + y
  6484.  
  6485.             Drawing.DrawCharacters(x, y, characters, textColour, bgColour)
  6486.         end,
  6487.  
  6488.         GetColour = function(hex)
  6489.             if hex == ' ' then
  6490.                 return colours.transparent
  6491.             end
  6492.             local value = tonumber(hex, 16)
  6493.             if not value then return nil end
  6494.             value = math.pow(2,value)
  6495.             return value
  6496.         end,
  6497.  
  6498.         Clear = function (_colour)
  6499.             _colour = _colour or colours.black
  6500.             Drawing.ClearBuffer()
  6501.             Drawing.DrawBlankArea(1, 1, Drawing.Screen.Width, Drawing.Screen.Height, _colour)
  6502.         end,
  6503.  
  6504.         Buffer = {},
  6505.         BackBuffer = {},
  6506.  
  6507.         DrawBuffer = function()
  6508.             for y,row in pairs(Drawing.Buffer) do
  6509.                 for x,pixel in pairs(row) do
  6510.                     local shouldDraw = true
  6511.                     local hasBackBuffer = true
  6512.                     if Drawing.BackBuffer[y] == nil or Drawing.BackBuffer[y][x] == nil or #Drawing.BackBuffer[y][x] ~= 3 then
  6513.                         hasBackBuffer = false
  6514.                     end
  6515.                     if hasBackBuffer and Drawing.BackBuffer[y][x][1] == Drawing.Buffer[y][x][1] and Drawing.BackBuffer[y][x][2] == Drawing.Buffer[y][x][2] and Drawing.BackBuffer[y][x][3] == Drawing.Buffer[y][x][3] then
  6516.                         shouldDraw = false
  6517.                     end
  6518.                     if shouldDraw then
  6519.                         term.setBackgroundColour(pixel[3])
  6520.                         term.setTextColour(pixel[2])
  6521.                         term.setCursorPos(x, y)
  6522.                         term.write(pixel[1])
  6523.                     end
  6524.                 end
  6525.             end
  6526.             Drawing.BackBuffer = Drawing.Buffer
  6527.             Drawing.Buffer = {}
  6528.             term.setCursorPos(1,1)
  6529.         end,
  6530.  
  6531.         ClearBuffer = function()
  6532.             Drawing.Buffer = {}
  6533.         end,
  6534.  
  6535.         WriteStringToBuffer = function (x, y, characters, textColour,bgColour)
  6536.             for i = 1, #characters do
  6537.                 local character = characters:sub(i,i)
  6538.                 Drawing.WriteToBuffer(x + i - 1, y, character, textColour, bgColour)
  6539.             end
  6540.         end,
  6541.  
  6542.         WriteToBuffer = function(x, y, character, textColour,bgColour)
  6543.             x = round(x)
  6544.             y = round(y)
  6545.             if bgColour == colours.transparent then
  6546.                 Drawing.Buffer[y] = Drawing.Buffer[y] or {}
  6547.                 Drawing.Buffer[y][x] = Drawing.Buffer[y][x] or {"", colours.white, colours.black}
  6548.                 Drawing.Buffer[y][x][1] = character
  6549.                 Drawing.Buffer[y][x][2] = textColour
  6550.             else
  6551.                 Drawing.Buffer[y] = Drawing.Buffer[y] or {}
  6552.                 Drawing.Buffer[y][x] = {character, textColour, bgColour}
  6553.             end
  6554.         end,
  6555.     }
  6556.  
  6557.     Current = {
  6558.         Document = nil,
  6559.         TextInput = nil,
  6560.         CursorPos = {1,1},
  6561.         CursorColour = colours.black,
  6562.         Selection = {8, 36},
  6563.         Window = nil,
  6564.         Modified = false,
  6565.     }
  6566.  
  6567.     local isQuitting = false
  6568.  
  6569.     function OrderSelection()
  6570.         if Current.Selection then
  6571.             if Current.Selection[1] <= Current.Selection[2] then
  6572.                 return Current.Selection
  6573.             else
  6574.                 return {Current.Selection[2], Current.Selection[1]}
  6575.             end
  6576.         end
  6577.     end
  6578.  
  6579.     function StripColours(str)
  6580.         return str:gsub('['..string.char(14)..'-'..string.char(29)..']','')
  6581.     end
  6582.  
  6583.     function FindColours(str)
  6584.         local _, count = str:gsub('['..string.char(14)..'-'..string.char(29)..']','')
  6585.         return count
  6586.     end
  6587.  
  6588.     ColourFromCharacter = function(character)
  6589.         local n = character:byte() - 14
  6590.         if n > 16 then
  6591.             return nil
  6592.         else
  6593.             return 2^n
  6594.         end
  6595.     end
  6596.  
  6597.     CharacterFromColour = function(colour)
  6598.         return string.char(math.floor(math.log(colour)/math.log(2))+14)
  6599.     end
  6600.  
  6601.     Events = {}
  6602.  
  6603.     Button = {
  6604.         X = 1,
  6605.         Y = 1,
  6606.         Width = 0,
  6607.         Height = 0,
  6608.         BackgroundColour = colours.lightGrey,
  6609.         TextColour = colours.white,
  6610.         ActiveBackgroundColour = colours.lightGrey,
  6611.         Text = "",
  6612.         Parent = nil,
  6613.         _Click = nil,
  6614.         Toggle = nil,
  6615.  
  6616.         AbsolutePosition = function(self)
  6617.             return self.Parent:AbsolutePosition()
  6618.         end,
  6619.  
  6620.         Draw = function(self)
  6621.             local bg = self.BackgroundColour
  6622.             local tc = self.TextColour
  6623.             if type(bg) == 'function' then
  6624.                 bg = bg()
  6625.             end
  6626.  
  6627.             if self.Toggle then
  6628.                 tc = UIColours.MenuBarActive
  6629.                 bg = self.ActiveBackgroundColour
  6630.             end
  6631.  
  6632.             local pos = GetAbsolutePosition(self)
  6633.             Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, bg)
  6634.             Drawing.DrawCharactersCenter(pos.X, pos.Y, self.Width, self.Height, self.Text, tc, bg)
  6635.         end,
  6636.  
  6637.         Initialise = function(self, x, y, width, height, backgroundColour, parent, click, text, textColour, toggle, activeBackgroundColour)
  6638.             local new = {}    -- the new instance
  6639.             setmetatable( new, {__index = self} )
  6640.             height = height or 1
  6641.             new.Width = width or #text + 2
  6642.             new.Height = height
  6643.             new.Y = y
  6644.             new.X = x
  6645.             new.Text = text or ""
  6646.             new.BackgroundColour = backgroundColour or colours.lightGrey
  6647.             new.TextColour = textColour or colours.white
  6648.             new.ActiveBackgroundColour = activeBackgroundColour or colours.lightGrey
  6649.             new.Parent = parent
  6650.             new._Click = click
  6651.             new.Toggle = toggle
  6652.             return new
  6653.         end,
  6654.  
  6655.         Click = function(self, side, x, y)
  6656.             if self._Click then
  6657.                 if self:_Click(side, x, y, not self.Toggle) ~= false and self.Toggle ~= nil then
  6658.                     self.Toggle = not self.Toggle
  6659.                     Draw()
  6660.                 end
  6661.                 return true
  6662.             else
  6663.                 return false
  6664.             end
  6665.         end
  6666.     }
  6667.  
  6668.     TextBox = {
  6669.         X = 1,
  6670.         Y = 1,
  6671.         Width = 0,
  6672.         Height = 0,
  6673.         BackgroundColour = colours.lightGrey,
  6674.         TextColour = colours.black,
  6675.         Parent = nil,
  6676.         TextInput = nil,
  6677.         Placeholder = '',
  6678.  
  6679.         AbsolutePosition = function(self)
  6680.             return self.Parent:AbsolutePosition()
  6681.         end,
  6682.  
  6683.         Draw = function(self)      
  6684.             local pos = GetAbsolutePosition(self)
  6685.             Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, self.BackgroundColour)
  6686.             local text = self.TextInput.Value
  6687.             if #tostring(text) > (self.Width - 2) then
  6688.                 text = text:sub(#text-(self.Width - 3))
  6689.                 if Current.TextInput == self.TextInput then
  6690.                     Current.CursorPos = {pos.X + 1 + self.Width-2, pos.Y}
  6691.                 end
  6692.             else
  6693.                 if Current.TextInput == self.TextInput then
  6694.                     Current.CursorPos = {pos.X + 1 + self.TextInput.CursorPos, pos.Y}
  6695.                 end
  6696.             end
  6697.            
  6698.             if #tostring(text) == 0 then
  6699.                 Drawing.DrawCharacters(pos.X + 1, pos.Y, self.Placeholder, colours.lightGrey, self.BackgroundColour)
  6700.             else
  6701.                 Drawing.DrawCharacters(pos.X + 1, pos.Y, text, self.TextColour, self.BackgroundColour)
  6702.             end
  6703.  
  6704.             term.setCursorBlink(true)
  6705.            
  6706.             Current.CursorColour = self.TextColour
  6707.         end,
  6708.  
  6709.         Initialise = function(self, x, y, width, height, parent, text, backgroundColour, textColour, done, numerical)
  6710.             local new = {}    -- the new instance
  6711.             setmetatable( new, {__index = self} )
  6712.             height = height or 1
  6713.             new.Width = width or #text + 2
  6714.             new.Height = height
  6715.             new.Y = y
  6716.             new.X = x
  6717.             new.TextInput = TextInput:Initialise(text or '', function(key)
  6718.                 if done then
  6719.                     done(key)
  6720.                 end
  6721.                 Draw()
  6722.             end, numerical)
  6723.             new.BackgroundColour = backgroundColour or colours.lightGrey
  6724.             new.TextColour = textColour or colours.black
  6725.             new.Parent = parent
  6726.             return new
  6727.         end,
  6728.  
  6729.         Click = function(self, side, x, y)
  6730.             Current.Input = self.TextInput
  6731.             self:Draw()
  6732.         end
  6733.     }
  6734.  
  6735.     TextInput = {
  6736.         Value = "",
  6737.         Change = nil,
  6738.         CursorPos = nil,
  6739.         Numerical = false,
  6740.         IsDocument = nil,
  6741.  
  6742.         Initialise = function(self, value, change, numerical, isDocument)
  6743.             local new = {}    -- the new instance
  6744.             setmetatable( new, {__index = self} )
  6745.             new.Value = tostring(value)
  6746.             new.Change = change
  6747.             new.CursorPos = #tostring(value)
  6748.             new.Numerical = numerical
  6749.             new.IsDocument = isDocument or false
  6750.             return new
  6751.         end,
  6752.  
  6753.         Insert = function(self, str)
  6754.             if self.Numerical then
  6755.                 str = tostring(tonumber(str))
  6756.             end
  6757.  
  6758.             local selection = OrderSelection()
  6759.  
  6760.             if self.IsDocument and selection then
  6761.                 self.Value = string.sub(self.Value, 1, selection[1]-1) .. str .. string.sub( self.Value, selection[2]+2)
  6762.                 self.CursorPos = selection[1]
  6763.                 Current.Selection = nil
  6764.             else
  6765.                 local _, newLineAdjust = string.gsub(self.Value:sub(1, self.CursorPos), '\n','')
  6766.  
  6767.                 self.Value = string.sub(self.Value, 1, self.CursorPos + newLineAdjust) .. str .. string.sub( self.Value, self.CursorPos + 1  + newLineAdjust)
  6768.                 self.CursorPos = self.CursorPos + 1
  6769.             end
  6770.            
  6771.             self.Change(key)
  6772.         end,
  6773.  
  6774.         Extract = function(self, remove)
  6775.             local selection = OrderSelection()
  6776.             if self.IsDocument and selection then
  6777.                 local _, newLineAdjust = string.gsub(self.Value:sub(selection[1], selection[2]), '\n','')
  6778.                 local str = string.sub(self.Value, selection[1], selection[2]+1+newLineAdjust)
  6779.                 if remove then
  6780.                     self.Value = string.sub(self.Value, 1, selection[1]-1) .. string.sub( self.Value, selection[2]+2+newLineAdjust)
  6781.                     self.CursorPos = selection[1] - 1
  6782.                     Current.Selection = nil
  6783.                 end
  6784.                 return str
  6785.             end
  6786.         end,
  6787.  
  6788.         Char = function(self, char)
  6789.             if char == 'nil' then
  6790.                 return
  6791.             end
  6792.             self:Insert(char)
  6793.         end,
  6794.  
  6795.         Key = function(self, key)
  6796.             if key == keys.enter then
  6797.                 if self.IsDocument then
  6798.                     self.Value = string.sub(self.Value, 1, self.CursorPos ) .. '\n' .. string.sub( self.Value, self.CursorPos + 1 )
  6799.                     self.CursorPos = self.CursorPos + 1
  6800.                 end
  6801.                 self.Change(key)       
  6802.             elseif key == keys.left then
  6803.                 -- Left
  6804.                 if self.CursorPos > 0 then
  6805.                     local colShift = FindColours(string.sub( self.Value, self.CursorPos, self.CursorPos))
  6806.                     self.CursorPos = self.CursorPos - 1 - colShift
  6807.                     self.Change(key)
  6808.                 end
  6809.                
  6810.             elseif key == keys.right then
  6811.                 -- Right               
  6812.                 if self.CursorPos < string.len(self.Value) then
  6813.                     local colShift = FindColours(string.sub( self.Value, self.CursorPos+1, self.CursorPos+1))
  6814.                     self.CursorPos = self.CursorPos + 1 + colShift
  6815.                     self.Change(key)
  6816.                 end
  6817.            
  6818.             elseif key == keys.backspace then
  6819.                 -- Backspace
  6820.                 if self.IsDocument and Current.Selection then
  6821.                     self:Extract(true)
  6822.                     self.Change(key)
  6823.                 elseif self.CursorPos > 0 then
  6824.                     local colShift = FindColours(string.sub( self.Value, self.CursorPos, self.CursorPos))
  6825.                     local _, newLineAdjust = string.gsub(self.Value:sub(1, self.CursorPos), '\n','')
  6826.  
  6827.                     self.Value = string.sub( self.Value, 1, self.CursorPos - 1 - colShift + newLineAdjust) .. string.sub( self.Value, self.CursorPos + 1 - colShift + newLineAdjust)
  6828.                     self.CursorPos = self.CursorPos - 1 - colShift
  6829.                     self.Change(key)
  6830.                 end
  6831.             elseif key == keys.home then
  6832.                 -- Home
  6833.                 self.CursorPos = 0
  6834.                 self.Change(key)
  6835.             elseif key == keys.delete then
  6836.                 if self.IsDocument and Current.Selection then
  6837.                     self:Extract(true)
  6838.                     self.Change(key)
  6839.                 elseif self.CursorPos < string.len(self.Value) then
  6840.                     self.Value = string.sub( self.Value, 1, self.CursorPos ) .. string.sub( self.Value, self.CursorPos + 2 )               
  6841.                     self.Change(key)
  6842.                 end
  6843.             elseif key == keys["end"] then
  6844.                 -- End
  6845.                 self.CursorPos = string.len(self.Value)
  6846.                 self.Change(key)
  6847.             elseif key == keys.up and self.IsDocument then
  6848.                 -- Up
  6849.                 if Current.Document.CursorPos then
  6850.                     local page = Current.Document.Pages[Current.Document.CursorPos.Page]
  6851.                     self.CursorPos = page:GetCursorPosFromPoint(Current.Document.CursorPos.Collum + page.MarginX, Current.Document.CursorPos.Line - page.MarginY - 1 + Current.Document.ScrollBar.Scroll, true)
  6852.                     self.Change(key)
  6853.                 end
  6854.             elseif key == keys.down and self.IsDocument then
  6855.                 -- Down
  6856.                 if Current.Document.CursorPos then
  6857.                     local page = Current.Document.Pages[Current.Document.CursorPos.Page]
  6858.                     self.CursorPos = page:GetCursorPosFromPoint(Current.Document.CursorPos.Collum + page.MarginX, Current.Document.CursorPos.Line - page.MarginY + 1 + Current.Document.ScrollBar.Scroll, true)
  6859.                     self.Change(key)
  6860.                 end
  6861.             end
  6862.         end
  6863.     }
  6864.  
  6865.     Menu = {
  6866.         X = 0,
  6867.         Y = 0,
  6868.         Width = 0,
  6869.         Height = 0,
  6870.         Owner = nil,
  6871.         Items = {},
  6872.         RemoveTop = false,
  6873.  
  6874.         Draw = function(self)
  6875.             Drawing.DrawBlankArea(self.X + 1, self.Y + 1, self.Width, self.Height, UIColours.Shadow)
  6876.             if not self.RemoveTop then
  6877.                 Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
  6878.                 for i, item in ipairs(self.Items) do
  6879.                     if item.Separator then
  6880.                         Drawing.DrawArea(self.X, self.Y + i, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
  6881.                     else
  6882.                         local textColour = item.Colour or UIColours.MenuText
  6883.                         if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
  6884.                             textColour = UIColours.MenuDisabledText
  6885.                         end
  6886.                         Drawing.DrawCharacters(self.X + 1, self.Y + i, item.Title, textColour, UIColours.MenuBackground)
  6887.                     end
  6888.                 end
  6889.             else
  6890.                 Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
  6891.                 for i, item in ipairs(self.Items) do
  6892.                     if item.Separator then
  6893.                         Drawing.DrawArea(self.X, self.Y + i - 1, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
  6894.                     else
  6895.                         local textColour = item.Colour or UIColours.MenuText
  6896.                         if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
  6897.                             textColour = UIColours.MenuDisabledText
  6898.                         end
  6899.                         Drawing.DrawCharacters(self.X + 1, self.Y + i - 1, item.Title, textColour, UIColours.MenuBackground)
  6900.  
  6901.                         Drawing.DrawCharacters(self.X - 1 + self.Width-#item.KeyName, self.Y + i - 1, item.KeyName, textColour, UIColours.MenuBackground)
  6902.                     end
  6903.                 end
  6904.             end
  6905.         end,
  6906.  
  6907.         NameForKey = function(self, key)
  6908.             if key == keys.leftCtrl then
  6909.                 return '^'
  6910.             elseif key == keys.tab then
  6911.                 return 'Tab'
  6912.             elseif key == keys.delete then
  6913.                 return 'Delete'
  6914.             elseif key == keys.n then
  6915.                 return 'N'
  6916.             elseif key == keys.a then
  6917.                 return 'A'
  6918.             elseif key == keys.s then
  6919.                 return 'S'
  6920.             elseif key == keys.o then
  6921.                 return 'O'
  6922.             elseif key == keys.z then
  6923.                 return 'Z'
  6924.             elseif key == keys.y then
  6925.                 return 'Y'
  6926.             elseif key == keys.c then
  6927.                 return 'C'
  6928.             elseif key == keys.x then
  6929.                 return 'X'
  6930.             elseif key == keys.v then
  6931.                 return 'V'
  6932.             elseif key == keys.r then
  6933.                 return 'R'
  6934.             elseif key == keys.l then
  6935.                 return 'L'
  6936.             elseif key == keys.t then
  6937.                 return 'T'
  6938.             elseif key == keys.h then
  6939.                 return 'H'
  6940.             elseif key == keys.e then
  6941.                 return 'E'
  6942.             elseif key == keys.p then
  6943.                 return 'P'
  6944.             elseif key == keys.f then
  6945.                 return 'F'
  6946.             elseif key == keys.m then
  6947.                 return 'M'
  6948.             elseif key == keys.q then
  6949.                 return 'Q'
  6950.             else
  6951.                 return '?'     
  6952.             end
  6953.         end,
  6954.  
  6955.         Initialise = function(self, x, y, items, owner, removeTop)
  6956.             local new = {}    -- the new instance
  6957.             setmetatable( new, {__index = self} )
  6958.             if not owner then
  6959.                 return
  6960.             end
  6961.  
  6962.             local keyNames = {}
  6963.  
  6964.             for i, v in ipairs(items) do
  6965.                 items[i].KeyName = ''
  6966.                 if v.Keys then
  6967.                     for _i, key in ipairs(v.Keys) do
  6968.                         items[i].KeyName = items[i].KeyName .. self:NameForKey(key)
  6969.                     end
  6970.                 end
  6971.                 if items[i].KeyName ~= '' then
  6972.                     table.insert(keyNames, items[i].KeyName)
  6973.                 end
  6974.             end
  6975.             local keysLength = LongestString(keyNames)
  6976.             if keysLength > 0 then
  6977.                 keysLength = keysLength + 2
  6978.             end
  6979.  
  6980.             new.Width = LongestString(items, 'Title') + 2 + keysLength
  6981.             if new.Width < 10 then
  6982.                 new.Width = 10
  6983.             end
  6984.             new.Height = #items + 2
  6985.             new.RemoveTop = removeTop or false
  6986.             if removeTop then
  6987.                 new.Height = new.Height - 1
  6988.             end
  6989.            
  6990.             if y < 1 then
  6991.                 y = 1
  6992.             end
  6993.             if x < 1 then
  6994.                 x = 1
  6995.             end
  6996.  
  6997.             if y + new.Height > Drawing.Screen.Height + 1 then
  6998.                 y = Drawing.Screen.Height - new.Height
  6999.             end
  7000.             if x + new.Width > Drawing.Screen.Width + 1 then
  7001.                 x = Drawing.Screen.Width - new.Width
  7002.             end
  7003.  
  7004.  
  7005.             new.Y = y
  7006.             new.X = x
  7007.             new.Items = items
  7008.             new.Owner = owner
  7009.             return new
  7010.         end,
  7011.  
  7012.         New = function(self, x, y, items, owner, removeTop)
  7013.             if Current.Menu and Current.Menu.Owner == owner then
  7014.                 Current.Menu = nil
  7015.                 return
  7016.             end
  7017.  
  7018.             local new = self:Initialise(x, y, items, owner, removeTop)
  7019.             Current.Menu = new
  7020.             return new
  7021.         end,
  7022.  
  7023.         Click = function(self, side, x, y)
  7024.             local i = y-1
  7025.             if self.RemoveTop then
  7026.                 i = y
  7027.             end
  7028.             if i >= 1 and y < self.Height then
  7029.                 if not ((self.Items[i].Enabled and type(self.Items[i].Enabled) == 'function' and self.Items[i].Enabled() == false) or self.Items[i].Enabled == false) and self.Items[i].Click then
  7030.                     self.Items[i]:Click()
  7031.                     if Current.Menu.Owner and Current.Menu.Owner.Toggle then
  7032.                         Current.Menu.Owner.Toggle = false
  7033.                     end
  7034.                     Current.Menu = nil
  7035.                     self = nil
  7036.                 end
  7037.                 return true
  7038.             end
  7039.         end
  7040.     }
  7041.  
  7042.     MenuBar = {
  7043.         X = 1,
  7044.         Y = 1,
  7045.         Width = Drawing.Screen.Width,
  7046.         Height = 1,
  7047.         MenuBarItems = {},
  7048.  
  7049.         AbsolutePosition = function(self)
  7050.             return {X = self.X, Y = self.Y}
  7051.         end,
  7052.  
  7053.         Draw = function(self)
  7054.             --Drawing.DrawArea(self.X - 1, self.Y, 1, self.Height, "|", UIColours.ToolbarText, UIColours.Background)
  7055.  
  7056.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, colours.grey)
  7057.             for i, button in ipairs(self.MenuBarItems) do
  7058.                 button:Draw()
  7059.             end
  7060.         end,
  7061.  
  7062.         Initialise = function(self, items)
  7063.             local new = {}    -- the new instance
  7064.             setmetatable( new, {__index = self} )
  7065.             new.X = 1
  7066.             new.Y = 1
  7067.             new.MenuBarItems = items
  7068.             return new
  7069.         end,
  7070.  
  7071.         AddToolbarItem = function(self, item)
  7072.             table.insert(self.ToolbarItems, item)
  7073.             self:CalculateToolbarItemPositions()
  7074.         end,
  7075.  
  7076.         CalculateToolbarItemPositions = function(self)
  7077.             local currY = 1
  7078.             for i, toolbarItem in ipairs(self.ToolbarItems) do
  7079.                 toolbarItem.Y = currY
  7080.                 currY = currY + toolbarItem.Height
  7081.             end
  7082.         end,
  7083.  
  7084.         Click = function(self, side, x, y)
  7085.             for i, item in ipairs(self.MenuBarItems) do
  7086.                 if item.X <= x and item.X + item.Width > x then
  7087.                     if item:Click(item, side, x - item.X + 1, 1) then
  7088.                         return true
  7089.                     end
  7090.                 end
  7091.             end
  7092.             return false
  7093.         end
  7094.     }
  7095.  
  7096.     TextFormatPlainText = 1
  7097.     TextFormatInkText = 2
  7098.  
  7099.     Document = {
  7100.         X = 1,
  7101.         Y = 1,
  7102.         PageSize = {Width = 25, Height = 21},
  7103.         TextInput = nil,
  7104.         Pages = {},
  7105.         Format = TextFormatPlainText,
  7106.         Title = '',
  7107.         Path = nil,
  7108.         ScrollBar = nil,
  7109.         Lines = {},
  7110.         CursorPos = nil,
  7111.  
  7112.         CalculateLineWrapping = function(self)
  7113.             local limit = self.PageSize.Width
  7114.             local text = self.TextInput.Value
  7115.             local lines = {''}
  7116.             local words = {}
  7117.  
  7118.             for word, space in text:gmatch('(%S+)(%s*)') do
  7119.                 for i = 1, math.ceil(#word/limit) do
  7120.                     local _space = ''
  7121.                     if i == math.ceil(#word/limit) then
  7122.                         _space = space
  7123.                     end
  7124.                     table.insert(words, {word:sub(1+limit*(i-1), limit*i), _space})
  7125.                 end
  7126.             end
  7127.  
  7128.             for i, ws in ipairs(words) do
  7129.                     local word = ws[1]
  7130.                     local space = ws[2]
  7131.                     local temp = lines[#lines] .. word .. space:gsub('\n','')
  7132.                     if #temp > limit then
  7133.                         table.insert(lines, '')
  7134.                     end
  7135.                     if space:find('\n') then
  7136.                         lines[#lines] = lines[#lines] .. word
  7137.                        
  7138.                         space = space:gsub('\n', function()
  7139.                                 table.insert(lines, '')
  7140.                                 return ''
  7141.                         end)
  7142.                     else
  7143.                         lines[#lines] = lines[#lines] .. word .. space
  7144.                     end
  7145.             end
  7146.             return lines
  7147.         end,
  7148.  
  7149.         CalculateCursorPos = function(self)
  7150.             local passedCharacters = 0
  7151.             Current.CursorPos = nil
  7152.             for p, page in ipairs(self.Pages) do
  7153.                 page:Draw()
  7154.                 if not Current.CursorPos then
  7155.                     for i, line in ipairs(page.Lines) do
  7156.                         local relCursor = self.TextInput.CursorPos - FindColours(self.TextInput.Value:sub(1,self.TextInput.CursorPos))
  7157.                         if passedCharacters + #StripColours(line.Text:gsub('\n','')) >= relCursor then
  7158.                             Current.CursorPos = {self.X + page.MarginX + (relCursor - passedCharacters), page.Y + 1 + i}
  7159.                             self.CursorPos = {Page = p, Line = i, Collum = relCursor - passedCharacters - FindColours(self.TextInput.Value:sub(1,self.TextInput.CursorPos-1))}
  7160.                             break
  7161.                         end
  7162.                         passedCharacters = passedCharacters + #StripColours(line.Text:gsub('\n',''))
  7163.                     end
  7164.                 end
  7165.             end
  7166.         end,
  7167.  
  7168.         Draw = function(self)
  7169.             self:CalculatePages()
  7170.             self:CalculateCursorPos()
  7171.             self.ScrollBar:Draw()
  7172.         end,
  7173.  
  7174.         CalculatePages = function(self)
  7175.             self.Pages = {}
  7176.             local lines = self:CalculateLineWrapping()
  7177.             self.Lines = lines
  7178.             local pageLines = {}
  7179.             local totalPageHeight = (3 + self.PageSize.Height + 2 * Page.MarginY)
  7180.             for i, line in ipairs(lines) do
  7181.                 table.insert(pageLines, TextLine:Initialise(line))
  7182.                 if i % self.PageSize.Height == 0 then
  7183.                     table.insert(self.Pages, Page:Initialise(self, pageLines, 3 - self.ScrollBar.Scroll + totalPageHeight*(#self.Pages)))
  7184.                     pageLines = {}
  7185.                 end
  7186.             end
  7187.             if #pageLines ~= 0 then
  7188.                 table.insert(self.Pages, Page:Initialise(self, pageLines, 3 - self.ScrollBar.Scroll + totalPageHeight*(#self.Pages)))
  7189.             end
  7190.  
  7191.             self.ScrollBar.MaxScroll = totalPageHeight*(#self.Pages) - Drawing.Screen.Height + 1
  7192.         end,
  7193.  
  7194.         ScrollToCursor = function(self)
  7195.             self:CalculateCursorPos()
  7196.             if Current.CursorPos and
  7197.                 (Current.CursorPos[2] > Drawing.Screen.Height
  7198.                 or Current.CursorPos[2] < 2) then
  7199.                 self.ScrollBar:DoScroll(Current.CursorPos[2] - Drawing.Screen.Height)
  7200.             end
  7201.         end,
  7202.  
  7203.         SetSelectionColour = function(self, colour)
  7204.             local selection = OrderSelection()
  7205.             local text = self.TextInput:Extract(true)
  7206.             local colChar = CharacterFromColour(colour)
  7207.             local precedingColour = ''
  7208.             if FindColours(self.TextInput.Value:sub(self.TextInput.CursorPos+1, self.TextInput.CursorPos+1)) == 0 then
  7209.                 for i = 1, self.TextInput.CursorPos do
  7210.                     local c = self.TextInput.Value:sub(self.TextInput.CursorPos - i,self.TextInput.CursorPos - i)
  7211.                     if FindColours(c) == 1 then
  7212.                         precedingColour = c
  7213.                         break
  7214.                     end
  7215.                 end
  7216.                 if precedingColour == '' then
  7217.                     precedingColour = CharacterFromColour(colours.black)
  7218.                 end
  7219.             end
  7220.  
  7221.             self.TextInput:Insert(colChar..StripColours(text)..precedingColour)
  7222.             --text = text:gsub('['..string.char(14)..'-'..string.char(29)..']','')
  7223.         end,
  7224.  
  7225.         Initialise = function(self, text, title, path)
  7226.             local new = {}    -- the new instance
  7227.             setmetatable( new, {__index = self} )
  7228.             new.Title = title or 'New Document'
  7229.             new.Path = path
  7230.             new.X = (Drawing.Screen.Width - (new.PageSize.Width + 2*(Page.MarginX)))/2
  7231.             new.Y = 2
  7232.             new.TextInput = TextInput:Initialise(text, function()
  7233.                 new:ScrollToCursor()
  7234.                 Current.Modified = true
  7235.                 Draw()
  7236.             end, false, true)
  7237.             new.ScrollBar = ScrollBar:Initialise(Drawing.Screen.Width, new.Y, Drawing.Screen.Height-1, 0, nil, nil, nil, function()end)
  7238.             Current.TextInput = new.TextInput
  7239.             Current.ScrollBar = new.ScrollBar
  7240.             return new
  7241.         end
  7242.     }
  7243.  
  7244.     ScrollBar = {
  7245.         X = 1,
  7246.         Y = 1,
  7247.         Width = 1,
  7248.         Height = 1,
  7249.         BackgroundColour = colours.grey,
  7250.         BarColour = colours.lightBlue,
  7251.         Parent = nil,
  7252.         Change = nil,
  7253.         Scroll = 0,
  7254.         MaxScroll = 0,
  7255.         ClickPoint = nil,
  7256.  
  7257.         AbsolutePosition = function(self)
  7258.             return self.Parent:AbsolutePosition()
  7259.         end,
  7260.  
  7261.         Draw = function(self)
  7262.             local pos = GetAbsolutePosition(self)
  7263.             local barHeight = self.Height - self.MaxScroll
  7264.             if barHeight < 3 then
  7265.               barHeight = 3
  7266.             end
  7267.             local percentage = (self.Scroll/self.MaxScroll)
  7268.  
  7269.             Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, self.BackgroundColour)
  7270.             Drawing.DrawBlankArea(pos.X, pos.Y + round(self.Height*percentage - barHeight*percentage), self.Width, barHeight, self.BarColour)
  7271.         end,
  7272.  
  7273.         Initialise = function(self, x, y, height, maxScroll, backgroundColour, barColour, parent, change)
  7274.             local new = {}    -- the new instance
  7275.             setmetatable( new, {__index = self} )
  7276.             new.Width = 1
  7277.             new.Height = height
  7278.             new.Y = y
  7279.             new.X = x
  7280.             new.BackgroundColour = backgroundColour or colours.grey
  7281.             new.BarColour = barColour or colours.lightBlue
  7282.             new.Parent = parent
  7283.             new.Change = change or function()end
  7284.             new.MaxScroll = maxScroll
  7285.             new.Scroll = 0
  7286.             return new
  7287.         end,
  7288.  
  7289.         DoScroll = function(self, amount)
  7290.             amount = round(amount)
  7291.             if self.Scroll < 0 or self.Scroll > self.MaxScroll then
  7292.                 return false
  7293.             end
  7294.             self.Scroll = self.Scroll + amount
  7295.             if self.Scroll < 0 then
  7296.                 self.Scroll = 0
  7297.             elseif self.Scroll > self.MaxScroll then
  7298.                 self.Scroll = self.MaxScroll
  7299.             end
  7300.             self.Change()
  7301.             return true
  7302.         end,
  7303.  
  7304.         Click = function(self, side, x, y, drag)
  7305.             local percentage = (self.Scroll/self.MaxScroll)
  7306.             local barHeight = (self.Height - self.MaxScroll)
  7307.             if barHeight < 3 then
  7308.                 barHeight = 3
  7309.             end
  7310.             local relScroll = (self.MaxScroll*(y + barHeight*percentage)/self.Height)
  7311.             if not drag then
  7312.                 self.ClickPoint = self.Scroll - relScroll + 1
  7313.             end
  7314.  
  7315.             if self.Scroll-1 ~= relScroll then
  7316.                 self:DoScroll(relScroll-self.Scroll-1 + self.ClickPoint)
  7317.             end
  7318.             return true
  7319.         end
  7320.     }
  7321.  
  7322.     AlignmentLeft = 1
  7323.     AlignmentCentre = 2
  7324.     AlignmentRight = 3
  7325.  
  7326.     TextLine = {
  7327.         Text = "",
  7328.         Alignment = AlignmentLeft,
  7329.  
  7330.         Initialise = function(self, text, alignment)
  7331.             local new = {}    -- the new instance
  7332.             setmetatable( new, {__index = self} )
  7333.             new.Text = text
  7334.             new.Alignment = alignment or AlignmentLeft
  7335.             return new
  7336.         end
  7337.     }
  7338.  
  7339.     local clickPos = 1
  7340.     Page = {
  7341.         X = 1,
  7342.         Y = 1,
  7343.         Width = 1,
  7344.         Height = 1,
  7345.         MarginX = 3,
  7346.         MarginY = 2,
  7347.         BackgroundColour = colours.white,
  7348.         TextColour = colours.white,
  7349.         ActiveBackgroundColour = colours.lightGrey,
  7350.         Lines = {},
  7351.         Parent = nil,
  7352.  
  7353.         AbsolutePosition = function(self)
  7354.             return self.Parent:AbsolutePosition()
  7355.         end,
  7356.  
  7357.         Draw = function(self)
  7358.             local pos = GetAbsolutePosition(self)
  7359.  
  7360.             if pos.Y > Drawing.Screen.Height or pos.Y + self.Height < 1 then
  7361.                 return
  7362.             end
  7363.  
  7364.             Drawing.DrawBlankArea(pos.X+self.Width,pos.Y -1 + 1, 1, self.Height, UIColours.Shadow)
  7365.             Drawing.DrawBlankArea(pos.X+1, pos.Y -1 + self.Height, self.Width, 1, UIColours.Shadow)
  7366.             Drawing.DrawBlankArea(pos.X, pos.Y -1, self.Width, self.Height, self.BackgroundColour)
  7367.  
  7368.             local textColour = self.TextColour
  7369.             if not Current.Selection then
  7370.                 for i, line in ipairs(self.Lines) do
  7371.                     local _c = 1
  7372.                     for c = 1, #line.Text do
  7373.                         local col = ColourFromCharacter(line.Text:sub(c,c))
  7374.                         if col then
  7375.                             textColour = col
  7376.                         else
  7377.                             Drawing.WriteToBuffer(pos.X + self.MarginX - 1 + _c, pos.Y -2 + i + self.MarginY, line.Text:sub(c,c), textColour, self.BackgroundColour)
  7378.                             _c = _c + 1
  7379.                         end
  7380.                     end
  7381.                 end
  7382.             else
  7383.                 local selection = OrderSelection()
  7384.                 local char = 1
  7385.                 local textColour = self.TextColour
  7386.                 for i, line in ipairs(self.Lines) do
  7387.                     local _c = 1
  7388.                     for c = 1, #line.Text do
  7389.                         local col = ColourFromCharacter(line.Text:sub(c,c))
  7390.                         if col then
  7391.                             textColour = col
  7392.                         else
  7393.                             local tc = textColour
  7394.                             local colour = colours.white
  7395.                             if char >= selection[1] and char <= selection[2] then
  7396.                                 colour = colours.lightBlue
  7397.                                 tc = colours.white
  7398.                             end
  7399.  
  7400.                             Drawing.WriteToBuffer(pos.X + self.MarginX - 1 + _c, pos.Y -2 + i + self.MarginY, line.Text:sub(c,c), tc, colour)
  7401.                             _c = _c + 1
  7402.                         end
  7403.                         char = char + 1
  7404.                     end
  7405.                 end
  7406.             end
  7407.         end,
  7408.  
  7409.         Initialise = function(self, parent, lines, y)
  7410.             local new = {}    -- the new instanc
  7411.             setmetatable( new, {__index = self} )
  7412.             new.Height = parent.PageSize.Height + 2 * self.MarginY
  7413.             new.Width = parent.PageSize.Width + 2 * self.MarginX
  7414.             new.X = 1
  7415.             new.Y = y or 1
  7416.             new.Lines = lines or {}
  7417.             new.BackgroundColour = colours.white
  7418.             new.TextColour = colours.black
  7419.             new.Parent = parent
  7420.             new.ClickPos = 1
  7421.             return new
  7422.         end,
  7423.  
  7424.         GetCursorPosFromPoint = function(self, x, y, rel)
  7425.             local pos = GetAbsolutePosition(self)
  7426.             if rel then
  7427.                 pos = {Y = 0, X = 0}
  7428.             end
  7429.             local row = y - pos.Y + self.MarginY - self.Parent.ScrollBar.Scroll
  7430.             local col = x - self.MarginX - pos.X + 1
  7431.             local cursorPos = 0
  7432.             if row <= 0 or col <= 0 then
  7433.                 return 0
  7434.             end
  7435.  
  7436.             if row > #self.Lines then
  7437.                 for i, v in ipairs(self.Lines) do
  7438.                     cursorPos = cursorPos + #v.Text-- - FindColours(v.Text)
  7439.                 end
  7440.                 return cursorPos
  7441.             end
  7442.  
  7443.             --term.setCursorPos(1,3)
  7444.             local prevLineCount = 0
  7445.             for i, v in ipairs(self.Lines) do
  7446.                 if i == row then
  7447.                     if col > #v.Text then
  7448.                         col = #v.Text-- + FindColours(v.Text)
  7449.                     else
  7450.                         col = col + FindColours(v.Text:sub(1, col))
  7451.                     end
  7452.                     --term.setCursorPos(1,2)
  7453.                     --print(prevLineCount)
  7454.                     cursorPos = cursorPos + col + 2 - i - prevLineCount
  7455.                     break
  7456.                 else
  7457.                     prevLineCount = FindColours(v.Text)
  7458.                     if prevLineCount ~= 0 then
  7459.                         prevLineCount = prevLineCount
  7460.                     end
  7461.                     cursorPos = cursorPos + #v.Text + 2 - i + FindColours(v.Text)
  7462.                 end
  7463.             end
  7464.  
  7465.             return cursorPos - 2
  7466.         end,
  7467.  
  7468.         Click = function(self, side, x, y, drag)
  7469.             local cursorPos = self:GetCursorPosFromPoint(x, y)
  7470.             self.Parent.TextInput.CursorPos = cursorPos
  7471.             if drag == nil then
  7472.                 Current.Selection = nil
  7473.                 clickPos = x
  7474.             else
  7475.                 local relCursor = cursorPos-- - FindColours(self.Parent.TextInput.Value:sub(1,cursorPos)) + 1
  7476.                 if not Current.Selection then
  7477.                     local adder = 1
  7478.                     if clickPos and clickPos < x then
  7479.                         adder = 0
  7480.                     end
  7481.                     Current.Selection = {relCursor + adder, relCursor + 1 + adder}
  7482.                 else
  7483.                     Current.Selection[2] = relCursor + 1
  7484.                 end
  7485.             end
  7486.             Draw()
  7487.             return true
  7488.         end
  7489.     }
  7490.  
  7491.     function GetAbsolutePosition(object)
  7492.         local obj = object
  7493.         local i = 0
  7494.         local x = 1
  7495.         local y = 1
  7496.         while true do
  7497.             x = x + obj.X - 1
  7498.             y = y + obj.Y - 1
  7499.  
  7500.             if not obj.Parent then
  7501.                 return {X = x, Y = y}
  7502.             end
  7503.  
  7504.             obj = obj.Parent
  7505.  
  7506.             if i > 32 then
  7507.                 return {X = 1, Y = 1}
  7508.             end
  7509.  
  7510.             i = i + 1
  7511.         end
  7512.  
  7513.     end
  7514.  
  7515.     function Draw()
  7516.         if not Current.Window then
  7517.             Drawing.Clear(colours.lightGrey)
  7518.         else
  7519.             Drawing.DrawArea(1, 2, Drawing.Screen.Width, Drawing.Screen.Height, '|', colours.black, colours.lightGrey)
  7520.         end
  7521.  
  7522.         if Current.Document then
  7523.             Current.Document:Draw()
  7524.         end
  7525.  
  7526.         Current.MenuBar:Draw()
  7527.  
  7528.         if Current.Window then
  7529.             Current.Window:Draw()
  7530.         end
  7531.  
  7532.         if Current.Menu then
  7533.             Current.Menu:Draw()
  7534.         end
  7535.  
  7536.         Drawing.DrawBuffer()
  7537.  
  7538.         if Current.TextInput and Current.CursorPos and not Current.Menu and not(Current.Window and Current.Document and Current.TextInput == Current.Document.TextInput) and Current.CursorPos[2] > 1 then
  7539.             term.setCursorPos(Current.CursorPos[1], Current.CursorPos[2])
  7540.             term.setCursorBlink(true)
  7541.             term.setTextColour(Current.CursorColour)
  7542.         else
  7543.             term.setCursorBlink(false)
  7544.         end
  7545.     end
  7546.     MainDraw = Draw
  7547.  
  7548.     LongestString = function(input, key)
  7549.         local length = 0
  7550.         for i = 1, #input do
  7551.             local value = input[i]
  7552.             if key then
  7553.                 if value[key] then
  7554.                     value = value[key]
  7555.                 else
  7556.                     value = ''
  7557.                 end
  7558.             end
  7559.             local titleLength = string.len(value)
  7560.             if titleLength > length then
  7561.                 length = titleLength
  7562.             end
  7563.         end
  7564.         return length
  7565.     end
  7566.  
  7567.     function LoadMenuBar()
  7568.         Current.MenuBar = MenuBar:Initialise({
  7569.             Button:Initialise(1, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
  7570.                 if toggle then
  7571.                     Menu:New(1, 2, {
  7572.                         {
  7573.                             Title = "New...",
  7574.                             Click = function()
  7575.                                 Current.Document = Document:Initialise('')                         
  7576.                             end,
  7577.                             Keys = {
  7578.                                 keys.leftCtrl,
  7579.                                 keys.n
  7580.                             }
  7581.                         },
  7582.                         {
  7583.                             Title = 'Open...',
  7584.                             Click = function()
  7585.                                 DisplayOpenDocumentWindow()
  7586.                             end,
  7587.                             Keys = {
  7588.                                 keys.leftCtrl,
  7589.                                 keys.o
  7590.                             }
  7591.                         },
  7592.                         {
  7593.                             Separator = true
  7594.                         },
  7595.                         {
  7596.                             Title = 'Save...',
  7597.                             Click = function()
  7598.                                 SaveDocument()
  7599.                             end,
  7600.                             Keys = {
  7601.                                 keys.leftCtrl,
  7602.                                 keys.s
  7603.                             },
  7604.                             Enabled = function()
  7605.                                 return true
  7606.                             end
  7607.                         },
  7608.                         {
  7609.                             Separator = true
  7610.                         },
  7611.                         {
  7612.                             Title = 'Print...',
  7613.                             Click = function()
  7614.                                 PrintDocument()
  7615.                             end,
  7616.                             Keys = {
  7617.                                 keys.leftCtrl,
  7618.                                 keys.p
  7619.                             },
  7620.                             Enabled = function()
  7621.                                 return true
  7622.                             end
  7623.                         },
  7624.                         {
  7625.                             Separator = true
  7626.                         },
  7627.                         {
  7628.                             Title = 'Quit',
  7629.                             Click = function()
  7630.                                 Close()
  7631.                             end
  7632.                         },
  7633.                 --[[
  7634.                         {
  7635.                             Title = 'Save As...',
  7636.                             Click = function()
  7637.  
  7638.                             end
  7639.                         }  
  7640.                 ]]--
  7641.                     }, self, true)
  7642.                 else
  7643.                     Current.Menu = nil
  7644.                 end
  7645.                 return true
  7646.             end, 'File', colours.lightGrey, false),
  7647.             Button:Initialise(7, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
  7648.                 if not self.Toggle then
  7649.                     Menu:New(7, 2, {
  7650.                 --[[
  7651.                         {
  7652.                             Title = "Undo",
  7653.                             Click = function()
  7654.                             end,
  7655.                             Keys = {
  7656.                                 keys.leftCtrl,
  7657.                                 keys.z
  7658.                             },
  7659.                             Enabled = function()
  7660.                                 return false
  7661.                             end
  7662.                         },
  7663.                         {
  7664.                             Title = 'Redo',
  7665.                             Click = function()
  7666.                                
  7667.                             end,
  7668.                             Keys = {
  7669.                                 keys.leftCtrl,
  7670.                                 keys.y
  7671.                             },
  7672.                             Enabled = function()
  7673.                                 return false
  7674.                             end
  7675.                         },
  7676.                         {
  7677.                             Separator = true
  7678.                         },
  7679.                 ]]--
  7680.                         {
  7681.                             Title = 'Cut',
  7682.                             Click = function()
  7683.                                 Clipboard.Cut(Current.Document.TextInput:Extract(true), 'text')
  7684.                             end,
  7685.                             Keys = {
  7686.                                 keys.leftCtrl,
  7687.                                 keys.x
  7688.                             },
  7689.                             Enabled = function()
  7690.                                 return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
  7691.                             end
  7692.                         },
  7693.                         {
  7694.                             Title = 'Copy',
  7695.                             Click = function()
  7696.                                 Clipboard.Copy(Current.Document.TextInput:Extract(), 'text')
  7697.                             end,
  7698.                             Keys = {
  7699.                                 keys.leftCtrl,
  7700.                                 keys.c
  7701.                             },
  7702.                             Enabled = function()
  7703.                                 return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
  7704.                             end
  7705.                         },
  7706.                         {
  7707.                             Title = 'Paste',
  7708.                             Click = function()
  7709.                                 local paste = Clipboard.Paste()
  7710.                                 Current.Document.TextInput:Insert(paste)
  7711.                                 Current.Document.TextInput.CursorPos = Current.Document.TextInput.CursorPos + #paste - 1
  7712.                             end,
  7713.                             Keys = {
  7714.                                 keys.leftCtrl,
  7715.                                 keys.v
  7716.                             },
  7717.                             Enabled = function()
  7718.                                 return Current.Document ~= nil and (not Clipboard.isEmpty()) and Clipboard.Type == 'text'
  7719.                             end
  7720.                         },
  7721.                         {
  7722.                             Separator = true,  
  7723.                         },
  7724.                         {
  7725.                             Title = 'Select All',
  7726.                             Click = function()
  7727.                                 Current.Selection = {1, #Current.Document.TextInput.Value:gsub('\n','')}
  7728.                             end,
  7729.                             Keys = {
  7730.                                 keys.leftCtrl,
  7731.                                 keys.a
  7732.                             },
  7733.                             Enabled = function()
  7734.                                 return Current.Document ~= nil
  7735.                             end
  7736.                         }
  7737.                     }, self, true)
  7738.                 else
  7739.                     Current.Menu = nil
  7740.                 end
  7741.                 return true
  7742.             end, 'Edit', colours.lightGrey, false)
  7743.         })
  7744.     end
  7745.  
  7746.     function LoadMenuBar()
  7747.         Current.MenuBar = MenuBar:Initialise({
  7748.             Button:Initialise(1, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
  7749.                 if toggle then
  7750.                     Menu:New(1, 2, {
  7751.                         {
  7752.                             Title = "New...",
  7753.                             Click = function()
  7754.                                 Current.Document = Document:Initialise('')                         
  7755.                             end,
  7756.                             Keys = {
  7757.                                 keys.leftCtrl,
  7758.                                 keys.n
  7759.                             }
  7760.                         },
  7761.                         {
  7762.                             Title = 'Open...',
  7763.                             Click = function()
  7764.                                 DisplayOpenDocumentWindow()
  7765.                             end,
  7766.                             Keys = {
  7767.                                 keys.leftCtrl,
  7768.                                 keys.o
  7769.                             }
  7770.                         },
  7771.                         {
  7772.                             Separator = true
  7773.                         },
  7774.                         {
  7775.                             Title = 'Save...',
  7776.                             Click = function()
  7777.                                 SaveDocument()
  7778.                             end,
  7779.                             Keys = {
  7780.                                 keys.leftCtrl,
  7781.                                 keys.s
  7782.                             },
  7783.                             Enabled = function()
  7784.                                 return Current.Document ~= nil
  7785.                             end
  7786.                         },
  7787.                         {
  7788.                             Separator = true
  7789.                         },
  7790.                         {
  7791.                             Title = 'Print...',
  7792.                             Click = function()
  7793.                                 PrintDocument()
  7794.                             end,
  7795.                             Keys = {
  7796.                                 keys.leftCtrl,
  7797.                                 keys.p
  7798.                             },
  7799.                             Enabled = function()
  7800.                                 return true
  7801.                             end
  7802.                         },
  7803.                         {
  7804.                             Separator = true
  7805.                         },
  7806.                         {
  7807.                             Title = 'Quit',
  7808.                             Click = function()
  7809.                                 if Close() and OneOS then
  7810.                                     OneOS.Close()
  7811.                                 end
  7812.                             end,
  7813.                             Keys = {
  7814.                                 keys.leftCtrl,
  7815.                                 keys.q
  7816.                             }
  7817.                         },
  7818.                 --[[
  7819.                         {
  7820.                             Title = 'Save As...',
  7821.                             Click = function()
  7822.  
  7823.                             end
  7824.                         }  
  7825.                 ]]--
  7826.                     }, self, true)
  7827.                 else
  7828.                     Current.Menu = nil
  7829.                 end
  7830.                 return true
  7831.             end, 'File', colours.lightGrey, false),
  7832.             Button:Initialise(7, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
  7833.                 if not self.Toggle then
  7834.                     Menu:New(7, 2, {
  7835.                 --[[
  7836.                         {
  7837.                             Title = "Undo",
  7838.                             Click = function()
  7839.                             end,
  7840.                             Keys = {
  7841.                                 keys.leftCtrl,
  7842.                                 keys.z
  7843.                             },
  7844.                             Enabled = function()
  7845.                                 return false
  7846.                             end
  7847.                         },
  7848.                         {
  7849.                             Title = 'Redo',
  7850.                             Click = function()
  7851.                                
  7852.                             end,
  7853.                             Keys = {
  7854.                                 keys.leftCtrl,
  7855.                                 keys.y
  7856.                             },
  7857.                             Enabled = function()
  7858.                                 return false
  7859.                             end
  7860.                         },
  7861.                         {
  7862.                             Separator = true
  7863.                         },
  7864.                 ]]--
  7865.                         {
  7866.                             Title = 'Cut',
  7867.                             Click = function()
  7868.                                 Clipboard.Cut(Current.Document.TextInput:Extract(true), 'text')
  7869.                             end,
  7870.                             Keys = {
  7871.                                 keys.leftCtrl,
  7872.                                 keys.x
  7873.                             },
  7874.                             Enabled = function()
  7875.                                 return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
  7876.                             end
  7877.                         },
  7878.                         {
  7879.                             Title = 'Copy',
  7880.                             Click = function()
  7881.                                 Clipboard.Copy(Current.Document.TextInput:Extract(), 'text')
  7882.                             end,
  7883.                             Keys = {
  7884.                                 keys.leftCtrl,
  7885.                                 keys.c
  7886.                             },
  7887.                             Enabled = function()
  7888.                                 return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
  7889.                             end
  7890.                         },
  7891.                         {
  7892.                             Title = 'Paste',
  7893.                             Click = function()
  7894.                                 local paste = Clipboard.Paste()
  7895.                                 Current.Document.TextInput:Insert(paste)
  7896.                                 Current.Document.TextInput.CursorPos = Current.Document.TextInput.CursorPos + #paste - 1
  7897.                             end,
  7898.                             Keys = {
  7899.                                 keys.leftCtrl,
  7900.                                 keys.v
  7901.                             },
  7902.                             Enabled = function()
  7903.                                 return Current.Document ~= nil and (not Clipboard.isEmpty()) and Clipboard.Type == 'text'
  7904.                             end
  7905.                         },
  7906.                         {
  7907.                             Separator = true,  
  7908.                         },
  7909.                         {
  7910.                             Title = 'Select All',
  7911.                             Click = function()
  7912.                                 Current.Selection = {1, #Current.Document.TextInput.Value:gsub('\n','')}
  7913.                             end,
  7914.                             Keys = {
  7915.                                 keys.leftCtrl,
  7916.                                 keys.a
  7917.                             },
  7918.                             Enabled = function()
  7919.                                 return Current.Document ~= nil
  7920.                             end
  7921.                         }
  7922.                     }, self, true)
  7923.                 else
  7924.                     Current.Menu = nil
  7925.                 end
  7926.                 return true
  7927.             end, 'Edit', colours.lightGrey, false),
  7928.             Button:Initialise(13, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
  7929.                 if not self.Toggle then
  7930.                     Menu:New(13, 2, {
  7931.                         {
  7932.                             Title = 'Red',
  7933.                             Click = function(item)
  7934.                                 Current.Document:SetSelectionColour(item.Colour)
  7935.                             end,
  7936.                             Colour = colours.red,
  7937.                             Enabled = function()
  7938.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  7939.                             end
  7940.                         },
  7941.                         {
  7942.                             Title = 'Orange',
  7943.                             Click = function(item)
  7944.                                 Current.Document:SetSelectionColour(item.Colour)
  7945.                             end,
  7946.                             Colour = colours.orange,
  7947.                             Enabled = function()
  7948.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  7949.                             end
  7950.                         },
  7951.                         {
  7952.                             Title = 'Yellow',
  7953.                             Click = function(item)
  7954.                                 Current.Document:SetSelectionColour(item.Colour)
  7955.                             end,
  7956.                             Colour = colours.yellow,
  7957.                             Enabled = function()
  7958.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  7959.                             end
  7960.                         },
  7961.                         {
  7962.                             Title = 'Pink',
  7963.                             Click = function(item)
  7964.                                 Current.Document:SetSelectionColour(item.Colour)
  7965.                             end,
  7966.                             Colour = colours.pink,
  7967.                             Enabled = function()
  7968.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  7969.                             end
  7970.                         },
  7971.                         {
  7972.                             Title = 'Magenta',
  7973.                             Click = function(item)
  7974.                                 Current.Document:SetSelectionColour(item.Colour)
  7975.                             end,
  7976.                             Colour = colours.magenta,
  7977.                             Enabled = function()
  7978.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  7979.                             end
  7980.                         },
  7981.                         {
  7982.                             Title = 'Purple',
  7983.                             Click = function(item)
  7984.                                 Current.Document:SetSelectionColour(item.Colour)
  7985.                             end,
  7986.                             Colour = colours.purple,
  7987.                             Enabled = function()
  7988.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  7989.                             end
  7990.                         },
  7991.                         {
  7992.                             Title = 'Light Blue',
  7993.                             Click = function(item)
  7994.                                 Current.Document:SetSelectionColour(item.Colour)
  7995.                             end,
  7996.                             Colour = colours.lightBlue,
  7997.                             Enabled = function()
  7998.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  7999.                             end
  8000.                         },
  8001.                         {
  8002.                             Title = 'Cyan',
  8003.                             Click = function(item)
  8004.                                 Current.Document:SetSelectionColour(item.Colour)
  8005.                             end,
  8006.                             Colour = colours.cyan,
  8007.                             Enabled = function()
  8008.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  8009.                             end
  8010.                         },
  8011.                         {
  8012.                             Title = 'Blue',
  8013.                             Click = function(item)
  8014.                                 Current.Document:SetSelectionColour(item.Colour)
  8015.                             end,
  8016.                             Colour = colours.blue,
  8017.                             Enabled = function()
  8018.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  8019.                             end
  8020.                         },
  8021.                         {
  8022.                             Title = 'Green',
  8023.                             Click = function(item)
  8024.                                 Current.Document:SetSelectionColour(item.Colour)
  8025.                             end,
  8026.                             Colour = colours.green,
  8027.                             Enabled = function()
  8028.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  8029.                             end
  8030.                         },
  8031.                         {
  8032.                             Title = 'Light Grey',
  8033.                             Click = function(item)
  8034.                                 Current.Document:SetSelectionColour(item.Colour)
  8035.                             end,
  8036.                             Colour = colours.lightGrey,
  8037.                             Enabled = function()
  8038.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  8039.                             end
  8040.                         },
  8041.                         {
  8042.                             Title = 'Grey',
  8043.                             Click = function(item)
  8044.                                 Current.Document:SetSelectionColour(item.Colour)
  8045.                             end,
  8046.                             Colour = colours.grey,
  8047.                             Enabled = function()
  8048.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  8049.                             end
  8050.                         },
  8051.                         {
  8052.                             Title = 'Black',
  8053.                             Click = function(item)
  8054.                                 Current.Document:SetSelectionColour(item.Colour)
  8055.                             end,
  8056.                             Colour = colours.black,
  8057.                             Enabled = function()
  8058.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  8059.                             end
  8060.                         },
  8061.                         {
  8062.                             Title = 'Brown',
  8063.                             Click = function(item)
  8064.                                 Current.Document:SetSelectionColour(item.Colour)
  8065.                             end,
  8066.                             Colour = colours.brown,
  8067.                             Enabled = function()
  8068.                                 return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
  8069.                             end
  8070.                         }
  8071.                     }, self, true)
  8072.                 else
  8073.                     Current.Menu = nil
  8074.                 end
  8075.                 return true
  8076.             end, 'Colour', colours.lightGrey, false)
  8077.         })
  8078.     end
  8079.  
  8080.     function SplashScreen()
  8081.         local w = colours.white
  8082.         local b = colours.black
  8083.         local u = colours.blue
  8084.         local lb = colours.lightBlue
  8085.         local splashIcon = {{w,w,w,b,w,w,w,b,w,w,w,},{w,w,w,b,w,w,w,b,w,w,w,},{w,w,w,b,u,u,u,b,w,w,w,},{w,b,b,u,u,u,u,u,b,b,w,},{b,u,u,lb,lb,u,u,u,u,u,b,},{b,u,lb,lb,u,u,u,u,u,u,b,},{b,u,lb,lb,u,u,u,u,u,u,b,},{b,u,u,u,u,u,u,u,u,u,b,},{w,b,b,b,b,b,b,b,b,b,w,},
  8086.         ["text"]={{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," ","I","n","k"," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," ","b","y"," ","o","e","e","d"," "," "},{" "," "," "," "," "," "," "," "," "," "," ",},},
  8087.         ["textcol"]={{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{lb,lb,lb,lb,lb,lb,lb,lb,lb,lb,lb,},{w,w,w,w,w,w,w,w,w,w,w,},},}
  8088.         Drawing.Clear(colours.white)
  8089.         Drawing.DrawImage((Drawing.Screen.Width - 11)/2, (Drawing.Screen.Height - 9)/2, splashIcon, 11, 9)
  8090.         Drawing.DrawBuffer()
  8091.         Drawing.Clear(colours.black)
  8092.         parallel.waitForAny(function()sleep(1)end, function()os.pullEvent('mouse_click')end)
  8093.     end
  8094.  
  8095.     function Initialise(arg)
  8096.         if OneOS then
  8097.             fs = OneOS.FS
  8098.         end
  8099.  
  8100.         if not OneOS then
  8101.             SplashScreen()
  8102.         end
  8103.         EventRegister('mouse_click', TryClick)
  8104.         EventRegister('mouse_drag', function(event, side, x, y)TryClick(event, side, x, y, true)end)
  8105.         EventRegister('mouse_scroll', Scroll)
  8106.         EventRegister('key', HandleKey)
  8107.         EventRegister('char', HandleKey)
  8108.         EventRegister('timer', Timer)
  8109.         EventRegister('terminate', function(event) if Close() then error( "Terminated", 0 ) end end)
  8110.        
  8111.         LoadMenuBar()
  8112.  
  8113.         --Current.Document = Document:Initialise('abcdefghijklmnopqrtuvwxy')--'Hello everybody!')
  8114.         if tArgs[1] then
  8115.             if fs.exists(tArgs[1]) then
  8116.                 OpenDocument(tArgs[1])
  8117.             else
  8118.                 --new
  8119.             end
  8120.         else
  8121.             Current.Document = Document:Initialise('')--'Hello everybody!')
  8122.         end
  8123.  
  8124.         --[[
  8125.         if arg and fs.exists(arg) then
  8126.                 OpenDocument(arg)
  8127.             else
  8128.                 DisplayNewDocumentWindow()
  8129.             end
  8130.         ]]--
  8131.         Draw()
  8132.  
  8133.         EventHandler()
  8134.     end
  8135.  
  8136.     local isControlPushed = false
  8137.     controlPushedTimer = nil
  8138.     closeWindowTimer = nil
  8139.     function Timer(event, timer)
  8140.         if timer == closeWindowTimer then
  8141.             if Current.Window then
  8142.                 Current.Window:Close()
  8143.             end
  8144.             Draw()
  8145.         elseif timer == controlPushedTimer then
  8146.             isControlPushed = false
  8147.         end
  8148.     end
  8149.  
  8150.     local ignoreNextChar = false
  8151.     function HandleKey(...)
  8152.         local args = {...}
  8153.         local event = args[1]
  8154.         local keychar = args[2]
  8155.                                                                                                 --Mac left command character
  8156.         if event == 'key' and keychar == keys.leftCtrl or keychar == keys.rightCtrl or keychar == 219 then
  8157.             isControlPushed = true
  8158.             controlPushedTimer = os.startTimer(0.5)
  8159.         elseif isControlPushed then
  8160.             if event == 'key' then
  8161.                 if CheckKeyboardShortcut(keychar) then
  8162.                     isControlPushed = false
  8163.                     ignoreNextChar = true
  8164.                 end
  8165.             end
  8166.         elseif ignoreNextChar then
  8167.             ignoreNextChar = false
  8168.         elseif Current.TextInput then
  8169.             if event == 'char' then
  8170.                 Current.TextInput:Char(keychar)
  8171.             elseif event == 'key' then
  8172.                 Current.TextInput:Key(keychar)
  8173.             end
  8174.         end
  8175.     end
  8176.  
  8177.     function CheckKeyboardShortcut(key)
  8178.         local shortcuts = {}
  8179.         shortcuts[keys.n] = function() Current.Document = Document:Initialise('') end
  8180.         shortcuts[keys.o] = function() DisplayOpenDocumentWindow() end
  8181.         shortcuts[keys.s] = function() if Current.Document ~= nil then SaveDocument() end end
  8182.         shortcuts[keys.left] = function() if Current.TextInput then Current.TextInput:Key(keys.home) end end
  8183.         shortcuts[keys.right] = function() if Current.TextInput then Current.TextInput:Key(keys["end"]) end end
  8184.     --  shortcuts[keys.q] = function() DisplayOpenDocumentWindow() end
  8185.         if Current.Document ~= nil then
  8186.             shortcuts[keys.s] = function() SaveDocument() end
  8187.             shortcuts[keys.p] = function() PrintDocument() end
  8188.             if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
  8189.                 shortcuts[keys.x] = function() Clipboard.Cut(Current.Document.TextInput:Extract(true), 'text') end
  8190.                 shortcuts[keys.c] = function() Clipboard.Copy(Current.Document.TextInput:Extract(), 'text') end
  8191.             end
  8192.             if (not Clipboard.isEmpty()) and Clipboard.Type == 'text' then
  8193.                 shortcuts[keys.v] = function() local paste = Clipboard.Paste()
  8194.                                         Current.Document.TextInput:Insert(paste)
  8195.                                         Current.Document.TextInput.CursorPos = Current.Document.TextInput.CursorPos + #paste - 1
  8196.                                     end
  8197.             end
  8198.             shortcuts[keys.a] = function() Current.Selection = {1, #Current.Document.TextInput.Value:gsub('\n','')} end
  8199.         end
  8200.                                
  8201.         if shortcuts[key] then
  8202.             shortcuts[key]()
  8203.             Draw()
  8204.             return true
  8205.         else
  8206.             return false
  8207.         end
  8208.     end
  8209.  
  8210.     --[[
  8211.         Check if the given object falls under the click coordinates
  8212.     ]]--
  8213.     function CheckClick(object, x, y)
  8214.         if object.X <= x and object.Y <= y and object.X + object.Width > x and object.Y + object.Height > y then
  8215.             return true
  8216.         end
  8217.     end
  8218.  
  8219.     --[[
  8220.         Attempt to clicka given object
  8221.     ]]--
  8222.     function DoClick(object, side, x, y, drag)
  8223.         local obj = GetAbsolutePosition(object)
  8224.         obj.Width = object.Width
  8225.         obj.Height = object.Height
  8226.         if object and CheckClick(obj, x, y) then
  8227.             return object:Click(side, x - object.X + 1, y - object.Y + 1, drag)
  8228.         end
  8229.     end
  8230.  
  8231.     --[[
  8232.         Try to click at the given coordinates
  8233.     ]]--
  8234.     function TryClick(event, side, x, y, drag)
  8235.         if Current.Menu then
  8236.             if DoClick(Current.Menu, side, x, y, drag) then
  8237.                 Draw()
  8238.                 return
  8239.             else
  8240.                 if Current.Menu.Owner and Current.Menu.Owner.Toggle then
  8241.                     Current.Menu.Owner.Toggle = false
  8242.                 end
  8243.                 Current.Menu = nil
  8244.                 Draw()
  8245.                 return
  8246.             end
  8247.         elseif Current.Window then
  8248.             if DoClick(Current.Window, side, x, y, drag) then
  8249.                 Draw()
  8250.                 return
  8251.             else
  8252.                 Current.Window:Flash()
  8253.                 return
  8254.             end
  8255.         end
  8256.         local interfaceElements = {}
  8257.  
  8258.         table.insert(interfaceElements, Current.MenuBar)
  8259.         table.insert(interfaceElements, Current.ScrollBar)
  8260.         for i, page in ipairs(Current.Document.Pages) do
  8261.             table.insert(interfaceElements, page)
  8262.         end
  8263.  
  8264.         for i, object in ipairs(interfaceElements) do
  8265.             if DoClick(object, side, x, y, drag) then
  8266.                 Draw()
  8267.                 return
  8268.             end    
  8269.         end
  8270.         Draw()
  8271.     end
  8272.  
  8273.     function Scroll(event, direction, x, y)
  8274.         if Current.Window and Current.Window.OpenButton then
  8275.             Current.Document.Scroll = Current.Document.Scroll + direction
  8276.             if Current.Window.Scroll < 0 then
  8277.                 Current.Window.Scroll = 0
  8278.             elseif Current.Window.Scroll > Current.Window.MaxScroll then
  8279.                 Current.Window.Scroll = Current.Window.MaxScroll
  8280.             end
  8281.             Draw()
  8282.         elseif Current.ScrollBar then
  8283.             if Current.ScrollBar:DoScroll(direction*2) then
  8284.                 Draw()
  8285.             end
  8286.         end
  8287.     end
  8288.  
  8289.  
  8290.     --[[
  8291.         Registers functions to run on certain events
  8292.     ]]--
  8293.     function EventRegister(event, func)
  8294.         if not Events[event] then
  8295.             Events[event] = {}
  8296.         end
  8297.  
  8298.         table.insert(Events[event], func)
  8299.     end
  8300.  
  8301.     --[[
  8302.         The main loop event handler, runs registered event functinos
  8303.     ]]--
  8304.     function EventHandler()
  8305.         while true do
  8306.             local event, arg1, arg2, arg3, arg4 = os.pullEventRaw()
  8307.             if Events[event] then
  8308.                 for i, e in ipairs(Events[event]) do
  8309.                     e(event, arg1, arg2, arg3, arg4)
  8310.                 end
  8311.             end
  8312.         end
  8313.     end
  8314.  
  8315.  
  8316.     local function Extension(path, addDot)
  8317.         if not path then
  8318.             return nil
  8319.         elseif not string.find(fs.getName(path), '%.') then
  8320.             if not addDot then
  8321.                 return fs.getName(path)
  8322.             else
  8323.                 return ''
  8324.             end
  8325.         else
  8326.             local _path = path
  8327.             if path:sub(#path) == '/' then
  8328.                 _path = path:sub(1,#path-1)
  8329.             end
  8330.             local extension = _path:gmatch('%.[0-9a-z]+$')()
  8331.             if extension then
  8332.                 extension = extension:sub(2)
  8333.             else
  8334.                 --extension = nil
  8335.                 return ''
  8336.             end
  8337.             if addDot then
  8338.                 extension = '.'..extension
  8339.             end
  8340.             return extension:lower()
  8341.         end
  8342.     end
  8343.  
  8344.     local RemoveExtension = function(path)
  8345.         if path:sub(1,1) == '.' then
  8346.             return path
  8347.         end
  8348.         local extension = Extension(path)
  8349.         if extension == path then
  8350.             return fs.getName(path)
  8351.         end
  8352.         return string.gsub(path, extension, ''):sub(1, -2)
  8353.     end
  8354.  
  8355.     local acknowledgedColour = false
  8356.     function PrintDocument()
  8357.         if OneOS then
  8358.             OneOS.LoadAPI('/System/API/Helpers.lua')
  8359.             OneOS.LoadAPI('/System/API/Peripheral.lua')
  8360.             OneOS.LoadAPI('/System/API/Printer.lua')
  8361.         end
  8362.  
  8363.         local doPrint = function()
  8364.             local window = PrintDocumentWindow:Initialise():Show()
  8365.         end
  8366.  
  8367.         if Peripheral.GetPeripheral('printer') == nil then
  8368.             ButtonDialougeWindow:Initialise('No Printer Found', 'Please place a printer next to your computer. Ensure you also insert dye (left slot) and paper (top slots)', 'Ok', nil, function(window, ok)
  8369.                 window:Close()
  8370.             end):Show()
  8371.         elseif not acknowledgedColour and FindColours(Current.Document.TextInput.Value) ~= 0 then
  8372.             ButtonDialougeWindow:Initialise('Important', 'Due to the way printers work, you can\'t print in more than one colour. The dye you use will be the colour of the text.', 'Ok', nil, function(window, ok)
  8373.                 acknowledgedColour = true
  8374.                 window:Close()
  8375.                 doPrint()
  8376.             end):Show()
  8377.         else
  8378.             doPrint()
  8379.         end
  8380.     end
  8381.  
  8382.     function SaveDocument()
  8383.         local function save()
  8384.             local h = fs.open(Current.Document.Path, 'w')
  8385.             if h then
  8386.                 if Current.Document.Format == TextFormatPlainText then
  8387.                     h.write(Current.Document.TextInput.Value)
  8388.                 else
  8389.                     local lines = {}
  8390.                     for p, page in ipairs(Current.Document.Pages) do
  8391.                         for i, line in ipairs(page.Lines) do
  8392.                             table.insert(lines, line)
  8393.                         end
  8394.                     end
  8395.                     h.write(textutils.serialize(lines))
  8396.                 end
  8397.                 Current.Modified = false
  8398.             else
  8399.                 ButtonDialougeWindow:Initialise('Error', 'An error occured while saving the file, try again.', 'Ok', nil, function(window, ok)
  8400.                     window:Close()
  8401.                 end):Show()
  8402.             end
  8403.             h.close()
  8404.         end
  8405.  
  8406.         if not Current.Document.Path then
  8407.             SaveDocumentWindow:Initialise(function(self, success, path)
  8408.                 self:Close()
  8409.                 if success then
  8410.                     local extension = ''
  8411.                     if Current.Document.Format == TextFormatPlainText then
  8412.                         extension = '.txt'
  8413.                     elseif Current.Document.Format == TextFormatInkText then
  8414.                         extension = '.ink'
  8415.                     end
  8416.                    
  8417.                     if path:sub(-4) ~= extension then
  8418.                         path = path .. extension
  8419.                     end
  8420.  
  8421.                     Current.Document.Path = path
  8422.                     Current.Document.Title = fs.getName(path)
  8423.                     save()
  8424.                 end
  8425.                 if Current.Document then
  8426.                     Current.TextInput = Current.Document.TextInput
  8427.                 end
  8428.             end):Show()
  8429.         else
  8430.             save()
  8431.         end
  8432.     end
  8433.  
  8434.     function DisplayOpenDocumentWindow()
  8435.         OpenDocumentWindow:Initialise(function(self, success, path)
  8436.             self:Close()
  8437.             if success then
  8438.                 OpenDocument(path)
  8439.             end
  8440.         end):Show()
  8441.     end
  8442.  
  8443.     function OpenDocument(path)
  8444.         Current.Selection = nil
  8445.         local h = fs.open(path, 'r')
  8446.         if h then
  8447.             Current.Document = Document:Initialise(h.readAll(), RemoveExtension(fs.getName(path)), path)
  8448.         else
  8449.             ButtonDialougeWindow:Initialise('Error', 'An error occured while opening the file, try again.', 'Ok', nil, function(window, ok)
  8450.                 window:Close()
  8451.                 if Current.Document then
  8452.                     Current.TextInput = Current.Document.TextInput
  8453.                 end
  8454.             end):Show()
  8455.         end
  8456.         h.close()
  8457.     end
  8458.  
  8459.     local TidyPath = function(path)
  8460.         path = '/'..path
  8461.         local fs = fs
  8462.         if OneOS then
  8463.             fs = OneOS.FS
  8464.         end
  8465.         if fs.isDir(path) then
  8466.             path = path .. '/'
  8467.         end
  8468.  
  8469.         path, n = path:gsub("//", "/")
  8470.         while n > 0 do
  8471.             path, n = path:gsub("//", "/")
  8472.         end
  8473.         return path
  8474.     end
  8475.  
  8476.     OpenDocumentWindow = {
  8477.         X = 1,
  8478.         Y = 1,
  8479.         Width = 0,
  8480.         Height = 0,
  8481.         CursorPos = 1,
  8482.         Visible = true,
  8483.         Return = nil,
  8484.         OpenButton = nil,
  8485.         PathTextBox = nil,
  8486.         CurrentDirectory = '/',
  8487.         Scroll = 0,
  8488.         MaxScroll = 0,
  8489.         GoUpButton = nil,
  8490.         SelectedFile = '',
  8491.         Files = {},
  8492.         Typed = false,
  8493.  
  8494.         AbsolutePosition = function(self)
  8495.             return {X = self.X, Y = self.Y}
  8496.         end,
  8497.  
  8498.         Draw = function(self)
  8499.             if not self.Visible then
  8500.                 return
  8501.             end
  8502.             Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
  8503.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, 3, colours.lightGrey)
  8504.             Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-6, colours.white)
  8505.             Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
  8506.             Drawing.DrawBlankArea(self.X, self.Y + self.Height - 5, self.Width, 5, colours.lightGrey)
  8507.             self:DrawFiles()
  8508.  
  8509.             if (fs.exists(self.PathTextBox.TextInput.Value)) or (self.SelectedFile and #self.SelectedFile > 0 and fs.exists(self.CurrentDirectory .. self.SelectedFile)) then
  8510.                 self.OpenButton.TextColour = colours.black
  8511.             else
  8512.                 self.OpenButton.TextColour = colours.lightGrey
  8513.             end
  8514.  
  8515.             self.PathTextBox:Draw()
  8516.             self.OpenButton:Draw()
  8517.             self.CancelButton:Draw()
  8518.             self.GoUpButton:Draw()
  8519.         end,
  8520.  
  8521.         DrawFiles = function(self)
  8522.             for i, file in ipairs(self.Files) do
  8523.                 if i > self.Scroll and i - self.Scroll <= 11 then
  8524.                     if file == self.SelectedFile then
  8525.                         Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.white, colours.lightBlue)
  8526.                     elseif string.find(file, '%.txt') or string.find(file, '%.text') or string.find(file, '%.ink') or fs.isDir(self.CurrentDirectory .. file) then
  8527.                         Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.black, colours.white)
  8528.                     else
  8529.                         Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.grey, colours.white)
  8530.                     end
  8531.                 end
  8532.             end
  8533.             self.MaxScroll = #self.Files - 11
  8534.             if self.MaxScroll < 0 then
  8535.                 self.MaxScroll = 0
  8536.             end
  8537.         end,
  8538.  
  8539.         Initialise = function(self, returnFunc)
  8540.             local new = {}    -- the new instance
  8541.             setmetatable( new, {__index = self} )
  8542.             new.Width = 32
  8543.             new.Height = 17
  8544.             new.Return = returnFunc
  8545.             new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
  8546.             new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
  8547.             new.Title = 'Open Document'
  8548.             new.Visible = true
  8549.             new.CurrentDirectory = '/'
  8550.             new.SelectedFile = nil
  8551.             if OneOS and fs.exists('/Desktop/Documents/') then
  8552.                 new.CurrentDirectory = '/Desktop/Documents/'
  8553.             end
  8554.             new.OpenButton = Button:Initialise(new.Width - 6, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
  8555.                 if fs.exists(new.PathTextBox.TextInput.Value) and self.TextColour == colours.black and not fs.isDir(new.PathTextBox.TextInput.Value) then
  8556.                     returnFunc(new, true, TidyPath(new.PathTextBox.TextInput.Value))
  8557.                 elseif new.SelectedFile and self.TextColour == colours.black and fs.isDir(new.CurrentDirectory .. new.SelectedFile) then
  8558.                     new:GoToDirectory(new.CurrentDirectory .. new.SelectedFile)
  8559.                 elseif new.SelectedFile and self.TextColour == colours.black then
  8560.                     returnFunc(new, true, TidyPath(new.CurrentDirectory .. '/' .. new.SelectedFile))
  8561.                 end
  8562.             end, 'Open', colours.black)
  8563.             new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
  8564.                 returnFunc(new, false)
  8565.             end, 'Cancel', colours.black)
  8566.             new.GoUpButton = Button:Initialise(2, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
  8567.                 local folderName = fs.getName(new.CurrentDirectory)
  8568.                 local parentDirectory = new.CurrentDirectory:sub(1, #new.CurrentDirectory-#folderName-1)
  8569.                 new:GoToDirectory(parentDirectory)
  8570.             end, 'Go Up', colours.black)
  8571.             new.PathTextBox = TextBox:Initialise(2, new.Height - 3, new.Width - 2, 1, new, new.CurrentDirectory, colours.white, colours.black)
  8572.             new:GoToDirectory(new.CurrentDirectory)
  8573.             return new
  8574.         end,
  8575.  
  8576.         Show = function(self)
  8577.             Current.Window = self
  8578.             return self
  8579.         end,
  8580.  
  8581.         Close = function(self)
  8582.             Current.Input = nil
  8583.             Current.Window = nil
  8584.             self = nil
  8585.         end,
  8586.  
  8587.         GoToDirectory = function(self, path)
  8588.             path = TidyPath(path)
  8589.             self.CurrentDirectory = path
  8590.             self.Scroll = 0
  8591.             self.SelectedFile = nil
  8592.             self.Typed = false
  8593.             self.PathTextBox.TextInput.Value = path
  8594.             local fs = fs
  8595.             if OneOS then
  8596.                 fs = OneOS.FS
  8597.             end
  8598.             self.Files = fs.list(self.CurrentDirectory)
  8599.             Draw()
  8600.         end,
  8601.  
  8602.         Flash = function(self)
  8603.             self.Visible = false
  8604.             Draw()
  8605.             sleep(0.15)
  8606.             self.Visible = true
  8607.             Draw()
  8608.             sleep(0.15)
  8609.             self.Visible = false
  8610.             Draw()
  8611.             sleep(0.15)
  8612.             self.Visible = true
  8613.             Draw()
  8614.         end,
  8615.  
  8616.         Click = function(self, side, x, y)
  8617.             local items = {self.OpenButton, self.CancelButton, self.PathTextBox, self.GoUpButton}
  8618.             local found = false
  8619.             for i, v in ipairs(items) do
  8620.                 if CheckClick(v, x, y) then
  8621.                     v:Click(side, x, y)
  8622.                     found = true
  8623.                 end
  8624.             end
  8625.  
  8626.             if not found then
  8627.                 if y <= 12 then
  8628.                     local fs = fs
  8629.                     if OneOS then
  8630.                         fs = OneOS.FS
  8631.                     end
  8632.                     self.SelectedFile = fs.list(self.CurrentDirectory)[y-1]
  8633.                     self.PathTextBox.TextInput.Value = TidyPath(self.CurrentDirectory .. '/' .. self.SelectedFile)
  8634.                     Draw()
  8635.                 end
  8636.             end
  8637.             return true
  8638.         end
  8639.     }
  8640.  
  8641.     PrintDocumentWindow = {
  8642.         X = 1,
  8643.         Y = 1,
  8644.         Width = 0,
  8645.         Height = 0,
  8646.         CursorPos = 1,
  8647.         Visible = true,
  8648.         Return = nil,
  8649.         PrintButton = nil,
  8650.         CopiesTextBox = nil,
  8651.         Scroll = 0,
  8652.         MaxScroll = 0,
  8653.         PrinterSelectButton = nil,
  8654.         Title = '',
  8655.         Status = 0, --0 = neutral, 1 = good, -1 = error
  8656.         StatusText = '',
  8657.         SelectedPrinter = nil,
  8658.  
  8659.         AbsolutePosition = function(self)
  8660.             return {X = self.X, Y = self.Y}
  8661.         end,
  8662.  
  8663.         Draw = function(self)
  8664.             if not self.Visible then
  8665.                 return
  8666.             end
  8667.             Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
  8668.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
  8669.             Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
  8670.             Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
  8671.            
  8672.             self.PrinterSelectButton:Draw()
  8673.             Drawing.DrawCharactersCenter(self.X,  self.Y + self.PrinterSelectButton.Y - 2, self.Width, 1, 'Printer', colours.black, colours.white)
  8674.             Drawing.DrawCharacters(self.X + self.Width - 3, self.Y + self.PrinterSelectButton.Y - 1, '\\/', colours.black, colours.lightGrey)
  8675.             Drawing.DrawCharacters(self.X + 1, self.Y + self.CopiesTextBox.Y - 1, 'Copies', colours.black, colours.white)
  8676.             local statusColour = colours.grey
  8677.             if self.Status == -1 then
  8678.                 statusColour = colours.red
  8679.             elseif self.Status == 1 then
  8680.                 statusColour = colours.green
  8681.             end
  8682.             Drawing.DrawCharacters(self.X + 1, self.Y + self.CopiesTextBox.Y + 1, self.StatusText, statusColour, colours.white)
  8683.  
  8684.             self.CopiesTextBox:Draw()
  8685.             self.PrintButton:Draw()
  8686.             self.CancelButton:Draw()
  8687.         end,
  8688.  
  8689.         Initialise = function(self)
  8690.             local new = {}    -- the new instance
  8691.             setmetatable( new, {__index = self} )
  8692.             new.Width = 32
  8693.             new.Height = 11
  8694.             new.Return = returnFunc
  8695.             new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
  8696.             new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
  8697.             new.Title = 'Print Document'
  8698.             new.Visible = true
  8699.             new.PrintButton = Button:Initialise(new.Width - 7, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
  8700.                 local doPrint = true
  8701.                 if new.SelectedPrinter == nil then
  8702.                     local p = Peripheral.GetPeripheral('printer')
  8703.                     if p then
  8704.                         new.SelectedPrinter = p.Side
  8705.                         new.PrinterSelectButton.Text = p.Fullname
  8706.                     else
  8707.                         new.StatusText = 'No Connected Printer'
  8708.                         new.Status = -1
  8709.                         doPrint = false
  8710.                     end
  8711.                 end
  8712.                 if doPrint then
  8713.                     local printer = Printer:Initialise(new.SelectedPrinter)
  8714.                     local err = printer:PrintLines(Current.Document.Lines, Current.Document.Title, tonumber(new.CopiesTextBox.TextInput.Value))
  8715.                     if not err then
  8716.                         new.StatusText = 'Document Printed!'
  8717.                         new.Status = 1
  8718.                         closeWindowTimer = os.startTimer(1)
  8719.                     else
  8720.                         new.StatusText = err
  8721.                         new.Status = -1
  8722.                     end
  8723.                 end
  8724.             end, 'Print', colours.black)
  8725.             new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
  8726.                 new:Close()
  8727.                 Draw()
  8728.             end, 'Close', colours.black)
  8729.             new.PrinterSelectButton = Button:Initialise(2, 4, new.Width - 2, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
  8730.                 local printers = {
  8731.                         {
  8732.                             Title = "Automatic",
  8733.                             Click = function()
  8734.                                 new.SelectedPrinter = nil
  8735.                                 new.PrinterSelectButton.Text = 'Automatic'
  8736.                             end
  8737.                         },
  8738.                         {
  8739.                             Separator = true
  8740.                         }
  8741.                     }
  8742.                 for i, p in ipairs(Peripheral.GetPeripherals('printer')) do
  8743.                     table.insert(printers, {
  8744.                         Title = p.Fullname,
  8745.                         Click = function(self)
  8746.                             new.SelectedPrinter = p.Side
  8747.                             new.PrinterSelectButton.Text = p.Fullname
  8748.                         end
  8749.                     })
  8750.                 end
  8751.                 Current.Menu = Menu:New(x, y+4, printers, self, true)
  8752.             end, 'Automatic', colours.black)
  8753.             new.CopiesTextBox = TextBox:Initialise(9, 6, 4, 1, new, 1, colours.lightGrey, colours.black, nil, true)
  8754.             Current.TextInput = new.CopiesTextBox.TextInput
  8755.             new.StatusText = 'Waiting...'
  8756.             new.Status = 0
  8757.             return new
  8758.         end,
  8759.  
  8760.         Show = function(self)
  8761.             Current.Window = self
  8762.             return self
  8763.         end,
  8764.  
  8765.         Close = function(self)
  8766.             Current.Input = nil
  8767.             Current.Window = nil
  8768.             self = nil
  8769.         end,
  8770.  
  8771.         Flash = function(self)
  8772.             self.Visible = false
  8773.             Draw()
  8774.             sleep(0.15)
  8775.             self.Visible = true
  8776.             Draw()
  8777.             sleep(0.15)
  8778.             self.Visible = false
  8779.             Draw()
  8780.             sleep(0.15)
  8781.             self.Visible = true
  8782.             Draw()
  8783.         end,
  8784.  
  8785.         Click = function(self, side, x, y)
  8786.             local items = {self.PrintButton, self.CancelButton, self.CopiesTextBox, self.PrinterSelectButton}
  8787.             for i, v in ipairs(items) do
  8788.                 if CheckClick(v, x, y) then
  8789.                     v:Click(side, x, y)
  8790.                 end
  8791.             end
  8792.             return true
  8793.         end
  8794.     }
  8795.  
  8796.     SaveDocumentWindow = {
  8797.         X = 1,
  8798.         Y = 1,
  8799.         Width = 0,
  8800.         Height = 0,
  8801.         CursorPos = 1,
  8802.         Visible = true,
  8803.         Return = nil,
  8804.         SaveButton = nil,
  8805.         PathTextBox = nil,
  8806.         CurrentDirectory = '/',
  8807.         Scroll = 0,
  8808.         MaxScroll = 0,
  8809.         ScrollBar = nil,
  8810.         GoUpButton = nil,
  8811.         Files = {},
  8812.         Typed = false,
  8813.  
  8814.         AbsolutePosition = function(self)
  8815.             return {X = self.X, Y = self.Y}
  8816.         end,
  8817.  
  8818.         Draw = function(self)
  8819.             if not self.Visible then
  8820.                 return
  8821.             end
  8822.             Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
  8823.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, 3, colours.lightGrey)
  8824.             Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-6, colours.white)
  8825.             Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
  8826.             Drawing.DrawBlankArea(self.X, self.Y + self.Height - 5, self.Width, 5, colours.lightGrey)
  8827.             Drawing.DrawCharacters(self.X + 1, self.Y + self.Height - 5, self.CurrentDirectory, colours.grey, colours.lightGrey)
  8828.             self:DrawFiles()
  8829.  
  8830.             if (self.PathTextBox.TextInput.Value) then
  8831.                 self.SaveButton.TextColour = colours.black
  8832.             else
  8833.                 self.SaveButton.TextColour = colours.lightGrey
  8834.             end
  8835.  
  8836.             self.PathTextBox:Draw()
  8837.             self.SaveButton:Draw()
  8838.             self.CancelButton:Draw()
  8839.             self.GoUpButton:Draw()
  8840.         end,
  8841.  
  8842.         DrawFiles = function(self)
  8843.             for i, file in ipairs(self.Files) do
  8844.                 if i > self.Scroll and i - self.Scroll <= 10 then
  8845.                     if file == self.SelectedFile then
  8846.                         Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.white, colours.lightBlue)
  8847.                     elseif fs.isDir(self.CurrentDirectory .. file) then
  8848.                         Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.black, colours.white)
  8849.                     else
  8850.                         Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.lightGrey, colours.white)
  8851.                     end
  8852.                 end
  8853.             end
  8854.             self.MaxScroll = #self.Files - 11
  8855.             if self.MaxScroll < 0 then
  8856.                 self.MaxScroll = 0
  8857.             end
  8858.         end,
  8859.  
  8860.         Initialise = function(self, returnFunc)
  8861.             local new = {}    -- the new instance
  8862.             setmetatable( new, {__index = self} )
  8863.             new.Width = 32
  8864.             new.Height = 16
  8865.             new.Return = returnFunc
  8866.             new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
  8867.             new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
  8868.             new.Title = 'Save Document'
  8869.             new.Visible = true
  8870.             new.CurrentDirectory = '/'
  8871.             if OneOS and fs.exists('/Desktop/Documents/') then
  8872.                 new.CurrentDirectory = '/Desktop/Documents/'
  8873.             end
  8874.             new.SaveButton = Button:Initialise(new.Width - 6, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
  8875.                 if self.TextColour == colours.black and not fs.isDir(new.CurrentDirectory ..'/' .. new.PathTextBox.TextInput.Value) then
  8876.                     returnFunc(new, true, TidyPath(new.CurrentDirectory ..'/' .. new.PathTextBox.TextInput.Value))
  8877.                 elseif new.SelectedFile and self.TextColour == colours.black and fs.isDir(new.CurrentDirectory .. new.SelectedFile) then
  8878.                     new:GoToDirectory(new.CurrentDirectory .. new.SelectedFile)
  8879.                 end
  8880.             end, 'Save', colours.black)
  8881.             new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
  8882.                 returnFunc(new, false)
  8883.             end, 'Cancel', colours.black)
  8884.             new.GoUpButton = Button:Initialise(2, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
  8885.                 local folderName = fs.getName(new.CurrentDirectory)
  8886.                 local parentDirectory = new.CurrentDirectory:sub(1, #new.CurrentDirectory-#folderName-1)
  8887.                 new:GoToDirectory(parentDirectory)
  8888.             end, 'Go Up', colours.black)
  8889.             new.PathTextBox = TextBox:Initialise(2, new.Height - 3, new.Width - 2, 1, new, '', colours.white, colours.black, function(key)
  8890.                 if key == keys.enter then
  8891.                     new.SaveButton:Click()
  8892.                 end
  8893.             end)
  8894.             new.PathTextBox.Placeholder = 'Document Name'
  8895.             Current.TextInput = new.PathTextBox.TextInput
  8896.             new:GoToDirectory(new.CurrentDirectory)
  8897.             return new
  8898.         end,
  8899.  
  8900.         Show = function(self)
  8901.             Current.Window = self
  8902.             return self
  8903.         end,
  8904.  
  8905.         Close = function(self)
  8906.             Current.Input = nil
  8907.             Current.Window = nil
  8908.             self = nil
  8909.         end,
  8910.  
  8911.         GoToDirectory = function(self, path)
  8912.             path = TidyPath(path)
  8913.             self.CurrentDirectory = path
  8914.             self.Scroll = 0
  8915.             self.Typed = false
  8916.             local fs = fs
  8917.             if OneOS then
  8918.                 fs = OneOS.FS
  8919.             end
  8920.             self.Files = fs.list(self.CurrentDirectory)
  8921.             Draw()
  8922.         end,
  8923.  
  8924.         Flash = function(self)
  8925.             self.Visible = false
  8926.             Draw()
  8927.             sleep(0.15)
  8928.             self.Visible = true
  8929.             Draw()
  8930.             sleep(0.15)
  8931.             self.Visible = false
  8932.             Draw()
  8933.             sleep(0.15)
  8934.             self.Visible = true
  8935.             Draw()
  8936.         end,
  8937.  
  8938.         Click = function(self, side, x, y)
  8939.             local items = {self.SaveButton, self.CancelButton, self.PathTextBox, self.GoUpButton}
  8940.             local found = false
  8941.             for i, v in ipairs(items) do
  8942.                 if CheckClick(v, x, y) then
  8943.                     v:Click(side, x, y)
  8944.                     found = true
  8945.                 end
  8946.             end
  8947.  
  8948.             if not found then
  8949.                 if y <= 11 then
  8950.                     local files = fs.list(self.CurrentDirectory)
  8951.                     if files[y-1] then
  8952.                         self:GoToDirectory(self.CurrentDirectory..files[y-1])
  8953.                         Draw()
  8954.                     end
  8955.                 end
  8956.             end
  8957.             return true
  8958.         end
  8959.     }
  8960.  
  8961.     local WrapText = function(text, maxWidth)
  8962.         local lines = {''}
  8963.         for word, space in text:gmatch('(%S+)(%s*)') do
  8964.                 local temp = lines[#lines] .. word .. space:gsub('\n','')
  8965.                 if #temp > maxWidth then
  8966.                         table.insert(lines, '')
  8967.                 end
  8968.                 if space:find('\n') then
  8969.                         lines[#lines] = lines[#lines] .. word
  8970.                        
  8971.                         space = space:gsub('\n', function()
  8972.                                 table.insert(lines, '')
  8973.                                 return ''
  8974.                         end)
  8975.                 else
  8976.                         lines[#lines] = lines[#lines] .. word .. space
  8977.                 end
  8978.         end
  8979.         return lines
  8980.     end
  8981.  
  8982.     ButtonDialougeWindow = {
  8983.         X = 1,
  8984.         Y = 1,
  8985.         Width = 0,
  8986.         Height = 0,
  8987.         CursorPos = 1,
  8988.         Visible = true,
  8989.         CancelButton = nil,
  8990.         OkButton = nil,
  8991.         Lines = {},
  8992.  
  8993.         AbsolutePosition = function(self)
  8994.             return {X = self.X, Y = self.Y}
  8995.         end,
  8996.  
  8997.         Draw = function(self)
  8998.             if not self.Visible then
  8999.                 return
  9000.             end
  9001.             Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
  9002.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
  9003.             Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
  9004.             Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
  9005.  
  9006.             for i, text in ipairs(self.Lines) do
  9007.                 Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
  9008.             end
  9009.  
  9010.             self.OkButton:Draw()
  9011.             if self.CancelButton then
  9012.                 self.CancelButton:Draw()
  9013.             end
  9014.         end,
  9015.  
  9016.         Initialise = function(self, title, message, okText, cancelText, returnFunc)
  9017.             local new = {}    -- the new instance
  9018.             setmetatable( new, {__index = self} )
  9019.             new.Width = 28
  9020.             new.Lines = WrapText(message, new.Width - 2)
  9021.             new.Height = 5 + #new.Lines
  9022.             new.Return = returnFunc
  9023.             new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
  9024.             new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
  9025.             new.Title = title
  9026.             new.Visible = true
  9027.             new.Visible = true
  9028.             new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
  9029.                 returnFunc(new, true)
  9030.             end, okText)
  9031.             if cancelText then
  9032.                 new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
  9033.                     returnFunc(new, false)
  9034.                 end, cancelText)
  9035.             end
  9036.  
  9037.             return new
  9038.         end,
  9039.  
  9040.         Show = function(self)
  9041.             Current.Window = self
  9042.             return self
  9043.         end,
  9044.  
  9045.         Close = function(self)
  9046.             Current.Window = nil
  9047.             self = nil
  9048.         end,
  9049.  
  9050.         Flash = function(self)
  9051.             self.Visible = false
  9052.             Draw()
  9053.             sleep(0.15)
  9054.             self.Visible = true
  9055.             Draw()
  9056.             sleep(0.15)
  9057.             self.Visible = false
  9058.             Draw()
  9059.             sleep(0.15)
  9060.             self.Visible = true
  9061.             Draw()
  9062.         end,
  9063.  
  9064.         Click = function(self, side, x, y)
  9065.             local items = {self.OkButton, self.CancelButton}
  9066.             local found = false
  9067.             for i, v in ipairs(items) do
  9068.                 if CheckClick(v, x, y) then
  9069.                     v:Click(side, x, y)
  9070.                     found = true
  9071.                 end
  9072.             end
  9073.             return true
  9074.         end
  9075.     }
  9076.  
  9077.     TextDialougeWindow = {
  9078.         X = 1,
  9079.         Y = 1,
  9080.         Width = 0,
  9081.         Height = 0,
  9082.         CursorPos = 1,
  9083.         Visible = true,
  9084.         CancelButton = nil,
  9085.         OkButton = nil,
  9086.         Lines = {},
  9087.         TextInput = nil,
  9088.  
  9089.         AbsolutePosition = function(self)
  9090.             return {X = self.X, Y = self.Y}
  9091.         end,
  9092.  
  9093.         Draw = function(self)
  9094.             if not self.Visible then
  9095.                 return
  9096.             end
  9097.             Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
  9098.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
  9099.             Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
  9100.             Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
  9101.  
  9102.             for i, text in ipairs(self.Lines) do
  9103.                 Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
  9104.             end
  9105.  
  9106.  
  9107.             Drawing.DrawBlankArea(self.X + 1, self.Y + self.Height - 4, self.Width - 2, 1, colours.lightGrey)
  9108.             Drawing.DrawCharacters(self.X + 2, self.Y + self.Height - 4, self.TextInput.Value, colours.black, colours.lightGrey)
  9109.             Current.CursorPos = {self.X + 2 + self.TextInput.CursorPos, self.Y + self.Height - 4}
  9110.             Current.CursorColour = colours.black
  9111.  
  9112.             self.OkButton:Draw()
  9113.             if self.CancelButton then
  9114.                 self.CancelButton:Draw()
  9115.             end
  9116.         end,
  9117.  
  9118.         Initialise = function(self, title, message, okText, cancelText, returnFunc, numerical)
  9119.             local new = {}    -- the new instance
  9120.             setmetatable( new, {__index = self} )
  9121.             new.Width = 28
  9122.             new.Lines = WrapText(message, new.Width - 2)
  9123.             new.Height = 7 + #new.Lines
  9124.             new.Return = returnFunc
  9125.             new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
  9126.             new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
  9127.             new.Title = title
  9128.             new.Visible = true
  9129.             new.Visible = true
  9130.             new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
  9131.                 if #new.TextInput.Value > 0 then
  9132.                     returnFunc(new, true, new.TextInput.Value)
  9133.                 end
  9134.             end, okText)
  9135.             if cancelText then
  9136.                 new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
  9137.                     returnFunc(new, false)
  9138.                 end, cancelText)
  9139.             end
  9140.             new.TextInput = TextInput:Initialise('', function(enter)
  9141.                 if enter then
  9142.                     new.OkButton:Click()
  9143.                 end
  9144.                 Draw()
  9145.             end, numerical)
  9146.  
  9147.             Current.Input = new.TextInput
  9148.  
  9149.             return new
  9150.         end,
  9151.  
  9152.         Show = function(self)
  9153.             Current.Window = self
  9154.             return self
  9155.         end,
  9156.  
  9157.         Close = function(self)
  9158.             Current.Window = nil
  9159.             Current.Input = nil
  9160.             self = nil
  9161.         end,
  9162.  
  9163.         Flash = function(self)
  9164.             self.Visible = false
  9165.             Draw()
  9166.             sleep(0.15)
  9167.             self.Visible = true
  9168.             Draw()
  9169.             sleep(0.15)
  9170.             self.Visible = false
  9171.             Draw()
  9172.             sleep(0.15)
  9173.             self.Visible = true
  9174.             Draw()
  9175.         end,
  9176.  
  9177.         Click = function(self, side, x, y)
  9178.             local items = {self.OkButton, self.CancelButton}
  9179.             local found = false
  9180.             for i, v in ipairs(items) do
  9181.                 if CheckClick(v, x, y) then
  9182.                     v:Click(side, x, y)
  9183.                     found = true
  9184.                 end
  9185.             end
  9186.             return true
  9187.         end
  9188.     }
  9189.  
  9190.     function PrintCentered(text, y)
  9191.         local w, h = term.getSize()
  9192.         x = math.ceil(math.ceil((w / 2) - (#text / 2)), 0)+1
  9193.         term.setCursorPos(x, y)
  9194.         print(text)
  9195.     end
  9196.  
  9197.     function DoVanillaClose()
  9198.         term.setBackgroundColour(colours.black)
  9199.         term.setTextColour(colours.white)
  9200.         term.clear()
  9201.         term.setCursorPos(1, 1)
  9202.         PrintCentered("Thanks for using Ink!", (Drawing.Screen.Height/2)-1)
  9203.         term.setTextColour(colours.lightGrey)
  9204.         PrintCentered("Word Proccessor for ComputerCraft", (Drawing.Screen.Height/2))
  9205.         term.setTextColour(colours.white)
  9206.         PrintCentered("(c) oeed 2014", (Drawing.Screen.Height/2)+3)
  9207.         term.setCursorPos(1, Drawing.Screen.Height)
  9208.         home()
  9209.     end
  9210.  
  9211.     function Close()
  9212.         if isQuitting or not Current.Document or not Current.Modified then
  9213.             if not OneOS then
  9214.                 DoVanillaClose()
  9215.             end
  9216.             return true
  9217.         else
  9218.             local _w = ButtonDialougeWindow:Initialise('Quit Ink?', 'You have unsaved changes, do you want to quit anyway?', 'Quit', 'Cancel', function(window, success)
  9219.                 if success then
  9220.                     if OneOS then
  9221.                         OneOS.Close(true)
  9222.                     else
  9223.                         DoVanillaClose()
  9224.                     end
  9225.                 end
  9226.                 window:Close()
  9227.                 Draw()
  9228.             end):Show()
  9229.             --it's hacky but it works
  9230.             os.queueEvent('mouse_click', 1, _w.X, _w.Y)
  9231.             return false
  9232.         end
  9233.     end
  9234.  
  9235.     if OneOS then
  9236.         OneOS.CanClose = function()
  9237.             return Close()
  9238.         end
  9239.     end
  9240.  
  9241.     Initialise()
  9242. end
  9243.  
  9244. -- Sketch (OEED)
  9245. function sketch()
  9246.     if OneOS then
  9247.         --running under OneOS
  9248.         OneOS.ToolBarColour = colours.grey
  9249.         OneOS.ToolBarTextColour = colours.white
  9250.     end
  9251.  
  9252.     colours.transparent = -1
  9253.     colors.transparent = -1
  9254.  
  9255.     --APIS--
  9256.  
  9257.     --This is my drawing API, is is pretty much identical to what drives OneOS, PearOS, etc.
  9258.     local _w, _h = term.getSize()
  9259.  
  9260.     local round = function(num, idp)
  9261.         local mult = 10^(idp or 0)
  9262.         return math.floor(num * mult + 0.5) / mult
  9263.     end
  9264.  
  9265.     Clipboard = {
  9266.         Content = nil,
  9267.         Type = nil,
  9268.         IsCut = false,
  9269.  
  9270.         Empty = function()
  9271.             Clipboard.Content = nil
  9272.             Clipboard.Type = nil
  9273.             Clipboard.IsCut = false
  9274.         end,
  9275.  
  9276.         isEmpty = function()
  9277.             return Clipboard.Content == nil
  9278.         end,
  9279.  
  9280.         Copy = function(content, _type)
  9281.             Clipboard.Content = content
  9282.             Clipboard.Type = _type or 'generic'
  9283.             Clipboard.IsCut = false
  9284.         end,
  9285.  
  9286.         Cut = function(content, _type)
  9287.             Clipboard.Content = content
  9288.             Clipboard.Type = _type or 'generic'
  9289.             Clipboard.IsCut = true
  9290.         end,
  9291.  
  9292.         Paste = function()
  9293.             local c, t = Clipboard.Content, Clipboard.Type
  9294.             if Clipboard.IsCut then
  9295.                 Clipboard.Empty()
  9296.             end
  9297.             return c, t
  9298.         end
  9299.     }
  9300.  
  9301.     if OneOS and OneOS.Clipboard then
  9302.         Clipboard = OneOS.Clipboard
  9303.     end
  9304.  
  9305.     Drawing = {
  9306.        
  9307.         Screen = {
  9308.             Width = _w,
  9309.             Height = _h
  9310.         },
  9311.  
  9312.         DrawCharacters = function (x, y, characters, textColour,bgColour)
  9313.             Drawing.WriteStringToBuffer(x, y, characters, textColour, bgColour)
  9314.         end,
  9315.        
  9316.         DrawBlankArea = function (x, y, w, h, colour)
  9317.             Drawing.DrawArea (x, y, w, h, " ", 1, colour)
  9318.         end,
  9319.  
  9320.         DrawArea = function (x, y, w, h, character, textColour, bgColour)
  9321.             --width must be greater than 1, other wise we get a stack overflow
  9322.             if w < 0 then
  9323.                 w = w * -1
  9324.             elseif w == 0 then
  9325.                 w = 1
  9326.             end
  9327.  
  9328.             for ix = 1, w do
  9329.                 local currX = x + ix - 1
  9330.                 for iy = 1, h do
  9331.                     local currY = y + iy - 1
  9332.                     Drawing.WriteToBuffer(currX, currY, character, textColour, bgColour)
  9333.                 end
  9334.             end
  9335.         end,
  9336.  
  9337.         DrawImage = function(_x,_y,tImage, w, h)
  9338.             if tImage then
  9339.                 for y = 1, h do
  9340.                     if not tImage[y] then
  9341.                         break
  9342.                     end
  9343.                     for x = 1, w do
  9344.                         if not tImage[y][x] then
  9345.                             break
  9346.                         end
  9347.                         local bgColour = tImage[y][x]
  9348.                         local textColour = tImage.textcol[y][x] or colours.white
  9349.                         local char = tImage.text[y][x]
  9350.                         Drawing.WriteToBuffer(x+_x-1, y+_y-1, char, textColour, bgColour)
  9351.                     end
  9352.                 end
  9353.             elseif w and h then
  9354.                 Drawing.DrawBlankArea(x, y, w, h, colours.green)
  9355.             end
  9356.         end,
  9357.         --using .nft
  9358.         LoadImage = function(path)
  9359.             local image = {
  9360.                 text = {},
  9361.                 textcol = {}
  9362.             }
  9363.             local _fs = fs
  9364.             if OneOS then
  9365.                 _fs = OneOS.FS
  9366.             end
  9367.             if _fs.exists(path) then
  9368.                 local _open = io.open
  9369.                 if OneOS then
  9370.                     _open = OneOS.IO.open
  9371.                 end
  9372.                 local file = _open(path, "r")
  9373.                 local sLine = file:read()
  9374.                 local num = 1
  9375.                 while sLine do  
  9376.                         table.insert(image, num, {})
  9377.                         table.insert(image.text, num, {})
  9378.                         table.insert(image.textcol, num, {})
  9379.                                                    
  9380.                         --As we're no longer 1-1, we keep track of what index to write to
  9381.                         local writeIndex = 1
  9382.                         --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour
  9383.                         local bgNext, fgNext = false, false
  9384.                         --The current background and foreground colours
  9385.                         local currBG, currFG = nil,nil
  9386.                         for i=1,#sLine do
  9387.                                 local nextChar = string.sub(sLine, i, i)
  9388.                                 if nextChar:byte() == 30 then
  9389.                                     bgNext = true
  9390.                                 elseif nextChar:byte() == 31 then
  9391.                                     fgNext = true
  9392.                                 elseif bgNext then
  9393.                                     currBG = Drawing.GetColour(nextChar)
  9394.                                     bgNext = false
  9395.                                 elseif fgNext then
  9396.                                     currFG = Drawing.GetColour(nextChar)
  9397.                                     fgNext = false
  9398.                                 else
  9399.                                     if nextChar ~= " " and currFG == nil then
  9400.                                            currFG = colours.white
  9401.                                     end
  9402.                                     image[num][writeIndex] = currBG
  9403.                                     image.textcol[num][writeIndex] = currFG
  9404.                                     image.text[num][writeIndex] = nextChar
  9405.                                     writeIndex = writeIndex + 1
  9406.                                 end
  9407.                         end
  9408.                         num = num+1
  9409.                         sLine = file:read()
  9410.                 end
  9411.                 file:close()
  9412.             end
  9413.             return image
  9414.         end,
  9415.  
  9416.         DrawCharactersCenter = function(x, y, w, h, characters, textColour,bgColour)
  9417.             w = w or Drawing.Screen.Width
  9418.             h = h or Drawing.Screen.Height
  9419.             x = x or 0
  9420.             y = y or 0
  9421.             x = math.ceil((w - #characters) / 2) + x
  9422.             y = math.floor(h / 2) + y
  9423.  
  9424.             Drawing.DrawCharacters(x, y, characters, textColour, bgColour)
  9425.         end,
  9426.  
  9427.         GetColour = function(hex)
  9428.             if hex == ' ' then
  9429.                 return colours.transparent
  9430.             end
  9431.             local value = tonumber(hex, 16)
  9432.             if not value then return nil end
  9433.             value = math.pow(2,value)
  9434.             return value
  9435.         end,
  9436.  
  9437.         Clear = function (_colour)
  9438.             _colour = _colour or colours.black
  9439.             Drawing.ClearBuffer()
  9440.             Drawing.DrawBlankArea(1, 1, Drawing.Screen.Width, Drawing.Screen.Height, _colour)
  9441.         end,
  9442.  
  9443.         Buffer = {},
  9444.         BackBuffer = {},
  9445.  
  9446.         DrawBuffer = function()
  9447.             for y,row in pairs(Drawing.Buffer) do
  9448.                 for x,pixel in pairs(row) do
  9449.                     local shouldDraw = true
  9450.                     local hasBackBuffer = true
  9451.                     if Drawing.BackBuffer[y] == nil or Drawing.BackBuffer[y][x] == nil or #Drawing.BackBuffer[y][x] ~= 3 then
  9452.                         hasBackBuffer = false
  9453.                     end
  9454.                     if hasBackBuffer and Drawing.BackBuffer[y][x][1] == Drawing.Buffer[y][x][1] and Drawing.BackBuffer[y][x][2] == Drawing.Buffer[y][x][2] and Drawing.BackBuffer[y][x][3] == Drawing.Buffer[y][x][3] then
  9455.                         shouldDraw = false
  9456.                     end
  9457.                     if shouldDraw then
  9458.                         term.setBackgroundColour(pixel[3])
  9459.                         term.setTextColour(pixel[2])
  9460.                         term.setCursorPos(x, y)
  9461.                         term.write(pixel[1])
  9462.                     end
  9463.                 end
  9464.             end
  9465.             Drawing.BackBuffer = Drawing.Buffer
  9466.             Drawing.Buffer = {}
  9467.             term.setCursorPos(1,1)
  9468.         end,
  9469.  
  9470.         ClearBuffer = function()
  9471.             Drawing.Buffer = {}
  9472.         end,
  9473.  
  9474.         WriteStringToBuffer = function (x, y, characters, textColour,bgColour)
  9475.             for i = 1, #characters do
  9476.                 local character = characters:sub(i,i)
  9477.                 Drawing.WriteToBuffer(x + i - 1, y, character, textColour, bgColour)
  9478.             end
  9479.         end,
  9480.  
  9481.         WriteToBuffer = function(x, y, character, textColour,bgColour)
  9482.             x = round(x)
  9483.             y = round(y)
  9484.             if bgColour == colours.transparent then
  9485.                 Drawing.Buffer[y] = Drawing.Buffer[y] or {}
  9486.                 Drawing.Buffer[y][x] = Drawing.Buffer[y][x] or {"", colours.white, colours.black}
  9487.                 Drawing.Buffer[y][x][1] = character
  9488.                 Drawing.Buffer[y][x][2] = textColour
  9489.             else
  9490.                 Drawing.Buffer[y] = Drawing.Buffer[y] or {}
  9491.                 Drawing.Buffer[y][x] = {character, textColour, bgColour}
  9492.             end
  9493.         end,
  9494.     }
  9495.  
  9496.     --Colour Deffitions--
  9497.     UIColours = {
  9498.         Toolbar = colours.grey,
  9499.         ToolbarText = colours.lightGrey,
  9500.         ToolbarSelected = colours.lightBlue,
  9501.         ControlText = colours.white,
  9502.         ToolbarItemTitle = colours.black,
  9503.         Background = colours.lightGrey,
  9504.         MenuBackground = colours.white,
  9505.         MenuText = colours.black,
  9506.         MenuSeparatorText = colours.grey,
  9507.         MenuDisabledText = colours.lightGrey,
  9508.         Shadow = colours.grey,
  9509.         TransparentBackgroundOne = colours.white,
  9510.         TransparentBackgroundTwo = colours.lightGrey,
  9511.         MenuBarActive = colours.white
  9512.     }
  9513.  
  9514.     --Lists--
  9515.     Current = {
  9516.         Artboard = nil,
  9517.         Layer = nil,
  9518.         Tool = nil,
  9519.         ToolSize = 1,
  9520.         Toolbar = nil,
  9521.         Colour = colours.lightBlue,
  9522.         Menu = nil,
  9523.         MenuBar = nil,
  9524.         Window = nil,
  9525.         Input = nil,
  9526.         CursorPos = {1,1},
  9527.         CursorColour = colours.black,
  9528.         InterfaceVisible = true,
  9529.         Selection = {},
  9530.         SelectionDrawTimer = nil,
  9531.         HandDragStart = {},
  9532.         Modified = false,
  9533.     }
  9534.  
  9535.     local isQuitting = false
  9536.  
  9537.     function PrintCentered(text, y)
  9538.         local w, h = term.getSize()
  9539.         x = math.ceil(math.ceil((w / 2) - (#text / 2)), 0)+1
  9540.         term.setCursorPos(x, y)
  9541.         print(text)
  9542.     end
  9543.  
  9544.     function DoVanillaClose()
  9545.         term.setBackgroundColour(colours.black)
  9546.         term.setTextColour(colours.white)
  9547.         term.clear()
  9548.         term.setCursorPos(1, 1)
  9549.         PrintCentered("Thanks for using Sketch!", (Drawing.Screen.Height/2)-1)
  9550.         term.setTextColour(colours.lightGrey)
  9551.         PrintCentered("Photoshop Inspired Image Editor for ComputerCraft", (Drawing.Screen.Height/2))
  9552.         term.setTextColour(colours.white)
  9553.         PrintCentered("(c) oeed 2013 - 2014", (Drawing.Screen.Height/2)+3)
  9554.         term.setCursorPos(1, Drawing.Screen.Height)
  9555.         home()
  9556.     end
  9557.  
  9558.     function Close()
  9559.         if isQuitting or not Current.Artboard or not Current.Modified then
  9560.             if not OneOS then
  9561.                 DoVanillaClose()
  9562.             end
  9563.             return true
  9564.         else
  9565.             local _w = ButtonDialougeWindow:Initialise('Quit Sketch?', 'You have unsaved changes, do you want to quit anyway?', 'Quit', 'Cancel', function(window, success)
  9566.                 if success then
  9567.                     if OneOS then
  9568.                         OneOS.Close(true)
  9569.                     else
  9570.                         DoVanillaClose()
  9571.                     end
  9572.                 end
  9573.                 window:Close()
  9574.                 Draw()
  9575.             end):Show()
  9576.             --it's hacky but it works
  9577.             os.queueEvent('mouse_click', 1, _w.X, _w.Y)
  9578.             return false
  9579.         end
  9580.     end
  9581.  
  9582.     if OneOS then
  9583.         OneOS.CanClose = function()
  9584.             return Close()
  9585.         end
  9586.     end
  9587.  
  9588.     Lists = {
  9589.         Artboards = {},
  9590.         Interface = {
  9591.             Toolbars = {}
  9592.         }  
  9593.     }
  9594.  
  9595.     Events = {
  9596.        
  9597.     }
  9598.  
  9599.     --Setters--
  9600.  
  9601.     function SetColour(colour)
  9602.         Current.Colour = colour
  9603.         Draw()
  9604.     end
  9605.  
  9606.     function SetTool(tool)
  9607.         if tool and tool.Select and tool:Select() then
  9608.             Current.Input = nil
  9609.             Current.Tool = tool
  9610.             return true
  9611.         end
  9612.         return false
  9613.     end
  9614.  
  9615.     function GetAbsolutePosition(object)
  9616.         local obj = object
  9617.         local i = 0
  9618.         local x = 1
  9619.         local y = 1
  9620.         while true do
  9621.             x = x + obj.X - 1
  9622.             y = y + obj.Y - 1
  9623.  
  9624.             if not obj.Parent then
  9625.                 return {X = x, Y = y}
  9626.             end
  9627.  
  9628.             obj = obj.Parent
  9629.  
  9630.             if i > 32 then
  9631.                 return {X = 1, Y = 1}
  9632.             end
  9633.  
  9634.             i = i + 1
  9635.         end
  9636.  
  9637.     end
  9638.  
  9639.     --Object Defintions--
  9640.  
  9641.     Pixel = {
  9642.         TextColour = colours.black,
  9643.         BackgroundColour = colours.white,
  9644.         Character = " ",
  9645.         Layer = nil,
  9646.  
  9647.         Draw = function(self, x, y)
  9648.             if self.BackgroundColour ~= colours.transparent or self.Character ~= ' ' then
  9649.                 Drawing.WriteToBuffer(self.Layer.Artboard.X + x - 1, self.Layer.Artboard.Y + y - 1, self.Character, self.TextColour, self.BackgroundColour)
  9650.             end
  9651.         end,
  9652.  
  9653.         Initialise = function(self, textColour, backgroundColour, character, layer)
  9654.             local new = {}    -- the new instance
  9655.             setmetatable( new, {__index = self} )
  9656.             new.TextColour = textColour or self.TextColour
  9657.             new.BackgroundColour = backgroundColour or self.BackgroundColour
  9658.             new.Character = character or self.Character
  9659.             new.Layer = layer
  9660.             return new
  9661.         end,
  9662.  
  9663.         Set = function(self, textColour, backgroundColour, character)
  9664.             self.TextColour = textColour or self.TextColour
  9665.             self.BackgroundColour = backgroundColour or self.BackgroundColour
  9666.             self.Character = character or self.Character
  9667.         end
  9668.     }
  9669.  
  9670.     Layer = {
  9671.         Name = "",
  9672.         Pixels = {
  9673.  
  9674.         },
  9675.         Artboard = nil,
  9676.         BackgroundColour = colours.white,
  9677.         Visible = true,
  9678.         Index = 1,
  9679.  
  9680.         Draw = function(self)
  9681.             if self.Visible then
  9682.                 for x = 1, self.Artboard.Width do
  9683.                     for y = 1, self.Artboard.Height do
  9684.                         self.Pixels[x][y]:Draw(x, y)
  9685.                     end
  9686.                 end
  9687.             end
  9688.         end,
  9689.  
  9690.         Remove = function(self)
  9691.             for i, v in ipairs(self.Artboard.Layers) do
  9692.                 if v == Current.Layer then
  9693.                     Current.Artboard.Layers[i] = nil
  9694.                     Current.Layer = Current.Artboard.Layers[1]
  9695.                     ModuleNamed('Layers'):Update()
  9696.                 end
  9697.             end
  9698.         end,
  9699.  
  9700.         Initialise = function(self, name, backgroundColour, artboard, index, pixels)
  9701.             local new = {}    -- the new instance
  9702.             setmetatable( new, {__index = self} )
  9703.             new.Name = name
  9704.             new.Pixels = {}
  9705.             new.BackgroundColour = backgroundColour
  9706.             new.Artboard = artboard
  9707.             new.Index = index or #artboard.Layers + 1
  9708.             if not pixels then
  9709.                 new:MakeAllBlankPixels()
  9710.             else
  9711.                 new:MakeAllBlankPixels()
  9712.                 for x, col in ipairs(pixels) do
  9713.                     for y, pixel in ipairs(col) do
  9714.                         new:SetPixel(x, y, pixel.TextColour, pixel.BackgroundColour, pixel.Character)
  9715.                     end
  9716.                 end
  9717.             end
  9718.            
  9719.             return new
  9720.         end,
  9721.  
  9722.         SetPixel = function(self, x, y, textColour, backgroundColour, character)
  9723.             textColour = textColour or Current.Colour
  9724.             backgroundColour = backgroundColour or Current.Colour
  9725.             character = character or " "
  9726.  
  9727.             if x < 1 or y < 1 or x > self.Artboard.Width or y > self.Artboard.Height then
  9728.                 return
  9729.             end
  9730.  
  9731.             if self.Pixels[x][y] then
  9732.                 self.Pixels[x][y]:Set(textColour, backgroundColour, character)
  9733.                 self.Pixels[x][y]:Draw(x,y)
  9734.             end
  9735.         end,
  9736.  
  9737.         MakePixel = function(self, x, y, backgroundColour)
  9738.             backgroundColour = backgroundColour or self.BackgroundColour           
  9739.             self.Pixels[x][y] = Pixel:Initialise(nil, backgroundColour, nil, self)
  9740.         end,
  9741.  
  9742.         MakeColumn = function(self, x)
  9743.             self.Pixels[x] = {}
  9744.         end,
  9745.  
  9746.         MakeAllBlankPixels = function(self)
  9747.             for x = 1, self.Artboard.Width do
  9748.                 if not self.Pixels[x] then
  9749.                     self:MakeColumn(x)
  9750.                 end
  9751.  
  9752.                 for y = 1, self.Artboard.Height do         
  9753.                
  9754.                     if not self.Pixels[x][y] then
  9755.                         self:MakePixel(x, y)
  9756.                     end
  9757.  
  9758.                 end
  9759.             end
  9760.         end,
  9761.  
  9762.         PixelsInSelection = function(self, cut)
  9763.             local pixels = {}
  9764.             if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
  9765.                 local point1 = Current.Selection[1]
  9766.                 local point2 = Current.Selection[2]
  9767.  
  9768.                 local size = point2 - point1
  9769.                 local cornerX = point1.x
  9770.                 local cornerY = point1.y
  9771.                 for x = 1, size.x + 1 do
  9772.                     for y = 1, size.y + 1 do
  9773.                         if not pixels[x] then
  9774.                             pixels[x] = {}
  9775.                         end
  9776.                         if not self.Pixels[cornerX + x - 1] or not self.Pixels[cornerX + x - 1][cornerY + y - 1] then
  9777.                             break
  9778.                         end
  9779.                         local pixel =  self.Pixels[cornerX + x - 1][cornerY + y - 1]
  9780.                         pixels[x][y] = Pixel:Initialise(pixel.TextColour, pixel.BackgroundColour, pixel.Character, Current.Layer)
  9781.                         if cut then
  9782.                             Current.Layer:SetPixel(cornerX + x - 1, cornerY + y - 1, nil, Current.Layer.BackgroundColour, nil)
  9783.                         end
  9784.                     end
  9785.                 end
  9786.             end
  9787.             return pixels
  9788.         end,
  9789.  
  9790.         EraseSelection = function(self)
  9791.             if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
  9792.                 local point1 = Current.Selection[1]
  9793.                 local point2 = Current.Selection[2]
  9794.  
  9795.                 local size = point2 - point1
  9796.                 local cornerX = point1.x
  9797.                 local cornerY = point1.y
  9798.                 for x = 1, size.x + 1 do
  9799.                     for y = 1, size.y + 1 do
  9800.                         Current.Layer:SetPixel(cornerX + x - 1, cornerY + y - 1, nil, Current.Layer.BackgroundColour, nil)
  9801.                     end
  9802.                 end
  9803.             end
  9804.         end,
  9805.  
  9806.         InsertPixels = function(self, pixels)
  9807.             local cornerX = Current.Selection[1].x
  9808.             local cornerY = Current.Selection[1].y
  9809.             for x, col in ipairs(pixels) do
  9810.                 for y, pixel in ipairs(col) do
  9811.                     Current.Layer:SetPixel(cornerX + x - 1, cornerY + y - 1, pixel.TextColour, pixel.BackgroundColour, pixel.Character)
  9812.                 end
  9813.             end
  9814.         end
  9815.     }
  9816.  
  9817.     Artboard = {
  9818.         X = 0,
  9819.         Y = 0,
  9820.         Name = "",
  9821.         Path = "",
  9822.         Width = 1,
  9823.         Height = 1,
  9824.         Layers = {},
  9825.         Format = nil,
  9826.         SelectionIsBlack = true,
  9827.  
  9828.         Draw = function(self)
  9829.             Drawing.DrawBlankArea(self.X + 1, self.Y + 1, self.Width, self.Height, UIColours.Shadow)
  9830.  
  9831.             local odd
  9832.             for x = 1, self.Width do
  9833.                 odd = x % 2
  9834.                 if odd == 1 then
  9835.                     odd = true
  9836.                 else
  9837.                     odd = false
  9838.                 end
  9839.                 for y = 1, self.Height do
  9840.                     if odd then
  9841.                         Drawing.WriteToBuffer(self.X + x - 1, self.Y + y - 1, ":", UIColours.TransparentBackgroundTwo, UIColours.TransparentBackgroundOne)
  9842.                     else
  9843.                         Drawing.WriteToBuffer(self.X + x - 1, self.Y + y - 1, ":", UIColours.TransparentBackgroundOne, UIColours.TransparentBackgroundTwo)
  9844.                     end
  9845.  
  9846.                     odd = not odd
  9847.                 end
  9848.             end
  9849.  
  9850.             for i, layer in ipairs(self.Layers) do
  9851.                 layer:Draw()
  9852.             end
  9853.  
  9854.             if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
  9855.                 local point1 = Current.Selection[1]
  9856.                 local point2 = Current.Selection[2]
  9857.  
  9858.                 local size = point2 - point1
  9859.  
  9860.                 local isBlack = self.SelectionIsBlack
  9861.  
  9862.                 local function c()
  9863.                     local c = colours.white
  9864.                     if isBlack then
  9865.                         c = colours.black
  9866.                     end
  9867.                     isBlack = not isBlack
  9868.                     return c
  9869.                 end
  9870.  
  9871.                 function horizontal(y)
  9872.                     Drawing.WriteToBuffer(self.X - 1 + point1.x, self.Y - 1 + y, '+', c(), colours.transparent)
  9873.                     if size.x > 0 then
  9874.                         for i = 1, size.x - 1 do
  9875.                             Drawing.WriteToBuffer(self.X - 1 + point1.x + i, self.Y - 1 + y, '-', c(), colours.transparent)
  9876.                         end
  9877.                     else
  9878.                         for i = 1, (-1 * size.x) - 1 do
  9879.                             Drawing.WriteToBuffer(self.X - 1 + point1.x - i, self.Y - 1 + y, '-', c(), colours.transparent)
  9880.                         end
  9881.                     end
  9882.  
  9883.                     Drawing.WriteToBuffer(self.X - 1 + point1.x + size.x, self.Y - 1 + y, '+', c(), colours.transparent)
  9884.                 end
  9885.  
  9886.                 function vertical(x)
  9887.                     if size.y < 0 then
  9888.                         for i = 1, (-1 * size.y) - 1 do
  9889.                             Drawing.WriteToBuffer(self.X - 1 + x, self.Y - 1 + point1.y  - i, '|', c(), colours.transparent)
  9890.                         end
  9891.                     else
  9892.                         for i = 1, size.y - 1 do
  9893.                             Drawing.WriteToBuffer(self.X - 1 + x, self.Y - 1 + point1.y  + i, '|', c(), colours.transparent)
  9894.                         end
  9895.                     end
  9896.                 end
  9897.  
  9898.                 horizontal(point1.y)
  9899.                 vertical(point1.x)
  9900.                 horizontal(point1.y + size.y)
  9901.                 vertical(point1.x + size.x)
  9902.             end
  9903.         end,
  9904.  
  9905.         Initialise = function(self, name, path, width, height, format, backgroundColour, layers)
  9906.             local new = {}    -- the new instance
  9907.             setmetatable( new, {__index = self} )
  9908.             new.Y = 3
  9909.             new.X = 2
  9910.             new.Name = name
  9911.             new.Path = path
  9912.             new.Width = width
  9913.             new.Height = height
  9914.             new.Format = format
  9915.             new.Layers = {}
  9916.             if not layers then
  9917.                 new:MakeLayer('Background', backgroundColour)
  9918.             else
  9919.                 for i, layer in ipairs(layers) do
  9920.                     new:MakeLayer(layer.Name, layer.BackgroundColour, layer.Index, layer.Pixels)
  9921.                     new.Layers[i].Visible = layer.Visible
  9922.                 end
  9923.                 Current.Layer = new.Layers[#new.Layers]
  9924.             end
  9925.             return new
  9926.         end,
  9927.  
  9928.         Resize = function(self, top, bottom, left, right)
  9929.             self.Height = self.Height + top + bottom
  9930.             self.Width = self.Width + left + right
  9931.  
  9932.             for i, layer in ipairs(self.Layers) do
  9933.  
  9934.                 if left < 0 then
  9935.                     for x = 1, -left do
  9936.                         table.remove(layer.Pixels, 1)
  9937.                     end
  9938.                 end
  9939.  
  9940.                 if right < 0 then
  9941.                     for x = 1, -right do
  9942.                         table.remove(layer.Pixels, #layer.Pixels)
  9943.                     end
  9944.                 end
  9945.  
  9946.                 for x = 1, left do
  9947.                     table.insert(layer.Pixels, 1, {})
  9948.                     for y = 1, self.Height do
  9949.                         layer:MakePixel(1, y)
  9950.                     end
  9951.                 end
  9952.  
  9953.                 for x = 1, right do
  9954.                     table.insert(layer.Pixels, {})
  9955.                     for y = 1, self.Height do
  9956.                         layer:MakePixel(#layer.Pixels, y)
  9957.                     end
  9958.                 end
  9959.  
  9960.                 for y = 1, top do
  9961.                     for x = 1, self.Width do
  9962.                         table.insert(layer.Pixels[x], 1, {})
  9963.                         layer:MakePixel(x, 1)
  9964.                     end
  9965.                 end
  9966.  
  9967.                 for y = 1, bottom do
  9968.                     for x = 1, self.Width do
  9969.                         table.insert(layer.Pixels[x], {})
  9970.                         layer:MakePixel(x, #layer.Pixels[x])
  9971.                     end
  9972.                 end
  9973.  
  9974.                 if top < 0 then
  9975.                     for y = 1, -top do
  9976.                         for x = 1, self.Width do
  9977.                             table.remove(layer.Pixels[x], 1)
  9978.                         end
  9979.                     end
  9980.                 end
  9981.  
  9982.                 if bottom < 0 then
  9983.                     for y = 1, -bottom do
  9984.                         for x = 1, self.Width do
  9985.                             table.remove(layer.Pixels[x], #layer.Pixels[x])
  9986.                         end
  9987.                     end
  9988.                 end
  9989.             end
  9990.         end,
  9991.  
  9992.         MakeLayer = function(self, name, backgroundColour, index, pixels)
  9993.             backgroundColour = backgroundColour or colours.white
  9994.             name = name or "Layer"
  9995.             local layer = Layer:Initialise(name, backgroundColour, self, index, pixels)
  9996.             table.insert(self.Layers, layer)
  9997.             Current.Layer = layer
  9998.             ModuleNamed('Layers'):Update()
  9999.             return layer
  10000.         end,
  10001.  
  10002.         New = function(self, name, path, width, height, format, backgroundColour, layers)
  10003.             local new = self:Initialise(name, path, width, height, format, backgroundColour, layers)
  10004.             table.insert(Lists.Artboards, new)
  10005.             Current.Artboard = new
  10006.             --new:Save()
  10007.             return new
  10008.         end,
  10009.  
  10010.         Save = function(self, path)
  10011.             Current.Artboard = self
  10012.             path = path or self.Path
  10013.             local _open = io.open
  10014.             if OneOS then
  10015.                 _open = OneOS.IO.open
  10016.             end
  10017.             local file = _open(path, "w", true)
  10018.             if self.Format == '.skch' then
  10019.                 file:write(textutils.serialize(SaveSKCH()))
  10020.             else
  10021.                 local lines = {}
  10022.                 if self.Format == '.nfp' then
  10023.                     lines = SaveNFP()
  10024.                 elseif self.Format == '.nft' then
  10025.                     lines = SaveNFT()
  10026.                 end
  10027.  
  10028.                 for i, line in ipairs(lines) do
  10029.                     file:write(line.."\n")
  10030.                 end
  10031.             end
  10032.             file:close()
  10033.             Current.Modified = false
  10034.         end,
  10035.  
  10036.         Click = function(self, side, x, y, drag)
  10037.             if Current.Tool and Current.Layer and Current.Layer.Visible then
  10038.                 Current.Tool:Use(x, y, side, drag)
  10039.                 Current.Modified = true
  10040.                 return true
  10041.             end
  10042.         end
  10043.     }
  10044.  
  10045.     Toolbar = {
  10046.         X = 0,
  10047.         Y = 0,
  10048.         Width = 0,
  10049.         ExpandedWidth = 14,
  10050.         ClosedWidth = 2,
  10051.         Height = 0,
  10052.         Expanded = true,
  10053.         ToolbarItems = {},
  10054.  
  10055.         AbsolutePosition = function(self)
  10056.             return {X = self.X, Y = self.Y}
  10057.         end,
  10058.  
  10059.         Draw = function(self)
  10060.             self:CalculateToolbarItemPositions()
  10061.             --Drawing.DrawArea(self.X - 1, self.Y, 1, self.Height, "|", UIColours.ToolbarText, UIColours.Background)
  10062.  
  10063.            
  10064.  
  10065.             --if not Current.Window then
  10066.                 Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.Toolbar)
  10067.             --else
  10068.             --  Drawing.DrawArea(self.X, self.Y, self.Width, self.Height, '|', colours.lightGrey, UIColours.Toolbar)
  10069.             --end
  10070.             for i, toolbarItem in ipairs(self.ToolbarItems) do
  10071.                 toolbarItem:Draw()
  10072.             end
  10073.         end,
  10074.  
  10075.         Initialise = function(self, side, expanded)
  10076.             local new = {}    -- the new instance
  10077.             setmetatable( new, {__index = self} )
  10078.             new.Expanded = expanded
  10079.  
  10080.             if expanded then
  10081.                 new.Width = new.ExpandedWidth
  10082.             else
  10083.                 new.Width = new.ClosedWidth
  10084.             end
  10085.  
  10086.             if side == 'right' then
  10087.                 new.X = Drawing.Screen.Width - new.Width + 1
  10088.             end
  10089.  
  10090.             if side == 'right' or side == 'left' then
  10091.                 new.Height = Drawing.Screen.Width
  10092.             end
  10093.  
  10094.             new.Y = 1
  10095.  
  10096.             return new
  10097.         end,
  10098.  
  10099.         AddToolbarItem = function(self, item)
  10100.             table.insert(self.ToolbarItems, item)
  10101.             self:CalculateToolbarItemPositions()
  10102.         end,
  10103.  
  10104.         CalculateToolbarItemPositions = function(self)
  10105.             local currY = 1
  10106.             for i, toolbarItem in ipairs(self.ToolbarItems) do
  10107.                 toolbarItem.Y = currY
  10108.                 currY = currY + toolbarItem.Height
  10109.             end
  10110.         end,
  10111.  
  10112.         Update = function(self)
  10113.             for i, toolbarItem in ipairs(self.ToolbarItems) do
  10114.                 if toolbarItem.Module.Update then
  10115.                     toolbarItem.Module:Update(toolbarItem)
  10116.                 end
  10117.             end
  10118.         end,
  10119.  
  10120.         New = function(self, side, expanded)
  10121.             local new = self:Initialise(side, expanded)
  10122.  
  10123.             --new:AddToolbarItem(ToolbarItem:Initialise("Colours", nil, true, new))
  10124.             --new:AddToolbarItem(ToolbarItem:Initialise("IDK", true, new))
  10125.  
  10126.             table.insert(Lists.Interface.Toolbars, new)
  10127.             return new
  10128.         end,
  10129.  
  10130.         Click = function(self, side, x, y)
  10131.             return false
  10132.         end
  10133.     }
  10134.  
  10135.     ToolbarItem = {
  10136.         X = 0,
  10137.         Y = 0,
  10138.         Width = 0,
  10139.         Height = 0,
  10140.         ExpandedHeight = 5,
  10141.         Expanded = true,
  10142.         Toolbar = nil,
  10143.         Title = "",
  10144.         MenuIcon = "=",
  10145.         ExpandedIcon = "+",
  10146.         ContractIcon = "-",
  10147.         ContentView = nil,
  10148.         Module = nil,
  10149.         MenuItems = nil,
  10150.  
  10151.         Draw = function(self)
  10152.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, UIColours.ToolbarItemTitle)
  10153.             Drawing.DrawCharacters(self.X + 1, self.Y, self.Title, UIColours.ToolbarText, UIColours.ToolbarItemTitle)
  10154.  
  10155.             Drawing.DrawCharacters(self.X + self.Width - 1, self.Y, self.MenuIcon, UIColours.ToolbarText, UIColours.ToolbarItemTitle)
  10156.  
  10157.             local expandContractIcon = self.ContractIcon
  10158.             if not self.Expanded then
  10159.                 expandContractIcon = self.ExpandedIcon
  10160.             end
  10161.  
  10162.             if self.Expanded and self.ContentView then
  10163.                 self.ContentView:Draw()
  10164.             end
  10165.  
  10166.             Drawing.DrawCharacters(self.X + self.Width - 2, self.Y, expandContractIcon, UIColours.ToolbarText, UIColours.ToolbarItemTitle)
  10167.         end,
  10168.  
  10169.         Initialise = function(self, module, height, expanded, toolbar, menuItems)
  10170.             local new = {}    -- the new instance
  10171.             setmetatable( new, {__index = self} )
  10172.             new.Expanded = expanded
  10173.             new.Title = module.Title
  10174.             new.Width = toolbar.Width
  10175.             new.Height = height or 5
  10176.             new.Module = module
  10177.             new.MenuItems = menuItems or {}
  10178.             table.insert(new.MenuItems,
  10179.                 {
  10180.                     Title = 'Shrink',
  10181.                     Click = function()
  10182.                         new:ToggleExpanded()
  10183.                     end
  10184.                 })
  10185.             new.ExpandedHeight = height or 5
  10186.             new.Y = 1
  10187.             new.X = toolbar.X
  10188.             new.ContentView = ContentView:Initialise(1, 2, new.Width, new.Height - 1, nil, new)
  10189.             new.Toolbar = toolbar
  10190.  
  10191.             return new
  10192.         end,
  10193.  
  10194.         ToggleExpanded = function(self)
  10195.             self.Expanded = not self.Expanded
  10196.             if self.Expanded then
  10197.                 self.Height = self.ExpandedHeight
  10198.             else
  10199.                 self.Height = 1
  10200.             end
  10201.         end,
  10202.  
  10203.         Click = function(self, side, x, y)
  10204.             local pos = GetAbsolutePosition(self)
  10205.             if x == self.Width and y == 1 then
  10206.                 local expandContract = "Shrink"
  10207.  
  10208.                 if not self.Expanded then
  10209.                     expandContract = "Expand"
  10210.                 end
  10211.                 self.MenuItems[#self.MenuItems].Title = expandContract
  10212.                 Menu:New(pos.X + x, pos.Y + y, self.MenuItems, self)
  10213.                 return true
  10214.             elseif x == self.Width - 1 and y == 1 then
  10215.                 self:ToggleExpanded()
  10216.                 return true
  10217.             elseif y ~= 1 then
  10218.                 return self.ContentView:Click(side,  x - self.ContentView.X + 1,  y - self.ContentView.Y + 1)
  10219.             end
  10220.  
  10221.             return false
  10222.         end
  10223.     }
  10224.  
  10225.     ContentView = {
  10226.         X = 1,
  10227.         Y = 1,
  10228.         Width = 0,
  10229.         Height = 0,
  10230.         Parent = nil,
  10231.         Views = {},
  10232.  
  10233.         AbsolutePosition = function(self)
  10234.             return self.Parent:AbsolutePosition()
  10235.         end,
  10236.  
  10237.         Draw = function(self)
  10238.             for i, view in ipairs(self.Views) do
  10239.                 view:Draw()
  10240.             end
  10241.         end,
  10242.  
  10243.         Initialise = function(self, x, y, width, height, views, parent)
  10244.             local new = {}    -- the new instance
  10245.             setmetatable( new, {__index = self} )
  10246.             new.Width = width
  10247.             new.Height = height
  10248.             new.Y = y
  10249.             new.X = x
  10250.             new.Views = views or {}
  10251.             new.Parent = parent
  10252.             return new
  10253.         end,
  10254.  
  10255.         Click = function(self, side, x, y)
  10256.             for k, view in pairs(self.Views) do
  10257.                 if DoClick(view, side, x, y) then
  10258.                     return true
  10259.                 end
  10260.             end
  10261.         end
  10262.     }
  10263.  
  10264.     Button = {
  10265.         X = 1,
  10266.         Y = 1,
  10267.         Width = 0,
  10268.         Height = 0,
  10269.         BackgroundColour = colours.lightGrey,
  10270.         TextColour = colours.white,
  10271.         ActiveBackgroundColour = colours.lightGrey,
  10272.         Text = "",
  10273.         Parent = nil,
  10274.         _Click = nil,
  10275.         Toggle = nil,
  10276.  
  10277.         AbsolutePosition = function(self)
  10278.             return self.Parent:AbsolutePosition()
  10279.         end,
  10280.  
  10281.         Draw = function(self)
  10282.             local bg = self.BackgroundColour
  10283.             local tc = self.TextColour
  10284.             if type(bg) == 'function' then
  10285.                 bg = bg()
  10286.             end
  10287.  
  10288.             if self.Toggle then
  10289.                 tc = UIColours.MenuBarActive
  10290.                 bg = self.ActiveBackgroundColour
  10291.             end
  10292.  
  10293.             local pos = GetAbsolutePosition(self)
  10294.             Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, bg)
  10295.             Drawing.DrawCharactersCenter(pos.X, pos.Y, self.Width, self.Height, self.Text, tc, bg)
  10296.         end,
  10297.  
  10298.         Initialise = function(self, x, y, width, height, backgroundColour, parent, click, text, textColour, toggle, activeBackgroundColour)
  10299.             local new = {}    -- the new instance
  10300.             setmetatable( new, {__index = self} )
  10301.             height = height or 1
  10302.             new.Width = width or #text + 2
  10303.             new.Height = height
  10304.             new.Y = y
  10305.             new.X = x
  10306.             new.Text = text or ""
  10307.             new.BackgroundColour = backgroundColour or colours.lightGrey
  10308.             new.TextColour = textColour or colours.white
  10309.             new.ActiveBackgroundColour = activeBackgroundColour or colours.lightGrey
  10310.             new.Parent = parent
  10311.             new._Click = click
  10312.             new.Toggle = toggle
  10313.             return new
  10314.         end,
  10315.  
  10316.         Click = function(self, side, x, y)
  10317.             if self._Click then
  10318.                 if self:_Click(side, x, y, not self.Toggle) ~= false and self.Toggle ~= nil then
  10319.                     self.Toggle = not self.Toggle
  10320.                     Draw()
  10321.                 end
  10322.                 return true
  10323.             else
  10324.                 return false
  10325.             end
  10326.         end
  10327.     }
  10328.  
  10329.     TextBox = {
  10330.         X = 1,
  10331.         Y = 1,
  10332.         Width = 0,
  10333.         Height = 0,
  10334.         BackgroundColour = colours.lightGrey,
  10335.         TextColour = colours.black,
  10336.         Parent = nil,
  10337.         TextInput = nil,
  10338.  
  10339.         AbsolutePosition = function(self)
  10340.             return self.Parent:AbsolutePosition()
  10341.         end,
  10342.  
  10343.         Draw = function(self)      
  10344.             local pos = GetAbsolutePosition(self)
  10345.             Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, self.BackgroundColour)
  10346.             local text = self.TextInput.Value
  10347.             if #text > (self.Width - 2) then
  10348.                 text = text:sub(#text-(self.Width - 3))
  10349.                 if Current.Input == self.TextInput then
  10350.                     Current.CursorPos = {pos.X + 1 + self.Width-2, pos.Y}
  10351.                 end
  10352.             else
  10353.                 if Current.Input == self.TextInput then
  10354.                     Current.CursorPos = {pos.X + 1 + self.TextInput.CursorPos, pos.Y}
  10355.                 end
  10356.             end
  10357.             Drawing.DrawCharacters(pos.X + 1, pos.Y, text, self.TextColour, self.BackgroundColour)
  10358.  
  10359.             term.setCursorBlink(true)
  10360.            
  10361.             Current.CursorColour = self.TextColour
  10362.         end,
  10363.  
  10364.         Initialise = function(self, x, y, width, height, parent, text, backgroundColour, textColour, done, numerical)
  10365.             local new = {}    -- the new instance
  10366.             setmetatable( new, {__index = self} )
  10367.             height = height or 1
  10368.             new.Width = width or #text + 2
  10369.             new.Height = height
  10370.             new.Y = y
  10371.             new.X = x
  10372.             new.TextInput = TextInput:Initialise(text or '', function(key)
  10373.                 if done then
  10374.                     done(key)
  10375.                 end
  10376.                 Draw()
  10377.             end, numerical)
  10378.             new.BackgroundColour = backgroundColour or colours.lightGrey
  10379.             new.TextColour = textColour or colours.black
  10380.             new.Parent = parent
  10381.             return new
  10382.         end,
  10383.  
  10384.         Click = function(self, side, x, y)
  10385.             Current.Input = self.TextInput
  10386.             self:Draw()
  10387.         end
  10388.     }
  10389.  
  10390.     TextInput = {
  10391.         Value = "",
  10392.         Change = nil,
  10393.         CursorPos = nil,
  10394.         Numerical = false,
  10395.  
  10396.         Initialise = function(self, value, change, numerical)
  10397.             local new = {}    -- the new instance
  10398.             setmetatable( new, {__index = self} )
  10399.             new.Value = value
  10400.             new.Change = change
  10401.             new.CursorPos = #value
  10402.             new.Numerical = numerical
  10403.             return new
  10404.         end,
  10405.  
  10406.         Char = function(self, char)
  10407.             if self.Numerical then
  10408.                 char = tostring(tonumber(char))
  10409.             end
  10410.             if char == 'nil' then
  10411.                 return
  10412.             end
  10413.             self.Value = string.sub(self.Value, 1, self.CursorPos ) .. char .. string.sub( self.Value, self.CursorPos + 1 )
  10414.            
  10415.             self.CursorPos = self.CursorPos + 1
  10416.             self.Change(key)
  10417.         end,
  10418.  
  10419.         Key = function(self, key)
  10420.             if key == keys.enter then
  10421.                 self.Change(key)       
  10422.             elseif key == keys.left then
  10423.                 -- Left
  10424.                 if self.CursorPos > 0 then
  10425.                     self.CursorPos = self.CursorPos - 1
  10426.                     self.Change(key)
  10427.                 end
  10428.                
  10429.             elseif key == keys.right then
  10430.                 -- Right               
  10431.                 if self.CursorPos < string.len(self.Value) then
  10432.                     self.CursorPos = self.CursorPos + 1
  10433.                     self.Change(key)
  10434.                 end
  10435.            
  10436.             elseif key == keys.backspace then
  10437.                 -- Backspace
  10438.                 if self.CursorPos > 0 then
  10439.                     self.Value = string.sub( self.Value, 1, self.CursorPos - 1 ) .. string.sub( self.Value, self.CursorPos + 1 )
  10440.                     self.CursorPos = self.CursorPos - 1
  10441.                 end
  10442.                 self.Change(key)
  10443.             elseif key == keys.home then
  10444.                 -- Home
  10445.                 self.CursorPos = 0
  10446.                 self.Change(key)
  10447.             elseif key == keys.delete then
  10448.                 if self.CursorPos < string.len(self.Value) then
  10449.                     self.Value = string.sub( self.Value, 1, self.CursorPos ) .. string.sub( self.Value, self.CursorPos + 2 )               
  10450.                     self.Change(key)
  10451.                 end
  10452.             elseif key == keys["end"] then
  10453.                 -- End
  10454.                 self.CursorPos = string.len(self.Value)
  10455.                 self.Change(key)
  10456.             end
  10457.         end
  10458.     }
  10459.  
  10460.     LayerItem = {
  10461.         X = 1,
  10462.         Y = 1,
  10463.         Parent = nil,
  10464.         Layer = nil,
  10465.  
  10466.         Draw = function(self)
  10467.             self.Y = self.Layer.Index
  10468.  
  10469.             local pos = GetAbsolutePosition(self)
  10470.  
  10471.             local tc = colours.lightGrey
  10472.  
  10473.             if Current.Layer == self.Layer then
  10474.                 tc = colours.white
  10475.             end
  10476.  
  10477.             Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, UIColours.Toolbar)
  10478.            
  10479.             Drawing.DrawCharacters(pos.X + 3, pos.Y, self.Layer.Name, tc, UIColours.Toolbar)
  10480.  
  10481.             if self.Layer.Visible then
  10482.                 Drawing.DrawCharacters(pos.X + 1, pos.Y, "@", tc, UIColours.Toolbar)
  10483.             else
  10484.                 Drawing.DrawCharacters(pos.X + 1, pos.Y, "X", tc, UIColours.Toolbar)
  10485.             end
  10486.  
  10487.         end,
  10488.  
  10489.         Initialise = function(self, layer, parent)
  10490.             local new = {}    -- the new instance
  10491.             setmetatable( new, {__index = self} )
  10492.             new.Width = parent.Width
  10493.             new.Height = 1
  10494.             new.Y = 1
  10495.             new.X = 1
  10496.             new.Layer = layer
  10497.             new.Parent = parent
  10498.             return new
  10499.         end,
  10500.  
  10501.         Click = function(self, side, x, y)
  10502.             if x == 2 then
  10503.                 self.Layer.Visible = not self.Layer.Visible
  10504.             else
  10505.                 Current.Layer = self.Layer
  10506.             end
  10507.             return true
  10508.         end
  10509.     }
  10510.  
  10511.     Menu = {
  10512.         X = 0,
  10513.         Y = 0,
  10514.         Width = 0,
  10515.         Height = 0,
  10516.         Owner = nil,
  10517.         Items = {},
  10518.         RemoveTop = false,
  10519.  
  10520.         Draw = function(self)
  10521.             Drawing.DrawBlankArea(self.X + 1, self.Y + 1, self.Width, self.Height, UIColours.Shadow)
  10522.             if not self.RemoveTop then
  10523.                 Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
  10524.                 for i, item in ipairs(self.Items) do
  10525.                     if item.Separator then
  10526.                         Drawing.DrawArea(self.X, self.Y + i, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
  10527.                     else
  10528.                         local textColour = UIColours.MenuText
  10529.                         if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
  10530.                             textColour = UIColours.MenuDisabledText
  10531.                         end
  10532.                         Drawing.DrawCharacters(self.X + 1, self.Y + i, item.Title, textColour, UIColours.MenuBackground)
  10533.                     end
  10534.                 end
  10535.             else
  10536.                 Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
  10537.                 for i, item in ipairs(self.Items) do
  10538.                     if item.Separator then
  10539.                         Drawing.DrawArea(self.X, self.Y + i - 1, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
  10540.                     else
  10541.                         local textColour = UIColours.MenuText
  10542.                         if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
  10543.                             textColour = UIColours.MenuDisabledText
  10544.                         end
  10545.                         Drawing.DrawCharacters(self.X + 1, self.Y + i - 1, item.Title, textColour, UIColours.MenuBackground)
  10546.  
  10547.                         Drawing.DrawCharacters(self.X - 1 + self.Width-#item.KeyName, self.Y + i - 1, item.KeyName, textColour, UIColours.MenuBackground)
  10548.                     end
  10549.                 end
  10550.             end
  10551.         end,
  10552.  
  10553.         NameForKey = function(self, key)
  10554.             if key == keys.leftCtrl then
  10555.                 return '^'
  10556.             elseif key == keys.tab then
  10557.                 return 'Tab'
  10558.             elseif key == keys.delete then
  10559.                 return 'Delete'
  10560.             elseif key == keys.n then
  10561.                 return 'N'
  10562.             elseif key == keys.s then
  10563.                 return 'S'
  10564.             elseif key == keys.o then
  10565.                 return 'O'
  10566.             elseif key == keys.z then
  10567.                 return 'Z'
  10568.             elseif key == keys.y then
  10569.                 return 'Y'
  10570.             elseif key == keys.c then
  10571.                 return 'C'
  10572.             elseif key == keys.x then
  10573.                 return 'X'
  10574.             elseif key == keys.v then
  10575.                 return 'V'
  10576.             elseif key == keys.r then
  10577.                 return 'R'
  10578.             elseif key == keys.l then
  10579.                 return 'L'
  10580.             elseif key == keys.t then
  10581.                 return 'T'
  10582.             elseif key == keys.h then
  10583.                 return 'H'
  10584.             elseif key == keys.e then
  10585.                 return 'E'
  10586.             elseif key == keys.p then
  10587.                 return 'P'
  10588.             elseif key == keys.f then
  10589.                 return 'F'
  10590.             elseif key == keys.m then
  10591.                 return 'M'
  10592.             else
  10593.                 return '?'     
  10594.             end
  10595.         end,
  10596.  
  10597.         Initialise = function(self, x, y, items, owner, removeTop)
  10598.             local new = {}    -- the new instance
  10599.             setmetatable( new, {__index = self} )
  10600.             if not owner then
  10601.                 return
  10602.             end
  10603.  
  10604.             local keyNames = {}
  10605.  
  10606.             for i, v in ipairs(items) do
  10607.                 items[i].KeyName = ''
  10608.                 if v.Keys then
  10609.                     for _i, key in ipairs(v.Keys) do
  10610.                         items[i].KeyName = items[i].KeyName .. self:NameForKey(key)
  10611.                     end
  10612.                 end
  10613.                 if items[i].KeyName ~= '' then
  10614.                     table.insert(keyNames, items[i].KeyName)
  10615.                 end
  10616.             end
  10617.             local keysLength = LongestString(keyNames)
  10618.             if keysLength > 0 then
  10619.                 keysLength = keysLength + 2
  10620.             end
  10621.  
  10622.             new.Width = LongestString(items, 'Title') + 2 + keysLength
  10623.             if new.Width < 10 then
  10624.                 new.Width = 10
  10625.             end
  10626.             new.Height = #items + 2
  10627.             new.RemoveTop = removeTop or false
  10628.             if removeTop then
  10629.                 new.Height = new.Height - 1
  10630.             end
  10631.            
  10632.             if y < 1 then
  10633.                 y = 1
  10634.             end
  10635.             if x < 1 then
  10636.                 x = 1
  10637.             end
  10638.  
  10639.             if y + new.Height > Drawing.Screen.Height + 1 then
  10640.                 y = Drawing.Screen.Height - new.Height
  10641.             end
  10642.             if x + new.Width > Drawing.Screen.Width + 1 then
  10643.                 x = Drawing.Screen.Width - new.Width
  10644.             end
  10645.  
  10646.  
  10647.             new.Y = y
  10648.             new.X = x
  10649.             new.Items = items
  10650.             new.Owner = owner
  10651.             return new
  10652.         end,
  10653.  
  10654.         New = function(self, x, y, items, owner, removeTop)
  10655.             if Current.Menu and Current.Menu.Owner == owner then
  10656.                 Current.Menu = nil
  10657.                 return
  10658.             end
  10659.  
  10660.             local new = self:Initialise(x, y, items, owner, removeTop)
  10661.             Current.Menu = new
  10662.             return new
  10663.         end,
  10664.  
  10665.         Click = function(self, side, x, y)
  10666.             local i = y-1
  10667.             if self.RemoveTop then
  10668.                 i = y
  10669.             end
  10670.             if i >= 1 and y < self.Height then
  10671.                 if not ((self.Items[i].Enabled and type(self.Items[i].Enabled) == 'function' and self.Items[i].Enabled() == false) or self.Items[i].Enabled == false) and self.Items[i].Click then
  10672.                     self.Items[i]:Click()
  10673.                     if Current.Menu.Owner and Current.Menu.Owner.Toggle then
  10674.                         Current.Menu.Owner.Toggle = false
  10675.                     end
  10676.                     Current.Menu = nil
  10677.                     self = nil
  10678.                 end
  10679.                 return true
  10680.             end
  10681.         end
  10682.     }
  10683.  
  10684.     MenuBar = {
  10685.         X = 1,
  10686.         Y = 1,
  10687.         Width = Drawing.Screen.Width,
  10688.         Height = 1,
  10689.         MenuBarItems = {},
  10690.  
  10691.         AbsolutePosition = function(self)
  10692.             return {X = self.X, Y = self.Y}
  10693.         end,
  10694.  
  10695.         Draw = function(self)
  10696.             --Drawing.DrawArea(self.X - 1, self.Y, 1, self.Height, "|", UIColours.ToolbarText, UIColours.Background)
  10697.  
  10698.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.Toolbar)
  10699.             for i, button in ipairs(self.MenuBarItems) do
  10700.                 button:Draw()
  10701.             end
  10702.         end,
  10703.  
  10704.         Initialise = function(self, items)
  10705.             local new = {}    -- the new instance
  10706.             setmetatable( new, {__index = self} )
  10707.             new.X = 1
  10708.             new.Y = 1
  10709.             new.MenuBarItems = items
  10710.             return new
  10711.         end,
  10712.  
  10713.         AddToolbarItem = function(self, item)
  10714.             table.insert(self.ToolbarItems, item)
  10715.             self:CalculateToolbarItemPositions()
  10716.         end,
  10717.  
  10718.         CalculateToolbarItemPositions = function(self)
  10719.             local currY = 1
  10720.             for i, toolbarItem in ipairs(self.ToolbarItems) do
  10721.                 toolbarItem.Y = currY
  10722.                 currY = currY + toolbarItem.Height
  10723.             end
  10724.         end,
  10725.  
  10726.         Click = function(self, side, x, y)
  10727.             for i, item in ipairs(self.MenuBarItems) do
  10728.                 if item.X <= x and item.X + item.Width > x then
  10729.                     if item:Click(item, side, x - item.X + 1, 1) then
  10730.                         break
  10731.                     end
  10732.                 end
  10733.             end
  10734.             return false
  10735.         end
  10736.     }
  10737.  
  10738.     --Modules--
  10739.  
  10740.     Modules = {
  10741.         {
  10742.             Title = "Colours",
  10743.             ToolbarItem = nil,
  10744.             Initialise = function(self)
  10745.                 self.ToolbarItem = ToolbarItem:Initialise(self, nil, true, Current.Toolbar)
  10746.  
  10747.                 local buttons = {}
  10748.  
  10749.                 local i = 0
  10750.  
  10751.                 local coloursWidth = 8
  10752.                 local _colours = {
  10753.                     colours.brown,
  10754.                     colours.yellow,
  10755.                     colours.orange,
  10756.                     colours.red,
  10757.                     colours.green,
  10758.                     colours.lime,
  10759.                     colours.magenta,
  10760.                     colours.pink,
  10761.                     colours.purple,
  10762.                     colours.blue,
  10763.                     colours.cyan,
  10764.                     colours.lightBlue,
  10765.                     colours.lightGrey,
  10766.                     colours.grey,
  10767.                     colours.black,
  10768.                     colours.white
  10769.                 }
  10770.  
  10771.                 for k, colour in pairs(_colours) do
  10772.                     if type(colour) == 'number' and colour ~= -1 then
  10773.                         i = i + 1
  10774.  
  10775.                         local y = math.floor(i/(coloursWidth/2))
  10776.  
  10777.                         local x = (i%(coloursWidth/2))
  10778.                         if x == 0 then
  10779.                             x = (coloursWidth/2)
  10780.                             y = y -1
  10781.                         end
  10782.  
  10783.                         table.insert(buttons,
  10784.                             {
  10785.                                 X = x*2 - 2 + self.ToolbarItem.Width - coloursWidth,
  10786.                                 Y = y+1,
  10787.                                 Width = 2,
  10788.                                 Height = 1,
  10789.                                 BackgroundColour = colour,
  10790.                                 Click = function(self, side, x, y)
  10791.                                     SetColour(self.BackgroundColour)
  10792.                                 end
  10793.                             }
  10794.                         )
  10795.                     end
  10796.                 end
  10797.  
  10798.                 for i, button in ipairs(buttons) do
  10799.                     table.insert(self.ToolbarItem.ContentView.Views,
  10800.                         Button:Initialise(button.X, button.Y, button.Width, button.Height, button.BackgroundColour, self.ToolbarItem.ContentView, button.Click))   
  10801.                 end
  10802.                
  10803.                 table.insert(self.ToolbarItem.ContentView.Views,
  10804.                         Button:Initialise(1, 1, 4, 3, function()return Current.Colour end, self.ToolbarItem.ContentView, nil))
  10805.            
  10806.                 Current.Toolbar:AddToolbarItem(self.ToolbarItem)
  10807.             end
  10808.         },
  10809.  
  10810.         {
  10811.             Title = "Tools",
  10812.             ToolbarItem = nil,
  10813.             Update = function(self)
  10814.                 for i, view in ipairs(self.ToolbarItem.ContentView.Views) do
  10815.                     if (Current.Tool and Current.Tool.Name == view.Text) then
  10816.                         view.TextColour = colours.white
  10817.                     else
  10818.                         view.TextColour = colours.lightGrey
  10819.                     end
  10820.                 end
  10821.                 self.ToolbarItem.ContentView.Views[1].Text = 'Size: '..Current.ToolSize
  10822.             end,
  10823.  
  10824.             Initialise = function(self)
  10825.                 self.ToolbarItem = ToolbarItem:Initialise(self, #Tools+2, true, Current.Toolbar,
  10826.                     {{
  10827.                         Title = "Change Tool Size",
  10828.                         Click = function()
  10829.                             DisplayToolSizeWindow()
  10830.                         end,
  10831.                     }})
  10832.  
  10833.                 table.insert(self.ToolbarItem.ContentView.Views, Button:Initialise(1, 1, self.ToolbarItem.Width, 1, UIColours.Toolbar, self.ToolbarItem.ContentView, DisplayToolSizeWindow, 'Size: '..Current.ToolSize))
  10834.  
  10835.                 local y = 2
  10836.                 for i, tool in ipairs(Tools) do
  10837.                     table.insert(self.ToolbarItem.ContentView.Views, Button:Initialise(1, y, self.ToolbarItem.Width, 1, UIColours.Toolbar, self.ToolbarItem.ContentView, function() SetTool(tool) self:Update(self.ToolbarItem) end, tool.Name))
  10838.                     y = y + 1
  10839.                 end
  10840.  
  10841.                 self:Update(self.ToolbarItem)
  10842.  
  10843.                 Current.Toolbar:AddToolbarItem(self.ToolbarItem)
  10844.             end
  10845.         },
  10846.  
  10847.         {
  10848.             Title = "Layers",
  10849.             ToolbarItem = nil,
  10850.             Update = function(self)
  10851.                 if Current.Artboard then
  10852.                     self.ToolbarItem.ContentView.Views = {}
  10853.                     for i = 1, #Current.Artboard.Layers do
  10854.                         table.insert(self.ToolbarItem.ContentView.Views, LayerItem:Initialise(Current.Artboard.Layers[#Current.Artboard.Layers-i+1], self.ToolbarItem.ContentView))
  10855.                     end                
  10856.                 end
  10857.             end,
  10858.  
  10859.             Initialise = function(self)
  10860.                 self.ToolbarItem = ToolbarItem:Initialise(self, nil, true, Current.Toolbar,
  10861.                     {{
  10862.                         Title = "New Layer",
  10863.                         Click = function()
  10864.                             MakeNewLayer()
  10865.                         end,
  10866.                         Enabled = function()
  10867.                             return CheckOpenArtboard()
  10868.                         end
  10869.                     },
  10870.                     {
  10871.                         Title = 'Delete Layer',
  10872.                         Click = function()
  10873.                             DeleteLayer()
  10874.                         end,
  10875.                         Enabled = function()
  10876.                             return CheckSelectedLayer()
  10877.                         end
  10878.                     },
  10879.                     {
  10880.                         Title = 'Rename Layer...',
  10881.                         Click = function()
  10882.                             RenameLayer()
  10883.                         end,
  10884.                         Enabled = function()
  10885.                             return CheckSelectedLayer()
  10886.                         end
  10887.                     }})
  10888.                
  10889.                 self:Update()
  10890.  
  10891.                 Current.Toolbar:AddToolbarItem(self.ToolbarItem)
  10892.             end
  10893.         }
  10894.  
  10895.     }
  10896.  
  10897.     function ModuleNamed(name)
  10898.         for i, v in ipairs(Modules) do
  10899.             if v.Title == name then
  10900.                 return v
  10901.             end
  10902.         end
  10903.     end
  10904.  
  10905.     --Tools--
  10906.  
  10907.     function ToolAffectedPixels(x, y)
  10908.         if not CheckSelectedLayer() then
  10909.             return {}
  10910.         end
  10911.         if Current.ToolSize == 1 then
  10912.             if Current.Layer.Pixels[x] and Current.Layer.Pixels[x][y] then
  10913.                 return {{Current.Layer.Pixels[x][y], x, y}}
  10914.             end
  10915.         else
  10916.             local pixels = {}
  10917.             local cornerX = x - math.ceil(Current.ToolSize/2)
  10918.             local cornerY = y - math.ceil(Current.ToolSize/2)
  10919.             for _x = 1, Current.ToolSize do
  10920.                 for _y = 1, Current.ToolSize do
  10921.                     if Current.Layer.Pixels[cornerX + _x] and Current.Layer.Pixels[cornerX + _x][cornerY + _y] then
  10922.                         table.insert(pixels, {Current.Layer.Pixels[cornerX + _x][cornerY + _y], cornerX + _x, cornerY + _y})
  10923.                     end
  10924.                 end
  10925.             end
  10926.             return pixels
  10927.         end
  10928.     end
  10929.     local moveStartPoint = {}
  10930.     Tools = {
  10931.         {
  10932.             Name = "Hand",
  10933.             Use = function(self, x, y, side, drag)
  10934.                 Current.Input = nil
  10935.                 if drag and Current.HandDragStart and Current.HandDragStart[1] and Current.HandDragStart[2] then
  10936.                     local deltaX = x - Current.HandDragStart[1]
  10937.                     local deltaY = y - Current.HandDragStart[2]
  10938.                     Current.Artboard.X = Current.Artboard.X + deltaX
  10939.                     Current.Artboard.Y = Current.Artboard.Y + deltaY
  10940.                 else
  10941.                     Current.HandDragStart = {x, y}
  10942.                 end
  10943.                 sleep(0)
  10944.             end,
  10945.             Select = function(self)
  10946.                 return true
  10947.             end
  10948.         },
  10949.  
  10950.         {
  10951.             Name = "Pencil",
  10952.             Use = function(self, _x, _y, side, artboard)
  10953.                 Current.Input = nil
  10954.                 for i, pixel in ipairs(ToolAffectedPixels(_x, _y)) do
  10955.                     if side == 1 then
  10956.                         pixel[1].BackgroundColour = Current.Colour
  10957.                     elseif side == 2 then
  10958.                         pixel[1].TextColour = Current.Colour
  10959.                     end
  10960.                     pixel[1]:Draw(pixel[2], pixel[3])
  10961.                 end
  10962.             end,
  10963.             Select = function(self)
  10964.                 return true
  10965.             end
  10966.         },
  10967.  
  10968.         {
  10969.             Name = "Eraser",
  10970.             Use = function(self, x, y, side)
  10971.                 Current.Input = nil
  10972.                 Current.Layer:SetPixel(x, y, nil, Current.Layer.BackgroundColour, nil)
  10973.                 for i, pixel in ipairs(ToolAffectedPixels(x, y)) do
  10974.                     Current.Layer:SetPixel(pixel[2], pixel[3], nil, Current.Layer.BackgroundColour, nil)
  10975.                 end
  10976.             end,
  10977.             Select = function(self)
  10978.                 return true
  10979.             end
  10980.         },
  10981.  
  10982.         {
  10983.             Name = "Fill Bucket",
  10984.             Use = function(self, x, y, side)
  10985.                 local replaceColour = Current.Layer.Pixels[x][y].BackgroundColour
  10986.                 if side == 2 then
  10987.                     replaceColour = Current.Layer.Pixels[x][y].TextColour
  10988.                 end
  10989.  
  10990.                 local nodes = {{X = x, Y = y}}
  10991.  
  10992.                 while #nodes > 0 do
  10993.                     local node = nodes[1]
  10994.                     if Current.Layer.Pixels[node.X] and Current.Layer.Pixels[node.X][node.Y] then
  10995.                         local replacing = Current.Layer.Pixels[node.X][node.Y].BackgroundColour
  10996.                         if side == 2 then
  10997.                             replacing = Current.Layer.Pixels[node.X][node.Y].TextColour
  10998.                         end
  10999.                         if replacing == replaceColour and replacing ~= Current.Colour then
  11000.                             if side == 1 then
  11001.                                 Current.Layer.Pixels[node.X][node.Y].BackgroundColour = Current.Colour
  11002.                             elseif side == 2 then
  11003.                                 Current.Layer.Pixels[node.X][node.Y].TextColour = Current.Colour
  11004.                             end
  11005.                             table.insert(nodes, {X = node.X, Y = node.Y + 1})
  11006.                             table.insert(nodes, {X = node.X + 1, Y = node.Y})
  11007.                             if x > 1 then
  11008.                                 table.insert(nodes, {X = node.X - 1, Y = node.Y})
  11009.                             end
  11010.                             if y > 1 then
  11011.                                 table.insert(nodes, {X = node.X, Y = node.Y - 1})
  11012.                             end
  11013.                         end
  11014.                     end
  11015.                     table.remove(nodes, 1)
  11016.                 end
  11017.                 Draw()
  11018.             end,
  11019.             Select = function(self)
  11020.                 return true
  11021.             end
  11022.         },
  11023.  
  11024.         {
  11025.             Name = "Select",
  11026.             Use = function(self, x, y, side, drag)
  11027.                 Current.Input = nil
  11028.                 if not drag then
  11029.                     Current.Selection[1] = vector.new(x, y, 0)
  11030.                     Current.Selection[2] = nil
  11031.                 else
  11032.                     Current.Selection[2] = vector.new(x, y, 0)
  11033.                 end
  11034.             end,
  11035.             Select = function(self)
  11036.                 return true
  11037.             end
  11038.         },
  11039.  
  11040.         {
  11041.             Name = "Move",
  11042.             Use = function(self, x, y, side, drag)
  11043.                 Current.Input = nil
  11044.  
  11045.                 if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
  11046.                     if drag and moveStartPoint then
  11047.                         local pixels = Current.Layer:PixelsInSelection(true)
  11048.                         local size = Current.Selection[1] - Current.Selection[2]
  11049.                         Current.Selection[1] = vector.new(x-moveStartPoint[1], y-moveStartPoint[2], 0)
  11050.                         Current.Selection[2] = vector.new(x-moveStartPoint[1]-size.x, y-moveStartPoint[2]-size.y, 0)
  11051.                         Current.Layer:InsertPixels(pixels)
  11052.                     else
  11053.                         moveStartPoint = {x-Current.Selection[1].x, y-Current.Selection[1].y}
  11054.                     end
  11055.                 end
  11056.             end,
  11057.             Select = function(self)
  11058.                 return true
  11059.             end
  11060.         },
  11061.  
  11062.         {
  11063.             Name = "Text",
  11064.             Use = function(self, x, y)
  11065.                 Current.Input = TextInput:Initialise('', function(key)
  11066.                     if key == keys.delete or key == keys.backspace then
  11067.                         if #Current.Input.Value == 0 then
  11068.                             if Current.Layer.Pixels[x] and Current.Layer.Pixels[x][y] then
  11069.                                 Current.Layer.Pixels[x][y]:Set(nil, nil, ' ')
  11070.                                 local newPos = Current.CursorPos[1] - Current.Artboard.X
  11071.                                 if newPos < Current.Artboard.X - 1 then
  11072.                                     newPos = Current.Artboard.X - 1
  11073.                                 end
  11074.                                 Current.Tool:Use(newPos, Current.CursorPos[2] - Current.Artboard.Y + 1)
  11075.                                 Draw()
  11076.                             end
  11077.                             return
  11078.                         else
  11079.                             if Current.Layer.Pixels[x+#Current.Input.Value] and Current.Layer.Pixels[x+#Current.Input.Value][y] then
  11080.                                 Current.Layer.Pixels[x+#Current.Input.Value][y]:Set(nil, nil, ' ')
  11081.                             end
  11082.                         end
  11083.                     else
  11084.                         local i = #Current.Input.Value
  11085.                         if Current.Layer.Pixels[x+i-1] then
  11086.                             Current.Layer.Pixels[x+i-1][y]:Set(Current.Colour, nil, Current.Input.Value:sub(i,i))
  11087.                             Current.Layer.Pixels[x+i-1][y]:Draw(x+i-1, y)
  11088.                         end
  11089.                     end
  11090.  
  11091.                     local newPos = x+Current.Input.CursorPos
  11092.  
  11093.                     if newPos > Current.Artboard.Width then
  11094.                         Current.Input.CursorPos = Current.Input.CursorPos - 1
  11095.                     end
  11096.  
  11097.                     Current.CursorPos = {x+Current.Input.CursorPos + Current.Artboard.X - 1, y + Current.Artboard.Y - 1}
  11098.                     Current.CursorColour = Current.Colour
  11099.                     Draw()
  11100.                 end)
  11101.  
  11102.                 Current.CursorPos = {x + Current.Artboard.X - 1, y + Current.Artboard.Y - 1}
  11103.                 Current.CursorColour = Current.Colour
  11104.             end,
  11105.             Select = function(self)
  11106.                 if Current.Artboard.Format == '.nfp' then
  11107.                     ButtonDialougeWindow:Initialise('NFP does not support text!', 'The format you are using, NFP, does not support text. Use NFT or SKCH to use text.', 'Ok', nil, function(window)
  11108.                         window:Close()
  11109.                     end):Show()
  11110.                     return false
  11111.                 else
  11112.                     return true
  11113.                 end
  11114.             end
  11115.         }
  11116.     }
  11117.  
  11118.  
  11119.     function ToolNamed(name)
  11120.         for i, v in ipairs(Tools) do
  11121.             if v.Name == name then
  11122.                 return v
  11123.             end
  11124.         end
  11125.     end
  11126.  
  11127.     --Windows--
  11128.  
  11129.     NewDocumentWindow = {
  11130.         X = 1,
  11131.         Y = 1,
  11132.         Width = 0,
  11133.         Height = 0,
  11134.         CursorPos = 1,
  11135.         Visible = true,
  11136.         Return = nil,
  11137.         OkButton = nil,
  11138.         Format = '.skch',
  11139.         ImageBackgroundColour = colours.white,
  11140.         NameLabelHighlight = false,
  11141.         SizeLabelHighlight = false,
  11142.  
  11143.  
  11144.         AbsolutePosition = function(self)
  11145.             return {X = self.X, Y = self.Y}
  11146.         end,
  11147.  
  11148.         Draw = function(self)
  11149.             if not self.Visible then
  11150.                 return
  11151.             end
  11152.             Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
  11153.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
  11154.             Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
  11155.             Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
  11156.  
  11157.             local nameLabelColour = colours.black
  11158.             if self.NameLabelHighlight then
  11159.                 nameLabelColour = colours.red
  11160.             end
  11161.  
  11162.             Drawing.DrawCharacters(self.X+1, self.Y+2, "Name", nameLabelColour, colours.white)
  11163.             Drawing.DrawCharacters(self.X+1, self.Y+4, "Type", colours.black, colours.white)
  11164.  
  11165.             local sizeLabelColour = colours.black
  11166.             if self.SizeLabelHighlight then
  11167.                 sizeLabelColour = colours.red
  11168.             end
  11169.             Drawing.DrawCharacters(self.X+1, self.Y+6, "Size", sizeLabelColour, colours.white)
  11170.             Drawing.DrawCharacters(self.X+11, self.Y+6, "x", colours.black, colours.white)
  11171.             Drawing.DrawCharacters(self.X+1, self.Y+8, "Background", colours.black, colours.white)
  11172.  
  11173.             self.OkButton:Draw()
  11174.             self.CancelButton:Draw()
  11175.             self.SKCHButton:Draw()
  11176.             self.NFTButton:Draw()
  11177.             self.NFPButton:Draw()
  11178.             self.PathTextBox:Draw()
  11179.             self.WidthTextBox:Draw()
  11180.             self.HeightTextBox:Draw()
  11181.             self.WhiteButton:Draw()
  11182.             self.BlackButton:Draw()
  11183.             self.TransparentButton:Draw()
  11184.         end,   
  11185.  
  11186.         Initialise = function(self, returnFunc)
  11187.             local new = {}    -- the new instance
  11188.             setmetatable( new, {__index = self} )
  11189.             new.Width = 32
  11190.             new.Height = 13
  11191.             new.Return = returnFunc
  11192.             new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
  11193.             new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
  11194.             new.Title = 'New Document'
  11195.             new.Visible = true
  11196.             new.NameLabelHighlight = false
  11197.             new.SizeLabelHighlight = false
  11198.             new.Format = '.skch'
  11199.             new.OkButton = Button:Initialise(new.Width - 4, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
  11200.                 local path = new.PathTextBox.TextInput.Value
  11201.                 local ok = true
  11202.                 new.NameLabelHighlight = false
  11203.                 new.SizeLabelHighlight = false
  11204.                 local _fs = fs
  11205.                 if OneOS then
  11206.                     _fs = OneOS.FS
  11207.                 end
  11208.                 if path:sub(-1) == '/' or _fs.isDir(path) or #path == 0 then
  11209.                     ok = false
  11210.                     new.NameLabelHighlight = true
  11211.                 end
  11212.  
  11213.                 if #new.WidthTextBox.TextInput.Value == 0 or tonumber(new.WidthTextBox.TextInput.Value) <= 0 then
  11214.                     ok = false
  11215.                     new.SizeLabelHighlight = true
  11216.                 end
  11217.  
  11218.                 if #new.HeightTextBox.TextInput.Value == 0 or tonumber(new.HeightTextBox.TextInput.Value) <= 0 then
  11219.                     ok = false
  11220.                     new.SizeLabelHighlight = true
  11221.                 end
  11222.  
  11223.                 if ok then
  11224.                     returnFunc(new, true, path, tonumber(new.WidthTextBox.TextInput.Value), tonumber(new.HeightTextBox.TextInput.Value), new.Format, new.ImageBackgroundColour)
  11225.                 else
  11226.                     Draw()
  11227.                 end
  11228.             end, 'Ok', colours.black)
  11229.             new.CancelButton = Button:Initialise(new.Width - 13, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)returnFunc(new, false)end, 'Cancel', colours.black)
  11230.  
  11231.             new.SKCHButton = Button:Initialise(7, 5, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
  11232.                 new.NFTButton.Toggle = false
  11233.                 new.NFPButton.Toggle = false
  11234.                 self.Toggle = false
  11235.                 new.Format = '.skch'
  11236.             end, '.skch', colours.black, true, colours.lightBlue)
  11237.             new.NFTButton = Button:Initialise(15, 5, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
  11238.                 new.SKCHButton.Toggle = false
  11239.                 new.NFPButton.Toggle = false
  11240.                 self.Toggle = false
  11241.                 new.Format = '.nft'
  11242.             end, '.nft', colours.black, false, colours.lightBlue)
  11243.             new.NFPButton = Button:Initialise(22, 5, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
  11244.                 new.SKCHButton.Toggle = false
  11245.                 new.NFTButton.Toggle = false
  11246.                 self.Toggle = false
  11247.                 new.Format = '.nfp'
  11248.             end, '.nfp', colours.black, false, colours.lightBlue)
  11249.  
  11250.             local path = ''
  11251.             if OneOS then
  11252.                 path = '/Desktop/'
  11253.             end
  11254.             new.PathTextBox = TextBox:Initialise(7, 3, new.Width - 7, 1, new, path, nil, nil, function(key)
  11255.                 if key == keys.enter or key == keys.tab then
  11256.                     Current.Input = new.WidthTextBox.TextInput
  11257.                 end        
  11258.             end)
  11259.             new.WidthTextBox = TextBox:Initialise(7, 7, 4, 1, new, tostring(15), nil, nil, function()
  11260.                 if key == keys.enter or key == keys.tab then
  11261.                     Current.Input = new.HeightTextBox.TextInput
  11262.                 end
  11263.             end, true)
  11264.             new.HeightTextBox = TextBox:Initialise(14, 7, 4, 1, new, tostring(10), nil, nil, function()
  11265.                 if key == keys.enter or key == keys.tab then
  11266.                     Current.Input = new.PathTextBox.TextInput
  11267.                 end
  11268.             end, true)
  11269.             Current.Input = new.PathTextBox.TextInput
  11270.  
  11271.  
  11272.             new.WhiteButton = Button:Initialise(2, 10, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
  11273.                 new.TransparentButton.Toggle = false
  11274.                 new.BlackButton.Toggle = false
  11275.                 self.Toggle = false
  11276.                 new.ImageBackgroundColour = colours.white
  11277.             end, 'White', colours.black, true, colours.lightBlue)
  11278.             new.BlackButton = Button:Initialise(10, 10, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
  11279.                 new.TransparentButton.Toggle = false
  11280.                 new.WhiteButton.Toggle = false
  11281.                 self.Toggle = false
  11282.                 new.ImageBackgroundColour = colours.black
  11283.             end, 'Black', colours.black, false, colours.lightBlue)
  11284.             new.TransparentButton = Button:Initialise(18, 10, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
  11285.                 new.WhiteButton.Toggle = false
  11286.                 new.BlackButton.Toggle = false
  11287.                 self.Toggle = false
  11288.                 new.ImageBackgroundColour = colours.transparent
  11289.             end, 'Transparent', colours.black, false, colours.lightBlue)
  11290.  
  11291.             return new
  11292.         end,
  11293.  
  11294.         Show = function(self)
  11295.             Current.Window = self
  11296.             return self
  11297.         end,
  11298.  
  11299.         Close = function(self)
  11300.             Current.Input = nil
  11301.             Current.Window = nil
  11302.             self = nil
  11303.         end,
  11304.  
  11305.         Flash = function(self)
  11306.             self.Visible = false
  11307.             Draw()
  11308.             sleep(0.15)
  11309.             self.Visible = true
  11310.             Draw()
  11311.             sleep(0.15)
  11312.             self.Visible = false
  11313.             Draw()
  11314.             sleep(0.15)
  11315.             self.Visible = true
  11316.             Draw()
  11317.         end,
  11318.  
  11319.         ButtonClick = function(self, button, x, y)
  11320.             if button.X <= x and button.Y <= y and button.X + button.Width > x and button.Y + button.Height > y then
  11321.                 button:Click()
  11322.             end
  11323.         end,
  11324.  
  11325.         Click = function(self, side, x, y)
  11326.             local items = {self.OkButton, self.CancelButton, self.SKCHButton, self.NFTButton, self.NFPButton, self.PathTextBox, self.WidthTextBox, self.HeightTextBox, self.WhiteButton, self.BlackButton, self.TransparentButton}
  11327.             for i, v in ipairs(items) do
  11328.                 if CheckClick(v, x, y) then
  11329.                     v:Click(side, x, y)
  11330.                 end
  11331.             end
  11332.             return true
  11333.         end
  11334.     }
  11335.  
  11336.     local TidyPath = function(path)
  11337.         path = '/'..path
  11338.         local _fs = fs
  11339.         if OneOS then
  11340.             _fs = OneOS.FS
  11341.         end
  11342.         if _fs.isDir(path) then
  11343.             path = path .. '/'
  11344.         end
  11345.  
  11346.         path, n = path:gsub("//", "/")
  11347.         while n > 0 do
  11348.             path, n = path:gsub("//", "/")
  11349.         end
  11350.         return path
  11351.     end
  11352.  
  11353.     local WrapText = function(text, maxWidth)
  11354.         local lines = {''}
  11355.         for word, space in text:gmatch('(%S+)(%s*)') do
  11356.                 local temp = lines[#lines] .. word .. space:gsub('\n','')
  11357.                 if #temp > maxWidth then
  11358.                         table.insert(lines, '')
  11359.                 end
  11360.                 if space:find('\n') then
  11361.                         lines[#lines] = lines[#lines] .. word
  11362.                        
  11363.                         space = space:gsub('\n', function()
  11364.                                 table.insert(lines, '')
  11365.                                 return ''
  11366.                         end)
  11367.                 else
  11368.                         lines[#lines] = lines[#lines] .. word .. space
  11369.                 end
  11370.         end
  11371.         return lines
  11372.     end
  11373.  
  11374.     OpenDocumentWindow = {
  11375.         X = 1,
  11376.         Y = 1,
  11377.         Width = 0,
  11378.         Height = 0,
  11379.         CursorPos = 1,
  11380.         Visible = true,
  11381.         Return = nil,
  11382.         OpenButton = nil,
  11383.         PathTextBox = nil,
  11384.         CurrentDirectory = '/',
  11385.         Scroll = 0,
  11386.         MaxScroll = 0,
  11387.         GoUpButton = nil,
  11388.         SelectedFile = '',
  11389.         Files = {},
  11390.         Typed = false,
  11391.  
  11392.         AbsolutePosition = function(self)
  11393.             return {X = self.X, Y = self.Y}
  11394.         end,
  11395.  
  11396.         Draw = function(self)
  11397.             if not self.Visible then
  11398.                 return
  11399.             end
  11400.             Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
  11401.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, 3, colours.lightGrey)
  11402.             Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-6, colours.white)
  11403.             Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
  11404.             Drawing.DrawBlankArea(self.X, self.Y + self.Height - 5, self.Width, 5, colours.lightGrey)
  11405.             self:DrawFiles()
  11406.  
  11407.             local _fs = fs
  11408.             if OneOS then
  11409.                 _fs = OneOS.FS
  11410.             end
  11411.             if (_fs.exists(self.PathTextBox.TextInput.Value)) or (self.SelectedFile and #self.SelectedFile > 0 and _fs.exists(self.CurrentDirectory .. self.SelectedFile)) then
  11412.                 self.OpenButton.TextColour = colours.black
  11413.             else
  11414.                 self.OpenButton.TextColour = colours.lightGrey
  11415.             end
  11416.  
  11417.             self.PathTextBox:Draw()
  11418.             self.OpenButton:Draw()
  11419.             self.CancelButton:Draw()
  11420.             self.GoUpButton:Draw()
  11421.         end,
  11422.  
  11423.         DrawFiles = function(self)
  11424.             local _fs = fs
  11425.             if OneOS then
  11426.                 _fs = OneOS.FS
  11427.             end
  11428.             for i, file in ipairs(self.Files) do
  11429.                 if i > self.Scroll and i - self.Scroll <= 11 then
  11430.                     if file == self.SelectedFile then
  11431.                         Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.white, colours.lightBlue)
  11432.                     elseif string.find(file, '%.skch') or string.find(file, '%.nft') or string.find(file, '%.nfp') or _fs.isDir(self.CurrentDirectory .. file) then
  11433.                         Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.black, colours.white)
  11434.                     else
  11435.                         Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.grey, colours.white)
  11436.                     end
  11437.                 end
  11438.             end
  11439.             self.MaxScroll = #self.Files - 11
  11440.             if self.MaxScroll < 0 then
  11441.                 self.MaxScroll = 0
  11442.             end
  11443.         end,
  11444.  
  11445.         Initialise = function(self, returnFunc)
  11446.             local new = {}    -- the new instance
  11447.             setmetatable( new, {__index = self} )
  11448.             new.Width = 32
  11449.             new.Height = 17
  11450.             new.Return = returnFunc
  11451.             new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
  11452.             new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
  11453.             new.Title = 'Open Document'
  11454.             new.Visible = true
  11455.             new.CurrentDirectory = '/'
  11456.             new.SelectedFile = nil
  11457.             if OneOS then
  11458.                 new.CurrentDirectory = '/Desktop/'
  11459.             end
  11460.             local _fs = fs
  11461.             if OneOS then
  11462.                 _fs = OneOS.FS
  11463.             end
  11464.             new.OpenButton = Button:Initialise(new.Width - 6, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
  11465.                 if _fs.exists(new.PathTextBox.TextInput.Value) and self.TextColour == colours.black and not _fs.isDir(new.PathTextBox.TextInput.Value) then
  11466.                     returnFunc(new, true, TidyPath(new.PathTextBox.TextInput.Value))
  11467.                 elseif new.SelectedFile and self.TextColour == colours.black and _fs.isDir(new.CurrentDirectory .. new.SelectedFile) then
  11468.                     new:GoToDirectory(new.CurrentDirectory .. new.SelectedFile)
  11469.                 elseif new.SelectedFile and self.TextColour == colours.black then
  11470.                     returnFunc(new, true, TidyPath(new.CurrentDirectory .. '/' .. new.SelectedFile))
  11471.                 end
  11472.             end, 'Open', colours.black)
  11473.             new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
  11474.                 returnFunc(new, false)
  11475.             end, 'Cancel', colours.black)
  11476.             new.GoUpButton = Button:Initialise(2, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
  11477.                 local folderName = _fs.getName(new.CurrentDirectory)
  11478.                 local parentDirectory = new.CurrentDirectory:sub(1, #new.CurrentDirectory-#folderName-1)
  11479.                 new:GoToDirectory(parentDirectory)
  11480.             end, 'Go Up', colours.black)
  11481.             new.PathTextBox = TextBox:Initialise(2, new.Height - 3, new.Width - 2, 1, new, new.CurrentDirectory, colours.white, colours.black)
  11482.             new:GoToDirectory(new.CurrentDirectory)
  11483.             return new
  11484.         end,
  11485.  
  11486.         Show = function(self)
  11487.             Current.Window = self
  11488.             return self
  11489.         end,
  11490.  
  11491.         Close = function(self)
  11492.             Current.Input = nil
  11493.             Current.Window = nil
  11494.             self = nil
  11495.         end,
  11496.  
  11497.         GoToDirectory = function(self, path)
  11498.             path = TidyPath(path)
  11499.             self.CurrentDirectory = path
  11500.             self.Scroll = 0
  11501.             self.SelectedFile = nil
  11502.             self.Typed = false
  11503.             self.PathTextBox.TextInput.Value = path
  11504.             local _fs = fs
  11505.             if OneOS then
  11506.                 _fs = OneOS.FS
  11507.             end
  11508.             self.Files = _fs.list(self.CurrentDirectory)
  11509.             Draw()
  11510.         end,
  11511.  
  11512.         Flash = function(self)
  11513.             self.Visible = false
  11514.             Draw()
  11515.             sleep(0.15)
  11516.             self.Visible = true
  11517.             Draw()
  11518.             sleep(0.15)
  11519.             self.Visible = false
  11520.             Draw()
  11521.             sleep(0.15)
  11522.             self.Visible = true
  11523.             Draw()
  11524.         end,
  11525.  
  11526.         Click = function(self, side, x, y)
  11527.             local items = {self.OpenButton, self.CancelButton, self.PathTextBox, self.GoUpButton}
  11528.             local found = false
  11529.             for i, v in ipairs(items) do
  11530.                 if CheckClick(v, x, y) then
  11531.                     v:Click(side, x, y)
  11532.                     found = true
  11533.                 end
  11534.             end
  11535.  
  11536.             if not found then
  11537.                 if y <= 12 then
  11538.                     local _fs = fs
  11539.                     if OneOS then
  11540.                         _fs = OneOS.FS
  11541.                     end
  11542.                     self.SelectedFile = _fs.list(self.CurrentDirectory)[y-1]
  11543.                     self.PathTextBox.TextInput.Value = TidyPath(self.CurrentDirectory .. '/' .. self.SelectedFile)
  11544.                     Draw()
  11545.                 end
  11546.             end
  11547.             return true
  11548.         end
  11549.     }
  11550.  
  11551.     ButtonDialougeWindow = {
  11552.         X = 1,
  11553.         Y = 1,
  11554.         Width = 0,
  11555.         Height = 0,
  11556.         CursorPos = 1,
  11557.         Visible = true,
  11558.         CancelButton = nil,
  11559.         OkButton = nil,
  11560.         Lines = {},
  11561.  
  11562.         AbsolutePosition = function(self)
  11563.             return {X = self.X, Y = self.Y}
  11564.         end,
  11565.  
  11566.         Draw = function(self)
  11567.             if not self.Visible then
  11568.                 return
  11569.             end
  11570.             Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
  11571.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
  11572.             Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
  11573.             Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
  11574.  
  11575.             for i, text in ipairs(self.Lines) do
  11576.                 Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
  11577.             end
  11578.  
  11579.             self.OkButton:Draw()
  11580.             if self.CancelButton then
  11581.                 self.CancelButton:Draw()
  11582.             end
  11583.         end,
  11584.  
  11585.         Initialise = function(self, title, message, okText, cancelText, returnFunc)
  11586.             local new = {}    -- the new instance
  11587.             setmetatable( new, {__index = self} )
  11588.             new.Width = 28
  11589.             new.Lines = WrapText(message, new.Width - 2)
  11590.             new.Height = 5 + #new.Lines
  11591.             new.Return = returnFunc
  11592.             new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
  11593.             new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
  11594.             new.Title = title
  11595.             new.Visible = true
  11596.             new.Visible = true
  11597.             new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
  11598.                 returnFunc(new, true)
  11599.             end, okText)
  11600.             if cancelText then
  11601.                 new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
  11602.                     returnFunc(new, false)
  11603.                 end, cancelText)
  11604.             end
  11605.  
  11606.             return new
  11607.         end,
  11608.  
  11609.         Show = function(self)
  11610.             Current.Window = self
  11611.             return self
  11612.         end,
  11613.  
  11614.         Close = function(self)
  11615.             Current.Window = nil
  11616.             self = nil
  11617.         end,
  11618.  
  11619.         Flash = function(self)
  11620.             self.Visible = false
  11621.             Draw()
  11622.             sleep(0.15)
  11623.             self.Visible = true
  11624.             Draw()
  11625.             sleep(0.15)
  11626.             self.Visible = false
  11627.             Draw()
  11628.             sleep(0.15)
  11629.             self.Visible = true
  11630.             Draw()
  11631.         end,
  11632.  
  11633.         Click = function(self, side, x, y)
  11634.             local items = {self.OkButton, self.CancelButton}
  11635.             local found = false
  11636.             for i, v in ipairs(items) do
  11637.                 if CheckClick(v, x, y) then
  11638.                     v:Click(side, x, y)
  11639.                     found = true
  11640.                 end
  11641.             end
  11642.             return true
  11643.         end
  11644.     }
  11645.  
  11646.     TextDialougeWindow = {
  11647.         X = 1,
  11648.         Y = 1,
  11649.         Width = 0,
  11650.         Height = 0,
  11651.         CursorPos = 1,
  11652.         Visible = true,
  11653.         CancelButton = nil,
  11654.         OkButton = nil,
  11655.         Lines = {},
  11656.         TextInput = nil,
  11657.  
  11658.         AbsolutePosition = function(self)
  11659.             return {X = self.X, Y = self.Y}
  11660.         end,
  11661.  
  11662.         Draw = function(self)
  11663.             if not self.Visible then
  11664.                 return
  11665.             end
  11666.             Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
  11667.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
  11668.             Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
  11669.             Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
  11670.  
  11671.             for i, text in ipairs(self.Lines) do
  11672.                 Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
  11673.             end
  11674.  
  11675.  
  11676.             Drawing.DrawBlankArea(self.X + 1, self.Y + self.Height - 4, self.Width - 2, 1, colours.lightGrey)
  11677.             Drawing.DrawCharacters(self.X + 2, self.Y + self.Height - 4, self.TextInput.Value, colours.black, colours.lightGrey)
  11678.             Current.CursorPos = {self.X + 2 + self.TextInput.CursorPos, self.Y + self.Height - 4}
  11679.             Current.CursorColour = colours.black
  11680.  
  11681.             self.OkButton:Draw()
  11682.             if self.CancelButton then
  11683.                 self.CancelButton:Draw()
  11684.             end
  11685.         end,
  11686.  
  11687.         Initialise = function(self, title, message, okText, cancelText, returnFunc, numerical)
  11688.             local new = {}    -- the new instance
  11689.             setmetatable( new, {__index = self} )
  11690.             new.Width = 28
  11691.             new.Lines = WrapText(message, new.Width - 2)
  11692.             new.Height = 7 + #new.Lines
  11693.             new.Return = returnFunc
  11694.             new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
  11695.             new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
  11696.             new.Title = title
  11697.             new.Visible = true
  11698.             new.Visible = true
  11699.             new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
  11700.                 if #new.TextInput.Value > 0 then
  11701.                     returnFunc(new, true, new.TextInput.Value)
  11702.                 end
  11703.             end, okText)
  11704.             if cancelText then
  11705.                 new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
  11706.                     returnFunc(new, false)
  11707.                 end, cancelText)
  11708.             end
  11709.             new.TextInput = TextInput:Initialise('', function(enter)
  11710.                 if enter then
  11711.                     new.OkButton:Click()
  11712.                 end
  11713.                 Draw()
  11714.             end, numerical)
  11715.  
  11716.             Current.Input = new.TextInput
  11717.  
  11718.             return new
  11719.         end,
  11720.  
  11721.         Show = function(self)
  11722.             Current.Window = self
  11723.             return self
  11724.         end,
  11725.  
  11726.         Close = function(self)
  11727.             Current.Window = nil
  11728.             Current.Input = nil
  11729.             self = nil
  11730.         end,
  11731.  
  11732.         Flash = function(self)
  11733.             self.Visible = false
  11734.             Draw()
  11735.             sleep(0.15)
  11736.             self.Visible = true
  11737.             Draw()
  11738.             sleep(0.15)
  11739.             self.Visible = false
  11740.             Draw()
  11741.             sleep(0.15)
  11742.             self.Visible = true
  11743.             Draw()
  11744.         end,
  11745.  
  11746.         Click = function(self, side, x, y)
  11747.             local items = {self.OkButton, self.CancelButton}
  11748.             local found = false
  11749.             for i, v in ipairs(items) do
  11750.                 if CheckClick(v, x, y) then
  11751.                     v:Click(side, x, y)
  11752.                     found = true
  11753.                 end
  11754.             end
  11755.             return true
  11756.         end
  11757.     }
  11758.  
  11759.     ResizeDocumentWindow = {
  11760.         X = 1,
  11761.         Y = 1,
  11762.         Width = 0,
  11763.         Height = 0,
  11764.         CursorPos = 1,
  11765.         Visible = true,
  11766.         Return = nil,
  11767.         OkButton = nil,
  11768.         AnchorPosition = 5,
  11769.         WidthLabelHighlight = false,
  11770.         HeightLabelHighlight = false,
  11771.  
  11772.         AbsolutePosition = function(self)
  11773.             return {X = self.X, Y = self.Y}
  11774.         end,
  11775.  
  11776.         Draw = function(self)
  11777.             if not self.Visible then
  11778.                 return
  11779.             end
  11780.             Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
  11781.             Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
  11782.             Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
  11783.             Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
  11784.  
  11785.             Drawing.DrawCharacters(self.X+1, self.Y+2, "New Size", colours.lightGrey, colours.white)
  11786.             if (#self.WidthTextBox.TextInput.Value > 0 and tonumber(self.WidthTextBox.TextInput.Value) < Current.Artboard.Width) or (#self.HeightTextBox.TextInput.Value > 0 and tonumber(self.HeightTextBox.TextInput.Value) < Current.Artboard.Height) then
  11787.                 Drawing.DrawCharacters(self.X+1, self.Y+8, "Clipping will occur!", colours.red, colours.white)
  11788.             end
  11789.  
  11790.             local widthLabelColour = colours.black
  11791.             if self.WidthLabelHighlight then
  11792.                 widthLabelColour = colours.red
  11793.             end
  11794.            
  11795.             local heightLabelColour = colours.black
  11796.             if self.HeightLabelHighlight then
  11797.                 heightLabelColour = colours.red
  11798.             end
  11799.  
  11800.             Drawing.DrawCharacters(self.X+1, self.Y+4, "Width", widthLabelColour, colours.white)
  11801.             Drawing.DrawCharacters(self.X+1, self.Y+6, "Height", heightLabelColour, colours.white)
  11802.  
  11803.             Drawing.DrawCharacters(self.X+14, self.Y+2, "Anchor", colours.lightGrey, colours.white)
  11804.  
  11805.             self.WidthTextBox:Draw()
  11806.             self.HeightTextBox:Draw()
  11807.             self.OkButton:Draw()
  11808.             self.Anchor1:Draw()
  11809.             self.Anchor2:Draw()
  11810.             self.Anchor3:Draw()
  11811.             self.Anchor4:Draw()
  11812.             self.Anchor5:Draw()
  11813.             self.Anchor6:Draw()
  11814.             self.Anchor7:Draw()
  11815.             self.Anchor8:Draw()
  11816.             self.Anchor9:Draw()
  11817.         end,   
  11818.  
  11819.         Initialise = function(self, returnFunc)
  11820.             local new = {}    -- the new instance
  11821.             setmetatable( new, {__index = self} )
  11822.             new.Width = 27
  11823.             new.Height = 10
  11824.             new.Return = returnFunc
  11825.             new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
  11826.             new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
  11827.             new.Title = 'Resize Document'
  11828.             new.Visible = true
  11829.  
  11830.             new.WidthTextBox = TextBox:Initialise(9, 5, 4, 1, new, tostring(Current.Artboard.Width), nil, nil, function()
  11831.                 new:UpdateAnchorButtons()
  11832.             end, true)
  11833.             new.HeightTextBox = TextBox:Initialise(9, 7, 4, 1, new, tostring(Current.Artboard.Height), nil, nil, function()
  11834.                 new:UpdateAnchorButtons()
  11835.             end, true)
  11836.             new.OkButton = Button:Initialise(new.Width - 4, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
  11837.                 local ok = true
  11838.                 new.WidthLabelHighlight = false
  11839.                 new.HeightLabelHighlight = false
  11840.  
  11841.                 if #new.WidthTextBox.TextInput.Value == 0 or tonumber(new.WidthTextBox.TextInput.Value) <= 0 then
  11842.                     ok = false
  11843.                     new.WidthLabelHighlight = true
  11844.                 end
  11845.  
  11846.                 if #new.HeightTextBox.TextInput.Value == 0 or tonumber(new.HeightTextBox.TextInput.Value) <= 0 then
  11847.                     ok = false
  11848.                     new.HeightLabelHighlight = true
  11849.                 end
  11850.  
  11851.                 if ok then
  11852.                     returnFunc(new, tonumber(new.WidthTextBox.TextInput.Value), tonumber(new.HeightTextBox.TextInput.Value), new.AnchorPosition)
  11853.                 else
  11854.                     Draw()
  11855.                 end
  11856.             end, 'Ok', colours.black)
  11857.  
  11858.             local anchorX = 15
  11859.             local anchorY = 5
  11860.             new.Anchor1 = Button:Initialise(anchorX, anchorY, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 1 new:UpdateAnchorButtons() end, ' ', colours.black)
  11861.             new.Anchor2 = Button:Initialise(anchorX+1, anchorY, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 2 new:UpdateAnchorButtons() end, '^', colours.black)
  11862.             new.Anchor3 = Button:Initialise(anchorX+2, anchorY, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 3 new:UpdateAnchorButtons() end, ' ', colours.black)
  11863.             new.Anchor4 = Button:Initialise(anchorX, anchorY+1, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 4 new:UpdateAnchorButtons() end, '<', colours.black)
  11864.             new.Anchor5 = Button:Initialise(anchorX+1, anchorY+1, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 5 new:UpdateAnchorButtons() end, '#', colours.black)
  11865.             new.Anchor6 = Button:Initialise(anchorX+2, anchorY+1, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 6 new:UpdateAnchorButtons() end, '>', colours.black)
  11866.             new.Anchor7 = Button:Initialise(anchorX, anchorY+2, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 7 new:UpdateAnchorButtons() end, ' ', colours.black)
  11867.             new.Anchor8 = Button:Initialise(anchorX+1, anchorY+2, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 8 new:UpdateAnchorButtons() end, 'v', colours.black)
  11868.             new.Anchor9 = Button:Initialise(anchorX+2, anchorY+2, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 9 new:UpdateAnchorButtons() end, ' ', colours.black)
  11869.  
  11870.             return new
  11871.         end,
  11872.  
  11873.         UpdateAnchorButtons = function(self)
  11874.             local anchor1 = ' '
  11875.             local anchor2 = ' '
  11876.             local anchor3 = ' '
  11877.             local anchor4 = ' '
  11878.             local anchor5 = ' '
  11879.             local anchor6 = ' '
  11880.             local anchor7 = ' '
  11881.             local anchor8 = ' '
  11882.             local anchor9 = ' '
  11883.             self.AnchorPosition = self.AnchorPosition or 5
  11884.             if self.AnchorPosition == 1 then
  11885.                 anchor1 = '#'
  11886.                 anchor2 = '>'
  11887.                 anchor4 = 'v'
  11888.             elseif self.AnchorPosition == 2 then
  11889.                 anchor1 = '<'
  11890.                 anchor2 = '#'
  11891.                 anchor3 = '>'
  11892.                 anchor5 = 'v'
  11893.             elseif self.AnchorPosition == 3 then
  11894.                 anchor2 = '<'
  11895.                 anchor3 = '#'
  11896.                 anchor6 = 'v'
  11897.             elseif self.AnchorPosition == 4 then
  11898.                 anchor1 = '^'
  11899.                 anchor4 = '#'
  11900.                 anchor5 = '>'
  11901.                 anchor7 = 'v'
  11902.             elseif self.AnchorPosition == 5 then
  11903.                 anchor2 = '^'
  11904.                 anchor4 = '<'
  11905.                 anchor5 = '#'
  11906.                 anchor6 = '>'
  11907.                 anchor8 = 'v'
  11908.             elseif self.AnchorPosition == 6 then
  11909.                 anchor3 = '^'
  11910.                 anchor6 = '#'
  11911.                 anchor5 = '<'
  11912.                 anchor9 = 'v'
  11913.             elseif self.AnchorPosition == 7 then
  11914.                 anchor4 = '^'
  11915.                 anchor7 = '#'
  11916.                 anchor8 = '>'
  11917.             elseif self.AnchorPosition == 8 then
  11918.                 anchor5 = '^'
  11919.                 anchor8 = '#'
  11920.                 anchor7 = '<'
  11921.                 anchor9 = '>'
  11922.             elseif self.AnchorPosition == 9 then
  11923.                 anchor6 = '^'
  11924.                 anchor9 = '#'
  11925.                 anchor8 = '<'
  11926.             end
  11927.  
  11928.             if #self.HeightTextBox.TextInput.Value > 0 and Current.Artboard.Height > tonumber(self.HeightTextBox.TextInput.Value) then
  11929.                 local r = function(str)
  11930.                     if string.find(str, "%^") then
  11931.                         str = str:gsub('%^','v')
  11932.                     elseif string.find(str, "v") then
  11933.                         str = str:gsub('v','%^')
  11934.                     end
  11935.                     return str
  11936.                 end
  11937.                 anchor1 = r(anchor1)
  11938.                 anchor2 = r(anchor2)
  11939.                 anchor3 = r(anchor3)
  11940.                 anchor4 = r(anchor4)
  11941.                 anchor5 = r(anchor5)
  11942.                 anchor6 = r(anchor6)
  11943.                 anchor7 = r(anchor7)
  11944.                 anchor8 = r(anchor8)
  11945.                 anchor9 = r(anchor9)
  11946.             end
  11947.  
  11948.             if #self.WidthTextBox.TextInput.Value > 0 and Current.Artboard.Width > tonumber(self.WidthTextBox.TextInput.Value) then
  11949.                 local r = function(str)
  11950.                     if string.find(str, ">") then
  11951.                         str = str:gsub('>','<')
  11952.                     elseif string.find(str, "<") then
  11953.                         str = str:gsub('<','>')
  11954.                     end
  11955.                     return str
  11956.                 end
  11957.                 anchor1 = r(anchor1)
  11958.                 anchor2 = r(anchor2)
  11959.                 anchor3 = r(anchor3)
  11960.                 anchor4 = r(anchor4)
  11961.                 anchor5 = r(anchor5)
  11962.                 anchor6 = r(anchor6)
  11963.                 anchor7 = r(anchor7)
  11964.                 anchor8 = r(anchor8)
  11965.                 anchor9 = r(anchor9)
  11966.             end
  11967.  
  11968.             self.Anchor1.Text = anchor1
  11969.             self.Anchor2.Text = anchor2
  11970.             self.Anchor3.Text = anchor3
  11971.             self.Anchor4.Text = anchor4
  11972.             self.Anchor5.Text = anchor5
  11973.             self.Anchor6.Text = anchor6
  11974.             self.Anchor7.Text = anchor7
  11975.             self.Anchor8.Text = anchor8
  11976.             self.Anchor9.Text = anchor9
  11977.         end,
  11978.  
  11979.         Show = function(self)
  11980.             Current.Window = self
  11981.             return self
  11982.         end,
  11983.  
  11984.         Close = function(self)
  11985.             Current.Input = nil
  11986.             Current.Window = nil
  11987.             self = nil
  11988.         end,
  11989.  
  11990.         Flash = function(self)
  11991.             self.Visible = false
  11992.             Draw()
  11993.             sleep(0.15)
  11994.             self.Visible = true
  11995.             Draw()
  11996.             sleep(0.15)
  11997.             self.Visible = false
  11998.             Draw()
  11999.             sleep(0.15)
  12000.             self.Visible = true
  12001.             Draw()
  12002.         end,
  12003.  
  12004.         ButtonClick = function(self, button, x, y)
  12005.             if button.X <= x and button.Y <= y and button.X + button.Width > x and button.Y + button.Height > y then
  12006.                 button:Click()
  12007.             end
  12008.         end,
  12009.  
  12010.         Click = function(self, side, x, y)
  12011.             local items = {self.OkButton, self.WidthTextBox, self.HeightTextBox, self.Anchor1, self.Anchor2, self.Anchor3, self.Anchor4, self.Anchor5, self.Anchor6, self.Anchor7, self.Anchor8, self.Anchor9}
  12012.             for i, v in ipairs(items) do
  12013.                 if CheckClick(v, x, y) then
  12014.                     v:Click(side, x, y)
  12015.                 end
  12016.             end
  12017.             return true
  12018.         end
  12019.     }
  12020.  
  12021.     ----------------------
  12022.  
  12023.     function CheckOpenArtboard()
  12024.         if Current.Artboard then
  12025.             return true
  12026.         else
  12027.             return false
  12028.         end
  12029.     end
  12030.  
  12031.     function CheckSelectedLayer()
  12032.         if Current.Artboard and Current.Layer then
  12033.             return true
  12034.         else
  12035.             return false
  12036.         end
  12037.     end
  12038.  
  12039.     function DisplayNewDocumentWindow()
  12040.         NewDocumentWindow:Initialise(function(self, success, path, width, height, format, backgroundColour)
  12041.             if success then
  12042.                 if path:sub(-4) ~= format then
  12043.                     path = path .. format
  12044.                 end
  12045.                 local oldWindow = self
  12046.                 Current.Input = nil
  12047.                 Current.Window = nil
  12048.                 makeDocument = function()oldWindow:Close()NewDocument(path, width, height, format, backgroundColour)end
  12049.                 local _fs = fs
  12050.                 if OneOS then
  12051.                     _fs = OneOS.FS
  12052.                 end
  12053.                 if _fs.exists(path) then
  12054.                     ButtonDialougeWindow:Initialise('File Exists', path..' already exists! Use a different name and try again.', 'Ok', nil, function(window, ok)
  12055.                         window:Close()
  12056.                         oldWindow:Show()
  12057.                     end):Show()
  12058.                 elseif format == '.nfp' then
  12059.                     Current.Window = nil
  12060.                     ButtonDialougeWindow:Initialise('Use NFP?', 'The NFT format does not support text or layers, if you use it you will only be able to use 1 layer and not have any text.', 'Use NFP', 'Cancel', function(window, ok)
  12061.                         window:Close()
  12062.                         if ok then
  12063.                             makeDocument()
  12064.                         else
  12065.                             oldWindow:Show()
  12066.                         end
  12067.                     end):Show()
  12068.                 elseif format == '.nft' then
  12069.                     ButtonDialougeWindow:Initialise('Use NFT?', 'The NFT format does not support layers, if you use it you will only be able to use 1 layer.', 'Use NFT', 'Cancel', function(window, ok)
  12070.                         window:Close()
  12071.                         if ok then
  12072.                             makeDocument()
  12073.                         else
  12074.                             oldWindow:Show()
  12075.                         end
  12076.                     end):Show()
  12077.                 else
  12078.                     makeDocument()
  12079.                 end
  12080.  
  12081.                
  12082.             else
  12083.                 self:Close()
  12084.             end
  12085.         end):Show()
  12086.     end
  12087.  
  12088.     function NewDocument(path, width, height, format, backgroundColour)
  12089.         local _fs = fs
  12090.         if OneOS then
  12091.             _fs = OneOS.FS
  12092.         end
  12093.         ab = Artboard:New(_fs.getName(path), path, width, height, format, backgroundColour)
  12094.         Current.Tool = Tools[2]
  12095.         Current.Toolbar:Update()
  12096.         Current.Modified = false
  12097.         Draw()
  12098.     end
  12099.  
  12100.     function DisplayToolSizeWindow()
  12101.         if not CheckOpenArtboard() then
  12102.             return
  12103.         end
  12104.         TextDialougeWindow:Initialise('Change Tool Size', 'Enter the new tool size you\'d like to use.', 'Ok', 'Cancel', function(window, success, value)
  12105.             if success then
  12106.                 Current.ToolSize = math.ceil(tonumber(value))
  12107.                 if Current.ToolSize < 1 then
  12108.                     Current.ToolSize = 1
  12109.                 elseif Current.ToolSize > 50 then
  12110.                     Current.ToolSize = 50
  12111.                 end
  12112.                 ModuleNamed('Tools'):Update()
  12113.             end
  12114.             window:Close()
  12115.         end, true):Show()  
  12116.     end
  12117.  
  12118.     --[[
  12119.         Attempt to figure out what format the image is if it doesn't have an extension
  12120.     ]]--
  12121.     function GetFormat(path)
  12122.         local _fs = fs
  12123.         if OneOS then
  12124.             _fs = OneOS.FS
  12125.         end
  12126.         local file = _fs.open(path, 'r')
  12127.         local content = file.readAll()
  12128.         file.close()
  12129.         if type(textutils.unserialize(content)) == 'table' then
  12130.             -- It's a serlized table, asume sketch
  12131.             return '.skch'
  12132.         elseif string.find(content, string.char(30)) or string.find(content, string.char(31)) then
  12133.             -- Contains the characters that set colours, asume nft
  12134.             return '.nft'
  12135.         else
  12136.             -- Otherwise asume nfp
  12137.             return '.nfp'
  12138.         end
  12139.     end
  12140.  
  12141.     function DisplayOpenDocumentWindow()
  12142.         OpenDocumentWindow:Initialise(function(self, success, path)
  12143.             self:Close()
  12144.             if success then
  12145.                 OpenDocument(path)
  12146.             end
  12147.         end):Show()
  12148.     end
  12149.  
  12150.  
  12151.     local function Extension(path, addDot)
  12152.         if not path then
  12153.             return nil
  12154.         elseif not string.find(fs.getName(path), '%.') then
  12155.             if not addDot then
  12156.                 return fs.getName(path)
  12157.             else
  12158.                 return ''
  12159.             end
  12160.         else
  12161.             local _path = path
  12162.             if path:sub(#path) == '/' then
  12163.                 _path = path:sub(1,#path-1)
  12164.             end
  12165.             local extension = _path:gmatch('[0-9a-z]+$')()
  12166.             if extension then
  12167.                 extension = extension:sub(2)
  12168.             else
  12169.                 --extension = nil
  12170.                 return ''
  12171.             end
  12172.             if addDot then
  12173.                 extension = '.'..extension
  12174.             end
  12175.             return extension:lower()
  12176.         end
  12177.     end
  12178.  
  12179.     local RemoveExtension = function(path)
  12180.         if path:sub(1,1) == '.' then
  12181.             return path
  12182.         end
  12183.         local extension = Extension(path)
  12184.         if extension == path then
  12185.             return fs.getName(path)
  12186.         end
  12187.         return string.gsub(path, extension, ''):sub(1, -2)
  12188.     end
  12189.     --[[
  12190.         Open a documet at a given path
  12191.     ]]--
  12192.     function OpenDocument(path)
  12193.         local _fs = fs
  12194.         if OneOS then
  12195.             _fs = OneOS.FS
  12196.         end
  12197.         if _fs.exists(path) and not _fs.isDir(path) then
  12198.             local format = Extension(path, true)
  12199.             if (not format or format == '') and (format ~= '.nfp' and format ~= '.nft' and format ~= '.skch') then
  12200.                 format = GetFormat(path)
  12201.             end
  12202.             local layers = {}
  12203.             if format == '.nfp' then
  12204.                 layers = ReadNFP(path)
  12205.             elseif format == '.nft' then
  12206.                 layers = ReadNFT(path)     
  12207.             elseif format == '.skch' then
  12208.                 layers = ReadSKCH(path)
  12209.             end
  12210.  
  12211.             for i, layer in ipairs(layers) do
  12212.                 if layer.Visible == nil then
  12213.                     layer.Visible = true
  12214.                 end
  12215.                 if layer.Index == nil then
  12216.                     layer.Index = 1
  12217.                 end
  12218.                 if layer.Name == nil then
  12219.                     if layer.Index == 1 then
  12220.                         layer.Name = 'Background'
  12221.                     else
  12222.                         layer.Name = 'Layer'
  12223.                     end
  12224.                 end
  12225.                 if layer.BackgroundColour == nil then
  12226.                     layer.BackgroundColour = colours.white
  12227.                 end
  12228.             end
  12229.  
  12230.             if not layers[1] then
  12231.                 --log('File could not be read.')
  12232.                 return
  12233.             end
  12234.  
  12235.             local width = #layers[1].Pixels
  12236.             local height = #layers[1].Pixels[1]
  12237.  
  12238.             Current.Artboard = nil
  12239.             local _fs = fs
  12240.             if OneOS then
  12241.                 _fs = OneOS.FS
  12242.             end
  12243.             ab = Artboard:New(_fs.getName('Image'), path, width, height, format, nil, layers)
  12244.             Current.Tool = Tools[2]
  12245.             Current.Toolbar:Update()
  12246.             Current.Modified = false
  12247.             Draw()
  12248.         end
  12249.     end
  12250.  
  12251.     function MakeNewLayer()
  12252.         if not CheckOpenArtboard() then
  12253.             return
  12254.         end
  12255.         if Current.Artboard.Format == '.skch' then
  12256.             TextDialougeWindow:Initialise('New Layer Name', 'Enter the name you want for the next layer.', 'Ok', 'Cancel', function(window, success, value)
  12257.                 if success then
  12258.                     Current.Artboard:MakeLayer(value, colours.transparent)
  12259.                 end
  12260.                 window:Close()
  12261.             end):Show()
  12262.         else
  12263.             local format = 'NFP'
  12264.             if Current.Artboard.Format == '.nft' then
  12265.                 format = 'NFT'
  12266.             end
  12267.             ButtonDialougeWindow:Initialise(format..' does not support layers!', 'The format you are using, '..format..', does not support multiple layers. Use SKCH to have more than one layer.', 'Ok', nil, function(window)
  12268.                 window:Close()
  12269.             end):Show()
  12270.         end
  12271.     end
  12272.  
  12273.     function ResizeDocument()
  12274.         if not CheckOpenArtboard() then
  12275.             return
  12276.         end
  12277.         ResizeDocumentWindow:Initialise(function(window, width, height, anchor)
  12278.             window:Close()
  12279.             local topResize = 0
  12280.             local rightResize = 0
  12281.             local bottomResize = 0
  12282.             local leftResize = 0
  12283.  
  12284.             if anchor == 1 then
  12285.                 rightResize = 1
  12286.                 bottomResize = 1
  12287.             elseif anchor == 2 then
  12288.                 rightResize = 0.5
  12289.                 leftResize = 0.5
  12290.                 bottomResize = 1
  12291.             elseif anchor == 3 then
  12292.                 leftResize = 1
  12293.                 bottomResize = 1
  12294.             elseif anchor == 4 then
  12295.                 rightResize = 1
  12296.                 bottomResize = 0.5
  12297.                 topResize = 0.5
  12298.             elseif anchor == 5 then
  12299.                 rightResize = 0.5
  12300.                 leftResize = 0.5
  12301.                 bottomResize = 0.5
  12302.                 topResize = 0.5
  12303.             elseif anchor == 6 then
  12304.                 leftResize = 1
  12305.                 bottomResize = 0.5
  12306.                 topResize = 0.5
  12307.             elseif anchor == 7 then
  12308.                 rightResize = 1
  12309.                 topResize = 1
  12310.             elseif anchor == 8 then
  12311.                 rightResize = 0.5
  12312.                 leftResize = 0.5
  12313.                 topResize = 1
  12314.             elseif anchor == 9 then
  12315.                 leftResize = 1
  12316.                 topResize = 1
  12317.             end
  12318.  
  12319.             topResize = topResize * (height - Current.Artboard.Height)
  12320.             if topResize > 0 then
  12321.                 topResize = math.floor(topResize)
  12322.             else
  12323.                 topResize = math.ceil(topResize)
  12324.             end
  12325.  
  12326.             bottomResize = bottomResize * (height - Current.Artboard.Height)
  12327.             if bottomResize > 0 then
  12328.                 bottomResize = math.ceil(bottomResize)
  12329.             else
  12330.                 bottomResize = math.floor(bottomResize)
  12331.             end
  12332.  
  12333.             leftResize = leftResize * (width - Current.Artboard.Width)
  12334.             if leftResize > 0 then
  12335.                 leftResize = math.floor(leftResize)
  12336.             else
  12337.                 leftResize = math.ceil(leftResize)
  12338.             end
  12339.  
  12340.             rightResize = rightResize * (width - Current.Artboard.Width)
  12341.             if rightResize > 0 then
  12342.                 rightResize = math.ceil(rightResize)
  12343.             else
  12344.                 rightResize = math.floor(rightResize)
  12345.             end
  12346.  
  12347.             Current.Artboard:Resize(topResize, bottomResize, leftResize, rightResize)
  12348.         end):Show()
  12349.     end
  12350.  
  12351.     function RenameLayer()
  12352.         if not CheckOpenArtboard() then
  12353.             return
  12354.         end
  12355.         if Current.Artboard.Format == '.skch' then
  12356.             TextDialougeWindow:Initialise("Rename Layer '"..Current.Layer.Name.."'", 'Enter the new name you want the layer to be called.', 'Ok', 'Cancel', function(window, success, value)
  12357.                 if success then
  12358.                     Current.Layer.Name = value
  12359.                 end
  12360.                 window:Close()
  12361.             end):Show()
  12362.         else
  12363.             local format = 'NFP'
  12364.             if Current.Artboard.Format == '.nft' then
  12365.                 format = 'NFT'
  12366.             end
  12367.             ButtonDialougeWindow:Initialise(format..' does not support layers!', 'The format you are using, '..format..', does not support renaming layers. Use SKCH to rename layers.', 'Ok', nil, function(window)
  12368.                 window:Close()
  12369.             end):Show()
  12370.         end
  12371.     end
  12372.  
  12373.     function DeleteLayer()
  12374.         if not CheckOpenArtboard() then
  12375.             return
  12376.         end
  12377.         if Current.Artboard.Format == '.skch' then
  12378.             if #Current.Artboard.Layers > 1 then
  12379.                 ButtonDialougeWindow:Initialise("Delete Layer '"..Current.Layer.Name.."'?", 'Are you sure you want delete the layer?', 'Ok', 'Cancel', function(window, success)
  12380.                     if success then
  12381.                         Current.Layer:Remove()
  12382.                     end
  12383.                     window:Close()
  12384.                 end):Show()
  12385.             else
  12386.                 ButtonDialougeWindow:Initialise('Can not delete layer!', 'You can not delete the last layer of an image! Make another layer to delete this one.', 'Ok', nil, function(window)
  12387.                     window:Close()
  12388.                 end):Show()
  12389.             end
  12390.         else
  12391.             local format = 'NFP'
  12392.             if Current.Artboard.Format == '.nft' then
  12393.                 format = 'NFT'
  12394.             end
  12395.             ButtonDialougeWindow:Initialise(format..' does not support layers!', 'The format you are using, '..format..', does not support deleting layers. Use SKCH to deleting layers.', 'Ok', nil, function(window)
  12396.                 window:Close()
  12397.             end):Show()
  12398.         end
  12399.     end
  12400.  
  12401.     needsDraw = false
  12402.     isDrawing = false
  12403.     function Draw()
  12404.         if isDrawing then
  12405.             needsDraw = true
  12406.             return
  12407.         end
  12408.         needsDraw = false
  12409.         isDrawing = true
  12410.         if not Current.Window then
  12411.             Drawing.Clear(UIColours.Background)
  12412.         else
  12413.             Drawing.DrawArea(1, 2, Drawing.Screen.Width, Drawing.Screen.Height, '|', colours.black, colours.lightGrey)
  12414.         end
  12415.  
  12416.         if Current.Artboard then
  12417.             ab:Draw()
  12418.         end
  12419.  
  12420.         if Current.InterfaceVisible then
  12421.             Current.MenuBar:Draw()
  12422.             Current.Toolbar.Width = Current.Toolbar.ExpandedWidth
  12423.             Current.Toolbar:Draw()
  12424.         else
  12425.             Current.Toolbar.Width = Current.Toolbar.ExpandedWidth
  12426.         end
  12427.  
  12428.         if Current.InterfaceVisible and Current.Menu then
  12429.             Current.Menu:Draw()
  12430.         end
  12431.  
  12432.         if Current.Window then
  12433.             Current.Window:Draw()
  12434.         end
  12435.  
  12436.         if not Current.InterfaceVisible then
  12437.             ShowInterfaceButton:Draw()
  12438.         end
  12439.  
  12440.         Drawing.DrawBuffer()
  12441.         if Current.Input and not Current.Menu then
  12442.             term.setCursorPos(Current.CursorPos[1], Current.CursorPos[2])
  12443.             term.setCursorBlink(true)
  12444.             term.setTextColour(Current.CursorColour)
  12445.         else
  12446.             term.setCursorBlink(false)
  12447.         end
  12448.  
  12449.         if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
  12450.             Current.SelectionDrawTimer = os.startTimer(0.5)
  12451.         end
  12452.         isDrawing = false
  12453.         if needsDraw then
  12454.             Draw()
  12455.         end
  12456.     end
  12457.  
  12458.     function LoadMenuBar()
  12459.         Current.MenuBar = MenuBar:Initialise({
  12460.             Button:Initialise(1, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
  12461.                 if toggle then
  12462.                     Menu:New(1, 2, {
  12463.                         {
  12464.                             Title = "New...",
  12465.                             Click = function()
  12466.                                 DisplayNewDocumentWindow()
  12467.                             end,
  12468.                             Keys = {
  12469.                                 keys.leftCtrl,
  12470.                                 keys.n
  12471.                             }
  12472.                         },
  12473.                         {
  12474.                             Title = 'Open...',
  12475.                             Click = function()
  12476.                                 DisplayOpenDocumentWindow()
  12477.                             end,
  12478.                             Keys = {
  12479.                                 keys.leftCtrl,
  12480.                                 keys.o
  12481.                             }
  12482.                         },
  12483.                         {
  12484.                             Separator = true
  12485.                         },
  12486.                         {
  12487.                             Title = 'Save...',
  12488.                             Click = function()
  12489.                                 Current.Artboard:Save()
  12490.                             end,
  12491.                             Keys = {
  12492.                                 keys.leftCtrl,
  12493.                                 keys.s
  12494.                             },
  12495.                             Enabled = function()
  12496.                                 return CheckOpenArtboard()
  12497.                             end
  12498.                         },
  12499.                         {
  12500.                             Separator = true
  12501.                         },
  12502.                         {
  12503.                             Title = 'Quit',
  12504.                             Click = function()
  12505.                                 if Close() then
  12506.                                     OneOS.Close()
  12507.                                 end
  12508.                             end
  12509.                         },
  12510.                 --[[
  12511.                         {
  12512.                             Title = 'Save As...',
  12513.                             Click = function()
  12514.  
  12515.                             end
  12516.                         }  
  12517.                 ]]--
  12518.                     }, self, true)
  12519.                 else
  12520.                     Current.Menu = nil
  12521.                 end
  12522.                 return true
  12523.             end, 'File', colours.lightGrey, false),
  12524.             Button:Initialise(7, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
  12525.                 if not self.Toggle then
  12526.                     Menu:New(7, 2, {
  12527.                 --[[
  12528.                         {
  12529.                             Title = "Undo",
  12530.                             Click = function()
  12531.                             end,
  12532.                             Keys = {
  12533.                                 keys.leftCtrl,
  12534.                                 keys.z
  12535.                             },
  12536.                             Enabled = function()
  12537.                                 return false
  12538.                             end
  12539.                         },
  12540.                         {
  12541.                             Title = 'Redo',
  12542.                             Click = function()
  12543.                                
  12544.                             end,
  12545.                             Keys = {
  12546.                                 keys.leftCtrl,
  12547.                                 keys.y
  12548.                             },
  12549.                             Enabled = function()
  12550.                                 return false
  12551.                             end
  12552.                         },
  12553.                         {
  12554.                             Separator = true
  12555.                         },
  12556.                 ]]--
  12557.                         {
  12558.                             Title = 'Cut',
  12559.                             Click = function()
  12560.                                 Clipboard.Cut(Current.Layer:PixelsInSelection(true), 'sketchpixels')
  12561.                             end,
  12562.                             Keys = {
  12563.                                 keys.leftCtrl,
  12564.                                 keys.x
  12565.                             },
  12566.                             Enabled = function()
  12567.                                 return Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
  12568.                             end
  12569.                         },
  12570.                         {
  12571.                             Title = 'Copy',
  12572.                             Click = function()
  12573.                                 Clipboard.Copy(Current.Layer:PixelsInSelection(), 'sketchpixels')
  12574.                             end,
  12575.                             Keys = {
  12576.                                 keys.leftCtrl,
  12577.                                 keys.c
  12578.                             },
  12579.                             Enabled = function()
  12580.                                 return Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
  12581.                             end
  12582.                         },
  12583.                         {
  12584.                             Title = 'Paste',
  12585.                             Click = function()
  12586.                                 Current.Layer:InsertPixels(Clipboard.Paste())
  12587.                             end,
  12588.                             Keys = {
  12589.                                 keys.leftCtrl,
  12590.                                 keys.v
  12591.                             },
  12592.                             Enabled = function()
  12593.                                 return (not Clipboard.isEmpty()) and Clipboard.Type == 'sketchpixels'
  12594.                             end
  12595.                         }
  12596.                     }, self, true)
  12597.                 else
  12598.                     Current.Menu = nil
  12599.                 end
  12600.                 return true
  12601.             end, 'Edit', colours.lightGrey, false),
  12602.             Button:Initialise(13, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
  12603.                 if toggle then
  12604.                     Menu:New(13, 2, {
  12605.                         {
  12606.                             Title = "Resize...",
  12607.                             Click = function()
  12608.                                 ResizeDocument()
  12609.                             end,
  12610.                             Keys = {
  12611.                                 keys.leftCtrl,
  12612.                                 keys.r
  12613.                             },
  12614.                             Enabled = function()
  12615.                                 return CheckOpenArtboard()
  12616.                             end
  12617.                         },
  12618.                         {
  12619.                             Title = "Crop",
  12620.                             Click = function()
  12621.                                 local top = 0
  12622.                                 local left = 0
  12623.                                 local bottom = 0
  12624.                                 local right = 0
  12625.                                 if Current.Selection[1].x < Current.Selection[2].x then
  12626.                                     left = Current.Selection[1].x - 1
  12627.                                     right = Current.Artboard.Width - Current.Selection[2].x
  12628.                                 else
  12629.                                     left = Current.Selection[2].x - 1
  12630.                                     right = Current.Artboard.Width - Current.Selection[1].x
  12631.                                 end
  12632.                                 if Current.Selection[1].y < Current.Selection[2].y then
  12633.                                     top = Current.Selection[1].y - 1
  12634.                                     bottom = Current.Artboard.Height - Current.Selection[2].y
  12635.                                 else
  12636.                                     top = Current.Selection[2].y - 1
  12637.                                     bottom = Current.Artboard.Height - Current.Selection[1].y
  12638.                                 end
  12639.                                 Current.Artboard:Resize(-1*top, -1*bottom, -1*left, -1*right)
  12640.  
  12641.                                 Current.Selection[2] = nil
  12642.                             end,
  12643.                             Enabled = function()
  12644.                                 if CheckSelectedLayer() and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
  12645.                                     return true
  12646.                                 else
  12647.                                     return false
  12648.                                 end
  12649.                             end
  12650.                         },
  12651.                         {
  12652.                             Separator = true
  12653.                         },
  12654.                         {
  12655.                             Title = 'New Layer...',
  12656.                             Click = function()
  12657.                                 MakeNewLayer()
  12658.                             end,
  12659.                             Keys = {
  12660.                                 keys.leftCtrl,
  12661.                                 keys.l
  12662.                             },
  12663.                             Enabled = function()
  12664.                                 return CheckOpenArtboard()
  12665.                             end
  12666.                         },
  12667.                         {
  12668.                             Title = 'Delete Layer',
  12669.                             Click = function()
  12670.                                 DeleteLayer()
  12671.                             end,
  12672.                             Enabled = function()
  12673.                                 return CheckSelectedLayer()
  12674.                             end
  12675.                         },
  12676.                         {
  12677.                             Title = 'Rename Layer...',
  12678.                             Click = function()
  12679.                                 RenameLayer()
  12680.                             end,
  12681.                             Enabled = function()
  12682.                                 return CheckSelectedLayer()
  12683.                             end
  12684.                         },
  12685.                         {
  12686.                             Separator = true
  12687.                         },
  12688.                         {
  12689.                             Title = 'Erase Selection',
  12690.                             Click = function()
  12691.                                 Current.Layer:EraseSelection()
  12692.                             end,
  12693.                             Keys = {
  12694.                                 keys.delete
  12695.                             },
  12696.                             Enabled = function()
  12697.                                 if CheckSelectedLayer() and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
  12698.                                     return true
  12699.                                 else
  12700.                                     return false
  12701.                                 end
  12702.                             end
  12703.                         },
  12704.                         {
  12705.                             Separator = true
  12706.                         },
  12707.                         {
  12708.                             Title = 'Hide Interface',
  12709.                             Click = function()
  12710.                                 Current.InterfaceVisible = not Current.InterfaceVisible
  12711.                             end,
  12712.                             Keys = {
  12713.                                 keys.tab
  12714.                             }
  12715.                         }
  12716.                     }, self, true)
  12717.                 else
  12718.                     Current.Menu = nil
  12719.                 end
  12720.                 return true
  12721.             end, 'Image', colours.lightGrey, false),
  12722.            
  12723.             Button:Initialise(20, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
  12724.                 if toggle then
  12725.                     local menuItems = {{
  12726.                             Title = "Change Size",
  12727.                             Click = function()
  12728.                                 DisplayToolSizeWindow()
  12729.                             end,
  12730.                             Keys = {
  12731.                                 keys.leftCtrl,
  12732.                                 keys.t
  12733.                             }
  12734.                         },
  12735.                         {
  12736.                             Separator = true
  12737.                         }
  12738.                     }
  12739.                    
  12740.                     local _keys = {'h','p','e','f','s','m','t'}
  12741.                     for i, tool in ipairs(Tools) do
  12742.                         table.insert(menuItems, {
  12743.                             Title = tool.Name,
  12744.                             Click = function()
  12745.                                 SetTool(tool)
  12746.                                 local m = ModuleNamed('Tools')
  12747.                                 m:Update(m.ToolbarItem)
  12748.                             end,
  12749.                             Keys = {
  12750.                                 keys[_keys[i]]
  12751.                             },
  12752.                             Enabled = function()
  12753.                                 return CheckOpenArtboard()
  12754.                             end
  12755.                         })
  12756.                     end
  12757.  
  12758.                     Menu:New(20, 2, menuItems, self, true)
  12759.                 else
  12760.                     Current.Menu = nil
  12761.                 end
  12762.                 return true
  12763.             end, 'Tools', colours.lightGrey, false),
  12764.         })
  12765.     end
  12766.  
  12767.     function Timer(event, timer)
  12768.         if timer == Current.ControlPressedTimer then
  12769.             Current.ControlPressedTimer = nil
  12770.         elseif timer == Current.SelectionDrawTimer then
  12771.             if Current.Artboard then
  12772.                 Current.Artboard.SelectionIsBlack = not Current.Artboard.SelectionIsBlack
  12773.                 Draw()
  12774.             end
  12775.         end
  12776.     end
  12777.  
  12778.     function Initialise(arg)
  12779.         if not OneOS then
  12780.             SplashScreen()
  12781.         end
  12782.         EventRegister('mouse_click', TryClick)
  12783.         EventRegister('mouse_drag', function(event, side, x, y)TryClick(event, side, x, y, true)end)
  12784.         EventRegister('mouse_scroll', Scroll)
  12785.         EventRegister('key', HandleKey)
  12786.         EventRegister('char', HandleKey)
  12787.         EventRegister('timer', Timer)
  12788.         EventRegister('terminate', function(event) if Close() then error( "Terminated", 0 ) end end)
  12789.  
  12790.  
  12791.         Current.Toolbar = Toolbar:New('right', true)
  12792.  
  12793.         for k, v in pairs(Modules) do
  12794.             v:Initialise()
  12795.         end
  12796.        
  12797.         --term.setBackgroundColour(UIColours.Background)
  12798.         --term.clear()
  12799.  
  12800.         LoadMenuBar()
  12801.  
  12802.         local _fs = fs
  12803.         if OneOS then
  12804.             _fs = OneOS.FS
  12805.         end
  12806.         if arg and _fs.exists(arg) then
  12807.             OpenDocument(arg)
  12808.         else
  12809.             DisplayNewDocumentWindow()
  12810.             Current.Window.Visible = false
  12811.         end
  12812.  
  12813.         ShowInterfaceButton = Button:Initialise(Drawing.Screen.Width - 15, 1, nil, 1, colours.grey, nil, function(self)
  12814.             Current.InterfaceVisible = true
  12815.             Draw()
  12816.         end, 'Show Interface')
  12817.  
  12818.         Draw()
  12819.         if Current.Window then
  12820.             Current.Window.Visible = true
  12821.             Draw()
  12822.         end
  12823.  
  12824.         EventHandler()
  12825.     end
  12826.  
  12827.     function SplashScreen()
  12828.         local splashIcon = {{1,1,1,256,256,256,256,256,256,256,256,1,1,1,},{1,256,256,8,8,8,8,8,8,8,8,256,256,1,},{256,8,8,8,8,8,8,8,8,8,8,8,8,256,},{256,256,256,8,8,8,8,8,8,8,8,256,256,256,},{256,256,256,256,256,256,256,256,256,256,256,256,256,256,},{2048,2048,256,256,256,256,256,256,256,256,256,256,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{256,256,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,256,256,},{1,256,256,256,256,256,256,256,256,256,256,256,256,1,},{1,1,1,256,256,256,256,256,256,256,256,1,1,1,},["text"]={{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," ","S","k","e","t","c","h"," "," "," "," ",},{" "," "," "," "," "," ","b","y"," "," "," "," "," "," ",},{" "," "," "," "," ","o","e","e","d"," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},},["textcol"]={{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,256,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,1,1,1,1,1,1,32768,32768,32768,32768,},{32768,32768,32768,32768,8,8,8,8,8,8,8,32768,32768,32768,},{32768,32768,32768,32768,1,1,1,1,1,32768,8,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},},}
  12829.         Drawing.Clear(colours.white)
  12830.         Drawing.DrawImage((Drawing.Screen.Width - 14)/2, (Drawing.Screen.Height - 13)/2, splashIcon, 14, 13)
  12831.         Drawing.DrawBuffer()
  12832.         parallel.waitForAny(function()sleep(1)end, function()os.pullEvent('mouse_click')end)
  12833.     end
  12834.  
  12835.     LongestString = function(input, key)
  12836.         local length = 0
  12837.         for i = 1, #input do
  12838.             local value = input[i]
  12839.             if key then
  12840.                 if value[key] then
  12841.                     value = value[key]
  12842.                 else
  12843.                     value = ''
  12844.                 end
  12845.             end
  12846.             local titleLength = string.len(value)
  12847.             if titleLength > length then
  12848.                 length = titleLength
  12849.             end
  12850.         end
  12851.         return length
  12852.     end
  12853.  
  12854.     function HandleKey(...)
  12855.         local args = {...}
  12856.         local event = args[1]
  12857.         local keychar = args[2]
  12858.         if event == 'key' and Current.Tool and Current.Tool.Name == 'Text' and Current.Input and (keychar == keys.up or keychar == keys.down or keychar == keys.left or keychar == keys.right) then
  12859.             local currentPos = {Current.CursorPos[1] - Current.Artboard.X + 1, Current.CursorPos[2] - Current.Artboard.Y + 1}
  12860.             if keychar == keys.up then
  12861.                 currentPos[2] = currentPos[2] - 1
  12862.             elseif keychar == keys.down then
  12863.                 currentPos[2] = currentPos[2] + 1
  12864.             elseif keychar == keys.left then
  12865.                 currentPos[1] = currentPos[1] - 1
  12866.             elseif keychar == keys.right then
  12867.                 currentPos[1] = currentPos[1] + 1
  12868.             end
  12869.  
  12870.             if currentPos[1] < 1 then
  12871.                 currentPos[1] = 1
  12872.             end
  12873.  
  12874.             if currentPos[1] > Current.Artboard.Width then
  12875.                 currentPos[1] = Current.Artboard.Width
  12876.             end
  12877.  
  12878.             if currentPos[2] < 1 then
  12879.                 currentPos[2] = 1
  12880.             end
  12881.  
  12882.             if currentPos[2] > Current.Artboard.Height then
  12883.                 currentPos[2] = Current.Artboard.Height
  12884.             end
  12885.  
  12886.             Current.Tool:Use(currentPos[1], currentPos[2])
  12887.             Current.Modified = true
  12888.             Draw()
  12889.         elseif Current.Input then
  12890.             if event == 'char' then
  12891.                 Current.Input:Char(keychar)
  12892.             elseif event == 'key' then
  12893.                 Current.Input:Key(keychar)
  12894.             end
  12895.         elseif event == 'key' then
  12896.             CheckKeyboardShortcut(keychar)
  12897.         end
  12898.     end
  12899.  
  12900.     function Scroll(event, direction, x, y)
  12901.         if Current.Window and Current.Window.OpenButton then
  12902.             Current.Window.Scroll = Current.Window.Scroll + direction
  12903.             if Current.Window.Scroll < 0 then
  12904.                 Current.Window.Scroll = 0
  12905.             elseif Current.Window.Scroll > Current.Window.MaxScroll then
  12906.                 Current.Window.Scroll = Current.Window.MaxScroll
  12907.             end
  12908.         end
  12909.         Draw()
  12910.     end
  12911.  
  12912.     function CheckKeyboardShortcut(key)
  12913.         local shortcuts = {}
  12914.  
  12915.         if key == keys.leftCtrl then
  12916.             Current.ControlPressedTimer = os.startTimer(0.5)
  12917.             return
  12918.         end
  12919.         if Current.ControlPressedTimer then
  12920.             shortcuts[keys.n] = function() DisplayNewDocumentWindow() end
  12921.             shortcuts[keys.o] = function() DisplayOpenDocumentWindow() end
  12922.             shortcuts[keys.s] = function() Current.Artboard:Save() end
  12923.             shortcuts[keys.x] = function() if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then Clipboard.Cut(Current.Layer:PixelsInSelection(true), 'sketchpixels') end end
  12924.             shortcuts[keys.c] = function() if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then Clipboard.Copy(Current.Layer:PixelsInSelection(), 'sketchpixels') end end
  12925.             shortcuts[keys.v] = function() if (not Clipboard.isEmpty()) and Clipboard.Type == 'sketchpixels' then Current.Layer:InsertPixels(Clipboard.Paste()) end end
  12926.             shortcuts[keys.r] = function() ResizeDocument() end
  12927.             shortcuts[keys.l] = function() MakeNewLayer() end
  12928.         end
  12929.  
  12930.         shortcuts[keys.delete] = function() if CheckSelectedLayer() and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then Current.Layer:EraseSelection() Draw() end end
  12931.         shortcuts[keys.backspace] = shortcuts[keys.delete]
  12932.         shortcuts[keys.tab] = function() Current.InterfaceVisible = not Current.InterfaceVisible Draw() end
  12933.  
  12934.         shortcuts[keys.h] = function() SetTool(ToolNamed('Hand')) ModuleNamed('Tools'):Update() Draw() end
  12935.         shortcuts[keys.e] = function() SetTool(ToolNamed('Eraser')) ModuleNamed('Tools'):Update() Draw() end
  12936.         shortcuts[keys.p] = function() SetTool(ToolNamed('Pencil')) ModuleNamed('Tools'):Update() Draw() end
  12937.         shortcuts[keys.f] = function() SetTool(ToolNamed('Fill Bucket')) ModuleNamed('Tools'):Update() Draw() end
  12938.         shortcuts[keys.m] = function() SetTool(ToolNamed('Move')) ModuleNamed('Tools'):Update() Draw() end
  12939.         shortcuts[keys.s] = function() SetTool(ToolNamed('Select')) ModuleNamed('Tools'):Update() Draw() end
  12940.         shortcuts[keys.t] = function() SetTool(ToolNamed('Text')) ModuleNamed('Tools'):Update() Draw() end
  12941.  
  12942.         if shortcuts[key] then
  12943.             shortcuts[key]()
  12944.             return true
  12945.         else
  12946.             return false
  12947.         end
  12948.     end
  12949.  
  12950.     --[[
  12951.         Check if the given object falls under the click coordinates
  12952.     ]]--
  12953.     function CheckClick(object, x, y)
  12954.         if object.X <= x and object.Y <= y and object.X + object.Width > x and object.Y + object.Height > y then
  12955.             return true
  12956.         end
  12957.     end
  12958.  
  12959.     --[[
  12960.         Attempt to clicka given object
  12961.     ]]--
  12962.     function DoClick(object, side, x, y, drag)
  12963.         if object and CheckClick(object, x, y) then
  12964.             return object:Click(side, x - object.X + 1, y - object.Y + 1, drag)
  12965.         end
  12966.     end
  12967.  
  12968.     --[[
  12969.         Try to click at the given coordinates
  12970.     ]]--
  12971.     function TryClick(event, side, x, y, drag)
  12972.         if Current.InterfaceVisible and Current.Menu then
  12973.             if DoClick(Current.Menu, side, x, y, drag) then
  12974.                 Draw()
  12975.                 return
  12976.             else
  12977.                 if Current.Menu.Owner and Current.Menu.Owner.Toggle then
  12978.                     Current.Menu.Owner.Toggle = false
  12979.                 end
  12980.                 Current.Menu = nil
  12981.                 Draw()
  12982.                 return
  12983.             end
  12984.         elseif Current.Window then
  12985.             if DoClick(Current.Window, side, x, y, drag) then
  12986.                 Draw()
  12987.                 return
  12988.             else
  12989.                 Current.Window:Flash()
  12990.                 return
  12991.             end
  12992.         end
  12993.         local interfaceElements = {}
  12994.  
  12995.         if Current.InterfaceVisible then
  12996.             table.insert(interfaceElements, Current.MenuBar)
  12997.         else
  12998.             table.insert(interfaceElements, ShowInterfaceButton)
  12999.         end
  13000.  
  13001.         for i, v in ipairs(Lists.Interface.Toolbars) do
  13002.             for i, v2 in ipairs(v.ToolbarItems) do
  13003.                 table.insert(interfaceElements, v2)
  13004.             end
  13005.             table.insert(interfaceElements, v)
  13006.         end
  13007.  
  13008.         table.insert(interfaceElements, Current.Artboard)
  13009.  
  13010.         for i, object in ipairs(interfaceElements) do
  13011.             if DoClick(object, side, x, y, drag) then
  13012.                 Draw()
  13013.                 return
  13014.             end    
  13015.         end
  13016.         Draw()
  13017.     end
  13018.  
  13019.     --[[
  13020.         Registers functions to run on certain events
  13021.     ]]--
  13022.     function EventRegister(event, func)
  13023.         if not Events[event] then
  13024.             Events[event] = {}
  13025.         end
  13026.  
  13027.         table.insert(Events[event], func)
  13028.     end
  13029.  
  13030.     --[[
  13031.         The main loop event handler, runs registered event functinos
  13032.     ]]--
  13033.     function EventHandler()
  13034.         while true do
  13035.             local event, arg1, arg2, arg3, arg4 = os.pullEventRaw()
  13036.             if Events[event] then
  13037.                 for i, e in ipairs(Events[event]) do
  13038.                     e(event, arg1, arg2, arg3, arg4)
  13039.                 end
  13040.             end
  13041.         end
  13042.     end
  13043.  
  13044.     --[[
  13045.         Thanks to NitrogenFingers for the colour functions and NFT + NFP read/write functions
  13046.     ]]--
  13047.  
  13048.     --[[
  13049.         Gets the hex value from a colour
  13050.     ]]--
  13051.     local hexnums = { [10] = "a", [11] = "b", [12] = "c", [13] = "d", [14] = "e" , [15] = "f" }
  13052.     local function getHexOf(colour)
  13053.         if colour == colours.transparent or not colour or not tonumber(colour) then
  13054.                 return " "
  13055.         end
  13056.         local value = math.log(colour)/math.log(2)
  13057.         if value > 9 then
  13058.                 value = hexnums[value]
  13059.         end
  13060.         return value
  13061.     end
  13062.  
  13063.     --[[
  13064.         Gets the colour from a hex value
  13065.     ]]--
  13066.     local function getColourOf(hex)
  13067.         if hex == ' ' then
  13068.             return colours.transparent
  13069.         end
  13070.         local value = tonumber(hex, 16)
  13071.         if not value then return nil end
  13072.         value = math.pow(2,value)
  13073.         return value
  13074.     end
  13075.  
  13076.     --[[
  13077.         Saves the current artboard in .skch format
  13078.     ]]--
  13079.     function SaveSKCH()
  13080.         local layers = {}
  13081.         for i, l in ipairs(Current.Artboard.Layers) do
  13082.             local pixels = SaveNFT(i)
  13083.             local layer = {
  13084.                 Name = l.Name,
  13085.                 Pixels = pixels,
  13086.                 BackgroundColour = l.BackgroundColour,
  13087.                 Visible = l.Visible,
  13088.                 Index = l.Index,
  13089.             }
  13090.             table.insert(layers, layer)
  13091.         end
  13092.         return layers
  13093.     end
  13094.  
  13095.     --[[
  13096.         Saves the current artboard in .nft format
  13097.     ]]--
  13098.     function SaveNFT(layer)
  13099.         layer = layer or 1
  13100.         local lines = {}
  13101.         local width = Current.Artboard.Width
  13102.         local height = Current.Artboard.Height
  13103.         for y = 1, height do
  13104.             local line = ''
  13105.             local currentBackgroundColour = nil
  13106.             local currentTextColour = nil
  13107.             for x = 1, width do
  13108.                 local pixel = Current.Artboard.Layers[layer].Pixels[x][y]
  13109.                 if pixel.BackgroundColour ~= currentBackgroundColour then
  13110.                     line = line..string.char(30)..getHexOf(pixel.BackgroundColour)
  13111.                     currentBackgroundColour = pixel.BackgroundColour
  13112.                 end
  13113.                 if pixel.TextColour ~= currentTextColour then
  13114.                     line = line..string.char(31)..getHexOf(pixel.TextColour)
  13115.                     currentTextColour = pixel.TextColour
  13116.                 end
  13117.                 line = line .. pixel.Character
  13118.             end
  13119.             table.insert(lines, line)
  13120.         end
  13121.         return lines
  13122.     end
  13123.  
  13124.     --[[
  13125.         Saves the current artboard in .nfp format
  13126.     ]]--
  13127.     function SaveNFP()
  13128.         local lines = {}
  13129.         local width = Current.Artboard.Width
  13130.         local height = Current.Artboard.Height
  13131.         for y = 1, height do
  13132.             local line = ''
  13133.             for x = 1, width do
  13134.                 line = line .. getHexOf(Current.Artboard.Layers[1].Pixels[x][y].BackgroundColour)
  13135.             end
  13136.             table.insert(lines, line)
  13137.         end
  13138.         return lines
  13139.     end
  13140.  
  13141.     --[[
  13142.         Reads a .nfp file from the given path
  13143.     ]]--
  13144.     function ReadNFP(path)
  13145.         local pixels = {}
  13146.         local _fs = fs
  13147.         if OneOS then
  13148.             _fs = OneOS.FS
  13149.         end
  13150.         local file = _fs.open(path, 'r')
  13151.         local line = file.readLine()
  13152.         local y = 1
  13153.         while line do
  13154.             for x = 1, #line do
  13155.                 if not pixels[x] then
  13156.                     pixels[x] = {}
  13157.                 end
  13158.                 pixels[x][y] = {BackgroundColour = getColourOf(line:sub(x,x))}
  13159.             end
  13160.             y = y + 1
  13161.             line = file.readLine()
  13162.         end
  13163.         file.close()
  13164.         return {{Pixels = pixels}}
  13165.     end
  13166.  
  13167.     --[[
  13168.         Reads a .nft file from the given path
  13169.     ]]--
  13170.     function ReadNFT(path)
  13171.         local _fs = fs
  13172.         if OneOS then
  13173.             _fs = OneOS.FS
  13174.         end
  13175.         local file = _fs.open(path, 'r')
  13176.         local line = file.readLine()
  13177.         local lines = {}
  13178.         while line do
  13179.             table.insert(lines, line)
  13180.             line = file.readLine()
  13181.         end
  13182.         file.close()
  13183.         return {{Pixels = ParseNFT(lines)}}
  13184.     end
  13185.  
  13186.     --[[
  13187.         Converts the lines of an .nft document to readble pixel data
  13188.     ]]--
  13189.     function ParseNFT(lines)
  13190.         local pixels = {}
  13191.         for y, line in ipairs(lines) do
  13192.             local bgNext, fgNext = false, false
  13193.             local currBG, currFG = nil,nil
  13194.             local writePosition = 1
  13195.             for x = 1, #line do
  13196.                 if not pixels[writePosition] then
  13197.                     pixels[writePosition] = {}
  13198.                 end
  13199.  
  13200.                 local nextChar = string.sub(line, x, x)
  13201.                 if nextChar:byte() == 30 then
  13202.                         bgNext = true
  13203.                 elseif nextChar:byte() == 31 then
  13204.                         fgNext = true
  13205.                 elseif bgNext then
  13206.                         currBG = getColourOf(nextChar)
  13207.                         if currBG == nil then
  13208.                             currBG = colours.transparent
  13209.                         end
  13210.                         bgNext = false
  13211.                 elseif fgNext then
  13212.                         currFG = getColourOf(nextChar)
  13213.                         fgNext = false
  13214.                 else
  13215.                         if nextChar ~= " " and currFG == nil then
  13216.                                 currFG = colours.white
  13217.                         end
  13218.                         pixels[writePosition][y] = {BackgroundColour = currBG, TextColour = currFG, Character = nextChar}
  13219.                         writePosition = writePosition + 1
  13220.                 end
  13221.             end
  13222.         end
  13223.         return pixels
  13224.     end
  13225.  
  13226.     --[[
  13227.         Read a .skch file from the given path
  13228.     ]]--
  13229.     function ReadSKCH(path)
  13230.         local _fs = fs
  13231.         if OneOS then
  13232.             _fs = OneOS.FS
  13233.         end
  13234.         local file = _fs.open(path, 'r')
  13235.         local _layers = textutils.unserialize(file.readAll())
  13236.         file.close()
  13237.         local layers = {}
  13238.  
  13239.         for i, l in ipairs(_layers) do
  13240.             local layer = {
  13241.                 Name = l.Name,
  13242.                 Pixels = ParseNFT(l.Pixels),
  13243.                 BackgroundColour = l.BackgroundColour,
  13244.                 Visible = l.Visible,
  13245.                 Index = l.Index,
  13246.             }
  13247.             table.insert(layers, layer)
  13248.         end
  13249.         return layers
  13250.     end
  13251.  
  13252.     --[[
  13253.         Start the program after all functions and tables are loaded
  13254.     ]]--
  13255.     if term.isColor and term.isColor() then
  13256.         Initialise()
  13257.     else
  13258.         print('Sorry, but Sketch only works on Advanced (gold) Computers')
  13259.     end
  13260. end
  13261.  
  13262. function flowoffice()
  13263.         -- Table
  13264.  
  13265.     cells = {}
  13266.     pageAmount = 1
  13267.     currentPage = 1
  13268.     letters = {"A", "B", "C", "D", "E", "F", "G", "H", "I"}
  13269.     menu = false
  13270.     exit = false
  13271.     w, h = term.getSize()
  13272.  
  13273.     -- Table Variable Syntax: table[page][column][row][value/position][x/y (only if position is selected before)]
  13274.     x5 = 5
  13275.     page = 1
  13276.     for y = 2, 18 do
  13277.         for x = 1, #letters do
  13278.             cells[#cells + 1] = {page, "", x5, y}
  13279.             x5 = x5 + 5
  13280.         end
  13281.         x5 = 5
  13282.     end
  13283.  
  13284.     function drawScreen(page)
  13285.         term.clear()
  13286.         term.setTextColor(colors.white)
  13287.         for y = 2, h - 1 do
  13288.             if (y % 2) == 0 then
  13289.                 white = true
  13290.             else
  13291.                 white = false
  13292.             end
  13293.             for x = 5, w - 1, 5 do
  13294.                 term.setCursorPos(x, y)
  13295.                 if white then
  13296.                     term.setBackgroundColor(colors.white)
  13297.                 else
  13298.                     term.setBackgroundColor(colors.lightGray)
  13299.                 end
  13300.                 write("     ")
  13301.                 white = not white
  13302.             end
  13303.         end
  13304.         term.setBackgroundColor(colors.gray)
  13305.         for x = 1, w do
  13306.             term.setCursorPos(x, 1)
  13307.             write(" ")
  13308.             term.setCursorPos(x, h)
  13309.             write(" ")
  13310.         end
  13311.         for y = 1, h do
  13312.             term.setCursorPos(1, y)
  13313.             write("    ")
  13314.             term.setCursorPos(w - 1, y)
  13315.             write("  ")
  13316.         end
  13317.         term.setBackgroundColor(colors.black)
  13318.         term.setCursorPos(w - 1, 2)
  13319.         write("UP")
  13320.         term.setCursorPos(w - 1, h - 1)
  13321.         write("DN")
  13322.         term.setBackgroundColor(colors.gray)
  13323.         pagetext = {"P", " ", "A", " ", "G", " ", "E", " ", page}
  13324.         for i = 1, #pagetext do
  13325.             term.setCursorPos(w, 3 + i)
  13326.             write(pagetext[i])
  13327.         end
  13328.         x = 7
  13329.         for i = 1, #letters do
  13330.             term.setCursorPos(x, 1)
  13331.             write(letters[i])
  13332.             x = x + 5
  13333.         end
  13334.         yaxistext = (page * 17) - 17
  13335.         y = 2
  13336.         for i = 1, 17 do
  13337.             if yaxistext + i < 10 then
  13338.                 term.setCursorPos(4, y)
  13339.             elseif yaxistext + i >= 10 and yaxistext + i < 100 then
  13340.                 term.setCursorPos(3, y)
  13341.             elseif yaxistext + i >= 100 then
  13342.                 term.setCursorPos(2, y)
  13343.             end
  13344.             write(yaxistext + i)
  13345.             y = y + 1
  13346.         end
  13347.         term.setBackgroundColor(colors.black)
  13348.         term.setCursorPos(1, h)
  13349.         write("MENU")
  13350.         term.setBackgroundColor(colors.gray)
  13351.         term.setCursorPos(6, h)
  13352.         write("Cell:")
  13353.         cellsonpage = (page * 153) - 153
  13354.         term.setTextColor(colors.black)
  13355.         for i = cellsonpage + 1, cellsonpage + 153 do
  13356.             if (cells[i][3] % 2) ~= 0 then
  13357.                 term.setBackgroundColor(colors.white)
  13358.             else
  13359.                 term.setBackgroundColor(colors.lightGray)
  13360.             end
  13361.             term.setCursorPos(cells[i][3], cells[i][4])
  13362.             term.write(string.sub(cells[i][2], 1, 4))
  13363.         end
  13364.     end
  13365.  
  13366.     function click(p1, p2, p3)
  13367.         if p2 > 0 and p2 < 5 and p3 == h then
  13368.             menu = true
  13369.         end
  13370.         for i = 1, #cells do
  13371.             if cells[i][1] == 1 and p2 >= cells[i][3] and p2 <= cells[i][3] + 4 and cells[i][4] == p3 then
  13372.                 term.setCursorPos(w - 8, h)
  13373.                 term.setBackgroundColor(colors.black)
  13374.                 term.setTextColor(colors.white)
  13375.                 write("OK")
  13376.                 term.setCursorPos(w - 5, h)
  13377.                 write("CANCEL")
  13378.                 term.setTextColor(colors.white)
  13379.                 term.setBackgroundColor(colors.gray)
  13380.                 if cells[i][2] == "" then
  13381.                     text = ""
  13382.                 else
  13383.                     text = cells[i][2]
  13384.                 end
  13385.                 while true do
  13386.                     event, param1, param2, param3 = os.pullEvent()
  13387.                     if event == "char" then
  13388.                         text = text .. param1
  13389.                         term.setCursorPos(13, h)
  13390.                         write(text)
  13391.                     elseif event == "mouse_click" then
  13392.                         if param2 > w - 9 and param2 < w - 6 and param3 == h then
  13393.                             cells[i][2] = text
  13394.                             break
  13395.                         elseif param2 > w - 6 and param2 < w + 1 and param3 == h then
  13396.                             break
  13397.                         end
  13398.                     end
  13399.                 end
  13400.             end
  13401.         end
  13402.     end
  13403.  
  13404.     drawScreen(currentPage)
  13405.  
  13406.     while not exit do
  13407.         event, param1, param2, param3 = os.pullEvent()
  13408.         if event == "mouse_click" then
  13409.             click(param1, param2, param3)
  13410.         end
  13411.         drawScreen(currentPage)
  13412.         if menu then
  13413.             menu = false
  13414.             term.setTextColor(colors.black)
  13415.             term.setBackgroundColor(colors.white)
  13416.             term.clear()
  13417.             term.setBackgroundColor(colors.lightGray)
  13418.             term.setCursorPos(2, 2)
  13419.             write("    ")
  13420.             term.setCursorPos(2, 4)
  13421.             write("    ")
  13422.             term.setCursorPos(2, 6)
  13423.             write("     ")
  13424.             term.setBackgroundColor(colors.white)
  13425.             term.setCursorPos(2, 2)
  13426.             write("Save")
  13427.             term.setCursorPos(2, 4)
  13428.             write("Open")
  13429.             term.setCursorPos(2, 6)
  13430.             write("Close")
  13431.             term.setCursorPos(2, 8)
  13432.             write("Menu will be better in next version!")
  13433.             event, param1, param2, param3 = os.pullEvent()
  13434.             while true do
  13435.                 if event == "mouse_click" then
  13436.                     if param3 == 2 then
  13437.                         term.clear()
  13438.                         term.setCursorPos(2, 2)
  13439.                         write("File name: ")
  13440.                         filename = read()
  13441.                         file = fs.open(filename, "w")
  13442.                         file.write(textutils.serialize(cells))
  13443.                         file.close()
  13444.                         drawScreen(currentPage)
  13445.                         break
  13446.                     elseif param3 == 4 then
  13447.                         term.clear()
  13448.                         term.setCursorPos(2, 2)
  13449.                         write("File name: ")
  13450.                         filename = read()
  13451.                         file = fs.open(filename, "r")
  13452.                         filelines = file.readAll()
  13453.                         cells = textutils.unserialize(filelines)
  13454.                         file.close()
  13455.                         drawScreen(currentPage)
  13456.                         break
  13457.                     elseif param3 == 6 then
  13458.                         home()
  13459.                         break
  13460.                     end
  13461.                 end
  13462.             end
  13463.         end
  13464.     end
  13465. end
  13466.  
  13467. function luaide()
  13468.  
  13469.     --  
  13470.     --  Lua IDE
  13471.     --  Made by GravityScore
  13472.     --  
  13473.  
  13474.  
  13475.     --  -------- Variables
  13476.  
  13477.     -- Version
  13478.     local version = "1.0"
  13479.     local args = {}
  13480.  
  13481.     -- Editing
  13482.     local w, h = term.getSize()
  13483.     local tabWidth = 2
  13484.  
  13485.     local autosaveInterval = 20
  13486.     local allowEditorEvent = true
  13487.     local keyboardShortcutTimeout = 0.4
  13488.  
  13489.     -- Clipboard
  13490.     local clipboard = nil
  13491.  
  13492.     -- Theme
  13493.     local theme = {}
  13494.  
  13495.     -- Language
  13496.     local languages = {}
  13497.     local curLanguage = {}
  13498.  
  13499.     -- Events
  13500.     local event_distract = "luaide_distractionEvent"
  13501.  
  13502.     -- Locations
  13503.     local updateURL = "https://raw.github.com/GravityScore/LuaIDE/master/luaide.lua"
  13504.     local ideLocation = "/" .. shell.getRunningProgram()
  13505.     local themeLocation = "/.LuaIDE-Theme"
  13506.  
  13507.     local function isAdvanced() return term.isColor and term.isColor() end
  13508.  
  13509.  
  13510.     --  -------- Utilities
  13511.  
  13512.     local function modRead(properties)
  13513.         local w, h = term.getSize()
  13514.         local defaults = {replaceChar = nil, history = nil, visibleLength = nil, textLength = nil,
  13515.             liveUpdates = nil, exitOnKey = nil}
  13516.         if not properties then properties = {} end
  13517.         for k, v in pairs(defaults) do if not properties[k] then properties[k] = v end end
  13518.         if properties.replaceChar then properties.replaceChar = properties.replaceChar:sub(1, 1) end
  13519.         if not properties.visibleLength then properties.visibleLength = w end
  13520.  
  13521.         local sx, sy = term.getCursorPos()
  13522.         local line = ""
  13523.         local pos = 0
  13524.         local historyPos = nil
  13525.  
  13526.         local function redraw(repl)
  13527.             local scroll = 0
  13528.             if properties.visibleLength and sx + pos > properties.visibleLength + 1 then
  13529.                 scroll = (sx + pos) - (properties.visibleLength + 1)
  13530.             end
  13531.  
  13532.             term.setCursorPos(sx, sy)
  13533.             local a = repl or properties.replaceChar
  13534.             if a then term.write(string.rep(a, line:len() - scroll))
  13535.             else term.write(line:sub(scroll + 1, -1)) end
  13536.             term.setCursorPos(sx + pos - scroll, sy)
  13537.         end
  13538.  
  13539.         local function sendLiveUpdates(event, ...)
  13540.             if type(properties.liveUpdates) == "function" then
  13541.                 local ox, oy = term.getCursorPos()
  13542.                 local a, data = properties.liveUpdates(line, event, ...)
  13543.                 if a == true and data == nil then
  13544.                     term.setCursorBlink(false)
  13545.                     return line
  13546.                 elseif a == true and data ~= nil then
  13547.                     term.setCursorBlink(false)
  13548.                     return data
  13549.                 end
  13550.                 term.setCursorPos(ox, oy)
  13551.             end
  13552.         end
  13553.  
  13554.         term.setCursorBlink(true)
  13555.         while true do
  13556.             local e, but, x, y, p4, p5 = os.pullEvent()
  13557.  
  13558.             if e == "char" then
  13559.                 local s = false
  13560.                 if properties.textLength and line:len() < properties.textLength then s = true
  13561.                 elseif not properties.textLength then s = true end
  13562.  
  13563.                 local canType = true
  13564.                 if not properties.grantPrint and properties.refusePrint then
  13565.                     local canTypeKeys = {}
  13566.                     if type(properties.refusePrint) == "table" then
  13567.                         for _, v in pairs(properties.refusePrint) do
  13568.                             table.insert(canTypeKeys, tostring(v):sub(1, 1))
  13569.                         end
  13570.                     elseif type(properties.refusePrint) == "string" then
  13571.                         for char in properties.refusePrint:gmatch(".") do
  13572.                             table.insert(canTypeKeys, char)
  13573.                         end
  13574.                     end
  13575.                     for _, v in pairs(canTypeKeys) do if but == v then canType = false end end
  13576.                 elseif properties.grantPrint then
  13577.                     canType = false
  13578.                     local canTypeKeys = {}
  13579.                     if type(properties.grantPrint) == "table" then
  13580.                         for _, v in pairs(properties.grantPrint) do
  13581.                             table.insert(canTypeKeys, tostring(v):sub(1, 1))
  13582.                         end
  13583.                     elseif type(properties.grantPrint) == "string" then
  13584.                         for char in properties.grantPrint:gmatch(".") do
  13585.                             table.insert(canTypeKeys, char)
  13586.                         end
  13587.                     end
  13588.                     for _, v in pairs(canTypeKeys) do if but == v then canType = true end end
  13589.                 end
  13590.  
  13591.                 if s and canType then
  13592.                     line = line:sub(1, pos) .. but .. line:sub(pos + 1, -1)
  13593.                     pos = pos + 1
  13594.                     redraw()
  13595.                 end
  13596.             elseif e == "key" then
  13597.                 if but == keys.enter then break
  13598.                 elseif but == keys.left then if pos > 0 then pos = pos - 1 redraw() end
  13599.                 elseif but == keys.right then if pos < line:len() then pos = pos + 1 redraw() end
  13600.                 elseif (but == keys.up or but == keys.down) and properties.history then
  13601.                     redraw(" ")
  13602.                     if but == keys.up then
  13603.                         if historyPos == nil and #properties.history > 0 then
  13604.                             historyPos = #properties.history
  13605.                         elseif historyPos > 1 then
  13606.                             historyPos = historyPos - 1
  13607.                         end
  13608.                     elseif but == keys.down then
  13609.                         if historyPos == #properties.history then historyPos = nil
  13610.                         elseif historyPos ~= nil then historyPos = historyPos + 1 end
  13611.                     end
  13612.  
  13613.                     if properties.history and historyPos then
  13614.                         line = properties.history[historyPos]
  13615.                         pos = line:len()
  13616.                     else
  13617.                         line = ""
  13618.                         pos = 0
  13619.                     end
  13620.  
  13621.                     redraw()
  13622.                     local a = sendLiveUpdates("history")
  13623.                     if a then return a end
  13624.                 elseif but == keys.backspace and pos > 0 then
  13625.                     redraw(" ")
  13626.                     line = line:sub(1, pos - 1) .. line:sub(pos + 1, -1)
  13627.                     pos = pos - 1
  13628.                     redraw()
  13629.                     local a = sendLiveUpdates("delete")
  13630.                     if a then return a end
  13631.                 elseif but == keys.home then
  13632.                     pos = 0
  13633.                     redraw()
  13634.                 elseif but == keys.delete and pos < line:len() then
  13635.                     redraw(" ")
  13636.                     line = line:sub(1, pos) .. line:sub(pos + 2, -1)
  13637.                     redraw()
  13638.                     local a = sendLiveUpdates("delete")
  13639.                     if a then return a end
  13640.                 elseif but == keys["end"] then
  13641.                     pos = line:len()
  13642.                     redraw()
  13643.                 elseif properties.exitOnKey then
  13644.                     if but == properties.exitOnKey or (properties.exitOnKey == "control" and
  13645.                             (but == 29 or but == 157)) then
  13646.                         term.setCursorBlink(false)
  13647.                         return nil
  13648.                     end
  13649.                 end
  13650.             end
  13651.             local a = sendLiveUpdates(e, but, x, y, p4, p5)
  13652.             if a then return a end
  13653.         end
  13654.  
  13655.         term.setCursorBlink(false)
  13656.         if line ~= nil then line = line:gsub("^%s*(.-)%s*$", "%1") end
  13657.         return line
  13658.     end
  13659.  
  13660.  
  13661.     --  -------- Themes
  13662.  
  13663.     local defaultTheme = {
  13664.         background = "gray",
  13665.         backgroundHighlight = "lightGray",
  13666.         prompt = "cyan",
  13667.         promptHighlight = "lightBlue",
  13668.         err = "red",
  13669.         errHighlight = "pink",
  13670.  
  13671.         editorBackground = "gray",
  13672.         editorLineHightlight = "lightBlue",
  13673.         editorLineNumbers = "gray",
  13674.         editorLineNumbersHighlight = "lightGray",
  13675.         editorError = "pink",
  13676.         editorErrorHighlight = "red",
  13677.  
  13678.         textColor = "white",
  13679.         conditional = "yellow",
  13680.         constant = "orange",
  13681.         ["function"] = "magenta",
  13682.         string = "red",
  13683.         comment = "lime"
  13684.     }
  13685.  
  13686.     local normalTheme = {
  13687.         background = "black",
  13688.         backgroundHighlight = "black",
  13689.         prompt = "black",
  13690.         promptHighlight = "black",
  13691.         err = "black",
  13692.         errHighlight = "black",
  13693.  
  13694.         editorBackground = "black",
  13695.         editorLineHightlight = "black",
  13696.         editorLineNumbers = "black",
  13697.         editorLineNumbersHighlight = "white",
  13698.         editorError = "black",
  13699.         editorErrorHighlight = "black",
  13700.  
  13701.         textColor = "white",
  13702.         conditional = "white",
  13703.         constant = "white",
  13704.         ["function"] = "white",
  13705.         string = "white",
  13706.         comment = "white"
  13707.     }
  13708.  
  13709.     local availableThemes = {
  13710.         {"Water (Default)", "https://raw.github.com/GravityScore/LuaIDE/master/themes/default.txt"},
  13711.         {"Fire", "https://raw.github.com/GravityScore/LuaIDE/master/themes/fire.txt"},
  13712.         {"Sublime Text 2", "https://raw.github.com/GravityScore/LuaIDE/master/themes/st2.txt"},
  13713.         {"Midnight", "https://raw.github.com/GravityScore/LuaIDE/master/themes/midnight.txt"},
  13714.         {"TheOriginalBIT", "https://raw.github.com/GravityScore/LuaIDE/master/themes/bit.txt"},
  13715.         {"Superaxander", "https://raw.github.com/GravityScore/LuaIDE/master/themes/superaxander.txt"},
  13716.         {"Forest", "https://raw.github.com/GravityScore/LuaIDE/master/themes/forest.txt"},
  13717.         {"Night", "https://raw.github.com/GravityScore/LuaIDE/master/themes/night.txt"},
  13718.         {"Original", "https://raw.github.com/GravityScore/LuaIDE/master/themes/original.txt"},
  13719.     }
  13720.  
  13721.     local function loadTheme(path)
  13722.         local f = io.open(path)
  13723.         local l = f:read("*l")
  13724.         local config = {}
  13725.         while l ~= nil do
  13726.             local k, v = string.match(l, "^(%a+)=(%a+)")
  13727.             if k and v then config[k] = v end
  13728.             l = f:read("*l")
  13729.         end
  13730.         f:close()
  13731.         return config
  13732.     end
  13733.  
  13734.     -- Load Theme
  13735.     if isAdvanced() then theme = defaultTheme
  13736.     else theme = normalTheme end
  13737.  
  13738.  
  13739.     --  -------- Drawing
  13740.  
  13741.     local function centerPrint(text, ny)
  13742.         if type(text) == "table" then for _, v in pairs(text) do centerPrint(v) end
  13743.         else
  13744.             local x, y = term.getCursorPos()
  13745.             local w, h = term.getSize()
  13746.             term.setCursorPos(w/2 - text:len()/2 + (#text % 2 == 0 and 1 or 0), ny or y)
  13747.             print(text)
  13748.         end
  13749.     end
  13750.  
  13751.     local function title(t)
  13752.         term.setTextColor(colors[theme.textColor])
  13753.         term.setBackgroundColor(colors[theme.background])
  13754.         term.clear()
  13755.  
  13756.         term.setBackgroundColor(colors[theme.backgroundHighlight])
  13757.         for i = 2, 4 do term.setCursorPos(1, i) term.clearLine() end
  13758.         term.setCursorPos(3, 3)
  13759.         term.write(t)
  13760.     end
  13761.  
  13762.     local function centerRead(wid, begt)
  13763.         local function liveUpdate(line, e, but, x, y, p4, p5)
  13764.             if isAdvanced() and e == "mouse_click" and x >= w/2 - wid/2 and x <= w/2 - wid/2 + 10
  13765.                     and y >= 13 and y <= 15 then
  13766.                 return true, ""
  13767.             end
  13768.         end
  13769.  
  13770.         if not begt then begt = "" end
  13771.         term.setTextColor(colors[theme.textColor])
  13772.         term.setBackgroundColor(colors[theme.promptHighlight])
  13773.         for i = 8, 10 do
  13774.             term.setCursorPos(w/2 - wid/2, i)
  13775.             term.write(string.rep(" ", wid))
  13776.         end
  13777.  
  13778.         if isAdvanced() then
  13779.             term.setBackgroundColor(colors[theme.errHighlight])
  13780.             for i = 13, 15 do
  13781.                 term.setCursorPos(w/2 - wid/2 + 1, i)
  13782.                 term.write(string.rep(" ", 10))
  13783.             end
  13784.             term.setCursorPos(w/2 - wid/2 + 2, 14)
  13785.             term.write("> Cancel")
  13786.         end
  13787.  
  13788.         term.setBackgroundColor(colors[theme.promptHighlight])
  13789.         term.setCursorPos(w/2 - wid/2 + 1, 9)
  13790.         term.write("> " .. begt)
  13791.         return modRead({visibleLength = w/2 + wid/2, liveUpdates = liveUpdate})
  13792.     end
  13793.  
  13794.  
  13795.     --  -------- Prompt
  13796.  
  13797.     local function prompt(list, dir, isGrid)
  13798.         local function draw(sel)
  13799.             for i, v in ipairs(list) do
  13800.                 if i == sel then term.setBackgroundColor(v.highlight or colors[theme.promptHighlight])
  13801.                 else term.setBackgroundColor(v.bg or colors[theme.prompt]) end
  13802.                 term.setTextColor(v.tc or colors[theme.textColor])
  13803.                 for i = -1, 1 do
  13804.                     term.setCursorPos(v[2], v[3] + i)
  13805.                     term.write(string.rep(" ", v[1]:len() + 4))
  13806.                 end
  13807.  
  13808.                 term.setCursorPos(v[2], v[3])
  13809.                 if i == sel then
  13810.                     term.setBackgroundColor(v.highlight or colors[theme.promptHighlight])
  13811.                     term.write(" > ")
  13812.                 else term.write(" - ") end
  13813.                 term.write(v[1] .. " ")
  13814.             end
  13815.         end
  13816.  
  13817.         local key1 = dir == "horizontal" and 203 or 200
  13818.         local key2 = dir == "horizontal" and 205 or 208
  13819.         local sel = 1
  13820.         draw(sel)
  13821.  
  13822.         while true do
  13823.             local e, but, x, y = os.pullEvent()
  13824.             if e == "key" and but == 28 then
  13825.                 return list[sel][1]
  13826.             elseif e == "key" and but == key1 and sel > 1 then
  13827.                 sel = sel - 1
  13828.                 draw(sel)
  13829.             elseif e == "key" and but == key2 and ((err == true and sel < #list - 1) or (sel < #list)) then
  13830.                 sel = sel + 1
  13831.                 draw(sel)
  13832.             elseif isGrid and e == "key" and but == 203 and sel > 2 then
  13833.                 sel = sel - 2
  13834.                 draw(sel)
  13835.             elseif isGrid and e == "key" and but == 205 and sel < 3 then
  13836.                 sel = sel + 2
  13837.                 draw(sel)
  13838.             elseif e == "mouse_click" then
  13839.                 for i, v in ipairs(list) do
  13840.                     if x >= v[2] - 1 and x <= v[2] + v[1]:len() + 3 and y >= v[3] - 1 and y <= v[3] + 1 then
  13841.                         return list[i][1]
  13842.                     end
  13843.                 end
  13844.             end
  13845.         end
  13846.     end
  13847.  
  13848.     local function scrollingPrompt(list)
  13849.         local function draw(items, sel, loc)
  13850.             for i, v in ipairs(items) do
  13851.                 local bg = colors[theme.prompt]
  13852.                 local bghigh = colors[theme.promptHighlight]
  13853.                 if v:find("Back") or v:find("Return") then
  13854.                     bg = colors[theme.err]
  13855.                     bghigh = colors[theme.errHighlight]
  13856.                 end
  13857.  
  13858.                 if i == sel then term.setBackgroundColor(bghigh)
  13859.                 else term.setBackgroundColor(bg) end
  13860.                 term.setTextColor(colors[theme.textColor])
  13861.                 for x = -1, 1 do
  13862.                     term.setCursorPos(3, (i * 4) + x + 4)
  13863.                     term.write(string.rep(" ", w - 13))
  13864.                 end
  13865.  
  13866.                 term.setCursorPos(3, i * 4 + 4)
  13867.                 if i == sel then
  13868.                     term.setBackgroundColor(bghigh)
  13869.                     term.write(" > ")
  13870.                 else term.write(" - ") end
  13871.                 term.write(v .. " ")
  13872.             end
  13873.         end
  13874.  
  13875.         local function updateDisplayList(items, loc, len)
  13876.             local ret = {}
  13877.             for i = 1, len do
  13878.                 local item = items[i + loc - 1]
  13879.                 if item then table.insert(ret, item) end
  13880.             end
  13881.             return ret
  13882.         end
  13883.  
  13884.         -- Variables
  13885.         local sel = 1
  13886.         local loc = 1
  13887.         local len = 3
  13888.         local disList = updateDisplayList(list, loc, len)
  13889.         draw(disList, sel, loc)
  13890.  
  13891.         -- Loop
  13892.         while true do
  13893.             local e, key, x, y = os.pullEvent()
  13894.  
  13895.             if e == "mouse_click" then
  13896.                 for i, v in ipairs(disList) do
  13897.                     if x >= 3 and x <= w - 11 and y >= i * 4 + 3 and y <= i * 4 + 5 then return v end
  13898.                 end
  13899.             elseif e == "key" and key == 200 then
  13900.                 if sel > 1 then
  13901.                     sel = sel - 1
  13902.                     draw(disList, sel, loc)
  13903.                 elseif loc > 1 then
  13904.                     loc = loc - 1
  13905.                     disList = updateDisplayList(list, loc, len)
  13906.                     draw(disList, sel, loc)
  13907.                 end
  13908.             elseif e == "key" and key == 208 then
  13909.                 if sel < len then
  13910.                     sel = sel + 1
  13911.                     draw(disList, sel, loc)
  13912.                 elseif loc + len - 1 < #list then
  13913.                     loc = loc + 1
  13914.                     disList = updateDisplayList(list, loc, len)
  13915.                     draw(disList, sel, loc)
  13916.                 end
  13917.             elseif e == "mouse_scroll" then
  13918.                 os.queueEvent("key", key == -1 and 200 or 208)
  13919.             elseif e == "key" and key == 28 then
  13920.                 return disList[sel]
  13921.             end
  13922.         end
  13923.     end
  13924.  
  13925.     function monitorKeyboardShortcuts()
  13926.         local ta, tb = nil, nil
  13927.         local allowChar = false
  13928.         local shiftPressed = false
  13929.         while true do
  13930.             local event, char = os.pullEvent()
  13931.             if event == "key" and (char == 42 or char == 52) then
  13932.                 shiftPressed = true
  13933.                 tb = os.startTimer(keyboardShortcutTimeout)
  13934.             elseif event == "key" and (char == 29 or char == 157 or char == 219 or char == 220) then
  13935.                 allowEditorEvent = false
  13936.                 allowChar = true
  13937.                 ta = os.startTimer(keyboardShortcutTimeout)
  13938.             elseif event == "key" and allowChar then
  13939.                 local name = nil
  13940.                 for k, v in pairs(keys) do
  13941.                     if v == char then
  13942.                         if shiftPressed then os.queueEvent("shortcut", "ctrl shift", k:lower())
  13943.                         else os.queueEvent("shortcut", "ctrl", k:lower()) end
  13944.                         sleep(0.005)
  13945.                         allowEditorEvent = true
  13946.                     end
  13947.                 end
  13948.                 if shiftPressed then os.queueEvent("shortcut", "ctrl shift", char)
  13949.                 else os.queueEvent("shortcut", "ctrl", char) end
  13950.             elseif event == "timer" and char == ta then
  13951.                 allowEditorEvent = true
  13952.                 allowChar = false
  13953.             elseif event == "timer" and char == tb then
  13954.                 shiftPressed = false
  13955.             end
  13956.         end
  13957.     end
  13958.  
  13959.  
  13960.     --  -------- Saving and Loading
  13961.  
  13962.     local function download(url, path)
  13963.         for i = 1, 3 do
  13964.             local response = http.get(url)
  13965.             if response then
  13966.                 local data = response.readAll()
  13967.                 response.close()
  13968.                 if path then
  13969.                     local f = io.open(path, "w")
  13970.                     f:write(data)
  13971.                     f:close()
  13972.                 end
  13973.                 return true
  13974.             end
  13975.         end
  13976.  
  13977.         return false
  13978.     end
  13979.  
  13980.     local function saveFile(path, lines)
  13981.         local dir = path:sub(1, path:len() - fs.getName(path):len())
  13982.         if not fs.exists(dir) then fs.makeDir(dir) end
  13983.         if not fs.isDir(path) and not fs.isReadOnly(path) then
  13984.             local a = ""
  13985.             for _, v in pairs(lines) do a = a .. v .. "\n" end
  13986.  
  13987.             local f = io.open(path, "w")
  13988.             f:write(a)
  13989.             f:close()
  13990.             return true
  13991.         else return false end
  13992.     end
  13993.  
  13994.     local function loadFile(path)
  13995.         if not fs.exists(path) then
  13996.             local dir = path:sub(1, path:len() - fs.getName(path):len())
  13997.             if not fs.exists(dir) then fs.makeDir(dir) end
  13998.             local f = io.open(path, "w")
  13999.             f:write("")
  14000.             f:close()
  14001.         end
  14002.  
  14003.         local l = {}
  14004.         if fs.exists(path) and not fs.isDir(path) then
  14005.             local f = io.open(path, "r")
  14006.             if f then
  14007.                 local a = f:read("*l")
  14008.                 while a do
  14009.                     table.insert(l, a)
  14010.                     a = f:read("*l")
  14011.                 end
  14012.                 f:close()
  14013.             end
  14014.         else return nil end
  14015.  
  14016.         if #l < 1 then table.insert(l, "") end
  14017.         return l
  14018.     end
  14019.  
  14020.  
  14021.     --  -------- Languages
  14022.  
  14023.     languages.lua = {}
  14024.     languages.brainfuck = {}
  14025.     languages.none = {}
  14026.  
  14027.     --  Lua
  14028.  
  14029.     languages.lua.helpTips = {
  14030.         "A function you tried to call doesn't exist.",
  14031.         "You made a typo.",
  14032.         "The index of an array is nil.",
  14033.         "The wrong variable type was passed.",
  14034.         "A function/variable doesn't exist.",
  14035.         "You missed an 'end'.",
  14036.         "You missed a 'then'.",
  14037.         "You declared a variable incorrectly.",
  14038.         "One of your variables is mysteriously nil."
  14039.     }
  14040.  
  14041.     languages.lua.defaultHelpTips = {
  14042.         2, 5
  14043.     }
  14044.  
  14045.     languages.lua.errors = {
  14046.         ["Attempt to call nil."] = {1, 2},
  14047.         ["Attempt to index nil."] = {3, 2},
  14048.         [".+ expected, got .+"] = {4, 2, 9},
  14049.         ["'end' expected"] = {6, 2},
  14050.         ["'then' expected"] = {7, 2},
  14051.         ["'=' expected"] = {8, 2}
  14052.     }
  14053.  
  14054.     languages.lua.keywords = {
  14055.         ["and"] = "conditional",
  14056.         ["break"] = "conditional",
  14057.         ["do"] = "conditional",
  14058.         ["else"] = "conditional",
  14059.         ["elseif"] = "conditional",
  14060.         ["end"] = "conditional",
  14061.         ["for"] = "conditional",
  14062.         ["function"] = "conditional",
  14063.         ["if"] = "conditional",
  14064.         ["in"] = "conditional",
  14065.         ["local"] = "conditional",
  14066.         ["not"] = "conditional",
  14067.         ["or"] = "conditional",
  14068.         ["repeat"] = "conditional",
  14069.         ["return"] = "conditional",
  14070.         ["then"] = "conditional",
  14071.         ["until"] = "conditional",
  14072.         ["while"] = "conditional",
  14073.  
  14074.         ["true"] = "constant",
  14075.         ["false"] = "constant",
  14076.         ["nil"] = "constant",
  14077.  
  14078.         ["print"] = "function",
  14079.         ["write"] = "function",
  14080.         ["sleep"] = "function",
  14081.         ["pairs"] = "function",
  14082.         ["ipairs"] = "function",
  14083.         ["loadstring"] = "function",
  14084.         ["loadfile"] = "function",
  14085.         ["dofile"] = "function",
  14086.         ["rawset"] = "function",
  14087.         ["rawget"] = "function",
  14088.         ["setfenv"] = "function",
  14089.         ["getfenv"] = "function",
  14090.     }
  14091.  
  14092.     languages.lua.parseError = function(e)
  14093.         local ret = {filename = "unknown", line = -1, display = "Unknown!", err = ""}
  14094.         if e and e ~= "" then
  14095.             ret.err = e
  14096.             if e:find(":") then
  14097.                 ret.filename = e:sub(1, e:find(":") - 1):gsub("^%s*(.-)%s*$", "%1")
  14098.                 -- The "" is needed to circumvent a CC bug
  14099.                 e = (e:sub(e:find(":") + 1) .. ""):gsub("^%s*(.-)%s*$", "%1")
  14100.                 if e:find(":") then
  14101.                     ret.line = e:sub(1, e:find(":") - 1)
  14102.                     e = e:sub(e:find(":") + 2):gsub("^%s*(.-)%s*$", "%1") .. ""
  14103.                 end
  14104.             end
  14105.             ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. "."
  14106.         end
  14107.  
  14108.         return ret
  14109.     end
  14110.  
  14111.     languages.lua.getCompilerErrors = function(code)
  14112.         code = "local function ee65da6af1cb6f63fee9a081246f2fd92b36ef2(...)\n\n" .. code .. "\n\nend"
  14113.         local fn, err = loadstring(code)
  14114.         if not err then
  14115.             local _, e = pcall(fn)
  14116.             if e then err = e end
  14117.         end
  14118.  
  14119.         if err then
  14120.             local a = err:find("]", 1, true)
  14121.             if a then err = "string" .. err:sub(a + 1, -1) end
  14122.             local ret = languages.lua.parseError(err)
  14123.             if tonumber(ret.line) then ret.line = tonumber(ret.line) end
  14124.             return ret
  14125.         else return languages.lua.parseError(nil) end
  14126.     end
  14127.  
  14128.     languages.lua.run = function(path, ar)
  14129.         local fn, err = loadfile(path)
  14130.         setfenv(fn, getfenv())
  14131.         if not err then
  14132.             _, err = pcall(function() fn(unpack(ar)) end)
  14133.         end
  14134.         return err
  14135.     end
  14136.  
  14137.  
  14138.     --  Brainfuck
  14139.  
  14140.     languages.brainfuck.helpTips = {
  14141.         "Well idk...",
  14142.         "Isn't this the whole point of the language?",
  14143.         "Ya know... Not being able to debug it?",
  14144.         "You made a typo."
  14145.     }
  14146.  
  14147.     languages.brainfuck.defaultHelpTips = {
  14148.         1, 2, 3
  14149.     }
  14150.  
  14151.     languages.brainfuck.errors = {
  14152.         ["No matching '['"] = {1, 2, 3, 4}
  14153.     }
  14154.  
  14155.     languages.brainfuck.keywords = {}
  14156.  
  14157.     languages.brainfuck.parseError = function(e)
  14158.         local ret = {filename = "unknown", line = -1, display = "Unknown!", err = ""}
  14159.         if e and e ~= "" then
  14160.             ret.err = e
  14161.             ret.line = e:sub(1, e:find(":") - 1)
  14162.             e = e:sub(e:find(":") + 2):gsub("^%s*(.-)%s*$", "%1") .. ""
  14163.             ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. "."
  14164.         end
  14165.  
  14166.         return ret
  14167.     end
  14168.  
  14169.     languages.brainfuck.mapLoops = function(code)
  14170.         -- Map loops
  14171.         local loopLocations = {}
  14172.         local loc = 1
  14173.         local line = 1
  14174.         for let in string.gmatch(code, ".") do
  14175.             if let == "[" then
  14176.                 loopLocations[loc] = true
  14177.             elseif let == "]" then
  14178.                 local found = false
  14179.                 for i = loc, 1, -1 do
  14180.                     if loopLocations[i] == true then
  14181.                         loopLocations[i] = loc
  14182.                         found = true
  14183.                     end
  14184.                 end
  14185.  
  14186.                 if not found then
  14187.                     return line .. ": No matching '['"
  14188.                 end
  14189.             end
  14190.  
  14191.             if let == "\n" then line = line + 1 end
  14192.             loc = loc + 1
  14193.         end
  14194.         return loopLocations
  14195.     end
  14196.  
  14197.     languages.brainfuck.getCompilerErrors = function(code)
  14198.         local a = languages.brainfuck.mapLoops(code)
  14199.         if type(a) == "string" then return languages.brainfuck.parseError(a)
  14200.         else return languages.brainfuck.parseError(nil) end
  14201.     end
  14202.  
  14203.     languages.brainfuck.run = function(path)
  14204.         -- Read from file
  14205.         local f = io.open(path, "r")
  14206.         local content = f:read("*a")
  14207.         f:close()
  14208.  
  14209.         -- Define environment
  14210.         local dataCells = {}
  14211.         local dataPointer = 1
  14212.         local instructionPointer = 1
  14213.  
  14214.         -- Map loops
  14215.         local loopLocations = languages.brainfuck.mapLoops(content)
  14216.         if type(loopLocations) == "string" then return loopLocations end
  14217.  
  14218.         -- Execute code
  14219.         while true do
  14220.             local let = content:sub(instructionPointer, instructionPointer)
  14221.  
  14222.             if let == ">" then
  14223.                 dataPointer = dataPointer + 1
  14224.                 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
  14225.             elseif let == "<" then
  14226.                 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
  14227.                 dataPointer = dataPointer - 1
  14228.                 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
  14229.             elseif let == "+" then
  14230.                 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
  14231.                 dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] + 1
  14232.             elseif let == "-" then
  14233.                 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
  14234.                 dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] - 1
  14235.             elseif let == "." then
  14236.                 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
  14237.                 if term.getCursorPos() >= w then print("") end
  14238.                 write(string.char(math.max(1, dataCells[tostring(dataPointer)])))
  14239.             elseif let == "," then
  14240.                 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
  14241.                 term.setCursorBlink(true)
  14242.                 local e, but = os.pullEvent("char")
  14243.                 term.setCursorBlink(false)
  14244.                 dataCells[tostring(dataPointer)] = string.byte(but)
  14245.                 if term.getCursorPos() >= w then print("") end
  14246.                 write(but)
  14247.             elseif let == "/" then
  14248.                 if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
  14249.                 if term.getCursorPos() >= w then print("") end
  14250.                 write(dataCells[tostring(dataPointer)])
  14251.             elseif let == "[" then
  14252.                 if dataCells[tostring(dataPointer)] == 0 then
  14253.                     for k, v in pairs(loopLocations) do
  14254.                         if k == instructionPointer then instructionPointer = v end
  14255.                     end
  14256.                 end
  14257.             elseif let == "]" then
  14258.                 for k, v in pairs(loopLocations) do
  14259.                     if v == instructionPointer then instructionPointer = k - 1 end
  14260.                 end
  14261.             end
  14262.  
  14263.             instructionPointer = instructionPointer + 1
  14264.             if instructionPointer > content:len() then print("") break end
  14265.         end
  14266.     end
  14267.  
  14268.     --  None
  14269.  
  14270.     languages.none.helpTips = {}
  14271.     languages.none.defaultHelpTips = {}
  14272.     languages.none.errors = {}
  14273.     languages.none.keywords = {}
  14274.  
  14275.     languages.none.parseError = function(err)
  14276.         return {filename = "", line = -1, display = "", err = ""}
  14277.     end
  14278.  
  14279.     languages.none.getCompilerErrors = function(code)
  14280.         return languages.none.parseError(nil)
  14281.     end
  14282.  
  14283.     languages.none.run = function(path) end
  14284.  
  14285.  
  14286.     -- Load language
  14287.     curLanguage = languages.lua
  14288.  
  14289.  
  14290.     --  -------- Run GUI
  14291.  
  14292.     local function viewErrorHelp(e)
  14293.         title("LuaIDE - Error Help")
  14294.  
  14295.         local tips = nil
  14296.         for k, v in pairs(curLanguage.errors) do
  14297.             if e.display:find(k) then tips = v break end
  14298.         end
  14299.  
  14300.         term.setBackgroundColor(colors[theme.err])
  14301.         for i = 6, 8 do
  14302.             term.setCursorPos(5, i)
  14303.             term.write(string.rep(" ", 35))
  14304.         end
  14305.  
  14306.         term.setBackgroundColor(colors[theme.prompt])
  14307.         for i = 10, 18 do
  14308.             term.setCursorPos(5, i)
  14309.             term.write(string.rep(" ", 46))
  14310.         end
  14311.  
  14312.         if tips then
  14313.             term.setBackgroundColor(colors[theme.err])
  14314.             term.setCursorPos(6, 7)
  14315.             term.write("Error Help")
  14316.  
  14317.             term.setBackgroundColor(colors[theme.prompt])
  14318.             for i, v in ipairs(tips) do
  14319.                 term.setCursorPos(7, i + 10)
  14320.                 term.write("- " .. curLanguage.helpTips[v])
  14321.             end
  14322.         else
  14323.             term.setBackgroundColor(colors[theme.err])
  14324.             term.setCursorPos(6, 7)
  14325.             term.write("No Error Tips Available!")
  14326.  
  14327.             term.setBackgroundColor(colors[theme.prompt])
  14328.             term.setCursorPos(6, 11)
  14329.             term.write("There are no error tips available, but")
  14330.             term.setCursorPos(6, 12)
  14331.             term.write("you could see if it was any of these:")
  14332.  
  14333.             for i, v in ipairs(curLanguage.defaultHelpTips) do
  14334.                 term.setCursorPos(7, i + 12)
  14335.                 term.write("- " .. curLanguage.helpTips[v])
  14336.             end
  14337.         end
  14338.  
  14339.         prompt({{"Back", w - 8, 7}}, "horizontal")
  14340.     end
  14341.  
  14342.     local function run(path, lines, useArgs)
  14343.         local ar = {}
  14344.         if useArgs then
  14345.             title("LuaIDE - Run " .. fs.getName(path))
  14346.             local s = centerRead(w - 13, fs.getName(path) .. " ")
  14347.             for m in string.gmatch(s, "[^ \t]+") do ar[#ar + 1] = m:gsub("^%s*(.-)%s*$", "%1") end
  14348.         end
  14349.        
  14350.         saveFile(path, lines)
  14351.         term.setCursorBlink(false)
  14352.         term.setBackgroundColor(colors.black)
  14353.         term.setTextColor(colors.white)
  14354.         term.clear()
  14355.         term.setCursorPos(1, 1)
  14356.         local err = curLanguage.run(path, ar)
  14357.  
  14358.         term.setBackgroundColor(colors.black)
  14359.         print("\n")
  14360.         if err then
  14361.             if isAdvanced() then term.setTextColor(colors.red) end
  14362.             centerPrint("The program has crashed!")
  14363.         end
  14364.         term.setTextColor(colors.white)
  14365.         centerPrint("Press any key to return to LuaIDE...")
  14366.         while true do
  14367.             local e = os.pullEvent()
  14368.             if e == "key" then break end
  14369.         end
  14370.  
  14371.         -- To prevent key from showing up in editor
  14372.         os.queueEvent(event_distract)
  14373.         os.pullEvent()
  14374.  
  14375.         if err then
  14376.             if curLanguage == languages.lua and err:find("]") then
  14377.                 err = fs.getName(path) .. err:sub(err:find("]", 1, true) + 1, -1)
  14378.             end
  14379.  
  14380.             while true do
  14381.                 title("LuaIDE - Error!")
  14382.  
  14383.                 term.setBackgroundColor(colors[theme.err])
  14384.                 for i = 6, 8 do
  14385.                     term.setCursorPos(3, i)
  14386.                     term.write(string.rep(" ", w - 5))
  14387.                 end
  14388.                 term.setCursorPos(4, 7)
  14389.                 term.write("The program has crashed!")
  14390.  
  14391.                 term.setBackgroundColor(colors[theme.prompt])
  14392.                 for i = 10, 14 do
  14393.                     term.setCursorPos(3, i)
  14394.                     term.write(string.rep(" ", w - 5))
  14395.                 end
  14396.  
  14397.                 local formattedErr = curLanguage.parseError(err)
  14398.                 term.setCursorPos(4, 11)
  14399.                 term.write("Line: " .. formattedErr.line)
  14400.                 term.setCursorPos(4, 12)
  14401.                 term.write("Error:")
  14402.                 term.setCursorPos(5, 13)
  14403.  
  14404.                 local a = formattedErr.display
  14405.                 local b = nil
  14406.                 if a:len() > w - 8 then
  14407.                     for i = a:len(), 1, -1 do
  14408.                         if a:sub(i, i) == " " then
  14409.                             b = a:sub(i + 1, -1)
  14410.                             a = a:sub(1, i)
  14411.                             break
  14412.                         end
  14413.                     end
  14414.                 end
  14415.  
  14416.                 term.write(a)
  14417.                 if b then
  14418.                     term.setCursorPos(5, 14)
  14419.                     term.write(b)
  14420.                 end
  14421.                
  14422.                 local opt = prompt({{"Error Help", w/2 - 15, 17}, {"Go To Line", w/2 + 2, 17}},
  14423.                     "horizontal")
  14424.                 if opt == "Error Help" then
  14425.                     viewErrorHelp(formattedErr)
  14426.                 elseif opt == "Go To Line" then
  14427.                     -- To prevent key from showing up in editor
  14428.                     os.queueEvent(event_distract)
  14429.                     os.pullEvent()
  14430.  
  14431.                     return "go to", tonumber(formattedErr.line)
  14432.                 end
  14433.             end
  14434.         end
  14435.     end
  14436.  
  14437.  
  14438.     --  -------- Functions
  14439.  
  14440.     local function goto()
  14441.         term.setBackgroundColor(colors[theme.backgroundHighlight])
  14442.         term.setCursorPos(2, 1)
  14443.         term.clearLine()
  14444.         term.write("Line: ")
  14445.         local line = modRead({visibleLength = w - 2})
  14446.  
  14447.         local num = tonumber(line)
  14448.         if num and num > 0 then return num
  14449.         else
  14450.             term.setCursorPos(2, 1)
  14451.             term.clearLine()
  14452.             term.write("Not a line number!")
  14453.             sleep(1.6)
  14454.             return nil
  14455.         end
  14456.     end
  14457.  
  14458.     local function setsyntax()
  14459.         local opts = {
  14460.             "[Lua]   Brainfuck    None ",
  14461.             " Lua   [Brainfuck]   None ",
  14462.             " Lua    Brainfuck   [None]"
  14463.         }
  14464.         local sel = 1
  14465.  
  14466.         term.setCursorBlink(false)
  14467.         term.setBackgroundColor(colors[theme.backgroundHighlight])
  14468.         term.setCursorPos(2, 1)
  14469.         term.clearLine()
  14470.         term.write(opts[sel])
  14471.         while true do
  14472.             local e, but, x, y = os.pullEvent("key")
  14473.             if but == 203 then
  14474.                 sel = math.max(1, sel - 1)
  14475.                 term.setCursorPos(2, 1)
  14476.                 term.clearLine()
  14477.                 term.write(opts[sel])
  14478.             elseif but == 205 then
  14479.                 sel = math.min(#opts, sel + 1)
  14480.                 term.setCursorPos(2, 1)
  14481.                 term.clearLine()
  14482.                 term.write(opts[sel])
  14483.             elseif but == 28 then
  14484.                 if sel == 1 then curLanguage = languages.lua
  14485.                 elseif sel == 2 then curLanguage = languages.brainfuck
  14486.                 elseif sel == 3 then curLanguage = languages.none end
  14487.                 term.setCursorBlink(true)
  14488.                 return
  14489.             end
  14490.         end
  14491.     end
  14492.  
  14493.  
  14494.     --  -------- Re-Indenting
  14495.  
  14496.     local tabWidth = 2
  14497.  
  14498.     local comments = {}
  14499.     local strings = {}
  14500.  
  14501.     local increment = {
  14502.         "if%s+.+%s+then%s*$",
  14503.         "for%s+.+%s+do%s*$",
  14504.         "while%s+.+%s+do%s*$",
  14505.         "repeat%s*$",
  14506.         "function%s+[a-zA-Z_0-9](.*)%s*$"
  14507.     }
  14508.  
  14509.     local decrement = {
  14510.         "end",
  14511.         "until%s+.+"
  14512.     }
  14513.  
  14514.     local special = {
  14515.         "else%s*$",
  14516.         "elseif%s+.+%s+then%s*$"
  14517.     }
  14518.  
  14519.     local function check(func)
  14520.         for _, v in pairs(func) do
  14521.             local cLineStart = v["lineStart"]
  14522.             local cLineEnd = v["lineEnd"]
  14523.             local cCharStart = v["charStart"]
  14524.             local cCharEnd = v["charEnd"]
  14525.  
  14526.             if line >= cLineStart and line <= cLineEnd then
  14527.                 if line == cLineStart then return cCharStart < charNumb
  14528.                 elseif line == cLineEnd then return cCharEnd > charNumb
  14529.                 else return true end
  14530.             end
  14531.         end
  14532.     end
  14533.  
  14534.     local function isIn(line, loc)
  14535.         if check(comments) then return true end
  14536.         if check(strings) then return true end
  14537.         return false
  14538.     end
  14539.  
  14540.     local function setComment(ls, le, cs, ce)
  14541.         comments[#comments + 1] = {}
  14542.         comments[#comments].lineStart = ls
  14543.         comments[#comments].lineEnd = le
  14544.         comments[#comments].charStart = cs
  14545.         comments[#comments].charEnd = ce
  14546.     end
  14547.  
  14548.     local function setString(ls, le, cs, ce)
  14549.         strings[#strings + 1] = {}
  14550.         strings[#strings].lineStart = ls
  14551.         strings[#strings].lineEnd = le
  14552.         strings[#strings].charStart = cs
  14553.         strings[#strings].charEnd = ce
  14554.     end
  14555.  
  14556.     local function map(contents)
  14557.         local inCom = false
  14558.         local inStr = false
  14559.  
  14560.         for i = 1, #contents do
  14561.             if content[i]:find("%-%-%[%[") and not inStr and not inCom then
  14562.                 local cStart = content[i]:find("%-%-%[%[")
  14563.                 setComment(i, nil, cStart, nil)
  14564.                 inCom = true
  14565.             elseif content[i]:find("%-%-%[=%[") and not inStr and not inCom then
  14566.                 local cStart = content[i]:find("%-%-%[=%[")
  14567.                 setComment(i, nil, cStart, nil)
  14568.                 inCom = true
  14569.             elseif content[i]:find("%[%[") and not inStr and not inCom then
  14570.                 local cStart = content[i]:find("%[%[")
  14571.                 setString(i, nil, cStart, nil)
  14572.                 inStr = true
  14573.             elseif content[i]:find("%[=%[") and not inStr and not inCom then
  14574.                 local cStart = content[i]:find("%[=%[")
  14575.                 setString(i, nil, cStart, nil)
  14576.                 inStr = true
  14577.             end
  14578.  
  14579.             if content[i]:find("%]%]") and inStr and not inCom then
  14580.                 local cStart, cEnd = content[i]:find("%]%]")
  14581.                 strings[#strings].lineEnd = i
  14582.                 strings[#strings].charEnd = cEnd
  14583.                 inStr = false
  14584.             elseif content[i]:find("%]=%]") and inStr and not inCom then
  14585.                 local cStart, cEnd = content[i]:find("%]=%]")
  14586.                 strings[#strings].lineEnd = i
  14587.                 strings[#strings].charEnd = cEnd
  14588.                 inStr = false
  14589.             end
  14590.  
  14591.             if content[i]:find("%]%]") and not inStr and inCom then
  14592.                 local cStart, cEnd = content[i]:find("%]%]")
  14593.                 comments[#comments].lineEnd = i
  14594.                 comments[#comments].charEnd = cEnd
  14595.                 inCom = false
  14596.             elseif content[i]:find("%]=%]") and not inStr and inCom then
  14597.                 local cStart, cEnd = content[i]:find("%]=%]")
  14598.                 comments[#comments].lineEnd = i
  14599.                 comments[#comments].charEnd = cEnd
  14600.                 inCom = false
  14601.             end
  14602.  
  14603.             if content[i]:find("%-%-") and not inStr and not inCom then
  14604.                 local cStart = content[i]:find("%-%-")
  14605.                 setComment(i, i, cStart, -1)
  14606.             elseif content[i]:find("'") and not inStr and not inCom then
  14607.                 local cStart, cEnd = content[i]:find("'")
  14608.                 local nextChar = content[i]:sub(cEnd + 1, string.len(content[i]))
  14609.                 local _, cEnd = nextChar:find("'")
  14610.                 setString(i, i, cStart, cEnd)
  14611.             elseif content[i]:find('"') and not inStr and not inCom then
  14612.                 local cStart, cEnd = content[i]:find('"')
  14613.                 local nextChar = content[i]:sub(cEnd + 1, string.len(content[i]))
  14614.                 local _, cEnd = nextChar:find('"')
  14615.                 setString(i, i, cStart, cEnd)
  14616.             end
  14617.         end
  14618.     end
  14619.  
  14620.     local function reindent(contents)
  14621.         local err = nil
  14622.         if curLanguage ~= languages.lua then
  14623.             err = "Cannot indent languages other than Lua!"
  14624.         elseif curLanguage.getCompilerErrors(table.concat(contents, "\n")).line ~= -1 then
  14625.             err = "Cannot indent a program with errors!"
  14626.         end
  14627.  
  14628.         if err then
  14629.             term.setCursorBlink(false)
  14630.             term.setCursorPos(2, 1)
  14631.             term.setBackgroundColor(colors[theme.backgroundHighlight])
  14632.             term.clearLine()
  14633.             term.write(err)
  14634.             sleep(1.6)
  14635.             return contents
  14636.         end
  14637.  
  14638.         local new = {}
  14639.         local level = 0
  14640.         for k, v in pairs(contents) do
  14641.             local incrLevel = false
  14642.             local foundIncr = false
  14643.             for _, incr in pairs(increment) do
  14644.                 if v:find(incr) and not isIn(k, v:find(incr)) then
  14645.                     incrLevel = true
  14646.                 end
  14647.                 if v:find(incr:sub(1, -2)) and not isIn(k, v:find(incr)) then
  14648.                     foundIncr = true
  14649.                 end
  14650.             end
  14651.  
  14652.             local decrLevel = false
  14653.             if not incrLevel then
  14654.                 for _, decr in pairs(decrement) do
  14655.                     if v:find(decr) and not isIn(k, v:find(decr)) and not foundIncr then
  14656.                         level = math.max(0, level - 1)
  14657.                         decrLevel = true
  14658.                     end
  14659.                 end
  14660.             end
  14661.  
  14662.             if not decrLevel then
  14663.                 for _, sp in pairs(special) do
  14664.                     if v:find(sp) and not isIn(k, v:find(sp)) then
  14665.                         incrLevel = true
  14666.                         level = math.max(0, level - 1)
  14667.                     end
  14668.                 end
  14669.             end
  14670.  
  14671.             new[k] = string.rep(" ", level * tabWidth) .. v
  14672.             if incrLevel then level = level + 1 end
  14673.         end
  14674.  
  14675.         return new
  14676.     end
  14677.  
  14678.  
  14679.     --  -------- Menu
  14680.  
  14681.     local menu = {
  14682.         [1] = {"File",
  14683.     --      "About",
  14684.     --      "Settings",
  14685.     --      "",
  14686.             "New File  ^+N",
  14687.             "Open File ^+O",
  14688.             "Save File ^+S",
  14689.             "Close     ^+W",
  14690.             "Print     ^+P",
  14691.             "Quit      ^+Q"
  14692.         }, [2] = {"Edit",
  14693.             "Cut Line   ^+X",
  14694.             "Copy Line  ^+C",
  14695.             "Paste Line ^+V",
  14696.             "Delete Line",
  14697.             "Clear Line"
  14698.         }, [3] = {"Functions",
  14699.             "Go To Line    ^+G",
  14700.             "Re-Indent     ^+I",
  14701.             "Set Syntax    ^+E",
  14702.             "Start of Line ^+<",
  14703.             "End of Line   ^+>"
  14704.         }, [4] = {"Run",
  14705.             "Run Program       ^+R",
  14706.             "Run w/ Args ^+Shift+R"
  14707.         }
  14708.     }
  14709.  
  14710.     local shortcuts = {
  14711.         -- File
  14712.         ["ctrl n"] = "New File  ^+N",
  14713.         ["ctrl o"] = "Open File ^+O",
  14714.         ["ctrl s"] = "Save File ^+S",
  14715.         ["ctrl w"] = "Close     ^+W",
  14716.         ["ctrl p"] = "Print     ^+P",
  14717.         ["ctrl q"] = "Quit      ^+Q",
  14718.  
  14719.         -- Edit
  14720.         ["ctrl x"] = "Cut Line   ^+X",
  14721.         ["ctrl c"] = "Copy Line  ^+C",
  14722.         ["ctrl v"] = "Paste Line ^+V",
  14723.  
  14724.         -- Functions
  14725.         ["ctrl g"] = "Go To Line    ^+G",
  14726.         ["ctrl i"] = "Re-Indent     ^+I",
  14727.         ["ctrl e"] = "Set Syntax    ^+E",
  14728.         ["ctrl 203"] = "Start of Line ^+<",
  14729.         ["ctrl 205"] = "End of Line   ^+>",
  14730.  
  14731.         -- Run
  14732.         ["ctrl r"] = "Run Program       ^+R",
  14733.         ["ctrl shift r"] = "Run w/ Args ^+Shift+R"
  14734.     }
  14735.  
  14736.     local menuFunctions = {
  14737.         -- File
  14738.     --  ["About"] = function() end,
  14739.     --  ["Settings"] = function() end,
  14740.         ["New File  ^+N"] = function(path, lines) saveFile(path, lines) return "new" end,
  14741.         ["Open File ^+O"] = function(path, lines) saveFile(path, lines) return "open" end,
  14742.         ["Save File ^+S"] = function(path, lines) saveFile(path, lines) end,
  14743.         ["Close     ^+W"] = function(path, lines) saveFile(path, lines) return "menu" end,
  14744.         ["Print     ^+P"] = function(path, lines) saveFile(path, lines) return nil end,
  14745.         ["Quit      ^+Q"] = function(path, lines) saveFile(path, lines) return "exit" end,
  14746.  
  14747.         -- Edit
  14748.         ["Cut Line   ^+X"] = function(path, lines, y)
  14749.             clipboard = lines[y] table.remove(lines, y) return nil, lines end,
  14750.         ["Copy Line  ^+C"] = function(path, lines, y) clipboard = lines[y] end,
  14751.         ["Paste Line ^+V"] = function(path, lines, y)
  14752.             if clipboard then table.insert(lines, y, clipboard) end return nil, lines end,
  14753.         ["Delete Line"] = function(path, lines, y) table.remove(lines, y) return nil, lines end,
  14754.         ["Clear Line"] = function(path, lines, y) lines[y] = "" return nil, lines, "cursor" end,
  14755.  
  14756.         -- Functions
  14757.         ["Go To Line    ^+G"] = function() return nil, "go to", goto() end,
  14758.         ["Re-Indent     ^+I"] = function(path, lines)
  14759.             local a = reindent(lines) saveFile(path, lines) return nil, a
  14760.         end,
  14761.         ["Set Syntax    ^+E"] = function(path, lines)
  14762.             setsyntax()
  14763.             if curLanguage == languages.brainfuck and lines[1] ~= "-- Syntax: Brainfuck" then
  14764.                 table.insert(lines, 1, "-- Syntax: Brainfuck")
  14765.                 return nil, lines
  14766.             end
  14767.         end,
  14768.         ["Start of Line ^+<"] = function() os.queueEvent("key", 199) end,
  14769.         ["End of Line   ^+>"] = function() os.queueEvent("key", 207) end,
  14770.  
  14771.         -- Run
  14772.         ["Run Program       ^+R"] = function(path, lines)
  14773.             saveFile(path, lines)
  14774.             return nil, run(path, lines, false)
  14775.         end,
  14776.         ["Run w/ Args ^+Shift+R"] = function(path, lines)
  14777.             saveFile(path, lines)
  14778.             return nil, run(path, lines, true)
  14779.         end,
  14780.     }
  14781.  
  14782.     local function drawMenu(open)
  14783.         term.setCursorPos(1, 1)
  14784.         term.setTextColor(colors[theme.textColor])
  14785.         term.setBackgroundColor(colors[theme.backgroundHighlight])
  14786.         term.clearLine()
  14787.         local curX = 0
  14788.         for _, v in pairs(menu) do
  14789.             term.setCursorPos(3 + curX, 1)
  14790.             term.write(v[1])
  14791.             curX = curX + v[1]:len() + 3
  14792.         end
  14793.  
  14794.         if open then
  14795.             local it = {}
  14796.             local x = 1
  14797.             for _, v in pairs(menu) do
  14798.                 if open == v[1] then
  14799.                     it = v
  14800.                     break
  14801.                 end
  14802.                 x = x + v[1]:len() + 3
  14803.             end
  14804.             x = x + 1
  14805.  
  14806.             local items = {}
  14807.             for i = 2, #it do
  14808.                 table.insert(items, it[i])
  14809.             end
  14810.  
  14811.             local len = 1
  14812.             for _, v in pairs(items) do if v:len() + 2 > len then len = v:len() + 2 end end
  14813.  
  14814.             for i, v in ipairs(items) do
  14815.                 term.setCursorPos(x, i + 1)
  14816.                 term.write(string.rep(" ", len))
  14817.                 term.setCursorPos(x + 1, i + 1)
  14818.                 term.write(v)
  14819.             end
  14820.             term.setCursorPos(x, #items + 2)
  14821.             term.write(string.rep(" ", len))
  14822.             return items, len
  14823.         end
  14824.     end
  14825.  
  14826.     local function triggerMenu(cx, cy)
  14827.         -- Determine clicked menu
  14828.         local curX = 0
  14829.         local open = nil
  14830.         for _, v in pairs(menu) do
  14831.             if cx >= curX + 3 and cx <= curX + v[1]:len() + 2 then
  14832.                 open = v[1]
  14833.                 break
  14834.             end
  14835.             curX = curX + v[1]:len() + 3
  14836.         end
  14837.         local menux = curX + 2
  14838.         if not open then return false end
  14839.  
  14840.         -- Flash menu item
  14841.         term.setCursorBlink(false)
  14842.         term.setCursorPos(menux, 1)
  14843.         term.setBackgroundColor(colors[theme.background])
  14844.         term.write(string.rep(" ", open:len() + 2))
  14845.         term.setCursorPos(menux + 1, 1)
  14846.         term.write(open)
  14847.         sleep(0.1)
  14848.         local items, len = drawMenu(open)
  14849.  
  14850.         local ret = true
  14851.  
  14852.         -- Pull events on menu
  14853.         local ox, oy = term.getCursorPos()
  14854.         while type(ret) ~= "string" do
  14855.             local e, but, x, y = os.pullEvent()
  14856.             if e == "mouse_click" then
  14857.                 -- If clicked outside menu
  14858.                 if x < menux - 1 or x > menux + len - 1 then break
  14859.                 elseif y > #items + 2 then break
  14860.                 elseif y == 1 then break end
  14861.  
  14862.                 for i, v in ipairs(items) do
  14863.                     if y == i + 1 and x >= menux and x <= menux + len - 2 then
  14864.                         -- Flash when clicked
  14865.                         term.setCursorPos(menux, y)
  14866.                         term.setBackgroundColor(colors[theme.background])
  14867.                         term.write(string.rep(" ", len))
  14868.                         term.setCursorPos(menux + 1, y)
  14869.                         term.write(v)
  14870.                         sleep(0.1)
  14871.                         drawMenu(open)
  14872.  
  14873.                         -- Return item
  14874.                         ret = v
  14875.                         break
  14876.                     end
  14877.                 end
  14878.             end
  14879.         end
  14880.  
  14881.         term.setCursorPos(ox, oy)
  14882.         term.setCursorBlink(true)
  14883.         return ret
  14884.     end
  14885.  
  14886.  
  14887.     --  -------- Editing
  14888.  
  14889.     local standardsCompletions = {
  14890.         "if%s+.+%s+then%s*$",
  14891.         "for%s+.+%s+do%s*$",
  14892.         "while%s+.+%s+do%s*$",
  14893.         "repeat%s*$",
  14894.         "function%s+[a-zA-Z_0-9]?(.*)%s*$",
  14895.         "=%s*function%s*(.*)%s*$",
  14896.         "else%s*$",
  14897.         "elseif%s+.+%s+then%s*$"
  14898.     }
  14899.  
  14900.     local liveCompletions = {
  14901.         ["("] = ")",
  14902.         ["{"] = "}",
  14903.         ["["] = "]",
  14904.         ["\""] = "\"",
  14905.         ["'"] = "'",
  14906.     }
  14907.  
  14908.     local x, y = 0, 0
  14909.     local edw, edh = 0, h - 1
  14910.     local offx, offy = 0, 1
  14911.     local scrollx, scrolly = 0, 0
  14912.     local lines = {}
  14913.     local liveErr = curLanguage.parseError(nil)
  14914.     local displayCode = true
  14915.     local lastEventClock = os.clock()
  14916.  
  14917.     local function attemptToHighlight(line, regex, col)
  14918.         local match = string.match(line, regex)
  14919.         if match then
  14920.             if type(col) == "number" then term.setTextColor(col)
  14921.             elseif type(col) == "function" then term.setTextColor(col(match)) end
  14922.             term.write(match)
  14923.             term.setTextColor(colors[theme.textColor])
  14924.             return line:sub(match:len() + 1, -1)
  14925.         end
  14926.         return nil
  14927.     end
  14928.  
  14929.     local function writeHighlighted(line)
  14930.         if curLanguage == languages.lua then
  14931.             while line:len() > 0 do
  14932.                 line = attemptToHighlight(line, "^%-%-%[%[.-%]%]", colors[theme.comment]) or
  14933.                     attemptToHighlight(line, "^%-%-.*", colors[theme.comment]) or
  14934.                     attemptToHighlight(line, "^\".*[^\\]\"", colors[theme.string]) or
  14935.                     attemptToHighlight(line, "^\'.*[^\\]\'", colors[theme.string]) or
  14936.                     attemptToHighlight(line, "^%[%[.-%]%]", colors[theme.string]) or
  14937.                     attemptToHighlight(line, "^[%w_]+", function(match)
  14938.                         if curLanguage.keywords[match] then
  14939.                             return colors[theme[curLanguage.keywords[match]]]
  14940.                         end
  14941.                         return colors[theme.textColor]
  14942.                     end) or
  14943.                     attemptToHighlight(line, "^[^%w_]", colors[theme.textColor])
  14944.             end
  14945.         else term.write(line) end
  14946.     end
  14947.  
  14948.     local function draw()
  14949.         -- Menu
  14950.         term.setTextColor(colors[theme.textColor])
  14951.         term.setBackgroundColor(colors[theme.editorBackground])
  14952.         term.clear()
  14953.         drawMenu()
  14954.  
  14955.         -- Line numbers
  14956.         offx, offy = tostring(#lines):len() + 1, 1
  14957.         edw, edh = w - offx, h - 1
  14958.  
  14959.         -- Draw text
  14960.         for i = 1, edh do
  14961.             local a = lines[scrolly + i]
  14962.             if a then
  14963.                 local ln = string.rep(" ", offx - 1 - tostring(scrolly + i):len()) .. tostring(scrolly + i)
  14964.                 local l = a:sub(scrollx + 1, edw + scrollx + 1)
  14965.                 ln = ln .. ":"
  14966.  
  14967.                 if liveErr.line == scrolly + i then ln = string.rep(" ", offx - 2) .. "!:" end
  14968.  
  14969.                 term.setCursorPos(1, i + offy)
  14970.                 term.setBackgroundColor(colors[theme.editorBackground])
  14971.                 if scrolly + i == y then
  14972.                     if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then
  14973.                         term.setBackgroundColor(colors[theme.editorErrorHighlight])
  14974.                     else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
  14975.                     term.clearLine()
  14976.                 elseif scrolly + i == liveErr.line then
  14977.                     term.setBackgroundColor(colors[theme.editorError])
  14978.                     term.clearLine()
  14979.                 end
  14980.  
  14981.                 term.setCursorPos(1 - scrollx + offx, i + offy)
  14982.                 if scrolly + i == y then
  14983.                     if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then
  14984.                         term.setBackgroundColor(colors[theme.editorErrorHighlight])
  14985.                     else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
  14986.                 elseif scrolly + i == liveErr.line then term.setBackgroundColor(colors[theme.editorError])
  14987.                 else term.setBackgroundColor(colors[theme.editorBackground]) end
  14988.                 if scrolly + i == liveErr.line then
  14989.                     if displayCode then term.write(a)
  14990.                     else term.write(liveErr.display) end
  14991.                 else writeHighlighted(a) end
  14992.  
  14993.                 term.setCursorPos(1, i + offy)
  14994.                 if scrolly + i == y then
  14995.                     if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then
  14996.                         term.setBackgroundColor(colors[theme.editorError])
  14997.                     else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end
  14998.                 elseif scrolly + i == liveErr.line then
  14999.                     term.setBackgroundColor(colors[theme.editorErrorHighlight])
  15000.                 else term.setBackgroundColor(colors[theme.editorLineNumbers]) end
  15001.                 term.write(ln)
  15002.             end
  15003.         end
  15004.         term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
  15005.     end
  15006.  
  15007.     local function drawLine(...)
  15008.         local ls = {...}
  15009.         offx = tostring(#lines):len() + 1
  15010.         for _, ly in pairs(ls) do
  15011.             local a = lines[ly]
  15012.             if a then
  15013.                 local ln = string.rep(" ", offx - 1 - tostring(ly):len()) .. tostring(ly)
  15014.                 local l = a:sub(scrollx + 1, edw + scrollx + 1)
  15015.                 ln = ln .. ":"
  15016.  
  15017.                 if liveErr.line == ly then ln = string.rep(" ", offx - 2) .. "!:" end
  15018.  
  15019.                 term.setCursorPos(1, (ly - scrolly) + offy)
  15020.                 term.setBackgroundColor(colors[theme.editorBackground])
  15021.                 if ly == y then
  15022.                     if ly == liveErr.line and os.clock() - lastEventClock > 3 then
  15023.                         term.setBackgroundColor(colors[theme.editorErrorHighlight])
  15024.                     else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
  15025.                 elseif ly == liveErr.line then
  15026.                     term.setBackgroundColor(colors[theme.editorError])
  15027.                 end
  15028.                 term.clearLine()
  15029.  
  15030.                 term.setCursorPos(1 - scrollx + offx, (ly - scrolly) + offy)
  15031.                 if ly == y then
  15032.                     if ly == liveErr.line and os.clock() - lastEventClock > 3 then
  15033.                         term.setBackgroundColor(colors[theme.editorErrorHighlight])
  15034.                     else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
  15035.                 elseif ly == liveErr.line then term.setBackgroundColor(colors[theme.editorError])
  15036.                 else term.setBackgroundColor(colors[theme.editorBackground]) end
  15037.                 if ly == liveErr.line then
  15038.                     if displayCode then term.write(a)
  15039.                     else term.write(liveErr.display) end
  15040.                 else writeHighlighted(a) end
  15041.  
  15042.                 term.setCursorPos(1, (ly - scrolly) + offy)
  15043.                 if ly == y then
  15044.                     if ly == liveErr.line and os.clock() - lastEventClock > 3 then
  15045.                         term.setBackgroundColor(colors[theme.editorError])
  15046.                     else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end
  15047.                 elseif ly == liveErr.line then
  15048.                     term.setBackgroundColor(colors[theme.editorErrorHighlight])
  15049.                 else term.setBackgroundColor(colors[theme.editorLineNumbers]) end
  15050.                 term.write(ln)
  15051.             end
  15052.         end
  15053.         term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
  15054.     end
  15055.  
  15056.     local function cursorLoc(x, y, force)
  15057.         local sx, sy = x - scrollx, y - scrolly
  15058.         local redraw = false
  15059.         if sx < 1 then
  15060.             scrollx = x - 1
  15061.             sx = 1
  15062.             redraw = true
  15063.         elseif sx > edw then
  15064.             scrollx = x - edw
  15065.             sx = edw
  15066.             redraw = true
  15067.         end if sy < 1 then
  15068.             scrolly = y - 1
  15069.             sy = 1
  15070.             redraw = true
  15071.         elseif sy > edh then
  15072.             scrolly = y - edh
  15073.             sy = edh
  15074.             redraw = true
  15075.         end if redraw or force then draw() end
  15076.         term.setCursorPos(sx + offx, sy + offy)
  15077.     end
  15078.  
  15079.     local function executeMenuItem(a, path)
  15080.         if type(a) == "string" and menuFunctions[a] then
  15081.             local opt, nl, gtln = menuFunctions[a](path, lines, y)
  15082.             if type(opt) == "string" then term.setCursorBlink(false) return opt end
  15083.             if type(nl) == "table" then
  15084.                 if #lines < 1 then table.insert(lines, "") end
  15085.                 y = math.min(y, #lines)
  15086.                 x = math.min(x, lines[y]:len() + 1)
  15087.                 lines = nl
  15088.             elseif type(nl) == "string" then
  15089.                 if nl == "go to" and gtln then
  15090.                     x, y = 1, math.min(#lines, gtln)
  15091.                     cursorLoc(x, y)
  15092.                 end
  15093.             end
  15094.         end
  15095.         term.setCursorBlink(true)
  15096.         draw()
  15097.         term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
  15098.     end
  15099.  
  15100.     local function edit(path)
  15101.         -- Variables
  15102.         x, y = 1, 1
  15103.         offx, offy = 0, 1
  15104.         scrollx, scrolly = 0, 0
  15105.         lines = loadFile(path)
  15106.         if not lines then return "menu" end
  15107.  
  15108.         -- Enable brainfuck
  15109.         if lines[1] == "-- Syntax: Brainfuck" then
  15110.             curLanguage = languages.brainfuck
  15111.         end
  15112.  
  15113.         -- Clocks
  15114.         local autosaveClock = os.clock()
  15115.         local scrollClock = os.clock() -- To prevent redraw flicker
  15116.         local liveErrorClock = os.clock()
  15117.         local hasScrolled = false
  15118.  
  15119.         -- Draw
  15120.         draw()
  15121.         term.setCursorPos(x + offx, y + offy)
  15122.         term.setCursorBlink(true)
  15123.        
  15124.         -- Main loop
  15125.         local tid = os.startTimer(3)
  15126.         while true do
  15127.             local e, key, cx, cy = os.pullEvent()
  15128.             if e == "key" and allowEditorEvent then
  15129.                 if key == 200 and y > 1 then
  15130.                     -- Up
  15131.                     x, y = math.min(x, lines[y - 1]:len() + 1), y - 1
  15132.                     drawLine(y, y + 1)
  15133.                     cursorLoc(x, y)
  15134.                 elseif key == 208 and y < #lines then
  15135.                     -- Down
  15136.                     x, y = math.min(x, lines[y + 1]:len() + 1), y + 1
  15137.                     drawLine(y, y - 1)
  15138.                     cursorLoc(x, y)
  15139.                 elseif key == 203 and x > 1 then
  15140.                     -- Left
  15141.                     x = x - 1
  15142.                     local force = false
  15143.                     if y - scrolly + offy < offy + 1 then force = true end
  15144.                     cursorLoc(x, y, force)
  15145.                 elseif key == 205 and x < lines[y]:len() + 1 then
  15146.                     -- Right
  15147.                     x = x + 1
  15148.                     local force = false
  15149.                     if y - scrolly + offy < offy + 1 then force = true end
  15150.                     cursorLoc(x, y, force)
  15151.                 elseif (key == 28 or key == 156) and (displayCode and true or y + scrolly - 1 ==
  15152.                         liveErr.line) then
  15153.                     -- Enter
  15154.                     local f = nil
  15155.                     for _, v in pairs(standardsCompletions) do
  15156.                         if lines[y]:find(v) then f = v end
  15157.                     end
  15158.  
  15159.                     local _, spaces = lines[y]:find("^[ ]+")
  15160.                     if not spaces then spaces = 0 end
  15161.                     if f then
  15162.                         table.insert(lines, y + 1, string.rep(" ", spaces + 2))
  15163.                         if not f:find("else", 1, true) and not f:find("elseif", 1, true) then
  15164.                             table.insert(lines, y + 2, string.rep(" ", spaces) ..
  15165.                                 (f:find("repeat", 1, true) and "until " or f:find("{", 1, true) and "}" or
  15166.                                 "end"))
  15167.                         end
  15168.                         x, y = spaces + 3, y + 1
  15169.                         cursorLoc(x, y, true)
  15170.                     else
  15171.                         local oldLine = lines[y]
  15172.  
  15173.                         lines[y] = lines[y]:sub(1, x - 1)
  15174.                         table.insert(lines, y + 1, string.rep(" ", spaces) .. oldLine:sub(x, -1))
  15175.  
  15176.                         x, y = spaces + 1, y + 1
  15177.                         cursorLoc(x, y, true)
  15178.                     end
  15179.                 elseif key == 14 and (displayCode and true or y + scrolly - 1 == liveErr.line) then
  15180.                     -- Backspace
  15181.                     if x > 1 then
  15182.                         local f = false
  15183.                         for k, v in pairs(liveCompletions) do
  15184.                             if lines[y]:sub(x - 1, x - 1) == k then f = true end
  15185.                         end
  15186.  
  15187.                         lines[y] = lines[y]:sub(1, x - 2) .. lines[y]:sub(x + (f and 1 or 0), -1)
  15188.                         drawLine(y)
  15189.                         x = x - 1
  15190.                         cursorLoc(x, y)
  15191.                     elseif y > 1 then
  15192.                         local prevLen = lines[y - 1]:len() + 1
  15193.                         lines[y - 1] = lines[y - 1] .. lines[y]
  15194.                         table.remove(lines, y)
  15195.                         x, y = prevLen, y - 1
  15196.                         cursorLoc(x, y, true)
  15197.                     end
  15198.                 elseif key == 199 then
  15199.                     -- Home
  15200.                     x = 1
  15201.                     local force = false
  15202.                     if y - scrolly + offy < offy + 1 then force = true end
  15203.                     cursorLoc(x, y, force)
  15204.                 elseif key == 207 then
  15205.                     -- End
  15206.                     x = lines[y]:len() + 1
  15207.                     local force = false
  15208.                     if y - scrolly + offy < offy + 1 then force = true end
  15209.                     cursorLoc(x, y, force)
  15210.                 elseif key == 211 and (displayCode and true or y + scrolly - 1 == liveErr.line) then
  15211.                     -- Forward Delete
  15212.                     if x < lines[y]:len() + 1 then
  15213.                         lines[y] = lines[y]:sub(1, x - 1) .. lines[y]:sub(x + 1)
  15214.                         local force = false
  15215.                         if y - scrolly + offy < offy + 1 then force = true end
  15216.                         drawLine(y)
  15217.                         cursorLoc(x, y, force)
  15218.                     elseif y < #lines then
  15219.                         lines[y] = lines[y] .. lines[y + 1]
  15220.                         table.remove(lines, y + 1)
  15221.                         draw()
  15222.                         cursorLoc(x, y)
  15223.                     end
  15224.                 elseif key == 15 and (displayCode and true or y + scrolly - 1 == liveErr.line) then
  15225.                     -- Tab
  15226.                     lines[y] = string.rep(" ", tabWidth) .. lines[y]
  15227.                     x = x + 2
  15228.                     local force = false
  15229.                     if y - scrolly + offy < offy + 1 then force = true end
  15230.                     drawLine(y)
  15231.                     cursorLoc(x, y, force)
  15232.                 elseif key == 201 then
  15233.                     -- Page up
  15234.                     y = math.min(math.max(y - edh, 1), #lines)
  15235.                     x = math.min(lines[y]:len() + 1, x)
  15236.                     cursorLoc(x, y, true)
  15237.                 elseif key == 209 then
  15238.                     -- Page down
  15239.                     y = math.min(math.max(y + edh, 1), #lines)
  15240.                     x = math.min(lines[y]:len() + 1, x)
  15241.                     cursorLoc(x, y, true)
  15242.                 end
  15243.             elseif e == "char" and allowEditorEvent and (displayCode and true or
  15244.                     y + scrolly - 1 == liveErr.line) then
  15245.                 local shouldIgnore = false
  15246.                 for k, v in pairs(liveCompletions) do
  15247.                     if key == v and lines[y]:find(k, 1, true) and lines[y]:sub(x, x) == v then
  15248.                         shouldIgnore = true
  15249.                     end
  15250.                 end
  15251.  
  15252.                 local addOne = false
  15253.                 if not shouldIgnore then
  15254.                     for k, v in pairs(liveCompletions) do
  15255.                         if key == k and lines[y]:sub(x, x) ~= k then key = key .. v addOne = true end
  15256.                     end
  15257.                     lines[y] = lines[y]:sub(1, x - 1) .. key .. lines[y]:sub(x, -1)
  15258.                 end
  15259.  
  15260.                 x = x + (addOne and 1 or key:len())
  15261.                 local force = false
  15262.                 if y - scrolly + offy < offy + 1 then force = true end
  15263.                 drawLine(y)
  15264.                 cursorLoc(x, y, force)
  15265.             elseif e == "mouse_click" and key == 1 then
  15266.                 if cy > 1 then
  15267.                     if cx <= offx and cy - offy == liveErr.line - scrolly then
  15268.                         displayCode = not displayCode
  15269.                         drawLine(liveErr.line)
  15270.                     else
  15271.                         local oldy = y
  15272.                         y = math.min(math.max(scrolly + cy - offy, 1), #lines)
  15273.                         x = math.min(math.max(scrollx + cx - offx, 1), lines[y]:len() + 1)
  15274.                         if oldy ~= y then drawLine(oldy, y) end
  15275.                         cursorLoc(x, y)
  15276.                     end
  15277.                 else
  15278.                     local a = triggerMenu(cx, cy)
  15279.                     if a then
  15280.                         local opt = executeMenuItem(a, path)
  15281.                         if opt then return opt end
  15282.                     end
  15283.                 end
  15284.             elseif e == "shortcut" then
  15285.                 local a = shortcuts[key .. " " .. cx]
  15286.                 if a then
  15287.                     local parent = nil
  15288.                     local curx = 0
  15289.                     for i, mv in ipairs(menu) do
  15290.                         for _, iv in pairs(mv) do
  15291.                             if iv == a then
  15292.                                 parent = menu[i][1]
  15293.                                 break
  15294.                             end
  15295.                         end
  15296.                         if parent then break end
  15297.                         curx = curx + mv[1]:len() + 3
  15298.                     end
  15299.                     local menux = curx + 2
  15300.  
  15301.                     -- Flash menu item
  15302.                     term.setCursorBlink(false)
  15303.                     term.setCursorPos(menux, 1)
  15304.                     term.setBackgroundColor(colors[theme.background])
  15305.                     term.write(string.rep(" ", parent:len() + 2))
  15306.                     term.setCursorPos(menux + 1, 1)
  15307.                     term.write(parent)
  15308.                     sleep(0.1)
  15309.                     drawMenu()
  15310.  
  15311.                     -- Execute item
  15312.                     local opt = executeMenuItem(a, path)
  15313.                     if opt then return opt end
  15314.                 end
  15315.             elseif e == "mouse_scroll" then
  15316.                 if key == -1 and scrolly > 0 then
  15317.                     scrolly = scrolly - 1
  15318.                     if os.clock() - scrollClock > 0.0005 then
  15319.                         draw()
  15320.                         term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
  15321.                     end
  15322.                     scrollClock = os.clock()
  15323.                     hasScrolled = true
  15324.                 elseif key == 1 and scrolly < #lines - edh then
  15325.                     scrolly = scrolly + 1
  15326.                     if os.clock() - scrollClock > 0.0005 then
  15327.                         draw()
  15328.                         term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
  15329.                     end
  15330.                     scrollClock = os.clock()
  15331.                     hasScrolled = true
  15332.                 end
  15333.             elseif e == "timer" and key == tid then
  15334.                 drawLine(y)
  15335.                 tid = os.startTimer(3)
  15336.             end
  15337.  
  15338.             -- Draw
  15339.             if hasScrolled and os.clock() - scrollClock > 0.1 then
  15340.                 draw()
  15341.                 term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
  15342.                 hasScrolled = false
  15343.             end
  15344.  
  15345.             -- Autosave
  15346.             if os.clock() - autosaveClock > autosaveInterval then
  15347.                 saveFile(path, lines)
  15348.                 autosaveClock = os.clock()
  15349.             end
  15350.  
  15351.             -- Errors
  15352.             if os.clock() - liveErrorClock > 1 then
  15353.                 local prevLiveErr = liveErr
  15354.                 liveErr = curLanguage.parseError(nil)
  15355.                 local code = ""
  15356.                 for _, v in pairs(lines) do code = code .. v .. "\n" end
  15357.  
  15358.                 liveErr = curLanguage.getCompilerErrors(code)
  15359.                 liveErr.line = math.min(liveErr.line - 2, #lines)
  15360.                 if liveErr ~= prevLiveErr then draw() end
  15361.                 liveErrorClock = os.clock()
  15362.             end
  15363.         end
  15364.  
  15365.         return "menu"
  15366.     end
  15367.  
  15368.  
  15369.     --  -------- Open File
  15370.  
  15371.     local function newFile()
  15372.         local wid = w - 13
  15373.  
  15374.         -- Get name
  15375.         title("Lua IDE - New File")
  15376.         local name = centerRead(wid, "/")
  15377.         if not name or name == "" then return "menu" end
  15378.         name = "/" .. name
  15379.  
  15380.         -- Clear
  15381.         title("Lua IDE - New File")
  15382.         term.setTextColor(colors[theme.textColor])
  15383.         term.setBackgroundColor(colors[theme.promptHighlight])
  15384.         for i = 8, 10 do
  15385.             term.setCursorPos(w/2 - wid/2, i)
  15386.             term.write(string.rep(" ", wid))
  15387.         end
  15388.         term.setCursorPos(1, 9)
  15389.         if fs.isDir(name) then
  15390.             centerPrint("Cannot Edit a Directory!")
  15391.             sleep(1.6)
  15392.             return "menu"
  15393.         elseif fs.exists(name) then
  15394.             centerPrint("File Already Exists!")
  15395.             local opt = prompt({{"Open", w/2 - 9, 14}, {"Cancel", w/2 + 2, 14}}, "horizontal")
  15396.             if opt == "Open" then return "edit", name
  15397.             elseif opt == "Cancel" then return "menu" end
  15398.         else return "edit", name end
  15399.     end
  15400.  
  15401.     local function openFile()
  15402.         local wid = w - 13
  15403.  
  15404.         -- Get name
  15405.         title("Lua IDE - Open File")
  15406.         local name = centerRead(wid, "/")
  15407.         if not name or name == "" then return "menu" end
  15408.         name = "/" .. name
  15409.  
  15410.         -- Clear
  15411.         title("Lua IDE - New File")
  15412.         term.setTextColor(colors[theme.textColor])
  15413.         term.setBackgroundColor(colors[theme.promptHighlight])
  15414.         for i = 8, 10 do
  15415.             term.setCursorPos(w/2 - wid/2, i)
  15416.             term.write(string.rep(" ", wid))
  15417.         end
  15418.         term.setCursorPos(1, 9)
  15419.         if fs.isDir(name) then
  15420.             centerPrint("Cannot Open a Directory!")
  15421.             sleep(1.6)
  15422.             return "menu"
  15423.         elseif not fs.exists(name) then
  15424.             centerPrint("File Doesn't Exist!")
  15425.             local opt = prompt({{"Create", w/2 - 11, 14}, {"Cancel", w/2 + 2, 14}}, "horizontal")
  15426.             if opt == "Create" then return "edit", name
  15427.             elseif opt == "Cancel" then return "menu" end
  15428.         else return "edit", name end
  15429.     end
  15430.  
  15431.  
  15432.     --  -------- Settings
  15433.  
  15434.     local function update()
  15435.         local function draw(status)
  15436.             title("LuaIDE - Update")
  15437.             term.setBackgroundColor(colors[theme.prompt])
  15438.             term.setTextColor(colors[theme.textColor])
  15439.             for i = 8, 10 do
  15440.                 term.setCursorPos(w/2 - (status:len() + 4), i)
  15441.                 write(string.rep(" ", status:len() + 4))
  15442.             end
  15443.             term.setCursorPos(w/2 - (status:len() + 4), 9)
  15444.             term.write(" - " .. status .. " ")
  15445.  
  15446.             term.setBackgroundColor(colors[theme.errHighlight])
  15447.             for i = 8, 10 do
  15448.                 term.setCursorPos(w/2 + 2, i)
  15449.                 term.write(string.rep(" ", 10))
  15450.             end
  15451.             term.setCursorPos(w/2 + 2, 9)
  15452.             term.write(" > Cancel ")
  15453.         end
  15454.  
  15455.         if not http then
  15456.             draw("HTTP API Disabled!")
  15457.             sleep(1.6)
  15458.             return "settings"
  15459.         end
  15460.  
  15461.         draw("Updating...")
  15462.         local tID = os.startTimer(10)
  15463.         http.request(updateURL)
  15464.         while true do
  15465.             local e, but, x, y = os.pullEvent()
  15466.             if (e == "key" and but == 28) or
  15467.                     (e == "mouse_click" and x >= w/2 + 2 and x <= w/2 + 12 and y == 9) then
  15468.                 draw("Cancelled")
  15469.                 sleep(1.6)
  15470.                 break
  15471.             elseif e == "http_success" and but == updateURL then
  15472.                 local new = x.readAll()
  15473.                 local curf = io.open(ideLocation, "r")
  15474.                 local cur = curf:read("*a")
  15475.                 curf:close()
  15476.  
  15477.                 if cur ~= new then
  15478.                     draw("Update Found")
  15479.                     sleep(1.6)
  15480.                     local f = io.open(ideLocation, "w")
  15481.                     f:write(new)
  15482.                     f:close()
  15483.  
  15484.                     draw("Click to Exit")
  15485.                     while true do
  15486.                         local e = os.pullEvent()
  15487.                         if e == "mouse_click" or (not isAdvanced() and e == "key") then break end
  15488.                     end
  15489.                     return "exit"
  15490.                 else
  15491.                     draw("No Updates Found!")
  15492.                     sleep(1.6)
  15493.                     break
  15494.                 end
  15495.             elseif e == "http_failure" or (e == "timer" and but == tID) then
  15496.                 draw("Update Failed!")
  15497.                 sleep(1.6)
  15498.                 break
  15499.             end
  15500.         end
  15501.  
  15502.         return "settings"
  15503.     end
  15504.  
  15505.     local function changeTheme()
  15506.         title("LuaIDE - Theme")
  15507.  
  15508.         if isAdvanced() then
  15509.             local disThemes = {"Back"}
  15510.             for _, v in pairs(availableThemes) do table.insert(disThemes, v[1]) end
  15511.             local t = scrollingPrompt(disThemes)
  15512.             local url = nil
  15513.             for _, v in pairs(availableThemes) do if v[1] == t then url = v[2] end end
  15514.  
  15515.             if not url then return "settings" end
  15516.             if t == "Dawn (Default)" then
  15517.                 term.setBackgroundColor(colors[theme.backgroundHighlight])
  15518.                 term.setCursorPos(3, 3)
  15519.                 term.clearLine()
  15520.                 term.write("LuaIDE - Loaded Theme!")
  15521.                 sleep(1.6)
  15522.  
  15523.                 fs.delete(themeLocation)
  15524.                 theme = defaultTheme
  15525.                 return "menu"
  15526.             end
  15527.  
  15528.             term.setBackgroundColor(colors[theme.backgroundHighlight])
  15529.             term.setCursorPos(3, 3)
  15530.             term.clearLine()
  15531.             term.write("LuaIDE - Downloading...")
  15532.  
  15533.             fs.delete("/.LuaIDE_temp_theme_file")
  15534.             download(url, "/.LuaIDE_temp_theme_file")
  15535.             local a = loadTheme("/.LuaIDE_temp_theme_file")
  15536.  
  15537.             term.setCursorPos(3, 3)
  15538.             term.clearLine()
  15539.             if a then
  15540.                 term.write("LuaIDE - Loaded Theme!")
  15541.                 fs.delete(themeLocation)
  15542.                 fs.move("/.LuaIDE_temp_theme_file", themeLocation)
  15543.                 theme = a
  15544.                 sleep(1.6)
  15545.                 return "menu"
  15546.             end
  15547.            
  15548.             term.write("LuaIDE - Could Not Load Theme!")
  15549.             fs.delete("/.LuaIDE_temp_theme_file")
  15550.             sleep(1.6)
  15551.             return "settings"
  15552.         else
  15553.             term.setCursorPos(1, 8)
  15554.             centerPrint("Themes are not available on")
  15555.             centerPrint("normal computers!")
  15556.         end
  15557.     end
  15558.  
  15559.     local function settings()
  15560.         title("LuaIDE - Settings")
  15561.  
  15562.         local opt = prompt({{"Change Theme", w/2 - 17, 8}, {"Return to Menu", w/2 - 22, 13},
  15563.             {"Check for Updates", w/2 + 2, 8}, {"Exit IDE", w/2 + 2, 13, bg = colors[theme.err],
  15564.             highlight = colors[theme.errHighlight]}}, "vertical", true)
  15565.         if opt == "Change Theme" then return changeTheme()
  15566.         elseif opt == "Check for Updates" then return update()
  15567.         elseif opt == "Return to Menu" then return "menu"
  15568.         elseif opt == "Exit IDE" then return "exit" end
  15569.     end
  15570.  
  15571.  
  15572.     --  -------- Menu
  15573.  
  15574.     local function menu()
  15575.         title("Welcome to LuaIDE " .. version)
  15576.  
  15577.         local opt = prompt({{"New File", w/2 - 13, 8}, {"Open File", w/2 - 14, 13},
  15578.             {"Settings", w/2 + 2, 8}, {"Exit IDE", w/2 + 2, 13, bg = colors[theme.err],
  15579.             highlight = colors[theme.errHighlight]}}, "vertical", true)
  15580.         if opt == "New File" then return "new"
  15581.         elseif opt == "Open File" then return "open"
  15582.         elseif opt == "Settings" then return "settings"
  15583.         elseif opt == "Exit IDE" then return "exit" end
  15584.     end
  15585.  
  15586.  
  15587.     --  -------- Main
  15588.  
  15589.     local function main(arguments)
  15590.         local opt, data = "menu", nil
  15591.  
  15592.         -- Check arguments
  15593.         if type(arguments) == "table" and #arguments > 0 then
  15594.             local f = "/" .. shell.resolve(arguments[1])
  15595.             if fs.isDir(f) then print("Cannot edit a directory.") end
  15596.             opt, data = "edit", f
  15597.         end
  15598.  
  15599.         -- Main run loop
  15600.         while true do
  15601.             -- Menu
  15602.             if opt == "menu" then opt = menu() end
  15603.  
  15604.             -- Other
  15605.             if opt == "new" then opt, data = newFile()
  15606.             elseif opt == "open" then opt, data = openFile()
  15607.             elseif opt == "settings" then opt = settings()
  15608.             end if opt == "exit" then break end
  15609.  
  15610.             -- Edit
  15611.             if opt == "edit" and data then opt = edit(data) end
  15612.         end
  15613.     end
  15614.  
  15615.     -- Load Theme
  15616.     if fs.exists(themeLocation) then theme = loadTheme(themeLocation) end
  15617.     if not theme and isAdvanced() then theme = defaultTheme
  15618.     elseif not theme then theme = normalTheme end
  15619.  
  15620.     -- Run
  15621.     local _, err = pcall(function()
  15622.         parallel.waitForAny(function() main(args) end, monitorKeyboardShortcuts)
  15623.     end)
  15624.  
  15625.     -- Catch errors
  15626.     if err and not err:find("Terminated") then
  15627.         term.setCursorBlink(false)
  15628.         title("LuaIDE - Crash! D:")
  15629.  
  15630.         term.setBackgroundColor(colors[theme.err])
  15631.         for i = 6, 8 do
  15632.             term.setCursorPos(5, i)
  15633.             term.write(string.rep(" ", 36))
  15634.         end
  15635.         term.setCursorPos(6, 7)
  15636.         term.write("LuaIDE Has Crashed! D:")
  15637.  
  15638.         term.setBackgroundColor(colors[theme.background])
  15639.         term.setCursorPos(2, 10)
  15640.         print(err)
  15641.  
  15642.         term.setBackgroundColor(colors[theme.prompt])
  15643.         local _, cy = term.getCursorPos()
  15644.         for i = cy + 1, cy + 4 do
  15645.             term.setCursorPos(5, i)
  15646.             term.write(string.rep(" ", 36))
  15647.         end
  15648.         term.setCursorPos(6, cy + 2)
  15649.         term.write("Please report this error to")
  15650.         term.setCursorPos(6, cy + 3)
  15651.         term.write("GravityScore! ")
  15652.        
  15653.         term.setBackgroundColor(colors[theme.background])
  15654.         if isAdvanced() then centerPrint("Click to Exit...", h - 1)
  15655.         else centerPrint("Press Any Key to Exit...", h - 1) end
  15656.         while true do
  15657.             local e = os.pullEvent()
  15658.             if e == "mouse_click" or (not isAdvanced() and e == "key") then break end
  15659.         end
  15660.  
  15661.         -- Prevent key from being shown
  15662.         os.queueEvent(event_distract)
  15663.         os.pullEvent()
  15664.     end
  15665.  
  15666.     -- Exit
  15667.     term.setBackgroundColor(colors.black)
  15668.     term.setTextColor(colors.white)
  15669.     term.clear()
  15670.     term.setCursorPos(1, 1)
  15671.     centerPrint("Thank You for Using Lua IDE " .. version)
  15672.     centerPrint("Made by GravityScore")
  15673.     sleep(1)
  15674.     home()
  15675. end
  15676.  
  15677. main()
Add Comment
Please, Sign In to add comment