Advertisement
programcreator

OmniOS: v15w26a

Jun 28th, 2015
438
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 493.88 KB | None | 0 0
  1. inputTable = {
  2.   [ "README.md" ] = "# OmniOS\
  3. GitHub repository of OmniOS",
  4.   [ "BIOS.lua" ] = "--[[\
  5.     BIOS by Creator\
  6.     for OmniOS\
  7. ]]--\
  8. \
  9. term.redirect(term.native())\
  10. \
  11. --Variables--\
  12. local gui = {}\
  13. local OS = {}\
  14. local timeLeft = 5\
  15. local currentOS = 1\
  16. local defaultOS = \"\"\
  17. local toBoot = 0\
  18. local layout = [[\
  19.     +-----------------------------------------+\
  20.     | Current selection:                      |\
  21.     |                                         |\
  22.     +-----------------------------------------+\
  23.     | Available OSes:                         |\
  24.     |                                         |\
  25.     |                                         |\
  26.     |                                         |\
  27.     |                                         |\
  28.     |                                         |\
  29.     |                                         |\
  30.     +-----------------------------------------+\
  31.     | S: Settings                             |\
  32.     +-----------------------------------------+\
  33.     | Time left:                              |\
  34.     +-----------------------------------------+\
  35. ]]\
  36. --Functions\
  37. function gui.clear()\
  38.     term.setBackgroundColor(colors.blue)\
  39.     term.setTextColor(colors.white)\
  40.     term.setCursorPos(1,2)\
  41.     term.clear()\
  42. end\
  43. \
  44. function gui.drawMain()\
  45.     gui.clear()\
  46.     term.setCursorPos(1,3)\
  47.     print(layout)\
  48.     term.setCursorPos(8,4)\
  49.     term.write(OS[currentOS][1])\
  50.     for i = 1, #OS do\
  51.         term.setCursorPos(8,i+6)\
  52.         term.write(i..\") \"..OS[i][1])\
  53.     end\
  54.     term.setCursorPos(19,16)\
  55.     term.write(timeLeft)\
  56. end\
  57. \
  58. local function loadOS()\
  59.     return dofile(\"OmniOS/BIOS/List\")\
  60. end\
  61. \
  62. local function loadDefault()\
  63.     return dofile(\"OmniOS/BIOS/default\")\
  64. end\
  65. \
  66. local function findCurrent()\
  67.     for i, v in pairs(OS) do\
  68.         if defaultOS == v[1] then\
  69.             return i\
  70.         end\
  71.     end\
  72.     error(\"The OS you are searching does not exist!\")\
  73. end\
  74. \
  75. --Code\
  76. OS = loadOS()\
  77. defaultOS = loadDefault()\
  78. currentOS = findCurrent()\
  79. while true do \
  80.     gui.drawMain()\
  81.     local timerID = os.startTimer(1)\
  82.     local event = {os.pullEvent()}\
  83.     if timeLeft == 0 then\
  84.         toBoot = currentOS\
  85.         break\
  86.     end\
  87.     if event[1] == \"key\" then\
  88.         os.cancelTimer(timerID)\
  89.         if 2 <= event[2] and event[2] <= 11 then\
  90.             event[2] = event[2] == 11 and 0 or event[2] - 1\
  91.             if OS[event[2]] then\
  92.                 toBoot = event[2]\
  93.                 break\
  94.             end\
  95.         elseif event[2] == keys.up then\
  96.             currentOS = currentOS - 1\
  97.             currentOS = currentOS == 0 and #OS or currentOS\
  98.         elseif event[2] == keys.down then\
  99.             currentOS = currentOS + 1\
  100.             currentOS = currentOS == #OS + 1 and 1 or currentOS\
  101.         elseif event[2] == keys.enter then\
  102.             toBoot = currentOS\
  103.             break\
  104.         end\
  105.     elseif event[1] == \"timer\" and event[2] == timerID then\
  106.         timeLeft = timeLeft - 1\
  107.     end\
  108. end\
  109. \
  110. if OS[toBoot][1] == \"CraftOS\" then\
  111.     term.setBackgroundColor(colors.black)\
  112.     term.setTextColor(colors.yellow)\
  113.     term.clear()\
  114.     term.setCursorPos(1,1)\
  115.     print(\"CraftOS 1.7\")\
  116. else\
  117.     dofile(OS[toBoot][2])\
  118. end",
  119.   Media = {
  120.     Boot = {
  121.       [ "Boot_Logo.nfp" ] = "bbbbb           b\
  122. b   b            \
  123. b   b bbbbb bbb b\
  124. b   b b b b b b b\
  125. bbbbb b b b b b b\
  126.                 \
  127. 11111111111111111",
  128.       [ "Boot_Hide.nfp" ] = "000000000000000000000000000\
  129. 000000000000000000000000000\
  130. 000000000000000000000000000\
  131. 000000000000000000000000000\
  132. 000000000000000000000000000\
  133. 000000000000000000000000000\
  134. 000000000000000000000000000\
  135. 000000000000000000000000000",
  136.     },
  137.   },
  138.   int = "   term.clear()\
  139.     gui = Interact.Initialize()\
  140.     button = gui.Button.new( {\
  141.             name = \"Hi\",\
  142.             label = \"hello\",\
  143.             xPos = 2,\
  144.             yPos = 5,\
  145.             fgColor = colors.white,\
  146.             bgColor = colors.orange,\
  147.             xLength = 7,\
  148.             yLength = 3,\
  149.             returnValue = \"hi\",\
  150.             xTextPos = 2,\
  151.             yTextPos = 2,\
  152.             onRightClick = function() print(\"wow\") sleep(3) end,\
  153.             onLeftClick = function() os.shutdown() end,\
  154.         })\
  155.     button:draw()\
  156.     \
  157.     os.pullEvent()",
  158.   BIOS = {
  159.     default = "return \"OmniOS\"",
  160.     List = " return {\
  161.     { \"OmniOS\",\"OmniOS/Core/Boot.lua\" },\
  162.     {\"CraftOS\",\"shell\"},\
  163. }",
  164.   },
  165.   CodeIDontNeedNow = {
  166.     [ "PeripheralAPI.lua" ] = "local oldPeripheralWrap = peripheral.wrap\
  167. function peripheral.wrap(...)\
  168.  local tArgs = {...}\
  169.  if tArgs[1] == \"term\" then return term.current() end\
  170.  return oldPeripheralWrap(...)\
  171. end\
  172. print(\"Loaded peripheral driver.\")",
  173.     [ "Installer.lua" ] = "args = {...}\
  174. local sPath = args[1]\
  175. local filesystem = {}\
  176. \
  177. local function readFile(path)\
  178.     local file = fs.open(path,\"r\")\
  179.     local variable = file.readAll()\
  180.     file.close()\
  181.     return variable\
  182. end\
  183. \
  184. filesystem = textutils.unserialize(readFile(sPath))\
  185. \
  186. \
  187. local function writeFile(path,content)\
  188.     local file = fs.open(path,\"w\")\
  189.     file.write(content)\
  190.     file.close()\
  191. end\
  192.     \
  193. function writeDown(input,dir)\
  194.     for i,v in pairs(input) do\
  195.         if type(v) == \"table\" then\
  196.             writeDown(v,dir..\"/\"..i)\
  197.         elseif type(v) == \"string\" then\
  198.             writeFile(dir..\"/\"..i,v)\
  199.         end\
  200.     end\
  201. end\
  202. writeDown(filesystem,\"TheOS\")",
  203.     toggles = " ToggleTable = {\
  204.     test = {\
  205.         name = \"beu\",\
  206.         state = false,\
  207.         xPos = 7,\
  208.         yPos = 8,\
  209.         trueColor = colors.green,\
  210.         falseColor = colors.red,\
  211.         trueText = \"T\",\
  212.         falseText = \"F\",\
  213.         selectedBg = colors.gray,\
  214.         notSelectedBg = colors.black,\
  215.         returnValue = \"yyy\",\
  216.     }\
  217. }",
  218.     [ "vfs.lua" ] = "--[[\
  219.     VFS by Creator\
  220. ]]--\
  221. \
  222. --Variables\
  223. filesystem = {}\
  224. \
  225. --Functions\
  226. \
  227. --Table generation and mapping\
  228. local function makeTable(t,path)\
  229.     path = fs.combine(\"\",path)\
  230.     local first = path:match(\"[^/]+\")\
  231.     if first then\
  232.         if t[first] then\
  233.             return makeTable(t[first],path:sub(#first+2,-1))\
  234.         else\
  235.             t[first] = {}\
  236.             return makeTable(t[first],path:sub(#first+2,-1))\
  237.         end\
  238.     else\
  239.         return t\
  240.     end\
  241. end\
  242. \
  243. local function explore(dir,parentTable)\
  244.     local sBuffer = fs.list(dir)\
  245.     for i,v in pairs(sBuffer) do\
  246.         if fs.isDir(dir..\"/\"..v) then\
  247.             if v ~= \".git\" then\
  248.                 print(\"Indexing directory: \"..dir..\"/\"..v)\
  249.                 parentTable[v] = {}\
  250.                 explore(dir..\"/\"..v,parentTable[v])\
  251.             end\
  252.         else\
  253.             print(\"Indexing file: \"..dir..\"/\"..v)\
  254.             parentTable[v] = dir..\"/\"..v\
  255.         end\
  256.     end\
  257.     parentTable[\"&&dir\"] = dir\
  258. end\
  259. \
  260. \
  261. --Internal\
  262. local function localExists(t,path)\
  263.     path = fs.combine(\"\",path)\
  264.     local first = path:match(\"[^/]+\")\
  265.     if first then\
  266.         if t[first] then\
  267.             return localExists(t[first],path:sub(#first+2,-1))\
  268.         else\
  269.             return false\
  270.         end\
  271.     else\
  272.         return true\
  273.     end\
  274. end\
  275. \
  276. local function localIsDir(t,path)\
  277.     path = fs.combine(\"\",path)\
  278.     --print(\"Path: \"..path)\
  279.     local first = path:match(\"[^/]+\")\
  280.     if first then\
  281.         return localIsDir(t[first],path:sub(#first+2,-1))\
  282.     else\
  283.         return type(t) == \"table\" and t or false\
  284.     end\
  285. end\
  286. \
  287. local function localList(t,path)\
  288.     path = fs.combine(\"\",path)\
  289.     print(\"Path: \"..path)\
  290.     local first = path:match(\"[^/]+\")\
  291.     if first then\
  292.         return localList(t[first],path:sub(#first+2,-1))\
  293.     else\
  294.         return t\
  295.     end\
  296. end\
  297. \
  298. local function localIsReadOnly(t,path)\
  299.     path = fs.combine(\"\",path)\
  300.     print(\"Pathm: \"..path)\
  301.     local first = path:match(\"[^/]+\")\
  302.     if first then\
  303.         return localIsReadOnly(t[first],path:sub(#first+2,-1))\
  304.     else\
  305.         if type(t) == \"table\" then\
  306.             local final = \"\"\
  307.             for i,v in pairs(t) do\
  308.                 if type(v) == \"string\" then\
  309.                     final = v\
  310.                     break\
  311.                 end\
  312.             end\
  313.             return fs.isReadOnly(fs.getDir(final))\
  314.         else\
  315.             return fs.isReadOnly(t)\
  316.         end\
  317.     end\
  318. end\
  319. \
  320. local function localGetDrive(t,path)\
  321.     path = fs.combine(\"\",path)\
  322.     print(\"Pathm: \"..path)\
  323.     local first = path:match(\"[^/]+\")\
  324.     if first then\
  325.         return localGetDrive(t[first],path:sub(#first+2,-1))\
  326.     else\
  327.         print(\"T: \",t)\
  328.         return type(t) == \"table\" and true or fs.getDrive(t)\
  329.     end\
  330. end\
  331. \
  332. \
  333. --External\
  334. function mount(source,destination)\
  335.     tab = makeTable(filesystem,destination)\
  336.     explore(source,tab)\
  337. end\
  338. \
  339. function unmount()\
  340. \
  341. end\
  342. \
  343. function exists(path)\
  344.     return localExists(filesystem,path)\
  345. end\
  346. \
  347. function isDir(path)\
  348.     if localExists(filesystem,path) then\
  349.         return localIsDir(filesystem,path)\
  350.     end\
  351. end\
  352. \
  353. function list(path)\
  354.     if isDir(path) then\
  355.         local buffer = localList(filesystem,path)\
  356.         local toReturn = {}\
  357.         for i,v in pairs(buffer) do\
  358.             toReturn[#toReturn+1] = i\
  359.         end\
  360.         table.sort(toReturn)\
  361.         return toReturn\
  362.     else\
  363.         return false\
  364.     end\
  365. end\
  366. \
  367. function isReadOnly(path)\
  368.     if localExists(filesystem,path) then\
  369.         return localIsReadOnly(filesystem,path)\
  370.     else \
  371.         return \"wow\"\
  372.     end\
  373. end\
  374. \
  375. --mount(\"rom\",\"/rom/\")\
  376. --print(isReadOnly(\"/rom/autorun\"))\
  377. --print(fs.isReadOnly(\"rom\"))",
  378.     [ "bios.lua" ] = "\
  379. --[[\
  380. -- Install safe versions of various library functions\
  381. -- These will not put cfunctions on the stack, so don't break serialisation\
  382. xpcall = function( _fn, _fnErrorHandler )\
  383.    local typeT = type( _fn )\
  384.    assert( typeT == \"function\", \"bad argument #1 to xpcall (function expected, got \"..typeT..\")\" )\
  385.    local co = coroutine.create( _fn )\
  386.    local tResults = { coroutine.resume( co ) }\
  387.    while coroutine.status( co ) ~= \"dead\" do\
  388.        tResults = { coroutine.resume( co, coroutine.yield() ) }\
  389.    end\
  390.    if tResults[1] == true then\
  391.        return true, unpack( tResults, 2 )\
  392.    else\
  393.        return false, _fnErrorHandler( tResults[2] )\
  394.    end\
  395. end\
  396. \
  397. pcall = function( _fn, ... )\
  398.    local typeT = type( _fn )\
  399.    assert( typeT == \"function\", \"bad argument #1 to pcall (function expected, got \"..typeT..\")\" )\
  400.    local tArgs = { ... }\
  401.    return xpcall( \
  402.        function()\
  403.            return _fn( unpack( tArgs ) )\
  404.        end,\
  405.        function( _error )\
  406.            return _error\
  407.        end\
  408.    )\
  409. end\
  410. \
  411. function pairs( _t )\
  412.    local typeT = type( _t )\
  413.    if typeT ~= \"table\" then\
  414.        error( \"bad argument #1 to pairs (table expected, got \"..typeT..\")\", 2 )\
  415.    end\
  416.    return next, _t, nil\
  417. end\
  418. \
  419. function ipairs( _t )\
  420.    local typeT = type( _t )\
  421.    if typeT ~= \"table\" then\
  422.        error( \"bad argument #1 to ipairs (table expected, got \"..typeT..\")\", 2 )\
  423.    end\
  424.    return function( t, var )\
  425.        var = var + 1\
  426.        local value = t[var] \
  427.        if value == nil then\
  428.            return\
  429.        end\
  430.        return var, value\
  431.    end, _t, 0\
  432. end\
  433. \
  434. function coroutine.wrap( _fn )\
  435.    local typeT = type( _fn )\
  436.    if typeT ~= \"function\" then\
  437.        error( \"bad argument #1 to coroutine.wrap (function expected, got \"..typeT..\")\", 2 )\
  438.    end\
  439.    local co = coroutine.create( _fn )\
  440.    return function( ... )\
  441.        local tResults = { coroutine.resume( co, ... ) }\
  442.        if tResults[1] then\
  443.            return unpack( tResults, 2 )\
  444.        else\
  445.            error( tResults[2], 2 )\
  446.        end\
  447.    end\
  448. end\
  449. \
  450. function string.gmatch( _s, _pattern )\
  451.    local type1 = type( _s )\
  452.    if type1 ~= \"string\" then\
  453.        error( \"bad argument #1 to string.gmatch (string expected, got \"..type1..\")\", 2 )\
  454.    end\
  455.    local type2 = type( _pattern )\
  456.    if type2 ~= \"string\" then\
  457.        error( \"bad argument #2 to string.gmatch (string expected, got \"..type2..\")\", 2 )\
  458.    end\
  459.    \
  460.    local nPos = 1\
  461.    return function()\
  462.        local nFirst, nLast = string.find( _s, _pattern, nPos )\
  463.        if nFirst == nil then\
  464.            return\
  465.        end        \
  466.        nPos = nLast + 1\
  467.        return string.match( _s, _pattern, nFirst )\
  468.    end\
  469. end\
  470. \
  471. local nativesetmetatable = setmetatable\
  472. function setmetatable( _o, _t )\
  473.    if _t and type(_t) == \"table\" then\
  474.        local idx = rawget( _t, \"__index\" )\
  475.        if idx and type( idx ) == \"table\" then\
  476.            rawset( _t, \"__index\", function( t, k ) return idx[k] end )\
  477.        end\
  478.        local newidx = rawget( _t, \"__newindex\" )\
  479.        if newidx and type( newidx ) == \"table\" then\
  480.            rawset( _t, \"__newindex\", function( t, k, v ) newidx[k] = v end )\
  481.        end\
  482.    end\
  483.    return nativesetmetatable( _o, _t )\
  484. end\
  485. ]]\
  486. \
  487. -- Install fix for luaj's broken string.sub/string.find\
  488. local nativestringfind = string.find\
  489. local nativestringsub = string.sub\
  490. function string.sub( ... )\
  491.    local r = nativestringsub( ... )\
  492.    if r then\
  493.        return r .. \"\"\
  494.    end\
  495.    return nil\
  496. end\
  497. function string.find( s, ... )\
  498.    return nativestringfind( s .. \"\", ... );\
  499. end\
  500. \
  501. -- Install lua parts of the os api\
  502. function os.version()\
  503.    return \"CraftOS 1.7\"\
  504. end\
  505. \
  506. function os.pullEventRaw( sFilter )\
  507.    return coroutine.yield( sFilter )\
  508. end\
  509. \
  510. function os.pullEvent( sFilter )\
  511.    local eventData = { os.pullEventRaw( sFilter ) }\
  512.    if eventData[1] == \"terminate\" then\
  513.        error( \"Terminated\", 0 )\
  514.    end\
  515.    return unpack( eventData )\
  516. end\
  517. \
  518. -- Install globals\
  519. function sleep( nTime )\
  520.    local timer = os.startTimer( nTime or 0 )\
  521.    repeat\
  522.        local sEvent, param = os.pullEvent( \"timer\" )\
  523.    until param == timer\
  524. end\
  525. \
  526. function write( sText )\
  527.    local w,h = term.getSize()        \
  528.    local x,y = term.getCursorPos()\
  529.    \
  530.    local nLinesPrinted = 0\
  531.    local function newLine()\
  532.        if y + 1 <= h then\
  533.            term.setCursorPos(1, y + 1)\
  534.        else\
  535.            term.setCursorPos(1, h)\
  536.            term.scroll(1)\
  537.        end\
  538.        x, y = term.getCursorPos()\
  539.        nLinesPrinted = nLinesPrinted + 1\
  540.    end\
  541.    \
  542.    -- Print the line with proper word wrapping\
  543.    while string.len(sText) > 0 do\
  544.        local whitespace = string.match( sText, \"^[ \\t]+\" )\
  545.        if whitespace then\
  546.            -- Print whitespace\
  547.            term.write( whitespace )\
  548.            x,y = term.getCursorPos()\
  549.            sText = string.sub( sText, string.len(whitespace) + 1 )\
  550.        end\
  551.        \
  552.        local newline = string.match( sText, \"^\\n\" )\
  553.        if newline then\
  554.            -- Print newlines\
  555.            newLine()\
  556.            sText = string.sub( sText, 2 )\
  557.        end\
  558.        \
  559.        local text = string.match( sText, \"^[^ \\t\\n]+\" )\
  560.        if text then\
  561.            sText = string.sub( sText, string.len(text) + 1 )\
  562.            if string.len(text) > w then\
  563.                -- Print a multiline word                \
  564.                while string.len( text ) > 0 do\
  565.                    if x > w then\
  566.                        newLine()\
  567.                    end\
  568.                    term.write( text )\
  569.                    text = string.sub( text, (w-x) + 2 )\
  570.                    x,y = term.getCursorPos()\
  571.                end\
  572.            else\
  573.                -- Print a word normally\
  574.                if x + string.len(text) - 1 > w then\
  575.                    newLine()\
  576.                end\
  577.                term.write( text )\
  578.                x,y = term.getCursorPos()\
  579.            end\
  580.        end\
  581.    end\
  582.    \
  583.    return nLinesPrinted\
  584. end\
  585. \
  586. function print( ... )\
  587.    local nLinesPrinted = 0\
  588.    for n,v in ipairs( { ... } ) do\
  589.        nLinesPrinted = nLinesPrinted + write( tostring( v ) )\
  590.    end\
  591.    nLinesPrinted = nLinesPrinted + write( \"\\n\" )\
  592.    return nLinesPrinted\
  593. end\
  594. \
  595. function printError( ... )\
  596.    if term.isColour() then\
  597.        term.setTextColour( colours.red )\
  598.    end\
  599.    local x,y = term.getCursorPos()\
  600.    print( ... )\
  601.    term.setTextColour( colours.white )\
  602. end\
  603. \
  604. function read( _sReplaceChar, _tHistory )\
  605.    term.setCursorBlink( true )\
  606. \
  607.    local sLine = \"\"\
  608.    local nHistoryPos\
  609.    local nPos = 0\
  610.    if _sReplaceChar then\
  611.        _sReplaceChar = string.sub( _sReplaceChar, 1, 1 )\
  612.    end\
  613.    \
  614.    local w = term.getSize()\
  615.    local sx = term.getCursorPos()\
  616.    \
  617.    local function redraw( _sCustomReplaceChar )\
  618.        local nScroll = 0\
  619.        if sx + nPos >= w then\
  620.            nScroll = (sx + nPos) - w\
  621.        end\
  622. \
  623.        local cx,cy = term.getCursorPos()\
  624.        term.setCursorPos( sx, cy )\
  625.        local sReplace = _sCustomReplaceChar or _sReplaceChar\
  626.        if sReplace then\
  627.            term.write( string.rep( sReplace, math.max( string.len(sLine) - nScroll, 0 ) ) )\
  628.        else\
  629.            term.write( string.sub( sLine, nScroll + 1 ) )\
  630.        end\
  631.        term.setCursorPos( sx + nPos - nScroll, cy )\
  632.    end\
  633.    \
  634.    while true do\
  635.        local sEvent, param = os.pullEvent()\
  636.        if sEvent == \"char\" then\
  637.            -- Typed key\
  638.            sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )\
  639.            nPos = nPos + 1\
  640.            redraw()\
  641. \
  642.        elseif sEvent == \"paste\" then\
  643.            -- Pasted text\
  644.            sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )\
  645.            nPos = nPos + string.len( param )\
  646.            redraw()\
  647. \
  648.        elseif sEvent == \"key\" then\
  649.            if param == keys.enter then\
  650.                -- Enter\
  651.                break\
  652.                \
  653.            elseif param == keys.left then\
  654.                -- Left\
  655.                if nPos > 0 then\
  656.                    nPos = nPos - 1\
  657.                    redraw()\
  658.                end\
  659.                \
  660.            elseif param == keys.right then\
  661.                -- Right                \
  662.                if nPos < string.len(sLine) then\
  663.                    redraw(\" \")\
  664.                    nPos = nPos + 1\
  665.                    redraw()\
  666.                end\
  667.            \
  668.            elseif param == keys.up or param == keys.down then\
  669.                -- Up or down\
  670.                if _tHistory then\
  671.                    redraw(\" \")\
  672.                    if param == keys.up then\
  673.                        -- Up\
  674.                        if nHistoryPos == nil then\
  675.                            if #_tHistory > 0 then\
  676.                                nHistoryPos = #_tHistory\
  677.                            end\
  678.                        elseif nHistoryPos > 1 then\
  679.                            nHistoryPos = nHistoryPos - 1\
  680.                        end\
  681.                    else\
  682.                        -- Down\
  683.                        if nHistoryPos == #_tHistory then\
  684.                            nHistoryPos = nil\
  685.                        elseif nHistoryPos ~= nil then\
  686.                            nHistoryPos = nHistoryPos + 1\
  687.                        end                        \
  688.                    end\
  689.                    if nHistoryPos then\
  690.                        sLine = _tHistory[nHistoryPos]\
  691.                        nPos = string.len( sLine ) \
  692.                    else\
  693.                        sLine = \"\"\
  694.                        nPos = 0\
  695.                    end\
  696.                    redraw()\
  697.                end\
  698.            elseif param == keys.backspace then\
  699.                -- Backspace\
  700.                if nPos > 0 then\
  701.                    redraw(\" \")\
  702.                    sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )\
  703.                    nPos = nPos - 1                    \
  704.                    redraw()\
  705.                end\
  706.            elseif param == keys.home then\
  707.                -- Home\
  708.                redraw(\" \")\
  709.                nPos = 0\
  710.                redraw()        \
  711.            elseif param == keys.delete then\
  712.                -- Delete\
  713.                if nPos < string.len(sLine) then\
  714.                    redraw(\" \")\
  715.                    sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )                \
  716.                    redraw()\
  717.                end\
  718.            elseif param == keys[\"end\"] then\
  719.                -- End\
  720.                redraw(\" \")\
  721.                nPos = string.len(sLine)\
  722.                redraw()\
  723.            end\
  724. \
  725.        elseif sEvent == \"term_resize\" then\
  726.            -- Terminal resized\
  727.            w = term.getSize()\
  728.            redraw()\
  729. \
  730.        end\
  731.    end\
  732. \
  733.    local cx, cy = term.getCursorPos()\
  734.    term.setCursorBlink( false )\
  735.    term.setCursorPos( w + 1, cy )\
  736.    print()\
  737.    \
  738.    return sLine\
  739. end\
  740. \
  741. loadfile = function( _sFile )\
  742.    local file = fs.open( _sFile, \"r\" )\
  743.    if file then\
  744.        local func, err = loadstring( file.readAll(), fs.getName( _sFile ) )\
  745.        file.close()\
  746.        return func, err\
  747.    end\
  748.    return nil, \"File not found\"\
  749. end\
  750. \
  751. dofile = function( _sFile )\
  752.    local fnFile, e = loadfile( _sFile )\
  753.    if fnFile then\
  754.        setfenv( fnFile, getfenv(2) )\
  755.        return fnFile()\
  756.    else\
  757.        error( e, 2 )\
  758.    end\
  759. end\
  760. \
  761. -- Install the rest of the OS api\
  762. function os.run( _tEnv, _sPath, ... )\
  763.    local tArgs = { ... }\
  764.    local fnFile, err = loadfile( _sPath )\
  765.    if fnFile then\
  766.        local tEnv = _tEnv\
  767.        --setmetatable( tEnv, { __index = function(t,k) return _G[k] end } )\
  768.        setmetatable( tEnv, { __index = _G } )\
  769.        setfenv( fnFile, tEnv )\
  770.        local ok, err = pcall( function()\
  771.            fnFile( unpack( tArgs ) )\
  772.        end )\
  773.        if not ok then\
  774.            if err and err ~= \"\" then\
  775.                printError( err )\
  776.            end\
  777.            return false\
  778.        end\
  779.        return true\
  780.    end\
  781.    if err and err ~= \"\" then\
  782.        printError( err )\
  783.    end\
  784.    return false\
  785. end\
  786. \
  787. -- Prevent access to metatables or environments of strings, as these are global between all computers\
  788. do\
  789.    local nativegetfenv = getfenv\
  790.    local nativegetmetatable = getmetatable\
  791.    local nativeerror = error\
  792.    local nativetype = type\
  793.    local string_metatable = nativegetmetatable(\"\")\
  794.    local string_env = nativegetfenv((\"\").gsub)\
  795.    function getmetatable( t )\
  796.        local mt = nativegetmetatable( t )\
  797.        if mt == string_metatable or mt == string_env then\
  798.            nativeerror( \"Attempt to access string metatable\", 2 )\
  799.        else\
  800.            return mt\
  801.        end\
  802.    end\
  803.    function getfenv( env )\
  804.        if env == nil then\
  805.            env = 2\
  806.        elseif nativetype( env ) == \"number\" and env > 0 then\
  807.            env = env + 1\
  808.        end\
  809.        local fenv = nativegetfenv(env)\
  810.        if fenv == string_metatable or fenv == string_env then\
  811.            --nativeerror( \"Attempt to access string metatable\", 2 )\
  812.            return nativegetfenv( 0 )\
  813.        else\
  814.            return fenv\
  815.        end\
  816.    end\
  817. end\
  818. \
  819. local tAPIsLoading = {}\
  820. function os.loadAPI( _sPath )\
  821.    local sName = fs.getName( _sPath )\
  822.    if tAPIsLoading[sName] == true then\
  823.        printError( \"API \"..sName..\" is already being loaded\" )\
  824.        return false\
  825.    end\
  826.    tAPIsLoading[sName] = true\
  827.        \
  828.    local tEnv = {}\
  829.    setmetatable( tEnv, { __index = _G } )\
  830.    local fnAPI, err = loadfile( _sPath )\
  831.    if fnAPI then\
  832.        setfenv( fnAPI, tEnv )\
  833.        local ok, err = pcall( fnAPI )\
  834.        if not ok then\
  835.            printError( err )\
  836.            tAPIsLoading[sName] = nil\
  837.            return false\
  838.        end\
  839.    else\
  840.        printError( err )\
  841.        tAPIsLoading[sName] = nil\
  842.        return false\
  843.    end\
  844.    \
  845.    local tAPI = {}\
  846.    for k,v in pairs( tEnv ) do\
  847.        tAPI[k] =  v\
  848.    end\
  849.    \
  850.    _G[sName] = tAPI    \
  851.    tAPIsLoading[sName] = nil\
  852.    return true\
  853. end\
  854. \
  855. function os.unloadAPI( _sName )\
  856.    if _sName ~= \"_G\" and type(_G[_sName]) == \"table\" then\
  857.        _G[_sName] = nil\
  858.    end\
  859. end\
  860. \
  861. function os.sleep( nTime )\
  862.    sleep( nTime )\
  863. end\
  864. \
  865. local nativeShutdown = os.shutdown\
  866. function os.shutdown()\
  867.    nativeShutdown()\
  868.    while true do\
  869.        coroutine.yield()\
  870.    end\
  871. end\
  872. \
  873. local nativeReboot = os.reboot\
  874. function os.reboot()\
  875.    nativeReboot()\
  876.    while true do\
  877.        coroutine.yield()\
  878.    end\
  879. end\
  880. \
  881. -- Install the lua part of the HTTP api (if enabled)\
  882. if http then\
  883.    local nativeHTTPRequest = http.request\
  884. \
  885.    local function wrapRequest( _url, _post, _headers )\
  886.        local ok, err = nativeHTTPRequest( _url, _post, _headers )\
  887.        if ok then\
  888.            while true do\
  889.                local event, param1, param2 = os.pullEvent()\
  890.                if event == \"http_success\" and param1 == _url then\
  891.                    return param2\
  892.                elseif event == \"http_failure\" and param1 == _url then\
  893.                    return nil, param2\
  894.                end\
  895.            end\
  896.        end\
  897.        return nil, err\
  898.    end\
  899.    \
  900.    http.get = function( _url, _headers )\
  901.        return wrapRequest( _url, nil, _headers )\
  902.    end\
  903. \
  904.    http.post = function( _url, _post, _headers )\
  905.        return wrapRequest( _url, _post or \"\", _headers )\
  906.    end\
  907. \
  908.    http.request = function( _url, _post, _headers )\
  909.        local ok, err = nativeHTTPRequest( _url, _post, _headers )\
  910.        if not ok then\
  911.            os.queueEvent( \"http_failure\", _url, err )\
  912.        end\
  913.        return ok, err\
  914.    end\
  915. end\
  916. \
  917. -- Load APIs\
  918. local bAPIError = false\
  919. local tApis = fs.list( \"rom/apis\" )\
  920. for n,sFile in ipairs( tApis ) do\
  921.    if string.sub( sFile, 1, 1 ) ~= \".\" then\
  922.        local sPath = fs.combine( \"rom/apis\", sFile )\
  923.        if not fs.isDir( sPath ) then\
  924.            if not os.loadAPI( sPath ) then\
  925.                bAPIError = true\
  926.            end\
  927.        end\
  928.    end\
  929. end\
  930. \
  931. if turtle then\
  932.    -- Load turtle APIs\
  933.    local tApis = fs.list( \"rom/apis/turtle\" )\
  934.    for n,sFile in ipairs( tApis ) do\
  935.        if string.sub( sFile, 1, 1 ) ~= \".\" then\
  936.            local sPath = fs.combine( \"rom/apis/turtle\", sFile )\
  937.            if not fs.isDir( sPath ) then\
  938.                if not os.loadAPI( sPath ) then\
  939.                    bAPIError = true\
  940.                end\
  941.            end\
  942.        end\
  943.    end\
  944. end\
  945. \
  946. if pocket and fs.isDir( \"rom/apis/pocket\" ) then\
  947.    -- Load pocket APIs\
  948.    local tApis = fs.list( \"rom/apis/pocket\" )\
  949.    for n,sFile in ipairs( tApis ) do\
  950.        if string.sub( sFile, 1, 1 ) ~= \".\" then\
  951.            local sPath = fs.combine( \"rom/apis/pocket\", sFile )\
  952.            if not fs.isDir( sPath ) then\
  953.                if not os.loadAPI( sPath ) then\
  954.                    bAPIError = true\
  955.                end\
  956.            end\
  957.        end\
  958.    end\
  959. end\
  960. \
  961. if commands and fs.isDir( \"rom/apis/command\" ) then\
  962.    -- Load command APIs\
  963.    if os.loadAPI( \"rom/apis/command/commands\" ) then\
  964.        -- Add a special case-insensitive metatable to the commands api\
  965.        local tCaseInsensitiveMetatable = {\
  966.            __index = function( table, key )\
  967.                local value = rawget( table, key )\
  968.                if value ~= nil then\
  969.                    return value\
  970.                end\
  971.                if type(key) == \"string\" then\
  972.                    local value = rawget( table, string.lower(key) )\
  973.                    if value ~= nil then\
  974.                        return value\
  975.                    end\
  976.                end\
  977.                return nil\
  978.            end\
  979.        }\
  980.        setmetatable( commands, tCaseInsensitiveMetatable )\
  981.        setmetatable( commands.async, tCaseInsensitiveMetatable )\
  982. \
  983.        -- Add global \"exec\" function\
  984.        exec = commands.exec\
  985.    else\
  986.        bAPIError = true\
  987.    end\
  988. end\
  989. \
  990. if bAPIError then\
  991.    print( \"Press any key to continue\" )\
  992.    os.pullEvent( \"key\" )\
  993.    term.clear()\
  994.    term.setCursorPos( 1,1 )\
  995. end\
  996. \
  997. -- Run the shell\
  998. local ok, err = pcall( function()\
  999.    parallel.waitForAny( \
  1000.        function()\
  1001.            if term.isColour() then\
  1002.                os.run( {}, \"rom/programs/advanced/multishell\" )\
  1003.            else\
  1004.                os.run( {}, \"rom/programs/shell\" )\
  1005.            end\
  1006.            os.run( {}, \"rom/programs/shutdown\" )\
  1007.        end,\
  1008.        function()\
  1009.            rednet.run()\
  1010.        end )\
  1011. end )\
  1012. \
  1013. -- If the shell errored, let the user read it.\
  1014. term.redirect( term.native() )\
  1015. if not ok then\
  1016.    printError( err )\
  1017.    pcall( function()\
  1018.        term.setCursorBlink( false )\
  1019.        print( \"Press any key to continue\" )\
  1020.        os.pullEvent( \"key\" )\
  1021.    end )\
  1022. end\
  1023. \
  1024. -- End\
  1025. os.shutdown()",
  1026.     [ "fsh.lua" ] = "--[[\
  1027.     VFS helper and moumting manager\
  1028.     Author: Wassil Janssen a.k.a. Creator\
  1029. ]]--\
  1030. \
  1031. --Variables\
  1032. local mounts = {}\
  1033. local Internal = {}\
  1034. local filesystems = {}\
  1035. \
  1036. --Functions\
  1037. function Internal.getFirstElement(path)\
  1038.     return path:sub(1,path:find(\"/\") and path:find(\"/\")-1 or -1)\
  1039. end\
  1040. \
  1041. function Internal.makeTable(path,tabl)\
  1042.     if type(path) ~= \"string\" then error(\"Expected string, got \"..type(path)..\"!\",2) end\
  1043.     if type(tabl) ~= \"table\" then error(\"Expected table, got \"..type(path)..\"!\",2) end\
  1044.     path = fs.combine(\"\",path)\
  1045.     local first = Internal.getFirstElement(path)\
  1046.     if first == path then\
  1047.         return tabl, first\
  1048.     else\
  1049.         if not tabl[first] then tabl[first] = {} end\
  1050.         return Internal.makeTable(path:sub(path:find(\"/\")+1,-1),tabl[first])\
  1051.     end\
  1052. end\
  1053. \
  1054. function mount(destination,source,fss)\
  1055.     fss = fss or \"ccfs\"\
  1056.     if not fs.exists(destination) then fs.makeDir(destination) end\
  1057.     if not fs.exists(source) then fs.makeDir(source) end\
  1058.     local tabl, dir = Internal.makeTable(destination,mounts)\
  1059.     tabl[dir] = source\
  1060.     if fss ~= \"ccfs\" then\
  1061.         local tabl, dir = Internal.makeTable(destination,filesystems)\
  1062.         tabl[dir] = fss\
  1063.     end\
  1064. end\
  1065. \
  1066. function setFS(path,fss)\
  1067.     if fss ~= \"ccfs\" then\
  1068.         local tabl, dir = Internal.makeTable(destination,filesystems)\
  1069.         tabl[dir] = fss\
  1070.     end\
  1071. end\
  1072. \
  1073. function Internal.resolveLinks(path,tabl)\
  1074.     local first = Internal.getFirstElement(path)\
  1075.     if first == path then return false end\
  1076.     if tabl[first] then\
  1077.         if type(tabl[first]) == \"table\" then\
  1078.             return Internal.resolveLinks(path:sub(path:find(\"/\")+1,-1),tabl[first])\
  1079.         elseif type(tabl[first]) == \"string\" then\
  1080.             return tabl[first]..\"/\"..path:sub(#Internal.getFirstElement(path)+2,-1)\
  1081.         end\
  1082.     end\
  1083.     return false\
  1084. end\
  1085. \
  1086. function resolveLinks(path)\
  1087.     resolved = Internal.resolveLinks(path,mounts)\
  1088.     if resolved == false then\
  1089.         log.log(\"Symlinks\",path..\" \"..path)\
  1090.         return path\
  1091.     else\
  1092.         local lol = resolveLinks(resolved)\
  1093.         log.log(\"Symlinks\",path..\" \"..lol)\
  1094.         return lol\
  1095.     end\
  1096. end\
  1097. \
  1098. function Internal.getFS(path,tabl)\
  1099.     local first = Internal.getFirstElement(path)\
  1100.     if first == path then return false end\
  1101.     if tabl[first] then\
  1102.         if type(tabl[first]) == \"table\" then\
  1103.             return Internal.getFS(path:sub(path:find(\"/\")+1,-1),tabl[first])\
  1104.         elseif type(tabl[first]) == \"string\" then\
  1105.             return tabl[first]\
  1106.         end\
  1107.     end\
  1108.     return false\
  1109. end\
  1110. \
  1111. function getFS(path)\
  1112.     resolved = Internal.getFS(path,filesystems)\
  1113.     if not resolved then\
  1114.         return \"ccfs\"\
  1115.     else\
  1116.         return resolved\
  1117.     end\
  1118. end\
  1119. \
  1120. --mount(\"OmniOS/Programs/FileX.app\",\"disk1\",\"mls\")\
  1121. --mount(\"disk1\",\"OmniOS/API\",\"lol\")\
  1122. --print(\"lol\")\
  1123. --print(resolveLinks(\"OmniOS/Programs/FileX.app/Data/coo\"))\
  1124. --print(\"lol\")\
  1125. --print(getFS(\"OmniOS/Programs\"))\
  1126. --print(textutils.serialize(filesystems))",
  1127.   },
  1128.   [ ".gitmodules" ] = "[submodule \"API/Interact\"]\
  1129.     path = API/Interact\
  1130.     url = ../Interact",
  1131.   Core = {
  1132.     [ "LoadAPIs.lua" ] = "--Code--\
  1133. local function loadAPI( _sPath )\
  1134.    local sName = fs.getName( _sPath )\
  1135.    local tEnv = {}\
  1136.    setmetatable( tEnv, { __index = _G } )\
  1137.    local fnAPI, err = loadfile( _sPath )\
  1138.    if fnAPI then\
  1139.        setfenv( fnAPI, tEnv )\
  1140.        local ok, err = pcall( fnAPI )\
  1141.        if not ok then\
  1142.            log.log(\"API\",err,sName)\
  1143.            return false\
  1144.        end\
  1145.    else\
  1146.        --log.log(\"API\",err,sName)\
  1147.        return false\
  1148.    end\
  1149. \
  1150.    local tAPI = {}\
  1151.    for k,v in pairs( tEnv ) do\
  1152.        tAPI[k] =  v\
  1153.    end\
  1154. \
  1155.    _G[sName:match(\"[^%.]+\")] = tAPI\
  1156.    return true\
  1157. end\
  1158. loadAPI(\"OmniOS/API/Utils.lua\")\
  1159. loadAPI(\"OmniOS/API/log.lua\")\
  1160. local function explore(dir)\
  1161.  --log.log(\"SpecialStuff\",dir)\
  1162.  local ignore = {}\
  1163.  if fs.exists(dir..\"/.ignoreme\") and not fs.isDir(dir..\"/.ignoreme\") then\
  1164.    local file = fs.open(dir..\"/.ignoreme\",\"r\")\
  1165.    ignore = textutils.unserialize(file.readAll())\
  1166.    file.close()\
  1167.  end\
  1168.  for i,v in pairs(fs.list(dir)) do\
  1169.       if fs.isDir(dir..\"/\"..v) then\
  1170.      if ignore[v] == nil then\
  1171.        explore(dir..\"/\"..v)\
  1172.      end\
  1173.    else\
  1174.      if ignore[v] == nil then\
  1175.        loadAPI(dir..\"/\"..v)\
  1176.        term.setTextColor(colors.black)\
  1177.          nPrint(v:match(\"[^%.]+\"))\
  1178.      end\
  1179.    end\
  1180.  end\
  1181.  ignore = nil\
  1182. end\
  1183. explore(\"OmniOS/API\")",
  1184.     [ "Boot.lua" ] = "--OmniOS: Boot--\
  1185. --by Creator--\
  1186. \
  1187. --Variables--\
  1188. local tasks = 2\
  1189. local finishedTasks = 0\
  1190. term.redirect(term.native())\
  1191. local w,h = term.getSize()\
  1192. local textutilsserialize = textutils.serialize\
  1193. local textutilsunserialize = textutils.unserialize\
  1194. local APIlist = {}\
  1195. local oldPullEvent = os.pullEvent\
  1196. local whichLang = nil\
  1197. local lang = {}\
  1198. local oldFs = {}\
  1199. local logo  = paintutils.loadImage(\"OmniOS/Media/Boot/Boot_Logo.nfp\")\
  1200. local hideLogo = paintutils.loadImage(\"OmniOS/Media/Boot/Boot_Hide.nfp\")\
  1201. local logoWide = 18\
  1202. --Functions--\
  1203. \
  1204. function nPrint(text)\
  1205.     finishedTasks = finishedTasks + 1\
  1206.     local txt = \"OmniOS by Creator\"\
  1207.     term.setBackgroundColor(colors.white)\
  1208.     term.setTextColor(colors.lightGray)\
  1209.     term.clear()\
  1210.     term.setCursorPos(math.floor((w-#txt)/2),math.floor(h/2)-1)\
  1211.     term.write(txt)\
  1212.     term.setTextColor(colors.gray)\
  1213.     term.setCursorPos(math.floor((w-#text)/2),math.floor(h/2))\
  1214.     term.write(text)\
  1215.     paintutils.drawImage(logo,math.floor((w-logoWide)/2),math.floor(h/2)+3)\
  1216.     paintutils.drawImage(hideLogo,math.floor((w-logoWide)/2)+math.ceil((finishedTasks/tasks)*logoWide),math.floor(h/2)+3)\
  1217.     sleep(.2)\
  1218. end\
  1219. \
  1220. --Code--\
  1221. \
  1222. term.setTextColor(colors.white)\
  1223. term.setBackgroundColor(colors.white)\
  1224. term.clear()\
  1225. term.setCursorPos(1,1)\
  1226. \
  1227. --Load language file--\
  1228. langFile = fs.open(\"OmniOS/Settings/Language/CurrentLang\",\"r\")\
  1229. whichLang = langFile.readAll()\
  1230. langFile.close()\
  1231. \
  1232. langFile = fs.open(\"OmniOS/Languages/Boot_\"..whichLang..\".lang\",\"r\")\
  1233. lang = textutilsunserialize(langFile.readAll())\
  1234. langFile.close()\
  1235. \
  1236. --Load APIs--\
  1237. nPrint(lang[3])\
  1238. dofile(\"OmniOS/Core/LoadAPIs.lua\")\
  1239. nPrint(lang[4])\
  1240. \
  1241. --Overwrite os.pullEventFunctions--\
  1242. --oldPullEvent = os.pullEvent\
  1243. --os.pullEvent = os.pullEventRaw\
  1244. \
  1245. --Go to next\
  1246. function goOn()\
  1247.     local login, err = loadfile(\"OmniOS/Core/Login.lua\")\
  1248.     if err then print(err) log.log(\"Error\",err) os.pullEvent() end\
  1249.     --login()\
  1250.     local kernel, err= loadfile(\"OmniOS/Core/Kernel.lua\")\
  1251.     if err then print(err) os.pullEvent() log.log(\"Error\",err) end\
  1252.     local startup, err = loadfile(\"OmniOS/Programs/Debug/Main.lua\")\
  1253.     if err then print(err) os.pullEvent() Utils.debug(\"Error\",err) end\
  1254.     kernel(startup,\"term\",\"admin\",\"Debug\")\
  1255. end\
  1256. \
  1257. ok, err = pcall(goOn)\
  1258. \
  1259. if not ok then\
  1260.     Utils.debug(\"Crash\",err)\
  1261.     pcall(shell.run(\"OmniOS/Core/Crash.lua \",err))\
  1262. end",
  1263.     [ "Login.lua" ] = "--Variables--\
  1264. local notLogin = true\
  1265. local w,h = term.getSize()\
  1266. term.redirect(term.native())\
  1267. local user = nil\
  1268. local pass = nil\
  1269. \
  1270. --Code--\
  1271. --Startup script--\
  1272. term.setBackgroundColor(colors.white)\
  1273. term.clear()\
  1274. term.setCursorPos(1,1)\
  1275. term.setTextColor(colors.black)\
  1276. \
  1277. --GUI\
  1278. gui.resetButtons()\
  1279. gui.resetKeys()\
  1280. gui.cPrint(\"Login\",colors.black,nil,math.floor((w-5)/2),3)\
  1281. --gui.cPrint(\"Username: >\",colors.gray,nil,3,6)\
  1282. gui.cPrint(\"Password: >\",colors.gray,nil,3,8)\
  1283. --gui.addField(15,6,20,1,\"userField\")\
  1284. --paintutils.drawFilledBox(15,6,35,6,colors.lightGray)\
  1285. gui.addField(15,8,20,1,\"passField\")\
  1286. paintutils.drawFilledBox(15,8,35,8,colors.lightGray)\
  1287. gui.addKey(keys.enter,\"Enter\")\
  1288. gui.drawButton(15,10,8,3,colors.green,2,2,\"Ready!\",colors.black,\"ready\")\
  1289. \
  1290. --Main Loop--\
  1291. while notLogin do\
  1292.     --Script\
  1293.     local result = gui.detectButtonOrKeyHit()\
  1294.     if result[1] == \"userField\" then\
  1295.         paintutils.drawFilledBox(15,6,35,6,colors.lightGray)\
  1296.         term.setCursorPos(15,6)\
  1297.         term.setTextColor(colors.black)\
  1298.         user = read()\
  1299.     elseif result[1] == \"passField\" then\
  1300.         paintutils.drawFilledBox(15,8,35,8,colors.lightGray)\
  1301.         term.setCursorPos(15,8)\
  1302.         term.setTextColor(colors.black)\
  1303.         pass = read(\"*\")\
  1304.     elseif result[1] == \"Enter\" or result[1] == \"ready\" then\
  1305.         if user == nil or pass == nil then\
  1306.         else\
  1307.             paintutils.drawFilledBox(15,15,35,15,colors.lightGray)\
  1308.             local realPass\
  1309.             ok = pcall( function()\
  1310.             f = fs.open(\"TheOS/Settings/Users/Admin\",\"r\")\
  1311.             realPass = f.readAll()\
  1312.             f.close()\
  1313.             end )\
  1314.             if realPass == Sha.sha256(pass) then\
  1315.                 notLogin = false\
  1316.             end\
  1317.             if ok == false or notLogin then\
  1318.                 gui.cPrint(\"Wrong username or password!\",colors.red,colors.white,13,15)\
  1319.             end\
  1320.         end\
  1321.     end\
  1322. end",
  1323.     [ "Crash.lua" ] = "os.pullEvent = os.pullEventRaw\
  1324. tArgs = {...}\
  1325. \
  1326. err = \"\"\
  1327. \
  1328. term.redirect(term.native())\
  1329. term.setBackgroundColor(colors.blue)\
  1330. term.clear()\
  1331. term.setTextColor(colors.white)\
  1332. term.setCursorPos(2,4)\
  1333. term.write(\"OmniOS has crashed :(\")\
  1334. term.setCursorPos(2,6)\
  1335. print(\"Click anywhere to restart the system, if the\\n problem persists send the error message\\n to Creator on the CC forums or to\\n Creator on GitHub.\")\
  1336. term.setCursorPos(2,11)\
  1337. term.write(\"Error message: \")\
  1338. term.setCursorPos(4,13)\
  1339. for i,v in pairs(tArgs) do\
  1340.     err = err..\" \"..v\
  1341. end\
  1342. print(err)\
  1343. log.log(\"Error\",err,\"Missing\")\
  1344. os.pullEvent(\"mouse_click\")\
  1345. --os.reboot()",
  1346.     [ "OldKernel.lua" ] = "--[[\
  1347.     TheOS Kernel\
  1348.     by Creator\
  1349.     for OmniOS &\
  1350.     you to learn\
  1351.     from it! (Yeah learn, rather become dumber)\
  1352.     theoriginalbit\
  1353.     also gets credit for\
  1354.     his safePairs function.\
  1355.     Lots of thanks to BombBloke too for\
  1356.     finalizing and bug fixing it.\
  1357. ]]--\
  1358. --[[::VARIABLES::]]--\
  1359. local logMessage = \"\"\
  1360. local newRoutine = \"\"\
  1361. local history = {}\
  1362. local w,h = term.getSize()\
  1363. local monitors = {}\
  1364. local currTerm, routines, activeRoutine, eventBuffer = term.current(), {}, \"\", {}\
  1365. local eventFilter = {[\"key\"] = true, [\"mouse_click\"] = true, [\"paste\"] = true,[\"char\"] = true, [\"terminate\"] = true, [\"mouse_scroll\"] = true, [\"mouse_drag\"] = true}\
  1366. \
  1367. \
  1368. --[[::FUNCTIONS::]]--\
  1369. local function safePairs(t)\
  1370.  local keys = {}\
  1371.  for k,v in pairs(t) do\
  1372.     keys[#keys+1] = k\
  1373.  end\
  1374.  local i = 0\
  1375.  return function()\
  1376.     i = i + 1\
  1377.     return keys[i], t[keys[i]]\
  1378.  end\
  1379. end\
  1380. \
  1381. local function drawClosed()\
  1382.     paintutils.drawLine(w,1,w,h,colors.black)\
  1383.     term.setTextColor(colors.white)\
  1384.     term.setBackgroundColor(colors.black)\
  1385.     term.setCursorPos(w,h/2+2)\
  1386.     term.write(\"<\")\
  1387. end\
  1388. \
  1389. --[[local function switch()\
  1390.     if routines[newRoutine] and not newRoutine == \"\" then\
  1391.         routines[activeRoutine].window.setVisible( false )\
  1392.         activeRoutine = newRoutine\
  1393.         routines[activeRoutine].window.setVisible(true)\
  1394.         newRoutine = \"\"\
  1395.     end\
  1396. end]]--\
  1397. \
  1398. local function drawOpen()\
  1399.     term.setCursorBlink(false)\
  1400.     paintutils.drawFilledBox(w-15,1,w,h,colors.black)\
  1401.     local xVsProcess, curr = {}, 1\
  1402.     term.setTextColor(colors.white)\
  1403.     for i,v in pairs(routines) do\
  1404.         paintutils.drawLine(w-15,curr*2,w,curr*2,i == activeRoutine and colours.blue or colours.black)\
  1405.         paintutils.drawLine(w-15,curr*2+1,w,curr*2+1,i == activeRoutine and colours.blue or colours.black)\
  1406.         term.setBackgroundColour(i == activeRoutine and colours.blue or colours.black)\
  1407.         term.setCursorPos(w-14,curr*2)\
  1408.         term.write(\"x \"..v.title)\
  1409.         term.setCursorPos(w-12,curr*2+1)\
  1410.         term.write(coroutine.status(v.routine))\
  1411.         xVsProcess[curr*2] = i\
  1412.         curr = curr + 1\
  1413.     end\
  1414. \
  1415.     while true do\
  1416.         local evnt = {os.pullEventRaw()}\
  1417.         log.log(\"Close\",xVsProcess[evnt[4]])\
  1418.         if evnt[1] == \"mouse_click\" then\
  1419.             if w-12 <= evnt[3] and evnt[3] <= w then\
  1420.                 if xVsProcess[evnt[4]] then\
  1421.                     --routines[activeRoutine].window.setVisible(false)\
  1422.                     log.log(\"Multitask\",\"Current: \"..activeRoutine..\" New: \"..xVsProcess[evnt[4]])\
  1423.                     activeRoutine = xVsProcess[evnt[4]]\
  1424.                     --routines[activeRoutine].window.setVisible(true)\
  1425.                     routines[activeRoutine].window.redraw()\
  1426.                     return\
  1427.                 end\
  1428.             elseif w-14 == evnt[3] then\
  1429.                 if xVsProcess[evnt[4]] and xVsProcess[evnt[4]] ~= \"Debug1\" then\
  1430.                     if activeRoutine == xVsProcess[evnt[4]] then\
  1431.                         routines[xVsProcess[evnt[4]]].window.setVisible(false)\
  1432.                         activeRoutine = \"Debug1\"\
  1433.                         routines[activeRoutine].window.setVisible(true)\
  1434.                     else\
  1435.                         routines[activeRoutine].window.redraw()\
  1436.                     end\
  1437.                     routines[xVsProcess[evnt[4]]] = nil\
  1438.                     return\
  1439.                 end\
  1440.             else return end\
  1441.         else eventBuffer[#eventBuffer+1] = evnt end\
  1442.     end\
  1443. end\
  1444. \
  1445. local function checkIfDead(routine)\
  1446.     if coroutine.status(routines[routine].routine) == \"dead\" then\
  1447.         routines[routine] = nil\
  1448.         if routine == activeRoutine then\
  1449.             activeRoutine = \"Debug1\"\
  1450.             routines[activeRoutine].window.redraw()\
  1451.         end\
  1452.         return true\
  1453.     else return false end\
  1454. end\
  1455. \
  1456. Kernel = {}\
  1457. \
  1458. function Kernel.newRoutine(name,title,func,permission,tParent,...)\
  1459.     if tParent == term or tParent == term.current() or tParent == \"term\" then\
  1460.         tParent = term.current()\
  1461.     else\
  1462.         if monitors[tParent] then\
  1463.             log.log(\"Processes/Mon\",\"A program is using the monitor!\")\
  1464.             return \"A program is using the monitor!\"\
  1465.         end\
  1466.         if not peripheral.isPresent(tParent) then\
  1467.             log.log(\"Processes/Mon\",\"The monitor does not exist!\")\
  1468.             return \"The monitor does not exist!\"\
  1469.         end\
  1470.         if not peripheral.getType(tParent) == \"monitor\" then\
  1471.             log.log(\"Processes/Mon\",\"The peripheral is not a monitor!\")\
  1472.             return \"The peripheral is not a monitor!\"\
  1473.         end\
  1474.         monitors[tParent] = true\
  1475.     end\
  1476.     log.log(\"System\",\"Launching task \"..name..\". By kernel\")\
  1477.     local oldName = name\
  1478.     do\
  1479.         local tries = 1\
  1480.         while routines[name .. tries] do tries = tries + 1 end\
  1481.         name = name .. tries\
  1482.     end\
  1483.     if permission == \"userTest\" then\
  1484.         log.log(\"Env\",\"Launching task \"..name..\": adding environment. By kernel\")\
  1485.         local env = Sandbox.newEnv(oldName)\
  1486.         log.log(\"Env\",\"Environment was successful\")\
  1487.         setfenv(func,env)\
  1488.     end\
  1489. \
  1490.     routines[name] = {\
  1491.         [\"title\"] = title,\
  1492.         [\"permission\"] = permission,\
  1493.         [\"path\"] = path,\
  1494.         [\"routine\"] = coroutine.create(func),\
  1495.         [\"window\"] = (tParent == term or tParent == term.current()) and  OmniWindow.create(tParent,1,1,w-1,h,false) or OmniWindow.create(peripheral.wrap(tParent),1,1,w-1,h,true),\
  1496.         [\"filter\"] = \"\",\
  1497.         [\"parent\"] = (tParent == term or tParent == term.current()) and \"term\" or \"mon\",\
  1498.     }\
  1499. \
  1500.     --Run it!\
  1501.     if routines[activeRoutine] then\
  1502.         term.redirect(routines[name].window)\
  1503.         --routines[name].window.setVisible(false)\
  1504.         logMessage, routines[name].filter = coroutine.resume(routines[name].routine,...)\
  1505.         if not logMessage then\
  1506.             log.log(name,\"Error: \"..tostring(routines[name].filter),name)\
  1507.         end\
  1508.         term.redirect(currTerm)\
  1509.         checkIfDead(name)\
  1510.         --routines[activeRoutine].window.redraw()\
  1511.     else\
  1512.         activeRoutine = name\
  1513.         term.redirect(routines[activeRoutine].window)\
  1514.         routines[activeRoutine].window.setVisible(true)\
  1515.         logMessage, routines[activeRoutine].filter = coroutine.resume(routines[activeRoutine].routine,...)\
  1516.         if not logMessage then\
  1517.             log.log(activeRoutine,\"Error: \"..tostring(routines[activeRoutine].filter),activeRoutine)\
  1518.         end\
  1519.         --routines[activeRoutine].window.setVisible(false)\
  1520.         term.redirect(currTerm)\
  1521.         checkIfDead(activeRoutine)\
  1522.     end\
  1523. end\
  1524. \
  1525. function Kernel.getPermission(program)\
  1526.     return routines[program].permission or \"Not a valid program\"\
  1527. end\
  1528. \
  1529. function Kernel.kill(thread)\
  1530.     if thread == \"Debug1\" then\
  1531.         return \"Cannot kill debug, instead use kill !zygote\"\
  1532.     else\
  1533.         if thread == activeRoutine then\
  1534.             activeRoutine = \"Debug1\"\
  1535.             routines[activeRoutine].window.setVisible(true)\
  1536.         end\
  1537.         routines[thread] = nil\
  1538.     end\
  1539. end\
  1540. \
  1541. function Kernel.getScreen(routine)\
  1542.     return routines[routine] and routines[routine].window.getBuffer() or false\
  1543. end\
  1544. \
  1545. function Kernel.list()\
  1546.     local buffer = {}\
  1547.     for i,v in pairs(routines) do\
  1548.         buffer[#buffer+1] = i\
  1549.     end\
  1550.     return buffer\
  1551. end\
  1552. \
  1553. function Kernel.switch(newTask)\
  1554.     newRoutine = newTask\
  1555. end\
  1556. \
  1557. drawClosed()\
  1558. \
  1559. Kernel.newRoutine(...)\
  1560. \
  1561. while true do\
  1562.  drawClosed()\
  1563.     --switch()\
  1564.     local event = #eventBuffer == 0 and {os.pullEventRaw()} or table.remove(eventBuffer,1)\
  1565.     if fs.exists(\"OmniOS/Drivers/\"..event[1]..\".lua\") then\
  1566.         local func = loadfile(\"OmniOS/Drivers/\"..event[1]..\".lua\")\
  1567.         func(unpack(event))\
  1568.         routines[activeRoutine].window.redraw()\
  1569.     else\
  1570.         if (event[1] == \"mouse_click\" or event[1] == \"monitor_touch\") and event[3] == w then\
  1571.             drawOpen()\
  1572.             drawClosed()\
  1573.             routines[activeRoutine].window.redraw()\
  1574.         elseif eventFilter[event[1]] then\
  1575.             if routines[activeRoutine].filter == nil or routines[activeRoutine].filter == \"\" or routines[activeRoutine].filter == event[1] then\
  1576.                 term.redirect(routines[activeRoutine].window)\
  1577.                 --routines[activeRoutine].window.setVisible(true)\
  1578.                 logMessage, routines[activeRoutine].filter = coroutine.resume(routines[activeRoutine].routine,unpack(event))\
  1579.                 if not logMessage then\
  1580.                     log.log(activeRoutine,\"Error: \"..tostring(routines[activeRoutine].filter),activeRoutine)\
  1581.                 end\
  1582.                 --routines[activeRoutine].window.setVisible(false)\
  1583.                 term.redirect(currTerm)\
  1584.                 checkIfDead(activeRoutine,\"term\")\
  1585.             end\
  1586.         else\
  1587.             for i,v in safePairs(routines) do\
  1588.                 if routines[i] and routines[i].filter == event[1] or routines[i].filter == nil then\
  1589.                     term.redirect(routines[i].window)\
  1590.                     logMessage, routines[i].filter = coroutine.resume(routines[i].routine,unpack(event))\
  1591.                     if not logMessage then\
  1592.                         log.log(i,\"Error: \"..tostring(routines[i].filter),i)\
  1593.                     end\
  1594.                     term.redirect(currTerm)\
  1595.                     checkIfDead(i,\"term\")\
  1596.                 end\
  1597.             end\
  1598.         end\
  1599.     end\
  1600. end",
  1601.     [ "Kernel.lua" ] = "--[[\
  1602.     Kernel\
  1603.     By: Creator a.k.a. Wassil Janssen\
  1604.     For OmniOS\
  1605. ]]--\
  1606. --[[\
  1607.     Specifications:\
  1608.     newProcess:\
  1609.         @parent: the object on which the process will be drawn\
  1610.         @func: the function, usually from a file\
  1611. ]]--\
  1612. \
  1613. --Variables\
  1614. local ids = {}\
  1615. local process = {}\
  1616. local tasks = {}\
  1617. local active = 1\
  1618. local bindings = {}\
  1619. local eventFilter = {[\"key\"] = true, [\"mouse_click\"] = true, [\"paste\"] = true,[\"char\"] = true, [\"terminate\"] = true, [\"mouse_scroll\"] = true, [\"mouse_drag\"] = true}\
  1620. local Internal = {}\
  1621. local eventBuffer = {}\
  1622. local nameIDLink = {}\
  1623. local currTerm = term.current()\
  1624. local w,h = term.getSize()\
  1625. local running = 0\
  1626. local time = 0\
  1627. \
  1628. Kernel = {}\
  1629. Internal.getMessages = {}\
  1630. Internal.messages = {}\
  1631. \
  1632. --Overwrites\
  1633. function assert(check,msg,level)\
  1634.     if not type(level) == \"number\" then error(\"The third argument has to be a number!\",2) end\
  1635.     level = level or 1\
  1636.     if not check then error(msg,level+1) end\
  1637. end\
  1638. \
  1639. --Functions\
  1640. --Local\
  1641. function Internal.finalKill(id)\
  1642.     process[id] = nil\
  1643. end\
  1644. \
  1645. function Internal.kill(id)\
  1646.     if id == 1 then\
  1647.         return\
  1648.     elseif id == active then\
  1649.         Kernel.switch(1)\
  1650.     end\
  1651.     Internal.queueTask(\"finalKill\",id)\
  1652. end\
  1653. \
  1654. function Internal.drawClosed()\
  1655.     local col = process[active].preferences.sideBarColor or colors.black\
  1656.     paintutils.drawLine(w,1,w,h,col)\
  1657.     term.setBackgroundColor(col)\
  1658.     term.setCursorPos(w,math.floor(h/2)+1)\
  1659.     term.setTextColor(col == colors.black and colors.white or colors.white)\
  1660.     term.write(\"<\")\
  1661. end\
  1662. \
  1663. function Internal.drawOpen()\
  1664.     process[active].window.setVisible(false)\
  1665.     term.setCursorBlink(false)\
  1666.     paintutils.drawFilledBox(w-15,1,w,h,colors.black)\
  1667.     term.setTextColor(colors.white)\
  1668.     local amount = 0\
  1669.     local links = {}\
  1670.     for i,v in pairs(process) do\
  1671.         if active == i then paintutils.drawLine(w-15,i,w,i,colors.blue) end\
  1672.         term.setCursorPos(w-14,i)\
  1673.         term.setBackgroundColor(active == i and colors.blue or colors.black)\
  1674.         --term.setTextColor(colors.white)\
  1675.         term.write(\"x \"..i..\" \"..v.name)\
  1676.         amount = amount + 1\
  1677.         links[amount] = i\
  1678.     end\
  1679. \
  1680.     while true do\
  1681.         local evnt = {os.pullEventRaw()}\
  1682.         if evnt[1] == \"mouse_click\" then\
  1683.             if evnt[3] < w-15 then break\
  1684.             elseif evnt[3] == w-14 and evnt[4] <= amount then\
  1685.                 Kernel.kill(links[evnt[4]])\
  1686.                 if links[evnt[4]] == active then break end\
  1687.             elseif evnt[3] >= w-12 and evnt[4] <= amount then\
  1688.                 Kernel.switch(links[evnt[4]])\
  1689.                 break\
  1690.             end\
  1691.         else eventBuffer[#eventBuffer+1] = evnt end\
  1692.     end\
  1693.     process[active].window.setVisible(true)\
  1694.     process[active].window.redraw()\
  1695.     Internal.drawClosed()\
  1696. end\
  1697. \
  1698. \
  1699. function Internal.newProcess(func,parent,permission,name,...)\
  1700.     local id = 1\
  1701.     while true do\
  1702.         if not process[id] then break end\
  1703.         id = id + 1\
  1704.     end\
  1705.     Utils.debug(\"Found ID\")\
  1706.     if permission == \"user\" then\
  1707.         local env = Sandbox.newEnv(name)\
  1708.         setfenv(func,env)\
  1709.         Utils.debug(\"User permission.\")\
  1710.     end\
  1711.     process[id] = {\
  1712.         [\"environement\"] = env,\
  1713.         [\"routine\"] = coroutine.create(func),\
  1714.         [\"name\"] = name,\
  1715.         [\"filter\"] = \"\",\
  1716.         [\"parent\"] = parent,\
  1717.         [\"window\"] = window.create(parent == \"term\" and term.current() or peripheral.wrap(parent),1,1,w-1,h,false),\
  1718.         [\"preferences\"] = {}\
  1719.     }\
  1720.     Utils.debug(\"Added process table.\")\
  1721. \
  1722.     if not nameIDLink[name] then nameIDLink[name] = {id} else nameIDLink[name][#nameIDLink[name]+1] = id end\
  1723.     Utils.debug(\"Added links.\")\
  1724.     if id == active then\
  1725.         process[id].window.setVisible(true)\
  1726.     end\
  1727.     term.redirect(process[id].window)\
  1728.     ok, process[id].filter = coroutine.resume(process[id].routine,...)\
  1729.     if not ok then Utils.debug(\"routines/\"..name,process[id].filter) end\
  1730.     term.redirect(currTerm)\
  1731. end\
  1732. \
  1733. function Internal.runBinds(event)\
  1734.     if bindings[event[1]] then\
  1735.         for i,v in pairs(bindings[event[1]]) do\
  1736.             pcall(v,unpack(event))\
  1737.         end\
  1738.     end\
  1739. end\
  1740. \
  1741. function Internal.queueTask(...)\
  1742.     tasks[#tasks+1] = {...}\
  1743. end\
  1744. \
  1745. function Internal.switch(...)\
  1746.  local args={...}\
  1747.  Utils.debug(\"Switch in kernel \"..(function(tabl) local x = \"\" for i,v in pairs(tabl) do x = x..\" \"..tostring(i)..\": \"..tostring(v) end return x end)(args))\
  1748.  if not type(args[1]) == \"number\" then Utils.debug(\"Expected number, got \"..type(args[1])) return end\
  1749.     Utils.debug(\"Args \"..tostring(args[1])..type(args[1]))\
  1750.     if process[args[1]] then\
  1751.         process[active].window.setVisible(false)\
  1752.         process[args[1]].window.setVisible(true)\
  1753.     process[args[1]].window.redraw()\
  1754.         active = args[1]\
  1755.     end\
  1756. end\
  1757. \
  1758. --API\
  1759. function Kernel.newProcess(func,parent,permission,name,...)\
  1760.     Internal.queueTask(\"newProcess\",func,parent,permission,name,...)\
  1761. end\
  1762. \
  1763. function Kernel.list()\
  1764.     local ret = {}\
  1765.     for i,v in pairs(process) do\
  1766.         ret[#ret+1] = {i,v.name,coroutine.status(v.routine)}\
  1767.     end\
  1768.     return ret\
  1769. end\
  1770. \
  1771. function Kernel.switch(newTaskID)\
  1772.     Utils.debug(\"Queueing switch event: \"..tostring(newTaskID))\
  1773.     Internal.queueTask(\"switch\",newTaskID)\
  1774. end\
  1775. \
  1776. function Kernel.bindEvent(event,func)\
  1777.     if type(func) ~= \"function\" then error(\"Ecxpected function, got \"..type(func)..\"!\",2) end\
  1778.     if bindings[event] then\
  1779.         bindings[event][#bindings[event]+1] = func\
  1780.     else\
  1781.         bindings[event] = {[1] = func}\
  1782.     end\
  1783. end\
  1784. \
  1785. function Kernel.kill(id)\
  1786.     Utils.debug(\"Killing \"..tostring(id))\
  1787.     Internal.queueTask(\"kill\",id)\
  1788. end\
  1789. \
  1790. function Kernel.getRunning()\
  1791.     return running\
  1792. end\
  1793. \
  1794. function Kernel.addMessage(destination,sender,...)\
  1795.     if not Internal.messages[destination] then\
  1796.         Internal.messages[destination] = {}\
  1797.     end\
  1798.     Internal.messages[destination][#Internal.messages[destination]+1] = {sender,...}\
  1799. end\
  1800. \
  1801. --Code\
  1802. dofile(\"OmniOS/Drivers/FS.lua\")\
  1803. dofile(\"OmniOS/Drivers/disk.lua\")\
  1804. \
  1805. local function keySwitch(_event,_code)\
  1806.  if _event == \"key\" and _code == 56 then\
  1807.    time = os.clock()\
  1808.  elseif _event == \"char\" and tonumber(_code) then\
  1809.    if os.clock()-time <= 0.30 then\
  1810.      Kernel.switch(tonumber(_code))\
  1811.    end\
  1812.  end\
  1813. end\
  1814. \
  1815. Kernel.bindEvent(\"key\",keySwitch)\
  1816. Kernel.bindEvent(\"char\",keySwitch)\
  1817. \
  1818. Internal.newProcess(...)\
  1819. \
  1820. fs.link(\"a\",\"/\")\
  1821. Internal.drawClosed()\
  1822. \
  1823. while true do\
  1824.     if tasks[1] then\
  1825.         if Internal[tasks[1][1]] then\
  1826.             Internal[tasks[1][1]](unpack(tasks[1],2))\
  1827.             Utils.debug(\"Completed task \"..tasks[1][1])\
  1828.             table.remove(tasks,1)\
  1829.         end\
  1830.     else\
  1831.         local event = #eventBuffer == 0 and {os.pullEvent()} or table.remove(eventBuffer,1)\
  1832.         Internal.runBinds(event)\
  1833.         if event[1] == \"mouse_click\" and event[3] == w then Internal.drawOpen() end\
  1834.         if eventFilter[event[1]] then\
  1835.             if process[active].filter == nil or process[active].filter == \"\" or process[active].filter == event[1] then\
  1836.                 Utils.debug(\"Running main routine with event \"..tostring(event[1]))\
  1837.                 term.redirect(process[active].window)\
  1838.                 running = active\
  1839.                 ok, process[active].filter = coroutine.resume(process[active].routine,unpack(event))\
  1840.                 if not ok then Utils.debug(process[active].filter) end\
  1841.                 term.redirect(currTerm)\
  1842.                 Internal.drawClosed()\
  1843.                 if coroutine.status(process[active].routine) == \"dead\" then\
  1844.                     Kernel.kill(active)\
  1845.                 elseif process[active].filter == \"kernel_messages\" then\
  1846.                     Internal.getMessages[active] = true\
  1847.                 end\
  1848.             end\
  1849.         else\
  1850.             for i,v in pairs(process) do\
  1851.                 if process[i].filter == nil or process[i].filter == \"\" or process[i].filter == event[1] then\
  1852.                     Utils.debug(\"Running secindary routine with event \"..tostring(event[1]))\
  1853.                     term.redirect(v.window)\
  1854.                     running = i\
  1855.                     ok, process[i].filter = coroutine.resume(v.routine,unpack(event))\
  1856.                     if not ok then Utils.debug(process[i].filter) end\
  1857.                     term.redirect(currTerm)\
  1858.                     if coroutine.status(process[i].routine) == \"dead\" then\
  1859.                         Kernel.kill(i)\
  1860.                     elseif process[i].filter == \"kernel_messages\" then\
  1861.                         Internal.getMessages[i] = true\
  1862.                     end\
  1863.                 end\
  1864.             end\
  1865.         end\
  1866.    local buffer = {}\
  1867.         for i,v in pairs(Internal.getMessages) do\
  1868.      term.redirect(process[i].window)\
  1869.      ok, process[i].filter = coroutine.resume(process[i].routine,Internal.messages[i])\
  1870.      term.redirect(currTerm)\
  1871.      if coroutine.status(process[i].routine) == \"dead\" then\
  1872.        Kernel.kill(i)\
  1873.      elseif process[i].filter == \"kernel_messages\" then\
  1874.        buffer[i] = true\
  1875.      end\
  1876.         end\
  1877.    Internal.getMessages = buffer\
  1878.    buffer = nil\
  1879.     end\
  1880. end",
  1881.   },
  1882.   [ ".gitignore" ] = "*.log",
  1883.   Programs = {
  1884.     Edit = {
  1885.       disk = {},
  1886.       [ "main.lua" ] = "-- Get file to edit\
  1887. local tArgs = { ... }\
  1888. if #tArgs == 0 then\
  1889.     term.setTextColour(colors.white)\
  1890.     term.setBackgroundColour(colors.black)\
  1891.     term.clear()\
  1892.    term.write(\"Path please!\")\
  1893.    tArgs[1] =read()\
  1894. end\
  1895. \
  1896. -- Error checking\
  1897. --local sPath = shell.resolve( tArgs[1] )\
  1898. local sPath = tArgs[1]\
  1899. local bReadOnly = fs.isReadOnly( sPath )\
  1900. if fs.exists( sPath ) and fs.isDir( sPath ) then\
  1901.     print( \"Cannot edit a directory.\" )\
  1902.     return\
  1903. end\
  1904. \
  1905. local x,y = 1,1\
  1906. local w,h = term.getSize()\
  1907. local scrollX, scrollY = 0,0\
  1908. \
  1909. local tLines = {}\
  1910. local bRunning = true\
  1911. \
  1912. -- Colours\
  1913. local highlightColour, keywordColour, commentColour, textColour, bgColour\
  1914. if term.isColour() then\
  1915.     bgColour = colours.black\
  1916.     textColour = colours.white\
  1917.     highlightColour = colours.yellow\
  1918.     keywordColour = colours.yellow\
  1919.     commentColour = colours.green\
  1920.     stringColour = colours.red\
  1921. else\
  1922.     bgColour = colours.black\
  1923.     textColour = colours.white\
  1924.     highlightColour = colours.white\
  1925.     keywordColour = colours.white\
  1926.     commentColour = colours.white\
  1927.     stringColour = colours.white\
  1928. end\
  1929. \
  1930. -- Menus\
  1931. local bMenu = false\
  1932. local nMenuItem = 1\
  1933. local tMenuItems\
  1934. if bReadOnly then\
  1935.     tMenuItems = { \"Exit\", \"Print\" }\
  1936. else\
  1937.     tMenuItems = { \"Save\", \"Exit\", \"Print\" }\
  1938. end\
  1939.     \
  1940. local sStatus = \"Press Ctrl to access menu\"\
  1941. \
  1942. local function load( _sPath )\
  1943.     tLines = {}\
  1944.     if fs.exists( _sPath ) then\
  1945.         local file = io.open( _sPath, \"r\" )\
  1946.         local sLine = file:read()\
  1947.         while sLine do\
  1948.             table.insert( tLines, sLine )\
  1949.             sLine = file:read()\
  1950.         end\
  1951.         file:close()\
  1952.     end\
  1953.     \
  1954.     if #tLines == 0 then\
  1955.         table.insert( tLines, \"\" )\
  1956.     end\
  1957. end\
  1958. \
  1959. local function save( _sPath )\
  1960.     -- Create intervening folder\
  1961.     local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )\
  1962.     if not fs.exists( sDir ) then\
  1963.         fs.makeDir( sDir )\
  1964.     end\
  1965. \
  1966.     -- Save\
  1967.     local file = nil\
  1968.     local function innerSave()\
  1969.         file = fs.open( _sPath, \"w\" )\
  1970.         if file then\
  1971.             for n, sLine in ipairs( tLines ) do\
  1972.                 file.write( sLine .. \"\\n\" )\
  1973.             end\
  1974.         else\
  1975.             error( \"Failed to open \".._sPath )\
  1976.         end\
  1977.     end\
  1978.     \
  1979.     local ok = pcall( innerSave )\
  1980.     if file then \
  1981.         file.close()\
  1982.     end\
  1983.     return ok\
  1984. end\
  1985. \
  1986. local tKeywords = {\
  1987.     [\"and\"] = true,\
  1988.     [\"break\"] = true,\
  1989.     [\"do\"] = true,\
  1990.     [\"else\"] = true,\
  1991.     [\"elseif\"] = true,\
  1992.     [\"end\"] = true,\
  1993.     [\"false\"] = true,\
  1994.     [\"for\"] = true,\
  1995.     [\"function\"] = true,\
  1996.     [\"if\"] = true,\
  1997.     [\"in\"] = true,\
  1998.     [\"local\"] = true,\
  1999.     [\"nil\"] = true,\
  2000.     [\"not\"] = true,\
  2001.     [\"or\"] = true,\
  2002.     [\"repeat\"] = true,\
  2003.     [\"return\"] = true,\
  2004.     [\"then\"] = true,\
  2005.     [\"true\"] = true,\
  2006.     [\"until\"]= true,\
  2007.     [\"while\"] = true,\
  2008. }\
  2009. \
  2010. local function tryWrite( sLine, regex, colour )\
  2011.     local match = string.match( sLine, regex )\
  2012.     if match then\
  2013.         if type(colour) == \"number\" then\
  2014.             term.setTextColour( colour )\
  2015.         else\
  2016.             term.setTextColour( colour(match) )\
  2017.         end\
  2018.         term.write( match )\
  2019.         term.setTextColour( textColour )\
  2020.         return string.sub( sLine, string.len(match) + 1 )\
  2021.     end\
  2022.     return nil\
  2023. end\
  2024. \
  2025. local function writeHighlighted( sLine )\
  2026.     while string.len(sLine) > 0 do  \
  2027.         sLine = \
  2028.             tryWrite( sLine, \"^%-%-%[%[.-%]%]\", commentColour ) or\
  2029.             tryWrite( sLine, \"^%-%-.*\", commentColour ) or\
  2030.             tryWrite( sLine, \"^\\\".-[^\\\\]\\\"\", stringColour ) or\
  2031.             tryWrite( sLine, \"^\\'.-[^\\\\]\\'\", stringColour ) or\
  2032.             tryWrite( sLine, \"^%[%[.-%]%]\", stringColour ) or\
  2033.             tryWrite( sLine, \"^[%w_]+\", function( match )\
  2034.                 if tKeywords[ match ] then\
  2035.                     return keywordColour\
  2036.                 end\
  2037.                 return textColour\
  2038.             end ) or\
  2039.             tryWrite( sLine, \"^[^%w_]\", textColour )\
  2040.     end\
  2041. end\
  2042. \
  2043. local function redrawText()\
  2044.     for y=1,h-1 do\
  2045.         term.setCursorPos( 1 - scrollX, y )\
  2046.         term.clearLine()\
  2047. \
  2048.         local sLine = tLines[ y + scrollY ]\
  2049.         if sLine ~= nil then\
  2050.             writeHighlighted( sLine )\
  2051.         end\
  2052.     end\
  2053.     term.setCursorPos( x - scrollX, y - scrollY )\
  2054. end\
  2055. \
  2056. local function redrawLine(_nY)\
  2057.     local sLine = tLines[_nY]\
  2058.     term.setCursorPos( 1 - scrollX, _nY - scrollY )\
  2059.     term.clearLine()\
  2060.     writeHighlighted( sLine )\
  2061.     term.setCursorPos( x - scrollX, _nY - scrollY )\
  2062. end\
  2063. \
  2064. local function redrawMenu()\
  2065.    -- Clear line\
  2066.    term.setCursorPos( 1, h )\
  2067.     term.clearLine()\
  2068. \
  2069.    -- Draw line numbers\
  2070.    term.setCursorPos( w - string.len( \"Ln \"..y ) + 1, h )\
  2071.    term.setTextColour( highlightColour )\
  2072.    term.write( \"Ln \" )\
  2073.    term.setTextColour( textColour )\
  2074.    term.write( y )\
  2075. \
  2076.    term.setCursorPos( 1, h )\
  2077.     if bMenu then\
  2078.        -- Draw menu\
  2079.         term.setTextColour( textColour )\
  2080.         for nItem,sItem in pairs( tMenuItems ) do\
  2081.             if nItem == nMenuItem then\
  2082.                 term.setTextColour( highlightColour )\
  2083.                 term.write( \"[\" )\
  2084.                 term.setTextColour( textColour )\
  2085.                 term.write( sItem )\
  2086.                 term.setTextColour( highlightColour )\
  2087.                 term.write( \"]\" )\
  2088.                 term.setTextColour( textColour )\
  2089.             else\
  2090.                 term.write( \" \"..sItem..\" \" )\
  2091.             end\
  2092.         end\
  2093.    else\
  2094.        -- Draw status\
  2095.        term.setTextColour( highlightColour )\
  2096.        term.write( sStatus )\
  2097.        term.setTextColour( textColour )\
  2098.    end\
  2099. \
  2100.     -- Reset cursor\
  2101.     term.setCursorPos( x - scrollX, y - scrollY )\
  2102. end\
  2103. \
  2104. local tMenuFuncs = { \
  2105.     Save=function()\
  2106.         if bReadOnly then\
  2107.             sStatus = \"Access denied\"\
  2108.         else\
  2109.             local ok, err = save( sPath )\
  2110.             if ok then\
  2111.                 sStatus=\"Saved to \"..sPath\
  2112.             else\
  2113.                 sStatus=\"Error saving to \"..sPath\
  2114.             end\
  2115.         end\
  2116.         redrawMenu()\
  2117.     end,\
  2118.     Print=function()\
  2119.         local printer = peripheral.find( \"printer\" )\
  2120.         if not printer then\
  2121.             sStatus = \"No printer attached\"\
  2122.             return\
  2123.         end\
  2124. \
  2125.         local nPage = 0\
  2126.         local sName = fs.getName( sPath )\
  2127.         if printer.getInkLevel() < 1 then\
  2128.             sStatus = \"Printer out of ink\"\
  2129.             return\
  2130.         elseif printer.getPaperLevel() < 1 then\
  2131.             sStatus = \"Printer out of paper\"\
  2132.             return\
  2133.         end\
  2134. \
  2135.         local screenTerminal = term.current()\
  2136.         local printerTerminal = {\
  2137.             getCursorPos = printer.getCursorPos,\
  2138.             setCursorPos = printer.setCursorPos,\
  2139.             getSize = printer.getPageSize,\
  2140.             write = printer.write,\
  2141.         }\
  2142.         printerTerminal.scroll = function()\
  2143.             if nPage == 1 then\
  2144.                 printer.setPageTitle( sName..\" (page \"..nPage..\")\" )            \
  2145.             end\
  2146.             \
  2147.             while not printer.newPage() do\
  2148.                 if printer.getInkLevel() < 1 then\
  2149.                     sStatus = \"Printer out of ink, please refill\"\
  2150.                 elseif printer.getPaperLevel() < 1 then\
  2151.                     sStatus = \"Printer out of paper, please refill\"\
  2152.                 else\
  2153.                     sStatus = \"Printer output tray full, please empty\"\
  2154.                 end\
  2155.     \
  2156.                 term.redirect( screenTerminal )\
  2157.                 redrawMenu()\
  2158.                 term.redirect( printerTerminal )\
  2159.                 \
  2160.                 local timer = os.startTimer(0.5)\
  2161.                 sleep(0.5)\
  2162.             end\
  2163. \
  2164.             nPage = nPage + 1\
  2165.             if nPage == 1 then\
  2166.                 printer.setPageTitle( sName )\
  2167.             else\
  2168.                 printer.setPageTitle( sName..\" (page \"..nPage..\")\" )\
  2169.             end\
  2170.         end\
  2171.         \
  2172.         bMenu = false\
  2173.         term.redirect( printerTerminal )\
  2174.         local ok, error = pcall( function()\
  2175.             term.scroll()\
  2176.             for n, sLine in ipairs( tLines ) do\
  2177.                 print( sLine )\
  2178.             end\
  2179.         end )\
  2180.        term.redirect( screenTerminal )\
  2181.         if not ok then\
  2182.             print( error )\
  2183.         end\
  2184.         \
  2185.         while not printer.endPage() do\
  2186.             sStatus = \"Printer output tray full, please empty\"\
  2187.             redrawMenu()\
  2188.             sleep( 0.5 )\
  2189.         end\
  2190.         bMenu = true\
  2191.             \
  2192.         if nPage > 1 then\
  2193.             sStatus = \"Printed \"..nPage..\" Pages\"\
  2194.         else\
  2195.             sStatus = \"Printed 1 Page\"\
  2196.         end\
  2197.         redrawMenu()\
  2198.     end,\
  2199.     Exit=function()\
  2200.         bRunning = false\
  2201.     end\
  2202. }\
  2203. \
  2204. local function doMenuItem( _n )\
  2205.     tMenuFuncs[tMenuItems[_n]]()\
  2206.     if bMenu then\
  2207.         bMenu = false\
  2208.         term.setCursorBlink( true )\
  2209.     end\
  2210.     redrawMenu()\
  2211. end\
  2212. \
  2213. local function setCursor( x, y )\
  2214.     local screenX = x - scrollX\
  2215.     local screenY = y - scrollY\
  2216.     \
  2217.     local bRedraw = false\
  2218.     if screenX < 1 then\
  2219.         scrollX = x - 1\
  2220.         screenX = 1\
  2221.         bRedraw = true\
  2222.     elseif screenX > w then\
  2223.         scrollX = x - w\
  2224.         screenX = w\
  2225.         bRedraw = true\
  2226.     end\
  2227.     \
  2228.     if screenY < 1 then\
  2229.         scrollY = y - 1\
  2230.         screenY = 1\
  2231.         bRedraw = true\
  2232.     elseif screenY > h-1 then\
  2233.         scrollY = y - (h-1)\
  2234.         screenY = h-1\
  2235.         bRedraw = true\
  2236.     end\
  2237.     \
  2238.     if bRedraw then\
  2239.         redrawText()\
  2240.     end\
  2241.     term.setCursorPos( screenX, screenY )\
  2242.     \
  2243.     -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.\
  2244.     redrawMenu()\
  2245. end\
  2246. \
  2247. -- Actual program functionality begins\
  2248. load(sPath)\
  2249. \
  2250. term.setBackgroundColour( bgColour )\
  2251. term.clear()\
  2252. term.setCursorPos(x,y)\
  2253. term.setCursorBlink( true )\
  2254. \
  2255. redrawText()\
  2256. redrawMenu()\
  2257. \
  2258. -- Handle input\
  2259. while bRunning do\
  2260.     local sEvent, param, param2, param3 = os.pullEvent()\
  2261.     if sEvent == \"key\" then\
  2262.         if param == keys.up then\
  2263.             -- Up\
  2264.             if not bMenu then\
  2265.                 if y > 1 then\
  2266.                     -- Move cursor up\
  2267.                     y = y - 1\
  2268.                     x = math.min( x, string.len( tLines[y] ) + 1 )\
  2269.                     setCursor( x, y )\
  2270.                 end\
  2271.             end\
  2272.         elseif param == keys.down then\
  2273.             -- Down\
  2274.             if not bMenu then\
  2275.                 -- Move cursor down\
  2276.                 if y < #tLines then\
  2277.                     y = y + 1\
  2278.                     x = math.min( x, string.len( tLines[y] ) + 1 )\
  2279.                     setCursor( x, y )\
  2280.                 end\
  2281.             end\
  2282.         elseif param == keys.tab then\
  2283.             -- Tab\
  2284.             if not bMenu and not bReadOnly then\
  2285.                 -- Indent line\
  2286.                 tLines[y]=\"  \"..tLines[y]\
  2287.                 x = x + 2\
  2288.                 setCursor( x, y )\
  2289.                 redrawLine(y)\
  2290.             end\
  2291.         elseif param == keys.pageUp then\
  2292.             -- Page Up\
  2293.             if not bMenu then\
  2294.                 -- Move up a page\
  2295.                 if y - (h - 1) >= 1 then\
  2296.                     y = y - (h - 1)\
  2297.                 else\
  2298.                     y = 1\
  2299.                 end\
  2300.                 x = math.min( x, string.len( tLines[y] ) + 1 )\
  2301.                 setCursor( x, y )\
  2302.             end\
  2303.         elseif param == keys.pageDown then\
  2304.             -- Page Down\
  2305.             if not bMenu then\
  2306.                 -- Move down a page\
  2307.                 if y + (h - 1) <= #tLines then\
  2308.                     y = y + (h - 1)\
  2309.                 else\
  2310.                     y = #tLines\
  2311.                 end\
  2312.                 x = math.min( x, string.len( tLines[y] ) + 1 )\
  2313.                 setCursor( x, y )\
  2314.             end\
  2315.         elseif param == keys.home then\
  2316.             -- Home\
  2317.             if not bMenu then\
  2318.                 -- Move cursor to the beginning\
  2319.                 x=1\
  2320.                 setCursor(x,y)\
  2321.             end\
  2322.         elseif param == keys[\"end\"] then\
  2323.             -- End\
  2324.             if not bMenu then\
  2325.                 -- Move cursor to the end\
  2326.                 x = string.len( tLines[y] ) + 1\
  2327.                 setCursor(x,y)\
  2328.             end\
  2329.         elseif param == keys.left then\
  2330.             -- Left\
  2331.             if not bMenu then\
  2332.                 if x > 1 then\
  2333.                     -- Move cursor left\
  2334.                     x = x - 1\
  2335.                 elseif x==1 and y>1 then\
  2336.                     x = string.len( tLines[y-1] ) + 1\
  2337.                     y = y - 1\
  2338.                 end\
  2339.                 setCursor( x, y )\
  2340.             else\
  2341.                 -- Move menu left\
  2342.                 nMenuItem = nMenuItem - 1\
  2343.                 if nMenuItem < 1 then\
  2344.                     nMenuItem = #tMenuItems\
  2345.                 end\
  2346.                 redrawMenu()\
  2347.             end\
  2348.         elseif param == keys.right then\
  2349.             -- Right\
  2350.             if not bMenu then\
  2351.                 if x < string.len( tLines[y] ) + 1 then\
  2352.                     -- Move cursor right\
  2353.                     x = x + 1\
  2354.                 elseif x==string.len( tLines[y] ) + 1 and y<#tLines then\
  2355.                     x = 1\
  2356.                     y = y + 1\
  2357.                 end\
  2358.                 setCursor( x, y )\
  2359.             else\
  2360.                 -- Move menu right\
  2361.                 nMenuItem = nMenuItem + 1\
  2362.                 if nMenuItem > #tMenuItems then\
  2363.                     nMenuItem = 1\
  2364.                 end\
  2365.                 redrawMenu()\
  2366.             end\
  2367.         elseif param == keys.delete then\
  2368.             -- Delete\
  2369.             if not bMenu and not bReadOnly then\
  2370.                 if  x < string.len( tLines[y] ) + 1 then\
  2371.                     local sLine = tLines[y]\
  2372.                     tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)\
  2373.                     redrawLine(y)\
  2374.                 elseif y<#tLines then\
  2375.                     tLines[y] = tLines[y] .. tLines[y+1]\
  2376.                     table.remove( tLines, y+1 )\
  2377.                     redrawText()\
  2378.                     redrawMenu()\
  2379.                 end\
  2380.             end\
  2381.         elseif param == keys.backspace then\
  2382.             -- Backspace\
  2383.             if not bMenu and not bReadOnly then\
  2384.                 if x > 1 then\
  2385.                     -- Remove character\
  2386.                     local sLine = tLines[y]\
  2387.                     tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)\
  2388.                     redrawLine(y)\
  2389.             \
  2390.                     x = x - 1\
  2391.                     setCursor( x, y )\
  2392.                 elseif y > 1 then\
  2393.                     -- Remove newline\
  2394.                     local sPrevLen = string.len( tLines[y-1] )\
  2395.                     tLines[y-1] = tLines[y-1] .. tLines[y]\
  2396.                     table.remove( tLines, y )\
  2397.                     redrawText()\
  2398.                 \
  2399.                     x = sPrevLen + 1\
  2400.                     y = y - 1\
  2401.                     setCursor( x, y )\
  2402.                 end\
  2403.             end\
  2404.         elseif param == keys.enter then\
  2405.             -- Enter\
  2406.             if not bMenu and not bReadOnly then\
  2407.                 -- Newline\
  2408.                 local sLine = tLines[y]\
  2409.                 local _,spaces=string.find(sLine,\"^[ ]+\")\
  2410.                 if not spaces then\
  2411.                     spaces=0\
  2412.                 end\
  2413.                 tLines[y] = string.sub(sLine,1,x-1)\
  2414.                 table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )\
  2415.                 redrawText()\
  2416.             \
  2417.                 x = spaces+1\
  2418.                 y = y + 1\
  2419.                 setCursor( x, y )\
  2420.             elseif bMenu then\
  2421.                 -- Menu selection\
  2422.                 doMenuItem( nMenuItem )\
  2423.             end\
  2424.         elseif param == keys.leftCtrl or param == keys.rightCtrl then\
  2425.             -- Menu toggle\
  2426.             bMenu = not bMenu\
  2427.             if bMenu then\
  2428.                 term.setCursorBlink( false )\
  2429.             else\
  2430.                 term.setCursorBlink( true )\
  2431.             end\
  2432.             redrawMenu()\
  2433.         end\
  2434.         \
  2435.     elseif sEvent == \"char\" then\
  2436.         if not bMenu and not bReadOnly then\
  2437.             -- Input text\
  2438.             local sLine = tLines[y]\
  2439.             tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\
  2440.             redrawLine(y)\
  2441.         \
  2442.             x = x + 1\
  2443.             setCursor( x, y )\
  2444.         elseif bMenu then\
  2445.             -- Select menu items\
  2446.             for n,sMenuItem in ipairs( tMenuItems ) do\
  2447.                 if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then\
  2448.                     doMenuItem( n )\
  2449.                     break\
  2450.                 end\
  2451.             end\
  2452.         end\
  2453. \
  2454.     elseif sEvent == \"paste\" then\
  2455.         if not bMenu and not bReadOnly then\
  2456.             -- Input text\
  2457.             local sLine = tLines[y]\
  2458.             tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\
  2459.             redrawLine(y)\
  2460. \
  2461.             x = x + string.len( param )\
  2462.             setCursor( x, y )\
  2463.         end\
  2464.         \
  2465.     elseif sEvent == \"mouse_click\" then\
  2466.         if not bMenu then\
  2467.             if param == 1 then\
  2468.                 -- Left click\
  2469.                 local cx,cy = param2, param3\
  2470.                 if cy < h then\
  2471.                     y = math.min( math.max( scrollY + cy, 1 ), #tLines )\
  2472.                     x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 )\
  2473.                     setCursor( x, y )\
  2474.                 end\
  2475.             end\
  2476.         end\
  2477.         \
  2478.     elseif sEvent == \"mouse_scroll\" then\
  2479.         if not bMenu then\
  2480.             if param == -1 then\
  2481.                 -- Scroll up\
  2482.                 if scrollY > 0 then\
  2483.                     -- Move cursor up\
  2484.                     scrollY = scrollY - 1\
  2485.                     redrawText()\
  2486.                 end\
  2487.             \
  2488.             elseif param == 1 then\
  2489.                 -- Scroll down\
  2490.                 local nMaxScroll = #tLines - (h-1)\
  2491.                 if scrollY < nMaxScroll then\
  2492.                     -- Move cursor down\
  2493.                     scrollY = scrollY + 1\
  2494.                     redrawText()\
  2495.                 end\
  2496.                 \
  2497.             end\
  2498.         end\
  2499. \
  2500.     elseif sEvent == \"term_resize\" then\
  2501.         w,h = term.getSize()\
  2502.        setCursor( x, y )\
  2503.        redrawMenu()\
  2504.        redrawText()\
  2505. \
  2506.     end\
  2507. end\
  2508. \
  2509. -- Cleanup\
  2510. term.clear()\
  2511. term.setCursorBlink( false )\
  2512. term.setCursorPos( 1, 1 )",
  2513.       meh = "such much",
  2514.       wow = "hi",
  2515.       startup = "",
  2516.       p = "d",
  2517.       [ "permission.data" ] = "userTest",
  2518.       [ "Edit.ico" ] = "error('This is an image, not a program!')\
  2519. {\
  2520.  {\
  2521.    {\
  2522.      2048,\
  2523.      \"-\",\
  2524.      1,\
  2525.    },\
  2526.    {\
  2527.      2048,\
  2528.      \"-\",\
  2529.      1,\
  2530.    },\
  2531.    {\
  2532.      2048,\
  2533.      \"-\",\
  2534.      1,\
  2535.    },\
  2536.  },\
  2537.  {\
  2538.    {\
  2539.      2048,\
  2540.      \"-\",\
  2541.      1,\
  2542.    },\
  2543.    {\
  2544.      2048,\
  2545.      \"-\",\
  2546.      1,\
  2547.    },\
  2548.    {\
  2549.      2048,\
  2550.      \"-\",\
  2551.      1,\
  2552.    },\
  2553.  },\
  2554.  {\
  2555.    {\
  2556.      2048,\
  2557.      \"-\",\
  2558.      1,\
  2559.    },\
  2560.    {\
  2561.      2048,\
  2562.      \"-\",\
  2563.      1,\
  2564.    },\
  2565.    {\
  2566.      2048,\
  2567.      \"-\",\
  2568.      1,\
  2569.    },\
  2570.  },\
  2571.  [ 0 ] = {\
  2572.    {\
  2573.      128,\
  2574.      \"|\",\
  2575.      1,\
  2576.    },\
  2577.    {\
  2578.      128,\
  2579.      \"|\",\
  2580.      1,\
  2581.    },\
  2582.    {\
  2583.      128,\
  2584.      \"|\",\
  2585.      1,\
  2586.    },\
  2587.  },\
  2588. }",
  2589.       h = "",
  2590.       here = "hi",
  2591.       OmniOS = {
  2592.         Data = {
  2593.           here = "hi",
  2594.         },
  2595.       },
  2596.     },
  2597.     Desktop = {
  2598.       disk = {},
  2599.       [ "permission.data" ] = "userTest",
  2600.       [ "Main.luaBlah.lua" ] = "--[[\
  2601.     Desktop in ComputerCraft\
  2602.     by Creator\
  2603.     for OmniOS\
  2604. ]]--\
  2605. --Variables--\
  2606. local textutilsserialize = textutils.serialize\
  2607. local textutilsunserialize = textutils.unserialize\
  2608. local w,h = term.getSize()\
  2609. local Settings = {}\
  2610. local result = {}\
  2611. local Main = {}\
  2612. local QuickSettings = {}\
  2613. local MatchingColors = {}\
  2614. local gui = {}\
  2615. local mainLayout = {}\
  2616. local quickSettingsLayout = {}\
  2617. local mainLayoutTable = {}\
  2618. local quickSettingsLayoutTable = {}\
  2619. local paths = {}\
  2620. local scroll = 0\
  2621. local programPath = \"OmniOS/Programs/Desktop.app/Data/\"\
  2622. \
  2623. --Functions--\
  2624. local function readFile(_path)\
  2625.     local file = fs.open(_path,\"r\")\
  2626.     local data = file.readAll()\
  2627.     file.close()\
  2628.     return data\
  2629. end\
  2630. \
  2631. local function split(str,sep)\
  2632.     local buffer = {}\
  2633.     for token in str:gmatch(sep) do\
  2634.         buffer[#buffer+1] = token\
  2635.     end\
  2636.     return buffer\
  2637. end\
  2638. \
  2639. local function loadShortcuts()\
  2640.     local buffer = readFile(programPath..\"Shortcuts\")\
  2641.     local sBuffer = textutilsunserialize(buffer)\
  2642.     local nBuffer = {}\
  2643.     paths = {}\
  2644.     for i,v in pairs(sBuffer) do\
  2645.         nBuffer[v.name] = {\
  2646.             xPos = 2+(6*(v.xPos-1)),\
  2647.             yPos = 1+(5*(v.yPos-1)),\
  2648.             name = v.name,\
  2649.             path = v.path..\".ico\",\
  2650.             yLength = 4,\
  2651.             xLength = 3,\
  2652.             returnValue = v.name,\
  2653.             label = string.sub(v.name,1,5),\
  2654.             labelFg = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  2655.             labelBg = Settings.bgColor,\
  2656.             moveY = true,\
  2657.         }\
  2658.         paths[v.name] = v.path\
  2659.     end\
  2660.     Main.BetterPaint = nBuffer\
  2661. end\
  2662. \
  2663. local function loadObjects()\
  2664. --Object table--\
  2665.     Main.Button = {\
  2666.         quickSettings = {\
  2667.             name = \"quickSettings\",\
  2668.             label = \"^\",\
  2669.             xPos = 1,\
  2670.             yPos = h,\
  2671.             xLength = 1,\
  2672.             yLength = 1,\
  2673.             xTextPos = 1,\
  2674.             yTextPos = 1,\
  2675.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  2676.             bgColor = Settings.bgColor,\
  2677.             returnValue = \"quickSettings\",\
  2678.         },\
  2679.         windowPlus = {\
  2680.             name = \"windowPlus\",\
  2681.             label = \">\",\
  2682.             xPos = w,\
  2683.             yPos = 1,\
  2684.             xLength = 1,\
  2685.             yLength = 1,\
  2686.             xTextPos = 1,\
  2687.             yTextPos = 1,\
  2688.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  2689.             bgColor = Settings.bgColor,\
  2690.             returnValue = \"windowPlus\",\
  2691.         },\
  2692.         windowMinus = {\
  2693.             name = \"windowMinus\",\
  2694.             label = \"<\",\
  2695.             xPos = 1,\
  2696.             yPos = 1,\
  2697.             xLength = 1,\
  2698.             yLength = 1,\
  2699.             xTextPos = 1,\
  2700.             yTextPos = 1,\
  2701.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  2702.             bgColor = Settings.bgColor,\
  2703.             returnValue = \"windowMinus\",\
  2704.         },\
  2705.     }\
  2706.     QuickSettings.Button = {\
  2707.         Right = {\
  2708.             name = \"Right\",\
  2709.             label = \">\",\
  2710.             xPos = w-1,\
  2711.             yPos = 5,\
  2712.             xLength = 1,\
  2713.             yLength = 1,\
  2714.             xTextPos = 1,\
  2715.             yTextPos = 1,\
  2716.             fgColor = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  2717.             bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  2718.             returnValue = \"Right\",\
  2719.         },\
  2720.         Left = {\
  2721.             name = \"Left\",\
  2722.             label = \"<\",\
  2723.             xPos = 2,\
  2724.             yPos = 5,\
  2725.             xLength = 1,\
  2726.             yLength = 1,\
  2727.             xTextPos = 1,\
  2728.             yTextPos = 1,\
  2729.             fgColor = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  2730.             bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  2731.             returnValue = \"Left\",\
  2732.         },\
  2733.         Green = {\
  2734.             name = \"Green\",\
  2735.             label = \" \",\
  2736.             xPos = 31,\
  2737.             yPos = 6,\
  2738.             xLength = 1,\
  2739.             yLength = 1,\
  2740.             xTextPos = 1,\
  2741.             yTextPos = 1,\
  2742.             fgColor = 1,\
  2743.             bgColor = colors.green,\
  2744.             returnValue = \"color:green\",\
  2745.         },\
  2746.         Lime = {\
  2747.             name = \"Lime\",\
  2748.             label = \" \",\
  2749.             xPos = 31,\
  2750.             yPos = 7,\
  2751.             xLength = 1,\
  2752.             yLength = 1,\
  2753.             xTextPos = 1,\
  2754.             yTextPos = 1,\
  2755.             fgColor = 1,\
  2756.             bgColor = colors.lime,\
  2757.             returnValue = \"color:lime\",\
  2758.         },\
  2759.         Brown = {\
  2760.             name = \"Brown\",\
  2761.             label = \" \",\
  2762.             xPos = 32,\
  2763.             yPos = 6,\
  2764.             xLength = 1,\
  2765.             yLength = 1,\
  2766.             xTextPos = 1,\
  2767.             yTextPos = 1,\
  2768.             fgColor = 1,\
  2769.             bgColor = colors.brown,\
  2770.             returnValue = \"color:brown\",\
  2771.         },\
  2772.         Purple = {\
  2773.             name = \"Purple\",\
  2774.             label = \" \",\
  2775.             xPos = 32,\
  2776.             yPos = 7,\
  2777.             xLength = 1,\
  2778.             yLength = 1,\
  2779.             xTextPos = 1,\
  2780.             yTextPos = 1,\
  2781.             fgColor = 1,\
  2782.             bgColor = colors.purple,\
  2783.             returnValue = \"color:purple\",\
  2784.         },\
  2785.         Blue = {\
  2786.             name = \"Blue\",\
  2787.             label = \" \",\
  2788.             xPos = 33,\
  2789.             yPos = 6,\
  2790.             xLength = 1,\
  2791.             yLength = 1,\
  2792.             xTextPos = 1,\
  2793.             yTextPos = 1,\
  2794.             fgColor = 1,\
  2795.             bgColor = colors.blue,\
  2796.             returnValue = \"color:blue\",\
  2797.         },\
  2798.         lightBlue = {\
  2799.             name = \"lightBlue\",\
  2800.             label = \" \",\
  2801.             xPos = 33,\
  2802.             yPos = 7,\
  2803.             xLength = 1,\
  2804.             yLength = 1,\
  2805.             xTextPos = 1,\
  2806.             yTextPos = 1,\
  2807.             fgColor = 1,\
  2808.             bgColor = colors.lightBlue,\
  2809.             returnValue = \"color:lightBlue\",\
  2810.         },\
  2811.         Yellow = {\
  2812.             name = \"Yellow\",\
  2813.             label = \" \",\
  2814.             xPos = 34,\
  2815.             yPos = 6,\
  2816.             xLength = 1,\
  2817.             yLength = 1,\
  2818.             xTextPos = 1,\
  2819.             yTextPos = 1,\
  2820.             fgColor = 1,\
  2821.             bgColor = colors.yellow,\
  2822.             returnValue = \"color:yellow\",\
  2823.         },\
  2824.         Cyan = {\
  2825.             name = \"Cyan\",\
  2826.             label = \" \",\
  2827.             xPos = 34,\
  2828.             yPos = 7,\
  2829.             xLength = 1,\
  2830.             yLength = 1,\
  2831.             xTextPos = 1,\
  2832.             yTextPos = 1,\
  2833.             fgColor = 1,\
  2834.             bgColor = colors.cyan,\
  2835.             returnValue = \"color:cyan\",\
  2836.         },\
  2837.         Orange = {\
  2838.             name = \"Orange\",\
  2839.             label = \" \",\
  2840.             xPos = 35,\
  2841.             yPos = 6,\
  2842.             xLength = 1,\
  2843.             yLength = 1,\
  2844.             xTextPos = 1,\
  2845.             yTextPos = 1,\
  2846.             fgColor = 1,\
  2847.             bgColor = colors.orange,\
  2848.             returnValue = \"color:orange\",\
  2849.         },\
  2850.         Pink = {\
  2851.             name = \"Pink\",\
  2852.             label = \" \",\
  2853.             xPos = 35,\
  2854.             yPos = 7,\
  2855.             xLength = 1,\
  2856.             yLength = 1,\
  2857.             xTextPos = 1,\
  2858.             yTextPos = 1,\
  2859.             fgColor = 1,\
  2860.             bgColor = colors.pink,\
  2861.             returnValue = \"color:pink\",\
  2862.         },\
  2863.         Red = {\
  2864.             name = \"Red\",\
  2865.             label = \" \",\
  2866.             xPos = 36,\
  2867.             yPos = 6,\
  2868.             xLength = 1,\
  2869.             yLength = 1,\
  2870.             xTextPos = 1,\
  2871.             yTextPos = 1,\
  2872.             fgColor = 1,\
  2873.             bgColor = colors.red,\
  2874.             returnValue = \"color:red\",\
  2875.         },\
  2876.         Magenta = {\
  2877.             name = \"Magenta\",\
  2878.             label = \" \",\
  2879.             xPos = 36,\
  2880.             yPos = 7,\
  2881.             xLength = 1,\
  2882.             yLength = 1,\
  2883.             xTextPos = 1,\
  2884.             yTextPos = 1,\
  2885.             fgColor = 1,\
  2886.             bgColor = colors.magenta,\
  2887.             returnValue = \"color:magenta\",\
  2888.         },\
  2889.         White = {\
  2890.             name = \"White\",\
  2891.             label = \" \",\
  2892.             xPos = 37,\
  2893.             yPos = 6,\
  2894.             xLength = 1,\
  2895.             yLength = 1,\
  2896.             xTextPos = 1,\
  2897.             yTextPos = 1,\
  2898.             fgColor = 1,\
  2899.             bgColor = colors.white,\
  2900.             returnValue = \"color:white\",\
  2901.         },\
  2902.         lightGray = {\
  2903.             name = \"lightGray\",\
  2904.             label = \" \",\
  2905.             xPos = 37,\
  2906.             yPos = 7,\
  2907.             xLength = 1,\
  2908.             yLength = 1,\
  2909.             xTextPos = 1,\
  2910.             yTextPos = 1,\
  2911.             fgColor = 1,\
  2912.             bgColor = colors.lightGray,\
  2913.             returnValue = \"color:lightGray\",\
  2914.         },\
  2915.         Black = {\
  2916.             name = \"Black\",\
  2917.             label = \" \",\
  2918.             xPos = 38,\
  2919.             yPos = 6,\
  2920.             xLength = 1,\
  2921.             yLength = 1,\
  2922.             xTextPos = 1,\
  2923.             yTextPos = 1,\
  2924.             fgColor = 1,\
  2925.             bgColor = colors.black,\
  2926.             returnValue = \"color:black\",\
  2927.         },\
  2928.         Gray = {\
  2929.             name = \"Gray\",\
  2930.             label = \" \",\
  2931.             xPos = 38,\
  2932.             yPos = 7,\
  2933.             xLength = 1,\
  2934.             yLength = 1,\
  2935.             xTextPos = 1,\
  2936.             yTextPos = 1,\
  2937.             fgColor = 1,\
  2938.             bgColor = colors.gray,\
  2939.             returnValue = \"color:gray\",\
  2940.         },\
  2941.         RefreshColor = {\
  2942.             name = \"RefreshColor\",\
  2943.             label = \"Refresh\",\
  2944.             xPos = 40,\
  2945.             yPos = 3,\
  2946.             xLength = 9,\
  2947.             yLength = 5,\
  2948.             xTextPos = 2,\
  2949.             yTextPos = 3,\
  2950.             fgColor = 1,\
  2951.             bgColor = colors.gray,\
  2952.             returnValue = \"Refresh\",\
  2953.         },\
  2954.     }\
  2955. \
  2956.     QuickSettings.BetterPaint = {\
  2957.         Restart = {\
  2958.             xPos = 4,\
  2959.             yPos = 2,\
  2960.             name = \"Restart\",\
  2961.             path = programPath..\"QuickSettings/restart.ico\",\
  2962.             yLength = 6,\
  2963.             xLength = 7,\
  2964.             returnValue = \"reboot\",\
  2965.             label = \"Restart\",\
  2966.             labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  2967.             labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  2968.         },\
  2969.         Shutdown = {\
  2970.             xPos = 22,\
  2971.             yPos = 2,\
  2972.             name = \"Shutdown\",\
  2973.             path = programPath..\"QuickSettings/shutdown.ico\",\
  2974.             yLength = 6,\
  2975.             xLength = 7,\
  2976.             returnValue = \"shutdown\",\
  2977.             label = \"Shutdown\",\
  2978.             labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  2979.             labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  2980.         },\
  2981.         Settings = {\
  2982.             xPos = 13,\
  2983.             yPos = 2,\
  2984.             name = \"Settings\",\
  2985.             path = programPath..\"QuickSettings/settings.ico\",\
  2986.             yLength = 6,\
  2987.             xLength = 7,\
  2988.             returnValue = \"settings\",\
  2989.             label = \"Settings\",\
  2990.             labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  2991.             labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  2992.         },\
  2993.     }\
  2994. \
  2995.     QuickSettings.Text = {\
  2996.         Label = {\
  2997.             name = \"Label\",\
  2998.             text = \"QuickSettings\",\
  2999.             xPos = w/2-6,\
  3000.             yPos = 1,\
  3001.             bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  3002.             fgColor = Settings.bgColor,\
  3003.         },\
  3004.     }\
  3005.     QuickSettings.Key = {\
  3006.         R = {\
  3007.             name = \"R\",\
  3008.             key = \"r\",\
  3009.             onPress = function() os.reboot() end,\
  3010.         },\
  3011.         S = {\
  3012.             name = \"S\",\
  3013.             key = \"s\",\
  3014.             onPress = function() os.shutdown() end,\
  3015.         },\
  3016.         LeftAlt = {\
  3017.             name = \"LeftAlt\",\
  3018.             key = \"LeftAlt\",\
  3019.             onPress = function() System.newTask(\"Settings\",\"Settings\") end,\
  3020.         },\
  3021.     }\
  3022.     loadShortcuts()\
  3023. \
  3024. end\
  3025. \
  3026. local function loadGUI()\
  3027.     --Initializing GUI components\
  3028.     gui = Interact:Initialize()\
  3029.     mainLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})\
  3030.     quickSettingsLayout = gui.Layout.new({xPos = 1,yPos = h-7, xLength = w,yLength = 7})\
  3031.     mainLayoutTable = {}\
  3032.     quickSettingsLayoutTable = {}\
  3033. end\
  3034. \
  3035. local function InitializeGUI()\
  3036.     loadObjects()\
  3037.     --Main--\
  3038.     mainLayoutTable = {}\
  3039.     mainLayoutTable = gui.loadObjects(Main)\
  3040.     mainLayoutTable.mainBgColor = gui.BackgroundColor.new({color = Settings.bgColor})\
  3041.     \
  3042.     --QuickSettings--\
  3043.     quickSettingsLayoutTable = {}\
  3044.     quickSettingsLayoutTable.Text = {}\
  3045.     quickSettingsLayoutTable = gui.loadObjects(QuickSettings)\
  3046.     quickSettingsLayoutTable.quickSettingsBgColor = gui.BackgroundColor.new({color = MatchingColors[Settings.bgColor][\"quickSettings\"]})\
  3047.     \
  3048.     --Initializing structures--\
  3049.     --Main--\
  3050.     for i,v in pairs(mainLayoutTable.Button) do\
  3051.         mainLayout:addButton(mainLayoutTable.Button[i]:returnData())\
  3052.     end\
  3053.     for i,v in pairs(mainLayoutTable.BetterPaint) do\
  3054.         mainLayout:addBetterPaint(mainLayoutTable.BetterPaint[i]:returnData())\
  3055.     end\
  3056.     mainLayout:addBackgroundColor(mainLayoutTable.mainBgColor:returnData())\
  3057.     \
  3058.     --QuickSettings--\
  3059.     for i,v in pairs(quickSettingsLayoutTable.Button) do\
  3060.         quickSettingsLayout:addButton(quickSettingsLayoutTable.Button[i]:returnData())\
  3061.     end\
  3062.     quickSettingsLayout:addBackgroundColor(quickSettingsLayoutTable.quickSettingsBgColor:returnData())\
  3063.     quickSettingsLayout:addBetterPaint(quickSettingsLayoutTable.BetterPaint.Restart)\
  3064.     quickSettingsLayout:addBetterPaint(quickSettingsLayoutTable.BetterPaint.Shutdown)\
  3065.     quickSettingsLayout:addBetterPaint(quickSettingsLayoutTable.BetterPaint.Settings)\
  3066.     quickSettingsLayout:addKey(quickSettingsLayoutTable.Key.R:returnData())\
  3067.     quickSettingsLayout:addKey(quickSettingsLayoutTable.Key.S:returnData())\
  3068.     quickSettingsLayout:addKey(quickSettingsLayoutTable.Key.LeftAlt:returnData())\
  3069. end\
  3070. \
  3071. local function changeColor(color)\
  3072.     Settings.bgColor = colors[color] or colors.green\
  3073.     local f = fs.open(programPath..\"Settings\",\"w\")\
  3074.     f.write(textutilsserialize(Settings))\
  3075.     f.close()\
  3076.     local buffer = readFile(programPath..\"Settings\")\
  3077.     Settings = textutils.unserialize( buffer )\
  3078.     local buffer = readFile(programPath..\"MatchingColors\")\
  3079.     MatchingColors = textutilsunserialize(buffer)\
  3080.     loadObjects()\
  3081.     InitializeGUI()\
  3082. end\
  3083. \
  3084. --Loading settings--\
  3085. local buffer = readFile(programPath..\"Settings\")\
  3086. Settings = textutils.unserialize( buffer )\
  3087. \
  3088. local buffer = readFile(programPath..\"MatchingColors\")\
  3089. MatchingColors = textutilsunserialize(buffer)\
  3090. \
  3091. \
  3092. \
  3093. loadObjects()\
  3094. loadGUI()\
  3095. InitializeGUI()\
  3096. \
  3097. \
  3098. --Code--\
  3099. while true do\
  3100.     mainLayout:draw(0,scroll)\
  3101.     local result = gui.eventHandler(mainLayout)\
  3102.     if result[1] == \"Button\" then\
  3103.         if result[2] == \"quickSettings\" then\
  3104.             quickSettingsLayout:draw()\
  3105.             local notClose = true\
  3106.             while notClose do\
  3107.                 local answer = gui.eventHandler(quickSettingsLayout)\
  3108.                 if answer[1] == \"Button\" then\
  3109.                     if answer[2] == \"reboot\" then\
  3110.                         os.reboot()\
  3111.                     elseif answer[2] == \"shutdown\" then\
  3112.                         os.shutdown()\
  3113.                     elseif answer[2] == \"Close\" then\
  3114.                         notClose = false\
  3115.                     elseif answer[2] == \"settings\" then\
  3116.                         System.newTask(\"Settings\",\"Settings\")\
  3117.                         notClose = false\
  3118.                     elseif answer[2] == \"Refresh\" then\
  3119.                         local buffer = readFile(programPath..\"Settings\")\
  3120.                         Settings = textutils.unserialize( buffer )\
  3121.                         local buffer = readFile(programPath..\"MatchingColors\")\
  3122.                         MatchingColors = textutilsunserialize(buffer)\
  3123.                         loadObjects()\
  3124.                         InitializeGUI()\
  3125.                         notClose = false\
  3126.                     else\
  3127.                         local buffer = split(answer[2],\"[^:]+\")\
  3128.                         changeColor(buffer[2])\
  3129.                         notClose = false\
  3130.                     end\
  3131.                 elseif answer[1] == \"Nil\" then\
  3132.                     if answer[2] == \"Nil\" then\
  3133.                         notClose = false\
  3134.                     end\
  3135.                 end\
  3136.             end\
  3137.         elseif result[2] == \"windowPlus\" then\
  3138.             scroll = scroll - 51\
  3139.         elseif result[2] == \"windowMinus\" then\
  3140.             scroll = scroll + 51\
  3141.         else\
  3142.             System.newTask(result[2],result[2])\
  3143.         end\
  3144.     end\
  3145. end",
  3146.       [ "Main.lua" ] = "--[[\
  3147.     Desktop in ComputerCraft\
  3148.     by Creator\
  3149.     for OmniOS\
  3150. ]]--\
  3151. --Variables--\
  3152. local textutilsserialize = textutils.serialize\
  3153. local textutilsunserialize = textutils.unserialize\
  3154. local w,h = term.getSize()\
  3155. local Settings = {}\
  3156. local result = {}\
  3157. local Main = {}\
  3158. local QuickSettings = {}\
  3159. local MatchingColors = {}\
  3160. local gui = {}\
  3161. local mainLayout = {}\
  3162. local quickSettingsLayout = {}\
  3163. local paths = {}\
  3164. local scroll = 0\
  3165. local programPath = \"Data/\"\
  3166. OmniOS.loadAPI(\"NewInteract\")\
  3167. \
  3168. --Functions--\
  3169. local function readFile(_path)\
  3170.     local file = fs.open(_path,\"r\")\
  3171.     local data = file.readAll()\
  3172.     file.close()\
  3173.     return data\
  3174. end\
  3175. \
  3176. local function split(str,sep)\
  3177.     local buffer = {}\
  3178.     for token in str:gmatch(sep) do\
  3179.         buffer[#buffer+1] = token\
  3180.     end\
  3181.     return buffer\
  3182. end\
  3183. \
  3184. \
  3185. local function loadGUI()\
  3186.     --Initializing GUI components\
  3187.     gui = NewInteract.Initialize()\
  3188.     mainLayout = gui.Layout.new(dofile(programPath..\"Layouts/Main.layout\"))\
  3189.     quickSettingsLayout = gui.Layout.new(dofile(programPath..\"Layouts/QuickSettings.layout\"))\
  3190. end\
  3191. \
  3192. local function changeColor(color)\
  3193.     Settings.bgColor = colors[color] or colors.green\
  3194.     local f = fs.open(programPath..\"Settings\",\"w\")\
  3195.     f.write(textutilsserialize(Settings))\
  3196.     f.close()\
  3197.     local buffer = readFile(programPath..\"Settings\")\
  3198.     Settings = textutils.unserialize( buffer )\
  3199.     local buffer = readFile(programPath..\"MatchingColors\")\
  3200.     MatchingColors = textutilsunserialize(buffer)\
  3201.     loadObjects()\
  3202.     InitializeGUI()\
  3203. end\
  3204. \
  3205. loadGUI()\
  3206. InitializeGUI()\
  3207. \
  3208. \
  3209. --Code--\
  3210. while true do\
  3211.     mainLayout:draw(0,scroll)\
  3212.     local result = gui.eventHandler(mainLayout)\
  3213.     if result[1] == \"Button\" then\
  3214.         if result[2] == \"quickSettings\" then\
  3215.             quickSettingsLayout:draw()\
  3216.             local notClose = true\
  3217.             while notClose do\
  3218.                 local answer = gui.eventHandler(quickSettingsLayout)\
  3219.                 if answer[1] == \"Button\" then\
  3220.                     if answer[2] == \"reboot\" then\
  3221.                         os.reboot()\
  3222.                     elseif answer[2] == \"shutdown\" then\
  3223.                         os.shutdown()\
  3224.                     elseif answer[2] == \"Close\" then\
  3225.                         notClose = false\
  3226.                     elseif answer[2] == \"settings\" then\
  3227.                         System.newTask(\"Settings\",\"Settings\")\
  3228.                         notClose = false\
  3229.                     elseif answer[2] == \"Refresh\" then\
  3230.                         local buffer = readFile(programPath..\"Settings\")\
  3231.                         Settings = textutils.unserialize( buffer )\
  3232.                         local buffer = readFile(programPath..\"MatchingColors\")\
  3233.                         MatchingColors = textutilsunserialize(buffer)\
  3234.                         loadObjects()\
  3235.                         InitializeGUI()\
  3236.                         notClose = false\
  3237.                     else\
  3238.                         local buffer = split(answer[2],\"[^:]+\")\
  3239.                         changeColor(buffer[2])\
  3240.                         notClose = false\
  3241.                     end\
  3242.                 elseif answer[1] == \"Nil\" then\
  3243.                     if answer[2] == \"Nil\" then\
  3244.                         notClose = false\
  3245.                     end\
  3246.                 end\
  3247.             end\
  3248.         elseif result[2] == \"windowPlus\" then\
  3249.             scroll = scroll - 51\
  3250.         elseif result[2] == \"windowMinus\" then\
  3251.             scroll = scroll + 51\
  3252.         else\
  3253.             System.newTask(result[2],result[2])\
  3254.         end\
  3255.     end\
  3256. end",
  3257.       Data = {
  3258.         Settings = "{\
  3259.  bgColor = 1024,\
  3260. }",
  3261.         QuickSettings = {
  3262.           [ "restart.ico" ] = "error('This is an image, not a program!')\
  3263. {\
  3264.  {\
  3265.    {\
  3266.      16384,\
  3267.      \"O\",\
  3268.      1,\
  3269.    },\
  3270.    {\
  3271.      16384,\
  3272.      \"O\",\
  3273.      1,\
  3274.    },\
  3275.    {\
  3276.      16384,\
  3277.      \"O\",\
  3278.      1,\
  3279.    },\
  3280.    {\
  3281.      16384,\
  3282.      \"O\",\
  3283.      1,\
  3284.    },\
  3285.    {\
  3286.      16384,\
  3287.      \"O\",\
  3288.      1,\
  3289.    },\
  3290.  },\
  3291.  {\
  3292.    {\
  3293.      16384,\
  3294.      \"O\",\
  3295.      1,\
  3296.    },\
  3297.    {\
  3298.      16384,\
  3299.      \" \",\
  3300.      32,\
  3301.    },\
  3302.    {\
  3303.      16384,\
  3304.      \"O\",\
  3305.      1,\
  3306.    },\
  3307.    {\
  3308.      16384,\
  3309.      \" \",\
  3310.      32,\
  3311.    },\
  3312.    {\
  3313.      16384,\
  3314.      \" \",\
  3315.      32,\
  3316.    },\
  3317.  },\
  3318.  {\
  3319.    {\
  3320.      16384,\
  3321.      \"O\",\
  3322.      1,\
  3323.    },\
  3324.    {\
  3325.      16384,\
  3326.      \" \",\
  3327.      32,\
  3328.    },\
  3329.    {\
  3330.      16384,\
  3331.      \"O\",\
  3332.      1,\
  3333.    },\
  3334.    {\
  3335.      16384,\
  3336.      \"O\",\
  3337.      1,\
  3338.    },\
  3339.    {\
  3340.      16384,\
  3341.      \" \",\
  3342.      32,\
  3343.    },\
  3344.  },\
  3345.  {\
  3346.    {\
  3347.      16384,\
  3348.      \"O\",\
  3349.      1,\
  3350.    },\
  3351.    {\
  3352.      16384,\
  3353.      \"O\",\
  3354.      1,\
  3355.    },\
  3356.    {\
  3357.      16384,\
  3358.      \"O\",\
  3359.      1,\
  3360.    },\
  3361.    {\
  3362.      16384,\
  3363.      \" \",\
  3364.      32,\
  3365.    },\
  3366.    {\
  3367.      16384,\
  3368.      \"O\",\
  3369.      1,\
  3370.    },\
  3371.  },\
  3372.  {\
  3373.    {\
  3374.      16384,\
  3375.      \" \",\
  3376.      1,\
  3377.    },\
  3378.    {\
  3379.      16384,\
  3380.      \" \",\
  3381.      1,\
  3382.    },\
  3383.    {\
  3384.      16384,\
  3385.      \" \",\
  3386.      1,\
  3387.    },\
  3388.    {\
  3389.      16384,\
  3390.      \" \",\
  3391.      1,\
  3392.    },\
  3393.    {\
  3394.      16384,\
  3395.      \" \",\
  3396.      32,\
  3397.    },\
  3398.  },\
  3399.  {\
  3400.    {\
  3401.      16384,\
  3402.      \" \",\
  3403.      1,\
  3404.    },\
  3405.    {\
  3406.      16384,\
  3407.      \" \",\
  3408.      1,\
  3409.    },\
  3410.    {\
  3411.      16384,\
  3412.      \" \",\
  3413.      1,\
  3414.    },\
  3415.    {\
  3416.      16384,\
  3417.      \" \",\
  3418.      1,\
  3419.    },\
  3420.    {\
  3421.      16384,\
  3422.      \" \",\
  3423.      1,\
  3424.    },\
  3425.  },\
  3426.  [ 0 ] = {\
  3427.    {\
  3428.      16384,\
  3429.      \" \",\
  3430.      32,\
  3431.    },\
  3432.    {\
  3433.      16384,\
  3434.      \" \",\
  3435.      32,\
  3436.    },\
  3437.    {\
  3438.      16384,\
  3439.      \" \",\
  3440.      32,\
  3441.    },\
  3442.    {\
  3443.      16384,\
  3444.      \" \",\
  3445.      32,\
  3446.    },\
  3447.    {\
  3448.      16384,\
  3449.      \" \",\
  3450.      32,\
  3451.    },\
  3452.  },\
  3453.  [ 10 ] = {},\
  3454. }",
  3455.           [ "settings.ico" ] = "error('This is an image, not a program!')\
  3456. {\
  3457.  {\
  3458.    {\
  3459.      2,\
  3460.      \"-\",\
  3461.      1,\
  3462.    },\
  3463.    {\
  3464.      2,\
  3465.      \"-\",\
  3466.      1,\
  3467.    },\
  3468.    {\
  3469.      2,\
  3470.      \"-\",\
  3471.      1,\
  3472.    },\
  3473.    {\
  3474.      2,\
  3475.      \"O\",\
  3476.      1,\
  3477.    },\
  3478.    {\
  3479.      2,\
  3480.      \"-\",\
  3481.      1,\
  3482.    },\
  3483.  },\
  3484.  {\
  3485.    {\
  3486.      2,\
  3487.      \"-\",\
  3488.      1,\
  3489.    },\
  3490.    {\
  3491.      2,\
  3492.      \"-\",\
  3493.      1,\
  3494.    },\
  3495.    {\
  3496.      2,\
  3497.      \"O\",\
  3498.      1,\
  3499.    },\
  3500.    {\
  3501.      2,\
  3502.      \"-\",\
  3503.      1,\
  3504.    },\
  3505.    {\
  3506.      2,\
  3507.      \"-\",\
  3508.      1,\
  3509.    },\
  3510.  },\
  3511.  {\
  3512.    {\
  3513.      2,\
  3514.      \"O\",\
  3515.      1,\
  3516.    },\
  3517.    {\
  3518.      2,\
  3519.      \"-\",\
  3520.      1,\
  3521.    },\
  3522.    {\
  3523.      2,\
  3524.      \"-\",\
  3525.      1,\
  3526.    },\
  3527.    {\
  3528.      2,\
  3529.      \"-\",\
  3530.      1,\
  3531.    },\
  3532.    {\
  3533.      2,\
  3534.      \"-\",\
  3535.      1,\
  3536.    },\
  3537.  },\
  3538.  {\
  3539.    {\
  3540.      2,\
  3541.      \"-\",\
  3542.      1,\
  3543.    },\
  3544.    {\
  3545.      2,\
  3546.      \"-\",\
  3547.      1,\
  3548.    },\
  3549.    {\
  3550.      2,\
  3551.      \"-\",\
  3552.      1,\
  3553.    },\
  3554.    {\
  3555.      2,\
  3556.      \"-\",\
  3557.      1,\
  3558.    },\
  3559.    {\
  3560.      2,\
  3561.      \"O\",\
  3562.      1,\
  3563.    },\
  3564.  },\
  3565.  {\
  3566.    {\
  3567.      2,\
  3568.      \"-\",\
  3569.      1,\
  3570.    },\
  3571.    {\
  3572.      2,\
  3573.      \"O\",\
  3574.      1,\
  3575.    },\
  3576.    {\
  3577.      2,\
  3578.      \"-\",\
  3579.      1,\
  3580.    },\
  3581.    {\
  3582.      2,\
  3583.      \"-\",\
  3584.      1,\
  3585.    },\
  3586.    {\
  3587.      2,\
  3588.      \"-\",\
  3589.      1,\
  3590.    },\
  3591.  },\
  3592.  {\
  3593.    {\
  3594.      2,\
  3595.      \" \",\
  3596.      2,\
  3597.    },\
  3598.    {\
  3599.      2,\
  3600.      \" \",\
  3601.      2,\
  3602.    },\
  3603.    {\
  3604.      2,\
  3605.      \" \",\
  3606.      2,\
  3607.    },\
  3608.    {\
  3609.      2,\
  3610.      \" \",\
  3611.      2,\
  3612.    },\
  3613.    {\
  3614.      2,\
  3615.      \" \",\
  3616.      1,\
  3617.    },\
  3618.  },\
  3619.  [ 0 ] = {\
  3620.    {\
  3621.      2,\
  3622.      \" \",\
  3623.      2,\
  3624.    },\
  3625.    {\
  3626.      2,\
  3627.      \" \",\
  3628.      2,\
  3629.    },\
  3630.    {\
  3631.      2,\
  3632.      \" \",\
  3633.      2,\
  3634.    },\
  3635.    {\
  3636.      2,\
  3637.      \" \",\
  3638.      2,\
  3639.    },\
  3640.    {\
  3641.      2,\
  3642.      \" \",\
  3643.      2,\
  3644.    },\
  3645.  },\
  3646. }",
  3647.           [ "shutdown.ico" ] = "error('This is an image, not a program!')\
  3648. {\
  3649.  {\
  3650.    {\
  3651.      8192,\
  3652.      \"O\",\
  3653.      1,\
  3654.    },\
  3655.    {\
  3656.      8192,\
  3657.      \"O\",\
  3658.      1,\
  3659.    },\
  3660.    {\
  3661.      8192,\
  3662.      \"O\",\
  3663.      1,\
  3664.    },\
  3665.    {\
  3666.      8192,\
  3667.      \" \",\
  3668.      8192,\
  3669.    },\
  3670.    {\
  3671.      8192,\
  3672.      \"O\",\
  3673.      1,\
  3674.    },\
  3675.  },\
  3676.  {\
  3677.    {\
  3678.      8192,\
  3679.      \"O\",\
  3680.      1,\
  3681.    },\
  3682.    {\
  3683.      8192,\
  3684.      \" \",\
  3685.      1,\
  3686.    },\
  3687.    {\
  3688.      8192,\
  3689.      \"O\",\
  3690.      1,\
  3691.    },\
  3692.    {\
  3693.      8192,\
  3694.      \" \",\
  3695.      8192,\
  3696.    },\
  3697.    {\
  3698.      8192,\
  3699.      \"O\",\
  3700.      1,\
  3701.    },\
  3702.  },\
  3703.  {\
  3704.    {\
  3705.      8192,\
  3706.      \"O\",\
  3707.      1,\
  3708.    },\
  3709.    {\
  3710.      8192,\
  3711.      \" \",\
  3712.      1,\
  3713.    },\
  3714.    {\
  3715.      8192,\
  3716.      \"O\",\
  3717.      1,\
  3718.    },\
  3719.    {\
  3720.      8192,\
  3721.      \" \",\
  3722.      8192,\
  3723.    },\
  3724.    {\
  3725.      8192,\
  3726.      \"O\",\
  3727.      1,\
  3728.    },\
  3729.  },\
  3730.  {\
  3731.    {\
  3732.      8192,\
  3733.      \"O\",\
  3734.      1,\
  3735.    },\
  3736.    {\
  3737.      8192,\
  3738.      \" \",\
  3739.      1,\
  3740.    },\
  3741.    {\
  3742.      8192,\
  3743.      \"O\",\
  3744.      1,\
  3745.    },\
  3746.    {\
  3747.      8192,\
  3748.      \"O\",\
  3749.      1,\
  3750.    },\
  3751.    {\
  3752.      8192,\
  3753.      \"O\",\
  3754.      1,\
  3755.    },\
  3756.  },\
  3757.  {\
  3758.    {\
  3759.      8192,\
  3760.      \" \",\
  3761.      8192,\
  3762.    },\
  3763.    {\
  3764.      8192,\
  3765.      \" \",\
  3766.      8192,\
  3767.    },\
  3768.    {\
  3769.      8192,\
  3770.      \" \",\
  3771.      8192,\
  3772.    },\
  3773.    {\
  3774.      8192,\
  3775.      \" \",\
  3776.      8192,\
  3777.    },\
  3778.    {\
  3779.      8192,\
  3780.      \" \",\
  3781.      8192,\
  3782.    },\
  3783.  },\
  3784.  {\
  3785.    {\
  3786.      8192,\
  3787.      \" \",\
  3788.      8192,\
  3789.    },\
  3790.    {\
  3791.      8192,\
  3792.      \" \",\
  3793.      8192,\
  3794.    },\
  3795.    {\
  3796.      8192,\
  3797.      \" \",\
  3798.      8192,\
  3799.    },\
  3800.    {\
  3801.      8192,\
  3802.      \" \",\
  3803.      8192,\
  3804.    },\
  3805.    {\
  3806.      8192,\
  3807.      \" \",\
  3808.      8192,\
  3809.    },\
  3810.  },\
  3811.  [ 0 ] = {\
  3812.    {\
  3813.      8192,\
  3814.      \" \",\
  3815.      8192,\
  3816.    },\
  3817.    {\
  3818.      8192,\
  3819.      \" \",\
  3820.      8192,\
  3821.    },\
  3822.    {\
  3823.      8192,\
  3824.      \" \",\
  3825.      8192,\
  3826.    },\
  3827.    {\
  3828.      8192,\
  3829.      \" \",\
  3830.      8192,\
  3831.    },\
  3832.    {\
  3833.      8192,\
  3834.      \" \",\
  3835.      8192,\
  3836.    },\
  3837.  },\
  3838. }",
  3839.         },
  3840.         MatchingColors = "{\
  3841.  [ 8192 ] = {\
  3842.    name = \"green\",\
  3843.    quickSettings = 32,\
  3844.     mainButtons  = 1,\
  3845.  },\
  3846.  [ 4096 ] = {\
  3847.    name = \"brown\",\
  3848.    quickSettings = 2,\
  3849.     mainButtons  = 1,\
  3850.  },\
  3851.  [ 32768 ] = {\
  3852.    name = \"black\",\
  3853.    quickSettings = 128,\
  3854.     mainButtons  = 1,\
  3855.  },\
  3856.  [ 64 ] = {\
  3857.    name = \"pink\",\
  3858.    quickSettings = 16384,\
  3859.     mainButtons  = 1,\
  3860.  },\
  3861.  [ 16 ] = {\
  3862.    name = \"yellow\",\
  3863.    quickSettings = 1,\
  3864.     mainButtons  = 32768,\
  3865.  },\
  3866.  [ 2 ] = {\
  3867.    name = \"orange\",\
  3868.    quickSettings = 4096,\
  3869.     mainButtons  = 1,\
  3870.  },\
  3871.  [ 4 ] = {\
  3872.    name = \"magenta\",\
  3873.    quickSettings = 1024,\
  3874.     mainButtons  = 1,\
  3875.  },\
  3876.  [ 1024 ] = {\
  3877.    name = \"purple\",\
  3878.    quickSettings = 4,\
  3879.     mainButtons  = 1,\
  3880.  },\
  3881.  [ 512 ] = {\
  3882.    name = \"cyan\",\
  3883.    quickSettings = 8,\
  3884.     mainButtons  = 1,\
  3885.  },\
  3886.  [ 16384 ] = {\
  3887.    name = \"red\",\
  3888.    quickSettings = 64,\
  3889.     mainButtons  = 1,\
  3890.  },\
  3891.  [ 1 ] = {\
  3892.    name = \"white\",\
  3893.    quickSettings = 128,\
  3894.     mainButtons  = 32768,\
  3895.  },\
  3896.  [ 8 ] = {\
  3897.    name = \"lightBlue\",\
  3898.    quickSettings = 2048,\
  3899.     mainButtons  = 32768,\
  3900.  },\
  3901.  [ 256 ] = {\
  3902.    name = \"lightGray\",\
  3903.    quickSettings = 1,\
  3904.     mainButtons  = 1,\
  3905.  },\
  3906.  [ 128 ] = {\
  3907.    name = \"gray\",\
  3908.    quickSettings = 256,\
  3909.     mainButtons  = 1,\
  3910.  },\
  3911.  [ 32 ] = {\
  3912.    name = \"lime\",\
  3913.    quickSettings = 8192,\
  3914.     mainButtons  = 1,\
  3915.  },\
  3916.  [ 2048 ] = {\
  3917.    name = \"blue\",\
  3918.    quickSettings = 8,\
  3919.     mainButtons  = 1,\
  3920.  },\
  3921. }",
  3922.         MatchingColorsT = "green 8192\
  3923. brown 4096\
  3924. black 32768\
  3925. pink 64\
  3926. yellow 16\
  3927. orange 2\
  3928. magenta 4\
  3929. purple 1024\
  3930. cyan 512\
  3931. red 16384\
  3932. white 1\
  3933. lightBlue 8\
  3934. lightGray 256\
  3935. gray 128\
  3936. lime 32\
  3937. blue 2048",
  3938.         Shortcuts = "{\
  3939.     {\
  3940.         xPos = 7,\
  3941.         yPos = 3,\
  3942.         path = \"OmniOS/Programs/FileX.app/FileX\",\
  3943.         name = \"FileX\",\
  3944.     },\
  3945.     {\
  3946.         xPos = 2,\
  3947.         yPos = 1,\
  3948.         path = \"OmniOS/Programs/nPaintPro.app/nPaintPro\",\
  3949.         name = \"nPaintPro\"\
  3950.     },\
  3951.     {\
  3952.         xPos = 2,\
  3953.         yPos = 3,\
  3954.         path = \"OmniOS/Programs/Aware.app/Aware\",\
  3955.         name = \"Aware\"\
  3956.     },\
  3957.     {\
  3958.         xPos = 3,\
  3959.         yPos = 1,\
  3960.         path = \"OmniOS/Programs/BetterPaint.app/BetterPaint\",\
  3961.         name = \"BetterPaint\"\
  3962.     },\
  3963.     {\
  3964.         xPos = 2,\
  3965.         yPos = 2,\
  3966.         path = \"OmniOS/Programs/Edit.app/Edit\",\
  3967.         name = \"Edit\"\
  3968.     },\
  3969.     {\
  3970.         xPos = 3,\
  3971.         yPos = 2,\
  3972.         path = \"OmniOS/Programs/Shell.app/Shell\",\
  3973.         name = \"Shell\"\
  3974.     },\
  3975.     {\
  3976.         xPos = 1,\
  3977.         yPos = 1,\
  3978.         path = \"OmniOS/Programs/Calculator.app/Calculator\",\
  3979.         name = \"Calculator\"\
  3980.     },\
  3981. }",
  3982.         Layouts = {
  3983.           [ "Main.layout" ] = "local function readFile(_path)\
  3984.     local file = fs.open(_path,\"r\")\
  3985.     local data = file.readAll()\
  3986.     file.close()\
  3987.     return data\
  3988. end\
  3989. \
  3990. local w,h = term.getSize()\
  3991. \
  3992. local buffer = readFile(programPath..\"Settings\")\
  3993. Settings = textutils.unserialize( buffer )\
  3994. \
  3995. local buffer = readFile(programPath..\"MatchingColors\")\
  3996. MatchingColors = textutilsunserialize(buffer)\
  3997. \
  3998. local buffer = readFile(programPath..\"Settings\")\
  3999. Settings = textutils.unserialize( buffer )\
  4000. \
  4001. local buffer = readFile(programPath..\"MatchingColors\")\
  4002. MatchingColors = textutilsunserialize(buffer)\
  4003. \
  4004. \
  4005. local function loadShortcuts()\
  4006.     local buffer = readFile(programPath..\"Shortcuts\")\
  4007.     local sBuffer = textutilsunserialize(buffer)\
  4008.     local nBuffer = {}\
  4009.     paths = {}\
  4010.     for i,v in pairs(sBuffer) do\
  4011.         nBuffer[v.name] = {\
  4012.             xPos = 2+(6*(v.xPos-1)),\
  4013.             yPos = 1+(5*(v.yPos-1)),\
  4014.             name = v.name,\
  4015.             path = v.path..\".ico\",\
  4016.             yLength = 4,\
  4017.             xLength = 3,\
  4018.             returnValue = v.name,\
  4019.             label = string.sub(v.name,1,5),\
  4020.             labelFg = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4021.             labelBg = Settings.bgColor,\
  4022.             moveY = true,\
  4023.         }\
  4024.         paths[v.name] = v.path\
  4025.     end\
  4026.     Main.BetterPaint = nBuffer\
  4027. end\
  4028. \
  4029. Main = {\
  4030.     xPos = 1,\
  4031.     yPos = 1,\
  4032.     xLength = w,\
  4033.     yLength = h,\
  4034. }\
  4035. \
  4036. Main.Button = {\
  4037.         quickSettings = {\
  4038.             name = \"quickSettings\",\
  4039.             label = \"^\",\
  4040.             xPos = 1,\
  4041.             yPos = h,\
  4042.             xLength = 1,\
  4043.             yLength = 1,\
  4044.             xTextPos = 1,\
  4045.             yTextPos = 1,\
  4046.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4047.             bgColor = Settings.bgColor,\
  4048.             returnValue = \"quickSettings\",\
  4049.         },\
  4050.         windowPlus = {\
  4051.             name = \"windowPlus\",\
  4052.             label = \">\",\
  4053.             xPos = w,\
  4054.             yPos = 1,\
  4055.             xLength = 1,\
  4056.             yLength = 1,\
  4057.             xTextPos = 1,\
  4058.             yTextPos = 1,\
  4059.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4060.             bgColor = Settings.bgColor,\
  4061.             returnValue = \"windowPlus\",\
  4062.         },\
  4063.         windowMinus = {\
  4064.             name = \"windowMinus\",\
  4065.             label = \"<\",\
  4066.             xPos = 1,\
  4067.             yPos = 1,\
  4068.             xLength = 1,\
  4069.             yLength = 1,\
  4070.             xTextPos = 1,\
  4071.             yTextPos = 1,\
  4072.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4073.             bgColor = Settings.bgColor,\
  4074.             returnValue = \"windowMinus\",\
  4075.         },\
  4076.     }",
  4077.           [ "QuickSettings.layout" ] = "local function readFile(_path)\
  4078.     local file = fs.open(_path,\"r\")\
  4079.     local data = file.readAll()\
  4080.     file.close()\
  4081.     return data\
  4082. end\
  4083. \
  4084. local buffer = readFile(programPath..\"Settings\")\
  4085. Settings = textutils.unserialize( buffer )\
  4086. \
  4087. local buffer = readFile(programPath..\"MatchingColors\")\
  4088. MatchingColors = textutilsunserialize(buffer)\
  4089. \
  4090. local buffer = readFile(programPath..\"Settings\")\
  4091. Settings = textutils.unserialize( buffer )\
  4092. \
  4093. local buffer = readFile(programPath..\"MatchingColors\")\
  4094. MatchingColors = textutilsunserialize(buffer)\
  4095. \
  4096. QuickSettings.Button = {\
  4097.     Right = {\
  4098.         name = \"Right\",\
  4099.         label = \">\",\
  4100.         xPos = w-1,\
  4101.         yPos = 5,\
  4102.         xLength = 1,\
  4103.         yLength = 1,\
  4104.         xTextPos = 1,\
  4105.         yTextPos = 1,\
  4106.         fgColor = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4107.         bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4108.         returnValue = \"Right\",\
  4109.     },\
  4110.     Left = {\
  4111.         name = \"Left\",\
  4112.         label = \"<\",\
  4113.         xPos = 2,\
  4114.         yPos = 5,\
  4115.         xLength = 1,\
  4116.         yLength = 1,\
  4117.         xTextPos = 1,\
  4118.         yTextPos = 1,\
  4119.         fgColor = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4120.         bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4121.         returnValue = \"Left\",\
  4122.     },\
  4123.     Green = {\
  4124.         name = \"Green\",\
  4125.         label = \" \",\
  4126.         xPos = 31,\
  4127.         yPos = 6,\
  4128.         xLength = 1,\
  4129.         yLength = 1,\
  4130.         xTextPos = 1,\
  4131.         yTextPos = 1,\
  4132.         fgColor = 1,\
  4133.         bgColor = colors.green,\
  4134.         returnValue = \"color:green\",\
  4135.     },\
  4136.     Lime = {\
  4137.         name = \"Lime\",\
  4138.         label = \" \",\
  4139.         xPos = 31,\
  4140.         yPos = 7,\
  4141.         xLength = 1,\
  4142.         yLength = 1,\
  4143.         xTextPos = 1,\
  4144.         yTextPos = 1,\
  4145.         fgColor = 1,\
  4146.         bgColor = colors.lime,\
  4147.         returnValue = \"color:lime\",\
  4148.     },\
  4149.     Brown = {\
  4150.         name = \"Brown\",\
  4151.         label = \" \",\
  4152.         xPos = 32,\
  4153.         yPos = 6,\
  4154.         xLength = 1,\
  4155.         yLength = 1,\
  4156.         xTextPos = 1,\
  4157.         yTextPos = 1,\
  4158.         fgColor = 1,\
  4159.         bgColor = colors.brown,\
  4160.         returnValue = \"color:brown\",\
  4161.     },\
  4162.     Purple = {\
  4163.         name = \"Purple\",\
  4164.         label = \" \",\
  4165.         xPos = 32,\
  4166.         yPos = 7,\
  4167.         xLength = 1,\
  4168.         yLength = 1,\
  4169.         xTextPos = 1,\
  4170.         yTextPos = 1,\
  4171.         fgColor = 1,\
  4172.         bgColor = colors.purple,\
  4173.         returnValue = \"color:purple\",\
  4174.     },\
  4175.     Blue = {\
  4176.         name = \"Blue\",\
  4177.         label = \" \",\
  4178.         xPos = 33,\
  4179.         yPos = 6,\
  4180.         xLength = 1,\
  4181.         yLength = 1,\
  4182.         xTextPos = 1,\
  4183.         yTextPos = 1,\
  4184.         fgColor = 1,\
  4185.         bgColor = colors.blue,\
  4186.         returnValue = \"color:blue\",\
  4187.     },\
  4188.     lightBlue = {\
  4189.         name = \"lightBlue\",\
  4190.         label = \" \",\
  4191.         xPos = 33,\
  4192.         yPos = 7,\
  4193.         xLength = 1,\
  4194.         yLength = 1,\
  4195.         xTextPos = 1,\
  4196.         yTextPos = 1,\
  4197.         fgColor = 1,\
  4198.         bgColor = colors.lightBlue,\
  4199.         returnValue = \"color:lightBlue\",\
  4200.     },\
  4201.     Yellow = {\
  4202.         name = \"Yellow\",\
  4203.         label = \" \",\
  4204.         xPos = 34,\
  4205.         yPos = 6,\
  4206.         xLength = 1,\
  4207.         yLength = 1,\
  4208.         xTextPos = 1,\
  4209.         yTextPos = 1,\
  4210.         fgColor = 1,\
  4211.         bgColor = colors.yellow,\
  4212.         returnValue = \"color:yellow\",\
  4213.     },\
  4214.     Cyan = {\
  4215.         name = \"Cyan\",\
  4216.         label = \" \",\
  4217.         xPos = 34,\
  4218.         yPos = 7,\
  4219.         xLength = 1,\
  4220.         yLength = 1,\
  4221.         xTextPos = 1,\
  4222.         yTextPos = 1,\
  4223.         fgColor = 1,\
  4224.         bgColor = colors.cyan,\
  4225.         returnValue = \"color:cyan\",\
  4226.     },\
  4227.     Orange = {\
  4228.         name = \"Orange\",\
  4229.         label = \" \",\
  4230.         xPos = 35,\
  4231.         yPos = 6,\
  4232.         xLength = 1,\
  4233.         yLength = 1,\
  4234.         xTextPos = 1,\
  4235.         yTextPos = 1,\
  4236.         fgColor = 1,\
  4237.         bgColor = colors.orange,\
  4238.         returnValue = \"color:orange\",\
  4239.     },\
  4240.     Pink = {\
  4241.         name = \"Pink\",\
  4242.         label = \" \",\
  4243.         xPos = 35,\
  4244.         yPos = 7,\
  4245.         xLength = 1,\
  4246.         yLength = 1,\
  4247.         xTextPos = 1,\
  4248.         yTextPos = 1,\
  4249.         fgColor = 1,\
  4250.         bgColor = colors.pink,\
  4251.         returnValue = \"color:pink\",\
  4252.     },\
  4253.     Red = {\
  4254.         name = \"Red\",\
  4255.         label = \" \",\
  4256.         xPos = 36,\
  4257.         yPos = 6,\
  4258.         xLength = 1,\
  4259.         yLength = 1,\
  4260.         xTextPos = 1,\
  4261.         yTextPos = 1,\
  4262.         fgColor = 1,\
  4263.         bgColor = colors.red,\
  4264.         returnValue = \"color:red\",\
  4265.     },\
  4266.     Magenta = {\
  4267.         name = \"Magenta\",\
  4268.         label = \" \",\
  4269.         xPos = 36,\
  4270.         yPos = 7,\
  4271.         xLength = 1,\
  4272.         yLength = 1,\
  4273.         xTextPos = 1,\
  4274.         yTextPos = 1,\
  4275.         fgColor = 1,\
  4276.         bgColor = colors.magenta,\
  4277.         returnValue = \"color:magenta\",\
  4278.     },\
  4279.     White = {\
  4280.         name = \"White\",\
  4281.         label = \" \",\
  4282.         xPos = 37,\
  4283.         yPos = 6,\
  4284.         xLength = 1,\
  4285.         yLength = 1,\
  4286.         xTextPos = 1,\
  4287.         yTextPos = 1,\
  4288.         fgColor = 1,\
  4289.         bgColor = colors.white,\
  4290.         returnValue = \"color:white\",\
  4291.     },\
  4292.     lightGray = {\
  4293.         name = \"lightGray\",\
  4294.         label = \" \",\
  4295.         xPos = 37,\
  4296.         yPos = 7,\
  4297.         xLength = 1,\
  4298.         yLength = 1,\
  4299.         xTextPos = 1,\
  4300.         yTextPos = 1,\
  4301.         fgColor = 1,\
  4302.         bgColor = colors.lightGray,\
  4303.         returnValue = \"color:lightGray\",\
  4304.     },\
  4305.     Black = {\
  4306.         name = \"Black\",\
  4307.         label = \" \",\
  4308.         xPos = 38,\
  4309.         yPos = 6,\
  4310.         xLength = 1,\
  4311.         yLength = 1,\
  4312.         xTextPos = 1,\
  4313.         yTextPos = 1,\
  4314.         fgColor = 1,\
  4315.         bgColor = colors.black,\
  4316.         returnValue = \"color:black\",\
  4317.     },\
  4318.     Gray = {\
  4319.         name = \"Gray\",\
  4320.         label = \" \",\
  4321.         xPos = 38,\
  4322.         yPos = 7,\
  4323.         xLength = 1,\
  4324.         yLength = 1,\
  4325.         xTextPos = 1,\
  4326.         yTextPos = 1,\
  4327.         fgColor = 1,\
  4328.         bgColor = colors.gray,\
  4329.         returnValue = \"color:gray\",\
  4330.     },\
  4331.     RefreshColor = {\
  4332.         name = \"RefreshColor\",\
  4333.         label = \"Refresh\",\
  4334.         xPos = 40,\
  4335.         yPos = 3,\
  4336.         xLength = 9,\
  4337.         yLength = 5,\
  4338.         xTextPos = 2,\
  4339.         yTextPos = 3,\
  4340.         fgColor = 1,\
  4341.         bgColor = colors.gray,\
  4342.         returnValue = \"Refresh\",\
  4343.     },\
  4344. }\
  4345. \
  4346. QuickSettings.BetterPaint = {\
  4347.     Restart = {\
  4348.         xPos = 4,\
  4349.         yPos = 2,\
  4350.         name = \"Restart\",\
  4351.         path = programPath..\"QuickSettings/restart.ico\",\
  4352.         yLength = 6,\
  4353.         xLength = 7,\
  4354.         returnValue = \"reboot\",\
  4355.         label = \"Restart\",\
  4356.         labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4357.         labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4358.     },\
  4359.     Shutdown = {\
  4360.         xPos = 22,\
  4361.         yPos = 2,\
  4362.         name = \"Shutdown\",\
  4363.         path = programPath..\"QuickSettings/shutdown.ico\",\
  4364.         yLength = 6,\
  4365.         xLength = 7,\
  4366.         returnValue = \"shutdown\",\
  4367.         label = \"Shutdown\",\
  4368.         labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4369.         labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4370.     },\
  4371.     Settings = {\
  4372.         xPos = 13,\
  4373.         yPos = 2,\
  4374.         name = \"Settings\",\
  4375.         path = programPath..\"QuickSettings/settings.ico\",\
  4376.         yLength = 6,\
  4377.         xLength = 7,\
  4378.         returnValue = \"settings\",\
  4379.         label = \"Settings\",\
  4380.         labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4381.         labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4382.     },\
  4383. }\
  4384. \
  4385. QuickSettings.Text = {\
  4386.     Label = {\
  4387.         name = \"Label\",\
  4388.         text = \"QuickSettings\",\
  4389.         xPos = w/2-6,\
  4390.         yPos = 1,\
  4391.         bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4392.         fgColor = Settings.bgColor,\
  4393.     },\
  4394. }\
  4395. QuickSettings.Key = {\
  4396.     R = {\
  4397.         name = \"R\",\
  4398.         key = \"r\",\
  4399.         onPress = function() os.reboot() end,\
  4400.     },\
  4401.     S = {\
  4402.         name = \"S\",\
  4403.         key = \"s\",\
  4404.         onPress = function() os.shutdown() end,\
  4405.     },\
  4406.     LeftAlt = {\
  4407.         name = \"LeftAlt\",\
  4408.         key = \"LeftAlt\",\
  4409.         onPress = function() System.newTask(\"Settings\",\"Settings\") end,\
  4410.     }\
  4411. },\
  4412. \
  4413. return QuickSettings",
  4414.         },
  4415.       },
  4416.     },
  4417.     Calculator = {
  4418.       disk = {},
  4419.       [ "Calculator.ico" ] = "error('This is an image, not a program!')\
  4420. {\
  4421.  {\
  4422.    {\
  4423.      8192,\
  4424.      \"a\",\
  4425.      1,\
  4426.    },\
  4427.    {\
  4428.      8192,\
  4429.      \"+\",\
  4430.      1,\
  4431.    },\
  4432.    {\
  4433.      8192,\
  4434.      \"-\",\
  4435.      1,\
  4436.    },\
  4437.  },\
  4438.  {\
  4439.    {\
  4440.      8192,\
  4441.      \"l\",\
  4442.      1,\
  4443.    },\
  4444.    {\
  4445.      8192,\
  4446.      \"*\",\
  4447.      1,\
  4448.    },\
  4449.    {\
  4450.      8192,\
  4451.      \"/\",\
  4452.      1,\
  4453.    },\
  4454.  },\
  4455.  {\
  4456.    {\
  4457.      8192,\
  4458.      \"c\",\
  4459.      1,\
  4460.    },\
  4461.    {\
  4462.      8192,\
  4463.      \" \",\
  4464.      1,\
  4465.    },\
  4466.    {\
  4467.      8192,\
  4468.      \" \",\
  4469.      1,\
  4470.    },\
  4471.  },\
  4472.  [ 0 ] = {\
  4473.    {\
  4474.      8192,\
  4475.      \"C\",\
  4476.      1,\
  4477.    },\
  4478.    {\
  4479.      8192,\
  4480.      \" \",\
  4481.      1,\
  4482.    },\
  4483.    {\
  4484.      8192,\
  4485.      \" \",\
  4486.      1,\
  4487.    },\
  4488.  },\
  4489. }",
  4490.       [ "permission.data" ] = "user",
  4491.       [ "Main.lua" ] = "--[[\
  4492.     Calculator App\
  4493.     for OmniOS by\
  4494.     Creator\
  4495. ]]--\
  4496. \
  4497. --Varialbles--\
  4498. local gui = {}\
  4499. local path = OmniOS and \"OmniOS/Programs/Calculator.app/Data/\" or \"Calculator/\"\
  4500. local MainLayout = {}\
  4501. local env = {\
  4502.     deg = math.deg,\
  4503.     fmod = math.fmod,\
  4504.     random = math.random,\
  4505.     asin = math.asin,\
  4506.     max = math.max,\
  4507.     modf = math.modf,\
  4508.     log10 = math.log10,\
  4509.     floor = math.floor,\
  4510.     cosh = math.cosh,\
  4511.     ldexp = math.ldexp,\
  4512.     log = math.log,\
  4513.     pow = math.pow,\
  4514.     rndsd = math.randomseed,\
  4515.     frexp = math.frexp,\
  4516.     abs = math.abs,\
  4517.     tanh = math.tanh,\
  4518.     acos = math.acos,\
  4519.     atan2 = math.atan2,\
  4520.     tan = math.tan,\
  4521.     min = math.min,\
  4522.     ceil = math.ceil,\
  4523.     sinh = math.sinh,\
  4524.     sqrt = math.sqrt,\
  4525.     huge = math.huge,\
  4526.     rad = math.rad,\
  4527.     sin = math.sin,\
  4528.     exp = math.exp,\
  4529.     cos = math.cos,\
  4530.     atan = math.atan,\
  4531.     pi = math.pi,\
  4532. }\
  4533. \
  4534. --Functions--\
  4535. local function readLayoutFile(sLayout)\
  4536.     local func, err = loadfile(path..\"Layouts/\"..sLayout..\".layout\")\
  4537.     if err then\
  4538.         log.log(\"Calculator\",err)\
  4539.     end\
  4540.     setfenv(func,_G)\
  4541.     return func()\
  4542. end\
  4543. \
  4544. \
  4545. --Code--\
  4546. if not OmniOS or not Interact then\
  4547.     shell.run(\"pastebin --- Interact\")\
  4548.     os.loadAPI(\"Intearct\")\
  4549. end\
  4550. gui = NewInteract:Initialize()\
  4551. MainLayout = gui.Layout.new(readLayoutFile(\"Main\"))\
  4552. local input = gui.Text.new({name = \"input\",text = \"\",xPos = 1,yPos = 2,bgColor = colors.orange,fgColor = colors.white})\
  4553. \
  4554. MainLayout:draw()\
  4555. while true do\
  4556.     MainLayout.ColorField.Top:draw()\
  4557.     MainLayout.Button.Exit:draw()\
  4558.     MainLayout.Button.Clear:draw()\
  4559.     MainLayout.Button.Delete:draw()\
  4560.     MainLayout.Button.xxx:draw()\
  4561.     input:draw()\
  4562.     local MainLayoutEvent = gui.eventHandler(MainLayout)\
  4563.     if MainLayoutEvent[2] == \"=\" then\
  4564.         local fOutput = setfenv(loadstring(\"return \"..input.text),env)\
  4565.         local ok, output = pcall(fOutput)\
  4566.         if not ok then \
  4567.             log.log(\"Calculator\",output,\"Calculator\")\
  4568.         end\
  4569.         input.text = output\
  4570.         input:draw()\
  4571.     elseif MainLayoutEvent[2] == \"Exit\" then\
  4572.         break\
  4573.     elseif MainLayoutEvent[2] == \"Clear\" then\
  4574.         input.text = \"\"\
  4575.     elseif MainLayoutEvent[2] == \"Delete\" then\
  4576.         input.text = input.text:sub(1,-2)\
  4577.     else\
  4578.         input.text = input.text..MainLayoutEvent[2]\
  4579.         log.log(\"Calculator\",MainLayoutEvent[2])\
  4580.     end\
  4581. end",
  4582.       Data = {
  4583.         Layouts = {
  4584.           [ "Main.layout" ] = "local w,h = term.getSize()\
  4585. local tTable = {\
  4586.     BackgroundColor = colors.gray,\
  4587.     xPos = 1,\
  4588.     yPos = 1,\
  4589.     xLength = w,\
  4590.     yLength = h,\
  4591.     Button = {\
  4592.         Exit = {\
  4593.             name = \"Exit\",\
  4594.             label = \"x\",\
  4595.             xPos = w-1,\
  4596.             yPos = 2,\
  4597.             fgColor = colors.white,\
  4598.             bgColor = colors.orange,\
  4599.             xLength = 1,\
  4600.             yLength = 1,\
  4601.             returnValue = \"Exit\",\
  4602.             xTextPos = 1,\
  4603.             yTextPos = 1,\
  4604.         },\
  4605.         Clear = {\
  4606.             name = \"Clear\",\
  4607.             label = \"Clear\",\
  4608.             xPos = w-7,\
  4609.             yPos = 2,\
  4610.             fgColor = colors.white,\
  4611.             bgColor = colors.orange,\
  4612.             xLength = 5,\
  4613.             yLength = 1,\
  4614.             returnValue = \"Clear\",\
  4615.             xTextPos = 1,\
  4616.             yTextPos = 1,\
  4617.         },\
  4618.         Delete = {\
  4619.             name = \"Delete\",\
  4620.             label = \"<--\",\
  4621.             xPos = w-7,\
  4622.             yPos = 1,\
  4623.             fgColor = colors.white,\
  4624.             bgColor = colors.orange,\
  4625.             xLength = 5,\
  4626.             yLength = 1,\
  4627.             returnValue = \"Delete\",\
  4628.             xTextPos = 1,\
  4629.             yTextPos = 1,\
  4630.         },\
  4631.         xxx = {\
  4632.             name = \"xxx\",\
  4633.             label = \"xxx\",\
  4634.             xPos = w-11,\
  4635.             yPos = 1,\
  4636.             fgColor = colors.white,\
  4637.             bgColor = colors.orange,\
  4638.             xLength = 3,\
  4639.             yLength = 1,\
  4640.             returnValue = \"xxx\",\
  4641.             xTextPos = 1,\
  4642.             yTextPos = 1,\
  4643.         },\
  4644.     },\
  4645.     ColorField = {\
  4646.         Top = {\
  4647.             name = \"Top\",\
  4648.             xPos = 1,\
  4649.             yPos = 1,\
  4650.             xLength = 51, \
  4651.             yLength = 2,\
  4652.             color = colors.orange,\
  4653.         },\
  4654.     },\
  4655.     Layout  = {\
  4656.         Input = {\
  4657.             name = \"Input\",\
  4658.             xPos = 1,\
  4659.             yPos = 1,\
  4660.             xLength = w,\
  4661.             yLength = h,\
  4662.             BackgroundColor = colors.gray,\
  4663.             Button = {\
  4664.                 One = {\
  4665.                     name = \"One\",\
  4666.                     label = \"1\",\
  4667.                     xPos = 35,\
  4668.                     yPos = 4,\
  4669.                     fgColor = colors.white,\
  4670.                     bgColor = colors.orange,\
  4671.                     xLength = 3,\
  4672.                     yLength = 3,\
  4673.                     returnValue = \"1\",\
  4674.                     xTextPos = 2,\
  4675.                     yTextPos = 2,\
  4676.                 },\
  4677.                 Two = {\
  4678.                     name = \"Two\",\
  4679.                     label = \"2\",\
  4680.                     xPos = 39,\
  4681.                     yPos = 4,\
  4682.                     fgColor = colors.white,\
  4683.                     bgColor = colors.orange,\
  4684.                     xLength = 3,\
  4685.                     yLength = 3,\
  4686.                     returnValue = \"2\",\
  4687.                     xTextPos = 2,\
  4688.                     yTextPos = 2,\
  4689.                 },\
  4690.                 Three = {\
  4691.                     name = \"Three\",\
  4692.                     label = \"3\",\
  4693.                     xPos = 43,\
  4694.                     yPos = 4,\
  4695.                     fgColor = colors.white,\
  4696.                     bgColor = colors.orange,\
  4697.                     xLength = 3,\
  4698.                     yLength = 3,\
  4699.                     returnValue = \"3\",\
  4700.                     xTextPos = 2,\
  4701.                     yTextPos = 2,\
  4702.                 },\
  4703.                 Four = {\
  4704.                     name = \"Four\",\
  4705.                     label = \"4\",\
  4706.                     xPos = 35,\
  4707.                     yPos = 8,\
  4708.                     fgColor = colors.white,\
  4709.                     bgColor = colors.orange,\
  4710.                     xLength = 3,\
  4711.                     yLength = 3,\
  4712.                     returnValue = \"4\",\
  4713.                     xTextPos = 2,\
  4714.                     yTextPos = 2,\
  4715.                 },\
  4716.                 Five = {\
  4717.                     name = \"Five\",\
  4718.                     label = \"5\",\
  4719.                     xPos = 39,\
  4720.                     yPos = 8,\
  4721.                     fgColor = colors.white,\
  4722.                     bgColor = colors.orange,\
  4723.                     xLength = 3,\
  4724.                     yLength = 3,\
  4725.                     returnValue = \"5\",\
  4726.                     xTextPos = 2,\
  4727.                     yTextPos = 2,\
  4728.                 },\
  4729.                 Six = {\
  4730.                     name = \"Six\",\
  4731.                     label = \"6\",\
  4732.                     xPos = 43,\
  4733.                     yPos = 8,\
  4734.                     fgColor = colors.white,\
  4735.                     bgColor = colors.orange,\
  4736.                     xLength = 3,\
  4737.                     yLength = 3,\
  4738.                     returnValue = \"6\",\
  4739.                     xTextPos = 2,\
  4740.                     yTextPos = 2,\
  4741.                 },\
  4742.                 Seven = {\
  4743.                     name = \"Seven\",\
  4744.                     label = \"7\",\
  4745.                     xPos = 35,\
  4746.                     yPos = 12,\
  4747.                     fgColor = colors.white,\
  4748.                     bgColor = colors.orange,\
  4749.                     xLength = 3,\
  4750.                     yLength = 3,\
  4751.                     returnValue = \"7\",\
  4752.                     xTextPos = 2,\
  4753.                     yTextPos = 2,\
  4754.                 },\
  4755.                 Eight = {\
  4756.                     name = \"Eight\",\
  4757.                     label = \"8\",\
  4758.                     xPos = 39,\
  4759.                     yPos = 12,\
  4760.                     fgColor = colors.white,\
  4761.                     bgColor = colors.orange,\
  4762.                     xLength = 3,\
  4763.                     yLength = 3,\
  4764.                     returnValue = \"8\",\
  4765.                     xTextPos = 2,\
  4766.                     yTextPos = 2,\
  4767.                 },\
  4768.                 Nine = {\
  4769.                     name = \"Nine\",\
  4770.                     label = \"9\",\
  4771.                     xPos = 43,\
  4772.                     yPos = 12,\
  4773.                     fgColor = colors.white,\
  4774.                     bgColor = colors.orange,\
  4775.                     xLength = 3,\
  4776.                     yLength = 3,\
  4777.                     returnValue = \"9\",\
  4778.                     xTextPos = 2,\
  4779.                     yTextPos = 2,\
  4780.                 },\
  4781.                 Zero = {\
  4782.                     name = \"Zero\",\
  4783.                     label = \"0\",\
  4784.                     xPos = 35,\
  4785.                     yPos = 16,\
  4786.                     fgColor = colors.white,\
  4787.                     bgColor = colors.orange,\
  4788.                     xLength = 3,\
  4789.                     yLength = 3,\
  4790.                     returnValue = \"0\",\
  4791.                     xTextPos = 2,\
  4792.                     yTextPos = 2,\
  4793.                 },\
  4794.                 Equals = {\
  4795.                     name = \"Equals\",\
  4796.                     label = \"=\",\
  4797.                     xPos = 39,\
  4798.                     yPos = 16,\
  4799.                     fgColor = colors.white,\
  4800.                     bgColor = colors.lightGray,\
  4801.                     xLength = 7,\
  4802.                     yLength = 3,\
  4803.                     returnValue = \"=\",\
  4804.                     xTextPos = 4,\
  4805.                     yTextPos = 2,\
  4806.                 },\
  4807.                 Add = {\
  4808.                     name = \"Add\",\
  4809.                     label = \"+\",\
  4810.                     xPos = 47,\
  4811.                     yPos = 4,\
  4812.                     fgColor = colors.white,\
  4813.                     bgColor = colors.green,\
  4814.                     xLength = 3,\
  4815.                     yLength = 3,\
  4816.                     returnValue = \"+\",\
  4817.                     xTextPos = 2,\
  4818.                     yTextPos = 2,\
  4819.                 },\
  4820.                 Sub = {\
  4821.                     name = \"Sub\",\
  4822.                     label = \"-\",\
  4823.                     xPos = 47,\
  4824.                     yPos = 8,\
  4825.                     fgColor = colors.white,\
  4826.                     bgColor = colors.green,\
  4827.                     xLength = 3,\
  4828.                     yLength = 3,\
  4829.                     returnValue = \"-\",\
  4830.                     xTextPos = 2,\
  4831.                     yTextPos = 2,\
  4832.                 },\
  4833.                 Mul = {\
  4834.                     name = \"Mul\",\
  4835.                     label = \"*\",\
  4836.                     xPos = 47,\
  4837.                     yPos = 12,\
  4838.                     fgColor = colors.white,\
  4839.                     bgColor = colors.green,\
  4840.                     xLength = 3,\
  4841.                     yLength = 3,\
  4842.                     returnValue = \"*\",\
  4843.                     xTextPos = 2,\
  4844.                     yTextPos = 2,\
  4845.                 },\
  4846.                 Div = {\
  4847.                     name = \"Div\",\
  4848.                     label = \"/\",\
  4849.                     xPos = 47,\
  4850.                     yPos = 16,\
  4851.                     fgColor = colors.white,\
  4852.                     bgColor = colors.green,\
  4853.                     xLength = 3,\
  4854.                     yLength = 3,\
  4855.                     returnValue = \"/\",\
  4856.                     xTextPos = 2,\
  4857.                     yTextPos = 2,\
  4858.                 },\
  4859.                 LPar = {\
  4860.                     name = \"LPar\",\
  4861.                     label = \"(\",\
  4862.                     xPos = 31,\
  4863.                     yPos = 12,\
  4864.                     fgColor = colors.white,\
  4865.                     bgColor = colors.green,\
  4866.                     xLength = 3,\
  4867.                     yLength = 3,\
  4868.                     returnValue = \"(\",\
  4869.                     xTextPos = 2,\
  4870.                     yTextPos = 2,\
  4871.                 },\
  4872.                 RPar = {\
  4873.                     name = \"RPar\",\
  4874.                     label = \")\",\
  4875.                     xPos = 31,\
  4876.                     yPos = 16,\
  4877.                     fgColor = colors.white,\
  4878.                     bgColor = colors.green,\
  4879.                     xLength = 3,\
  4880.                     yLength = 3,\
  4881.                     returnValue = \")\",\
  4882.                     xTextPos = 2,\
  4883.                     yTextPos = 2,\
  4884.                 },\
  4885.                 Mod = {\
  4886.                     name = \"Mod\",\
  4887.                     label = \"%\",\
  4888.                     xPos = 31,\
  4889.                     yPos = 8,\
  4890.                     fgColor = colors.white,\
  4891.                     bgColor = colors.green,\
  4892.                     xLength = 3,\
  4893.                     yLength = 3,\
  4894.                     returnValue = \"%\",\
  4895.                     xTextPos = 2,\
  4896.                     yTextPos = 2,\
  4897.                 },\
  4898.                 Comma = {\
  4899.                     name = \"Comma\",\
  4900.                     label = \",\",\
  4901.                     xPos = 31,\
  4902.                     yPos = 4,\
  4903.                     fgColor = colors.white,\
  4904.                     bgColor = colors.green,\
  4905.                     xLength = 3,\
  4906.                     yLength = 3,\
  4907.                     returnValue = \",\",\
  4908.                     xTextPos = 2,\
  4909.                     yTextPos = 2,\
  4910.                 },\
  4911.                 Abs = {\
  4912.                     name = \"Abs\",\
  4913.                     label = \"abs\",\
  4914.                     xPos = 25,\
  4915.                     yPos = 4,\
  4916.                     fgColor = colors.white,\
  4917.                     bgColor = colors.lightGray,\
  4918.                     xLength = 5,\
  4919.                     yLength = 3,\
  4920.                     returnValue = \"abs(\",\
  4921.                     xTextPos = 2,\
  4922.                     yTextPos = 2,\
  4923.                 },\
  4924.                 Deg = {\
  4925.                     name = \"Deg\",\
  4926.                     label = \"deg\",\
  4927.                     xPos = 25,\
  4928.                     yPos = 8,\
  4929.                     fgColor = colors.white,\
  4930.                     bgColor = colors.lightGray,\
  4931.                     xLength = 5,\
  4932.                     yLength = 3,\
  4933.                     returnValue = \"deg(\",\
  4934.                     xTextPos = 2,\
  4935.                     yTextPos = 2,\
  4936.                 },\
  4937.                 Max = {\
  4938.                     name = \"Max\",\
  4939.                     label = \"max\",\
  4940.                     xPos = 25,\
  4941.                     yPos = 12,\
  4942.                     fgColor = colors.white,\
  4943.                     bgColor = colors.lightGray,\
  4944.                     xLength = 5,\
  4945.                     yLength = 3,\
  4946.                     returnValue = \"max(\",\
  4947.                     xTextPos = 2,\
  4948.                     yTextPos = 2,\
  4949.                 },\
  4950.                 Log = {\
  4951.                     name = \"Log\",\
  4952.                     label = \"log\",\
  4953.                     xPos = 25,\
  4954.                     yPos = 16,\
  4955.                     fgColor = colors.white,\
  4956.                     bgColor = colors.lightGray,\
  4957.                     xLength = 5,\
  4958.                     yLength = 3,\
  4959.                     returnValue = \"log(\",\
  4960.                     xTextPos = 2,\
  4961.                     yTextPos = 2,\
  4962.                 },\
  4963.                 Pow = {\
  4964.                     name = \"Pow\",\
  4965.                     label = \"pow\",\
  4966.                     xPos = 19,\
  4967.                     yPos = 4,\
  4968.                     fgColor = colors.white,\
  4969.                     bgColor = colors.lightGray,\
  4970.                     xLength = 5,\
  4971.                     yLength = 3,\
  4972.                     returnValue = \"pow(\",\
  4973.                     xTextPos = 2,\
  4974.                     yTextPos = 2,\
  4975.                 },\
  4976.                 Tan = {\
  4977.                     name = \"Tan\",\
  4978.                     label = \"tan\",\
  4979.                     xPos = 19,\
  4980.                     yPos = 8,\
  4981.                     fgColor = colors.white,\
  4982.                     bgColor = colors.lightGray,\
  4983.                     xLength = 5,\
  4984.                     yLength = 3,\
  4985.                     returnValue = \"tan(\",\
  4986.                     xTextPos = 2,\
  4987.                     yTextPos = 2,\
  4988.                 },\
  4989.                 Min = {\
  4990.                     name = \"Min\",\
  4991.                     label = \"min\",\
  4992.                     xPos = 19,\
  4993.                     yPos = 12,\
  4994.                     fgColor = colors.white,\
  4995.                     bgColor = colors.lightGray,\
  4996.                     xLength = 5,\
  4997.                     yLength = 3,\
  4998.                     returnValue = \"min(\",\
  4999.                     xTextPos = 2,\
  5000.                     yTextPos = 2,\
  5001.                 },\
  5002.                 Rad = {\
  5003.                     name = \"Rad\",\
  5004.                     label = \"rad\",\
  5005.                     xPos = 19,\
  5006.                     yPos = 16,\
  5007.                     fgColor = colors.white,\
  5008.                     bgColor = colors.lightGray,\
  5009.                     xLength = 5,\
  5010.                     yLength = 3,\
  5011.                     returnValue = \"rad(\",\
  5012.                     xTextPos = 2,\
  5013.                     yTextPos = 2,\
  5014.                 },\
  5015.                 Sin = {\
  5016.                     name = \"Sin\",\
  5017.                     label = \"sin\",\
  5018.                     xPos = 13,\
  5019.                     yPos = 4,\
  5020.                     fgColor = colors.white,\
  5021.                     bgColor = colors.lightGray,\
  5022.                     xLength = 5,\
  5023.                     yLength = 3,\
  5024.                     returnValue = \"sin(\",\
  5025.                     xTextPos = 2,\
  5026.                     yTextPos = 2,\
  5027.                 },\
  5028.                 Exp = {\
  5029.                     name = \"Exp\",\
  5030.                     label = \"exp\",\
  5031.                     xPos = 13,\
  5032.                     yPos = 8,\
  5033.                     fgColor = colors.white,\
  5034.                     bgColor = colors.lightGray,\
  5035.                     xLength = 5,\
  5036.                     yLength = 3,\
  5037.                     returnValue = \"exp(\",\
  5038.                     xTextPos = 2,\
  5039.                     yTextPos = 2,\
  5040.                 },\
  5041.                 Cos = {\
  5042.                     name = \"Cos\",\
  5043.                     label = \"cos\",\
  5044.                     xPos = 13,\
  5045.                     yPos = 12,\
  5046.                     fgColor = colors.white,\
  5047.                     bgColor = colors.lightGray,\
  5048.                     xLength = 5,\
  5049.                     yLength = 3,\
  5050.                     returnValue = \"cos(\",\
  5051.                     xTextPos = 2,\
  5052.                     yTextPos = 2,\
  5053.                 },\
  5054.                 Pi = {\
  5055.                     name = \"Pi\",\
  5056.                     label = \"pi\",\
  5057.                     xPos = 14,\
  5058.                     yPos = 16,\
  5059.                     fgColor = colors.white,\
  5060.                     bgColor = colors.lightGray,\
  5061.                     xLength = 4,\
  5062.                     yLength = 3,\
  5063.                     returnValue = \"pi\",\
  5064.                     xTextPos = 2,\
  5065.                     yTextPos = 2,\
  5066.                 },\
  5067.                 Atan = {\
  5068.                     name = \"Atan\",\
  5069.                     label = \"atan\",\
  5070.                     xPos = 7,\
  5071.                     yPos = 16,\
  5072.                     fgColor = colors.white,\
  5073.                     bgColor = colors.lightGray,\
  5074.                     xLength = 6,\
  5075.                     yLength = 3,\
  5076.                     returnValue = \"atan(\",\
  5077.                     xTextPos = 2,\
  5078.                     yTextPos = 2,\
  5079.                 },\
  5080.             },\
  5081.         }\
  5082.     }\
  5083. }\
  5084. \
  5085. return tTable",
  5086.         },
  5087.       },
  5088.     },
  5089.     Debug = {
  5090.       disk = {},
  5091.       Commands = {
  5092.         [ "cmds.lua" ] = "--[[\
  5093.  author: Wassil Janssen a.k.a. Creator\
  5094. ]]\
  5095. \
  5096. \
  5097. print(\"The commands are:\")\
  5098. for i,v in pairs(fs.list(\"OmniOS/Programs/Debug/Commands\")) do\
  5099.     print(\" \"..v:match(\"[^.]+\"))\
  5100. end",
  5101.         [ "help.lua" ] = "--[[\
  5102.  author: Wassil Janssen a.k.a. Creator\
  5103. ]]\
  5104. \
  5105. local tArgs = {...}\
  5106. help = tArgs[1]\
  5107. local p = print\
  5108. if help == \"cmds\" then\
  5109.     p(\"Usage: cmds\")\
  5110.     p(\"  Prints all the commands. \")\
  5111. elseif help == \"kill\" then\
  5112.     p(\"Usage: kill <process>\")\
  5113.     p(\"  Kils the specified process\")\
  5114.     p(\"  !all will terminate every process except Debug1.\")\
  5115.     p(\"  !zygote will terminate every process.\")\
  5116. elseif help == \"launch\" then\
  5117.     p(\"Usage: launch <app>\")\
  5118.     p(\"  Will launch an app on the terminal\")\
  5119. elseif help == \"list\" then\
  5120.     p(\"Usage: list\")\
  5121.     p(\"  Lists the processes.\")\
  5122. elseif help == \"logs\" then\
  5123.     p(\"Usage: logs <log>\")\
  5124.     p(\"  Deletes the specified log.\")\
  5125.     p(\"  !all will delete all the logs.\")\
  5126. elseif help == \"ls\" then\
  5127.     p(\"Type help list\")\
  5128. elseif help == \"monitor\" then\
  5129.     p(\"Usage: monitor <action> <args>\")\
  5130.     p(\"  What each action does:\")\
  5131.     p(\"Launch:\")\
  5132.     p(\"  Usage: monitor launch <monitor> <app>\")\
  5133.     p(\"  Is the same as launch, but uses a monitor instead.\")\
  5134.     p(\"List:\")\
  5135.     p(\"  Lists the available monitors.\")\
  5136. else\
  5137.     p(\"Usage: help <command>\")\
  5138. end",
  5139.         [ "kill.lua" ] = "--[[\
  5140.  Author: Wassil Janssen a.k.a. Creator\
  5141. ]]\
  5142. \
  5143. local tArgs = {...}\
  5144. if tArgs[1] == \"!zygote\" then\
  5145.     error(\"Zygote killed!\")\
  5146. elseif tArgs[1] == \"!all\" then\
  5147.     for i,v in pairs(Kernel.list()) do\
  5148.         Kernel.kill(v)\
  5149.     end\
  5150. else\
  5151.     if tonumber(tArgs[1]:sub(-1,-1)) then\
  5152.         local resp = Kernel.kill(tArgs[1])\
  5153.         if resp then\
  5154.             print(resp)\
  5155.         end\
  5156.     else\
  5157.         print(\"The routines have a number at the end. Don't forget it!\")\
  5158.     end\
  5159. end",
  5160.         [ "ls.lua" ] = "--[[\
  5161.  Author: Wassil Janssen a.k.a. Creator\
  5162. ]]\
  5163. \
  5164. print(\"The threads are:\")\
  5165. for i,v in pairs(Kernel.list()) do\
  5166.     print(v[1]..string.rep(\" \",5-#tostring(v[1]))..v[2]..\": \"..v[3])\
  5167. end",
  5168.         [ "clear.lua" ] = "--[[\
  5169.  author: Wassil Janssen a.k.a. Creator\
  5170. ]]\
  5171. \
  5172. promptColour = colours.yellow\
  5173. textColour = colours.white\
  5174. bgColour = colours.black\
  5175. \
  5176. \
  5177. term.setBackgroundColor( bgColour )\
  5178. term.setTextColour( promptColour )\
  5179. term.clear()\
  5180. term.setCursorPos(1,1)\
  5181. print(\"OmniOS/Debug\")\
  5182. term.setTextColour( textColour )",
  5183.         [ "logs.lua" ] = "--[[\
  5184.  author: Wassil Janssen a.k.a. Creator\
  5185. ]]\
  5186. \
  5187. local tArgs = {...}\
  5188. if tArgs[1] == \"clear\" then\
  5189.     if tArgs[2] == \"!all\" then\
  5190.         fs.delete(\"OmniOS/Logs\")\
  5191.     elseif fs.exists(\"OmniOS/Logs/\"..tArgs[2]) then\
  5192.         tArgs[2] = tArgs[2]:gsub(\"%.%.\",\"\")\
  5193.         fs.delete(\"OmniOS/Logs/\"..tArgs[2])\
  5194.     end\
  5195. end",
  5196.         [ "shutdown.lua" ] = "--[[\
  5197.  author: Wassil Janssen a.k.a. Creator\
  5198. ]]\
  5199. \
  5200. os.shutdown()",
  5201.         [ "switch.lua" ] = "--[[\
  5202.  author: Wassil Janssen a.k.a. Creator\
  5203. ]]\
  5204. \
  5205. local tArgs = {...}\
  5206. num = tonumber(tArgs[1])\
  5207. if type(num) == \"number\" then\
  5208.  Kernel.switch(num)\
  5209. end",
  5210.         [ "terminate.lua" ] = "--[[\
  5211.  author: Wassil Janssen a.k.a. Creator\
  5212. ]]\
  5213. \
  5214. error(\"OmniOS is being terminated...\")",
  5215.         [ "panic.lua" ] = "--[[\
  5216.  author: Wassil Janssen a.k.a. Creator\
  5217. ]]\
  5218. \
  5219. OmniOS.debug.run(\"kill !all\")\
  5220. os.pullEvent = os.pullEventRaw\
  5221. local countdown = 1000\
  5222. while true do\
  5223.     print(\"We're under attack\")\
  5224.     print(\"System will self destroy in \"..tostring(countdown)..\" seconds\")\
  5225.     sleep(1)\
  5226.     countdown = countdown - 1\
  5227.     if countdown == 0 then error() end\
  5228. end",
  5229.         [ "screen.lua" ] = "--[[\
  5230.  author: Wassil Janssen a.k.a. Creator\
  5231. ]]\
  5232. \
  5233. local tArgs = {...}\
  5234. local tArgs = {...}\
  5235. if #tArgs == 0 then\
  5236.     print(\"Usage:\")\
  5237.     print(\"screen get <routine>\")\
  5238.     print(\"screen set <routine> <table>\")\
  5239.     error(\"wow\")\
  5240.     --return\
  5241. end\
  5242. \
  5243. if tArgs[1] == \"get\" then\
  5244.     local file = fs.open(\"OmniOS/Screen/\"..tostring(os.day())..\".\"..tostring(os.time()),\"w\")\
  5245.     file.write(textutils.serialze(OmniOS.screen.getScreen(tArgs[2])))\
  5246.     file.close()\
  5247. end",
  5248.         [ "launch.lua" ] = "--[[\
  5249.  author: Wassil Janssen a.k.a. Creator\
  5250. ]]\
  5251. local links = {\
  5252.  [\"-p:\"] = \"permission\",\
  5253.  [\"-t:\"] = \"terminal\",\
  5254.  [\"-n:\"] = \"name\",\
  5255. }\
  5256. \
  5257. local tArgs = {...}\
  5258. if #tArgs == 0 then\
  5259.  print(\"Usage: Program, terminal object, permission, name\")\
  5260.  print(\"The flags are respectively: -t, -p, -n\")\
  5261.  print(\"The first does not have a flag!\")\
  5262. end\
  5263. local second = {unpack(tArgs,2)}\
  5264. local final = {}\
  5265. \
  5266. if not fs.exists(\"OmniOS/Programs/\"..tArgs[1]..\"/Main.lua\") then error(tArgs[1]..\" is not a valid program!\") end\
  5267. local func = loadfile(\"OmniOS/Programs/\"..tArgs[1]..\"/Main.lua\")\
  5268. setfenv(func,_G)\
  5269. \
  5270. for i,v in pairs(second) do\
  5271.  if links[v:sub(1,3)] then\
  5272.    final[links[v:sub(1,3)]] = v:sub(4,-1)\
  5273.  end\
  5274. end\
  5275. \
  5276. local parent = final.terminal and (final.terminal == \"term\" and \"term\" or peripheral.isPresent(final.terminal) and final.terminal or \"term\") or \"term\"\
  5277. \
  5278. local permission = final.permission or \"user\"\
  5279. \
  5280. local name = final.name or tArgs[1]\
  5281. \
  5282. Kernel.newProcess(func,parent,permission,name)",
  5283.         [ "shell.lua" ] = "--[[\
  5284.  author: Dan200 a.k.a. Daniel Ratcliff\
  5285. ]]\
  5286. \
  5287. local multishell = multishell\
  5288. local parentShell = shell\
  5289. local parentTerm = term.current()\
  5290. \
  5291. if multishell then\
  5292.    multishell.setTitle( multishell.getCurrent(), \"shell\" )\
  5293. end\
  5294. \
  5295. local bExit = false\
  5296. local sDir = (parentShell and parentShell.dir()) or \"\"\
  5297. local sPath = (parentShell and parentShell.path()) or \".:/rom/programs\"\
  5298. local tAliases = (parentShell and parentShell.aliases()) or {}\
  5299. local tProgramStack = {}\
  5300. \
  5301. local shell = {}\
  5302. local tEnv = {\
  5303.     [ \"shell\" ] = shell,\
  5304.     [ \"multishell\" ] = multishell,\
  5305. }\
  5306. \
  5307. -- Colours\
  5308. local promptColour, textColour, bgColour\
  5309. if term.isColour() then\
  5310.     promptColour = colours.yellow\
  5311.     textColour = colours.white\
  5312.     bgColour = colours.black\
  5313. else\
  5314.     promptColour = colours.white\
  5315.     textColour = colours.white\
  5316.     bgColour = colours.black\
  5317. end\
  5318. \
  5319. local function run( _sCommand, ... )\
  5320.     local sPath = shell.resolveProgram( _sCommand )\
  5321.     if sPath ~= nil then\
  5322.         tProgramStack[#tProgramStack + 1] = sPath\
  5323.         if multishell then\
  5324.             multishell.setTitle( multishell.getCurrent(), fs.getName( sPath ) )\
  5325.         end\
  5326.         local result = os.run( tEnv, sPath, ... )\
  5327.         tProgramStack[#tProgramStack] = nil\
  5328.         if multishell then\
  5329.             if #tProgramStack > 0 then\
  5330.                 multishell.setTitle( multishell.getCurrent(), fs.getName( tProgramStack[#tProgramStack] ) )\
  5331.             else\
  5332.                 multishell.setTitle( multishell.getCurrent(), \"shell\" )\
  5333.             end\
  5334.         end\
  5335.         return result\
  5336.     else\
  5337.         printError( \"No such program\" )\
  5338.         return false\
  5339.    end\
  5340. end\
  5341. \
  5342. local function tokenise( ... )\
  5343.    local sLine = table.concat( { ... }, \" \" )\
  5344.     local tWords = {}\
  5345.    local bQuoted = false\
  5346.    for match in string.gmatch( sLine .. \"\\\"\", \"(.-)\\\"\" ) do\
  5347.        if bQuoted then\
  5348.            table.insert( tWords, match )\
  5349.        else\
  5350.            for m in string.gmatch( match, \"[^ \\t]+\" ) do\
  5351.                table.insert( tWords, m )\
  5352.            end\
  5353.        end\
  5354.        bQuoted = not bQuoted\
  5355.    end\
  5356.    return tWords\
  5357. end\
  5358. \
  5359. -- Install shell API\
  5360. function shell.run( ... )\
  5361.     local tWords = tokenise( ... )\
  5362.     local sCommand = tWords[1]\
  5363.     if sCommand then\
  5364.         return run( sCommand, unpack( tWords, 2 ) )\
  5365.     end\
  5366.     return false\
  5367. end\
  5368. \
  5369. function shell.exit()\
  5370.    bExit = true\
  5371. end\
  5372. \
  5373. function shell.dir()\
  5374.     return sDir\
  5375. end\
  5376. \
  5377. function shell.setDir( _sDir )\
  5378.     sDir = _sDir\
  5379. end\
  5380. \
  5381. function shell.path()\
  5382.     return sPath\
  5383. end\
  5384. \
  5385. function shell.setPath( _sPath )\
  5386.     sPath = _sPath\
  5387. end\
  5388. \
  5389. function shell.resolve( _sPath )\
  5390.     local sStartChar = string.sub( _sPath, 1, 1 )\
  5391.     if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
  5392.         return fs.combine( \"\", _sPath )\
  5393.     else\
  5394.         return fs.combine( sDir, _sPath )\
  5395.     end\
  5396. end\
  5397. \
  5398. function shell.resolveProgram( _sCommand )\
  5399.     -- Substitute aliases firsts\
  5400.     if tAliases[ _sCommand ] ~= nil then\
  5401.         _sCommand = tAliases[ _sCommand ]\
  5402.     end\
  5403. \
  5404.    -- If the path is a global path, use it directly\
  5405.    local sStartChar = string.sub( _sCommand, 1, 1 )\
  5406.    if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
  5407.         local sPath = fs.combine( \"\", _sCommand )\
  5408.         if fs.exists( sPath ) and not fs.isDir( sPath ) then\
  5409.             return sPath\
  5410.         end\
  5411.         return nil\
  5412.    end\
  5413. \
  5414.     -- Otherwise, look on the path variable\
  5415.    for sPath in string.gmatch(sPath, \"[^:]+\") do\
  5416.         sPath = fs.combine( shell.resolve( sPath ), _sCommand )\
  5417.         if fs.exists( sPath ) and not fs.isDir( sPath ) then\
  5418.             return sPath\
  5419.         end\
  5420.    end\
  5421. \
  5422.     -- Not found\
  5423.     return nil\
  5424. end\
  5425. \
  5426. function shell.programs( _bIncludeHidden )\
  5427.     local tItems = {}\
  5428. \
  5429.     -- Add programs from the path\
  5430.    for sPath in string.gmatch(sPath, \"[^:]+\") do\
  5431.         sPath = shell.resolve( sPath )\
  5432.         if fs.isDir( sPath ) then\
  5433.             local tList = fs.list( sPath )\
  5434.             for n,sFile in pairs( tList ) do\
  5435.                 if not fs.isDir( fs.combine( sPath, sFile ) ) and\
  5436.                    (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= \".\") then\
  5437.                     tItems[ sFile ] = true\
  5438.                 end\
  5439.             end\
  5440.         end\
  5441.    end\
  5442. \
  5443.     -- Sort and return\
  5444.     local tItemList = {}\
  5445.     for sItem, b in pairs( tItems ) do\
  5446.         table.insert( tItemList, sItem )\
  5447.     end\
  5448.     table.sort( tItemList )\
  5449.     return tItemList\
  5450. end\
  5451. \
  5452. function shell.getRunningProgram()\
  5453.     if #tProgramStack > 0 then\
  5454.         return tProgramStack[#tProgramStack]\
  5455.     end\
  5456.     return nil\
  5457. end\
  5458. \
  5459. function shell.setAlias( _sCommand, _sProgram )\
  5460.     tAliases[ _sCommand ] = _sProgram\
  5461. end\
  5462. \
  5463. function shell.clearAlias( _sCommand )\
  5464.     tAliases[ _sCommand ] = nil\
  5465. end\
  5466. \
  5467. function shell.aliases()\
  5468.     -- Add aliases\
  5469.     local tCopy = {}\
  5470.     for sAlias, sCommand in pairs( tAliases ) do\
  5471.         tCopy[sAlias] = sCommand\
  5472.     end\
  5473.     return tCopy\
  5474. end\
  5475. \
  5476. if multishell then\
  5477.    function shell.openTab( ... )\
  5478.        local tWords = tokenise( ... )\
  5479.        local sCommand = tWords[1]\
  5480.        if sCommand then\
  5481.             local sPath = shell.resolveProgram( sCommand )\
  5482.             if sPath == \"rom/programs/shell\" then\
  5483.                return multishell.launch( tEnv, sPath, unpack( tWords, 2 ) )\
  5484.            elseif sPath ~= nil then\
  5485.                return multishell.launch( tEnv, \"rom/programs/shell\", sPath, unpack( tWords, 2 ) )\
  5486.            else\
  5487.                printError( \"No such program\" )\
  5488.            end\
  5489.        end\
  5490.    end\
  5491. \
  5492.    function shell.switchTab( nID )\
  5493.        multishell.setFocus( nID )\
  5494.    end\
  5495. end\
  5496. \
  5497. local tArgs = { ... }\
  5498. if #tArgs > 0 then\
  5499.    -- \"shell x y z\"\
  5500.    -- Run the program specified on the commandline\
  5501.    shell.run( ... )\
  5502. \
  5503. else\
  5504.    -- \"shell\"\
  5505.    -- Print the header\
  5506.    term.setBackgroundColor( bgColour )\
  5507.    term.setTextColour( promptColour )\
  5508.    print( os.version() )\
  5509.    term.setTextColour( textColour )\
  5510. \
  5511.    -- Run the startup program\
  5512.    if parentShell == nil then\
  5513.        shell.run( \"/rom/startup\" )\
  5514.    end\
  5515. \
  5516.    -- Read commands and execute them\
  5517.    local tCommandHistory = {}\
  5518.    while not bExit do\
  5519.        term.redirect( parentTerm )\
  5520.        term.setBackgroundColor( bgColour )\
  5521.        term.setTextColour( promptColour )\
  5522.        write( shell.dir() .. \"> \" )\
  5523.        term.setTextColour( textColour )\
  5524. \
  5525.        local sLine = read( nil, tCommandHistory )\
  5526.        table.insert( tCommandHistory, sLine )\
  5527.        shell.run( sLine )\
  5528.    end\
  5529. end",
  5530.         [ "list.lua" ] = "--[[\
  5531.  Author: Wassil Janssen a.k.a. Creator\
  5532. ]]\
  5533. \
  5534. print(\"The threads are:\")\
  5535. for i,v in pairs(Kernel.list()) do\
  5536.     print(v[1]..string.rep(\" \",5-#tostring(v[1]))..v[2]..\": \"..v[3])\
  5537. end",
  5538.         [ "reboot.lua" ] = "--[[\
  5539.  author: Wassil Janssen a.k.a. Creator\
  5540. ]]\
  5541. \
  5542. os.reboot()",
  5543.         [ "restart.lua" ] = "--[[\
  5544.  author: Wassil Janssen a.k.a. Creator\
  5545. ]]\
  5546. \
  5547. os.reboot()",
  5548.       },
  5549.       [ "permission.data" ] = "admin",
  5550.       [ "startup.txt" ] = "FileX -p:admin\
  5551. Event -p:admin",
  5552.       [ "Main.lua" ] = "--[[\
  5553.     OmniOS debug\
  5554.     app\
  5555. ]]--\
  5556. \
  5557. --[[\
  5558.     Modified version of Shell\
  5559. ]]--\
  5560. promptColour = colours.yellow\
  5561. textColour = colours.white\
  5562. bgColour = colours.black\
  5563. \
  5564. \
  5565. local function run(command,...)\
  5566.     if fs.exists(\"OmniOS/Programs/Debug/Commands/\"..command..\".lua\") and not fs.isDir(\"OmniOS/Programs/Debug/Commands/\"..command..\".lua\") then\
  5567.         local func, err = loadfile(\"OmniOS/Programs/Debug/Commands/\"..command..\".lua\")\
  5568.         if err then log.log(\"Debug\",err)  return false end\
  5569.         local overArgs = {...}\
  5570.         setfenv(func,_G)\
  5571.         if command == \"kill\" or command == \"terminate\" then\
  5572.                 func(firstArg,unpack(overArgs))\
  5573.         elseif #overArgs == 0 then\
  5574.             local ok, data = pcall(func)\
  5575.             if not ok then log.log(\"Debug\",data) end\
  5576.         else\
  5577.             local ok, data = pcall(func,unpack(overArgs))\
  5578.             if not ok then log.log(\"Debug\",data) end\
  5579.         end\
  5580.     else\
  5581.         print(\"Command is non-existent! Pay more attention when writting!\")\
  5582.     end\
  5583. end\
  5584. \
  5585. local function tokenise( ... )\
  5586.     local sLine = table.concat( { ... }, \" \" )\
  5587.     local tWords = {}\
  5588.     local bQuoted = false\
  5589.     for match in string.gmatch( sLine .. \"\\\"\", \"(.-)\\\"\" ) do\
  5590.         if bQuoted then\
  5591.             table.insert( tWords, match )\
  5592.         else\
  5593.             for m in string.gmatch( match, \"[^ \\t]+\" ) do\
  5594.                 table.insert( tWords, m )\
  5595.             end\
  5596.         end\
  5597.         bQuoted = not bQuoted\
  5598.     end\
  5599.     return tWords\
  5600. end\
  5601. \
  5602. if not OmniOS or not type(OmniOS) == \"table\" then OmniOS = {} end\
  5603. OmniOS.debug = {}\
  5604. \
  5605. function OmniOS.debug.run( ... )\
  5606.     local tWords = tokenise( ... )\
  5607.     local sCommand = tWords[1]\
  5608.     if sCommand then\
  5609.         return run( sCommand, unpack( tWords, 2 ) )\
  5610.     end\
  5611.     return false\
  5612. end\
  5613. \
  5614. local file = fs.open(\"OmniOS/Programs/Debug/startup.txt\",\"r\")\
  5615. local data = file.readAll()\
  5616. file.close()\
  5617. local toOpen = {}\
  5618. for token in data:gmatch(\"[^\\n]+\") do\
  5619.     toOpen[#toOpen+1] = token\
  5620. end\
  5621. for i,v in pairs(toOpen) do\
  5622.     OmniOS.debug.run(\"launch \"..v)\
  5623. end\
  5624. --Kernel.switch(\"FileX1\")\
  5625. \
  5626. term.setCursorPos(1,1)\
  5627. term.setBackgroundColor( bgColour )\
  5628. term.setTextColour( promptColour )\
  5629. term.clear()\
  5630. print(\"OmniOS/Debug\")\
  5631. term.setTextColour( textColour )\
  5632. \
  5633. -- Read commands and execute them\
  5634. local tCommandHistory = {}\
  5635. while true do\
  5636.     term.setBackgroundColor( bgColour )\
  5637.     term.setTextColour( promptColour )\
  5638.     write(\"> \")\
  5639.     term.setTextColour( textColour )\
  5640. \
  5641.     local sLine = read( nil, tCommandHistory )\
  5642.     table.insert( tCommandHistory, sLine )\
  5643.     OmniOS.debug.run( sLine )\
  5644. end",
  5645.     },
  5646.     BetterPaint = {
  5647.       disk = {},
  5648.       [ "main.lua" ] = "transparentIcon = \"-\"\
  5649. args = {...}\
  5650. tX, tY = term.getSize()\
  5651. \
  5652. function drawImage(file,xSet,ySet,redirection)\
  5653. init()\
  5654. lastImage = file\
  5655. lastX = xSet\
  5656. lastY = ySet\
  5657. lastRedirection = redirection\
  5658. if redirection then\
  5659.  current = term.current()\
  5660.  term.redirect(redirection)\
  5661. end\
  5662. drawData(xSet,ySet,file)\
  5663. if redirection then\
  5664.  term.redirect(current)\
  5665. end\
  5666. end\
  5667. \
  5668. function overWrite(textSet,xSet,ySet,colorSet)\
  5669. init()\
  5670. exists = true\
  5671. if not lastImage then\
  5672.  error(\"Use drawImage first!\")\
  5673. end\
  5674. if not writeBuffer then\
  5675.  writeBuffer = {}\
  5676. end\
  5677. if not writeBuffer[lastImage] then\
  5678.  writeBuffer[lastImage] = {}\
  5679. end\
  5680. plusPos = 0\
  5681. for char in string.gmatch(textSet,\".\") do\
  5682.  if not writeBuffer[lastImage][xSet+plusPos] then\
  5683.   writeBuffer[lastImage][xSet+plusPos] = {}\
  5684.  end\
  5685.  if not writeBuffer[lastImage][xSet+plusPos][ySet] then\
  5686.   writeBuffer[lastImage][xSet+plusPos][ySet] = {colors.black,\" \",colors.white}\
  5687.  end\
  5688.  writeBuffer[lastImage][xSet+plusPos][ySet][2] = char\
  5689.  writeBuffer[lastImage][xSet+plusPos][ySet][3] = colorSet\
  5690.  plusPos = plusPos + 1 \
  5691. end\
  5692. drawImage(lastImage,lastX,lastY,lastRedirection)\
  5693. end\
  5694. \
  5695. function init()\
  5696. function eventHandler()\
  5697. while true do\
  5698.  event = {os.pullEvent()}\
  5699.  if event[1] == \"key\" then\
  5700.   if event[2] == keys.leftCtrl or event[2] == 157 then\
  5701.    menuStatus = not menuStatus\
  5702.    writeMenuBar(menuStatus)\
  5703.   end\
  5704.   if menuStatus == true then\
  5705.    if event[2] == keys.right or event[2] == keys.left then\
  5706.     if menuItemSelected == 1 then\
  5707.      menuItemSelected = 2\
  5708.     else\
  5709.      menuItemSelected = 1\
  5710.     end\
  5711.     writeMenuBar(menuStatus)\
  5712.    elseif event[2] == keys.enter then\
  5713.     if menuItemSelected == 1 then\
  5714.      save()\
  5715.      writeMenuBar(false)\
  5716.     else\
  5717.      term.setTextColor(colors.yellow)\
  5718.      term.setBackgroundColor(colors.black)\
  5719.      term.clear()\
  5720.      term.setCursorPos(1,1)\
  5721.      error()\
  5722.     end\
  5723.    end\
  5724.   else   \
  5725.    if event[2] == keys.right then\
  5726.     drawData(offSetX-1,offSetY)\
  5727.     drawMenu()\
  5728.     writeMenuBar(menuStatus)\
  5729.    elseif event[2] == keys.left then\
  5730.     drawData(offSetX+1,offSetY)\
  5731.     drawMenu()\
  5732.     writeMenuBar(menuStatus)\
  5733.    elseif event[2] == keys.up then\
  5734.     drawData(offSetX,offSetY+1)\
  5735.     drawMenu()\
  5736.     writeMenuBar(menuStatus)\
  5737.    elseif event[2] == keys.down then\
  5738.     drawData(offSetX,offSetY-1)\
  5739.     drawMenu()\
  5740.     writeMenuBar(menuStatus)\
  5741.    end\
  5742.   end\
  5743.  end\
  5744.  if event[1] == \"mouse_click\" or event[1] == \"mouse_drag\" then\
  5745.   if event[3] > 2 and event[4] ~= tY then\
  5746.    insertItem(event[3],event[4],event[2])\
  5747.   elseif event[4] < 18 and event[4] > 1 then\
  5748.    if event[3] == 1 then\
  5749.     bgSelected = 2^(event[4]-2)\
  5750.    elseif event[3] == 2 then\
  5751.     tSelected = 2^(event[4]-2)\
  5752.    end\
  5753.    drawMenu()\
  5754.   elseif event[4] == tY - 1 and event[3] == 1 then\
  5755.    setLetter()\
  5756.    drawData(offSetX,offSetY)\
  5757.    drawMenu()\
  5758.   elseif event[3] == tX and event[4] == tY and menuStatus == false then\
  5759.    writeHelp()\
  5760.   end\
  5761.  end\
  5762.  if event[1] == \"char\" then\
  5763.   textSelected = string.sub(event[2],1,1)\
  5764.   drawMenu()\
  5765.  end\
  5766.  --drawData(offSetX,offSetY)\
  5767. end\
  5768. end\
  5769. \
  5770. function writeHelp()\
  5771. term.setBackgroundColor(colors.black)\
  5772. term.setTextColor(colors.green)\
  5773. term.clear()\
  5774. term.setCursorPos(1,1)\
  5775. term.write(\"Help:\")\
  5776. term.setTextColor(colors.white)\
  5777. term.setCursorPos(1,3)\
  5778. print(\"Usage:\")\
  5779. term.setTextColor(colors.lightGray)\
  5780. print(\"  Select color: Click on the color on the left\")\
  5781. print(\"  Change draw char: Press a key on the keyboard\")\
  5782. print(\"  Change transparent icon: Click on the icon's char in the menu\")\
  5783. print(\"  Change text color: Click on a color in the menu on the right side\")\
  5784. print(\"  Change background color: Click on a color in the menu on the left side\")\
  5785. term.setTextColor(colors.white)\
  5786. print()\
  5787. print(\"Controls:\")\
  5788. term.setTextColor(colors.lightGray)\
  5789. print(\"  Arrow keys to pan\")\
  5790. print(\"  Left mouse button to select and draw\")\
  5791. print(\"  Right mouse button to delete\")\
  5792. print(\"  Ctrl to open menu\")\
  5793. print()\
  5794. term.setTextColor(colors.white)\
  5795. term.write(\"Click a mouse button to exit.\")\
  5796. term.setTextColor(colors.orange)\
  5797. term.setCursorPos(tX-9,1)\
  5798. term.write(\"API help >\")\
  5799. event = {os.pullEvent(\"mouse_click\")}\
  5800. if event[3] > tX-10 and event[4] == 1 then\
  5801.  drawAPIhelp()\
  5802. end\
  5803. drawData(offSetX,offSetY)\
  5804. drawMenu()\
  5805. writeMenuBar(menuStatus)\
  5806. end\
  5807. \
  5808. function drawAPIhelp()\
  5809. term.clear()\
  5810. term.setCursorPos(1,1)\
  5811. term.setTextColor(colors.orange)\
  5812. print(\"API help menu:\")\
  5813. print()\
  5814. term.setTextColor(colors.white)\
  5815. print(\"Drawing an image: \")\
  5816. term.setTextColor(colors.lightGray)\
  5817. print(shell.getRunningProgram(),\".drawImage(<file name>,<x pos>,<y pos>,[redirection object])\")\
  5818. print()\
  5819. term.setTextColor(colors.white)\
  5820. print(\"Overlaying text on the last image:\")\
  5821. term.setTextColor(colors.lightGray)\
  5822. print(shell.getRunningProgram(),\".overWrite(<Text>,<x pos>,<y pos>,<text color>\")\
  5823. print()\
  5824. term.setTextColor(colors.red)\
  5825. print(\"Overwriting text will only work AFTER drawing an image!\")\
  5826. term.setTextColor(colors.white)\
  5827. print()\
  5828. print(\"Example:\")\
  5829. term.setTextColor(colors.lightGray)\
  5830. print(\"os.loadAPI(\\\"\",shell.getRunningProgram(),\"\\\")\")\
  5831. print(shell.getRunningProgram(),\".drawImage(\\\"myPicture\\\",1,1)\")\
  5832. print(shell.getRunningProgram(),\".overWrite(\\\"Hello!\\\",2,3,colors.orange)\")\
  5833. os.pullEvent(\"mouse_click\")\
  5834. end\
  5835. \
  5836. function setLetter()\
  5837. term.setBackgroundColor(colors.red)\
  5838. term.setTextColor(colors.black)\
  5839. for i=1,4 do\
  5840.  term.setCursorPos(tX/2-11,(tY/2-4)+i)\
  5841.  term.write(\"                     \")\
  5842. end\
  5843. term.setCursorPos(tX/2-10,tY/2-2)\
  5844. term.write(\"Change transparancy\")\
  5845. term.setCursorPos(tX/2-10,tY/2-1)\
  5846. term.write(\"character to: (key)\")\
  5847. event = {os.pullEvent(\"char\")}\
  5848. transparentIcon = event[2]\
  5849. end\
  5850. \
  5851. function insertItem(xPos,yPos,modeSet)\
  5852. if saved == true then\
  5853.  saved = false\
  5854.  writeMenuBar(false)\
  5855. end\
  5856. --bgSelected\
  5857. --tSelected\
  5858. --textSelected\
  5859. if not painted then\
  5860.  painted = {}\
  5861. end\
  5862. if not painted[xPos-offSetX] then\
  5863.  painted[xPos-offSetX] = {}\
  5864. end\
  5865. if modeSet == 1 then\
  5866.   if not textSelected then\
  5867.    textSelected = \" \"\
  5868.   end\
  5869.   TMPtextSelected = textSelected\
  5870.   painted[xPos-offSetX][yPos-offSetY] = {bgSelected,textSelected,tSelected}\
  5871.   term.setBackgroundColor(bgSelected)\
  5872.   term.setTextColor(tSelected)\
  5873.  else\
  5874.   TMPtextSelected = transparentIcon\
  5875.   term.setBackgroundColor(colors.black)\
  5876.   term.setTextColor(colors.gray)\
  5877.   painted[xPos-offSetX][yPos-offSetY] = nil\
  5878. end\
  5879. term.setCursorPos(xPos,yPos)\
  5880. term.write(TMPtextSelected)\
  5881. end\
  5882. \
  5883. --if #args ~= 1 then\
  5884. -- print(\"Usage: \"..shell.getRunningProgram()..\" <path>\")\
  5885. -- return\
  5886. --end\
  5887. \
  5888. if args[1] and fs.exists(args[1]) == true then\
  5889. buff = fs.open(args[1],\"r\")\
  5890. previousData = buff.readAll()\
  5891. buff.close()\
  5892. processed = string.sub(previousData,43)\
  5893. painted = textutils.unserialize(processed)\
  5894. else\
  5895. painted = {}\
  5896. end\
  5897. \
  5898. function save()\
  5899. file = fs.open(args[1],\"w\")\
  5900. file.write(\"error('This is an image, not a program!')\\n\"..textutils.serialize(painted))\
  5901. file.close()\
  5902. saved = true\
  5903. end\
  5904. \
  5905. function drawData(xStart, yStart, file)\
  5906. offSetX = xStart\
  5907. offSetY = yStart\
  5908. if not file then\
  5909.  term.setBackgroundColor(colors.black)\
  5910.  term.setTextColor(colors.gray)\
  5911.  transparentLine = \"\"\
  5912.  for x=1,tX-2 do\
  5913.   transparentLine = transparentIcon..transparentLine\
  5914.  end\
  5915.  for y=1,tY-1 do\
  5916.   term.setCursorPos(3,y)\
  5917.   term.write(transparentLine)\
  5918.  end\
  5919. else\
  5920.  if fs.exists(file) == false then\
  5921.   error(\"File given doesnt exists! file name: \"..file)\
  5922.  else\
  5923.   local fileD = fs.open(file,\"r\")\
  5924.   raw = fileD.readAll()\
  5925.   --ignoreL = string.len(fileD.readLine(1))\
  5926.   processed = string.sub(raw,43)\
  5927.   --term.redirect(term.native())\
  5928.  -- textutils.pagedPrint(processed)\
  5929.   painted = textutils.unserialize(processed)\
  5930.   fileD.close()\
  5931.  end\
  5932. end\
  5933. if not painted then\
  5934.  painted = {}\
  5935. end\
  5936. paintedF = painted\
  5937. count = 0\
  5938. repeat ---------\
  5939. count = count + 1\
  5940. for xPos,v in pairs(paintedF) do\
  5941.  for yPos in pairs (paintedF[xPos]) do\
  5942.    overWrite = true\
  5943.    if not lastImage or not writeBuffer or not writeBuffer[lastImage] then\
  5944.     overWrite = false\
  5945.    end\
  5946.    if overWrite == true then\
  5947.     if not writeBuffer[lastImage][xPos] then\
  5948.      overWrite = false\
  5949.     end\
  5950.    end\
  5951.    if overWrite == true then\
  5952.     if not writeBuffer[lastImage][xPos][yPos] then\
  5953.      overWrite = false\
  5954.     end\
  5955.    end\
  5956.    if overWrite == false then\
  5957.     bgColor = paintedF[xPos][yPos][1]\
  5958.     text = paintedF[xPos][yPos][2]\
  5959.     tColor = paintedF[xPos][yPos][3]\
  5960.    else\
  5961.     if painted and painted[xPos] and painted[xPos][yPos] and painted[xPos][yPos][1] then\
  5962.      bgColor = painted[xPos][yPos][1]\
  5963.      else\
  5964.      bgColor = colors.black\
  5965.     end\
  5966.     --if not bgColor then\
  5967.    --  bgColor = colors.black\
  5968.     --end\
  5969.     text = writeBuffer[lastImage][xPos][yPos][2]\
  5970.     tColor = writeBuffer[lastImage][xPos][yPos][3]\
  5971.    end\
  5972.    if not tColor then\
  5973.     tColor = colors.white\
  5974.    end\
  5975.    if not text then\
  5976.     text = \" \"\
  5977.    end\
  5978.    term.setCursorPos(xPos+xStart,yPos+yStart)\
  5979.    term.setBackgroundColor(bgColor)\
  5980.    term.setTextColor(tColor)\
  5981.    term.write(text)\
  5982.   end\
  5983.  end\
  5984.  if count == 1 and writeBuffer and lastImage then\
  5985.   paintedF = writeBuffer[lastImage]\
  5986.  elseif count == 1 and not lastImage or not writeBuffer then\
  5987.   count = 2\
  5988.  end\
  5989. until count == 2\
  5990. term.setCursorPos(1,tY)\
  5991. end\
  5992. \
  5993. function drawMenu()\
  5994. term.setCursorPos(1,1)\
  5995. term.setTextColor(colors.white)\
  5996. if not bgSelected then\
  5997.  bgSelected = colors.black\
  5998. elseif bgSelected == colors.white then\
  5999.  term.setTextColor(colors.black)\
  6000. end\
  6001. if not tSelected then\
  6002.  tSelected = colors.white\
  6003. elseif tSelected == colors.white then\
  6004.  term.setTextColor(colors.black)\
  6005. end\
  6006. if not textSelected then\
  6007.  textSelected = \" \"\
  6008. end\
  6009. term.setBackgroundColor(bgSelected)\
  6010. term.write(\"B\")\
  6011. term.setBackgroundColor(tSelected)\
  6012. term.write(\"T\")\
  6013. for i=1,16 do\
  6014.  i=i-1\
  6015.  term.setCursorPos(1,i+2)\
  6016.  term.setBackgroundColor(2^i)\
  6017.  term.write(\"  \")\
  6018. end\
  6019. term.setCursorPos(1,18)\
  6020. term.setBackgroundColor(colors.black)\
  6021. if not textSelected then\
  6022.  textSelected = \" \"\
  6023. elseif string.len(textSelected) > 1 then\
  6024.  textSelected = string.sub(textSelected,1,1)\
  6025. end\
  6026. term.setTextColor(colors.gray)\
  6027. term.setBackgroundColor(colors.black)\
  6028. term.write(transparentIcon)\
  6029. term.setTextColor(tSelected)\
  6030. term.setBackgroundColor(bgSelected)\
  6031. term.write(textSelected)\
  6032. end\
  6033. \
  6034. function writeMenuBar(booly)\
  6035. menuStatus = booly\
  6036. term.setBackgroundColor(colors.black)\
  6037. if booly == true then\
  6038.  term.setCursorPos(1,tY)\
  6039.  term.clearLine()\
  6040.  if not menuItemSelected then\
  6041.   menuItemSelected = 1\
  6042.  end\
  6043.  term.setTextColor(colors.white)\
  6044.  term.write(\" Save  Exit \")\
  6045.  term.setCursorPos(6*menuItemSelected-5,tY)\
  6046.  term.setTextColor(colors.yellow)\
  6047.  term.write(\"[\")\
  6048.  term.setCursorPos(6*menuItemSelected,tY)\
  6049.  term.write(\"]\")\
  6050. elseif booly == false then\
  6051.  term.setCursorPos(1,tY)\
  6052.  term.setTextColor(colors.yellow)\
  6053.  term.clearLine()\
  6054.  if saved == true then\
  6055.   term.write(\"Saved to \"..args[1])\
  6056.  else\
  6057.   term.write(\"Press Ctrl to access menu\")\
  6058.  end\
  6059.  term.setCursorPos(tX,tY)\
  6060.  term.setTextColor(colors.lightGray)\
  6061.  term.write(\"?\")\
  6062. end\
  6063. end\
  6064. end\
  6065. \
  6066. if #args > 0 then\
  6067.  init()\
  6068.  menuStatus = false\
  6069.  saved = false\
  6070.  writeMenuBar(menuStatus)\
  6071.  menuItemSelected = 1\
  6072.  drawData(3,0)\
  6073.  drawMenu()\
  6074.  eventHandler()\
  6075. else\
  6076.  term.setBackgroundColor(colors.black)\
  6077.  term.setTextColor(colors.white)\
  6078.  term.clear()\
  6079.  term.setCursorPos(1,1)\
  6080.  term.write(\"Do you want to create a new file? <y/n>\")\
  6081.  local answ = read()\
  6082.  if answ:sub(1,1) == \"y\" then\
  6083.    print()\
  6084.    term.write(\"Path please!\")\
  6085.    args[1] = \"OmniOS/Data/\"..read()\
  6086.     init()\
  6087.      menuStatus = false\
  6088.      saved = false\
  6089.      writeMenuBar(menuStatus)\
  6090.      menuItemSelected = 1\
  6091.      drawData(3,0)\
  6092.      drawMenu()\
  6093.      eventHandler()\
  6094.  end\
  6095. end",
  6096.       [ "permission.data" ] = "user",
  6097.       [ "BetterPaint.ico" ] = "error('This is an image, not a program!')\
  6098. {\
  6099.  {\
  6100.    {\
  6101.      1,\
  6102.      \"'\",\
  6103.      256,\
  6104.    },\
  6105.    {\
  6106.      8,\
  6107.      \" \",\
  6108.      8,\
  6109.    },\
  6110.    {\
  6111.      32,\
  6112.      \"w\",\
  6113.      8192,\
  6114.    },\
  6115.  },\
  6116.  {\
  6117.    {\
  6118.      8,\
  6119.      \" \",\
  6120.      8,\
  6121.    },\
  6122.    {\
  6123.      8,\
  6124.      \" \",\
  6125.      8,\
  6126.    },\
  6127.    {\
  6128.      32,\
  6129.      \"w\",\
  6130.      8192,\
  6131.    },\
  6132.  },\
  6133.  {\
  6134.    {\
  6135.      8,\
  6136.      \"@\",\
  6137.      16,\
  6138.    },\
  6139.    {\
  6140.      8,\
  6141.      \" \",\
  6142.      8,\
  6143.    },\
  6144.    {\
  6145.      32,\
  6146.      \"w\",\
  6147.      8192,\
  6148.    },\
  6149.  },\
  6150.  [ 0 ] = {\
  6151.    {\
  6152.      1,\
  6153.      \"'\",\
  6154.      256,\
  6155.    },\
  6156.    {\
  6157.      8,\
  6158.      \" \",\
  6159.      8,\
  6160.    },\
  6161.    {\
  6162.      32,\
  6163.      \"w\",\
  6164.      8192,\
  6165.    },\
  6166.  },\
  6167. }",
  6168.     },
  6169.     FileX = {
  6170.       disk = {},
  6171.       [ "permission.data" ] = "user",
  6172.       [ "hohoho.txt" ] = "",
  6173.       Data = {
  6174.         shell = "local path = \"\"\
  6175. local args = \"\"\
  6176. local tArgs = {...}\
  6177. for i,v in pairs(tArgs) do \
  6178.  if i == 1 then\
  6179.    path = v\
  6180.  else\
  6181.    args = args..\" \"..v\
  6182.  end\
  6183. end\
  6184. pcall(shell.run,path..\" \"..args)",
  6185.         nPaintPro = "--[[\
  6186.         NPaintPro\
  6187.         By NitrogenFingers\
  6188. ]]--\
  6189. \
  6190. --The screen size\
  6191. local w,h = term.getSize()\
  6192. --Whether or not the program is currently waiting on user input\
  6193. local inMenu = false\
  6194. --Whether or not a drop down menu is active\
  6195. local inDropDown = false\
  6196. --Whether or not animation tools are enabled (use -a to turn them on)\
  6197. local animated = false\
  6198. --Whether or not \"blueprint\" display mode is on\
  6199. local blueprint = false\
  6200. --Whether or not the \"layer\" display is on\
  6201. local layerDisplay = false\
  6202. --Whether or not the \"direction\" display is on\
  6203. local printDirection = false\
  6204. --The tool/mode npaintpro is currently in. Default is \"paint\"\
  6205. --For a list of modes, check out the help file\
  6206. local state = \"paint\"\
  6207. --Whether or not the program is presently running\
  6208. local isRunning = true\
  6209. --The rednet address of the 3D printer, if one has been attached\
  6210. local printer = nil\
  6211. \
  6212. --The list of every frame, containing every image in the picture/animation\
  6213. --Note: nfp files always have the picture at frame 1\
  6214. local frames = { }\
  6215. --How many frames are currently in the given animation.\
  6216. local frameCount = 1\
  6217. --The Colour Picker column\
  6218. local column = {}\
  6219. --The currently selected left and right colours\
  6220. local lSel,rSel = colours.white,nil\
  6221. --The amount of scrolling on the X and Y axis\
  6222. local sx,sy = 0,0\
  6223. --The alpha channel colour\
  6224. --Change this to change default canvas colour\
  6225. local alphaC = colours.yellow\
  6226. --The currently selected frame. Default is 1\
  6227. local sFrame = 1\
  6228. --The contents of the image buffer- contains contents, width and height\
  6229. local buffer = nil\
  6230. --The position, width and height of the selection rectangle\
  6231. local selectrect = nil\
  6232. \
  6233. --The currently calculated required materials\
  6234. local requiredMaterials = {}\
  6235. --Whether or not required materials are being displayed in the pallette\
  6236. local requirementsDisplayed = false\
  6237. --A list of the rednet ID's all in-range printers located\
  6238. local printerList = { }\
  6239. --A list of the names of all in-range printers located. Same as the printerList in reference\
  6240. local printerNames = { }\
  6241. --The selected printer\
  6242. local selectedPrinter = 1\
  6243. --The X,Y,Z and facing of the printer\
  6244. local px,py,pz,pfx,pfz = 0,0,0,0,0\
  6245. --The form of layering used\
  6246. local layering = \"up\"\
  6247. \
  6248. --The animation state of the selection rectangle and image buffer \
  6249. local rectblink = 0\
  6250. --The ID for the timer\
  6251. local recttimer = nil\
  6252. --The radius of the brush tool\
  6253. local brushsize = 3\
  6254. --Whether or not \"record\" mode is activated (animation mode only)\
  6255. local record = false\
  6256. --The time between each frame when in play mode (animation mode only)\
  6257. local animtime = 0.3\
  6258. \
  6259. --A list of hexidecimal conversions from numbers to hex digits\
  6260. local hexnums = { [10] = \"a\", [11] = \"b\", [12] = \"c\", [13] = \"d\", [14] = \"e\" , [15] = \"f\" }\
  6261. --The NPaintPro logo (divine, isn't it?)\
  6262. local logo = {\
  6263. \"fcc              3   339\";\
  6264. \" fcc          9333    33\";\
  6265. \"  fcc        933 333  33\";\
  6266. \"   fcc       933  33  33\";\
  6267. \"    fcc      933   33 33\";\
  6268. \"     c88     333   93333\";\
  6269. \"     888     333    9333\";\
  6270. \"      333 3  333     939\";\
  6271. }\
  6272. --The Layer Up and Layer Forward printing icons\
  6273. local layerUpIcon = {\
  6274.     \"0000000\";\
  6275.     \"0088880\";\
  6276.     \"0888870\";\
  6277.     \"07777f0\";\
  6278.     \"0ffff00\";\
  6279.     \"0000000\";\
  6280. }\
  6281. local layerForwardIcon = {\
  6282.     \"0000000\";\
  6283.     \"000fff0\";\
  6284.     \"00777f0\";\
  6285.     \"0888700\";\
  6286.     \"0888000\";\
  6287.     \"0000000\";\
  6288. }\
  6289. --The available menu options in the ctrl menu\
  6290. local mChoices = {\"Save\",\"Exit\"}\
  6291. --The available modes from the dropdown menu- tables indicate submenus (include a name!)\
  6292. local ddModes = { { \"paint\", \"brush\", \"pippette\", \"flood\", \"move\", \"clear\", \"select\", name = \"painting\" }, { \"alpha to left\", \"alpha to right\", \"blueprint on\", \"layers on\", name = \"display\" }, \"help\", { \"print\", \"save\", \"exit\", name = \"file\" }, name = \"menu\" }\
  6293. --The available modes from the selection right-click menu\
  6294. local srModes = { \"cut\", \"copy\", \"paste\", \"clear\", \"hide\", name = \"selection\" }\
  6295. --The list of available help topics for each mode 127\
  6296. local helpTopics = {\
  6297.     [1] = {\
  6298.         name = \"Paint Mode\",\
  6299.         key = nil,\
  6300.         animonly = false,\
  6301.         message = \"The default mode for NPaintPro, for painting pixels.\"\
  6302.         ..\" Controls here that are not overridden will apply for all other modes. Leaving a mode by selecting that mode \"\
  6303.         ..\" again will always send the user back to paint mode.\",\
  6304.         controls = {\
  6305.             { \"Arrow keys\", \"Scroll the canvas\" },\
  6306.             { \"Left Click\", \"Paint/select left colour\" },\
  6307.             { \"Right Click\", \"Paint/select right colour\" },\
  6308.             { \"Z Key\", \"Clear image on screen\" },\
  6309.             { \"Tab Key\", \"Hide selection rectangle if visible\" },\
  6310.             { \"Q Key\", \"Set alpha mask to left colour\" },\
  6311.             { \"W Key\", \"Set alpha mask to right colour\" },\
  6312.             { \"Number Keys\", \"Swich between frames 1-9\" },\
  6313.             { \"</> keys\", \"Move to the next/last frame\" },\
  6314.             { \"R Key\", \"Removes every frame after the current frame\"}\
  6315.         }\
  6316.     },\
  6317.     [2] = {\
  6318.         name = \"Brush Mode\",\
  6319.         key = \"b\",\
  6320.         animonly = false,\
  6321.         message = \"Brush mode allows painting a circular area of variable diameter rather than a single pixel, working in \"..\
  6322.         \"the exact same way as paint mode in all other regards.\",\
  6323.         controls = {\
  6324.             { \"Left Click\", \"Paints a brush blob with the left colour\" },\
  6325.             { \"Right Click\", \"Paints a brush blob with the right colour\" },\
  6326.             { \"Number Keys\", \"Changes the radius of the brush blob from 2-9\" }\
  6327.         }\
  6328.     },\
  6329.     [3] = {\
  6330.         name = \"Pippette Mode\",\
  6331.         key = \"p\",\
  6332.         animonly = false,\
  6333.         message = \"Pippette mode allows the user to click the canvas and set the colour clicked to the left or right \"..\
  6334.         \"selected colour, for later painting.\",\
  6335.         controls = {\
  6336.             { \"Left Click\", \"Sets clicked colour to the left selected colour\" },\
  6337.             { \"Right Click\", \"Sets clicked colour to the right selected colour\" }\
  6338.         }\
  6339.     },\
  6340.     [4] = {\
  6341.         name = \"Move Mode\",\
  6342.         key = \"m\",\
  6343.         animonly = false,\
  6344.         message = \"Mode mode allows the moving of the entire image on the screen. This is especially useful for justifying\"..\
  6345.         \" the image to the top-left for animations or game assets.\",\
  6346.         controls = {\
  6347.             { \"Left/Right Click\", \"Moves top-left corner of image to selected square\" },\
  6348.             { \"Arrow keys\", \"Moves image one pixel in any direction\" }\
  6349.         }\
  6350.     },\
  6351.     [5] = {\
  6352.         name = \"Flood Mode (NYI)\",\
  6353.         key = \"f\",\
  6354.         animonly = false,\
  6355.         message = \"Flood mode allows the changing of an area of a given colour to that of the selected colour. \"..\
  6356.         \"The tool uses a flood4 algorithm and will not fill diagonally. Transparency cannot be flood filled.\",\
  6357.         controls = {\
  6358.             { \"Left Click\", \"Flood fills selected area to left colour\" },\
  6359.             { \"Right Click\", \"Flood fills selected area to right colour\" }\
  6360.         }\
  6361.     },\
  6362.     [6] = {\
  6363.         name = \"Select Mode\",\
  6364.         key = \"s\",\
  6365.         animonly = false,\
  6366.         message = \"Select mode allows the creation and use of the selection rectangle, to highlight specific areas on \"..\
  6367.         \"the screen and perform operations on the selected area of the image. The selection rectangle can contain an \"..\
  6368.         \"image on the clipboard- if it does, the image will flash inside the rectangle, and the rectangle edges will \"..\
  6369.         \"be light grey instead of dark grey.\",\
  6370.         controls = {\
  6371.             { \"C Key\", \"Copy: Moves selection into the clipboard\" },\
  6372.             { \"X Key\", \"Cut: Clears canvas under the rectangle, and moves it into the clipboard\" },\
  6373.             { \"V Key\", \"Paste: Copys clipboard to the canvas\" },\
  6374.             { \"Z Key\", \"Clears clipboard\" },\
  6375.             { \"Left Click\", \"Moves top-left corner of rectangle to selected pixel\" },\
  6376.             { \"Right Click\", \"Opens selection menu\" },\
  6377.             { \"Arrow Keys\", \"Moves rectangle one pixel in any direction\" }\
  6378.         }\
  6379.     },\
  6380.     [7] = {\
  6381.         name = \"Corner Select Mode\",\
  6382.         key = nil,\
  6383.         animonly = false,\
  6384.         message = \"If a selection rectangle isn't visible, this mode is selected automatically. It allows the \"..\
  6385.         \"defining of the corners of the rectangle- one the top-left and bottom-right corners have been defined, \"..\
  6386.         \"NPaintPro switches to selection mode. Note rectangle must be at least 2 pixels wide and high.\",\
  6387.         controls = {\
  6388.             { \"Left/Right Click\", \"Defines a corner of the selection rectangle\" }\
  6389.         }\
  6390.     },\
  6391.     [8] = {\
  6392.         name = \"Play Mode\",\
  6393.         key = \"space\",\
  6394.         animonly = true,\
  6395.         message = \"Play mode will loop through each frame in your animation at a constant rate. Editing tools are \"..\
  6396.         \"locked in this mode, and the coordinate display will turn green to indicate it is on.\",\
  6397.         controls = {\
  6398.             { \"</> Keys\", \"Increases/Decreases speed of the animation\" },\
  6399.             { \"Space Bar\", \"Returns to paint mode\" }\
  6400.         }\
  6401.     },\
  6402.     [9] = {\
  6403.         name = \"Record Mode\",\
  6404.         key = \"\\\\\",\
  6405.         animonly = true,\
  6406.         message = \"Record mode is not a true mode, but influences how other modes work. Changes made that modify the \"..\
  6407.         \"canvas in record mode will affect ALL frames in the animation. The coordinates will turn red to indicate that \"..\
  6408.         \"record mode is on.\",\
  6409.         controls = {\
  6410.             { \"\", \"Affects:\" },\
  6411.             { \"- Paint Mode\", \"\" },\
  6412.             { \"- Brush Mode\", \"\" },\
  6413.             { \"- Cut and Paste in Select Mode\", \"\"},\
  6414.             { \"- Move Mode\", \"\"}\
  6415.         }\
  6416.     },\
  6417.     [10] = {\
  6418.         name = \"Help Mode\",\
  6419.         key = \"h\",\
  6420.         animonly = false,\
  6421.         message = \"Displays this help screen. Clicking on options will display help on that topic. Clicking out of the screen\"..\
  6422.         \" will leave this mode.\",\
  6423.         controls = {\
  6424.             { \"Left/Right Click\", \"Displays a topic/Leaves the mode\" }\
  6425.         }\
  6426.     },\
  6427.     [11] = {\
  6428.         name = \"File Mode\",\
  6429.         keys = nil,\
  6430.         animonly = false,\
  6431.         message = \"Clicking on the mode display at the bottom of the screen will open the options menu. Here you can\"..\
  6432.         \" activate all of the modes in the program with a simple mouse click. Pressing left control will open up the\"..\
  6433.         \" file menu automatically.\",\
  6434.         controls = { \
  6435.             { \"leftCtrl\", \"Opens the file menu\" },\
  6436.             { \"leftAlt\", \"Opens the paint menu\" }\
  6437.             \
  6438.         }\
  6439.     }\
  6440. }\
  6441. --The \"bounds\" of the image- the first/last point on both axes where a pixel appears\
  6442. local toplim,botlim,leflim,riglim = nil,nil,nil,nil\
  6443. --The selected path\
  6444. local sPath = nil\
  6445. \
  6446. --[[  \
  6447.             Section:  Helpers       \
  6448. ]]--\
  6449. \
  6450. --[[Converts a colour parameter into a single-digit hex coordinate for the colour\
  6451.    Params: colour:int = The colour to be converted\
  6452.     Returns:string A string conversion of the colour\
  6453. ]]--\
  6454. local function getHexOf(colour)\
  6455.     if not colour or not tonumber(colour) then \
  6456.         return \" \" \
  6457.     end\
  6458.     local value = math.log(colour)/math.log(2)\
  6459.     if value > 9 then \
  6460.         value = hexnums[value] \
  6461.     end\
  6462.     return value\
  6463. end\
  6464. \
  6465. --[[Converts a hex digit into a colour value\
  6466.     Params: hex:?string = the hex digit to be converted\
  6467.     Returns:string A colour value corresponding to the hex, or nil if the character is invalid\
  6468. ]]--\
  6469. local function getColourOf(hex)\
  6470.     local value = tonumber(hex, 16)\
  6471.     if not value then return nil end\
  6472.     value = math.pow(2,value)\
  6473.     return value\
  6474. end\
  6475. \
  6476. --[[Finds the biggest and smallest bounds of the image- the outside points beyond which pixels do not appear\
  6477.     These values are assigned to the \"lim\" parameters for access by other methods\
  6478.     Params: forAllFrames:bool = True if all frames should be used to find bounds, otherwise false or nil\
  6479.     Returns:nil\
  6480. ]]--\
  6481. local function updateImageLims(forAllFrames)\
  6482.     local f,l = sFrame,sFrame\
  6483.     if forAllFrames == true then f,l = 1,framecount end\
  6484.     \
  6485.     toplim,botlim,leflim,riglim = nil,nil,nil,nil\
  6486.     for locf = f,l do\
  6487.         for y,_ in pairs(frames[locf]) do\
  6488.             for x,_ in pairs(frames[locf][y]) do\
  6489.                 if frames[locf][y][x] ~= nil then\
  6490.                     if leflim == nil or x < leflim then leflim = x end\
  6491.                     if toplim == nil or y < toplim then toplim = y end\
  6492.                     if riglim == nil or x > riglim then riglim = x end\
  6493.                     if botlim == nil or y > botlim then botlim = y end\
  6494.                 end\
  6495.             end\
  6496.         end\
  6497.     end\
  6498. end\
  6499. \
  6500. --[[Determines how much of each material is required for a print. Done each time printing is called.\
  6501.     Params: none\
  6502.     Returns:table A complete list of how much of each material is required.\
  6503. ]]--\
  6504. function calculateMaterials()\
  6505.     updateImageLims(animated)\
  6506.     requiredMaterials = {}\
  6507.     for i=1,16 do \
  6508.         requiredMaterials[i] = 0 \
  6509.     end\
  6510.     \
  6511.     if not toplim then return end\
  6512.     \
  6513.     for i=1,#frames do\
  6514.         for y = toplim, botlim do\
  6515.             for x = leflim, riglim do\
  6516.                 if type(frames[i][y][x]) == \"number\" then\
  6517.                     requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] = \
  6518.                         requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] + 1\
  6519.                 end \
  6520.             end\
  6521.         end\
  6522.     end\
  6523. end\
  6524. \
  6525. \
  6526. --[[Updates the rectangle blink timer. Should be called anywhere events are captured, along with a timer capture.\
  6527.     Params: nil\
  6528.     Returns:nil\
  6529. ]]--\
  6530. local function updateTimer(id)\
  6531.     if id == recttimer then\
  6532.         recttimer = os.startTimer(0.5)\
  6533.         rectblink = (rectblink % 2) + 1\
  6534.     end\
  6535. end\
  6536. \
  6537. --[[Constructs a message based on the state currently selected\
  6538.     Params: nil\
  6539.     Returns:string A message regarding the state of the application\
  6540. ]]--\
  6541. local function getStateMessage()\
  6542.     local msg = \" \"..string.upper(string.sub(state, 1, 1))..string.sub(state, 2, #state)..\" mode\"\
  6543.     if state == \"brush\" then msg = msg..\", size=\"..brushsize end\
  6544.     return msg\
  6545. end\
  6546. \
  6547. --[[Calls the rednet_message event, but also looks for timer events to keep then\
  6548.     system timer ticking.\
  6549.     Params: timeout:number how long before the event times out\
  6550.     Returns:number the id of the sender\
  6551.            :number the message send\
  6552. ]]--\
  6553. local function rsTimeReceive(timeout)\
  6554.     local timerID\
  6555.     if timeout then timerID = os.startTimer(timeout) end\
  6556.     \
  6557.     local id,key,msg = nil,nil\
  6558.     while true do\
  6559.         id,key,msg = os.pullEvent()\
  6560.         \
  6561.         if id == \"timer\" then\
  6562.             if key == timerID then return\
  6563.             else updateTimer(key) end\
  6564.         end\
  6565.         if id == \"rednet_message\" then \
  6566.             return key,msg\
  6567.         end\
  6568.     end\
  6569. end\
  6570. \
  6571. --[[Draws a picture, in paint table format on the screen\
  6572.     Params: image:table = the image to display\
  6573.             xinit:number = the x position of the top-left corner of the image\
  6574.             yinit:number = the y position of the top-left corner of the image\
  6575.             alpha:number = the color to display for the alpha channel. Default is white.\
  6576.     Returns:nil\
  6577. ]]--\
  6578. local function drawPictureTable(image, xinit, yinit, alpha)\
  6579.     if not alpha then alpha = 1 end\
  6580.     for y=1,#image do\
  6581.         for x=1,#image[y] do\
  6582.             term.setCursorPos(xinit + x-1, yinit + y-1)\
  6583.             local col = getColourOf(string.sub(image[y], x, x))\
  6584.             if not col then col = alpha end\
  6585.             term.setBackgroundColour(col)\
  6586.             term.write(\" \")\
  6587.         end\
  6588.     end\
  6589. end\
  6590. \
  6591. --[[  \
  6592.             Section: Loading  \
  6593. ]]-- \
  6594. \
  6595. --[[Loads a non-animted paint file into the program\
  6596.     Params: path:string = The path in which the file is located\
  6597.     Returns:nil\
  6598. ]]--\
  6599. local function loadNFP(path)\
  6600.     sFrame = 1\
  6601.     frames[sFrame] = { }\
  6602.     if fs.exists(path) then\
  6603.         local file = io.open(path, \"r\" )\
  6604.         local sLine = file:read()\
  6605.         local num = 1\
  6606.         while sLine do\
  6607.             table.insert(frames[sFrame], num, {})\
  6608.             for i=1,#sLine do\
  6609.                 frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))\
  6610.             end\
  6611.             num = num+1\
  6612.             sLine = file:read()\
  6613.         end\
  6614.         file:close()\
  6615.     end\
  6616. end\
  6617. \
  6618. --[[Saves a non-animated paint file to the specified path\
  6619.     Params: path:string = The path to save the file to\
  6620.     Returns:nil\
  6621. ]]--\
  6622. local function saveNFP(path)\
  6623.     local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))\
  6624.     if not fs.exists(sDir) then\
  6625.         fs.makeDir(sDir)\
  6626.     end\
  6627. \
  6628.     local file = io.open(path, \"w\")\
  6629.     updateImageLims(false)\
  6630.     if not toplim then \
  6631.         file:close()\
  6632.         return\
  6633.     end\
  6634.     for y=1,botlim do\
  6635.         local line = \"\"\
  6636.         if frames[sFrame][y] then \
  6637.             for x=1,riglim do\
  6638.                 line = line..getHexOf(frames[sFrame][y][x])\
  6639.             end\
  6640.         end\
  6641.         file:write(line..\"\\n\")\
  6642.     end\
  6643.     file:close()\
  6644. end\
  6645. \
  6646. --[[Loads an animated paint file into the program\
  6647.     Params: path:string = The path in which the file is located\
  6648.     Returns:nil\
  6649. ]]--\
  6650. local function loadNFA(path)\
  6651.     frames[sFrame] = { }\
  6652.     if fs.exists(path) then\
  6653.         local file = io.open(path, \"r\" )\
  6654.         local sLine = file:read()\
  6655.         local num = 1\
  6656.         while sLine do\
  6657.             table.insert(frames[sFrame], num, {})\
  6658.             if sLine == \"~\" then\
  6659.                 sFrame = sFrame + 1\
  6660.                 frames[sFrame] = { }\
  6661.                 num = 1\
  6662.             else\
  6663.                 for i=1,#sLine do\
  6664.                     frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))\
  6665.                 end\
  6666.                 num = num+1\
  6667.             end\
  6668.             sLine = file:read()\
  6669.         end\
  6670.         file:close()\
  6671.     end\
  6672.     framecount = sFrame\
  6673.     sFrame = 1\
  6674. end\
  6675. \
  6676. --[[Saves a animated paint file to the specified path\
  6677.     Params: path:string = The path to save the file to\
  6678.     Returns:nil\
  6679. ]]--\
  6680. local function saveNFA(path)\
  6681.     local file = io.open(path, \"w\")\
  6682.     updateImageLims(true)\
  6683.     if not toplim then \
  6684.         file:close()\
  6685.         return\
  6686.     end\
  6687.     for i=1,#frames do\
  6688.         for y=1,botlim do\
  6689.             local line = \"\"\
  6690.             if frames[i][y] then \
  6691.                 for x=1,riglim do\
  6692.                     line = line..getHexOf(frames[i][y][x])\
  6693.                 end\
  6694.             end\
  6695.             file:write(line..\"\\n\")\
  6696.         end\
  6697.         if i < #frames then file:write(\"~\\n\") end\
  6698.     end\
  6699.     file:close()\
  6700. end\
  6701. \
  6702. --[[Initializes the program, by loading in the paint file. Called at the start of each program.\
  6703.     Params: none\
  6704.     Returns:nil\
  6705. ]]--\
  6706. local function init()\
  6707.     if animated then \
  6708.         loadNFA(sPath)\
  6709.         table.insert(ddModes, #ddModes, { \"record\", \"play\", name = \"anim\" })\
  6710.         table.insert(ddModes, #ddModes, { \"go to\", \"remove\", name = \"frames\"})\
  6711.     else loadNFP(sPath) end\
  6712. \
  6713.     for i=0,15 do\
  6714.         table.insert(column, math.pow(2,i))\
  6715.     end\
  6716. end\
  6717. \
  6718. --[[  \
  6719.             Section: Drawing  \
  6720. ]]--\
  6721. \
  6722. \
  6723. --[[Draws the rather superflous logo. Takes about 1 second, before user is able to move to the\
  6724.     actual program.\
  6725.     Params: none\
  6726.     Returns:nil\
  6727. ]]--\
  6728. local function drawLogo()\
  6729.     term.setBackgroundColour(colours.white)\
  6730.     term.clear()\
  6731.     drawPictureTable(logo, w/2 - #logo[1]/2, h/2 - #logo/2, colours.white)\
  6732.     term.setBackgroundColour(colours.white)\
  6733.     term.setTextColour(colours.black)\
  6734.     local msg = \"NPaintPro\"\
  6735.     term.setCursorPos(w/2 - #msg/2, h-3)\
  6736.     term.write(msg)\
  6737.     msg = \"By NitrogenFingers\"\
  6738.     term.setCursorPos(w/2 - #msg/2, h-2)\
  6739.     term.write(msg)\
  6740.     msg = \"Thanks to faubiguy for testing\"\
  6741.     term.setCursorPos(w/2 - #msg/2, h)\
  6742.     term.write(msg)\
  6743.     \
  6744.     os.pullEvent()\
  6745. end\
  6746. \
  6747. --[[Clears the display to the alpha channel colour, draws the canvas, the image buffer and the selection\
  6748.     rectanlge if any of these things are present.\
  6749.     Params: none\
  6750.     Returns:nil\
  6751. ]]--\
  6752. local function drawCanvas()\
  6753.     --We have to readjust the position of the canvas if we're printing\
  6754.     turtlechar = \"@\"\
  6755.     if state == \"active print\" then\
  6756.         if layering == \"up\" then\
  6757.             if py >= 1 and py <= #frames then\
  6758.                 sFrame = py\
  6759.             end\
  6760.             if pz < sy then sy = pz\
  6761.             elseif pz > sy + h - 1 then sy = pz + h - 1 end\
  6762.             if px < sx then sx = px\
  6763.             elseif px > sx + w - 2 then sx = px + w - 2 end\
  6764.         else\
  6765.             if pz >= 1 and pz <= #frames then\
  6766.                 sFrame = pz\
  6767.             end\
  6768.             \
  6769.             if py < sy then sy = py\
  6770.             elseif py > sy + h - 1 then sy = py + h - 1 end\
  6771.             if px < sx then sx = px\
  6772.             elseif px > sx + w - 2 then sx = px + w - 2 end\
  6773.         end\
  6774.         \
  6775.         if pfx == 1 then turtlechar = \">\"\
  6776.         elseif pfx == -1 then turtlechar = \"<\"\
  6777.         elseif pfz == 1 then turtlechar = \"V\"\
  6778.         elseif pfz == -1 then turtlechar = \"^\"\
  6779.         end\
  6780.     end\
  6781. \
  6782.     --Picture next\
  6783.     local topLayer, botLayer\
  6784.     if layerDisplay then\
  6785.         topLayer = sFrame\
  6786.         botLayer = 1\
  6787.     else\
  6788.         topLayer,botLayer = sFrame,sFrame\
  6789.     end\
  6790.     \
  6791.     for currframe = botLayer,topLayer,1 do\
  6792.         for y=sy+1,sy+h-1 do\
  6793.             if frames[currframe][y] then \
  6794.                 for x=sx+1,sx+w-2 do\
  6795.                     term.setCursorPos(x-sx,y-sy)\
  6796.                     if frames[currframe][y][x] then\
  6797.                         term.setBackgroundColour(frames[currframe][y][x])\
  6798.                         term.write(\" \")\
  6799.                     else \
  6800.                         tileExists = false\
  6801.                         for i=currframe-1,botLayer,-1 do\
  6802.                             if frames[i][y][x] then\
  6803.                                 tileExists = true\
  6804.                                 break\
  6805.                             end\
  6806.                         end\
  6807.                         \
  6808.                         if not tileExists then\
  6809.                             if blueprint then\
  6810.                                 term.setBackgroundColour(colours.blue)\
  6811.                                 term.setTextColour(colours.white)\
  6812.                                 if x == sx+1 and y % 4 == 1 then\
  6813.                                     term.write(\"\"..((y/4) % 10))\
  6814.                                 elseif y == sy + 1 and x % 4 == 1 then\
  6815.                                     term.write(\"\"..((x/4) % 10))\
  6816.                                 elseif x % 2 == 1 and y % 2 == 1 then\
  6817.                                     term.write(\"+\")\
  6818.                                 elseif x % 2 == 1 then\
  6819.                                     term.write(\"|\")\
  6820.                                 elseif y % 2 == 1 then\
  6821.                                     term.write(\"-\")\
  6822.                                 else\
  6823.                                     term.write(\" \")\
  6824.                                 end\
  6825.                             else\
  6826.                                 term.setBackgroundColour(alphaC) \
  6827.                                 term.write(\" \")\
  6828.                             end\
  6829.                         end\
  6830.                     end\
  6831.                 end\
  6832.             else\
  6833.                 for x=sx+1,sx+w-2 do\
  6834.                     term.setCursorPos(x-sx,y-sy)\
  6835.                     \
  6836.                     tileExists = false\
  6837.                     for i=currframe-1,botLayer,-1 do\
  6838.                         if frames[i][y] and frames[i][y][x] then\
  6839.                             tileExists = true\
  6840.                             break\
  6841.                         end\
  6842.                     end\
  6843.                     \
  6844.                     if not tileExists then\
  6845.                         if blueprint then\
  6846.                             term.setBackgroundColour(colours.blue)\
  6847.                             term.setTextColour(colours.white)\
  6848.                             if x == sx+1 and y % 4 == 1 then\
  6849.                                 term.write(\"\"..((y/4) % 10))\
  6850.                             elseif y == sy + 1 and x % 4 == 1 then\
  6851.                                 term.write(\"\"..((x/4) % 10))\
  6852.                             elseif x % 2 == 1 and y % 2 == 1 then\
  6853.                                 term.write(\"+\")\
  6854.                             elseif x % 2 == 1 then\
  6855.                                 term.write(\"|\")\
  6856.                             elseif y % 2 == 1 then\
  6857.                                 term.write(\"-\")\
  6858.                             else\
  6859.                                 term.write(\" \")\
  6860.                             end\
  6861.                         else\
  6862.                             term.setBackgroundColour(alphaC) \
  6863.                             term.write(\" \")\
  6864.                         end\
  6865.                     end\
  6866.                 end\
  6867.             end\
  6868.         end\
  6869.     end\
  6870.     \
  6871.     --Then the printer, if he's on\
  6872.     if state == \"active print\" then\
  6873.         local bgColour = alphaC\
  6874.         if layering == \"up\" then\
  6875.             term.setCursorPos(px-sx,pz-sy)\
  6876.             if frames[sFrame] and frames[sFrame][pz-sy] and frames[sFrame][pz-sy][px-sx] then\
  6877.                 bgColour = frames[sFrame][pz-sy][px-sx]\
  6878.             elseif blueprint then bgColour = colours.blue end\
  6879.         else\
  6880.             term.setCursorPos(px-sx,py-sy)\
  6881.             if frames[sFrame] and frames[sFrame][py-sy] and frames[sFrame][py-sy][px-sx] then\
  6882.                 bgColour = frames[sFrame][py-sy][px-sx]\
  6883.             elseif blueprint then bgColour = colours.blue end\
  6884.         end\
  6885.         \
  6886.         term.setBackgroundColour(bgColour)\
  6887.         if bgColour == colours.black then term.setTextColour(colours.white)\
  6888.         else term.setTextColour(colours.black) end\
  6889.         \
  6890.         term.write(turtlechar)\
  6891.     end\
  6892.     \
  6893.     --Then the buffer\
  6894.     if selectrect then\
  6895.         if buffer and rectblink == 1 then\
  6896.         for y=selectrect.y1, math.min(selectrect.y2, selectrect.y1 + buffer.height-1) do\
  6897.             for x=selectrect.x1, math.min(selectrect.x2, selectrect.x1 + buffer.width-1) do\
  6898.                 if buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1] then\
  6899.                     term.setCursorPos(x+sx,y+sy)\
  6900.                     term.setBackgroundColour(buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1])\
  6901.                     term.write(\" \")\
  6902.                 end\
  6903.             end\
  6904.         end\
  6905.         end\
  6906.     \
  6907.         --This draws the \"selection\" box\
  6908.         local add = nil\
  6909.         if buffer then\
  6910.             term.setBackgroundColour(colours.lightGrey)\
  6911.         else \
  6912.             term.setBackgroundColour(colours.grey)\
  6913.         end\
  6914.         for i=selectrect.x1, selectrect.x2 do\
  6915.             add = (i + selectrect.y1 + rectblink) % 2 == 0\
  6916.             term.setCursorPos(i-sx,selectrect.y1-sy)\
  6917.             if add then term.write(\" \") end\
  6918.             add = (i + selectrect.y2 + rectblink) % 2 == 0\
  6919.             term.setCursorPos(i-sx,selectrect.y2-sy)\
  6920.             if add then term.write(\" \") end\
  6921.         end\
  6922.         for i=selectrect.y1 + 1, selectrect.y2 - 1 do\
  6923.             add = (i + selectrect.x1 + rectblink) % 2 == 0\
  6924.             term.setCursorPos(selectrect.x1-sx,i-sy)\
  6925.             if add then term.write(\" \") end\
  6926.             add = (i + selectrect.x2 + rectblink) % 2 == 0\
  6927.             term.setCursorPos(selectrect.x2-sx,i-sy)\
  6928.             if add then term.write(\" \") end\
  6929.         end\
  6930.     end\
  6931. end\
  6932. \
  6933. --[[Draws the colour picker on the right side of the screen, the colour pallette and the footer with any \
  6934.     messages currently being displayed\
  6935.     Params: none\
  6936.     Returns:nil\
  6937. ]]--\
  6938. local function drawInterface()\
  6939.     --Picker\
  6940.     for i=1,#column do\
  6941.         term.setCursorPos(w-1, i)\
  6942.         term.setBackgroundColour(column[i])\
  6943.         if state == \"print\" then\
  6944.             if i == 16 then\
  6945.                 term.setTextColour(colours.white)\
  6946.             else\
  6947.                 term.setTextColour(colours.black)\
  6948.             end\
  6949.             if requirementsDisplayed then\
  6950.                 if requiredMaterials[i] < 10 then term.write(\" \") end\
  6951.                 term.setCursorPos(w-#tostring(requiredMaterials[i])+1, i)\
  6952.                 term.write(requiredMaterials[i])\
  6953.             else\
  6954.                 if i < 10 then term.write(\" \") end\
  6955.                 term.write(i)\
  6956.             end\
  6957.         else\
  6958.             term.write(\"  \")\
  6959.         end\
  6960.     end\
  6961.     term.setCursorPos(w-1,#column+1)\
  6962.     term.setBackgroundColour(colours.black)\
  6963.     term.setTextColour(colours.red)\
  6964.     term.write(\"XX\")\
  6965.     --Pallette\
  6966.     term.setCursorPos(w-1,h-1)\
  6967.     if not lSel then\
  6968.         term.setBackgroundColour(colours.black)\
  6969.         term.setTextColour(colours.red)\
  6970.         term.write(\"X\")\
  6971.     else\
  6972.         term.setBackgroundColour(lSel)\
  6973.         term.setTextColour(lSel)\
  6974.         term.write(\" \")\
  6975.     end\
  6976.     if not rSel then\
  6977.         term.setBackgroundColour(colours.black)\
  6978.         term.setTextColour(colours.red)\
  6979.         term.write(\"X\")\
  6980.     else\
  6981.         term.setBackgroundColour(rSel)\
  6982.         term.setTextColour(rSel)\
  6983.         term.write(\" \")\
  6984.     end\
  6985.     --Footer\
  6986.     if inMenu then return end\
  6987.     \
  6988.     term.setCursorPos(1, h)\
  6989.     term.setBackgroundColour(colours.lightGrey)\
  6990.     term.setTextColour(colours.grey)\
  6991.     term.clearLine()\
  6992.     if inDropDown then\
  6993.         term.write(string.rep(\" \", 6))\
  6994.     else\
  6995.         term.setBackgroundColour(colours.grey)\
  6996.         term.setTextColour(colours.lightGrey)\
  6997.         term.write(\"menu  \")\
  6998.     end\
  6999.     term.setBackgroundColour(colours.lightGrey)\
  7000.     term.setTextColour(colours.grey)\
  7001.     term.write(getStateMessage())\
  7002.     \
  7003.     local coords=\"X:\"..sx..\" Y:\"..sy\
  7004.     if animated then coords = coords..\" Frame:\"..sFrame..\"/\"..framecount..\"   \" end\
  7005.     term.setCursorPos(w-#coords+1,h)\
  7006.     if state == \"play\" then term.setBackgroundColour(colours.lime)\
  7007.     elseif record then term.setBackgroundColour(colours.red) end\
  7008.     term.write(coords)\
  7009.     \
  7010.     if animated then\
  7011.         term.setCursorPos(w-1,h)\
  7012.         term.setBackgroundColour(colours.grey)\
  7013.         term.setTextColour(colours.lightGrey)\
  7014.         term.write(\"<>\")\
  7015.     end\
  7016. end\
  7017. \
  7018. --[[Runs an interface where users can select topics of help. Will return once the user quits the help screen.\
  7019.     Params: none\
  7020.     Returns:nil\
  7021. ]]--\
  7022. local function drawHelpScreen()\
  7023.     local selectedHelp = nil\
  7024.     while true do\
  7025.         term.setBackgroundColour(colours.lightGrey)\
  7026.         term.clear()\
  7027.         if not selectedHelp then\
  7028.             term.setCursorPos(4, 1)\
  7029.             term.setTextColour(colours.brown)\
  7030.             term.write(\"Available modes (click for info):\")\
  7031.             for i=1,#helpTopics do\
  7032.                 term.setCursorPos(2, 2 + i)\
  7033.                 term.setTextColour(colours.black)\
  7034.                 term.write(helpTopics[i].name)\
  7035.                 if helpTopics[i].key then\
  7036.                     term.setTextColour(colours.red)\
  7037.                     term.write(\" (\"..helpTopics[i].key..\")\")\
  7038.                 end\
  7039.             end\
  7040.             term.setCursorPos(4,h)\
  7041.             term.setTextColour(colours.black)\
  7042.             term.write(\"Press any key to exit\")\
  7043.         else\
  7044.             term.setCursorPos(4,1)\
  7045.             term.setTextColour(colours.brown)\
  7046.             term.write(helpTopics[selectedHelp].name)\
  7047.             if helpTopics[selectedHelp].key then\
  7048.                 term.setTextColour(colours.red)\
  7049.                 term.write(\" (\"..helpTopics[selectedHelp].key..\")\")\
  7050.             end\
  7051.             term.setCursorPos(1,3)\
  7052.             term.setTextColour(colours.black)\
  7053.             print(helpTopics[selectedHelp].message..\"\\n\")\
  7054.             for i=1,#helpTopics[selectedHelp].controls do\
  7055.                 term.setTextColour(colours.brown)\
  7056.                 term.write(helpTopics[selectedHelp].controls[i][1]..\" \")\
  7057.                 term.setTextColour(colours.black)\
  7058.                 print(helpTopics[selectedHelp].controls[i][2])\
  7059.             end\
  7060.         end\
  7061.         \
  7062.         local id,p1,p2,p3 = os.pullEvent()\
  7063.         \
  7064.         if id == \"timer\" then updateTimer(p1)\
  7065.         elseif id == \"key\" then \
  7066.             if selectedHelp then selectedHelp = nil\
  7067.             else break end\
  7068.         elseif id == \"mouse_click\" then\
  7069.             if not selectedHelp then \
  7070.                 if p3 >=3 and p3 <= 2+#helpTopics then\
  7071.                     selectedHelp = p3-2 \
  7072.                 else break end\
  7073.             else\
  7074.                 selectedHelp = nil\
  7075.             end\
  7076.         end\
  7077.     end\
  7078. end\
  7079. \
  7080. --[[Draws a message in the footer bar. A helper for DrawInterface, but can be called for custom messages, if the\
  7081.     inMenu paramter is set to true while this is being done (remember to set it back when done!)\
  7082.     Params: message:string = The message to be drawn\
  7083.     Returns:nil\
  7084. ]]--\
  7085. local function drawMessage(message)\
  7086.     term.setCursorPos(1,h)\
  7087.     term.setBackgroundColour(colours.lightGrey)\
  7088.     term.setTextColour(colours.grey)\
  7089.     term.clearLine()\
  7090.     term.write(message)\
  7091. end\
  7092. \
  7093. --[[\
  7094.             Section: Generic Interfaces\
  7095. ]]--\
  7096. \
  7097. \
  7098. --[[One of my generic text printing methods, printing a message at a specified position with width and offset.\
  7099.     No colour materials included.\
  7100.     Params: msg:string = The message to print off-center\
  7101.             height:number = The starting height of the message\
  7102.             width:number = The limit as to how many characters long each line may be\
  7103.             offset:number = The starting width offset of the message\
  7104.     Returns:number the number of lines used in printing the message\
  7105. ]]--\
  7106. local function wprintOffCenter(msg, height, width, offset)\
  7107.     local inc = 0\
  7108.     local ops = 1\
  7109.     while #msg - ops > width do\
  7110.         local nextspace = 0\
  7111.         while string.find(msg, \" \", ops + nextspace) and\
  7112.                 string.find(msg, \" \", ops + nextspace) - ops < width do\
  7113.             nextspace = string.find(msg, \" \", nextspace + ops) + 1 - ops\
  7114.         end\
  7115.         local ox,oy = term.getCursorPos()\
  7116.         term.setCursorPos(width/2 - (nextspace)/2 + offset, height + inc)\
  7117.         inc = inc + 1\
  7118.         term.write(string.sub(msg, ops, nextspace + ops - 1))\
  7119.         ops = ops + nextspace\
  7120.     end\
  7121.     term.setCursorPos(width/2 - #string.sub(msg, ops)/2 + offset, height + inc)\
  7122.     term.write(string.sub(msg, ops))\
  7123.     \
  7124.     return inc + 1\
  7125. end\
  7126. \
  7127. --[[Draws a message that must be clicked on or a key struck to be cleared. No options, so used for displaying\
  7128.     generic information.\
  7129.     Params: ctitle:string = The title of the confirm dialogue\
  7130.             msg:string = The message displayed in the dialogue\
  7131.     Returns:nil\
  7132. ]]--\
  7133. local function displayConfirmDialogue(ctitle, msg)\
  7134.     local dialogoffset = 8\
  7135.     --We actually print twice- once to get the lines, second time to print proper. Easier this way.\
  7136.     local lines = wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)\
  7137.     \
  7138.     term.setCursorPos(dialogoffset, 3)\
  7139.     term.setBackgroundColour(colours.grey)\
  7140.     term.setTextColour(colours.lightGrey)\
  7141.     term.write(string.rep(\" \", w - dialogoffset * 2))\
  7142.     term.setCursorPos(dialogoffset + (w - dialogoffset * 2)/2 - #ctitle/2, 3)\
  7143.     term.write(ctitle)\
  7144.     term.setTextColour(colours.grey)\
  7145.     term.setBackgroundColour(colours.lightGrey)\
  7146.     term.setCursorPos(dialogoffset, 4)\
  7147.     term.write(string.rep(\" \", w - dialogoffset * 2))\
  7148.     for i=5,5+lines do\
  7149.         term.setCursorPos(dialogoffset, i) \
  7150.         term.write(\" \"..string.rep(\" \", w - (dialogoffset) * 2 - 2)..\" \")\
  7151.     end\
  7152.     wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)\
  7153.     \
  7154.     --In the event of a message, the player hits anything to continue\
  7155.     while true do\
  7156.         local id,key = os.pullEvent()\
  7157.         if id == \"timer\" then updateTimer(key);\
  7158.         elseif id == \"key\" or id == \"mouse_click\" or id == \"mouse_drag\" then break end\
  7159.     end\
  7160. end\
  7161. \
  7162. --[[Produces a nice dropdown menu based on a table of strings. Depending on the position, this will auto-adjust the position\
  7163.     of the menu drawn, and allows nesting of menus and sub menus. Clicking anywhere outside the menu will cancel and return nothing\
  7164.     Params: x:int = the x position the menu should be displayed at\
  7165.             y:int = the y position the menu should be displayed at\
  7166.             options:table = the list of options available to the user, as strings or submenus (tables of strings, with a name parameter)\
  7167.     Returns:string the selected menu option.\
  7168. ]]--\
  7169. local function displayDropDown(x, y, options)\
  7170.     inDropDown = true\
  7171.     --Figures out the dimensions of our thing\
  7172.     local longestX = #options.name\
  7173.     for i=1,#options do\
  7174.         local currVal = options[i]\
  7175.         if type(currVal) == \"table\" then currVal = currVal.name end\
  7176.         \
  7177.         longestX = math.max(longestX, #currVal)\
  7178.     end\
  7179.     local xOffset = math.max(0, longestX - ((w-2) - x) + 1)\
  7180.     local yOffset = math.max(0, #options - ((h-1) - y))\
  7181.     \
  7182.     local clickTimes = 0\
  7183.     local tid = nil\
  7184.     local selection = nil\
  7185.     while clickTimes < 2 do\
  7186.         drawCanvas()\
  7187.         drawInterface()\
  7188.         \
  7189.         term.setCursorPos(x-xOffset,y-yOffset)\
  7190.         term.setBackgroundColour(colours.grey)\
  7191.         term.setTextColour(colours.lightGrey)\
  7192.         term.write(options.name..string.rep(\" \", longestX-#options.name + 2))\
  7193.     \
  7194.         for i=1,#options do\
  7195.             term.setCursorPos(x-xOffset, y-yOffset+i)\
  7196.             if i==selection and clickTimes % 2 == 0 then\
  7197.                 term.setBackgroundColour(colours.grey)\
  7198.                 term.setTextColour(colours.lightGrey)\
  7199.             else\
  7200.                 term.setBackgroundColour(colours.lightGrey)\
  7201.                 term.setTextColour(colours.grey)\
  7202.             end\
  7203.             local currVal = options[i]\
  7204.             if type(currVal) == \"table\" then \
  7205.                 term.write(currVal.name..string.rep(\" \", longestX-#currVal.name + 1))\
  7206.                 term.setBackgroundColour(colours.grey)\
  7207.                 term.setTextColour(colours.lightGrey)\
  7208.                 term.write(\">\")\
  7209.             else\
  7210.                 term.write(currVal..string.rep(\" \", longestX-#currVal + 2))\
  7211.             end\
  7212.         end\
  7213.         \
  7214.         local id, p1, p2, p3 = os.pullEvent()\
  7215.         if id == \"timer\" then\
  7216.             if p1 == tid then \
  7217.                 clickTimes = clickTimes + 1\
  7218.                 if clickTimes > 2 then \
  7219.                     break\
  7220.                 else \
  7221.                     tid = os.startTimer(0.1) \
  7222.                 end\
  7223.             else \
  7224.                 updateTimer(p1) \
  7225.                 drawCanvas()\
  7226.                 drawInterface()\
  7227.             end\
  7228.         elseif id == \"mouse_click\" then\
  7229.             if p2 >=x-xOffset and p2 <= x-xOffset + longestX + 1 and p3 >= y-yOffset+1 and p3 <= y-yOffset+#options then\
  7230.                 selection = p3-(y-yOffset)\
  7231.                 tid = os.startTimer(0.1)\
  7232.             else\
  7233.                 selection = \"\"\
  7234.                 break\
  7235.             end\
  7236.         end\
  7237.     end\
  7238.     \
  7239.     if type(selection) == \"number\" then\
  7240.         selection = options[selection]\
  7241.     end\
  7242.     \
  7243.     if type(selection) == \"string\" then \
  7244.         inDropDown = false\
  7245.         return selection\
  7246.     elseif type(selection) == \"table\" then \
  7247.         return displayDropDown(x, y, selection)\
  7248.     end\
  7249. end\
  7250. \
  7251. --[[A custom io.read() function with a few differences- it limits the number of characters being printed,\
  7252.     waits a 1/100th of a second so any keys still in the event library are removed before input is read and\
  7253.     the timer for the selectionrectangle is continuously updated during the process.\
  7254.     Params: lim:int = the number of characters input is allowed\
  7255.     Returns:string the inputted string, trimmed of leading and tailing whitespace\
  7256. ]]--\
  7257. local function readInput(lim)\
  7258.     term.setCursorBlink(true)\
  7259. \
  7260.     local inputString = \"\"\
  7261.     if not lim or type(lim) ~= \"number\" or lim < 1 then lim = w - ox end\
  7262.     local ox,oy = term.getCursorPos()\
  7263.     --We only get input from the footer, so this is safe. Change if recycling\
  7264.     term.setBackgroundColour(colours.lightGrey)\
  7265.     term.setTextColour(colours.grey)\
  7266.     term.write(string.rep(\" \", lim))\
  7267.     term.setCursorPos(ox, oy)\
  7268.     --As events queue immediately, we may get an unwanted key... this will solve that problem\
  7269.     local inputTimer = os.startTimer(0.01)\
  7270.     local keysAllowed = false\
  7271.     \
  7272.     while true do\
  7273.         local id,key = os.pullEvent()\
  7274.         \
  7275.         if keysAllowed then\
  7276.             if id == \"key\" and key == 14 and #inputString > 0 then\
  7277.                 inputString = string.sub(inputString, 1, #inputString-1)\
  7278.                 term.setCursorPos(ox + #inputString,oy)\
  7279.                 term.write(\" \")\
  7280.             elseif id == \"key\" and key == 28 and inputString ~= string.rep(\" \", #inputString) then \
  7281.                 break\
  7282.             elseif id == \"key\" and key == keys.leftCtrl then\
  7283.                 return \"\"\
  7284.             elseif id == \"char\" and #inputString < lim then\
  7285.                 inputString = inputString..key\
  7286.             end\
  7287.         end\
  7288.         \
  7289.         if id == \"timer\" then\
  7290.             if key == inputTimer then \
  7291.                 keysAllowed = true\
  7292.             else\
  7293.                 updateTimer(key)\
  7294.                 drawCanvas()\
  7295.                 drawInterface()\
  7296.                 term.setBackgroundColour(colours.lightGrey)\
  7297.                 term.setTextColour(colours.grey)\
  7298.             end\
  7299.         end\
  7300.         term.setCursorPos(ox,oy)\
  7301.         term.write(inputString)\
  7302.         term.setCursorPos(ox + #inputString, oy)\
  7303.     end\
  7304.     \
  7305.     while string.sub(inputString, 1, 1) == \" \" do\
  7306.         inputString = string.sub(inputString, 2, #inputString)\
  7307.     end\
  7308.     while string.sub(inputString, #inputString, #inputString) == \" \" do\
  7309.         inputString = string.sub(inputString, 1, #inputString-1)\
  7310.     end\
  7311.     term.setCursorBlink(false)\
  7312.     \
  7313.     return inputString\
  7314. end\
  7315. \
  7316. --[[  \
  7317.             Section: Image tools \
  7318. ]]--\
  7319. \
  7320. \
  7321. --[[Copies all pixels beneath the selection rectangle into the image buffer. Empty buffers are converted to nil.\
  7322.     Params: removeImage:bool = true if the image is to be erased after copying, false otherwise\
  7323.     Returns:nil\
  7324. ]]--\
  7325. local function copyToBuffer(removeImage)\
  7326.     buffer = { width = selectrect.x2 - selectrect.x1 + 1, height = selectrect.y2 - selectrect.y1 + 1, contents = { } }\
  7327.     \
  7328.     local containsSomething = false\
  7329.     for y=1,buffer.height do\
  7330.         buffer.contents[y] = { }\
  7331.         local f,l = sFrame,sFrame\
  7332.         if record then f,l = 1, framecount end\
  7333.         \
  7334.         for fra = f,l do\
  7335.             if frames[fra][selectrect.y1 + y - 1] then\
  7336.                 for x=1,buffer.width do\
  7337.                     buffer.contents[y][x] = frames[sFrame][selectrect.y1 + y - 1][selectrect.x1 + x - 1]\
  7338.                     if removeImage then frames[fra][selectrect.y1 + y - 1][selectrect.x1 + x - 1] = nil end\
  7339.                     if buffer.contents[y][x] then containsSomething = true end\
  7340.                 end\
  7341.             end\
  7342.         end\
  7343.     end\
  7344.     --I don't classify an empty buffer as a real buffer- confusing to the user.\
  7345.     if not containsSomething then buffer = nil end\
  7346. end\
  7347. \
  7348. --[[Replaces all pixels under the selection rectangle with the image buffer (or what can be seen of it). Record-dependent.\
  7349.     Params: removeBuffer:bool = true if the buffer is to be emptied after copying, false otherwise\
  7350.     Returns:nil\
  7351. ]]--\
  7352. local function copyFromBuffer(removeBuffer)\
  7353.     if not buffer then return end\
  7354. \
  7355.     for y = 1, math.min(buffer.height,selectrect.y2-selectrect.y1+1) do\
  7356.         local f,l = sFrame, sFrame\
  7357.         if record then f,l = 1, framecount end\
  7358.         \
  7359.         for fra = f,l do\
  7360.             if not frames[fra][selectrect.y1+y-1] then frames[fra][selectrect.y1+y-1] = { } end\
  7361.             for x = 1, math.min(buffer.width,selectrect.x2-selectrect.x1+1) do\
  7362.                 frames[fra][selectrect.y1+y-1][selectrect.x1+x-1] = buffer.contents[y][x]\
  7363.             end\
  7364.         end\
  7365.     end\
  7366.     \
  7367.     if removeBuffer then buffer = nil end\
  7368. end\
  7369. \
  7370. --[[Moves the entire image (or entire animation) to the specified coordinates. Record-dependent.\
  7371.     Params: newx:int = the X coordinate to move the image to\
  7372.             newy:int = the Y coordinate to move the image to\
  7373.     Returns:nil\
  7374. ]]--\
  7375. local function moveImage(newx,newy)\
  7376.     if not leflim or not toplim then return end\
  7377.     if newx <=0 or newy <=0 then return end\
  7378.     local f,l = sFrame,sFrame\
  7379.     if record then f,l = 1,framecount end\
  7380.     \
  7381.     for i=f,l do\
  7382.         local newlines = { }\
  7383.         for y,line in pairs(frames[i]) do\
  7384.             newlines[y-toplim+newy] = { }\
  7385.             for x,char in pairs(line) do\
  7386.                 newlines[y-toplim+newy][x-leflim+newx] = char\
  7387.             end\
  7388.         end\
  7389.         frames[i] = newlines\
  7390.     end\
  7391. end\
  7392. \
  7393. --[[Prompts the user to clear the current frame or all frames. Record-dependent.,\
  7394.     Params: none\
  7395.     Returns:nil\
  7396. ]]--\
  7397. local function clearImage()\
  7398.     inMenu = true\
  7399.     if not animated then\
  7400.         drawMessage(\"Clear image? Y/N: \")\
  7401.     elseif record then\
  7402.         drawMessage(\"Clear ALL frames? Y/N: \")\
  7403.     else\
  7404.         drawMessage(\"Clear current frame? Y/N :\")\
  7405.     end\
  7406.     if string.find(string.upper(readInput(1)), \"Y\") then\
  7407.         local f,l = sFrame,sFrame\
  7408.         if record then f,l = 1,framecount end\
  7409.         \
  7410.         for i=f,l do\
  7411.             frames[i] = { }\
  7412.         end\
  7413.     end\
  7414.     inMenu = false\
  7415. end\
  7416. \
  7417. --[[A recursively called method (watch out for big calls!) in which every pixel of a set colour is\
  7418.     changed to another colour. Does not work on the nil colour, for obvious reasons.\
  7419.     Params: x:int = The X coordinate of the colour to flood-fill\
  7420.             y:int = The Y coordinate of the colour to flood-fill\
  7421.             targetColour:colour = the colour that is being flood-filled\
  7422.             newColour:colour = the colour with which to replace the target colour\
  7423.     Returns:nil\
  7424. ]]--\
  7425. local function floodFill(x, y, targetColour, newColour)\
  7426.     if not newColour or not targetColour then return end\
  7427.     local nodeList = { }\
  7428.     \
  7429.     table.insert(nodeList, {x = x, y = y})\
  7430.     \
  7431.     while #nodeList > 0 do\
  7432.         local node = nodeList[1]\
  7433.         if frames[sFrame][node.y] and frames[sFrame][node.y][node.x] == targetColour then\
  7434.             frames[sFrame][node.y][node.x] = newColour\
  7435.             table.insert(nodeList, { x = node.x + 1, y = node.y})\
  7436.             table.insert(nodeList, { x = node.x, y = node.y + 1})\
  7437.             if x > 1 then table.insert(nodeList, { x = node.x - 1, y = node.y}) end\
  7438.             if y > 1 then table.insert(nodeList, { x = node.x, y = node.y - 1}) end\
  7439.         end\
  7440.         table.remove(nodeList, 1)\
  7441.     end\
  7442. end\
  7443. \
  7444. --[[  \
  7445.             Section: Animation Tools  \
  7446. ]]--\
  7447. \
  7448. --[[Enters play mode, allowing the animation to play through. Interface is restricted to allow this,\
  7449.     and method only leaves once the player leaves play mode.\
  7450.     Params: none\
  7451.     Returns:nil\
  7452. ]]--\
  7453. local function playAnimation()\
  7454.     state = \"play\"\
  7455.     selectedrect = nil\
  7456.     \
  7457.     local animt = os.startTimer(animtime)\
  7458.     repeat\
  7459.         drawCanvas()\
  7460.         drawInterface()\
  7461.         \
  7462.         local id,key,_,y = os.pullEvent()\
  7463.         \
  7464.         if id==\"timer\" then\
  7465.             if key == animt then\
  7466.                 animt = os.startTimer(animtime)\
  7467.                 sFrame = (sFrame % framecount) + 1\
  7468.             else\
  7469.                 updateTimer(key)\
  7470.             end\
  7471.         elseif id==\"key\" then\
  7472.             if key == keys.comma and animtime > 0.1 then animtime = animtime - 0.05\
  7473.             elseif key == keys.period and animtime < 0.5 then animtime = animtime + 0.05\
  7474.             elseif key == keys.space then state = \"paint\" end\
  7475.         elseif id==\"mouse_click\" and y == h then\
  7476.             state = \"paint\"\
  7477.         end\
  7478.     until state ~= \"play\"\
  7479.     os.startTimer(0.5)\
  7480. end\
  7481. \
  7482. --[[Changes the selected frame (sFrame) to the chosen frame. If this frame is above the framecount,\
  7483.     additional frames are created with a copy of the image on the selected frame.\
  7484.     Params: newframe:int = the new frame to move to\
  7485.     Returns:nil\
  7486. ]]--\
  7487. local function changeFrame(newframe)\
  7488.     inMenu = true\
  7489.     if not tonumber(newframe) then\
  7490.         term.setCursorPos(1,h)\
  7491.         term.setBackgroundColour(colours.lightGrey)\
  7492.         term.setTextColour(colours.grey)\
  7493.         term.clearLine()\
  7494.     \
  7495.         term.write(\"Go to frame: \")\
  7496.         newframe = tonumber(readInput(2))\
  7497.         if not newframe or newframe <= 0 then\
  7498.             inMenu = false\
  7499.             return \
  7500.         end\
  7501.     elseif newframe <= 0 then return end\
  7502.     \
  7503.     if newframe > framecount then\
  7504.         for i=framecount+1,newframe do\
  7505.             frames[i] = {}\
  7506.             for y,line in pairs(frames[sFrame]) do\
  7507.                 frames[i][y] = { }\
  7508.                 for x,v in pairs(line) do\
  7509.                     frames[i][y][x] = v\
  7510.                 end\
  7511.             end\
  7512.         end\
  7513.         framecount = newframe\
  7514.     end\
  7515.     sFrame = newframe\
  7516.     inMenu = false\
  7517. end\
  7518. \
  7519. --[[Removes every frame leading after the frame passed in\
  7520.     Params: frame:int the non-inclusive lower bounds of the delete\
  7521.     Returns:nil\
  7522. ]]--\
  7523. local function removeFramesAfter(frame)\
  7524.     inMenu = true\
  7525.     if frame==framecount then return end\
  7526.     drawMessage(\"Remove frames \"..(frame+1)..\"/\"..framecount..\"? Y/N :\")\
  7527.     local answer = string.upper(readInput(1))\
  7528.     \
  7529.     if string.find(answer, string.upper(\"Y\")) ~= 1 then \
  7530.         inMenu = false\
  7531.         return \
  7532.     end\
  7533.     \
  7534.     for i=frame+1, framecount do\
  7535.         frames[i] = nil\
  7536.     end\
  7537.     framecount = frame\
  7538.     inMenu = false\
  7539. end\
  7540. \
  7541. --[[\
  7542.             Section: Printing Tools\
  7543. ]]--\
  7544. \
  7545. --[[Constructs a new facing to the left of the current facing\
  7546.     Params: curx:number = The facing on the X axis\
  7547.             curz:number = The facing on the Z axis\
  7548.             hand:string = The hand of the axis (\"right\" or \"left\")\
  7549.     Returns:number,number = the new facing on the X and Z axis after a left turn\
  7550. ]]--\
  7551. local function getLeft(curx, curz)\
  7552.     local hand = \"left\"\
  7553.     if layering == \"up\" then hand = \"right\" end\
  7554.     \
  7555.     if hand == \"right\" then\
  7556.         if curx == 1 then return 0,-1 end\
  7557.         if curx == -1 then return 0,1 end\
  7558.         if curz == 1 then return 1,0 end\
  7559.         if curz == -1 then return -1,0 end\
  7560.     else\
  7561.         if curx == 1 then return 0,1 end\
  7562.         if curx == -1 then return 0,-1 end\
  7563.         if curz == 1 then return -1,0 end\
  7564.         if curz == -1 then return 1,0 end\
  7565.     end\
  7566. end\
  7567. \
  7568. --[[Constructs a new facing to the right of the current facing\
  7569.     Params: curx:number = The facing on the X axis\
  7570.             curz:number = The facing on the Z axis\
  7571.             hand:string = The hand of the axis (\"right\" or \"left\")\
  7572.     Returns:number,number = the new facing on the X and Z axis after a right turn\
  7573. ]]--\
  7574. local function getRight(curx, curz)\
  7575.     local hand = \"left\"\
  7576.     if layering == \"up\" then hand = \"right\" end\
  7577.     \
  7578.     if hand == \"right\" then\
  7579.         if curx == 1 then return 0,1 end\
  7580.         if curx == -1 then return 0,-1 end\
  7581.         if curz == 1 then return -1,0 end\
  7582.         if curz == -1 then return 1,0 end\
  7583.     else\
  7584.         if curx == 1 then return 0,-1 end\
  7585.         if curx == -1 then return 0,1 end\
  7586.         if curz == 1 then return 1,0 end\
  7587.         if curz == -1 then return -1,0 end\
  7588.     end\
  7589. end\
  7590. \
  7591. \
  7592. --[[Sends out a rednet signal requesting local printers, and will listen for any responses. Printers found are added to the\
  7593.     printerList (for ID's) and printerNames (for names)\
  7594.     Params: nil\
  7595.     Returns:nil\
  7596. ]]--\
  7597. local function locatePrinters()\
  7598.     printerList = { }\
  7599.     printerNames = { name = \"Printers\" }\
  7600.     local oldState = state\
  7601.     state = \"Locating printers, please wait...   \"\
  7602.     drawCanvas()\
  7603.     drawInterface()\
  7604.     state = oldState\
  7605.     \
  7606.     local modemOpened = false\
  7607.     for k,v in pairs(rs.getSides()) do\
  7608.         if peripheral.isPresent(v) and peripheral.getType(v) == \"modem\" then\
  7609.             rednet.open(v)\
  7610.             modemOpened = true\
  7611.             break\
  7612.         end\
  7613.     end\
  7614.     \
  7615.     if not modemOpened then\
  7616.         displayConfirmDialogue(\"Modem not found!\", \"No modem peripheral. Must have network modem to locate printers.\")\
  7617.         return false\
  7618.     end\
  7619.     \
  7620.     rednet.broadcast(\"$3DPRINT IDENTIFY\")\
  7621.     \
  7622.     while true do\
  7623.         local id, msg = rsTimeReceive(1)\
  7624.         \
  7625.         if not id then break end\
  7626.         if string.find(msg, \"$3DPRINT IDACK\") == 1 then\
  7627.             msg = string.gsub(msg, \"$3DPRINT IDACK \", \"\")\
  7628.             table.insert(printerList, id)\
  7629.             table.insert(printerNames, msg)\
  7630.         end\
  7631.     end\
  7632.     \
  7633.     if #printerList == 0 then\
  7634.         displayConfirmDialogue(\"Printers not found!\", \"No active printers found in proximity of this computer.\")\
  7635.         return false\
  7636.     else\
  7637.         return true\
  7638.     end\
  7639. end\
  7640. \
  7641. --[[Sends a request to the printer. Waits on a response and updates the state of the application accordingly.\
  7642.     Params: command:string the command to send\
  7643.             param:string a parameter to send, if any\
  7644.     Returns:nil\
  7645. ]]--\
  7646. local function sendPC(command,param)\
  7647.     local msg = \"$PC \"..command\
  7648.     if param then msg = msg..\" \"..param end\
  7649.     rednet.send(printerList[selectedPrinter], msg)\
  7650.     \
  7651.     while true do\
  7652.         local id,key = rsTimeReceive()\
  7653.         if id == printerList[selectedPrinter] then\
  7654.             if key == \"$3DPRINT ACK\" then\
  7655.                 break\
  7656.             elseif key == \"$3DPRINT DEP\" then\
  7657.                 displayConfirmDialogue(\"Printer Empty\", \"The printer has exhasted a material. Please refill slot \"..param..\
  7658.                     \", and click this message when ready to continue.\")\
  7659.                 rednet.send(printerList[selectedPrinter], msg)\
  7660.             end\
  7661.         end\
  7662.     end\
  7663.     \
  7664.     --Changes to position are handled after the event has been successfully completed\
  7665.     if command == \"FW\" then\
  7666.         px = px + pfx\
  7667.         pz = pz + pfz\
  7668.     elseif command == \"BK\" then\
  7669.         px = px - pfx\
  7670.         pz = pz - pfz\
  7671.     elseif command == \"UP\" then\
  7672.         if layering == \"up\" then\
  7673.             py = py + 1\
  7674.         else \
  7675.             py = py - 1\
  7676.         end\
  7677.     elseif command == \"DW\" then\
  7678.         if layering == \"up\" then\
  7679.             py = py - 1\
  7680.         else    \
  7681.             py = py + 1\
  7682.         end\
  7683.     elseif command == \"TL\" then\
  7684.         pfx,pfz = getLeft(pfx,pfz)\
  7685.     elseif command == \"TR\" then\
  7686.         pfx,pfz = getRight(pfx,pfz)\
  7687.     elseif command == \"TU\" then\
  7688.         pfx = -pfx\
  7689.         pfz = -pfz\
  7690.     end\
  7691.     \
  7692.     drawCanvas()\
  7693.     drawInterface()\
  7694. end\
  7695. \
  7696. --[[A printing function that commands the printer to turn to face the desired direction, if it is not already doing so\
  7697.     Params: desx:number = the normalized x direction to face\
  7698.             desz:number = the normalized z direction to face\
  7699.     Returns:nil\
  7700. ]]--\
  7701. local function turnToFace(desx,desz)\
  7702.     if desx ~= 0 then\
  7703.         if pfx ~= desx then\
  7704.             local temppfx,_ = getLeft(pfx,pfz)\
  7705.             if temppfx == desx then\
  7706.                 sendPC(\"TL\")\
  7707.             elseif temppfx == -desx then\
  7708.                 sendPC(\"TR\")\
  7709.             else\
  7710.                 sendPC(\"TU\")\
  7711.             end\
  7712.         end\
  7713.     else\
  7714.         print(\"on the z axis\")\
  7715.         if pfz ~= desz then\
  7716.             local _,temppfz = getLeft(pfx,pfz)\
  7717.             if temppfz == desz then\
  7718.                 sendPC(\"TL\")\
  7719.             elseif temppfz == -desz then\
  7720.                 sendPC(\"TR\")\
  7721.             else\
  7722.                 sendPC(\"TU\")\
  7723.             end\
  7724.         end\
  7725.     end\
  7726. end\
  7727. \
  7728. --[[Performs the print\
  7729.     Params: nil\
  7730.     Returns:nil\
  7731. ]]--\
  7732. local function performPrint()\
  7733.     state = \"active print\"\
  7734.     if layering == \"up\" then\
  7735.         --An up layering starts our builder bot on the bottom left corner of our build\
  7736.         px,py,pz = leflim, 0, botlim + 1\
  7737.         pfx,pfz = 0,-1\
  7738.         \
  7739.         --We move him forward and up a bit from his original position.\
  7740.         sendPC(\"FW\")\
  7741.         sendPC(\"UP\")\
  7742.         --For each layer that needs to be completed, we go up by one each time\
  7743.         for layers=1,#frames do\
  7744.             --We first decide if we're going forwards or back, depending on what side we're on\
  7745.             local rowbot,rowtop,rowinc = nil,nil,nil\
  7746.             if pz == botlim then\
  7747.                 rowbot,rowtop,rowinc = botlim,toplim,-1\
  7748.             else\
  7749.                 rowbot,rowtop,rowinc = toplim,botlim,1\
  7750.             end\
  7751.             \
  7752.             for rows = rowbot,rowtop,rowinc do\
  7753.                 --Then we decide if we're going left or right, depending on what side we're on\
  7754.                 local linebot,linetop,lineinc = nil,nil,nil\
  7755.                 if px == leflim then\
  7756.                     --Facing from the left side has to be easterly- it's changed here\
  7757.                     turnToFace(1,0)\
  7758.                     linebot,linetop,lineinc = leflim,riglim,1\
  7759.                 else\
  7760.                     --Facing from the right side has to be westerly- it's changed here\
  7761.                     turnToFace(-1,0)\
  7762.                     linebot,linetop,lineinc = riglim,leflim,-1\
  7763.                 end\
  7764.                 \
  7765.                 for lines = linebot,linetop,lineinc do\
  7766.                     --We move our turtle forward, placing the right material at each step\
  7767.                     local material = frames[py][pz][px]\
  7768.                     if material then\
  7769.                         material = math.log10(frames[py][pz][px])/math.log10(2) + 1\
  7770.                         sendPC(\"SS\", material)\
  7771.                         sendPC(\"PD\")\
  7772.                     end\
  7773.                     if lines ~= linetop then\
  7774.                         sendPC(\"FW\")\
  7775.                     end\
  7776.                 end\
  7777.                 \
  7778.                 --The printer then has to do a U-turn, depending on which way he's facing and\
  7779.                 --which way he needs to go\
  7780.                 local temppfx,temppfz = getLeft(pfx,pfz)\
  7781.                 if temppfz == rowinc and rows ~= rowtop then\
  7782.                     sendPC(\"TL\")\
  7783.                     sendPC(\"FW\")\
  7784.                     sendPC(\"TL\")\
  7785.                 elseif temppfz == -rowinc and rows ~= rowtop then\
  7786.                     sendPC(\"TR\")\
  7787.                     sendPC(\"FW\")\
  7788.                     sendPC(\"TR\")\
  7789.                 end\
  7790.             end\
  7791.             --Now at the end of a run he does a 180 and moves up to begin the next part of the print\
  7792.             sendPC(\"TU\")\
  7793.             if layers ~= #frames then\
  7794.                 sendPC(\"UP\")\
  7795.             end\
  7796.         end\
  7797.         --All done- now we head back to where we started.\
  7798.         if px ~= leflim then\
  7799.             turnToFace(-1,0)\
  7800.             while px ~= leflim do\
  7801.                 sendPC(\"FW\")\
  7802.             end\
  7803.         end\
  7804.         if pz ~= botlim then\
  7805.             turnToFace(0,-1)\
  7806.             while pz ~= botlim do\
  7807.                 sendPC(\"BK\")\
  7808.             end\
  7809.         end\
  7810.         turnToFace(0,-1)\
  7811.         sendPC(\"BK\")\
  7812.         while py > 0 do\
  7813.             sendPC(\"DW\")\
  7814.         end\
  7815.     else\
  7816.         --The front facing is at the top-left corner, facing south not north\
  7817.         px,py,pz = leflim, botlim, 1\
  7818.         pfx,pfz = 0,1\
  7819.         --We move the printer to the last layer- he prints from the back forwards\
  7820.         while pz < #frames do\
  7821.             sendPC(\"FW\")\
  7822.         end\
  7823.         \
  7824.         --For each layer in the frame we build our wall, the move back\
  7825.         for layers = 1,#frames do\
  7826.             --We first decide if we're going left or right based on our position\
  7827.             local rowbot,rowtop,rowinc = nil,nil,nil\
  7828.             if px == leflim then\
  7829.                 rowbot,rowtop,rowinc = leflim,riglim,1\
  7830.             else\
  7831.                 rowbot,rowtop,rowinc = riglim,leflim,-1\
  7832.             end\
  7833.             \
  7834.             for rows = rowbot,rowtop,rowinc do\
  7835.                 --Then we decide if we're going up or down, depending on our given altitude\
  7836.                 local linebot,linetop,lineinc = nil,nil,nil\
  7837.                 if py == botlim then\
  7838.                     linebot,linetop,lineinc = botlim,toplim,-1\
  7839.                 else\
  7840.                     linebot,linetop,lineinc = toplim,botlim,1\
  7841.                 end\
  7842.                 \
  7843.                 for lines = linebot,linetop,lineinc do\
  7844.                 --We move our turtle up/down, placing the right material at each step\
  7845.                     local material = frames[pz][py][px]\
  7846.                     if material then\
  7847.                         material = math.log10(frames[pz][py][px])/math.log10(2) + 1\
  7848.                         sendPC(\"SS\", material)\
  7849.                         sendPC(\"PF\")\
  7850.                     end\
  7851.                     if lines ~= linetop then\
  7852.                         if lineinc == 1 then sendPC(\"DW\")\
  7853.                         else sendPC(\"UP\") end\
  7854.                     end\
  7855.                 end\
  7856.                     \
  7857.                 if rows ~= rowtop then\
  7858.                     turnToFace(rowinc,0)\
  7859.                     sendPC(\"FW\")\
  7860.                     turnToFace(0,1)\
  7861.                 end\
  7862.             end\
  7863.             \
  7864.             if layers ~= #frames then\
  7865.                 sendPC(\"TU\")\
  7866.                 sendPC(\"FW\")\
  7867.                 sendPC(\"TU\")\
  7868.             end\
  7869.         end\
  7870.         --He's easy to reset\
  7871.         while px ~= leflim do\
  7872.             turnToFace(-1,0)\
  7873.             sendPC(\"FW\")\
  7874.         end\
  7875.         turnToFace(0,1)\
  7876.     end\
  7877.     \
  7878.     sendPC(\"DE\")\
  7879.     \
  7880.     displayConfirmDialogue(\"Print complete\", \"The 3D print was successful.\")\
  7881. end\
  7882. \
  7883. --[[  \
  7884.             Section: Interface  \
  7885. ]]--\
  7886. \
  7887. --[[Runs the printing interface. Allows users to find/select a printer, the style of printing to perform and to begin the operation\
  7888.     Params: none\
  7889.     Returns:boolean true if printing was started, false otherwse\
  7890. ]]--\
  7891. local function runPrintInterface()\
  7892.     if not locatePrinters() then\
  7893.         return false\
  7894.     end\
  7895.     \
  7896.     calculateMaterials()\
  7897.     layering = \"up\"\
  7898.     requirementsDisplayed = false\
  7899.     selectedPrinter = 1\
  7900.     while true do\
  7901.         drawCanvas()\
  7902.         term.setBackgroundColour(colours.lightGrey)\
  7903.         for i=1,10 do\
  7904.             term.setCursorPos(1,i)\
  7905.             term.clearLine()\
  7906.         end\
  7907.         drawInterface()\
  7908.         term.setBackgroundColour(colours.lightGrey)\
  7909.         term.setTextColour(colours.black)\
  7910.         \
  7911.         local msg = \"3D Printing\"\
  7912.         term.setCursorPos(w/2-#msg/2 - 2, 1)\
  7913.         term.write(msg)\
  7914.         term.setBackgroundColour(colours.grey)\
  7915.         term.setTextColour(colours.lightGrey)\
  7916.         if(requirementsDisplayed) then\
  7917.             msg = \"Count:\"\
  7918.         else\
  7919.             msg = \" Slot:\"\
  7920.         end\
  7921.         term.setCursorPos(w-3-#msg, 1)\
  7922.         term.write(msg)\
  7923.         term.setBackgroundColour(colours.lightGrey)\
  7924.         term.setTextColour(colours.black)\
  7925.         \
  7926.         term.setCursorPos(7, 2)\
  7927.         term.write(\"Layering\")\
  7928.         drawPictureTable(layerUpIcon, 3, 3, colours.white)\
  7929.         drawPictureTable(layerForwardIcon, 12, 3, colours.white)\
  7930.         if layering == \"up\" then\
  7931.             term.setBackgroundColour(colours.red)\
  7932.         else\
  7933.             term.setBackgroundColour(colours.lightGrey)\
  7934.         end\
  7935.         term.setCursorPos(3, 9)\
  7936.         term.write(\"Upwards\")\
  7937.         if layering == \"forward\" then\
  7938.             term.setBackgroundColour(colours.red)\
  7939.         else\
  7940.             term.setBackgroundColour(colours.lightGrey)\
  7941.         end\
  7942.         term.setCursorPos(12, 9)\
  7943.         term.write(\"Forward\")\
  7944.         \
  7945.         term.setBackgroundColour(colours.lightGrey)\
  7946.         term.setTextColour(colours.black)\
  7947.         term.setCursorPos(31, 2)\
  7948.         term.write(\"Printer ID\")\
  7949.         term.setCursorPos(33, 3)\
  7950.         if #printerList > 1 then\
  7951.             term.setBackgroundColour(colours.grey)\
  7952.             term.setTextColour(colours.lightGrey)\
  7953.         else\
  7954.             term.setTextColour(colours.red)\
  7955.         end\
  7956.         term.write(\" \"..printerNames[selectedPrinter]..\" \")\
  7957.         \
  7958.         term.setBackgroundColour(colours.grey)\
  7959.         term.setTextColour(colours.lightGrey)\
  7960.         term.setCursorPos(25, 10)\
  7961.         term.write(\" Cancel \")\
  7962.         term.setCursorPos(40, 10)\
  7963.         term.write(\" Print \")\
  7964.         \
  7965.         local id, p1, p2, p3 = os.pullEvent()\
  7966.         \
  7967.         if id == \"timer\" then\
  7968.             updateTimer(p1)\
  7969.         elseif id == \"mouse_click\" then\
  7970.             --Layering Buttons\
  7971.             if p2 >= 3 and p2 <= 9 and p3 >= 3 and p3 <= 9 then\
  7972.                 layering = \"up\"\
  7973.             elseif p2 >= 12 and p2 <= 18 and p3 >= 3 and p3 <= 9 then\
  7974.                 layering = \"forward\"\
  7975.             --Count/Slot\
  7976.             elseif p2 >= w - #msg - 3 and p2 <= w - 3 and p3 == 1 then\
  7977.                 requirementsDisplayed = not requirementsDisplayed\
  7978.             --Printer ID\
  7979.             elseif p2 >= 33 and p2 <= 33 + #printerNames[selectedPrinter] and p3 == 3 and #printerList > 1 then\
  7980.                 local chosenName = displayDropDown(33, 3, printerNames)\
  7981.                 for i=1,#printerNames do\
  7982.                     if printerNames[i] == chosenName then\
  7983.                         selectedPrinter = i\
  7984.                         break;\
  7985.                     end\
  7986.                 end\
  7987.             --Print and Cancel\
  7988.             elseif p2 >= 25 and p2 <= 32 and p3 == 10 then\
  7989.                 break\
  7990.             elseif p2 >= 40 and p2 <= 46 and p3 == 10 then\
  7991.                 rednet.send(printerList[selectedPrinter], \"$3DPRINT ACTIVATE\")\
  7992.                 ready = false\
  7993.                 while true do\
  7994.                     local id,msg = rsTimeReceive(10)\
  7995.                     \
  7996.                     if id == printerList[selectedPrinter] and msg == \"$3DPRINT ACTACK\" then\
  7997.                         ready = true\
  7998.                         break\
  7999.                     end\
  8000.                 end\
  8001.                 if ready then\
  8002.                     performPrint()\
  8003.                     break\
  8004.                 else\
  8005.                     displayConfirmDialogue(\"Printer Didn't Respond\", \"The printer didn't respond to the activation command. Check to see if it's online\")\
  8006.                 end\
  8007.             end\
  8008.         end\
  8009.     end\
  8010.     state = \"paint\"\
  8011. end\
  8012. \
  8013. --[[This function changes the current paint program to another tool or mode, depending on user input. Handles\
  8014.     any necessary changes in logic involved in that.\
  8015.     Params: mode:string = the name of the mode to change to\
  8016.     Returns:nil\
  8017. ]]--\
  8018. local function performSelection(mode)\
  8019.     if not mode or mode == \"\" then return\
  8020.     \
  8021.     elseif mode == \"help\" then\
  8022.         drawHelpScreen()\
  8023.         \
  8024.     elseif mode == \"blueprint on\" then\
  8025.         blueprint = true\
  8026.         ddModes[2][3] = \"blueprint off\"\
  8027.         \
  8028.     elseif mode == \"blueprint off\" then\
  8029.         blueprint = false\
  8030.         ddModes[2][3] = \"blueprint on\"\
  8031.         \
  8032.     elseif mode == \"layers on\" then\
  8033.         layerDisplay = true\
  8034.         ddModes[2][4] = \"layers off\"\
  8035.     \
  8036.     elseif mode == \"layers off\" then\
  8037.         layerDisplay = false\
  8038.         ddModes[2][4] = \"layers on\"\
  8039.     \
  8040.     elseif mode == \"direction on\" then\
  8041.         printDirection = true\
  8042.         ddModes[2][5] = \"direction off\"\
  8043.         \
  8044.     elseif mode == \"direction off\" then\
  8045.         printDirection = false\
  8046.         ddModes[2][5] = \"direction on\"\
  8047.     \
  8048.     elseif mode == \"go to\" then\
  8049.         changeFrame()\
  8050.     \
  8051.     elseif mode == \"remove\" then\
  8052.         removeFramesAfter(sFrame)\
  8053.     \
  8054.     elseif mode == \"play\" then\
  8055.         playAnimation()\
  8056.         \
  8057.     elseif mode == \"copy\" then\
  8058.         if selectrect and selectrect.x1 ~= selectrect.x2 then\
  8059.             copyToBuffer(false)\
  8060.         end\
  8061.     \
  8062.     elseif mode == \"cut\" then\
  8063.         if selectrect and selectrect.x1 ~= selectrect.x2 then \
  8064.             copyToBuffer(true)\
  8065.         end\
  8066.         \
  8067.     elseif mode == \"paste\" then\
  8068.         if selectrect and selectrect.x1 ~= selectrect.x2 then \
  8069.             copyFromBuffer(false)\
  8070.         end\
  8071.         \
  8072.     elseif mode == \"hide\" then\
  8073.         selectrect = nil\
  8074.         if state == \"select\" then state = \"corner select\" end\
  8075.         \
  8076.     elseif mode == \"alpha to left\" then\
  8077.         if lSel then alphaC = lSel end\
  8078.         \
  8079.     elseif mode == \"alpha to right\" then\
  8080.         if rSel then alphaC = rSel end\
  8081.         \
  8082.     elseif mode == \"record\" then\
  8083.         record = not record\
  8084.         \
  8085.     elseif mode == \"clear\" then\
  8086.         if state==\"select\" then buffer = nil\
  8087.         else clearImage() end\
  8088.     \
  8089.     elseif mode == \"select\" then\
  8090.         if state==\"corner select\" or state==\"select\" then\
  8091.             state = \"paint\"\
  8092.         elseif selectrect and selectrect.x1 ~= selectrect.x2 then\
  8093.             state = \"select\"\
  8094.         else\
  8095.             state = \"corner select\" \
  8096.         end\
  8097.         \
  8098.     elseif mode == \"print\" then\
  8099.         state = \"print\"\
  8100.         runPrintInterface()\
  8101.         state = \"paint\"\
  8102.         \
  8103.     elseif mode == \"save\" then\
  8104.         if animated then saveNFA(sPath)\
  8105.         else saveNFP(sPath) end\
  8106.         \
  8107.     elseif mode == \"exit\" then\
  8108.         isRunning = false\
  8109.     \
  8110.     elseif mode ~= state then state = mode\
  8111.     else state = \"paint\"\
  8112.     end\
  8113. end\
  8114. \
  8115. --[[The main function of the program, reads and handles all events and updates them accordingly. Mode changes,\
  8116.     painting to the canvas and general selections are done here.\
  8117.     Params: none\
  8118.     Returns:nil\
  8119. ]]--\
  8120. local function handleEvents()\
  8121.     recttimer = os.startTimer(0.5)\
  8122.     while isRunning do\
  8123.         drawCanvas()\
  8124.         drawInterface()\
  8125.         local id,p1,p2,p3 = os.pullEvent()\
  8126.         if id==\"timer\" then\
  8127.             updateTimer(p1)\
  8128.         elseif id==\"mouse_click\" or id==\"mouse_drag\" then\
  8129.             if p2 >=w-1 and p3 < #column+1 then\
  8130.                 if p1==1 then lSel = column[p3]\
  8131.                 else rSel = column[p3] end\
  8132.             elseif p2 >=w-1 and p3==#column+1 then\
  8133.                 if p1==1 then lSel = nil\
  8134.                 else rSel = nil end\
  8135.             elseif p2==w-1 and p3==h and animated then\
  8136.                 changeFrame(sFrame-1)\
  8137.             elseif p2==w and p3==h and animated then\
  8138.                 changeFrame(sFrame+1)\
  8139.             elseif p2 < w-10 and p3==h then\
  8140.                 local sel = displayDropDown(1, h-1, ddModes)\
  8141.                 performSelection(sel)\
  8142.             elseif p2 < w-1 and p3 <= h-1 then\
  8143.                 if state==\"pippette\" then\
  8144.                     if p1==1 then\
  8145.                         if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then\
  8146.                             lSel = frames[sFrame][p3+sy][p2+sx] \
  8147.                         end\
  8148.                     elseif p1==2 then\
  8149.                         if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then\
  8150.                             rSel = frames[sFrame][p3+sy][p2+sx] \
  8151.                         end\
  8152.                     end\
  8153.                 elseif state==\"move\" then\
  8154.                     updateImageLims(record)\
  8155.                     moveImage(p2,p3)\
  8156.                 elseif state==\"flood\" then\
  8157.                     if p1 == 1 and lSel and frames[sFrame][p3+sy]  then \
  8158.                         floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],lSel)\
  8159.                     elseif p1 == 2 and rSel and frames[sFrame][p3+sy] then \
  8160.                         floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],rSel)\
  8161.                     end\
  8162.                 elseif state==\"corner select\" then\
  8163.                     if not selectrect then\
  8164.                         selectrect = { x1=p2+sx, x2=p2+sx, y1=p3+sy, y2=p3+sy }\
  8165.                     elseif selectrect.x1 ~= p2+sx and selectrect.y1 ~= p3+sy then\
  8166.                         if p2+sx<selectrect.x1 then selectrect.x1 = p2+sx\
  8167.                         else selectrect.x2 = p2+sx end\
  8168.                         \
  8169.                         if p3+sy<selectrect.y1 then selectrect.y1 = p3+sy\
  8170.                         else selectrect.y2 = p3+sy end\
  8171.                         \
  8172.                         state = \"select\"\
  8173.                     end\
  8174.                 elseif state==\"select\" then\
  8175.                     if p1 == 1 then\
  8176.                         local swidth = selectrect.x2 - selectrect.x1\
  8177.                         local sheight = selectrect.y2 - selectrect.y1\
  8178.                     \
  8179.                         selectrect.x1 = p2 + sx\
  8180.                         selectrect.y1 = p3 + sy\
  8181.                         selectrect.x2 = p2 + swidth + sx\
  8182.                         selectrect.y2 = p3 + sheight + sy\
  8183.                     elseif p1 == 2 and p2 < w-2 and p3 < h-1 then\
  8184.                         inMenu = true\
  8185.                         local sel = displayDropDown(p2, p3, srModes) \
  8186.                         inMenu = false\
  8187.                         performSelection(sel)\
  8188.                     end\
  8189.                 else\
  8190.                     local f,l = sFrame,sFrame\
  8191.                     if record then f,l = 1,framecount end\
  8192.                     local bwidth = 0\
  8193.                     if state == \"brush\" then bwidth = brushsize-1 end\
  8194.                 \
  8195.                     for i=f,l do\
  8196.                         for x = math.max(1,p2+sx-bwidth),p2+sx+bwidth do\
  8197.                             for y = math.max(1,p3+sy-bwidth), p3+sy+bwidth do\
  8198.                                 if math.abs(x - (p2+sx)) + math.abs(y - (p3+sy)) <= bwidth then\
  8199.                                     if not frames[i][y] then frames[i][y] = {} end\
  8200.                                     if p1==1 then frames[i][y][x] = lSel\
  8201.                                     else frames[i][y][x] = rSel end\
  8202.                                 end\
  8203.                             end\
  8204.                         end\
  8205.                     end\
  8206.                 end\
  8207.             end\
  8208.         elseif id==\"key\" then\
  8209.             if p1==keys.leftCtrl then\
  8210.                 local sel = displayDropDown(1, h-1, ddModes[#ddModes]) \
  8211.                 performSelection(sel)\
  8212.             elseif p1==keys.leftAlt then\
  8213.                 local sel = displayDropDown(1, h-1, ddModes[1]) \
  8214.                 performSelection(sel)\
  8215.             elseif p1==keys.h then \
  8216.                 performSelection(\"help\")\
  8217.             elseif p1==keys.x then \
  8218.                 performSelection(\"cut\")\
  8219.             elseif p1==keys.c then\
  8220.                 performSelection(\"copy\")\
  8221.             elseif p1==keys.v then\
  8222.                 performSelection(\"paste\")\
  8223.             elseif p1==keys.z then\
  8224.                 performSelection(\"clear\")\
  8225.             elseif p1==keys.s then\
  8226.                 performSelection(\"select\")\
  8227.             elseif p1==keys.tab then\
  8228.                 performSelection(\"hide\")\
  8229.             elseif p1==keys.q then\
  8230.                 performSelection(\"alpha to left\")\
  8231.             elseif p1==keys.w then\
  8232.                 performSelection(\"alpha to right\")\
  8233.             elseif p1==keys.f then\
  8234.                 performSelection(\"flood\")\
  8235.             elseif p1==keys.b then\
  8236.                 performSelection(\"brush\")\
  8237.             elseif p1==keys.m then\
  8238.                 performSelection(\"move\")\
  8239.             elseif p1==keys.backslash and animated then\
  8240.                 performSelection(\"record\")\
  8241.             elseif p1==keys.p then\
  8242.                 performSelection(\"pippette\")\
  8243.             elseif p1==keys.g and animated then\
  8244.                 performSelection(\"go to\")\
  8245.             elseif p1==keys.period and animated then\
  8246.                 changeFrame(sFrame+1)\
  8247.             elseif p1==keys.comma and animated then\
  8248.                 changeFrame(sFrame-1)\
  8249.             elseif p1==keys.r and animated then\
  8250.                 performSelection(\"remove\")\
  8251.             elseif p1==keys.space and animated then\
  8252.                 performSelection(\"play\")\
  8253.             elseif p1==keys.left then\
  8254.                 if state == \"move\" then\
  8255.                     updateImageLims(record)\
  8256.                     moveImage(leflim-1,toplim)\
  8257.                 elseif state==\"select\" and selectrect.x1 > 1 then\
  8258.                     selectrect.x1 = selectrect.x1-1\
  8259.                     selectrect.x2 = selectrect.x2-1\
  8260.                 elseif sx > 0 then sx=sx-1 end\
  8261.             elseif p1==keys.right then\
  8262.                 if state == \"move\" then\
  8263.                     updateImageLims(record)\
  8264.                     moveImage(leflim+1,toplim)\
  8265.                 elseif state==\"select\" then\
  8266.                     selectrect.x1 = selectrect.x1+1\
  8267.                     selectrect.x2 = selectrect.x2+1\
  8268.                 else sx=sx+1 end\
  8269.             elseif p1==keys.up then\
  8270.                 if state == \"move\" then\
  8271.                     updateImageLims(record)\
  8272.                     moveImage(leflim,toplim-1)\
  8273.                 elseif state==\"select\" and selectrect.y1 > 1 then\
  8274.                     selectrect.y1 = selectrect.y1-1\
  8275.                     selectrect.y2 = selectrect.y2-1\
  8276.                 elseif sy > 0 then sy=sy-1 end\
  8277.             elseif p1==keys.down then \
  8278.                 if state == \"move\" then\
  8279.                     updateImageLims(record)\
  8280.                     moveImage(leflim,toplim+1)\
  8281.                 elseif state==\"select\" then\
  8282.                     selectrect.y1 = selectrect.y1+1\
  8283.                     selectrect.y2 = selectrect.y2+1\
  8284.                 else sy=sy+1 end\
  8285.             end\
  8286.         elseif id==\"char\" and tonumber(p1) then\
  8287.             if state==\"brush\" and tonumber(p1) > 1 then\
  8288.                 brushsize = tonumber(p1)\
  8289.             elseif tonumber(p1) > 0 then\
  8290.                 changeFrame(tonumber(p1))\
  8291.             end\
  8292.         end\
  8293.     end\
  8294. end\
  8295. \
  8296. --[[  \
  8297.             Section: Main  \
  8298. ]]--\
  8299. \
  8300. --Taken almost directly from edit (for consistency)\
  8301. local tArgs = {...}\
  8302. \
  8303. local ca = 1\
  8304. \
  8305. if tArgs[ca] == \"-a\" then\
  8306.     animated = true\
  8307.     ca = ca + 1\
  8308. end\
  8309. \
  8310. if #tArgs < ca then\
  8311.     print(\"Usage: npaintpro [-a] <path>\")\
  8312.     return\
  8313. end\
  8314. \
  8315. sPath = shell.resolve(tArgs[ca])\
  8316. local bReadOnly = fs.isReadOnly(sPath)\
  8317. if fs.exists(sPath) then\
  8318.     if fs.isDir(sPath) then\
  8319.         print(\"Cannot edit a directory.\")\
  8320.         return\
  8321.     elseif string.find(sPath, \".nfp\") ~= #sPath-3 and string.find(sPath, \".nfa\") ~= #sPath-3 then\
  8322.         print(\"Can only edit .nfp and nfa files:\",string.find(sPath, \".nfp\"),#sPath-3)\
  8323.         return\
  8324.     end\
  8325.     \
  8326.     if string.find(sPath, \".nfa\") == #sPath-3 then\
  8327.         animated = true\
  8328.     end\
  8329.     \
  8330.     if string.find(sPath, \".nfp\") == #sPath-3 and animated then\
  8331.         print(\"Convert to nfa? Y/N\")\
  8332.         if string.find(string.lower(io.read()), \"y\") then\
  8333.             local nsPath = string.sub(sPath, 1, #sPath-1)..\"a\"\
  8334.             fs.move(sPath, nsPath)\
  8335.             sPath = nsPath\
  8336.         else\
  8337.             animated = false\
  8338.         end\
  8339.     end\
  8340. else\
  8341.     if not animated and string.find(sPath, \".nfp\") ~= #sPath-3 then \
  8342.         sPath = sPath..\".nfp\"\
  8343.     elseif animated and string.find(sPath, \".nfa\") ~= #sPath-3 then \
  8344.         sPath = sPath..\".nfa\"\
  8345.     end\
  8346. end \
  8347. \
  8348. if not term.isColour() then\
  8349.     print(\"For colour computers only\")\
  8350.     return\
  8351. end\
  8352. \
  8353. drawLogo()\
  8354. init()\
  8355. handleEvents()\
  8356. \
  8357. term.setBackgroundColour(colours.black)\
  8358. shell.run(\"clear\")",
  8359.         edit = "-- Get file to edit\
  8360. local tArgs = { ... }\
  8361. if #tArgs == 0 then\
  8362.     print( \"Usage: edit <path>\" )\
  8363.     return\
  8364. end\
  8365. \
  8366. -- Error checking\
  8367. local sPath = shell.resolve( tArgs[1] )\
  8368. local bReadOnly = fs.isReadOnly( sPath )\
  8369. if fs.exists( sPath ) and fs.isDir( sPath ) then\
  8370.     print( \"Cannot edit a directory.\" )\
  8371.     return\
  8372. end\
  8373. \
  8374. local x,y = 1,1\
  8375. local w,h = term.getSize()\
  8376. local scrollX, scrollY = 0,0\
  8377. \
  8378. local tLines = {}\
  8379. local bRunning = true\
  8380. \
  8381. -- Colours\
  8382. local highlightColour, keywordColour, commentColour, textColour, bgColour\
  8383. if term.isColour() then\
  8384.     bgColour = colours.black\
  8385.     textColour = colours.white\
  8386.     highlightColour = colours.yellow\
  8387.     keywordColour = colours.yellow\
  8388.     commentColour = colours.green\
  8389.     stringColour = colours.red\
  8390. else\
  8391.     bgColour = colours.black\
  8392.     textColour = colours.white\
  8393.     highlightColour = colours.white\
  8394.     keywordColour = colours.white\
  8395.     commentColour = colours.white\
  8396.     stringColour = colours.white\
  8397. end\
  8398. \
  8399. -- Menus\
  8400. local bMenu = false\
  8401. local nMenuItem = 1\
  8402. local tMenuItems\
  8403. if bReadOnly then\
  8404.     tMenuItems = { \"Exit\", \"Print\" }\
  8405. else\
  8406.     tMenuItems = { \"Save\", \"Exit\", \"Print\" }\
  8407. end\
  8408.     \
  8409. local sStatus = \"Press Ctrl to access menu\"\
  8410. \
  8411. local function load( _sPath )\
  8412.     tLines = {}\
  8413.     if fs.exists( _sPath ) then\
  8414.         local file = io.open( _sPath, \"r\" )\
  8415.         local sLine = file:read()\
  8416.         while sLine do\
  8417.             table.insert( tLines, sLine )\
  8418.             sLine = file:read()\
  8419.         end\
  8420.         file:close()\
  8421.     end\
  8422.     \
  8423.     if #tLines == 0 then\
  8424.         table.insert( tLines, \"\" )\
  8425.     end\
  8426. end\
  8427. \
  8428. local function save( _sPath )\
  8429.     -- Create intervening folder\
  8430.     local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )\
  8431.     if not fs.exists( sDir ) then\
  8432.         fs.makeDir( sDir )\
  8433.     end\
  8434. \
  8435.     -- Save\
  8436.     local file = nil\
  8437.     local function innerSave()\
  8438.         file = fs.open( _sPath, \"w\" )\
  8439.         if file then\
  8440.             for n, sLine in ipairs( tLines ) do\
  8441.                 file.write( sLine .. \"\\n\" )\
  8442.             end\
  8443.         else\
  8444.             error( \"Failed to open \".._sPath )\
  8445.         end\
  8446.     end\
  8447.     \
  8448.     local ok = pcall( innerSave )\
  8449.     if file then \
  8450.         file.close()\
  8451.     end\
  8452.     return ok\
  8453. end\
  8454. \
  8455. local tKeywords = {\
  8456.     [\"and\"] = true,\
  8457.     [\"break\"] = true,\
  8458.     [\"do\"] = true,\
  8459.     [\"else\"] = true,\
  8460.     [\"elseif\"] = true,\
  8461.     [\"end\"] = true,\
  8462.     [\"false\"] = true,\
  8463.     [\"for\"] = true,\
  8464.     [\"function\"] = true,\
  8465.     [\"if\"] = true,\
  8466.     [\"in\"] = true,\
  8467.     [\"local\"] = true,\
  8468.     [\"nil\"] = true,\
  8469.     [\"not\"] = true,\
  8470.     [\"or\"] = true,\
  8471.     [\"repeat\"] = true,\
  8472.     [\"return\"] = true,\
  8473.     [\"then\"] = true,\
  8474.     [\"true\"] = true,\
  8475.     [\"until\"]= true,\
  8476.     [\"while\"] = true,\
  8477. }\
  8478. \
  8479. local function tryWrite( sLine, regex, colour )\
  8480.     local match = string.match( sLine, regex )\
  8481.     if match then\
  8482.         if type(colour) == \"number\" then\
  8483.             term.setTextColour( colour )\
  8484.         else\
  8485.             term.setTextColour( colour(match) )\
  8486.         end\
  8487.         term.write( match )\
  8488.         term.setTextColour( textColour )\
  8489.         return string.sub( sLine, string.len(match) + 1 )\
  8490.     end\
  8491.     return nil\
  8492. end\
  8493. \
  8494. local function writeHighlighted( sLine )\
  8495.     while string.len(sLine) > 0 do  \
  8496.         sLine = \
  8497.             tryWrite( sLine, \"^%-%-%[%[.-%]%]\", commentColour ) or\
  8498.             tryWrite( sLine, \"^%-%-.*\", commentColour ) or\
  8499.             tryWrite( sLine, \"^\\\".-[^\\\\]\\\"\", stringColour ) or\
  8500.             tryWrite( sLine, \"^\\'.-[^\\\\]\\'\", stringColour ) or\
  8501.             tryWrite( sLine, \"^%[%[.-%]%]\", stringColour ) or\
  8502.             tryWrite( sLine, \"^[%w_]+\", function( match )\
  8503.                 if tKeywords[ match ] then\
  8504.                     return keywordColour\
  8505.                 end\
  8506.                 return textColour\
  8507.             end ) or\
  8508.             tryWrite( sLine, \"^[^%w_]\", textColour )\
  8509.     end\
  8510. end\
  8511. \
  8512. local function redrawText()\
  8513.     for y=1,h-1 do\
  8514.         term.setCursorPos( 1 - scrollX, y )\
  8515.         term.clearLine()\
  8516. \
  8517.         local sLine = tLines[ y + scrollY ]\
  8518.         if sLine ~= nil then\
  8519.             writeHighlighted( sLine )\
  8520.         end\
  8521.     end\
  8522.     term.setCursorPos( x - scrollX, y - scrollY )\
  8523. end\
  8524. \
  8525. local function redrawLine(_nY)\
  8526.     local sLine = tLines[_nY]\
  8527.     term.setCursorPos( 1 - scrollX, _nY - scrollY )\
  8528.     term.clearLine()\
  8529.     writeHighlighted( sLine )\
  8530.     term.setCursorPos( x - scrollX, _nY - scrollY )\
  8531. end\
  8532. \
  8533. local function redrawMenu()\
  8534.    -- Clear line\
  8535.    term.setCursorPos( 1, h )\
  8536.     term.clearLine()\
  8537. \
  8538.    -- Draw line numbers\
  8539.    term.setCursorPos( w - string.len( \"Ln \"..y ) + 1, h )\
  8540.    term.setTextColour( highlightColour )\
  8541.    term.write( \"Ln \" )\
  8542.    term.setTextColour( textColour )\
  8543.    term.write( y )\
  8544. \
  8545.    term.setCursorPos( 1, h )\
  8546.     if bMenu then\
  8547.        -- Draw menu\
  8548.         term.setTextColour( textColour )\
  8549.         for nItem,sItem in pairs( tMenuItems ) do\
  8550.             if nItem == nMenuItem then\
  8551.                 term.setTextColour( highlightColour )\
  8552.                 term.write( \"[\" )\
  8553.                 term.setTextColour( textColour )\
  8554.                 term.write( sItem )\
  8555.                 term.setTextColour( highlightColour )\
  8556.                 term.write( \"]\" )\
  8557.                 term.setTextColour( textColour )\
  8558.             else\
  8559.                 term.write( \" \"..sItem..\" \" )\
  8560.             end\
  8561.         end\
  8562.    else\
  8563.        -- Draw status\
  8564.        term.setTextColour( highlightColour )\
  8565.        term.write( sStatus )\
  8566.        term.setTextColour( textColour )\
  8567.    end\
  8568. \
  8569.     -- Reset cursor\
  8570.     term.setCursorPos( x - scrollX, y - scrollY )\
  8571. end\
  8572. \
  8573. local tMenuFuncs = { \
  8574.     Save=function()\
  8575.         if bReadOnly then\
  8576.             sStatus = \"Access denied\"\
  8577.         else\
  8578.             local ok, err = save( sPath )\
  8579.             if ok then\
  8580.                 sStatus=\"Saved to \"..sPath\
  8581.             else\
  8582.                 sStatus=\"Error saving to \"..sPath\
  8583.             end\
  8584.         end\
  8585.         redrawMenu()\
  8586.     end,\
  8587.     Print=function()\
  8588.         local printer = peripheral.find( \"printer\" )\
  8589.         if not printer then\
  8590.             sStatus = \"No printer attached\"\
  8591.             return\
  8592.         end\
  8593. \
  8594.         local nPage = 0\
  8595.         local sName = fs.getName( sPath )\
  8596.         if printer.getInkLevel() < 1 then\
  8597.             sStatus = \"Printer out of ink\"\
  8598.             return\
  8599.         elseif printer.getPaperLevel() < 1 then\
  8600.             sStatus = \"Printer out of paper\"\
  8601.             return\
  8602.         end\
  8603. \
  8604.         local screenTerminal = term.current()\
  8605.         local printerTerminal = {\
  8606.             getCursorPos = printer.getCursorPos,\
  8607.             setCursorPos = printer.setCursorPos,\
  8608.             getSize = printer.getPageSize,\
  8609.             write = printer.write,\
  8610.         }\
  8611.         printerTerminal.scroll = function()\
  8612.             if nPage == 1 then\
  8613.                 printer.setPageTitle( sName..\" (page \"..nPage..\")\" )            \
  8614.             end\
  8615.             \
  8616.             while not printer.newPage() do\
  8617.                 if printer.getInkLevel() < 1 then\
  8618.                     sStatus = \"Printer out of ink, please refill\"\
  8619.                 elseif printer.getPaperLevel() < 1 then\
  8620.                     sStatus = \"Printer out of paper, please refill\"\
  8621.                 else\
  8622.                     sStatus = \"Printer output tray full, please empty\"\
  8623.                 end\
  8624.     \
  8625.                 term.redirect( screenTerminal )\
  8626.                 redrawMenu()\
  8627.                 term.redirect( printerTerminal )\
  8628.                 \
  8629.                 local timer = os.startTimer(0.5)\
  8630.                 sleep(0.5)\
  8631.             end\
  8632. \
  8633.             nPage = nPage + 1\
  8634.             if nPage == 1 then\
  8635.                 printer.setPageTitle( sName )\
  8636.             else\
  8637.                 printer.setPageTitle( sName..\" (page \"..nPage..\")\" )\
  8638.             end\
  8639.         end\
  8640.         \
  8641.         bMenu = false\
  8642.         term.redirect( printerTerminal )\
  8643.         local ok, error = pcall( function()\
  8644.             term.scroll()\
  8645.             for n, sLine in ipairs( tLines ) do\
  8646.                 print( sLine )\
  8647.             end\
  8648.         end )\
  8649.        term.redirect( screenTerminal )\
  8650.         if not ok then\
  8651.             print( error )\
  8652.         end\
  8653.         \
  8654.         while not printer.endPage() do\
  8655.             sStatus = \"Printer output tray full, please empty\"\
  8656.             redrawMenu()\
  8657.             sleep( 0.5 )\
  8658.         end\
  8659.         bMenu = true\
  8660.             \
  8661.         if nPage > 1 then\
  8662.             sStatus = \"Printed \"..nPage..\" Pages\"\
  8663.         else\
  8664.             sStatus = \"Printed 1 Page\"\
  8665.         end\
  8666.         redrawMenu()\
  8667.     end,\
  8668.     Exit=function()\
  8669.         bRunning = false\
  8670.     end\
  8671. }\
  8672. \
  8673. local function doMenuItem( _n )\
  8674.     tMenuFuncs[tMenuItems[_n]]()\
  8675.     if bMenu then\
  8676.         bMenu = false\
  8677.         term.setCursorBlink( true )\
  8678.     end\
  8679.     redrawMenu()\
  8680. end\
  8681. \
  8682. local function setCursor( x, y )\
  8683.     local screenX = x - scrollX\
  8684.     local screenY = y - scrollY\
  8685.     \
  8686.     local bRedraw = false\
  8687.     if screenX < 1 then\
  8688.         scrollX = x - 1\
  8689.         screenX = 1\
  8690.         bRedraw = true\
  8691.     elseif screenX > w then\
  8692.         scrollX = x - w\
  8693.         screenX = w\
  8694.         bRedraw = true\
  8695.     end\
  8696.     \
  8697.     if screenY < 1 then\
  8698.         scrollY = y - 1\
  8699.         screenY = 1\
  8700.         bRedraw = true\
  8701.     elseif screenY > h-1 then\
  8702.         scrollY = y - (h-1)\
  8703.         screenY = h-1\
  8704.         bRedraw = true\
  8705.     end\
  8706.     \
  8707.     if bRedraw then\
  8708.         redrawText()\
  8709.     end\
  8710.     term.setCursorPos( screenX, screenY )\
  8711.     \
  8712.     -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.\
  8713.     redrawMenu()\
  8714. end\
  8715. \
  8716. -- Actual program functionality begins\
  8717. load(sPath)\
  8718. \
  8719. term.setBackgroundColour( bgColour )\
  8720. term.clear()\
  8721. term.setCursorPos(x,y)\
  8722. term.setCursorBlink( true )\
  8723. \
  8724. redrawText()\
  8725. redrawMenu()\
  8726. \
  8727. -- Handle input\
  8728. while bRunning do\
  8729.     local sEvent, param, param2, param3 = os.pullEvent()\
  8730.     if sEvent == \"key\" then\
  8731.         if param == keys.up then\
  8732.             -- Up\
  8733.             if not bMenu then\
  8734.                 if y > 1 then\
  8735.                     -- Move cursor up\
  8736.                     y = y - 1\
  8737.                     x = math.min( x, string.len( tLines[y] ) + 1 )\
  8738.                     setCursor( x, y )\
  8739.                 end\
  8740.             end\
  8741.         elseif param == keys.down then\
  8742.             -- Down\
  8743.             if not bMenu then\
  8744.                 -- Move cursor down\
  8745.                 if y < #tLines then\
  8746.                     y = y + 1\
  8747.                     x = math.min( x, string.len( tLines[y] ) + 1 )\
  8748.                     setCursor( x, y )\
  8749.                 end\
  8750.             end\
  8751.         elseif param == keys.tab then\
  8752.             -- Tab\
  8753.             if not bMenu and not bReadOnly then\
  8754.                 -- Indent line\
  8755.                 tLines[y]=\"  \"..tLines[y]\
  8756.                 x = x + 2\
  8757.                 setCursor( x, y )\
  8758.                 redrawLine(y)\
  8759.             end\
  8760.         elseif param == keys.pageUp then\
  8761.             -- Page Up\
  8762.             if not bMenu then\
  8763.                 -- Move up a page\
  8764.                 if y - (h - 1) >= 1 then\
  8765.                     y = y - (h - 1)\
  8766.                 else\
  8767.                     y = 1\
  8768.                 end\
  8769.                 x = math.min( x, string.len( tLines[y] ) + 1 )\
  8770.                 setCursor( x, y )\
  8771.             end\
  8772.         elseif param == keys.pageDown then\
  8773.             -- Page Down\
  8774.             if not bMenu then\
  8775.                 -- Move down a page\
  8776.                 if y + (h - 1) <= #tLines then\
  8777.                     y = y + (h - 1)\
  8778.                 else\
  8779.                     y = #tLines\
  8780.                 end\
  8781.                 x = math.min( x, string.len( tLines[y] ) + 1 )\
  8782.                 setCursor( x, y )\
  8783.             end\
  8784.         elseif param == keys.home then\
  8785.             -- Home\
  8786.             if not bMenu then\
  8787.                 -- Move cursor to the beginning\
  8788.                 x=1\
  8789.                 setCursor(x,y)\
  8790.             end\
  8791.         elseif param == keys[\"end\"] then\
  8792.             -- End\
  8793.             if not bMenu then\
  8794.                 -- Move cursor to the end\
  8795.                 x = string.len( tLines[y] ) + 1\
  8796.                 setCursor(x,y)\
  8797.             end\
  8798.         elseif param == keys.left then\
  8799.             -- Left\
  8800.             if not bMenu then\
  8801.                 if x > 1 then\
  8802.                     -- Move cursor left\
  8803.                     x = x - 1\
  8804.                 elseif x==1 and y>1 then\
  8805.                     x = string.len( tLines[y-1] ) + 1\
  8806.                     y = y - 1\
  8807.                 end\
  8808.                 setCursor( x, y )\
  8809.             else\
  8810.                 -- Move menu left\
  8811.                 nMenuItem = nMenuItem - 1\
  8812.                 if nMenuItem < 1 then\
  8813.                     nMenuItem = #tMenuItems\
  8814.                 end\
  8815.                 redrawMenu()\
  8816.             end\
  8817.         elseif param == keys.right then\
  8818.             -- Right\
  8819.             if not bMenu then\
  8820.                 if x < string.len( tLines[y] ) + 1 then\
  8821.                     -- Move cursor right\
  8822.                     x = x + 1\
  8823.                 elseif x==string.len( tLines[y] ) + 1 and y<#tLines then\
  8824.                     x = 1\
  8825.                     y = y + 1\
  8826.                 end\
  8827.                 setCursor( x, y )\
  8828.             else\
  8829.                 -- Move menu right\
  8830.                 nMenuItem = nMenuItem + 1\
  8831.                 if nMenuItem > #tMenuItems then\
  8832.                     nMenuItem = 1\
  8833.                 end\
  8834.                 redrawMenu()\
  8835.             end\
  8836.         elseif param == keys.delete then\
  8837.             -- Delete\
  8838.             if not bMenu and not bReadOnly then\
  8839.                 if  x < string.len( tLines[y] ) + 1 then\
  8840.                     local sLine = tLines[y]\
  8841.                     tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)\
  8842.                     redrawLine(y)\
  8843.                 elseif y<#tLines then\
  8844.                     tLines[y] = tLines[y] .. tLines[y+1]\
  8845.                     table.remove( tLines, y+1 )\
  8846.                     redrawText()\
  8847.                     redrawMenu()\
  8848.                 end\
  8849.             end\
  8850.         elseif param == keys.backspace then\
  8851.             -- Backspace\
  8852.             if not bMenu and not bReadOnly then\
  8853.                 if x > 1 then\
  8854.                     -- Remove character\
  8855.                     local sLine = tLines[y]\
  8856.                     tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)\
  8857.                     redrawLine(y)\
  8858.             \
  8859.                     x = x - 1\
  8860.                     setCursor( x, y )\
  8861.                 elseif y > 1 then\
  8862.                     -- Remove newline\
  8863.                     local sPrevLen = string.len( tLines[y-1] )\
  8864.                     tLines[y-1] = tLines[y-1] .. tLines[y]\
  8865.                     table.remove( tLines, y )\
  8866.                     redrawText()\
  8867.                 \
  8868.                     x = sPrevLen + 1\
  8869.                     y = y - 1\
  8870.                     setCursor( x, y )\
  8871.                 end\
  8872.             end\
  8873.         elseif param == keys.enter then\
  8874.             -- Enter\
  8875.             if not bMenu and not bReadOnly then\
  8876.                 -- Newline\
  8877.                 local sLine = tLines[y]\
  8878.                 local _,spaces=string.find(sLine,\"^[ ]+\")\
  8879.                 if not spaces then\
  8880.                     spaces=0\
  8881.                 end\
  8882.                 tLines[y] = string.sub(sLine,1,x-1)\
  8883.                 table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )\
  8884.                 redrawText()\
  8885.             \
  8886.                 x = spaces+1\
  8887.                 y = y + 1\
  8888.                 setCursor( x, y )\
  8889.             elseif bMenu then\
  8890.                 -- Menu selection\
  8891.                 doMenuItem( nMenuItem )\
  8892.             end\
  8893.         elseif param == keys.leftCtrl or param == keys.rightCtrl then\
  8894.             -- Menu toggle\
  8895.             bMenu = not bMenu\
  8896.             if bMenu then\
  8897.                 term.setCursorBlink( false )\
  8898.             else\
  8899.                 term.setCursorBlink( true )\
  8900.             end\
  8901.             redrawMenu()\
  8902.         end\
  8903.         \
  8904.     elseif sEvent == \"char\" then\
  8905.         if not bMenu and not bReadOnly then\
  8906.             -- Input text\
  8907.             local sLine = tLines[y]\
  8908.             tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\
  8909.             redrawLine(y)\
  8910.         \
  8911.             x = x + 1\
  8912.             setCursor( x, y )\
  8913.         elseif bMenu then\
  8914.             -- Select menu items\
  8915.             for n,sMenuItem in ipairs( tMenuItems ) do\
  8916.                 if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then\
  8917.                     doMenuItem( n )\
  8918.                     break\
  8919.                 end\
  8920.             end\
  8921.         end\
  8922. \
  8923.     elseif sEvent == \"paste\" then\
  8924.         if not bMenu and not bReadOnly then\
  8925.             -- Input text\
  8926.             local sLine = tLines[y]\
  8927.             tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\
  8928.             redrawLine(y)\
  8929. \
  8930.             x = x + string.len( param )\
  8931.             setCursor( x, y )\
  8932.         end\
  8933.         \
  8934.     elseif sEvent == \"mouse_click\" then\
  8935.         if not bMenu then\
  8936.             if param == 1 then\
  8937.                 -- Left click\
  8938.                 local cx,cy = param2, param3\
  8939.                 if cy < h then\
  8940.                     y = math.min( math.max( scrollY + cy, 1 ), #tLines )\
  8941.                     x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 )\
  8942.                     setCursor( x, y )\
  8943.                 end\
  8944.             end\
  8945.         end\
  8946.         \
  8947.     elseif sEvent == \"mouse_scroll\" then\
  8948.         if not bMenu then\
  8949.             if param == -1 then\
  8950.                 -- Scroll up\
  8951.                 if scrollY > 0 then\
  8952.                     -- Move cursor up\
  8953.                     scrollY = scrollY - 1\
  8954.                     redrawText()\
  8955.                 end\
  8956.             \
  8957.             elseif param == 1 then\
  8958.                 -- Scroll down\
  8959.                 local nMaxScroll = #tLines - (h-1)\
  8960.                 if scrollY < nMaxScroll then\
  8961.                     -- Move cursor down\
  8962.                     scrollY = scrollY + 1\
  8963.                     redrawText()\
  8964.                 end\
  8965.                 \
  8966.             end\
  8967.         end\
  8968. \
  8969.     elseif sEvent == \"term_resize\" then\
  8970.         w,h = term.getSize()\
  8971.        setCursor( x, y )\
  8972.        redrawMenu()\
  8973.        redrawText()\
  8974. \
  8975.     end\
  8976. end\
  8977. \
  8978. -- Cleanup\
  8979. term.clear()\
  8980. term.setCursorBlink( false )\
  8981. term.setCursorPos( 1, 1 )",
  8982.       },
  8983.       [ "Main.lua" ] = "--------------FileX v1.2-------------\
  8984. ---------------Program---------------\
  8985. --------------by Creator-------------\
  8986. \
  8987. --Variables--\
  8988. term.current(term.native())\
  8989. local copyPath = \"\"\
  8990. local copyHelp = \"\"\
  8991. local textutilsserialize = textutils.serialize\
  8992. local textutilsunserialize = textutils.unserialize\
  8993. local w, h = term.getSize()\
  8994. local folderMenu = {\
  8995.     term.current(),\
  8996.     16,\
  8997.     \"Folder Options\",\
  8998.     colors.white,\
  8999.     colors.blue,\
  9000.     colors.black,\
  9001.     colors.lightGray,\
  9002.     {\
  9003.         {\
  9004.             \"Open\",\
  9005.             \"open\",\
  9006.         },\
  9007.         {\
  9008.             \"Delete\",\
  9009.             \"delete\",\
  9010.         },\
  9011.         {\
  9012.             \"Rename\",\
  9013.             \"rename\",\
  9014.         },\
  9015.         {\
  9016.             \"Move\",\
  9017.             \"move\",\
  9018.         },\
  9019.         {\
  9020.             \"Copy\",\
  9021.             \"copy\",\
  9022.         },\
  9023.         {\
  9024.             \"Cancel\",\
  9025.             \"cancel\",\
  9026.         },\
  9027.     },\
  9028. }\
  9029. local fileMenu = {\
  9030.     term.current(),\
  9031.     16,\
  9032.     \"File Options\",\
  9033.     colors.white,\
  9034.     colors.blue,\
  9035.     colors.black,\
  9036.     colors.lightGray,\
  9037.     {\
  9038.         {\
  9039.             \"Open\",\
  9040.             \"open\",\
  9041.         },\
  9042.         {\
  9043.             \"Delete\",\
  9044.             \"delete\",\
  9045.         },\
  9046.         {\
  9047.             \"Rename\",\
  9048.             \"rename\",\
  9049.         },\
  9050.         {\
  9051.             \"Move\",\
  9052.             \"move\",\
  9053.         },\
  9054.         {\
  9055.             \"Cancel\",\
  9056.             \"cancel\",\
  9057.         },\
  9058.         {\
  9059.             \"Run\",\
  9060.             \"run\",\
  9061.         },\
  9062.         {\
  9063.             \"Copy\",\
  9064.             \"copy\",\
  9065.         },\
  9066.         {\
  9067.             \"Open with\",\
  9068.             \"openWith\",\
  9069.         },\
  9070.     },\
  9071. }\
  9072. local nilMenu = {\
  9073.     term.current(),\
  9074.     16,\
  9075.     \"Options\",\
  9076.     colors.white,\
  9077.     colors.blue,\
  9078.     colors.black,\
  9079.     colors.lightGray,\
  9080.     {\
  9081.         {\
  9082.             \"Make a folder\",\
  9083.             \"makeFolder\",\
  9084.         },\
  9085.         {\
  9086.             \"Make a file\",\
  9087.             \"makeFile\",\
  9088.         },\
  9089.         {\
  9090.             \"Cancel\",\
  9091.             \"cancel\",\
  9092.         },\
  9093.     },\
  9094. }\
  9095. local newFolderWindow = {\
  9096.     term.current(),\
  9097.     math.floor((w-32)/2),\
  9098.     math.floor((h-8)/2),\
  9099.     32,\
  9100.     8,\
  9101.     true,\
  9102.     \"New folder name\",\
  9103.     colors.white,\
  9104.     colors.blue,\
  9105.     \"Write the name of%the new folder.\",\
  9106.     colors.black,\
  9107.     colors.lightGray,\
  9108.     colors.white,\
  9109.     colors.black,\
  9110. }\
  9111. local newFileWindow = {\
  9112.     term.current(),\
  9113.     math.floor((w-32)/2),\
  9114.     math.floor((h-8)/2),\
  9115.     32,\
  9116.     8,\
  9117.     true,\
  9118.     \"New file name\",\
  9119.     colors.white,\
  9120.     colors.blue,\
  9121.     \"Write the name of%the new file.\",\
  9122.     colors.black,\
  9123.     colors.lightGray,\
  9124.     colors.white,\
  9125.     colors.black,\
  9126. }\
  9127. local upFileWindow = {\
  9128.     term.current(),\
  9129.     math.floor((w-32)/2),\
  9130.     math.floor((h-8)/2),\
  9131.     32,\
  9132.     8,\
  9133.     true,\
  9134.     \"File path\",\
  9135.     colors.white,\
  9136.     colors.blue,\
  9137.     \"Write the path of%the file.\",\
  9138.     colors.black,\
  9139.     colors.lightGray,\
  9140.     colors.white,\
  9141.     colors.black,\
  9142. }\
  9143. local moveFolderWindow = {\
  9144.     term.current(),\
  9145.     math.floor((w-32)/2),\
  9146.     math.floor((h-8)/2),\
  9147.     32,\
  9148.     8,\
  9149.     true,\
  9150.     \"New folder path\",\
  9151.     colors.white,\
  9152.     colors.blue,\
  9153.     \"Write the name of%the new folder path.\",\
  9154.     colors.black,\
  9155.     colors.lightGray,\
  9156.     colors.white,\
  9157.     colors.black,\
  9158. }\
  9159. local bgColor = colors.black\
  9160. local txtColor = colors.white\
  9161. local domain = {}\
  9162. local currDir = \"\"\
  9163. local files = {}\
  9164. local Buttons = {\
  9165.     {\
  9166.         2,\
  9167.         2,\
  9168.         9,\
  9169.         1,\
  9170.         \" Refresh \",\
  9171.         colors.white,\
  9172.         colors.green,\
  9173.         \"refresh\"\
  9174.     },\
  9175.     {\
  9176.         13,\
  9177.         2,\
  9178.         4,\
  9179.         1,\
  9180.         \" Up \",\
  9181.         colors.white,\
  9182.         colors.green,\
  9183.         \"up\"\
  9184.     },\
  9185.     {\
  9186.         19,\
  9187.         2,\
  9188.         7,\
  9189.         1,\
  9190.         \" Paste \",\
  9191.         colors.white,\
  9192.         colors.green,\
  9193.         \"paste\"\
  9194.     },\
  9195. }\
  9196. local folderIcon = {{2,2,2,2,16,16,16,16,},{2,2,2,2,2,2,2,2,},{2,2,2,2,2,2,2,2,},{2,2,2,2,2,2,2,2,},}\
  9197. local fileIcon = {{8192,8192,8192,8192,8192,8192,8192,8192,},{8192,8192,8192,8192,8192,8192,8192,8192,},{8192,8192,8192,8192,8192,8192,8192,8192,},{8192,8192,8192,8192,8192,8192,8192,8192,},}\
  9198. local scroll = 0\
  9199. local globalButtonList = {}\
  9200. local notEnded = true\
  9201. local fileExtensions = {\
  9202. nfp = \"nPaintPro\",\
  9203. nfa = \"nPaintPro\",\
  9204. txt = \"Edit\",\
  9205. exe = \"Shell\",\
  9206. lua = \"Shell\",\
  9207. ico = \"BetterPaint\",\
  9208. }\
  9209. \
  9210. --Functions--\
  9211. \
  9212. local function detectButtonHit(buttonsToTest)\
  9213.     local event, button, x, y\
  9214.     repeat\
  9215.         event, button, x, y = os.pullEvent()\
  9216.     until event == \"mouse_click\" or event == \"key\"\
  9217.     if event == \"mouse_click\" then\
  9218.         for i,v in pairs(buttonsToTest) do\
  9219.             if v[1] <= x and x <= v[3] and v[2] <= y and y <= v[4] then\
  9220.                 return {v[5], button, x, y}\
  9221.             end\
  9222.         end\
  9223.     elseif event == \"key\" then\
  9224.         return {\"key:\"..tostring(button)}\
  9225.     end\
  9226.     return {\"pong\"}\
  9227. end\
  9228. \
  9229. local function mkStrShort(str,lenght,n)\
  9230.     local bufferTable = {}\
  9231.     local toReturnTable = {}\
  9232.     local lenghtN = tonumber(lenght)\
  9233.     if lenghtN == nil then return false end\
  9234.     for i = 0,n-1 do \
  9235.         bufferTable[i+1] = string.sub(tostring(str),(i*lenghtN)+1,(i*lenghtN)+lenghtN)\
  9236.     end\
  9237.     for i,v in pairs(bufferTable) do\
  9238.         if v ~= nil then\
  9239.             toReturnTable[#toReturnTable+1] = v\
  9240.         end\
  9241.     end\
  9242.     return toReturnTable\
  9243. end\
  9244. \
  9245. local function clear(bgColorArg)\
  9246.     term.setBackgroundColor(bgColorArg or bgColor)\
  9247.     term.setTextColor(txtColor)\
  9248.     term.setCursorPos(1,1)\
  9249.     term.clear()\
  9250.     globalButtonList = {}\
  9251. end\
  9252. \
  9253. local function dropDownMenu(tableInput,clearBg,x,y)\
  9254.     term.setCursorPos(1,1)\
  9255.     if clearBg ~= false then\
  9256.         clear(colors.cyan)\
  9257.     end\
  9258.     globalButtonList = {}\
  9259.     local nTable = {}\
  9260.     local dropDownMenuWindow = window.create(tableInput[1],x,y,tableInput[2],#tableInput[8]+1,true)\
  9261.     dropDownMenuWindow.setTextColor(tableInput[4])\
  9262.     dropDownMenuWindow.setBackgroundColor(tableInput[5])\
  9263.     dropDownMenuWindow.setCursorPos(1,1)\
  9264.     dropDownMenuWindow.clearLine()\
  9265.     dropDownMenuWindow.write(tableInput[3])\
  9266.     dropDownMenuWindow.setTextColor(tableInput[6])\
  9267.     dropDownMenuWindow.setBackgroundColor(tableInput[7])\
  9268.     for i = 1 , #tableInput[8] do\
  9269.         dropDownMenuWindow.setCursorPos(1,i+1)\
  9270.         dropDownMenuWindow.clearLine()\
  9271.         dropDownMenuWindow.write(tableInput[8][i][1])\
  9272.         globalButtonList[#globalButtonList+1] = {x+1,y+i,x+tableInput[2],y+i,tableInput[8][i][2]}\
  9273.     end\
  9274.     local result\
  9275.     repeat\
  9276.         result =  detectButtonHit(globalButtonList)\
  9277.     until result[1] ~= \"pong\"\
  9278.     return result[1]\
  9279. end\
  9280. \
  9281. local function dialogBox(tableInput,clearBg)\
  9282.     if clearBg ~= false then\
  9283.         clear(colors.cyan)\
  9284.     end\
  9285.     local nTable = {}\
  9286.     dialogBoxWindow = window.create(\
  9287.     tableInput[1],\
  9288.     tableInput[2],\
  9289.     tableInput[3],\
  9290.     tableInput[4],\
  9291.     tableInput[5])\
  9292.     dialogBoxWindow.setBackgroundColor(tableInput[9])\
  9293.     dialogBoxWindow.setCursorPos(2,1)\
  9294.     dialogBoxWindow.clearLine()\
  9295.     dialogBoxWindow.setTextColor(tableInput[8])\
  9296.     dialogBoxWindow.write(tableInput[7])\
  9297.     dialogBoxWindow.setCursorPos(1,2)\
  9298.     dialogBoxWindow.setBackgroundColor(tableInput[12])\
  9299.     for i = 2 , tableInput[5] do\
  9300.         dialogBoxWindow.setCursorPos(1,i)\
  9301.         dialogBoxWindow.clearLine()\
  9302.     end\
  9303.     dialogBoxWindow.setCursorPos(1,2)\
  9304.     dialogBoxWindow.setTextColor(tableInput[11])\
  9305.     for token in string.gmatch(tableInput[10],\"[^%%]+\") do\
  9306.         nTable[#nTable+1] = token\
  9307.     end\
  9308.     for i,v in pairs(nTable) do\
  9309.         dialogBoxWindow.setCursorPos(2,1+i)\
  9310.         dialogBoxWindow.write(v)\
  9311.     end\
  9312.     local totalLenght = 0\
  9313.     globalButtonList = {}\
  9314.     for i,v in pairs(tableInput[13]) do\
  9315.         dialogBoxWindow.setCursorPos(2+totalLenght,tableInput[5]-1)\
  9316.         dialogBoxWindow.setTextColor(v[2])\
  9317.         dialogBoxWindow.setBackgroundColor(v[3])\
  9318.         local toWrite = \" \"..v[1]..\" \"\
  9319.         dialogBoxWindow.write(toWrite)\
  9320.         if globalButtonList == nil then\
  9321.             globalButtonList = {{tableInput[2]+1+totalLenght,tableInput[3] + tableInput[5]-2,tableInput[2]+totalLenght + #toWrite,tableInput[3] + tableInput[5]-1,v[4]}}\
  9322.         else\
  9323.             globalButtonList[#globalButtonList+1] = {tableInput[2]+1+totalLenght,tableInput[3] + tableInput[5]-2,tableInput[2]+totalLenght + #toWrite,tableInput[3] + tableInput[5]-1,v[4]}\
  9324.         end\
  9325.         totalLenght = #toWrite + totalLenght + 2\
  9326.     end\
  9327.     local repeatIt = true\
  9328.     while repeatIt == true do\
  9329.         local unparsedResult = detectButtonHit(globalButtonList)\
  9330.         result = unparsedResult[1]\
  9331.         if result ~= \"pong\" then\
  9332.             repeatIt = false\
  9333.         end\
  9334.     end\
  9335.     return result\
  9336. end\
  9337. \
  9338. local function textBox(tableInput,secret,clearBg)\
  9339.     if clearBg ~= false then\
  9340.         clear(colors.cyan)\
  9341.     end\
  9342.     local nTable = {}\
  9343.     textBoxWindow = window.create(tableInput[1],tableInput[2],tableInput[3],tableInput[4],tableInput[5])\
  9344.     textBoxWindow.setCursorPos(2,1)\
  9345.     textBoxWindow.setBackgroundColor(tableInput[9])\
  9346.     textBoxWindow.clearLine()\
  9347.     textBoxWindow.setTextColor(tableInput[8])\
  9348.     textBoxWindow.write(tableInput[7])\
  9349.     textBoxWindow.setCursorPos(1,2)\
  9350.     textBoxWindow.setBackgroundColor(tableInput[12])\
  9351.     for i = 2 , tableInput[5] do\
  9352.         textBoxWindow.setCursorPos(1,i)\
  9353.         textBoxWindow.clearLine()\
  9354.     end\
  9355.     textBoxWindow.setTextColor(tableInput[11])\
  9356.     for token in string.gmatch(tableInput[10],\"[^%%]+\") do\
  9357.         nTable[#nTable+1] = token\
  9358.     end\
  9359.     for i,v in pairs(nTable) do\
  9360.         textBoxWindow.setCursorPos(2,1+i)\
  9361.         textBoxWindow.write(v)\
  9362.     end\
  9363.     textBoxWindow.setTextColor(tableInput[13])\
  9364.     textBoxWindow.setBackgroundColor(tableInput[14])\
  9365.     textBoxWindow.setCursorPos(2,tableInput[5]-1)\
  9366.     textBoxWindow.clearLine()\
  9367.     textBoxWindow.setCursorPos(2,tableInput[5]-1)\
  9368.     textBoxWindow.setTextColor(tableInput[13])\
  9369.     textBoxWindow.setBackgroundColor(tableInput[14])\
  9370.     if secret then\
  9371.         return read(\"*\")\
  9372.     else\
  9373.         return read()\
  9374.     end\
  9375. end\
  9376. \
  9377. local function refresh(dir)\
  9378.     local bufferFiles = {}\
  9379.     for i,v in pairs(fs.list(dir)) do\
  9380.         if fs.isDir(currDir..\"/\"..v) then\
  9381.             bufferFiles[#bufferFiles+1] = {v,\"folder\"}\
  9382.         else\
  9383.             bufferFiles[#bufferFiles+1] = {v,\"file\"}\
  9384.         end\
  9385.     end\
  9386.     return bufferFiles\
  9387. end\
  9388. \
  9389. local function drawOptions(tableInputDrawOptions)\
  9390.     for i,v in pairs(tableInputDrawOptions) do\
  9391.         term.setCursorPos(v[1],v[2])\
  9392.         paintutils.drawFilledBox(v[1],v[2],v[3]+v[1]-1,v[4]+v[2]-1,v[7])\
  9393.         term.setCursorPos(v[1],v[2])\
  9394.         term.setTextColor(v[6])\
  9395.         term.write(v[5])\
  9396.         if globalButtonList == nil then\
  9397.             globalButtonList = {{v[1],v[2],v[3]+v[1]-1,v[4]+v[2]-1,\"button:\"..v[8]}}\
  9398.         else\
  9399.             globalButtonList[#globalButtonList+1] = {v[1],v[2],v[3]+v[1]-1,v[4]+v[2]-1,\"button:\"..v[8]}\
  9400.         end\
  9401.     end\
  9402. end\
  9403. \
  9404. local function drawFiles(filesToDisplay)\
  9405.     local numItemsX = math.floor((w-1)/10)\
  9406.     numItemsY = math.ceil(#filesToDisplay/numItemsX)\
  9407.     local currFile = 1\
  9408.     for i = 0 , numItemsY-1 do\
  9409.         for k = 0 , numItemsX - 1 do\
  9410.             if currFile > #filesToDisplay then\
  9411.                 break\
  9412.             else\
  9413.                 term.setTextColor(colors.black)\
  9414.                 if filesToDisplay[currFile][2] == \"file\" then\
  9415.                     paintutils.drawImage(fileIcon,(k*10)+2,(i*5)+4-scroll)\
  9416.                     for l,m in pairs(mkStrShort(filesToDisplay[currFile][1],6,3)) do \
  9417.                         term.setCursorPos((k*10)+3,(i*5)+4+l-scroll)\
  9418.                         term.write(m)\
  9419.                     end\
  9420.                     if ((i*5)+4-scroll) < 4 then\
  9421.                         if ((i*5)+7-scroll) >= 4 then\
  9422.                             if globalButtonList == nil then\
  9423.                                 globalButtonList = {{((k*10)+2),4,((k*10)+9),((i*5)+7-scroll),\"file:\"..filesToDisplay[currFile][1]}}\
  9424.                             else\
  9425.                                 globalButtonList[#globalButtonList+1] = {((k*10)+2),4,((k*10)+9),((i*5)+7-scroll),\"file:\"..filesToDisplay[currFile][1]}\
  9426.                             end\
  9427.                         end\
  9428.                     else\
  9429.                         if globalButtonList == nil then\
  9430.                             globalButtonList = {{((k*10)+2),((i*5)+4-scroll),((k*10)+9),((i*5)+7-scroll),\"file:\"..filesToDisplay[currFile][1]}}\
  9431.                         else\
  9432.                             globalButtonList[#globalButtonList+1] = {((k*10)+2),((i*5)+4-scroll),((k*10)+9),((i*5)+7-scroll),\"file:\"..filesToDisplay[currFile][1]}\
  9433.                         end\
  9434.                     end\
  9435.                 elseif filesToDisplay[currFile][2] == \"folder\" then\
  9436.                     paintutils.drawImage(folderIcon,(k*10)+2,(i*5)+4-scroll)\
  9437.                     for l,m in pairs(mkStrShort(filesToDisplay[currFile][1],6,3)) do \
  9438.                         term.setCursorPos((k*10)+3,(i*5)+4+l-scroll)\
  9439.                         term.write(m)\
  9440.                     end\
  9441.                     if ((i*5)+4-scroll) < 4 then\
  9442.                         if ((i*5)+7-scroll) >= 4 then\
  9443.                             if globalButtonList == nil then\
  9444.                                 globalButtonList = {{((k*10)+2),4,((k*10)+9),((i*5)+7-scroll),\"folder:\"..filesToDisplay[currFile][1]}}\
  9445.                             else\
  9446.                                 globalButtonList[#globalButtonList+1] = {((k*10)+2),4,((k*10)+9),((i*5)+7-scroll),\"folder:\"..filesToDisplay[currFile][1]}\
  9447.                             end\
  9448.                         end\
  9449.                     else\
  9450.                         if globalButtonList == nil then\
  9451.                             globalButtonList = {{((k*10)+2),((i*5)+4-scroll),((k*10)+9),((i*5)+7-scroll),\"folder:\"..filesToDisplay[currFile][1]}}\
  9452.                         else\
  9453.                             globalButtonList[#globalButtonList+1] = {((k*10)+2),((i*5)+4-scroll),((k*10)+9),((i*5)+7-scroll),\"folder:\"..filesToDisplay[currFile][1]}\
  9454.                         end\
  9455.                     end\
  9456.                 end\
  9457.                 currFile = currFile + 1\
  9458.             end\
  9459.         end\
  9460.     end\
  9461. end\
  9462. \
  9463. local function drawSideBar()\
  9464.     local lenghtSideBar = h-4\
  9465.     if numItemsY ~= 0 then\
  9466.          lenghtSideBar = math.ceil(((h-5)*(h-5))/(numItemsY*5))\
  9467.     end\
  9468.     paintutils.drawLine(w,3,w,3+lenghtSideBar,colors.green)\
  9469.     term.setBackgroundColor(colors.blue)\
  9470.     term.setCursorPos(w,3)\
  9471.     term.write(\"^\")\
  9472.     term.setCursorPos(w,h-1)\
  9473.     term.write(\"v\")\
  9474.     if globalButtonList == nil then\
  9475.         globalButtonList = {{w,3,w,3,\"button:scrollUp\"}}\
  9476.     else\
  9477.         globalButtonList[#globalButtonList+1] = {w,3,w,3,\"button:scrollUp\"}\
  9478.     end\
  9479.     if globalButtonList == nil then\
  9480.         globalButtonList = {{w,h-1,w,h-1,\"button:scrollDown\"}}\
  9481.     else\
  9482.         globalButtonList[#globalButtonList+1] = {w,h-1,w,h-1,\"button:scrollDown\"}\
  9483.     end\
  9484. end\
  9485. \
  9486. local function program(extension)\
  9487.     if fileExtensions[extension] ~= nil then\
  9488.         return fileExtensions[extension]\
  9489.     else\
  9490.         return \"edit\"\
  9491.     end\
  9492. end\
  9493. \
  9494. local function main(filesToDisplay,buttonsToDisplay)\
  9495.     clear(colors.white)\
  9496.     drawFiles(filesToDisplay)\
  9497.     drawSideBar()\
  9498.     term.setBackgroundColor(colors.orange)\
  9499.     for i = 1,2 do\
  9500.         term.setCursorPos(1,i)\
  9501.         term.clearLine()\
  9502.     end\
  9503.     term.setCursorPos(1,1)\
  9504.     term.setTextColor(colors.black)\
  9505.     term.write(\"Creator\\'s FileX v1.0\")\
  9506.     term.setCursorPos(w,1)\
  9507.     term.setBackgroundColor(colors.magenta)\
  9508.     term.write(\"X\")\
  9509.     if globalButtonList == nil then\
  9510.         globalButtonList = {{w,1,w,1,\"button:x\"}}\
  9511.     else\
  9512.         globalButtonList[#globalButtonList+1] = {w,1,w,1,\"button:x\"}\
  9513.     end\
  9514.     if globalButtonList == nil then\
  9515.         globalButtonList = {{1,3,w,h,\"nil:nil\"}}\
  9516.     else\
  9517.         globalButtonList[#globalButtonList+1] = {1,4,w,h,\"nil:nil\"}\
  9518.     end\
  9519.     drawOptions(buttonsToDisplay)\
  9520.     if globalButtonList == nil then\
  9521.         globalButtonList = {{1,1,w,3,\"nil:nilnil\"}}\
  9522.     else\
  9523.         globalButtonList[#globalButtonList+1] = {1,1,w,3,\"nil:nilnil\"}\
  9524.     end\
  9525.     term.setCursorPos(1,h)\
  9526.     term.setBackgroundColor(colors.orange)\
  9527.     term.clearLine()\
  9528.     term.setTextColor(colors.black)\
  9529.     term.write(currDir)\
  9530.     term.setCursorPos(1,1)\
  9531.     local detectedButtonUnparsedTable = detectButtonHit(globalButtonList)\
  9532.     local detectedButtonUnparsed = detectedButtonUnparsedTable[1]\
  9533.     local button = detectedButtonUnparsedTable[2]\
  9534.     local detectedButtonParsedTable = {}\
  9535.     for token in string.gmatch(detectedButtonUnparsed,\"[^:]+\") do\
  9536.         detectedButtonParsedTable[#detectedButtonParsedTable + 1] = token\
  9537.     end\
  9538.     local action = detectedButtonParsedTable[2]\
  9539.     if detectedButtonParsedTable[1] == \"button\" then\
  9540.         if action == \"x\" then\
  9541.             term.setBackgroundColor(colors.black)\
  9542.             clear()\
  9543.             print(\"Thank you for using Creator\\'s FTPclient. More coming soon...\\nSpecial thanks to:\\nNitrogenFingers for nPaintPro\")\
  9544.             notEnded = false\
  9545.         elseif action == \"up\" then\
  9546.             scroll = 0\
  9547.             if currDir == \"/\" then\
  9548.             else\
  9549.                 local currDirBuffer = {}\
  9550.                 for token in string.gmatch(currDir,\"(/[^/]+)\") do\
  9551.                     currDirBuffer[#currDirBuffer + 1] = token\
  9552.                 end\
  9553.                 currDir = \"\"\
  9554.                 if #currDirBuffer == 1 then\
  9555.                     currDir = \"\"\
  9556.                 else\
  9557.                     for i = 1, #currDirBuffer-1 do\
  9558.                         if i == 1 then\
  9559.                             currDir = currDirBuffer[1]\
  9560.                         else\
  9561.                             currDir = currDir..currDirBuffer[i]\
  9562.                         end\
  9563.                     end\
  9564.                 end\
  9565.                 files = refresh(currDir)\
  9566.             end\
  9567.         elseif action == \"refresh\" then\
  9568.             files = refresh(currDir)\
  9569.         elseif action == \"scrollUp\" then\
  9570.             scroll = scroll - 1\
  9571.             if scroll < 0 then\
  9572.                 scroll = 0\
  9573.             end\
  9574.         elseif action == \"scrollDown\" then\
  9575.             scroll = scroll + 1\
  9576.             if scroll > numItemsY*6 - h then\
  9577.                 scroll = scroll - 1\
  9578.             end\
  9579.         elseif action == \"paste\" then\
  9580.             term.setCursorPos(1,1)\
  9581.             print(pathToCopy)\
  9582.             print(currDir)\
  9583.             print(copyHelp)\
  9584.             sleep(3)\
  9585.             fs.copy(copyPath,currDir..\"/\"..copyHelp)\
  9586.             files = refresh(currDir)\
  9587.             \
  9588.         end\
  9589.     elseif detectedButtonParsedTable[1] == \"key\" then\
  9590.         if tonumber(action) == keys.up then\
  9591.             scroll = scroll - 1\
  9592.             if scroll < 0 then\
  9593.                 scroll = 0\
  9594.             end\
  9595.         elseif tonumber(action) == keys.down then\
  9596.             scroll = scroll + 1\
  9597.             if scroll > numItemsY*6 - h then\
  9598.                 scroll = scroll - 1\
  9599.             end\
  9600.         end\
  9601.     elseif detectedButtonParsedTable[1] == \"folder\" then\
  9602.         if button == 1 then\
  9603.             currDir = currDir..\"/\"..action\
  9604.             files = refresh(currDir)\
  9605.             scroll = 0\
  9606.         elseif button == 2 then\
  9607.             local result = dropDownMenu(folderMenu,false,detectedButtonUnparsedTable[3],detectedButtonUnparsedTable[4])\
  9608.             if result == \"open\" then\
  9609.                 currDir = currDir..\"/\"..action\
  9610.                 files = refresh(currDir)\
  9611.                 scroll = 0\
  9612.             elseif result == \"copy\" then\
  9613.                 pathToCopy = currDir..action\
  9614.             elseif result == \"delete\" then\
  9615.                 fs.delete(currDir..\"/\"..action)\
  9616.                 files = refresh(currDir)\
  9617.             elseif result == \"rename\" then\
  9618.                 local answ = textBox(newFolderWindow,false,false)\
  9619.                 fs.move(currDir..\"/\"..action,currDir..\"/\"..answ)\
  9620.                 files = refresh(currDir)\
  9621.             elseif result == \"move\" then\
  9622.                 local answ = textBox(moveFolderWindow,false,false)\
  9623.                 if string.sub(answ,1,1) ~= \"/\" then\
  9624.                     answ = \"/\"..answ\
  9625.                 end\
  9626.                 fs.move(currDir..\"/\"..action,answ)\
  9627.                 files = refresh(currDir)\
  9628.             elseif result == \"copy\" then\
  9629.                 copyPath = currDir..\"/\"..action\
  9630.                 copyHelp = action\
  9631.             end\
  9632.         end\
  9633.     elseif detectedButtonParsedTable[1] == \"file\" then\
  9634.         if button == 1 then\
  9635.             local fileExtension\
  9636.             for token in string.gmatch(action,\"[^%.]+\") do\
  9637.                 fileExtension = token\
  9638.             end\
  9639.             if fileExtension == action then\
  9640.                 fileExtension = \"txt\"\
  9641.             end\
  9642.             programT = program(fileExtension)\
  9643.             --shell.run(progsDir..\"/\"..programT..\" \"..currDir..\"/\"..action)\
  9644.             System.newTask(programT,programT,currDir..\"/\"..action)\
  9645.         elseif button == 2 then\
  9646.             local result = dropDownMenu(fileMenu,false,detectedButtonUnparsedTable[3],detectedButtonUnparsedTable[4])\
  9647.             if result == \"open\" then\
  9648.                 local fileExtension\
  9649.                 for token in string.gmatch(action,\"[^%.]+\") do\
  9650.                     fileExtension = token\
  9651.                 end\
  9652.                 if fileExtension == action then\
  9653.                     fileExtension = \"txt\"\
  9654.                 end\
  9655.                 programT = program(fileExtension)\
  9656.                 System.newTask(programT,programT, currDir..\"/\"..action)\
  9657.             elseif result == \"delete\" then\
  9658.                 fs.delete(currDir..\"/\"..action)\
  9659.                 files = refresh(currDir)\
  9660.             elseif result == \"rename\" then\
  9661.                 local answ = textBox(newFolderWindow,false,false)\
  9662.                 fs.move(currDir..\"/\"..action,currDir..\"/\"..answ)\
  9663.                 files = refresh(currDir)\
  9664.             elseif result == \"move\" then\
  9665.                 local answ = textBox(moveFolderWindow,false,false)\
  9666.                 if string.sub(answ,1,1) ~= \"/\" then\
  9667.                     answ = \"/\"..answ\
  9668.                 end\
  9669.                 fs.move(currDir..\"/\"..action,answ)\
  9670.                 files = refresh(currDir)\
  9671.             elseif result == \"run\" then\
  9672.                 shell.run(progsDir..\"/shell \"..currDir..\"/\"..action)\
  9673.             elseif result == \"openWith\" then\
  9674.                 local possibleExtensions = {}\
  9675.                 for i,v in pairs(fileExtensions) do\
  9676.                     local alreadyRegistered = false\
  9677.                     for m,k in pairs(possibleExtensions) do\
  9678.                         if v == k then\
  9679.                             alreadyRegistered = true\
  9680.                         end\
  9681.                     end\
  9682.                     if not alreadyRegistered then\
  9683.                         possibleExtensions[#possibleExtensions+1] = v\
  9684.                     end\
  9685.                 end\
  9686.                 local openWith = {\
  9687.                     term.current(),\
  9688.                     16,\
  9689.                     \"Open with:\",\
  9690.                     colors.white,\
  9691.                     colors.blue,\
  9692.                     colors.black,\
  9693.                     colors.lightGray,\
  9694.                     {}\
  9695.                 }\
  9696.                 for i,v in pairs(possibleExtensions) do\
  9697.                     openWith[8][#openWith[8]+1] = {v,v}\
  9698.                 end\
  9699.                 openWith[8][#openWith[8]+1] = {\"Cancel\",\"cancel\"}\
  9700.                 globalButtonList = {}\
  9701.                 result = dropDownMenu(openWith,false,detectedButtonUnparsedTable[3],detectedButtonUnparsedTable[4]+6)\
  9702.                 System.newTask(result,result,currDir..\"/\"..action)\
  9703.             elseif result == \"copy\" then\
  9704.                 copyPath = currDir..\"/\"..action\
  9705.                 copyHelp = action\
  9706.             end\
  9707.         end\
  9708.     elseif detectedButtonParsedTable[1] == \"nil\" then\
  9709.         if button == 2 then\
  9710.             if action == \"nil\" then\
  9711.                 local result = dropDownMenu(nilMenu,false,detectedButtonUnparsedTable[3],detectedButtonUnparsedTable[4])\
  9712.                 if result == \"makeFolder\" then\
  9713.                     local answ = textBox(newFolderWindow,false,false)\
  9714.                     fs.makeDir(currDir..\"/\"..answ)\
  9715.                     files = refresh(currDir)\
  9716.                     scroll = 0\
  9717.                 elseif result == \"makeFile\" then\
  9718.                     local answ = textBox(newFileWindow,false,false)\
  9719.                     f = fs.open(currDir..\"/\"..answ,\"w\")\
  9720.                     f.close()\
  9721.                     files = refresh(currDir)\
  9722.                     scroll = 0\
  9723.                 end\
  9724.             end\
  9725.         end\
  9726.     end\
  9727. end\
  9728. \
  9729. --Code--\
  9730. \
  9731. clear()\
  9732. files = refresh(currDir)\
  9733. while notEnded do\
  9734.     main(files,Buttons)\
  9735. end\
  9736. shell.setDir(currDir)",
  9737.       [ "FileX.ico" ] = "error('This is an image, not a program!')\
  9738. {\
  9739.  {\
  9740.    {\
  9741.      16,\
  9742.      \" \",\
  9743.      1,\
  9744.    },\
  9745.    {\
  9746.      16,\
  9747.      \"F\",\
  9748.      32768,\
  9749.    },\
  9750.    {\
  9751.      16,\
  9752.      \" \",\
  9753.      1,\
  9754.    },\
  9755.  },\
  9756.  {\
  9757.    {\
  9758.      2,\
  9759.      \" \",\
  9760.      2,\
  9761.    },\
  9762.    {\
  9763.      16,\
  9764.      \"X\",\
  9765.      32768,\
  9766.    },\
  9767.    {\
  9768.      16,\
  9769.      \" \",\
  9770.      1,\
  9771.    },\
  9772.  },\
  9773.  {\
  9774.    {\
  9775.      2,\
  9776.      \" \",\
  9777.      2,\
  9778.    },\
  9779.    {\
  9780.      16,\
  9781.      \" \",\
  9782.      1,\
  9783.    },\
  9784.    {\
  9785.      16,\
  9786.      \" \",\
  9787.      1,\
  9788.    },\
  9789.  },\
  9790.  {},\
  9791.  [ 0 ] = {\
  9792.    {\
  9793.      16,\
  9794.      \" \",\
  9795.      1,\
  9796.    },\
  9797.    {\
  9798.      16,\
  9799.      \" \",\
  9800.      1,\
  9801.    },\
  9802.    {\
  9803.      16,\
  9804.      \" \",\
  9805.      1,\
  9806.    },\
  9807.  },\
  9808.  [ 14 ] = {},\
  9809.  [ 12 ] = {},\
  9810.  [ 24 ] = {},\
  9811.  [ 26 ] = {},\
  9812.  [ 13 ] = {},\
  9813. }",
  9814.     },
  9815.     Aware = {
  9816.       disk = {},
  9817.       [ "permission.data" ] = "user",
  9818.       [ "Aware.ico" ] = "error('This is an image, not a program!')\
  9819. {\
  9820.  {\
  9821.    {\
  9822.      2,\
  9823.      \"_\",\
  9824.      1,\
  9825.    },\
  9826.    {\
  9827.      2,\
  9828.      \"U\",\
  9829.      1,\
  9830.    },\
  9831.    {\
  9832.      2,\
  9833.      \"_\",\
  9834.      1,\
  9835.    },\
  9836.  },\
  9837.  {\
  9838.    {\
  9839.      2,\
  9840.      \"_\",\
  9841.      1,\
  9842.    },\
  9843.    {\
  9844.      2,\
  9845.      \"U\",\
  9846.      1,\
  9847.    },\
  9848.    {\
  9849.      2,\
  9850.      \"_\",\
  9851.      1,\
  9852.    },\
  9853.  },\
  9854.  {\
  9855.    {\
  9856.      2,\
  9857.      \" \",\
  9858.      1,\
  9859.    },\
  9860.    {\
  9861.      2,\
  9862.      \" \",\
  9863.      1,\
  9864.    },\
  9865.    {\
  9866.      2,\
  9867.      \"/\",\
  9868.      1,\
  9869.    },\
  9870.  },\
  9871.  [ 0 ] = {\
  9872.    {\
  9873.      2,\
  9874.      \" \",\
  9875.      2,\
  9876.    },\
  9877.    {\
  9878.      2,\
  9879.      \" \",\
  9880.      1,\
  9881.    },\
  9882.    {\
  9883.      2,\
  9884.      \"\\\\\",\
  9885.      1,\
  9886.    },\
  9887.  },\
  9888. }",
  9889.       Data = {
  9890.         UselessWords = "what\
  9891. is\
  9892. the\
  9893. it",
  9894.         Commands = "{\
  9895.     shutdown = \"os.shutdown()\",\
  9896.     reboot = \"os.reboot()\",\
  9897.     time = \"print(\\\"The time is \\\"..textutils.formatTime(os.time()))\",\
  9898.     hi = \"redirect(\\\"hello\\\")\",\
  9899.     hello = \"randomElement(wordSet(\\\"Greetings\\\"))\",\
  9900.     exit = \"error(\\\"Thanks for using this thingy thingy!\\\")\",\
  9901.     shutup = \"redirect(\\\"exit\\\")\",\
  9902. }",
  9903.         [ "Aware.layout" ] = "--[[\
  9904.     The Aware Project\
  9905.     by Creator\
  9906.     for TheOS\
  9907. ]]--\
  9908. \
  9909. local layout = {}\
  9910. \
  9911. layout.",
  9912.       },
  9913.       [ "Main.lua" ] = "--[[\
  9914.     The Aware Project\
  9915.     by Creator\
  9916.     for TheOS\
  9917. ]]--\
  9918. --[[\
  9919.     First I am doing the mechanics of the program, afterwards I will do the GUI\
  9920. ]]--\
  9921. \
  9922. --GUI\
  9923. --if _G.Interact == nil then os.loadAPI(\"TheOS/API/Interact\") end\
  9924. --local gui = Interact.Initialize()\
  9925. \
  9926. --Variables--\
  9927. local input = {}\
  9928. local Commands = {}\
  9929. local path = \"TheOS/Programs/Aware.app/\"\
  9930. local UselessWords = {}\
  9931. --Functions--\
  9932. \
  9933. function split(str,sep)\
  9934.     local buffer = {}\
  9935.     for token in str:gmatch(sep) do\
  9936.         buffer[#buffer+1] = token\
  9937.     end\
  9938.     return buffer\
  9939. end\
  9940. \
  9941. function getData()\
  9942.     local var = http.get(\"https://raw.githubusercontent.com/TheOnlyCreator/Aware/master/Test/Test\")\
  9943.     print(var.readAll())\
  9944.     os.pullEvent()\
  9945.     error()\
  9946. end\
  9947. \
  9948. local function readFile(_path)\
  9949.     local file = fs.open(_path,\"r\")\
  9950.     local data = file.readAll()\
  9951.     file.close()\
  9952.     return data\
  9953. end\
  9954. \
  9955. function filter(input)\
  9956.     local buffer = {}\
  9957.     for i,v in pairs(input) do\
  9958.         if UselessWords[v] == true then\
  9959.             buffer[#buffer+1] = i\
  9960.         end\
  9961.     end\
  9962.     for i,v in pairs(buffer) do\
  9963.         input[i] = nil\
  9964.     end\
  9965.     buffer = {}\
  9966.     for i,v in pairs(input) do\
  9967.         local sBuffer = {}\
  9968.         local f = \"\"\
  9969.         for token in string.gmatch(v,\"[%a]+\") do\
  9970.             sBuffer[#sBuffer+1] = token\
  9971.         end\
  9972.         for i,v in pairs(sBuffer) do\
  9973.             f = f..v\
  9974.         end\
  9975.         buffer[#buffer+1] = f\
  9976.     end\
  9977.     return buffer\
  9978. end\
  9979. \
  9980. function redirect(word)\
  9981.     word = string.lower(word)\
  9982.     oneWordCommand(word)\
  9983. end\
  9984. \
  9985. function wordSet(arg)\
  9986.     local fromWeb = http.get(\"https://raw.githubusercontent.com/CodingRevolution/Aware/master/WordSets/\"..arg)\
  9987.     local buffer = fromWeb.readAll()\
  9988.     return split(buffer,\"[^\\n]+\")\
  9989. end\
  9990. \
  9991. function randomElement(input)\
  9992.     local element\
  9993.     local buffer = {}\
  9994.     for i,v in pairs(input) do\
  9995.         buffer[#buffer+1] = i\
  9996.     end\
  9997.     local rnd = buffer[math.random(1,#buffer)]\
  9998.     return input[rnd]\
  9999. end\
  10000. \
  10001. function oneWordCommand(word)\
  10002.     if Commands[word] ~= nil then\
  10003.         local func = loadstring(Commands[word])\
  10004.         setfenv(func, getfenv())\
  10005.         func()\
  10006.     else\
  10007.         local firstLetter = string.sub(word,1,1)\
  10008.         print(firstLetter)\
  10009.         print(word)\
  10010.         local fromWeb = http.get(\"https://raw.githubusercontent.com/CodingRevolution/Aware/master/Actions/\"..firstLetter)\
  10011.         local buffer = fromWeb.readAll()\
  10012.         local tableFromWeb = textutils.unserialize(buffer)\
  10013.         print(tableFromWeb[word])\
  10014.         local func = loadstring(tableFromWeb[word])\
  10015.         setfenv(func, getfenv())\
  10016.         func()\
  10017.     end\
  10018. end\
  10019. \
  10020. function main()\
  10021.     print(\"I am listening...\")\
  10022.     local buffer = read()\
  10023.     input = split(buffer,\"[^%s]+\")\
  10024.     for i,v in pairs(input) do\
  10025.         input[i] = string.lower(v)\
  10026.     end\
  10027.     if #input == 1 then\
  10028.         oneWordCommand(input[1])\
  10029.     else\
  10030.         oneWordCommand(filter(input)[1])\
  10031.     end\
  10032. end\
  10033. \
  10034. \
  10035. --Code--\
  10036. local buffer = readFile(path..\"Commands\")\
  10037. Commands = textutils.unserialize(buffer)\
  10038. \
  10039. local buffer = readFile(path..\"UselessWords\")\
  10040. buffer = split(buffer,\"[^\\n]+\")\
  10041. for i,v in pairs(buffer) do\
  10042.     UselessWords[v] = true\
  10043. end\
  10044. \
  10045. term.setCursorPos(1,1)\
  10046. term.setBackgroundColor(colors.black)\
  10047. term.setTextColor(colors.white)\
  10048. term.clear()\
  10049. \
  10050. while true do\
  10051.     main()\
  10052. end",
  10053.     },
  10054.     Test = {
  10055.       disk = {},
  10056.       [ "Main.lua" ] = "term.clear()\
  10057. local timer = 0\
  10058. while true do\
  10059.     Utils.debug(\"Timer is at \"..tostring(timer)..\" seconds.\")\
  10060.     log.log(\"test\",\"Timer: \"..tostring(timer))\
  10061.     print(timer)\
  10062.     sleep(1)\
  10063.     timer = timer + 1\
  10064. end",
  10065.       [ "permission.data" ] = "userTest",
  10066.     },
  10067.     Lua = {
  10068.       disk = {},
  10069.       [ "Main.lua" ] = "\
  10070. local tArgs = { ... }\
  10071. if #tArgs > 0 then\
  10072.     print( \"This is an interactive Lua prompt.\" )\
  10073.     print( \"To run a lua program, just type its name.\" )\
  10074.     return\
  10075. end\
  10076. \
  10077. local bRunning = true\
  10078. local tCommandHistory = {}\
  10079. local tEnv = {\
  10080.     [\"exit\"] = function()\
  10081.         bRunning = false\
  10082.     end,\
  10083.     [\"_echo\"] = function( ... )\
  10084.         return ...\
  10085.     end,\
  10086. }\
  10087. setmetatable( tEnv, { __index = getfenv() } )\
  10088. \
  10089. if term.isColour() then\
  10090.     term.setTextColour( colours.yellow )\
  10091. end\
  10092. print( \"Interactive Lua prompt.\" )\
  10093. print( \"Call exit() to exit.\" )\
  10094. term.setTextColour( colours.white )\
  10095. \
  10096. while bRunning do\
  10097.     --if term.isColour() then\
  10098.     --  term.setTextColour( colours.yellow )\
  10099.     --end\
  10100.     write( \"lua> \" )\
  10101.     --term.setTextColour( colours.white )\
  10102.     \
  10103.     local s = read( nil, tCommandHistory )\
  10104.     table.insert( tCommandHistory, s )\
  10105.     \
  10106.     local nForcePrint = 0\
  10107.     local func, e = loadstring( s, \"lua\" )\
  10108.     local func2, e2 = loadstring( \"return _echo(\"..s..\");\", \"lua\" )\
  10109.     if not func then\
  10110.         if func2 then\
  10111.             func = func2\
  10112.             e = nil\
  10113.             nForcePrint = 1\
  10114.         end\
  10115.     else\
  10116.         if func2 then\
  10117.             func = func2\
  10118.         end\
  10119.     end\
  10120.     \
  10121.     if func then\
  10122.        setfenv( func, tEnv )\
  10123.        local tResults = { pcall( func ) }\
  10124.        if tResults[1] then\
  10125.             local n = 1\
  10126.             while (tResults[n + 1] ~= nil) or (n <= nForcePrint) do\
  10127.                 local value = tResults[ n + 1 ]\
  10128.                 if type( value ) == \"table\" then\
  10129.                     local ok, serialised = pcall( textutils.serialise, value )\
  10130.                     if ok then\
  10131.                         print( serialised )\
  10132.                     else\
  10133.                         print( tostring( value ) )\
  10134.                     end\
  10135.                 else\
  10136.                     print( tostring( value ) )\
  10137.                 end\
  10138.                 n = n + 1\
  10139.             end\
  10140.        else\
  10141.             printError( tResults[2] )\
  10142.        end\
  10143.    else\
  10144.         printError( e )\
  10145.    end\
  10146.    \
  10147. end",
  10148.     },
  10149.     nPaintPro = {
  10150.       disk = {},
  10151.       [ "main.lua" ] = "--[[\
  10152.         NPaintPro\
  10153.         By NitrogenFingers\
  10154. ]]--\
  10155. \
  10156. --The screen size\
  10157. local w,h = term.getSize()\
  10158. --Whether or not the program is currently waiting on user input\
  10159. local inMenu = false\
  10160. --Whether or not a drop down menu is active\
  10161. local inDropDown = false\
  10162. --Whether or not animation tools are enabled (use -a to turn them on)\
  10163. local animated = false\
  10164. --Whether or not \"blueprint\" display mode is on\
  10165. local blueprint = false\
  10166. --Whether or not the \"layer\" display is on\
  10167. local layerDisplay = false\
  10168. --Whether or not the \"direction\" display is on\
  10169. local printDirection = false\
  10170. --The tool/mode npaintpro is currently in. Default is \"paint\"\
  10171. --For a list of modes, check out the help file\
  10172. local state = \"paint\"\
  10173. --Whether or not the program is presently running\
  10174. local isRunning = true\
  10175. --The rednet address of the 3D printer, if one has been attached\
  10176. local printer = nil\
  10177. \
  10178. --The list of every frame, containing every image in the picture/animation\
  10179. --Note: nfp files always have the picture at frame 1\
  10180. local frames = { }\
  10181. --How many frames are currently in the given animation.\
  10182. local frameCount = 1\
  10183. --The Colour Picker column\
  10184. local column = {}\
  10185. --The currently selected left and right colours\
  10186. local lSel,rSel = colours.white,nil\
  10187. --The amount of scrolling on the X and Y axis\
  10188. local sx,sy = 0,0\
  10189. --The alpha channel colour\
  10190. --Change this to change default canvas colour\
  10191. local alphaC = colours.yellow\
  10192. --The currently selected frame. Default is 1\
  10193. local sFrame = 1\
  10194. --The contents of the image buffer- contains contents, width and height\
  10195. local buffer = nil\
  10196. --The position, width and height of the selection rectangle\
  10197. local selectrect = nil\
  10198. \
  10199. --The currently calculated required materials\
  10200. local requiredMaterials = {}\
  10201. --Whether or not required materials are being displayed in the pallette\
  10202. local requirementsDisplayed = false\
  10203. --A list of the rednet ID's all in-range printers located\
  10204. local printerList = { }\
  10205. --A list of the names of all in-range printers located. Same as the printerList in reference\
  10206. local printerNames = { }\
  10207. --The selected printer\
  10208. local selectedPrinter = 1\
  10209. --The X,Y,Z and facing of the printer\
  10210. local px,py,pz,pfx,pfz = 0,0,0,0,0\
  10211. --The form of layering used\
  10212. local layering = \"up\"\
  10213. \
  10214. --The animation state of the selection rectangle and image buffer \
  10215. local rectblink = 0\
  10216. --The ID for the timer\
  10217. local recttimer = nil\
  10218. --The radius of the brush tool\
  10219. local brushsize = 3\
  10220. --Whether or not \"record\" mode is activated (animation mode only)\
  10221. local record = false\
  10222. --The time between each frame when in play mode (animation mode only)\
  10223. local animtime = 0.3\
  10224. \
  10225. --A list of hexidecimal conversions from numbers to hex digits\
  10226. local hexnums = { [10] = \"a\", [11] = \"b\", [12] = \"c\", [13] = \"d\", [14] = \"e\" , [15] = \"f\" }\
  10227. --The NPaintPro logo (divine, isn't it?)\
  10228. local logo = {\
  10229. \"fcc              3   339\";\
  10230. \" fcc          9333    33\";\
  10231. \"  fcc        933 333  33\";\
  10232. \"   fcc       933  33  33\";\
  10233. \"    fcc      933   33 33\";\
  10234. \"     c88     333   93333\";\
  10235. \"     888     333    9333\";\
  10236. \"      333 3  333     939\";\
  10237. }\
  10238. --The Layer Up and Layer Forward printing icons\
  10239. local layerUpIcon = {\
  10240.     \"0000000\";\
  10241.     \"0088880\";\
  10242.     \"0888870\";\
  10243.     \"07777f0\";\
  10244.     \"0ffff00\";\
  10245.     \"0000000\";\
  10246. }\
  10247. local layerForwardIcon = {\
  10248.     \"0000000\";\
  10249.     \"000fff0\";\
  10250.     \"00777f0\";\
  10251.     \"0888700\";\
  10252.     \"0888000\";\
  10253.     \"0000000\";\
  10254. }\
  10255. --The available menu options in the ctrl menu\
  10256. local mChoices = {\"Save\",\"Exit\"}\
  10257. --The available modes from the dropdown menu- tables indicate submenus (include a name!)\
  10258. local ddModes = { { \"paint\", \"brush\", \"pippette\", \"flood\", \"move\", \"clear\", \"select\", name = \"painting\" }, { \"alpha to left\", \"alpha to right\", \"blueprint on\", \"layers on\", name = \"display\" }, \"help\", { \"print\", \"save\", \"exit\", name = \"file\" }, name = \"menu\" }\
  10259. --The available modes from the selection right-click menu\
  10260. local srModes = { \"cut\", \"copy\", \"paste\", \"clear\", \"hide\", name = \"selection\" }\
  10261. --The list of available help topics for each mode 127\
  10262. local helpTopics = {\
  10263.     [1] = {\
  10264.         name = \"Paint Mode\",\
  10265.         key = nil,\
  10266.         animonly = false,\
  10267.         message = \"The default mode for NPaintPro, for painting pixels.\"\
  10268.         ..\" Controls here that are not overridden will apply for all other modes. Leaving a mode by selecting that mode \"\
  10269.         ..\" again will always send the user back to paint mode.\",\
  10270.         controls = {\
  10271.             { \"Arrow keys\", \"Scroll the canvas\" },\
  10272.             { \"Left Click\", \"Paint/select left colour\" },\
  10273.             { \"Right Click\", \"Paint/select right colour\" },\
  10274.             { \"Z Key\", \"Clear image on screen\" },\
  10275.             { \"Tab Key\", \"Hide selection rectangle if visible\" },\
  10276.             { \"Q Key\", \"Set alpha mask to left colour\" },\
  10277.             { \"W Key\", \"Set alpha mask to right colour\" },\
  10278.             { \"Number Keys\", \"Swich between frames 1-9\" },\
  10279.             { \"</> keys\", \"Move to the next/last frame\" },\
  10280.             { \"R Key\", \"Removes every frame after the current frame\"}\
  10281.         }\
  10282.     },\
  10283.     [2] = {\
  10284.         name = \"Brush Mode\",\
  10285.         key = \"b\",\
  10286.         animonly = false,\
  10287.         message = \"Brush mode allows painting a circular area of variable diameter rather than a single pixel, working in \"..\
  10288.         \"the exact same way as paint mode in all other regards.\",\
  10289.         controls = {\
  10290.             { \"Left Click\", \"Paints a brush blob with the left colour\" },\
  10291.             { \"Right Click\", \"Paints a brush blob with the right colour\" },\
  10292.             { \"Number Keys\", \"Changes the radius of the brush blob from 2-9\" }\
  10293.         }\
  10294.     },\
  10295.     [3] = {\
  10296.         name = \"Pippette Mode\",\
  10297.         key = \"p\",\
  10298.         animonly = false,\
  10299.         message = \"Pippette mode allows the user to click the canvas and set the colour clicked to the left or right \"..\
  10300.         \"selected colour, for later painting.\",\
  10301.         controls = {\
  10302.             { \"Left Click\", \"Sets clicked colour to the left selected colour\" },\
  10303.             { \"Right Click\", \"Sets clicked colour to the right selected colour\" }\
  10304.         }\
  10305.     },\
  10306.     [4] = {\
  10307.         name = \"Move Mode\",\
  10308.         key = \"m\",\
  10309.         animonly = false,\
  10310.         message = \"Mode mode allows the moving of the entire image on the screen. This is especially useful for justifying\"..\
  10311.         \" the image to the top-left for animations or game assets.\",\
  10312.         controls = {\
  10313.             { \"Left/Right Click\", \"Moves top-left corner of image to selected square\" },\
  10314.             { \"Arrow keys\", \"Moves image one pixel in any direction\" }\
  10315.         }\
  10316.     },\
  10317.     [5] = {\
  10318.         name = \"Flood Mode (NYI)\",\
  10319.         key = \"f\",\
  10320.         animonly = false,\
  10321.         message = \"Flood mode allows the changing of an area of a given colour to that of the selected colour. \"..\
  10322.         \"The tool uses a flood4 algorithm and will not fill diagonally. Transparency cannot be flood filled.\",\
  10323.         controls = {\
  10324.             { \"Left Click\", \"Flood fills selected area to left colour\" },\
  10325.             { \"Right Click\", \"Flood fills selected area to right colour\" }\
  10326.         }\
  10327.     },\
  10328.     [6] = {\
  10329.         name = \"Select Mode\",\
  10330.         key = \"s\",\
  10331.         animonly = false,\
  10332.         message = \"Select mode allows the creation and use of the selection rectangle, to highlight specific areas on \"..\
  10333.         \"the screen and perform operations on the selected area of the image. The selection rectangle can contain an \"..\
  10334.         \"image on the clipboard- if it does, the image will flash inside the rectangle, and the rectangle edges will \"..\
  10335.         \"be light grey instead of dark grey.\",\
  10336.         controls = {\
  10337.             { \"C Key\", \"Copy: Moves selection into the clipboard\" },\
  10338.             { \"X Key\", \"Cut: Clears canvas under the rectangle, and moves it into the clipboard\" },\
  10339.             { \"V Key\", \"Paste: Copys clipboard to the canvas\" },\
  10340.             { \"Z Key\", \"Clears clipboard\" },\
  10341.             { \"Left Click\", \"Moves top-left corner of rectangle to selected pixel\" },\
  10342.             { \"Right Click\", \"Opens selection menu\" },\
  10343.             { \"Arrow Keys\", \"Moves rectangle one pixel in any direction\" }\
  10344.         }\
  10345.     },\
  10346.     [7] = {\
  10347.         name = \"Corner Select Mode\",\
  10348.         key = nil,\
  10349.         animonly = false,\
  10350.         message = \"If a selection rectangle isn't visible, this mode is selected automatically. It allows the \"..\
  10351.         \"defining of the corners of the rectangle- one the top-left and bottom-right corners have been defined, \"..\
  10352.         \"NPaintPro switches to selection mode. Note rectangle must be at least 2 pixels wide and high.\",\
  10353.         controls = {\
  10354.             { \"Left/Right Click\", \"Defines a corner of the selection rectangle\" }\
  10355.         }\
  10356.     },\
  10357.     [8] = {\
  10358.         name = \"Play Mode\",\
  10359.         key = \"space\",\
  10360.         animonly = true,\
  10361.         message = \"Play mode will loop through each frame in your animation at a constant rate. Editing tools are \"..\
  10362.         \"locked in this mode, and the coordinate display will turn green to indicate it is on.\",\
  10363.         controls = {\
  10364.             { \"</> Keys\", \"Increases/Decreases speed of the animation\" },\
  10365.             { \"Space Bar\", \"Returns to paint mode\" }\
  10366.         }\
  10367.     },\
  10368.     [9] = {\
  10369.         name = \"Record Mode\",\
  10370.         key = \"\\\\\",\
  10371.         animonly = true,\
  10372.         message = \"Record mode is not a true mode, but influences how other modes work. Changes made that modify the \"..\
  10373.         \"canvas in record mode will affect ALL frames in the animation. The coordinates will turn red to indicate that \"..\
  10374.         \"record mode is on.\",\
  10375.         controls = {\
  10376.             { \"\", \"Affects:\" },\
  10377.             { \"- Paint Mode\", \"\" },\
  10378.             { \"- Brush Mode\", \"\" },\
  10379.             { \"- Cut and Paste in Select Mode\", \"\"},\
  10380.             { \"- Move Mode\", \"\"}\
  10381.         }\
  10382.     },\
  10383.     [10] = {\
  10384.         name = \"Help Mode\",\
  10385.         key = \"h\",\
  10386.         animonly = false,\
  10387.         message = \"Displays this help screen. Clicking on options will display help on that topic. Clicking out of the screen\"..\
  10388.         \" will leave this mode.\",\
  10389.         controls = {\
  10390.             { \"Left/Right Click\", \"Displays a topic/Leaves the mode\" }\
  10391.         }\
  10392.     },\
  10393.     [11] = {\
  10394.         name = \"File Mode\",\
  10395.         keys = nil,\
  10396.         animonly = false,\
  10397.         message = \"Clicking on the mode display at the bottom of the screen will open the options menu. Here you can\"..\
  10398.         \" activate all of the modes in the program with a simple mouse click. Pressing left control will open up the\"..\
  10399.         \" file menu automatically.\",\
  10400.         controls = { \
  10401.             { \"leftCtrl\", \"Opens the file menu\" },\
  10402.             { \"leftAlt\", \"Opens the paint menu\" }\
  10403.             \
  10404.         }\
  10405.     }\
  10406. }\
  10407. --The \"bounds\" of the image- the first/last point on both axes where a pixel appears\
  10408. local toplim,botlim,leflim,riglim = nil,nil,nil,nil\
  10409. --The selected path\
  10410. local sPath = nil\
  10411. \
  10412. --[[  \
  10413.             Section:  Helpers       \
  10414. ]]--\
  10415. \
  10416. --[[Converts a colour parameter into a single-digit hex coordinate for the colour\
  10417.    Params: colour:int = The colour to be converted\
  10418.     Returns:string A string conversion of the colour\
  10419. ]]--\
  10420. local function getHexOf(colour)\
  10421.     if not colour or not tonumber(colour) then \
  10422.         return \" \" \
  10423.     end\
  10424.     local value = math.log(colour)/math.log(2)\
  10425.     if value > 9 then \
  10426.         value = hexnums[value] \
  10427.     end\
  10428.     return value\
  10429. end\
  10430. \
  10431. --[[Converts a hex digit into a colour value\
  10432.     Params: hex:?string = the hex digit to be converted\
  10433.     Returns:string A colour value corresponding to the hex, or nil if the character is invalid\
  10434. ]]--\
  10435. local function getColourOf(hex)\
  10436.     local value = tonumber(hex, 16)\
  10437.     if not value then return nil end\
  10438.     value = math.pow(2,value)\
  10439.     return value\
  10440. end\
  10441. \
  10442. --[[Finds the biggest and smallest bounds of the image- the outside points beyond which pixels do not appear\
  10443.     These values are assigned to the \"lim\" parameters for access by other methods\
  10444.     Params: forAllFrames:bool = True if all frames should be used to find bounds, otherwise false or nil\
  10445.     Returns:nil\
  10446. ]]--\
  10447. local function updateImageLims(forAllFrames)\
  10448.     local f,l = sFrame,sFrame\
  10449.     if forAllFrames == true then f,l = 1,framecount end\
  10450.     \
  10451.     toplim,botlim,leflim,riglim = nil,nil,nil,nil\
  10452.     for locf = f,l do\
  10453.         for y,_ in pairs(frames[locf]) do\
  10454.             for x,_ in pairs(frames[locf][y]) do\
  10455.                 if frames[locf][y][x] ~= nil then\
  10456.                     if leflim == nil or x < leflim then leflim = x end\
  10457.                     if toplim == nil or y < toplim then toplim = y end\
  10458.                     if riglim == nil or x > riglim then riglim = x end\
  10459.                     if botlim == nil or y > botlim then botlim = y end\
  10460.                 end\
  10461.             end\
  10462.         end\
  10463.     end\
  10464. end\
  10465. \
  10466. --[[Determines how much of each material is required for a print. Done each time printing is called.\
  10467.     Params: none\
  10468.     Returns:table A complete list of how much of each material is required.\
  10469. ]]--\
  10470. function calculateMaterials()\
  10471.     updateImageLims(animated)\
  10472.     requiredMaterials = {}\
  10473.     for i=1,16 do \
  10474.         requiredMaterials[i] = 0 \
  10475.     end\
  10476.     \
  10477.     if not toplim then return end\
  10478.     \
  10479.     for i=1,#frames do\
  10480.         for y = toplim, botlim do\
  10481.             for x = leflim, riglim do\
  10482.                 if type(frames[i][y][x]) == \"number\" then\
  10483.                     requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] = \
  10484.                         requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] + 1\
  10485.                 end \
  10486.             end\
  10487.         end\
  10488.     end\
  10489. end\
  10490. \
  10491. \
  10492. --[[Updates the rectangle blink timer. Should be called anywhere events are captured, along with a timer capture.\
  10493.     Params: nil\
  10494.     Returns:nil\
  10495. ]]--\
  10496. local function updateTimer(id)\
  10497.     if id == recttimer then\
  10498.         recttimer = os.startTimer(0.5)\
  10499.         rectblink = (rectblink % 2) + 1\
  10500.     end\
  10501. end\
  10502. \
  10503. --[[Constructs a message based on the state currently selected\
  10504.     Params: nil\
  10505.     Returns:string A message regarding the state of the application\
  10506. ]]--\
  10507. local function getStateMessage()\
  10508.     local msg = \" \"..string.upper(string.sub(state, 1, 1))..string.sub(state, 2, #state)..\" mode\"\
  10509.     if state == \"brush\" then msg = msg..\", size=\"..brushsize end\
  10510.     return msg\
  10511. end\
  10512. \
  10513. --[[Calls the rednet_message event, but also looks for timer events to keep then\
  10514.     system timer ticking.\
  10515.     Params: timeout:number how long before the event times out\
  10516.     Returns:number the id of the sender\
  10517.            :number the message send\
  10518. ]]--\
  10519. local function rsTimeReceive(timeout)\
  10520.     local timerID\
  10521.     if timeout then timerID = os.startTimer(timeout) end\
  10522.     \
  10523.     local id,key,msg = nil,nil\
  10524.     while true do\
  10525.         id,key,msg = os.pullEvent()\
  10526.         \
  10527.         if id == \"timer\" then\
  10528.             if key == timerID then return\
  10529.             else updateTimer(key) end\
  10530.         end\
  10531.         if id == \"rednet_message\" then \
  10532.             return key,msg\
  10533.         end\
  10534.     end\
  10535. end\
  10536. \
  10537. --[[Draws a picture, in paint table format on the screen\
  10538.     Params: image:table = the image to display\
  10539.             xinit:number = the x position of the top-left corner of the image\
  10540.             yinit:number = the y position of the top-left corner of the image\
  10541.             alpha:number = the color to display for the alpha channel. Default is white.\
  10542.     Returns:nil\
  10543. ]]--\
  10544. local function drawPictureTable(image, xinit, yinit, alpha)\
  10545.     if not alpha then alpha = 1 end\
  10546.     for y=1,#image do\
  10547.         for x=1,#image[y] do\
  10548.             term.setCursorPos(xinit + x-1, yinit + y-1)\
  10549.             local col = getColourOf(string.sub(image[y], x, x))\
  10550.             if not col then col = alpha end\
  10551.             term.setBackgroundColour(col)\
  10552.             term.write(\" \")\
  10553.         end\
  10554.     end\
  10555. end\
  10556. \
  10557. --[[  \
  10558.             Section: Loading  \
  10559. ]]-- \
  10560. \
  10561. --[[Loads a non-animted paint file into the program\
  10562.     Params: path:string = The path in which the file is located\
  10563.     Returns:nil\
  10564. ]]--\
  10565. local function loadNFP(path)\
  10566.     sFrame = 1\
  10567.     frames[sFrame] = { }\
  10568.     if fs.exists(path) then\
  10569.         local file = io.open(path, \"r\" )\
  10570.         local sLine = file:read()\
  10571.         local num = 1\
  10572.         while sLine do\
  10573.             table.insert(frames[sFrame], num, {})\
  10574.             for i=1,#sLine do\
  10575.                 frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))\
  10576.             end\
  10577.             num = num+1\
  10578.             sLine = file:read()\
  10579.         end\
  10580.         file:close()\
  10581.     end\
  10582. end\
  10583. \
  10584. --[[Saves a non-animated paint file to the specified path\
  10585.     Params: path:string = The path to save the file to\
  10586.     Returns:nil\
  10587. ]]--\
  10588. local function saveNFP(path)\
  10589.     local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))\
  10590.     if not fs.exists(sDir) then\
  10591.         fs.makeDir(sDir)\
  10592.     end\
  10593. \
  10594.     local file = io.open(path, \"w\")\
  10595.     updateImageLims(false)\
  10596.     if not toplim then \
  10597.         file:close()\
  10598.         return\
  10599.     end\
  10600.     for y=1,botlim do\
  10601.         local line = \"\"\
  10602.         if frames[sFrame][y] then \
  10603.             for x=1,riglim do\
  10604.                 line = line..getHexOf(frames[sFrame][y][x])\
  10605.             end\
  10606.         end\
  10607.         file:write(line..\"\\n\")\
  10608.     end\
  10609.     file:close()\
  10610. end\
  10611. \
  10612. --[[Loads an animated paint file into the program\
  10613.     Params: path:string = The path in which the file is located\
  10614.     Returns:nil\
  10615. ]]--\
  10616. local function loadNFA(path)\
  10617.     frames[sFrame] = { }\
  10618.     if fs.exists(path) then\
  10619.         local file = io.open(path, \"r\" )\
  10620.         local sLine = file:read()\
  10621.         local num = 1\
  10622.         while sLine do\
  10623.             table.insert(frames[sFrame], num, {})\
  10624.             if sLine == \"~\" then\
  10625.                 sFrame = sFrame + 1\
  10626.                 frames[sFrame] = { }\
  10627.                 num = 1\
  10628.             else\
  10629.                 for i=1,#sLine do\
  10630.                     frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))\
  10631.                 end\
  10632.                 num = num+1\
  10633.             end\
  10634.             sLine = file:read()\
  10635.         end\
  10636.         file:close()\
  10637.     end\
  10638.     framecount = sFrame\
  10639.     sFrame = 1\
  10640. end\
  10641. \
  10642. --[[Saves a animated paint file to the specified path\
  10643.     Params: path:string = The path to save the file to\
  10644.     Returns:nil\
  10645. ]]--\
  10646. local function saveNFA(path)\
  10647.     local file = io.open(path, \"w\")\
  10648.     updateImageLims(true)\
  10649.     if not toplim then \
  10650.         file:close()\
  10651.         return\
  10652.     end\
  10653.     for i=1,#frames do\
  10654.         for y=1,botlim do\
  10655.             local line = \"\"\
  10656.             if frames[i][y] then \
  10657.                 for x=1,riglim do\
  10658.                     line = line..getHexOf(frames[i][y][x])\
  10659.                 end\
  10660.             end\
  10661.             file:write(line..\"\\n\")\
  10662.         end\
  10663.         if i < #frames then file:write(\"~\\n\") end\
  10664.     end\
  10665.     file:close()\
  10666. end\
  10667. \
  10668. --[[Initializes the program, by loading in the paint file. Called at the start of each program.\
  10669.     Params: none\
  10670.     Returns:nil\
  10671. ]]--\
  10672. local function init()\
  10673.     if animated then \
  10674.         loadNFA(sPath)\
  10675.         table.insert(ddModes, #ddModes, { \"record\", \"play\", name = \"anim\" })\
  10676.         table.insert(ddModes, #ddModes, { \"go to\", \"remove\", name = \"frames\"})\
  10677.     else loadNFP(sPath) end\
  10678. \
  10679.     for i=0,15 do\
  10680.         table.insert(column, math.pow(2,i))\
  10681.     end\
  10682. end\
  10683. \
  10684. --[[  \
  10685.             Section: Drawing  \
  10686. ]]--\
  10687. \
  10688. \
  10689. --[[Draws the rather superflous logo. Takes about 1 second, before user is able to move to the\
  10690.     actual program.\
  10691.     Params: none\
  10692.     Returns:nil\
  10693. ]]--\
  10694. local function drawLogo()\
  10695.     term.setBackgroundColour(colours.white)\
  10696.     term.clear()\
  10697.     drawPictureTable(logo, w/2 - #logo[1]/2, h/2 - #logo/2, colours.white)\
  10698.     term.setBackgroundColour(colours.white)\
  10699.     term.setTextColour(colours.black)\
  10700.     local msg = \"NPaintPro\"\
  10701.     term.setCursorPos(w/2 - #msg/2, h-3)\
  10702.     term.write(msg)\
  10703.     msg = \"By NitrogenFingers\"\
  10704.     term.setCursorPos(w/2 - #msg/2, h-2)\
  10705.     term.write(msg)\
  10706.     msg = \"Thanks to faubiguy for testing\"\
  10707.     term.setCursorPos(w/2 - #msg/2, h)\
  10708.     term.write(msg)\
  10709.     \
  10710.     os.pullEvent()\
  10711. end\
  10712. \
  10713. --[[Clears the display to the alpha channel colour, draws the canvas, the image buffer and the selection\
  10714.     rectanlge if any of these things are present.\
  10715.     Params: none\
  10716.     Returns:nil\
  10717. ]]--\
  10718. local function drawCanvas()\
  10719.     --We have to readjust the position of the canvas if we're printing\
  10720.     turtlechar = \"@\"\
  10721.     if state == \"active print\" then\
  10722.         if layering == \"up\" then\
  10723.             if py >= 1 and py <= #frames then\
  10724.                 sFrame = py\
  10725.             end\
  10726.             if pz < sy then sy = pz\
  10727.             elseif pz > sy + h - 1 then sy = pz + h - 1 end\
  10728.             if px < sx then sx = px\
  10729.             elseif px > sx + w - 2 then sx = px + w - 2 end\
  10730.         else\
  10731.             if pz >= 1 and pz <= #frames then\
  10732.                 sFrame = pz\
  10733.             end\
  10734.             \
  10735.             if py < sy then sy = py\
  10736.             elseif py > sy + h - 1 then sy = py + h - 1 end\
  10737.             if px < sx then sx = px\
  10738.             elseif px > sx + w - 2 then sx = px + w - 2 end\
  10739.         end\
  10740.         \
  10741.         if pfx == 1 then turtlechar = \">\"\
  10742.         elseif pfx == -1 then turtlechar = \"<\"\
  10743.         elseif pfz == 1 then turtlechar = \"V\"\
  10744.         elseif pfz == -1 then turtlechar = \"^\"\
  10745.         end\
  10746.     end\
  10747. \
  10748.     --Picture next\
  10749.     local topLayer, botLayer\
  10750.     if layerDisplay then\
  10751.         topLayer = sFrame\
  10752.         botLayer = 1\
  10753.     else\
  10754.         topLayer,botLayer = sFrame,sFrame\
  10755.     end\
  10756.     \
  10757.     for currframe = botLayer,topLayer,1 do\
  10758.         for y=sy+1,sy+h-1 do\
  10759.             if frames[currframe][y] then \
  10760.                 for x=sx+1,sx+w-2 do\
  10761.                     term.setCursorPos(x-sx,y-sy)\
  10762.                     if frames[currframe][y][x] then\
  10763.                         term.setBackgroundColour(frames[currframe][y][x])\
  10764.                         term.write(\" \")\
  10765.                     else \
  10766.                         tileExists = false\
  10767.                         for i=currframe-1,botLayer,-1 do\
  10768.                             if frames[i][y][x] then\
  10769.                                 tileExists = true\
  10770.                                 break\
  10771.                             end\
  10772.                         end\
  10773.                         \
  10774.                         if not tileExists then\
  10775.                             if blueprint then\
  10776.                                 term.setBackgroundColour(colours.blue)\
  10777.                                 term.setTextColour(colours.white)\
  10778.                                 if x == sx+1 and y % 4 == 1 then\
  10779.                                     term.write(\"\"..((y/4) % 10))\
  10780.                                 elseif y == sy + 1 and x % 4 == 1 then\
  10781.                                     term.write(\"\"..((x/4) % 10))\
  10782.                                 elseif x % 2 == 1 and y % 2 == 1 then\
  10783.                                     term.write(\"+\")\
  10784.                                 elseif x % 2 == 1 then\
  10785.                                     term.write(\"|\")\
  10786.                                 elseif y % 2 == 1 then\
  10787.                                     term.write(\"-\")\
  10788.                                 else\
  10789.                                     term.write(\" \")\
  10790.                                 end\
  10791.                             else\
  10792.                                 term.setBackgroundColour(alphaC) \
  10793.                                 term.write(\" \")\
  10794.                             end\
  10795.                         end\
  10796.                     end\
  10797.                 end\
  10798.             else\
  10799.                 for x=sx+1,sx+w-2 do\
  10800.                     term.setCursorPos(x-sx,y-sy)\
  10801.                     \
  10802.                     tileExists = false\
  10803.                     for i=currframe-1,botLayer,-1 do\
  10804.                         if frames[i][y] and frames[i][y][x] then\
  10805.                             tileExists = true\
  10806.                             break\
  10807.                         end\
  10808.                     end\
  10809.                     \
  10810.                     if not tileExists then\
  10811.                         if blueprint then\
  10812.                             term.setBackgroundColour(colours.blue)\
  10813.                             term.setTextColour(colours.white)\
  10814.                             if x == sx+1 and y % 4 == 1 then\
  10815.                                 term.write(\"\"..((y/4) % 10))\
  10816.                             elseif y == sy + 1 and x % 4 == 1 then\
  10817.                                 term.write(\"\"..((x/4) % 10))\
  10818.                             elseif x % 2 == 1 and y % 2 == 1 then\
  10819.                                 term.write(\"+\")\
  10820.                             elseif x % 2 == 1 then\
  10821.                                 term.write(\"|\")\
  10822.                             elseif y % 2 == 1 then\
  10823.                                 term.write(\"-\")\
  10824.                             else\
  10825.                                 term.write(\" \")\
  10826.                             end\
  10827.                         else\
  10828.                             term.setBackgroundColour(alphaC) \
  10829.                             term.write(\" \")\
  10830.                         end\
  10831.                     end\
  10832.                 end\
  10833.             end\
  10834.         end\
  10835.     end\
  10836.     \
  10837.     --Then the printer, if he's on\
  10838.     if state == \"active print\" then\
  10839.         local bgColour = alphaC\
  10840.         if layering == \"up\" then\
  10841.             term.setCursorPos(px-sx,pz-sy)\
  10842.             if frames[sFrame] and frames[sFrame][pz-sy] and frames[sFrame][pz-sy][px-sx] then\
  10843.                 bgColour = frames[sFrame][pz-sy][px-sx]\
  10844.             elseif blueprint then bgColour = colours.blue end\
  10845.         else\
  10846.             term.setCursorPos(px-sx,py-sy)\
  10847.             if frames[sFrame] and frames[sFrame][py-sy] and frames[sFrame][py-sy][px-sx] then\
  10848.                 bgColour = frames[sFrame][py-sy][px-sx]\
  10849.             elseif blueprint then bgColour = colours.blue end\
  10850.         end\
  10851.         \
  10852.         term.setBackgroundColour(bgColour)\
  10853.         if bgColour == colours.black then term.setTextColour(colours.white)\
  10854.         else term.setTextColour(colours.black) end\
  10855.         \
  10856.         term.write(turtlechar)\
  10857.     end\
  10858.     \
  10859.     --Then the buffer\
  10860.     if selectrect then\
  10861.         if buffer and rectblink == 1 then\
  10862.         for y=selectrect.y1, math.min(selectrect.y2, selectrect.y1 + buffer.height-1) do\
  10863.             for x=selectrect.x1, math.min(selectrect.x2, selectrect.x1 + buffer.width-1) do\
  10864.                 if buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1] then\
  10865.                     term.setCursorPos(x+sx,y+sy)\
  10866.                     term.setBackgroundColour(buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1])\
  10867.                     term.write(\" \")\
  10868.                 end\
  10869.             end\
  10870.         end\
  10871.         end\
  10872.     \
  10873.         --This draws the \"selection\" box\
  10874.         local add = nil\
  10875.         if buffer then\
  10876.             term.setBackgroundColour(colours.lightGrey)\
  10877.         else \
  10878.             term.setBackgroundColour(colours.grey)\
  10879.         end\
  10880.         for i=selectrect.x1, selectrect.x2 do\
  10881.             add = (i + selectrect.y1 + rectblink) % 2 == 0\
  10882.             term.setCursorPos(i-sx,selectrect.y1-sy)\
  10883.             if add then term.write(\" \") end\
  10884.             add = (i + selectrect.y2 + rectblink) % 2 == 0\
  10885.             term.setCursorPos(i-sx,selectrect.y2-sy)\
  10886.             if add then term.write(\" \") end\
  10887.         end\
  10888.         for i=selectrect.y1 + 1, selectrect.y2 - 1 do\
  10889.             add = (i + selectrect.x1 + rectblink) % 2 == 0\
  10890.             term.setCursorPos(selectrect.x1-sx,i-sy)\
  10891.             if add then term.write(\" \") end\
  10892.             add = (i + selectrect.x2 + rectblink) % 2 == 0\
  10893.             term.setCursorPos(selectrect.x2-sx,i-sy)\
  10894.             if add then term.write(\" \") end\
  10895.         end\
  10896.     end\
  10897. end\
  10898. \
  10899. --[[Draws the colour picker on the right side of the screen, the colour pallette and the footer with any \
  10900.     messages currently being displayed\
  10901.     Params: none\
  10902.     Returns:nil\
  10903. ]]--\
  10904. local function drawInterface()\
  10905.     --Picker\
  10906.     for i=1,#column do\
  10907.         term.setCursorPos(w-1, i)\
  10908.         term.setBackgroundColour(column[i])\
  10909.         if state == \"print\" then\
  10910.             if i == 16 then\
  10911.                 term.setTextColour(colours.white)\
  10912.             else\
  10913.                 term.setTextColour(colours.black)\
  10914.             end\
  10915.             if requirementsDisplayed then\
  10916.                 if requiredMaterials[i] < 10 then term.write(\" \") end\
  10917.                 term.setCursorPos(w-#tostring(requiredMaterials[i])+1, i)\
  10918.                 term.write(requiredMaterials[i])\
  10919.             else\
  10920.                 if i < 10 then term.write(\" \") end\
  10921.                 term.write(i)\
  10922.             end\
  10923.         else\
  10924.             term.write(\"  \")\
  10925.         end\
  10926.     end\
  10927.     term.setCursorPos(w-1,#column+1)\
  10928.     term.setBackgroundColour(colours.black)\
  10929.     term.setTextColour(colours.red)\
  10930.     term.write(\"XX\")\
  10931.     --Pallette\
  10932.     term.setCursorPos(w-1,h-1)\
  10933.     if not lSel then\
  10934.         term.setBackgroundColour(colours.black)\
  10935.         term.setTextColour(colours.red)\
  10936.         term.write(\"X\")\
  10937.     else\
  10938.         term.setBackgroundColour(lSel)\
  10939.         term.setTextColour(lSel)\
  10940.         term.write(\" \")\
  10941.     end\
  10942.     if not rSel then\
  10943.         term.setBackgroundColour(colours.black)\
  10944.         term.setTextColour(colours.red)\
  10945.         term.write(\"X\")\
  10946.     else\
  10947.         term.setBackgroundColour(rSel)\
  10948.         term.setTextColour(rSel)\
  10949.         term.write(\" \")\
  10950.     end\
  10951.     --Footer\
  10952.     if inMenu then return end\
  10953.     \
  10954.     term.setCursorPos(1, h)\
  10955.     term.setBackgroundColour(colours.lightGrey)\
  10956.     term.setTextColour(colours.grey)\
  10957.     term.clearLine()\
  10958.     if inDropDown then\
  10959.         term.write(string.rep(\" \", 6))\
  10960.     else\
  10961.         term.setBackgroundColour(colours.grey)\
  10962.         term.setTextColour(colours.lightGrey)\
  10963.         term.write(\"menu  \")\
  10964.     end\
  10965.     term.setBackgroundColour(colours.lightGrey)\
  10966.     term.setTextColour(colours.grey)\
  10967.     term.write(getStateMessage())\
  10968.     \
  10969.     local coords=\"X:\"..sx..\" Y:\"..sy\
  10970.     if animated then coords = coords..\" Frame:\"..sFrame..\"/\"..framecount..\"   \" end\
  10971.     term.setCursorPos(w-#coords+1,h)\
  10972.     if state == \"play\" then term.setBackgroundColour(colours.lime)\
  10973.     elseif record then term.setBackgroundColour(colours.red) end\
  10974.     term.write(coords)\
  10975.     \
  10976.     if animated then\
  10977.         term.setCursorPos(w-1,h)\
  10978.         term.setBackgroundColour(colours.grey)\
  10979.         term.setTextColour(colours.lightGrey)\
  10980.         term.write(\"<>\")\
  10981.     end\
  10982. end\
  10983. \
  10984. --[[Runs an interface where users can select topics of help. Will return once the user quits the help screen.\
  10985.     Params: none\
  10986.     Returns:nil\
  10987. ]]--\
  10988. local function drawHelpScreen()\
  10989.     local selectedHelp = nil\
  10990.     while true do\
  10991.         term.setBackgroundColour(colours.lightGrey)\
  10992.         term.clear()\
  10993.         if not selectedHelp then\
  10994.             term.setCursorPos(4, 1)\
  10995.             term.setTextColour(colours.brown)\
  10996.             term.write(\"Available modes (click for info):\")\
  10997.             for i=1,#helpTopics do\
  10998.                 term.setCursorPos(2, 2 + i)\
  10999.                 term.setTextColour(colours.black)\
  11000.                 term.write(helpTopics[i].name)\
  11001.                 if helpTopics[i].key then\
  11002.                     term.setTextColour(colours.red)\
  11003.                     term.write(\" (\"..helpTopics[i].key..\")\")\
  11004.                 end\
  11005.             end\
  11006.             term.setCursorPos(4,h)\
  11007.             term.setTextColour(colours.black)\
  11008.             term.write(\"Press any key to exit\")\
  11009.         else\
  11010.             term.setCursorPos(4,1)\
  11011.             term.setTextColour(colours.brown)\
  11012.             term.write(helpTopics[selectedHelp].name)\
  11013.             if helpTopics[selectedHelp].key then\
  11014.                 term.setTextColour(colours.red)\
  11015.                 term.write(\" (\"..helpTopics[selectedHelp].key..\")\")\
  11016.             end\
  11017.             term.setCursorPos(1,3)\
  11018.             term.setTextColour(colours.black)\
  11019.             print(helpTopics[selectedHelp].message..\"\\n\")\
  11020.             for i=1,#helpTopics[selectedHelp].controls do\
  11021.                 term.setTextColour(colours.brown)\
  11022.                 term.write(helpTopics[selectedHelp].controls[i][1]..\" \")\
  11023.                 term.setTextColour(colours.black)\
  11024.                 print(helpTopics[selectedHelp].controls[i][2])\
  11025.             end\
  11026.         end\
  11027.         \
  11028.         local id,p1,p2,p3 = os.pullEvent()\
  11029.         \
  11030.         if id == \"timer\" then updateTimer(p1)\
  11031.         elseif id == \"key\" then \
  11032.             if selectedHelp then selectedHelp = nil\
  11033.             else break end\
  11034.         elseif id == \"mouse_click\" then\
  11035.             if not selectedHelp then \
  11036.                 if p3 >=3 and p3 <= 2+#helpTopics then\
  11037.                     selectedHelp = p3-2 \
  11038.                 else break end\
  11039.             else\
  11040.                 selectedHelp = nil\
  11041.             end\
  11042.         end\
  11043.     end\
  11044. end\
  11045. \
  11046. --[[Draws a message in the footer bar. A helper for DrawInterface, but can be called for custom messages, if the\
  11047.     inMenu paramter is set to true while this is being done (remember to set it back when done!)\
  11048.     Params: message:string = The message to be drawn\
  11049.     Returns:nil\
  11050. ]]--\
  11051. local function drawMessage(message)\
  11052.     term.setCursorPos(1,h)\
  11053.     term.setBackgroundColour(colours.lightGrey)\
  11054.     term.setTextColour(colours.grey)\
  11055.     term.clearLine()\
  11056.     term.write(message)\
  11057. end\
  11058. \
  11059. --[[\
  11060.             Section: Generic Interfaces\
  11061. ]]--\
  11062. \
  11063. \
  11064. --[[One of my generic text printing methods, printing a message at a specified position with width and offset.\
  11065.     No colour materials included.\
  11066.     Params: msg:string = The message to print off-center\
  11067.             height:number = The starting height of the message\
  11068.             width:number = The limit as to how many characters long each line may be\
  11069.             offset:number = The starting width offset of the message\
  11070.     Returns:number the number of lines used in printing the message\
  11071. ]]--\
  11072. local function wprintOffCenter(msg, height, width, offset)\
  11073.     local inc = 0\
  11074.     local ops = 1\
  11075.     while #msg - ops > width do\
  11076.         local nextspace = 0\
  11077.         while string.find(msg, \" \", ops + nextspace) and\
  11078.                 string.find(msg, \" \", ops + nextspace) - ops < width do\
  11079.             nextspace = string.find(msg, \" \", nextspace + ops) + 1 - ops\
  11080.         end\
  11081.         local ox,oy = term.getCursorPos()\
  11082.         term.setCursorPos(width/2 - (nextspace)/2 + offset, height + inc)\
  11083.         inc = inc + 1\
  11084.         term.write(string.sub(msg, ops, nextspace + ops - 1))\
  11085.         ops = ops + nextspace\
  11086.     end\
  11087.     term.setCursorPos(width/2 - #string.sub(msg, ops)/2 + offset, height + inc)\
  11088.     term.write(string.sub(msg, ops))\
  11089.     \
  11090.     return inc + 1\
  11091. end\
  11092. \
  11093. --[[Draws a message that must be clicked on or a key struck to be cleared. No options, so used for displaying\
  11094.     generic information.\
  11095.     Params: ctitle:string = The title of the confirm dialogue\
  11096.             msg:string = The message displayed in the dialogue\
  11097.     Returns:nil\
  11098. ]]--\
  11099. local function displayConfirmDialogue(ctitle, msg)\
  11100.     local dialogoffset = 8\
  11101.     --We actually print twice- once to get the lines, second time to print proper. Easier this way.\
  11102.     local lines = wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)\
  11103.     \
  11104.     term.setCursorPos(dialogoffset, 3)\
  11105.     term.setBackgroundColour(colours.grey)\
  11106.     term.setTextColour(colours.lightGrey)\
  11107.     term.write(string.rep(\" \", w - dialogoffset * 2))\
  11108.     term.setCursorPos(dialogoffset + (w - dialogoffset * 2)/2 - #ctitle/2, 3)\
  11109.     term.write(ctitle)\
  11110.     term.setTextColour(colours.grey)\
  11111.     term.setBackgroundColour(colours.lightGrey)\
  11112.     term.setCursorPos(dialogoffset, 4)\
  11113.     term.write(string.rep(\" \", w - dialogoffset * 2))\
  11114.     for i=5,5+lines do\
  11115.         term.setCursorPos(dialogoffset, i) \
  11116.         term.write(\" \"..string.rep(\" \", w - (dialogoffset) * 2 - 2)..\" \")\
  11117.     end\
  11118.     wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)\
  11119.     \
  11120.     --In the event of a message, the player hits anything to continue\
  11121.     while true do\
  11122.         local id,key = os.pullEvent()\
  11123.         if id == \"timer\" then updateTimer(key);\
  11124.         elseif id == \"key\" or id == \"mouse_click\" or id == \"mouse_drag\" then break end\
  11125.     end\
  11126. end\
  11127. \
  11128. --[[Produces a nice dropdown menu based on a table of strings. Depending on the position, this will auto-adjust the position\
  11129.     of the menu drawn, and allows nesting of menus and sub menus. Clicking anywhere outside the menu will cancel and return nothing\
  11130.     Params: x:int = the x position the menu should be displayed at\
  11131.             y:int = the y position the menu should be displayed at\
  11132.             options:table = the list of options available to the user, as strings or submenus (tables of strings, with a name parameter)\
  11133.     Returns:string the selected menu option.\
  11134. ]]--\
  11135. local function displayDropDown(x, y, options)\
  11136.     inDropDown = true\
  11137.     --Figures out the dimensions of our thing\
  11138.     local longestX = #options.name\
  11139.     for i=1,#options do\
  11140.         local currVal = options[i]\
  11141.         if type(currVal) == \"table\" then currVal = currVal.name end\
  11142.         \
  11143.         longestX = math.max(longestX, #currVal)\
  11144.     end\
  11145.     local xOffset = math.max(0, longestX - ((w-2) - x) + 1)\
  11146.     local yOffset = math.max(0, #options - ((h-1) - y))\
  11147.     \
  11148.     local clickTimes = 0\
  11149.     local tid = nil\
  11150.     local selection = nil\
  11151.     while clickTimes < 2 do\
  11152.         drawCanvas()\
  11153.         drawInterface()\
  11154.         \
  11155.         term.setCursorPos(x-xOffset,y-yOffset)\
  11156.         term.setBackgroundColour(colours.grey)\
  11157.         term.setTextColour(colours.lightGrey)\
  11158.         term.write(options.name..string.rep(\" \", longestX-#options.name + 2))\
  11159.     \
  11160.         for i=1,#options do\
  11161.             term.setCursorPos(x-xOffset, y-yOffset+i)\
  11162.             if i==selection and clickTimes % 2 == 0 then\
  11163.                 term.setBackgroundColour(colours.grey)\
  11164.                 term.setTextColour(colours.lightGrey)\
  11165.             else\
  11166.                 term.setBackgroundColour(colours.lightGrey)\
  11167.                 term.setTextColour(colours.grey)\
  11168.             end\
  11169.             local currVal = options[i]\
  11170.             if type(currVal) == \"table\" then \
  11171.                 term.write(currVal.name..string.rep(\" \", longestX-#currVal.name + 1))\
  11172.                 term.setBackgroundColour(colours.grey)\
  11173.                 term.setTextColour(colours.lightGrey)\
  11174.                 term.write(\">\")\
  11175.             else\
  11176.                 term.write(currVal..string.rep(\" \", longestX-#currVal + 2))\
  11177.             end\
  11178.         end\
  11179.         \
  11180.         local id, p1, p2, p3 = os.pullEvent()\
  11181.         if id == \"timer\" then\
  11182.             if p1 == tid then \
  11183.                 clickTimes = clickTimes + 1\
  11184.                 if clickTimes > 2 then \
  11185.                     break\
  11186.                 else \
  11187.                     tid = os.startTimer(0.1) \
  11188.                 end\
  11189.             else \
  11190.                 updateTimer(p1) \
  11191.                 drawCanvas()\
  11192.                 drawInterface()\
  11193.             end\
  11194.         elseif id == \"mouse_click\" then\
  11195.             if p2 >=x-xOffset and p2 <= x-xOffset + longestX + 1 and p3 >= y-yOffset+1 and p3 <= y-yOffset+#options then\
  11196.                 selection = p3-(y-yOffset)\
  11197.                 tid = os.startTimer(0.1)\
  11198.             else\
  11199.                 selection = \"\"\
  11200.                 break\
  11201.             end\
  11202.         end\
  11203.     end\
  11204.     \
  11205.     if type(selection) == \"number\" then\
  11206.         selection = options[selection]\
  11207.     end\
  11208.     \
  11209.     if type(selection) == \"string\" then \
  11210.         inDropDown = false\
  11211.         return selection\
  11212.     elseif type(selection) == \"table\" then \
  11213.         return displayDropDown(x, y, selection)\
  11214.     end\
  11215. end\
  11216. \
  11217. --[[A custom io.read() function with a few differences- it limits the number of characters being printed,\
  11218.     waits a 1/100th of a second so any keys still in the event library are removed before input is read and\
  11219.     the timer for the selectionrectangle is continuously updated during the process.\
  11220.     Params: lim:int = the number of characters input is allowed\
  11221.     Returns:string the inputted string, trimmed of leading and tailing whitespace\
  11222. ]]--\
  11223. local function readInput(lim)\
  11224.     term.setCursorBlink(true)\
  11225. \
  11226.     local inputString = \"\"\
  11227.     if not lim or type(lim) ~= \"number\" or lim < 1 then lim = w - ox end\
  11228.     local ox,oy = term.getCursorPos()\
  11229.     --We only get input from the footer, so this is safe. Change if recycling\
  11230.     term.setBackgroundColour(colours.lightGrey)\
  11231.     term.setTextColour(colours.grey)\
  11232.     term.write(string.rep(\" \", lim))\
  11233.     term.setCursorPos(ox, oy)\
  11234.     --As events queue immediately, we may get an unwanted key... this will solve that problem\
  11235.     local inputTimer = os.startTimer(0.01)\
  11236.     local keysAllowed = false\
  11237.     \
  11238.     while true do\
  11239.         local id,key = os.pullEvent()\
  11240.         \
  11241.         if keysAllowed then\
  11242.             if id == \"key\" and key == 14 and #inputString > 0 then\
  11243.                 inputString = string.sub(inputString, 1, #inputString-1)\
  11244.                 term.setCursorPos(ox + #inputString,oy)\
  11245.                 term.write(\" \")\
  11246.             elseif id == \"key\" and key == 28 and inputString ~= string.rep(\" \", #inputString) then \
  11247.                 break\
  11248.             elseif id == \"key\" and key == keys.leftCtrl then\
  11249.                 return \"\"\
  11250.             elseif id == \"char\" and #inputString < lim then\
  11251.                 inputString = inputString..key\
  11252.             end\
  11253.         end\
  11254.         \
  11255.         if id == \"timer\" then\
  11256.             if key == inputTimer then \
  11257.                 keysAllowed = true\
  11258.             else\
  11259.                 updateTimer(key)\
  11260.                 drawCanvas()\
  11261.                 drawInterface()\
  11262.                 term.setBackgroundColour(colours.lightGrey)\
  11263.                 term.setTextColour(colours.grey)\
  11264.             end\
  11265.         end\
  11266.         term.setCursorPos(ox,oy)\
  11267.         term.write(inputString)\
  11268.         term.setCursorPos(ox + #inputString, oy)\
  11269.     end\
  11270.     \
  11271.     while string.sub(inputString, 1, 1) == \" \" do\
  11272.         inputString = string.sub(inputString, 2, #inputString)\
  11273.     end\
  11274.     while string.sub(inputString, #inputString, #inputString) == \" \" do\
  11275.         inputString = string.sub(inputString, 1, #inputString-1)\
  11276.     end\
  11277.     term.setCursorBlink(false)\
  11278.     \
  11279.     return inputString\
  11280. end\
  11281. \
  11282. --[[  \
  11283.             Section: Image tools \
  11284. ]]--\
  11285. \
  11286. \
  11287. --[[Copies all pixels beneath the selection rectangle into the image buffer. Empty buffers are converted to nil.\
  11288.     Params: removeImage:bool = true if the image is to be erased after copying, false otherwise\
  11289.     Returns:nil\
  11290. ]]--\
  11291. local function copyToBuffer(removeImage)\
  11292.     buffer = { width = selectrect.x2 - selectrect.x1 + 1, height = selectrect.y2 - selectrect.y1 + 1, contents = { } }\
  11293.     \
  11294.     local containsSomething = false\
  11295.     for y=1,buffer.height do\
  11296.         buffer.contents[y] = { }\
  11297.         local f,l = sFrame,sFrame\
  11298.         if record then f,l = 1, framecount end\
  11299.         \
  11300.         for fra = f,l do\
  11301.             if frames[fra][selectrect.y1 + y - 1] then\
  11302.                 for x=1,buffer.width do\
  11303.                     buffer.contents[y][x] = frames[sFrame][selectrect.y1 + y - 1][selectrect.x1 + x - 1]\
  11304.                     if removeImage then frames[fra][selectrect.y1 + y - 1][selectrect.x1 + x - 1] = nil end\
  11305.                     if buffer.contents[y][x] then containsSomething = true end\
  11306.                 end\
  11307.             end\
  11308.         end\
  11309.     end\
  11310.     --I don't classify an empty buffer as a real buffer- confusing to the user.\
  11311.     if not containsSomething then buffer = nil end\
  11312. end\
  11313. \
  11314. --[[Replaces all pixels under the selection rectangle with the image buffer (or what can be seen of it). Record-dependent.\
  11315.     Params: removeBuffer:bool = true if the buffer is to be emptied after copying, false otherwise\
  11316.     Returns:nil\
  11317. ]]--\
  11318. local function copyFromBuffer(removeBuffer)\
  11319.     if not buffer then return end\
  11320. \
  11321.     for y = 1, math.min(buffer.height,selectrect.y2-selectrect.y1+1) do\
  11322.         local f,l = sFrame, sFrame\
  11323.         if record then f,l = 1, framecount end\
  11324.         \
  11325.         for fra = f,l do\
  11326.             if not frames[fra][selectrect.y1+y-1] then frames[fra][selectrect.y1+y-1] = { } end\
  11327.             for x = 1, math.min(buffer.width,selectrect.x2-selectrect.x1+1) do\
  11328.                 frames[fra][selectrect.y1+y-1][selectrect.x1+x-1] = buffer.contents[y][x]\
  11329.             end\
  11330.         end\
  11331.     end\
  11332.     \
  11333.     if removeBuffer then buffer = nil end\
  11334. end\
  11335. \
  11336. --[[Moves the entire image (or entire animation) to the specified coordinates. Record-dependent.\
  11337.     Params: newx:int = the X coordinate to move the image to\
  11338.             newy:int = the Y coordinate to move the image to\
  11339.     Returns:nil\
  11340. ]]--\
  11341. local function moveImage(newx,newy)\
  11342.     if not leflim or not toplim then return end\
  11343.     if newx <=0 or newy <=0 then return end\
  11344.     local f,l = sFrame,sFrame\
  11345.     if record then f,l = 1,framecount end\
  11346.     \
  11347.     for i=f,l do\
  11348.         local newlines = { }\
  11349.         for y,line in pairs(frames[i]) do\
  11350.             newlines[y-toplim+newy] = { }\
  11351.             for x,char in pairs(line) do\
  11352.                 newlines[y-toplim+newy][x-leflim+newx] = char\
  11353.             end\
  11354.         end\
  11355.         frames[i] = newlines\
  11356.     end\
  11357. end\
  11358. \
  11359. --[[Prompts the user to clear the current frame or all frames. Record-dependent.,\
  11360.     Params: none\
  11361.     Returns:nil\
  11362. ]]--\
  11363. local function clearImage()\
  11364.     inMenu = true\
  11365.     if not animated then\
  11366.         drawMessage(\"Clear image? Y/N: \")\
  11367.     elseif record then\
  11368.         drawMessage(\"Clear ALL frames? Y/N: \")\
  11369.     else\
  11370.         drawMessage(\"Clear current frame? Y/N :\")\
  11371.     end\
  11372.     if string.find(string.upper(readInput(1)), \"Y\") then\
  11373.         local f,l = sFrame,sFrame\
  11374.         if record then f,l = 1,framecount end\
  11375.         \
  11376.         for i=f,l do\
  11377.             frames[i] = { }\
  11378.         end\
  11379.     end\
  11380.     inMenu = false\
  11381. end\
  11382. \
  11383. --[[A recursively called method (watch out for big calls!) in which every pixel of a set colour is\
  11384.     changed to another colour. Does not work on the nil colour, for obvious reasons.\
  11385.     Params: x:int = The X coordinate of the colour to flood-fill\
  11386.             y:int = The Y coordinate of the colour to flood-fill\
  11387.             targetColour:colour = the colour that is being flood-filled\
  11388.             newColour:colour = the colour with which to replace the target colour\
  11389.     Returns:nil\
  11390. ]]--\
  11391. local function floodFill(x, y, targetColour, newColour)\
  11392.     if not newColour or not targetColour then return end\
  11393.     local nodeList = { }\
  11394.     \
  11395.     table.insert(nodeList, {x = x, y = y})\
  11396.     \
  11397.     while #nodeList > 0 do\
  11398.         local node = nodeList[1]\
  11399.         if frames[sFrame][node.y] and frames[sFrame][node.y][node.x] == targetColour then\
  11400.             frames[sFrame][node.y][node.x] = newColour\
  11401.             table.insert(nodeList, { x = node.x + 1, y = node.y})\
  11402.             table.insert(nodeList, { x = node.x, y = node.y + 1})\
  11403.             if x > 1 then table.insert(nodeList, { x = node.x - 1, y = node.y}) end\
  11404.             if y > 1 then table.insert(nodeList, { x = node.x, y = node.y - 1}) end\
  11405.         end\
  11406.         table.remove(nodeList, 1)\
  11407.     end\
  11408. end\
  11409. \
  11410. --[[  \
  11411.             Section: Animation Tools  \
  11412. ]]--\
  11413. \
  11414. --[[Enters play mode, allowing the animation to play through. Interface is restricted to allow this,\
  11415.     and method only leaves once the player leaves play mode.\
  11416.     Params: none\
  11417.     Returns:nil\
  11418. ]]--\
  11419. local function playAnimation()\
  11420.     state = \"play\"\
  11421.     selectedrect = nil\
  11422.     \
  11423.     local animt = os.startTimer(animtime)\
  11424.     repeat\
  11425.         drawCanvas()\
  11426.         drawInterface()\
  11427.         \
  11428.         local id,key,_,y = os.pullEvent()\
  11429.         \
  11430.         if id==\"timer\" then\
  11431.             if key == animt then\
  11432.                 animt = os.startTimer(animtime)\
  11433.                 sFrame = (sFrame % framecount) + 1\
  11434.             else\
  11435.                 updateTimer(key)\
  11436.             end\
  11437.         elseif id==\"key\" then\
  11438.             if key == keys.comma and animtime > 0.1 then animtime = animtime - 0.05\
  11439.             elseif key == keys.period and animtime < 0.5 then animtime = animtime + 0.05\
  11440.             elseif key == keys.space then state = \"paint\" end\
  11441.         elseif id==\"mouse_click\" and y == h then\
  11442.             state = \"paint\"\
  11443.         end\
  11444.     until state ~= \"play\"\
  11445.     os.startTimer(0.5)\
  11446. end\
  11447. \
  11448. --[[Changes the selected frame (sFrame) to the chosen frame. If this frame is above the framecount,\
  11449.     additional frames are created with a copy of the image on the selected frame.\
  11450.     Params: newframe:int = the new frame to move to\
  11451.     Returns:nil\
  11452. ]]--\
  11453. local function changeFrame(newframe)\
  11454.     inMenu = true\
  11455.     if not tonumber(newframe) then\
  11456.         term.setCursorPos(1,h)\
  11457.         term.setBackgroundColour(colours.lightGrey)\
  11458.         term.setTextColour(colours.grey)\
  11459.         term.clearLine()\
  11460.     \
  11461.         term.write(\"Go to frame: \")\
  11462.         newframe = tonumber(readInput(2))\
  11463.         if not newframe or newframe <= 0 then\
  11464.             inMenu = false\
  11465.             return \
  11466.         end\
  11467.     elseif newframe <= 0 then return end\
  11468.     \
  11469.     if newframe > framecount then\
  11470.         for i=framecount+1,newframe do\
  11471.             frames[i] = {}\
  11472.             for y,line in pairs(frames[sFrame]) do\
  11473.                 frames[i][y] = { }\
  11474.                 for x,v in pairs(line) do\
  11475.                     frames[i][y][x] = v\
  11476.                 end\
  11477.             end\
  11478.         end\
  11479.         framecount = newframe\
  11480.     end\
  11481.     sFrame = newframe\
  11482.     inMenu = false\
  11483. end\
  11484. \
  11485. --[[Removes every frame leading after the frame passed in\
  11486.     Params: frame:int the non-inclusive lower bounds of the delete\
  11487.     Returns:nil\
  11488. ]]--\
  11489. local function removeFramesAfter(frame)\
  11490.     inMenu = true\
  11491.     if frame==framecount then return end\
  11492.     drawMessage(\"Remove frames \"..(frame+1)..\"/\"..framecount..\"? Y/N :\")\
  11493.     local answer = string.upper(readInput(1))\
  11494.     \
  11495.     if string.find(answer, string.upper(\"Y\")) ~= 1 then \
  11496.         inMenu = false\
  11497.         return \
  11498.     end\
  11499.     \
  11500.     for i=frame+1, framecount do\
  11501.         frames[i] = nil\
  11502.     end\
  11503.     framecount = frame\
  11504.     inMenu = false\
  11505. end\
  11506. \
  11507. --[[\
  11508.             Section: Printing Tools\
  11509. ]]--\
  11510. \
  11511. --[[Constructs a new facing to the left of the current facing\
  11512.     Params: curx:number = The facing on the X axis\
  11513.             curz:number = The facing on the Z axis\
  11514.             hand:string = The hand of the axis (\"right\" or \"left\")\
  11515.     Returns:number,number = the new facing on the X and Z axis after a left turn\
  11516. ]]--\
  11517. local function getLeft(curx, curz)\
  11518.     local hand = \"left\"\
  11519.     if layering == \"up\" then hand = \"right\" end\
  11520.     \
  11521.     if hand == \"right\" then\
  11522.         if curx == 1 then return 0,-1 end\
  11523.         if curx == -1 then return 0,1 end\
  11524.         if curz == 1 then return 1,0 end\
  11525.         if curz == -1 then return -1,0 end\
  11526.     else\
  11527.         if curx == 1 then return 0,1 end\
  11528.         if curx == -1 then return 0,-1 end\
  11529.         if curz == 1 then return -1,0 end\
  11530.         if curz == -1 then return 1,0 end\
  11531.     end\
  11532. end\
  11533. \
  11534. --[[Constructs a new facing to the right of the current facing\
  11535.     Params: curx:number = The facing on the X axis\
  11536.             curz:number = The facing on the Z axis\
  11537.             hand:string = The hand of the axis (\"right\" or \"left\")\
  11538.     Returns:number,number = the new facing on the X and Z axis after a right turn\
  11539. ]]--\
  11540. local function getRight(curx, curz)\
  11541.     local hand = \"left\"\
  11542.     if layering == \"up\" then hand = \"right\" end\
  11543.     \
  11544.     if hand == \"right\" then\
  11545.         if curx == 1 then return 0,1 end\
  11546.         if curx == -1 then return 0,-1 end\
  11547.         if curz == 1 then return -1,0 end\
  11548.         if curz == -1 then return 1,0 end\
  11549.     else\
  11550.         if curx == 1 then return 0,-1 end\
  11551.         if curx == -1 then return 0,1 end\
  11552.         if curz == 1 then return 1,0 end\
  11553.         if curz == -1 then return -1,0 end\
  11554.     end\
  11555. end\
  11556. \
  11557. \
  11558. --[[Sends out a rednet signal requesting local printers, and will listen for any responses. Printers found are added to the\
  11559.     printerList (for ID's) and printerNames (for names)\
  11560.     Params: nil\
  11561.     Returns:nil\
  11562. ]]--\
  11563. local function locatePrinters()\
  11564.     printerList = { }\
  11565.     printerNames = { name = \"Printers\" }\
  11566.     local oldState = state\
  11567.     state = \"Locating printers, please wait...   \"\
  11568.     drawCanvas()\
  11569.     drawInterface()\
  11570.     state = oldState\
  11571.     \
  11572.     local modemOpened = false\
  11573.     for k,v in pairs(rs.getSides()) do\
  11574.         if peripheral.isPresent(v) and peripheral.getType(v) == \"modem\" then\
  11575.             rednet.open(v)\
  11576.             modemOpened = true\
  11577.             break\
  11578.         end\
  11579.     end\
  11580.     \
  11581.     if not modemOpened then\
  11582.         displayConfirmDialogue(\"Modem not found!\", \"No modem peripheral. Must have network modem to locate printers.\")\
  11583.         return false\
  11584.     end\
  11585.     \
  11586.     rednet.broadcast(\"$3DPRINT IDENTIFY\")\
  11587.     \
  11588.     while true do\
  11589.         local id, msg = rsTimeReceive(1)\
  11590.         \
  11591.         if not id then break end\
  11592.         if string.find(msg, \"$3DPRINT IDACK\") == 1 then\
  11593.             msg = string.gsub(msg, \"$3DPRINT IDACK \", \"\")\
  11594.             table.insert(printerList, id)\
  11595.             table.insert(printerNames, msg)\
  11596.         end\
  11597.     end\
  11598.     \
  11599.     if #printerList == 0 then\
  11600.         displayConfirmDialogue(\"Printers not found!\", \"No active printers found in proximity of this computer.\")\
  11601.         return false\
  11602.     else\
  11603.         return true\
  11604.     end\
  11605. end\
  11606. \
  11607. --[[Sends a request to the printer. Waits on a response and updates the state of the application accordingly.\
  11608.     Params: command:string the command to send\
  11609.             param:string a parameter to send, if any\
  11610.     Returns:nil\
  11611. ]]--\
  11612. local function sendPC(command,param)\
  11613.     local msg = \"$PC \"..command\
  11614.     if param then msg = msg..\" \"..param end\
  11615.     rednet.send(printerList[selectedPrinter], msg)\
  11616.     \
  11617.     while true do\
  11618.         local id,key = rsTimeReceive()\
  11619.         if id == printerList[selectedPrinter] then\
  11620.             if key == \"$3DPRINT ACK\" then\
  11621.                 break\
  11622.             elseif key == \"$3DPRINT DEP\" then\
  11623.                 displayConfirmDialogue(\"Printer Empty\", \"The printer has exhasted a material. Please refill slot \"..param..\
  11624.                     \", and click this message when ready to continue.\")\
  11625.                 rednet.send(printerList[selectedPrinter], msg)\
  11626.             end\
  11627.         end\
  11628.     end\
  11629.     \
  11630.     --Changes to position are handled after the event has been successfully completed\
  11631.     if command == \"FW\" then\
  11632.         px = px + pfx\
  11633.         pz = pz + pfz\
  11634.     elseif command == \"BK\" then\
  11635.         px = px - pfx\
  11636.         pz = pz - pfz\
  11637.     elseif command == \"UP\" then\
  11638.         if layering == \"up\" then\
  11639.             py = py + 1\
  11640.         else \
  11641.             py = py - 1\
  11642.         end\
  11643.     elseif command == \"DW\" then\
  11644.         if layering == \"up\" then\
  11645.             py = py - 1\
  11646.         else    \
  11647.             py = py + 1\
  11648.         end\
  11649.     elseif command == \"TL\" then\
  11650.         pfx,pfz = getLeft(pfx,pfz)\
  11651.     elseif command == \"TR\" then\
  11652.         pfx,pfz = getRight(pfx,pfz)\
  11653.     elseif command == \"TU\" then\
  11654.         pfx = -pfx\
  11655.         pfz = -pfz\
  11656.     end\
  11657.     \
  11658.     drawCanvas()\
  11659.     drawInterface()\
  11660. end\
  11661. \
  11662. --[[A printing function that commands the printer to turn to face the desired direction, if it is not already doing so\
  11663.     Params: desx:number = the normalized x direction to face\
  11664.             desz:number = the normalized z direction to face\
  11665.     Returns:nil\
  11666. ]]--\
  11667. local function turnToFace(desx,desz)\
  11668.     if desx ~= 0 then\
  11669.         if pfx ~= desx then\
  11670.             local temppfx,_ = getLeft(pfx,pfz)\
  11671.             if temppfx == desx then\
  11672.                 sendPC(\"TL\")\
  11673.             elseif temppfx == -desx then\
  11674.                 sendPC(\"TR\")\
  11675.             else\
  11676.                 sendPC(\"TU\")\
  11677.             end\
  11678.         end\
  11679.     else\
  11680.         print(\"on the z axis\")\
  11681.         if pfz ~= desz then\
  11682.             local _,temppfz = getLeft(pfx,pfz)\
  11683.             if temppfz == desz then\
  11684.                 sendPC(\"TL\")\
  11685.             elseif temppfz == -desz then\
  11686.                 sendPC(\"TR\")\
  11687.             else\
  11688.                 sendPC(\"TU\")\
  11689.             end\
  11690.         end\
  11691.     end\
  11692. end\
  11693. \
  11694. --[[Performs the print\
  11695.     Params: nil\
  11696.     Returns:nil\
  11697. ]]--\
  11698. local function performPrint()\
  11699.     state = \"active print\"\
  11700.     if layering == \"up\" then\
  11701.         --An up layering starts our builder bot on the bottom left corner of our build\
  11702.         px,py,pz = leflim, 0, botlim + 1\
  11703.         pfx,pfz = 0,-1\
  11704.         \
  11705.         --We move him forward and up a bit from his original position.\
  11706.         sendPC(\"FW\")\
  11707.         sendPC(\"UP\")\
  11708.         --For each layer that needs to be completed, we go up by one each time\
  11709.         for layers=1,#frames do\
  11710.             --We first decide if we're going forwards or back, depending on what side we're on\
  11711.             local rowbot,rowtop,rowinc = nil,nil,nil\
  11712.             if pz == botlim then\
  11713.                 rowbot,rowtop,rowinc = botlim,toplim,-1\
  11714.             else\
  11715.                 rowbot,rowtop,rowinc = toplim,botlim,1\
  11716.             end\
  11717.             \
  11718.             for rows = rowbot,rowtop,rowinc do\
  11719.                 --Then we decide if we're going left or right, depending on what side we're on\
  11720.                 local linebot,linetop,lineinc = nil,nil,nil\
  11721.                 if px == leflim then\
  11722.                     --Facing from the left side has to be easterly- it's changed here\
  11723.                     turnToFace(1,0)\
  11724.                     linebot,linetop,lineinc = leflim,riglim,1\
  11725.                 else\
  11726.                     --Facing from the right side has to be westerly- it's changed here\
  11727.                     turnToFace(-1,0)\
  11728.                     linebot,linetop,lineinc = riglim,leflim,-1\
  11729.                 end\
  11730.                 \
  11731.                 for lines = linebot,linetop,lineinc do\
  11732.                     --We move our turtle forward, placing the right material at each step\
  11733.                     local material = frames[py][pz][px]\
  11734.                     if material then\
  11735.                         material = math.log10(frames[py][pz][px])/math.log10(2) + 1\
  11736.                         sendPC(\"SS\", material)\
  11737.                         sendPC(\"PD\")\
  11738.                     end\
  11739.                     if lines ~= linetop then\
  11740.                         sendPC(\"FW\")\
  11741.                     end\
  11742.                 end\
  11743.                 \
  11744.                 --The printer then has to do a U-turn, depending on which way he's facing and\
  11745.                 --which way he needs to go\
  11746.                 local temppfx,temppfz = getLeft(pfx,pfz)\
  11747.                 if temppfz == rowinc and rows ~= rowtop then\
  11748.                     sendPC(\"TL\")\
  11749.                     sendPC(\"FW\")\
  11750.                     sendPC(\"TL\")\
  11751.                 elseif temppfz == -rowinc and rows ~= rowtop then\
  11752.                     sendPC(\"TR\")\
  11753.                     sendPC(\"FW\")\
  11754.                     sendPC(\"TR\")\
  11755.                 end\
  11756.             end\
  11757.             --Now at the end of a run he does a 180 and moves up to begin the next part of the print\
  11758.             sendPC(\"TU\")\
  11759.             if layers ~= #frames then\
  11760.                 sendPC(\"UP\")\
  11761.             end\
  11762.         end\
  11763.         --All done- now we head back to where we started.\
  11764.         if px ~= leflim then\
  11765.             turnToFace(-1,0)\
  11766.             while px ~= leflim do\
  11767.                 sendPC(\"FW\")\
  11768.             end\
  11769.         end\
  11770.         if pz ~= botlim then\
  11771.             turnToFace(0,-1)\
  11772.             while pz ~= botlim do\
  11773.                 sendPC(\"BK\")\
  11774.             end\
  11775.         end\
  11776.         turnToFace(0,-1)\
  11777.         sendPC(\"BK\")\
  11778.         while py > 0 do\
  11779.             sendPC(\"DW\")\
  11780.         end\
  11781.     else\
  11782.         --The front facing is at the top-left corner, facing south not north\
  11783.         px,py,pz = leflim, botlim, 1\
  11784.         pfx,pfz = 0,1\
  11785.         --We move the printer to the last layer- he prints from the back forwards\
  11786.         while pz < #frames do\
  11787.             sendPC(\"FW\")\
  11788.         end\
  11789.         \
  11790.         --For each layer in the frame we build our wall, the move back\
  11791.         for layers = 1,#frames do\
  11792.             --We first decide if we're going left or right based on our position\
  11793.             local rowbot,rowtop,rowinc = nil,nil,nil\
  11794.             if px == leflim then\
  11795.                 rowbot,rowtop,rowinc = leflim,riglim,1\
  11796.             else\
  11797.                 rowbot,rowtop,rowinc = riglim,leflim,-1\
  11798.             end\
  11799.             \
  11800.             for rows = rowbot,rowtop,rowinc do\
  11801.                 --Then we decide if we're going up or down, depending on our given altitude\
  11802.                 local linebot,linetop,lineinc = nil,nil,nil\
  11803.                 if py == botlim then\
  11804.                     linebot,linetop,lineinc = botlim,toplim,-1\
  11805.                 else\
  11806.                     linebot,linetop,lineinc = toplim,botlim,1\
  11807.                 end\
  11808.                 \
  11809.                 for lines = linebot,linetop,lineinc do\
  11810.                 --We move our turtle up/down, placing the right material at each step\
  11811.                     local material = frames[pz][py][px]\
  11812.                     if material then\
  11813.                         material = math.log10(frames[pz][py][px])/math.log10(2) + 1\
  11814.                         sendPC(\"SS\", material)\
  11815.                         sendPC(\"PF\")\
  11816.                     end\
  11817.                     if lines ~= linetop then\
  11818.                         if lineinc == 1 then sendPC(\"DW\")\
  11819.                         else sendPC(\"UP\") end\
  11820.                     end\
  11821.                 end\
  11822.                     \
  11823.                 if rows ~= rowtop then\
  11824.                     turnToFace(rowinc,0)\
  11825.                     sendPC(\"FW\")\
  11826.                     turnToFace(0,1)\
  11827.                 end\
  11828.             end\
  11829.             \
  11830.             if layers ~= #frames then\
  11831.                 sendPC(\"TU\")\
  11832.                 sendPC(\"FW\")\
  11833.                 sendPC(\"TU\")\
  11834.             end\
  11835.         end\
  11836.         --He's easy to reset\
  11837.         while px ~= leflim do\
  11838.             turnToFace(-1,0)\
  11839.             sendPC(\"FW\")\
  11840.         end\
  11841.         turnToFace(0,1)\
  11842.     end\
  11843.     \
  11844.     sendPC(\"DE\")\
  11845.     \
  11846.     displayConfirmDialogue(\"Print complete\", \"The 3D print was successful.\")\
  11847. end\
  11848. \
  11849. --[[  \
  11850.             Section: Interface  \
  11851. ]]--\
  11852. \
  11853. --[[Runs the printing interface. Allows users to find/select a printer, the style of printing to perform and to begin the operation\
  11854.     Params: none\
  11855.     Returns:boolean true if printing was started, false otherwse\
  11856. ]]--\
  11857. local function runPrintInterface()\
  11858.     if not locatePrinters() then\
  11859.         return false\
  11860.     end\
  11861.     \
  11862.     calculateMaterials()\
  11863.     layering = \"up\"\
  11864.     requirementsDisplayed = false\
  11865.     selectedPrinter = 1\
  11866.     while true do\
  11867.         drawCanvas()\
  11868.         term.setBackgroundColour(colours.lightGrey)\
  11869.         for i=1,10 do\
  11870.             term.setCursorPos(1,i)\
  11871.             term.clearLine()\
  11872.         end\
  11873.         drawInterface()\
  11874.         term.setBackgroundColour(colours.lightGrey)\
  11875.         term.setTextColour(colours.black)\
  11876.         \
  11877.         local msg = \"3D Printing\"\
  11878.         term.setCursorPos(w/2-#msg/2 - 2, 1)\
  11879.         term.write(msg)\
  11880.         term.setBackgroundColour(colours.grey)\
  11881.         term.setTextColour(colours.lightGrey)\
  11882.         if(requirementsDisplayed) then\
  11883.             msg = \"Count:\"\
  11884.         else\
  11885.             msg = \" Slot:\"\
  11886.         end\
  11887.         term.setCursorPos(w-3-#msg, 1)\
  11888.         term.write(msg)\
  11889.         term.setBackgroundColour(colours.lightGrey)\
  11890.         term.setTextColour(colours.black)\
  11891.         \
  11892.         term.setCursorPos(7, 2)\
  11893.         term.write(\"Layering\")\
  11894.         drawPictureTable(layerUpIcon, 3, 3, colours.white)\
  11895.         drawPictureTable(layerForwardIcon, 12, 3, colours.white)\
  11896.         if layering == \"up\" then\
  11897.             term.setBackgroundColour(colours.red)\
  11898.         else\
  11899.             term.setBackgroundColour(colours.lightGrey)\
  11900.         end\
  11901.         term.setCursorPos(3, 9)\
  11902.         term.write(\"Upwards\")\
  11903.         if layering == \"forward\" then\
  11904.             term.setBackgroundColour(colours.red)\
  11905.         else\
  11906.             term.setBackgroundColour(colours.lightGrey)\
  11907.         end\
  11908.         term.setCursorPos(12, 9)\
  11909.         term.write(\"Forward\")\
  11910.         \
  11911.         term.setBackgroundColour(colours.lightGrey)\
  11912.         term.setTextColour(colours.black)\
  11913.         term.setCursorPos(31, 2)\
  11914.         term.write(\"Printer ID\")\
  11915.         term.setCursorPos(33, 3)\
  11916.         if #printerList > 1 then\
  11917.             term.setBackgroundColour(colours.grey)\
  11918.             term.setTextColour(colours.lightGrey)\
  11919.         else\
  11920.             term.setTextColour(colours.red)\
  11921.         end\
  11922.         term.write(\" \"..printerNames[selectedPrinter]..\" \")\
  11923.         \
  11924.         term.setBackgroundColour(colours.grey)\
  11925.         term.setTextColour(colours.lightGrey)\
  11926.         term.setCursorPos(25, 10)\
  11927.         term.write(\" Cancel \")\
  11928.         term.setCursorPos(40, 10)\
  11929.         term.write(\" Print \")\
  11930.         \
  11931.         local id, p1, p2, p3 = os.pullEvent()\
  11932.         \
  11933.         if id == \"timer\" then\
  11934.             updateTimer(p1)\
  11935.         elseif id == \"mouse_click\" then\
  11936.             --Layering Buttons\
  11937.             if p2 >= 3 and p2 <= 9 and p3 >= 3 and p3 <= 9 then\
  11938.                 layering = \"up\"\
  11939.             elseif p2 >= 12 and p2 <= 18 and p3 >= 3 and p3 <= 9 then\
  11940.                 layering = \"forward\"\
  11941.             --Count/Slot\
  11942.             elseif p2 >= w - #msg - 3 and p2 <= w - 3 and p3 == 1 then\
  11943.                 requirementsDisplayed = not requirementsDisplayed\
  11944.             --Printer ID\
  11945.             elseif p2 >= 33 and p2 <= 33 + #printerNames[selectedPrinter] and p3 == 3 and #printerList > 1 then\
  11946.                 local chosenName = displayDropDown(33, 3, printerNames)\
  11947.                 for i=1,#printerNames do\
  11948.                     if printerNames[i] == chosenName then\
  11949.                         selectedPrinter = i\
  11950.                         break;\
  11951.                     end\
  11952.                 end\
  11953.             --Print and Cancel\
  11954.             elseif p2 >= 25 and p2 <= 32 and p3 == 10 then\
  11955.                 break\
  11956.             elseif p2 >= 40 and p2 <= 46 and p3 == 10 then\
  11957.                 rednet.send(printerList[selectedPrinter], \"$3DPRINT ACTIVATE\")\
  11958.                 ready = false\
  11959.                 while true do\
  11960.                     local id,msg = rsTimeReceive(10)\
  11961.                     \
  11962.                     if id == printerList[selectedPrinter] and msg == \"$3DPRINT ACTACK\" then\
  11963.                         ready = true\
  11964.                         break\
  11965.                     end\
  11966.                 end\
  11967.                 if ready then\
  11968.                     performPrint()\
  11969.                     break\
  11970.                 else\
  11971.                     displayConfirmDialogue(\"Printer Didn't Respond\", \"The printer didn't respond to the activation command. Check to see if it's online\")\
  11972.                 end\
  11973.             end\
  11974.         end\
  11975.     end\
  11976.     state = \"paint\"\
  11977. end\
  11978. \
  11979. --[[This function changes the current paint program to another tool or mode, depending on user input. Handles\
  11980.     any necessary changes in logic involved in that.\
  11981.     Params: mode:string = the name of the mode to change to\
  11982.     Returns:nil\
  11983. ]]--\
  11984. local function performSelection(mode)\
  11985.     if not mode or mode == \"\" then return\
  11986.     \
  11987.     elseif mode == \"help\" then\
  11988.         drawHelpScreen()\
  11989.         \
  11990.     elseif mode == \"blueprint on\" then\
  11991.         blueprint = true\
  11992.         ddModes[2][3] = \"blueprint off\"\
  11993.         \
  11994.     elseif mode == \"blueprint off\" then\
  11995.         blueprint = false\
  11996.         ddModes[2][3] = \"blueprint on\"\
  11997.         \
  11998.     elseif mode == \"layers on\" then\
  11999.         layerDisplay = true\
  12000.         ddModes[2][4] = \"layers off\"\
  12001.     \
  12002.     elseif mode == \"layers off\" then\
  12003.         layerDisplay = false\
  12004.         ddModes[2][4] = \"layers on\"\
  12005.     \
  12006.     elseif mode == \"direction on\" then\
  12007.         printDirection = true\
  12008.         ddModes[2][5] = \"direction off\"\
  12009.         \
  12010.     elseif mode == \"direction off\" then\
  12011.         printDirection = false\
  12012.         ddModes[2][5] = \"direction on\"\
  12013.     \
  12014.     elseif mode == \"go to\" then\
  12015.         changeFrame()\
  12016.     \
  12017.     elseif mode == \"remove\" then\
  12018.         removeFramesAfter(sFrame)\
  12019.     \
  12020.     elseif mode == \"play\" then\
  12021.         playAnimation()\
  12022.         \
  12023.     elseif mode == \"copy\" then\
  12024.         if selectrect and selectrect.x1 ~= selectrect.x2 then\
  12025.             copyToBuffer(false)\
  12026.         end\
  12027.     \
  12028.     elseif mode == \"cut\" then\
  12029.         if selectrect and selectrect.x1 ~= selectrect.x2 then \
  12030.             copyToBuffer(true)\
  12031.         end\
  12032.         \
  12033.     elseif mode == \"paste\" then\
  12034.         if selectrect and selectrect.x1 ~= selectrect.x2 then \
  12035.             copyFromBuffer(false)\
  12036.         end\
  12037.         \
  12038.     elseif mode == \"hide\" then\
  12039.         selectrect = nil\
  12040.         if state == \"select\" then state = \"corner select\" end\
  12041.         \
  12042.     elseif mode == \"alpha to left\" then\
  12043.         if lSel then alphaC = lSel end\
  12044.         \
  12045.     elseif mode == \"alpha to right\" then\
  12046.         if rSel then alphaC = rSel end\
  12047.         \
  12048.     elseif mode == \"record\" then\
  12049.         record = not record\
  12050.         \
  12051.     elseif mode == \"clear\" then\
  12052.         if state==\"select\" then buffer = nil\
  12053.         else clearImage() end\
  12054.     \
  12055.     elseif mode == \"select\" then\
  12056.         if state==\"corner select\" or state==\"select\" then\
  12057.             state = \"paint\"\
  12058.         elseif selectrect and selectrect.x1 ~= selectrect.x2 then\
  12059.             state = \"select\"\
  12060.         else\
  12061.             state = \"corner select\" \
  12062.         end\
  12063.         \
  12064.     elseif mode == \"print\" then\
  12065.         state = \"print\"\
  12066.         runPrintInterface()\
  12067.         state = \"paint\"\
  12068.         \
  12069.     elseif mode == \"save\" then\
  12070.         if animated then saveNFA(sPath)\
  12071.         else saveNFP(sPath) end\
  12072.         \
  12073.     elseif mode == \"exit\" then\
  12074.         isRunning = false\
  12075.     \
  12076.     elseif mode ~= state then state = mode\
  12077.     else state = \"paint\"\
  12078.     end\
  12079. end\
  12080. \
  12081. --[[The main function of the program, reads and handles all events and updates them accordingly. Mode changes,\
  12082.     painting to the canvas and general selections are done here.\
  12083.     Params: none\
  12084.     Returns:nil\
  12085. ]]--\
  12086. local function handleEvents()\
  12087.     recttimer = os.startTimer(0.5)\
  12088.     while isRunning do\
  12089.         drawCanvas()\
  12090.         drawInterface()\
  12091.         local id,p1,p2,p3 = os.pullEvent()\
  12092.         if id==\"timer\" then\
  12093.             updateTimer(p1)\
  12094.         elseif id==\"mouse_click\" or id==\"mouse_drag\" then\
  12095.             if p2 >=w-1 and p3 < #column+1 then\
  12096.                 if p1==1 then lSel = column[p3]\
  12097.                 else rSel = column[p3] end\
  12098.             elseif p2 >=w-1 and p3==#column+1 then\
  12099.                 if p1==1 then lSel = nil\
  12100.                 else rSel = nil end\
  12101.             elseif p2==w-1 and p3==h and animated then\
  12102.                 changeFrame(sFrame-1)\
  12103.             elseif p2==w and p3==h and animated then\
  12104.                 changeFrame(sFrame+1)\
  12105.             elseif p2 < w-10 and p3==h then\
  12106.                 local sel = displayDropDown(1, h-1, ddModes)\
  12107.                 performSelection(sel)\
  12108.             elseif p2 < w-1 and p3 <= h-1 then\
  12109.                 if state==\"pippette\" then\
  12110.                     if p1==1 then\
  12111.                         if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then\
  12112.                             lSel = frames[sFrame][p3+sy][p2+sx] \
  12113.                         end\
  12114.                     elseif p1==2 then\
  12115.                         if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then\
  12116.                             rSel = frames[sFrame][p3+sy][p2+sx] \
  12117.                         end\
  12118.                     end\
  12119.                 elseif state==\"move\" then\
  12120.                     updateImageLims(record)\
  12121.                     moveImage(p2,p3)\
  12122.                 elseif state==\"flood\" then\
  12123.                     if p1 == 1 and lSel and frames[sFrame][p3+sy]  then \
  12124.                         floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],lSel)\
  12125.                     elseif p1 == 2 and rSel and frames[sFrame][p3+sy] then \
  12126.                         floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],rSel)\
  12127.                     end\
  12128.                 elseif state==\"corner select\" then\
  12129.                     if not selectrect then\
  12130.                         selectrect = { x1=p2+sx, x2=p2+sx, y1=p3+sy, y2=p3+sy }\
  12131.                     elseif selectrect.x1 ~= p2+sx and selectrect.y1 ~= p3+sy then\
  12132.                         if p2+sx<selectrect.x1 then selectrect.x1 = p2+sx\
  12133.                         else selectrect.x2 = p2+sx end\
  12134.                         \
  12135.                         if p3+sy<selectrect.y1 then selectrect.y1 = p3+sy\
  12136.                         else selectrect.y2 = p3+sy end\
  12137.                         \
  12138.                         state = \"select\"\
  12139.                     end\
  12140.                 elseif state==\"select\" then\
  12141.                     if p1 == 1 then\
  12142.                         local swidth = selectrect.x2 - selectrect.x1\
  12143.                         local sheight = selectrect.y2 - selectrect.y1\
  12144.                     \
  12145.                         selectrect.x1 = p2 + sx\
  12146.                         selectrect.y1 = p3 + sy\
  12147.                         selectrect.x2 = p2 + swidth + sx\
  12148.                         selectrect.y2 = p3 + sheight + sy\
  12149.                     elseif p1 == 2 and p2 < w-2 and p3 < h-1 then\
  12150.                         inMenu = true\
  12151.                         local sel = displayDropDown(p2, p3, srModes) \
  12152.                         inMenu = false\
  12153.                         performSelection(sel)\
  12154.                     end\
  12155.                 else\
  12156.                     local f,l = sFrame,sFrame\
  12157.                     if record then f,l = 1,framecount end\
  12158.                     local bwidth = 0\
  12159.                     if state == \"brush\" then bwidth = brushsize-1 end\
  12160.                 \
  12161.                     for i=f,l do\
  12162.                         for x = math.max(1,p2+sx-bwidth),p2+sx+bwidth do\
  12163.                             for y = math.max(1,p3+sy-bwidth), p3+sy+bwidth do\
  12164.                                 if math.abs(x - (p2+sx)) + math.abs(y - (p3+sy)) <= bwidth then\
  12165.                                     if not frames[i][y] then frames[i][y] = {} end\
  12166.                                     if p1==1 then frames[i][y][x] = lSel\
  12167.                                     else frames[i][y][x] = rSel end\
  12168.                                 end\
  12169.                             end\
  12170.                         end\
  12171.                     end\
  12172.                 end\
  12173.             end\
  12174.         elseif id==\"key\" then\
  12175.             if p1==keys.leftCtrl then\
  12176.                 local sel = displayDropDown(1, h-1, ddModes[#ddModes]) \
  12177.                 performSelection(sel)\
  12178.             elseif p1==keys.leftAlt then\
  12179.                 local sel = displayDropDown(1, h-1, ddModes[1]) \
  12180.                 performSelection(sel)\
  12181.             elseif p1==keys.h then \
  12182.                 performSelection(\"help\")\
  12183.             elseif p1==keys.x then \
  12184.                 performSelection(\"cut\")\
  12185.             elseif p1==keys.c then\
  12186.                 performSelection(\"copy\")\
  12187.             elseif p1==keys.v then\
  12188.                 performSelection(\"paste\")\
  12189.             elseif p1==keys.z then\
  12190.                 performSelection(\"clear\")\
  12191.             elseif p1==keys.s then\
  12192.                 performSelection(\"select\")\
  12193.             elseif p1==keys.tab then\
  12194.                 performSelection(\"hide\")\
  12195.             elseif p1==keys.q then\
  12196.                 performSelection(\"alpha to left\")\
  12197.             elseif p1==keys.w then\
  12198.                 performSelection(\"alpha to right\")\
  12199.             elseif p1==keys.f then\
  12200.                 performSelection(\"flood\")\
  12201.             elseif p1==keys.b then\
  12202.                 performSelection(\"brush\")\
  12203.             elseif p1==keys.m then\
  12204.                 performSelection(\"move\")\
  12205.             elseif p1==keys.backslash and animated then\
  12206.                 performSelection(\"record\")\
  12207.             elseif p1==keys.p then\
  12208.                 performSelection(\"pippette\")\
  12209.             elseif p1==keys.g and animated then\
  12210.                 performSelection(\"go to\")\
  12211.             elseif p1==keys.period and animated then\
  12212.                 changeFrame(sFrame+1)\
  12213.             elseif p1==keys.comma and animated then\
  12214.                 changeFrame(sFrame-1)\
  12215.             elseif p1==keys.r and animated then\
  12216.                 performSelection(\"remove\")\
  12217.             elseif p1==keys.space and animated then\
  12218.                 performSelection(\"play\")\
  12219.             elseif p1==keys.left then\
  12220.                 if state == \"move\" then\
  12221.                     updateImageLims(record)\
  12222.                     moveImage(leflim-1,toplim)\
  12223.                 elseif state==\"select\" and selectrect.x1 > 1 then\
  12224.                     selectrect.x1 = selectrect.x1-1\
  12225.                     selectrect.x2 = selectrect.x2-1\
  12226.                 elseif sx > 0 then sx=sx-1 end\
  12227.             elseif p1==keys.right then\
  12228.                 if state == \"move\" then\
  12229.                     updateImageLims(record)\
  12230.                     moveImage(leflim+1,toplim)\
  12231.                 elseif state==\"select\" then\
  12232.                     selectrect.x1 = selectrect.x1+1\
  12233.                     selectrect.x2 = selectrect.x2+1\
  12234.                 else sx=sx+1 end\
  12235.             elseif p1==keys.up then\
  12236.                 if state == \"move\" then\
  12237.                     updateImageLims(record)\
  12238.                     moveImage(leflim,toplim-1)\
  12239.                 elseif state==\"select\" and selectrect.y1 > 1 then\
  12240.                     selectrect.y1 = selectrect.y1-1\
  12241.                     selectrect.y2 = selectrect.y2-1\
  12242.                 elseif sy > 0 then sy=sy-1 end\
  12243.             elseif p1==keys.down then \
  12244.                 if state == \"move\" then\
  12245.                     updateImageLims(record)\
  12246.                     moveImage(leflim,toplim+1)\
  12247.                 elseif state==\"select\" then\
  12248.                     selectrect.y1 = selectrect.y1+1\
  12249.                     selectrect.y2 = selectrect.y2+1\
  12250.                 else sy=sy+1 end\
  12251.             end\
  12252.         elseif id==\"char\" and tonumber(p1) then\
  12253.             if state==\"brush\" and tonumber(p1) > 1 then\
  12254.                 brushsize = tonumber(p1)\
  12255.             elseif tonumber(p1) > 0 then\
  12256.                 changeFrame(tonumber(p1))\
  12257.             end\
  12258.         end\
  12259.     end\
  12260. end\
  12261. \
  12262. --[[  \
  12263.             Section: Main  \
  12264. ]]--\
  12265. \
  12266. --Taken almost directly from edit (for consistency)\
  12267. local tArgs = {...}\
  12268. \
  12269. local ca = 1\
  12270. \
  12271. if tArgs[ca] == \"-a\" then\
  12272.     animated = true\
  12273.     ca = ca + 1\
  12274. end\
  12275. \
  12276. if #tArgs < ca then\
  12277.     print(\"Usage: npaintpro [-a] <path>\")\
  12278.     return\
  12279. end\
  12280. \
  12281. sPath = shell.resolve(tArgs[ca])\
  12282. local bReadOnly = fs.isReadOnly(sPath)\
  12283. if fs.exists(sPath) then\
  12284.     if fs.isDir(sPath) then\
  12285.         print(\"Cannot edit a directory.\")\
  12286.         return\
  12287.     elseif string.find(sPath, \".nfp\") ~= #sPath-3 and string.find(sPath, \".nfa\") ~= #sPath-3 then\
  12288.         print(\"Can only edit .nfp and nfa files:\",string.find(sPath, \".nfp\"),#sPath-3)\
  12289.         return\
  12290.     end\
  12291.     \
  12292.     if string.find(sPath, \".nfa\") == #sPath-3 then\
  12293.         animated = true\
  12294.     end\
  12295.     \
  12296.     if string.find(sPath, \".nfp\") == #sPath-3 and animated then\
  12297.         print(\"Convert to nfa? Y/N\")\
  12298.         if string.find(string.lower(io.read()), \"y\") then\
  12299.             local nsPath = string.sub(sPath, 1, #sPath-1)..\"a\"\
  12300.             fs.move(sPath, nsPath)\
  12301.             sPath = nsPath\
  12302.         else\
  12303.             animated = false\
  12304.         end\
  12305.     end\
  12306. else\
  12307.     if not animated and string.find(sPath, \".nfp\") ~= #sPath-3 then \
  12308.         sPath = sPath..\".nfp\"\
  12309.     elseif animated and string.find(sPath, \".nfa\") ~= #sPath-3 then \
  12310.         sPath = sPath..\".nfa\"\
  12311.     end\
  12312. end \
  12313. \
  12314. if not term.isColour() then\
  12315.     print(\"For colour computers only\")\
  12316.     return\
  12317. end\
  12318. \
  12319. drawLogo()\
  12320. init()\
  12321. handleEvents()\
  12322. \
  12323. term.setBackgroundColour(colours.black)\
  12324. shell.run(\"clear\")",
  12325.       [ "nPaintPro.ico" ] = "error('This is an image, not a program!')\
  12326. {\
  12327.  {\
  12328.    {\
  12329.      2048,\
  12330.      \"N\",\
  12331.      1,\
  12332.    },\
  12333.    {\
  12334.      2048,\
  12335.      \"p\",\
  12336.      1,\
  12337.    },\
  12338.    {\
  12339.      2048,\
  12340.      \"p\",\
  12341.      1,\
  12342.    },\
  12343.  },\
  12344.  {\
  12345.    {\
  12346.      2048,\
  12347.      \" \",\
  12348.      1,\
  12349.    },\
  12350.    {\
  12351.      2048,\
  12352.      \" \",\
  12353.      2048,\
  12354.    },\
  12355.    {\
  12356.      2048,\
  12357.      \" \",\
  12358.      2048,\
  12359.    },\
  12360.  },\
  12361.  {\
  12362.    {\
  12363.      2048,\
  12364.      \" \",\
  12365.      2048,\
  12366.    },\
  12367.    {\
  12368.      2048,\
  12369.      \" \",\
  12370.      2048,\
  12371.    },\
  12372.    {\
  12373.      2048,\
  12374.      \" \",\
  12375.      2048,\
  12376.    },\
  12377.  },\
  12378.  [ 0 ] = {\
  12379.    {\
  12380.      2048,\
  12381.      \" \",\
  12382.      2048,\
  12383.    },\
  12384.    {\
  12385.      2048,\
  12386.      \" \",\
  12387.      2048,\
  12388.    },\
  12389.    {\
  12390.      2048,\
  12391.      \" \",\
  12392.      2048,\
  12393.    },\
  12394.  },\
  12395. }",
  12396.       [ "permission.data" ] = "",
  12397.     },
  12398.     Shell = {
  12399.       disk = {},
  12400.       [ "permission.data" ] = "userTest",
  12401.       [ "Shell.ico" ] = "error('This is an image, not a program!')\
  12402. {\
  12403.  {\
  12404.    {\
  12405.      32768,\
  12406.      \"_\",\
  12407.      1,\
  12408.    },\
  12409.    {\
  12410.      32768,\
  12411.      \" \",\
  12412.      128,\
  12413.    },\
  12414.    {\
  12415.      32768,\
  12416.      \" \",\
  12417.      128,\
  12418.    },\
  12419.  },\
  12420.  {\
  12421.    {\
  12422.      32768,\
  12423.      \" \",\
  12424.      16,\
  12425.    },\
  12426.    {\
  12427.      32768,\
  12428.      \" \",\
  12429.      128,\
  12430.    },\
  12431.    {\
  12432.      32768,\
  12433.      \" \",\
  12434.      128,\
  12435.    },\
  12436.  },\
  12437.  {\
  12438.    {\
  12439.      32768,\
  12440.      \" \",\
  12441.      16,\
  12442.    },\
  12443.    {\
  12444.      32768,\
  12445.      \" \",\
  12446.      128,\
  12447.    },\
  12448.    {\
  12449.      32768,\
  12450.      \" \",\
  12451.      128,\
  12452.    },\
  12453.  },\
  12454.  [ 0 ] = {\
  12455.    {\
  12456.      32768,\
  12457.      \">\",\
  12458.      16,\
  12459.    },\
  12460.    {\
  12461.      32768,\
  12462.      \" \",\
  12463.      128,\
  12464.    },\
  12465.    {\
  12466.      32768,\
  12467.      \" \",\
  12468.      128,\
  12469.    },\
  12470.  },\
  12471. }",
  12472.       [ "Main.lua" ] = "--[[\
  12473.    Modified version of Shell\
  12474. ]]--\
  12475. \
  12476. local multishell = multishell\
  12477. local parentShell = shell\
  12478. local parentTerm = term.current()\
  12479. \
  12480. if multishell then\
  12481.    multishell.setTitle( multishell.getCurrent(), \"shell\" )\
  12482. end\
  12483. \
  12484. local bExit = false\
  12485. local sDir = (parentShell and parentShell.dir()) or \"\"\
  12486. local sPath = (parentShell and parentShell.path()) or \".:/rom/programs\"\
  12487. local tAliases = (parentShell and parentShell.aliases()) or {}\
  12488. local tProgramStack = {}\
  12489. \
  12490. local shell = {}\
  12491. local tEnv = {\
  12492.     [ \"shell\" ] = shell,\
  12493.     [ \"multishell\" ] = multishell,\
  12494. }\
  12495. \
  12496. -- Colours\
  12497. local promptColour, textColour, bgColour\
  12498. if term.isColour() then\
  12499.     promptColour = colours.yellow\
  12500.     textColour = colours.white\
  12501.     bgColour = colours.black\
  12502. else\
  12503.     promptColour = colours.white\
  12504.     textColour = colours.white\
  12505.     bgColour = colours.black\
  12506. end\
  12507. \
  12508. term.setBackgroundColor(bgColour)\
  12509. term.clear()\
  12510. \
  12511. local function run( _sCommand, ... )\
  12512.     local sPath = shell.resolveProgram( _sCommand )\
  12513.     if sPath ~= nil then\
  12514.         tProgramStack[#tProgramStack + 1] = sPath\
  12515.         if multishell then\
  12516.             multishell.setTitle( multishell.getCurrent(), fs.getName( sPath ) )\
  12517.         end\
  12518.         local result = os.run( tEnv, sPath, ... )\
  12519.         tProgramStack[#tProgramStack] = nil\
  12520.         if multishell then\
  12521.             if #tProgramStack > 0 then\
  12522.                 multishell.setTitle( multishell.getCurrent(), fs.getName( tProgramStack[#tProgramStack] ) )\
  12523.             else\
  12524.                 multishell.setTitle( multishell.getCurrent(), \"shell\" )\
  12525.             end\
  12526.         end\
  12527.         return result\
  12528.     else\
  12529.         printError( \"No such program\" )\
  12530.         return false\
  12531.    end\
  12532. end\
  12533. \
  12534. local function tokenise( ... )\
  12535.    local sLine = table.concat( { ... }, \" \" )\
  12536.     local tWords = {}\
  12537.    local bQuoted = false\
  12538.    for match in string.gmatch( sLine .. \"\\\"\", \"(.-)\\\"\" ) do\
  12539.        if bQuoted then\
  12540.            table.insert( tWords, match )\
  12541.        else\
  12542.            for m in string.gmatch( match, \"[^ \\t]+\" ) do\
  12543.                table.insert( tWords, m )\
  12544.            end\
  12545.        end\
  12546.        bQuoted = not bQuoted\
  12547.    end\
  12548.    return tWords\
  12549. end\
  12550. \
  12551. -- Install shell API\
  12552. function shell.run( ... )\
  12553.     local tWords = tokenise( ... )\
  12554.     local sCommand = tWords[1]\
  12555.     if sCommand then\
  12556.         return run( sCommand, unpack( tWords, 2 ) )\
  12557.     end\
  12558.     return false\
  12559. end\
  12560. \
  12561. function shell.exit()\
  12562.    bExit = true\
  12563. end\
  12564. \
  12565. function shell.dir()\
  12566.     return sDir\
  12567. end\
  12568. \
  12569. function shell.setDir( _sDir )\
  12570.     sDir = _sDir\
  12571. end\
  12572. \
  12573. function shell.path()\
  12574.     return sPath\
  12575. end\
  12576. \
  12577. function shell.setPath( _sPath )\
  12578.     sPath = _sPath\
  12579. end\
  12580. \
  12581. function shell.resolve( _sPath )\
  12582.     local sStartChar = string.sub( _sPath, 1, 1 )\
  12583.     if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
  12584.         return fs.combine( \"\", _sPath )\
  12585.     else\
  12586.         return fs.combine( sDir, _sPath )\
  12587.     end\
  12588. end\
  12589. \
  12590. function shell.resolveProgram( _sCommand )\
  12591.     -- Substitute aliases firsts\
  12592.     if tAliases[ _sCommand ] ~= nil then\
  12593.         _sCommand = tAliases[ _sCommand ]\
  12594.     end\
  12595. \
  12596.    -- If the path is a global path, use it directly\
  12597.    local sStartChar = string.sub( _sCommand, 1, 1 )\
  12598.    if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
  12599.         local sPath = fs.combine( \"\", _sCommand )\
  12600.         if fs.exists( sPath ) and not fs.isDir( sPath ) then\
  12601.             return sPath\
  12602.         end\
  12603.         return nil\
  12604.    end\
  12605.    \
  12606.     -- Otherwise, look on the path variable\
  12607.    for sPath in string.gmatch(sPath, \"[^:]+\") do\
  12608.         sPath = fs.combine( shell.resolve( sPath ), _sCommand )\
  12609.         if fs.exists( sPath ) and not fs.isDir( sPath ) then\
  12610.             return sPath\
  12611.         end\
  12612.    end\
  12613.     \
  12614.     -- Not found\
  12615.     return nil\
  12616. end\
  12617. \
  12618. function shell.programs( _bIncludeHidden )\
  12619.     local tItems = {}\
  12620.     \
  12621.     -- Add programs from the path\
  12622.    for sPath in string.gmatch(sPath, \"[^:]+\") do\
  12623.         sPath = shell.resolve( sPath )\
  12624.         if fs.isDir( sPath ) then\
  12625.             local tList = fs.list( sPath )\
  12626.             for n,sFile in pairs( tList ) do\
  12627.                 if not fs.isDir( fs.combine( sPath, sFile ) ) and\
  12628.                    (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= \".\") then\
  12629.                     tItems[ sFile ] = true\
  12630.                 end\
  12631.             end\
  12632.         end\
  12633.     end \
  12634. \
  12635.     -- Sort and return\
  12636.     local tItemList = {}\
  12637.     for sItem, b in pairs( tItems ) do\
  12638.         table.insert( tItemList, sItem )\
  12639.     end\
  12640.     table.sort( tItemList )\
  12641.     return tItemList\
  12642. end\
  12643. \
  12644. if multishell then\
  12645.    function shell.openTab( ... )\
  12646.        local tWords = tokenise( ... )\
  12647.        local sCommand = tWords[1]\
  12648.        if sCommand then\
  12649.             local sPath = shell.resolveProgram( sCommand )\
  12650.             if sPath == \"rom/programs/shell\" then\
  12651.                return multishell.launch( tEnv, sPath, unpack( tWords, 2 ) )\
  12652.            elseif sPath ~= nil then\
  12653.                return multishell.launch( tEnv, \"rom/programs/shell\", sPath, unpack( tWords, 2 ) )\
  12654.            else\
  12655.                printError( \"No such program\" )\
  12656.            end\
  12657.        end\
  12658.    end\
  12659. \
  12660.    function shell.switchTab( nID )\
  12661.        multishell.setFocus( nID )\
  12662.    end\
  12663. end\
  12664. \
  12665. local tArgs = { ... }\
  12666. if #tArgs > 0 then\
  12667.    -- \"shell x y z\"\
  12668.    -- Run the program specified on the commandline\
  12669.    shell.run( ... )\
  12670. \
  12671. else\
  12672.    -- \"shell\"\
  12673.    -- Print the header\
  12674.    term.setBackgroundColor( bgColour )\
  12675.    term.setTextColour( promptColour )\
  12676.    print( os.version() )\
  12677.    term.setTextColour( textColour )\
  12678. \
  12679.    -- Read commands and execute them\
  12680.    local tCommandHistory = {}\
  12681.    while not bExit do\
  12682.        term.redirect( parentTerm )\
  12683.        term.setBackgroundColor( bgColour )\
  12684.        term.setTextColour( promptColour )\
  12685.        write( shell.dir() .. \"> \" )\
  12686.        term.setTextColour( textColour )\
  12687. \
  12688.        local sLine = read( nil, tCommandHistory )\
  12689.        table.insert( tCommandHistory, sLine )\
  12690.        shell.run( sLine )\
  12691.    end\
  12692. end",
  12693.     },
  12694.     Event = {
  12695.       [ "Main.lua" ] = "while true do\
  12696.  print(table.concat({coroutine.yield()},\" \"))\
  12697.  print(os.time())\
  12698.  print(os.clock())\
  12699. end",
  12700.     },
  12701.     Settings = {
  12702.       disk = {},
  12703.       [ "permission.data" ] = "admin",
  12704.       [ "Settings.ico" ] = "error('This is an image, not a program!')\
  12705. {\
  12706.  {\
  12707.    {\
  12708.      2,\
  12709.      \"-\",\
  12710.      1,\
  12711.    },\
  12712.    {\
  12713.      2,\
  12714.      \"-\",\
  12715.      1,\
  12716.    },\
  12717.    {\
  12718.      2,\
  12719.      \"O\",\
  12720.      1,\
  12721.    },\
  12722.  },\
  12723.  {\
  12724.    {\
  12725.      2,\
  12726.      \"-\",\
  12727.      1,\
  12728.    },\
  12729.    {\
  12730.      2,\
  12731.      \"-\",\
  12732.      1,\
  12733.    },\
  12734.    {\
  12735.      2,\
  12736.      \"-\",\
  12737.      1,\
  12738.    },\
  12739.  },\
  12740.  {\
  12741.    {\
  12742.      2,\
  12743.      \"-\",\
  12744.      1,\
  12745.    },\
  12746.    {\
  12747.      2,\
  12748.      \"O\",\
  12749.      1,\
  12750.    },\
  12751.    {\
  12752.      2,\
  12753.      \"-\",\
  12754.      1,\
  12755.    },\
  12756.  },\
  12757.  [ 0 ] = {\
  12758.    {\
  12759.      2,\
  12760.      \"O\",\
  12761.      1,\
  12762.    },\
  12763.    {\
  12764.      2,\
  12765.      \"-\",\
  12766.      1,\
  12767.    },\
  12768.    {\
  12769.      2,\
  12770.      \"-\",\
  12771.      1,\
  12772.    },\
  12773.  },\
  12774. }",
  12775.       [ "Main.lua" ] = "--[[\
  12776.     Settings app\
  12777.     by Creator\
  12778.     for OmniOS\
  12779. ]]--\
  12780. \
  12781. --variables--\
  12782. local w,h = term.getSize()\
  12783. local MainLayoutTable = {}\
  12784. local path = \"OmniOS/Programs/Settings.app/Data/\"\
  12785. \
  12786. --functions--\
  12787. local loadLayout = function(sPath,...)\
  12788.     local func = loadfile(sPath,...)\
  12789.     return func()\
  12790. end\
  12791. \
  12792. local function changeColor(color)\
  12793.     local f = fs.open(\"OmniOS/Programs/Desktop.app/Data/Settings\",\"r\")\
  12794.     local Settings = textutils.unserialize(f.readAll())\
  12795.     print(f.readAll())\
  12796.     f.close()\
  12797.     Settings.bgColor = colors[color] or colors.green\
  12798.     local f = fs.open(\"OmniOS/Programs/Desktop.app/Data/Settings\",\"w\")\
  12799.     f.write(textutils.serialize(Settings))\
  12800.     f.close()\
  12801. end\
  12802. \
  12803. local function split(str,sep)\
  12804.     local buffer = {}\
  12805.     for token in str:gmatch(sep) do\
  12806.         buffer[#buffer+1] = token\
  12807.     end\
  12808.     return buffer\
  12809. end\
  12810. \
  12811. local function drawPrograms()\
  12812.     local tRawPrograms = fs.list(\"OmniOS/Programs\")\
  12813.     local tPrograms = {}\
  12814.     for i,v in pairs(tRawPrograms) do\
  12815.         tPrograms[#tPrograms+1] = string.match(v,\"[^.]+\")\
  12816.     end\
  12817.     local SelectLayout = gui.Layout.new({xPos = 1,\
  12818.         yPos = h-#tPrograms,\
  12819.         xLength = 15,\
  12820.         yLength = #tPrograms})\
  12821.     SelectLayoutTable = gui.loadObjects(loadLayout(path..\"Layouts/Select.layout\",tPrograms))\
  12822.     gui.loadLayout(SelectLayoutTable,SelectLayout)\
  12823.     SelectLayout:addBackgroundColor({color = colors.white})\
  12824.     SelectLayout:draw()\
  12825.     SelectLayoutEvent = gui.eventHandler(SelectLayout)\
  12826. end\
  12827. \
  12828. --Code--\
  12829. os.loadAPI(\"OmniOS/API/Interact\")\
  12830. local gui = Interact.Initialize()\
  12831. \
  12832. --Layouts--\
  12833. local MainLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})\
  12834. local DesktopLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})\
  12835. local SecurityLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})\
  12836. local ShortcutsLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})\
  12837. \
  12838. --MainLayout--\
  12839. local MainLayoutTable = gui.loadObjects(loadLayout(path..\"Layouts/Main.layout\"))\
  12840. gui.loadLayout(MainLayoutTable,MainLayout)\
  12841. MainLayout:addBackgroundColor({color = colors.white})\
  12842. \
  12843. --Desktop Layout--\
  12844. local DesktopLayoutTable = gui.loadObjects(loadLayout(path..\"Layouts/Desktop.layout\"))\
  12845. gui.loadLayout(DesktopLayoutTable,DesktopLayout)\
  12846. DesktopLayout:addBackgroundColor({color = colors.white})\
  12847. \
  12848. --SecurityLayout--\
  12849. local SecurityLayoutTable = gui.loadObjects(loadLayout(path..\"Layouts/Security.layout\"))\
  12850. gui.loadLayout(SecurityLayoutTable,SecurityLayout)\
  12851. SecurityLayout:addBackgroundColor({color = colors.white})\
  12852. \
  12853. --Desktop Shortcuts Layout\
  12854. local ShortcutsLayoutTable = gui.loadObjects(loadLayout(path..\"Layouts/Shortcuts.layout\"))\
  12855. gui.loadLayout(ShortcutsLayoutTable,ShortcutsLayout)\
  12856. ShortcutsLayout:addBackgroundColor({color = colors.white})\
  12857. \
  12858. --Select Layout\
  12859. local SelectLayoutTable = {}\
  12860. \
  12861. \
  12862. while true do\
  12863.     MainLayout:draw()\
  12864.     local MainLayoutEvent = gui.eventHandler(MainLayout)\
  12865.     if MainLayoutEvent[1] == \"Button\" then\
  12866.         if MainLayoutEvent[2] == \"Desktop\" then\
  12867.             local notClose = true\
  12868.             while notClose do\
  12869.                 DesktopLayout:draw()\
  12870.                 DesktopLayoutEvent = gui.eventHandler(DesktopLayout)\
  12871.                 if DesktopLayoutEvent[1] == \"Button\" then\
  12872.                     if DesktopLayoutEvent[2] == \"Done\" then\
  12873.                         notClose = false\
  12874.                     elseif DesktopLayoutEvent[2] == \"Shortcuts\" then\
  12875.                         while true do\
  12876.                             ShortcutsLayout:draw()\
  12877.                             ShortcutsLayoutEvent = gui.eventHandler(ShortcutsLayout)\
  12878.                             if ShortcutsLayoutEvent[1] == \"Button\" then\
  12879.                                 if ShortcutsLayoutEvent[2] == \"Add\" then\
  12880.                                     drawPrograms()\
  12881.                                 elseif ShortcutsLayoutEvent[2] == \"Done\" then\
  12882.                                     break\
  12883.                                 end\
  12884.                             elseif ShortcutsLayoutEvent[1] == \"BeterPaint\" then\
  12885. \
  12886.                             end\
  12887.                         end\
  12888.                         notClose = false\
  12889.                     else\
  12890.                         local buffer = split(DesktopLayoutEvent[2],\"[^:]+\")\
  12891.                         print(DesktopLayoutEvent[2])\
  12892.                         changeColor(buffer[2])\
  12893.                     end\
  12894.                 end\
  12895.             end\
  12896.         elseif MainLayoutEvent[2] == \"Security\" then\
  12897.             local notClose = true\
  12898.             while notClose do\
  12899.                 SecurityLayout:draw()\
  12900.                 SecurityLayoutEvent = gui.eventHandler(SecurityLayout)\
  12901.                 if SecurityLayoutEvent[1] == \"TextBox\" then\
  12902.                     if SecurityLayoutEvent[2] == \"Password\" then\
  12903.                         local newPass = SecurityLayout.TextBox.Password:read()\
  12904.                         local file = fs.open(\"OmniOS/Settings/Users/Admin\",\"w\")\
  12905.                         file.write(Sha.sha256(newPass))\
  12906.                         file.close()\
  12907.                     end\
  12908.                 elseif SecurityLayoutEvent[1] == \"Button\" then\
  12909.                     if SecurityLayoutEvent[2] == \"Done\" then\
  12910.                         notClose = false\
  12911.                     end\
  12912.                 end\
  12913.             end\
  12914.         elseif MainLayoutEvent[2] == \"Close\" then\
  12915.             break\
  12916.         end\
  12917.     end\
  12918. end",
  12919.       Data = {
  12920.         Layouts = {
  12921.           [ "Shortcuts.layout" ] = "local w,h = term.getSize()\
  12922. local programPath = \"OmniOS/Programs/Desktop.app/Data/\"\
  12923. \
  12924. MainTable = {\
  12925.     Button = {\
  12926.         Done = {\
  12927.             name = \"Done\",\
  12928.             label = \"Done\",\
  12929.             xPos = w-3,\
  12930.             yPos = h,\
  12931.             fgColor = colors.white,\
  12932.             bgColor = colors.green,\
  12933.             xLength = 4,\
  12934.             yLength = 1,\
  12935.             returnValue = \"Done\",\
  12936.             xTextPos = 1,\
  12937.             yTextPos = 1,\
  12938.         },\
  12939.         Add = {\
  12940.             name = \"Add\",\
  12941.             label = \"+\",\
  12942.             xPos = 1,\
  12943.             yPos = h,\
  12944.             fgColor = colors.black,\
  12945.             bgColor = colors.white,\
  12946.             xLength = 11,\
  12947.             yLength = 3,\
  12948.             returnValue = \"Add\",\
  12949.             xTextPos = 1,\
  12950.             yTextPos = 1,\
  12951.         },\
  12952.     },\
  12953. }\
  12954. \
  12955. local function readFile(_path)\
  12956.     local file = fs.open(_path,\"r\")\
  12957.     local data = file.readAll()\
  12958.     file.close()\
  12959.     return data\
  12960. end\
  12961. \
  12962. local function loadShortcuts()\
  12963.     local buffer = readFile(programPath..\"Shortcuts\")\
  12964.     local sBuffer = textutils.unserialize(buffer)\
  12965.     local nBuffer = {}\
  12966.     paths = {}\
  12967.     for i,v in pairs(sBuffer) do\
  12968.         nBuffer[v.name] = {\
  12969.             xPos = 2+(6*(v.xPos-1)),\
  12970.             yPos = 1+(5*(v.yPos-1)),\
  12971.             name = v.name,\
  12972.             path = v.path..\".ico\",\
  12973.             yLength = 4,\
  12974.             xLength = 3,\
  12975.             returnValue = v.name,\
  12976.             label = string.sub(v.name,1,5),\
  12977.             labelFg = colors.black,\
  12978.             labelBg = colors.white,\
  12979.             moveY = true,\
  12980.         }\
  12981.         paths[v.name] = v.path\
  12982.     end\
  12983.     MainTable.BetterPaint = nBuffer\
  12984. end\
  12985. \
  12986. loadShortcuts()\
  12987. \
  12988. return MainTable",
  12989.           [ "Select.layout" ] = "local tArgs = {...}\
  12990. local w,h = term.getSize()\
  12991. local tReturnTable = {\
  12992.     Button = {},\
  12993.     Text = {\
  12994.         Title = {\
  12995.             name = \"Title\",\
  12996.             text = \"Select\",\
  12997.             xPos = 1,\
  12998.             yPos = 1,\
  12999.             bgColor = colors.gray,\
  13000.             fgColor = colors.white,\
  13001.         },\
  13002.     }\
  13003. }",
  13004.           [ "Desktop.layout" ] = "local w,h = term.getSize()\
  13005. MainTable = {\
  13006.     ColorField = {\
  13007.         Top = {\
  13008.             name = \"Top\",\
  13009.             xPos = 1,\
  13010.             yPos = 1,\
  13011.             xLength = w,\
  13012.             yLength = 3,\
  13013.             color = colors.orange,\
  13014.             \
  13015.         },\
  13016.     },\
  13017.     Button = {\
  13018.         Done = {\
  13019.             name = \"Done\",\
  13020.             label = \"Done\",\
  13021.             xPos = w-6,\
  13022.             yPos = h-3,\
  13023.             fgColor = colors.white,\
  13024.             bgColor = colors.green,\
  13025.             xLength = 6,\
  13026.             yLength = 3,\
  13027.             returnValue = \"Done\",\
  13028.             xTextPos = 2,\
  13029.             yTextPos = 2,\
  13030.         },\
  13031.         Shortcuts = {\
  13032.             name = \"Shortcuts\",\
  13033.             label = \"Shortcuts\",\
  13034.             xPos = 3,\
  13035.             yPos = h-3,\
  13036.             fgColor = colors.white,\
  13037.             bgColor = colors.cyan,\
  13038.             xLength = 11,\
  13039.             yLength = 3,\
  13040.             returnValue = \"Shortcuts\",\
  13041.             xTextPos = 2,\
  13042.             yTextPos = 2,\
  13043.         },\
  13044.             Green = {\
  13045.             name = \"Green\",\
  13046.             label = \" \",\
  13047.             xPos = w-3,\
  13048.             yPos = 5,\
  13049.             xLength = 1,\
  13050.             yLength = 1,\
  13051.             xTextPos = 1,\
  13052.             yTextPos = 1,\
  13053.             fgColor = 1,\
  13054.             bgColor = colors.green,\
  13055.             returnValue = \"color:green\",\
  13056.         },\
  13057.         Lime = {\
  13058.             name = \"Lime\",\
  13059.             label = \" \",\
  13060.             xPos = w-4,\
  13061.             yPos = 5,\
  13062.             xLength = 1,\
  13063.             yLength = 1,\
  13064.             xTextPos = 1,\
  13065.             yTextPos = 1,\
  13066.             fgColor = 1,\
  13067.             bgColor = colors.lime,\
  13068.             returnValue = \"color:lime\",\
  13069.         },\
  13070.         Brown = {\
  13071.             name = \"Brown\",\
  13072.             label = \" \",\
  13073.             xPos = w-5,\
  13074.             yPos = 5,\
  13075.             xLength = 1,\
  13076.             yLength = 1,\
  13077.             xTextPos = 1,\
  13078.             yTextPos = 1,\
  13079.             fgColor = 1,\
  13080.             bgColor = colors.brown,\
  13081.             returnValue = \"color:brown\",\
  13082.         },\
  13083.         Purple = {\
  13084.             name = \"Purple\",\
  13085.             label = \" \",\
  13086.             xPos = w-6,\
  13087.             yPos = 5,\
  13088.             xLength = 1,\
  13089.             yLength = 1,\
  13090.             xTextPos = 1,\
  13091.             yTextPos = 1,\
  13092.             fgColor = 1,\
  13093.             bgColor = colors.purple,\
  13094.             returnValue = \"color:purple\",\
  13095.         },\
  13096.         Blue = {\
  13097.             name = \"Blue\",\
  13098.             label = \" \",\
  13099.             xPos = w-7,\
  13100.             yPos = 5,\
  13101.             xLength = 1,\
  13102.             yLength = 1,\
  13103.             xTextPos = 1,\
  13104.             yTextPos = 1,\
  13105.             fgColor = 1,\
  13106.             bgColor = colors.blue,\
  13107.             returnValue = \"color:blue\",\
  13108.         },\
  13109.         lightBlue = {\
  13110.             name = \"lightBlue\",\
  13111.             label = \" \",\
  13112.             xPos = w-8,\
  13113.             yPos = 5,\
  13114.             xLength = 1,\
  13115.             yLength = 1,\
  13116.             xTextPos = 1,\
  13117.             yTextPos = 1,\
  13118.             fgColor = 1,\
  13119.             bgColor = colors.lightBlue,\
  13120.             returnValue = \"color:lightBlue\",\
  13121.         },\
  13122.         Yellow = {\
  13123.             name = \"Yellow\",\
  13124.             label = \" \",\
  13125.             xPos = w-9,\
  13126.             yPos = 5,\
  13127.             xLength = 1,\
  13128.             yLength = 1,\
  13129.             xTextPos = 1,\
  13130.             yTextPos = 1,\
  13131.             fgColor = 1,\
  13132.             bgColor = colors.yellow,\
  13133.             returnValue = \"color:yellow\",\
  13134.         },\
  13135.         Cyan = {\
  13136.             name = \"Cyan\",\
  13137.             label = \" \",\
  13138.             xPos = w-10,\
  13139.             yPos = 5,\
  13140.             xLength = 1,\
  13141.             yLength = 1,\
  13142.             xTextPos = 1,\
  13143.             yTextPos = 1,\
  13144.             fgColor = 1,\
  13145.             bgColor = colors.cyan,\
  13146.             returnValue = \"color:cyan\",\
  13147.         },\
  13148.         Orange = {\
  13149.             name = \"Orange\",\
  13150.             label = \" \",\
  13151.             xPos = w-11,\
  13152.             yPos = 5,\
  13153.             xLength = 1,\
  13154.             yLength = 1,\
  13155.             xTextPos = 1,\
  13156.             yTextPos = 1,\
  13157.             fgColor = 1,\
  13158.             bgColor = colors.orange,\
  13159.             returnValue = \"color:orange\",\
  13160.         },\
  13161.         Pink = {\
  13162.             name = \"Pink\",\
  13163.             label = \" \",\
  13164.             xPos = w-12,\
  13165.             yPos = 5,\
  13166.             xLength = 1,\
  13167.             yLength = 1,\
  13168.             xTextPos = 1,\
  13169.             yTextPos = 1,\
  13170.             fgColor = 1,\
  13171.             bgColor = colors.pink,\
  13172.             returnValue = \"color:pink\",\
  13173.         },\
  13174.         Red = {\
  13175.             name = \"Red\",\
  13176.             label = \" \",\
  13177.             xPos = w-13,\
  13178.             yPos = 5,\
  13179.             xLength = 1,\
  13180.             yLength = 1,\
  13181.             xTextPos = 1,\
  13182.             yTextPos = 1,\
  13183.             fgColor = 1,\
  13184.             bgColor = colors.red,\
  13185.             returnValue = \"color:red\",\
  13186.         },\
  13187.         Magenta = {\
  13188.             name = \"Magenta\",\
  13189.             label = \" \",\
  13190.             xPos = w-14,\
  13191.             yPos = 5,\
  13192.             xLength = 1,\
  13193.             yLength = 1,\
  13194.             xTextPos = 1,\
  13195.             yTextPos = 1,\
  13196.             fgColor = 1,\
  13197.             bgColor = colors.magenta,\
  13198.             returnValue = \"color:magenta\",\
  13199.         },\
  13200.         White = {\
  13201.             name = \"White\",\
  13202.             label = \" \",\
  13203.             xPos = w-15,\
  13204.             yPos = 5,\
  13205.             xLength = 1,\
  13206.             yLength = 1,\
  13207.             xTextPos = 1,\
  13208.             yTextPos = 1,\
  13209.             fgColor = 1,\
  13210.             bgColor = colors.white,\
  13211.             returnValue = \"color:white\",\
  13212.         },\
  13213.         lightGray = {\
  13214.             name = \"lightGray\",\
  13215.             label = \" \",\
  13216.             xPos = w-16,\
  13217.             yPos = 5,\
  13218.             xLength = 1,\
  13219.             yLength = 1,\
  13220.             xTextPos = 1,\
  13221.             yTextPos = 1,\
  13222.             fgColor = 1,\
  13223.             bgColor = colors.lightGray,\
  13224.             returnValue = \"color:lightGray\",\
  13225.         },\
  13226.         Black = {\
  13227.             name = \"Black\",\
  13228.             label = \" \",\
  13229.             xPos = w-17,\
  13230.             yPos = 5,\
  13231.             xLength = 1,\
  13232.             yLength = 1,\
  13233.             xTextPos = 1,\
  13234.             yTextPos = 1,\
  13235.             fgColor = 1,\
  13236.             bgColor = colors.black,\
  13237.             returnValue = \"color:black\",\
  13238.         },\
  13239.         Gray = {\
  13240.             name = \"Gray\",\
  13241.             label = \" \",\
  13242.             xPos = w-18,\
  13243.             yPos = 5,\
  13244.             xLength = 1,\
  13245.             yLength = 1,\
  13246.             xTextPos = 1,\
  13247.             yTextPos = 1,\
  13248.             fgColor = 1,\
  13249.             bgColor = colors.gray,\
  13250.             returnValue = \"color:gray\",\
  13251.         },\
  13252.     },\
  13253.     Text = {\
  13254.         Color = {\
  13255.             name = \"Color\",\
  13256.             text = \"Desktop Color\",\
  13257.             xPos = 3,\
  13258.             yPos = 5,\
  13259.             bgColor = colors.white,\
  13260.             fgColor = colors.black,\
  13261.         },\
  13262.         Title = {\
  13263.             name = \"Title\",\
  13264.             text = \"Settings/Desktop\",\
  13265.             xPos = 2,\
  13266.             yPos = 2,\
  13267.             fgColor = colors.white,\
  13268.             bgColor = colors.orange,\
  13269.         },\
  13270.     },\
  13271. }\
  13272. return MainTable",
  13273.           [ "Security.layout" ] = "local w,h = term.getSize()\
  13274. MainTable = {\
  13275.     ColorField = {\
  13276.         Top = {\
  13277.             name = \"Top\",\
  13278.             xPos = 1,\
  13279.             yPos = 1,\
  13280.             xLength = w,\
  13281.             yLength = 3,\
  13282.             color = colors.orange,\
  13283.             \
  13284.         },\
  13285.     },\
  13286.     Text = {\
  13287.         Title = {\
  13288.             name = \"Title\",\
  13289.             text = \"Settings/Security\",\
  13290.             xPos = 2,\
  13291.             yPos = 2,\
  13292.             fgColor = colors.white,\
  13293.             bgColor = colors.orange,\
  13294.         },\
  13295.         Password = {\
  13296.             name = \"Password\",\
  13297.             text = \"Password\",\
  13298.             xPos = 2,\
  13299.             yPos = 5,\
  13300.             fgColor = colors.black,\
  13301.             bgColor = colors.white,\
  13302.         },\
  13303.     },\
  13304.     TextBox = {\
  13305.         Password = {\
  13306.             name = \"Password\",\
  13307.             helpText = \"Change password...\",\
  13308.             xPos = 20,\
  13309.             yPos = 5,\
  13310.             xLength = 30,\
  13311.             yLength = 1,\
  13312.             bgColor = colors.lightGray,\
  13313.             fgColor = colors.black,\
  13314.             helpFgColor = colors.gray,\
  13315.             charLimit = 4,\
  13316.             confidential = true,\
  13317.             returnValue = \"Password\",\
  13318.         }\
  13319.     },\
  13320.     Button = {\
  13321.         Done = {\
  13322.             name = \"Done\",\
  13323.             label = \"Done\",\
  13324.             xPos = w-6,\
  13325.             yPos = h-3,\
  13326.             fgColor = colors.white,\
  13327.             bgColor = colors.green,\
  13328.             xLength = 6,\
  13329.             yLength = 3,\
  13330.             returnValue = \"Done\",\
  13331.             xTextPos = 2,\
  13332.             yTextPos = 2,\
  13333.         },\
  13334.     },\
  13335. }\
  13336. return MainTable",
  13337.           [ "Main.layout" ] = "local w,h = term.getSize()\
  13338. MainTable = {\
  13339.     ColorField = {\
  13340.         Top = {\
  13341.             name = \"Top\",\
  13342.             xPos = 1,\
  13343.             yPos = 1,\
  13344.             xLength = w,\
  13345.             yLength = 3,\
  13346.             color = colors.orange,\
  13347.         },\
  13348.     },\
  13349.     Button = {\
  13350.         Desktop = {\
  13351.             name = \"Desktop\",\
  13352.             label = \"Desktop\",\
  13353.             xPos = 2,\
  13354.             yPos = 5,\
  13355.             fgColor = colors.white,\
  13356.             bgColor = colors.blue,\
  13357.             xLength = 11,\
  13358.             yLength = 3,\
  13359.             returnValue = \"Desktop\",\
  13360.             xTextPos = 2,\
  13361.             yTextPos = 2,\
  13362.         },\
  13363.         Security = {\
  13364.             name = \"Security\",\
  13365.             label = \"Security\",\
  13366.             xPos = 2,\
  13367.             yPos = 9,\
  13368.             fgColor = colors.white,\
  13369.             bgColor = colors.green,\
  13370.             xLength = 11,\
  13371.             yLength = 3,\
  13372.             returnValue = \"Security\",\
  13373.             xTextPos = 2,\
  13374.             yTextPos = 2,\
  13375.         },\
  13376.         Close = {\
  13377.             name = \"Close\",\
  13378.             label = \"x\",\
  13379.             xPos = w-2,\
  13380.             yPos = 2,\
  13381.             fgColor = colors.white,\
  13382.             bgColor = colors.orange,\
  13383.             xLength = 1,\
  13384.             yLength = 1,\
  13385.             returnValue = \"Close\",\
  13386.             xTextPos = 1,\
  13387.             yTextPos = 1,\
  13388.         },\
  13389.     },\
  13390.     Text = {\
  13391.         Title = {\
  13392.             name = \"Title\",\
  13393.             text = \"TheOS Settings\",\
  13394.             xPos = 2,\
  13395.             yPos = 2,\
  13396.             fgColor = colors.white,\
  13397.             bgColor = colors.orange,\
  13398.         },\
  13399.     },\
  13400. }\
  13401. return MainTable",
  13402.         },
  13403.       },
  13404.     },
  13405.   },
  13406.   Drivers = {
  13407.     FS = {
  13408.       [ "devfs.lua" ] = "--[[\
  13409.  Everything is a file!\
  13410.  Author: Wassil Janssen a.k.a. Creator\
  13411. ]]--\
  13412. \
  13413. --Variables\
  13414. devfs = {}\
  13415. \
  13416. local oldFS = Utils.table.copy(fs)\
  13417. local peripheral = Utils.table.copy(peripheral)\
  13418. devfs.getName = oldFS.getName\
  13419. devfs.getSize = oldFS.getSize\
  13420. devfs.isDir = oldFS.isDir\
  13421. devfs.getDrive = oldFS.getDrive\
  13422. \
  13423. --Functions\
  13424. function devfs.isReadOnly() return false end\
  13425. function devfs.getFreeSpace() return oldFS.getFreeSpace('OmniOS') end\
  13426. function devfs.makeDir() return false end\
  13427. function devfs.move() return false end\
  13428. function devfs.copy() return false end\
  13429. function devfs.delete() return false end\
  13430. \
  13431. function devfs.list()\
  13432.  local ret = {}\
  13433.  for i,v in pairs(peripheral.getNames()) do\
  13434.    ret[i] = peripheral.getType(v)..\"_\"..v\
  13435.  end\
  13436.  return ret\
  13437. end\
  13438. \
  13439. function devfs.exists(path)\
  13440.  local path = oldFS.getName(path)\
  13441.  return peripheral.isPresent(path) or (function(path) for i,v in pairs(devfs.list()) do if v == path then return true end end return false end)(path)\
  13442. end\
  13443. \
  13444. function devfs.open(path)\
  13445.  assert(path:find(\"_\"),\"Path is invalid\")\
  13446.  assert(peripheral.isPresent(path:sub(path:find(\"_\")+1,-1)),\"No such peripheral!\")\
  13447.  local side = path:sub(path:find(\"_\")+1,-1)\
  13448.  local handle = {\
  13449.    ioctl = peripheral.wrap(side),\
  13450.    close = function() handle = nil end,\
  13451.  }\
  13452.  local handle_mt = {\
  13453.    __call = function(method,...)\
  13454.      return peripheral.call(side,\
  13455.      method,...)\
  13456.    end,\
  13457.    __metatable = function() return {} end,\
  13458.  }\
  13459.  setmetatable(handle.ioctl,handle_mt)\
  13460.  setmetatable(handle,{__index = handle.ioctl})\
  13461.  return handle\
  13462. end\
  13463. \
  13464. return devfs",
  13465.       [ "ccfs.lua" ] = "--[[\
  13466.  Standart ComputerCraft File System\
  13467. ]]--\
  13468. \
  13469. return Utils.table.copy(fs)",
  13470.     },
  13471.     peripheral = {
  13472.       [ "multi_mon.lua" ] = "--[[\
  13473.  Author: Wassil Janssen a.k.a. Creator\
  13474. ]]--\
  13475. local function toRet(...)\
  13476.  local monTable = (...)\
  13477.  assert(type(monTable) == \"table\",\"Expected table!\",2)\
  13478. \
  13479.  local num = \"\"\
  13480.  local x,y,isColor = 0,0,0\
  13481.  local temp = {x = 0,y = 0}\
  13482. \
  13483.  for i,v in pairs(monTable) do\
  13484.    assert(type(v) == \"table\",\"Expected table!\",2)\
  13485.    if num == \"\" then\
  13486.      num = #v\
  13487.    elseif #v ~= num then\
  13488.      error(\"Table is invalid\",2)\
  13489.    end\
  13490.  end\
  13491.  for i,v in pairs(monTable) do\
  13492.    for k,m in pairs(v) do\
  13493.      assert(peripheral.isPresent(m),\"The monitor \"..m..\" does not exist!\",2)\
  13494.      assert(peripheral.getType(m) == \"monitor\",\"Not a monitor, sorry!\",2)\
  13495.      if x == 0 and y == 0 then\
  13496.        x,y = peripheral.call(m,\"getSize\")\
  13497.      else\
  13498.        temp.x,temp.y = peripheral.call(m,\"getSize\")\
  13499.        assert(temp.x == x and temp.y == y,\"The monitors don't have the same size!\",2)\
  13500.      end\
  13501.      if isColor == 0 then\
  13502.        isColor = peripheral.call(m,\"isColor\")\
  13503.      else\
  13504.        assert(isColor == peripheral.call(m,\"isColor\"),\"The monitors are not of the same type!\",2)\
  13505.      end\
  13506.    end\
  13507.  end\
  13508.  --Check done!\
  13509.  --Functions\
  13510.  local monitors = {}\
  13511.  local handle = {}\
  13512.  local x,y = 1,1\
  13513.  local w,h = peripheral.call(monTable[1][1],\"getSize\")\
  13514.  local isBlink = false\
  13515. \
  13516.  for i,v in pairs(monTable) do\
  13517.    monitors[#monitors+1] = (function()\
  13518.      local ret = {}\
  13519.      for k,m in pairs(v) do\
  13520.        ret[#ret+1] = peripheral.wrap(m)\
  13521.      end\
  13522.      return ret\
  13523.    end)()\
  13524.  end\
  13525. \
  13526.  handle.isColor = monitors[1][1].isColor\
  13527.  handle.isColour = monitors[1][1].isColor\
  13528. \
  13529.  function handle.getSize()\
  13530.    return w*#monitors[1],h*#monitors\
  13531.  end\
  13532. \
  13533.  function handle.setCursorPos(tx,ty)\
  13534.    x = tx\
  13535.    y = ty\
  13536.    handle.setCursorBlink(isBlink)\
  13537.  end\
  13538. \
  13539.  function handle.setTextScale(scale)\
  13540.    for i,v in pairs(monitors) do\
  13541.      for k,m in pairs(v) do\
  13542.        m.setTextScale(scale)\
  13543.      end\
  13544.    end\
  13545.    w,h = monitors[1][1].getSize()\
  13546.  end\
  13547. \
  13548.  function handle.clear()\
  13549.    for i,v in pairs(monitors) do\
  13550.      for k,m in pairs(v) do\
  13551.        m.clear()\
  13552.      end\
  13553.    end\
  13554.  end\
  13555. \
  13556.  function handle.setTextColor(color)\
  13557.    for i,v in pairs(monitors) do\
  13558.      for k,m in pairs(v) do\
  13559.        m.setTextColor(color)\
  13560.      end\
  13561.    end\
  13562.  end\
  13563. \
  13564.  handle.setTextColour = handle.setTextColor\
  13565. \
  13566.  function handle.setBackgroundColor(color)\
  13567.    for i,v in pairs(monitors) do\
  13568.      for k,m in pairs(v) do\
  13569.        m.setBackgroundColor(color)\
  13570.      end\
  13571.    end\
  13572.  end\
  13573. \
  13574.  handle.setBackgroundColour = handle.setBackgroundColor\
  13575. \
  13576.  function handle.scroll(lines)\
  13577.    for i,v in pairs(monitors) do\
  13578.      for k,m in pairs(v) do\
  13579.        m.scroll(lines)\
  13580.      end\
  13581.    end\
  13582.  end\
  13583. \
  13584.  function handle.setCursorBlink(blink)\
  13585.    for i,v in pairs(monitors) do\
  13586.      for k,m in pairs(v) do\
  13587.        m.setCursorBlink(false)\
  13588.      end\
  13589.    end\
  13590.    local whichY = math.ceil(y/h)\
  13591.    local whichX = math.ceil(x/w)\
  13592.    monitors[whichY][whichX].setCursorPos(x%w,y%h)\
  13593.    monitors[whichY][whichX].setCursorBlink(blink)\
  13594.    isBlink = blink\
  13595.  end\
  13596. \
  13597.  function handle.clearLine()\
  13598.    local whichY = math.ceil(y/h)\
  13599.    local height = y%h\
  13600.    local whichX = math.ceil(x/w)\
  13601.    for i,v in pairs(monitors[whichY]) do\
  13602.      if i == whichX then\
  13603.        v.setCursorPos(x%w,height)\
  13604.        v.clearLine()\
  13605.      else\
  13606.        v.setCursorPos(1,height)\
  13607.        v.clearLine()\
  13608.      end\
  13609.    end\
  13610.  end\
  13611. \
  13612.  function handle.getCursorPos()\
  13613.    return x,y\
  13614.  end\
  13615. \
  13616.  function handle.write(text)\
  13617.    local tempX = x\
  13618.    local tempBlink = isBlink\
  13619.    handle.setCursorBlink(false)\
  13620.    text = tostring(text)\
  13621.    for i = 1, text:len() do\
  13622.      local whichY = math.ceil(y/h)\
  13623.      local height = y%h\
  13624.      local whichX = math.ceil(tempX/w)\
  13625.      local width = tempX%w\
  13626.      handle.setCursorPos(tempX,y)\
  13627.      monitor[whichY][whichX].write(text:sub(i,i))\
  13628.      tempX = tempX + 1\
  13629.    end\
  13630.    handle.setCursorPos(tempX+1,y)\
  13631.    x = tempX\
  13632.    handle.setCursorBlink(tempBlink)\
  13633.  end\
  13634. \
  13635.  return handle\
  13636. end\
  13637. return toRet",
  13638.     },
  13639.     [ "disk.lua" ] = "local function mountDisk(event,side)\
  13640.  for i,v in pairs(fs.list(\"OmniOS/Programs\")) do\
  13641.    if not disk.hasAudio(side) then\
  13642.      fs.link(\"OmniOS/Programs/\"..v..\"/\"..disk.getMountPath(side),disk.getMountPath(side))\
  13643.    end\
  13644.  end\
  13645. end\
  13646. \
  13647. for i,side in pairs(peripheral.getNames()) do\
  13648.  if peripheral.getType(side) == \"drive\" then\
  13649.    if not disk.hasAudio(side) then\
  13650.      for k,m in pairs(fs.list(\"OmniOS/Programs\")) do\
  13651.        fs.link(\"OmniOS/Programs/\"..m..\"/\"..disk.getMountPath(side),disk.getMountPath(side))\
  13652.      end\
  13653.    end\
  13654.  end\
  13655. end\
  13656. \
  13657. Kernel.bindEvent(\"disk\",mountDisk)",
  13658.     [ "FS.lua" ] = "--[[\
  13659.     FS overwrite\
  13660.     Author: Wassil JAnssen a.k.a. Creator\
  13661. ]]--\
  13662. \
  13663. --Variables\
  13664. local altFS = {}\
  13665. local altFS_mt = {\
  13666.     __index = function(t,k) Utils.debug(\"Tried to acces fs \"..k..\", total fail!\") return altFS.ccfs end\
  13667. }\
  13668. setmetatable(altFS,altFS_mt)\
  13669. \
  13670. altFS.ccfs = Utils.table.copy(fs)\
  13671. print(\"Loading FSes\")\
  13672. for i,v in pairs(fs.list(\"OmniOS/Drivers/FS\")) do\
  13673.     print(\"Loading FS \"..v)\
  13674.     altFS[v:match(\"[^%.]+\")] = dofile(\"OmniOS/Drivers/FS/\"..v)\
  13675.     Utils.debug(\"Loading FS \"..v)\
  13676. end\
  13677. --Functions\
  13678. \
  13679. fs.getFS = fsh.getFS\
  13680. fs.mount = fsh.mount\
  13681. fs.getMountPath = fsh.resolveLinks\
  13682. fs.setFS = fsh.setFS\
  13683. fs.link = fsh.link\
  13684. fs.fs = altFS\
  13685. \
  13686. function fs.isReadOnly(path)\
  13687.     local path = fsh.resolveLinks(path)\
  13688.     local fss = fs.getFS(path)\
  13689.     --ffs = altFS[fss] or altFS.ccfs\
  13690.     return altFS[fss].isReadOnly(path)\
  13691. end\
  13692. \
  13693. function fs.list(path)\
  13694.     Utils.debug(path)\
  13695.     local path = fsh.resolveLinks(path)\
  13696.     Utils.debug(path)\
  13697.     local fss = fs.getFS(path)\
  13698.     Utils.debug(\"The fs for \"..path..\" is \"..fss)\
  13699.     --local ffs = altFS[fss] or altFS.ccfs\
  13700.     return altFS[fss].list(path)\
  13701. end\
  13702. \
  13703. function fs.exists(path)\
  13704.     local path = Utils.debug(fsh.resolveLinks(path))\
  13705.     local fss = fs.getFS(path)\
  13706.     --local ffs = altFS[fss] or altFS.ccfs\
  13707.     return altFS[fss].exists(path)\
  13708. end\
  13709. \
  13710. function fs.isDir(path)\
  13711.     local path = fsh.resolveLinks(path)\
  13712.     local fss = fs.getFS(path)\
  13713.     --ffs = altFS[fss] or altFS.ccfs\
  13714.     return altFS[fss].isDir(path)\
  13715. end\
  13716. \
  13717. function fs.getDrive(path)\
  13718.     local path = fsh.resolveLinks(path)\
  13719.     local fss = fs.getFS(path)\
  13720.     --local ffs = altFS[fss] or altFS.ccfs\
  13721.     return altFS[fss].getDrive(path)\
  13722. end\
  13723. \
  13724. function fs.getSize(path)\
  13725.     local path = fsh.resolveLinks(path)\
  13726.     local fss = fs.getFS(path)\
  13727.     --local ffs = altFS[fss] or altFS.ccfs\
  13728.     return altFS[fss].getSize(path)\
  13729. end\
  13730. \
  13731. function fs.getFreeSpace(path)\
  13732.     local path = fsh.resolveLinks(path)\
  13733.     local fss = fs.getFS(path)\
  13734.     --local ffs = altFS[fss] or altFS.ccfs\
  13735.     return altFS[fss].getFreeSpace(path)\
  13736. end\
  13737. \
  13738. function fs.makeDir(path)\
  13739.     local path = fsh.resolveLinks(path)\
  13740.     local fss = fs.getFS(path)\
  13741.     --local ffs = altFS[fss] or altFS.ccfs\
  13742.     return altFS[fss].makeDir(path)\
  13743. end\
  13744. --[[Elaborate]]--\
  13745. function fs.copy(path1,path2)\
  13746.     local path1 = fsh.resolveLinks(path1)\
  13747.     local fss1 = fs.getFS(path1)\
  13748.     local path2 = fsh.resolveLinks(path2)\
  13749.     local fss2 = fs.getFS(path2)\
  13750.     local buffer = {}\
  13751.     if (altFS[fss] or altFS.ccfs).isDir(path1) then\
  13752. \
  13753.     else\
  13754. \
  13755.     end\
  13756.     return oldFS.copy(path1,path2)\
  13757. end\
  13758. \
  13759. function fs.move(path1,path2)\
  13760.     local path1 = fsh.resolveLinks(path1)\
  13761.     local path2 = fsh.resolveLinks(path2)\
  13762.     return oldFS.move(path1,path2)\
  13763. end\
  13764. \
  13765. function fs.delete(path)\
  13766.     local path = fsh.resolveLinks(path)\
  13767.     local fss = fs.getFS(path)\
  13768.     --local ffs = altFS[fss] or altFS.ccfs\
  13769.     return altFS[fss].delete(path)\
  13770. end\
  13771. \
  13772. function fs.open(path,mode)\
  13773.     local path = fsh.resolveLinks(path)\
  13774.     local fss = fs.getFS(path)\
  13775.     --local ffs = altFS[fss] or altFS.ccfs\
  13776.     return altFS[fss].open(path,mode)\
  13777. end\
  13778. \
  13779. Utils.debug(\"Loaded FS driver.\")\
  13780. fs.setFS(\"/dev\",\"devfs\")\
  13781. fs.link(\"p\",\"OmniOS/Programs\")",
  13782.     [ "peripheral.lua" ] = "--[[\
  13783.  Author: Wassil Janssen a.k.a. Creator\
  13784. ]]--\
  13785. \
  13786. local per = Utils.table.copy(peripheral)\
  13787. local extra = {}\
  13788. for i,v in pairs(fs.list(\"OmniOS/Drivers/peripheral\")) do\
  13789.  extra[v:match(\"[^%.]+\")] = dofile(\"OmniOS/Drivers/peripheral/\"..v)\
  13790. end\
  13791. \
  13792. function peripheral.wrap(side,...)\
  13793.  if extra[side] then\
  13794.    return extra[side](...)\
  13795.  else\
  13796.    return per.wrap(side)\
  13797.  end\
  13798. end",
  13799.   },
  13800.   API = {
  13801.     [ "Sha.lua" ] = "local MOD = 2^32\
  13802. local MODM = MOD-1\
  13803. \
  13804. local function memoize(f)\
  13805.        local mt = {}\
  13806.        local t = setmetatable({}, mt)\
  13807.        function mt:__index(k)\
  13808.                local v = f(k)\
  13809.                t[k] = v\
  13810.                return v\
  13811.        end\
  13812.        return t\
  13813. end\
  13814. \
  13815. local function make_bitop_uncached(t, m)\
  13816.        local function bitop(a, b)\
  13817.                local res,p = 0,1\
  13818.                while a ~= 0 and b ~= 0 do\
  13819.                        local am, bm = a % m, b % m\
  13820.                        res = res + t[am][bm] * p\
  13821.                        a = (a - am) / m\
  13822.                        b = (b - bm) / m\
  13823.                        p = p*m\
  13824.                end\
  13825.                res = res + (a + b) * p\
  13826.                return res\
  13827.        end\
  13828.        return bitop\
  13829. end\
  13830. \
  13831. local function make_bitop(t)\
  13832.        local op1 = make_bitop_uncached(t,2^1)\
  13833.        local op2 = memoize(function(a) return memoize(function(b) return op1(a, b) end) end)\
  13834.        return make_bitop_uncached(op2, 2 ^ (t.n or 1))\
  13835. end\
  13836. \
  13837. local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})\
  13838. \
  13839. local function bxor(a, b, c, ...)\
  13840.        local z = nil\
  13841.        if b then\
  13842.                a = a % MOD\
  13843.                b = b % MOD\
  13844.                z = bxor1(a, b)\
  13845.                if c then z = bxor(z, c, ...) end\
  13846.                return z\
  13847.        elseif a then return a % MOD\
  13848.        else return 0 end\
  13849. end\
  13850. \
  13851. local function band(a, b, c, ...)\
  13852.        local z\
  13853.        if b then\
  13854.                a = a % MOD\
  13855.                b = b % MOD\
  13856.                z = ((a + b) - bxor1(a,b)) / 2\
  13857.                if c then z = bit32_band(z, c, ...) end\
  13858.                return z\
  13859.        elseif a then return a % MOD\
  13860.        else return MODM end\
  13861. end\
  13862. \
  13863. local function bnot(x) return (-1 - x) % MOD end\
  13864. \
  13865. local function rshift1(a, disp)\
  13866.        if disp < 0 then return lshift(a,-disp) end\
  13867.        return math.floor(a % 2 ^ 32 / 2 ^ disp)\
  13868. end\
  13869. \
  13870. local function rshift(x, disp)\
  13871.        if disp > 31 or disp < -31 then return 0 end\
  13872.        return rshift1(x % MOD, disp)\
  13873. end\
  13874. \
  13875. local function lshift(a, disp)\
  13876.        if disp < 0 then return rshift(a,-disp) end\
  13877.        return (a * 2 ^ disp) % 2 ^ 32\
  13878. end\
  13879. \
  13880. local function rrotate(x, disp)\
  13881.    x = x % MOD\
  13882.    disp = disp % 32\
  13883.    local low = band(x, 2 ^ disp - 1)\
  13884.    return rshift(x, disp) + lshift(low, 32 - disp)\
  13885. end\
  13886. \
  13887. local k = {\
  13888.        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,\
  13889.        0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\
  13890.        0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\
  13891.        0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\
  13892.        0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,\
  13893.        0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\
  13894.        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,\
  13895.        0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\
  13896.        0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\
  13897.        0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\
  13898.        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,\
  13899.        0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\
  13900.        0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,\
  13901.        0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\
  13902.        0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\
  13903.        0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\
  13904. }\
  13905. \
  13906. local function str2hexa(s)\
  13907.        return (string.gsub(s, \".\", function(c) return string.format(\"%02x\", string.byte(c)) end))\
  13908. end\
  13909. \
  13910. local function num2s(l, n)\
  13911.        local s = \"\"\
  13912.        for i = 1, n do\
  13913.                local rem = l % 256\
  13914.                s = string.char(rem) .. s\
  13915.                l = (l - rem) / 256\
  13916.        end\
  13917.        return s\
  13918. end\
  13919. \
  13920. local function s232num(s, i)\
  13921.        local n = 0\
  13922.        for i = i, i + 3 do n = n*256 + string.byte(s, i) end\
  13923.        return n\
  13924. end\
  13925. \
  13926. local function preproc(msg, len)\
  13927.        local extra = 64 - ((len + 9) % 64)\
  13928.        len = num2s(8 * len, 8)\
  13929.        msg = msg .. \"\\128\" .. string.rep(\"\\0\", extra) .. len\
  13930.        assert(#msg % 64 == 0)\
  13931.        return msg\
  13932. end\
  13933. \
  13934. local function initH256(H)\
  13935.        H[1] = 0x6a09e667\
  13936.        H[2] = 0xbb67ae85\
  13937.        H[3] = 0x3c6ef372\
  13938.        H[4] = 0xa54ff53a\
  13939.        H[5] = 0x510e527f\
  13940.        H[6] = 0x9b05688c\
  13941.        H[7] = 0x1f83d9ab\
  13942.        H[8] = 0x5be0cd19\
  13943.        return H\
  13944. end\
  13945. \
  13946. local function digestblock(msg, i, H)\
  13947.        local w = {}\
  13948.        for j = 1, 16 do w[j] = s232num(msg, i + (j - 1)*4) end\
  13949.        for j = 17, 64 do\
  13950.                local v = w[j - 15]\
  13951.                local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3))\
  13952.                v = w[j - 2]\
  13953.                w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10))\
  13954.        end\
  13955. \
  13956.        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]\
  13957.        for i = 1, 64 do\
  13958.                local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))\
  13959.                local maj = bxor(band(a, b), band(a, c), band(b, c))\
  13960.                local t2 = s0 + maj\
  13961.                local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))\
  13962.                local ch = bxor (band(e, f), band(bnot(e), g))\
  13963.                local t1 = h + s1 + ch + k[i] + w[i]\
  13964.                h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2\
  13965.        end\
  13966. \
  13967.        H[1] = band(H[1] + a)\
  13968.        H[2] = band(H[2] + b)\
  13969.        H[3] = band(H[3] + c)\
  13970.        H[4] = band(H[4] + d)\
  13971.        H[5] = band(H[5] + e)\
  13972.        H[6] = band(H[6] + f)\
  13973.        H[7] = band(H[7] + g)\
  13974.        H[8] = band(H[8] + h)\
  13975. end\
  13976. \
  13977. function sha256(msg)\
  13978.        msg = preproc(msg, #msg)\
  13979.        local H = initH256({})\
  13980.        for i = 1, #msg, 64 do digestblock(msg, i, H) end\
  13981.        return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) ..\
  13982.                num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4))\
  13983. end",
  13984.     [ ".ignoreme" ] = "{\
  13985.  [\".ignoreme\"] = true,\
  13986. }",
  13987.     [ "Utils.lua" ] = "--[[\
  13988.  Utils API\
  13989.  by Wassil Janssen a.k.a. Creator\
  13990.  OmniOS\
  13991. ]]--\
  13992. \
  13993. debugprint = false\
  13994. debuglog = true -- don't you judge me!\
  13995. local oldOpen = fs.open\
  13996. \
  13997. function split(toSplit,sep)\
  13998.  if type(toSplit) ~= \"string\" then return false end\
  13999.  sep = sep or \"%s\"\
  14000.  local ret = {}\
  14001.  local count = 1\
  14002.  for token in toSplit:gmatch(\"[^\"..sep..\"]+\") do\
  14003.    ret[count] = token\
  14004.    count = count + 1\
  14005.  end\
  14006.  return ret\
  14007. end\
  14008. \
  14009. local function tablecopy(source,destination)\
  14010.  for i,v in pairs(source) do\
  14011.    if type(v) == \"table\" then\
  14012.      destination[i] = {}\
  14013.      tablecopy(source[i],destination[i])\
  14014.    else\
  14015.      destination[i] = v\
  14016.    end\
  14017.  end\
  14018. end\
  14019. \
  14020. function log(destination,message,app)\
  14021.     local finalMsg = \"[\"..os.day()..\":\"..os.time()..\"]\"\
  14022.     if app then\
  14023.         finalMsg = finalMsg..\".[\"..tostring(app)..\"]:\"..tostring(message)\
  14024.     else\
  14025.         finalMsg = finalMsg..\":\"..tostring(message)\
  14026.     end\
  14027.     local m = oldOpen(\"OmniOS/Logs/\"..destination..\".log\",\"a\")\
  14028.     m.write(finalMsg..\"\\n\")\
  14029.     m.close()\
  14030. end\
  14031. \
  14032. function debug(...)\
  14033.  if debugprint then\
  14034.    print(...)\
  14035.  end\
  14036.  if debuglog then\
  14037.    log(\"PrintIO\",(function(tabl,sep) local endRes = \"\" for i,v in pairs(tabl) do endRes = endRes..sep..v end return endRes:sub(#sep+1,-1) end)({...},\" && \"))\
  14038.  end\
  14039.  return ...\
  14040. end\
  14041. \
  14042. table = {\
  14043.  copy = function(source,destination)\
  14044.    destination = destination or {}\
  14045.    tablecopy(source,destination)\
  14046.    return destination\
  14047.  end\
  14048. }",
  14049.     [ "textutils.lua" ] = "\
  14050. function slowWrite( sText, nRate )\
  14051.    nRate = nRate or 20\
  14052.    if nRate < 0 then\
  14053.        error( \"Rate must be positive\", 2 )\
  14054.    end\
  14055.    local nSleep = 1 / nRate\
  14056.        \
  14057.    sText = tostring( sText )\
  14058.    local x,y = term.getCursorPos(x,y)\
  14059.    local len = string.len( sText )\
  14060.    \
  14061.    for n=1,len do\
  14062.        term.setCursorPos( x, y )\
  14063.        sleep( nSleep )\
  14064.        local nLines = write( string.sub( sText, 1, n ) )\
  14065.        local newX, newY = term.getCursorPos()\
  14066.        y = newY - nLines\
  14067.    end\
  14068. end\
  14069. \
  14070. function slowPrint( sText, nRate )\
  14071.    slowWrite( sText, nRate)\
  14072.    print()\
  14073. end\
  14074. \
  14075. function formatTime( nTime, bTwentyFourHour )\
  14076.    local sTOD = nil\
  14077.    if not bTwentyFourHour then\
  14078.        if nTime >= 12 then\
  14079.            sTOD = \"PM\"\
  14080.        else\
  14081.            sTOD = \"AM\"\
  14082.        end\
  14083.        if nTime >= 13 then\
  14084.            nTime = nTime - 12\
  14085.        end\
  14086.    end\
  14087. \
  14088.    local nHour = math.floor(nTime)\
  14089.    local nMinute = math.floor((nTime - nHour)*60)\
  14090.    if sTOD then\
  14091.        return string.format( \"%d:%02d %s\", nHour, nMinute, sTOD )\
  14092.    else\
  14093.        return string.format( \"%d:%02d\", nHour, nMinute )\
  14094.    end\
  14095. end\
  14096. \
  14097. local function makePagedScroll( _term, _nFreeLines )\
  14098.    local nativeScroll = _term.scroll\
  14099.    local nFreeLines = _nFreeLines or 0\
  14100.    return function( _n )\
  14101.        for n=1,_n do\
  14102.            nativeScroll( 1 )\
  14103.            \
  14104.            if nFreeLines <= 0 then\
  14105.                local w,h = _term.getSize()\
  14106.                _term.setCursorPos( 1, h )\
  14107.                _term.write( \"Press any key to continue\" )\
  14108.                os.pullEvent( \"key\" )\
  14109.                _term.clearLine()\
  14110.                _term.setCursorPos( 1, h )\
  14111.            else\
  14112.                nFreeLines = nFreeLines - 1\
  14113.            end\
  14114.        end\
  14115.    end\
  14116. end\
  14117. \
  14118. function pagedPrint( _sText, _nFreeLines )\
  14119.    -- Setup a redirector\
  14120.    local oldTerm = term.current()\
  14121.    local newTerm = {}\
  14122.    for k,v in pairs( oldTerm ) do\
  14123.        newTerm[k] = v\
  14124.    end\
  14125.    newTerm.scroll = makePagedScroll( oldTerm, _nFreeLines )\
  14126.    term.redirect( newTerm )\
  14127. \
  14128.    -- Print the text\
  14129.    local result\
  14130.    local ok, err = pcall( function()\
  14131.        result = print( _sText )\
  14132.    end )\
  14133. \
  14134.    -- Removed the redirector\
  14135.    term.redirect( oldTerm )\
  14136. \
  14137.    -- Propogate errors\
  14138.    if not ok then\
  14139.        error( err, 0 )\
  14140.    end\
  14141.    return result\
  14142. end\
  14143. \
  14144. local function tabulateCommon( bPaged, ... )\
  14145.    local tAll = { ... }\
  14146.    \
  14147.    local w,h = term.getSize()\
  14148.    local nMaxLen = w / 8\
  14149.    for n, t in ipairs( tAll ) do\
  14150.        if type(t) == \"table\" then\
  14151.            for n, sItem in pairs(t) do\
  14152.                nMaxLen = math.max( string.len( sItem ) + 1, nMaxLen )\
  14153.            end\
  14154.        end\
  14155.    end\
  14156.    local nCols = math.floor( w / nMaxLen )\
  14157.    local nLines = 0\
  14158.    local function newLine()\
  14159.        if bPaged and nLines >= (h-3) then\
  14160.            pagedPrint()\
  14161.        else\
  14162.            print()\
  14163.        end\
  14164.        nLines = nLines + 1\
  14165.    end\
  14166.    \
  14167.    local function drawCols( _t )\
  14168.        local nCol = 1\
  14169.        for n, s in ipairs( _t ) do\
  14170.            if nCol > nCols then\
  14171.                nCol = 1\
  14172.                newLine()\
  14173.            end\
  14174. \
  14175.            local cx, cy = term.getCursorPos()\
  14176.            cx = 1 + ((nCol - 1) * nMaxLen)\
  14177.            term.setCursorPos( cx, cy )\
  14178.            term.write( s )\
  14179. \
  14180.            nCol = nCol + 1      \
  14181.        end\
  14182.        print()\
  14183.    end\
  14184.    for n, t in ipairs( tAll ) do\
  14185.        if type(t) == \"table\" then\
  14186.            if #t > 0 then\
  14187.                drawCols( t )\
  14188.            end\
  14189.        elseif type(t) == \"number\" then\
  14190.            term.setTextColor( t )\
  14191.        end\
  14192.    end    \
  14193. end\
  14194. \
  14195. function tabulate( ... )\
  14196.    tabulateCommon( false, ... )\
  14197. end\
  14198. \
  14199. function pagedTabulate( ... )\
  14200.    tabulateCommon( true, ... )\
  14201. end\
  14202. \
  14203. local g_tLuaKeywords = {\
  14204.    [ \"and\" ] = true,\
  14205.    [ \"break\" ] = true,\
  14206.    [ \"do\" ] = true,\
  14207.    [ \"else\" ] = true,\
  14208.    [ \"elseif\" ] = true,\
  14209.    [ \"end\" ] = true,\
  14210.    [ \"false\" ] = true,\
  14211.    [ \"for\" ] = true,\
  14212.    [ \"function\" ] = true,\
  14213.    [ \"if\" ] = true,\
  14214.    [ \"in\" ] = true,\
  14215.    [ \"local\" ] = true,\
  14216.    [ \"nil\" ] = true,\
  14217.    [ \"not\" ] = true,\
  14218.    [ \"or\" ] = true,\
  14219.    [ \"repeat\" ] = true,\
  14220.    [ \"return\" ] = true,\
  14221.    [ \"then\" ] = true,\
  14222.    [ \"true\" ] = true,\
  14223.    [ \"until\" ] = true,\
  14224.    [ \"while\" ] = true,\
  14225. }\
  14226. \
  14227. local function serializeImpl( t, tTracking, sIndent )\
  14228.    local sType = type(t)\
  14229.    if sType == \"table\" then\
  14230.        --if tTracking[t] ~= nil then\
  14231.           -- error( \"Cannot serialize table with recursive entries\", 0 )\
  14232.        --end\
  14233.        tTracking[t] = true\
  14234. \
  14235.        if next(t) == nil then\
  14236.            -- Empty tables are simple\
  14237.            return \"{}\"\
  14238.        else\
  14239.            -- Other tables take more work\
  14240.            local sResult = \"{\\n\"\
  14241.            local sSubIndent = sIndent .. \"  \"\
  14242.            local tSeen = {}\
  14243.            for k,v in ipairs(t) do\
  14244.                tSeen[k] = true\
  14245.                sResult = sResult .. sSubIndent .. serializeImpl( v, tTracking, sSubIndent ) .. \",\\n\"\
  14246.            end\
  14247.            for k,v in pairs(t) do\
  14248.                if not tSeen[k] then\
  14249.                    local sEntry\
  14250.                    if type(k) == \"string\" and not g_tLuaKeywords[k] and string.match( k, \"^[%a_][%a%d_]*$\" ) then\
  14251.                        sEntry = k .. \" = \" .. serializeImpl( v, tTracking, sSubIndent ) .. \",\\n\"\
  14252.                    else\
  14253.                        sEntry = \"[ \" .. serializeImpl( k, tTracking, sSubIndent ) .. \" ] = \" .. serializeImpl( v, tTracking, sSubIndent ) .. \",\\n\"\
  14254.                    end\
  14255.                    sResult = sResult .. sSubIndent .. sEntry\
  14256.                end\
  14257.            end\
  14258.            sResult = sResult .. sIndent .. \"}\"\
  14259.            return sResult\
  14260.        end\
  14261.        \
  14262.    elseif sType == \"string\" then\
  14263.        return string.format( \"%q\", t )\
  14264.    \
  14265.    elseif sType == \"number\" or sType == \"boolean\" or sType == \"nil\" then\
  14266.        return tostring(t)\
  14267.        \
  14268.    else\
  14269.        error( \"Cannot serialize type \"..sType, 0 )\
  14270.        \
  14271.    end\
  14272. end\
  14273. \
  14274. EMPTY_ARRAY = {}\
  14275. \
  14276. local function serializeJSONImpl( t, tTracking )\
  14277.    local sType = type(t)\
  14278.    if t == EMPTY_ARRAY then\
  14279.        return \"[]\"\
  14280. \
  14281.    elseif sType == \"table\" then\
  14282.        --if tTracking[t] ~= nil then\
  14283.          --  error( \"Cannot serialize table with recursive entries\", 0 )\
  14284.        --end\
  14285.        tTracking[t] = true\
  14286. \
  14287.        if next(t) == nil then\
  14288.            -- Empty tables are simple\
  14289.            return \"{}\"\
  14290.        else\
  14291.            -- Other tables take more work\
  14292.            local sObjectResult = \"{\"\
  14293.            local sArrayResult = \"[\"\
  14294.            local nObjectSize = 0\
  14295.            local nArraySize = 0\
  14296.            for k,v in pairs(t) do\
  14297.                if type(k) == \"string\" then\
  14298.                    local sEntry = serializeJSONImpl( k, tTracking ) .. \":\" .. serializeJSONImpl( v, tTracking )\
  14299.                    if nObjectSize == 0 then\
  14300.                        sObjectResult = sObjectResult .. sEntry\
  14301.                    else\
  14302.                        sObjectResult = sObjectResult .. \",\" .. sEntry\
  14303.                    end\
  14304.                    nObjectSize = nObjectSize + 1\
  14305.                end\
  14306.            end\
  14307.            for n,v in ipairs(t) do\
  14308.                local sEntry = serializeJSONImpl( v, tTracking )\
  14309.                if nArraySize == 0 then\
  14310.                    sArrayResult = sArrayResult .. sEntry\
  14311.                else\
  14312.                    sArrayResult = sArrayResult .. \",\" .. sEntry\
  14313.                end\
  14314.                nArraySize = nArraySize + 1\
  14315.            end\
  14316.            sObjectResult = sObjectResult .. \"}\"\
  14317.            sArrayResult = sArrayResult .. \"]\"\
  14318.            if nObjectSize > 0 or nArraySize == 0 then\
  14319.                return sObjectResult\
  14320.            else\
  14321.                return sArrayResult\
  14322.            end\
  14323.        end\
  14324. \
  14325.    elseif sType == \"string\" then\
  14326.        return string.format( \"%q\", t )\
  14327. \
  14328.    elseif sType == \"number\" or sType == \"boolean\" then\
  14329.        return tostring(t)\
  14330. \
  14331.    else\
  14332.        error( \"Cannot serialize type \"..sType, 0 )\
  14333. \
  14334.    end\
  14335. end\
  14336. \
  14337. function serialize( t )\
  14338.    local tTracking = {}\
  14339.    return serializeImpl( t, tTracking, \"\" )\
  14340. end\
  14341. \
  14342. function unserialize( s )\
  14343.    local func = loadstring( \"return \"..s, \"unserialize\" )\
  14344.    if func then\
  14345.        setfenv( func, {} )\
  14346.        local ok, result = pcall( func )\
  14347.        if ok then\
  14348.            return result\
  14349.        end\
  14350.    end\
  14351.    return nil\
  14352. end\
  14353. \
  14354. function serializeJSON( t )\
  14355.    local tTracking = {}\
  14356.    return serializeJSONImpl( t, tTracking )\
  14357. end\
  14358. \
  14359. function urlEncode( str )\
  14360.    if str then\
  14361.        str = string.gsub(str, \"\\n\", \"\\r\\n\")\
  14362.        str = string.gsub(str, \"([^%w ])\", function(c)\
  14363.            return string.format(\"%%%02X\", string.byte(c))\
  14364.        end )\
  14365.        str = string.gsub(str, \" \", \"+\")\
  14366.    end\
  14367.    return str    \
  14368. end\
  14369. \
  14370. -- GB versions\
  14371. serialise = serialize\
  14372. unserialise = unserialize\
  14373. serialiseJSON = serializeJSON",
  14374.     [ "OmniWindow.lua" ] = "--[[\
  14375.  Author: dan200\
  14376.  Modified by: Creator\
  14377. ]]--\
  14378. function create( parent, nX, nY, nWidth, nHeight, bStartVisible )\
  14379. \
  14380.     if type( parent ) ~= \"table\" or\
  14381.        type( nX ) ~= \"number\" or\
  14382.        type( nY ) ~= \"number\" or\
  14383.        type( nWidth ) ~= \"number\" or\
  14384.        type( nHeight ) ~= \"number\" or\
  14385.        (bStartVisible ~= nil and type( bStartVisible ) ~= \"boolean\") then\
  14386.         error( \"Expected object, number, number, number, number, [boolean]\", 2 )\
  14387.     end\
  14388. \
  14389.     if parent == term then\
  14390.         error( \"term is not a recommended window parent, try term.current() instead\", 2 )\
  14391.     end\
  14392. \
  14393.     local bVisible = (bStartVisible ~= false)\
  14394.     local nCursorX = 1\
  14395.     local nCursorY = 1\
  14396.     local bCursorBlink = false\
  14397.     local nTextColor = colors.white\
  14398.     local nBackgroundColor = colors.black\
  14399.     local sEmpty = string.rep( \" \", nWidth )\
  14400.     local tLines = {}\
  14401.     do\
  14402.         local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  14403.         for y=1,nHeight do\
  14404.             tLines[y] = tEmpty\
  14405.         end\
  14406.     end\
  14407. \
  14408.     local function updateCursorPos()\
  14409.         if nCursorX >= 1 and nCursorY >= 1 and\
  14410.            nCursorX <= nWidth and nCursorY <= nHeight then\
  14411.             parent.setCursorPos( nX + nCursorX - 1, nY + nCursorY - 1 )\
  14412.         else\
  14413.             parent.setCursorPos( 0, 0 )\
  14414.         end\
  14415.     end\
  14416. \
  14417.     local function updateCursorBlink()\
  14418.         parent.setCursorBlink( bCursorBlink )\
  14419.     end\
  14420. \
  14421.     local function updateCursorColor()\
  14422.         parent.setTextColor( nTextColor )\
  14423.     end\
  14424. \
  14425.     local function redrawLine( n )\
  14426.         parent.setCursorPos( nX, nY + n - 1 )\
  14427.         local tLine = tLines[ n ]\
  14428.         for m=1,#tLine do\
  14429.             local tBit = tLine[ m ]\
  14430.             parent.setTextColor( tBit[2] )\
  14431.             parent.setBackgroundColor( tBit[3] )\
  14432.             parent.write( tBit[1] )\
  14433.         end\
  14434.     end\
  14435. \
  14436.     local function lineLen( tLine )\
  14437.         local nLength = 0\
  14438.         for n=1,#tLine do\
  14439.             nLength = nLength + string.len( tLine[n][1] )\
  14440.         end\
  14441.         return nLength\
  14442.     end\
  14443. \
  14444.     local function lineSub( tLine, nStart, nEnd )\
  14445.         local tSubLine = {}\
  14446.         local nBitStart = 1\
  14447.         for n=1,#tLine do\
  14448.             local tBit = tLine[n]\
  14449.             local sBit = tBit[1]\
  14450.             local nBitEnd = nBitStart + string.len( sBit ) - 1\
  14451.             if nBitEnd >= nStart and nBitStart <= nEnd then\
  14452.                 if nBitStart >= nStart and nBitEnd <= nEnd then\
  14453.                     table.insert( tSubLine, tBit )\
  14454.                 elseif nBitStart < nStart and nBitEnd <= nEnd then\
  14455.                     table.insert( tSubLine, {\
  14456.                         string.sub( sBit, nStart - nBitStart + 1 ),\
  14457.                         tBit[2], tBit[3]\
  14458.                     } )\
  14459.                 elseif nBitStart >= nStart and nBitEnd > nEnd then\
  14460.                     -- Include beginning of bit\
  14461.                     table.insert( tSubLine, {\
  14462.                         string.sub( sBit, 1, nEnd - nBitStart + 1 ),\
  14463.                         tBit[2], tBit[3]\
  14464.                     } )\
  14465.                 else\
  14466.                     table.insert( tSubLine, {\
  14467.                         string.sub( sBit, nStart - nBitStart + 1, nEnd - nBitStart + 1 ),\
  14468.                         tBit[2], tBit[3]\
  14469.                     } )\
  14470.                 end\
  14471.             end\
  14472.             nBitStart = nBitEnd + 1\
  14473.         end\
  14474.         return tSubLine\
  14475.     end\
  14476. \
  14477.     local function lineJoin( tLine1, tLine2 )\
  14478.         local tNewLine = {}\
  14479.         if tLine1[#tLine1][2] == tLine2[1][2] and\
  14480.            tLine1[#tLine1][3] == tLine2[1][3] then\
  14481.             for n=1,#tLine1-1 do\
  14482.                 table.insert( tNewLine, tLine1[n] )\
  14483.             end\
  14484.             table.insert( tNewLine, {\
  14485.                 tLine1[#tLine1][1] .. tLine2[1][1],\
  14486.                 tLine2[1][2], tLine2[1][3]\
  14487.             } )\
  14488.             for n=2,#tLine2 do\
  14489.                 table.insert( tNewLine, tLine2[n] )\
  14490.             end\
  14491.         else\
  14492.             for n=1,#tLine1 do\
  14493.                 table.insert( tNewLine, tLine1[n] )\
  14494.             end\
  14495.             for n=1,#tLine2 do\
  14496.                 table.insert( tNewLine, tLine2[n] )\
  14497.             end\
  14498.         end\
  14499.         return tNewLine\
  14500.     end\
  14501. \
  14502.     local function redraw()\
  14503.         for n=1,nHeight do\
  14504.             redrawLine( n )\
  14505.         end\
  14506.     end\
  14507. \
  14508.     local window = {}\
  14509. \
  14510.     -- Terminal implementation\
  14511.     function window.write( sText )\
  14512.         local nLen = string.len( sText )\
  14513.         local nStart = nCursorX\
  14514.         local nEnd = nStart + nLen - 1\
  14515.         if nCursorY >= 1 and nCursorY <= nHeight then\
  14516.             if nStart <= nWidth and nEnd >= 1 then\
  14517.                 -- Construct new line\
  14518.                 local tLine = tLines[ nCursorY ]\
  14519.                 if nStart == 1 and nEnd == nWidth then\
  14520.                     tLine = {\
  14521.                         { sText, nTextColor, nBackgroundColor }\
  14522.                     }\
  14523.                 elseif nStart <= 1 and nEnd >= nWidth then\
  14524.                     -- Overwrite line with subset\
  14525.                     tLine = {\
  14526.                         { string.sub( sText, 1 - nStart + 1, nWidth - nStart + 1 ), nTextColor, nBackgroundColor }\
  14527.                     }\
  14528.                     --assert( lineLen( tLine ) == nWidth )\
  14529.                 elseif nStart <= 1 then\
  14530.                     -- Overwrite beginning of line\
  14531.                     tLine = lineJoin(\
  14532.                         { { string.sub( sText, 1 - nStart + 1 ), nTextColor, nBackgroundColor } },\
  14533.                         lineSub( tLine, nEnd + 1, nWidth )\
  14534.                     )\
  14535.                     --assert( lineLen( tLine ) == nWidth )\
  14536.                 elseif nEnd >= nWidth then\
  14537.                     -- Overwrite end of line\
  14538.                     tLine = lineJoin(\
  14539.                         lineSub( tLine, 1, nStart - 1 ),\
  14540.                         { { string.sub( sText, 1, nWidth - nStart + 1 ), nTextColor, nBackgroundColor } }\
  14541.                     )\
  14542.                     --assert( lineLen( tLine ) == nWidth )\
  14543.                 else\
  14544.                     -- Overwrite middle of line\
  14545.                     tLine = lineJoin(\
  14546.                         lineJoin(\
  14547.                             lineSub( tLine, 1, nStart - 1 ),\
  14548.                             { { sText, nTextColor, nBackgroundColor } }\
  14549.                         ),\
  14550.                         lineSub( tLine, nEnd + 1, nWidth )\
  14551.                     )\
  14552.                     --assert( lineLen( tLine ) == nWidth )\
  14553.                 end\
  14554. \
  14555.                 -- Store and redraw new line\
  14556.                 tLines[ nCursorY ] = tLine\
  14557.                 if bVisible then\
  14558.                     redrawLine( nCursorY )\
  14559.                 end\
  14560.             end\
  14561.         end\
  14562. \
  14563.         -- Move and redraw cursor\
  14564.         nCursorX = nEnd + 1\
  14565.         if bVisible then\
  14566.             updateCursorColor()\
  14567.             updateCursorPos()\
  14568.         end\
  14569.     end\
  14570. \
  14571.     function window.clear()\
  14572.         local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  14573.         for y=1,nHeight do\
  14574.             tLines[y] = tEmpty\
  14575.         end\
  14576.         if bVisible then\
  14577.             redraw()\
  14578.             updateCursorColor()\
  14579.             updateCursorPos()\
  14580.         end\
  14581.     end\
  14582. \
  14583.     function window.clearLine()\
  14584.         if nCursorY >= 1 and nCursorY <= nHeight then\
  14585.             tLines[ nCursorY ] = { { sEmpty, nTextColor, nBackgroundColor } }\
  14586.             if bVisible then\
  14587.                 redrawLine( nCursorY )\
  14588.                 updateCursorColor()\
  14589.                 updateCursorPos()\
  14590.             end\
  14591.         end\
  14592.     end\
  14593. \
  14594.     function window.getCursorPos()\
  14595.         return nCursorX, nCursorY\
  14596.     end\
  14597. \
  14598.     function window.setCursorPos( x, y )\
  14599.         nCursorX = math.floor( x )\
  14600.         nCursorY = math.floor( y )\
  14601.         if bVisible then\
  14602.             updateCursorPos()\
  14603.         end\
  14604.     end\
  14605. \
  14606.     function window.setCursorBlink( blink )\
  14607.         bCursorBlink = blink\
  14608.         if bVisible then\
  14609.             updateCursorBlink()\
  14610.         end\
  14611.     end\
  14612. \
  14613.     function window.isColor()\
  14614.         return parent.isColor()\
  14615.     end\
  14616. \
  14617.     function window.isColour()\
  14618.         return parent.isColor()\
  14619.     end\
  14620. \
  14621.     local function setTextColor( color )\
  14622.         if not parent.isColor() then\
  14623.             if color ~= colors.white and color ~= colors.black then\
  14624.                 error( \"Colour not supported\", 3 )\
  14625.             end\
  14626.         end\
  14627.         nTextColor = color\
  14628.         if bVisible then\
  14629.             updateCursorColor()\
  14630.         end\
  14631.     end\
  14632. \
  14633.     function window.setTextColor( color )\
  14634.         setTextColor( color )\
  14635.     end\
  14636. \
  14637.     function window.setTextColour( color )\
  14638.         setTextColor( color )\
  14639.     end\
  14640. \
  14641.     local function setBackgroundColor( color )\
  14642.         if not parent.isColor() then\
  14643.             if color ~= colors.white and color ~= colors.black then\
  14644.                 error( \"Colour not supported\", 3 )\
  14645.             end\
  14646.         end\
  14647.         nBackgroundColor = color\
  14648.     end\
  14649. \
  14650.     function window.setBackgroundColor( color )\
  14651.         setBackgroundColor( color )\
  14652.     end\
  14653. \
  14654.     function window.setBackgroundColour( color )\
  14655.         setBackgroundColor( color )\
  14656.     end\
  14657. \
  14658.     function window.getSize()\
  14659.         return nWidth, nHeight\
  14660.     end\
  14661. \
  14662.     function window.scroll( n )\
  14663.         if n ~= 0 then\
  14664.             local tNewLines = {}\
  14665.             local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  14666.             for newY=1,nHeight do\
  14667.                 local y = newY + n\
  14668.                 if y >= 1 and y <= nHeight then\
  14669.                     tNewLines[newY] = tLines[y]\
  14670.                 else\
  14671.                     tNewLines[newY] = tEmpty\
  14672.                 end\
  14673.             end\
  14674.             tLines = tNewLines\
  14675.             if bVisible then\
  14676.                 redraw()\
  14677.                 updateCursorColor()\
  14678.                 updateCursorPos()\
  14679.             end\
  14680.         end\
  14681.     end\
  14682. \
  14683.     -- Other functions\
  14684.     function window.setVisible( bVis )\
  14685.         bVisible = bVis\
  14686.     end\
  14687. \
  14688.     function window.redraw()\
  14689.         if bVisible then\
  14690.             redraw()\
  14691.             updateCursorBlink()\
  14692.             updateCursorColor()\
  14693.             updateCursorPos()\
  14694.         end\
  14695.     end\
  14696. \
  14697.     function window.restoreCursor()\
  14698.         if bVisible then\
  14699.             updateCursorBlink()\
  14700.             updateCursorColor()\
  14701.             updateCursorPos()\
  14702.         end\
  14703.     end\
  14704. \
  14705.     function window.getPosition()\
  14706.         return nX, nY\
  14707.     end\
  14708. \
  14709.     function window.reposition( nNewX, nNewY, nNewWidth, nNewHeight )\
  14710.         nX = nNewX\
  14711.         nY = nNewY\
  14712.         if nNewWidth and nNewHeight then\
  14713.             sEmpty = string.rep( \" \", nNewWidth )\
  14714.             local tNewLines = {}\
  14715.             local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  14716.             for y=1,nNewHeight do\
  14717.                 if y > nHeight then\
  14718.                     tNewLines[y] = tEmpty\
  14719.                 else\
  14720.                     if nNewWidth == nWidth then\
  14721.                         tNewLines[y] = tLines[y]\
  14722.                     elseif nNewWidth < nWidth then\
  14723.                         tNewLines[y] = lineSub( tLines[y], 1, nNewWidth )\
  14724.                     else\
  14725.                         tNewLines[y] = lineJoin( tLines[y], { { string.sub( sEmpty, nWidth + 1, nNewWidth ), nTextColor, nBackgroundColor } } )\
  14726.                     end\
  14727.                 end\
  14728.             end\
  14729.             nWidth = nNewWidth\
  14730.             nHeight = nNewHeight\
  14731.             tLines = tNewLines\
  14732.         end\
  14733.         if bVisible then\
  14734.             window.redraw()\
  14735.         end\
  14736.     end\
  14737. \
  14738.     function window.getBuffer()\
  14739.         return tLines\
  14740.     end\
  14741. \
  14742.     function window.setBuffer(tNewBuffer)\
  14743.         tLines = tNewBuffer\
  14744.     end\
  14745. \
  14746.     if bVisible then\
  14747.         window.redraw()\
  14748.     end\
  14749.     return window\
  14750. end",
  14751.     [ "Sandbox.lua" ] = "--[[\
  14752.     Sandbox \
  14753.     environment\
  14754.     by Creator\
  14755.     for TheOS\
  14756. ]]--\
  14757. \
  14758. --Variables--\
  14759. local oldGetfenv = getfenv\
  14760. local oldLoadfile = loadfile\
  14761. local globalName = \"\"\
  14762. \
  14763. \
  14764. --Functions--\
  14765. \
  14766. local function tableCopy(tbl)\
  14767.     if type(tbl) == \"table\" then\
  14768.         local buffer = {}\
  14769.         for i,v in pairs(tbl) do\
  14770.             if type(v) == \"table\" then\
  14771.                 buffer[i] = tableCopy(v)\
  14772.             else\
  14773.                 buffer[i] = v\
  14774.             end\
  14775.         end\
  14776.         return buffer\
  14777.     else\
  14778.         error(\"Table expected\",2)\
  14779.         sleep(3)\
  14780.     end\
  14781. end\
  14782. \
  14783. function newEnv(name)\
  14784.     globalName = name\
  14785.     toReturn = {\
  14786.         redstone = tableCopy(redstone),\
  14787.         gps = tableCopy(gps),\
  14788.         _VERSION = _VERSION,\
  14789.         keys = tableCopy(keys),\
  14790.         printError = printError,\
  14791.         peripheral = tableCopy(peripheral),\
  14792.         assert = assert,\
  14793.         getfenv = function(env) if env == nil then env = toReturn elseif getfenv( env ) == \"number\" and env > 0 then  env = env + 1 end local fenv = getfenv(env) return fenv end,\
  14794.         bit = tableCopy(bit),\
  14795.         rawset = rawset,\
  14796.         tonumber = tonumber,\
  14797.         loadstring = function(str) local func = loadstring(str) setfenv(func,getfenv(1))end,\
  14798.         error = error,\
  14799.         tostring = tostring,\
  14800.         type = type,\
  14801.         coroutine = { \
  14802.             create = coroutine.create,\
  14803.             resume = coroutine.resume,\
  14804.             running = coroutine.running,\
  14805.             status = coroutine.status,\
  14806.             wrap = coroutine.wrap,\
  14807.         },\
  14808.         disk = tableCopy(disk),\
  14809.         window = tableCopy(window),\
  14810.         next = next,\
  14811.         unpack = unpack,\
  14812.         colours = colours,\
  14813.         pcall = pcall,\
  14814.         sleep = sleep,\
  14815.         loadfile = function(path) return setfenv(loadfile(\"OmniOS/Programs/\"..globalName..\".app/\"..path),toReturn) end,\
  14816.         math = math,\
  14817.         pairs = pairs,\
  14818.         fs = {\
  14819.             combine = fs.combine,\
  14820.             isReadOnly = function(path) log.log(\"SandboxPath\",\"OmniOS/Programs/\"..globalName..\".app/\"..path) return fs.isReadOnly(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  14821.             getSize = function(path) return fs.getSize(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  14822.             move = function(path1,path2) return fs.move(\"OmniOS/Programs/\"..globalName..\".app/\"..path1,\"OmniOS/Programs/\"..globalName..\".app/\"..path2) end,\
  14823.             exists = function(path) return fs.exists(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  14824.             copy = function(path1,path2) return fs.copy(\"OmniOS/Programs/\"..globalName..\".app/\"..path1,\"OmniOS/Programs/\"..globalName..\".app/\"..path2) end,\
  14825.             getFreeSpace = function(path) return fs.getFreeSpace(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  14826.             makeDir = function(path) return fs.makeDir(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  14827.             find = function(path) return fs.find(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  14828.             getDir = fs.getDir,\
  14829.             delete = function(path) return fs.delete(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  14830.             open = function(path,...) return fs.open(\"OmniOS/Programs/\"..globalName..\".app/\"..path,...) end,\
  14831.             list = function(path) log.log(\"SandboxPath\",\"OmniOS/Programs/\"..globalName..\".app/\"..path) return fs.list(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  14832.             getDrive = function(path) return fs.getDrive(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  14833.             getName = fs.getName,\
  14834.             isDir = function(path) return fs.isDir(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  14835.         },\
  14836.         rawget = rawget,\
  14837.         _G = envToReturn,\
  14838.         __inext = __inext,\
  14839.         read = read,\
  14840.         rednet = rednet,\
  14841.         ipairs = ipairs,\
  14842.         xpcall = xpcall,\
  14843.         os = os,\
  14844.         help = help,\
  14845.         io = io,\
  14846.         rawequal = rawequal,\
  14847.         setfenv = setfenv,\
  14848.         rs = rs,\
  14849.         http = http,\
  14850.         write = write,\
  14851.         string = string,\
  14852.         setmetatable = setmetatable,\
  14853.         print = print,\
  14854.         getmetatable = getmetatable,\
  14855.         table = table,\
  14856.         parallel = parallel,\
  14857.         dofile = function(path) dofile(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  14858.         textutils = textutils,\
  14859.         term = term,\
  14860.         colors = colors,\
  14861.         vector = vectors,\
  14862.         select = select,\
  14863.         paintutils = paintutils,\
  14864.         System = System,\
  14865.         OmniOS = OmniOS,\
  14866.         log = log,\
  14867.     }\
  14868.     setfenv(toReturn.loadfile,toReturn)\
  14869.     setfenv(toReturn.dofile,toReturn)\
  14870.     setfenv(toReturn.loadstring,toReturn)\
  14871.     for i,v in pairs(toReturn.io) do\
  14872.         setfenv(v,toReturn)\
  14873.     end\
  14874.     return toReturn\
  14875. end",
  14876.     [ "log.lua" ] = "--[[\
  14877.     Log API\
  14878.     by Creator\
  14879.     for TheOS\
  14880. ]]--\
  14881. \
  14882. --[[function log(destination,message,app)\
  14883.     local finalMsg = \"[\"..os.day()..\":\"..os.time()..\"]\"\
  14884.     if app then\
  14885.         finalMsg = finalMsg..\".[\"..tostring(app)..\"]:\"..tostring(message)\
  14886.     else\
  14887.         finalMsg = finalMsg..\":\"..tostring(message)\
  14888.     end\
  14889.     local m = oldOpen(\"OmniOS/Logs/\"..destination..\".log\",\"a\")\
  14890.     m.write(finalMsg..\"\\n\")\
  14891.     m.close()\
  14892. end]]--\
  14893. \
  14894. log = Utils.log",
  14895.     [ "OmniOS.lua" ] = "version = \"alpha\"\
  14896. tag = \"15w16a\"\
  14897. function launch(program,parent,...)\
  14898.     program = program:gsub(\"%.%.\",\"\"):gsub(\"/\",\"\")\
  14899.     if fs.exists(\"OmniOS/Programs/\"..program..\"/Main.lua\") and not fs.isDir(\"OmniOS/Programs/\"..program..\"/Main.lua\") then\
  14900.         local func, err = loadfile(\"OmniOS/Programs/\"..program..\"/Main.lua\")\
  14901.         if not func then Utils.log(\"Launch\",err,program) return end\
  14902.         setfenv(func,_G)\
  14903.         Kernel.newProcess(func,parent,\"user\",program,...)\
  14904.     end\
  14905. end\
  14906. function message(thread,...)\
  14907.  Kernel.addMessage(thread,Kernel.getRunning(),...)\
  14908. end",
  14909.     [ "gui.lua" ] = "--[[\
  14910.     GUI API in ComputerCraft\
  14911.     by Creator\
  14912.     Complete rewrite in OOP\
  14913. ]]--\
  14914. \
  14915. --Button Class--\
  14916. \
  14917. Button = {}\
  14918. \
  14919. newButton = function(_name,_label,_xPos,_yPos,_xLength,_yLength,_fgColor,_bgColor,_returnValue)\
  14920.     local self = {}\
  14921.     setmetatable(self,{__index = Button})\
  14922.     self.name = _name\
  14923.     self.label = _label\
  14924.     self.xPos = _xPos\
  14925.     self.yPos = _yPos\
  14926.     self.fgColor = _fgColor\
  14927.     self.bgColor = _bgColor\
  14928.     self.xLength = _xLength\
  14929.     self.yLength = _yLength\
  14930.     self.returnValue = _returnValue\
  14931.     return self\
  14932. end\
  14933. \
  14934. Button.draw = function(self)\
  14935.     --term.setBackgroundColor(self.bgColor)\
  14936.     paintutils.drawFilledBox(self.xPos,self.yPos,self.xLength-1,self.yLength-1,self.bgColor)\
  14937.     \
  14938. end\
  14939. \
  14940. --Variables--\
  14941. --Functions--\
  14942. \
  14943. function addKey(key,returnValue)\
  14944.     keysMain[#keysMain+1] = {key,returnValue}\
  14945. end\
  14946. \
  14947. function resetKeys()\
  14948.     keysMain = {}\
  14949. end\
  14950. \
  14951. local function localAddField(minX,minY,maxX,maxY,returnV)\
  14952.     buttonsMain[#buttonsMain+1] = {minX,minY,minX+maxX-1,minY+maxY-1,returnV}\
  14953. end\
  14954. \
  14955. function addField(minX,minY,maxX,maxY,returnV)\
  14956.     if not pcall(localAddField,minX,minY,maxX,maxY,returnV) then\
  14957.         print([[\
  14958.         Usage:\
  14959.         As an argument pass a table structured like this:\
  14960.         {\
  14961.             xPos,\
  14962.             yPos,\
  14963.             wide,\
  14964.             height,\
  14965.             returnValue,\
  14966.         }\
  14967.         ]])\
  14968.     end\
  14969. end\
  14970. \
  14971. local function localDrawButton(xPos,yPos,wide,height,colorOfButton,inButtonXPosOfLabel,inButtonYPosOfLabel,label,textColor,returnValue)\
  14972.     if colorOfButton ~= nil then\
  14973.         paintutils.drawFilledBox(xPos,yPos,xPos+wide-1,yPos+height-1,colorOfButton)\
  14974.     end\
  14975.     term.setTextColor(textColor)\
  14976.     term.setCursorPos(xPos+inButtonXPosOfLabel-1,yPos+inButtonYPosOfLabel-1)\
  14977.     local textToPrint = string.sub(label,1,xPos+wide-inButtonXPosOfLabel)\
  14978.     term.write(textToPrint)\
  14979.     buttonsMain[#buttonsMain+1] = {xPos,yPos,xPos+wide-1,yPos+height-1,returnValue}\
  14980. end\
  14981. \
  14982. function drawButton(xPos,yPos,wide,height,colorOfButton,inButtonXPosOfLabel,inButtonYPosOfLabel,label,textColor,returnValue)\
  14983.     if not pcall(localDrawButton,xPos,yPos,wide,height,colorOfButton,inButtonXPosOfLabel,inButtonYPosOfLabel,label,textColor,returnValue) then\
  14984.         print([[\
  14985.         Usage:\
  14986.         As an argument pass a table structured like this:\
  14987.         {\
  14988.             xPos,\
  14989.             yPos,\
  14990.             wide,\
  14991.             height,\
  14992.             colorOfButton,\
  14993.             inButtonXPosOfLabel,\
  14994.             inButtonYPosOfLabel,\
  14995.             label,\
  14996.             textColor,\
  14997.             returnValue,\
  14998.         }\
  14999.         You can have the option to not use the background color.\
  15000.         You can do this by simply setting color of button to nil.\
  15001.         ]])\
  15002.     end\
  15003. end\
  15004. \
  15005. function detectButtonOrKeyHit()\
  15006.     while true do\
  15007.         local event, button, x, y\
  15008.         repeat\
  15009.             event, button, x, y = os.pullEvent()\
  15010.         until (event == \"mouse_click\" and buttonsMain ~= nil) or (event == \"key\" and keysMain ~= nil)\
  15011.         if event == \"mouse_click\" then\
  15012.             for i,v in pairs(buttonsMain) do\
  15013.                 if v[1] <= x and x <= v[3] and v[2] <= y and y <= v[4] then\
  15014.                     return {v[5], button, x, y}\
  15015.                 end\
  15016.             end\
  15017.         elseif event == \"key\" then\
  15018.             for i,v in pairs(keysMain) do\
  15019.                 if button == v[1] then\
  15020.                     return {v[2]}\
  15021.                 end\
  15022.             end\
  15023.         end\
  15024.     end\
  15025. end\
  15026. \
  15027. function resetButtons()\
  15028.     buttonsMain = {}\
  15029. end\
  15030. \
  15031. local function localCPrint(txt,color,bgColor,xPos,yPos,maxL)\
  15032.     if not maxL == nil then\
  15033.         txt = string.sub(txt,1,maxL)\
  15034.     end\
  15035.     term.setTextColor(color)\
  15036.     if bgColor ~= nil then\
  15037.         term.setBackgroundColor(bgColor)\
  15038.     end\
  15039.     term.setCursorPos(xPos,yPos)\
  15040.     term.write(txt)\
  15041. end\
  15042. \
  15043. function cPrint(txt,color,bgColor,xPos,yPos,maxL)\
  15044.     if not pcall(localCPrint,txt,color,bgColor,xPos,yPos,maxL) then\
  15045.         print([[\
  15046.             Usage:\
  15047.             Arguments are as follws:\
  15048.             {\
  15049.             Text to print\
  15050.             Text color\
  15051.             Background color\
  15052.             xPos\
  15053.             yPos\
  15054.             Maximal lenght of the string\
  15055.             }\
  15056.             Maximal lenght of the string can be left \"nil\" with qoutes\
  15057.         ]])\
  15058.     end\
  15059. end",
  15060.     Interact = {
  15061.       [ "Interact.lua" ] = "--[[\
  15062.     Interact API in ComputerCraft\
  15063.     by Creator\
  15064.     Complete rewrite in OOP\
  15065. ]]--\
  15066. \
  15067. --Variables\
  15068. local textutilsserialize = textutils.serialize\
  15069. local textutilsunserialize = textutils.unserialize\
  15070. local KeyCodes = {\
  15071.     [ 2 ] =  1 ,\
  15072.     [ 3 ] =  2,\
  15073.     [ 4 ] =  3,\
  15074.     [ 5 ] =  4,\
  15075.     [ 6 ] =  5,\
  15076.     [ 7 ] =  6,\
  15077.     [ 8 ] =  7,\
  15078.     [ 9 ] =  8,\
  15079.     [ 10 ] =  9,\
  15080.     [ 11 ] =  0,\
  15081.     [ 12 ] = \"-\",\
  15082.     [ 13 ] = \"=\",\
  15083.     [ 14 ] = \"Backspace\",\
  15084.     [ 15 ] = \"Tab\",\
  15085.     [ 16 ] = \"q\",\
  15086.     [ 17 ] = \"w\",\
  15087.     [ 18 ] = \"e\",\
  15088.     [ 19 ] = \"r\",\
  15089.     [ 20 ] = \"t\",\
  15090.     [ 21 ] = \"y\",\
  15091.     [ 22 ] = \"u\",\
  15092.     [ 23 ] = \"i\",\
  15093.     [ 24 ] = \"o\",\
  15094.     [ 25 ] = \"p\",\
  15095.     [ 26 ] = \"LeftBracket\",\
  15096.     [ 27 ] = \"RightBracket\",\
  15097.     [ 28 ] = \"Enter\",\
  15098.     [ 29 ] = \"LeftControl\",\
  15099.     [ 30 ] = \"a\",\
  15100.     [ 31 ] = \"s\",\
  15101.     [ 32 ] = \"d\",\
  15102.     [ 33 ] = \"f\",\
  15103.     [ 34 ] = \"g\",\
  15104.     [ 35 ] = \"h\",\
  15105.     [ 36 ] = \"j\",\
  15106.     [ 37 ] = \"k\",\
  15107.     [ 38 ] = \"l\",\
  15108.     [ 39 ] = \";\",\
  15109.     [ 40 ] = \"\\'\",\
  15110.     [ 41 ] = \"`\",\
  15111.     [ 42 ] = \"LeftShift\",\
  15112.     [ 43 ] = \"Backslash\",\
  15113.     [ 44 ] = \"z\",\
  15114.     [ 45 ] = \"x\",\
  15115.     [ 46 ] = \"c\",\
  15116.     [ 47 ] = \"v\",\
  15117.     [ 48 ] = \"b\",\
  15118.     [ 49 ] = \"n\",\
  15119.     [ 50 ] = \"m\",\
  15120.     [ 51 ] = \",\",\
  15121.     [ 52 ] = \".\",\
  15122.     [ 53 ] = \"/\",\
  15123.     [ 54 ] = \"RightShift\",\
  15124.     [ 55 ] = \"*\",\
  15125.     [ 56 ] = \"LeftAlt\",\
  15126.     [ 57 ] = \" \",\
  15127.     [ 58 ] = \"CapsLock\",\
  15128.     [ 59 ] = \"F1\",\
  15129.     [ 60 ] = \"F2\",\
  15130.     [ 61 ] = \"F3\",\
  15131.     [ 62 ] = \"F4\",\
  15132.     [ 63 ] = \"F5\",\
  15133.     [ 64 ] = \"F6\",\
  15134.     [ 65 ] = \"F7\",\
  15135.     [ 66 ] = \"F8\",\
  15136.     [ 67 ] = \"F9\",\
  15137.     [ 68 ] = \"F10\",\
  15138.     [ 69 ] = \"NumberLock\",\
  15139.     [ 70 ] = \"ScrollLock\",\
  15140.     [ 71 ] = \"NumPAd7\",\
  15141.     [ 72 ] = \"NumPAd8\",\
  15142.     [ 73 ] = \"NumPAd9\",\
  15143.     [ 74 ] = \"Substract\",\
  15144.     [ 75 ] = \"NumPAd4\",\
  15145.     [ 76 ] = \"NumPAd5\",\
  15146.     [ 77 ] = \"NumPAd6\",\
  15147.     [ 78 ] = \"Add\",\
  15148.     [ 79 ] = \"NumPAd1\",\
  15149.     [ 80 ] = \"NumPAd2\",\
  15150.     [ 81 ] = \"NumPAd3\",\
  15151.     [ 82 ] = \"NumPAd0\",\
  15152.     [ 83 ] = \"Decimal\",\
  15153.     [ 87 ] = \"F11\",\
  15154.     [ 88 ] = \"F12\",\
  15155.     [ 100] = \"F13\",\
  15156.     [ 101] = \"F14\",\
  15157.     [ 102] = \"F15\",\
  15158.     [ 103] = \"F16\",\
  15159.     [ 104] = \"F17\",\
  15160.     [ 105] = \"F18\",\
  15161.     [ 112] = \"Kana\",\
  15162.     [ 113] = \"F19\",\
  15163.     [ 121] = \"Convert\",\
  15164.     [ 123] = \"Noconvert\",\
  15165.     [ 125] = \"Yen\",\
  15166.     [ 141] = \"NumPadEquals\",\
  15167.     [ 144] = \"^\",\
  15168.     [ 145] = \"@\",\
  15169.     [ 146] = \":\",\
  15170.     [ 147] = \"_\",\
  15171.     [ 148] = \"Kanji\",\
  15172.     [ 149] = \"Stop\",\
  15173.     [ 150] = \"Ax\",\
  15174.     [ 151] = \"Unlabeled\",\
  15175.     [ 156] = \"NumPadEnter\",\
  15176.     [ 157] = \"RightControl\",\
  15177.     [ 157] = \"Section\",\
  15178.     [ 179] = \"NumPadComma\",\
  15179.     [ 181] = \"Dvide\",\
  15180.     [ 183] = \"Sysrq\",\
  15181.     [ 184] = \"RightAlt\",\
  15182.     [ 196] = \"Function\",\
  15183.     [ 197] = \"Pause\",\
  15184.     [ 199] = \"Home\",\
  15185.     [ 200] = \"Up\",\
  15186.     [ 201] = \"PageUp\",\
  15187.     [ 203] = \"Left\",\
  15188.     [ 205] = \"Right\",\
  15189.     [ 207] = \"End\",\
  15190.     [ 208] = \"Down\",\
  15191.     [ 209] = \"PageDown\",\
  15192.     [ 210] = \"Insert\",\
  15193.     [ 211] = \"Delete\",\
  15194. }\
  15195. \
  15196. --Class declarations--\
  15197. local Button = {}\
  15198. local Layout = {}\
  15199. local Toggle = {}\
  15200. local BackgroundColor = {}\
  15201. local ColorField = {}\
  15202. local BetterPaint = {}\
  15203. local Text = {}\
  15204. local TextBox = {}\
  15205. local Key = {}\
  15206. \
  15207. function loadObjects(self)\
  15208.     local output = {}\
  15209.     output.Button = {}\
  15210.     output.Toggle = {}\
  15211.     output.ColorField = {}\
  15212.     output.BetterPaint = {}\
  15213.     output.Text = {}\
  15214.     output.TextBox = {}\
  15215.     output.Key = {}\
  15216.     output.Layout = {}\
  15217.     for o,v in pairs(output) do\
  15218.         if self[o] == nil then\
  15219.             self[o] = {}\
  15220.         end\
  15221.     end\
  15222.     for i,v in pairs(self.Button) do\
  15223.         output.Button[i] = Button.new(self.Button[i])\
  15224.     end\
  15225.     for i,v in pairs(self.Toggle) do\
  15226.         output.Toggle[i] = Toggle.new(self.Toggle[i])\
  15227.     end\
  15228.     for i,v in pairs(self.ColorField) do\
  15229.         output.ColorField[i] = ColorField.new(self.ColorField[i])\
  15230.     end\
  15231.     for i,v in pairs(self.BetterPaint) do\
  15232.         output.BetterPaint[i] = BetterPaint.new(self.BetterPaint[i])\
  15233.     end\
  15234.     for i,v in pairs(self.Text) do\
  15235.         output.Text[i] = Text.new(self.Text[i])\
  15236.     end\
  15237.     for i,v in pairs(self.TextBox) do\
  15238.         output.TextBox[i] = TextBox.new(self.TextBox[i])\
  15239.     end\
  15240.     for i,v in pairs(self.Key) do\
  15241.         output.Key[i] = Key.new(self.Key[i])\
  15242.     end\
  15243.     for i,v in pairs(self.Layout) do\
  15244.         output.Layout[i] = Layout.new(self.Layout[i])\
  15245.     end\
  15246.     output.BackgroundColor = self.BackgroundColor or 1\
  15247.     output.nilClick = self.nilClick or false\
  15248.     return output\
  15249. end\
  15250. \
  15251. function loadLayout(input,output)\
  15252.     for i,v in pairs(input.Button) do\
  15253.         output:addButton(input.Button[i])\
  15254.     end\
  15255.     for i,v in pairs(input.Toggle) do\
  15256.         output:addToggle(input.Toggle[i])\
  15257.     end\
  15258.     for i,v in pairs(input.ColorField) do\
  15259.         output:addColorField(input.ColorField[i])\
  15260.     end\
  15261.     for i,v in pairs(input.BetterPaint) do\
  15262.         output:addBetterPaint(input.BetterPaint[i])\
  15263.     end\
  15264.     for i,v in pairs(input.Text) do\
  15265.         output:addText(input.Text[i])\
  15266.     end\
  15267.     for i,v in pairs(input.TextBox) do\
  15268.         output:addTextBox(input.TextBox[i])\
  15269.     end\
  15270.     for i,v in pairs(input.Key) do\
  15271.         output:addKey(input.Key[i])\
  15272.     end\
  15273.     for i,v in pairs(input.Layout) do\
  15274.         output:addLayout(input.Layout[i])\
  15275.     end\
  15276.     output.BackgroundColor = input.BackgroundColor\
  15277.     output.nilClick = input.nilClick\
  15278. end\
  15279. \
  15280. --Class Layout--\
  15281. --Layout initialization function--\
  15282. Layout.new = function(input)\
  15283.     local self = {}\
  15284.     setmetatable(self,{__index = Layout})\
  15285.     self.Button = {}\
  15286.     self.Toggle = {}\
  15287.     self.ColorField = {}\
  15288.     self.BetterPaint = {}\
  15289.     self.Text = {}\
  15290.     self.TextBox = {}\
  15291.     self.Key = {}\
  15292.     self.Window = {}\
  15293.     self.BackgroundColor = 1\
  15294.     self.xPos = input.xPos or 1\
  15295.     self.yPos = input.yPos or 1\
  15296.     self.xLength = input.xLength or 51\
  15297.     self.yLength = input.yLength or 19\
  15298.     self.nilClick = input.nilClick or false\
  15299.     self.windowBuffer = Screen.new(term.current(),self.xPos,self.yPos,self.xLength,self.yLength)\
  15300.     return self\
  15301. end\
  15302. \
  15303. --Add element function--\
  15304. Layout.addButton = function(self,_elementData)\
  15305.     self.Button[_elementData.name] = _elementData\
  15306. end\
  15307. \
  15308. Layout.addToggle = function(self,_elementData)\
  15309.     self.Toggle[_elementData.name] = _elementData\
  15310. end\
  15311. \
  15312. Layout.addBackgroundColor = function(self,_elementData)\
  15313.     self.BackgroundColor = _elementData.color\
  15314. end\
  15315. \
  15316. Layout.addColorField = function(self,_elementData)\
  15317.     self.ColorField[_elementData.name] = _elementData\
  15318. end\
  15319. \
  15320. Layout.addBetterPaint = function(self,_elementData)\
  15321.     self.BetterPaint[_elementData.name] = _elementData\
  15322. end\
  15323. \
  15324. Layout.addText = function(self,_elementData)\
  15325.     self.Text[_elementData.name] = _elementData\
  15326. end\
  15327. \
  15328. Layout.addTextBox = function(self,_elementData)\
  15329.     self.TextBox[_elementData.name] = _elementData\
  15330. end\
  15331. \
  15332. Layout.addKey = function(self,_elementData)\
  15333.     self.Key[_elementData.name] = _elementData\
  15334. end\
  15335. \
  15336. Layout.addLayout = function(self,_elementData)\
  15337.     loadLayout(self.Layout[_elementData.name],_elementData)\
  15338. end\
  15339. \
  15340. Layout.draw = function(self,xPlus,yPlus)\
  15341.     xPlus = xPlus or 0\
  15342.     yPlus = yPlus or 0\
  15343.     local oldTerm= term.current()\
  15344.     term.redirect(self.windowBuffer)\
  15345.     local buttonFunctions = {}\
  15346.     local toggleFunctions = {}\
  15347.     local colorFieldFunctions = {}\
  15348.     local betterPaintFunctions = {}\
  15349.     local textFunctions = {}\
  15350.     local textBoxFunctions = {}\
  15351.     local layoutFunctions = {}\
  15352.     setmetatable(buttonFunctions,{__index = Button})\
  15353.     setmetatable(toggleFunctions,{__index = Toggle})\
  15354.     setmetatable(colorFieldFunctions,{__index = ColorField})\
  15355.     setmetatable(betterPaintFunctions,{__index = BetterPaint})\
  15356.     setmetatable(textFunctions,{__index = Text})\
  15357.     setmetatable(textBoxFunctions,{__index = TextBox})\
  15358.     setmetatable(layoutFunctions,{__index = Layout})\
  15359.     paintutils.drawFilledBox(1,1,self.xLength,self.yLength,self.BackgroundColor)\
  15360.     for i,v in pairs(self.ColorField) do\
  15361.         colorFieldFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  15362.     end\
  15363.     for i,v in pairs(self.Button) do\
  15364.         buttonFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  15365.     end\
  15366.     for i,v in pairs(self.BetterPaint) do\
  15367.         betterPaintFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  15368.     end\
  15369.     for i,v in pairs(self.Toggle) do\
  15370.         toggleFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  15371.     end\
  15372.     for i,v in pairs(self.Text) do\
  15373.         textFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  15374.     end\
  15375.     for i,v in pairs(self.TextBox) do\
  15376.         textBoxFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  15377.     end\
  15378.     term.redirect(oldTerm)\
  15379. end\
  15380. \
  15381. --Class Button--\
  15382. --Button initialization function\
  15383. Button.new = function(input)\
  15384.     local self = {}\
  15385.     setmetatable(self,{__index = Button})\
  15386.     self.name = input.name\
  15387.     self.label = input.label\
  15388.     self.xPos = input.xPos\
  15389.     self.yPos = input.yPos\
  15390.     self.fgColor = input.fgColor\
  15391.     self.bgColor = input.bgColor\
  15392.     self.xLength = input.xLength\
  15393.     self.yLength = input.yLength\
  15394.     self.returnValue = input.returnValue\
  15395.     self.xTextPos = input.xTextPos\
  15396.     self.yTextPos = input.yTextPos\
  15397.     self.onRightClick = input.onRightClick or nil\
  15398.     self.onLeftClick = input.onLeftClick or nil\
  15399.     return self\
  15400. end\
  15401. \
  15402. --Draw function\
  15403. Button.draw = function(self,addX,addY)\
  15404.     addX = addX or 0\
  15405.     addY = addY or 0\
  15406.     local finalX = self.xPos + addX\
  15407.     local finalY = self.yPos + addY\
  15408. \
  15409.     self.finalX = finalX\
  15410.     self.finalY = finalY\
  15411.     local newText\
  15412.     if #self.label > self.xLength then\
  15413.         newText = string.sub(self.label,1,self.xLength)\
  15414.     else\
  15415.         newText = self.label\
  15416.     end\
  15417.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.bgColor)\
  15418.     term.setTextColor(self.fgColor)\
  15419.     term.setCursorPos(finalX+self.xTextPos-1,finalY+self.yTextPos-1)\
  15420.     term.write(newText)\
  15421. end\
  15422. \
  15423. --Return function--\
  15424. Button.returnData = function(self)\
  15425.     local toReturn = {}\
  15426.     for i,v in pairs(self) do\
  15427.         toReturn[i] = v\
  15428.     end\
  15429.     return toReturn\
  15430. end\
  15431. \
  15432. --Sample Input table--\
  15433. example = [[\
  15434.     example = {\
  15435.         name = \"quickSettings\",\
  15436.         label = \">\",\
  15437.         xPos = 1,\
  15438.         yPos = 3,\
  15439.         xLength = 1,\
  15440.         yLength = 6,\
  15441.         xTextPos = 1,\
  15442.         yTextPos = 1,\
  15443.         fgColor = colors.blue,\
  15444.         bgColor = colors.lightGray,\
  15445.         returnValue = \"quickSettings\",\
  15446.     },\
  15447. ]]\
  15448. \
  15449. --Class Toggle--\
  15450. --Initialize Toggle Object--\
  15451. Toggle.new = function(input)\
  15452.     local self = {}\
  15453.     setmetatable(self,{__index = Toggle})\
  15454.     self.name = input.name or \"randomName\"\
  15455.     self.state = input.state or true\
  15456.     self.xPos = input.xPos or 1\
  15457.     self.yPos = input.yPos or 1\
  15458.     self.trueColor = input.trueColor or colors.green\
  15459.     self.falseColor = input.falseColor or colors.red\
  15460.     self.trueText = input.trueText or \"T\"\
  15461.     self.falseText = input.falseText or \"F\"\
  15462.     self.selectedBg = input.selectedBg or colors.gray\
  15463.     self.notSelectedBg = input.notSelectedBg or colors.lightGray\
  15464.     self.returnValue = input.returnValue or \"mmmmmmm\"\
  15465.     self.moveX = input.moveX or false\
  15466.     self.moveY = input.moveY or false\
  15467.     self.onRightClick = input.onRightClick or nil\
  15468.     self.onLeftClick = input.onLeftClick or nil\
  15469.     return self\
  15470. end\
  15471. \
  15472. function Toggle.draw(self,addX,addY)\
  15473.     addX = addX or 0\
  15474.     addY = addY or 0\
  15475.     local finalX = self.xPos + addX\
  15476.     local finalY = self.yPos + addY\
  15477.     self.finalX = finalX\
  15478.     self.finalY = finalY\
  15479.     term.setCursorPos(finalX,finalY)\
  15480.     if self.state == false then\
  15481.         term.setBackgroundColor(self.notSelectedBg)\
  15482.         term.setTextColor(self.trueColor)\
  15483.         term.write(string.sub(self.trueText,1,1))\
  15484.         term.setBackgroundColor(self.selectedBg)\
  15485.         term.setTextColor(self.falseColor)\
  15486.         term.write(\" \"..string.sub(self.falseText,1,1)..\" \")\
  15487.     elseif self.state == true then\
  15488.         term.setBackgroundColor(self.selectedBg)\
  15489.         term.setTextColor(self.trueColor)\
  15490.         term.write(\" \"..string.sub(self.trueText,1,1)..\" \")\
  15491.         term.setBackgroundColor(self.notSelectedBg)\
  15492.         term.setTextColor(self.falseColor)\
  15493.         term.write(string.sub(self.falseText,1,1))\
  15494.     end\
  15495. end\
  15496. \
  15497. function Toggle.returnData(self)\
  15498.     local toReturn = {}\
  15499.     for i,v in pairs(self) do\
  15500.         toReturn[i] = v\
  15501.     end\
  15502.     return toReturn\
  15503. end\
  15504. \
  15505. function Toggle.toggle(self)\
  15506.     if self.state == true then\
  15507.         self.state = false\
  15508.     else\
  15509.         self.state = true\
  15510.     end\
  15511. end\
  15512. \
  15513. function Toggle.getState(self)\
  15514.     return self.state\
  15515. end\
  15516. \
  15517. --BackgroundColor Class--\
  15518. function BackgroundColor.new(input)\
  15519.     local self = {}\
  15520.     setmetatable(self,{__index = BackgroundColor})\
  15521.     self.color = input.color\
  15522.     return self\
  15523. end\
  15524. \
  15525. function BackgroundColor.setColor(self,color)\
  15526.     self.color = color\
  15527. end\
  15528. \
  15529. function BackgroundColor.returnData(self)\
  15530.     local toReturn = {}\
  15531.     for i,v in pairs(self) do\
  15532.         toReturn[i] = v\
  15533.     end\
  15534.     return toReturn\
  15535. end\
  15536. \
  15537. --ColorField Class--\
  15538. function ColorField.new(input)\
  15539.     local self = {}\
  15540.     setmetatable(self,{__index = ColorField})\
  15541.     self.name = input.name\
  15542.     self.xPos = input.xPos\
  15543.     self.yPos = input.yPos\
  15544.     self.xLength = input.xLength\
  15545.     self.yLength = input.yLength\
  15546.     self.color = input.color\
  15547.     self.moveX = input.moveX or false\
  15548.     self.moveY = input.moveY or false\
  15549.     return self\
  15550. end\
  15551. \
  15552. function  ColorField.draw(self,addX,addY)\
  15553.     addX = addX or 0\
  15554.     addY = addY or 0\
  15555.     local finalX = self.xPos + addX\
  15556.     local finalY = self.yPos + addY\
  15557.     self.finalX = finalX\
  15558.     self.finalY = finalY\
  15559.     term.setTextColor(colors.black)\
  15560.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.color)\
  15561. end\
  15562. \
  15563. function ColorField.returnData(self)\
  15564.     local toReturn = {}\
  15565.     for i,v in pairs(self) do\
  15566.         toReturn[i] = v\
  15567.     end\
  15568.     return toReturn\
  15569. end\
  15570. \
  15571. --BetterPaint Class--\
  15572. function BetterPaint.new(input)\
  15573.     local self = {}\
  15574.     setmetatable(self,{__index = BetterPaint})\
  15575.     self.xPos = input.xPos\
  15576.     self.yPos = input.yPos\
  15577.     self.name = input.name\
  15578.     self.path = input.path\
  15579.     self.xLength = input.xLength\
  15580.     self.yLength = input.yLength\
  15581.     self.returnValue = input.returnValue\
  15582.     self.label = input.label\
  15583.     self.labelBg = input.labelBg\
  15584.     self.labelFg = input.labelFg\
  15585.     self.moveX = input.moveX or false\
  15586.     self.moveY = input.moveY or false\
  15587.     self.onRightClick = input.onRightClick or nil\
  15588.     self.onLeftClick = input.onLeftClick or nil\
  15589.     return self\
  15590. end\
  15591. \
  15592. function BetterPaint.returnData(self)\
  15593.     local toReturn = {}\
  15594.     for i,v in pairs(self) do\
  15595.         toReturn[i] = v\
  15596.     end\
  15597.     return toReturn\
  15598. end\
  15599. \
  15600. function BetterPaint.draw(self,addX,addY)\
  15601.     addX = addX or 0\
  15602.     addY = addY or 0\
  15603.     local finalX = self.xPos + addX\
  15604.     local finalY = self.yPos + addY\
  15605.     self.finalX = finalX\
  15606.     self.finalY = finalY\
  15607.     paint.drawImage(self.path,finalX,finalY)\
  15608.     term.setCursorPos(finalX,finalY+self.yLength)\
  15609.     term.setTextColor(self.labelFg)\
  15610.     term.setBackgroundColor(self.labelBg)\
  15611.     term.write(self.label)\
  15612. end\
  15613. \
  15614. --Text Class--\
  15615. function Text.new(input)\
  15616.     local self = {}\
  15617.     setmetatable(self,{__index = Text})\
  15618.     self.name = input.name\
  15619.     self.text = input.text\
  15620.     self.xPos = input.xPos\
  15621.     self.yPos = input.yPos\
  15622.     self.bgColor = input.bgColor\
  15623.     self.fgColor = input.fgColor\
  15624.     return self\
  15625. end\
  15626. \
  15627. function Text.draw(self,addX,addY)\
  15628.     addX = addX or 0\
  15629.     addY = addY or 0\
  15630.     local finalX = self.xPos + addX\
  15631.     local finalY = self.yPos + addY\
  15632.     self.finalX = finalX\
  15633.     self.finalY = finalY\
  15634.     term.setCursorPos(finalX,finalY)\
  15635.     term.setTextColor(self.fgColor)\
  15636.     term.setBackgroundColor(self.bgColor)\
  15637.     term.write(self.text)\
  15638. end\
  15639. \
  15640. function Text.returnData(self)\
  15641.     local toReturn = {}\
  15642.     for i,v in pairs(self) do\
  15643.         toReturn[i] = v\
  15644.     end\
  15645.     return toReturn\
  15646. end\
  15647. \
  15648. --TextBox Class \
  15649. \
  15650. function TextBox.new(input)\
  15651.     local self = {}\
  15652.     setmetatable(self,{__index = TextBox})\
  15653.     self.name = input.name\
  15654.     self.helpText = input.helpText\
  15655.     self.xPos = input.xPos\
  15656.     self.yPos = input.yPos\
  15657.     self.xLength = input.xLength\
  15658.     self.yLength = input.yLength\
  15659.     self.bgColor = input.bgColor\
  15660.     self.fgColor = input.fgColor\
  15661.     self.helpFgColor = input.helpFgColor\
  15662.     self.charLimit = input.charLimit\
  15663.     self.moveX = input.moveX or false\
  15664.     self.moveY = input.moveY or false\
  15665.     self.text = \"\"\
  15666.     self.returnValue = input.returnValue\
  15667.     self.confidential = input.confidential or false\
  15668.     return self\
  15669. end\
  15670. \
  15671. function TextBox.returnData(self)\
  15672.     local toReturn = {}\
  15673.     for i,v in pairs(self) do\
  15674.         toReturn[i] = v\
  15675.     end\
  15676.     return toReturn\
  15677. end\
  15678. \
  15679. function TextBox.draw(self,addX,addY)\
  15680.     addX = addX or 0\
  15681.     addY = addY or 0\
  15682.     local finalX = self.xPos + addX\
  15683.     local finalY = self.yPos + addY\
  15684.     self.finalX = finalX\
  15685.     self.finalY = finalY\
  15686.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.bgColor)\
  15687.     term.setBackgroundColor(self.bgColor)\
  15688.     term.setCursorPos(self.finalX,self.finalY)\
  15689.     if self.text == \"\" or self.confidential then\
  15690.         term.setTextColor(self.helpFgColor)\
  15691.         term.write(self.helpText)\
  15692.     else\
  15693.         term.setTextColor(self.fgColor)\
  15694.         term.write(self.text)\
  15695.     end\
  15696. end\
  15697. \
  15698. function TextBox.read(self,_sReplaceChar, _tHistory)\
  15699.     paintutils.drawFilledBox(self.finalX,self.finalY,self.finalX+self.xLength-1,self.finalY+self.yLength-1,self.bgColor)\
  15700.     term.setTextColor(self.fgColor)\
  15701.     term.setCursorPos(self.finalX,self.finalY)\
  15702.     return read()\
  15703. end\
  15704. \
  15705. --Key Class\
  15706. function Key.new(input)\
  15707.     local self = {}\
  15708.     setmetatable(self,{__index = TextBox})\
  15709.     self.name = input.name\
  15710.     self.key = input.key\
  15711.     self.onPress = input.onPress or nil\
  15712.     return self\
  15713. end\
  15714. \
  15715. function Key.returnData(self)\
  15716.     local toReturn = {}\
  15717.     for i,v in pairs(self) do\
  15718.         toReturn[i] = v\
  15719.     end\
  15720.     return toReturn\
  15721. end\
  15722. \
  15723. local function localEventHandler(self,event, p1, p2, p3, p4, p5, p6)\
  15724.     local toAddX = self.xPos - 1\
  15725.     local toAddY = self.yPos - 1\
  15726.     while true do\
  15727.         if event == \"mouse_click\" then\
  15728.             for i,v in pairs(self.Button) do\
  15729.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + v.xLength-1 + toAddX and v.finalY + toAddY <= p3 and p3 <= v.finalY + v.yLength-1 + toAddY then\
  15730.                     if p1 == 1 then\
  15731.                         if v.onLeftClick then \
  15732.                             v.onLeftClick()\
  15733.                         end\
  15734.                     elseif p1 == 2 then\
  15735.                         if v.onRightClick then\
  15736.                             v.onRightClick()\
  15737.                         end\
  15738.                     end\
  15739.                     return {\"Button\",tostring(v.returnValue),p1,p2,p3}\
  15740.                 end\
  15741.             end\
  15742.             for i,v in pairs(self.Toggle) do\
  15743.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + 3 + toAddX and v.finalY + toAddY == p3 then\
  15744.                     return {\"Toggle\",tostring(v.returnValue),p1,p2,p3}\
  15745.                 end\
  15746.             end\
  15747.             for i,v in pairs(self.BetterPaint) do \
  15748.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + v.xLength-1 + toAddX and v.finalY + toAddY <= p3 and p3 <= v.finalY + v.yLength-1 + toAddY then\
  15749.                     return {\"Button\",tostring(v.returnValue),p1,p2,p3}\
  15750.                 end\
  15751.             end\
  15752.             for i,v in pairs(self.TextBox) do \
  15753.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + v.xLength-1 + toAddX and v.finalY + toAddY <= p3 and p3 <= v.finalY + v.yLength-1 + toAddY then\
  15754.                     return {\"TextBox\",tostring(v.returnValue),p1,p2,p3}\
  15755.                 end\
  15756.             end\
  15757.             if self.nilClick then\
  15758.                 if not (self.xPos <= p2 and p2 <= self.xPos+self.xLength-1 and self.yPos <= p3 and p3 <= self.yPos+self.yLength-1) then\
  15759.                     return {\"Nil\",\"Nil\",p1,p2,p3}\
  15760.                 end\
  15761.             end\
  15762.         elseif event == \"key\" then\
  15763.             local pressedKey = p1\
  15764.             for i,v in pairs(self.Key) do\
  15765.                 if v.key == KeyCodes[pressedKey] then\
  15766.                     if v.onPress then\
  15767.                         v.onPress()\
  15768.                     else\
  15769.                         return {\"Key\",KeyCodes[pressedKey],pressedKey}\
  15770.                     end\
  15771.                 end\
  15772. \
  15773.             end\
  15774.         elseif event == \"monitor_touch\" then\
  15775.             os.queueEvent(\"mouse_click\", p1, p2, p3, p4, p5, p6)\
  15776.         end\
  15777.     end\
  15778. end\
  15779. \
  15780. --Event handler function--\
  15781. eventHandler = function(self)\
  15782.     local tEvent = {os.pullEvent()}\
  15783.     return localEventHandler(self,unpack(tEvent))\
  15784. end\
  15785. \
  15786. --Load Function--\
  15787. function Initialize()\
  15788.     local toReturn = {}\
  15789.     toReturn.Button = Button\
  15790.     toReturn.Layout = Layout\
  15791.     toReturn.Toggle = Toggle\
  15792.     toReturn.BackgroundColor = BackgroundColor\
  15793.     toReturn.ColorField = ColorField\
  15794.     toReturn.BetterPaint = BetterPaint\
  15795.     toReturn.Text = Text\
  15796.     toReturn.TextBox = TextBox\
  15797.     toReturn.Key = Key\
  15798.     toReturn.eventHandler = eventHandler\
  15799.     toReturn.loadObjects = loadObjects\
  15800.     toReturn.loadLayout = loadLayout\
  15801.     return toReturn\
  15802. end",
  15803.       Backup = {
  15804.         Interact = "--[[\
  15805.     Interact API in ComputerCraft\
  15806.     by Creator\
  15807.     Complete rewrite in OOP\
  15808. ]]--\
  15809. \
  15810. --Variables\
  15811. local textutilsserialize = textutils.serialize\
  15812. local textutilsunserialize = textutils.unserialize\
  15813. local KeyCodes = {\
  15814.     [ 2 ] =  1 ,\
  15815.     [ 3 ] =  2,\
  15816.     [ 4 ] =  3,\
  15817.     [ 5 ] =  4,\
  15818.     [ 6 ] =  5,\
  15819.     [ 7 ] =  6,\
  15820.     [ 8 ] =  7,\
  15821.     [ 9 ] =  8,\
  15822.     [ 10 ] =  9,\
  15823.     [ 11 ] =  0,\
  15824.     [ 12 ] = \"-\",\
  15825.     [ 13 ] = \"=\",\
  15826.     [ 14 ] = \"Backspace\",\
  15827.     [ 15 ] = \"Tab\",\
  15828.     [ 16 ] = \"q\",\
  15829.     [ 17 ] = \"w\",\
  15830.     [ 18 ] = \"e\",\
  15831.     [ 19 ] = \"r\",\
  15832.     [ 20 ] = \"t\",\
  15833.     [ 21 ] = \"y\",\
  15834.     [ 22 ] = \"u\",\
  15835.     [ 23 ] = \"i\",\
  15836.     [ 24 ] = \"o\",\
  15837.     [ 25 ] = \"p\",\
  15838.     [ 26 ] = \"LeftBracket\",\
  15839.     [ 27 ] = \"RightBracket\",\
  15840.     [ 28 ] = \"Enter\",\
  15841.     [ 29 ] = \"LeftControl\",\
  15842.     [ 30 ] = \"a\",\
  15843.     [ 31 ] = \"s\",\
  15844.     [ 32 ] = \"d\",\
  15845.     [ 33 ] = \"f\",\
  15846.     [ 34 ] = \"g\",\
  15847.     [ 35 ] = \"h\",\
  15848.     [ 36 ] = \"j\",\
  15849.     [ 37 ] = \"k\",\
  15850.     [ 38 ] = \"l\",\
  15851.     [ 39 ] = \";\",\
  15852.     [ 40 ] = \"\\'\",\
  15853.     [ 41 ] = \"`\",\
  15854.     [ 42 ] = \"LeftShift\",\
  15855.     [ 43 ] = \"Backslash\",\
  15856.     [ 44 ] = \"z\",\
  15857.     [ 45 ] = \"x\",\
  15858.     [ 46 ] = \"c\",\
  15859.     [ 47 ] = \"v\",\
  15860.     [ 48 ] = \"b\",\
  15861.     [ 49 ] = \"n\",\
  15862.     [ 50 ] = \"m\",\
  15863.     [ 51 ] = \",\",\
  15864.     [ 52 ] = \".\",\
  15865.     [ 53 ] = \"/\",\
  15866.     [ 54 ] = \"RightShift\",\
  15867.     [ 55 ] = \"*\",\
  15868.     [ 56 ] = \"LeftAlt\",\
  15869.     [ 57 ] = \" \",\
  15870.     [ 58 ] = \"CapsLock\",\
  15871.     [ 59 ] = \"F1\",\
  15872.     [ 60 ] = \"F2\",\
  15873.     [ 61 ] = \"F3\",\
  15874.     [ 62 ] = \"F4\",\
  15875.     [ 63 ] = \"F5\",\
  15876.     [ 64 ] = \"F6\",\
  15877.     [ 65 ] = \"F7\",\
  15878.     [ 66 ] = \"F8\",\
  15879.     [ 67 ] = \"F9\",\
  15880.     [ 68 ] = \"F10\",\
  15881.     [ 69 ] = \"NumberLock\",\
  15882.     [ 70 ] = \"ScrollLock\",\
  15883.     [ 71 ] = \"NumPAd7\",\
  15884.     [ 72 ] = \"NumPAd8\",\
  15885.     [ 73 ] = \"NumPAd9\",\
  15886.     [ 74 ] = \"Substract\",\
  15887.     [ 75 ] = \"NumPAd4\",\
  15888.     [ 76 ] = \"NumPAd5\",\
  15889.     [ 77 ] = \"NumPAd6\",\
  15890.     [ 78 ] = \"Add\",\
  15891.     [ 79 ] = \"NumPAd1\",\
  15892.     [ 80 ] = \"NumPAd2\",\
  15893.     [ 81 ] = \"NumPAd3\",\
  15894.     [ 82 ] = \"NumPAd0\",\
  15895.     [ 83 ] = \"Decimal\",\
  15896.     [ 87 ] = \"F11\",\
  15897.     [ 88 ] = \"F12\",\
  15898.     [ 100] = \"F13\",\
  15899.     [ 101] = \"F14\",\
  15900.     [ 102] = \"F15\",\
  15901.     [ 103] = \"F16\",\
  15902.     [ 104] = \"F17\",\
  15903.     [ 105] = \"F18\",\
  15904.     [ 112] = \"Kana\",\
  15905.     [ 113] = \"F19\",\
  15906.     [ 121] = \"Convert\",\
  15907.     [ 123] = \"Noconvert\",\
  15908.     [ 125] = \"Yen\",\
  15909.     [ 141] = \"NumPadEquals\",\
  15910.     [ 144] = \"^\",\
  15911.     [ 145] = \"@\",\
  15912.     [ 146] = \":\",\
  15913.     [ 147] = \"_\",\
  15914.     [ 148] = \"Kanji\",\
  15915.     [ 149] = \"Stop\",\
  15916.     [ 150] = \"Ax\",\
  15917.     [ 151] = \"Unlabeled\",\
  15918.     [ 156] = \"NumPadEnter\",\
  15919.     [ 157] = \"RightControl\",\
  15920.     [ 157] = \"Section\",\
  15921.     [ 179] = \"NumPadComma\",\
  15922.     [ 181] = \"Dvide\",\
  15923.     [ 183] = \"Sysrq\",\
  15924.     [ 184] = \"RightAlt\",\
  15925.     [ 196] = \"Function\",\
  15926.     [ 197] = \"Pause\",\
  15927.     [ 199] = \"Home\",\
  15928.     [ 200] = \"Up\",\
  15929.     [ 201] = \"PageUp\",\
  15930.     [ 203] = \"Left\",\
  15931.     [ 205] = \"Right\",\
  15932.     [ 207] = \"End\",\
  15933.     [ 208] = \"Down\",\
  15934.     [ 209] = \"PageDown\",\
  15935.     [ 210] = \"Insert\",\
  15936.     [ 211] = \"Delete\",\
  15937. }\
  15938. \
  15939. --Class declarations--\
  15940. local Button = {}\
  15941. local Layout = {}\
  15942. local Toggle = {}\
  15943. local BackgroundColor = {}\
  15944. local ColorField = {}\
  15945. local BetterPaint = {}\
  15946. local Text = {}\
  15947. local TextBox = {}\
  15948. local Key = {}\
  15949. \
  15950. function loadObjects(self)\
  15951.     local output = {}\
  15952.     output.Button = {}\
  15953.     output.Toggle = {}\
  15954.     output.ColorField = {}\
  15955.     output.BetterPaint = {}\
  15956.     output.Text = {}\
  15957.     output.TextBox = {}\
  15958.     output.Key = {}\
  15959.     for o,v in pairs(output) do\
  15960.         if self[o] == nil then\
  15961.             self[o] = {}\
  15962.         end\
  15963.     end\
  15964.     for i,v in pairs(self.Button) do\
  15965.         output.Button[i] = Button.new(self.Button[i])\
  15966.     end\
  15967.     for i,v in pairs(self.Toggle) do\
  15968.         output.Toggle[i] = Toggle.new(self.Toggle[i])\
  15969.     end\
  15970.     for i,v in pairs(self.ColorField) do\
  15971.         output.ColorField[i] = ColorField.new(self.ColorField[i])\
  15972.     end\
  15973.     for i,v in pairs(self.BetterPaint) do\
  15974.         output.BetterPaint[i] = BetterPaint.new(self.BetterPaint[i])\
  15975.     end\
  15976.     for i,v in pairs(self.Text) do\
  15977.         output.Text[i] = Text.new(self.Text[i])\
  15978.     end\
  15979.     for i,v in pairs(self.TextBox) do\
  15980.         output.TextBox[i] = TextBox.new(self.TextBox[i])\
  15981.     end\
  15982.     for i,v in pairs(self.Key) do\
  15983.         output.Key[i] = Key.new(self.Key[i])\
  15984.     end\
  15985.     return output\
  15986. end\
  15987. \
  15988. function loadLayout(input,output)\
  15989.     for i,v in pairs(input.Button) do\
  15990.         output:addButton(input.Button[i])\
  15991.     end\
  15992.     for i,v in pairs(input.Toggle) do\
  15993.         output:addToggle(input.Toggle[i])\
  15994.     end\
  15995.     for i,v in pairs(input.ColorField) do\
  15996.         output:addColorField(input.ColorField[i])\
  15997.     end\
  15998.     for i,v in pairs(input.BetterPaint) do\
  15999.         output:addBetterPaint(input.BetterPaint[i])\
  16000.     end\
  16001.     for i,v in pairs(input.Text) do\
  16002.         output:addText(input.Text[i])\
  16003.     end\
  16004.     for i,v in pairs(input.TextBox) do\
  16005.         output:addTextBox(input.TextBox[i])\
  16006.     end\
  16007.     for i,v in pairs(input.Key) do\
  16008.         output:addKey(input.Key[i])\
  16009.     end\
  16010. end\
  16011. \
  16012. --Class Layout--\
  16013. --Layout initialization function--\
  16014. Layout.new = function(input)\
  16015.     local self = {}\
  16016.     setmetatable(self,{__index = Layout})\
  16017.     self.Button = {}\
  16018.     self.Toggle = {}\
  16019.     self.ColorField = {}\
  16020.     self.BetterPaint = {}\
  16021.     self.Text = {}\
  16022.     self.TextBox = {}\
  16023.     self.Key = {}\
  16024.     self.BackgroundColor = 1\
  16025.     self.xPos = input.xPos or 1\
  16026.     self.yPos = input.yPos or 1\
  16027.     self.xLength = input.xLength or 51\
  16028.     self.yLength = input.yLength or 19\
  16029.     self.nilClick = input.nilClick or false\
  16030.     self.window = Screen.new(term.current(),self.xPos,self.yPos,self.xLength,self.yLength)\
  16031.     return self\
  16032. end\
  16033. \
  16034. --Add element function--\
  16035. Layout.addButton = function(self,_elementData)\
  16036.     self.Button[_elementData.name] = _elementData\
  16037. end\
  16038. \
  16039. Layout.addToggle = function(self,_elementData)\
  16040.     self.Toggle[_elementData.name] = _elementData\
  16041. end\
  16042. \
  16043. Layout.addBackgroundColor = function(self,_elementData)\
  16044.     self.BackgroundColor = _elementData.color\
  16045. end\
  16046. \
  16047. Layout.addColorField = function(self,_elementData)\
  16048.     self.ColorField[_elementData.name] = _elementData\
  16049. end\
  16050. \
  16051. Layout.addBetterPaint = function(self,_elementData)\
  16052.     self.BetterPaint[_elementData.name] = _elementData\
  16053. end\
  16054. \
  16055. Layout.addText = function(self,_elementData)\
  16056.     self.Text[_elementData.name] = _elementData\
  16057. end\
  16058. \
  16059. Layout.addTextBox = function(self,_elementData)\
  16060.     self.TextBox[_elementData.name] = _elementData\
  16061. end\
  16062. \
  16063. Layout.addKey = function(self,_elementData)\
  16064.     self.Key[_elementData.name] = _elementData\
  16065. end\
  16066. \
  16067. Layout.draw = function(self,xPlus,yPlus)\
  16068.     local oldTerm= term.current()\
  16069.     term.redirect(self.window)\
  16070.     local buttonFunctions = {}\
  16071.     local toggleFunctions = {}\
  16072.     local colorFieldFunctions = {}\
  16073.     local betterPaintFunctions = {}\
  16074.     local textFunctions = {}\
  16075.     local textBoxFunctions = {}\
  16076.     setmetatable(buttonFunctions,{__index = Button})\
  16077.     setmetatable(toggleFunctions,{__index = Toggle})\
  16078.     setmetatable(colorFieldFunctions,{__index = ColorField})\
  16079.     setmetatable(betterPaintFunctions,{__index = BetterPaint})\
  16080.     setmetatable(textFunctions,{__index = Text})\
  16081.     setmetatable(textBoxFunctions,{__index = TextBox})\
  16082.     --paintutils.drawFilledBox(self.xPos,self.yPos,self.xPos+self.xLength-1,self.yPos+self.yLength-1,self.BackgroundColor)\
  16083.     paintutils.drawFilledBox(1,1,self.xLength,self.yLength,self.BackgroundColor)\
  16084.     for i,v in pairs(self.ColorField) do\
  16085.         colorFieldFunctions.draw(v,self.xPos,self.yPos,xPlus,yPlus)\
  16086.     end\
  16087.     for i,v in pairs(self.Button) do\
  16088.         buttonFunctions.draw(v,self.xPos,self.yPos,xPlus,yPlus)\
  16089.     end\
  16090.     for i,v in pairs(self.BetterPaint) do\
  16091.         betterPaintFunctions.draw(v,self.xPos,self.yPos,xPlus,yPlus)\
  16092.     end\
  16093.     for i,v in pairs(self.Toggle) do\
  16094.         toggleFunctions.draw(v,self.xPos,self.yPos,xPlus,yPlus)\
  16095.     end\
  16096.     for i,v in pairs(self.Text) do\
  16097.         textFunctions.draw(v,self.xPos,self.yPos,xPlus,yPlus)\
  16098.     end\
  16099.     for i,v in pairs(self.TextBox) do\
  16100.         textBoxFunctions.draw(v,self.xPos,self.yPos,xPlus,yPlus)\
  16101.     end\
  16102.     term.redirect(oldTerm)\
  16103. end\
  16104. \
  16105. --Class Button--\
  16106. --Button initialization function\
  16107. Button.new = function(input)\
  16108.     local self = {}\
  16109.     setmetatable(self,{__index = Button})\
  16110.     self.name = input.name\
  16111.     self.label = input.label\
  16112.     self.xPos = input.xPos\
  16113.     self.yPos = input.yPos\
  16114.     self.fgColor = input.fgColor\
  16115.     self.bgColor = input.bgColor\
  16116.     self.xLength = input.xLength\
  16117.     self.yLength = input.yLength\
  16118.     self.returnValue = input.returnValue\
  16119.     self.xTextPos = input.xTextPos\
  16120.     self.yTextPos = input.yTextPos\
  16121.     self.onRightClick = input.onRightClick or nil\
  16122.     self.onLeftClick = input.onLeftClick or nil\
  16123.     return self\
  16124. end\
  16125. \
  16126. --Draw function\
  16127. Button.draw = function(self,addX,addY)\
  16128.     addX = addX or 0\
  16129.     addY = addY or 0\
  16130.     local finalX = self.xPos + addX\
  16131.     local finalY = self.yPos + addY\
  16132. \
  16133.     self.finalX = finalX\
  16134.     self.finalY = finalY\
  16135.     local newText\
  16136.     if #self.label > self.xLength then\
  16137.         newText = string.sub(self.label,1,self.xLength)\
  16138.     else\
  16139.         newText = self.label\
  16140.     end\
  16141.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.bgColor)\
  16142.     term.setTextColor(self.fgColor)\
  16143.     term.setCursorPos(finalX+self.xTextPos-1,finalY+self.yTextPos-1)\
  16144.     term.write(newText)\
  16145. end\
  16146. \
  16147. --Return function--\
  16148. Button.returnData = function(self)\
  16149.     local toReturn = {}\
  16150.     for i,v in pairs(self) do\
  16151.         toReturn[i] = v\
  16152.     end\
  16153.     return toReturn\
  16154. end\
  16155. \
  16156. --Sample Input table--\
  16157. example = [[\
  16158.     example = {\
  16159.         name = \"quickSettings\",\
  16160.         label = \">\",\
  16161.         xPos = 1,\
  16162.         yPos = 3,\
  16163.         xLength = 1,\
  16164.         yLength = 6,\
  16165.         xTextPos = 1,\
  16166.         yTextPos = 1,\
  16167.         fgColor = colors.blue,\
  16168.         bgColor = colors.lightGray,\
  16169.         returnValue = \"quickSettings\",\
  16170.     },\
  16171. ]]\
  16172. \
  16173. --Class Toggle--\
  16174. --Initialize Toggle Object--\
  16175. Toggle.new = function(input)\
  16176.     local self = {}\
  16177.     setmetatable(self,{__index = Toggle})\
  16178.     self.name = input.name or \"randomName\"\
  16179.     self.state = input.state or true\
  16180.     self.xPos = input.xPos or 1\
  16181.     self.yPos = input.yPos or 1\
  16182.     self.trueColor = input.trueColor or colors.green\
  16183.     self.falseColor = input.falseColor or colors.red\
  16184.     self.trueText = input.trueText or \"T\"\
  16185.     self.falseText = input.falseText or \"F\"\
  16186.     self.selectedBg = input.selectedBg or colors.gray\
  16187.     self.notSelectedBg = input.notSelectedBg or colors.lightGray\
  16188.     self.returnValue = input.returnValue or \"mmmmmmm\"\
  16189.     self.moveX = input.moveX or false\
  16190.     self.moveY = input.moveY or false\
  16191.     self.onRightClick = input.onRightClick or nil\
  16192.     self.onLeftClick = input.onLeftClick or nil\
  16193.     return self\
  16194. end\
  16195. \
  16196. function Toggle.draw(self,addX,addY)\
  16197.     addX = addX or 0\
  16198.     addY = addY or 0\
  16199.     local finalX = self.xPos + addX\
  16200.     local finalY = self.yPos + addY\
  16201.     self.finalX = finalX\
  16202.     self.finalY = finalY\
  16203.     term.setCursorPos(finalX,finalY)\
  16204.     if self.state == false then\
  16205.         term.setBackgroundColor(self.notSelectedBg)\
  16206.         term.setTextColor(self.trueColor)\
  16207.         term.write(string.sub(self.trueText,1,1))\
  16208.         term.setBackgroundColor(self.selectedBg)\
  16209.         term.setTextColor(self.falseColor)\
  16210.         term.write(\" \"..string.sub(self.falseText,1,1)..\" \")\
  16211.     elseif self.state == true then\
  16212.         term.setBackgroundColor(self.selectedBg)\
  16213.         term.setTextColor(self.trueColor)\
  16214.         term.write(\" \"..string.sub(self.trueText,1,1)..\" \")\
  16215.         term.setBackgroundColor(self.notSelectedBg)\
  16216.         term.setTextColor(self.falseColor)\
  16217.         term.write(string.sub(self.falseText,1,1))\
  16218.     end\
  16219. end\
  16220. \
  16221. function Toggle.returnData(self)\
  16222.     local toReturn = {}\
  16223.     for i,v in pairs(self) do\
  16224.         toReturn[i] = v\
  16225.     end\
  16226.     return toReturn\
  16227. end\
  16228. \
  16229. function Toggle.toggle(self)\
  16230.     if self.state == true then\
  16231.         self.state = false\
  16232.     else\
  16233.         self.state = true\
  16234.     end\
  16235. end\
  16236. \
  16237. function Toggle.getState(self)\
  16238.     return self.state\
  16239. end\
  16240. \
  16241. --BackgroundColor Class--\
  16242. function BackgroundColor.new(input)\
  16243.     local self = {}\
  16244.     setmetatable(self,{__index = BackgroundColor})\
  16245.     self.color = input.color\
  16246.     return self\
  16247. end\
  16248. \
  16249. function BackgroundColor.setColor(self,color)\
  16250.     self.color = color\
  16251. end\
  16252. \
  16253. function BackgroundColor.returnData(self)\
  16254.     local toReturn = {}\
  16255.     for i,v in pairs(self) do\
  16256.         toReturn[i] = v\
  16257.     end\
  16258.     return toReturn\
  16259. end\
  16260. \
  16261. --ColorField Class--\
  16262. function ColorField.new(input)\
  16263.     local self = {}\
  16264.     setmetatable(self,{__index = ColorField})\
  16265.     self.name = input.name\
  16266.     self.xPos = input.xPos\
  16267.     self.yPos = input.yPos\
  16268.     self.xLength = input.xLength\
  16269.     self.yLength = input.yLength\
  16270.     self.color = input.color\
  16271.     self.moveX = input.moveX or false\
  16272.     self.moveY = input.moveY or false\
  16273.     return self\
  16274. end\
  16275. \
  16276. function  ColorField.draw(self,addX,addY)\
  16277.     addX = addX or 0\
  16278.     addY = addY or 0\
  16279.     local finalX = self.xPos + addX\
  16280.     local finalY = self.yPos + addY\
  16281.     self.finalX = finalX\
  16282.     self.finalY = finalY\
  16283.     term.setTextColor(colors.black)\
  16284.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.color)\
  16285. end\
  16286. \
  16287. function ColorField.returnData(self)\
  16288.     local toReturn = {}\
  16289.     for i,v in pairs(self) do\
  16290.         toReturn[i] = v\
  16291.     end\
  16292.     return toReturn\
  16293. end\
  16294. \
  16295. --BetterPaint Class--\
  16296. function BetterPaint.new(input)\
  16297.     local self = {}\
  16298.     setmetatable(self,{__index = BetterPaint})\
  16299.     self.xPos = input.xPos\
  16300.     self.yPos = input.yPos\
  16301.     self.name = input.name\
  16302.     self.path = input.path\
  16303.     self.xLength = input.xLength\
  16304.     self.yLength = input.yLength\
  16305.     self.returnValue = input.returnValue\
  16306.     self.label = input.label\
  16307.     self.labelBg = input.labelBg\
  16308.     self.labelFg = input.labelFg\
  16309.     self.moveX = input.moveX or false\
  16310.     self.moveY = input.moveY or false\
  16311.     self.onRightClick = input.onRightClick or nil\
  16312.     self.onLeftClick = input.onLeftClick or nil\
  16313.     return self\
  16314. end\
  16315. \
  16316. function BetterPaint.returnData(self)\
  16317.     local toReturn = {}\
  16318.     for i,v in pairs(self) do\
  16319.         toReturn[i] = v\
  16320.     end\
  16321.     return toReturn\
  16322. end\
  16323. \
  16324. function BetterPaint.draw(self,addX,addY)\
  16325.     addX = addX or 0\
  16326.     addY = addY or 0\
  16327.     local finalX = self.xPos + addX\
  16328.     local finalY = self.yPos + addY\
  16329.     self.finalX = finalX\
  16330.     self.finalY = finalY\
  16331.     paint.drawImage(self.path,finalX,finalY)\
  16332.     term.setCursorPos(finalX,finalY+self.yLength)\
  16333.     term.setTextColor(self.labelFg)\
  16334.     term.setBackgroundColor(self.labelBg)\
  16335.     term.write(self.label)\
  16336. end\
  16337. \
  16338. --Text Class--\
  16339. function Text.new(input)\
  16340.     local self = {}\
  16341.     setmetatable(self,{__index = Text})\
  16342.     self.name = input.name\
  16343.     self.text = input.text\
  16344.     self.xPos = input.xPos\
  16345.     self.yPos = input.yPos\
  16346.     self.bgColor = input.bgColor\
  16347.     self.fgColor = input.fgColor\
  16348.     self.moveX = input.moveX or false\
  16349.     self.moveY = input.moveY or false\
  16350.     return self\
  16351. end\
  16352. \
  16353. function Text.draw(self,addX,addY)\
  16354.     addX = addX or 0\
  16355.     addY = addY or 0\
  16356.     local finalX = self.xPos + addX\
  16357.     local finalY = self.yPos + addY\
  16358.     self.finalX = finalX\
  16359.     self.finalY = finalY\
  16360.     term.setCursorPos(finalX,finalY)\
  16361.     term.setTextColor(self.fgColor)\
  16362.     term.setBackgroundColor(self.bgColor)\
  16363.     term.write(self.text)\
  16364. end\
  16365. \
  16366. function Text.returnData(self)\
  16367.     local toReturn = {}\
  16368.     for i,v in pairs(self) do\
  16369.         toReturn[i] = v\
  16370.     end\
  16371.     return toReturn\
  16372. end\
  16373. \
  16374. --TextBox Class \
  16375. \
  16376. function TextBox.new(input)\
  16377.     local self = {}\
  16378.     setmetatable(self,{__index = TextBox})\
  16379.     self.name = input.name\
  16380.     self.helpText = input.helpText\
  16381.     self.xPos = input.xPos\
  16382.     self.yPos = input.yPos\
  16383.     self.xLength = input.xLength\
  16384.     self.yLength = input.yLength\
  16385.     self.bgColor = input.bgColor\
  16386.     self.fgColor = input.fgColor\
  16387.     self.helpFgColor = input.helpFgColor\
  16388.     self.charLimit = input.charLimit\
  16389.     self.moveX = input.moveX or false\
  16390.     self.moveY = input.moveY or false\
  16391.     self.text = \"\"\
  16392.     self.returnValue = input.returnValue\
  16393.     self.confidential = input.confidential or false\
  16394.     return self\
  16395. end\
  16396. \
  16397. function TextBox.returnData(self)\
  16398.     local toReturn = {}\
  16399.     for i,v in pairs(self) do\
  16400.         toReturn[i] = v\
  16401.     end\
  16402.     return toReturn\
  16403. end\
  16404. \
  16405. function TextBox.draw(self,addX,addY)\
  16406.     addX = addX or 0\
  16407.     addY = addY or 0\
  16408.     local finalX = self.xPos + addX\
  16409.     local finalY = self.yPos + addY\
  16410.     self.finalX = finalX\
  16411.     self.finalY = finalY\
  16412.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.bgColor)\
  16413.     term.setBackgroundColor(self.bgColor)\
  16414.     term.setCursorPos(self.finalX,self.finalY)\
  16415.     if self.text == \"\" or self.confidential then\
  16416.         term.setTextColor(self.helpFgColor)\
  16417.         term.write(self.helpText)\
  16418.     else\
  16419.         term.setTextColor(self.fgColor)\
  16420.         term.write(self.text)\
  16421.     end\
  16422. end\
  16423. \
  16424. function TextBox.read(self,_sReplaceChar, _tHistory)\
  16425.     paintutils.drawFilledBox(self.finalX,self.finalY,self.finalX+self.xLength-1,self.finalY+self.yLength-1,self.bgColor)\
  16426.     term.setTextColor(self.fgColor)\
  16427.     term.setCursorPos(self.finalX,self.finalY)\
  16428.     return read()\
  16429. end\
  16430. \
  16431. --Key Class\
  16432. function Key.new(input)\
  16433.     local self = {}\
  16434.     setmetatable(self,{__index = TextBox})\
  16435.     self.name = input.name\
  16436.     self.key = input.key\
  16437.     self.onPress = input.onPress or nil\
  16438.     return self\
  16439. end\
  16440. \
  16441. function Key.returnData(self)\
  16442.     local toReturn = {}\
  16443.     for i,v in pairs(self) do\
  16444.         toReturn[i] = v\
  16445.     end\
  16446.     return toReturn\
  16447. end\
  16448. \
  16449. \
  16450. \
  16451. --Event handler function--\
  16452. eventHandler = function(self)\
  16453.     local toAddX = self.xPos - 1\
  16454.     local toAddY = self.yPos - 1\
  16455.     while true do\
  16456.         local event, p1, p2, p3, p4, p5, p6 = os.pullEvent()\
  16457.         if event == \"mouse_click\" then\
  16458.             for i,v in pairs(self.Button) do\
  16459.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + v.xLength-1 + toAddX and v.finalY + toAddY <= p3 and p3 <= v.finalY + v.yLength-1 + toAddY then\
  16460.                     if p1 == 1 then\
  16461.                         if v.onLeftClick then \
  16462.                             v.onLeftClick()\
  16463.                         end\
  16464.                     elseif p1 == 2 then\
  16465.                         if v.onRightClick then\
  16466.                             v.onRightClick()\
  16467.                         end\
  16468.                     end\
  16469.                     return {\"Button\",tostring(v.returnValue),p1,p2,p3}\
  16470.                 end\
  16471.             end\
  16472.             for i,v in pairs(self.Toggle) do\
  16473.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + 3 + toAddX and v.finalY + toAddY == p3 then\
  16474.                     return {\"Toggle\",tostring(v.returnValue),p1,p2,p3}\
  16475.                 end\
  16476.             end\
  16477.             for i,v in pairs(self.BetterPaint) do \
  16478.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + v.xLength-1 + toAddX and v.finalY + toAddY <= p3 and p3 <= v.finalY + v.yLength-1 + toAddY then\
  16479.                     return {\"Button\",tostring(v.returnValue),p1,p2,p3}\
  16480.                 end\
  16481.             end\
  16482.             for i,v in pairs(self.TextBox) do \
  16483.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + v.xLength-1 + toAddX and v.finalY + toAddY <= p3 and p3 <= v.finalY + v.yLength-1 + toAddY then\
  16484.                     return {\"TextBox\",tostring(v.returnValue),p1,p2,p3}\
  16485.                 end\
  16486.             end\
  16487.             if self.nilClick then\
  16488.                 if not (self.xPos <= p2 and p2 <= self.xPos+self.xLength-1 and self.yPos <= p3 and p3 <= self.yPos+self.yLength-1) then\
  16489.                     return {\"Nil\",\"Nil\",p1,p2,p3}\
  16490.                 end\
  16491.             end\
  16492.         elseif event == \"key\" then\
  16493.             local pressedKey = p1\
  16494.             for i,v in pairs(self.Key) do\
  16495.                 if v.key == KeyCodes[pressedKey] then\
  16496.                     if v.onPress then\
  16497.                         v.onPress()\
  16498.                     else\
  16499.                         return {\"Key\",KeyCodes[pressedKey],pressedKey}\
  16500.                     end\
  16501.                 end\
  16502. \
  16503.             end\
  16504.         elseif event == \"monitor_touch\" then\
  16505.             os.queueEvent(\"mouse_click\", p1, p2, p3, p4, p5, p6)\
  16506.         end\
  16507.     end\
  16508. end\
  16509. \
  16510. --Load Function--\
  16511. function Initialize()\
  16512.     local toReturn = {}\
  16513.     toReturn.Button = Button\
  16514.     toReturn.Layout = Layout\
  16515.     toReturn.Toggle = Toggle\
  16516.     toReturn.BackgroundColor = BackgroundColor\
  16517.     toReturn.ColorField = ColorField\
  16518.     toReturn.BetterPaint = BetterPaint\
  16519.     toReturn.Text = Text\
  16520.     toReturn.TextBox = TextBox\
  16521.     toReturn.Key = Key\
  16522.     toReturn.eventHandler = eventHandler\
  16523.     toReturn.loadObjects = loadObjects\
  16524.     toReturn.loadLayout = loadLayout\
  16525.     return toReturn\
  16526. end",
  16527.       },
  16528.       [ "README.md" ] = "# Interact\
  16529. Interact is the GUI API developed by me for the need of TheOS.",
  16530.       [ ".ignoreme" ] = "{\
  16531.  [\".git\"] = true,\
  16532.  [\".ignoreme\"] = true,\
  16533.  [\"LICENSE\"] = true,\
  16534.  [\"README.md\"] = true,\
  16535.  [\"Backup\"] = true,\
  16536. }",
  16537.       [ "KeyCodes.lua" ] = "local Keys = {\
  16538. [ 2 ] =  1 ,\
  16539. [ 3 ] =  2,\
  16540. [ 4 ] =  3,\
  16541. [ 5 ] =  4,\
  16542. [ 6 ] =  5,\
  16543. [ 7 ] =  6,\
  16544. [ 8 ] =  7,\
  16545. [ 9 ] =  8,\
  16546. [ 10 ] =  9,\
  16547. [ 11 ] =  0,\
  16548. [ 12 ] = \"-\",\
  16549. [ 13 ] = \"=\",\
  16550. [ 14 ] = \"Backspace\",\
  16551. [ 15 ] = \"Tab\",\
  16552. [ 16 ] = \"Q\",\
  16553. [ 17 ] = \"W\",\
  16554. [ 18 ] = \"E\",\
  16555. [ 19 ] = \"R\",\
  16556. [ 20 ] = \"T\",\
  16557. [ 21 ] = \"Y\",\
  16558. [ 22 ] = \"U\",\
  16559. [ 23 ] = \"I\",\
  16560. [ 24 ] = \"O\",\
  16561. [ 25 ] = \"P\",\
  16562. [ 26 ] = \"LeftBracket\",\
  16563. [ 27 ] = \"RightBracket\",\
  16564. [ 28 ] = \"Enter\",\
  16565. [ 29 ] = \"LeftControl\",\
  16566. [ 30 ] = \"A\",\
  16567. [ 31 ] = \"S\",\
  16568. [ 32 ] = \"D\",\
  16569. [ 33 ] = \"F\",\
  16570. [ 34 ] = \"G\",\
  16571. [ 35 ] = \"H\",\
  16572. [ 36 ] = \"J\",\
  16573. [ 37 ] = \"K\",\
  16574. [ 38 ] = \"L\",\
  16575. [ 39 ] = \";\",\
  16576. [ 40 ] = \"\\'\",\
  16577. [ 41 ] = \"`\",\
  16578. [ 42 ] = \"LeftShift\",\
  16579. [ 43 ] = \"Backslash\",\
  16580. [ 44 ] = \"Z\",\
  16581. [ 45 ] = \"X\",\
  16582. [ 46 ] = \"C\",\
  16583. [ 47 ] = \"V\",\
  16584. [ 48 ] = \"B\",\
  16585. [ 49 ] = \"N\",\
  16586. [ 50 ] = \"M\",\
  16587. [ 51 ] = \",\",\
  16588. [ 52 ] = \".\",\
  16589. [ 53 ] = \"/\",\
  16590. [ 54 ] = \"RightShift\",\
  16591. [ 55 ] = \"*\",\
  16592. [ 56 ] = \"LeftAlt\",\
  16593. [ 57 ] = \" \",\
  16594. [ 58 ] = \"CapsLock\",\
  16595. [ 59 ] = \"F1\",\
  16596. [ 60 ] = \"F2\",\
  16597. [ 61 ] = \"F3\",\
  16598. [ 62 ] = \"F4\",\
  16599. [ 63 ] = \"F5\",\
  16600. [ 64 ] = \"F6\",\
  16601. [ 65 ] = \"F7\",\
  16602. [ 66 ] =  \"F8\",\
  16603. [ 67 ] =  \"F9\",\
  16604. [ 68 ] =  \"F10\",\
  16605. [ 69 ] = \"NumberLock\",\
  16606. [ 70 ] = \"ScrollLock\",\
  16607. [ 71 ] = \"NumPAd7\",\
  16608. [ 72 ] = \"NumPAd8\",\
  16609. [ 73 ] = \"NumPAd9\",\
  16610. [ 74 ] = \"Substract\",\
  16611. [ 75 ] = \"NumPAd4\",\
  16612. [ 76 ] = \"NumPAd5\",\
  16613. [ 77 ] = \"NumPAd6\",\
  16614. [ 78 ] = \"Add\",\
  16615. [ 79 ] = \"NumPAd1\",\
  16616. [ 80 ] = \"NumPAd2\",\
  16617. [ 81 ] = \"NumPAd3\",\
  16618. [ 82 ] = \"NumPAd0\",\
  16619. [ 83 ] = \"Decimal\",\
  16620. [ 87 ] = \"F11\",\
  16621. [ 88 ] = \"F12\",\
  16622. [ 100] = \"F13\",\
  16623. [ 101] = \"F14\",\
  16624. [ 102] = \"F15\",\
  16625. [ 103] = \"F16\",\
  16626. [ 104] = \"F17\",\
  16627. [ 105] = \"F18\",\
  16628. [ 112] = \"Kana\",\
  16629. [ 113] = \"F19\",\
  16630. [ 121] = \"Convert\",\
  16631. [ 123] = \"Noconvert\",\
  16632. [ 125] = \"Yen\",\
  16633. [ 141] = \"NumPadEquals\",\
  16634. [ 144] = \"^\",\
  16635. [ 145] = \"@\",\
  16636. [ 146] = \":\",\
  16637. [ 147] = \"_\",\
  16638. [ 148] = \"Kanji\",\
  16639. [ 149] = \"Stop\",\
  16640. [ 150] = \"Ax\",\
  16641. [ 151] = \"Unlabeled\",\
  16642. [ 156] = \"NumPadEnter\",\
  16643. [ 157] = \"RightControl\",\
  16644. [ 157] = \"Section\",\
  16645. [ 179] = \"NumPadComma\",\
  16646. [ 181] = \"Dvide\",\
  16647. [ 183] = \"Sysrq\",\
  16648. [ 184] = \"RightAlt\",\
  16649. [ 196] = \"Function\",\
  16650. [ 197] = \"Pause\",\
  16651. [ 199] = \"Home\",\
  16652. [ 200] = \"Up\",\
  16653. [ 201] = \"PageUp\",\
  16654. [ 203] = \"Left\",\
  16655. [ 205] = \"Right\",\
  16656. [ 207] = \"End\",\
  16657. [ 208] = \"Down\",\
  16658. [ 209] = \"PageDown\",\
  16659. [ 210] = \"Insert\",\
  16660. [ 211] = \"Delete\",\
  16661. }",
  16662.       [ ".git" ] = "gitdir: ../../.git/modules/API/Interact",
  16663.       [ "NewInteract.lua" ] = "--[[\
  16664.     Interact API in ComputerCraft\
  16665.     by Creator\
  16666.     Complete rewrite in OOP\
  16667. ]]--\
  16668. \
  16669. --Variables\
  16670. local textutilsserialize = textutils.serialize\
  16671. local textutilsunserialize = textutils.unserialize\
  16672. local KeyCodes = {\
  16673.     [ 2 ] =  1 ,\
  16674.     [ 3 ] =  2,\
  16675.     [ 4 ] =  3,\
  16676.     [ 5 ] =  4,\
  16677.     [ 6 ] =  5,\
  16678.     [ 7 ] =  6,\
  16679.     [ 8 ] =  7,\
  16680.     [ 9 ] =  8,\
  16681.     [ 10 ] =  9,\
  16682.     [ 11 ] =  0,\
  16683.     [ 12 ] = \"-\",\
  16684.     [ 13 ] = \"=\",\
  16685.     [ 14 ] = \"Backspace\",\
  16686.     [ 15 ] = \"Tab\",\
  16687.     [ 16 ] = \"q\",\
  16688.     [ 17 ] = \"w\",\
  16689.     [ 18 ] = \"e\",\
  16690.     [ 19 ] = \"r\",\
  16691.     [ 20 ] = \"t\",\
  16692.     [ 21 ] = \"y\",\
  16693.     [ 22 ] = \"u\",\
  16694.     [ 23 ] = \"i\",\
  16695.     [ 24 ] = \"o\",\
  16696.     [ 25 ] = \"p\",\
  16697.     [ 26 ] = \"LeftBracket\",\
  16698.     [ 27 ] = \"RightBracket\",\
  16699.     [ 28 ] = \"Enter\",\
  16700.     [ 29 ] = \"LeftControl\",\
  16701.     [ 30 ] = \"a\",\
  16702.     [ 31 ] = \"s\",\
  16703.     [ 32 ] = \"d\",\
  16704.     [ 33 ] = \"f\",\
  16705.     [ 34 ] = \"g\",\
  16706.     [ 35 ] = \"h\",\
  16707.     [ 36 ] = \"j\",\
  16708.     [ 37 ] = \"k\",\
  16709.     [ 38 ] = \"l\",\
  16710.     [ 39 ] = \";\",\
  16711.     [ 40 ] = \"\\'\",\
  16712.     [ 41 ] = \"`\",\
  16713.     [ 42 ] = \"LeftShift\",\
  16714.     [ 43 ] = \"Backslash\",\
  16715.     [ 44 ] = \"z\",\
  16716.     [ 45 ] = \"x\",\
  16717.     [ 46 ] = \"c\",\
  16718.     [ 47 ] = \"v\",\
  16719.     [ 48 ] = \"b\",\
  16720.     [ 49 ] = \"n\",\
  16721.     [ 50 ] = \"m\",\
  16722.     [ 51 ] = \",\",\
  16723.     [ 52 ] = \".\",\
  16724.     [ 53 ] = \"/\",\
  16725.     [ 54 ] = \"RightShift\",\
  16726.     [ 55 ] = \"*\",\
  16727.     [ 56 ] = \"LeftAlt\",\
  16728.     [ 57 ] = \" \",\
  16729.     [ 58 ] = \"CapsLock\",\
  16730.     [ 59 ] = \"F1\",\
  16731.     [ 60 ] = \"F2\",\
  16732.     [ 61 ] = \"F3\",\
  16733.     [ 62 ] = \"F4\",\
  16734.     [ 63 ] = \"F5\",\
  16735.     [ 64 ] = \"F6\",\
  16736.     [ 65 ] = \"F7\",\
  16737.     [ 66 ] = \"F8\",\
  16738.     [ 67 ] = \"F9\",\
  16739.     [ 68 ] = \"F10\",\
  16740.     [ 69 ] = \"NumberLock\",\
  16741.     [ 70 ] = \"ScrollLock\",\
  16742.     [ 71 ] = \"NumPAd7\",\
  16743.     [ 72 ] = \"NumPAd8\",\
  16744.     [ 73 ] = \"NumPAd9\",\
  16745.     [ 74 ] = \"Substract\",\
  16746.     [ 75 ] = \"NumPAd4\",\
  16747.     [ 76 ] = \"NumPAd5\",\
  16748.     [ 77 ] = \"NumPAd6\",\
  16749.     [ 78 ] = \"Add\",\
  16750.     [ 79 ] = \"NumPAd1\",\
  16751.     [ 80 ] = \"NumPAd2\",\
  16752.     [ 81 ] = \"NumPAd3\",\
  16753.     [ 82 ] = \"NumPAd0\",\
  16754.     [ 83 ] = \"Decimal\",\
  16755.     [ 87 ] = \"F11\",\
  16756.     [ 88 ] = \"F12\",\
  16757.     [ 100] = \"F13\",\
  16758.     [ 101] = \"F14\",\
  16759.     [ 102] = \"F15\",\
  16760.     [ 103] = \"F16\",\
  16761.     [ 104] = \"F17\",\
  16762.     [ 105] = \"F18\",\
  16763.     [ 112] = \"Kana\",\
  16764.     [ 113] = \"F19\",\
  16765.     [ 121] = \"Convert\",\
  16766.     [ 123] = \"Noconvert\",\
  16767.     [ 125] = \"Yen\",\
  16768.     [ 141] = \"NumPadEquals\",\
  16769.     [ 144] = \"^\",\
  16770.     [ 145] = \"@\",\
  16771.     [ 146] = \":\",\
  16772.     [ 147] = \"_\",\
  16773.     [ 148] = \"Kanji\",\
  16774.     [ 149] = \"Stop\",\
  16775.     [ 150] = \"Ax\",\
  16776.     [ 151] = \"Unlabeled\",\
  16777.     [ 156] = \"NumPadEnter\",\
  16778.     [ 157] = \"RightControl\",\
  16779.     [ 157] = \"Section\",\
  16780.     [ 179] = \"NumPadComma\",\
  16781.     [ 181] = \"Dvide\",\
  16782.     [ 183] = \"Sysrq\",\
  16783.     [ 184] = \"RightAlt\",\
  16784.     [ 196] = \"Function\",\
  16785.     [ 197] = \"Pause\",\
  16786.     [ 199] = \"Home\",\
  16787.     [ 200] = \"Up\",\
  16788.     [ 201] = \"PageUp\",\
  16789.     [ 203] = \"Left\",\
  16790.     [ 205] = \"Right\",\
  16791.     [ 207] = \"End\",\
  16792.     [ 208] = \"Down\",\
  16793.     [ 209] = \"PageDown\",\
  16794.     [ 210] = \"Insert\",\
  16795.     [ 211] = \"Delete\",\
  16796. }\
  16797. \
  16798. --Class declarations--\
  16799. local Button = {}\
  16800. local Layout = {}\
  16801. local Toggle = {}\
  16802. local BackgroundColor = {}\
  16803. local ColorField = {}\
  16804. local BetterPaint = {}\
  16805. local Text = {}\
  16806. local TextBox = {}\
  16807. local Key = {}\
  16808. \
  16809. function loadObjects(self)\
  16810.     local output = {}\
  16811.     output.Button = {}\
  16812.     output.Toggle = {}\
  16813.     output.ColorField = {}\
  16814.     output.BetterPaint = {}\
  16815.     output.Text = {}\
  16816.     output.TextBox = {}\
  16817.     output.Key = {}\
  16818.     output.Layout = {}\
  16819.     for o,v in pairs(output) do\
  16820.         if self[o] == nil then\
  16821.             self[o] = {}\
  16822.         end\
  16823.     end\
  16824.     for i,v in pairs(self.Button) do\
  16825.         output.Button[i] = Button.new(self.Button[i])\
  16826.     end\
  16827.     for i,v in pairs(self.Toggle) do\
  16828.         output.Toggle[i] = Toggle.new(self.Toggle[i])\
  16829.     end\
  16830.     for i,v in pairs(self.ColorField) do\
  16831.         output.ColorField[i] = ColorField.new(self.ColorField[i])\
  16832.     end\
  16833.     for i,v in pairs(self.BetterPaint) do\
  16834.         output.BetterPaint[i] = BetterPaint.new(self.BetterPaint[i])\
  16835.     end\
  16836.     for i,v in pairs(self.Text) do\
  16837.         output.Text[i] = Text.new(self.Text[i])\
  16838.     end\
  16839.     for i,v in pairs(self.TextBox) do\
  16840.         output.TextBox[i] = TextBox.new(self.TextBox[i])\
  16841.     end\
  16842.     for i,v in pairs(self.Key) do\
  16843.         output.Key[i] = Key.new(self.Key[i])\
  16844.     end\
  16845.     for i,v in pairs(self.Layout) do\
  16846.         output.Layout[i] = Layout.new(self.Layout[i])\
  16847.     end\
  16848.     output.BackgroundColor = self.BackgroundColor or 1\
  16849.     output.nilClick = self.nilClick or false\
  16850.     return output\
  16851. end\
  16852. \
  16853. function loadLayout(input,output)\
  16854.     for i,v in pairs(input.Button) do\
  16855.         output:addButton(input.Button[i])\
  16856.     end\
  16857.     for i,v in pairs(input.Toggle) do\
  16858.         output:addToggle(input.Toggle[i])\
  16859.     end\
  16860.     for i,v in pairs(input.ColorField) do\
  16861.         output:addColorField(input.ColorField[i])\
  16862.     end\
  16863.     for i,v in pairs(input.BetterPaint) do\
  16864.         output:addBetterPaint(input.BetterPaint[i])\
  16865.     end\
  16866.     for i,v in pairs(input.Text) do\
  16867.         output:addText(input.Text[i])\
  16868.     end\
  16869.     for i,v in pairs(input.TextBox) do\
  16870.         output:addTextBox(input.TextBox[i])\
  16871.     end\
  16872.     for i,v in pairs(input.Key) do\
  16873.         output:addKey(input.Key[i])\
  16874.     end\
  16875.     for i,v in pairs(input.Layout) do\
  16876.         output:addLayout(input.Layout[i])\
  16877.     end\
  16878.     output.BackgroundColor = input.BackgroundColor\
  16879.     output.nilClick = input.nilClick\
  16880. end\
  16881. \
  16882. --Class Layout--\
  16883. --Layout initialization function--\
  16884. Layout.new = function(input)\
  16885.     local self = {}\
  16886.     setmetatable(self,{__index = Layout})\
  16887.     self.Button = {}\
  16888.     self.Toggle = {}\
  16889.     self.ColorField = {}\
  16890.     self.BetterPaint = {}\
  16891.     self.Text = {}\
  16892.     self.TextBox = {}\
  16893.     self.Key = {}\
  16894.     self.Layout = {}\
  16895.     for i,v in pairs(self) do\
  16896.         if input[i] == nil then\
  16897.             input[i] = {}\
  16898.         end\
  16899.     end\
  16900.     self.BackgroundColor = 1\
  16901.     self.xPos = input.xPos or 1\
  16902.     self.yPos = input.yPos or 1\
  16903.     self.xLength = input.xLength or 51\
  16904.     self.yLength = input.yLength or 19\
  16905.     self.nilClick = input.nilClick or false\
  16906.     self.window = Screen.new(term.current(),self.xPos,self.yPos,self.xLength,self.yLength)\
  16907.     for i,v in pairs(input.Button) do\
  16908.         self:addButton(input.Button[i])\
  16909.     end\
  16910.     for i,v in pairs(input.Toggle) do\
  16911.         self:addToggle(input.Toggle[i])\
  16912.     end\
  16913.     for i,v in pairs(input.ColorField) do\
  16914.         self:addColorField(input.ColorField[i])\
  16915.     end\
  16916.     for i,v in pairs(input.BetterPaint) do\
  16917.         self:addBetterPaint(input.BetterPaint[i])\
  16918.     end\
  16919.     for i,v in pairs(input.Text) do\
  16920.         self:addText(input.Text[i])\
  16921.     end\
  16922.     for i,v in pairs(input.TextBox) do\
  16923.         self:addTextBox(input.TextBox[i])\
  16924.     end\
  16925.     for i,v in pairs(input.Key) do\
  16926.         self:addKey(input.Key[i])\
  16927.     end\
  16928.     for i,v in pairs(input.Layout) do\
  16929.         self:addLayout(input.Layout[i])\
  16930.     end\
  16931.     self.BackgroundColor = input.BackgroundColor\
  16932.     self.nilClick = input.nilClick\
  16933.     return self\
  16934. end\
  16935. \
  16936. --Add element function--\
  16937. Layout.addButton = function(self,_elementData)\
  16938.     setmetatable(_elementData,{__index = Button})\
  16939.     self.Button[_elementData.name] = _elementData\
  16940. end\
  16941. \
  16942. Layout.addToggle = function(self,_elementData)\
  16943.     setmetatable(_elementData,{__index = Toggle})\
  16944.     self.Toggle[_elementData.name] = _elementData\
  16945. end\
  16946. \
  16947. Layout.addBackgroundColor = function(self,_elementData)\
  16948.     self.BackgroundColor = _elementData.color\
  16949. end\
  16950. \
  16951. Layout.addColorField = function(self,_elementData)\
  16952.     setmetatable(_elementData,{__index = ColorField})\
  16953.     self.ColorField[_elementData.name] = _elementData\
  16954. end\
  16955. \
  16956. Layout.addBetterPaint = function(self,_elementData)\
  16957.     setmetatable(_elementData,{__index = BetterPaint})\
  16958.     self.BetterPaint[_elementData.name] = _elementData\
  16959. end\
  16960. \
  16961. Layout.addText = function(self,_elementData)\
  16962.     setmetatable(_elementData,{__index = Text})\
  16963.     self.Text[_elementData.name] = _elementData\
  16964. end\
  16965. \
  16966. Layout.addTextBox = function(self,_elementData)\
  16967.     setmetatable(_elementData,{__index = TextBox})\
  16968.     self.TextBox[_elementData.name] = _elementData\
  16969. end\
  16970. \
  16971. Layout.addKey = function(self,_elementData)\
  16972.     setmetatable(_elementData,{__index = Key})\
  16973.     self.Key[_elementData.name] = _elementData\
  16974. end\
  16975. \
  16976. Layout.addLayout = function(self,_elementData)\
  16977.     self.Layout[_elementData.name] = Layout.new(_elementData)\
  16978. end\
  16979. \
  16980. Layout.draw = function(self,xPlus,yPlus)\
  16981.     xPlus = xPlus or 0\
  16982.     yPlus = yPlus or 0\
  16983.     self.finalX = xPlus\
  16984.     self.finalY = yPlus\
  16985.     local oldTerm = term.current()\
  16986.     term.redirect(self.window)\
  16987.     local buttonFunctions = {}\
  16988.     local toggleFunctions = {}\
  16989.     local colorFieldFunctions = {}\
  16990.     local betterPaintFunctions = {}\
  16991.     local textFunctions = {}\
  16992.     local textBoxFunctions = {}\
  16993.     local layoutFunctions = {}\
  16994.     setmetatable(buttonFunctions,{__index = Button})\
  16995.     setmetatable(toggleFunctions,{__index = Toggle})\
  16996.     setmetatable(colorFieldFunctions,{__index = ColorField})\
  16997.     setmetatable(betterPaintFunctions,{__index = BetterPaint})\
  16998.     setmetatable(textFunctions,{__index = Text})\
  16999.     setmetatable(textBoxFunctions,{__index = TextBox})\
  17000.     setmetatable(layoutFunctions,{__index = Layout})\
  17001.     paintutils.drawFilledBox(1,1,self.xLength,self.yLength,self.BackgroundColor)\
  17002.     for i,v in pairs(self.ColorField) do\
  17003.         colorFieldFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  17004.     end\
  17005.     for i,v in pairs(self.Button) do\
  17006.         buttonFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  17007.     end\
  17008.     for i,v in pairs(self.BetterPaint) do\
  17009.         betterPaintFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  17010.     end\
  17011.     for i,v in pairs(self.Toggle) do\
  17012.         toggleFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  17013.     end\
  17014.     for i,v in pairs(self.Text) do\
  17015.         textFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  17016.     end\
  17017.     for i,v in pairs(self.TextBox) do\
  17018.         textBoxFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  17019.     end\
  17020.     for i,v in pairs(self.Layout) do\
  17021.         layoutFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  17022.     end\
  17023.     term.redirect(oldTerm)\
  17024. end\
  17025. \
  17026. --Class Button--\
  17027. --Button initialization function\
  17028. Button.new = function(input)\
  17029.     local self = {}\
  17030.     setmetatable(self,{__index = Button})\
  17031.     self.name = input.name\
  17032.     self.label = input.label\
  17033.     self.xPos = input.xPos\
  17034.     self.yPos = input.yPos\
  17035.     self.fgColor = input.fgColor\
  17036.     self.bgColor = input.bgColor\
  17037.     self.xLength = input.xLength\
  17038.     self.yLength = input.yLength\
  17039.     self.returnValue = input.returnValue\
  17040.     self.xTextPos = input.xTextPos\
  17041.     self.yTextPos = input.yTextPos\
  17042.     self.onRightClick = input.onRightClick or nil\
  17043.     self.onLeftClick = input.onLeftClick or nil\
  17044.     return self\
  17045. end\
  17046. \
  17047. --Draw function\
  17048. Button.draw = function(self,addX,addY)\
  17049.     addX = addX or 0\
  17050.     addY = addY or 0\
  17051.     local finalX = self.xPos + addX\
  17052.     local finalY = self.yPos + addY\
  17053. \
  17054.     self.finalX = finalX\
  17055.     self.finalY = finalY\
  17056.     local newText\
  17057.     if #self.label > self.xLength then\
  17058.         newText = string.sub(self.label,1,self.xLength)\
  17059.     else\
  17060.         newText = self.label\
  17061.     end\
  17062.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.bgColor)\
  17063.     term.setTextColor(self.fgColor)\
  17064.     term.setCursorPos(finalX+self.xTextPos-1,finalY+self.yTextPos-1)\
  17065.     term.write(newText)\
  17066. end\
  17067. \
  17068. --Return function--\
  17069. Button.returnData = function(self)\
  17070.     local toReturn = {}\
  17071.     for i,v in pairs(self) do\
  17072.         toReturn[i] = v\
  17073.     end\
  17074.     return toReturn\
  17075. end\
  17076. \
  17077. --Sample Input table--\
  17078. example = [[\
  17079.     example = {\
  17080.         name = \"quickSettings\",\
  17081.         label = \">\",\
  17082.         xPos = 1,\
  17083.         yPos = 3,\
  17084.         xLength = 1,\
  17085.         yLength = 6,\
  17086.         xTextPos = 1,\
  17087.         yTextPos = 1,\
  17088.         fgColor = colors.blue,\
  17089.         bgColor = colors.lightGray,\
  17090.         returnValue = \"quickSettings\",\
  17091.     },\
  17092. ]]\
  17093. \
  17094. --Class Toggle--\
  17095. --Initialize Toggle Object--\
  17096. Toggle.new = function(input)\
  17097.     local self = {}\
  17098.     setmetatable(self,{__index = Toggle})\
  17099.     self.name = input.name or \"randomName\"\
  17100.     self.state = input.state or true\
  17101.     self.xPos = input.xPos or 1\
  17102.     self.yPos = input.yPos or 1\
  17103.     self.trueColor = input.trueColor or colors.green\
  17104.     self.falseColor = input.falseColor or colors.red\
  17105.     self.trueText = input.trueText or \"T\"\
  17106.     self.falseText = input.falseText or \"F\"\
  17107.     self.selectedBg = input.selectedBg or colors.gray\
  17108.     self.notSelectedBg = input.notSelectedBg or colors.lightGray\
  17109.     self.returnValue = input.returnValue or \"mmmmmmm\"\
  17110.     self.moveX = input.moveX or false\
  17111.     self.moveY = input.moveY or false\
  17112.     self.onRightClick = input.onRightClick or nil\
  17113.     self.onLeftClick = input.onLeftClick or nil\
  17114.     return self\
  17115. end\
  17116. \
  17117. function Toggle.draw(self,addX,addY)\
  17118.     addX = addX or 0\
  17119.     addY = addY or 0\
  17120.     local finalX = self.xPos + addX\
  17121.     local finalY = self.yPos + addY\
  17122.     self.finalX = finalX\
  17123.     self.finalY = finalY\
  17124.     term.setCursorPos(finalX,finalY)\
  17125.     if self.state == false then\
  17126.         term.setBackgroundColor(self.notSelectedBg)\
  17127.         term.setTextColor(self.trueColor)\
  17128.         term.write(string.sub(self.trueText,1,1))\
  17129.         term.setBackgroundColor(self.selectedBg)\
  17130.         term.setTextColor(self.falseColor)\
  17131.         term.write(\" \"..string.sub(self.falseText,1,1)..\" \")\
  17132.     elseif self.state == true then\
  17133.         term.setBackgroundColor(self.selectedBg)\
  17134.         term.setTextColor(self.trueColor)\
  17135.         term.write(\" \"..string.sub(self.trueText,1,1)..\" \")\
  17136.         term.setBackgroundColor(self.notSelectedBg)\
  17137.         term.setTextColor(self.falseColor)\
  17138.         term.write(string.sub(self.falseText,1,1))\
  17139.     end\
  17140. end\
  17141. \
  17142. function Toggle.returnData(self)\
  17143.     local toReturn = {}\
  17144.     for i,v in pairs(self) do\
  17145.         toReturn[i] = v\
  17146.     end\
  17147.     return toReturn\
  17148. end\
  17149. \
  17150. function Toggle.toggle(self)\
  17151.     if self.state == true then\
  17152.         self.state = false\
  17153.     else\
  17154.         self.state = true\
  17155.     end\
  17156. end\
  17157. \
  17158. function Toggle.getState(self)\
  17159.     return self.state\
  17160. end\
  17161. \
  17162. --BackgroundColor Class--\
  17163. function BackgroundColor.new(input)\
  17164.     local self = {}\
  17165.     setmetatable(self,{__index = BackgroundColor})\
  17166.     self.color = input.color\
  17167.     return self\
  17168. end\
  17169. \
  17170. function BackgroundColor.setColor(self,color)\
  17171.     self.color = color\
  17172. end\
  17173. \
  17174. function BackgroundColor.returnData(self)\
  17175.     local toReturn = {}\
  17176.     for i,v in pairs(self) do\
  17177.         toReturn[i] = v\
  17178.     end\
  17179.     return toReturn\
  17180. end\
  17181. \
  17182. --ColorField Class--\
  17183. function ColorField.new(input)\
  17184.     local self = {}\
  17185.     setmetatable(self,{__index = ColorField})\
  17186.     self.name = input.name\
  17187.     self.xPos = input.xPos\
  17188.     self.yPos = input.yPos\
  17189.     self.xLength = input.xLength\
  17190.     self.yLength = input.yLength\
  17191.     self.color = input.color\
  17192.     self.moveX = input.moveX or false\
  17193.     self.moveY = input.moveY or false\
  17194.     return self\
  17195. end\
  17196. \
  17197. function  ColorField.draw(self,addX,addY)\
  17198.     addX = addX or 0\
  17199.     addY = addY or 0\
  17200.     local finalX = self.xPos + addX\
  17201.     local finalY = self.yPos + addY\
  17202.     self.finalX = finalX\
  17203.     self.finalY = finalY\
  17204.     term.setTextColor(colors.black)\
  17205.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.color)\
  17206. end\
  17207. \
  17208. function ColorField.returnData(self)\
  17209.     local toReturn = {}\
  17210.     for i,v in pairs(self) do\
  17211.         toReturn[i] = v\
  17212.     end\
  17213.     return toReturn\
  17214. end\
  17215. \
  17216. --BetterPaint Class--\
  17217. function BetterPaint.new(input)\
  17218.     local self = {}\
  17219.     setmetatable(self,{__index = BetterPaint})\
  17220.     self.xPos = input.xPos\
  17221.     self.yPos = input.yPos\
  17222.     self.name = input.name\
  17223.     self.path = input.path\
  17224.     self.xLength = input.xLength\
  17225.     self.yLength = input.yLength\
  17226.     self.returnValue = input.returnValue\
  17227.     self.label = input.label\
  17228.     self.labelBg = input.labelBg\
  17229.     self.labelFg = input.labelFg\
  17230.     self.moveX = input.moveX or false\
  17231.     self.moveY = input.moveY or false\
  17232.     self.onRightClick = input.onRightClick or nil\
  17233.     self.onLeftClick = input.onLeftClick or nil\
  17234.     return self\
  17235. end\
  17236. \
  17237. function BetterPaint.returnData(self)\
  17238.     local toReturn = {}\
  17239.     for i,v in pairs(self) do\
  17240.         toReturn[i] = v\
  17241.     end\
  17242.     return toReturn\
  17243. end\
  17244. \
  17245. function BetterPaint.draw(self,addX,addY)\
  17246.     addX = addX or 0\
  17247.     addY = addY or 0\
  17248.     local finalX = self.xPos + addX\
  17249.     local finalY = self.yPos + addY\
  17250.     self.finalX = finalX\
  17251.     self.finalY = finalY\
  17252.     paint.drawImage(self.path,finalX,finalY)\
  17253.     term.setCursorPos(finalX,finalY+self.yLength)\
  17254.     term.setTextColor(self.labelFg)\
  17255.     term.setBackgroundColor(self.labelBg)\
  17256.     term.write(self.label)\
  17257. end\
  17258. \
  17259. --Text Class--\
  17260. function Text.new(input)\
  17261.     local self = {}\
  17262.     setmetatable(self,{__index = Text})\
  17263.     self.name = input.name\
  17264.     self.text = input.text\
  17265.     self.xPos = input.xPos\
  17266.     self.yPos = input.yPos\
  17267.     self.bgColor = input.bgColor\
  17268.     self.fgColor = input.fgColor\
  17269.     return self\
  17270. end\
  17271. \
  17272. function Text.draw(self,addX,addY)\
  17273.     addX = addX or 0\
  17274.     addY = addY or 0\
  17275.     local finalX = self.xPos + addX\
  17276.     local finalY = self.yPos + addY\
  17277.     self.finalX = finalX\
  17278.     self.finalY = finalY\
  17279.     term.setCursorPos(finalX,finalY)\
  17280.     term.setTextColor(self.fgColor)\
  17281.     term.setBackgroundColor(self.bgColor)\
  17282.     term.write(self.text)\
  17283. end\
  17284. \
  17285. function Text.returnData(self)\
  17286.     local toReturn = {}\
  17287.     for i,v in pairs(self) do\
  17288.         toReturn[i] = v\
  17289.     end\
  17290.     return toReturn\
  17291. end\
  17292. \
  17293. --TextBox Class \
  17294. \
  17295. function TextBox.new(input)\
  17296.     local self = {}\
  17297.     setmetatable(self,{__index = TextBox})\
  17298.     self.name = input.name\
  17299.     self.helpText = input.helpText\
  17300.     self.xPos = input.xPos\
  17301.     self.yPos = input.yPos\
  17302.     self.xLength = input.xLength\
  17303.     self.yLength = input.yLength\
  17304.     self.bgColor = input.bgColor\
  17305.     self.fgColor = input.fgColor\
  17306.     self.helpFgColor = input.helpFgColor\
  17307.     self.charLimit = input.charLimit\
  17308.     self.moveX = input.moveX or false\
  17309.     self.moveY = input.moveY or false\
  17310.     self.text = \"\"\
  17311.     self.returnValue = input.returnValue\
  17312.     self.confidential = input.confidential or false\
  17313.     return self\
  17314. end\
  17315. \
  17316. function TextBox.returnData(self)\
  17317.     local toReturn = {}\
  17318.     for i,v in pairs(self) do\
  17319.         toReturn[i] = v\
  17320.     end\
  17321.     return toReturn\
  17322. end\
  17323. \
  17324. function TextBox.draw(self,addX,addY)\
  17325.     addX = addX or 0\
  17326.     addY = addY or 0\
  17327.     local finalX = self.xPos + addX\
  17328.     local finalY = self.yPos + addY\
  17329.     self.finalX = finalX\
  17330.     self.finalY = finalY\
  17331.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.bgColor)\
  17332.     term.setBackgroundColor(self.bgColor)\
  17333.     term.setCursorPos(self.finalX,self.finalY)\
  17334.     if self.text == \"\" or self.confidential then\
  17335.         term.setTextColor(self.helpFgColor)\
  17336.         term.write(self.helpText)\
  17337.     else\
  17338.         term.setTextColor(self.fgColor)\
  17339.         term.write(self.text)\
  17340.     end\
  17341. end\
  17342. \
  17343. function TextBox.read(self,_sReplaceChar, _tHistory)\
  17344.     paintutils.drawFilledBox(self.finalX,self.finalY,self.finalX+self.xLength-1,self.finalY+self.yLength-1,self.bgColor)\
  17345.     term.setTextColor(self.fgColor)\
  17346.     term.setCursorPos(self.finalX,self.finalY)\
  17347.     return read()\
  17348. end\
  17349. \
  17350. --Key Class\
  17351. function Key.new(input)\
  17352.     local self = {}\
  17353.     setmetatable(self,{__index = TextBox})\
  17354.     self.name = input.name\
  17355.     self.key = input.key\
  17356.     self.onPress = input.onPress or nil\
  17357.     return self\
  17358. end\
  17359. \
  17360. function Key.returnData(self)\
  17361.     local toReturn = {}\
  17362.     for i,v in pairs(self) do\
  17363.         toReturn[i] = v\
  17364.     end\
  17365.     return toReturn\
  17366. end\
  17367. \
  17368. local function localEventHandler(self,toAddX, toAddY, event, p1, p2, p3, p4, p5, p6)\
  17369.     while true do\
  17370.         if event == \"mouse_click\" then\
  17371.             for i,v in pairs(self.Button) do\
  17372.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + v.xLength-1 + toAddX and v.finalY + toAddY <= p3 and p3 <= v.finalY + v.yLength-1 + toAddY then\
  17373.                     if p1 == 1 then\
  17374.                         if v.onLeftClick then \
  17375.                             v.onLeftClick()\
  17376.                         end\
  17377.                     elseif p1 == 2 then\
  17378.                         if v.onRightClick then\
  17379.                             v.onRightClick()\
  17380.                         end\
  17381.                     end\
  17382.                     return {\"Button\",tostring(v.returnValue),p1,p2,p3}\
  17383.                 end\
  17384.             end\
  17385.             for i,v in pairs(self.Toggle) do\
  17386.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + 3 + toAddX and v.finalY + toAddY == p3 then\
  17387.                     return {\"Toggle\",tostring(v.returnValue),p1,p2,p3}\
  17388.                 end\
  17389.             end\
  17390.             for i,v in pairs(self.BetterPaint) do \
  17391.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + v.xLength-1 + toAddX and v.finalY + toAddY <= p3 and p3 <= v.finalY + v.yLength-1 + toAddY then\
  17392.                     return {\"Button\",tostring(v.returnValue),p1,p2,p3}\
  17393.                 end\
  17394.             end\
  17395.             for i,v in pairs(self.TextBox) do \
  17396.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + v.xLength-1 + toAddX and v.finalY + toAddY <= p3 and p3 <= v.finalY + v.yLength-1 + toAddY then\
  17397.                     return {\"TextBox\",tostring(v.returnValue),p1,p2,p3}\
  17398.                 end\
  17399.             end\
  17400.             for i,v in pairs(self.Layout) do \
  17401.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + v.xLength-1 + toAddX and v.finalY + toAddY <= p3 and p3 <= v.finalY + v.yLength-1 + toAddY then\
  17402.                     local toReturn = localEventHandler(v,v.finalX-1,v.finalY-1, event, p1, p2, p3, p4, p5, p6)\
  17403.                     return {toReturn[1],toReturn[2],p1,p2,p3}\
  17404.                 end\
  17405.             end\
  17406.             if self.nilClick then\
  17407.                 if not (self.xPos <= p2 and p2 <= self.xPos+self.xLength-1 and self.yPos <= p3 and p3 <= self.yPos+self.yLength-1) then\
  17408.                     return {\"Nil\",\"Nil\",p1,p2,p3}\
  17409.                 end\
  17410.             end\
  17411.         elseif event == \"key\" then\
  17412.             local pressedKey = p1\
  17413.             for i,v in pairs(self.Key) do\
  17414.                 if v.key == KeyCodes[pressedKey] then\
  17415.                     if v.onPress then\
  17416.                         v.onPress()\
  17417.                     else\
  17418.                         return {\"Key\",KeyCodes[pressedKey],pressedKey}\
  17419.                     end\
  17420.                 end\
  17421. \
  17422.             end\
  17423.         elseif event == \"monitor_touch\" then\
  17424.             os.queueEvent(\"mouse_click\", p1, p2, p3, p4, p5, p6)\
  17425.         end\
  17426.     end\
  17427. end\
  17428. \
  17429. --Event handler function--\
  17430. eventHandler = function(self)\
  17431. \
  17432.     return localEventHandler(self,self.xPos-1,self.yPos-1,os.pullEvent())\
  17433. end\
  17434. \
  17435. --Load Function--\
  17436. function Initialize()\
  17437.     local toReturn = {}\
  17438.     toReturn.Button = Button\
  17439.     toReturn.Layout = Layout\
  17440.     toReturn.Toggle = Toggle\
  17441.     toReturn.BackgroundColor = BackgroundColor\
  17442.     toReturn.ColorField = ColorField\
  17443.     toReturn.BetterPaint = BetterPaint\
  17444.     toReturn.Text = Text\
  17445.     toReturn.TextBox = TextBox\
  17446.     toReturn.Key = Key\
  17447.     toReturn.eventHandler = eventHandler\
  17448.     toReturn.loadObjects = loadObjects\
  17449.     toReturn.loadLayout = loadLayout\
  17450.     return toReturn\
  17451. end",
  17452.       LICENSE = "GNU GENERAL PUBLIC LICENSE\
  17453.                       Version 2, June 1991\
  17454. \
  17455. Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>\
  17456. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\
  17457. Everyone is permitted to copy and distribute verbatim copies\
  17458. of this license document, but changing it is not allowed.\
  17459. \
  17460.                            Preamble\
  17461. \
  17462.  The licenses for most software are designed to take away your\
  17463. freedom to share and change it.  By contrast, the GNU General Public\
  17464. License is intended to guarantee your freedom to share and change free\
  17465. software--to make sure the software is free for all its users.  This\
  17466. General Public License applies to most of the Free Software\
  17467. Foundation's software and to any other program whose authors commit to\
  17468. using it.  (Some other Free Software Foundation software is covered by\
  17469. the GNU Lesser General Public License instead.)  You can apply it to\
  17470. your programs, too.\
  17471. \
  17472.  When we speak of free software, we are referring to freedom, not\
  17473. price.  Our General Public Licenses are designed to make sure that you\
  17474. have the freedom to distribute copies of free software (and charge for\
  17475. this service if you wish), that you receive source code or can get it\
  17476. if you want it, that you can change the software or use pieces of it\
  17477. in new free programs; and that you know you can do these things.\
  17478. \
  17479.  To protect your rights, we need to make restrictions that forbid\
  17480. anyone to deny you these rights or to ask you to surrender the rights.\
  17481. These restrictions translate to certain responsibilities for you if you\
  17482. distribute copies of the software, or if you modify it.\
  17483. \
  17484.  For example, if you distribute copies of such a program, whether\
  17485. gratis or for a fee, you must give the recipients all the rights that\
  17486. you have.  You must make sure that they, too, receive or can get the\
  17487. source code.  And you must show them these terms so they know their\
  17488. rights.\
  17489. \
  17490.  We protect your rights with two steps: (1) copyright the software, and\
  17491. (2) offer you this license which gives you legal permission to copy,\
  17492. distribute and/or modify the software.\
  17493. \
  17494.  Also, for each author's protection and ours, we want to make certain\
  17495. that everyone understands that there is no warranty for this free\
  17496. software.  If the software is modified by someone else and passed on, we\
  17497. want its recipients to know that what they have is not the original, so\
  17498. that any problems introduced by others will not reflect on the original\
  17499. authors' reputations.\
  17500. \
  17501.  Finally, any free program is threatened constantly by software\
  17502. patents.  We wish to avoid the danger that redistributors of a free\
  17503. program will individually obtain patent licenses, in effect making the\
  17504. program proprietary.  To prevent this, we have made it clear that any\
  17505. patent must be licensed for everyone's free use or not licensed at all.\
  17506. \
  17507.  The precise terms and conditions for copying, distribution and\
  17508. modification follow.\
  17509. \
  17510.                    GNU GENERAL PUBLIC LICENSE\
  17511.   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\
  17512. \
  17513.  0. This License applies to any program or other work which contains\
  17514. a notice placed by the copyright holder saying it may be distributed\
  17515. under the terms of this General Public License.  The \"Program\", below,\
  17516. refers to any such program or work, and a \"work based on the Program\"\
  17517. means either the Program or any derivative work under copyright law:\
  17518. that is to say, a work containing the Program or a portion of it,\
  17519. either verbatim or with modifications and/or translated into another\
  17520. language.  (Hereinafter, translation is included without limitation in\
  17521. the term \"modification\".)  Each licensee is addressed as \"you\".\
  17522. \
  17523. Activities other than copying, distribution and modification are not\
  17524. covered by this License; they are outside its scope.  The act of\
  17525. running the Program is not restricted, and the output from the Program\
  17526. is covered only if its contents constitute a work based on the\
  17527. Program (independent of having been made by running the Program).\
  17528. Whether that is true depends on what the Program does.\
  17529. \
  17530.  1. You may copy and distribute verbatim copies of the Program's\
  17531. source code as you receive it, in any medium, provided that you\
  17532. conspicuously and appropriately publish on each copy an appropriate\
  17533. copyright notice and disclaimer of warranty; keep intact all the\
  17534. notices that refer to this License and to the absence of any warranty;\
  17535. and give any other recipients of the Program a copy of this License\
  17536. along with the Program.\
  17537. \
  17538. You may charge a fee for the physical act of transferring a copy, and\
  17539. you may at your option offer warranty protection in exchange for a fee.\
  17540. \
  17541.  2. You may modify your copy or copies of the Program or any portion\
  17542. of it, thus forming a work based on the Program, and copy and\
  17543. distribute such modifications or work under the terms of Section 1\
  17544. above, provided that you also meet all of these conditions:\
  17545. \
  17546.    a) You must cause the modified files to carry prominent notices\
  17547.    stating that you changed the files and the date of any change.\
  17548. \
  17549.    b) You must cause any work that you distribute or publish, that in\
  17550.    whole or in part contains or is derived from the Program or any\
  17551.    part thereof, to be licensed as a whole at no charge to all third\
  17552.    parties under the terms of this License.\
  17553. \
  17554.    c) If the modified program normally reads commands interactively\
  17555.    when run, you must cause it, when started running for such\
  17556.    interactive use in the most ordinary way, to print or display an\
  17557.    announcement including an appropriate copyright notice and a\
  17558.    notice that there is no warranty (or else, saying that you provide\
  17559.    a warranty) and that users may redistribute the program under\
  17560.    these conditions, and telling the user how to view a copy of this\
  17561.    License.  (Exception: if the Program itself is interactive but\
  17562.    does not normally print such an announcement, your work based on\
  17563.    the Program is not required to print an announcement.)\
  17564. \
  17565. These requirements apply to the modified work as a whole.  If\
  17566. identifiable sections of that work are not derived from the Program,\
  17567. and can be reasonably considered independent and separate works in\
  17568. themselves, then this License, and its terms, do not apply to those\
  17569. sections when you distribute them as separate works.  But when you\
  17570. distribute the same sections as part of a whole which is a work based\
  17571. on the Program, the distribution of the whole must be on the terms of\
  17572. this License, whose permissions for other licensees extend to the\
  17573. entire whole, and thus to each and every part regardless of who wrote it.\
  17574. \
  17575. Thus, it is not the intent of this section to claim rights or contest\
  17576. your rights to work written entirely by you; rather, the intent is to\
  17577. exercise the right to control the distribution of derivative or\
  17578. collective works based on the Program.\
  17579. \
  17580. In addition, mere aggregation of another work not based on the Program\
  17581. with the Program (or with a work based on the Program) on a volume of\
  17582. a storage or distribution medium does not bring the other work under\
  17583. the scope of this License.\
  17584. \
  17585.  3. You may copy and distribute the Program (or a work based on it,\
  17586. under Section 2) in object code or executable form under the terms of\
  17587. Sections 1 and 2 above provided that you also do one of the following:\
  17588. \
  17589.    a) Accompany it with the complete corresponding machine-readable\
  17590.    source code, which must be distributed under the terms of Sections\
  17591.    1 and 2 above on a medium customarily used for software interchange; or,\
  17592. \
  17593.    b) Accompany it with a written offer, valid for at least three\
  17594.    years, to give any third party, for a charge no more than your\
  17595.    cost of physically performing source distribution, a complete\
  17596.    machine-readable copy of the corresponding source code, to be\
  17597.    distributed under the terms of Sections 1 and 2 above on a medium\
  17598.    customarily used for software interchange; or,\
  17599. \
  17600.    c) Accompany it with the information you received as to the offer\
  17601.    to distribute corresponding source code.  (This alternative is\
  17602.    allowed only for noncommercial distribution and only if you\
  17603.    received the program in object code or executable form with such\
  17604.    an offer, in accord with Subsection b above.)\
  17605. \
  17606. The source code for a work means the preferred form of the work for\
  17607. making modifications to it.  For an executable work, complete source\
  17608. code means all the source code for all modules it contains, plus any\
  17609. associated interface definition files, plus the scripts used to\
  17610. control compilation and installation of the executable.  However, as a\
  17611. special exception, the source code distributed need not include\
  17612. anything that is normally distributed (in either source or binary\
  17613. form) with the major components (compiler, kernel, and so on) of the\
  17614. operating system on which the executable runs, unless that component\
  17615. itself accompanies the executable.\
  17616. \
  17617. If distribution of executable or object code is made by offering\
  17618. access to copy from a designated place, then offering equivalent\
  17619. access to copy the source code from the same place counts as\
  17620. distribution of the source code, even though third parties are not\
  17621. compelled to copy the source along with the object code.\
  17622. \
  17623.  4. You may not copy, modify, sublicense, or distribute the Program\
  17624. except as expressly provided under this License.  Any attempt\
  17625. otherwise to copy, modify, sublicense or distribute the Program is\
  17626. void, and will automatically terminate your rights under this License.\
  17627. However, parties who have received copies, or rights, from you under\
  17628. this License will not have their licenses terminated so long as such\
  17629. parties remain in full compliance.\
  17630. \
  17631.  5. You are not required to accept this License, since you have not\
  17632. signed it.  However, nothing else grants you permission to modify or\
  17633. distribute the Program or its derivative works.  These actions are\
  17634. prohibited by law if you do not accept this License.  Therefore, by\
  17635. modifying or distributing the Program (or any work based on the\
  17636. Program), you indicate your acceptance of this License to do so, and\
  17637. all its terms and conditions for copying, distributing or modifying\
  17638. the Program or works based on it.\
  17639. \
  17640.  6. Each time you redistribute the Program (or any work based on the\
  17641. Program), the recipient automatically receives a license from the\
  17642. original licensor to copy, distribute or modify the Program subject to\
  17643. these terms and conditions.  You may not impose any further\
  17644. restrictions on the recipients' exercise of the rights granted herein.\
  17645. You are not responsible for enforcing compliance by third parties to\
  17646. this License.\
  17647. \
  17648.  7. If, as a consequence of a court judgment or allegation of patent\
  17649. infringement or for any other reason (not limited to patent issues),\
  17650. conditions are imposed on you (whether by court order, agreement or\
  17651. otherwise) that contradict the conditions of this License, they do not\
  17652. excuse you from the conditions of this License.  If you cannot\
  17653. distribute so as to satisfy simultaneously your obligations under this\
  17654. License and any other pertinent obligations, then as a consequence you\
  17655. may not distribute the Program at all.  For example, if a patent\
  17656. license would not permit royalty-free redistribution of the Program by\
  17657. all those who receive copies directly or indirectly through you, then\
  17658. the only way you could satisfy both it and this License would be to\
  17659. refrain entirely from distribution of the Program.\
  17660. \
  17661. If any portion of this section is held invalid or unenforceable under\
  17662. any particular circumstance, the balance of the section is intended to\
  17663. apply and the section as a whole is intended to apply in other\
  17664. circumstances.\
  17665. \
  17666. It is not the purpose of this section to induce you to infringe any\
  17667. patents or other property right claims or to contest validity of any\
  17668. such claims; this section has the sole purpose of protecting the\
  17669. integrity of the free software distribution system, which is\
  17670. implemented by public license practices.  Many people have made\
  17671. generous contributions to the wide range of software distributed\
  17672. through that system in reliance on consistent application of that\
  17673. system; it is up to the author/donor to decide if he or she is willing\
  17674. to distribute software through any other system and a licensee cannot\
  17675. impose that choice.\
  17676. \
  17677. This section is intended to make thoroughly clear what is believed to\
  17678. be a consequence of the rest of this License.\
  17679. \
  17680.  8. If the distribution and/or use of the Program is restricted in\
  17681. certain countries either by patents or by copyrighted interfaces, the\
  17682. original copyright holder who places the Program under this License\
  17683. may add an explicit geographical distribution limitation excluding\
  17684. those countries, so that distribution is permitted only in or among\
  17685. countries not thus excluded.  In such case, this License incorporates\
  17686. the limitation as if written in the body of this License.\
  17687. \
  17688.  9. The Free Software Foundation may publish revised and/or new versions\
  17689. of the General Public License from time to time.  Such new versions will\
  17690. be similar in spirit to the present version, but may differ in detail to\
  17691. address new problems or concerns.\
  17692. \
  17693. Each version is given a distinguishing version number.  If the Program\
  17694. specifies a version number of this License which applies to it and \"any\
  17695. later version\", you have the option of following the terms and conditions\
  17696. either of that version or of any later version published by the Free\
  17697. Software Foundation.  If the Program does not specify a version number of\
  17698. this License, you may choose any version ever published by the Free Software\
  17699. Foundation.\
  17700. \
  17701.  10. If you wish to incorporate parts of the Program into other free\
  17702. programs whose distribution conditions are different, write to the author\
  17703. to ask for permission.  For software which is copyrighted by the Free\
  17704. Software Foundation, write to the Free Software Foundation; we sometimes\
  17705. make exceptions for this.  Our decision will be guided by the two goals\
  17706. of preserving the free status of all derivatives of our free software and\
  17707. of promoting the sharing and reuse of software generally.\
  17708. \
  17709.                            NO WARRANTY\
  17710. \
  17711.  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\
  17712. FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\
  17713. OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\
  17714. PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\
  17715. OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\
  17716. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\
  17717. TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\
  17718. PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\
  17719. REPAIR OR CORRECTION.\
  17720. \
  17721.  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\
  17722. WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\
  17723. REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\
  17724. INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\
  17725. OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\
  17726. TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\
  17727. YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\
  17728. PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\
  17729. POSSIBILITY OF SUCH DAMAGES.\
  17730. \
  17731.                     END OF TERMS AND CONDITIONS\
  17732. \
  17733.            How to Apply These Terms to Your New Programs\
  17734. \
  17735.  If you develop a new program, and you want it to be of the greatest\
  17736. possible use to the public, the best way to achieve this is to make it\
  17737. free software which everyone can redistribute and change under these terms.\
  17738. \
  17739.  To do so, attach the following notices to the program.  It is safest\
  17740. to attach them to the start of each source file to most effectively\
  17741. convey the exclusion of warranty; and each file should have at least\
  17742. the \"copyright\" line and a pointer to where the full notice is found.\
  17743. \
  17744.    {description}\
  17745.    Copyright (C) {year}  {fullname}\
  17746. \
  17747.    This program is free software; you can redistribute it and/or modify\
  17748.    it under the terms of the GNU General Public License as published by\
  17749.    the Free Software Foundation; either version 2 of the License, or\
  17750.    (at your option) any later version.\
  17751. \
  17752.    This program is distributed in the hope that it will be useful,\
  17753.    but WITHOUT ANY WARRANTY; without even the implied warranty of\
  17754.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\
  17755.    GNU General Public License for more details.\
  17756. \
  17757.    You should have received a copy of the GNU General Public License along\
  17758.    with this program; if not, write to the Free Software Foundation, Inc.,\
  17759.    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\
  17760. \
  17761. Also add information on how to contact you by electronic and paper mail.\
  17762. \
  17763. If the program is interactive, make it output a short notice like this\
  17764. when it starts in an interactive mode:\
  17765. \
  17766.    Gnomovision version 69, Copyright (C) year name of author\
  17767.    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\
  17768.    This is free software, and you are welcome to redistribute it\
  17769.    under certain conditions; type `show c' for details.\
  17770. \
  17771. The hypothetical commands `show w' and `show c' should show the appropriate\
  17772. parts of the General Public License.  Of course, the commands you use may\
  17773. be called something other than `show w' and `show c'; they could even be\
  17774. mouse-clicks or menu items--whatever suits your program.\
  17775. \
  17776. You should also get your employer (if you work as a programmer) or your\
  17777. school, if any, to sign a \"copyright disclaimer\" for the program, if\
  17778. necessary.  Here is a sample; alter the names:\
  17779. \
  17780.  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\
  17781.  `Gnomovision' (which makes passes at compilers) written by James Hacker.\
  17782. \
  17783.  {signature of Ty Coon}, 1 April 1989\
  17784.  Ty Coon, President of Vice\
  17785. \
  17786. This General Public License does not permit incorporating your program into\
  17787. proprietary programs.  If your program is a subroutine library, you may\
  17788. consider it more useful to permit linking proprietary applications with the\
  17789. library.  If this is what you want to do, use the GNU Lesser General\
  17790. Public License instead of this License.\
  17791. ",
  17792.     },
  17793.     [ "paint.lua" ] = "transparentIcon = \"-\"\
  17794. args = {...}\
  17795. tX, tY = term.getSize()\
  17796. \
  17797. function import(source,dest)\
  17798. init()\
  17799. if fs.exists(source) == false then\
  17800.  print(\"File \"..source..\" doesnt exists!\")\
  17801.  error()\
  17802. elseif not dest then\
  17803.  print(\"Provide an output file.\")\
  17804.  error()\
  17805. elseif fs.exists(dest) == true then\
  17806.  print(\"File \"..dest..\" already exists!\")\
  17807.  error()\
  17808. end\
  17809. --if mode == \"import\" then\
  17810.  h = fs.open(source,\"r\")\
  17811.  lines = {}\
  17812.  count = 0\
  17813.  repeat\
  17814.   count = count + 1\
  17815.   lines[count] = h.readLine(count)  \
  17816.  until lines[count] == nil\
  17817.  h.close()\
  17818.  data = {}\
  17819.  if not painted then\
  17820.   painted = {}\
  17821.  end\
  17822.  for i=1,#lines do\
  17823.   data[i] = {}\
  17824.   string.gsub(lines[i],\".\",function(char) table.insert(data[i],char) end)\
  17825.  end\
  17826.  x=0\
  17827.  y=0\
  17828.  for i=1,#data do\
  17829.   y = y + 1\
  17830.   x = 0\
  17831.   for a=1,#data[i] do\
  17832.    x = x + 1\
  17833.    if not painted[x] then\
  17834.     painted[x] = {}\
  17835.    end\
  17836.    if not painted[x][y] then\
  17837.     painted[x][y] = {}\
  17838.    end\
  17839.    rawColor = data[i][x]\
  17840.    if rawColor == \"0\" then\
  17841.     colorLoaded = colors.white\
  17842.    elseif rawColor == \"1\" then\
  17843.     colorLoaded = colors.orange\
  17844.    elseif rawColor == \"2\" then\
  17845.     colorLoaded = colors.magenta\
  17846.    elseif rawColor == \"3\" then\
  17847.     colorLoaded = colors.lightBlue\
  17848.    elseif rawColor == \"4\" then\
  17849.     colorLoaded = colors.yellow\
  17850.    elseif rawColor == \"5\" then\
  17851.     colorLoaded = colors.lime\
  17852.    elseif rawColor == \"6\" then\
  17853.     colorLoaded = colors.pink\
  17854.    elseif rawColor == \"7\" then\
  17855.     colorLoaded = colors.gray\
  17856.    elseif rawColor == \"8\" then\
  17857.     colorLoaded = colors.lightGray\
  17858.    elseif rawColor == \"9\" then\
  17859.     colorLoaded = colors.cyan\
  17860.    elseif rawColor == \"a\" then\
  17861.     colorLoaded = colors.purple\
  17862.    elseif rawColor == \"b\" then\
  17863.     colorLoaded = colors.blue\
  17864.    elseif rawColor == \"c\" then\
  17865.     colorLaoded = colors.brown\
  17866.    elseif rawColor == \"d\" then\
  17867.     colorLoaded = colors.green\
  17868.    elseif rawColor == \"e\" then\
  17869.     colorLoaded = colors.red\
  17870.    elseif rawColor == \"f\" then\
  17871.     colorLoaded = colors.black\
  17872.    elseif rawColor == \" \" then\
  17873.     -- Do nothing, allow it\
  17874.    else\
  17875.     error(\"File: \\\"\"..source..\"\\\" has an incorrect format!\")\
  17876.    end\
  17877.    if rawColor ~= \" \" then\
  17878.     painted[x][y] = {colorLoaded,\" \",colorLoaded}   \
  17879.    else\
  17880.     painted[x][y] = nil\
  17881.    end\
  17882.   end\
  17883.  end\
  17884. --end\
  17885. args[1] = dest\
  17886. save()\
  17887. end\
  17888. \
  17889. \
  17890. function drawImage(file,xSet,ySet,redirection)\
  17891. init()\
  17892. lastImage = file\
  17893. lastX = xSet\
  17894. lastY = ySet\
  17895. lastRedirection = redirection\
  17896. if redirection then\
  17897.  current = term.current()\
  17898.  term.redirect(redirection)\
  17899. end\
  17900. drawData(xSet,ySet,file)\
  17901. if redirection then\
  17902.  term.redirect(current)\
  17903. end\
  17904. end\
  17905. \
  17906. function overWrite(textSet,xSet,ySet,colorSet)\
  17907. init()\
  17908. exists = true\
  17909. if not lastImage then\
  17910.  error(\"Use drawImage first!\")\
  17911. end\
  17912. if not writeBuffer then\
  17913.  writeBuffer = {}\
  17914. end\
  17915. if not writeBuffer[lastImage] then\
  17916.  writeBuffer[lastImage] = {}\
  17917. end\
  17918. plusPos = 0\
  17919. for char in string.gmatch(textSet,\".\") do\
  17920.  if not writeBuffer[lastImage][xSet+plusPos] then\
  17921.   writeBuffer[lastImage][xSet+plusPos] = {}\
  17922.  end\
  17923.  if not writeBuffer[lastImage][xSet+plusPos][ySet] then\
  17924.   writeBuffer[lastImage][xSet+plusPos][ySet] = {colors.black,\" \",colors.white}\
  17925.  end\
  17926.  writeBuffer[lastImage][xSet+plusPos][ySet][2] = char\
  17927.  writeBuffer[lastImage][xSet+plusPos][ySet][3] = colorSet\
  17928.  plusPos = plusPos + 1 \
  17929. end\
  17930. drawImage(lastImage,lastX,lastY,lastRedirection)\
  17931. end\
  17932. \
  17933. function init()\
  17934. function eventHandler()\
  17935. while true do\
  17936.  event = {os.pullEvent()}\
  17937.  if event[1] == \"key\" then\
  17938.   if event[2] == keys.leftCtrl or event[2] == 157 then\
  17939.    menuStatus = not menuStatus\
  17940.    writeMenuBar(menuStatus)\
  17941.   end\
  17942.   if menuStatus == true then\
  17943.    if event[2] == keys.right or event[2] == keys.left then\
  17944.     if menuItemSelected == 1 then\
  17945.      menuItemSelected = 2\
  17946.     else\
  17947.      menuItemSelected = 1\
  17948.     end\
  17949.     writeMenuBar(menuStatus)\
  17950.    elseif event[2] == keys.enter then\
  17951.     if menuItemSelected == 1 then\
  17952.      save()\
  17953.      writeMenuBar(false)\
  17954.     else\
  17955.      term.setTextColor(colors.yellow)\
  17956.      term.setBackgroundColor(colors.black)\
  17957.      term.clear()\
  17958.      term.setCursorPos(1,1)\
  17959.      error()\
  17960.     end\
  17961.    end\
  17962.   else   \
  17963.    if event[2] == keys.right then\
  17964.     drawData(offSetX-1,offSetY)\
  17965.     drawMenu()\
  17966.     writeMenuBar(menuStatus)\
  17967.    elseif event[2] == keys.left then\
  17968.     drawData(offSetX+1,offSetY)\
  17969.     drawMenu()\
  17970.     writeMenuBar(menuStatus)\
  17971.    elseif event[2] == keys.up then\
  17972.     drawData(offSetX,offSetY+1)\
  17973.     drawMenu()\
  17974.     writeMenuBar(menuStatus)\
  17975.    elseif event[2] == keys.down then\
  17976.     drawData(offSetX,offSetY-1)\
  17977.     drawMenu()\
  17978.     writeMenuBar(menuStatus)\
  17979.    end\
  17980.   end\
  17981.  end\
  17982.  if event[1] == \"mouse_click\" or event[1] == \"mouse_drag\" then\
  17983.   if event[3] > 2 and event[4] ~= tY then\
  17984.    insertItem(event[3],event[4],event[2])\
  17985.   elseif event[4] < 18 and event[4] > 1 then\
  17986.    if event[3] == 1 then\
  17987.     bgSelected = 2^(event[4]-2)\
  17988.    elseif event[3] == 2 then\
  17989.     tSelected = 2^(event[4]-2)\
  17990.    end\
  17991.    drawMenu()\
  17992.   elseif event[4] == tY - 1 and event[3] == 1 then\
  17993.    setLetter()\
  17994.    drawData(offSetX,offSetY)\
  17995.    drawMenu()\
  17996.   elseif event[3] == tX and event[4] == tY and menuStatus == false then\
  17997.    writeHelp()\
  17998.   end\
  17999.  end\
  18000.  if event[1] == \"char\" then\
  18001.   textSelected = string.sub(event[2],1,1)\
  18002.   drawMenu()\
  18003.  end\
  18004.  --drawData(offSetX,offSetY)\
  18005. end\
  18006. end\
  18007. \
  18008. function writeHelp()\
  18009. term.setBackgroundColor(colors.black)\
  18010. term.setTextColor(colors.green)\
  18011. term.clear()\
  18012. term.setCursorPos(1,1)\
  18013. term.write(\"Help:\")\
  18014. term.setTextColor(colors.white)\
  18015. term.setCursorPos(1,3)\
  18016. print(\"Usage:\")\
  18017. term.setTextColor(colors.lightGray)\
  18018. print(\"  Select color: Click on the color on the left\")\
  18019. print(\"  Change draw char: Press a key on the keyboard\")\
  18020. print(\"  Change transparent icon: Click on the icon's char in the menu\")\
  18021. print(\"  Change text color: Click on a color in the menu on the right side\")\
  18022. print(\"  Change background color: Click on a color in the menu on the left side\")\
  18023. term.setTextColor(colors.white)\
  18024. print()\
  18025. print(\"Controls:\")\
  18026. term.setTextColor(colors.lightGray)\
  18027. print(\"  Arrow keys to pan\")\
  18028. print(\"  Left mouse button to select and draw\")\
  18029. print(\"  Right mouse button to delete\")\
  18030. print(\"  Ctrl to open menu\")\
  18031. print()\
  18032. term.setTextColor(colors.white)\
  18033. term.write(\"Click a mouse button to exit.\")\
  18034. term.setTextColor(colors.orange)\
  18035. term.setCursorPos(tX-9,1)\
  18036. term.write(\"API help >\")\
  18037. event = {os.pullEvent(\"mouse_click\")}\
  18038. if event[3] > tX-10 and event[4] == 1 then\
  18039.  drawAPIhelp()\
  18040. end\
  18041. drawData(offSetX,offSetY)\
  18042. drawMenu()\
  18043. writeMenuBar(menuStatus)\
  18044. end\
  18045. \
  18046. function drawAPIhelp()\
  18047. term.clear()\
  18048. term.setCursorPos(1,1)\
  18049. term.setTextColor(colors.orange)\
  18050. print(\"API help menu:\")\
  18051. term.setTextColor(colors.white)\
  18052. print(\"Drawing an image: \")\
  18053. term.setTextColor(colors.lightGray)\
  18054. print(shell.getRunningProgram(),\".drawImage(<file name>,<x pos>,<y pos>,[redirection object])\")\
  18055. print()\
  18056. term.setTextColor(colors.white)\
  18057. print(\"Overlaying text on the last image:\")\
  18058. term.setTextColor(colors.lightGray)\
  18059. print(shell.getRunningProgram(),\".overWrite(<Text>,<x pos>,<y pos>,<text color>)\")\
  18060. print()\
  18061. term.setTextColor(colors.white)\
  18062. print(\"Convert a paintutils file to betterpaint file:\")\
  18063. term.setTextColor(colors.lightGray)\
  18064. print(shell.getRunningProgram(),\".import(<source>,<destination>)\")\
  18065. term.setTextColor(colors.red)\
  18066. print()\
  18067. print(\"Overwriting text will only work AFTER drawing an image!\")\
  18068. term.setTextColor(colors.white)\
  18069. print()\
  18070. print(\"Example:\")\
  18071. term.setTextColor(colors.lightGray)\
  18072. print(\"os.loadAPI(\\\"\",shell.getRunningProgram(),\"\\\")\")\
  18073. print(shell.getRunningProgram(),\".drawImage(\\\"myPicture\\\",1,1)\")\
  18074. term.write((shell.getRunningProgram()..\".overWrite(\\\"Hello!\\\",2,3,colors.orange)\"))\
  18075. os.pullEvent(\"mouse_click\")\
  18076. end\
  18077. \
  18078. function setLetter()\
  18079. term.setBackgroundColor(colors.red)\
  18080. term.setTextColor(colors.black)\
  18081. for i=1,4 do\
  18082.  term.setCursorPos(tX/2-11,(tY/2-4)+i)\
  18083.  term.write(\"                     \")\
  18084. end\
  18085. term.setCursorPos(tX/2-10,tY/2-2)\
  18086. term.write(\"Change transparancy\")\
  18087. term.setCursorPos(tX/2-10,tY/2-1)\
  18088. term.write(\"character to: (key)\")\
  18089. event = {os.pullEvent(\"char\")}\
  18090. transparentIcon = event[2]\
  18091. end\
  18092. \
  18093. function insertItem(xPos,yPos,modeSet)\
  18094. if saved == true then\
  18095.  saved = false\
  18096.  writeMenuBar(false)\
  18097. end\
  18098. --bgSelected\
  18099. --tSelected\
  18100. --textSelected\
  18101. if not painted then\
  18102.  painted = {}\
  18103. end\
  18104. if not painted[xPos-offSetX] then\
  18105.  painted[xPos-offSetX] = {}\
  18106. end\
  18107. if modeSet == 1 then\
  18108.   if not textSelected then\
  18109.    textSelected = \" \"\
  18110.   end\
  18111.   TMPtextSelected = textSelected\
  18112.   painted[xPos-offSetX][yPos-offSetY] = {bgSelected,textSelected,tSelected}\
  18113.   term.setBackgroundColor(bgSelected)\
  18114.   term.setTextColor(tSelected)\
  18115.  else\
  18116.   TMPtextSelected = transparentIcon\
  18117.   term.setBackgroundColor(colors.black)\
  18118.   term.setTextColor(colors.gray)\
  18119.   painted[xPos-offSetX][yPos-offSetY] = nil\
  18120. end\
  18121. term.setCursorPos(xPos,yPos)\
  18122. term.write(TMPtextSelected)\
  18123. end\
  18124. \
  18125. --if #args ~= 1 then\
  18126. -- print(\"Usage: \"..shell.getRunningProgram()..\" <path>\")\
  18127. -- return\
  18128. --end\
  18129. \
  18130. if args[1] and fs.exists(args[1]) == true then\
  18131. buff = fs.open(args[1],\"r\")\
  18132. previousData = buff.readAll()\
  18133. buff.close()\
  18134. processed = string.sub(previousData,43)\
  18135. painted = textutils.unserialize(processed)\
  18136. else\
  18137. painted = {}\
  18138. end\
  18139. \
  18140. function save()\
  18141. file = fs.open(args[1],\"w\")\
  18142. file.write(\"error('This is an image, not a program!')\\n\"..textutils.serialize(painted))\
  18143. file.close()\
  18144. saved = true\
  18145. end\
  18146. \
  18147. function drawData(xStart, yStart, file)\
  18148. offSetX = xStart\
  18149. offSetY = yStart\
  18150. if not file then\
  18151.  term.setBackgroundColor(colors.black)\
  18152.  term.setTextColor(colors.gray)\
  18153.  transparentLine = \"\"\
  18154.  for x=1,tX-2 do\
  18155.   transparentLine = transparentIcon..transparentLine\
  18156.  end\
  18157.  for y=1,tY-1 do\
  18158.   term.setCursorPos(3,y)\
  18159.   term.write(transparentLine)\
  18160.  end\
  18161. else\
  18162.  if fs.exists(file) == false then\
  18163.   error(\"File given doesnt exists! file name: \"..file)\
  18164.  else\
  18165.   local fileD = fs.open(file,\"r\")\
  18166.   raw = fileD.readAll()\
  18167.   --ignoreL = string.len(fileD.readLine(1))\
  18168.   processed = string.sub(raw,43)\
  18169.   --term.redirect(term.native())\
  18170.  -- textutils.pagedPrint(processed)\
  18171.   painted = textutils.unserialize(processed)\
  18172.   fileD.close()\
  18173.  end\
  18174. end\
  18175. if not painted then\
  18176.  painted = {}\
  18177. end\
  18178. paintedF = painted\
  18179. count = 0\
  18180. repeat ---------\
  18181. count = count + 1\
  18182. for xPos,v in pairs(paintedF) do\
  18183.  for yPos in pairs (paintedF[xPos]) do\
  18184.    overWrite = true\
  18185.    if not lastImage or not writeBuffer or not writeBuffer[lastImage] then\
  18186.     overWrite = false\
  18187.    end\
  18188.    if overWrite == true then\
  18189.     if not writeBuffer[lastImage][xPos] then\
  18190.      overWrite = false\
  18191.     end\
  18192.    end\
  18193.    if overWrite == true then\
  18194.     if not writeBuffer[lastImage][xPos][yPos] then\
  18195.      overWrite = false\
  18196.     end\
  18197.    end\
  18198.    if overWrite == false then\
  18199.     bgColor = paintedF[xPos][yPos][1]\
  18200.     text = paintedF[xPos][yPos][2]\
  18201.     tColor = paintedF[xPos][yPos][3]\
  18202.    else\
  18203.     if painted and painted[xPos] and painted[xPos][yPos] and painted[xPos][yPos][1] then\
  18204.      bgColor = painted[xPos][yPos][1]\
  18205.      else\
  18206.      bgColor = colors.black\
  18207.     end\
  18208.     --if not bgColor then\
  18209.    --  bgColor = colors.black\
  18210.     --end\
  18211.     text = writeBuffer[lastImage][xPos][yPos][2]\
  18212.     tColor = writeBuffer[lastImage][xPos][yPos][3]\
  18213.    end\
  18214.    if not tColor then\
  18215.     tColor = colors.white\
  18216.    end\
  18217.    if not text then\
  18218.     text = \" \"\
  18219.    end\
  18220.    term.setCursorPos(xPos+xStart,yPos+yStart)\
  18221.    term.setBackgroundColor(bgColor)\
  18222.    term.setTextColor(tColor)\
  18223.    term.write(text)\
  18224.   end\
  18225.  end\
  18226.  if count == 1 and writeBuffer and lastImage then\
  18227.   paintedF = writeBuffer[lastImage]\
  18228.  elseif count == 1 and not lastImage or not writeBuffer then\
  18229.   count = 2\
  18230.  end\
  18231. until count == 2\
  18232. term.setCursorPos(1,tY)\
  18233. end\
  18234. \
  18235. function drawMenu()\
  18236. term.setCursorPos(1,1)\
  18237. term.setTextColor(colors.white)\
  18238. if not bgSelected then\
  18239.  bgSelected = colors.black\
  18240. elseif bgSelected == colors.white then\
  18241.  term.setTextColor(colors.black)\
  18242. end\
  18243. if not tSelected then\
  18244.  tSelected = colors.white\
  18245. elseif tSelected == colors.white then\
  18246.  term.setTextColor(colors.black)\
  18247. end\
  18248. if not textSelected then\
  18249.  textSelected = \" \"\
  18250. end\
  18251. term.setBackgroundColor(bgSelected)\
  18252. term.write(\"B\")\
  18253. term.setBackgroundColor(tSelected)\
  18254. term.write(\"T\")\
  18255. for i=1,16 do\
  18256.  i=i-1\
  18257.  term.setCursorPos(1,i+2)\
  18258.  term.setBackgroundColor(2^i)\
  18259.  term.write(\"  \")\
  18260. end\
  18261. term.setCursorPos(1,18)\
  18262. term.setBackgroundColor(colors.black)\
  18263. if not textSelected then\
  18264.  textSelected = \" \"\
  18265. elseif string.len(textSelected) > 1 then\
  18266.  textSelected = string.sub(textSelected,1,1)\
  18267. end\
  18268. term.setTextColor(colors.gray)\
  18269. term.setBackgroundColor(colors.black)\
  18270. term.write(transparentIcon)\
  18271. term.setTextColor(tSelected)\
  18272. term.setBackgroundColor(bgSelected)\
  18273. term.write(textSelected)\
  18274. end\
  18275. \
  18276. function writeMenuBar(booly)\
  18277. menuStatus = booly\
  18278. term.setBackgroundColor(colors.black)\
  18279. if booly == true then\
  18280.  term.setCursorPos(1,tY)\
  18281.  term.clearLine()\
  18282.  if not menuItemSelected then\
  18283.   menuItemSelected = 1\
  18284.  end\
  18285.  term.setTextColor(colors.white)\
  18286.  term.write(\" Save  Exit \")\
  18287.  term.setCursorPos(6*menuItemSelected-5,tY)\
  18288.  term.setTextColor(colors.yellow)\
  18289.  term.write(\"[\")\
  18290.  term.setCursorPos(6*menuItemSelected,tY)\
  18291.  term.write(\"]\")\
  18292. elseif booly == false then\
  18293.  term.setCursorPos(1,tY)\
  18294.  term.setTextColor(colors.yellow)\
  18295.  term.clearLine()\
  18296.  if saved == true then\
  18297.   term.write(\"Saved to \"..args[1])\
  18298.  else\
  18299.   term.write(\"Press Ctrl to access menu\")\
  18300.  end\
  18301.  term.setCursorPos(tX,tY)\
  18302.  term.setTextColor(colors.lightGray)\
  18303.  term.write(\"?\")\
  18304. end\
  18305. end\
  18306. end\
  18307. \
  18308. if args[1] == \"import\" then -- or args[1] == \"export\" then\
  18309. init()\
  18310. mode = args[1]\
  18311. source = args[2]\
  18312. destination = args[3]\
  18313. if not args[2] then\
  18314.  print(\"Usage: \"..shell.getRunningProgram()..\" \"..mode..\" <source> <destination>\")\
  18315.  error()\
  18316. end\
  18317. import(source,destination)\
  18318. if mode == \"import\" then\
  18319.  print(\"File imported.\")\
  18320.  error()\
  18321. end\
  18322. elseif #args > 0 then\
  18323. init()\
  18324. menuStatus = false\
  18325. saved = false\
  18326. writeMenuBar(menuStatus)\
  18327. menuItemSelected = 1\
  18328. drawData(3,0)\
  18329. drawMenu()\
  18330. eventHandler()\
  18331. end",
  18332.     [ "Screen.lua" ] = "function new( parent, nX, nY, nWidth, nHeight)\
  18333. \
  18334.     if type( parent ) ~= \"table\" then error( \"Expected object\",2 ) end\
  18335.     if type( nX ) ~= \"number\" then error( \"Expected number1\", 2 ) end\
  18336.     if type( nY ) ~= \"number\" then error( \"Expected number2\", 2 ) end\
  18337.     if type( nWidth ) ~= \"number\" then error( \"Expected number3\", 2 ) end\
  18338.     if type( nHeight ) ~= \"number\" then error( \"Expected number4\", 2 ) end\
  18339. \
  18340.     if parent == term then\
  18341.         parent = term.current()\
  18342.     end\
  18343. \
  18344.     -- Setup\
  18345.     local nCursorX = 1\
  18346.     local nCursorY = 1\
  18347. \
  18348.     -- Helper functions\
  18349.     local function updateCursorPos()\
  18350.         if nCursorX >= 1 and nCursorY >= 1 and\
  18351.            nCursorX <= nWidth and nCursorY <= nHeight then\
  18352.             parent.setCursorPos( nX + nCursorX - 1, nY + nCursorY - 1 )\
  18353.         else\
  18354.             parent.setCursorPos( 0, 0 )\
  18355.         end\
  18356.     end\
  18357. \
  18358.     local window = {}\
  18359. \
  18360.     -- Terminal implementation\
  18361.     function window.write( sText )\
  18362.         local nLen = sText:len()\
  18363.         updateCursorPos()\
  18364.         for i = 1, nLen do\
  18365.             if nCursorX <= nWidth and nCursorY <= nHeight then\
  18366.                 parent.write(sText:sub(i,i))\
  18367.                 nCursorX = nCursorX + 1\
  18368.             end\
  18369.         end\
  18370.     end\
  18371. \
  18372.     local function clearLine()\
  18373.         for i=1,nWidth do\
  18374.             parent.write(\" \")\
  18375.             nCursorX = nCursorX + 1\
  18376.         end\
  18377.     end\
  18378. \
  18379.     function window.clear()\
  18380.         for m=1, nHeight do\
  18381.             updateCursorPos()\
  18382.             clearLine()\
  18383.             nCursorY = nCursorY + 1\
  18384.         end\
  18385.     end\
  18386. \
  18387.     function window.clearLine()\
  18388.         clearLine()\
  18389.     end\
  18390. \
  18391.     function window.getCursorPos()\
  18392.         return nCursorX, nCursorY\
  18393.     end\
  18394. \
  18395.     function window.setCursorPos( x, y )\
  18396.         nCursorX = math.floor( x )\
  18397.         nCursorY = math.floor( y )\
  18398.         updateCursorPos()\
  18399.     end\
  18400. \
  18401.     function window.setCursorBlink( blink )\
  18402.         parent.setCursorBlink(blink)\
  18403.     end\
  18404. \
  18405.     function window.isColor()\
  18406.         return parent.isColor()\
  18407.     end\
  18408. \
  18409.     function window.isColour()\
  18410.         return parent.isColor()\
  18411.     end\
  18412. \
  18413.     local function setTextColor( color )\
  18414.         if not parent.isColor() then\
  18415.             if color ~= colors.white and color ~= colors.black then\
  18416.                 error( \"Colour not supported\", 3 )\
  18417.             end\
  18418.         end\
  18419.         parent.setTextColour(color)\
  18420.     end\
  18421. \
  18422.     function window.setTextColor( color )\
  18423.         setTextColor( color )\
  18424.     end\
  18425. \
  18426.     function window.setTextColour( color )\
  18427.         setTextColor( color )\
  18428.     end\
  18429. \
  18430.     local function setBackgroundColor( color )\
  18431.         if not parent.isColor() then\
  18432.             if color ~= colors.white and color ~= colors.black then\
  18433.                 error( \"Colour not supported\", 3 )\
  18434.             end\
  18435.         end\
  18436.         parent.setBackgroundColor(color)\
  18437.     end\
  18438. \
  18439.     function window.setBackgroundColor( color )\
  18440.         setBackgroundColor( color )\
  18441.     end\
  18442. \
  18443.     function window.setBackgroundColour( color )\
  18444.         setBackgroundColor( color )\
  18445.     end\
  18446. \
  18447.     function window.getSize()\
  18448.         return nWidth, nHeight\
  18449.     end\
  18450. \
  18451.     function window.scroll( n )\
  18452.         print(\"Fuck you! No freaking buffer.\")\
  18453.     end\
  18454. \
  18455.     return window\
  18456. end",
  18457.     [ "fsh.lua" ] = "--[[\
  18458.     VFS helper and moumting manager\
  18459.     Author: Wassil Janssen a.k.a. Creator\
  18460. ]]--\
  18461. \
  18462. --Variables\
  18463. local mounts = {}\
  18464. local Internal = {}\
  18465. local filesystems = {}\
  18466. \
  18467. --Functions\
  18468. function Internal.getFirstElement(path)\
  18469.     if not type(path) == \"string\" then error(\"This is not a string: \"..tostring(path),2) end\
  18470.     --Utils.debug(\"Getting first element: \"..tostring(path))\
  18471.     return string.sub(path,1,string.find(path,\"/\") and string.find(path,\"/\")-1 or -1)\
  18472. end\
  18473. \
  18474. function Internal.makeTable(path,tabl)\
  18475.     if type(path) ~= \"string\" then error(\"Expected string, got \"..type(path)..\"!\",2) end\
  18476.     if type(tabl) ~= \"table\" then error(\"Expected table, got \"..type(tabl)..\"!\",2) end\
  18477.     path = fs.combine(\"\",path)\
  18478.     local first = Internal.getFirstElement(path)\
  18479.     if first == path then\
  18480.         return tabl, first\
  18481.     else\
  18482.         if not tabl[first] then tabl[first] = {} end\
  18483.         return Internal.makeTable(path:sub(path:find(\"/\")+1,-1),tabl[first])\
  18484.     end\
  18485. end\
  18486. \
  18487. function mount(destination,source,fss)\
  18488.     fss = fss or \"ccfs\"\
  18489.     if not fs.exists(destination) then fs.makeDir(destination) end\
  18490.     if not fs.exists(source) then fs.makeDir(source) end\
  18491.     local tabl, dir = Internal.makeTable(destination,mounts)\
  18492.     tabl[dir] = source\
  18493.     if fss and fss ~= \"ccfs\" then\
  18494.         local tabl, dir = Internal.makeTable(destination,filesystems)\
  18495.         tabl[dir] = fss\
  18496.     end\
  18497. end\
  18498. \
  18499. function setFS(path,fss)\
  18500.     if not fs.isDir(path) then fs.makeDir(path) end\
  18501.     if fss ~= \"ccfs\" then\
  18502.         local tabl, dir = Internal.makeTable(path,filesystems)\
  18503.         tabl[dir] = fss\
  18504.     end\
  18505. end\
  18506. \
  18507. function link(destination,source)\
  18508.     if not fs.exists(destination) then fs.makeDir(destination) end\
  18509.     if not fs.exists(source) then fs.makeDir(source) end\
  18510.     local tabl, dir = Internal.makeTable(destination,mounts)\
  18511.     tabl[dir] = source\
  18512. end\
  18513. \
  18514. function Internal.resolveLinks(path,tabl)\
  18515.     local first = Internal.getFirstElement(path)\
  18516.     if tabl[first] then\
  18517.         if type(tabl[first]) == \"table\" then\
  18518.             return Internal.resolveLinks(path:sub(path:find(\"/\") and path:find(\"/\")+1 or 1,-1),tabl[first])\
  18519.         elseif type(tabl[first]) == \"string\" then\
  18520.             return tabl[first]..\"/\"..path:sub(#Internal.getFirstElement(path)+2,-1)\
  18521.         end\
  18522.     end\
  18523.     return false\
  18524. end\
  18525. \
  18526. function Internal.intermediateResolveLinks(path)\
  18527.     resolved = Internal.resolveLinks(path,mounts)\
  18528.     if resolved == false then\
  18529.         return path\
  18530.     else\
  18531.         Utils.debug(\"Using Immediate again\")\
  18532.         return Internal.intermediateResolveLinks(resolved)\
  18533.     end\
  18534. end\
  18535. \
  18536. function resolveLinks(path)\
  18537.     --Utils.debug(\"Resolving link: \"..tostring(path))\
  18538.     local toReturn =  Internal.intermediateResolveLinks(fs.combine(\"\",path))\
  18539.     --Utils.debug(\"Resolved link: \"..tostring(toReturn))\
  18540.     return toReturn\
  18541. end\
  18542. \
  18543. function Internal.getFS(path,tabl)\
  18544.     --Utils.debug(\"Getinng FS, internal \"..path,tostring(tabl))\
  18545.     local first = Internal.getFirstElement(path)\
  18546.     if tabl[first] then\
  18547.         if type(tabl[first]) == \"table\" then\
  18548.             return Internal.getFS(path:sub(path:find(\"/\") and path:find(\"/\")+1 or 1,-1),tabl[first])\
  18549.         elseif type(tabl[first]) == \"string\" then\
  18550.             return tabl[first]\
  18551.         end\
  18552.     end\
  18553.     return false\
  18554. end\
  18555. \
  18556. function getFS(path)\
  18557.     resolved = Internal.getFS(fs.combine(\"\",path),filesystems)\
  18558.     --Utils.debug(\"Path \"..path..\" has FS \"..(resolved or \"ccfs\")..\" while resolved is \"..(resolved or \"false\")..\".\")\
  18559.     return resolved or \"ccfs\"\
  18560. end\
  18561. \
  18562. --mount(\"OmniOS/Programs/FileX.app\",\"disk1\",\"mls\")\
  18563. --mount(\"disk1\",\"OmniOS/API\",\"lol\")\
  18564. --print(\"lol\")\
  18565. --print(resolveLinks(\"OmniOS/Programs/FileX.app/Data/coo\"))\
  18566. --print(\"lol\")\
  18567. --print(getFS(\"OmniOS/Programs\"))\
  18568. --print(textutils.serialize(filesystems))",
  18569.   },
  18570.   Languages = {
  18571.     [ "Boot_EN.lang" ] = "{\
  18572.     \"Loading API list...\",\
  18573.     \"Finished loading API list...\",\
  18574.     \"Loading APIs...\",\
  18575.     \"Finished loading APIs...\",\
  18576.     \"\",\
  18577. }",
  18578.   },
  18579.   Settings = {
  18580.     Language = {
  18581.       CurrentLang = "EN",
  18582.     },
  18583.     Users = {
  18584.       Admin = "8e7d6efe3995f32fa9481828d3d52f0777e740f2d8cb468a82506b9e5dc78f8a",
  18585.     },
  18586.   },
  18587. }
  18588.  
  18589.  
  18590.  
  18591.  
  18592.  
  18593.  
  18594.  
  18595.  
  18596. local function writeFile(path,content)
  18597.     local file = fs.open(path,"w")
  18598.     file.write(content)
  18599.     file.close()
  18600. end
  18601. function writeDown(input,dir)
  18602.         for i,v in pairs(input) do
  18603.         if type(v) == "table" then
  18604.             writeDown(v,dir.."/"..i)
  18605.         elseif type(v) == "string" then
  18606.             writeFile(dir.."/"..i,v)
  18607.         end
  18608.     end
  18609. end
  18610.  
  18611. args = {...}
  18612. if #args == 0 then
  18613.     print("Please input a destination folder.")
  18614. else
  18615.     writeDown(inputTable,args[1])
  18616. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement