Advertisement
programcreator

OmniOS: v15w17a

Apr 21st, 2015
380
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 396.32 KB | None | 0 0
  1. inputTable = {
  2.   Logs = {
  3.     [ "Desktop1.log" ] = "[1:19.937].[Desktop1]:Error: NewInteract.lua:240: bad argument: table expected, got nil\
  4. [1:23.196].[Desktop1]:Error: NewInteract.lua:266: bad argument: table expected, got nil\
  5. [2:0.564].[Desktop1]:Error: Main.lua:59: attempt to call nil\
  6. [2:14.59].[Desktop1]:Error: Main.lua:58: attempt to call nil\
  7. [2:22.897].[Desktop1]:Error: Main.lua:60: attempt to call nil\
  8. [3:0.392].[Desktop1]:Error: Main.lua:63: attempt to call nil\
  9. [3:1.288].[Desktop1]:Error: Main.lua:63: attempt to call nil\
  10. [3:2.773].[Desktop1]:Error: NewInteract.lua:316: Invalid redirect target\
  11. [3:3.907].[Desktop1]:Error: Main.lua:69: attempt to call nil\
  12. [4:4.75].[Desktop1]:Error: Main.lua:70: attempt to index ? (a nil value)\
  13. [4:7.729].[Desktop1]:Error: NewInteract.lua:710: attempt to perform arithmetic __add on number and nil\
  14. [4:17.287].[Desktop1]:Error: Main.lua:90: attempt to concatenate string and table\
  15. [12:13.78].[Desktop1]:Error: Kernel.lua:116: attempt to index ? (a nil value)\
  16. [12:14.271].[Desktop1]:Error: Kernel.lua:116: attempt to index ? (a nil value)\
  17. [12:16.966].[Desktop1]:Error: Kernel.lua:116: attempt to index ? (a nil value)\
  18. [13:9.149].[Desktop1]:Error: Sandbox.lua:19: attempt to call nil\
  19. [15:17.764].[Desktop1]:Error: Kernel.lua:118: attempt to call nil\
  20. [15:20.064].[Desktop1]:Error: Kernel.lua:118: attempt to call nil\
  21. [15:21.409].[Desktop1]:Error: Kernel.lua:118: attempt to call nil\
  22. [16:1.498].[Desktop1]:Error: Kernel.lua:118: attempt to call nil\
  23. [16:2.398].[Desktop1]:Error: Kernel.lua:118: attempt to call nil",
  24.     [ "Sandbox.log" ] = "[16:22.159]:FileX1\
  25. [17:3.7]:FileX1\
  26. [17:9.873]:FileX1\
  27. [17:12.003]:FileX\
  28. [17:13.086]:FileX\
  29. [17:17.765]:Edit\
  30. [17:19.83]:FileX\
  31. [17:19.904]:edit\
  32. [18:1.495]:FileX",
  33.     [ "edit1.log" ] = "[17:19.905].[edit1]:Error: Main.lua:61: attempt to index ? (a nil value)",
  34.     [ "SandboxPath.log" ] = "[17:9.875]:OmniOS/Programs/FileX1.app/\
  35. [17:12.005]:OmniOS/Programs/FileX.app/\
  36. [17:12.072]:OmniOS/Programs/FileX.app/\
  37. [17:12.092]:OmniOS/Programs/FileX.app//Data\
  38. [17:12.11]:OmniOS/Programs/FileX.app/\
  39. [17:12.841]:OmniOS/Programs/FileX.app/\
  40. [17:13.091]:OmniOS/Programs/FileX.app/\
  41. [17:17.81]:OmniOS/Programs/Edit.app/OmniOS/Data/here\
  42. [17:19.831]:OmniOS/Programs/FileX.app/\
  43. [17:19.905]:OmniOS/Programs/edit.app//permission.data\
  44. [18:1.496]:OmniOS/Programs/FileX.app/",
  45.     [ "Aware1.log" ] = "[15:8.569].[Aware1]:Error: Main.lua:38: attempt to index ? (a nil value)",
  46.     [ "Calculator.log" ] = "[3:0.392]:bios:366: [string \"Main.layout\"]:48: unexpected symbol\
  47. [3:1.288]:bios:366: [string \"Main.layout\"]:59: '}' expected (to close '{' at line 2)\
  48. [11:1.347]:atan(\
  49. [11:1.385]:1\
  50. [11:1.411]:2\
  51. [12:12.198]:2\
  52. [12:12.223]:+",
  53.     [ "System.log" ] = "[15:20.028]:Launching task Desktop. By kernel\
  54. [15:20.064]:Opening app FileX\
  55. [15:20.064]:Opening app FileX: retrieved permissions.\
  56. [15:20.064]:Opening app FileX: about to launch task.\
  57. [15:20.064]:Launching task FileX. By kernel\
  58. [15:20.064]:Launching task FileX1: adding environment. By kernel\
  59. [15:21.381]:Launching task Desktop. By kernel\
  60. [15:21.409]:Opening app FileX\
  61. [15:21.409]:Opening app FileX: retrieved permissions.\
  62. [15:21.409]:Opening app FileX: about to launch task.\
  63. [15:21.409]:Launching task FileX. By kernel\
  64. [15:21.409]:Launching task FileX1: adding environment. By kernel\
  65. [16:1.466]:Launching task Desktop. By kernel\
  66. [16:1.498]:Opening app FileX\
  67. [16:1.498]:Opening app FileX: retrieved permissions.\
  68. [16:1.498]:Opening app FileX: about to launch task.\
  69. [16:1.498]:Launching task FileX. By kernel\
  70. [16:1.498]:Launching task FileX1: adding environment. By kernel\
  71. [16:2.373]:Launching task Desktop. By kernel\
  72. [16:2.398]:Opening app Edit\
  73. [16:2.398]:Opening app Edit: retrieved permissions.\
  74. [16:2.398]:Opening app Edit: about to launch task.\
  75. [16:2.398]:Launching task Edit. By kernel\
  76. [16:2.398]:Launching task Edit1: adding environment. By kernel\
  77. [16:3.636]:Launching task Desktop. By kernel\
  78. [16:3.682]:Opening app FileX\
  79. [16:3.682]:Opening app FileX: retrieved permissions.\
  80. [16:3.682]:Opening app FileX: about to launch task.\
  81. [16:3.682]:Launching task FileX. By kernel\
  82. [16:3.682]:Launching task FileX1: adding environment. By kernel\
  83. [16:3.683]:Opening app FileX: launched task.\
  84. [16:22.128]:Launching task Desktop. By kernel\
  85. [16:22.159]:Opening app FileX\
  86. [16:22.159]:Opening app FileX: retrieved permissions.\
  87. [16:22.159]:Opening app FileX: about to launch task.\
  88. [16:22.159]:Launching task FileX. By kernel\
  89. [16:22.159]:Launching task FileX1: adding environment. By kernel\
  90. [16:22.161]:Opening app FileX: launched task.\
  91. [17:3.7]:Opening app FileX\
  92. [17:3.7]:Opening app FileX: retrieved permissions.\
  93. [17:3.7]:Opening app FileX: about to launch task.\
  94. [17:3.7]:Launching task FileX. By kernel\
  95. [17:3.7]:Launching task FileX1: adding environment. By kernel\
  96. [17:3.701]:Opening app FileX: launched task.\
  97. [17:9.84]:Launching task Desktop. By kernel\
  98. [17:9.872]:Opening app FileX\
  99. [17:9.872]:Opening app FileX: retrieved permissions.\
  100. [17:9.872]:Opening app FileX: about to launch task.\
  101. [17:9.873]:Launching task FileX. By kernel\
  102. [17:9.873]:Launching task FileX1: adding environment. By kernel\
  103. [17:9.875]:Opening app FileX: launched task.\
  104. [17:11.972]:Launching task Desktop. By kernel\
  105. [17:12.002]:Opening app FileX\
  106. [17:12.002]:Opening app FileX: retrieved permissions.\
  107. [17:12.003]:Opening app FileX: about to launch task.\
  108. [17:12.003]:Launching task FileX. By kernel\
  109. [17:12.003]:Launching task FileX1: adding environment. By kernel\
  110. [17:12.005]:Opening app FileX: launched task.\
  111. [17:12.864]:Opening app BetterPaint\
  112. [17:12.864]:Opening app BetterPaint: retrieved permissions.\
  113. [17:12.865]:Opening app BetterPaint: about to launch task.\
  114. [17:12.865]:Launching task BetterPaint. By kernel\
  115. [17:12.868]:Opening app BetterPaint: launched task.\
  116. [17:13.086]:Opening app FileX\
  117. [17:13.086]:Opening app FileX: retrieved permissions.\
  118. [17:13.086]:Opening app FileX: about to launch task.\
  119. [17:13.086]:Launching task FileX. By kernel\
  120. [17:13.086]:Launching task FileX2: adding environment. By kernel\
  121. [17:13.092]:Opening app FileX: launched task.\
  122. [17:13.196]:Opening app BetterPaint\
  123. [17:13.196]:Opening app BetterPaint: retrieved permissions.\
  124. [17:13.196]:Opening app BetterPaint: about to launch task.\
  125. [17:13.196]:Launching task BetterPaint. By kernel\
  126. [17:13.199]:Opening app BetterPaint: launched task.\
  127. [17:17.737]:Launching task Desktop. By kernel\
  128. [17:17.765]:Opening app Edit\
  129. [17:17.765]:Opening app Edit: retrieved permissions.\
  130. [17:17.765]:Opening app Edit: about to launch task.\
  131. [17:17.765]:Launching task Edit. By kernel\
  132. [17:17.765]:Launching task Edit1: adding environment. By kernel\
  133. [17:17.766]:Opening app Edit: launched task.\
  134. [17:19.83]:Opening app FileX\
  135. [17:19.83]:Opening app FileX: retrieved permissions.\
  136. [17:19.83]:Opening app FileX: about to launch task.\
  137. [17:19.83]:Launching task FileX. By kernel\
  138. [17:19.83]:Launching task FileX1: adding environment. By kernel\
  139. [17:19.831]:Opening app FileX: launched task.\
  140. [17:19.904]:Opening app edit\
  141. [17:19.904]:Opening app edit: retrieved permissions.\
  142. [17:19.904]:Opening app edit: about to launch task.\
  143. [17:19.904]:Launching task edit. By kernel\
  144. [17:19.904]:Launching task edit1: adding environment. By kernel\
  145. [17:19.905]:Opening app edit: launched task.\
  146. [18:1.411]:Launching task Desktop. By kernel\
  147. [18:1.495]:Opening app FileX\
  148. [18:1.495]:Opening app FileX: retrieved permissions.\
  149. [18:1.495]:Opening app FileX: about to launch task.\
  150. [18:1.495]:Launching task FileX. By kernel\
  151. [18:1.495]:Launching task FileX1: adding environment. By kernel\
  152. [18:1.496]:Opening app FileX: launched task.",
  153.     [ "Error.log" ] = "[1:19.937].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  154. [1:23.196].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  155. [2:0.565].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  156. [2:14.592].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  157. [2:22.897].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  158. [3:0.393].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  159. [3:1.289].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  160. [3:2.773].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  161. [3:3.907].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  162. [4:4.637].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  163. [4:4.75].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  164. [4:7.729].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  165. [4:9.837].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  166. [4:17.288].[Missing]: Kernel.lua:104: attempt to index ? (a nil value)\
  167. [12:13.78].[Missing]: Kernel.lua:105: attempt to index ? (a nil value)\
  168. [12:14.271].[Missing]: Kernel.lua:105: attempt to index ? (a nil value)\
  169. [12:16.966].[Missing]: Kernel.lua:105: attempt to index ? (a nil value)\
  170. [13:9.15].[Missing]: Kernel.lua:105: attempt to index ? (a nil value)\
  171. [15:17.764].[Missing]: 199\
  172. [15:20.064].[Missing]: 194\
  173. [15:21.411].[Missing]: 194\
  174. [16:1.499].[Missing]: 198\
  175. [16:2.399].[Missing]: 194",
  176.     [ "FileX1.log" ] = "[1:12.644].[FileX1]:Error: Main.lua:756: attempt to index ? (a nil value)\
  177. [15:10.283].[FileX1]:Error: Main.lua:756: attempt to index ? (a nil value)\
  178. [15:15.363].[FileX1]:Error: Main.lua:756: attempt to index ? (a nil value)\
  179. [16:3.683].[FileX1]:Error: Main.lua:-1: Not a directory\
  180. [16:22.161].[FileX1]:Error: Main.lua:397: Not a directory\
  181. [17:3.701].[FileX1]:Error: Main.lua:-1: Not a directory\
  182. [17:9.875].[FileX1]:Error: Main.lua:397: Not a directory",
  183.   },
  184.   [ "README.md" ] = "# TheOS\
  185. GitHub repository of TheOS",
  186.   [ "BIOS.lua" ] = "--[[\
  187.     BIOS by Creator\
  188.     for OmniOS\
  189. ]]--\
  190. \
  191. term.redirect(term.native())\
  192. \
  193. --Variables--\
  194. local gui = {}\
  195. local OS = {}\
  196. local timeLeft = 5\
  197. local currentOS = 1\
  198. local defaultOS = \"\"\
  199. local toBoot = 0\
  200. local layout = [[\
  201.     +-----------------------------------------+\
  202.     | Current selection:                      |\
  203.     |                                         |\
  204.     +-----------------------------------------+\
  205.     | Available OSes:                         |\
  206.     |                                         |\
  207.     |                                         |\
  208.     |                                         |\
  209.     |                                         |\
  210.     |                                         |\
  211.     |                                         |\
  212.     +-----------------------------------------+\
  213.     | S: Settings                             |\
  214.     +-----------------------------------------+\
  215.     | Time left:                              |\
  216.     +-----------------------------------------+\
  217. ]]\
  218. --Functions\
  219. function gui.clear()\
  220.     term.setBackgroundColor(colors.blue)\
  221.     term.setTextColor(colors.white)\
  222.     term.setCursorPos(1,2)\
  223.     term.clear()\
  224. end\
  225. \
  226. function gui.drawMain()\
  227.     gui.clear()\
  228.     term.setCursorPos(1,3)\
  229.     print(layout)\
  230.     term.setCursorPos(8,4)\
  231.     term.write(OS[currentOS][1])\
  232.     for i = 1, #OS do\
  233.         term.setCursorPos(8,i+6)\
  234.         term.write(i..\") \"..OS[i][1])\
  235.     end\
  236.     term.setCursorPos(19,16)\
  237.     term.write(timeLeft)\
  238. end\
  239. \
  240. local function loadOS()\
  241.     return dofile(\"OmniOS/BIOS/List\")\
  242. end\
  243. \
  244. local function loadDefault()\
  245.     return dofile(\"OmniOS/BIOS/default\")\
  246. end\
  247. \
  248. local function findCurrent()\
  249.     for i, v in pairs(OS) do\
  250.         if defaultOS == v[1] then\
  251.             return i\
  252.         end\
  253.     end\
  254.     error(\"The OS you are searching does not exist!\")\
  255. end\
  256. \
  257. --Code\
  258. OS = loadOS()\
  259. defaultOS = loadDefault()\
  260. currentOS = findCurrent()\
  261. while true do \
  262.     gui.drawMain()\
  263.     local timerID = os.startTimer(1)\
  264.     local event = {os.pullEvent()}\
  265.     if timeLeft == 0 then\
  266.         toBoot = currentOS\
  267.         break\
  268.     end\
  269.     if event[1] == \"key\" then\
  270.         os.cancelTimer(timerID)\
  271.         if 2 <= event[2] and event[2] <= 11 then\
  272.             event[2] = event[2] == 11 and 0 or event[2] - 1\
  273.             if OS[event[2]] then\
  274.                 toBoot = event[2]\
  275.                 break\
  276.             end\
  277.         elseif event[2] == keys.up then\
  278.             currentOS = currentOS - 1\
  279.             currentOS = currentOS == 0 and #OS or currentOS\
  280.         elseif event[2] == keys.down then\
  281.             currentOS = currentOS + 1\
  282.             currentOS = currentOS == #OS + 1 and 1 or currentOS\
  283.         elseif event[2] == keys.enter then\
  284.             toBoot = currentOS\
  285.             break\
  286.         end\
  287.     elseif event[1] == \"timer\" and event[2] == timerID then\
  288.         timeLeft = timeLeft - 1\
  289.     end\
  290. end\
  291. \
  292. if OS[toBoot][1] == \"CraftOS\" then\
  293.     term.setBackgroundColor(colors.black)\
  294.     term.setTextColor(colors.yellow)\
  295.     term.clear()\
  296.     term.setCursorPos(1,1)\
  297.     print(\"CraftOS 1.7\")\
  298. else\
  299.     dofile(OS[toBoot][2])\
  300. end",
  301.   Media = {
  302.     Boot = {
  303.       [ "Boot_Logo.nfp" ] = "d  d     eeeeeeeee\
  304. dd d  ddde   ee   \
  305. d  dddddde   eeeee\
  306. d  d dd  e   e   e\
  307. dddd ddddeeeeeeeee",
  308.       [ "Boot_Hide.nfp" ] = "000000000000000000000000000\
  309. 000000000000000000000000000\
  310. 000000000000000000000000000\
  311. 000000000000000000000000000\
  312. 000000000000000000000000000\
  313. 000000000000000000000000000\
  314. 000000000000000000000000000\
  315. 000000000000000000000000000",
  316.     },
  317.   },
  318.   int = "   term.clear()\
  319.     gui = Interact.Initialize()\
  320.     button = gui.Button.new( {\
  321.             name = \"Hi\",\
  322.             label = \"hello\",\
  323.             xPos = 2,\
  324.             yPos = 5,\
  325.             fgColor = colors.white,\
  326.             bgColor = colors.orange,\
  327.             xLength = 7,\
  328.             yLength = 3,\
  329.             returnValue = \"hi\",\
  330.             xTextPos = 2,\
  331.             yTextPos = 2,\
  332.             onRightClick = function() print(\"wow\") sleep(3) end,\
  333.             onLeftClick = function() os.shutdown() end,\
  334.         })\
  335.     button:draw()\
  336.     \
  337.     os.pullEvent()",
  338.   BIOS = {
  339.     default = "return \"OmniOS\"",
  340.     List = " return {\
  341.     { \"OmniOS\",\"OmniOS/Core/Boot.lua\" },\
  342.     {\"CraftOS\",\"shell\"},\
  343. }",
  344.   },
  345.   CodeIDontNeedNow = {
  346.     toggles = " ToggleTable = {\
  347.     test = {\
  348.         name = \"beu\",\
  349.         state = false,\
  350.         xPos = 7,\
  351.         yPos = 8,\
  352.         trueColor = colors.green,\
  353.         falseColor = colors.red,\
  354.         trueText = \"T\",\
  355.         falseText = \"F\",\
  356.         selectedBg = colors.gray,\
  357.         notSelectedBg = colors.black,\
  358.         returnValue = \"yyy\",\
  359.     }\
  360. }",
  361.     [ "Installer.lua" ] = "args = {...}\
  362. local sPath = args[1]\
  363. local filesystem = {}\
  364. \
  365. local function readFile(path)\
  366.     local file = fs.open(path,\"r\")\
  367.     local variable = file.readAll()\
  368.     file.close()\
  369.     return variable\
  370. end\
  371. \
  372. filesystem = textutils.unserialize(readFile(sPath))\
  373. \
  374. \
  375. local function writeFile(path,content)\
  376.     local file = fs.open(path,\"w\")\
  377.     file.write(content)\
  378.     file.close()\
  379. end\
  380.     \
  381. function writeDown(input,dir)\
  382.     for i,v in pairs(input) do\
  383.         if type(v) == \"table\" then\
  384.             writeDown(v,dir..\"/\"..i)\
  385.         elseif type(v) == \"string\" then\
  386.             writeFile(dir..\"/\"..i,v)\
  387.         end\
  388.     end\
  389. end\
  390. writeDown(filesystem,\"TheOS\")",
  391.   },
  392.   wow = "function test()\
  393. pritn(\"hello\") --# will error\
  394. end\
  395. \
  396. local ok, res = coroutine.resume( coroutine.create( test ) )\
  397. \
  398. print( tostring(ok) .. \":\" .. res )",
  399.   Core = {
  400.     [ "LoadAPIs.lua" ] = "--Code--\
  401. local apis = fs.list(\"OmniOS/API/\")\
  402. local dirs = {}\
  403. function loadAPI( _sPath )\
  404.    local sName = fs.getName( _sPath )\
  405.    local tEnv = {}\
  406.    setmetatable( tEnv, { __index = _G } )\
  407.    local fnAPI, err = loadfile( _sPath )\
  408.    if fnAPI then\
  409.        setfenv( fnAPI, tEnv )\
  410.        local ok, err = pcall( fnAPI )\
  411.        if not ok then\
  412.            printError( err )\
  413.            return false\
  414.        end\
  415.    else\
  416.        printError( err )\
  417.        return false\
  418.    end\
  419.    \
  420.    local tAPI = {}\
  421.    for k,v in pairs( tEnv ) do\
  422.        tAPI[k] =  v\
  423.    end\
  424.    \
  425.    _G[sName:match(\"[^%.]+\")] = tAPI    \
  426.    return true\
  427. end\
  428. for i,v in pairs(apis) do\
  429.     if fs.isDir(\"OmniOS/API/\"..v) then\
  430.         dirs[i] = true\
  431.     end\
  432. end\
  433. for i,v in pairs(dirs) do\
  434.     apis[i] = nil\
  435. end\
  436. for i,v in pairs(apis) do\
  437.     loadAPI(\"OmniOS/API/\"..v)\
  438.     term.setTextColor(colors.black)\
  439.     print(v)\
  440. end\
  441. os.pullEvent()",
  442.     [ "Boot.lua" ] = "--OmniOS: Boot--\
  443. --by Creator--\
  444. \
  445. --Variables--\
  446. local tasks = 2\
  447. local finishedTasks = 0\
  448. term.redirect(term.native())\
  449. local w,h = term.getSize()\
  450. local textutilsserialize = textutils.serialize\
  451. local textutilsunserialize = textutils.unserialize\
  452. local APIlist = {}\
  453. local oldPullEvent = os.pullEvent\
  454. local whichLang = nil\
  455. local lang = {}\
  456. local oldFs = {}\
  457. local logo  = paintutils.loadImage(\"OmniOS/Media/Boot/Boot_Logo.nfp\")\
  458. local hideLogo = paintutils.loadImage(\"OmniOS/Media/Boot/Boot_Hide.nfp\")\
  459. local logoWide = 18\
  460. --Functions--\
  461. \
  462. local function nPrint(text)\
  463.     finishedTasks = finishedTasks + 1\
  464.     local txt = \"OmniOS by Creator\"\
  465.     term.setBackgroundColor(colors.white)\
  466.     term.setTextColor(colors.lightGray)\
  467.     term.clear()\
  468.     term.setCursorPos(math.floor((w-#txt)/2),math.floor(h/2)-1)\
  469.     term.write(txt)\
  470.     term.setTextColor(colors.gray)\
  471.     term.setCursorPos(math.floor((w-#text)/2),math.floor(h/2))\
  472.     term.write(text)\
  473.     paintutils.drawImage(logo,math.floor((w-logoWide)/2),math.floor(h/2)+3)\
  474.     paintutils.drawImage(hideLogo,math.floor((w-logoWide)/2)+math.ceil((finishedTasks/tasks)*logoWide),math.floor(h/2)+3)\
  475.     sleep(.2)\
  476. end\
  477. \
  478. --Code--\
  479. \
  480. term.setTextColor(colors.white)\
  481. term.setBackgroundColor(colors.white)\
  482. term.clear()\
  483. term.setCursorPos(1,1)\
  484. \
  485. --Load language file--\
  486. langFile = fs.open(\"OmniOS/Settings/Language/CurrentLang\",\"r\")\
  487. whichLang = langFile.readAll()\
  488. langFile.close()\
  489. \
  490. langFile = fs.open(\"OmniOS/Languages/Boot_\"..whichLang..\".lang\",\"r\")\
  491. lang = textutilsunserialize(langFile.readAll())\
  492. langFile.close()\
  493. \
  494. --Load APIs--\
  495. nPrint(lang[3])\
  496. dofile(\"OmniOS/Core/LoadAPIs.lua\")\
  497. nPrint(lang[4])\
  498. \
  499. --Overwrite os.pullEventFunctions--\
  500. --oldPullEvent = os.pullEvent\
  501. --os.pullEvent = os.pullEventRaw\
  502. \
  503. --Go to next\
  504. function goOn()\
  505.     local login, err = loadfile(\"OmniOS/Core/Login.lua\")\
  506.     if err then print(err) log.log(\"Error\",err) os.pullEvent() end\
  507.     --login()\
  508.     local kernel, err= loadfile(\"OmniOS/Core/Kernel.lua\")\
  509.     if err then print(err) os.pullEvent() log.log(\"Error\",err) end\
  510.     local desktop,err = loadfile(\"OmniOS/Programs/Desktop.app/Main.lua\")\
  511.     if err then print(err) os.pullEvent() log.log(\"Error\",err) end\
  512.     kernel(\"Desktop\",\"Desktop\",desktop,\"user\")\
  513. end\
  514. \
  515. ok, err = pcall(goOn)\
  516. \
  517. if not ok then\
  518.     pcall(shell.run(\"OmniOS/Core/Crash.lua \"..err))\
  519. end",
  520.     [ "Login.lua" ] = "--Variables--\
  521. local notLogin = true\
  522. local w,h = term.getSize()\
  523. term.redirect(term.native())\
  524. local user = nil\
  525. local pass = nil\
  526. \
  527. --Code--\
  528. --Startup script--\
  529. term.setBackgroundColor(colors.white)\
  530. term.clear()\
  531. term.setCursorPos(1,1)\
  532. term.setTextColor(colors.black)\
  533. \
  534. --GUI\
  535. gui.resetButtons()\
  536. gui.resetKeys()\
  537. gui.cPrint(\"Login\",colors.black,nil,math.floor((w-5)/2),3)\
  538. --gui.cPrint(\"Username: >\",colors.gray,nil,3,6)\
  539. gui.cPrint(\"Password: >\",colors.gray,nil,3,8)\
  540. --gui.addField(15,6,20,1,\"userField\")\
  541. --paintutils.drawFilledBox(15,6,35,6,colors.lightGray)\
  542. gui.addField(15,8,20,1,\"passField\")\
  543. paintutils.drawFilledBox(15,8,35,8,colors.lightGray)\
  544. gui.addKey(keys.enter,\"Enter\")\
  545. gui.drawButton(15,10,8,3,colors.green,2,2,\"Ready!\",colors.black,\"ready\")\
  546. \
  547. --Main Loop--\
  548. while notLogin do\
  549.     --Script\
  550.     local result = gui.detectButtonOrKeyHit()\
  551.     if result[1] == \"userField\" then\
  552.         paintutils.drawFilledBox(15,6,35,6,colors.lightGray)\
  553.         term.setCursorPos(15,6)\
  554.         term.setTextColor(colors.black)\
  555.         user = read()\
  556.     elseif result[1] == \"passField\" then\
  557.         paintutils.drawFilledBox(15,8,35,8,colors.lightGray)\
  558.         term.setCursorPos(15,8)\
  559.         term.setTextColor(colors.black)\
  560.         pass = read(\"*\")\
  561.     elseif result[1] == \"Enter\" or result[1] == \"ready\" then\
  562.         if user == nil or pass == nil then\
  563.         else\
  564.             paintutils.drawFilledBox(15,15,35,15,colors.lightGray)\
  565.             local realPass\
  566.             ok = pcall( function()\
  567.             f = fs.open(\"TheOS/Settings/Users/Admin\",\"r\")\
  568.             realPass = f.readAll()\
  569.             f.close()\
  570.             end )\
  571.             if realPass == Sha.sha256(pass) then\
  572.                 notLogin = false\
  573.             end\
  574.             if ok == false or notLogin then\
  575.                 gui.cPrint(\"Wrong username or password!\",colors.red,colors.white,13,15)\
  576.             end\
  577.         end\
  578.     end\
  579. end",
  580.     [ "Crash.lua" ] = "os.pullEvent = os.pullEventRaw\
  581. tArgs = {...}\
  582. \
  583. err = \"\"\
  584. \
  585. term.redirect(term.native())\
  586. term.setBackgroundColor(colors.blue)\
  587. term.clear()\
  588. term.setTextColor(colors.white)\
  589. term.setCursorPos(2,4)\
  590. term.write(\"TheOS has crashed :(\")\
  591. term.setCursorPos(2,6)\
  592. 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 TheOnlyCreator on GitHub.\")\
  593. term.setCursorPos(2,11)\
  594. term.write(\"Error message: \")\
  595. term.setCursorPos(4,13)\
  596. for i,v in pairs(tArgs) do\
  597.     err = err..\" \"..v\
  598. end\
  599. print(err)\
  600. log.log(\"Error\",err,\"Missing\")\
  601. os.pullEvent(\"mouse_click\")\
  602. --os.reboot()",
  603.     [ "Kernel.lua" ] = "--[[\
  604.     TheOS Kernel\
  605.     by Creator\
  606.     for TheOS &\
  607.     you to learn\
  608.     from it! (Yeah learn, rather become dumber)\
  609.     theoriginalbit\
  610.     also gets credit for \
  611.     his safePairs function.\
  612.     Lots of thanks to BombBloke too for \
  613.     finalizing and bug fixing it.\
  614. ]]--\
  615. \
  616. local logMessage = \"\"\
  617. local history = {}\
  618. local w,h = term.getSize()\
  619. local currTerm, routines, activeRoutine, eventBuffer = term.current(), {}, \"\", {}\
  620. local eventFilter = {[\"key\"] = true, [\"mouse_click\"] = true, [\"monitor_touch\"] = true, [\"paste\"] = true,\
  621.     [\"char\"] = true, [\"terminate\"] = true, [\"mouse_scroll\"] = true, [\"mouse_drag\"] = true}\
  622. \
  623. local function safePairs(t)\
  624.  local keys = {}\
  625.  for k,v in pairs(t) do\
  626.     keys[#keys+1] = k\
  627.  end\
  628.  local i = 0\
  629.  return function()\
  630.     i = i + 1\
  631.     return keys[i], t[keys[i]]\
  632.  end\
  633. end\
  634. \
  635. local function drawClosed()\
  636.     paintutils.drawLine(w,1,w,h,colors.black)\
  637.     term.setTextColor(colors.white)\
  638.     term.setBackgroundColor(colors.black)\
  639.     term.setCursorPos(w,h/2+2)\
  640.     term.write(\"<\")\
  641. end\
  642. \
  643. local function drawOpen()\
  644.     term.setCursorBlink(false)\
  645.     paintutils.drawFilledBox(w-15,1,w,h,colors.black)\
  646.     local xVsProcess, curr = {}, 1\
  647.     term.setTextColor(colors.white)\
  648.     for i,v in pairs(routines) do\
  649.         paintutils.drawLine(w-15,curr*2,w,curr*2,i == activeRoutine and colours.blue or colours.black)\
  650.         paintutils.drawLine(w-15,curr*2+1,w,curr*2+1,i == activeRoutine and colours.blue or colours.black)\
  651.         term.setBackgroundColour(i == activeRoutine and colours.blue or colours.black)\
  652.         term.setCursorPos(w-14,curr*2)\
  653.         term.write(\"x \"..v.title)\
  654.         term.setCursorPos(w-12,curr*2+1)\
  655.         term.write(coroutine.status(v.routine))\
  656.         xVsProcess[curr*2] = i\
  657.         curr = curr + 1\
  658.     end\
  659.     --print(activeRoutine)\
  660.     --for i,v in pairs(history) do\
  661.     --  print(i..\" \"..v)\
  662.     --end\
  663. \
  664.     while true do\
  665.         local evnt = {os.pullEventRaw()}\
  666.         if evnt[1] == \"mouse_click\" then\
  667.             if w-12 <= evnt[3] and evnt[3] <= w then\
  668.                 if xVsProcess[evnt[4]] then\
  669.                     routines[activeRoutine].window.setVisible( false )\
  670.                     activeRoutine = xVsProcess[evnt[4]]\
  671.                     routines[activeRoutine].window.setVisible(true)\
  672.                     history[#history+1] = activeRoutine\
  673.                     return\
  674.                 end\
  675.             elseif w-14 == evnt[3] then\
  676.                 if xVsProcess[evnt[4]] and xVsProcess[evnt[4]] ~= \"Desktop1\" then\
  677.                     if activeRoutine == xVsProcess[evnt[4]] then\
  678.                         --history[#history] = nil\
  679.                         --for i,v in pairs(history) do\
  680.                         --  if xVsProcess[evnt[4]] == v then\
  681.                         --      table.remove(history,i)\
  682.                         --  end\
  683.                         --activeRoutine = history[#history]\
  684.                         activeRoutine = \"Desktop1\"\
  685.                         routines[activeRoutine].window.setVisible(true)\
  686.                     end\
  687.                     routines[xVsProcess[evnt[4]]] = nil\
  688.                     return\
  689.                 end\
  690.             else return end\
  691.         else eventBuffer[#eventBuffer+1] = evnt end\
  692.     end\
  693. end\
  694. \
  695. local function checkIfDead(routine)\
  696.     if coroutine.status(routines[routine].routine) == \"dead\" then\
  697.         routines[routine] = nil\
  698.         if routine == activeRoutine then\
  699.             --history[#history] = nil\
  700.             --[[for i,v in pairs(history) do\
  701.                 if routine == v then\
  702.                     table.remove(history,i)\
  703.                 end\
  704.             end\
  705.             activeRoutine = history[#history]]--\
  706.             activeRoutine = \"Desktop1\"\
  707.             routines[activeRoutine].window.setVisible(true)\
  708.         end\
  709.         return true\
  710.     else return false end\
  711. end\
  712. \
  713. function newRoutine(name,title,func,permission,...)\
  714.     log.log(\"System\",\"Launching task \"..name..\". By kernel\")\
  715.     local oldName = name\
  716.     local tries = 1\
  717.     while routines[name .. tries] do tries = tries + 1 end\
  718.     name = name .. tries\
  719.     if permission == \"userTest\" then\
  720.         log.log(\"System\",\"Launching task \"..name..\": adding environment. By kernel\")\
  721.         local env = Sandbox.newEnv(oldName)\
  722.         --log.log(\"SandboxOutput\",textutils.serialize(env))\
  723.         setfenv(func,env)\
  724.     end\
  725. \
  726.     routines[name] = {\
  727.         [\"title\"] = title,\
  728.         [\"permission\"] = permission,\
  729.         [\"path\"] = path,\
  730.         [\"routine\"] = coroutine.create(func),\
  731.         [\"window\"] = OmniWindow.create(currTerm,1,1,w-1,h,true),\
  732.         [\"filter\"] = \"\",\
  733.     }\
  734. \
  735.     --Run it!\
  736.     if routines[activeRoutine] then routines[activeRoutine].window.setVisible(false) end\
  737.     activeRoutine = name\
  738.     term.redirect(routines[activeRoutine].window)\
  739.     routines[activeRoutine].window.setVisible(true)\
  740.     logMessage, routines[activeRoutine].filter = coroutine.resume(routines[activeRoutine].routine,...)\
  741.     if not logMessage then\
  742.         log.log(activeRoutine,\"Error: \"..tostring(routines[activeRoutine].filter),activeRoutine)\
  743.     end\
  744.     term.redirect(currTerm)\
  745.     checkIfDead(activeRoutine)\
  746.     history[#history+1] = activeRoutine\
  747. end\
  748. \
  749. function getPermission(program)\
  750.     return routines[program].permission or \"Not a valid program\"\
  751. end\
  752. \
  753. drawClosed()\
  754. \
  755. newRoutine(...)\
  756. \
  757. while true do\
  758.     local event = #eventBuffer == 0 and {os.pullEventRaw()} or table.remove(eventBuffer,1)\
  759.     if (event[1] == \"mouse_click\" or event[1] == \"monitor_touch\") and event[3] == w then\
  760.         drawOpen()\
  761.         drawClosed()\
  762.         routines[activeRoutine].window.redraw()\
  763.     elseif eventFilter[event[1]] then\
  764.         if routines[activeRoutine].filter == nil or routines[activeRoutine].filter == \"\" or routines[activeRoutine].filter == event[1] then\
  765.             term.redirect(routines[activeRoutine].window)\
  766.             logMessage, routines[activeRoutine].filter = coroutine.resume(routines[activeRoutine].routine,unpack(event))\
  767.             if not logMessage then\
  768.                 log.log(activeRoutine,\"Error: \"..tostring(routines[activeRoutine].filter),activeRoutine)\
  769.             end\
  770.             term.redirect(currTerm)\
  771.             checkIfDead(activeRoutine)\
  772.         end\
  773.     else\
  774.         for i,v in safePairs(routines) do\
  775.             term.redirect(routines[i].window)\
  776.             logMessage, routines[i].filter = coroutine.resume(routines[i].routine,unpack(event))\
  777.             if not logMessage then\
  778.                 log.log(i,\"Error: \"..tostring(routines[i].filter),i)\
  779.             end\
  780.             term.redirect(currTerm)\
  781.             checkIfDead(i)\
  782.         end\
  783.     end\
  784. end",
  785.   },
  786.   [ ".gitignore" ] = "*.log",
  787.   Data = {
  788.     [ ".toGitHub" ] = "",
  789.     wow = "really",
  790.     heyBro = "",
  791.     wut = "",
  792.     here = "error('This is an image, not a program!')\
  793. {\
  794.  {\
  795.    {\
  796.      1,\
  797.      \" \",\
  798.      1,\
  799.    },\
  800.  },\
  801.  [ 0 ] = {\
  802.    {\
  803.      1,\
  804.      \" \",\
  805.      1,\
  806.    },\
  807.  },\
  808.  [ 5 ] = {},\
  809. }",
  810.     where = "error('This is an image, not a program!')\
  811. {\
  812.  [ 11 ] = {\
  813.    [ 9 ] = {\
  814.      32768,\
  815.      \" \",\
  816.      1,\
  817.    },\
  818.  },\
  819. }",
  820.   },
  821.   API = {
  822.     [ "OmniWindow.lua" ] = "\
  823. function create( parent, nX, nY, nWidth, nHeight, bStartVisible )\
  824. \
  825.    if type( parent ) ~= \"table\" or\
  826.       type( nX ) ~= \"number\" or\
  827.       type( nY ) ~= \"number\" or\
  828.       type( nWidth ) ~= \"number\" or\
  829.       type( nHeight ) ~= \"number\" or\
  830.       (bStartVisible ~= nil and type( bStartVisible ) ~= \"boolean\") then\
  831.        error( \"Expected object, number, number, number, number, [boolean]\", 2 )\
  832.    end\
  833. \
  834.    if parent == term then\
  835.        error( \"term is not a recommended window parent, try term.current() instead\", 2 )\
  836.    end\
  837. \
  838.    -- Setup\
  839.    local bVisible = (bStartVisible ~= false)\
  840.    local nCursorX = 1\
  841.    local nCursorY = 1\
  842.    local bCursorBlink = false\
  843.    local nTextColor = colors.white\
  844.    local nBackgroundColor = colors.black\
  845.    local sEmpty = string.rep( \" \", nWidth )\
  846.    local tLines = {}\
  847.    do\
  848.        local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  849.        for y=1,nHeight do\
  850.            tLines[y] = tEmpty\
  851.        end\
  852.    end\
  853. \
  854.    -- Helper functions\
  855.    local function updateCursorPos()\
  856.        if nCursorX >= 1 and nCursorY >= 1 and\
  857.           nCursorX <= nWidth and nCursorY <= nHeight then\
  858.            parent.setCursorPos( nX + nCursorX - 1, nY + nCursorY - 1 )\
  859.        else\
  860.            parent.setCursorPos( 0, 0 )\
  861.        end\
  862.    end\
  863.    \
  864.    local function updateCursorBlink()\
  865.        parent.setCursorBlink( bCursorBlink )\
  866.    end\
  867.    \
  868.    local function updateCursorColor()\
  869.        parent.setTextColor( nTextColor )\
  870.    end\
  871.    \
  872.    local function redrawLine( n )\
  873.        parent.setCursorPos( nX, nY + n - 1 )\
  874.        local tLine = tLines[ n ]\
  875.        for m=1,#tLine do\
  876.            local tBit = tLine[ m ]\
  877.            parent.setTextColor( tBit[2] )\
  878.            parent.setBackgroundColor( tBit[3] )\
  879.            parent.write( tBit[1] )\
  880.        end\
  881.    end\
  882. \
  883.    local function lineLen( tLine )\
  884.        local nLength = 0\
  885.        for n=1,#tLine do\
  886.            nLength = nLength + string.len( tLine[n][1] )\
  887.        end\
  888.        return nLength\
  889.    end\
  890. \
  891.    local function lineSub( tLine, nStart, nEnd )\
  892.        --assert( math.floor(nStart) == nStart )\
  893.        --assert( math.floor(nEnd) == nEnd )\
  894.        --assert( nStart >= 1 )\
  895.        --assert( nEnd >= nStart )\
  896.        --assert( nEnd <= lineLen( tLine ) )\
  897.        local tSubLine = {}\
  898.        local nBitStart = 1\
  899.        for n=1,#tLine do\
  900.            local tBit = tLine[n]\
  901.            local sBit = tBit[1]\
  902.            local nBitEnd = nBitStart + string.len( sBit ) - 1\
  903.            if nBitEnd >= nStart and nBitStart <= nEnd then\
  904.                if nBitStart >= nStart and nBitEnd <= nEnd then\
  905.                    -- Include bit wholesale\
  906.                    table.insert( tSubLine, tBit )\
  907.                    --assert( lineLen( tSubLine ) == (math.min(nEnd, nBitEnd) - nStart + 1) )\
  908.                elseif nBitStart < nStart and nBitEnd <= nEnd then\
  909.                    -- Include end of bit\
  910.                    table.insert( tSubLine, {\
  911.                        string.sub( sBit, nStart - nBitStart + 1 ),\
  912.                        tBit[2], tBit[3]\
  913.                    } )\
  914.                    --assert( lineLen( tSubLine ) == (math.min(nEnd, nBitEnd) - nStart + 1) )\
  915.                elseif nBitStart >= nStart and nBitEnd > nEnd then\
  916.                    -- Include beginning of bit\
  917.                    table.insert( tSubLine, {\
  918.                        string.sub( sBit, 1, nEnd - nBitStart + 1 ),\
  919.                        tBit[2], tBit[3]\
  920.                    } )\
  921.                    --assert( lineLen( tSubLine ) == (math.min(nEnd, nBitEnd) - nStart + 1) )\
  922.                else\
  923.                    -- Include middle of bit\
  924.                    table.insert( tSubLine, {\
  925.                        string.sub( sBit, nStart - nBitStart + 1, nEnd - nBitStart + 1 ),\
  926.                        tBit[2], tBit[3]\
  927.                    } )\
  928.                    --assert( lineLen( tSubLine ) == (math.min(nEnd, nBitEnd) - nStart + 1) )\
  929.                end\
  930.            end\
  931.            nBitStart = nBitEnd + 1\
  932.        end\
  933.        --assert( lineLen( tSubLine ) == (nEnd - nStart + 1) )\
  934.        return tSubLine\
  935.    end\
  936. \
  937.    local function lineJoin( tLine1, tLine2 )\
  938.        local tNewLine = {}\
  939.        if tLine1[#tLine1][2] == tLine2[1][2] and\
  940.           tLine1[#tLine1][3] == tLine2[1][3] then\
  941.            -- Merge middle bits\
  942.            for n=1,#tLine1-1 do\
  943.                table.insert( tNewLine, tLine1[n] )\
  944.            end\
  945.            table.insert( tNewLine, {\
  946.                tLine1[#tLine1][1] .. tLine2[1][1],\
  947.                tLine2[1][2], tLine2[1][3]\
  948.            } )\
  949.            for n=2,#tLine2 do\
  950.                table.insert( tNewLine, tLine2[n] )\
  951.            end\
  952.            --assert( lineLen( tNewLine ) == lineLen(tLine1) + lineLen(tLine2) )\
  953.        else\
  954.            -- Just concatenate\
  955.            for n=1,#tLine1 do\
  956.                table.insert( tNewLine, tLine1[n] )\
  957.            end\
  958.            for n=1,#tLine2 do\
  959.                table.insert( tNewLine, tLine2[n] )\
  960.            end\
  961.            --assert( lineLen( tNewLine ) == lineLen(tLine1) + lineLen(tLine2) )\
  962.        end\
  963.        return tNewLine\
  964.    end\
  965. \
  966.    local function redraw()\
  967.        for n=1,nHeight do\
  968.            redrawLine( n )\
  969.        end\
  970.    end\
  971. \
  972.    local window = {}\
  973. \
  974.    -- Terminal implementation\
  975.    function window.write( sText )\
  976.        local nLen = string.len( sText )\
  977.        local nStart = nCursorX\
  978.        local nEnd = nStart + nLen - 1\
  979.        if nCursorY >= 1 and nCursorY <= nHeight then\
  980.            -- Work out where to put new line\
  981.            --assert( math.floor(nStart) == nStart )\
  982.            --assert( math.floor(nEnd) == nEnd )\
  983.            if nStart <= nWidth and nEnd >= 1 then\
  984.                -- Construct new line\
  985.                local tLine = tLines[ nCursorY ]\
  986.                if nStart == 1 and nEnd == nWidth then\
  987.                    -- Exactly replace line\
  988.                    tLine = {\
  989.                        { sText, nTextColor, nBackgroundColor }\
  990.                    }\
  991.                    --assert( lineLen( tLine ) == nWidth )\
  992.                elseif nStart <= 1 and nEnd >= nWidth then\
  993.                    -- Overwrite line with subset\
  994.                    tLine = {\
  995.                        { string.sub( sText, 1 - nStart + 1, nWidth - nStart + 1 ), nTextColor, nBackgroundColor }\
  996.                    }\
  997.                    --assert( lineLen( tLine ) == nWidth )\
  998.                elseif nStart <= 1 then\
  999.                    -- Overwrite beginning of line\
  1000.                    tLine = lineJoin(\
  1001.                        { { string.sub( sText, 1 - nStart + 1 ), nTextColor, nBackgroundColor } },\
  1002.                        lineSub( tLine, nEnd + 1, nWidth )\
  1003.                    )\
  1004.                    --assert( lineLen( tLine ) == nWidth )\
  1005.                elseif nEnd >= nWidth then\
  1006.                    -- Overwrite end of line\
  1007.                    tLine = lineJoin(\
  1008.                        lineSub( tLine, 1, nStart - 1 ),\
  1009.                        { { string.sub( sText, 1, nWidth - nStart + 1 ), nTextColor, nBackgroundColor } }\
  1010.                    )\
  1011.                    --assert( lineLen( tLine ) == nWidth )\
  1012.                else\
  1013.                    -- Overwrite middle of line\
  1014.                    tLine = lineJoin(\
  1015.                        lineJoin(\
  1016.                            lineSub( tLine, 1, nStart - 1 ),\
  1017.                            { { sText, nTextColor, nBackgroundColor } }\
  1018.                        ),\
  1019.                        lineSub( tLine, nEnd + 1, nWidth )\
  1020.                    )\
  1021.                    --assert( lineLen( tLine ) == nWidth )\
  1022.                end\
  1023. \
  1024.                -- Store and redraw new line\
  1025.                tLines[ nCursorY ] = tLine\
  1026.                if bVisible then\
  1027.                    redrawLine( nCursorY )\
  1028.                end\
  1029.            end\
  1030.        end\
  1031. \
  1032.        -- Move and redraw cursor\
  1033.        nCursorX = nEnd + 1\
  1034.        if bVisible then\
  1035.            updateCursorColor()\
  1036.            updateCursorPos()\
  1037.        end\
  1038.    end\
  1039. \
  1040.    function window.clear()\
  1041.        local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  1042.        for y=1,nHeight do\
  1043.            tLines[y] = tEmpty\
  1044.        end\
  1045.        if bVisible then\
  1046.            redraw()\
  1047.            updateCursorColor()\
  1048.            updateCursorPos()\
  1049.        end\
  1050.    end\
  1051. \
  1052.    function window.clearLine()\
  1053.        if nCursorY >= 1 and nCursorY <= nHeight then\
  1054.            tLines[ nCursorY ] = { { sEmpty, nTextColor, nBackgroundColor } }\
  1055.            if bVisible then\
  1056.                redrawLine( nCursorY )\
  1057.                updateCursorColor()\
  1058.                updateCursorPos()\
  1059.            end\
  1060.        end\
  1061.    end\
  1062. \
  1063.    function window.getCursorPos()\
  1064.        return nCursorX, nCursorY\
  1065.    end\
  1066. \
  1067.    function window.setCursorPos( x, y )\
  1068.        nCursorX = math.floor( x )\
  1069.        nCursorY = math.floor( y )\
  1070.        if bVisible then\
  1071.            updateCursorPos()\
  1072.        end\
  1073.    end\
  1074. \
  1075.    function window.setCursorBlink( blink )\
  1076.        bCursorBlink = blink\
  1077.        if bVisible then\
  1078.            updateCursorBlink()\
  1079.        end\
  1080.    end\
  1081. \
  1082.    function window.isColor()\
  1083.        return parent.isColor()\
  1084.    end\
  1085. \
  1086.    function window.isColour()\
  1087.        return parent.isColor()\
  1088.    end\
  1089. \
  1090.    local function setTextColor( color )\
  1091.        if not parent.isColor() then\
  1092.            if color ~= colors.white and color ~= colors.black then\
  1093.                error( \"Colour not supported\", 3 )\
  1094.            end\
  1095.        end\
  1096.        nTextColor = color\
  1097.        if bVisible then\
  1098.            updateCursorColor()\
  1099.        end\
  1100.    end\
  1101. \
  1102.    function window.setTextColor( color )\
  1103.        setTextColor( color )\
  1104.    end\
  1105. \
  1106.    function window.setTextColour( color )\
  1107.        setTextColor( color )\
  1108.    end\
  1109. \
  1110.    local function setBackgroundColor( color )\
  1111.        if not parent.isColor() then\
  1112.            if color ~= colors.white and color ~= colors.black then\
  1113.                error( \"Colour not supported\", 3 )\
  1114.            end\
  1115.        end\
  1116.        nBackgroundColor = color\
  1117.    end\
  1118. \
  1119.    function window.setBackgroundColor( color )\
  1120.        setBackgroundColor( color )\
  1121.    end\
  1122. \
  1123.    function window.setBackgroundColour( color )\
  1124.        setBackgroundColor( color )\
  1125.    end\
  1126. \
  1127.    function window.getSize()\
  1128.        return nWidth, nHeight\
  1129.    end\
  1130. \
  1131.    function window.scroll( n )\
  1132.        if n ~= 0 then\
  1133.            local tNewLines = {}\
  1134.            local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  1135.            for newY=1,nHeight do\
  1136.                local y = newY + n\
  1137.                if y >= 1 and y <= nHeight then\
  1138.                    tNewLines[newY] = tLines[y]\
  1139.                else\
  1140.                    tNewLines[newY] = tEmpty\
  1141.                end\
  1142.            end\
  1143.            tLines = tNewLines\
  1144.            if bVisible then\
  1145.                redraw()\
  1146.                updateCursorColor()\
  1147.                updateCursorPos()\
  1148.            end\
  1149.        end\
  1150.    end\
  1151. \
  1152.    -- Other functions\
  1153.    function window.setVisible( bVis )\
  1154.        if bVisible ~= bVis then\
  1155.            bVisible = bVis\
  1156.            if bVisible then\
  1157.                window.redraw()\
  1158.            end\
  1159.        end\
  1160.    end\
  1161. \
  1162.    function window.redraw()\
  1163.        if bVisible then\
  1164.            redraw()\
  1165.            updateCursorBlink()\
  1166.            updateCursorColor()\
  1167.            updateCursorPos()\
  1168.        end\
  1169.    end\
  1170. \
  1171.    function window.restoreCursor()\
  1172.        if bVisible then\
  1173.            updateCursorBlink()\
  1174.            updateCursorColor()\
  1175.            updateCursorPos()\
  1176.        end\
  1177.    end\
  1178. \
  1179.    function window.getPosition()\
  1180.        return nX, nY\
  1181.    end\
  1182. \
  1183.    function window.reposition( nNewX, nNewY, nNewWidth, nNewHeight )\
  1184.        nX = nNewX\
  1185.        nY = nNewY\
  1186.        if nNewWidth and nNewHeight then\
  1187.            sEmpty = string.rep( \" \", nNewWidth )\
  1188.            local tNewLines = {}\
  1189.            local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  1190.            for y=1,nNewHeight do\
  1191.                if y > nHeight then\
  1192.                    tNewLines[y] = tEmpty\
  1193.                else\
  1194.                    if nNewWidth == nWidth then\
  1195.                        tNewLines[y] = tLines[y]\
  1196.                    elseif nNewWidth < nWidth then\
  1197.                        tNewLines[y] = lineSub( tLines[y], 1, nNewWidth )\
  1198.                    else\
  1199.                        tNewLines[y] = lineJoin( tLines[y], { { string.sub( sEmpty, nWidth + 1, nNewWidth ), nTextColor, nBackgroundColor } } )\
  1200.                    end\
  1201.                end\
  1202.            end\
  1203.            nWidth = nNewWidth\
  1204.            nHeight = nNewHeight\
  1205.            tLines = tNewLines\
  1206.        end\
  1207.        if bVisible then\
  1208.            window.redraw()\
  1209.        end\
  1210.    end\
  1211. \
  1212.    function window.getBuffer()\
  1213.        return tLines\
  1214.    end\
  1215. \
  1216.    function window.setBuffer(tNewBuffer)\
  1217.        tLines = tNewBuffer\
  1218.    end\
  1219. \
  1220.    if bVisible then\
  1221.        window.redraw()\
  1222.    end\
  1223.    return window\
  1224. end",
  1225.     [ "Interact.lua" ] = "--[[\
  1226.     Interact API in ComputerCraft\
  1227.     by Creator\
  1228.     Complete rewrite in OOP\
  1229. ]]--\
  1230. \
  1231. --Variables\
  1232. local textutilsserialize = textutils.serialize\
  1233. local textutilsunserialize = textutils.unserialize\
  1234. local KeyCodes = {\
  1235.     [ 2 ] =  1 ,\
  1236.     [ 3 ] =  2,\
  1237.     [ 4 ] =  3,\
  1238.     [ 5 ] =  4,\
  1239.     [ 6 ] =  5,\
  1240.     [ 7 ] =  6,\
  1241.     [ 8 ] =  7,\
  1242.     [ 9 ] =  8,\
  1243.     [ 10 ] =  9,\
  1244.     [ 11 ] =  0,\
  1245.     [ 12 ] = \"-\",\
  1246.     [ 13 ] = \"=\",\
  1247.     [ 14 ] = \"Backspace\",\
  1248.     [ 15 ] = \"Tab\",\
  1249.     [ 16 ] = \"q\",\
  1250.     [ 17 ] = \"w\",\
  1251.     [ 18 ] = \"e\",\
  1252.     [ 19 ] = \"r\",\
  1253.     [ 20 ] = \"t\",\
  1254.     [ 21 ] = \"y\",\
  1255.     [ 22 ] = \"u\",\
  1256.     [ 23 ] = \"i\",\
  1257.     [ 24 ] = \"o\",\
  1258.     [ 25 ] = \"p\",\
  1259.     [ 26 ] = \"LeftBracket\",\
  1260.     [ 27 ] = \"RightBracket\",\
  1261.     [ 28 ] = \"Enter\",\
  1262.     [ 29 ] = \"LeftControl\",\
  1263.     [ 30 ] = \"a\",\
  1264.     [ 31 ] = \"s\",\
  1265.     [ 32 ] = \"d\",\
  1266.     [ 33 ] = \"f\",\
  1267.     [ 34 ] = \"g\",\
  1268.     [ 35 ] = \"h\",\
  1269.     [ 36 ] = \"j\",\
  1270.     [ 37 ] = \"k\",\
  1271.     [ 38 ] = \"l\",\
  1272.     [ 39 ] = \";\",\
  1273.     [ 40 ] = \"\\'\",\
  1274.     [ 41 ] = \"`\",\
  1275.     [ 42 ] = \"LeftShift\",\
  1276.     [ 43 ] = \"Backslash\",\
  1277.     [ 44 ] = \"z\",\
  1278.     [ 45 ] = \"x\",\
  1279.     [ 46 ] = \"c\",\
  1280.     [ 47 ] = \"v\",\
  1281.     [ 48 ] = \"b\",\
  1282.     [ 49 ] = \"n\",\
  1283.     [ 50 ] = \"m\",\
  1284.     [ 51 ] = \",\",\
  1285.     [ 52 ] = \".\",\
  1286.     [ 53 ] = \"/\",\
  1287.     [ 54 ] = \"RightShift\",\
  1288.     [ 55 ] = \"*\",\
  1289.     [ 56 ] = \"LeftAlt\",\
  1290.     [ 57 ] = \" \",\
  1291.     [ 58 ] = \"CapsLock\",\
  1292.     [ 59 ] = \"F1\",\
  1293.     [ 60 ] = \"F2\",\
  1294.     [ 61 ] = \"F3\",\
  1295.     [ 62 ] = \"F4\",\
  1296.     [ 63 ] = \"F5\",\
  1297.     [ 64 ] = \"F6\",\
  1298.     [ 65 ] = \"F7\",\
  1299.     [ 66 ] = \"F8\",\
  1300.     [ 67 ] = \"F9\",\
  1301.     [ 68 ] = \"F10\",\
  1302.     [ 69 ] = \"NumberLock\",\
  1303.     [ 70 ] = \"ScrollLock\",\
  1304.     [ 71 ] = \"NumPAd7\",\
  1305.     [ 72 ] = \"NumPAd8\",\
  1306.     [ 73 ] = \"NumPAd9\",\
  1307.     [ 74 ] = \"Substract\",\
  1308.     [ 75 ] = \"NumPAd4\",\
  1309.     [ 76 ] = \"NumPAd5\",\
  1310.     [ 77 ] = \"NumPAd6\",\
  1311.     [ 78 ] = \"Add\",\
  1312.     [ 79 ] = \"NumPAd1\",\
  1313.     [ 80 ] = \"NumPAd2\",\
  1314.     [ 81 ] = \"NumPAd3\",\
  1315.     [ 82 ] = \"NumPAd0\",\
  1316.     [ 83 ] = \"Decimal\",\
  1317.     [ 87 ] = \"F11\",\
  1318.     [ 88 ] = \"F12\",\
  1319.     [ 100] = \"F13\",\
  1320.     [ 101] = \"F14\",\
  1321.     [ 102] = \"F15\",\
  1322.     [ 103] = \"F16\",\
  1323.     [ 104] = \"F17\",\
  1324.     [ 105] = \"F18\",\
  1325.     [ 112] = \"Kana\",\
  1326.     [ 113] = \"F19\",\
  1327.     [ 121] = \"Convert\",\
  1328.     [ 123] = \"Noconvert\",\
  1329.     [ 125] = \"Yen\",\
  1330.     [ 141] = \"NumPadEquals\",\
  1331.     [ 144] = \"^\",\
  1332.     [ 145] = \"@\",\
  1333.     [ 146] = \":\",\
  1334.     [ 147] = \"_\",\
  1335.     [ 148] = \"Kanji\",\
  1336.     [ 149] = \"Stop\",\
  1337.     [ 150] = \"Ax\",\
  1338.     [ 151] = \"Unlabeled\",\
  1339.     [ 156] = \"NumPadEnter\",\
  1340.     [ 157] = \"RightControl\",\
  1341.     [ 157] = \"Section\",\
  1342.     [ 179] = \"NumPadComma\",\
  1343.     [ 181] = \"Dvide\",\
  1344.     [ 183] = \"Sysrq\",\
  1345.     [ 184] = \"RightAlt\",\
  1346.     [ 196] = \"Function\",\
  1347.     [ 197] = \"Pause\",\
  1348.     [ 199] = \"Home\",\
  1349.     [ 200] = \"Up\",\
  1350.     [ 201] = \"PageUp\",\
  1351.     [ 203] = \"Left\",\
  1352.     [ 205] = \"Right\",\
  1353.     [ 207] = \"End\",\
  1354.     [ 208] = \"Down\",\
  1355.     [ 209] = \"PageDown\",\
  1356.     [ 210] = \"Insert\",\
  1357.     [ 211] = \"Delete\",\
  1358. }\
  1359. \
  1360. --Class declarations--\
  1361. local Button = {}\
  1362. local Layout = {}\
  1363. local Toggle = {}\
  1364. local BackgroundColor = {}\
  1365. local ColorField = {}\
  1366. local BetterPaint = {}\
  1367. local Text = {}\
  1368. local TextBox = {}\
  1369. local Key = {}\
  1370. \
  1371. function loadObjects(self)\
  1372.     local output = {}\
  1373.     output.Button = {}\
  1374.     output.Toggle = {}\
  1375.     output.ColorField = {}\
  1376.     output.BetterPaint = {}\
  1377.     output.Text = {}\
  1378.     output.TextBox = {}\
  1379.     output.Key = {}\
  1380.     output.Layout = {}\
  1381.     for o,v in pairs(output) do\
  1382.         if self[o] == nil then\
  1383.             self[o] = {}\
  1384.         end\
  1385.     end\
  1386.     for i,v in pairs(self.Button) do\
  1387.         output.Button[i] = Button.new(self.Button[i])\
  1388.     end\
  1389.     for i,v in pairs(self.Toggle) do\
  1390.         output.Toggle[i] = Toggle.new(self.Toggle[i])\
  1391.     end\
  1392.     for i,v in pairs(self.ColorField) do\
  1393.         output.ColorField[i] = ColorField.new(self.ColorField[i])\
  1394.     end\
  1395.     for i,v in pairs(self.BetterPaint) do\
  1396.         output.BetterPaint[i] = BetterPaint.new(self.BetterPaint[i])\
  1397.     end\
  1398.     for i,v in pairs(self.Text) do\
  1399.         output.Text[i] = Text.new(self.Text[i])\
  1400.     end\
  1401.     for i,v in pairs(self.TextBox) do\
  1402.         output.TextBox[i] = TextBox.new(self.TextBox[i])\
  1403.     end\
  1404.     for i,v in pairs(self.Key) do\
  1405.         output.Key[i] = Key.new(self.Key[i])\
  1406.     end\
  1407.     for i,v in pairs(self.Layout) do\
  1408.         output.Layout[i] = Layout.new(self.Layout[i])\
  1409.     end\
  1410.     output.BackgroundColor = self.BackgroundColor or 1\
  1411.     output.nilClick = self.nilClick or false\
  1412.     return output\
  1413. end\
  1414. \
  1415. function loadLayout(input,output)\
  1416.     for i,v in pairs(input.Button) do\
  1417.         output:addButton(input.Button[i])\
  1418.     end\
  1419.     for i,v in pairs(input.Toggle) do\
  1420.         output:addToggle(input.Toggle[i])\
  1421.     end\
  1422.     for i,v in pairs(input.ColorField) do\
  1423.         output:addColorField(input.ColorField[i])\
  1424.     end\
  1425.     for i,v in pairs(input.BetterPaint) do\
  1426.         output:addBetterPaint(input.BetterPaint[i])\
  1427.     end\
  1428.     for i,v in pairs(input.Text) do\
  1429.         output:addText(input.Text[i])\
  1430.     end\
  1431.     for i,v in pairs(input.TextBox) do\
  1432.         output:addTextBox(input.TextBox[i])\
  1433.     end\
  1434.     for i,v in pairs(input.Key) do\
  1435.         output:addKey(input.Key[i])\
  1436.     end\
  1437.     for i,v in pairs(input.Layout) do\
  1438.         output:addLayout(input.Layout[i])\
  1439.     end\
  1440.     output.BackgroundColor = input.BackgroundColor\
  1441.     output.nilClick = input.nilClick\
  1442. end\
  1443. \
  1444. --Class Layout--\
  1445. --Layout initialization function--\
  1446. Layout.new = function(input)\
  1447.     local self = {}\
  1448.     setmetatable(self,{__index = Layout})\
  1449.     self.Button = {}\
  1450.     self.Toggle = {}\
  1451.     self.ColorField = {}\
  1452.     self.BetterPaint = {}\
  1453.     self.Text = {}\
  1454.     self.TextBox = {}\
  1455.     self.Key = {}\
  1456.     self.Window = {}\
  1457.     self.BackgroundColor = 1\
  1458.     self.xPos = input.xPos or 1\
  1459.     self.yPos = input.yPos or 1\
  1460.     self.xLength = input.xLength or 51\
  1461.     self.yLength = input.yLength or 19\
  1462.     self.nilClick = input.nilClick or false\
  1463.     self.windowBuffer = Screen.new(term.current(),self.xPos,self.yPos,self.xLength,self.yLength)\
  1464.     return self\
  1465. end\
  1466. \
  1467. --Add element function--\
  1468. Layout.addButton = function(self,_elementData)\
  1469.     self.Button[_elementData.name] = _elementData\
  1470. end\
  1471. \
  1472. Layout.addToggle = function(self,_elementData)\
  1473.     self.Toggle[_elementData.name] = _elementData\
  1474. end\
  1475. \
  1476. Layout.addBackgroundColor = function(self,_elementData)\
  1477.     self.BackgroundColor = _elementData.color\
  1478. end\
  1479. \
  1480. Layout.addColorField = function(self,_elementData)\
  1481.     self.ColorField[_elementData.name] = _elementData\
  1482. end\
  1483. \
  1484. Layout.addBetterPaint = function(self,_elementData)\
  1485.     self.BetterPaint[_elementData.name] = _elementData\
  1486. end\
  1487. \
  1488. Layout.addText = function(self,_elementData)\
  1489.     self.Text[_elementData.name] = _elementData\
  1490. end\
  1491. \
  1492. Layout.addTextBox = function(self,_elementData)\
  1493.     self.TextBox[_elementData.name] = _elementData\
  1494. end\
  1495. \
  1496. Layout.addKey = function(self,_elementData)\
  1497.     self.Key[_elementData.name] = _elementData\
  1498. end\
  1499. \
  1500. Layout.addLayout = function(self,_elementData)\
  1501.     loadLayout(self.Layout[_elementData.name],_elementData)\
  1502. end\
  1503. \
  1504. Layout.draw = function(self,xPlus,yPlus)\
  1505.     xPlus = xPlus or 0\
  1506.     yPlus = yPlus or 0\
  1507.     local oldTerm= term.current()\
  1508.     term.redirect(self.windowBuffer)\
  1509.     local buttonFunctions = {}\
  1510.     local toggleFunctions = {}\
  1511.     local colorFieldFunctions = {}\
  1512.     local betterPaintFunctions = {}\
  1513.     local textFunctions = {}\
  1514.     local textBoxFunctions = {}\
  1515.     local layoutFunctions = {}\
  1516.     setmetatable(buttonFunctions,{__index = Button})\
  1517.     setmetatable(toggleFunctions,{__index = Toggle})\
  1518.     setmetatable(colorFieldFunctions,{__index = ColorField})\
  1519.     setmetatable(betterPaintFunctions,{__index = BetterPaint})\
  1520.     setmetatable(textFunctions,{__index = Text})\
  1521.     setmetatable(textBoxFunctions,{__index = TextBox})\
  1522.     setmetatable(layoutFunctions,{__index = Layout})\
  1523.     paintutils.drawFilledBox(1,1,self.xLength,self.yLength,self.BackgroundColor)\
  1524.     for i,v in pairs(self.ColorField) do\
  1525.         colorFieldFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  1526.     end\
  1527.     for i,v in pairs(self.Button) do\
  1528.         buttonFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  1529.     end\
  1530.     for i,v in pairs(self.BetterPaint) do\
  1531.         betterPaintFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  1532.     end\
  1533.     for i,v in pairs(self.Toggle) do\
  1534.         toggleFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  1535.     end\
  1536.     for i,v in pairs(self.Text) do\
  1537.         textFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  1538.     end\
  1539.     for i,v in pairs(self.TextBox) do\
  1540.         textBoxFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  1541.     end\
  1542.     term.redirect(oldTerm)\
  1543. end\
  1544. \
  1545. --Class Button--\
  1546. --Button initialization function\
  1547. Button.new = function(input)\
  1548.     local self = {}\
  1549.     setmetatable(self,{__index = Button})\
  1550.     self.name = input.name\
  1551.     self.label = input.label\
  1552.     self.xPos = input.xPos\
  1553.     self.yPos = input.yPos\
  1554.     self.fgColor = input.fgColor\
  1555.     self.bgColor = input.bgColor\
  1556.     self.xLength = input.xLength\
  1557.     self.yLength = input.yLength\
  1558.     self.returnValue = input.returnValue\
  1559.     self.xTextPos = input.xTextPos\
  1560.     self.yTextPos = input.yTextPos\
  1561.     self.onRightClick = input.onRightClick or nil\
  1562.     self.onLeftClick = input.onLeftClick or nil\
  1563.     return self\
  1564. end\
  1565. \
  1566. --Draw function\
  1567. Button.draw = function(self,addX,addY)\
  1568.     addX = addX or 0\
  1569.     addY = addY or 0\
  1570.     local finalX = self.xPos + addX\
  1571.     local finalY = self.yPos + addY\
  1572. \
  1573.     self.finalX = finalX\
  1574.     self.finalY = finalY\
  1575.     local newText\
  1576.     if #self.label > self.xLength then\
  1577.         newText = string.sub(self.label,1,self.xLength)\
  1578.     else\
  1579.         newText = self.label\
  1580.     end\
  1581.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.bgColor)\
  1582.     term.setTextColor(self.fgColor)\
  1583.     term.setCursorPos(finalX+self.xTextPos-1,finalY+self.yTextPos-1)\
  1584.     term.write(newText)\
  1585. end\
  1586. \
  1587. --Return function--\
  1588. Button.returnData = function(self)\
  1589.     local toReturn = {}\
  1590.     for i,v in pairs(self) do\
  1591.         toReturn[i] = v\
  1592.     end\
  1593.     return toReturn\
  1594. end\
  1595. \
  1596. --Sample Input table--\
  1597. example = [[\
  1598.     example = {\
  1599.         name = \"quickSettings\",\
  1600.         label = \">\",\
  1601.         xPos = 1,\
  1602.         yPos = 3,\
  1603.         xLength = 1,\
  1604.         yLength = 6,\
  1605.         xTextPos = 1,\
  1606.         yTextPos = 1,\
  1607.         fgColor = colors.blue,\
  1608.         bgColor = colors.lightGray,\
  1609.         returnValue = \"quickSettings\",\
  1610.     },\
  1611. ]]\
  1612. \
  1613. --Class Toggle--\
  1614. --Initialize Toggle Object--\
  1615. Toggle.new = function(input)\
  1616.     local self = {}\
  1617.     setmetatable(self,{__index = Toggle})\
  1618.     self.name = input.name or \"randomName\"\
  1619.     self.state = input.state or true\
  1620.     self.xPos = input.xPos or 1\
  1621.     self.yPos = input.yPos or 1\
  1622.     self.trueColor = input.trueColor or colors.green\
  1623.     self.falseColor = input.falseColor or colors.red\
  1624.     self.trueText = input.trueText or \"T\"\
  1625.     self.falseText = input.falseText or \"F\"\
  1626.     self.selectedBg = input.selectedBg or colors.gray\
  1627.     self.notSelectedBg = input.notSelectedBg or colors.lightGray\
  1628.     self.returnValue = input.returnValue or \"mmmmmmm\"\
  1629.     self.moveX = input.moveX or false\
  1630.     self.moveY = input.moveY or false\
  1631.     self.onRightClick = input.onRightClick or nil\
  1632.     self.onLeftClick = input.onLeftClick or nil\
  1633.     return self\
  1634. end\
  1635. \
  1636. function Toggle.draw(self,addX,addY)\
  1637.     addX = addX or 0\
  1638.     addY = addY or 0\
  1639.     local finalX = self.xPos + addX\
  1640.     local finalY = self.yPos + addY\
  1641.     self.finalX = finalX\
  1642.     self.finalY = finalY\
  1643.     term.setCursorPos(finalX,finalY)\
  1644.     if self.state == false then\
  1645.         term.setBackgroundColor(self.notSelectedBg)\
  1646.         term.setTextColor(self.trueColor)\
  1647.         term.write(string.sub(self.trueText,1,1))\
  1648.         term.setBackgroundColor(self.selectedBg)\
  1649.         term.setTextColor(self.falseColor)\
  1650.         term.write(\" \"..string.sub(self.falseText,1,1)..\" \")\
  1651.     elseif self.state == true then\
  1652.         term.setBackgroundColor(self.selectedBg)\
  1653.         term.setTextColor(self.trueColor)\
  1654.         term.write(\" \"..string.sub(self.trueText,1,1)..\" \")\
  1655.         term.setBackgroundColor(self.notSelectedBg)\
  1656.         term.setTextColor(self.falseColor)\
  1657.         term.write(string.sub(self.falseText,1,1))\
  1658.     end\
  1659. end\
  1660. \
  1661. function Toggle.returnData(self)\
  1662.     local toReturn = {}\
  1663.     for i,v in pairs(self) do\
  1664.         toReturn[i] = v\
  1665.     end\
  1666.     return toReturn\
  1667. end\
  1668. \
  1669. function Toggle.toggle(self)\
  1670.     if self.state == true then\
  1671.         self.state = false\
  1672.     else\
  1673.         self.state = true\
  1674.     end\
  1675. end\
  1676. \
  1677. function Toggle.getState(self)\
  1678.     return self.state\
  1679. end\
  1680. \
  1681. --BackgroundColor Class--\
  1682. function BackgroundColor.new(input)\
  1683.     local self = {}\
  1684.     setmetatable(self,{__index = BackgroundColor})\
  1685.     self.color = input.color\
  1686.     return self\
  1687. end\
  1688. \
  1689. function BackgroundColor.setColor(self,color)\
  1690.     self.color = color\
  1691. end\
  1692. \
  1693. function BackgroundColor.returnData(self)\
  1694.     local toReturn = {}\
  1695.     for i,v in pairs(self) do\
  1696.         toReturn[i] = v\
  1697.     end\
  1698.     return toReturn\
  1699. end\
  1700. \
  1701. --ColorField Class--\
  1702. function ColorField.new(input)\
  1703.     local self = {}\
  1704.     setmetatable(self,{__index = ColorField})\
  1705.     self.name = input.name\
  1706.     self.xPos = input.xPos\
  1707.     self.yPos = input.yPos\
  1708.     self.xLength = input.xLength\
  1709.     self.yLength = input.yLength\
  1710.     self.color = input.color\
  1711.     self.moveX = input.moveX or false\
  1712.     self.moveY = input.moveY or false\
  1713.     return self\
  1714. end\
  1715. \
  1716. function  ColorField.draw(self,addX,addY)\
  1717.     addX = addX or 0\
  1718.     addY = addY or 0\
  1719.     local finalX = self.xPos + addX\
  1720.     local finalY = self.yPos + addY\
  1721.     self.finalX = finalX\
  1722.     self.finalY = finalY\
  1723.     term.setTextColor(colors.black)\
  1724.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.color)\
  1725. end\
  1726. \
  1727. function ColorField.returnData(self)\
  1728.     local toReturn = {}\
  1729.     for i,v in pairs(self) do\
  1730.         toReturn[i] = v\
  1731.     end\
  1732.     return toReturn\
  1733. end\
  1734. \
  1735. --BetterPaint Class--\
  1736. function BetterPaint.new(input)\
  1737.     local self = {}\
  1738.     setmetatable(self,{__index = BetterPaint})\
  1739.     self.xPos = input.xPos\
  1740.     self.yPos = input.yPos\
  1741.     self.name = input.name\
  1742.     self.path = input.path\
  1743.     self.xLength = input.xLength\
  1744.     self.yLength = input.yLength\
  1745.     self.returnValue = input.returnValue\
  1746.     self.label = input.label\
  1747.     self.labelBg = input.labelBg\
  1748.     self.labelFg = input.labelFg\
  1749.     self.moveX = input.moveX or false\
  1750.     self.moveY = input.moveY or false\
  1751.     self.onRightClick = input.onRightClick or nil\
  1752.     self.onLeftClick = input.onLeftClick or nil\
  1753.     return self\
  1754. end\
  1755. \
  1756. function BetterPaint.returnData(self)\
  1757.     local toReturn = {}\
  1758.     for i,v in pairs(self) do\
  1759.         toReturn[i] = v\
  1760.     end\
  1761.     return toReturn\
  1762. end\
  1763. \
  1764. function BetterPaint.draw(self,addX,addY)\
  1765.     addX = addX or 0\
  1766.     addY = addY or 0\
  1767.     local finalX = self.xPos + addX\
  1768.     local finalY = self.yPos + addY\
  1769.     self.finalX = finalX\
  1770.     self.finalY = finalY\
  1771.     paint.drawImage(self.path,finalX,finalY)\
  1772.     term.setCursorPos(finalX,finalY+self.yLength)\
  1773.     term.setTextColor(self.labelFg)\
  1774.     term.setBackgroundColor(self.labelBg)\
  1775.     term.write(self.label)\
  1776. end\
  1777. \
  1778. --Text Class--\
  1779. function Text.new(input)\
  1780.     local self = {}\
  1781.     setmetatable(self,{__index = Text})\
  1782.     self.name = input.name\
  1783.     self.text = input.text\
  1784.     self.xPos = input.xPos\
  1785.     self.yPos = input.yPos\
  1786.     self.bgColor = input.bgColor\
  1787.     self.fgColor = input.fgColor\
  1788.     return self\
  1789. end\
  1790. \
  1791. function Text.draw(self,addX,addY)\
  1792.     addX = addX or 0\
  1793.     addY = addY or 0\
  1794.     local finalX = self.xPos + addX\
  1795.     local finalY = self.yPos + addY\
  1796.     self.finalX = finalX\
  1797.     self.finalY = finalY\
  1798.     term.setCursorPos(finalX,finalY)\
  1799.     term.setTextColor(self.fgColor)\
  1800.     term.setBackgroundColor(self.bgColor)\
  1801.     term.write(self.text)\
  1802. end\
  1803. \
  1804. function Text.returnData(self)\
  1805.     local toReturn = {}\
  1806.     for i,v in pairs(self) do\
  1807.         toReturn[i] = v\
  1808.     end\
  1809.     return toReturn\
  1810. end\
  1811. \
  1812. --TextBox Class \
  1813. \
  1814. function TextBox.new(input)\
  1815.     local self = {}\
  1816.     setmetatable(self,{__index = TextBox})\
  1817.     self.name = input.name\
  1818.     self.helpText = input.helpText\
  1819.     self.xPos = input.xPos\
  1820.     self.yPos = input.yPos\
  1821.     self.xLength = input.xLength\
  1822.     self.yLength = input.yLength\
  1823.     self.bgColor = input.bgColor\
  1824.     self.fgColor = input.fgColor\
  1825.     self.helpFgColor = input.helpFgColor\
  1826.     self.charLimit = input.charLimit\
  1827.     self.moveX = input.moveX or false\
  1828.     self.moveY = input.moveY or false\
  1829.     self.text = \"\"\
  1830.     self.returnValue = input.returnValue\
  1831.     self.confidential = input.confidential or false\
  1832.     return self\
  1833. end\
  1834. \
  1835. function TextBox.returnData(self)\
  1836.     local toReturn = {}\
  1837.     for i,v in pairs(self) do\
  1838.         toReturn[i] = v\
  1839.     end\
  1840.     return toReturn\
  1841. end\
  1842. \
  1843. function TextBox.draw(self,addX,addY)\
  1844.     addX = addX or 0\
  1845.     addY = addY or 0\
  1846.     local finalX = self.xPos + addX\
  1847.     local finalY = self.yPos + addY\
  1848.     self.finalX = finalX\
  1849.     self.finalY = finalY\
  1850.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.bgColor)\
  1851.     term.setBackgroundColor(self.bgColor)\
  1852.     term.setCursorPos(self.finalX,self.finalY)\
  1853.     if self.text == \"\" or self.confidential then\
  1854.         term.setTextColor(self.helpFgColor)\
  1855.         term.write(self.helpText)\
  1856.     else\
  1857.         term.setTextColor(self.fgColor)\
  1858.         term.write(self.text)\
  1859.     end\
  1860. end\
  1861. \
  1862. function TextBox.read(self,_sReplaceChar, _tHistory)\
  1863.     paintutils.drawFilledBox(self.finalX,self.finalY,self.finalX+self.xLength-1,self.finalY+self.yLength-1,self.bgColor)\
  1864.     term.setTextColor(self.fgColor)\
  1865.     term.setCursorPos(self.finalX,self.finalY)\
  1866.     return read()\
  1867. end\
  1868. \
  1869. --Key Class\
  1870. function Key.new(input)\
  1871.     local self = {}\
  1872.     setmetatable(self,{__index = TextBox})\
  1873.     self.name = input.name\
  1874.     self.key = input.key\
  1875.     self.onPress = input.onPress or nil\
  1876.     return self\
  1877. end\
  1878. \
  1879. function Key.returnData(self)\
  1880.     local toReturn = {}\
  1881.     for i,v in pairs(self) do\
  1882.         toReturn[i] = v\
  1883.     end\
  1884.     return toReturn\
  1885. end\
  1886. \
  1887. local function localEventHandler(self,event, p1, p2, p3, p4, p5, p6)\
  1888.     local toAddX = self.xPos - 1\
  1889.     local toAddY = self.yPos - 1\
  1890.     while true do\
  1891.         if event == \"mouse_click\" then\
  1892.             for i,v in pairs(self.Button) do\
  1893.                 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\
  1894.                     if p1 == 1 then\
  1895.                         if v.onLeftClick then \
  1896.                             v.onLeftClick()\
  1897.                         end\
  1898.                     elseif p1 == 2 then\
  1899.                         if v.onRightClick then\
  1900.                             v.onRightClick()\
  1901.                         end\
  1902.                     end\
  1903.                     return {\"Button\",tostring(v.returnValue),p1,p2,p3}\
  1904.                 end\
  1905.             end\
  1906.             for i,v in pairs(self.Toggle) do\
  1907.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + 3 + toAddX and v.finalY + toAddY == p3 then\
  1908.                     return {\"Toggle\",tostring(v.returnValue),p1,p2,p3}\
  1909.                 end\
  1910.             end\
  1911.             for i,v in pairs(self.BetterPaint) do \
  1912.                 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\
  1913.                     return {\"Button\",tostring(v.returnValue),p1,p2,p3}\
  1914.                 end\
  1915.             end\
  1916.             for i,v in pairs(self.TextBox) do \
  1917.                 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\
  1918.                     return {\"TextBox\",tostring(v.returnValue),p1,p2,p3}\
  1919.                 end\
  1920.             end\
  1921.             if self.nilClick then\
  1922.                 if not (self.xPos <= p2 and p2 <= self.xPos+self.xLength-1 and self.yPos <= p3 and p3 <= self.yPos+self.yLength-1) then\
  1923.                     return {\"Nil\",\"Nil\",p1,p2,p3}\
  1924.                 end\
  1925.             end\
  1926.         elseif event == \"key\" then\
  1927.             local pressedKey = p1\
  1928.             for i,v in pairs(self.Key) do\
  1929.                 if v.key == KeyCodes[pressedKey] then\
  1930.                     if v.onPress then\
  1931.                         v.onPress()\
  1932.                     else\
  1933.                         return {\"Key\",KeyCodes[pressedKey],pressedKey}\
  1934.                     end\
  1935.                 end\
  1936. \
  1937.             end\
  1938.         elseif event == \"monitor_touch\" then\
  1939.             os.queueEvent(\"mouse_click\", p1, p2, p3, p4, p5, p6)\
  1940.         end\
  1941.     end\
  1942. end\
  1943. \
  1944. --Event handler function--\
  1945. eventHandler = function(self)\
  1946.     local tEvent = {os.pullEvent()}\
  1947.     return localEventHandler(self,unpack(tEvent))\
  1948. end\
  1949. \
  1950. --Load Function--\
  1951. function Initialize()\
  1952.     local toReturn = {}\
  1953.     toReturn.Button = Button\
  1954.     toReturn.Layout = Layout\
  1955.     toReturn.Toggle = Toggle\
  1956.     toReturn.BackgroundColor = BackgroundColor\
  1957.     toReturn.ColorField = ColorField\
  1958.     toReturn.BetterPaint = BetterPaint\
  1959.     toReturn.Text = Text\
  1960.     toReturn.TextBox = TextBox\
  1961.     toReturn.Key = Key\
  1962.     toReturn.eventHandler = eventHandler\
  1963.     toReturn.loadObjects = loadObjects\
  1964.     toReturn.loadLayout = loadLayout\
  1965.     return toReturn\
  1966. end",
  1967.     [ "paint.lua" ] = "transparentIcon = \"-\"\
  1968. args = {...}\
  1969. tX, tY = term.getSize()\
  1970. \
  1971. function import(source,dest)\
  1972. init()\
  1973. if fs.exists(source) == false then\
  1974.  print(\"File \"..source..\" doesnt exists!\")\
  1975.  error()\
  1976. elseif not dest then\
  1977.  print(\"Provide an output file.\")\
  1978.  error()\
  1979. elseif fs.exists(dest) == true then\
  1980.  print(\"File \"..dest..\" already exists!\")\
  1981.  error()\
  1982. end\
  1983. --if mode == \"import\" then\
  1984.  h = fs.open(source,\"r\")\
  1985.  lines = {}\
  1986.  count = 0\
  1987.  repeat\
  1988.   count = count + 1\
  1989.   lines[count] = h.readLine(count)  \
  1990.  until lines[count] == nil\
  1991.  h.close()\
  1992.  data = {}\
  1993.  if not painted then\
  1994.   painted = {}\
  1995.  end\
  1996.  for i=1,#lines do\
  1997.   data[i] = {}\
  1998.   string.gsub(lines[i],\".\",function(char) table.insert(data[i],char) end)\
  1999.  end\
  2000.  x=0\
  2001.  y=0\
  2002.  for i=1,#data do\
  2003.   y = y + 1\
  2004.   x = 0\
  2005.   for a=1,#data[i] do\
  2006.    x = x + 1\
  2007.    if not painted[x] then\
  2008.     painted[x] = {}\
  2009.    end\
  2010.    if not painted[x][y] then\
  2011.     painted[x][y] = {}\
  2012.    end\
  2013.    rawColor = data[i][x]\
  2014.    if rawColor == \"0\" then\
  2015.     colorLoaded = colors.white\
  2016.    elseif rawColor == \"1\" then\
  2017.     colorLoaded = colors.orange\
  2018.    elseif rawColor == \"2\" then\
  2019.     colorLoaded = colors.magenta\
  2020.    elseif rawColor == \"3\" then\
  2021.     colorLoaded = colors.lightBlue\
  2022.    elseif rawColor == \"4\" then\
  2023.     colorLoaded = colors.yellow\
  2024.    elseif rawColor == \"5\" then\
  2025.     colorLoaded = colors.lime\
  2026.    elseif rawColor == \"6\" then\
  2027.     colorLoaded = colors.pink\
  2028.    elseif rawColor == \"7\" then\
  2029.     colorLoaded = colors.gray\
  2030.    elseif rawColor == \"8\" then\
  2031.     colorLoaded = colors.lightGray\
  2032.    elseif rawColor == \"9\" then\
  2033.     colorLoaded = colors.cyan\
  2034.    elseif rawColor == \"a\" then\
  2035.     colorLoaded = colors.purple\
  2036.    elseif rawColor == \"b\" then\
  2037.     colorLoaded = colors.blue\
  2038.    elseif rawColor == \"c\" then\
  2039.     colorLaoded = colors.brown\
  2040.    elseif rawColor == \"d\" then\
  2041.     colorLoaded = colors.green\
  2042.    elseif rawColor == \"e\" then\
  2043.     colorLoaded = colors.red\
  2044.    elseif rawColor == \"f\" then\
  2045.     colorLoaded = colors.black\
  2046.    elseif rawColor == \" \" then\
  2047.     -- Do nothing, allow it\
  2048.    else\
  2049.     error(\"File: \\\"\"..source..\"\\\" has an incorrect format!\")\
  2050.    end\
  2051.    if rawColor ~= \" \" then\
  2052.     painted[x][y] = {colorLoaded,\" \",colorLoaded}   \
  2053.    else\
  2054.     painted[x][y] = nil\
  2055.    end\
  2056.   end\
  2057.  end\
  2058. --end\
  2059. args[1] = dest\
  2060. save()\
  2061. end\
  2062. \
  2063. \
  2064. function drawImage(file,xSet,ySet,redirection)\
  2065. init()\
  2066. lastImage = file\
  2067. lastX = xSet\
  2068. lastY = ySet\
  2069. lastRedirection = redirection\
  2070. if redirection then\
  2071.  current = term.current()\
  2072.  term.redirect(redirection)\
  2073. end\
  2074. drawData(xSet,ySet,file)\
  2075. if redirection then\
  2076.  term.redirect(current)\
  2077. end\
  2078. end\
  2079. \
  2080. function overWrite(textSet,xSet,ySet,colorSet)\
  2081. init()\
  2082. exists = true\
  2083. if not lastImage then\
  2084.  error(\"Use drawImage first!\")\
  2085. end\
  2086. if not writeBuffer then\
  2087.  writeBuffer = {}\
  2088. end\
  2089. if not writeBuffer[lastImage] then\
  2090.  writeBuffer[lastImage] = {}\
  2091. end\
  2092. plusPos = 0\
  2093. for char in string.gmatch(textSet,\".\") do\
  2094.  if not writeBuffer[lastImage][xSet+plusPos] then\
  2095.   writeBuffer[lastImage][xSet+plusPos] = {}\
  2096.  end\
  2097.  if not writeBuffer[lastImage][xSet+plusPos][ySet] then\
  2098.   writeBuffer[lastImage][xSet+plusPos][ySet] = {colors.black,\" \",colors.white}\
  2099.  end\
  2100.  writeBuffer[lastImage][xSet+plusPos][ySet][2] = char\
  2101.  writeBuffer[lastImage][xSet+plusPos][ySet][3] = colorSet\
  2102.  plusPos = plusPos + 1 \
  2103. end\
  2104. drawImage(lastImage,lastX,lastY,lastRedirection)\
  2105. end\
  2106. \
  2107. function init()\
  2108. function eventHandler()\
  2109. while true do\
  2110.  event = {os.pullEvent()}\
  2111.  if event[1] == \"key\" then\
  2112.   if event[2] == keys.leftCtrl or event[2] == 157 then\
  2113.    menuStatus = not menuStatus\
  2114.    writeMenuBar(menuStatus)\
  2115.   end\
  2116.   if menuStatus == true then\
  2117.    if event[2] == keys.right or event[2] == keys.left then\
  2118.     if menuItemSelected == 1 then\
  2119.      menuItemSelected = 2\
  2120.     else\
  2121.      menuItemSelected = 1\
  2122.     end\
  2123.     writeMenuBar(menuStatus)\
  2124.    elseif event[2] == keys.enter then\
  2125.     if menuItemSelected == 1 then\
  2126.      save()\
  2127.      writeMenuBar(false)\
  2128.     else\
  2129.      term.setTextColor(colors.yellow)\
  2130.      term.setBackgroundColor(colors.black)\
  2131.      term.clear()\
  2132.      term.setCursorPos(1,1)\
  2133.      error()\
  2134.     end\
  2135.    end\
  2136.   else   \
  2137.    if event[2] == keys.right then\
  2138.     drawData(offSetX-1,offSetY)\
  2139.     drawMenu()\
  2140.     writeMenuBar(menuStatus)\
  2141.    elseif event[2] == keys.left then\
  2142.     drawData(offSetX+1,offSetY)\
  2143.     drawMenu()\
  2144.     writeMenuBar(menuStatus)\
  2145.    elseif event[2] == keys.up then\
  2146.     drawData(offSetX,offSetY+1)\
  2147.     drawMenu()\
  2148.     writeMenuBar(menuStatus)\
  2149.    elseif event[2] == keys.down then\
  2150.     drawData(offSetX,offSetY-1)\
  2151.     drawMenu()\
  2152.     writeMenuBar(menuStatus)\
  2153.    end\
  2154.   end\
  2155.  end\
  2156.  if event[1] == \"mouse_click\" or event[1] == \"mouse_drag\" then\
  2157.   if event[3] > 2 and event[4] ~= tY then\
  2158.    insertItem(event[3],event[4],event[2])\
  2159.   elseif event[4] < 18 and event[4] > 1 then\
  2160.    if event[3] == 1 then\
  2161.     bgSelected = 2^(event[4]-2)\
  2162.    elseif event[3] == 2 then\
  2163.     tSelected = 2^(event[4]-2)\
  2164.    end\
  2165.    drawMenu()\
  2166.   elseif event[4] == tY - 1 and event[3] == 1 then\
  2167.    setLetter()\
  2168.    drawData(offSetX,offSetY)\
  2169.    drawMenu()\
  2170.   elseif event[3] == tX and event[4] == tY and menuStatus == false then\
  2171.    writeHelp()\
  2172.   end\
  2173.  end\
  2174.  if event[1] == \"char\" then\
  2175.   textSelected = string.sub(event[2],1,1)\
  2176.   drawMenu()\
  2177.  end\
  2178.  --drawData(offSetX,offSetY)\
  2179. end\
  2180. end\
  2181. \
  2182. function writeHelp()\
  2183. term.setBackgroundColor(colors.black)\
  2184. term.setTextColor(colors.green)\
  2185. term.clear()\
  2186. term.setCursorPos(1,1)\
  2187. term.write(\"Help:\")\
  2188. term.setTextColor(colors.white)\
  2189. term.setCursorPos(1,3)\
  2190. print(\"Usage:\")\
  2191. term.setTextColor(colors.lightGray)\
  2192. print(\"  Select color: Click on the color on the left\")\
  2193. print(\"  Change draw char: Press a key on the keyboard\")\
  2194. print(\"  Change transparent icon: Click on the icon's char in the menu\")\
  2195. print(\"  Change text color: Click on a color in the menu on the right side\")\
  2196. print(\"  Change background color: Click on a color in the menu on the left side\")\
  2197. term.setTextColor(colors.white)\
  2198. print()\
  2199. print(\"Controls:\")\
  2200. term.setTextColor(colors.lightGray)\
  2201. print(\"  Arrow keys to pan\")\
  2202. print(\"  Left mouse button to select and draw\")\
  2203. print(\"  Right mouse button to delete\")\
  2204. print(\"  Ctrl to open menu\")\
  2205. print()\
  2206. term.setTextColor(colors.white)\
  2207. term.write(\"Click a mouse button to exit.\")\
  2208. term.setTextColor(colors.orange)\
  2209. term.setCursorPos(tX-9,1)\
  2210. term.write(\"API help >\")\
  2211. event = {os.pullEvent(\"mouse_click\")}\
  2212. if event[3] > tX-10 and event[4] == 1 then\
  2213.  drawAPIhelp()\
  2214. end\
  2215. drawData(offSetX,offSetY)\
  2216. drawMenu()\
  2217. writeMenuBar(menuStatus)\
  2218. end\
  2219. \
  2220. function drawAPIhelp()\
  2221. term.clear()\
  2222. term.setCursorPos(1,1)\
  2223. term.setTextColor(colors.orange)\
  2224. print(\"API help menu:\")\
  2225. term.setTextColor(colors.white)\
  2226. print(\"Drawing an image: \")\
  2227. term.setTextColor(colors.lightGray)\
  2228. print(shell.getRunningProgram(),\".drawImage(<file name>,<x pos>,<y pos>,[redirection object])\")\
  2229. print()\
  2230. term.setTextColor(colors.white)\
  2231. print(\"Overlaying text on the last image:\")\
  2232. term.setTextColor(colors.lightGray)\
  2233. print(shell.getRunningProgram(),\".overWrite(<Text>,<x pos>,<y pos>,<text color>)\")\
  2234. print()\
  2235. term.setTextColor(colors.white)\
  2236. print(\"Convert a paintutils file to betterpaint file:\")\
  2237. term.setTextColor(colors.lightGray)\
  2238. print(shell.getRunningProgram(),\".import(<source>,<destination>)\")\
  2239. term.setTextColor(colors.red)\
  2240. print()\
  2241. print(\"Overwriting text will only work AFTER drawing an image!\")\
  2242. term.setTextColor(colors.white)\
  2243. print()\
  2244. print(\"Example:\")\
  2245. term.setTextColor(colors.lightGray)\
  2246. print(\"os.loadAPI(\\\"\",shell.getRunningProgram(),\"\\\")\")\
  2247. print(shell.getRunningProgram(),\".drawImage(\\\"myPicture\\\",1,1)\")\
  2248. term.write((shell.getRunningProgram()..\".overWrite(\\\"Hello!\\\",2,3,colors.orange)\"))\
  2249. os.pullEvent(\"mouse_click\")\
  2250. end\
  2251. \
  2252. function setLetter()\
  2253. term.setBackgroundColor(colors.red)\
  2254. term.setTextColor(colors.black)\
  2255. for i=1,4 do\
  2256.  term.setCursorPos(tX/2-11,(tY/2-4)+i)\
  2257.  term.write(\"                     \")\
  2258. end\
  2259. term.setCursorPos(tX/2-10,tY/2-2)\
  2260. term.write(\"Change transparancy\")\
  2261. term.setCursorPos(tX/2-10,tY/2-1)\
  2262. term.write(\"character to: (key)\")\
  2263. event = {os.pullEvent(\"char\")}\
  2264. transparentIcon = event[2]\
  2265. end\
  2266. \
  2267. function insertItem(xPos,yPos,modeSet)\
  2268. if saved == true then\
  2269.  saved = false\
  2270.  writeMenuBar(false)\
  2271. end\
  2272. --bgSelected\
  2273. --tSelected\
  2274. --textSelected\
  2275. if not painted then\
  2276.  painted = {}\
  2277. end\
  2278. if not painted[xPos-offSetX] then\
  2279.  painted[xPos-offSetX] = {}\
  2280. end\
  2281. if modeSet == 1 then\
  2282.   if not textSelected then\
  2283.    textSelected = \" \"\
  2284.   end\
  2285.   TMPtextSelected = textSelected\
  2286.   painted[xPos-offSetX][yPos-offSetY] = {bgSelected,textSelected,tSelected}\
  2287.   term.setBackgroundColor(bgSelected)\
  2288.   term.setTextColor(tSelected)\
  2289.  else\
  2290.   TMPtextSelected = transparentIcon\
  2291.   term.setBackgroundColor(colors.black)\
  2292.   term.setTextColor(colors.gray)\
  2293.   painted[xPos-offSetX][yPos-offSetY] = nil\
  2294. end\
  2295. term.setCursorPos(xPos,yPos)\
  2296. term.write(TMPtextSelected)\
  2297. end\
  2298. \
  2299. --if #args ~= 1 then\
  2300. -- print(\"Usage: \"..shell.getRunningProgram()..\" <path>\")\
  2301. -- return\
  2302. --end\
  2303. \
  2304. if args[1] and fs.exists(args[1]) == true then\
  2305. buff = fs.open(args[1],\"r\")\
  2306. previousData = buff.readAll()\
  2307. buff.close()\
  2308. processed = string.sub(previousData,43)\
  2309. painted = textutils.unserialize(processed)\
  2310. else\
  2311. painted = {}\
  2312. end\
  2313. \
  2314. function save()\
  2315. file = fs.open(args[1],\"w\")\
  2316. file.write(\"error('This is an image, not a program!')\\n\"..textutils.serialize(painted))\
  2317. file.close()\
  2318. saved = true\
  2319. end\
  2320. \
  2321. function drawData(xStart, yStart, file)\
  2322. offSetX = xStart\
  2323. offSetY = yStart\
  2324. if not file then\
  2325.  term.setBackgroundColor(colors.black)\
  2326.  term.setTextColor(colors.gray)\
  2327.  transparentLine = \"\"\
  2328.  for x=1,tX-2 do\
  2329.   transparentLine = transparentIcon..transparentLine\
  2330.  end\
  2331.  for y=1,tY-1 do\
  2332.   term.setCursorPos(3,y)\
  2333.   term.write(transparentLine)\
  2334.  end\
  2335. else\
  2336.  if fs.exists(file) == false then\
  2337.   error(\"File given doesnt exists! file name: \"..file)\
  2338.  else\
  2339.   local fileD = fs.open(file,\"r\")\
  2340.   raw = fileD.readAll()\
  2341.   --ignoreL = string.len(fileD.readLine(1))\
  2342.   processed = string.sub(raw,43)\
  2343.   --term.redirect(term.native())\
  2344.  -- textutils.pagedPrint(processed)\
  2345.   painted = textutils.unserialize(processed)\
  2346.   fileD.close()\
  2347.  end\
  2348. end\
  2349. if not painted then\
  2350.  painted = {}\
  2351. end\
  2352. paintedF = painted\
  2353. count = 0\
  2354. repeat ---------\
  2355. count = count + 1\
  2356. for xPos,v in pairs(paintedF) do\
  2357.  for yPos in pairs (paintedF[xPos]) do\
  2358.    overWrite = true\
  2359.    if not lastImage or not writeBuffer or not writeBuffer[lastImage] then\
  2360.     overWrite = false\
  2361.    end\
  2362.    if overWrite == true then\
  2363.     if not writeBuffer[lastImage][xPos] then\
  2364.      overWrite = false\
  2365.     end\
  2366.    end\
  2367.    if overWrite == true then\
  2368.     if not writeBuffer[lastImage][xPos][yPos] then\
  2369.      overWrite = false\
  2370.     end\
  2371.    end\
  2372.    if overWrite == false then\
  2373.     bgColor = paintedF[xPos][yPos][1]\
  2374.     text = paintedF[xPos][yPos][2]\
  2375.     tColor = paintedF[xPos][yPos][3]\
  2376.    else\
  2377.     if painted and painted[xPos] and painted[xPos][yPos] and painted[xPos][yPos][1] then\
  2378.      bgColor = painted[xPos][yPos][1]\
  2379.      else\
  2380.      bgColor = colors.black\
  2381.     end\
  2382.     --if not bgColor then\
  2383.    --  bgColor = colors.black\
  2384.     --end\
  2385.     text = writeBuffer[lastImage][xPos][yPos][2]\
  2386.     tColor = writeBuffer[lastImage][xPos][yPos][3]\
  2387.    end\
  2388.    if not tColor then\
  2389.     tColor = colors.white\
  2390.    end\
  2391.    if not text then\
  2392.     text = \" \"\
  2393.    end\
  2394.    term.setCursorPos(xPos+xStart,yPos+yStart)\
  2395.    term.setBackgroundColor(bgColor)\
  2396.    term.setTextColor(tColor)\
  2397.    term.write(text)\
  2398.   end\
  2399.  end\
  2400.  if count == 1 and writeBuffer and lastImage then\
  2401.   paintedF = writeBuffer[lastImage]\
  2402.  elseif count == 1 and not lastImage or not writeBuffer then\
  2403.   count = 2\
  2404.  end\
  2405. until count == 2\
  2406. term.setCursorPos(1,tY)\
  2407. end\
  2408. \
  2409. function drawMenu()\
  2410. term.setCursorPos(1,1)\
  2411. term.setTextColor(colors.white)\
  2412. if not bgSelected then\
  2413.  bgSelected = colors.black\
  2414. elseif bgSelected == colors.white then\
  2415.  term.setTextColor(colors.black)\
  2416. end\
  2417. if not tSelected then\
  2418.  tSelected = colors.white\
  2419. elseif tSelected == colors.white then\
  2420.  term.setTextColor(colors.black)\
  2421. end\
  2422. if not textSelected then\
  2423.  textSelected = \" \"\
  2424. end\
  2425. term.setBackgroundColor(bgSelected)\
  2426. term.write(\"B\")\
  2427. term.setBackgroundColor(tSelected)\
  2428. term.write(\"T\")\
  2429. for i=1,16 do\
  2430.  i=i-1\
  2431.  term.setCursorPos(1,i+2)\
  2432.  term.setBackgroundColor(2^i)\
  2433.  term.write(\"  \")\
  2434. end\
  2435. term.setCursorPos(1,18)\
  2436. term.setBackgroundColor(colors.black)\
  2437. if not textSelected then\
  2438.  textSelected = \" \"\
  2439. elseif string.len(textSelected) > 1 then\
  2440.  textSelected = string.sub(textSelected,1,1)\
  2441. end\
  2442. term.setTextColor(colors.gray)\
  2443. term.setBackgroundColor(colors.black)\
  2444. term.write(transparentIcon)\
  2445. term.setTextColor(tSelected)\
  2446. term.setBackgroundColor(bgSelected)\
  2447. term.write(textSelected)\
  2448. end\
  2449. \
  2450. function writeMenuBar(booly)\
  2451. menuStatus = booly\
  2452. term.setBackgroundColor(colors.black)\
  2453. if booly == true then\
  2454.  term.setCursorPos(1,tY)\
  2455.  term.clearLine()\
  2456.  if not menuItemSelected then\
  2457.   menuItemSelected = 1\
  2458.  end\
  2459.  term.setTextColor(colors.white)\
  2460.  term.write(\" Save  Exit \")\
  2461.  term.setCursorPos(6*menuItemSelected-5,tY)\
  2462.  term.setTextColor(colors.yellow)\
  2463.  term.write(\"[\")\
  2464.  term.setCursorPos(6*menuItemSelected,tY)\
  2465.  term.write(\"]\")\
  2466. elseif booly == false then\
  2467.  term.setCursorPos(1,tY)\
  2468.  term.setTextColor(colors.yellow)\
  2469.  term.clearLine()\
  2470.  if saved == true then\
  2471.   term.write(\"Saved to \"..args[1])\
  2472.  else\
  2473.   term.write(\"Press Ctrl to access menu\")\
  2474.  end\
  2475.  term.setCursorPos(tX,tY)\
  2476.  term.setTextColor(colors.lightGray)\
  2477.  term.write(\"?\")\
  2478. end\
  2479. end\
  2480. end\
  2481. \
  2482. if args[1] == \"import\" then -- or args[1] == \"export\" then\
  2483. init()\
  2484. mode = args[1]\
  2485. source = args[2]\
  2486. destination = args[3]\
  2487. if not args[2] then\
  2488.  print(\"Usage: \"..shell.getRunningProgram()..\" \"..mode..\" <source> <destination>\")\
  2489.  error()\
  2490. end\
  2491. import(source,destination)\
  2492. if mode == \"import\" then\
  2493.  print(\"File imported.\")\
  2494.  error()\
  2495. end\
  2496. elseif #args > 0 then\
  2497. init()\
  2498. menuStatus = false\
  2499. saved = false\
  2500. writeMenuBar(menuStatus)\
  2501. menuItemSelected = 1\
  2502. drawData(3,0)\
  2503. drawMenu()\
  2504. eventHandler()\
  2505. end",
  2506.     [ "Sha.lua" ] = "local MOD = 2^32\
  2507. local MODM = MOD-1\
  2508. \
  2509. local function memoize(f)\
  2510.        local mt = {}\
  2511.        local t = setmetatable({}, mt)\
  2512.        function mt:__index(k)\
  2513.                local v = f(k)\
  2514.                t[k] = v\
  2515.                return v\
  2516.        end\
  2517.        return t\
  2518. end\
  2519. \
  2520. local function make_bitop_uncached(t, m)\
  2521.        local function bitop(a, b)\
  2522.                local res,p = 0,1\
  2523.                while a ~= 0 and b ~= 0 do\
  2524.                        local am, bm = a % m, b % m\
  2525.                        res = res + t[am][bm] * p\
  2526.                        a = (a - am) / m\
  2527.                        b = (b - bm) / m\
  2528.                        p = p*m\
  2529.                end\
  2530.                res = res + (a + b) * p\
  2531.                return res\
  2532.        end\
  2533.        return bitop\
  2534. end\
  2535. \
  2536. local function make_bitop(t)\
  2537.        local op1 = make_bitop_uncached(t,2^1)\
  2538.        local op2 = memoize(function(a) return memoize(function(b) return op1(a, b) end) end)\
  2539.        return make_bitop_uncached(op2, 2 ^ (t.n or 1))\
  2540. end\
  2541. \
  2542. local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})\
  2543. \
  2544. local function bxor(a, b, c, ...)\
  2545.        local z = nil\
  2546.        if b then\
  2547.                a = a % MOD\
  2548.                b = b % MOD\
  2549.                z = bxor1(a, b)\
  2550.                if c then z = bxor(z, c, ...) end\
  2551.                return z\
  2552.        elseif a then return a % MOD\
  2553.        else return 0 end\
  2554. end\
  2555. \
  2556. local function band(a, b, c, ...)\
  2557.        local z\
  2558.        if b then\
  2559.                a = a % MOD\
  2560.                b = b % MOD\
  2561.                z = ((a + b) - bxor1(a,b)) / 2\
  2562.                if c then z = bit32_band(z, c, ...) end\
  2563.                return z\
  2564.        elseif a then return a % MOD\
  2565.        else return MODM end\
  2566. end\
  2567. \
  2568. local function bnot(x) return (-1 - x) % MOD end\
  2569. \
  2570. local function rshift1(a, disp)\
  2571.        if disp < 0 then return lshift(a,-disp) end\
  2572.        return math.floor(a % 2 ^ 32 / 2 ^ disp)\
  2573. end\
  2574. \
  2575. local function rshift(x, disp)\
  2576.        if disp > 31 or disp < -31 then return 0 end\
  2577.        return rshift1(x % MOD, disp)\
  2578. end\
  2579. \
  2580. local function lshift(a, disp)\
  2581.        if disp < 0 then return rshift(a,-disp) end\
  2582.        return (a * 2 ^ disp) % 2 ^ 32\
  2583. end\
  2584. \
  2585. local function rrotate(x, disp)\
  2586.    x = x % MOD\
  2587.    disp = disp % 32\
  2588.    local low = band(x, 2 ^ disp - 1)\
  2589.    return rshift(x, disp) + lshift(low, 32 - disp)\
  2590. end\
  2591. \
  2592. local k = {\
  2593.        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,\
  2594.        0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\
  2595.        0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\
  2596.        0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\
  2597.        0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,\
  2598.        0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\
  2599.        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,\
  2600.        0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\
  2601.        0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\
  2602.        0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\
  2603.        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,\
  2604.        0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\
  2605.        0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,\
  2606.        0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\
  2607.        0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\
  2608.        0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\
  2609. }\
  2610. \
  2611. local function str2hexa(s)\
  2612.        return (string.gsub(s, \".\", function(c) return string.format(\"%02x\", string.byte(c)) end))\
  2613. end\
  2614. \
  2615. local function num2s(l, n)\
  2616.        local s = \"\"\
  2617.        for i = 1, n do\
  2618.                local rem = l % 256\
  2619.                s = string.char(rem) .. s\
  2620.                l = (l - rem) / 256\
  2621.        end\
  2622.        return s\
  2623. end\
  2624. \
  2625. local function s232num(s, i)\
  2626.        local n = 0\
  2627.        for i = i, i + 3 do n = n*256 + string.byte(s, i) end\
  2628.        return n\
  2629. end\
  2630. \
  2631. local function preproc(msg, len)\
  2632.        local extra = 64 - ((len + 9) % 64)\
  2633.        len = num2s(8 * len, 8)\
  2634.        msg = msg .. \"\\128\" .. string.rep(\"\\0\", extra) .. len\
  2635.        assert(#msg % 64 == 0)\
  2636.        return msg\
  2637. end\
  2638. \
  2639. local function initH256(H)\
  2640.        H[1] = 0x6a09e667\
  2641.        H[2] = 0xbb67ae85\
  2642.        H[3] = 0x3c6ef372\
  2643.        H[4] = 0xa54ff53a\
  2644.        H[5] = 0x510e527f\
  2645.        H[6] = 0x9b05688c\
  2646.        H[7] = 0x1f83d9ab\
  2647.        H[8] = 0x5be0cd19\
  2648.        return H\
  2649. end\
  2650. \
  2651. local function digestblock(msg, i, H)\
  2652.        local w = {}\
  2653.        for j = 1, 16 do w[j] = s232num(msg, i + (j - 1)*4) end\
  2654.        for j = 17, 64 do\
  2655.                local v = w[j - 15]\
  2656.                local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3))\
  2657.                v = w[j - 2]\
  2658.                w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10))\
  2659.        end\
  2660. \
  2661.        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]\
  2662.        for i = 1, 64 do\
  2663.                local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))\
  2664.                local maj = bxor(band(a, b), band(a, c), band(b, c))\
  2665.                local t2 = s0 + maj\
  2666.                local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))\
  2667.                local ch = bxor (band(e, f), band(bnot(e), g))\
  2668.                local t1 = h + s1 + ch + k[i] + w[i]\
  2669.                h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2\
  2670.        end\
  2671. \
  2672.        H[1] = band(H[1] + a)\
  2673.        H[2] = band(H[2] + b)\
  2674.        H[3] = band(H[3] + c)\
  2675.        H[4] = band(H[4] + d)\
  2676.        H[5] = band(H[5] + e)\
  2677.        H[6] = band(H[6] + f)\
  2678.        H[7] = band(H[7] + g)\
  2679.        H[8] = band(H[8] + h)\
  2680. end\
  2681. \
  2682. function sha256(msg)\
  2683.        msg = preproc(msg, #msg)\
  2684.        local H = initH256({})\
  2685.        for i = 1, #msg, 64 do digestblock(msg, i, H) end\
  2686.        return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) ..\
  2687.                num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4))\
  2688. end",
  2689.     [ "OmniOS.lua" ] = "version = \"alpha\"\
  2690. tag = \"15w16a\"\
  2691. loadAPI = function(_sPath)\
  2692.     local sName = fs.getName( _sPath )\
  2693.     local tEnv = {}\
  2694.     setmetatable( tEnv, { __index = _G } )\
  2695.     local fnAPI, err = loadfile( _sPath )\
  2696.     if fnAPI then\
  2697.         setfenv( fnAPI, tEnv )\
  2698.         local ok, err = pcall( fnAPI )\
  2699.         if not ok then\
  2700.             printError( err )\
  2701.             return false\
  2702.         end\
  2703.     else\
  2704.         printError( err )\
  2705.         return false\
  2706.     end\
  2707.     \
  2708.     local tAPI = {}\
  2709.     for k,v in pairs( tEnv ) do\
  2710.         tAPI[k] =  v\
  2711.     end\
  2712.     \
  2713.     _G[sName:match(\"[^%.]+\")] = tAPI  \
  2714.     return true\
  2715. end\
  2716. \
  2717. requireAPI = function(_sPath)\
  2718.     local sName = fs.getName( _sPath )\
  2719.     local tEnv = {}\
  2720.     setmetatable( tEnv, { __index = _G } )\
  2721.     local fnAPI, err = loadfile( _sPath )\
  2722.     if fnAPI then\
  2723.         setfenv( fnAPI, tEnv )\
  2724.         local ok, err = pcall( fnAPI )\
  2725.         if not ok then\
  2726.             printError( err )\
  2727.             return false\
  2728.         end\
  2729.     else\
  2730.         printError( err )\
  2731.         return false\
  2732.     end\
  2733.     \
  2734.     local tAPI = {}\
  2735.     for k,v in pairs( tEnv ) do\
  2736.         tAPI[k] =  v\
  2737.     end\
  2738.     return tAPI \
  2739. end",
  2740.     [ "Sandbox.lua" ] = "--[[\
  2741.     Sandbox \
  2742.     environment\
  2743.     by Creator\
  2744.     for TheOS\
  2745. ]]--\
  2746. \
  2747. --Variables--\
  2748. local oldGetfenv = getfenv\
  2749. local oldLoadfile = loadfile\
  2750. local globalName = \"\"\
  2751. \
  2752. --Functions--\
  2753. \
  2754. function newEnv(name)\
  2755.     globalName = name\
  2756.     log.log(\"Sandbox\",globalName)\
  2757.     return {\
  2758.         redstone = redstone,\
  2759.         gps = gps,\
  2760.         _VERSION = _VERSION,\
  2761.         keys = keys,\
  2762.         printError = printError,\
  2763.         peripheral = peripheral,\
  2764.         assert = assert,\
  2765.         getfenv = function(a)\
  2766.             if type(a) == \"number\" then\
  2767.                 oldGetfenv(1)\
  2768.             elseif type(a) == \"function\" then\
  2769.                 oldGetfenv(a)\
  2770.             else\
  2771.                 error(\"Expected function or number, got \"..type(a))\
  2772.             end end,\
  2773.         bit = bit,\
  2774.         rawset = rawset,\
  2775.         tonumber = tonumber,\
  2776.         loadstring = function(str) local func = loadstring(str) setfenv(func,getfenv(1))end,\
  2777.         error = error,\
  2778.         tostring = tostring,\
  2779.         type = type,\
  2780.         coroutine = { \
  2781.             create = coroutine.create,\
  2782.             resume = coroutine.resume,\
  2783.             running = coroutine.running,\
  2784.             status = coroutine.status,\
  2785.             wrap = coroutine.wrap,\
  2786.         },\
  2787.         disk = disk,\
  2788.         window = window,\
  2789.         next = next,\
  2790.         unpack = unpack,\
  2791.         colours = colours,\
  2792.         pcall = pcall,\
  2793.         sleep = sleep,\
  2794.         loadfile = function(a) \
  2795.             local func = oldLoadfile(a)\
  2796.             setfenv(func,getfenv(1))\
  2797.             end,\
  2798.         math = math,\
  2799.         pairs = pairs,\
  2800.         fs = {\
  2801.             combine = fs.combine,\
  2802.             isReadOnly = function(path) log.log(\"SandboxPath\",\"OmniOS/Programs/\"..globalName..\".app/\"..path) return fs.isReadOnly(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  2803.             getSize = function(path) return fs.getSize(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  2804.             move = function(path1,path2) return fs.move(\"OmniOS/Programs/\"..globalName..\".app/\"..path1,\"OmniOS/Programs/\"..globalName..\".app/\"..path2) end,\
  2805.             exists = function(path) return fs.exists(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  2806.             copy = function(path1,path2) return fs.copy(\"OmniOS/Programs/\"..globalName..\".app/\"..path1,\"OmniOS/Programs/\"..globalName..\".app/\"..path2) end,\
  2807.             getFreeSpace = function(path) return fs.getFreeSpace(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  2808.             makeDir = function(path) return fs.makeDir(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  2809.             find = function(path) return fs.find(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  2810.             getDir = fs.getDir,\
  2811.             delete = function(path) return fs.delete(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  2812.             open = function(path,...) return fs.open(\"OmniOS/Programs/\"..globalName..\".app/\"..path,...) end,\
  2813.             list = function(path) log.log(\"SandboxPath\",\"OmniOS/Programs/\"..globalName..\".app/\"..path) return fs.list(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  2814.             getDrive = function(path) return fs.getDrive(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  2815.             getName = fs.getName,\
  2816.             isDir = function(path) return fs.isDir(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  2817.         },\
  2818.         rawget = rawget,\
  2819.         _G = envToReturn,\
  2820.         __inext = __inext,\
  2821.         read = read,\
  2822.         rednet = rednet,\
  2823.         ipairs = ipairs,\
  2824.         xpcall = xpcall,\
  2825.         os = os,\
  2826.         help = help,\
  2827.         io = io,\
  2828.         rawequal = rawequal,\
  2829.         setfenv = setfenv,\
  2830.         rs = rs,\
  2831.         http = http,\
  2832.         write = write,\
  2833.         string = string,\
  2834.         setmetatable = setmetatable,\
  2835.         print = print,\
  2836.         getmetatable = getmetatable,\
  2837.         table = table,\
  2838.         parallel = parallel,\
  2839.         dofile = function(path) dofile(\"OmniOS/Programs/\"..globalName..\".app/\"..path) end,\
  2840.         textutils = textutils,\
  2841.         term = term,\
  2842.         colors = colors,\
  2843.         vector = vectors,\
  2844.         select = select,\
  2845.         paintutils = paintutils,\
  2846.         System = System,\
  2847.         OmniOS = OmniOS,\
  2848.         log = log,\
  2849.     }\
  2850. end",
  2851.     [ "OldSandbox.lua" ] = "--[[\
  2852.     Sandbox \
  2853.     environment\
  2854.     by Creator\
  2855.     for TheOS\
  2856. ]]--\
  2857. \
  2858. --Variables--\
  2859. local oldGetfenv = getfenv\
  2860. local oldLoadfile = loadfile\
  2861. --Functions--\
  2862. \
  2863. function newEnv(permission)\
  2864.     if permission == \"admin\" then\
  2865.         return \"global\"\
  2866.     else\
  2867.         return \"custom\" , customEnv()\
  2868.     end\
  2869. end\
  2870. \
  2871. local function makeDir(path)\
  2872.     local parentPath = \"\"\
  2873.     local buffer = {}\
  2874.     for token in string.gmatch(path,\"[^/]+\") do\
  2875.         buffer[#buffer+1] = token\
  2876.     end\
  2877.     for i=1,#buffer-1 do\
  2878.         parentPath = parentPath..\"/\"..buffer[i]\
  2879.     end\
  2880.     local _,permission = isReadOnly(parentPath)\
  2881.     if permission == \"admin\" then\
  2882.         error(\"Operation not allowed, you have no power here...\",2)\
  2883.     elseif permission == \"user\" then\
  2884.     \
  2885.     elseif permission == \"public\" then\
  2886.         fs.makeDir(path)\
  2887.     end\
  2888. end\
  2889. \
  2890. local function copy(a,b)\
  2891.     local function readFile(path)\
  2892.         local file = fs.open(path,\"r\")\
  2893.         local variable = file.readAll()\
  2894.         file.close()\
  2895.         return variable\
  2896.     end\
  2897.     \
  2898.     local function writeFile(path,content)\
  2899.         local file = fs.open(path,\"w\")\
  2900.         file.write(content)\
  2901.         file.close()\
  2902.     end\
  2903.     \
  2904.     if fs.isDir(a) then\
  2905.         local function explore(dir)\
  2906.             local buffer = {}\
  2907.             local sBuffer = fs.list(dir)\
  2908.             for i,v in pairs(sBuffer) do\
  2909.                 sleep(0.05)\
  2910.                 if fs.isDir(dir..\"/\"..v) then\
  2911.                     buffer[v] = explore(dir..\"/\"..v)\
  2912.                 else\
  2913.                     buffer[v] = readFile(dir..\"/\"..v)\
  2914.                 end\
  2915.             end\
  2916.             return buffer\
  2917.         end\
  2918.         filesystem = explore(\"TheOS\")\
  2919.         \
  2920.         function writeDown(input,dir)\
  2921.             for i,v in pairs(input) do\
  2922.                 if type(v) == \"table\" then\
  2923.                     writeDown(v,dir..\"/\"..i)\
  2924.                 elseif type(v) == \"string\" then\
  2925.                     writeFile(dir..\"/\"..i,v)\
  2926.                 end\
  2927.             end\
  2928.         end\
  2929.         writeDown(explore(a),b)\
  2930.     else\
  2931.         writeFile(b,readFile(a))\
  2932.     end\
  2933. end\
  2934. \
  2935. local function isReadOnly(path)\
  2936.     if fs.isDir(path) then\
  2937.         if \
  2938.             \
  2939.     else\
  2940. \
  2941.     end\
  2942. end\
  2943. \
  2944. local function customEnv()\
  2945.     return {\
  2946.         redstone = redstone,\
  2947.         gps = gps,\
  2948.         _VERSION = _VERSION,\
  2949.         keys = keys,\
  2950.         printError = printError,\
  2951.         peripheral = peripheral,\
  2952.         assert = assert,\
  2953.         getfenv = function(a)\
  2954.             if type(a) == \"number\" then\
  2955.                 oldGetfenv(1)\
  2956.             elseif type(a) == \"function\" then\
  2957.                 oldGetfenv(a)\
  2958.             else\
  2959.                 error(\"Expected function or number, got \"..type(a))\
  2960.             end,\
  2961.         bit = bit,\
  2962.         rawset = rawset,\
  2963.         tonumber = tonumber,\
  2964.         loadstring = function(str) local func = loadstring(str) setfenv(func,getfenv(1))end,\
  2965.         error = error,\
  2966.         tostring = tostring,\
  2967.         type = type,\
  2968.         coroutine = { \
  2969.             create = coroutine.create,\
  2970.             resume = coroutine.resume,\
  2971.             running = coroutine.running,\
  2972.             status = coroutine.status,\
  2973.             wrap = coroutine.wrap,\
  2974.         },\
  2975.         disk = disk,\
  2976.         window = window,\
  2977.         next = next,\
  2978.         unpack = unpack,\
  2979.         colours = colours,\
  2980.         pcall = pcall,\
  2981.         sleep = sleep,\
  2982.         loadfile = function(a) \
  2983.             local func = oldLoadfile(a)\
  2984.             setfenv(func,getfenv(1))\
  2985.             end,\
  2986.         math = math,\
  2987.         pairs = pairs,\
  2988.         fs = {\
  2989.             combine = fs.combine,\
  2990.             isReadOnly = isReadOnly,\
  2991.             getSize = fs.getSize,\
  2992.             move = function(a,b)\
  2993.                 copy(a,b)\
  2994.                 fs.delete(a)\
  2995.                 end,\
  2996.             exists = fs.exists,\
  2997.             copy = copy(a,b)\
  2998.             getFreeSpace = fs.getFreeSpace,\
  2999.             makeDir = makeDir,\
  3000.             find = fs.find,\
  3001.             getDir = fs.getDir,\
  3002.             delete = \
  3003.             open\
  3004.             list\
  3005.             getDrive\
  3006.             getName\
  3007.             isDir\
  3008.         },\
  3009.         rawget = rawget\
  3010.         _G \
  3011.         __inext \
  3012.         read \
  3013.         rednet \
  3014.         ipairs \
  3015.         xpcall \
  3016.         os \
  3017.         help \
  3018.         io \
  3019.         rawequal \
  3020.         setfenv \
  3021.         rs \
  3022.         http \
  3023.         write \
  3024.         string \
  3025.         setmetatable \
  3026.         print \
  3027.         getmetatable \
  3028.         table \
  3029.         parallel \
  3030.         dofile \
  3031.         textutils \
  3032.         term \
  3033.         colors \
  3034.         vector \
  3035.         select \
  3036.         paintutils \
  3037.     },\
  3038. end",
  3039.     [ "System.lua" ] = "--[[\
  3040.     System API\
  3041.     for \
  3042.     TheOS\
  3043.     by Creator\
  3044. ]]--\
  3045. \
  3046. function reboot()\
  3047.     os.reboot()\
  3048. end\
  3049. \
  3050. function newTask(name,title,...)\
  3051.     log.log(\"System\",\"Opening app \"..name)\
  3052.     local mainPath = \"OmniOS/Programs/\"..name..\".app/Main.lua\"\
  3053.     local permissionPath = \"OmniOS/Programs/\"..name..\".app/permission.data\"\
  3054.     local file = fs.open(permissionPath,\"r\")\
  3055.     local permission = file.readAll and file.readAll() or \"user\"\
  3056.     file.close()\
  3057.     log.log(\"System\",\"Opening app \"..name..\": retrieved permissions.\")\
  3058.     if fs.exists(mainPath) then\
  3059.         local func, err = loadfile(mainPath)\
  3060.         if func then\
  3061.             log.log(\"System\",\"Opening app \"..name..\": about to launch task.\")\
  3062.             newRoutine(name,title,func,permission,...)\
  3063.             log.log(\"System\",\"Opening app \"..name..\": launched task.\")\
  3064.         end\
  3065.     end\
  3066.     return false\
  3067. end\
  3068. \
  3069. function getPerimssion(program)\
  3070.     return getPerimssion(program)\
  3071. end",
  3072.     [ "NewInteract.lua" ] = "--[[\
  3073.     Interact API in ComputerCraft\
  3074.     by Creator\
  3075.     Complete rewrite in OOP\
  3076. ]]--\
  3077. \
  3078. --Variables\
  3079. local textutilsserialize = textutils.serialize\
  3080. local textutilsunserialize = textutils.unserialize\
  3081. local KeyCodes = {\
  3082.     [ 2 ] =  1 ,\
  3083.     [ 3 ] =  2,\
  3084.     [ 4 ] =  3,\
  3085.     [ 5 ] =  4,\
  3086.     [ 6 ] =  5,\
  3087.     [ 7 ] =  6,\
  3088.     [ 8 ] =  7,\
  3089.     [ 9 ] =  8,\
  3090.     [ 10 ] =  9,\
  3091.     [ 11 ] =  0,\
  3092.     [ 12 ] = \"-\",\
  3093.     [ 13 ] = \"=\",\
  3094.     [ 14 ] = \"Backspace\",\
  3095.     [ 15 ] = \"Tab\",\
  3096.     [ 16 ] = \"q\",\
  3097.     [ 17 ] = \"w\",\
  3098.     [ 18 ] = \"e\",\
  3099.     [ 19 ] = \"r\",\
  3100.     [ 20 ] = \"t\",\
  3101.     [ 21 ] = \"y\",\
  3102.     [ 22 ] = \"u\",\
  3103.     [ 23 ] = \"i\",\
  3104.     [ 24 ] = \"o\",\
  3105.     [ 25 ] = \"p\",\
  3106.     [ 26 ] = \"LeftBracket\",\
  3107.     [ 27 ] = \"RightBracket\",\
  3108.     [ 28 ] = \"Enter\",\
  3109.     [ 29 ] = \"LeftControl\",\
  3110.     [ 30 ] = \"a\",\
  3111.     [ 31 ] = \"s\",\
  3112.     [ 32 ] = \"d\",\
  3113.     [ 33 ] = \"f\",\
  3114.     [ 34 ] = \"g\",\
  3115.     [ 35 ] = \"h\",\
  3116.     [ 36 ] = \"j\",\
  3117.     [ 37 ] = \"k\",\
  3118.     [ 38 ] = \"l\",\
  3119.     [ 39 ] = \";\",\
  3120.     [ 40 ] = \"\\'\",\
  3121.     [ 41 ] = \"`\",\
  3122.     [ 42 ] = \"LeftShift\",\
  3123.     [ 43 ] = \"Backslash\",\
  3124.     [ 44 ] = \"z\",\
  3125.     [ 45 ] = \"x\",\
  3126.     [ 46 ] = \"c\",\
  3127.     [ 47 ] = \"v\",\
  3128.     [ 48 ] = \"b\",\
  3129.     [ 49 ] = \"n\",\
  3130.     [ 50 ] = \"m\",\
  3131.     [ 51 ] = \",\",\
  3132.     [ 52 ] = \".\",\
  3133.     [ 53 ] = \"/\",\
  3134.     [ 54 ] = \"RightShift\",\
  3135.     [ 55 ] = \"*\",\
  3136.     [ 56 ] = \"LeftAlt\",\
  3137.     [ 57 ] = \" \",\
  3138.     [ 58 ] = \"CapsLock\",\
  3139.     [ 59 ] = \"F1\",\
  3140.     [ 60 ] = \"F2\",\
  3141.     [ 61 ] = \"F3\",\
  3142.     [ 62 ] = \"F4\",\
  3143.     [ 63 ] = \"F5\",\
  3144.     [ 64 ] = \"F6\",\
  3145.     [ 65 ] = \"F7\",\
  3146.     [ 66 ] = \"F8\",\
  3147.     [ 67 ] = \"F9\",\
  3148.     [ 68 ] = \"F10\",\
  3149.     [ 69 ] = \"NumberLock\",\
  3150.     [ 70 ] = \"ScrollLock\",\
  3151.     [ 71 ] = \"NumPAd7\",\
  3152.     [ 72 ] = \"NumPAd8\",\
  3153.     [ 73 ] = \"NumPAd9\",\
  3154.     [ 74 ] = \"Substract\",\
  3155.     [ 75 ] = \"NumPAd4\",\
  3156.     [ 76 ] = \"NumPAd5\",\
  3157.     [ 77 ] = \"NumPAd6\",\
  3158.     [ 78 ] = \"Add\",\
  3159.     [ 79 ] = \"NumPAd1\",\
  3160.     [ 80 ] = \"NumPAd2\",\
  3161.     [ 81 ] = \"NumPAd3\",\
  3162.     [ 82 ] = \"NumPAd0\",\
  3163.     [ 83 ] = \"Decimal\",\
  3164.     [ 87 ] = \"F11\",\
  3165.     [ 88 ] = \"F12\",\
  3166.     [ 100] = \"F13\",\
  3167.     [ 101] = \"F14\",\
  3168.     [ 102] = \"F15\",\
  3169.     [ 103] = \"F16\",\
  3170.     [ 104] = \"F17\",\
  3171.     [ 105] = \"F18\",\
  3172.     [ 112] = \"Kana\",\
  3173.     [ 113] = \"F19\",\
  3174.     [ 121] = \"Convert\",\
  3175.     [ 123] = \"Noconvert\",\
  3176.     [ 125] = \"Yen\",\
  3177.     [ 141] = \"NumPadEquals\",\
  3178.     [ 144] = \"^\",\
  3179.     [ 145] = \"@\",\
  3180.     [ 146] = \":\",\
  3181.     [ 147] = \"_\",\
  3182.     [ 148] = \"Kanji\",\
  3183.     [ 149] = \"Stop\",\
  3184.     [ 150] = \"Ax\",\
  3185.     [ 151] = \"Unlabeled\",\
  3186.     [ 156] = \"NumPadEnter\",\
  3187.     [ 157] = \"RightControl\",\
  3188.     [ 157] = \"Section\",\
  3189.     [ 179] = \"NumPadComma\",\
  3190.     [ 181] = \"Dvide\",\
  3191.     [ 183] = \"Sysrq\",\
  3192.     [ 184] = \"RightAlt\",\
  3193.     [ 196] = \"Function\",\
  3194.     [ 197] = \"Pause\",\
  3195.     [ 199] = \"Home\",\
  3196.     [ 200] = \"Up\",\
  3197.     [ 201] = \"PageUp\",\
  3198.     [ 203] = \"Left\",\
  3199.     [ 205] = \"Right\",\
  3200.     [ 207] = \"End\",\
  3201.     [ 208] = \"Down\",\
  3202.     [ 209] = \"PageDown\",\
  3203.     [ 210] = \"Insert\",\
  3204.     [ 211] = \"Delete\",\
  3205. }\
  3206. \
  3207. --Class declarations--\
  3208. local Button = {}\
  3209. local Layout = {}\
  3210. local Toggle = {}\
  3211. local BackgroundColor = {}\
  3212. local ColorField = {}\
  3213. local BetterPaint = {}\
  3214. local Text = {}\
  3215. local TextBox = {}\
  3216. local Key = {}\
  3217. \
  3218. function loadObjects(self)\
  3219.     local output = {}\
  3220.     output.Button = {}\
  3221.     output.Toggle = {}\
  3222.     output.ColorField = {}\
  3223.     output.BetterPaint = {}\
  3224.     output.Text = {}\
  3225.     output.TextBox = {}\
  3226.     output.Key = {}\
  3227.     output.Layout = {}\
  3228.     for o,v in pairs(output) do\
  3229.         if self[o] == nil then\
  3230.             self[o] = {}\
  3231.         end\
  3232.     end\
  3233.     for i,v in pairs(self.Button) do\
  3234.         output.Button[i] = Button.new(self.Button[i])\
  3235.     end\
  3236.     for i,v in pairs(self.Toggle) do\
  3237.         output.Toggle[i] = Toggle.new(self.Toggle[i])\
  3238.     end\
  3239.     for i,v in pairs(self.ColorField) do\
  3240.         output.ColorField[i] = ColorField.new(self.ColorField[i])\
  3241.     end\
  3242.     for i,v in pairs(self.BetterPaint) do\
  3243.         output.BetterPaint[i] = BetterPaint.new(self.BetterPaint[i])\
  3244.     end\
  3245.     for i,v in pairs(self.Text) do\
  3246.         output.Text[i] = Text.new(self.Text[i])\
  3247.     end\
  3248.     for i,v in pairs(self.TextBox) do\
  3249.         output.TextBox[i] = TextBox.new(self.TextBox[i])\
  3250.     end\
  3251.     for i,v in pairs(self.Key) do\
  3252.         output.Key[i] = Key.new(self.Key[i])\
  3253.     end\
  3254.     for i,v in pairs(self.Layout) do\
  3255.         output.Layout[i] = Layout.new(self.Layout[i])\
  3256.     end\
  3257.     output.BackgroundColor = self.BackgroundColor or 1\
  3258.     output.nilClick = self.nilClick or false\
  3259.     return output\
  3260. end\
  3261. \
  3262. function loadLayout(input,output)\
  3263.     for i,v in pairs(input.Button) do\
  3264.         output:addButton(input.Button[i])\
  3265.     end\
  3266.     for i,v in pairs(input.Toggle) do\
  3267.         output:addToggle(input.Toggle[i])\
  3268.     end\
  3269.     for i,v in pairs(input.ColorField) do\
  3270.         output:addColorField(input.ColorField[i])\
  3271.     end\
  3272.     for i,v in pairs(input.BetterPaint) do\
  3273.         output:addBetterPaint(input.BetterPaint[i])\
  3274.     end\
  3275.     for i,v in pairs(input.Text) do\
  3276.         output:addText(input.Text[i])\
  3277.     end\
  3278.     for i,v in pairs(input.TextBox) do\
  3279.         output:addTextBox(input.TextBox[i])\
  3280.     end\
  3281.     for i,v in pairs(input.Key) do\
  3282.         output:addKey(input.Key[i])\
  3283.     end\
  3284.     for i,v in pairs(input.Layout) do\
  3285.         output:addLayout(input.Layout[i])\
  3286.     end\
  3287.     output.BackgroundColor = input.BackgroundColor\
  3288.     output.nilClick = input.nilClick\
  3289. end\
  3290. \
  3291. --Class Layout--\
  3292. --Layout initialization function--\
  3293. Layout.new = function(input)\
  3294.     local self = {}\
  3295.     setmetatable(self,{__index = Layout})\
  3296.     self.Button = {}\
  3297.     self.Toggle = {}\
  3298.     self.ColorField = {}\
  3299.     self.BetterPaint = {}\
  3300.     self.Text = {}\
  3301.     self.TextBox = {}\
  3302.     self.Key = {}\
  3303.     self.Layout = {}\
  3304.     for i,v in pairs(self) do\
  3305.         if input[i] == nil then\
  3306.             input[i] = {}\
  3307.         end\
  3308.     end\
  3309.     self.BackgroundColor = 1\
  3310.     self.xPos = input.xPos or 1\
  3311.     self.yPos = input.yPos or 1\
  3312.     self.xLength = input.xLength or 51\
  3313.     self.yLength = input.yLength or 19\
  3314.     self.nilClick = input.nilClick or false\
  3315.     self.window = Screen.new(term.current(),self.xPos,self.yPos,self.xLength,self.yLength)\
  3316.     for i,v in pairs(input.Button) do\
  3317.         self:addButton(input.Button[i])\
  3318.     end\
  3319.     for i,v in pairs(input.Toggle) do\
  3320.         self:addToggle(input.Toggle[i])\
  3321.     end\
  3322.     for i,v in pairs(input.ColorField) do\
  3323.         self:addColorField(input.ColorField[i])\
  3324.     end\
  3325.     for i,v in pairs(input.BetterPaint) do\
  3326.         self:addBetterPaint(input.BetterPaint[i])\
  3327.     end\
  3328.     for i,v in pairs(input.Text) do\
  3329.         self:addText(input.Text[i])\
  3330.     end\
  3331.     for i,v in pairs(input.TextBox) do\
  3332.         self:addTextBox(input.TextBox[i])\
  3333.     end\
  3334.     for i,v in pairs(input.Key) do\
  3335.         self:addKey(input.Key[i])\
  3336.     end\
  3337.     for i,v in pairs(input.Layout) do\
  3338.         self:addLayout(input.Layout[i])\
  3339.     end\
  3340.     self.BackgroundColor = input.BackgroundColor\
  3341.     self.nilClick = input.nilClick\
  3342.     return self\
  3343. end\
  3344. \
  3345. --Add element function--\
  3346. Layout.addButton = function(self,_elementData)\
  3347.     setmetatable(_elementData,{__index = Button})\
  3348.     self.Button[_elementData.name] = _elementData\
  3349. end\
  3350. \
  3351. Layout.addToggle = function(self,_elementData)\
  3352.     setmetatable(_elementData,{__index = Toggle})\
  3353.     self.Toggle[_elementData.name] = _elementData\
  3354. end\
  3355. \
  3356. Layout.addBackgroundColor = function(self,_elementData)\
  3357.     self.BackgroundColor = _elementData.color\
  3358. end\
  3359. \
  3360. Layout.addColorField = function(self,_elementData)\
  3361.     setmetatable(_elementData,{__index = ColorField})\
  3362.     self.ColorField[_elementData.name] = _elementData\
  3363. end\
  3364. \
  3365. Layout.addBetterPaint = function(self,_elementData)\
  3366.     setmetatable(_elementData,{__index = BetterPaint})\
  3367.     self.BetterPaint[_elementData.name] = _elementData\
  3368. end\
  3369. \
  3370. Layout.addText = function(self,_elementData)\
  3371.     setmetatable(_elementData,{__index = Text})\
  3372.     self.Text[_elementData.name] = _elementData\
  3373. end\
  3374. \
  3375. Layout.addTextBox = function(self,_elementData)\
  3376.     setmetatable(_elementData,{__index = TextBox})\
  3377.     self.TextBox[_elementData.name] = _elementData\
  3378. end\
  3379. \
  3380. Layout.addKey = function(self,_elementData)\
  3381.     setmetatable(_elementData,{__index = Key})\
  3382.     self.Key[_elementData.name] = _elementData\
  3383. end\
  3384. \
  3385. Layout.addLayout = function(self,_elementData)\
  3386.     self.Layout[_elementData.name] = Layout.new(_elementData)\
  3387. end\
  3388. \
  3389. Layout.draw = function(self,xPlus,yPlus)\
  3390.     xPlus = xPlus or 0\
  3391.     yPlus = yPlus or 0\
  3392.     self.finalX = xPlus\
  3393.     self.finalY = yPlus\
  3394.     local oldTerm = term.current()\
  3395.     term.redirect(self.window)\
  3396.     local buttonFunctions = {}\
  3397.     local toggleFunctions = {}\
  3398.     local colorFieldFunctions = {}\
  3399.     local betterPaintFunctions = {}\
  3400.     local textFunctions = {}\
  3401.     local textBoxFunctions = {}\
  3402.     local layoutFunctions = {}\
  3403.     setmetatable(buttonFunctions,{__index = Button})\
  3404.     setmetatable(toggleFunctions,{__index = Toggle})\
  3405.     setmetatable(colorFieldFunctions,{__index = ColorField})\
  3406.     setmetatable(betterPaintFunctions,{__index = BetterPaint})\
  3407.     setmetatable(textFunctions,{__index = Text})\
  3408.     setmetatable(textBoxFunctions,{__index = TextBox})\
  3409.     setmetatable(layoutFunctions,{__index = Layout})\
  3410.     paintutils.drawFilledBox(1,1,self.xLength,self.yLength,self.BackgroundColor)\
  3411.     for i,v in pairs(self.ColorField) do\
  3412.         colorFieldFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  3413.     end\
  3414.     for i,v in pairs(self.Button) do\
  3415.         buttonFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  3416.     end\
  3417.     for i,v in pairs(self.BetterPaint) do\
  3418.         betterPaintFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  3419.     end\
  3420.     for i,v in pairs(self.Toggle) do\
  3421.         toggleFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  3422.     end\
  3423.     for i,v in pairs(self.Text) do\
  3424.         textFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  3425.     end\
  3426.     for i,v in pairs(self.TextBox) do\
  3427.         textBoxFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  3428.     end\
  3429.     for i,v in pairs(self.Layout) do\
  3430.         layoutFunctions.draw(v,self.xPos-1+xPlus,self.yPos-1+yPlus)\
  3431.     end\
  3432.     term.redirect(oldTerm)\
  3433. end\
  3434. \
  3435. --Class Button--\
  3436. --Button initialization function\
  3437. Button.new = function(input)\
  3438.     local self = {}\
  3439.     setmetatable(self,{__index = Button})\
  3440.     self.name = input.name\
  3441.     self.label = input.label\
  3442.     self.xPos = input.xPos\
  3443.     self.yPos = input.yPos\
  3444.     self.fgColor = input.fgColor\
  3445.     self.bgColor = input.bgColor\
  3446.     self.xLength = input.xLength\
  3447.     self.yLength = input.yLength\
  3448.     self.returnValue = input.returnValue\
  3449.     self.xTextPos = input.xTextPos\
  3450.     self.yTextPos = input.yTextPos\
  3451.     self.onRightClick = input.onRightClick or nil\
  3452.     self.onLeftClick = input.onLeftClick or nil\
  3453.     return self\
  3454. end\
  3455. \
  3456. --Draw function\
  3457. Button.draw = function(self,addX,addY)\
  3458.     addX = addX or 0\
  3459.     addY = addY or 0\
  3460.     local finalX = self.xPos + addX\
  3461.     local finalY = self.yPos + addY\
  3462. \
  3463.     self.finalX = finalX\
  3464.     self.finalY = finalY\
  3465.     local newText\
  3466.     if #self.label > self.xLength then\
  3467.         newText = string.sub(self.label,1,self.xLength)\
  3468.     else\
  3469.         newText = self.label\
  3470.     end\
  3471.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.bgColor)\
  3472.     term.setTextColor(self.fgColor)\
  3473.     term.setCursorPos(finalX+self.xTextPos-1,finalY+self.yTextPos-1)\
  3474.     term.write(newText)\
  3475. end\
  3476. \
  3477. --Return function--\
  3478. Button.returnData = function(self)\
  3479.     local toReturn = {}\
  3480.     for i,v in pairs(self) do\
  3481.         toReturn[i] = v\
  3482.     end\
  3483.     return toReturn\
  3484. end\
  3485. \
  3486. --Sample Input table--\
  3487. example = [[\
  3488.     example = {\
  3489.         name = \"quickSettings\",\
  3490.         label = \">\",\
  3491.         xPos = 1,\
  3492.         yPos = 3,\
  3493.         xLength = 1,\
  3494.         yLength = 6,\
  3495.         xTextPos = 1,\
  3496.         yTextPos = 1,\
  3497.         fgColor = colors.blue,\
  3498.         bgColor = colors.lightGray,\
  3499.         returnValue = \"quickSettings\",\
  3500.     },\
  3501. ]]\
  3502. \
  3503. --Class Toggle--\
  3504. --Initialize Toggle Object--\
  3505. Toggle.new = function(input)\
  3506.     local self = {}\
  3507.     setmetatable(self,{__index = Toggle})\
  3508.     self.name = input.name or \"randomName\"\
  3509.     self.state = input.state or true\
  3510.     self.xPos = input.xPos or 1\
  3511.     self.yPos = input.yPos or 1\
  3512.     self.trueColor = input.trueColor or colors.green\
  3513.     self.falseColor = input.falseColor or colors.red\
  3514.     self.trueText = input.trueText or \"T\"\
  3515.     self.falseText = input.falseText or \"F\"\
  3516.     self.selectedBg = input.selectedBg or colors.gray\
  3517.     self.notSelectedBg = input.notSelectedBg or colors.lightGray\
  3518.     self.returnValue = input.returnValue or \"mmmmmmm\"\
  3519.     self.moveX = input.moveX or false\
  3520.     self.moveY = input.moveY or false\
  3521.     self.onRightClick = input.onRightClick or nil\
  3522.     self.onLeftClick = input.onLeftClick or nil\
  3523.     return self\
  3524. end\
  3525. \
  3526. function Toggle.draw(self,addX,addY)\
  3527.     addX = addX or 0\
  3528.     addY = addY or 0\
  3529.     local finalX = self.xPos + addX\
  3530.     local finalY = self.yPos + addY\
  3531.     self.finalX = finalX\
  3532.     self.finalY = finalY\
  3533.     term.setCursorPos(finalX,finalY)\
  3534.     if self.state == false then\
  3535.         term.setBackgroundColor(self.notSelectedBg)\
  3536.         term.setTextColor(self.trueColor)\
  3537.         term.write(string.sub(self.trueText,1,1))\
  3538.         term.setBackgroundColor(self.selectedBg)\
  3539.         term.setTextColor(self.falseColor)\
  3540.         term.write(\" \"..string.sub(self.falseText,1,1)..\" \")\
  3541.     elseif self.state == true then\
  3542.         term.setBackgroundColor(self.selectedBg)\
  3543.         term.setTextColor(self.trueColor)\
  3544.         term.write(\" \"..string.sub(self.trueText,1,1)..\" \")\
  3545.         term.setBackgroundColor(self.notSelectedBg)\
  3546.         term.setTextColor(self.falseColor)\
  3547.         term.write(string.sub(self.falseText,1,1))\
  3548.     end\
  3549. end\
  3550. \
  3551. function Toggle.returnData(self)\
  3552.     local toReturn = {}\
  3553.     for i,v in pairs(self) do\
  3554.         toReturn[i] = v\
  3555.     end\
  3556.     return toReturn\
  3557. end\
  3558. \
  3559. function Toggle.toggle(self)\
  3560.     if self.state == true then\
  3561.         self.state = false\
  3562.     else\
  3563.         self.state = true\
  3564.     end\
  3565. end\
  3566. \
  3567. function Toggle.getState(self)\
  3568.     return self.state\
  3569. end\
  3570. \
  3571. --BackgroundColor Class--\
  3572. function BackgroundColor.new(input)\
  3573.     local self = {}\
  3574.     setmetatable(self,{__index = BackgroundColor})\
  3575.     self.color = input.color\
  3576.     return self\
  3577. end\
  3578. \
  3579. function BackgroundColor.setColor(self,color)\
  3580.     self.color = color\
  3581. end\
  3582. \
  3583. function BackgroundColor.returnData(self)\
  3584.     local toReturn = {}\
  3585.     for i,v in pairs(self) do\
  3586.         toReturn[i] = v\
  3587.     end\
  3588.     return toReturn\
  3589. end\
  3590. \
  3591. --ColorField Class--\
  3592. function ColorField.new(input)\
  3593.     local self = {}\
  3594.     setmetatable(self,{__index = ColorField})\
  3595.     self.name = input.name\
  3596.     self.xPos = input.xPos\
  3597.     self.yPos = input.yPos\
  3598.     self.xLength = input.xLength\
  3599.     self.yLength = input.yLength\
  3600.     self.color = input.color\
  3601.     self.moveX = input.moveX or false\
  3602.     self.moveY = input.moveY or false\
  3603.     return self\
  3604. end\
  3605. \
  3606. function  ColorField.draw(self,addX,addY)\
  3607.     addX = addX or 0\
  3608.     addY = addY or 0\
  3609.     local finalX = self.xPos + addX\
  3610.     local finalY = self.yPos + addY\
  3611.     self.finalX = finalX\
  3612.     self.finalY = finalY\
  3613.     term.setTextColor(colors.black)\
  3614.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.color)\
  3615. end\
  3616. \
  3617. function ColorField.returnData(self)\
  3618.     local toReturn = {}\
  3619.     for i,v in pairs(self) do\
  3620.         toReturn[i] = v\
  3621.     end\
  3622.     return toReturn\
  3623. end\
  3624. \
  3625. --BetterPaint Class--\
  3626. function BetterPaint.new(input)\
  3627.     local self = {}\
  3628.     setmetatable(self,{__index = BetterPaint})\
  3629.     self.xPos = input.xPos\
  3630.     self.yPos = input.yPos\
  3631.     self.name = input.name\
  3632.     self.path = input.path\
  3633.     self.xLength = input.xLength\
  3634.     self.yLength = input.yLength\
  3635.     self.returnValue = input.returnValue\
  3636.     self.label = input.label\
  3637.     self.labelBg = input.labelBg\
  3638.     self.labelFg = input.labelFg\
  3639.     self.moveX = input.moveX or false\
  3640.     self.moveY = input.moveY or false\
  3641.     self.onRightClick = input.onRightClick or nil\
  3642.     self.onLeftClick = input.onLeftClick or nil\
  3643.     return self\
  3644. end\
  3645. \
  3646. function BetterPaint.returnData(self)\
  3647.     local toReturn = {}\
  3648.     for i,v in pairs(self) do\
  3649.         toReturn[i] = v\
  3650.     end\
  3651.     return toReturn\
  3652. end\
  3653. \
  3654. function BetterPaint.draw(self,addX,addY)\
  3655.     addX = addX or 0\
  3656.     addY = addY or 0\
  3657.     local finalX = self.xPos + addX\
  3658.     local finalY = self.yPos + addY\
  3659.     self.finalX = finalX\
  3660.     self.finalY = finalY\
  3661.     paint.drawImage(self.path,finalX,finalY)\
  3662.     term.setCursorPos(finalX,finalY+self.yLength)\
  3663.     term.setTextColor(self.labelFg)\
  3664.     term.setBackgroundColor(self.labelBg)\
  3665.     term.write(self.label)\
  3666. end\
  3667. \
  3668. --Text Class--\
  3669. function Text.new(input)\
  3670.     local self = {}\
  3671.     setmetatable(self,{__index = Text})\
  3672.     self.name = input.name\
  3673.     self.text = input.text\
  3674.     self.xPos = input.xPos\
  3675.     self.yPos = input.yPos\
  3676.     self.bgColor = input.bgColor\
  3677.     self.fgColor = input.fgColor\
  3678.     return self\
  3679. end\
  3680. \
  3681. function Text.draw(self,addX,addY)\
  3682.     addX = addX or 0\
  3683.     addY = addY or 0\
  3684.     local finalX = self.xPos + addX\
  3685.     local finalY = self.yPos + addY\
  3686.     self.finalX = finalX\
  3687.     self.finalY = finalY\
  3688.     term.setCursorPos(finalX,finalY)\
  3689.     term.setTextColor(self.fgColor)\
  3690.     term.setBackgroundColor(self.bgColor)\
  3691.     term.write(self.text)\
  3692. end\
  3693. \
  3694. function Text.returnData(self)\
  3695.     local toReturn = {}\
  3696.     for i,v in pairs(self) do\
  3697.         toReturn[i] = v\
  3698.     end\
  3699.     return toReturn\
  3700. end\
  3701. \
  3702. --TextBox Class \
  3703. \
  3704. function TextBox.new(input)\
  3705.     local self = {}\
  3706.     setmetatable(self,{__index = TextBox})\
  3707.     self.name = input.name\
  3708.     self.helpText = input.helpText\
  3709.     self.xPos = input.xPos\
  3710.     self.yPos = input.yPos\
  3711.     self.xLength = input.xLength\
  3712.     self.yLength = input.yLength\
  3713.     self.bgColor = input.bgColor\
  3714.     self.fgColor = input.fgColor\
  3715.     self.helpFgColor = input.helpFgColor\
  3716.     self.charLimit = input.charLimit\
  3717.     self.moveX = input.moveX or false\
  3718.     self.moveY = input.moveY or false\
  3719.     self.text = \"\"\
  3720.     self.returnValue = input.returnValue\
  3721.     self.confidential = input.confidential or false\
  3722.     return self\
  3723. end\
  3724. \
  3725. function TextBox.returnData(self)\
  3726.     local toReturn = {}\
  3727.     for i,v in pairs(self) do\
  3728.         toReturn[i] = v\
  3729.     end\
  3730.     return toReturn\
  3731. end\
  3732. \
  3733. function TextBox.draw(self,addX,addY)\
  3734.     addX = addX or 0\
  3735.     addY = addY or 0\
  3736.     local finalX = self.xPos + addX\
  3737.     local finalY = self.yPos + addY\
  3738.     self.finalX = finalX\
  3739.     self.finalY = finalY\
  3740.     paintutils.drawFilledBox(finalX,finalY,finalX+self.xLength-1,finalY+self.yLength-1,self.bgColor)\
  3741.     term.setBackgroundColor(self.bgColor)\
  3742.     term.setCursorPos(self.finalX,self.finalY)\
  3743.     if self.text == \"\" or self.confidential then\
  3744.         term.setTextColor(self.helpFgColor)\
  3745.         term.write(self.helpText)\
  3746.     else\
  3747.         term.setTextColor(self.fgColor)\
  3748.         term.write(self.text)\
  3749.     end\
  3750. end\
  3751. \
  3752. function TextBox.read(self,_sReplaceChar, _tHistory)\
  3753.     paintutils.drawFilledBox(self.finalX,self.finalY,self.finalX+self.xLength-1,self.finalY+self.yLength-1,self.bgColor)\
  3754.     term.setTextColor(self.fgColor)\
  3755.     term.setCursorPos(self.finalX,self.finalY)\
  3756.     return read()\
  3757. end\
  3758. \
  3759. --Key Class\
  3760. function Key.new(input)\
  3761.     local self = {}\
  3762.     setmetatable(self,{__index = TextBox})\
  3763.     self.name = input.name\
  3764.     self.key = input.key\
  3765.     self.onPress = input.onPress or nil\
  3766.     return self\
  3767. end\
  3768. \
  3769. function Key.returnData(self)\
  3770.     local toReturn = {}\
  3771.     for i,v in pairs(self) do\
  3772.         toReturn[i] = v\
  3773.     end\
  3774.     return toReturn\
  3775. end\
  3776. \
  3777. local function localEventHandler(self,toAddX, toAddY, event, p1, p2, p3, p4, p5, p6)\
  3778.     while true do\
  3779.         if event == \"mouse_click\" then\
  3780.             for i,v in pairs(self.Button) do\
  3781.                 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\
  3782.                     if p1 == 1 then\
  3783.                         if v.onLeftClick then \
  3784.                             v.onLeftClick()\
  3785.                         end\
  3786.                     elseif p1 == 2 then\
  3787.                         if v.onRightClick then\
  3788.                             v.onRightClick()\
  3789.                         end\
  3790.                     end\
  3791.                     return {\"Button\",tostring(v.returnValue),p1,p2,p3}\
  3792.                 end\
  3793.             end\
  3794.             for i,v in pairs(self.Toggle) do\
  3795.                 if v.finalX + toAddX <= p2 and p2 <= v.finalX + 3 + toAddX and v.finalY + toAddY == p3 then\
  3796.                     return {\"Toggle\",tostring(v.returnValue),p1,p2,p3}\
  3797.                 end\
  3798.             end\
  3799.             for i,v in pairs(self.BetterPaint) do \
  3800.                 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\
  3801.                     return {\"Button\",tostring(v.returnValue),p1,p2,p3}\
  3802.                 end\
  3803.             end\
  3804.             for i,v in pairs(self.TextBox) do \
  3805.                 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\
  3806.                     return {\"TextBox\",tostring(v.returnValue),p1,p2,p3}\
  3807.                 end\
  3808.             end\
  3809.             for i,v in pairs(self.Layout) do \
  3810.                 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\
  3811.                     local toReturn = localEventHandler(v,v.finalX-1,v.finalY-1, event, p1, p2, p3, p4, p5, p6)\
  3812.                     return {toReturn[1],toReturn[2],p1,p2,p3}\
  3813.                 end\
  3814.             end\
  3815.             if self.nilClick then\
  3816.                 if not (self.xPos <= p2 and p2 <= self.xPos+self.xLength-1 and self.yPos <= p3 and p3 <= self.yPos+self.yLength-1) then\
  3817.                     return {\"Nil\",\"Nil\",p1,p2,p3}\
  3818.                 end\
  3819.             end\
  3820.         elseif event == \"key\" then\
  3821.             local pressedKey = p1\
  3822.             for i,v in pairs(self.Key) do\
  3823.                 if v.key == KeyCodes[pressedKey] then\
  3824.                     if v.onPress then\
  3825.                         v.onPress()\
  3826.                     else\
  3827.                         return {\"Key\",KeyCodes[pressedKey],pressedKey}\
  3828.                     end\
  3829.                 end\
  3830. \
  3831.             end\
  3832.         elseif event == \"monitor_touch\" then\
  3833.             os.queueEvent(\"mouse_click\", p1, p2, p3, p4, p5, p6)\
  3834.         end\
  3835.     end\
  3836. end\
  3837. \
  3838. --Event handler function--\
  3839. eventHandler = function(self)\
  3840. \
  3841.     return localEventHandler(self,self.xPos-1,self.yPos-1,os.pullEvent())\
  3842. end\
  3843. \
  3844. --Load Function--\
  3845. function Initialize()\
  3846.     local toReturn = {}\
  3847.     toReturn.Button = Button\
  3848.     toReturn.Layout = Layout\
  3849.     toReturn.Toggle = Toggle\
  3850.     toReturn.BackgroundColor = BackgroundColor\
  3851.     toReturn.ColorField = ColorField\
  3852.     toReturn.BetterPaint = BetterPaint\
  3853.     toReturn.Text = Text\
  3854.     toReturn.TextBox = TextBox\
  3855.     toReturn.Key = Key\
  3856.     toReturn.eventHandler = eventHandler\
  3857.     toReturn.loadObjects = loadObjects\
  3858.     toReturn.loadLayout = loadLayout\
  3859.     return toReturn\
  3860. end",
  3861.     [ "gui.lua" ] = "--[[\
  3862.     GUI API in ComputerCraft\
  3863.     by Creator\
  3864.     Complete rewrite in OOP\
  3865. ]]--\
  3866. \
  3867. --Button Class--\
  3868. \
  3869. Button = {}\
  3870. \
  3871. newButton = function(_name,_label,_xPos,_yPos,_xLength,_yLength,_fgColor,_bgColor,_returnValue)\
  3872.     local self = {}\
  3873.     setmetatable(self,{__index = Button})\
  3874.     self.name = _name\
  3875.     self.label = _label\
  3876.     self.xPos = _xPos\
  3877.     self.yPos = _yPos\
  3878.     self.fgColor = _fgColor\
  3879.     self.bgColor = _bgColor\
  3880.     self.xLength = _xLength\
  3881.     self.yLength = _yLength\
  3882.     self.returnValue = _returnValue\
  3883.     return self\
  3884. end\
  3885. \
  3886. Button.draw = function(self)\
  3887.     --term.setBackgroundColor(self.bgColor)\
  3888.     paintutils.drawFilledBox(self.xPos,self.yPos,self.xLength-1,self.yLength-1,self.bgColor)\
  3889.     \
  3890. end\
  3891. \
  3892. --Variables--\
  3893. --Functions--\
  3894. \
  3895. function addKey(key,returnValue)\
  3896.     keysMain[#keysMain+1] = {key,returnValue}\
  3897. end\
  3898. \
  3899. function resetKeys()\
  3900.     keysMain = {}\
  3901. end\
  3902. \
  3903. local function localAddField(minX,minY,maxX,maxY,returnV)\
  3904.     buttonsMain[#buttonsMain+1] = {minX,minY,minX+maxX-1,minY+maxY-1,returnV}\
  3905. end\
  3906. \
  3907. function addField(minX,minY,maxX,maxY,returnV)\
  3908.     if not pcall(localAddField,minX,minY,maxX,maxY,returnV) then\
  3909.         print([[\
  3910.         Usage:\
  3911.         As an argument pass a table structured like this:\
  3912.         {\
  3913.             xPos,\
  3914.             yPos,\
  3915.             wide,\
  3916.             height,\
  3917.             returnValue,\
  3918.         }\
  3919.         ]])\
  3920.     end\
  3921. end\
  3922. \
  3923. local function localDrawButton(xPos,yPos,wide,height,colorOfButton,inButtonXPosOfLabel,inButtonYPosOfLabel,label,textColor,returnValue)\
  3924.     if colorOfButton ~= nil then\
  3925.         paintutils.drawFilledBox(xPos,yPos,xPos+wide-1,yPos+height-1,colorOfButton)\
  3926.     end\
  3927.     term.setTextColor(textColor)\
  3928.     term.setCursorPos(xPos+inButtonXPosOfLabel-1,yPos+inButtonYPosOfLabel-1)\
  3929.     local textToPrint = string.sub(label,1,xPos+wide-inButtonXPosOfLabel)\
  3930.     term.write(textToPrint)\
  3931.     buttonsMain[#buttonsMain+1] = {xPos,yPos,xPos+wide-1,yPos+height-1,returnValue}\
  3932. end\
  3933. \
  3934. function drawButton(xPos,yPos,wide,height,colorOfButton,inButtonXPosOfLabel,inButtonYPosOfLabel,label,textColor,returnValue)\
  3935.     if not pcall(localDrawButton,xPos,yPos,wide,height,colorOfButton,inButtonXPosOfLabel,inButtonYPosOfLabel,label,textColor,returnValue) then\
  3936.         print([[\
  3937.         Usage:\
  3938.         As an argument pass a table structured like this:\
  3939.         {\
  3940.             xPos,\
  3941.             yPos,\
  3942.             wide,\
  3943.             height,\
  3944.             colorOfButton,\
  3945.             inButtonXPosOfLabel,\
  3946.             inButtonYPosOfLabel,\
  3947.             label,\
  3948.             textColor,\
  3949.             returnValue,\
  3950.         }\
  3951.         You can have the option to not use the background color.\
  3952.         You can do this by simply setting color of button to nil.\
  3953.         ]])\
  3954.     end\
  3955. end\
  3956. \
  3957. function detectButtonOrKeyHit()\
  3958.     while true do\
  3959.         local event, button, x, y\
  3960.         repeat\
  3961.             event, button, x, y = os.pullEvent()\
  3962.         until (event == \"mouse_click\" and buttonsMain ~= nil) or (event == \"key\" and keysMain ~= nil)\
  3963.         if event == \"mouse_click\" then\
  3964.             for i,v in pairs(buttonsMain) do\
  3965.                 if v[1] <= x and x <= v[3] and v[2] <= y and y <= v[4] then\
  3966.                     return {v[5], button, x, y}\
  3967.                 end\
  3968.             end\
  3969.         elseif event == \"key\" then\
  3970.             for i,v in pairs(keysMain) do\
  3971.                 if button == v[1] then\
  3972.                     return {v[2]}\
  3973.                 end\
  3974.             end\
  3975.         end\
  3976.     end\
  3977. end\
  3978. \
  3979. function resetButtons()\
  3980.     buttonsMain = {}\
  3981. end\
  3982. \
  3983. local function localCPrint(txt,color,bgColor,xPos,yPos,maxL)\
  3984.     if not maxL == nil then\
  3985.         txt = string.sub(txt,1,maxL)\
  3986.     end\
  3987.     term.setTextColor(color)\
  3988.     if bgColor ~= nil then\
  3989.         term.setBackgroundColor(bgColor)\
  3990.     end\
  3991.     term.setCursorPos(xPos,yPos)\
  3992.     term.write(txt)\
  3993. end\
  3994. \
  3995. function cPrint(txt,color,bgColor,xPos,yPos,maxL)\
  3996.     if not pcall(localCPrint,txt,color,bgColor,xPos,yPos,maxL) then\
  3997.         print([[\
  3998.             Usage:\
  3999.             Arguments are as follws:\
  4000.             {\
  4001.             Text to print\
  4002.             Text color\
  4003.             Background color\
  4004.             xPos\
  4005.             yPos\
  4006.             Maximal lenght of the string\
  4007.             }\
  4008.             Maximal lenght of the string can be left \"nil\" with qoutes\
  4009.         ]])\
  4010.     end\
  4011. end",
  4012.     [ "log.lua" ] = "--[[\
  4013.     Log API\
  4014.     by Creator\
  4015.     for TheOS\
  4016. ]]--\
  4017. \
  4018. function log(destination,message,app)\
  4019.     local finalMsg = \"[\"..os.day()..\":\"..os.time()..\"]\"\
  4020.     if app then\
  4021.         finalMsg = finalMsg..\".[\"..tostring(app)..\"]:\"..tostring(message)\
  4022.     else\
  4023.         finalMsg = finalMsg..\":\"..tostring(message)\
  4024.     end\
  4025.     local m = fs.open(\"OmniOS/Logs/\"..destination..\".log\",\"a\")\
  4026.     m.write(finalMsg..\"\\n\")\
  4027.     m.close()\
  4028. end",
  4029.     [ "Screen.lua" ] = "function new( parent, nX, nY, nWidth, nHeight)\
  4030. \
  4031.     if type( parent ) ~= \"table\" then error( \"Expected object\",2 ) end\
  4032.     if type( nX ) ~= \"number\" then error( \"Expected number1\", 2 ) end\
  4033.     if type( nY ) ~= \"number\" then error( \"Expected number2\", 2 ) end\
  4034.     if type( nWidth ) ~= \"number\" then error( \"Expected number3\", 2 ) end\
  4035.     if type( nHeight ) ~= \"number\" then error( \"Expected number4\", 2 ) end\
  4036. \
  4037.     if parent == term then\
  4038.         parent = term.current()\
  4039.     end\
  4040. \
  4041.     -- Setup\
  4042.     local nCursorX = 1\
  4043.     local nCursorY = 1\
  4044. \
  4045.     -- Helper functions\
  4046.     local function updateCursorPos()\
  4047.         if nCursorX >= 1 and nCursorY >= 1 and\
  4048.            nCursorX <= nWidth and nCursorY <= nHeight then\
  4049.             parent.setCursorPos( nX + nCursorX - 1, nY + nCursorY - 1 )\
  4050.         else\
  4051.             parent.setCursorPos( 0, 0 )\
  4052.         end\
  4053.     end\
  4054. \
  4055.     local window = {}\
  4056. \
  4057.     -- Terminal implementation\
  4058.     function window.write( sText )\
  4059.         local nLen = sText:len()\
  4060.         updateCursorPos()\
  4061.         for i = 1, nLen do\
  4062.             if nCursorX <= nWidth and nCursorY <= nHeight then\
  4063.                 parent.write(sText:sub(i,i))\
  4064.                 nCursorX = nCursorX + 1\
  4065.             end\
  4066.         end\
  4067.     end\
  4068. \
  4069.     local function clearLine()\
  4070.         for i=1,nWidth do\
  4071.             parent.write(\" \")\
  4072.             nCursorX = nCursorX + 1\
  4073.         end\
  4074.     end\
  4075. \
  4076.     function window.clear()\
  4077.         for m=1, nHeight do\
  4078.             updateCursorPos()\
  4079.             clearLine()\
  4080.             nCursorY = nCursorY + 1\
  4081.         end\
  4082.     end\
  4083. \
  4084.     function window.clearLine()\
  4085.         clearLine()\
  4086.     end\
  4087. \
  4088.     function window.getCursorPos()\
  4089.         return nCursorX, nCursorY\
  4090.     end\
  4091. \
  4092.     function window.setCursorPos( x, y )\
  4093.         nCursorX = math.floor( x )\
  4094.         nCursorY = math.floor( y )\
  4095.         updateCursorPos()\
  4096.     end\
  4097. \
  4098.     function window.setCursorBlink( blink )\
  4099.         parent.setCursorBlink(blink)\
  4100.     end\
  4101. \
  4102.     function window.isColor()\
  4103.         return parent.isColor()\
  4104.     end\
  4105. \
  4106.     function window.isColour()\
  4107.         return parent.isColor()\
  4108.     end\
  4109. \
  4110.     local function setTextColor( color )\
  4111.         if not parent.isColor() then\
  4112.             if color ~= colors.white and color ~= colors.black then\
  4113.                 error( \"Colour not supported\", 3 )\
  4114.             end\
  4115.         end\
  4116.         parent.setTextColour(color)\
  4117.     end\
  4118. \
  4119.     function window.setTextColor( color )\
  4120.         setTextColor( color )\
  4121.     end\
  4122. \
  4123.     function window.setTextColour( color )\
  4124.         setTextColor( color )\
  4125.     end\
  4126. \
  4127.     local function setBackgroundColor( color )\
  4128.         if not parent.isColor() then\
  4129.             if color ~= colors.white and color ~= colors.black then\
  4130.                 error( \"Colour not supported\", 3 )\
  4131.             end\
  4132.         end\
  4133.         parent.setBackgroundColor(color)\
  4134.     end\
  4135. \
  4136.     function window.setBackgroundColor( color )\
  4137.         setBackgroundColor( color )\
  4138.     end\
  4139. \
  4140.     function window.setBackgroundColour( color )\
  4141.         setBackgroundColor( color )\
  4142.     end\
  4143. \
  4144.     function window.getSize()\
  4145.         return nWidth, nHeight\
  4146.     end\
  4147. \
  4148.     function window.scroll( n )\
  4149.         print(\"Fuck you! No freaking buffer.\")\
  4150.     end\
  4151. \
  4152.     return window\
  4153. end",
  4154.   },
  4155.   Programs = {
  4156.     [ "Desktop.app" ] = {
  4157.       [ "permission.data" ] = "",
  4158.       [ "Main.luaBlah.lua" ] = "--[[\
  4159.     Desktop in ComputerCraft\
  4160.     by Creator\
  4161.     for OmniOS\
  4162. ]]--\
  4163. --Variables--\
  4164. local textutilsserialize = textutils.serialize\
  4165. local textutilsunserialize = textutils.unserialize\
  4166. local w,h = term.getSize()\
  4167. local Settings = {}\
  4168. local result = {}\
  4169. local Main = {}\
  4170. local QuickSettings = {}\
  4171. local MatchingColors = {}\
  4172. local gui = {}\
  4173. local mainLayout = {}\
  4174. local quickSettingsLayout = {}\
  4175. local mainLayoutTable = {}\
  4176. local quickSettingsLayoutTable = {}\
  4177. local paths = {}\
  4178. local scroll = 0\
  4179. local programPath = \"OmniOS/Programs/Desktop.app/Data/\"\
  4180. \
  4181. --Functions--\
  4182. local function readFile(_path)\
  4183.     local file = fs.open(_path,\"r\")\
  4184.     local data = file.readAll()\
  4185.     file.close()\
  4186.     return data\
  4187. end\
  4188. \
  4189. local function split(str,sep)\
  4190.     local buffer = {}\
  4191.     for token in str:gmatch(sep) do\
  4192.         buffer[#buffer+1] = token\
  4193.     end\
  4194.     return buffer\
  4195. end\
  4196. \
  4197. local function loadShortcuts()\
  4198.     local buffer = readFile(programPath..\"Shortcuts\")\
  4199.     local sBuffer = textutilsunserialize(buffer)\
  4200.     local nBuffer = {}\
  4201.     paths = {}\
  4202.     for i,v in pairs(sBuffer) do\
  4203.         nBuffer[v.name] = {\
  4204.             xPos = 2+(6*(v.xPos-1)),\
  4205.             yPos = 1+(5*(v.yPos-1)),\
  4206.             name = v.name,\
  4207.             path = v.path..\".ico\",\
  4208.             yLength = 4,\
  4209.             xLength = 3,\
  4210.             returnValue = v.name,\
  4211.             label = string.sub(v.name,1,5),\
  4212.             labelFg = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4213.             labelBg = Settings.bgColor,\
  4214.             moveY = true,\
  4215.         }\
  4216.         paths[v.name] = v.path\
  4217.     end\
  4218.     Main.BetterPaint = nBuffer\
  4219. end\
  4220. \
  4221. local function loadObjects()\
  4222. --Object table--\
  4223.     Main.Button = {\
  4224.         quickSettings = {\
  4225.             name = \"quickSettings\",\
  4226.             label = \"^\",\
  4227.             xPos = 1,\
  4228.             yPos = h,\
  4229.             xLength = 1,\
  4230.             yLength = 1,\
  4231.             xTextPos = 1,\
  4232.             yTextPos = 1,\
  4233.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4234.             bgColor = Settings.bgColor,\
  4235.             returnValue = \"quickSettings\",\
  4236.         },\
  4237.         windowPlus = {\
  4238.             name = \"windowPlus\",\
  4239.             label = \">\",\
  4240.             xPos = w,\
  4241.             yPos = 1,\
  4242.             xLength = 1,\
  4243.             yLength = 1,\
  4244.             xTextPos = 1,\
  4245.             yTextPos = 1,\
  4246.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4247.             bgColor = Settings.bgColor,\
  4248.             returnValue = \"windowPlus\",\
  4249.         },\
  4250.         windowMinus = {\
  4251.             name = \"windowMinus\",\
  4252.             label = \"<\",\
  4253.             xPos = 1,\
  4254.             yPos = 1,\
  4255.             xLength = 1,\
  4256.             yLength = 1,\
  4257.             xTextPos = 1,\
  4258.             yTextPos = 1,\
  4259.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4260.             bgColor = Settings.bgColor,\
  4261.             returnValue = \"windowMinus\",\
  4262.         },\
  4263.     }\
  4264.     QuickSettings.Button = {\
  4265.         Right = {\
  4266.             name = \"Right\",\
  4267.             label = \">\",\
  4268.             xPos = w-1,\
  4269.             yPos = 5,\
  4270.             xLength = 1,\
  4271.             yLength = 1,\
  4272.             xTextPos = 1,\
  4273.             yTextPos = 1,\
  4274.             fgColor = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4275.             bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4276.             returnValue = \"Right\",\
  4277.         },\
  4278.         Left = {\
  4279.             name = \"Left\",\
  4280.             label = \"<\",\
  4281.             xPos = 2,\
  4282.             yPos = 5,\
  4283.             xLength = 1,\
  4284.             yLength = 1,\
  4285.             xTextPos = 1,\
  4286.             yTextPos = 1,\
  4287.             fgColor = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4288.             bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4289.             returnValue = \"Left\",\
  4290.         },\
  4291.         Green = {\
  4292.             name = \"Green\",\
  4293.             label = \" \",\
  4294.             xPos = 31,\
  4295.             yPos = 6,\
  4296.             xLength = 1,\
  4297.             yLength = 1,\
  4298.             xTextPos = 1,\
  4299.             yTextPos = 1,\
  4300.             fgColor = 1,\
  4301.             bgColor = colors.green,\
  4302.             returnValue = \"color:green\",\
  4303.         },\
  4304.         Lime = {\
  4305.             name = \"Lime\",\
  4306.             label = \" \",\
  4307.             xPos = 31,\
  4308.             yPos = 7,\
  4309.             xLength = 1,\
  4310.             yLength = 1,\
  4311.             xTextPos = 1,\
  4312.             yTextPos = 1,\
  4313.             fgColor = 1,\
  4314.             bgColor = colors.lime,\
  4315.             returnValue = \"color:lime\",\
  4316.         },\
  4317.         Brown = {\
  4318.             name = \"Brown\",\
  4319.             label = \" \",\
  4320.             xPos = 32,\
  4321.             yPos = 6,\
  4322.             xLength = 1,\
  4323.             yLength = 1,\
  4324.             xTextPos = 1,\
  4325.             yTextPos = 1,\
  4326.             fgColor = 1,\
  4327.             bgColor = colors.brown,\
  4328.             returnValue = \"color:brown\",\
  4329.         },\
  4330.         Purple = {\
  4331.             name = \"Purple\",\
  4332.             label = \" \",\
  4333.             xPos = 32,\
  4334.             yPos = 7,\
  4335.             xLength = 1,\
  4336.             yLength = 1,\
  4337.             xTextPos = 1,\
  4338.             yTextPos = 1,\
  4339.             fgColor = 1,\
  4340.             bgColor = colors.purple,\
  4341.             returnValue = \"color:purple\",\
  4342.         },\
  4343.         Blue = {\
  4344.             name = \"Blue\",\
  4345.             label = \" \",\
  4346.             xPos = 33,\
  4347.             yPos = 6,\
  4348.             xLength = 1,\
  4349.             yLength = 1,\
  4350.             xTextPos = 1,\
  4351.             yTextPos = 1,\
  4352.             fgColor = 1,\
  4353.             bgColor = colors.blue,\
  4354.             returnValue = \"color:blue\",\
  4355.         },\
  4356.         lightBlue = {\
  4357.             name = \"lightBlue\",\
  4358.             label = \" \",\
  4359.             xPos = 33,\
  4360.             yPos = 7,\
  4361.             xLength = 1,\
  4362.             yLength = 1,\
  4363.             xTextPos = 1,\
  4364.             yTextPos = 1,\
  4365.             fgColor = 1,\
  4366.             bgColor = colors.lightBlue,\
  4367.             returnValue = \"color:lightBlue\",\
  4368.         },\
  4369.         Yellow = {\
  4370.             name = \"Yellow\",\
  4371.             label = \" \",\
  4372.             xPos = 34,\
  4373.             yPos = 6,\
  4374.             xLength = 1,\
  4375.             yLength = 1,\
  4376.             xTextPos = 1,\
  4377.             yTextPos = 1,\
  4378.             fgColor = 1,\
  4379.             bgColor = colors.yellow,\
  4380.             returnValue = \"color:yellow\",\
  4381.         },\
  4382.         Cyan = {\
  4383.             name = \"Cyan\",\
  4384.             label = \" \",\
  4385.             xPos = 34,\
  4386.             yPos = 7,\
  4387.             xLength = 1,\
  4388.             yLength = 1,\
  4389.             xTextPos = 1,\
  4390.             yTextPos = 1,\
  4391.             fgColor = 1,\
  4392.             bgColor = colors.cyan,\
  4393.             returnValue = \"color:cyan\",\
  4394.         },\
  4395.         Orange = {\
  4396.             name = \"Orange\",\
  4397.             label = \" \",\
  4398.             xPos = 35,\
  4399.             yPos = 6,\
  4400.             xLength = 1,\
  4401.             yLength = 1,\
  4402.             xTextPos = 1,\
  4403.             yTextPos = 1,\
  4404.             fgColor = 1,\
  4405.             bgColor = colors.orange,\
  4406.             returnValue = \"color:orange\",\
  4407.         },\
  4408.         Pink = {\
  4409.             name = \"Pink\",\
  4410.             label = \" \",\
  4411.             xPos = 35,\
  4412.             yPos = 7,\
  4413.             xLength = 1,\
  4414.             yLength = 1,\
  4415.             xTextPos = 1,\
  4416.             yTextPos = 1,\
  4417.             fgColor = 1,\
  4418.             bgColor = colors.pink,\
  4419.             returnValue = \"color:pink\",\
  4420.         },\
  4421.         Red = {\
  4422.             name = \"Red\",\
  4423.             label = \" \",\
  4424.             xPos = 36,\
  4425.             yPos = 6,\
  4426.             xLength = 1,\
  4427.             yLength = 1,\
  4428.             xTextPos = 1,\
  4429.             yTextPos = 1,\
  4430.             fgColor = 1,\
  4431.             bgColor = colors.red,\
  4432.             returnValue = \"color:red\",\
  4433.         },\
  4434.         Magenta = {\
  4435.             name = \"Magenta\",\
  4436.             label = \" \",\
  4437.             xPos = 36,\
  4438.             yPos = 7,\
  4439.             xLength = 1,\
  4440.             yLength = 1,\
  4441.             xTextPos = 1,\
  4442.             yTextPos = 1,\
  4443.             fgColor = 1,\
  4444.             bgColor = colors.magenta,\
  4445.             returnValue = \"color:magenta\",\
  4446.         },\
  4447.         White = {\
  4448.             name = \"White\",\
  4449.             label = \" \",\
  4450.             xPos = 37,\
  4451.             yPos = 6,\
  4452.             xLength = 1,\
  4453.             yLength = 1,\
  4454.             xTextPos = 1,\
  4455.             yTextPos = 1,\
  4456.             fgColor = 1,\
  4457.             bgColor = colors.white,\
  4458.             returnValue = \"color:white\",\
  4459.         },\
  4460.         lightGray = {\
  4461.             name = \"lightGray\",\
  4462.             label = \" \",\
  4463.             xPos = 37,\
  4464.             yPos = 7,\
  4465.             xLength = 1,\
  4466.             yLength = 1,\
  4467.             xTextPos = 1,\
  4468.             yTextPos = 1,\
  4469.             fgColor = 1,\
  4470.             bgColor = colors.lightGray,\
  4471.             returnValue = \"color:lightGray\",\
  4472.         },\
  4473.         Black = {\
  4474.             name = \"Black\",\
  4475.             label = \" \",\
  4476.             xPos = 38,\
  4477.             yPos = 6,\
  4478.             xLength = 1,\
  4479.             yLength = 1,\
  4480.             xTextPos = 1,\
  4481.             yTextPos = 1,\
  4482.             fgColor = 1,\
  4483.             bgColor = colors.black,\
  4484.             returnValue = \"color:black\",\
  4485.         },\
  4486.         Gray = {\
  4487.             name = \"Gray\",\
  4488.             label = \" \",\
  4489.             xPos = 38,\
  4490.             yPos = 7,\
  4491.             xLength = 1,\
  4492.             yLength = 1,\
  4493.             xTextPos = 1,\
  4494.             yTextPos = 1,\
  4495.             fgColor = 1,\
  4496.             bgColor = colors.gray,\
  4497.             returnValue = \"color:gray\",\
  4498.         },\
  4499.         RefreshColor = {\
  4500.             name = \"RefreshColor\",\
  4501.             label = \"Refresh\",\
  4502.             xPos = 40,\
  4503.             yPos = 3,\
  4504.             xLength = 9,\
  4505.             yLength = 5,\
  4506.             xTextPos = 2,\
  4507.             yTextPos = 3,\
  4508.             fgColor = 1,\
  4509.             bgColor = colors.gray,\
  4510.             returnValue = \"Refresh\",\
  4511.         },\
  4512.     }\
  4513. \
  4514.     QuickSettings.BetterPaint = {\
  4515.         Restart = {\
  4516.             xPos = 4,\
  4517.             yPos = 2,\
  4518.             name = \"Restart\",\
  4519.             path = programPath..\"QuickSettings/restart.ico\",\
  4520.             yLength = 6,\
  4521.             xLength = 7,\
  4522.             returnValue = \"reboot\",\
  4523.             label = \"Restart\",\
  4524.             labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4525.             labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4526.         },\
  4527.         Shutdown = {\
  4528.             xPos = 22,\
  4529.             yPos = 2,\
  4530.             name = \"Shutdown\",\
  4531.             path = programPath..\"QuickSettings/shutdown.ico\",\
  4532.             yLength = 6,\
  4533.             xLength = 7,\
  4534.             returnValue = \"shutdown\",\
  4535.             label = \"Shutdown\",\
  4536.             labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4537.             labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4538.         },\
  4539.         Settings = {\
  4540.             xPos = 13,\
  4541.             yPos = 2,\
  4542.             name = \"Settings\",\
  4543.             path = programPath..\"QuickSettings/settings.ico\",\
  4544.             yLength = 6,\
  4545.             xLength = 7,\
  4546.             returnValue = \"settings\",\
  4547.             label = \"Settings\",\
  4548.             labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4549.             labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4550.         },\
  4551.     }\
  4552. \
  4553.     QuickSettings.Text = {\
  4554.         Label = {\
  4555.             name = \"Label\",\
  4556.             text = \"QuickSettings\",\
  4557.             xPos = w/2-6,\
  4558.             yPos = 1,\
  4559.             bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4560.             fgColor = Settings.bgColor,\
  4561.         },\
  4562.     }\
  4563.     QuickSettings.Key = {\
  4564.         R = {\
  4565.             name = \"R\",\
  4566.             key = \"r\",\
  4567.             onPress = function() os.reboot() end,\
  4568.         },\
  4569.         S = {\
  4570.             name = \"S\",\
  4571.             key = \"s\",\
  4572.             onPress = function() os.shutdown() end,\
  4573.         },\
  4574.         LeftAlt = {\
  4575.             name = \"LeftAlt\",\
  4576.             key = \"LeftAlt\",\
  4577.             onPress = function() System.newTask(\"Settings\",\"Settings\") end,\
  4578.         },\
  4579.     }\
  4580.     loadShortcuts()\
  4581. \
  4582. end\
  4583. \
  4584. local function loadGUI()\
  4585.     --Initializing GUI components\
  4586.     gui = Interact:Initialize()\
  4587.     mainLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})\
  4588.     quickSettingsLayout = gui.Layout.new({xPos = 1,yPos = h-7, xLength = w,yLength = 7})\
  4589.     mainLayoutTable = {}\
  4590.     quickSettingsLayoutTable = {}\
  4591. end\
  4592. \
  4593. local function InitializeGUI()\
  4594.     loadObjects()\
  4595.     --Main--\
  4596.     mainLayoutTable = {}\
  4597.     mainLayoutTable = gui.loadObjects(Main)\
  4598.     mainLayoutTable.mainBgColor = gui.BackgroundColor.new({color = Settings.bgColor})\
  4599.     \
  4600.     --QuickSettings--\
  4601.     quickSettingsLayoutTable = {}\
  4602.     quickSettingsLayoutTable.Text = {}\
  4603.     quickSettingsLayoutTable = gui.loadObjects(QuickSettings)\
  4604.     quickSettingsLayoutTable.quickSettingsBgColor = gui.BackgroundColor.new({color = MatchingColors[Settings.bgColor][\"quickSettings\"]})\
  4605.     \
  4606.     --Initializing structures--\
  4607.     --Main--\
  4608.     for i,v in pairs(mainLayoutTable.Button) do\
  4609.         mainLayout:addButton(mainLayoutTable.Button[i]:returnData())\
  4610.     end\
  4611.     for i,v in pairs(mainLayoutTable.BetterPaint) do\
  4612.         mainLayout:addBetterPaint(mainLayoutTable.BetterPaint[i]:returnData())\
  4613.     end\
  4614.     mainLayout:addBackgroundColor(mainLayoutTable.mainBgColor:returnData())\
  4615.     \
  4616.     --QuickSettings--\
  4617.     for i,v in pairs(quickSettingsLayoutTable.Button) do\
  4618.         quickSettingsLayout:addButton(quickSettingsLayoutTable.Button[i]:returnData())\
  4619.     end\
  4620.     quickSettingsLayout:addBackgroundColor(quickSettingsLayoutTable.quickSettingsBgColor:returnData())\
  4621.     quickSettingsLayout:addBetterPaint(quickSettingsLayoutTable.BetterPaint.Restart)\
  4622.     quickSettingsLayout:addBetterPaint(quickSettingsLayoutTable.BetterPaint.Shutdown)\
  4623.     quickSettingsLayout:addBetterPaint(quickSettingsLayoutTable.BetterPaint.Settings)\
  4624.     quickSettingsLayout:addKey(quickSettingsLayoutTable.Key.R:returnData())\
  4625.     quickSettingsLayout:addKey(quickSettingsLayoutTable.Key.S:returnData())\
  4626.     quickSettingsLayout:addKey(quickSettingsLayoutTable.Key.LeftAlt:returnData())\
  4627. end\
  4628. \
  4629. local function changeColor(color)\
  4630.     Settings.bgColor = colors[color] or colors.green\
  4631.     local f = fs.open(programPath..\"Settings\",\"w\")\
  4632.     f.write(textutilsserialize(Settings))\
  4633.     f.close()\
  4634.     local buffer = readFile(programPath..\"Settings\")\
  4635.     Settings = textutils.unserialize( buffer )\
  4636.     local buffer = readFile(programPath..\"MatchingColors\")\
  4637.     MatchingColors = textutilsunserialize(buffer)\
  4638.     loadObjects()\
  4639.     InitializeGUI()\
  4640. end\
  4641. \
  4642. --Loading settings--\
  4643. local buffer = readFile(programPath..\"Settings\")\
  4644. Settings = textutils.unserialize( buffer )\
  4645. \
  4646. local buffer = readFile(programPath..\"MatchingColors\")\
  4647. MatchingColors = textutilsunserialize(buffer)\
  4648. \
  4649. \
  4650. \
  4651. loadObjects()\
  4652. loadGUI()\
  4653. InitializeGUI()\
  4654. \
  4655. \
  4656. --Code--\
  4657. while true do\
  4658.     mainLayout:draw(0,scroll)\
  4659.     local result = gui.eventHandler(mainLayout)\
  4660.     if result[1] == \"Button\" then\
  4661.         if result[2] == \"quickSettings\" then\
  4662.             quickSettingsLayout:draw()\
  4663.             local notClose = true\
  4664.             while notClose do\
  4665.                 local answer = gui.eventHandler(quickSettingsLayout)\
  4666.                 if answer[1] == \"Button\" then\
  4667.                     if answer[2] == \"reboot\" then\
  4668.                         os.reboot()\
  4669.                     elseif answer[2] == \"shutdown\" then\
  4670.                         os.shutdown()\
  4671.                     elseif answer[2] == \"Close\" then\
  4672.                         notClose = false\
  4673.                     elseif answer[2] == \"settings\" then\
  4674.                         System.newTask(\"Settings\",\"Settings\")\
  4675.                         notClose = false\
  4676.                     elseif answer[2] == \"Refresh\" then\
  4677.                         local buffer = readFile(programPath..\"Settings\")\
  4678.                         Settings = textutils.unserialize( buffer )\
  4679.                         local buffer = readFile(programPath..\"MatchingColors\")\
  4680.                         MatchingColors = textutilsunserialize(buffer)\
  4681.                         loadObjects()\
  4682.                         InitializeGUI()\
  4683.                         notClose = false\
  4684.                     else\
  4685.                         local buffer = split(answer[2],\"[^:]+\")\
  4686.                         changeColor(buffer[2])\
  4687.                         notClose = false\
  4688.                     end\
  4689.                 elseif answer[1] == \"Nil\" then\
  4690.                     if answer[2] == \"Nil\" then\
  4691.                         notClose = false\
  4692.                     end\
  4693.                 end\
  4694.             end\
  4695.         elseif result[2] == \"windowPlus\" then\
  4696.             scroll = scroll - 51\
  4697.         elseif result[2] == \"windowMinus\" then\
  4698.             scroll = scroll + 51\
  4699.         else\
  4700.             System.newTask(result[2],result[2])\
  4701.         end\
  4702.     end\
  4703. end",
  4704.       [ "Main.lua" ] = "--[[\
  4705.     Desktop in ComputerCraft\
  4706.     by Creator\
  4707.     for OmniOS\
  4708. ]]--\
  4709. --Variables--\
  4710. local textutilsserialize = textutils.serialize\
  4711. local textutilsunserialize = textutils.unserialize\
  4712. local w,h = term.getSize()\
  4713. local Settings = {}\
  4714. local result = {}\
  4715. local Main = {}\
  4716. local QuickSettings = {}\
  4717. local MatchingColors = {}\
  4718. local gui = {}\
  4719. local mainLayout = {}\
  4720. local quickSettingsLayout = {}\
  4721. local mainLayoutTable = {}\
  4722. local quickSettingsLayoutTable = {}\
  4723. local paths = {}\
  4724. local scroll = 0\
  4725. local programPath = \"OmniOS/Programs/Desktop.app/Data/\"\
  4726. \
  4727. --Functions--\
  4728. local function readFile(_path)\
  4729.     local file = fs.open(_path,\"r\")\
  4730.     local data = file.readAll()\
  4731.     file.close()\
  4732.     return data\
  4733. end\
  4734. \
  4735. local function split(str,sep)\
  4736.     local buffer = {}\
  4737.     for token in str:gmatch(sep) do\
  4738.         buffer[#buffer+1] = token\
  4739.     end\
  4740.     return buffer\
  4741. end\
  4742. \
  4743. local function loadShortcuts()\
  4744.     local buffer = readFile(programPath..\"Shortcuts\")\
  4745.     local sBuffer = textutilsunserialize(buffer)\
  4746.     local nBuffer = {}\
  4747.     paths = {}\
  4748.     for i,v in pairs(sBuffer) do\
  4749.         nBuffer[v.name] = {\
  4750.             xPos = 2+(6*(v.xPos-1)),\
  4751.             yPos = 1+(5*(v.yPos-1)),\
  4752.             name = v.name,\
  4753.             path = v.path..\".ico\",\
  4754.             yLength = 4,\
  4755.             xLength = 3,\
  4756.             returnValue = v.name,\
  4757.             label = string.sub(v.name,1,5),\
  4758.             labelFg = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4759.             labelBg = Settings.bgColor,\
  4760.             moveY = true,\
  4761.         }\
  4762.         paths[v.name] = v.path\
  4763.     end\
  4764.     Main.BetterPaint = nBuffer\
  4765. end\
  4766. \
  4767. local function loadObjects()\
  4768. --Object table--\
  4769.     Main.Button = {\
  4770.         quickSettings = {\
  4771.             name = \"quickSettings\",\
  4772.             label = \"^\",\
  4773.             xPos = 1,\
  4774.             yPos = h,\
  4775.             xLength = 1,\
  4776.             yLength = 1,\
  4777.             xTextPos = 1,\
  4778.             yTextPos = 1,\
  4779.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4780.             bgColor = Settings.bgColor,\
  4781.             returnValue = \"quickSettings\",\
  4782.         },\
  4783.         windowPlus = {\
  4784.             name = \"windowPlus\",\
  4785.             label = \">\",\
  4786.             xPos = w,\
  4787.             yPos = 1,\
  4788.             xLength = 1,\
  4789.             yLength = 1,\
  4790.             xTextPos = 1,\
  4791.             yTextPos = 1,\
  4792.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4793.             bgColor = Settings.bgColor,\
  4794.             returnValue = \"windowPlus\",\
  4795.         },\
  4796.         windowMinus = {\
  4797.             name = \"windowMinus\",\
  4798.             label = \"<\",\
  4799.             xPos = 1,\
  4800.             yPos = 1,\
  4801.             xLength = 1,\
  4802.             yLength = 1,\
  4803.             xTextPos = 1,\
  4804.             yTextPos = 1,\
  4805.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  4806.             bgColor = Settings.bgColor,\
  4807.             returnValue = \"windowMinus\",\
  4808.         },\
  4809.     }\
  4810.     Main.Layout = {\
  4811.         QuickSettings\
  4812.     }\
  4813.     QuickSettings.Button = {\
  4814.         Right = {\
  4815.             name = \"Right\",\
  4816.             label = \">\",\
  4817.             xPos = w-1,\
  4818.             yPos = 5,\
  4819.             xLength = 1,\
  4820.             yLength = 1,\
  4821.             xTextPos = 1,\
  4822.             yTextPos = 1,\
  4823.             fgColor = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4824.             bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4825.             returnValue = \"Right\",\
  4826.         },\
  4827.         Left = {\
  4828.             name = \"Left\",\
  4829.             label = \"<\",\
  4830.             xPos = 2,\
  4831.             yPos = 5,\
  4832.             xLength = 1,\
  4833.             yLength = 1,\
  4834.             xTextPos = 1,\
  4835.             yTextPos = 1,\
  4836.             fgColor = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  4837.             bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  4838.             returnValue = \"Left\",\
  4839.         },\
  4840.         Green = {\
  4841.             name = \"Green\",\
  4842.             label = \" \",\
  4843.             xPos = 31,\
  4844.             yPos = 6,\
  4845.             xLength = 1,\
  4846.             yLength = 1,\
  4847.             xTextPos = 1,\
  4848.             yTextPos = 1,\
  4849.             fgColor = 1,\
  4850.             bgColor = colors.green,\
  4851.             returnValue = \"color:green\",\
  4852.         },\
  4853.         Lime = {\
  4854.             name = \"Lime\",\
  4855.             label = \" \",\
  4856.             xPos = 31,\
  4857.             yPos = 7,\
  4858.             xLength = 1,\
  4859.             yLength = 1,\
  4860.             xTextPos = 1,\
  4861.             yTextPos = 1,\
  4862.             fgColor = 1,\
  4863.             bgColor = colors.lime,\
  4864.             returnValue = \"color:lime\",\
  4865.         },\
  4866.         Brown = {\
  4867.             name = \"Brown\",\
  4868.             label = \" \",\
  4869.             xPos = 32,\
  4870.             yPos = 6,\
  4871.             xLength = 1,\
  4872.             yLength = 1,\
  4873.             xTextPos = 1,\
  4874.             yTextPos = 1,\
  4875.             fgColor = 1,\
  4876.             bgColor = colors.brown,\
  4877.             returnValue = \"color:brown\",\
  4878.         },\
  4879.         Purple = {\
  4880.             name = \"Purple\",\
  4881.             label = \" \",\
  4882.             xPos = 32,\
  4883.             yPos = 7,\
  4884.             xLength = 1,\
  4885.             yLength = 1,\
  4886.             xTextPos = 1,\
  4887.             yTextPos = 1,\
  4888.             fgColor = 1,\
  4889.             bgColor = colors.purple,\
  4890.             returnValue = \"color:purple\",\
  4891.         },\
  4892.         Blue = {\
  4893.             name = \"Blue\",\
  4894.             label = \" \",\
  4895.             xPos = 33,\
  4896.             yPos = 6,\
  4897.             xLength = 1,\
  4898.             yLength = 1,\
  4899.             xTextPos = 1,\
  4900.             yTextPos = 1,\
  4901.             fgColor = 1,\
  4902.             bgColor = colors.blue,\
  4903.             returnValue = \"color:blue\",\
  4904.         },\
  4905.         lightBlue = {\
  4906.             name = \"lightBlue\",\
  4907.             label = \" \",\
  4908.             xPos = 33,\
  4909.             yPos = 7,\
  4910.             xLength = 1,\
  4911.             yLength = 1,\
  4912.             xTextPos = 1,\
  4913.             yTextPos = 1,\
  4914.             fgColor = 1,\
  4915.             bgColor = colors.lightBlue,\
  4916.             returnValue = \"color:lightBlue\",\
  4917.         },\
  4918.         Yellow = {\
  4919.             name = \"Yellow\",\
  4920.             label = \" \",\
  4921.             xPos = 34,\
  4922.             yPos = 6,\
  4923.             xLength = 1,\
  4924.             yLength = 1,\
  4925.             xTextPos = 1,\
  4926.             yTextPos = 1,\
  4927.             fgColor = 1,\
  4928.             bgColor = colors.yellow,\
  4929.             returnValue = \"color:yellow\",\
  4930.         },\
  4931.         Cyan = {\
  4932.             name = \"Cyan\",\
  4933.             label = \" \",\
  4934.             xPos = 34,\
  4935.             yPos = 7,\
  4936.             xLength = 1,\
  4937.             yLength = 1,\
  4938.             xTextPos = 1,\
  4939.             yTextPos = 1,\
  4940.             fgColor = 1,\
  4941.             bgColor = colors.cyan,\
  4942.             returnValue = \"color:cyan\",\
  4943.         },\
  4944.         Orange = {\
  4945.             name = \"Orange\",\
  4946.             label = \" \",\
  4947.             xPos = 35,\
  4948.             yPos = 6,\
  4949.             xLength = 1,\
  4950.             yLength = 1,\
  4951.             xTextPos = 1,\
  4952.             yTextPos = 1,\
  4953.             fgColor = 1,\
  4954.             bgColor = colors.orange,\
  4955.             returnValue = \"color:orange\",\
  4956.         },\
  4957.         Pink = {\
  4958.             name = \"Pink\",\
  4959.             label = \" \",\
  4960.             xPos = 35,\
  4961.             yPos = 7,\
  4962.             xLength = 1,\
  4963.             yLength = 1,\
  4964.             xTextPos = 1,\
  4965.             yTextPos = 1,\
  4966.             fgColor = 1,\
  4967.             bgColor = colors.pink,\
  4968.             returnValue = \"color:pink\",\
  4969.         },\
  4970.         Red = {\
  4971.             name = \"Red\",\
  4972.             label = \" \",\
  4973.             xPos = 36,\
  4974.             yPos = 6,\
  4975.             xLength = 1,\
  4976.             yLength = 1,\
  4977.             xTextPos = 1,\
  4978.             yTextPos = 1,\
  4979.             fgColor = 1,\
  4980.             bgColor = colors.red,\
  4981.             returnValue = \"color:red\",\
  4982.         },\
  4983.         Magenta = {\
  4984.             name = \"Magenta\",\
  4985.             label = \" \",\
  4986.             xPos = 36,\
  4987.             yPos = 7,\
  4988.             xLength = 1,\
  4989.             yLength = 1,\
  4990.             xTextPos = 1,\
  4991.             yTextPos = 1,\
  4992.             fgColor = 1,\
  4993.             bgColor = colors.magenta,\
  4994.             returnValue = \"color:magenta\",\
  4995.         },\
  4996.         White = {\
  4997.             name = \"White\",\
  4998.             label = \" \",\
  4999.             xPos = 37,\
  5000.             yPos = 6,\
  5001.             xLength = 1,\
  5002.             yLength = 1,\
  5003.             xTextPos = 1,\
  5004.             yTextPos = 1,\
  5005.             fgColor = 1,\
  5006.             bgColor = colors.white,\
  5007.             returnValue = \"color:white\",\
  5008.         },\
  5009.         lightGray = {\
  5010.             name = \"lightGray\",\
  5011.             label = \" \",\
  5012.             xPos = 37,\
  5013.             yPos = 7,\
  5014.             xLength = 1,\
  5015.             yLength = 1,\
  5016.             xTextPos = 1,\
  5017.             yTextPos = 1,\
  5018.             fgColor = 1,\
  5019.             bgColor = colors.lightGray,\
  5020.             returnValue = \"color:lightGray\",\
  5021.         },\
  5022.         Black = {\
  5023.             name = \"Black\",\
  5024.             label = \" \",\
  5025.             xPos = 38,\
  5026.             yPos = 6,\
  5027.             xLength = 1,\
  5028.             yLength = 1,\
  5029.             xTextPos = 1,\
  5030.             yTextPos = 1,\
  5031.             fgColor = 1,\
  5032.             bgColor = colors.black,\
  5033.             returnValue = \"color:black\",\
  5034.         },\
  5035.         Gray = {\
  5036.             name = \"Gray\",\
  5037.             label = \" \",\
  5038.             xPos = 38,\
  5039.             yPos = 7,\
  5040.             xLength = 1,\
  5041.             yLength = 1,\
  5042.             xTextPos = 1,\
  5043.             yTextPos = 1,\
  5044.             fgColor = 1,\
  5045.             bgColor = colors.gray,\
  5046.             returnValue = \"color:gray\",\
  5047.         },\
  5048.         RefreshColor = {\
  5049.             name = \"RefreshColor\",\
  5050.             label = \"Refresh\",\
  5051.             xPos = 40,\
  5052.             yPos = 3,\
  5053.             xLength = 9,\
  5054.             yLength = 5,\
  5055.             xTextPos = 2,\
  5056.             yTextPos = 3,\
  5057.             fgColor = 1,\
  5058.             bgColor = colors.gray,\
  5059.             returnValue = \"Refresh\",\
  5060.         },\
  5061.     }\
  5062. \
  5063.     QuickSettings.BetterPaint = {\
  5064.         Restart = {\
  5065.             xPos = 4,\
  5066.             yPos = 2,\
  5067.             name = \"Restart\",\
  5068.             path = programPath..\"QuickSettings/restart.ico\",\
  5069.             yLength = 6,\
  5070.             xLength = 7,\
  5071.             returnValue = \"reboot\",\
  5072.             label = \"Restart\",\
  5073.             labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  5074.             labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  5075.         },\
  5076.         Shutdown = {\
  5077.             xPos = 22,\
  5078.             yPos = 2,\
  5079.             name = \"Shutdown\",\
  5080.             path = programPath..\"QuickSettings/shutdown.ico\",\
  5081.             yLength = 6,\
  5082.             xLength = 7,\
  5083.             returnValue = \"shutdown\",\
  5084.             label = \"Shutdown\",\
  5085.             labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  5086.             labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  5087.         },\
  5088.         Settings = {\
  5089.             xPos = 13,\
  5090.             yPos = 2,\
  5091.             name = \"Settings\",\
  5092.             path = programPath..\"QuickSettings/settings.ico\",\
  5093.             yLength = 6,\
  5094.             xLength = 7,\
  5095.             returnValue = \"settings\",\
  5096.             label = \"Settings\",\
  5097.             labelFg = MatchingColors[MatchingColors[Settings.bgColor][\"quickSettings\"]][\"mainButtons\"],\
  5098.             labelBg = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  5099.         },\
  5100.     }\
  5101. \
  5102.     QuickSettings.Text = {\
  5103.         Label = {\
  5104.             name = \"Label\",\
  5105.             text = \"QuickSettings\",\
  5106.             xPos = w/2-6,\
  5107.             yPos = 1,\
  5108.             bgColor = MatchingColors[Settings.bgColor][\"quickSettings\"],\
  5109.             fgColor = Settings.bgColor,\
  5110.         },\
  5111.     }\
  5112.     QuickSettings.Key = {\
  5113.         R = {\
  5114.             name = \"R\",\
  5115.             key = \"r\",\
  5116.             onPress = function() os.reboot() end,\
  5117.         },\
  5118.         S = {\
  5119.             name = \"S\",\
  5120.             key = \"s\",\
  5121.             onPress = function() os.shutdown() end,\
  5122.         },\
  5123.         LeftAlt = {\
  5124.             name = \"LeftAlt\",\
  5125.             key = \"LeftAlt\",\
  5126.             onPress = function() System.newTask(\"Settings\",\"Settings\") end,\
  5127.         },\
  5128.     }\
  5129. \
  5130.     loadShortcuts()\
  5131. \
  5132. end\
  5133. \
  5134. local function loadGUI()\
  5135.     --Initializing GUI components\
  5136.     gui = Interact.Initialize()\
  5137.     mainLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})\
  5138.     quickSettingsLayout = gui.Layout.new({xPos = 1,yPos = h-7,xLength = w,yLength = h, nilClick = true})\
  5139.     mainLayoutTable = {}\
  5140.     quickSettingsLayoutTable = {}\
  5141. end\
  5142. \
  5143. local function InitializeGUI()\
  5144.     loadObjects()\
  5145.     --Main--\
  5146.     mainLayoutTable = {}\
  5147.     mainLayoutTable = gui.loadObjects(Main)\
  5148.     mainLayoutTable.mainBgColor = gui.BackgroundColor.new({color = Settings.bgColor})\
  5149.     \
  5150.     --QuickSettings--\
  5151.     quickSettingsLayoutTable = {}\
  5152.     quickSettingsLayoutTable.Text = {}\
  5153.     quickSettingsLayoutTable = gui.loadObjects(QuickSettings)\
  5154.     quickSettingsLayoutTable.quickSettingsBgColor = gui.BackgroundColor.new({color = MatchingColors[Settings.bgColor][\"quickSettings\"]})\
  5155.     \
  5156.     --Initializing structures--\
  5157.     --Main--\
  5158.     for i,v in pairs(mainLayoutTable.Button) do\
  5159.         mainLayout:addButton(mainLayoutTable.Button[i]:returnData())\
  5160.     end\
  5161.     for i,v in pairs(mainLayoutTable.BetterPaint) do\
  5162.         mainLayout:addBetterPaint(mainLayoutTable.BetterPaint[i]:returnData())\
  5163.     end\
  5164.     mainLayout:addBackgroundColor(mainLayoutTable.mainBgColor:returnData())\
  5165.     \
  5166.     --QuickSettings--\
  5167.     for i,v in pairs(quickSettingsLayoutTable.Button) do\
  5168.         quickSettingsLayout:addButton(quickSettingsLayoutTable.Button[i]:returnData())\
  5169.     end\
  5170.     quickSettingsLayout:addBackgroundColor(quickSettingsLayoutTable.quickSettingsBgColor:returnData())\
  5171.     quickSettingsLayout:addBetterPaint(quickSettingsLayoutTable.BetterPaint.Restart)\
  5172.     quickSettingsLayout:addBetterPaint(quickSettingsLayoutTable.BetterPaint.Shutdown)\
  5173.     quickSettingsLayout:addBetterPaint(quickSettingsLayoutTable.BetterPaint.Settings)\
  5174.     quickSettingsLayout:addKey(quickSettingsLayoutTable.Key.R:returnData())\
  5175.     quickSettingsLayout:addKey(quickSettingsLayoutTable.Key.S:returnData())\
  5176.     quickSettingsLayout:addKey(quickSettingsLayoutTable.Key.LeftAlt:returnData())\
  5177. end\
  5178. \
  5179. local function changeColor(color)\
  5180.     Settings.bgColor = colors[color] or colors.green\
  5181.     local f = fs.open(programPath..\"Settings\",\"w\")\
  5182.     f.write(textutilsserialize(Settings))\
  5183.     f.close()\
  5184.     local buffer = readFile(programPath..\"Settings\")\
  5185.     Settings = textutils.unserialize( buffer )\
  5186.     local buffer = readFile(programPath..\"MatchingColors\")\
  5187.     MatchingColors = textutilsunserialize(buffer)\
  5188.     loadObjects()\
  5189.     InitializeGUI()\
  5190. end\
  5191. \
  5192. --Loading settings--\
  5193. local buffer = readFile(programPath..\"Settings\")\
  5194. Settings = textutils.unserialize( buffer )\
  5195. \
  5196. local buffer = readFile(programPath..\"MatchingColors\")\
  5197. MatchingColors = textutilsunserialize(buffer)\
  5198. \
  5199. \
  5200. \
  5201. loadObjects()\
  5202. loadGUI()\
  5203. InitializeGUI()\
  5204. \
  5205. \
  5206. --Code--\
  5207. while true do\
  5208.     mainLayout:draw(0,scroll)\
  5209.     local result = gui.eventHandler(mainLayout)\
  5210.     if result[1] == \"Button\" then\
  5211.         if result[2] == \"quickSettings\" then\
  5212.             quickSettingsLayout:draw()\
  5213.             local notClose = true\
  5214.             while notClose do\
  5215.                 local answer = gui.eventHandler(quickSettingsLayout)\
  5216.                 if answer[1] == \"Button\" then\
  5217.                     if answer[2] == \"reboot\" then\
  5218.                         os.reboot()\
  5219.                     elseif answer[2] == \"shutdown\" then\
  5220.                         os.shutdown()\
  5221.                     elseif answer[2] == \"Close\" then\
  5222.                         notClose = false\
  5223.                     elseif answer[2] == \"settings\" then\
  5224.                         System.newTask(\"Settings\",\"Settings\")\
  5225.                         notClose = false\
  5226.                     elseif answer[2] == \"Refresh\" then\
  5227.                         local buffer = readFile(programPath..\"Settings\")\
  5228.                         Settings = textutils.unserialize( buffer )\
  5229.                         local buffer = readFile(programPath..\"MatchingColors\")\
  5230.                         MatchingColors = textutilsunserialize(buffer)\
  5231.                         loadObjects()\
  5232.                         InitializeGUI()\
  5233.                         notClose = false\
  5234.                     else\
  5235.                         local buffer = split(answer[2],\"[^:]+\")\
  5236.                         changeColor(buffer[2])\
  5237.                         notClose = false\
  5238.                     end\
  5239.                 elseif answer[1] == \"Nil\" then\
  5240.                     if answer[2] == \"Nil\" then\
  5241.                         notClose = false\
  5242.                     end\
  5243.                 end\
  5244.             end\
  5245.         elseif result[2] == \"windowPlus\" then\
  5246.             scroll = scroll - 51\
  5247.         elseif result[2] == \"windowMinus\" then\
  5248.             scroll = scroll + 51\
  5249.         else\
  5250.             System.newTask(result[2],result[2])\
  5251.         end\
  5252.     end\
  5253. end",
  5254.       Data = {
  5255.         Settings = "{\
  5256.  bgColor = 1024,\
  5257. }",
  5258.         QuickSettings = {
  5259.           [ "restart.ico" ] = "error('This is an image, not a program!')\
  5260. {\
  5261.  {\
  5262.    {\
  5263.      16384,\
  5264.      \"O\",\
  5265.      1,\
  5266.    },\
  5267.    {\
  5268.      16384,\
  5269.      \"O\",\
  5270.      1,\
  5271.    },\
  5272.    {\
  5273.      16384,\
  5274.      \"O\",\
  5275.      1,\
  5276.    },\
  5277.    {\
  5278.      16384,\
  5279.      \"O\",\
  5280.      1,\
  5281.    },\
  5282.    {\
  5283.      16384,\
  5284.      \"O\",\
  5285.      1,\
  5286.    },\
  5287.  },\
  5288.  {\
  5289.    {\
  5290.      16384,\
  5291.      \"O\",\
  5292.      1,\
  5293.    },\
  5294.    {\
  5295.      16384,\
  5296.      \" \",\
  5297.      32,\
  5298.    },\
  5299.    {\
  5300.      16384,\
  5301.      \"O\",\
  5302.      1,\
  5303.    },\
  5304.    {\
  5305.      16384,\
  5306.      \" \",\
  5307.      32,\
  5308.    },\
  5309.    {\
  5310.      16384,\
  5311.      \" \",\
  5312.      32,\
  5313.    },\
  5314.  },\
  5315.  {\
  5316.    {\
  5317.      16384,\
  5318.      \"O\",\
  5319.      1,\
  5320.    },\
  5321.    {\
  5322.      16384,\
  5323.      \" \",\
  5324.      32,\
  5325.    },\
  5326.    {\
  5327.      16384,\
  5328.      \"O\",\
  5329.      1,\
  5330.    },\
  5331.    {\
  5332.      16384,\
  5333.      \"O\",\
  5334.      1,\
  5335.    },\
  5336.    {\
  5337.      16384,\
  5338.      \" \",\
  5339.      32,\
  5340.    },\
  5341.  },\
  5342.  {\
  5343.    {\
  5344.      16384,\
  5345.      \"O\",\
  5346.      1,\
  5347.    },\
  5348.    {\
  5349.      16384,\
  5350.      \"O\",\
  5351.      1,\
  5352.    },\
  5353.    {\
  5354.      16384,\
  5355.      \"O\",\
  5356.      1,\
  5357.    },\
  5358.    {\
  5359.      16384,\
  5360.      \" \",\
  5361.      32,\
  5362.    },\
  5363.    {\
  5364.      16384,\
  5365.      \"O\",\
  5366.      1,\
  5367.    },\
  5368.  },\
  5369.  {\
  5370.    {\
  5371.      16384,\
  5372.      \" \",\
  5373.      1,\
  5374.    },\
  5375.    {\
  5376.      16384,\
  5377.      \" \",\
  5378.      1,\
  5379.    },\
  5380.    {\
  5381.      16384,\
  5382.      \" \",\
  5383.      1,\
  5384.    },\
  5385.    {\
  5386.      16384,\
  5387.      \" \",\
  5388.      1,\
  5389.    },\
  5390.    {\
  5391.      16384,\
  5392.      \" \",\
  5393.      32,\
  5394.    },\
  5395.  },\
  5396.  {\
  5397.    {\
  5398.      16384,\
  5399.      \" \",\
  5400.      1,\
  5401.    },\
  5402.    {\
  5403.      16384,\
  5404.      \" \",\
  5405.      1,\
  5406.    },\
  5407.    {\
  5408.      16384,\
  5409.      \" \",\
  5410.      1,\
  5411.    },\
  5412.    {\
  5413.      16384,\
  5414.      \" \",\
  5415.      1,\
  5416.    },\
  5417.    {\
  5418.      16384,\
  5419.      \" \",\
  5420.      1,\
  5421.    },\
  5422.  },\
  5423.  [ 0 ] = {\
  5424.    {\
  5425.      16384,\
  5426.      \" \",\
  5427.      32,\
  5428.    },\
  5429.    {\
  5430.      16384,\
  5431.      \" \",\
  5432.      32,\
  5433.    },\
  5434.    {\
  5435.      16384,\
  5436.      \" \",\
  5437.      32,\
  5438.    },\
  5439.    {\
  5440.      16384,\
  5441.      \" \",\
  5442.      32,\
  5443.    },\
  5444.    {\
  5445.      16384,\
  5446.      \" \",\
  5447.      32,\
  5448.    },\
  5449.  },\
  5450.  [ 10 ] = {},\
  5451. }",
  5452.           [ "settings.ico" ] = "error('This is an image, not a program!')\
  5453. {\
  5454.  {\
  5455.    {\
  5456.      2,\
  5457.      \"-\",\
  5458.      1,\
  5459.    },\
  5460.    {\
  5461.      2,\
  5462.      \"-\",\
  5463.      1,\
  5464.    },\
  5465.    {\
  5466.      2,\
  5467.      \"-\",\
  5468.      1,\
  5469.    },\
  5470.    {\
  5471.      2,\
  5472.      \"O\",\
  5473.      1,\
  5474.    },\
  5475.    {\
  5476.      2,\
  5477.      \"-\",\
  5478.      1,\
  5479.    },\
  5480.  },\
  5481.  {\
  5482.    {\
  5483.      2,\
  5484.      \"-\",\
  5485.      1,\
  5486.    },\
  5487.    {\
  5488.      2,\
  5489.      \"-\",\
  5490.      1,\
  5491.    },\
  5492.    {\
  5493.      2,\
  5494.      \"O\",\
  5495.      1,\
  5496.    },\
  5497.    {\
  5498.      2,\
  5499.      \"-\",\
  5500.      1,\
  5501.    },\
  5502.    {\
  5503.      2,\
  5504.      \"-\",\
  5505.      1,\
  5506.    },\
  5507.  },\
  5508.  {\
  5509.    {\
  5510.      2,\
  5511.      \"O\",\
  5512.      1,\
  5513.    },\
  5514.    {\
  5515.      2,\
  5516.      \"-\",\
  5517.      1,\
  5518.    },\
  5519.    {\
  5520.      2,\
  5521.      \"-\",\
  5522.      1,\
  5523.    },\
  5524.    {\
  5525.      2,\
  5526.      \"-\",\
  5527.      1,\
  5528.    },\
  5529.    {\
  5530.      2,\
  5531.      \"-\",\
  5532.      1,\
  5533.    },\
  5534.  },\
  5535.  {\
  5536.    {\
  5537.      2,\
  5538.      \"-\",\
  5539.      1,\
  5540.    },\
  5541.    {\
  5542.      2,\
  5543.      \"-\",\
  5544.      1,\
  5545.    },\
  5546.    {\
  5547.      2,\
  5548.      \"-\",\
  5549.      1,\
  5550.    },\
  5551.    {\
  5552.      2,\
  5553.      \"-\",\
  5554.      1,\
  5555.    },\
  5556.    {\
  5557.      2,\
  5558.      \"O\",\
  5559.      1,\
  5560.    },\
  5561.  },\
  5562.  {\
  5563.    {\
  5564.      2,\
  5565.      \"-\",\
  5566.      1,\
  5567.    },\
  5568.    {\
  5569.      2,\
  5570.      \"O\",\
  5571.      1,\
  5572.    },\
  5573.    {\
  5574.      2,\
  5575.      \"-\",\
  5576.      1,\
  5577.    },\
  5578.    {\
  5579.      2,\
  5580.      \"-\",\
  5581.      1,\
  5582.    },\
  5583.    {\
  5584.      2,\
  5585.      \"-\",\
  5586.      1,\
  5587.    },\
  5588.  },\
  5589.  {\
  5590.    {\
  5591.      2,\
  5592.      \" \",\
  5593.      2,\
  5594.    },\
  5595.    {\
  5596.      2,\
  5597.      \" \",\
  5598.      2,\
  5599.    },\
  5600.    {\
  5601.      2,\
  5602.      \" \",\
  5603.      2,\
  5604.    },\
  5605.    {\
  5606.      2,\
  5607.      \" \",\
  5608.      2,\
  5609.    },\
  5610.    {\
  5611.      2,\
  5612.      \" \",\
  5613.      1,\
  5614.    },\
  5615.  },\
  5616.  [ 0 ] = {\
  5617.    {\
  5618.      2,\
  5619.      \" \",\
  5620.      2,\
  5621.    },\
  5622.    {\
  5623.      2,\
  5624.      \" \",\
  5625.      2,\
  5626.    },\
  5627.    {\
  5628.      2,\
  5629.      \" \",\
  5630.      2,\
  5631.    },\
  5632.    {\
  5633.      2,\
  5634.      \" \",\
  5635.      2,\
  5636.    },\
  5637.    {\
  5638.      2,\
  5639.      \" \",\
  5640.      2,\
  5641.    },\
  5642.  },\
  5643. }",
  5644.           [ "shutdown.ico" ] = "error('This is an image, not a program!')\
  5645. {\
  5646.  {\
  5647.    {\
  5648.      8192,\
  5649.      \"O\",\
  5650.      1,\
  5651.    },\
  5652.    {\
  5653.      8192,\
  5654.      \"O\",\
  5655.      1,\
  5656.    },\
  5657.    {\
  5658.      8192,\
  5659.      \"O\",\
  5660.      1,\
  5661.    },\
  5662.    {\
  5663.      8192,\
  5664.      \" \",\
  5665.      8192,\
  5666.    },\
  5667.    {\
  5668.      8192,\
  5669.      \"O\",\
  5670.      1,\
  5671.    },\
  5672.  },\
  5673.  {\
  5674.    {\
  5675.      8192,\
  5676.      \"O\",\
  5677.      1,\
  5678.    },\
  5679.    {\
  5680.      8192,\
  5681.      \" \",\
  5682.      1,\
  5683.    },\
  5684.    {\
  5685.      8192,\
  5686.      \"O\",\
  5687.      1,\
  5688.    },\
  5689.    {\
  5690.      8192,\
  5691.      \" \",\
  5692.      8192,\
  5693.    },\
  5694.    {\
  5695.      8192,\
  5696.      \"O\",\
  5697.      1,\
  5698.    },\
  5699.  },\
  5700.  {\
  5701.    {\
  5702.      8192,\
  5703.      \"O\",\
  5704.      1,\
  5705.    },\
  5706.    {\
  5707.      8192,\
  5708.      \" \",\
  5709.      1,\
  5710.    },\
  5711.    {\
  5712.      8192,\
  5713.      \"O\",\
  5714.      1,\
  5715.    },\
  5716.    {\
  5717.      8192,\
  5718.      \" \",\
  5719.      8192,\
  5720.    },\
  5721.    {\
  5722.      8192,\
  5723.      \"O\",\
  5724.      1,\
  5725.    },\
  5726.  },\
  5727.  {\
  5728.    {\
  5729.      8192,\
  5730.      \"O\",\
  5731.      1,\
  5732.    },\
  5733.    {\
  5734.      8192,\
  5735.      \" \",\
  5736.      1,\
  5737.    },\
  5738.    {\
  5739.      8192,\
  5740.      \"O\",\
  5741.      1,\
  5742.    },\
  5743.    {\
  5744.      8192,\
  5745.      \"O\",\
  5746.      1,\
  5747.    },\
  5748.    {\
  5749.      8192,\
  5750.      \"O\",\
  5751.      1,\
  5752.    },\
  5753.  },\
  5754.  {\
  5755.    {\
  5756.      8192,\
  5757.      \" \",\
  5758.      8192,\
  5759.    },\
  5760.    {\
  5761.      8192,\
  5762.      \" \",\
  5763.      8192,\
  5764.    },\
  5765.    {\
  5766.      8192,\
  5767.      \" \",\
  5768.      8192,\
  5769.    },\
  5770.    {\
  5771.      8192,\
  5772.      \" \",\
  5773.      8192,\
  5774.    },\
  5775.    {\
  5776.      8192,\
  5777.      \" \",\
  5778.      8192,\
  5779.    },\
  5780.  },\
  5781.  {\
  5782.    {\
  5783.      8192,\
  5784.      \" \",\
  5785.      8192,\
  5786.    },\
  5787.    {\
  5788.      8192,\
  5789.      \" \",\
  5790.      8192,\
  5791.    },\
  5792.    {\
  5793.      8192,\
  5794.      \" \",\
  5795.      8192,\
  5796.    },\
  5797.    {\
  5798.      8192,\
  5799.      \" \",\
  5800.      8192,\
  5801.    },\
  5802.    {\
  5803.      8192,\
  5804.      \" \",\
  5805.      8192,\
  5806.    },\
  5807.  },\
  5808.  [ 0 ] = {\
  5809.    {\
  5810.      8192,\
  5811.      \" \",\
  5812.      8192,\
  5813.    },\
  5814.    {\
  5815.      8192,\
  5816.      \" \",\
  5817.      8192,\
  5818.    },\
  5819.    {\
  5820.      8192,\
  5821.      \" \",\
  5822.      8192,\
  5823.    },\
  5824.    {\
  5825.      8192,\
  5826.      \" \",\
  5827.      8192,\
  5828.    },\
  5829.    {\
  5830.      8192,\
  5831.      \" \",\
  5832.      8192,\
  5833.    },\
  5834.  },\
  5835. }",
  5836.         },
  5837.         MatchingColors = "{\
  5838.  [ 8192 ] = {\
  5839.    name = \"green\",\
  5840.    quickSettings = 32,\
  5841.     mainButtons  = 1,\
  5842.  },\
  5843.  [ 4096 ] = {\
  5844.    name = \"brown\",\
  5845.    quickSettings = 2,\
  5846.     mainButtons  = 1,\
  5847.  },\
  5848.  [ 32768 ] = {\
  5849.    name = \"black\",\
  5850.    quickSettings = 128,\
  5851.     mainButtons  = 1,\
  5852.  },\
  5853.  [ 64 ] = {\
  5854.    name = \"pink\",\
  5855.    quickSettings = 16384,\
  5856.     mainButtons  = 1,\
  5857.  },\
  5858.  [ 16 ] = {\
  5859.    name = \"yellow\",\
  5860.    quickSettings = 1,\
  5861.     mainButtons  = 32768,\
  5862.  },\
  5863.  [ 2 ] = {\
  5864.    name = \"orange\",\
  5865.    quickSettings = 4096,\
  5866.     mainButtons  = 1,\
  5867.  },\
  5868.  [ 4 ] = {\
  5869.    name = \"magenta\",\
  5870.    quickSettings = 1024,\
  5871.     mainButtons  = 1,\
  5872.  },\
  5873.  [ 1024 ] = {\
  5874.    name = \"purple\",\
  5875.    quickSettings = 4,\
  5876.     mainButtons  = 1,\
  5877.  },\
  5878.  [ 512 ] = {\
  5879.    name = \"cyan\",\
  5880.    quickSettings = 8,\
  5881.     mainButtons  = 1,\
  5882.  },\
  5883.  [ 16384 ] = {\
  5884.    name = \"red\",\
  5885.    quickSettings = 64,\
  5886.     mainButtons  = 1,\
  5887.  },\
  5888.  [ 1 ] = {\
  5889.    name = \"white\",\
  5890.    quickSettings = 128,\
  5891.     mainButtons  = 32768,\
  5892.  },\
  5893.  [ 8 ] = {\
  5894.    name = \"lightBlue\",\
  5895.    quickSettings = 2048,\
  5896.     mainButtons  = 32768,\
  5897.  },\
  5898.  [ 256 ] = {\
  5899.    name = \"lightGray\",\
  5900.    quickSettings = 1,\
  5901.     mainButtons  = 1,\
  5902.  },\
  5903.  [ 128 ] = {\
  5904.    name = \"gray\",\
  5905.    quickSettings = 256,\
  5906.     mainButtons  = 1,\
  5907.  },\
  5908.  [ 32 ] = {\
  5909.    name = \"lime\",\
  5910.    quickSettings = 8192,\
  5911.     mainButtons  = 1,\
  5912.  },\
  5913.  [ 2048 ] = {\
  5914.    name = \"blue\",\
  5915.    quickSettings = 8,\
  5916.     mainButtons  = 1,\
  5917.  },\
  5918. }",
  5919.         MatchingColorsT = "green 8192\
  5920. brown 4096\
  5921. black 32768\
  5922. pink 64\
  5923. yellow 16\
  5924. orange 2\
  5925. magenta 4\
  5926. purple 1024\
  5927. cyan 512\
  5928. red 16384\
  5929. white 1\
  5930. lightBlue 8\
  5931. lightGray 256\
  5932. gray 128\
  5933. lime 32\
  5934. blue 2048",
  5935.         Shortcuts = "{\
  5936.     {\
  5937.         xPos = 7,\
  5938.         yPos = 3,\
  5939.         path = \"OmniOS/Programs/FileX.app/FileX\",\
  5940.         name = \"FileX\",\
  5941.     },\
  5942.     {\
  5943.         xPos = 2,\
  5944.         yPos = 1,\
  5945.         path = \"OmniOS/Programs/nPaintPro.app/nPaintPro\",\
  5946.         name = \"nPaintPro\"\
  5947.     },\
  5948.     {\
  5949.         xPos = 2,\
  5950.         yPos = 3,\
  5951.         path = \"OmniOS/Programs/Aware.app/Aware\",\
  5952.         name = \"Aware\"\
  5953.     },\
  5954.     {\
  5955.         xPos = 3,\
  5956.         yPos = 1,\
  5957.         path = \"OmniOS/Programs/BetterPaint.app/BetterPaint\",\
  5958.         name = \"BetterPaint\"\
  5959.     },\
  5960.     {\
  5961.         xPos = 2,\
  5962.         yPos = 2,\
  5963.         path = \"OmniOS/Programs/Edit.app/Edit\",\
  5964.         name = \"Edit\"\
  5965.     },\
  5966.     {\
  5967.         xPos = 3,\
  5968.         yPos = 2,\
  5969.         path = \"OmniOS/Programs/Shell.app/Shell\",\
  5970.         name = \"Shell\"\
  5971.     },\
  5972.     {\
  5973.         xPos = 1,\
  5974.         yPos = 1,\
  5975.         path = \"OmniOS/Programs/Calculator.app/Calculator\",\
  5976.         name = \"Calculator\"\
  5977.     },\
  5978. }",
  5979.         Layouts = {
  5980.           [ "Main.layout" ] = "local function loadShortcuts()\
  5981.     local buffer = readFile(programPath..\"Shortcuts\")\
  5982.     local sBuffer = textutilsunserialize(buffer)\
  5983.     local nBuffer = {}\
  5984.     paths = {}\
  5985.     for i,v in pairs(sBuffer) do\
  5986.         nBuffer[v.name] = {\
  5987.             xPos = 2+(6*(v.xPos-1)),\
  5988.             yPos = 1+(5*(v.yPos-1)),\
  5989.             name = v.name,\
  5990.             path = v.path..\".ico\",\
  5991.             yLength = 4,\
  5992.             xLength = 3,\
  5993.             returnValue = v.name,\
  5994.             label = string.sub(v.name,1,5),\
  5995.             labelFg = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  5996.             labelBg = Settings.bgColor,\
  5997.             moveY = true,\
  5998.         }\
  5999.         paths[v.name] = v.path\
  6000.     end\
  6001.     Main.BetterPaint = nBuffer\
  6002. end\
  6003. \
  6004. Main.Button = {\
  6005.         quickSettings = {\
  6006.             name = \"quickSettings\",\
  6007.             label = \"^\",\
  6008.             xPos = 1,\
  6009.             yPos = h,\
  6010.             xLength = 1,\
  6011.             yLength = 1,\
  6012.             xTextPos = 1,\
  6013.             yTextPos = 1,\
  6014.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  6015.             bgColor = Settings.bgColor,\
  6016.             returnValue = \"quickSettings\",\
  6017.         },\
  6018.         windowPlus = {\
  6019.             name = \"windowPlus\",\
  6020.             label = \">\",\
  6021.             xPos = w,\
  6022.             yPos = 1,\
  6023.             xLength = 1,\
  6024.             yLength = 1,\
  6025.             xTextPos = 1,\
  6026.             yTextPos = 1,\
  6027.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  6028.             bgColor = Settings.bgColor,\
  6029.             returnValue = \"windowPlus\",\
  6030.         },\
  6031.         windowMinus = {\
  6032.             name = \"windowMinus\",\
  6033.             label = \"<\",\
  6034.             xPos = 1,\
  6035.             yPos = 1,\
  6036.             xLength = 1,\
  6037.             yLength = 1,\
  6038.             xTextPos = 1,\
  6039.             yTextPos = 1,\
  6040.             fgColor = MatchingColors[Settings.bgColor][\"mainButtons\"],\
  6041.             bgColor = Settings.bgColor,\
  6042.             returnValue = \"windowMinus\",\
  6043.         },\
  6044.     }",
  6045.         },
  6046.       },
  6047.     },
  6048.     [ "Aware.app" ] = {
  6049.       [ "permission.data" ] = "user",
  6050.       [ "Aware.ico" ] = "error('This is an image, not a program!')\
  6051. {\
  6052.  {\
  6053.    {\
  6054.      2,\
  6055.      \"_\",\
  6056.      1,\
  6057.    },\
  6058.    {\
  6059.      2,\
  6060.      \"U\",\
  6061.      1,\
  6062.    },\
  6063.    {\
  6064.      2,\
  6065.      \"_\",\
  6066.      1,\
  6067.    },\
  6068.  },\
  6069.  {\
  6070.    {\
  6071.      2,\
  6072.      \"_\",\
  6073.      1,\
  6074.    },\
  6075.    {\
  6076.      2,\
  6077.      \"U\",\
  6078.      1,\
  6079.    },\
  6080.    {\
  6081.      2,\
  6082.      \"_\",\
  6083.      1,\
  6084.    },\
  6085.  },\
  6086.  {\
  6087.    {\
  6088.      2,\
  6089.      \" \",\
  6090.      1,\
  6091.    },\
  6092.    {\
  6093.      2,\
  6094.      \" \",\
  6095.      1,\
  6096.    },\
  6097.    {\
  6098.      2,\
  6099.      \"/\",\
  6100.      1,\
  6101.    },\
  6102.  },\
  6103.  [ 0 ] = {\
  6104.    {\
  6105.      2,\
  6106.      \" \",\
  6107.      2,\
  6108.    },\
  6109.    {\
  6110.      2,\
  6111.      \" \",\
  6112.      1,\
  6113.    },\
  6114.    {\
  6115.      2,\
  6116.      \"\\\\\",\
  6117.      1,\
  6118.    },\
  6119.  },\
  6120. }",
  6121.       Data = {
  6122.         UselessWords = "what\
  6123. is\
  6124. the\
  6125. it",
  6126.         Commands = "{\
  6127.     shutdown = \"os.shutdown()\",\
  6128.     reboot = \"os.reboot()\",\
  6129.     time = \"print(\\\"The time is \\\"..textutils.formatTime(os.time()))\",\
  6130.     hi = \"redirect(\\\"hello\\\")\",\
  6131.     hello = \"randomElement(wordSet(\\\"Greetings\\\"))\",\
  6132.     exit = \"error(\\\"Thanks for using this thingy thingy!\\\")\",\
  6133.     shutup = \"redirect(\\\"exit\\\")\",\
  6134. }",
  6135.         [ "Aware.layout" ] = "--[[\
  6136.     The Aware Project\
  6137.     by Creator\
  6138.     for TheOS\
  6139. ]]--\
  6140. \
  6141. local layout = {}\
  6142. \
  6143. layout.",
  6144.       },
  6145.       [ "Main.lua" ] = "--[[\
  6146.     The Aware Project\
  6147.     by Creator\
  6148.     for TheOS\
  6149. ]]--\
  6150. --[[\
  6151.     First I am doing the mechanics of the program, afterwards I will do the GUI\
  6152. ]]--\
  6153. \
  6154. --GUI\
  6155. --if _G.Interact == nil then os.loadAPI(\"TheOS/API/Interact\") end\
  6156. --local gui = Interact.Initialize()\
  6157. \
  6158. --Variables--\
  6159. local input = {}\
  6160. local Commands = {}\
  6161. local path = \"TheOS/Programs/Aware.app/\"\
  6162. local UselessWords = {}\
  6163. --Functions--\
  6164. \
  6165. function split(str,sep)\
  6166.     local buffer = {}\
  6167.     for token in str:gmatch(sep) do\
  6168.         buffer[#buffer+1] = token\
  6169.     end\
  6170.     return buffer\
  6171. end\
  6172. \
  6173. function getData()\
  6174.     local var = http.get(\"https://raw.githubusercontent.com/TheOnlyCreator/Aware/master/Test/Test\")\
  6175.     print(var.readAll())\
  6176.     os.pullEvent()\
  6177.     error()\
  6178. end\
  6179. \
  6180. local function readFile(_path)\
  6181.     local file = fs.open(_path,\"r\")\
  6182.     local data = file.readAll()\
  6183.     file.close()\
  6184.     return data\
  6185. end\
  6186. \
  6187. function filter(input)\
  6188.     local buffer = {}\
  6189.     for i,v in pairs(input) do\
  6190.         if UselessWords[v] == true then\
  6191.             buffer[#buffer+1] = i\
  6192.         end\
  6193.     end\
  6194.     for i,v in pairs(buffer) do\
  6195.         input[i] = nil\
  6196.     end\
  6197.     buffer = {}\
  6198.     for i,v in pairs(input) do\
  6199.         local sBuffer = {}\
  6200.         local f = \"\"\
  6201.         for token in string.gmatch(v,\"[%a]+\") do\
  6202.             sBuffer[#sBuffer+1] = token\
  6203.         end\
  6204.         for i,v in pairs(sBuffer) do\
  6205.             f = f..v\
  6206.         end\
  6207.         buffer[#buffer+1] = f\
  6208.     end\
  6209.     return buffer\
  6210. end\
  6211. \
  6212. function redirect(word)\
  6213.     word = string.lower(word)\
  6214.     oneWordCommand(word)\
  6215. end\
  6216. \
  6217. function wordSet(arg)\
  6218.     local fromWeb = http.get(\"https://raw.githubusercontent.com/CodingRevolution/Aware/master/WordSets/\"..arg)\
  6219.     local buffer = fromWeb.readAll()\
  6220.     return split(buffer,\"[^\\n]+\")\
  6221. end\
  6222. \
  6223. function randomElement(input)\
  6224.     local element\
  6225.     local buffer = {}\
  6226.     for i,v in pairs(input) do\
  6227.         buffer[#buffer+1] = i\
  6228.     end\
  6229.     local rnd = buffer[math.random(1,#buffer)]\
  6230.     return input[rnd]\
  6231. end\
  6232. \
  6233. function oneWordCommand(word)\
  6234.     if Commands[word] ~= nil then\
  6235.         local func = loadstring(Commands[word])\
  6236.         setfenv(func, getfenv())\
  6237.         func()\
  6238.     else\
  6239.         local firstLetter = string.sub(word,1,1)\
  6240.         print(firstLetter)\
  6241.         print(word)\
  6242.         local fromWeb = http.get(\"https://raw.githubusercontent.com/CodingRevolution/Aware/master/Actions/\"..firstLetter)\
  6243.         local buffer = fromWeb.readAll()\
  6244.         local tableFromWeb = textutils.unserialize(buffer)\
  6245.         print(tableFromWeb[word])\
  6246.         local func = loadstring(tableFromWeb[word])\
  6247.         setfenv(func, getfenv())\
  6248.         func()\
  6249.     end\
  6250. end\
  6251. \
  6252. function main()\
  6253.     print(\"I am listening...\")\
  6254.     local buffer = read()\
  6255.     input = split(buffer,\"[^%s]+\")\
  6256.     for i,v in pairs(input) do\
  6257.         input[i] = string.lower(v)\
  6258.     end\
  6259.     if #input == 1 then\
  6260.         oneWordCommand(input[1])\
  6261.     else\
  6262.         oneWordCommand(filter(input)[1])\
  6263.     end\
  6264. end\
  6265. \
  6266. \
  6267. --Code--\
  6268. local buffer = readFile(path..\"Commands\")\
  6269. Commands = textutils.unserialize(buffer)\
  6270. \
  6271. local buffer = readFile(path..\"UselessWords\")\
  6272. buffer = split(buffer,\"[^\\n]+\")\
  6273. for i,v in pairs(buffer) do\
  6274.     UselessWords[v] = true\
  6275. end\
  6276. \
  6277. term.setCursorPos(1,1)\
  6278. term.setBackgroundColor(colors.black)\
  6279. term.setTextColor(colors.white)\
  6280. term.clear()\
  6281. \
  6282. while true do\
  6283.     main()\
  6284. end",
  6285.     },
  6286.     [ "Settings.app" ] = {
  6287.       [ "permission.data" ] = "admin",
  6288.       [ "Settings.ico" ] = "error('This is an image, not a program!')\
  6289. {\
  6290.  {\
  6291.    {\
  6292.      2,\
  6293.      \"-\",\
  6294.      1,\
  6295.    },\
  6296.    {\
  6297.      2,\
  6298.      \"-\",\
  6299.      1,\
  6300.    },\
  6301.    {\
  6302.      2,\
  6303.      \"O\",\
  6304.      1,\
  6305.    },\
  6306.  },\
  6307.  {\
  6308.    {\
  6309.      2,\
  6310.      \"-\",\
  6311.      1,\
  6312.    },\
  6313.    {\
  6314.      2,\
  6315.      \"-\",\
  6316.      1,\
  6317.    },\
  6318.    {\
  6319.      2,\
  6320.      \"-\",\
  6321.      1,\
  6322.    },\
  6323.  },\
  6324.  {\
  6325.    {\
  6326.      2,\
  6327.      \"-\",\
  6328.      1,\
  6329.    },\
  6330.    {\
  6331.      2,\
  6332.      \"O\",\
  6333.      1,\
  6334.    },\
  6335.    {\
  6336.      2,\
  6337.      \"-\",\
  6338.      1,\
  6339.    },\
  6340.  },\
  6341.  [ 0 ] = {\
  6342.    {\
  6343.      2,\
  6344.      \"O\",\
  6345.      1,\
  6346.    },\
  6347.    {\
  6348.      2,\
  6349.      \"-\",\
  6350.      1,\
  6351.    },\
  6352.    {\
  6353.      2,\
  6354.      \"-\",\
  6355.      1,\
  6356.    },\
  6357.  },\
  6358. }",
  6359.       [ "Main.lua" ] = "--[[\
  6360.     Settings app\
  6361.     by Creator\
  6362.     for OmniOS\
  6363. ]]--\
  6364. \
  6365. --variables--\
  6366. local w,h = term.getSize()\
  6367. local MainLayoutTable = {}\
  6368. local path = \"OmniOS/Programs/Settings.app/Data/\"\
  6369. \
  6370. --functions--\
  6371. local loadLayout = function(sPath,...)\
  6372.     local func = loadfile(sPath,...)\
  6373.     return func()\
  6374. end\
  6375. \
  6376. local function changeColor(color)\
  6377.     local f = fs.open(\"OmniOS/Programs/Desktop.app/Data/Settings\",\"r\")\
  6378.     local Settings = textutils.unserialize(f.readAll())\
  6379.     print(f.readAll())\
  6380.     f.close()\
  6381.     Settings.bgColor = colors[color] or colors.green\
  6382.     local f = fs.open(\"OmniOS/Programs/Desktop.app/Data/Settings\",\"w\")\
  6383.     f.write(textutils.serialize(Settings))\
  6384.     f.close()\
  6385. end\
  6386. \
  6387. local function split(str,sep)\
  6388.     local buffer = {}\
  6389.     for token in str:gmatch(sep) do\
  6390.         buffer[#buffer+1] = token\
  6391.     end\
  6392.     return buffer\
  6393. end\
  6394. \
  6395. local function drawPrograms()\
  6396.     local tRawPrograms = fs.list(\"OmniOS/Programs\")\
  6397.     local tPrograms = {}\
  6398.     for i,v in pairs(tRawPrograms) do\
  6399.         tPrograms[#tPrograms+1] = string.match(v,\"[^.]+\")\
  6400.     end\
  6401.     local SelectLayout = gui.Layout.new({xPos = 1,\
  6402.         yPos = h-#tPrograms,\
  6403.         xLength = 15,\
  6404.         yLength = #tPrograms})\
  6405.     SelectLayoutTable = gui.loadObjects(loadLayout(path..\"Layouts/Select.layout\",tPrograms))\
  6406.     gui.loadLayout(SelectLayoutTable,SelectLayout)\
  6407.     SelectLayout:addBackgroundColor({color = colors.white})\
  6408.     SelectLayout:draw()\
  6409.     SelectLayoutEvent = gui.eventHandler(SelectLayout)\
  6410. end\
  6411. \
  6412. --Code--\
  6413. os.loadAPI(\"OmniOS/API/Interact\")\
  6414. local gui = Interact.Initialize()\
  6415. \
  6416. --Layouts--\
  6417. local MainLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})\
  6418. local DesktopLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})\
  6419. local SecurityLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})\
  6420. local ShortcutsLayout = gui.Layout.new({xPos = 1,yPos = 1,xLength = w,yLength = h})\
  6421. \
  6422. --MainLayout--\
  6423. local MainLayoutTable = gui.loadObjects(loadLayout(path..\"Layouts/Main.layout\"))\
  6424. gui.loadLayout(MainLayoutTable,MainLayout)\
  6425. MainLayout:addBackgroundColor({color = colors.white})\
  6426. \
  6427. --Desktop Layout--\
  6428. local DesktopLayoutTable = gui.loadObjects(loadLayout(path..\"Layouts/Desktop.layout\"))\
  6429. gui.loadLayout(DesktopLayoutTable,DesktopLayout)\
  6430. DesktopLayout:addBackgroundColor({color = colors.white})\
  6431. \
  6432. --SecurityLayout--\
  6433. local SecurityLayoutTable = gui.loadObjects(loadLayout(path..\"Layouts/Security.layout\"))\
  6434. gui.loadLayout(SecurityLayoutTable,SecurityLayout)\
  6435. SecurityLayout:addBackgroundColor({color = colors.white})\
  6436. \
  6437. --Desktop Shortcuts Layout\
  6438. local ShortcutsLayoutTable = gui.loadObjects(loadLayout(path..\"Layouts/Shortcuts.layout\"))\
  6439. gui.loadLayout(ShortcutsLayoutTable,ShortcutsLayout)\
  6440. ShortcutsLayout:addBackgroundColor({color = colors.white})\
  6441. \
  6442. --Select Layout\
  6443. local SelectLayoutTable = {}\
  6444. \
  6445. \
  6446. while true do\
  6447.     MainLayout:draw()\
  6448.     local MainLayoutEvent = gui.eventHandler(MainLayout)\
  6449.     if MainLayoutEvent[1] == \"Button\" then\
  6450.         if MainLayoutEvent[2] == \"Desktop\" then\
  6451.             local notClose = true\
  6452.             while notClose do\
  6453.                 DesktopLayout:draw()\
  6454.                 DesktopLayoutEvent = gui.eventHandler(DesktopLayout)\
  6455.                 if DesktopLayoutEvent[1] == \"Button\" then\
  6456.                     if DesktopLayoutEvent[2] == \"Done\" then\
  6457.                         notClose = false\
  6458.                     elseif DesktopLayoutEvent[2] == \"Shortcuts\" then\
  6459.                         while true do\
  6460.                             ShortcutsLayout:draw()\
  6461.                             ShortcutsLayoutEvent = gui.eventHandler(ShortcutsLayout)\
  6462.                             if ShortcutsLayoutEvent[1] == \"Button\" then\
  6463.                                 if ShortcutsLayoutEvent[2] == \"Add\" then\
  6464.                                     drawPrograms()\
  6465.                                 elseif ShortcutsLayoutEvent[2] == \"Done\" then\
  6466.                                     break\
  6467.                                 end\
  6468.                             elseif ShortcutsLayoutEvent[1] == \"BeterPaint\" then\
  6469. \
  6470.                             end\
  6471.                         end\
  6472.                         notClose = false\
  6473.                     else\
  6474.                         local buffer = split(DesktopLayoutEvent[2],\"[^:]+\")\
  6475.                         print(DesktopLayoutEvent[2])\
  6476.                         changeColor(buffer[2])\
  6477.                     end\
  6478.                 end\
  6479.             end\
  6480.         elseif MainLayoutEvent[2] == \"Security\" then\
  6481.             local notClose = true\
  6482.             while notClose do\
  6483.                 SecurityLayout:draw()\
  6484.                 SecurityLayoutEvent = gui.eventHandler(SecurityLayout)\
  6485.                 if SecurityLayoutEvent[1] == \"TextBox\" then\
  6486.                     if SecurityLayoutEvent[2] == \"Password\" then\
  6487.                         local newPass = SecurityLayout.TextBox.Password:read()\
  6488.                         local file = fs.open(\"OmniOS/Settings/Users/Admin\",\"w\")\
  6489.                         file.write(Sha.sha256(newPass))\
  6490.                         file.close()\
  6491.                     end\
  6492.                 elseif SecurityLayoutEvent[1] == \"Button\" then\
  6493.                     if SecurityLayoutEvent[2] == \"Done\" then\
  6494.                         notClose = false\
  6495.                     end\
  6496.                 end\
  6497.             end\
  6498.         elseif MainLayoutEvent[2] == \"Close\" then\
  6499.             break\
  6500.         end\
  6501.     end\
  6502. end",
  6503.       Data = {
  6504.         Layouts = {
  6505.           [ "Shortcuts.layout" ] = "local w,h = term.getSize()\
  6506. local programPath = \"OmniOS/Programs/Desktop.app/Data/\"\
  6507. \
  6508. MainTable = {\
  6509.     Button = {\
  6510.         Done = {\
  6511.             name = \"Done\",\
  6512.             label = \"Done\",\
  6513.             xPos = w-3,\
  6514.             yPos = h,\
  6515.             fgColor = colors.white,\
  6516.             bgColor = colors.green,\
  6517.             xLength = 4,\
  6518.             yLength = 1,\
  6519.             returnValue = \"Done\",\
  6520.             xTextPos = 1,\
  6521.             yTextPos = 1,\
  6522.         },\
  6523.         Add = {\
  6524.             name = \"Add\",\
  6525.             label = \"+\",\
  6526.             xPos = 1,\
  6527.             yPos = h,\
  6528.             fgColor = colors.black,\
  6529.             bgColor = colors.white,\
  6530.             xLength = 11,\
  6531.             yLength = 3,\
  6532.             returnValue = \"Add\",\
  6533.             xTextPos = 1,\
  6534.             yTextPos = 1,\
  6535.         },\
  6536.     },\
  6537. }\
  6538. \
  6539. local function readFile(_path)\
  6540.     local file = fs.open(_path,\"r\")\
  6541.     local data = file.readAll()\
  6542.     file.close()\
  6543.     return data\
  6544. end\
  6545. \
  6546. local function loadShortcuts()\
  6547.     local buffer = readFile(programPath..\"Shortcuts\")\
  6548.     local sBuffer = textutils.unserialize(buffer)\
  6549.     local nBuffer = {}\
  6550.     paths = {}\
  6551.     for i,v in pairs(sBuffer) do\
  6552.         nBuffer[v.name] = {\
  6553.             xPos = 2+(6*(v.xPos-1)),\
  6554.             yPos = 1+(5*(v.yPos-1)),\
  6555.             name = v.name,\
  6556.             path = v.path..\".ico\",\
  6557.             yLength = 4,\
  6558.             xLength = 3,\
  6559.             returnValue = v.name,\
  6560.             label = string.sub(v.name,1,5),\
  6561.             labelFg = colors.black,\
  6562.             labelBg = colors.white,\
  6563.             moveY = true,\
  6564.         }\
  6565.         paths[v.name] = v.path\
  6566.     end\
  6567.     MainTable.BetterPaint = nBuffer\
  6568. end\
  6569. \
  6570. loadShortcuts()\
  6571. \
  6572. return MainTable",
  6573.           [ "Select.layout" ] = "local tArgs = {...}\
  6574. local w,h = term.getSize()\
  6575. local tReturnTable = {\
  6576.     Button = {},\
  6577.     Text = {\
  6578.         Title = {\
  6579.             name = \"Title\",\
  6580.             text = \"Select\",\
  6581.             xPos = 1,\
  6582.             yPos = 1,\
  6583.             bgColor = colors.gray,\
  6584.             fgColor = colors.white,\
  6585.         },\
  6586.     }\
  6587. }",
  6588.           [ "Desktop.layout" ] = "local w,h = term.getSize()\
  6589. MainTable = {\
  6590.     ColorField = {\
  6591.         Top = {\
  6592.             name = \"Top\",\
  6593.             xPos = 1,\
  6594.             yPos = 1,\
  6595.             xLength = w,\
  6596.             yLength = 3,\
  6597.             color = colors.orange,\
  6598.             \
  6599.         },\
  6600.     },\
  6601.     Button = {\
  6602.         Done = {\
  6603.             name = \"Done\",\
  6604.             label = \"Done\",\
  6605.             xPos = w-6,\
  6606.             yPos = h-3,\
  6607.             fgColor = colors.white,\
  6608.             bgColor = colors.green,\
  6609.             xLength = 6,\
  6610.             yLength = 3,\
  6611.             returnValue = \"Done\",\
  6612.             xTextPos = 2,\
  6613.             yTextPos = 2,\
  6614.         },\
  6615.         Shortcuts = {\
  6616.             name = \"Shortcuts\",\
  6617.             label = \"Shortcuts\",\
  6618.             xPos = 3,\
  6619.             yPos = h-3,\
  6620.             fgColor = colors.white,\
  6621.             bgColor = colors.cyan,\
  6622.             xLength = 11,\
  6623.             yLength = 3,\
  6624.             returnValue = \"Shortcuts\",\
  6625.             xTextPos = 2,\
  6626.             yTextPos = 2,\
  6627.         },\
  6628.             Green = {\
  6629.             name = \"Green\",\
  6630.             label = \" \",\
  6631.             xPos = w-3,\
  6632.             yPos = 5,\
  6633.             xLength = 1,\
  6634.             yLength = 1,\
  6635.             xTextPos = 1,\
  6636.             yTextPos = 1,\
  6637.             fgColor = 1,\
  6638.             bgColor = colors.green,\
  6639.             returnValue = \"color:green\",\
  6640.         },\
  6641.         Lime = {\
  6642.             name = \"Lime\",\
  6643.             label = \" \",\
  6644.             xPos = w-4,\
  6645.             yPos = 5,\
  6646.             xLength = 1,\
  6647.             yLength = 1,\
  6648.             xTextPos = 1,\
  6649.             yTextPos = 1,\
  6650.             fgColor = 1,\
  6651.             bgColor = colors.lime,\
  6652.             returnValue = \"color:lime\",\
  6653.         },\
  6654.         Brown = {\
  6655.             name = \"Brown\",\
  6656.             label = \" \",\
  6657.             xPos = w-5,\
  6658.             yPos = 5,\
  6659.             xLength = 1,\
  6660.             yLength = 1,\
  6661.             xTextPos = 1,\
  6662.             yTextPos = 1,\
  6663.             fgColor = 1,\
  6664.             bgColor = colors.brown,\
  6665.             returnValue = \"color:brown\",\
  6666.         },\
  6667.         Purple = {\
  6668.             name = \"Purple\",\
  6669.             label = \" \",\
  6670.             xPos = w-6,\
  6671.             yPos = 5,\
  6672.             xLength = 1,\
  6673.             yLength = 1,\
  6674.             xTextPos = 1,\
  6675.             yTextPos = 1,\
  6676.             fgColor = 1,\
  6677.             bgColor = colors.purple,\
  6678.             returnValue = \"color:purple\",\
  6679.         },\
  6680.         Blue = {\
  6681.             name = \"Blue\",\
  6682.             label = \" \",\
  6683.             xPos = w-7,\
  6684.             yPos = 5,\
  6685.             xLength = 1,\
  6686.             yLength = 1,\
  6687.             xTextPos = 1,\
  6688.             yTextPos = 1,\
  6689.             fgColor = 1,\
  6690.             bgColor = colors.blue,\
  6691.             returnValue = \"color:blue\",\
  6692.         },\
  6693.         lightBlue = {\
  6694.             name = \"lightBlue\",\
  6695.             label = \" \",\
  6696.             xPos = w-8,\
  6697.             yPos = 5,\
  6698.             xLength = 1,\
  6699.             yLength = 1,\
  6700.             xTextPos = 1,\
  6701.             yTextPos = 1,\
  6702.             fgColor = 1,\
  6703.             bgColor = colors.lightBlue,\
  6704.             returnValue = \"color:lightBlue\",\
  6705.         },\
  6706.         Yellow = {\
  6707.             name = \"Yellow\",\
  6708.             label = \" \",\
  6709.             xPos = w-9,\
  6710.             yPos = 5,\
  6711.             xLength = 1,\
  6712.             yLength = 1,\
  6713.             xTextPos = 1,\
  6714.             yTextPos = 1,\
  6715.             fgColor = 1,\
  6716.             bgColor = colors.yellow,\
  6717.             returnValue = \"color:yellow\",\
  6718.         },\
  6719.         Cyan = {\
  6720.             name = \"Cyan\",\
  6721.             label = \" \",\
  6722.             xPos = w-10,\
  6723.             yPos = 5,\
  6724.             xLength = 1,\
  6725.             yLength = 1,\
  6726.             xTextPos = 1,\
  6727.             yTextPos = 1,\
  6728.             fgColor = 1,\
  6729.             bgColor = colors.cyan,\
  6730.             returnValue = \"color:cyan\",\
  6731.         },\
  6732.         Orange = {\
  6733.             name = \"Orange\",\
  6734.             label = \" \",\
  6735.             xPos = w-11,\
  6736.             yPos = 5,\
  6737.             xLength = 1,\
  6738.             yLength = 1,\
  6739.             xTextPos = 1,\
  6740.             yTextPos = 1,\
  6741.             fgColor = 1,\
  6742.             bgColor = colors.orange,\
  6743.             returnValue = \"color:orange\",\
  6744.         },\
  6745.         Pink = {\
  6746.             name = \"Pink\",\
  6747.             label = \" \",\
  6748.             xPos = w-12,\
  6749.             yPos = 5,\
  6750.             xLength = 1,\
  6751.             yLength = 1,\
  6752.             xTextPos = 1,\
  6753.             yTextPos = 1,\
  6754.             fgColor = 1,\
  6755.             bgColor = colors.pink,\
  6756.             returnValue = \"color:pink\",\
  6757.         },\
  6758.         Red = {\
  6759.             name = \"Red\",\
  6760.             label = \" \",\
  6761.             xPos = w-13,\
  6762.             yPos = 5,\
  6763.             xLength = 1,\
  6764.             yLength = 1,\
  6765.             xTextPos = 1,\
  6766.             yTextPos = 1,\
  6767.             fgColor = 1,\
  6768.             bgColor = colors.red,\
  6769.             returnValue = \"color:red\",\
  6770.         },\
  6771.         Magenta = {\
  6772.             name = \"Magenta\",\
  6773.             label = \" \",\
  6774.             xPos = w-14,\
  6775.             yPos = 5,\
  6776.             xLength = 1,\
  6777.             yLength = 1,\
  6778.             xTextPos = 1,\
  6779.             yTextPos = 1,\
  6780.             fgColor = 1,\
  6781.             bgColor = colors.magenta,\
  6782.             returnValue = \"color:magenta\",\
  6783.         },\
  6784.         White = {\
  6785.             name = \"White\",\
  6786.             label = \" \",\
  6787.             xPos = w-15,\
  6788.             yPos = 5,\
  6789.             xLength = 1,\
  6790.             yLength = 1,\
  6791.             xTextPos = 1,\
  6792.             yTextPos = 1,\
  6793.             fgColor = 1,\
  6794.             bgColor = colors.white,\
  6795.             returnValue = \"color:white\",\
  6796.         },\
  6797.         lightGray = {\
  6798.             name = \"lightGray\",\
  6799.             label = \" \",\
  6800.             xPos = w-16,\
  6801.             yPos = 5,\
  6802.             xLength = 1,\
  6803.             yLength = 1,\
  6804.             xTextPos = 1,\
  6805.             yTextPos = 1,\
  6806.             fgColor = 1,\
  6807.             bgColor = colors.lightGray,\
  6808.             returnValue = \"color:lightGray\",\
  6809.         },\
  6810.         Black = {\
  6811.             name = \"Black\",\
  6812.             label = \" \",\
  6813.             xPos = w-17,\
  6814.             yPos = 5,\
  6815.             xLength = 1,\
  6816.             yLength = 1,\
  6817.             xTextPos = 1,\
  6818.             yTextPos = 1,\
  6819.             fgColor = 1,\
  6820.             bgColor = colors.black,\
  6821.             returnValue = \"color:black\",\
  6822.         },\
  6823.         Gray = {\
  6824.             name = \"Gray\",\
  6825.             label = \" \",\
  6826.             xPos = w-18,\
  6827.             yPos = 5,\
  6828.             xLength = 1,\
  6829.             yLength = 1,\
  6830.             xTextPos = 1,\
  6831.             yTextPos = 1,\
  6832.             fgColor = 1,\
  6833.             bgColor = colors.gray,\
  6834.             returnValue = \"color:gray\",\
  6835.         },\
  6836.     },\
  6837.     Text = {\
  6838.         Color = {\
  6839.             name = \"Color\",\
  6840.             text = \"Desktop Color\",\
  6841.             xPos = 3,\
  6842.             yPos = 5,\
  6843.             bgColor = colors.white,\
  6844.             fgColor = colors.black,\
  6845.         },\
  6846.         Title = {\
  6847.             name = \"Title\",\
  6848.             text = \"Settings/Desktop\",\
  6849.             xPos = 2,\
  6850.             yPos = 2,\
  6851.             fgColor = colors.white,\
  6852.             bgColor = colors.orange,\
  6853.         },\
  6854.     },\
  6855. }\
  6856. return MainTable",
  6857.           [ "Security.layout" ] = "local w,h = term.getSize()\
  6858. MainTable = {\
  6859.     ColorField = {\
  6860.         Top = {\
  6861.             name = \"Top\",\
  6862.             xPos = 1,\
  6863.             yPos = 1,\
  6864.             xLength = w,\
  6865.             yLength = 3,\
  6866.             color = colors.orange,\
  6867.             \
  6868.         },\
  6869.     },\
  6870.     Text = {\
  6871.         Title = {\
  6872.             name = \"Title\",\
  6873.             text = \"Settings/Security\",\
  6874.             xPos = 2,\
  6875.             yPos = 2,\
  6876.             fgColor = colors.white,\
  6877.             bgColor = colors.orange,\
  6878.         },\
  6879.         Password = {\
  6880.             name = \"Password\",\
  6881.             text = \"Password\",\
  6882.             xPos = 2,\
  6883.             yPos = 5,\
  6884.             fgColor = colors.black,\
  6885.             bgColor = colors.white,\
  6886.         },\
  6887.     },\
  6888.     TextBox = {\
  6889.         Password = {\
  6890.             name = \"Password\",\
  6891.             helpText = \"Change password...\",\
  6892.             xPos = 20,\
  6893.             yPos = 5,\
  6894.             xLength = 30,\
  6895.             yLength = 1,\
  6896.             bgColor = colors.lightGray,\
  6897.             fgColor = colors.black,\
  6898.             helpFgColor = colors.gray,\
  6899.             charLimit = 4,\
  6900.             confidential = true,\
  6901.             returnValue = \"Password\",\
  6902.         }\
  6903.     },\
  6904.     Button = {\
  6905.         Done = {\
  6906.             name = \"Done\",\
  6907.             label = \"Done\",\
  6908.             xPos = w-6,\
  6909.             yPos = h-3,\
  6910.             fgColor = colors.white,\
  6911.             bgColor = colors.green,\
  6912.             xLength = 6,\
  6913.             yLength = 3,\
  6914.             returnValue = \"Done\",\
  6915.             xTextPos = 2,\
  6916.             yTextPos = 2,\
  6917.         },\
  6918.     },\
  6919. }\
  6920. return MainTable",
  6921.           [ "Main.layout" ] = "local w,h = term.getSize()\
  6922. MainTable = {\
  6923.     ColorField = {\
  6924.         Top = {\
  6925.             name = \"Top\",\
  6926.             xPos = 1,\
  6927.             yPos = 1,\
  6928.             xLength = w,\
  6929.             yLength = 3,\
  6930.             color = colors.orange,\
  6931.         },\
  6932.     },\
  6933.     Button = {\
  6934.         Desktop = {\
  6935.             name = \"Desktop\",\
  6936.             label = \"Desktop\",\
  6937.             xPos = 2,\
  6938.             yPos = 5,\
  6939.             fgColor = colors.white,\
  6940.             bgColor = colors.blue,\
  6941.             xLength = 11,\
  6942.             yLength = 3,\
  6943.             returnValue = \"Desktop\",\
  6944.             xTextPos = 2,\
  6945.             yTextPos = 2,\
  6946.         },\
  6947.         Security = {\
  6948.             name = \"Security\",\
  6949.             label = \"Security\",\
  6950.             xPos = 2,\
  6951.             yPos = 9,\
  6952.             fgColor = colors.white,\
  6953.             bgColor = colors.green,\
  6954.             xLength = 11,\
  6955.             yLength = 3,\
  6956.             returnValue = \"Security\",\
  6957.             xTextPos = 2,\
  6958.             yTextPos = 2,\
  6959.         },\
  6960.         Close = {\
  6961.             name = \"Close\",\
  6962.             label = \"x\",\
  6963.             xPos = w-2,\
  6964.             yPos = 2,\
  6965.             fgColor = colors.white,\
  6966.             bgColor = colors.orange,\
  6967.             xLength = 1,\
  6968.             yLength = 1,\
  6969.             returnValue = \"Close\",\
  6970.             xTextPos = 1,\
  6971.             yTextPos = 1,\
  6972.         },\
  6973.     },\
  6974.     Text = {\
  6975.         Title = {\
  6976.             name = \"Title\",\
  6977.             text = \"TheOS Settings\",\
  6978.             xPos = 2,\
  6979.             yPos = 2,\
  6980.             fgColor = colors.white,\
  6981.             bgColor = colors.orange,\
  6982.         },\
  6983.     },\
  6984. }\
  6985. return MainTable",
  6986.         },
  6987.       },
  6988.     },
  6989.     [ "Test.app" ] = {
  6990.       [ "Main.lua" ] = "local tArgs = {...}\
  6991. while true do\
  6992. term.setBackgroundColor(colors.black)\
  6993. term.setTextColor(colors.white)\
  6994. term.clear()\
  6995. term.setCursorPos(1,1)\
  6996. print(\"Protocol is initializng...\")\
  6997. if System then \
  6998.     print(\"System API has been loaded..\")\
  6999.     print(\"The available methods are:\")\
  7000.     for i,v in pairs(System) do\
  7001.         print(\" - \"..i)\
  7002.     end\
  7003.     print(\"Done\")\
  7004. else\
  7005.     print(\"System API has not been loaded..\")\
  7006. end\
  7007. print(tArgs[1])\
  7008. os.pullEvent()\
  7009. System.newTask(\"Edit\",\"Edit\",\"TheOS_15w14b\")\
  7010. end",
  7011.     },
  7012.     [ "Shell.app" ] = {
  7013.       [ "Main.lua" ] = "--[[\
  7014.    Modified version of Shell\
  7015. ]]--\
  7016. \
  7017. local multishell = multishell\
  7018. local parentShell = shell\
  7019. local parentTerm = term.current()\
  7020. \
  7021. if multishell then\
  7022.    multishell.setTitle( multishell.getCurrent(), \"shell\" )\
  7023. end\
  7024. \
  7025. local bExit = false\
  7026. local sDir = (parentShell and parentShell.dir()) or \"\"\
  7027. local sPath = (parentShell and parentShell.path()) or \".:/rom/programs\"\
  7028. local tAliases = (parentShell and parentShell.aliases()) or {}\
  7029. local tProgramStack = {}\
  7030. \
  7031. local shell = {}\
  7032. local tEnv = {\
  7033.     [ \"shell\" ] = shell,\
  7034.     [ \"multishell\" ] = multishell,\
  7035. }\
  7036. \
  7037. -- Colours\
  7038. local promptColour, textColour, bgColour\
  7039. if term.isColour() then\
  7040.     promptColour = colours.yellow\
  7041.     textColour = colours.white\
  7042.     bgColour = colours.black\
  7043. else\
  7044.     promptColour = colours.white\
  7045.     textColour = colours.white\
  7046.     bgColour = colours.black\
  7047. end\
  7048. \
  7049. term.setBackgroundColor(bgColour)\
  7050. term.clear()\
  7051. \
  7052. local function run( _sCommand, ... )\
  7053.     local sPath = shell.resolveProgram( _sCommand )\
  7054.     if sPath ~= nil then\
  7055.         tProgramStack[#tProgramStack + 1] = sPath\
  7056.         if multishell then\
  7057.             multishell.setTitle( multishell.getCurrent(), fs.getName( sPath ) )\
  7058.         end\
  7059.         local result = os.run( tEnv, sPath, ... )\
  7060.         tProgramStack[#tProgramStack] = nil\
  7061.         if multishell then\
  7062.             if #tProgramStack > 0 then\
  7063.                 multishell.setTitle( multishell.getCurrent(), fs.getName( tProgramStack[#tProgramStack] ) )\
  7064.             else\
  7065.                 multishell.setTitle( multishell.getCurrent(), \"shell\" )\
  7066.             end\
  7067.         end\
  7068.         return result\
  7069.     else\
  7070.         printError( \"No such program\" )\
  7071.         return false\
  7072.    end\
  7073. end\
  7074. \
  7075. local function tokenise( ... )\
  7076.    local sLine = table.concat( { ... }, \" \" )\
  7077.     local tWords = {}\
  7078.    local bQuoted = false\
  7079.    for match in string.gmatch( sLine .. \"\\\"\", \"(.-)\\\"\" ) do\
  7080.        if bQuoted then\
  7081.            table.insert( tWords, match )\
  7082.        else\
  7083.            for m in string.gmatch( match, \"[^ \\t]+\" ) do\
  7084.                table.insert( tWords, m )\
  7085.            end\
  7086.        end\
  7087.        bQuoted = not bQuoted\
  7088.    end\
  7089.    return tWords\
  7090. end\
  7091. \
  7092. -- Install shell API\
  7093. function shell.run( ... )\
  7094.     local tWords = tokenise( ... )\
  7095.     local sCommand = tWords[1]\
  7096.     if sCommand then\
  7097.         return run( sCommand, unpack( tWords, 2 ) )\
  7098.     end\
  7099.     return false\
  7100. end\
  7101. \
  7102. function shell.exit()\
  7103.    bExit = true\
  7104. end\
  7105. \
  7106. function shell.dir()\
  7107.     return sDir\
  7108. end\
  7109. \
  7110. function shell.setDir( _sDir )\
  7111.     sDir = _sDir\
  7112. end\
  7113. \
  7114. function shell.path()\
  7115.     return sPath\
  7116. end\
  7117. \
  7118. function shell.setPath( _sPath )\
  7119.     sPath = _sPath\
  7120. end\
  7121. \
  7122. function shell.resolve( _sPath )\
  7123.     local sStartChar = string.sub( _sPath, 1, 1 )\
  7124.     if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
  7125.         return fs.combine( \"\", _sPath )\
  7126.     else\
  7127.         return fs.combine( sDir, _sPath )\
  7128.     end\
  7129. end\
  7130. \
  7131. function shell.resolveProgram( _sCommand )\
  7132.     -- Substitute aliases firsts\
  7133.     if tAliases[ _sCommand ] ~= nil then\
  7134.         _sCommand = tAliases[ _sCommand ]\
  7135.     end\
  7136. \
  7137.    -- If the path is a global path, use it directly\
  7138.    local sStartChar = string.sub( _sCommand, 1, 1 )\
  7139.    if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
  7140.         local sPath = fs.combine( \"\", _sCommand )\
  7141.         if fs.exists( sPath ) and not fs.isDir( sPath ) then\
  7142.             return sPath\
  7143.         end\
  7144.         return nil\
  7145.    end\
  7146.    \
  7147.     -- Otherwise, look on the path variable\
  7148.    for sPath in string.gmatch(sPath, \"[^:]+\") do\
  7149.         sPath = fs.combine( shell.resolve( sPath ), _sCommand )\
  7150.         if fs.exists( sPath ) and not fs.isDir( sPath ) then\
  7151.             return sPath\
  7152.         end\
  7153.    end\
  7154.     \
  7155.     -- Not found\
  7156.     return nil\
  7157. end\
  7158. \
  7159. function shell.programs( _bIncludeHidden )\
  7160.     local tItems = {}\
  7161.     \
  7162.     -- Add programs from the path\
  7163.    for sPath in string.gmatch(sPath, \"[^:]+\") do\
  7164.         sPath = shell.resolve( sPath )\
  7165.         if fs.isDir( sPath ) then\
  7166.             local tList = fs.list( sPath )\
  7167.             for n,sFile in pairs( tList ) do\
  7168.                 if not fs.isDir( fs.combine( sPath, sFile ) ) and\
  7169.                    (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= \".\") then\
  7170.                     tItems[ sFile ] = true\
  7171.                 end\
  7172.             end\
  7173.         end\
  7174.     end \
  7175. \
  7176.     -- Sort and return\
  7177.     local tItemList = {}\
  7178.     for sItem, b in pairs( tItems ) do\
  7179.         table.insert( tItemList, sItem )\
  7180.     end\
  7181.     table.sort( tItemList )\
  7182.     return tItemList\
  7183. end\
  7184. \
  7185. if multishell then\
  7186.    function shell.openTab( ... )\
  7187.        local tWords = tokenise( ... )\
  7188.        local sCommand = tWords[1]\
  7189.        if sCommand then\
  7190.             local sPath = shell.resolveProgram( sCommand )\
  7191.             if sPath == \"rom/programs/shell\" then\
  7192.                return multishell.launch( tEnv, sPath, unpack( tWords, 2 ) )\
  7193.            elseif sPath ~= nil then\
  7194.                return multishell.launch( tEnv, \"rom/programs/shell\", sPath, unpack( tWords, 2 ) )\
  7195.            else\
  7196.                printError( \"No such program\" )\
  7197.            end\
  7198.        end\
  7199.    end\
  7200. \
  7201.    function shell.switchTab( nID )\
  7202.        multishell.setFocus( nID )\
  7203.    end\
  7204. end\
  7205. \
  7206. local tArgs = { ... }\
  7207. if #tArgs > 0 then\
  7208.    -- \"shell x y z\"\
  7209.    -- Run the program specified on the commandline\
  7210.    shell.run( ... )\
  7211. \
  7212. else\
  7213.    -- \"shell\"\
  7214.    -- Print the header\
  7215.    term.setBackgroundColor( bgColour )\
  7216.    term.setTextColour( promptColour )\
  7217.    print( os.version() )\
  7218.    term.setTextColour( textColour )\
  7219. \
  7220.    -- Read commands and execute them\
  7221.    local tCommandHistory = {}\
  7222.    while not bExit do\
  7223.        term.redirect( parentTerm )\
  7224.        term.setBackgroundColor( bgColour )\
  7225.        term.setTextColour( promptColour )\
  7226.        write( shell.dir() .. \"> \" )\
  7227.        term.setTextColour( textColour )\
  7228. \
  7229.        local sLine = read( nil, tCommandHistory )\
  7230.        table.insert( tCommandHistory, sLine )\
  7231.        shell.run( sLine )\
  7232.    end\
  7233. end",
  7234.       [ "permission.data" ] = "user",
  7235.       [ "Shell.ico" ] = "error('This is an image, not a program!')\
  7236. {\
  7237.  {\
  7238.    {\
  7239.      32768,\
  7240.      \"_\",\
  7241.      1,\
  7242.    },\
  7243.    {\
  7244.      32768,\
  7245.      \" \",\
  7246.      128,\
  7247.    },\
  7248.    {\
  7249.      32768,\
  7250.      \" \",\
  7251.      128,\
  7252.    },\
  7253.  },\
  7254.  {\
  7255.    {\
  7256.      32768,\
  7257.      \" \",\
  7258.      16,\
  7259.    },\
  7260.    {\
  7261.      32768,\
  7262.      \" \",\
  7263.      128,\
  7264.    },\
  7265.    {\
  7266.      32768,\
  7267.      \" \",\
  7268.      128,\
  7269.    },\
  7270.  },\
  7271.  {\
  7272.    {\
  7273.      32768,\
  7274.      \" \",\
  7275.      16,\
  7276.    },\
  7277.    {\
  7278.      32768,\
  7279.      \" \",\
  7280.      128,\
  7281.    },\
  7282.    {\
  7283.      32768,\
  7284.      \" \",\
  7285.      128,\
  7286.    },\
  7287.  },\
  7288.  [ 0 ] = {\
  7289.    {\
  7290.      32768,\
  7291.      \">\",\
  7292.      16,\
  7293.    },\
  7294.    {\
  7295.      32768,\
  7296.      \" \",\
  7297.      128,\
  7298.    },\
  7299.    {\
  7300.      32768,\
  7301.      \" \",\
  7302.      128,\
  7303.    },\
  7304.  },\
  7305. }",
  7306.     },
  7307.     [ "FileX.app" ] = {
  7308.       [ "permission.data" ] = "userTest",
  7309.       [ "Main.lua" ] = "--------------FileX v1.2-------------\
  7310. ---------------Program---------------\
  7311. --------------by Creator-------------\
  7312. \
  7313. --Variables--\
  7314. term.current(term.native())\
  7315. local copyPath = \"\"\
  7316. local copyHelp = \"\"\
  7317. local textutilsserialize = textutils.serialize\
  7318. local textutilsunserialize = textutils.unserialize\
  7319. local w, h = term.getSize()\
  7320. local folderMenu = {\
  7321.     term.current(),\
  7322.     16,\
  7323.     \"Folder Options\",\
  7324.     colors.white,\
  7325.     colors.blue,\
  7326.     colors.black,\
  7327.     colors.lightGray,\
  7328.     {\
  7329.         {\
  7330.             \"Open\",\
  7331.             \"open\",\
  7332.         },\
  7333.         {\
  7334.             \"Delete\",\
  7335.             \"delete\",\
  7336.         },\
  7337.         {\
  7338.             \"Rename\",\
  7339.             \"rename\",\
  7340.         },\
  7341.         {\
  7342.             \"Move\",\
  7343.             \"move\",\
  7344.         },\
  7345.         {\
  7346.             \"Copy\",\
  7347.             \"copy\",\
  7348.         },\
  7349.         {\
  7350.             \"Cancel\",\
  7351.             \"cancel\",\
  7352.         },\
  7353.     },\
  7354. }\
  7355. local fileMenu = {\
  7356.     term.current(),\
  7357.     16,\
  7358.     \"File Options\",\
  7359.     colors.white,\
  7360.     colors.blue,\
  7361.     colors.black,\
  7362.     colors.lightGray,\
  7363.     {\
  7364.         {\
  7365.             \"Open\",\
  7366.             \"open\",\
  7367.         },\
  7368.         {\
  7369.             \"Delete\",\
  7370.             \"delete\",\
  7371.         },\
  7372.         {\
  7373.             \"Rename\",\
  7374.             \"rename\",\
  7375.         },\
  7376.         {\
  7377.             \"Move\",\
  7378.             \"move\",\
  7379.         },\
  7380.         {\
  7381.             \"Cancel\",\
  7382.             \"cancel\",\
  7383.         },\
  7384.         {\
  7385.             \"Run\",\
  7386.             \"run\",\
  7387.         },\
  7388.         {\
  7389.             \"Copy\",\
  7390.             \"copy\",\
  7391.         },\
  7392.         {\
  7393.             \"Open with\",\
  7394.             \"openWith\",\
  7395.         },\
  7396.     },\
  7397. }\
  7398. local nilMenu = {\
  7399.     term.current(),\
  7400.     16,\
  7401.     \"Options\",\
  7402.     colors.white,\
  7403.     colors.blue,\
  7404.     colors.black,\
  7405.     colors.lightGray,\
  7406.     {\
  7407.         {\
  7408.             \"Make a folder\",\
  7409.             \"makeFolder\",\
  7410.         },\
  7411.         {\
  7412.             \"Make a file\",\
  7413.             \"makeFile\",\
  7414.         },\
  7415.         {\
  7416.             \"Cancel\",\
  7417.             \"cancel\",\
  7418.         },\
  7419.     },\
  7420. }\
  7421. local newFolderWindow = {\
  7422.     term.current(),\
  7423.     math.floor((w-32)/2),\
  7424.     math.floor((h-8)/2),\
  7425.     32,\
  7426.     8,\
  7427.     true,\
  7428.     \"New folder name\",\
  7429.     colors.white,\
  7430.     colors.blue,\
  7431.     \"Write the name of%the new folder.\",\
  7432.     colors.black,\
  7433.     colors.lightGray,\
  7434.     colors.white,\
  7435.     colors.black,\
  7436. }\
  7437. local newFileWindow = {\
  7438.     term.current(),\
  7439.     math.floor((w-32)/2),\
  7440.     math.floor((h-8)/2),\
  7441.     32,\
  7442.     8,\
  7443.     true,\
  7444.     \"New file name\",\
  7445.     colors.white,\
  7446.     colors.blue,\
  7447.     \"Write the name of%the new file.\",\
  7448.     colors.black,\
  7449.     colors.lightGray,\
  7450.     colors.white,\
  7451.     colors.black,\
  7452. }\
  7453. local upFileWindow = {\
  7454.     term.current(),\
  7455.     math.floor((w-32)/2),\
  7456.     math.floor((h-8)/2),\
  7457.     32,\
  7458.     8,\
  7459.     true,\
  7460.     \"File path\",\
  7461.     colors.white,\
  7462.     colors.blue,\
  7463.     \"Write the path of%the file.\",\
  7464.     colors.black,\
  7465.     colors.lightGray,\
  7466.     colors.white,\
  7467.     colors.black,\
  7468. }\
  7469. local moveFolderWindow = {\
  7470.     term.current(),\
  7471.     math.floor((w-32)/2),\
  7472.     math.floor((h-8)/2),\
  7473.     32,\
  7474.     8,\
  7475.     true,\
  7476.     \"New folder path\",\
  7477.     colors.white,\
  7478.     colors.blue,\
  7479.     \"Write the name of%the new folder path.\",\
  7480.     colors.black,\
  7481.     colors.lightGray,\
  7482.     colors.white,\
  7483.     colors.black,\
  7484. }\
  7485. local bgColor = colors.black\
  7486. local txtColor = colors.white\
  7487. local domain = {}\
  7488. local currDir = \"\"\
  7489. local files = {}\
  7490. local Buttons = {\
  7491.     {\
  7492.         2,\
  7493.         2,\
  7494.         9,\
  7495.         1,\
  7496.         \" Refresh \",\
  7497.         colors.white,\
  7498.         colors.green,\
  7499.         \"refresh\"\
  7500.     },\
  7501.     {\
  7502.         13,\
  7503.         2,\
  7504.         4,\
  7505.         1,\
  7506.         \" Up \",\
  7507.         colors.white,\
  7508.         colors.green,\
  7509.         \"up\"\
  7510.     },\
  7511.     {\
  7512.         19,\
  7513.         2,\
  7514.         7,\
  7515.         1,\
  7516.         \" Paste \",\
  7517.         colors.white,\
  7518.         colors.green,\
  7519.         \"paste\"\
  7520.     },\
  7521. }\
  7522. 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,},}\
  7523. 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,},}\
  7524. local scroll = 0\
  7525. local globalButtonList = {}\
  7526. local notEnded = true\
  7527. local fileExtensions = {\
  7528. nfp = \"nPaintPro\",\
  7529. nfa = \"nPaintPro\",\
  7530. txt = \"Edit\",\
  7531. exe = \"Shell\",\
  7532. lua = \"Shell\",\
  7533. ico = \"BetterPaint\",\
  7534. }\
  7535. \
  7536. --Functions--\
  7537. \
  7538. local function detectButtonHit(buttonsToTest)\
  7539.     local event, button, x, y\
  7540.     repeat\
  7541.         event, button, x, y = os.pullEvent()\
  7542.     until event == \"mouse_click\" or event == \"key\"\
  7543.     if event == \"mouse_click\" then\
  7544.         for i,v in pairs(buttonsToTest) do\
  7545.             if v[1] <= x and x <= v[3] and v[2] <= y and y <= v[4] then\
  7546.                 return {v[5], button, x, y}\
  7547.             end\
  7548.         end\
  7549.     elseif event == \"key\" then\
  7550.         return {\"key:\"..tostring(button)}\
  7551.     end\
  7552.     return {\"pong\"}\
  7553. end\
  7554. \
  7555. local function mkStrShort(str,lenght,n)\
  7556.     local bufferTable = {}\
  7557.     local toReturnTable = {}\
  7558.     local lenghtN = tonumber(lenght)\
  7559.     if lenghtN == nil then return false end\
  7560.     for i = 0,n-1 do \
  7561.         bufferTable[i+1] = string.sub(tostring(str),(i*lenghtN)+1,(i*lenghtN)+lenghtN)\
  7562.     end\
  7563.     for i,v in pairs(bufferTable) do\
  7564.         if v ~= nil then\
  7565.             toReturnTable[#toReturnTable+1] = v\
  7566.         end\
  7567.     end\
  7568.     return toReturnTable\
  7569. end\
  7570. \
  7571. local function clear(bgColorArg)\
  7572.     term.setBackgroundColor(bgColorArg or bgColor)\
  7573.     term.setTextColor(txtColor)\
  7574.     term.setCursorPos(1,1)\
  7575.     term.clear()\
  7576.     globalButtonList = {}\
  7577. end\
  7578. \
  7579. local function dropDownMenu(tableInput,clearBg,x,y)\
  7580.     term.setCursorPos(1,1)\
  7581.     if clearBg ~= false then\
  7582.         clear(colors.cyan)\
  7583.     end\
  7584.     globalButtonList = {}\
  7585.     local nTable = {}\
  7586.     local dropDownMenuWindow = window.create(tableInput[1],x,y,tableInput[2],#tableInput[8]+1,true)\
  7587.     dropDownMenuWindow.setTextColor(tableInput[4])\
  7588.     dropDownMenuWindow.setBackgroundColor(tableInput[5])\
  7589.     dropDownMenuWindow.setCursorPos(1,1)\
  7590.     dropDownMenuWindow.clearLine()\
  7591.     dropDownMenuWindow.write(tableInput[3])\
  7592.     dropDownMenuWindow.setTextColor(tableInput[6])\
  7593.     dropDownMenuWindow.setBackgroundColor(tableInput[7])\
  7594.     for i = 1 , #tableInput[8] do\
  7595.         dropDownMenuWindow.setCursorPos(1,i+1)\
  7596.         dropDownMenuWindow.clearLine()\
  7597.         dropDownMenuWindow.write(tableInput[8][i][1])\
  7598.         globalButtonList[#globalButtonList+1] = {x+1,y+i,x+tableInput[2],y+i,tableInput[8][i][2]}\
  7599.     end\
  7600.     local result\
  7601.     repeat\
  7602.         result =  detectButtonHit(globalButtonList)\
  7603.     until result[1] ~= \"pong\"\
  7604.     return result[1]\
  7605. end\
  7606. \
  7607. local function dialogBox(tableInput,clearBg)\
  7608.     if clearBg ~= false then\
  7609.         clear(colors.cyan)\
  7610.     end\
  7611.     local nTable = {}\
  7612.     dialogBoxWindow = window.create(\
  7613.     tableInput[1],\
  7614.     tableInput[2],\
  7615.     tableInput[3],\
  7616.     tableInput[4],\
  7617.     tableInput[5])\
  7618.     dialogBoxWindow.setBackgroundColor(tableInput[9])\
  7619.     dialogBoxWindow.setCursorPos(2,1)\
  7620.     dialogBoxWindow.clearLine()\
  7621.     dialogBoxWindow.setTextColor(tableInput[8])\
  7622.     dialogBoxWindow.write(tableInput[7])\
  7623.     dialogBoxWindow.setCursorPos(1,2)\
  7624.     dialogBoxWindow.setBackgroundColor(tableInput[12])\
  7625.     for i = 2 , tableInput[5] do\
  7626.         dialogBoxWindow.setCursorPos(1,i)\
  7627.         dialogBoxWindow.clearLine()\
  7628.     end\
  7629.     dialogBoxWindow.setCursorPos(1,2)\
  7630.     dialogBoxWindow.setTextColor(tableInput[11])\
  7631.     for token in string.gmatch(tableInput[10],\"[^%%]+\") do\
  7632.         nTable[#nTable+1] = token\
  7633.     end\
  7634.     for i,v in pairs(nTable) do\
  7635.         dialogBoxWindow.setCursorPos(2,1+i)\
  7636.         dialogBoxWindow.write(v)\
  7637.     end\
  7638.     local totalLenght = 0\
  7639.     globalButtonList = {}\
  7640.     for i,v in pairs(tableInput[13]) do\
  7641.         dialogBoxWindow.setCursorPos(2+totalLenght,tableInput[5]-1)\
  7642.         dialogBoxWindow.setTextColor(v[2])\
  7643.         dialogBoxWindow.setBackgroundColor(v[3])\
  7644.         local toWrite = \" \"..v[1]..\" \"\
  7645.         dialogBoxWindow.write(toWrite)\
  7646.         if globalButtonList == nil then\
  7647.             globalButtonList = {{tableInput[2]+1+totalLenght,tableInput[3] + tableInput[5]-2,tableInput[2]+totalLenght + #toWrite,tableInput[3] + tableInput[5]-1,v[4]}}\
  7648.         else\
  7649.             globalButtonList[#globalButtonList+1] = {tableInput[2]+1+totalLenght,tableInput[3] + tableInput[5]-2,tableInput[2]+totalLenght + #toWrite,tableInput[3] + tableInput[5]-1,v[4]}\
  7650.         end\
  7651.         totalLenght = #toWrite + totalLenght + 2\
  7652.     end\
  7653.     local repeatIt = true\
  7654.     while repeatIt == true do\
  7655.         local unparsedResult = detectButtonHit(globalButtonList)\
  7656.         result = unparsedResult[1]\
  7657.         if result ~= \"pong\" then\
  7658.             repeatIt = false\
  7659.         end\
  7660.     end\
  7661.     return result\
  7662. end\
  7663. \
  7664. local function textBox(tableInput,secret,clearBg)\
  7665.     if clearBg ~= false then\
  7666.         clear(colors.cyan)\
  7667.     end\
  7668.     local nTable = {}\
  7669.     textBoxWindow = window.create(tableInput[1],tableInput[2],tableInput[3],tableInput[4],tableInput[5])\
  7670.     textBoxWindow.setCursorPos(2,1)\
  7671.     textBoxWindow.setBackgroundColor(tableInput[9])\
  7672.     textBoxWindow.clearLine()\
  7673.     textBoxWindow.setTextColor(tableInput[8])\
  7674.     textBoxWindow.write(tableInput[7])\
  7675.     textBoxWindow.setCursorPos(1,2)\
  7676.     textBoxWindow.setBackgroundColor(tableInput[12])\
  7677.     for i = 2 , tableInput[5] do\
  7678.         textBoxWindow.setCursorPos(1,i)\
  7679.         textBoxWindow.clearLine()\
  7680.     end\
  7681.     textBoxWindow.setTextColor(tableInput[11])\
  7682.     for token in string.gmatch(tableInput[10],\"[^%%]+\") do\
  7683.         nTable[#nTable+1] = token\
  7684.     end\
  7685.     for i,v in pairs(nTable) do\
  7686.         textBoxWindow.setCursorPos(2,1+i)\
  7687.         textBoxWindow.write(v)\
  7688.     end\
  7689.     textBoxWindow.setTextColor(tableInput[13])\
  7690.     textBoxWindow.setBackgroundColor(tableInput[14])\
  7691.     textBoxWindow.setCursorPos(2,tableInput[5]-1)\
  7692.     textBoxWindow.clearLine()\
  7693.     textBoxWindow.setCursorPos(2,tableInput[5]-1)\
  7694.     textBoxWindow.setTextColor(tableInput[13])\
  7695.     textBoxWindow.setBackgroundColor(tableInput[14])\
  7696.     if secret then\
  7697.         return read(\"*\")\
  7698.     else\
  7699.         return read()\
  7700.     end\
  7701. end\
  7702. \
  7703. local function refresh(dir)\
  7704.     local bufferFiles = {}\
  7705.     for i,v in pairs(fs.list(dir)) do\
  7706.         if fs.isDir(currDir..\"/\"..v) then\
  7707.             bufferFiles[#bufferFiles+1] = {v,\"folder\"}\
  7708.         else\
  7709.             bufferFiles[#bufferFiles+1] = {v,\"file\"}\
  7710.         end\
  7711.     end\
  7712.     return bufferFiles\
  7713. end\
  7714. \
  7715. local function drawOptions(tableInputDrawOptions)\
  7716.     for i,v in pairs(tableInputDrawOptions) do\
  7717.         term.setCursorPos(v[1],v[2])\
  7718.         paintutils.drawFilledBox(v[1],v[2],v[3]+v[1]-1,v[4]+v[2]-1,v[7])\
  7719.         term.setCursorPos(v[1],v[2])\
  7720.         term.setTextColor(v[6])\
  7721.         term.write(v[5])\
  7722.         if globalButtonList == nil then\
  7723.             globalButtonList = {{v[1],v[2],v[3]+v[1]-1,v[4]+v[2]-1,\"button:\"..v[8]}}\
  7724.         else\
  7725.             globalButtonList[#globalButtonList+1] = {v[1],v[2],v[3]+v[1]-1,v[4]+v[2]-1,\"button:\"..v[8]}\
  7726.         end\
  7727.     end\
  7728. end\
  7729. \
  7730. local function drawFiles(filesToDisplay)\
  7731.     local numItemsX = math.floor((w-1)/10)\
  7732.     numItemsY = math.ceil(#filesToDisplay/numItemsX)\
  7733.     local currFile = 1\
  7734.     for i = 0 , numItemsY-1 do\
  7735.         for k = 0 , numItemsX - 1 do\
  7736.             if currFile > #filesToDisplay then\
  7737.                 break\
  7738.             else\
  7739.                 term.setTextColor(colors.black)\
  7740.                 if filesToDisplay[currFile][2] == \"file\" then\
  7741.                     paintutils.drawImage(fileIcon,(k*10)+2,(i*5)+4-scroll)\
  7742.                     for l,m in pairs(mkStrShort(filesToDisplay[currFile][1],6,3)) do \
  7743.                         term.setCursorPos((k*10)+3,(i*5)+4+l-scroll)\
  7744.                         term.write(m)\
  7745.                     end\
  7746.                     if ((i*5)+4-scroll) < 4 then\
  7747.                         if ((i*5)+7-scroll) >= 4 then\
  7748.                             if globalButtonList == nil then\
  7749.                                 globalButtonList = {{((k*10)+2),4,((k*10)+9),((i*5)+7-scroll),\"file:\"..filesToDisplay[currFile][1]}}\
  7750.                             else\
  7751.                                 globalButtonList[#globalButtonList+1] = {((k*10)+2),4,((k*10)+9),((i*5)+7-scroll),\"file:\"..filesToDisplay[currFile][1]}\
  7752.                             end\
  7753.                         end\
  7754.                     else\
  7755.                         if globalButtonList == nil then\
  7756.                             globalButtonList = {{((k*10)+2),((i*5)+4-scroll),((k*10)+9),((i*5)+7-scroll),\"file:\"..filesToDisplay[currFile][1]}}\
  7757.                         else\
  7758.                             globalButtonList[#globalButtonList+1] = {((k*10)+2),((i*5)+4-scroll),((k*10)+9),((i*5)+7-scroll),\"file:\"..filesToDisplay[currFile][1]}\
  7759.                         end\
  7760.                     end\
  7761.                 elseif filesToDisplay[currFile][2] == \"folder\" then\
  7762.                     paintutils.drawImage(folderIcon,(k*10)+2,(i*5)+4-scroll)\
  7763.                     for l,m in pairs(mkStrShort(filesToDisplay[currFile][1],6,3)) do \
  7764.                         term.setCursorPos((k*10)+3,(i*5)+4+l-scroll)\
  7765.                         term.write(m)\
  7766.                     end\
  7767.                     if ((i*5)+4-scroll) < 4 then\
  7768.                         if ((i*5)+7-scroll) >= 4 then\
  7769.                             if globalButtonList == nil then\
  7770.                                 globalButtonList = {{((k*10)+2),4,((k*10)+9),((i*5)+7-scroll),\"folder:\"..filesToDisplay[currFile][1]}}\
  7771.                             else\
  7772.                                 globalButtonList[#globalButtonList+1] = {((k*10)+2),4,((k*10)+9),((i*5)+7-scroll),\"folder:\"..filesToDisplay[currFile][1]}\
  7773.                             end\
  7774.                         end\
  7775.                     else\
  7776.                         if globalButtonList == nil then\
  7777.                             globalButtonList = {{((k*10)+2),((i*5)+4-scroll),((k*10)+9),((i*5)+7-scroll),\"folder:\"..filesToDisplay[currFile][1]}}\
  7778.                         else\
  7779.                             globalButtonList[#globalButtonList+1] = {((k*10)+2),((i*5)+4-scroll),((k*10)+9),((i*5)+7-scroll),\"folder:\"..filesToDisplay[currFile][1]}\
  7780.                         end\
  7781.                     end\
  7782.                 end\
  7783.                 currFile = currFile + 1\
  7784.             end\
  7785.         end\
  7786.     end\
  7787. end\
  7788. \
  7789. local function drawSideBar()\
  7790.     local lenghtSideBar = h-4\
  7791.     if numItemsY ~= 0 then\
  7792.          lenghtSideBar = math.ceil(((h-5)*(h-5))/(numItemsY*5))\
  7793.     end\
  7794.     paintutils.drawLine(w,3,w,3+lenghtSideBar,colors.green)\
  7795.     term.setBackgroundColor(colors.blue)\
  7796.     term.setCursorPos(w,3)\
  7797.     term.write(\"^\")\
  7798.     term.setCursorPos(w,h-1)\
  7799.     term.write(\"v\")\
  7800.     if globalButtonList == nil then\
  7801.         globalButtonList = {{w,3,w,3,\"button:scrollUp\"}}\
  7802.     else\
  7803.         globalButtonList[#globalButtonList+1] = {w,3,w,3,\"button:scrollUp\"}\
  7804.     end\
  7805.     if globalButtonList == nil then\
  7806.         globalButtonList = {{w,h-1,w,h-1,\"button:scrollDown\"}}\
  7807.     else\
  7808.         globalButtonList[#globalButtonList+1] = {w,h-1,w,h-1,\"button:scrollDown\"}\
  7809.     end\
  7810. end\
  7811. \
  7812. local function program(extension)\
  7813.     if fileExtensions[extension] ~= nil then\
  7814.         return fileExtensions[extension]\
  7815.     else\
  7816.         return \"edit\"\
  7817.     end\
  7818. end\
  7819. \
  7820. local function main(filesToDisplay,buttonsToDisplay)\
  7821.     clear(colors.white)\
  7822.     drawFiles(filesToDisplay)\
  7823.     drawSideBar()\
  7824.     term.setBackgroundColor(colors.orange)\
  7825.     for i = 1,2 do\
  7826.         term.setCursorPos(1,i)\
  7827.         term.clearLine()\
  7828.     end\
  7829.     term.setCursorPos(1,1)\
  7830.     term.setTextColor(colors.black)\
  7831.     term.write(\"Creator\\'s FileX v1.0\")\
  7832.     term.setCursorPos(w,1)\
  7833.     term.setBackgroundColor(colors.magenta)\
  7834.     term.write(\"X\")\
  7835.     if globalButtonList == nil then\
  7836.         globalButtonList = {{w,1,w,1,\"button:x\"}}\
  7837.     else\
  7838.         globalButtonList[#globalButtonList+1] = {w,1,w,1,\"button:x\"}\
  7839.     end\
  7840.     if globalButtonList == nil then\
  7841.         globalButtonList = {{1,3,w,h,\"nil:nil\"}}\
  7842.     else\
  7843.         globalButtonList[#globalButtonList+1] = {1,4,w,h,\"nil:nil\"}\
  7844.     end\
  7845.     drawOptions(buttonsToDisplay)\
  7846.     if globalButtonList == nil then\
  7847.         globalButtonList = {{1,1,w,3,\"nil:nilnil\"}}\
  7848.     else\
  7849.         globalButtonList[#globalButtonList+1] = {1,1,w,3,\"nil:nilnil\"}\
  7850.     end\
  7851.     term.setCursorPos(1,h)\
  7852.     term.setBackgroundColor(colors.orange)\
  7853.     term.clearLine()\
  7854.     term.setTextColor(colors.black)\
  7855.     term.write(currDir)\
  7856.     term.setCursorPos(1,1)\
  7857.     local detectedButtonUnparsedTable = detectButtonHit(globalButtonList)\
  7858.     local detectedButtonUnparsed = detectedButtonUnparsedTable[1]\
  7859.     local button = detectedButtonUnparsedTable[2]\
  7860.     local detectedButtonParsedTable = {}\
  7861.     for token in string.gmatch(detectedButtonUnparsed,\"[^:]+\") do\
  7862.         detectedButtonParsedTable[#detectedButtonParsedTable + 1] = token\
  7863.     end\
  7864.     local action = detectedButtonParsedTable[2]\
  7865.     if detectedButtonParsedTable[1] == \"button\" then\
  7866.         if action == \"x\" then\
  7867.             term.setBackgroundColor(colors.black)\
  7868.             clear()\
  7869.             print(\"Thank you for using Creator\\'s FTPclient. More coming soon...\\nSpecial thanks to:\\nNitrogenFingers for nPaintPro\")\
  7870.             notEnded = false\
  7871.         elseif action == \"up\" then\
  7872.             scroll = 0\
  7873.             if currDir == \"/\" then\
  7874.             else\
  7875.                 local currDirBuffer = {}\
  7876.                 for token in string.gmatch(currDir,\"(/[^/]+)\") do\
  7877.                     currDirBuffer[#currDirBuffer + 1] = token\
  7878.                 end\
  7879.                 currDir = \"\"\
  7880.                 if #currDirBuffer == 1 then\
  7881.                     currDir = \"\"\
  7882.                 else\
  7883.                     for i = 1, #currDirBuffer-1 do\
  7884.                         if i == 1 then\
  7885.                             currDir = currDirBuffer[1]\
  7886.                         else\
  7887.                             currDir = currDir..currDirBuffer[i]\
  7888.                         end\
  7889.                     end\
  7890.                 end\
  7891.                 files = refresh(currDir)\
  7892.             end\
  7893.         elseif action == \"refresh\" then\
  7894.             files = refresh(currDir)\
  7895.         elseif action == \"scrollUp\" then\
  7896.             scroll = scroll - 1\
  7897.             if scroll < 0 then\
  7898.                 scroll = 0\
  7899.             end\
  7900.         elseif action == \"scrollDown\" then\
  7901.             scroll = scroll + 1\
  7902.             if scroll > numItemsY*6 - h then\
  7903.                 scroll = scroll - 1\
  7904.             end\
  7905.         elseif action == \"paste\" then\
  7906.             term.setCursorPos(1,1)\
  7907.             print(pathToCopy)\
  7908.             print(currDir)\
  7909.             print(copyHelp)\
  7910.             sleep(3)\
  7911.             fs.copy(copyPath,currDir..\"/\"..copyHelp)\
  7912.             files = refresh(currDir)\
  7913.             \
  7914.         end\
  7915.     elseif detectedButtonParsedTable[1] == \"key\" then\
  7916.         if tonumber(action) == keys.up then\
  7917.             scroll = scroll - 1\
  7918.             if scroll < 0 then\
  7919.                 scroll = 0\
  7920.             end\
  7921.         elseif tonumber(action) == keys.down then\
  7922.             scroll = scroll + 1\
  7923.             if scroll > numItemsY*6 - h then\
  7924.                 scroll = scroll - 1\
  7925.             end\
  7926.         end\
  7927.     elseif detectedButtonParsedTable[1] == \"folder\" then\
  7928.         if button == 1 then\
  7929.             currDir = currDir..\"/\"..action\
  7930.             files = refresh(currDir)\
  7931.             scroll = 0\
  7932.         elseif button == 2 then\
  7933.             local result = dropDownMenu(folderMenu,false,detectedButtonUnparsedTable[3],detectedButtonUnparsedTable[4])\
  7934.             if result == \"open\" then\
  7935.                 currDir = currDir..\"/\"..action\
  7936.                 files = refresh(currDir)\
  7937.                 scroll = 0\
  7938.             elseif result == \"copy\" then\
  7939.                 pathToCopy = currDir..action\
  7940.             elseif result == \"delete\" then\
  7941.                 fs.delete(currDir..\"/\"..action)\
  7942.                 files = refresh(currDir)\
  7943.             elseif result == \"rename\" then\
  7944.                 local answ = textBox(newFolderWindow,false,false)\
  7945.                 fs.move(currDir..\"/\"..action,currDir..\"/\"..answ)\
  7946.                 files = refresh(currDir)\
  7947.             elseif result == \"move\" then\
  7948.                 local answ = textBox(moveFolderWindow,false,false)\
  7949.                 if string.sub(answ,1,1) ~= \"/\" then\
  7950.                     answ = \"/\"..answ\
  7951.                 end\
  7952.                 fs.move(currDir..\"/\"..action,answ)\
  7953.                 files = refresh(currDir)\
  7954.             elseif result == \"copy\" then\
  7955.                 copyPath = currDir..\"/\"..action\
  7956.                 copyHelp = action\
  7957.             end\
  7958.         end\
  7959.     elseif detectedButtonParsedTable[1] == \"file\" then\
  7960.         if button == 1 then\
  7961.             local fileExtension\
  7962.             for token in string.gmatch(action,\"[^%.]+\") do\
  7963.                 fileExtension = token\
  7964.             end\
  7965.             if fileExtension == action then\
  7966.                 fileExtension = \"txt\"\
  7967.             end\
  7968.             programT = program(fileExtension)\
  7969.             --shell.run(progsDir..\"/\"..programT..\" \"..currDir..\"/\"..action)\
  7970.             System.newTask(programT,programT,currDir..\"/\"..action)\
  7971.         elseif button == 2 then\
  7972.             local result = dropDownMenu(fileMenu,false,detectedButtonUnparsedTable[3],detectedButtonUnparsedTable[4])\
  7973.             if result == \"open\" then\
  7974.                 local fileExtension\
  7975.                 for token in string.gmatch(action,\"[^%.]+\") do\
  7976.                     fileExtension = token\
  7977.                 end\
  7978.                 if fileExtension == action then\
  7979.                     fileExtension = \"txt\"\
  7980.                 end\
  7981.                 programT = program(fileExtension)\
  7982.                 System.newTask(programT,programT, currDir..\"/\"..action)\
  7983.             elseif result == \"delete\" then\
  7984.                 fs.delete(currDir..\"/\"..action)\
  7985.                 files = refresh(currDir)\
  7986.             elseif result == \"rename\" then\
  7987.                 local answ = textBox(newFolderWindow,false,false)\
  7988.                 fs.move(currDir..\"/\"..action,currDir..\"/\"..answ)\
  7989.                 files = refresh(currDir)\
  7990.             elseif result == \"move\" then\
  7991.                 local answ = textBox(moveFolderWindow,false,false)\
  7992.                 if string.sub(answ,1,1) ~= \"/\" then\
  7993.                     answ = \"/\"..answ\
  7994.                 end\
  7995.                 fs.move(currDir..\"/\"..action,answ)\
  7996.                 files = refresh(currDir)\
  7997.             elseif result == \"run\" then\
  7998.                 shell.run(progsDir..\"/shell \"..currDir..\"/\"..action)\
  7999.             elseif result == \"openWith\" then\
  8000.                 local possibleExtensions = {}\
  8001.                 for i,v in pairs(fileExtensions) do\
  8002.                     local alreadyRegistered = false\
  8003.                     for m,k in pairs(possibleExtensions) do\
  8004.                         if v == k then\
  8005.                             alreadyRegistered = true\
  8006.                         end\
  8007.                     end\
  8008.                     if not alreadyRegistered then\
  8009.                         possibleExtensions[#possibleExtensions+1] = v\
  8010.                     end\
  8011.                 end\
  8012.                 local openWith = {\
  8013.                     term.current(),\
  8014.                     16,\
  8015.                     \"Open with:\",\
  8016.                     colors.white,\
  8017.                     colors.blue,\
  8018.                     colors.black,\
  8019.                     colors.lightGray,\
  8020.                     {}\
  8021.                 }\
  8022.                 for i,v in pairs(possibleExtensions) do\
  8023.                     openWith[8][#openWith[8]+1] = {v,v}\
  8024.                 end\
  8025.                 openWith[8][#openWith[8]+1] = {\"Cancel\",\"cancel\"}\
  8026.                 globalButtonList = {}\
  8027.                 result = dropDownMenu(openWith,false,detectedButtonUnparsedTable[3],detectedButtonUnparsedTable[4]+6)\
  8028.                 System.newTask(result,result,currDir..\"/\"..action)\
  8029.             elseif result == \"copy\" then\
  8030.                 copyPath = currDir..\"/\"..action\
  8031.                 copyHelp = action\
  8032.             end\
  8033.         end\
  8034.     elseif detectedButtonParsedTable[1] == \"nil\" then\
  8035.         if button == 2 then\
  8036.             if action == \"nil\" then\
  8037.                 local result = dropDownMenu(nilMenu,false,detectedButtonUnparsedTable[3],detectedButtonUnparsedTable[4])\
  8038.                 if result == \"makeFolder\" then\
  8039.                     local answ = textBox(newFolderWindow,false,false)\
  8040.                     fs.makeDir(currDir..\"/\"..answ)\
  8041.                     files = refresh(currDir)\
  8042.                     scroll = 0\
  8043.                 elseif result == \"makeFile\" then\
  8044.                     local answ = textBox(newFileWindow,false,false)\
  8045.                     f = fs.open(currDir..\"/\"..answ,\"w\")\
  8046.                     f.close()\
  8047.                     files = refresh(currDir)\
  8048.                     scroll = 0\
  8049.                 end\
  8050.             end\
  8051.         end\
  8052.     end\
  8053. end\
  8054. \
  8055. --Code--\
  8056. \
  8057. clear()\
  8058. files = refresh(currDir)\
  8059. while notEnded do\
  8060.     main(files,Buttons)\
  8061. end\
  8062. shell.setDir(currDir)",
  8063.       Data = {
  8064.         shell = "local path = \"\"\
  8065. local args = \"\"\
  8066. local tArgs = {...}\
  8067. for i,v in pairs(tArgs) do \
  8068.  if i == 1 then\
  8069.    path = v\
  8070.  else\
  8071.    args = args..\" \"..v\
  8072.  end\
  8073. end\
  8074. pcall(shell.run,path..\" \"..args)",
  8075.         nPaintPro = "--[[\
  8076.         NPaintPro\
  8077.         By NitrogenFingers\
  8078. ]]--\
  8079. \
  8080. --The screen size\
  8081. local w,h = term.getSize()\
  8082. --Whether or not the program is currently waiting on user input\
  8083. local inMenu = false\
  8084. --Whether or not a drop down menu is active\
  8085. local inDropDown = false\
  8086. --Whether or not animation tools are enabled (use -a to turn them on)\
  8087. local animated = false\
  8088. --Whether or not \"blueprint\" display mode is on\
  8089. local blueprint = false\
  8090. --Whether or not the \"layer\" display is on\
  8091. local layerDisplay = false\
  8092. --Whether or not the \"direction\" display is on\
  8093. local printDirection = false\
  8094. --The tool/mode npaintpro is currently in. Default is \"paint\"\
  8095. --For a list of modes, check out the help file\
  8096. local state = \"paint\"\
  8097. --Whether or not the program is presently running\
  8098. local isRunning = true\
  8099. --The rednet address of the 3D printer, if one has been attached\
  8100. local printer = nil\
  8101. \
  8102. --The list of every frame, containing every image in the picture/animation\
  8103. --Note: nfp files always have the picture at frame 1\
  8104. local frames = { }\
  8105. --How many frames are currently in the given animation.\
  8106. local frameCount = 1\
  8107. --The Colour Picker column\
  8108. local column = {}\
  8109. --The currently selected left and right colours\
  8110. local lSel,rSel = colours.white,nil\
  8111. --The amount of scrolling on the X and Y axis\
  8112. local sx,sy = 0,0\
  8113. --The alpha channel colour\
  8114. --Change this to change default canvas colour\
  8115. local alphaC = colours.yellow\
  8116. --The currently selected frame. Default is 1\
  8117. local sFrame = 1\
  8118. --The contents of the image buffer- contains contents, width and height\
  8119. local buffer = nil\
  8120. --The position, width and height of the selection rectangle\
  8121. local selectrect = nil\
  8122. \
  8123. --The currently calculated required materials\
  8124. local requiredMaterials = {}\
  8125. --Whether or not required materials are being displayed in the pallette\
  8126. local requirementsDisplayed = false\
  8127. --A list of the rednet ID's all in-range printers located\
  8128. local printerList = { }\
  8129. --A list of the names of all in-range printers located. Same as the printerList in reference\
  8130. local printerNames = { }\
  8131. --The selected printer\
  8132. local selectedPrinter = 1\
  8133. --The X,Y,Z and facing of the printer\
  8134. local px,py,pz,pfx,pfz = 0,0,0,0,0\
  8135. --The form of layering used\
  8136. local layering = \"up\"\
  8137. \
  8138. --The animation state of the selection rectangle and image buffer \
  8139. local rectblink = 0\
  8140. --The ID for the timer\
  8141. local recttimer = nil\
  8142. --The radius of the brush tool\
  8143. local brushsize = 3\
  8144. --Whether or not \"record\" mode is activated (animation mode only)\
  8145. local record = false\
  8146. --The time between each frame when in play mode (animation mode only)\
  8147. local animtime = 0.3\
  8148. \
  8149. --A list of hexidecimal conversions from numbers to hex digits\
  8150. local hexnums = { [10] = \"a\", [11] = \"b\", [12] = \"c\", [13] = \"d\", [14] = \"e\" , [15] = \"f\" }\
  8151. --The NPaintPro logo (divine, isn't it?)\
  8152. local logo = {\
  8153. \"fcc              3   339\";\
  8154. \" fcc          9333    33\";\
  8155. \"  fcc        933 333  33\";\
  8156. \"   fcc       933  33  33\";\
  8157. \"    fcc      933   33 33\";\
  8158. \"     c88     333   93333\";\
  8159. \"     888     333    9333\";\
  8160. \"      333 3  333     939\";\
  8161. }\
  8162. --The Layer Up and Layer Forward printing icons\
  8163. local layerUpIcon = {\
  8164.     \"0000000\";\
  8165.     \"0088880\";\
  8166.     \"0888870\";\
  8167.     \"07777f0\";\
  8168.     \"0ffff00\";\
  8169.     \"0000000\";\
  8170. }\
  8171. local layerForwardIcon = {\
  8172.     \"0000000\";\
  8173.     \"000fff0\";\
  8174.     \"00777f0\";\
  8175.     \"0888700\";\
  8176.     \"0888000\";\
  8177.     \"0000000\";\
  8178. }\
  8179. --The available menu options in the ctrl menu\
  8180. local mChoices = {\"Save\",\"Exit\"}\
  8181. --The available modes from the dropdown menu- tables indicate submenus (include a name!)\
  8182. 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\" }\
  8183. --The available modes from the selection right-click menu\
  8184. local srModes = { \"cut\", \"copy\", \"paste\", \"clear\", \"hide\", name = \"selection\" }\
  8185. --The list of available help topics for each mode 127\
  8186. local helpTopics = {\
  8187.     [1] = {\
  8188.         name = \"Paint Mode\",\
  8189.         key = nil,\
  8190.         animonly = false,\
  8191.         message = \"The default mode for NPaintPro, for painting pixels.\"\
  8192.         ..\" Controls here that are not overridden will apply for all other modes. Leaving a mode by selecting that mode \"\
  8193.         ..\" again will always send the user back to paint mode.\",\
  8194.         controls = {\
  8195.             { \"Arrow keys\", \"Scroll the canvas\" },\
  8196.             { \"Left Click\", \"Paint/select left colour\" },\
  8197.             { \"Right Click\", \"Paint/select right colour\" },\
  8198.             { \"Z Key\", \"Clear image on screen\" },\
  8199.             { \"Tab Key\", \"Hide selection rectangle if visible\" },\
  8200.             { \"Q Key\", \"Set alpha mask to left colour\" },\
  8201.             { \"W Key\", \"Set alpha mask to right colour\" },\
  8202.             { \"Number Keys\", \"Swich between frames 1-9\" },\
  8203.             { \"</> keys\", \"Move to the next/last frame\" },\
  8204.             { \"R Key\", \"Removes every frame after the current frame\"}\
  8205.         }\
  8206.     },\
  8207.     [2] = {\
  8208.         name = \"Brush Mode\",\
  8209.         key = \"b\",\
  8210.         animonly = false,\
  8211.         message = \"Brush mode allows painting a circular area of variable diameter rather than a single pixel, working in \"..\
  8212.         \"the exact same way as paint mode in all other regards.\",\
  8213.         controls = {\
  8214.             { \"Left Click\", \"Paints a brush blob with the left colour\" },\
  8215.             { \"Right Click\", \"Paints a brush blob with the right colour\" },\
  8216.             { \"Number Keys\", \"Changes the radius of the brush blob from 2-9\" }\
  8217.         }\
  8218.     },\
  8219.     [3] = {\
  8220.         name = \"Pippette Mode\",\
  8221.         key = \"p\",\
  8222.         animonly = false,\
  8223.         message = \"Pippette mode allows the user to click the canvas and set the colour clicked to the left or right \"..\
  8224.         \"selected colour, for later painting.\",\
  8225.         controls = {\
  8226.             { \"Left Click\", \"Sets clicked colour to the left selected colour\" },\
  8227.             { \"Right Click\", \"Sets clicked colour to the right selected colour\" }\
  8228.         }\
  8229.     },\
  8230.     [4] = {\
  8231.         name = \"Move Mode\",\
  8232.         key = \"m\",\
  8233.         animonly = false,\
  8234.         message = \"Mode mode allows the moving of the entire image on the screen. This is especially useful for justifying\"..\
  8235.         \" the image to the top-left for animations or game assets.\",\
  8236.         controls = {\
  8237.             { \"Left/Right Click\", \"Moves top-left corner of image to selected square\" },\
  8238.             { \"Arrow keys\", \"Moves image one pixel in any direction\" }\
  8239.         }\
  8240.     },\
  8241.     [5] = {\
  8242.         name = \"Flood Mode (NYI)\",\
  8243.         key = \"f\",\
  8244.         animonly = false,\
  8245.         message = \"Flood mode allows the changing of an area of a given colour to that of the selected colour. \"..\
  8246.         \"The tool uses a flood4 algorithm and will not fill diagonally. Transparency cannot be flood filled.\",\
  8247.         controls = {\
  8248.             { \"Left Click\", \"Flood fills selected area to left colour\" },\
  8249.             { \"Right Click\", \"Flood fills selected area to right colour\" }\
  8250.         }\
  8251.     },\
  8252.     [6] = {\
  8253.         name = \"Select Mode\",\
  8254.         key = \"s\",\
  8255.         animonly = false,\
  8256.         message = \"Select mode allows the creation and use of the selection rectangle, to highlight specific areas on \"..\
  8257.         \"the screen and perform operations on the selected area of the image. The selection rectangle can contain an \"..\
  8258.         \"image on the clipboard- if it does, the image will flash inside the rectangle, and the rectangle edges will \"..\
  8259.         \"be light grey instead of dark grey.\",\
  8260.         controls = {\
  8261.             { \"C Key\", \"Copy: Moves selection into the clipboard\" },\
  8262.             { \"X Key\", \"Cut: Clears canvas under the rectangle, and moves it into the clipboard\" },\
  8263.             { \"V Key\", \"Paste: Copys clipboard to the canvas\" },\
  8264.             { \"Z Key\", \"Clears clipboard\" },\
  8265.             { \"Left Click\", \"Moves top-left corner of rectangle to selected pixel\" },\
  8266.             { \"Right Click\", \"Opens selection menu\" },\
  8267.             { \"Arrow Keys\", \"Moves rectangle one pixel in any direction\" }\
  8268.         }\
  8269.     },\
  8270.     [7] = {\
  8271.         name = \"Corner Select Mode\",\
  8272.         key = nil,\
  8273.         animonly = false,\
  8274.         message = \"If a selection rectangle isn't visible, this mode is selected automatically. It allows the \"..\
  8275.         \"defining of the corners of the rectangle- one the top-left and bottom-right corners have been defined, \"..\
  8276.         \"NPaintPro switches to selection mode. Note rectangle must be at least 2 pixels wide and high.\",\
  8277.         controls = {\
  8278.             { \"Left/Right Click\", \"Defines a corner of the selection rectangle\" }\
  8279.         }\
  8280.     },\
  8281.     [8] = {\
  8282.         name = \"Play Mode\",\
  8283.         key = \"space\",\
  8284.         animonly = true,\
  8285.         message = \"Play mode will loop through each frame in your animation at a constant rate. Editing tools are \"..\
  8286.         \"locked in this mode, and the coordinate display will turn green to indicate it is on.\",\
  8287.         controls = {\
  8288.             { \"</> Keys\", \"Increases/Decreases speed of the animation\" },\
  8289.             { \"Space Bar\", \"Returns to paint mode\" }\
  8290.         }\
  8291.     },\
  8292.     [9] = {\
  8293.         name = \"Record Mode\",\
  8294.         key = \"\\\\\",\
  8295.         animonly = true,\
  8296.         message = \"Record mode is not a true mode, but influences how other modes work. Changes made that modify the \"..\
  8297.         \"canvas in record mode will affect ALL frames in the animation. The coordinates will turn red to indicate that \"..\
  8298.         \"record mode is on.\",\
  8299.         controls = {\
  8300.             { \"\", \"Affects:\" },\
  8301.             { \"- Paint Mode\", \"\" },\
  8302.             { \"- Brush Mode\", \"\" },\
  8303.             { \"- Cut and Paste in Select Mode\", \"\"},\
  8304.             { \"- Move Mode\", \"\"}\
  8305.         }\
  8306.     },\
  8307.     [10] = {\
  8308.         name = \"Help Mode\",\
  8309.         key = \"h\",\
  8310.         animonly = false,\
  8311.         message = \"Displays this help screen. Clicking on options will display help on that topic. Clicking out of the screen\"..\
  8312.         \" will leave this mode.\",\
  8313.         controls = {\
  8314.             { \"Left/Right Click\", \"Displays a topic/Leaves the mode\" }\
  8315.         }\
  8316.     },\
  8317.     [11] = {\
  8318.         name = \"File Mode\",\
  8319.         keys = nil,\
  8320.         animonly = false,\
  8321.         message = \"Clicking on the mode display at the bottom of the screen will open the options menu. Here you can\"..\
  8322.         \" activate all of the modes in the program with a simple mouse click. Pressing left control will open up the\"..\
  8323.         \" file menu automatically.\",\
  8324.         controls = { \
  8325.             { \"leftCtrl\", \"Opens the file menu\" },\
  8326.             { \"leftAlt\", \"Opens the paint menu\" }\
  8327.             \
  8328.         }\
  8329.     }\
  8330. }\
  8331. --The \"bounds\" of the image- the first/last point on both axes where a pixel appears\
  8332. local toplim,botlim,leflim,riglim = nil,nil,nil,nil\
  8333. --The selected path\
  8334. local sPath = nil\
  8335. \
  8336. --[[  \
  8337.             Section:  Helpers       \
  8338. ]]--\
  8339. \
  8340. --[[Converts a colour parameter into a single-digit hex coordinate for the colour\
  8341.    Params: colour:int = The colour to be converted\
  8342.     Returns:string A string conversion of the colour\
  8343. ]]--\
  8344. local function getHexOf(colour)\
  8345.     if not colour or not tonumber(colour) then \
  8346.         return \" \" \
  8347.     end\
  8348.     local value = math.log(colour)/math.log(2)\
  8349.     if value > 9 then \
  8350.         value = hexnums[value] \
  8351.     end\
  8352.     return value\
  8353. end\
  8354. \
  8355. --[[Converts a hex digit into a colour value\
  8356.     Params: hex:?string = the hex digit to be converted\
  8357.     Returns:string A colour value corresponding to the hex, or nil if the character is invalid\
  8358. ]]--\
  8359. local function getColourOf(hex)\
  8360.     local value = tonumber(hex, 16)\
  8361.     if not value then return nil end\
  8362.     value = math.pow(2,value)\
  8363.     return value\
  8364. end\
  8365. \
  8366. --[[Finds the biggest and smallest bounds of the image- the outside points beyond which pixels do not appear\
  8367.     These values are assigned to the \"lim\" parameters for access by other methods\
  8368.     Params: forAllFrames:bool = True if all frames should be used to find bounds, otherwise false or nil\
  8369.     Returns:nil\
  8370. ]]--\
  8371. local function updateImageLims(forAllFrames)\
  8372.     local f,l = sFrame,sFrame\
  8373.     if forAllFrames == true then f,l = 1,framecount end\
  8374.     \
  8375.     toplim,botlim,leflim,riglim = nil,nil,nil,nil\
  8376.     for locf = f,l do\
  8377.         for y,_ in pairs(frames[locf]) do\
  8378.             for x,_ in pairs(frames[locf][y]) do\
  8379.                 if frames[locf][y][x] ~= nil then\
  8380.                     if leflim == nil or x < leflim then leflim = x end\
  8381.                     if toplim == nil or y < toplim then toplim = y end\
  8382.                     if riglim == nil or x > riglim then riglim = x end\
  8383.                     if botlim == nil or y > botlim then botlim = y end\
  8384.                 end\
  8385.             end\
  8386.         end\
  8387.     end\
  8388. end\
  8389. \
  8390. --[[Determines how much of each material is required for a print. Done each time printing is called.\
  8391.     Params: none\
  8392.     Returns:table A complete list of how much of each material is required.\
  8393. ]]--\
  8394. function calculateMaterials()\
  8395.     updateImageLims(animated)\
  8396.     requiredMaterials = {}\
  8397.     for i=1,16 do \
  8398.         requiredMaterials[i] = 0 \
  8399.     end\
  8400.     \
  8401.     if not toplim then return end\
  8402.     \
  8403.     for i=1,#frames do\
  8404.         for y = toplim, botlim do\
  8405.             for x = leflim, riglim do\
  8406.                 if type(frames[i][y][x]) == \"number\" then\
  8407.                     requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] = \
  8408.                         requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] + 1\
  8409.                 end \
  8410.             end\
  8411.         end\
  8412.     end\
  8413. end\
  8414. \
  8415. \
  8416. --[[Updates the rectangle blink timer. Should be called anywhere events are captured, along with a timer capture.\
  8417.     Params: nil\
  8418.     Returns:nil\
  8419. ]]--\
  8420. local function updateTimer(id)\
  8421.     if id == recttimer then\
  8422.         recttimer = os.startTimer(0.5)\
  8423.         rectblink = (rectblink % 2) + 1\
  8424.     end\
  8425. end\
  8426. \
  8427. --[[Constructs a message based on the state currently selected\
  8428.     Params: nil\
  8429.     Returns:string A message regarding the state of the application\
  8430. ]]--\
  8431. local function getStateMessage()\
  8432.     local msg = \" \"..string.upper(string.sub(state, 1, 1))..string.sub(state, 2, #state)..\" mode\"\
  8433.     if state == \"brush\" then msg = msg..\", size=\"..brushsize end\
  8434.     return msg\
  8435. end\
  8436. \
  8437. --[[Calls the rednet_message event, but also looks for timer events to keep then\
  8438.     system timer ticking.\
  8439.     Params: timeout:number how long before the event times out\
  8440.     Returns:number the id of the sender\
  8441.            :number the message send\
  8442. ]]--\
  8443. local function rsTimeReceive(timeout)\
  8444.     local timerID\
  8445.     if timeout then timerID = os.startTimer(timeout) end\
  8446.     \
  8447.     local id,key,msg = nil,nil\
  8448.     while true do\
  8449.         id,key,msg = os.pullEvent()\
  8450.         \
  8451.         if id == \"timer\" then\
  8452.             if key == timerID then return\
  8453.             else updateTimer(key) end\
  8454.         end\
  8455.         if id == \"rednet_message\" then \
  8456.             return key,msg\
  8457.         end\
  8458.     end\
  8459. end\
  8460. \
  8461. --[[Draws a picture, in paint table format on the screen\
  8462.     Params: image:table = the image to display\
  8463.             xinit:number = the x position of the top-left corner of the image\
  8464.             yinit:number = the y position of the top-left corner of the image\
  8465.             alpha:number = the color to display for the alpha channel. Default is white.\
  8466.     Returns:nil\
  8467. ]]--\
  8468. local function drawPictureTable(image, xinit, yinit, alpha)\
  8469.     if not alpha then alpha = 1 end\
  8470.     for y=1,#image do\
  8471.         for x=1,#image[y] do\
  8472.             term.setCursorPos(xinit + x-1, yinit + y-1)\
  8473.             local col = getColourOf(string.sub(image[y], x, x))\
  8474.             if not col then col = alpha end\
  8475.             term.setBackgroundColour(col)\
  8476.             term.write(\" \")\
  8477.         end\
  8478.     end\
  8479. end\
  8480. \
  8481. --[[  \
  8482.             Section: Loading  \
  8483. ]]-- \
  8484. \
  8485. --[[Loads a non-animted paint file into the program\
  8486.     Params: path:string = The path in which the file is located\
  8487.     Returns:nil\
  8488. ]]--\
  8489. local function loadNFP(path)\
  8490.     sFrame = 1\
  8491.     frames[sFrame] = { }\
  8492.     if fs.exists(path) then\
  8493.         local file = io.open(path, \"r\" )\
  8494.         local sLine = file:read()\
  8495.         local num = 1\
  8496.         while sLine do\
  8497.             table.insert(frames[sFrame], num, {})\
  8498.             for i=1,#sLine do\
  8499.                 frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))\
  8500.             end\
  8501.             num = num+1\
  8502.             sLine = file:read()\
  8503.         end\
  8504.         file:close()\
  8505.     end\
  8506. end\
  8507. \
  8508. --[[Saves a non-animated paint file to the specified path\
  8509.     Params: path:string = The path to save the file to\
  8510.     Returns:nil\
  8511. ]]--\
  8512. local function saveNFP(path)\
  8513.     local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))\
  8514.     if not fs.exists(sDir) then\
  8515.         fs.makeDir(sDir)\
  8516.     end\
  8517. \
  8518.     local file = io.open(path, \"w\")\
  8519.     updateImageLims(false)\
  8520.     if not toplim then \
  8521.         file:close()\
  8522.         return\
  8523.     end\
  8524.     for y=1,botlim do\
  8525.         local line = \"\"\
  8526.         if frames[sFrame][y] then \
  8527.             for x=1,riglim do\
  8528.                 line = line..getHexOf(frames[sFrame][y][x])\
  8529.             end\
  8530.         end\
  8531.         file:write(line..\"\\n\")\
  8532.     end\
  8533.     file:close()\
  8534. end\
  8535. \
  8536. --[[Loads an animated paint file into the program\
  8537.     Params: path:string = The path in which the file is located\
  8538.     Returns:nil\
  8539. ]]--\
  8540. local function loadNFA(path)\
  8541.     frames[sFrame] = { }\
  8542.     if fs.exists(path) then\
  8543.         local file = io.open(path, \"r\" )\
  8544.         local sLine = file:read()\
  8545.         local num = 1\
  8546.         while sLine do\
  8547.             table.insert(frames[sFrame], num, {})\
  8548.             if sLine == \"~\" then\
  8549.                 sFrame = sFrame + 1\
  8550.                 frames[sFrame] = { }\
  8551.                 num = 1\
  8552.             else\
  8553.                 for i=1,#sLine do\
  8554.                     frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))\
  8555.                 end\
  8556.                 num = num+1\
  8557.             end\
  8558.             sLine = file:read()\
  8559.         end\
  8560.         file:close()\
  8561.     end\
  8562.     framecount = sFrame\
  8563.     sFrame = 1\
  8564. end\
  8565. \
  8566. --[[Saves a animated paint file to the specified path\
  8567.     Params: path:string = The path to save the file to\
  8568.     Returns:nil\
  8569. ]]--\
  8570. local function saveNFA(path)\
  8571.     local file = io.open(path, \"w\")\
  8572.     updateImageLims(true)\
  8573.     if not toplim then \
  8574.         file:close()\
  8575.         return\
  8576.     end\
  8577.     for i=1,#frames do\
  8578.         for y=1,botlim do\
  8579.             local line = \"\"\
  8580.             if frames[i][y] then \
  8581.                 for x=1,riglim do\
  8582.                     line = line..getHexOf(frames[i][y][x])\
  8583.                 end\
  8584.             end\
  8585.             file:write(line..\"\\n\")\
  8586.         end\
  8587.         if i < #frames then file:write(\"~\\n\") end\
  8588.     end\
  8589.     file:close()\
  8590. end\
  8591. \
  8592. --[[Initializes the program, by loading in the paint file. Called at the start of each program.\
  8593.     Params: none\
  8594.     Returns:nil\
  8595. ]]--\
  8596. local function init()\
  8597.     if animated then \
  8598.         loadNFA(sPath)\
  8599.         table.insert(ddModes, #ddModes, { \"record\", \"play\", name = \"anim\" })\
  8600.         table.insert(ddModes, #ddModes, { \"go to\", \"remove\", name = \"frames\"})\
  8601.     else loadNFP(sPath) end\
  8602. \
  8603.     for i=0,15 do\
  8604.         table.insert(column, math.pow(2,i))\
  8605.     end\
  8606. end\
  8607. \
  8608. --[[  \
  8609.             Section: Drawing  \
  8610. ]]--\
  8611. \
  8612. \
  8613. --[[Draws the rather superflous logo. Takes about 1 second, before user is able to move to the\
  8614.     actual program.\
  8615.     Params: none\
  8616.     Returns:nil\
  8617. ]]--\
  8618. local function drawLogo()\
  8619.     term.setBackgroundColour(colours.white)\
  8620.     term.clear()\
  8621.     drawPictureTable(logo, w/2 - #logo[1]/2, h/2 - #logo/2, colours.white)\
  8622.     term.setBackgroundColour(colours.white)\
  8623.     term.setTextColour(colours.black)\
  8624.     local msg = \"NPaintPro\"\
  8625.     term.setCursorPos(w/2 - #msg/2, h-3)\
  8626.     term.write(msg)\
  8627.     msg = \"By NitrogenFingers\"\
  8628.     term.setCursorPos(w/2 - #msg/2, h-2)\
  8629.     term.write(msg)\
  8630.     msg = \"Thanks to faubiguy for testing\"\
  8631.     term.setCursorPos(w/2 - #msg/2, h)\
  8632.     term.write(msg)\
  8633.     \
  8634.     os.pullEvent()\
  8635. end\
  8636. \
  8637. --[[Clears the display to the alpha channel colour, draws the canvas, the image buffer and the selection\
  8638.     rectanlge if any of these things are present.\
  8639.     Params: none\
  8640.     Returns:nil\
  8641. ]]--\
  8642. local function drawCanvas()\
  8643.     --We have to readjust the position of the canvas if we're printing\
  8644.     turtlechar = \"@\"\
  8645.     if state == \"active print\" then\
  8646.         if layering == \"up\" then\
  8647.             if py >= 1 and py <= #frames then\
  8648.                 sFrame = py\
  8649.             end\
  8650.             if pz < sy then sy = pz\
  8651.             elseif pz > sy + h - 1 then sy = pz + h - 1 end\
  8652.             if px < sx then sx = px\
  8653.             elseif px > sx + w - 2 then sx = px + w - 2 end\
  8654.         else\
  8655.             if pz >= 1 and pz <= #frames then\
  8656.                 sFrame = pz\
  8657.             end\
  8658.             \
  8659.             if py < sy then sy = py\
  8660.             elseif py > sy + h - 1 then sy = py + h - 1 end\
  8661.             if px < sx then sx = px\
  8662.             elseif px > sx + w - 2 then sx = px + w - 2 end\
  8663.         end\
  8664.         \
  8665.         if pfx == 1 then turtlechar = \">\"\
  8666.         elseif pfx == -1 then turtlechar = \"<\"\
  8667.         elseif pfz == 1 then turtlechar = \"V\"\
  8668.         elseif pfz == -1 then turtlechar = \"^\"\
  8669.         end\
  8670.     end\
  8671. \
  8672.     --Picture next\
  8673.     local topLayer, botLayer\
  8674.     if layerDisplay then\
  8675.         topLayer = sFrame\
  8676.         botLayer = 1\
  8677.     else\
  8678.         topLayer,botLayer = sFrame,sFrame\
  8679.     end\
  8680.     \
  8681.     for currframe = botLayer,topLayer,1 do\
  8682.         for y=sy+1,sy+h-1 do\
  8683.             if frames[currframe][y] then \
  8684.                 for x=sx+1,sx+w-2 do\
  8685.                     term.setCursorPos(x-sx,y-sy)\
  8686.                     if frames[currframe][y][x] then\
  8687.                         term.setBackgroundColour(frames[currframe][y][x])\
  8688.                         term.write(\" \")\
  8689.                     else \
  8690.                         tileExists = false\
  8691.                         for i=currframe-1,botLayer,-1 do\
  8692.                             if frames[i][y][x] then\
  8693.                                 tileExists = true\
  8694.                                 break\
  8695.                             end\
  8696.                         end\
  8697.                         \
  8698.                         if not tileExists then\
  8699.                             if blueprint then\
  8700.                                 term.setBackgroundColour(colours.blue)\
  8701.                                 term.setTextColour(colours.white)\
  8702.                                 if x == sx+1 and y % 4 == 1 then\
  8703.                                     term.write(\"\"..((y/4) % 10))\
  8704.                                 elseif y == sy + 1 and x % 4 == 1 then\
  8705.                                     term.write(\"\"..((x/4) % 10))\
  8706.                                 elseif x % 2 == 1 and y % 2 == 1 then\
  8707.                                     term.write(\"+\")\
  8708.                                 elseif x % 2 == 1 then\
  8709.                                     term.write(\"|\")\
  8710.                                 elseif y % 2 == 1 then\
  8711.                                     term.write(\"-\")\
  8712.                                 else\
  8713.                                     term.write(\" \")\
  8714.                                 end\
  8715.                             else\
  8716.                                 term.setBackgroundColour(alphaC) \
  8717.                                 term.write(\" \")\
  8718.                             end\
  8719.                         end\
  8720.                     end\
  8721.                 end\
  8722.             else\
  8723.                 for x=sx+1,sx+w-2 do\
  8724.                     term.setCursorPos(x-sx,y-sy)\
  8725.                     \
  8726.                     tileExists = false\
  8727.                     for i=currframe-1,botLayer,-1 do\
  8728.                         if frames[i][y] and frames[i][y][x] then\
  8729.                             tileExists = true\
  8730.                             break\
  8731.                         end\
  8732.                     end\
  8733.                     \
  8734.                     if not tileExists then\
  8735.                         if blueprint then\
  8736.                             term.setBackgroundColour(colours.blue)\
  8737.                             term.setTextColour(colours.white)\
  8738.                             if x == sx+1 and y % 4 == 1 then\
  8739.                                 term.write(\"\"..((y/4) % 10))\
  8740.                             elseif y == sy + 1 and x % 4 == 1 then\
  8741.                                 term.write(\"\"..((x/4) % 10))\
  8742.                             elseif x % 2 == 1 and y % 2 == 1 then\
  8743.                                 term.write(\"+\")\
  8744.                             elseif x % 2 == 1 then\
  8745.                                 term.write(\"|\")\
  8746.                             elseif y % 2 == 1 then\
  8747.                                 term.write(\"-\")\
  8748.                             else\
  8749.                                 term.write(\" \")\
  8750.                             end\
  8751.                         else\
  8752.                             term.setBackgroundColour(alphaC) \
  8753.                             term.write(\" \")\
  8754.                         end\
  8755.                     end\
  8756.                 end\
  8757.             end\
  8758.         end\
  8759.     end\
  8760.     \
  8761.     --Then the printer, if he's on\
  8762.     if state == \"active print\" then\
  8763.         local bgColour = alphaC\
  8764.         if layering == \"up\" then\
  8765.             term.setCursorPos(px-sx,pz-sy)\
  8766.             if frames[sFrame] and frames[sFrame][pz-sy] and frames[sFrame][pz-sy][px-sx] then\
  8767.                 bgColour = frames[sFrame][pz-sy][px-sx]\
  8768.             elseif blueprint then bgColour = colours.blue end\
  8769.         else\
  8770.             term.setCursorPos(px-sx,py-sy)\
  8771.             if frames[sFrame] and frames[sFrame][py-sy] and frames[sFrame][py-sy][px-sx] then\
  8772.                 bgColour = frames[sFrame][py-sy][px-sx]\
  8773.             elseif blueprint then bgColour = colours.blue end\
  8774.         end\
  8775.         \
  8776.         term.setBackgroundColour(bgColour)\
  8777.         if bgColour == colours.black then term.setTextColour(colours.white)\
  8778.         else term.setTextColour(colours.black) end\
  8779.         \
  8780.         term.write(turtlechar)\
  8781.     end\
  8782.     \
  8783.     --Then the buffer\
  8784.     if selectrect then\
  8785.         if buffer and rectblink == 1 then\
  8786.         for y=selectrect.y1, math.min(selectrect.y2, selectrect.y1 + buffer.height-1) do\
  8787.             for x=selectrect.x1, math.min(selectrect.x2, selectrect.x1 + buffer.width-1) do\
  8788.                 if buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1] then\
  8789.                     term.setCursorPos(x+sx,y+sy)\
  8790.                     term.setBackgroundColour(buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1])\
  8791.                     term.write(\" \")\
  8792.                 end\
  8793.             end\
  8794.         end\
  8795.         end\
  8796.     \
  8797.         --This draws the \"selection\" box\
  8798.         local add = nil\
  8799.         if buffer then\
  8800.             term.setBackgroundColour(colours.lightGrey)\
  8801.         else \
  8802.             term.setBackgroundColour(colours.grey)\
  8803.         end\
  8804.         for i=selectrect.x1, selectrect.x2 do\
  8805.             add = (i + selectrect.y1 + rectblink) % 2 == 0\
  8806.             term.setCursorPos(i-sx,selectrect.y1-sy)\
  8807.             if add then term.write(\" \") end\
  8808.             add = (i + selectrect.y2 + rectblink) % 2 == 0\
  8809.             term.setCursorPos(i-sx,selectrect.y2-sy)\
  8810.             if add then term.write(\" \") end\
  8811.         end\
  8812.         for i=selectrect.y1 + 1, selectrect.y2 - 1 do\
  8813.             add = (i + selectrect.x1 + rectblink) % 2 == 0\
  8814.             term.setCursorPos(selectrect.x1-sx,i-sy)\
  8815.             if add then term.write(\" \") end\
  8816.             add = (i + selectrect.x2 + rectblink) % 2 == 0\
  8817.             term.setCursorPos(selectrect.x2-sx,i-sy)\
  8818.             if add then term.write(\" \") end\
  8819.         end\
  8820.     end\
  8821. end\
  8822. \
  8823. --[[Draws the colour picker on the right side of the screen, the colour pallette and the footer with any \
  8824.     messages currently being displayed\
  8825.     Params: none\
  8826.     Returns:nil\
  8827. ]]--\
  8828. local function drawInterface()\
  8829.     --Picker\
  8830.     for i=1,#column do\
  8831.         term.setCursorPos(w-1, i)\
  8832.         term.setBackgroundColour(column[i])\
  8833.         if state == \"print\" then\
  8834.             if i == 16 then\
  8835.                 term.setTextColour(colours.white)\
  8836.             else\
  8837.                 term.setTextColour(colours.black)\
  8838.             end\
  8839.             if requirementsDisplayed then\
  8840.                 if requiredMaterials[i] < 10 then term.write(\" \") end\
  8841.                 term.setCursorPos(w-#tostring(requiredMaterials[i])+1, i)\
  8842.                 term.write(requiredMaterials[i])\
  8843.             else\
  8844.                 if i < 10 then term.write(\" \") end\
  8845.                 term.write(i)\
  8846.             end\
  8847.         else\
  8848.             term.write(\"  \")\
  8849.         end\
  8850.     end\
  8851.     term.setCursorPos(w-1,#column+1)\
  8852.     term.setBackgroundColour(colours.black)\
  8853.     term.setTextColour(colours.red)\
  8854.     term.write(\"XX\")\
  8855.     --Pallette\
  8856.     term.setCursorPos(w-1,h-1)\
  8857.     if not lSel then\
  8858.         term.setBackgroundColour(colours.black)\
  8859.         term.setTextColour(colours.red)\
  8860.         term.write(\"X\")\
  8861.     else\
  8862.         term.setBackgroundColour(lSel)\
  8863.         term.setTextColour(lSel)\
  8864.         term.write(\" \")\
  8865.     end\
  8866.     if not rSel then\
  8867.         term.setBackgroundColour(colours.black)\
  8868.         term.setTextColour(colours.red)\
  8869.         term.write(\"X\")\
  8870.     else\
  8871.         term.setBackgroundColour(rSel)\
  8872.         term.setTextColour(rSel)\
  8873.         term.write(\" \")\
  8874.     end\
  8875.     --Footer\
  8876.     if inMenu then return end\
  8877.     \
  8878.     term.setCursorPos(1, h)\
  8879.     term.setBackgroundColour(colours.lightGrey)\
  8880.     term.setTextColour(colours.grey)\
  8881.     term.clearLine()\
  8882.     if inDropDown then\
  8883.         term.write(string.rep(\" \", 6))\
  8884.     else\
  8885.         term.setBackgroundColour(colours.grey)\
  8886.         term.setTextColour(colours.lightGrey)\
  8887.         term.write(\"menu  \")\
  8888.     end\
  8889.     term.setBackgroundColour(colours.lightGrey)\
  8890.     term.setTextColour(colours.grey)\
  8891.     term.write(getStateMessage())\
  8892.     \
  8893.     local coords=\"X:\"..sx..\" Y:\"..sy\
  8894.     if animated then coords = coords..\" Frame:\"..sFrame..\"/\"..framecount..\"   \" end\
  8895.     term.setCursorPos(w-#coords+1,h)\
  8896.     if state == \"play\" then term.setBackgroundColour(colours.lime)\
  8897.     elseif record then term.setBackgroundColour(colours.red) end\
  8898.     term.write(coords)\
  8899.     \
  8900.     if animated then\
  8901.         term.setCursorPos(w-1,h)\
  8902.         term.setBackgroundColour(colours.grey)\
  8903.         term.setTextColour(colours.lightGrey)\
  8904.         term.write(\"<>\")\
  8905.     end\
  8906. end\
  8907. \
  8908. --[[Runs an interface where users can select topics of help. Will return once the user quits the help screen.\
  8909.     Params: none\
  8910.     Returns:nil\
  8911. ]]--\
  8912. local function drawHelpScreen()\
  8913.     local selectedHelp = nil\
  8914.     while true do\
  8915.         term.setBackgroundColour(colours.lightGrey)\
  8916.         term.clear()\
  8917.         if not selectedHelp then\
  8918.             term.setCursorPos(4, 1)\
  8919.             term.setTextColour(colours.brown)\
  8920.             term.write(\"Available modes (click for info):\")\
  8921.             for i=1,#helpTopics do\
  8922.                 term.setCursorPos(2, 2 + i)\
  8923.                 term.setTextColour(colours.black)\
  8924.                 term.write(helpTopics[i].name)\
  8925.                 if helpTopics[i].key then\
  8926.                     term.setTextColour(colours.red)\
  8927.                     term.write(\" (\"..helpTopics[i].key..\")\")\
  8928.                 end\
  8929.             end\
  8930.             term.setCursorPos(4,h)\
  8931.             term.setTextColour(colours.black)\
  8932.             term.write(\"Press any key to exit\")\
  8933.         else\
  8934.             term.setCursorPos(4,1)\
  8935.             term.setTextColour(colours.brown)\
  8936.             term.write(helpTopics[selectedHelp].name)\
  8937.             if helpTopics[selectedHelp].key then\
  8938.                 term.setTextColour(colours.red)\
  8939.                 term.write(\" (\"..helpTopics[selectedHelp].key..\")\")\
  8940.             end\
  8941.             term.setCursorPos(1,3)\
  8942.             term.setTextColour(colours.black)\
  8943.             print(helpTopics[selectedHelp].message..\"\\n\")\
  8944.             for i=1,#helpTopics[selectedHelp].controls do\
  8945.                 term.setTextColour(colours.brown)\
  8946.                 term.write(helpTopics[selectedHelp].controls[i][1]..\" \")\
  8947.                 term.setTextColour(colours.black)\
  8948.                 print(helpTopics[selectedHelp].controls[i][2])\
  8949.             end\
  8950.         end\
  8951.         \
  8952.         local id,p1,p2,p3 = os.pullEvent()\
  8953.         \
  8954.         if id == \"timer\" then updateTimer(p1)\
  8955.         elseif id == \"key\" then \
  8956.             if selectedHelp then selectedHelp = nil\
  8957.             else break end\
  8958.         elseif id == \"mouse_click\" then\
  8959.             if not selectedHelp then \
  8960.                 if p3 >=3 and p3 <= 2+#helpTopics then\
  8961.                     selectedHelp = p3-2 \
  8962.                 else break end\
  8963.             else\
  8964.                 selectedHelp = nil\
  8965.             end\
  8966.         end\
  8967.     end\
  8968. end\
  8969. \
  8970. --[[Draws a message in the footer bar. A helper for DrawInterface, but can be called for custom messages, if the\
  8971.     inMenu paramter is set to true while this is being done (remember to set it back when done!)\
  8972.     Params: message:string = The message to be drawn\
  8973.     Returns:nil\
  8974. ]]--\
  8975. local function drawMessage(message)\
  8976.     term.setCursorPos(1,h)\
  8977.     term.setBackgroundColour(colours.lightGrey)\
  8978.     term.setTextColour(colours.grey)\
  8979.     term.clearLine()\
  8980.     term.write(message)\
  8981. end\
  8982. \
  8983. --[[\
  8984.             Section: Generic Interfaces\
  8985. ]]--\
  8986. \
  8987. \
  8988. --[[One of my generic text printing methods, printing a message at a specified position with width and offset.\
  8989.     No colour materials included.\
  8990.     Params: msg:string = The message to print off-center\
  8991.             height:number = The starting height of the message\
  8992.             width:number = The limit as to how many characters long each line may be\
  8993.             offset:number = The starting width offset of the message\
  8994.     Returns:number the number of lines used in printing the message\
  8995. ]]--\
  8996. local function wprintOffCenter(msg, height, width, offset)\
  8997.     local inc = 0\
  8998.     local ops = 1\
  8999.     while #msg - ops > width do\
  9000.         local nextspace = 0\
  9001.         while string.find(msg, \" \", ops + nextspace) and\
  9002.                 string.find(msg, \" \", ops + nextspace) - ops < width do\
  9003.             nextspace = string.find(msg, \" \", nextspace + ops) + 1 - ops\
  9004.         end\
  9005.         local ox,oy = term.getCursorPos()\
  9006.         term.setCursorPos(width/2 - (nextspace)/2 + offset, height + inc)\
  9007.         inc = inc + 1\
  9008.         term.write(string.sub(msg, ops, nextspace + ops - 1))\
  9009.         ops = ops + nextspace\
  9010.     end\
  9011.     term.setCursorPos(width/2 - #string.sub(msg, ops)/2 + offset, height + inc)\
  9012.     term.write(string.sub(msg, ops))\
  9013.     \
  9014.     return inc + 1\
  9015. end\
  9016. \
  9017. --[[Draws a message that must be clicked on or a key struck to be cleared. No options, so used for displaying\
  9018.     generic information.\
  9019.     Params: ctitle:string = The title of the confirm dialogue\
  9020.             msg:string = The message displayed in the dialogue\
  9021.     Returns:nil\
  9022. ]]--\
  9023. local function displayConfirmDialogue(ctitle, msg)\
  9024.     local dialogoffset = 8\
  9025.     --We actually print twice- once to get the lines, second time to print proper. Easier this way.\
  9026.     local lines = wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)\
  9027.     \
  9028.     term.setCursorPos(dialogoffset, 3)\
  9029.     term.setBackgroundColour(colours.grey)\
  9030.     term.setTextColour(colours.lightGrey)\
  9031.     term.write(string.rep(\" \", w - dialogoffset * 2))\
  9032.     term.setCursorPos(dialogoffset + (w - dialogoffset * 2)/2 - #ctitle/2, 3)\
  9033.     term.write(ctitle)\
  9034.     term.setTextColour(colours.grey)\
  9035.     term.setBackgroundColour(colours.lightGrey)\
  9036.     term.setCursorPos(dialogoffset, 4)\
  9037.     term.write(string.rep(\" \", w - dialogoffset * 2))\
  9038.     for i=5,5+lines do\
  9039.         term.setCursorPos(dialogoffset, i) \
  9040.         term.write(\" \"..string.rep(\" \", w - (dialogoffset) * 2 - 2)..\" \")\
  9041.     end\
  9042.     wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)\
  9043.     \
  9044.     --In the event of a message, the player hits anything to continue\
  9045.     while true do\
  9046.         local id,key = os.pullEvent()\
  9047.         if id == \"timer\" then updateTimer(key);\
  9048.         elseif id == \"key\" or id == \"mouse_click\" or id == \"mouse_drag\" then break end\
  9049.     end\
  9050. end\
  9051. \
  9052. --[[Produces a nice dropdown menu based on a table of strings. Depending on the position, this will auto-adjust the position\
  9053.     of the menu drawn, and allows nesting of menus and sub menus. Clicking anywhere outside the menu will cancel and return nothing\
  9054.     Params: x:int = the x position the menu should be displayed at\
  9055.             y:int = the y position the menu should be displayed at\
  9056.             options:table = the list of options available to the user, as strings or submenus (tables of strings, with a name parameter)\
  9057.     Returns:string the selected menu option.\
  9058. ]]--\
  9059. local function displayDropDown(x, y, options)\
  9060.     inDropDown = true\
  9061.     --Figures out the dimensions of our thing\
  9062.     local longestX = #options.name\
  9063.     for i=1,#options do\
  9064.         local currVal = options[i]\
  9065.         if type(currVal) == \"table\" then currVal = currVal.name end\
  9066.         \
  9067.         longestX = math.max(longestX, #currVal)\
  9068.     end\
  9069.     local xOffset = math.max(0, longestX - ((w-2) - x) + 1)\
  9070.     local yOffset = math.max(0, #options - ((h-1) - y))\
  9071.     \
  9072.     local clickTimes = 0\
  9073.     local tid = nil\
  9074.     local selection = nil\
  9075.     while clickTimes < 2 do\
  9076.         drawCanvas()\
  9077.         drawInterface()\
  9078.         \
  9079.         term.setCursorPos(x-xOffset,y-yOffset)\
  9080.         term.setBackgroundColour(colours.grey)\
  9081.         term.setTextColour(colours.lightGrey)\
  9082.         term.write(options.name..string.rep(\" \", longestX-#options.name + 2))\
  9083.     \
  9084.         for i=1,#options do\
  9085.             term.setCursorPos(x-xOffset, y-yOffset+i)\
  9086.             if i==selection and clickTimes % 2 == 0 then\
  9087.                 term.setBackgroundColour(colours.grey)\
  9088.                 term.setTextColour(colours.lightGrey)\
  9089.             else\
  9090.                 term.setBackgroundColour(colours.lightGrey)\
  9091.                 term.setTextColour(colours.grey)\
  9092.             end\
  9093.             local currVal = options[i]\
  9094.             if type(currVal) == \"table\" then \
  9095.                 term.write(currVal.name..string.rep(\" \", longestX-#currVal.name + 1))\
  9096.                 term.setBackgroundColour(colours.grey)\
  9097.                 term.setTextColour(colours.lightGrey)\
  9098.                 term.write(\">\")\
  9099.             else\
  9100.                 term.write(currVal..string.rep(\" \", longestX-#currVal + 2))\
  9101.             end\
  9102.         end\
  9103.         \
  9104.         local id, p1, p2, p3 = os.pullEvent()\
  9105.         if id == \"timer\" then\
  9106.             if p1 == tid then \
  9107.                 clickTimes = clickTimes + 1\
  9108.                 if clickTimes > 2 then \
  9109.                     break\
  9110.                 else \
  9111.                     tid = os.startTimer(0.1) \
  9112.                 end\
  9113.             else \
  9114.                 updateTimer(p1) \
  9115.                 drawCanvas()\
  9116.                 drawInterface()\
  9117.             end\
  9118.         elseif id == \"mouse_click\" then\
  9119.             if p2 >=x-xOffset and p2 <= x-xOffset + longestX + 1 and p3 >= y-yOffset+1 and p3 <= y-yOffset+#options then\
  9120.                 selection = p3-(y-yOffset)\
  9121.                 tid = os.startTimer(0.1)\
  9122.             else\
  9123.                 selection = \"\"\
  9124.                 break\
  9125.             end\
  9126.         end\
  9127.     end\
  9128.     \
  9129.     if type(selection) == \"number\" then\
  9130.         selection = options[selection]\
  9131.     end\
  9132.     \
  9133.     if type(selection) == \"string\" then \
  9134.         inDropDown = false\
  9135.         return selection\
  9136.     elseif type(selection) == \"table\" then \
  9137.         return displayDropDown(x, y, selection)\
  9138.     end\
  9139. end\
  9140. \
  9141. --[[A custom io.read() function with a few differences- it limits the number of characters being printed,\
  9142.     waits a 1/100th of a second so any keys still in the event library are removed before input is read and\
  9143.     the timer for the selectionrectangle is continuously updated during the process.\
  9144.     Params: lim:int = the number of characters input is allowed\
  9145.     Returns:string the inputted string, trimmed of leading and tailing whitespace\
  9146. ]]--\
  9147. local function readInput(lim)\
  9148.     term.setCursorBlink(true)\
  9149. \
  9150.     local inputString = \"\"\
  9151.     if not lim or type(lim) ~= \"number\" or lim < 1 then lim = w - ox end\
  9152.     local ox,oy = term.getCursorPos()\
  9153.     --We only get input from the footer, so this is safe. Change if recycling\
  9154.     term.setBackgroundColour(colours.lightGrey)\
  9155.     term.setTextColour(colours.grey)\
  9156.     term.write(string.rep(\" \", lim))\
  9157.     term.setCursorPos(ox, oy)\
  9158.     --As events queue immediately, we may get an unwanted key... this will solve that problem\
  9159.     local inputTimer = os.startTimer(0.01)\
  9160.     local keysAllowed = false\
  9161.     \
  9162.     while true do\
  9163.         local id,key = os.pullEvent()\
  9164.         \
  9165.         if keysAllowed then\
  9166.             if id == \"key\" and key == 14 and #inputString > 0 then\
  9167.                 inputString = string.sub(inputString, 1, #inputString-1)\
  9168.                 term.setCursorPos(ox + #inputString,oy)\
  9169.                 term.write(\" \")\
  9170.             elseif id == \"key\" and key == 28 and inputString ~= string.rep(\" \", #inputString) then \
  9171.                 break\
  9172.             elseif id == \"key\" and key == keys.leftCtrl then\
  9173.                 return \"\"\
  9174.             elseif id == \"char\" and #inputString < lim then\
  9175.                 inputString = inputString..key\
  9176.             end\
  9177.         end\
  9178.         \
  9179.         if id == \"timer\" then\
  9180.             if key == inputTimer then \
  9181.                 keysAllowed = true\
  9182.             else\
  9183.                 updateTimer(key)\
  9184.                 drawCanvas()\
  9185.                 drawInterface()\
  9186.                 term.setBackgroundColour(colours.lightGrey)\
  9187.                 term.setTextColour(colours.grey)\
  9188.             end\
  9189.         end\
  9190.         term.setCursorPos(ox,oy)\
  9191.         term.write(inputString)\
  9192.         term.setCursorPos(ox + #inputString, oy)\
  9193.     end\
  9194.     \
  9195.     while string.sub(inputString, 1, 1) == \" \" do\
  9196.         inputString = string.sub(inputString, 2, #inputString)\
  9197.     end\
  9198.     while string.sub(inputString, #inputString, #inputString) == \" \" do\
  9199.         inputString = string.sub(inputString, 1, #inputString-1)\
  9200.     end\
  9201.     term.setCursorBlink(false)\
  9202.     \
  9203.     return inputString\
  9204. end\
  9205. \
  9206. --[[  \
  9207.             Section: Image tools \
  9208. ]]--\
  9209. \
  9210. \
  9211. --[[Copies all pixels beneath the selection rectangle into the image buffer. Empty buffers are converted to nil.\
  9212.     Params: removeImage:bool = true if the image is to be erased after copying, false otherwise\
  9213.     Returns:nil\
  9214. ]]--\
  9215. local function copyToBuffer(removeImage)\
  9216.     buffer = { width = selectrect.x2 - selectrect.x1 + 1, height = selectrect.y2 - selectrect.y1 + 1, contents = { } }\
  9217.     \
  9218.     local containsSomething = false\
  9219.     for y=1,buffer.height do\
  9220.         buffer.contents[y] = { }\
  9221.         local f,l = sFrame,sFrame\
  9222.         if record then f,l = 1, framecount end\
  9223.         \
  9224.         for fra = f,l do\
  9225.             if frames[fra][selectrect.y1 + y - 1] then\
  9226.                 for x=1,buffer.width do\
  9227.                     buffer.contents[y][x] = frames[sFrame][selectrect.y1 + y - 1][selectrect.x1 + x - 1]\
  9228.                     if removeImage then frames[fra][selectrect.y1 + y - 1][selectrect.x1 + x - 1] = nil end\
  9229.                     if buffer.contents[y][x] then containsSomething = true end\
  9230.                 end\
  9231.             end\
  9232.         end\
  9233.     end\
  9234.     --I don't classify an empty buffer as a real buffer- confusing to the user.\
  9235.     if not containsSomething then buffer = nil end\
  9236. end\
  9237. \
  9238. --[[Replaces all pixels under the selection rectangle with the image buffer (or what can be seen of it). Record-dependent.\
  9239.     Params: removeBuffer:bool = true if the buffer is to be emptied after copying, false otherwise\
  9240.     Returns:nil\
  9241. ]]--\
  9242. local function copyFromBuffer(removeBuffer)\
  9243.     if not buffer then return end\
  9244. \
  9245.     for y = 1, math.min(buffer.height,selectrect.y2-selectrect.y1+1) do\
  9246.         local f,l = sFrame, sFrame\
  9247.         if record then f,l = 1, framecount end\
  9248.         \
  9249.         for fra = f,l do\
  9250.             if not frames[fra][selectrect.y1+y-1] then frames[fra][selectrect.y1+y-1] = { } end\
  9251.             for x = 1, math.min(buffer.width,selectrect.x2-selectrect.x1+1) do\
  9252.                 frames[fra][selectrect.y1+y-1][selectrect.x1+x-1] = buffer.contents[y][x]\
  9253.             end\
  9254.         end\
  9255.     end\
  9256.     \
  9257.     if removeBuffer then buffer = nil end\
  9258. end\
  9259. \
  9260. --[[Moves the entire image (or entire animation) to the specified coordinates. Record-dependent.\
  9261.     Params: newx:int = the X coordinate to move the image to\
  9262.             newy:int = the Y coordinate to move the image to\
  9263.     Returns:nil\
  9264. ]]--\
  9265. local function moveImage(newx,newy)\
  9266.     if not leflim or not toplim then return end\
  9267.     if newx <=0 or newy <=0 then return end\
  9268.     local f,l = sFrame,sFrame\
  9269.     if record then f,l = 1,framecount end\
  9270.     \
  9271.     for i=f,l do\
  9272.         local newlines = { }\
  9273.         for y,line in pairs(frames[i]) do\
  9274.             newlines[y-toplim+newy] = { }\
  9275.             for x,char in pairs(line) do\
  9276.                 newlines[y-toplim+newy][x-leflim+newx] = char\
  9277.             end\
  9278.         end\
  9279.         frames[i] = newlines\
  9280.     end\
  9281. end\
  9282. \
  9283. --[[Prompts the user to clear the current frame or all frames. Record-dependent.,\
  9284.     Params: none\
  9285.     Returns:nil\
  9286. ]]--\
  9287. local function clearImage()\
  9288.     inMenu = true\
  9289.     if not animated then\
  9290.         drawMessage(\"Clear image? Y/N: \")\
  9291.     elseif record then\
  9292.         drawMessage(\"Clear ALL frames? Y/N: \")\
  9293.     else\
  9294.         drawMessage(\"Clear current frame? Y/N :\")\
  9295.     end\
  9296.     if string.find(string.upper(readInput(1)), \"Y\") then\
  9297.         local f,l = sFrame,sFrame\
  9298.         if record then f,l = 1,framecount end\
  9299.         \
  9300.         for i=f,l do\
  9301.             frames[i] = { }\
  9302.         end\
  9303.     end\
  9304.     inMenu = false\
  9305. end\
  9306. \
  9307. --[[A recursively called method (watch out for big calls!) in which every pixel of a set colour is\
  9308.     changed to another colour. Does not work on the nil colour, for obvious reasons.\
  9309.     Params: x:int = The X coordinate of the colour to flood-fill\
  9310.             y:int = The Y coordinate of the colour to flood-fill\
  9311.             targetColour:colour = the colour that is being flood-filled\
  9312.             newColour:colour = the colour with which to replace the target colour\
  9313.     Returns:nil\
  9314. ]]--\
  9315. local function floodFill(x, y, targetColour, newColour)\
  9316.     if not newColour or not targetColour then return end\
  9317.     local nodeList = { }\
  9318.     \
  9319.     table.insert(nodeList, {x = x, y = y})\
  9320.     \
  9321.     while #nodeList > 0 do\
  9322.         local node = nodeList[1]\
  9323.         if frames[sFrame][node.y] and frames[sFrame][node.y][node.x] == targetColour then\
  9324.             frames[sFrame][node.y][node.x] = newColour\
  9325.             table.insert(nodeList, { x = node.x + 1, y = node.y})\
  9326.             table.insert(nodeList, { x = node.x, y = node.y + 1})\
  9327.             if x > 1 then table.insert(nodeList, { x = node.x - 1, y = node.y}) end\
  9328.             if y > 1 then table.insert(nodeList, { x = node.x, y = node.y - 1}) end\
  9329.         end\
  9330.         table.remove(nodeList, 1)\
  9331.     end\
  9332. end\
  9333. \
  9334. --[[  \
  9335.             Section: Animation Tools  \
  9336. ]]--\
  9337. \
  9338. --[[Enters play mode, allowing the animation to play through. Interface is restricted to allow this,\
  9339.     and method only leaves once the player leaves play mode.\
  9340.     Params: none\
  9341.     Returns:nil\
  9342. ]]--\
  9343. local function playAnimation()\
  9344.     state = \"play\"\
  9345.     selectedrect = nil\
  9346.     \
  9347.     local animt = os.startTimer(animtime)\
  9348.     repeat\
  9349.         drawCanvas()\
  9350.         drawInterface()\
  9351.         \
  9352.         local id,key,_,y = os.pullEvent()\
  9353.         \
  9354.         if id==\"timer\" then\
  9355.             if key == animt then\
  9356.                 animt = os.startTimer(animtime)\
  9357.                 sFrame = (sFrame % framecount) + 1\
  9358.             else\
  9359.                 updateTimer(key)\
  9360.             end\
  9361.         elseif id==\"key\" then\
  9362.             if key == keys.comma and animtime > 0.1 then animtime = animtime - 0.05\
  9363.             elseif key == keys.period and animtime < 0.5 then animtime = animtime + 0.05\
  9364.             elseif key == keys.space then state = \"paint\" end\
  9365.         elseif id==\"mouse_click\" and y == h then\
  9366.             state = \"paint\"\
  9367.         end\
  9368.     until state ~= \"play\"\
  9369.     os.startTimer(0.5)\
  9370. end\
  9371. \
  9372. --[[Changes the selected frame (sFrame) to the chosen frame. If this frame is above the framecount,\
  9373.     additional frames are created with a copy of the image on the selected frame.\
  9374.     Params: newframe:int = the new frame to move to\
  9375.     Returns:nil\
  9376. ]]--\
  9377. local function changeFrame(newframe)\
  9378.     inMenu = true\
  9379.     if not tonumber(newframe) then\
  9380.         term.setCursorPos(1,h)\
  9381.         term.setBackgroundColour(colours.lightGrey)\
  9382.         term.setTextColour(colours.grey)\
  9383.         term.clearLine()\
  9384.     \
  9385.         term.write(\"Go to frame: \")\
  9386.         newframe = tonumber(readInput(2))\
  9387.         if not newframe or newframe <= 0 then\
  9388.             inMenu = false\
  9389.             return \
  9390.         end\
  9391.     elseif newframe <= 0 then return end\
  9392.     \
  9393.     if newframe > framecount then\
  9394.         for i=framecount+1,newframe do\
  9395.             frames[i] = {}\
  9396.             for y,line in pairs(frames[sFrame]) do\
  9397.                 frames[i][y] = { }\
  9398.                 for x,v in pairs(line) do\
  9399.                     frames[i][y][x] = v\
  9400.                 end\
  9401.             end\
  9402.         end\
  9403.         framecount = newframe\
  9404.     end\
  9405.     sFrame = newframe\
  9406.     inMenu = false\
  9407. end\
  9408. \
  9409. --[[Removes every frame leading after the frame passed in\
  9410.     Params: frame:int the non-inclusive lower bounds of the delete\
  9411.     Returns:nil\
  9412. ]]--\
  9413. local function removeFramesAfter(frame)\
  9414.     inMenu = true\
  9415.     if frame==framecount then return end\
  9416.     drawMessage(\"Remove frames \"..(frame+1)..\"/\"..framecount..\"? Y/N :\")\
  9417.     local answer = string.upper(readInput(1))\
  9418.     \
  9419.     if string.find(answer, string.upper(\"Y\")) ~= 1 then \
  9420.         inMenu = false\
  9421.         return \
  9422.     end\
  9423.     \
  9424.     for i=frame+1, framecount do\
  9425.         frames[i] = nil\
  9426.     end\
  9427.     framecount = frame\
  9428.     inMenu = false\
  9429. end\
  9430. \
  9431. --[[\
  9432.             Section: Printing Tools\
  9433. ]]--\
  9434. \
  9435. --[[Constructs a new facing to the left of the current facing\
  9436.     Params: curx:number = The facing on the X axis\
  9437.             curz:number = The facing on the Z axis\
  9438.             hand:string = The hand of the axis (\"right\" or \"left\")\
  9439.     Returns:number,number = the new facing on the X and Z axis after a left turn\
  9440. ]]--\
  9441. local function getLeft(curx, curz)\
  9442.     local hand = \"left\"\
  9443.     if layering == \"up\" then hand = \"right\" end\
  9444.     \
  9445.     if hand == \"right\" then\
  9446.         if curx == 1 then return 0,-1 end\
  9447.         if curx == -1 then return 0,1 end\
  9448.         if curz == 1 then return 1,0 end\
  9449.         if curz == -1 then return -1,0 end\
  9450.     else\
  9451.         if curx == 1 then return 0,1 end\
  9452.         if curx == -1 then return 0,-1 end\
  9453.         if curz == 1 then return -1,0 end\
  9454.         if curz == -1 then return 1,0 end\
  9455.     end\
  9456. end\
  9457. \
  9458. --[[Constructs a new facing to the right of the current facing\
  9459.     Params: curx:number = The facing on the X axis\
  9460.             curz:number = The facing on the Z axis\
  9461.             hand:string = The hand of the axis (\"right\" or \"left\")\
  9462.     Returns:number,number = the new facing on the X and Z axis after a right turn\
  9463. ]]--\
  9464. local function getRight(curx, curz)\
  9465.     local hand = \"left\"\
  9466.     if layering == \"up\" then hand = \"right\" end\
  9467.     \
  9468.     if hand == \"right\" then\
  9469.         if curx == 1 then return 0,1 end\
  9470.         if curx == -1 then return 0,-1 end\
  9471.         if curz == 1 then return -1,0 end\
  9472.         if curz == -1 then return 1,0 end\
  9473.     else\
  9474.         if curx == 1 then return 0,-1 end\
  9475.         if curx == -1 then return 0,1 end\
  9476.         if curz == 1 then return 1,0 end\
  9477.         if curz == -1 then return -1,0 end\
  9478.     end\
  9479. end\
  9480. \
  9481. \
  9482. --[[Sends out a rednet signal requesting local printers, and will listen for any responses. Printers found are added to the\
  9483.     printerList (for ID's) and printerNames (for names)\
  9484.     Params: nil\
  9485.     Returns:nil\
  9486. ]]--\
  9487. local function locatePrinters()\
  9488.     printerList = { }\
  9489.     printerNames = { name = \"Printers\" }\
  9490.     local oldState = state\
  9491.     state = \"Locating printers, please wait...   \"\
  9492.     drawCanvas()\
  9493.     drawInterface()\
  9494.     state = oldState\
  9495.     \
  9496.     local modemOpened = false\
  9497.     for k,v in pairs(rs.getSides()) do\
  9498.         if peripheral.isPresent(v) and peripheral.getType(v) == \"modem\" then\
  9499.             rednet.open(v)\
  9500.             modemOpened = true\
  9501.             break\
  9502.         end\
  9503.     end\
  9504.     \
  9505.     if not modemOpened then\
  9506.         displayConfirmDialogue(\"Modem not found!\", \"No modem peripheral. Must have network modem to locate printers.\")\
  9507.         return false\
  9508.     end\
  9509.     \
  9510.     rednet.broadcast(\"$3DPRINT IDENTIFY\")\
  9511.     \
  9512.     while true do\
  9513.         local id, msg = rsTimeReceive(1)\
  9514.         \
  9515.         if not id then break end\
  9516.         if string.find(msg, \"$3DPRINT IDACK\") == 1 then\
  9517.             msg = string.gsub(msg, \"$3DPRINT IDACK \", \"\")\
  9518.             table.insert(printerList, id)\
  9519.             table.insert(printerNames, msg)\
  9520.         end\
  9521.     end\
  9522.     \
  9523.     if #printerList == 0 then\
  9524.         displayConfirmDialogue(\"Printers not found!\", \"No active printers found in proximity of this computer.\")\
  9525.         return false\
  9526.     else\
  9527.         return true\
  9528.     end\
  9529. end\
  9530. \
  9531. --[[Sends a request to the printer. Waits on a response and updates the state of the application accordingly.\
  9532.     Params: command:string the command to send\
  9533.             param:string a parameter to send, if any\
  9534.     Returns:nil\
  9535. ]]--\
  9536. local function sendPC(command,param)\
  9537.     local msg = \"$PC \"..command\
  9538.     if param then msg = msg..\" \"..param end\
  9539.     rednet.send(printerList[selectedPrinter], msg)\
  9540.     \
  9541.     while true do\
  9542.         local id,key = rsTimeReceive()\
  9543.         if id == printerList[selectedPrinter] then\
  9544.             if key == \"$3DPRINT ACK\" then\
  9545.                 break\
  9546.             elseif key == \"$3DPRINT DEP\" then\
  9547.                 displayConfirmDialogue(\"Printer Empty\", \"The printer has exhasted a material. Please refill slot \"..param..\
  9548.                     \", and click this message when ready to continue.\")\
  9549.                 rednet.send(printerList[selectedPrinter], msg)\
  9550.             end\
  9551.         end\
  9552.     end\
  9553.     \
  9554.     --Changes to position are handled after the event has been successfully completed\
  9555.     if command == \"FW\" then\
  9556.         px = px + pfx\
  9557.         pz = pz + pfz\
  9558.     elseif command == \"BK\" then\
  9559.         px = px - pfx\
  9560.         pz = pz - pfz\
  9561.     elseif command == \"UP\" then\
  9562.         if layering == \"up\" then\
  9563.             py = py + 1\
  9564.         else \
  9565.             py = py - 1\
  9566.         end\
  9567.     elseif command == \"DW\" then\
  9568.         if layering == \"up\" then\
  9569.             py = py - 1\
  9570.         else    \
  9571.             py = py + 1\
  9572.         end\
  9573.     elseif command == \"TL\" then\
  9574.         pfx,pfz = getLeft(pfx,pfz)\
  9575.     elseif command == \"TR\" then\
  9576.         pfx,pfz = getRight(pfx,pfz)\
  9577.     elseif command == \"TU\" then\
  9578.         pfx = -pfx\
  9579.         pfz = -pfz\
  9580.     end\
  9581.     \
  9582.     drawCanvas()\
  9583.     drawInterface()\
  9584. end\
  9585. \
  9586. --[[A printing function that commands the printer to turn to face the desired direction, if it is not already doing so\
  9587.     Params: desx:number = the normalized x direction to face\
  9588.             desz:number = the normalized z direction to face\
  9589.     Returns:nil\
  9590. ]]--\
  9591. local function turnToFace(desx,desz)\
  9592.     if desx ~= 0 then\
  9593.         if pfx ~= desx then\
  9594.             local temppfx,_ = getLeft(pfx,pfz)\
  9595.             if temppfx == desx then\
  9596.                 sendPC(\"TL\")\
  9597.             elseif temppfx == -desx then\
  9598.                 sendPC(\"TR\")\
  9599.             else\
  9600.                 sendPC(\"TU\")\
  9601.             end\
  9602.         end\
  9603.     else\
  9604.         print(\"on the z axis\")\
  9605.         if pfz ~= desz then\
  9606.             local _,temppfz = getLeft(pfx,pfz)\
  9607.             if temppfz == desz then\
  9608.                 sendPC(\"TL\")\
  9609.             elseif temppfz == -desz then\
  9610.                 sendPC(\"TR\")\
  9611.             else\
  9612.                 sendPC(\"TU\")\
  9613.             end\
  9614.         end\
  9615.     end\
  9616. end\
  9617. \
  9618. --[[Performs the print\
  9619.     Params: nil\
  9620.     Returns:nil\
  9621. ]]--\
  9622. local function performPrint()\
  9623.     state = \"active print\"\
  9624.     if layering == \"up\" then\
  9625.         --An up layering starts our builder bot on the bottom left corner of our build\
  9626.         px,py,pz = leflim, 0, botlim + 1\
  9627.         pfx,pfz = 0,-1\
  9628.         \
  9629.         --We move him forward and up a bit from his original position.\
  9630.         sendPC(\"FW\")\
  9631.         sendPC(\"UP\")\
  9632.         --For each layer that needs to be completed, we go up by one each time\
  9633.         for layers=1,#frames do\
  9634.             --We first decide if we're going forwards or back, depending on what side we're on\
  9635.             local rowbot,rowtop,rowinc = nil,nil,nil\
  9636.             if pz == botlim then\
  9637.                 rowbot,rowtop,rowinc = botlim,toplim,-1\
  9638.             else\
  9639.                 rowbot,rowtop,rowinc = toplim,botlim,1\
  9640.             end\
  9641.             \
  9642.             for rows = rowbot,rowtop,rowinc do\
  9643.                 --Then we decide if we're going left or right, depending on what side we're on\
  9644.                 local linebot,linetop,lineinc = nil,nil,nil\
  9645.                 if px == leflim then\
  9646.                     --Facing from the left side has to be easterly- it's changed here\
  9647.                     turnToFace(1,0)\
  9648.                     linebot,linetop,lineinc = leflim,riglim,1\
  9649.                 else\
  9650.                     --Facing from the right side has to be westerly- it's changed here\
  9651.                     turnToFace(-1,0)\
  9652.                     linebot,linetop,lineinc = riglim,leflim,-1\
  9653.                 end\
  9654.                 \
  9655.                 for lines = linebot,linetop,lineinc do\
  9656.                     --We move our turtle forward, placing the right material at each step\
  9657.                     local material = frames[py][pz][px]\
  9658.                     if material then\
  9659.                         material = math.log10(frames[py][pz][px])/math.log10(2) + 1\
  9660.                         sendPC(\"SS\", material)\
  9661.                         sendPC(\"PD\")\
  9662.                     end\
  9663.                     if lines ~= linetop then\
  9664.                         sendPC(\"FW\")\
  9665.                     end\
  9666.                 end\
  9667.                 \
  9668.                 --The printer then has to do a U-turn, depending on which way he's facing and\
  9669.                 --which way he needs to go\
  9670.                 local temppfx,temppfz = getLeft(pfx,pfz)\
  9671.                 if temppfz == rowinc and rows ~= rowtop then\
  9672.                     sendPC(\"TL\")\
  9673.                     sendPC(\"FW\")\
  9674.                     sendPC(\"TL\")\
  9675.                 elseif temppfz == -rowinc and rows ~= rowtop then\
  9676.                     sendPC(\"TR\")\
  9677.                     sendPC(\"FW\")\
  9678.                     sendPC(\"TR\")\
  9679.                 end\
  9680.             end\
  9681.             --Now at the end of a run he does a 180 and moves up to begin the next part of the print\
  9682.             sendPC(\"TU\")\
  9683.             if layers ~= #frames then\
  9684.                 sendPC(\"UP\")\
  9685.             end\
  9686.         end\
  9687.         --All done- now we head back to where we started.\
  9688.         if px ~= leflim then\
  9689.             turnToFace(-1,0)\
  9690.             while px ~= leflim do\
  9691.                 sendPC(\"FW\")\
  9692.             end\
  9693.         end\
  9694.         if pz ~= botlim then\
  9695.             turnToFace(0,-1)\
  9696.             while pz ~= botlim do\
  9697.                 sendPC(\"BK\")\
  9698.             end\
  9699.         end\
  9700.         turnToFace(0,-1)\
  9701.         sendPC(\"BK\")\
  9702.         while py > 0 do\
  9703.             sendPC(\"DW\")\
  9704.         end\
  9705.     else\
  9706.         --The front facing is at the top-left corner, facing south not north\
  9707.         px,py,pz = leflim, botlim, 1\
  9708.         pfx,pfz = 0,1\
  9709.         --We move the printer to the last layer- he prints from the back forwards\
  9710.         while pz < #frames do\
  9711.             sendPC(\"FW\")\
  9712.         end\
  9713.         \
  9714.         --For each layer in the frame we build our wall, the move back\
  9715.         for layers = 1,#frames do\
  9716.             --We first decide if we're going left or right based on our position\
  9717.             local rowbot,rowtop,rowinc = nil,nil,nil\
  9718.             if px == leflim then\
  9719.                 rowbot,rowtop,rowinc = leflim,riglim,1\
  9720.             else\
  9721.                 rowbot,rowtop,rowinc = riglim,leflim,-1\
  9722.             end\
  9723.             \
  9724.             for rows = rowbot,rowtop,rowinc do\
  9725.                 --Then we decide if we're going up or down, depending on our given altitude\
  9726.                 local linebot,linetop,lineinc = nil,nil,nil\
  9727.                 if py == botlim then\
  9728.                     linebot,linetop,lineinc = botlim,toplim,-1\
  9729.                 else\
  9730.                     linebot,linetop,lineinc = toplim,botlim,1\
  9731.                 end\
  9732.                 \
  9733.                 for lines = linebot,linetop,lineinc do\
  9734.                 --We move our turtle up/down, placing the right material at each step\
  9735.                     local material = frames[pz][py][px]\
  9736.                     if material then\
  9737.                         material = math.log10(frames[pz][py][px])/math.log10(2) + 1\
  9738.                         sendPC(\"SS\", material)\
  9739.                         sendPC(\"PF\")\
  9740.                     end\
  9741.                     if lines ~= linetop then\
  9742.                         if lineinc == 1 then sendPC(\"DW\")\
  9743.                         else sendPC(\"UP\") end\
  9744.                     end\
  9745.                 end\
  9746.                     \
  9747.                 if rows ~= rowtop then\
  9748.                     turnToFace(rowinc,0)\
  9749.                     sendPC(\"FW\")\
  9750.                     turnToFace(0,1)\
  9751.                 end\
  9752.             end\
  9753.             \
  9754.             if layers ~= #frames then\
  9755.                 sendPC(\"TU\")\
  9756.                 sendPC(\"FW\")\
  9757.                 sendPC(\"TU\")\
  9758.             end\
  9759.         end\
  9760.         --He's easy to reset\
  9761.         while px ~= leflim do\
  9762.             turnToFace(-1,0)\
  9763.             sendPC(\"FW\")\
  9764.         end\
  9765.         turnToFace(0,1)\
  9766.     end\
  9767.     \
  9768.     sendPC(\"DE\")\
  9769.     \
  9770.     displayConfirmDialogue(\"Print complete\", \"The 3D print was successful.\")\
  9771. end\
  9772. \
  9773. --[[  \
  9774.             Section: Interface  \
  9775. ]]--\
  9776. \
  9777. --[[Runs the printing interface. Allows users to find/select a printer, the style of printing to perform and to begin the operation\
  9778.     Params: none\
  9779.     Returns:boolean true if printing was started, false otherwse\
  9780. ]]--\
  9781. local function runPrintInterface()\
  9782.     if not locatePrinters() then\
  9783.         return false\
  9784.     end\
  9785.     \
  9786.     calculateMaterials()\
  9787.     layering = \"up\"\
  9788.     requirementsDisplayed = false\
  9789.     selectedPrinter = 1\
  9790.     while true do\
  9791.         drawCanvas()\
  9792.         term.setBackgroundColour(colours.lightGrey)\
  9793.         for i=1,10 do\
  9794.             term.setCursorPos(1,i)\
  9795.             term.clearLine()\
  9796.         end\
  9797.         drawInterface()\
  9798.         term.setBackgroundColour(colours.lightGrey)\
  9799.         term.setTextColour(colours.black)\
  9800.         \
  9801.         local msg = \"3D Printing\"\
  9802.         term.setCursorPos(w/2-#msg/2 - 2, 1)\
  9803.         term.write(msg)\
  9804.         term.setBackgroundColour(colours.grey)\
  9805.         term.setTextColour(colours.lightGrey)\
  9806.         if(requirementsDisplayed) then\
  9807.             msg = \"Count:\"\
  9808.         else\
  9809.             msg = \" Slot:\"\
  9810.         end\
  9811.         term.setCursorPos(w-3-#msg, 1)\
  9812.         term.write(msg)\
  9813.         term.setBackgroundColour(colours.lightGrey)\
  9814.         term.setTextColour(colours.black)\
  9815.         \
  9816.         term.setCursorPos(7, 2)\
  9817.         term.write(\"Layering\")\
  9818.         drawPictureTable(layerUpIcon, 3, 3, colours.white)\
  9819.         drawPictureTable(layerForwardIcon, 12, 3, colours.white)\
  9820.         if layering == \"up\" then\
  9821.             term.setBackgroundColour(colours.red)\
  9822.         else\
  9823.             term.setBackgroundColour(colours.lightGrey)\
  9824.         end\
  9825.         term.setCursorPos(3, 9)\
  9826.         term.write(\"Upwards\")\
  9827.         if layering == \"forward\" then\
  9828.             term.setBackgroundColour(colours.red)\
  9829.         else\
  9830.             term.setBackgroundColour(colours.lightGrey)\
  9831.         end\
  9832.         term.setCursorPos(12, 9)\
  9833.         term.write(\"Forward\")\
  9834.         \
  9835.         term.setBackgroundColour(colours.lightGrey)\
  9836.         term.setTextColour(colours.black)\
  9837.         term.setCursorPos(31, 2)\
  9838.         term.write(\"Printer ID\")\
  9839.         term.setCursorPos(33, 3)\
  9840.         if #printerList > 1 then\
  9841.             term.setBackgroundColour(colours.grey)\
  9842.             term.setTextColour(colours.lightGrey)\
  9843.         else\
  9844.             term.setTextColour(colours.red)\
  9845.         end\
  9846.         term.write(\" \"..printerNames[selectedPrinter]..\" \")\
  9847.         \
  9848.         term.setBackgroundColour(colours.grey)\
  9849.         term.setTextColour(colours.lightGrey)\
  9850.         term.setCursorPos(25, 10)\
  9851.         term.write(\" Cancel \")\
  9852.         term.setCursorPos(40, 10)\
  9853.         term.write(\" Print \")\
  9854.         \
  9855.         local id, p1, p2, p3 = os.pullEvent()\
  9856.         \
  9857.         if id == \"timer\" then\
  9858.             updateTimer(p1)\
  9859.         elseif id == \"mouse_click\" then\
  9860.             --Layering Buttons\
  9861.             if p2 >= 3 and p2 <= 9 and p3 >= 3 and p3 <= 9 then\
  9862.                 layering = \"up\"\
  9863.             elseif p2 >= 12 and p2 <= 18 and p3 >= 3 and p3 <= 9 then\
  9864.                 layering = \"forward\"\
  9865.             --Count/Slot\
  9866.             elseif p2 >= w - #msg - 3 and p2 <= w - 3 and p3 == 1 then\
  9867.                 requirementsDisplayed = not requirementsDisplayed\
  9868.             --Printer ID\
  9869.             elseif p2 >= 33 and p2 <= 33 + #printerNames[selectedPrinter] and p3 == 3 and #printerList > 1 then\
  9870.                 local chosenName = displayDropDown(33, 3, printerNames)\
  9871.                 for i=1,#printerNames do\
  9872.                     if printerNames[i] == chosenName then\
  9873.                         selectedPrinter = i\
  9874.                         break;\
  9875.                     end\
  9876.                 end\
  9877.             --Print and Cancel\
  9878.             elseif p2 >= 25 and p2 <= 32 and p3 == 10 then\
  9879.                 break\
  9880.             elseif p2 >= 40 and p2 <= 46 and p3 == 10 then\
  9881.                 rednet.send(printerList[selectedPrinter], \"$3DPRINT ACTIVATE\")\
  9882.                 ready = false\
  9883.                 while true do\
  9884.                     local id,msg = rsTimeReceive(10)\
  9885.                     \
  9886.                     if id == printerList[selectedPrinter] and msg == \"$3DPRINT ACTACK\" then\
  9887.                         ready = true\
  9888.                         break\
  9889.                     end\
  9890.                 end\
  9891.                 if ready then\
  9892.                     performPrint()\
  9893.                     break\
  9894.                 else\
  9895.                     displayConfirmDialogue(\"Printer Didn't Respond\", \"The printer didn't respond to the activation command. Check to see if it's online\")\
  9896.                 end\
  9897.             end\
  9898.         end\
  9899.     end\
  9900.     state = \"paint\"\
  9901. end\
  9902. \
  9903. --[[This function changes the current paint program to another tool or mode, depending on user input. Handles\
  9904.     any necessary changes in logic involved in that.\
  9905.     Params: mode:string = the name of the mode to change to\
  9906.     Returns:nil\
  9907. ]]--\
  9908. local function performSelection(mode)\
  9909.     if not mode or mode == \"\" then return\
  9910.     \
  9911.     elseif mode == \"help\" then\
  9912.         drawHelpScreen()\
  9913.         \
  9914.     elseif mode == \"blueprint on\" then\
  9915.         blueprint = true\
  9916.         ddModes[2][3] = \"blueprint off\"\
  9917.         \
  9918.     elseif mode == \"blueprint off\" then\
  9919.         blueprint = false\
  9920.         ddModes[2][3] = \"blueprint on\"\
  9921.         \
  9922.     elseif mode == \"layers on\" then\
  9923.         layerDisplay = true\
  9924.         ddModes[2][4] = \"layers off\"\
  9925.     \
  9926.     elseif mode == \"layers off\" then\
  9927.         layerDisplay = false\
  9928.         ddModes[2][4] = \"layers on\"\
  9929.     \
  9930.     elseif mode == \"direction on\" then\
  9931.         printDirection = true\
  9932.         ddModes[2][5] = \"direction off\"\
  9933.         \
  9934.     elseif mode == \"direction off\" then\
  9935.         printDirection = false\
  9936.         ddModes[2][5] = \"direction on\"\
  9937.     \
  9938.     elseif mode == \"go to\" then\
  9939.         changeFrame()\
  9940.     \
  9941.     elseif mode == \"remove\" then\
  9942.         removeFramesAfter(sFrame)\
  9943.     \
  9944.     elseif mode == \"play\" then\
  9945.         playAnimation()\
  9946.         \
  9947.     elseif mode == \"copy\" then\
  9948.         if selectrect and selectrect.x1 ~= selectrect.x2 then\
  9949.             copyToBuffer(false)\
  9950.         end\
  9951.     \
  9952.     elseif mode == \"cut\" then\
  9953.         if selectrect and selectrect.x1 ~= selectrect.x2 then \
  9954.             copyToBuffer(true)\
  9955.         end\
  9956.         \
  9957.     elseif mode == \"paste\" then\
  9958.         if selectrect and selectrect.x1 ~= selectrect.x2 then \
  9959.             copyFromBuffer(false)\
  9960.         end\
  9961.         \
  9962.     elseif mode == \"hide\" then\
  9963.         selectrect = nil\
  9964.         if state == \"select\" then state = \"corner select\" end\
  9965.         \
  9966.     elseif mode == \"alpha to left\" then\
  9967.         if lSel then alphaC = lSel end\
  9968.         \
  9969.     elseif mode == \"alpha to right\" then\
  9970.         if rSel then alphaC = rSel end\
  9971.         \
  9972.     elseif mode == \"record\" then\
  9973.         record = not record\
  9974.         \
  9975.     elseif mode == \"clear\" then\
  9976.         if state==\"select\" then buffer = nil\
  9977.         else clearImage() end\
  9978.     \
  9979.     elseif mode == \"select\" then\
  9980.         if state==\"corner select\" or state==\"select\" then\
  9981.             state = \"paint\"\
  9982.         elseif selectrect and selectrect.x1 ~= selectrect.x2 then\
  9983.             state = \"select\"\
  9984.         else\
  9985.             state = \"corner select\" \
  9986.         end\
  9987.         \
  9988.     elseif mode == \"print\" then\
  9989.         state = \"print\"\
  9990.         runPrintInterface()\
  9991.         state = \"paint\"\
  9992.         \
  9993.     elseif mode == \"save\" then\
  9994.         if animated then saveNFA(sPath)\
  9995.         else saveNFP(sPath) end\
  9996.         \
  9997.     elseif mode == \"exit\" then\
  9998.         isRunning = false\
  9999.     \
  10000.     elseif mode ~= state then state = mode\
  10001.     else state = \"paint\"\
  10002.     end\
  10003. end\
  10004. \
  10005. --[[The main function of the program, reads and handles all events and updates them accordingly. Mode changes,\
  10006.     painting to the canvas and general selections are done here.\
  10007.     Params: none\
  10008.     Returns:nil\
  10009. ]]--\
  10010. local function handleEvents()\
  10011.     recttimer = os.startTimer(0.5)\
  10012.     while isRunning do\
  10013.         drawCanvas()\
  10014.         drawInterface()\
  10015.         local id,p1,p2,p3 = os.pullEvent()\
  10016.         if id==\"timer\" then\
  10017.             updateTimer(p1)\
  10018.         elseif id==\"mouse_click\" or id==\"mouse_drag\" then\
  10019.             if p2 >=w-1 and p3 < #column+1 then\
  10020.                 if p1==1 then lSel = column[p3]\
  10021.                 else rSel = column[p3] end\
  10022.             elseif p2 >=w-1 and p3==#column+1 then\
  10023.                 if p1==1 then lSel = nil\
  10024.                 else rSel = nil end\
  10025.             elseif p2==w-1 and p3==h and animated then\
  10026.                 changeFrame(sFrame-1)\
  10027.             elseif p2==w and p3==h and animated then\
  10028.                 changeFrame(sFrame+1)\
  10029.             elseif p2 < w-10 and p3==h then\
  10030.                 local sel = displayDropDown(1, h-1, ddModes)\
  10031.                 performSelection(sel)\
  10032.             elseif p2 < w-1 and p3 <= h-1 then\
  10033.                 if state==\"pippette\" then\
  10034.                     if p1==1 then\
  10035.                         if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then\
  10036.                             lSel = frames[sFrame][p3+sy][p2+sx] \
  10037.                         end\
  10038.                     elseif p1==2 then\
  10039.                         if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then\
  10040.                             rSel = frames[sFrame][p3+sy][p2+sx] \
  10041.                         end\
  10042.                     end\
  10043.                 elseif state==\"move\" then\
  10044.                     updateImageLims(record)\
  10045.                     moveImage(p2,p3)\
  10046.                 elseif state==\"flood\" then\
  10047.                     if p1 == 1 and lSel and frames[sFrame][p3+sy]  then \
  10048.                         floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],lSel)\
  10049.                     elseif p1 == 2 and rSel and frames[sFrame][p3+sy] then \
  10050.                         floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],rSel)\
  10051.                     end\
  10052.                 elseif state==\"corner select\" then\
  10053.                     if not selectrect then\
  10054.                         selectrect = { x1=p2+sx, x2=p2+sx, y1=p3+sy, y2=p3+sy }\
  10055.                     elseif selectrect.x1 ~= p2+sx and selectrect.y1 ~= p3+sy then\
  10056.                         if p2+sx<selectrect.x1 then selectrect.x1 = p2+sx\
  10057.                         else selectrect.x2 = p2+sx end\
  10058.                         \
  10059.                         if p3+sy<selectrect.y1 then selectrect.y1 = p3+sy\
  10060.                         else selectrect.y2 = p3+sy end\
  10061.                         \
  10062.                         state = \"select\"\
  10063.                     end\
  10064.                 elseif state==\"select\" then\
  10065.                     if p1 == 1 then\
  10066.                         local swidth = selectrect.x2 - selectrect.x1\
  10067.                         local sheight = selectrect.y2 - selectrect.y1\
  10068.                     \
  10069.                         selectrect.x1 = p2 + sx\
  10070.                         selectrect.y1 = p3 + sy\
  10071.                         selectrect.x2 = p2 + swidth + sx\
  10072.                         selectrect.y2 = p3 + sheight + sy\
  10073.                     elseif p1 == 2 and p2 < w-2 and p3 < h-1 then\
  10074.                         inMenu = true\
  10075.                         local sel = displayDropDown(p2, p3, srModes) \
  10076.                         inMenu = false\
  10077.                         performSelection(sel)\
  10078.                     end\
  10079.                 else\
  10080.                     local f,l = sFrame,sFrame\
  10081.                     if record then f,l = 1,framecount end\
  10082.                     local bwidth = 0\
  10083.                     if state == \"brush\" then bwidth = brushsize-1 end\
  10084.                 \
  10085.                     for i=f,l do\
  10086.                         for x = math.max(1,p2+sx-bwidth),p2+sx+bwidth do\
  10087.                             for y = math.max(1,p3+sy-bwidth), p3+sy+bwidth do\
  10088.                                 if math.abs(x - (p2+sx)) + math.abs(y - (p3+sy)) <= bwidth then\
  10089.                                     if not frames[i][y] then frames[i][y] = {} end\
  10090.                                     if p1==1 then frames[i][y][x] = lSel\
  10091.                                     else frames[i][y][x] = rSel end\
  10092.                                 end\
  10093.                             end\
  10094.                         end\
  10095.                     end\
  10096.                 end\
  10097.             end\
  10098.         elseif id==\"key\" then\
  10099.             if p1==keys.leftCtrl then\
  10100.                 local sel = displayDropDown(1, h-1, ddModes[#ddModes]) \
  10101.                 performSelection(sel)\
  10102.             elseif p1==keys.leftAlt then\
  10103.                 local sel = displayDropDown(1, h-1, ddModes[1]) \
  10104.                 performSelection(sel)\
  10105.             elseif p1==keys.h then \
  10106.                 performSelection(\"help\")\
  10107.             elseif p1==keys.x then \
  10108.                 performSelection(\"cut\")\
  10109.             elseif p1==keys.c then\
  10110.                 performSelection(\"copy\")\
  10111.             elseif p1==keys.v then\
  10112.                 performSelection(\"paste\")\
  10113.             elseif p1==keys.z then\
  10114.                 performSelection(\"clear\")\
  10115.             elseif p1==keys.s then\
  10116.                 performSelection(\"select\")\
  10117.             elseif p1==keys.tab then\
  10118.                 performSelection(\"hide\")\
  10119.             elseif p1==keys.q then\
  10120.                 performSelection(\"alpha to left\")\
  10121.             elseif p1==keys.w then\
  10122.                 performSelection(\"alpha to right\")\
  10123.             elseif p1==keys.f then\
  10124.                 performSelection(\"flood\")\
  10125.             elseif p1==keys.b then\
  10126.                 performSelection(\"brush\")\
  10127.             elseif p1==keys.m then\
  10128.                 performSelection(\"move\")\
  10129.             elseif p1==keys.backslash and animated then\
  10130.                 performSelection(\"record\")\
  10131.             elseif p1==keys.p then\
  10132.                 performSelection(\"pippette\")\
  10133.             elseif p1==keys.g and animated then\
  10134.                 performSelection(\"go to\")\
  10135.             elseif p1==keys.period and animated then\
  10136.                 changeFrame(sFrame+1)\
  10137.             elseif p1==keys.comma and animated then\
  10138.                 changeFrame(sFrame-1)\
  10139.             elseif p1==keys.r and animated then\
  10140.                 performSelection(\"remove\")\
  10141.             elseif p1==keys.space and animated then\
  10142.                 performSelection(\"play\")\
  10143.             elseif p1==keys.left then\
  10144.                 if state == \"move\" then\
  10145.                     updateImageLims(record)\
  10146.                     moveImage(leflim-1,toplim)\
  10147.                 elseif state==\"select\" and selectrect.x1 > 1 then\
  10148.                     selectrect.x1 = selectrect.x1-1\
  10149.                     selectrect.x2 = selectrect.x2-1\
  10150.                 elseif sx > 0 then sx=sx-1 end\
  10151.             elseif p1==keys.right then\
  10152.                 if state == \"move\" then\
  10153.                     updateImageLims(record)\
  10154.                     moveImage(leflim+1,toplim)\
  10155.                 elseif state==\"select\" then\
  10156.                     selectrect.x1 = selectrect.x1+1\
  10157.                     selectrect.x2 = selectrect.x2+1\
  10158.                 else sx=sx+1 end\
  10159.             elseif p1==keys.up then\
  10160.                 if state == \"move\" then\
  10161.                     updateImageLims(record)\
  10162.                     moveImage(leflim,toplim-1)\
  10163.                 elseif state==\"select\" and selectrect.y1 > 1 then\
  10164.                     selectrect.y1 = selectrect.y1-1\
  10165.                     selectrect.y2 = selectrect.y2-1\
  10166.                 elseif sy > 0 then sy=sy-1 end\
  10167.             elseif p1==keys.down then \
  10168.                 if state == \"move\" then\
  10169.                     updateImageLims(record)\
  10170.                     moveImage(leflim,toplim+1)\
  10171.                 elseif state==\"select\" then\
  10172.                     selectrect.y1 = selectrect.y1+1\
  10173.                     selectrect.y2 = selectrect.y2+1\
  10174.                 else sy=sy+1 end\
  10175.             end\
  10176.         elseif id==\"char\" and tonumber(p1) then\
  10177.             if state==\"brush\" and tonumber(p1) > 1 then\
  10178.                 brushsize = tonumber(p1)\
  10179.             elseif tonumber(p1) > 0 then\
  10180.                 changeFrame(tonumber(p1))\
  10181.             end\
  10182.         end\
  10183.     end\
  10184. end\
  10185. \
  10186. --[[  \
  10187.             Section: Main  \
  10188. ]]--\
  10189. \
  10190. --Taken almost directly from edit (for consistency)\
  10191. local tArgs = {...}\
  10192. \
  10193. local ca = 1\
  10194. \
  10195. if tArgs[ca] == \"-a\" then\
  10196.     animated = true\
  10197.     ca = ca + 1\
  10198. end\
  10199. \
  10200. if #tArgs < ca then\
  10201.     print(\"Usage: npaintpro [-a] <path>\")\
  10202.     return\
  10203. end\
  10204. \
  10205. sPath = shell.resolve(tArgs[ca])\
  10206. local bReadOnly = fs.isReadOnly(sPath)\
  10207. if fs.exists(sPath) then\
  10208.     if fs.isDir(sPath) then\
  10209.         print(\"Cannot edit a directory.\")\
  10210.         return\
  10211.     elseif string.find(sPath, \".nfp\") ~= #sPath-3 and string.find(sPath, \".nfa\") ~= #sPath-3 then\
  10212.         print(\"Can only edit .nfp and nfa files:\",string.find(sPath, \".nfp\"),#sPath-3)\
  10213.         return\
  10214.     end\
  10215.     \
  10216.     if string.find(sPath, \".nfa\") == #sPath-3 then\
  10217.         animated = true\
  10218.     end\
  10219.     \
  10220.     if string.find(sPath, \".nfp\") == #sPath-3 and animated then\
  10221.         print(\"Convert to nfa? Y/N\")\
  10222.         if string.find(string.lower(io.read()), \"y\") then\
  10223.             local nsPath = string.sub(sPath, 1, #sPath-1)..\"a\"\
  10224.             fs.move(sPath, nsPath)\
  10225.             sPath = nsPath\
  10226.         else\
  10227.             animated = false\
  10228.         end\
  10229.     end\
  10230. else\
  10231.     if not animated and string.find(sPath, \".nfp\") ~= #sPath-3 then \
  10232.         sPath = sPath..\".nfp\"\
  10233.     elseif animated and string.find(sPath, \".nfa\") ~= #sPath-3 then \
  10234.         sPath = sPath..\".nfa\"\
  10235.     end\
  10236. end \
  10237. \
  10238. if not term.isColour() then\
  10239.     print(\"For colour computers only\")\
  10240.     return\
  10241. end\
  10242. \
  10243. drawLogo()\
  10244. init()\
  10245. handleEvents()\
  10246. \
  10247. term.setBackgroundColour(colours.black)\
  10248. shell.run(\"clear\")",
  10249.         edit = "-- Get file to edit\
  10250. local tArgs = { ... }\
  10251. if #tArgs == 0 then\
  10252.     print( \"Usage: edit <path>\" )\
  10253.     return\
  10254. end\
  10255. \
  10256. -- Error checking\
  10257. local sPath = shell.resolve( tArgs[1] )\
  10258. local bReadOnly = fs.isReadOnly( sPath )\
  10259. if fs.exists( sPath ) and fs.isDir( sPath ) then\
  10260.     print( \"Cannot edit a directory.\" )\
  10261.     return\
  10262. end\
  10263. \
  10264. local x,y = 1,1\
  10265. local w,h = term.getSize()\
  10266. local scrollX, scrollY = 0,0\
  10267. \
  10268. local tLines = {}\
  10269. local bRunning = true\
  10270. \
  10271. -- Colours\
  10272. local highlightColour, keywordColour, commentColour, textColour, bgColour\
  10273. if term.isColour() then\
  10274.     bgColour = colours.black\
  10275.     textColour = colours.white\
  10276.     highlightColour = colours.yellow\
  10277.     keywordColour = colours.yellow\
  10278.     commentColour = colours.green\
  10279.     stringColour = colours.red\
  10280. else\
  10281.     bgColour = colours.black\
  10282.     textColour = colours.white\
  10283.     highlightColour = colours.white\
  10284.     keywordColour = colours.white\
  10285.     commentColour = colours.white\
  10286.     stringColour = colours.white\
  10287. end\
  10288. \
  10289. -- Menus\
  10290. local bMenu = false\
  10291. local nMenuItem = 1\
  10292. local tMenuItems\
  10293. if bReadOnly then\
  10294.     tMenuItems = { \"Exit\", \"Print\" }\
  10295. else\
  10296.     tMenuItems = { \"Save\", \"Exit\", \"Print\" }\
  10297. end\
  10298.     \
  10299. local sStatus = \"Press Ctrl to access menu\"\
  10300. \
  10301. local function load( _sPath )\
  10302.     tLines = {}\
  10303.     if fs.exists( _sPath ) then\
  10304.         local file = io.open( _sPath, \"r\" )\
  10305.         local sLine = file:read()\
  10306.         while sLine do\
  10307.             table.insert( tLines, sLine )\
  10308.             sLine = file:read()\
  10309.         end\
  10310.         file:close()\
  10311.     end\
  10312.     \
  10313.     if #tLines == 0 then\
  10314.         table.insert( tLines, \"\" )\
  10315.     end\
  10316. end\
  10317. \
  10318. local function save( _sPath )\
  10319.     -- Create intervening folder\
  10320.     local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )\
  10321.     if not fs.exists( sDir ) then\
  10322.         fs.makeDir( sDir )\
  10323.     end\
  10324. \
  10325.     -- Save\
  10326.     local file = nil\
  10327.     local function innerSave()\
  10328.         file = fs.open( _sPath, \"w\" )\
  10329.         if file then\
  10330.             for n, sLine in ipairs( tLines ) do\
  10331.                 file.write( sLine .. \"\\n\" )\
  10332.             end\
  10333.         else\
  10334.             error( \"Failed to open \".._sPath )\
  10335.         end\
  10336.     end\
  10337.     \
  10338.     local ok = pcall( innerSave )\
  10339.     if file then \
  10340.         file.close()\
  10341.     end\
  10342.     return ok\
  10343. end\
  10344. \
  10345. local tKeywords = {\
  10346.     [\"and\"] = true,\
  10347.     [\"break\"] = true,\
  10348.     [\"do\"] = true,\
  10349.     [\"else\"] = true,\
  10350.     [\"elseif\"] = true,\
  10351.     [\"end\"] = true,\
  10352.     [\"false\"] = true,\
  10353.     [\"for\"] = true,\
  10354.     [\"function\"] = true,\
  10355.     [\"if\"] = true,\
  10356.     [\"in\"] = true,\
  10357.     [\"local\"] = true,\
  10358.     [\"nil\"] = true,\
  10359.     [\"not\"] = true,\
  10360.     [\"or\"] = true,\
  10361.     [\"repeat\"] = true,\
  10362.     [\"return\"] = true,\
  10363.     [\"then\"] = true,\
  10364.     [\"true\"] = true,\
  10365.     [\"until\"]= true,\
  10366.     [\"while\"] = true,\
  10367. }\
  10368. \
  10369. local function tryWrite( sLine, regex, colour )\
  10370.     local match = string.match( sLine, regex )\
  10371.     if match then\
  10372.         if type(colour) == \"number\" then\
  10373.             term.setTextColour( colour )\
  10374.         else\
  10375.             term.setTextColour( colour(match) )\
  10376.         end\
  10377.         term.write( match )\
  10378.         term.setTextColour( textColour )\
  10379.         return string.sub( sLine, string.len(match) + 1 )\
  10380.     end\
  10381.     return nil\
  10382. end\
  10383. \
  10384. local function writeHighlighted( sLine )\
  10385.     while string.len(sLine) > 0 do  \
  10386.         sLine = \
  10387.             tryWrite( sLine, \"^%-%-%[%[.-%]%]\", commentColour ) or\
  10388.             tryWrite( sLine, \"^%-%-.*\", commentColour ) or\
  10389.             tryWrite( sLine, \"^\\\".-[^\\\\]\\\"\", stringColour ) or\
  10390.             tryWrite( sLine, \"^\\'.-[^\\\\]\\'\", stringColour ) or\
  10391.             tryWrite( sLine, \"^%[%[.-%]%]\", stringColour ) or\
  10392.             tryWrite( sLine, \"^[%w_]+\", function( match )\
  10393.                 if tKeywords[ match ] then\
  10394.                     return keywordColour\
  10395.                 end\
  10396.                 return textColour\
  10397.             end ) or\
  10398.             tryWrite( sLine, \"^[^%w_]\", textColour )\
  10399.     end\
  10400. end\
  10401. \
  10402. local function redrawText()\
  10403.     for y=1,h-1 do\
  10404.         term.setCursorPos( 1 - scrollX, y )\
  10405.         term.clearLine()\
  10406. \
  10407.         local sLine = tLines[ y + scrollY ]\
  10408.         if sLine ~= nil then\
  10409.             writeHighlighted( sLine )\
  10410.         end\
  10411.     end\
  10412.     term.setCursorPos( x - scrollX, y - scrollY )\
  10413. end\
  10414. \
  10415. local function redrawLine(_nY)\
  10416.     local sLine = tLines[_nY]\
  10417.     term.setCursorPos( 1 - scrollX, _nY - scrollY )\
  10418.     term.clearLine()\
  10419.     writeHighlighted( sLine )\
  10420.     term.setCursorPos( x - scrollX, _nY - scrollY )\
  10421. end\
  10422. \
  10423. local function redrawMenu()\
  10424.    -- Clear line\
  10425.    term.setCursorPos( 1, h )\
  10426.     term.clearLine()\
  10427. \
  10428.    -- Draw line numbers\
  10429.    term.setCursorPos( w - string.len( \"Ln \"..y ) + 1, h )\
  10430.    term.setTextColour( highlightColour )\
  10431.    term.write( \"Ln \" )\
  10432.    term.setTextColour( textColour )\
  10433.    term.write( y )\
  10434. \
  10435.    term.setCursorPos( 1, h )\
  10436.     if bMenu then\
  10437.        -- Draw menu\
  10438.         term.setTextColour( textColour )\
  10439.         for nItem,sItem in pairs( tMenuItems ) do\
  10440.             if nItem == nMenuItem then\
  10441.                 term.setTextColour( highlightColour )\
  10442.                 term.write( \"[\" )\
  10443.                 term.setTextColour( textColour )\
  10444.                 term.write( sItem )\
  10445.                 term.setTextColour( highlightColour )\
  10446.                 term.write( \"]\" )\
  10447.                 term.setTextColour( textColour )\
  10448.             else\
  10449.                 term.write( \" \"..sItem..\" \" )\
  10450.             end\
  10451.         end\
  10452.    else\
  10453.        -- Draw status\
  10454.        term.setTextColour( highlightColour )\
  10455.        term.write( sStatus )\
  10456.        term.setTextColour( textColour )\
  10457.    end\
  10458. \
  10459.     -- Reset cursor\
  10460.     term.setCursorPos( x - scrollX, y - scrollY )\
  10461. end\
  10462. \
  10463. local tMenuFuncs = { \
  10464.     Save=function()\
  10465.         if bReadOnly then\
  10466.             sStatus = \"Access denied\"\
  10467.         else\
  10468.             local ok, err = save( sPath )\
  10469.             if ok then\
  10470.                 sStatus=\"Saved to \"..sPath\
  10471.             else\
  10472.                 sStatus=\"Error saving to \"..sPath\
  10473.             end\
  10474.         end\
  10475.         redrawMenu()\
  10476.     end,\
  10477.     Print=function()\
  10478.         local printer = peripheral.find( \"printer\" )\
  10479.         if not printer then\
  10480.             sStatus = \"No printer attached\"\
  10481.             return\
  10482.         end\
  10483. \
  10484.         local nPage = 0\
  10485.         local sName = fs.getName( sPath )\
  10486.         if printer.getInkLevel() < 1 then\
  10487.             sStatus = \"Printer out of ink\"\
  10488.             return\
  10489.         elseif printer.getPaperLevel() < 1 then\
  10490.             sStatus = \"Printer out of paper\"\
  10491.             return\
  10492.         end\
  10493. \
  10494.         local screenTerminal = term.current()\
  10495.         local printerTerminal = {\
  10496.             getCursorPos = printer.getCursorPos,\
  10497.             setCursorPos = printer.setCursorPos,\
  10498.             getSize = printer.getPageSize,\
  10499.             write = printer.write,\
  10500.         }\
  10501.         printerTerminal.scroll = function()\
  10502.             if nPage == 1 then\
  10503.                 printer.setPageTitle( sName..\" (page \"..nPage..\")\" )            \
  10504.             end\
  10505.             \
  10506.             while not printer.newPage() do\
  10507.                 if printer.getInkLevel() < 1 then\
  10508.                     sStatus = \"Printer out of ink, please refill\"\
  10509.                 elseif printer.getPaperLevel() < 1 then\
  10510.                     sStatus = \"Printer out of paper, please refill\"\
  10511.                 else\
  10512.                     sStatus = \"Printer output tray full, please empty\"\
  10513.                 end\
  10514.     \
  10515.                 term.redirect( screenTerminal )\
  10516.                 redrawMenu()\
  10517.                 term.redirect( printerTerminal )\
  10518.                 \
  10519.                 local timer = os.startTimer(0.5)\
  10520.                 sleep(0.5)\
  10521.             end\
  10522. \
  10523.             nPage = nPage + 1\
  10524.             if nPage == 1 then\
  10525.                 printer.setPageTitle( sName )\
  10526.             else\
  10527.                 printer.setPageTitle( sName..\" (page \"..nPage..\")\" )\
  10528.             end\
  10529.         end\
  10530.         \
  10531.         bMenu = false\
  10532.         term.redirect( printerTerminal )\
  10533.         local ok, error = pcall( function()\
  10534.             term.scroll()\
  10535.             for n, sLine in ipairs( tLines ) do\
  10536.                 print( sLine )\
  10537.             end\
  10538.         end )\
  10539.        term.redirect( screenTerminal )\
  10540.         if not ok then\
  10541.             print( error )\
  10542.         end\
  10543.         \
  10544.         while not printer.endPage() do\
  10545.             sStatus = \"Printer output tray full, please empty\"\
  10546.             redrawMenu()\
  10547.             sleep( 0.5 )\
  10548.         end\
  10549.         bMenu = true\
  10550.             \
  10551.         if nPage > 1 then\
  10552.             sStatus = \"Printed \"..nPage..\" Pages\"\
  10553.         else\
  10554.             sStatus = \"Printed 1 Page\"\
  10555.         end\
  10556.         redrawMenu()\
  10557.     end,\
  10558.     Exit=function()\
  10559.         bRunning = false\
  10560.     end\
  10561. }\
  10562. \
  10563. local function doMenuItem( _n )\
  10564.     tMenuFuncs[tMenuItems[_n]]()\
  10565.     if bMenu then\
  10566.         bMenu = false\
  10567.         term.setCursorBlink( true )\
  10568.     end\
  10569.     redrawMenu()\
  10570. end\
  10571. \
  10572. local function setCursor( x, y )\
  10573.     local screenX = x - scrollX\
  10574.     local screenY = y - scrollY\
  10575.     \
  10576.     local bRedraw = false\
  10577.     if screenX < 1 then\
  10578.         scrollX = x - 1\
  10579.         screenX = 1\
  10580.         bRedraw = true\
  10581.     elseif screenX > w then\
  10582.         scrollX = x - w\
  10583.         screenX = w\
  10584.         bRedraw = true\
  10585.     end\
  10586.     \
  10587.     if screenY < 1 then\
  10588.         scrollY = y - 1\
  10589.         screenY = 1\
  10590.         bRedraw = true\
  10591.     elseif screenY > h-1 then\
  10592.         scrollY = y - (h-1)\
  10593.         screenY = h-1\
  10594.         bRedraw = true\
  10595.     end\
  10596.     \
  10597.     if bRedraw then\
  10598.         redrawText()\
  10599.     end\
  10600.     term.setCursorPos( screenX, screenY )\
  10601.     \
  10602.     -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.\
  10603.     redrawMenu()\
  10604. end\
  10605. \
  10606. -- Actual program functionality begins\
  10607. load(sPath)\
  10608. \
  10609. term.setBackgroundColour( bgColour )\
  10610. term.clear()\
  10611. term.setCursorPos(x,y)\
  10612. term.setCursorBlink( true )\
  10613. \
  10614. redrawText()\
  10615. redrawMenu()\
  10616. \
  10617. -- Handle input\
  10618. while bRunning do\
  10619.     local sEvent, param, param2, param3 = os.pullEvent()\
  10620.     if sEvent == \"key\" then\
  10621.         if param == keys.up then\
  10622.             -- Up\
  10623.             if not bMenu then\
  10624.                 if y > 1 then\
  10625.                     -- Move cursor up\
  10626.                     y = y - 1\
  10627.                     x = math.min( x, string.len( tLines[y] ) + 1 )\
  10628.                     setCursor( x, y )\
  10629.                 end\
  10630.             end\
  10631.         elseif param == keys.down then\
  10632.             -- Down\
  10633.             if not bMenu then\
  10634.                 -- Move cursor down\
  10635.                 if y < #tLines then\
  10636.                     y = y + 1\
  10637.                     x = math.min( x, string.len( tLines[y] ) + 1 )\
  10638.                     setCursor( x, y )\
  10639.                 end\
  10640.             end\
  10641.         elseif param == keys.tab then\
  10642.             -- Tab\
  10643.             if not bMenu and not bReadOnly then\
  10644.                 -- Indent line\
  10645.                 tLines[y]=\"  \"..tLines[y]\
  10646.                 x = x + 2\
  10647.                 setCursor( x, y )\
  10648.                 redrawLine(y)\
  10649.             end\
  10650.         elseif param == keys.pageUp then\
  10651.             -- Page Up\
  10652.             if not bMenu then\
  10653.                 -- Move up a page\
  10654.                 if y - (h - 1) >= 1 then\
  10655.                     y = y - (h - 1)\
  10656.                 else\
  10657.                     y = 1\
  10658.                 end\
  10659.                 x = math.min( x, string.len( tLines[y] ) + 1 )\
  10660.                 setCursor( x, y )\
  10661.             end\
  10662.         elseif param == keys.pageDown then\
  10663.             -- Page Down\
  10664.             if not bMenu then\
  10665.                 -- Move down a page\
  10666.                 if y + (h - 1) <= #tLines then\
  10667.                     y = y + (h - 1)\
  10668.                 else\
  10669.                     y = #tLines\
  10670.                 end\
  10671.                 x = math.min( x, string.len( tLines[y] ) + 1 )\
  10672.                 setCursor( x, y )\
  10673.             end\
  10674.         elseif param == keys.home then\
  10675.             -- Home\
  10676.             if not bMenu then\
  10677.                 -- Move cursor to the beginning\
  10678.                 x=1\
  10679.                 setCursor(x,y)\
  10680.             end\
  10681.         elseif param == keys[\"end\"] then\
  10682.             -- End\
  10683.             if not bMenu then\
  10684.                 -- Move cursor to the end\
  10685.                 x = string.len( tLines[y] ) + 1\
  10686.                 setCursor(x,y)\
  10687.             end\
  10688.         elseif param == keys.left then\
  10689.             -- Left\
  10690.             if not bMenu then\
  10691.                 if x > 1 then\
  10692.                     -- Move cursor left\
  10693.                     x = x - 1\
  10694.                 elseif x==1 and y>1 then\
  10695.                     x = string.len( tLines[y-1] ) + 1\
  10696.                     y = y - 1\
  10697.                 end\
  10698.                 setCursor( x, y )\
  10699.             else\
  10700.                 -- Move menu left\
  10701.                 nMenuItem = nMenuItem - 1\
  10702.                 if nMenuItem < 1 then\
  10703.                     nMenuItem = #tMenuItems\
  10704.                 end\
  10705.                 redrawMenu()\
  10706.             end\
  10707.         elseif param == keys.right then\
  10708.             -- Right\
  10709.             if not bMenu then\
  10710.                 if x < string.len( tLines[y] ) + 1 then\
  10711.                     -- Move cursor right\
  10712.                     x = x + 1\
  10713.                 elseif x==string.len( tLines[y] ) + 1 and y<#tLines then\
  10714.                     x = 1\
  10715.                     y = y + 1\
  10716.                 end\
  10717.                 setCursor( x, y )\
  10718.             else\
  10719.                 -- Move menu right\
  10720.                 nMenuItem = nMenuItem + 1\
  10721.                 if nMenuItem > #tMenuItems then\
  10722.                     nMenuItem = 1\
  10723.                 end\
  10724.                 redrawMenu()\
  10725.             end\
  10726.         elseif param == keys.delete then\
  10727.             -- Delete\
  10728.             if not bMenu and not bReadOnly then\
  10729.                 if  x < string.len( tLines[y] ) + 1 then\
  10730.                     local sLine = tLines[y]\
  10731.                     tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)\
  10732.                     redrawLine(y)\
  10733.                 elseif y<#tLines then\
  10734.                     tLines[y] = tLines[y] .. tLines[y+1]\
  10735.                     table.remove( tLines, y+1 )\
  10736.                     redrawText()\
  10737.                     redrawMenu()\
  10738.                 end\
  10739.             end\
  10740.         elseif param == keys.backspace then\
  10741.             -- Backspace\
  10742.             if not bMenu and not bReadOnly then\
  10743.                 if x > 1 then\
  10744.                     -- Remove character\
  10745.                     local sLine = tLines[y]\
  10746.                     tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)\
  10747.                     redrawLine(y)\
  10748.             \
  10749.                     x = x - 1\
  10750.                     setCursor( x, y )\
  10751.                 elseif y > 1 then\
  10752.                     -- Remove newline\
  10753.                     local sPrevLen = string.len( tLines[y-1] )\
  10754.                     tLines[y-1] = tLines[y-1] .. tLines[y]\
  10755.                     table.remove( tLines, y )\
  10756.                     redrawText()\
  10757.                 \
  10758.                     x = sPrevLen + 1\
  10759.                     y = y - 1\
  10760.                     setCursor( x, y )\
  10761.                 end\
  10762.             end\
  10763.         elseif param == keys.enter then\
  10764.             -- Enter\
  10765.             if not bMenu and not bReadOnly then\
  10766.                 -- Newline\
  10767.                 local sLine = tLines[y]\
  10768.                 local _,spaces=string.find(sLine,\"^[ ]+\")\
  10769.                 if not spaces then\
  10770.                     spaces=0\
  10771.                 end\
  10772.                 tLines[y] = string.sub(sLine,1,x-1)\
  10773.                 table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )\
  10774.                 redrawText()\
  10775.             \
  10776.                 x = spaces+1\
  10777.                 y = y + 1\
  10778.                 setCursor( x, y )\
  10779.             elseif bMenu then\
  10780.                 -- Menu selection\
  10781.                 doMenuItem( nMenuItem )\
  10782.             end\
  10783.         elseif param == keys.leftCtrl or param == keys.rightCtrl then\
  10784.             -- Menu toggle\
  10785.             bMenu = not bMenu\
  10786.             if bMenu then\
  10787.                 term.setCursorBlink( false )\
  10788.             else\
  10789.                 term.setCursorBlink( true )\
  10790.             end\
  10791.             redrawMenu()\
  10792.         end\
  10793.         \
  10794.     elseif sEvent == \"char\" then\
  10795.         if not bMenu and not bReadOnly then\
  10796.             -- Input text\
  10797.             local sLine = tLines[y]\
  10798.             tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\
  10799.             redrawLine(y)\
  10800.         \
  10801.             x = x + 1\
  10802.             setCursor( x, y )\
  10803.         elseif bMenu then\
  10804.             -- Select menu items\
  10805.             for n,sMenuItem in ipairs( tMenuItems ) do\
  10806.                 if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then\
  10807.                     doMenuItem( n )\
  10808.                     break\
  10809.                 end\
  10810.             end\
  10811.         end\
  10812. \
  10813.     elseif sEvent == \"paste\" then\
  10814.         if not bMenu and not bReadOnly then\
  10815.             -- Input text\
  10816.             local sLine = tLines[y]\
  10817.             tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\
  10818.             redrawLine(y)\
  10819. \
  10820.             x = x + string.len( param )\
  10821.             setCursor( x, y )\
  10822.         end\
  10823.         \
  10824.     elseif sEvent == \"mouse_click\" then\
  10825.         if not bMenu then\
  10826.             if param == 1 then\
  10827.                 -- Left click\
  10828.                 local cx,cy = param2, param3\
  10829.                 if cy < h then\
  10830.                     y = math.min( math.max( scrollY + cy, 1 ), #tLines )\
  10831.                     x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 )\
  10832.                     setCursor( x, y )\
  10833.                 end\
  10834.             end\
  10835.         end\
  10836.         \
  10837.     elseif sEvent == \"mouse_scroll\" then\
  10838.         if not bMenu then\
  10839.             if param == -1 then\
  10840.                 -- Scroll up\
  10841.                 if scrollY > 0 then\
  10842.                     -- Move cursor up\
  10843.                     scrollY = scrollY - 1\
  10844.                     redrawText()\
  10845.                 end\
  10846.             \
  10847.             elseif param == 1 then\
  10848.                 -- Scroll down\
  10849.                 local nMaxScroll = #tLines - (h-1)\
  10850.                 if scrollY < nMaxScroll then\
  10851.                     -- Move cursor down\
  10852.                     scrollY = scrollY + 1\
  10853.                     redrawText()\
  10854.                 end\
  10855.                 \
  10856.             end\
  10857.         end\
  10858. \
  10859.     elseif sEvent == \"term_resize\" then\
  10860.         w,h = term.getSize()\
  10861.        setCursor( x, y )\
  10862.        redrawMenu()\
  10863.        redrawText()\
  10864. \
  10865.     end\
  10866. end\
  10867. \
  10868. -- Cleanup\
  10869. term.clear()\
  10870. term.setCursorBlink( false )\
  10871. term.setCursorPos( 1, 1 )",
  10872.       },
  10873.       [ "FileX.ico" ] = "error('This is an image, not a program!')\
  10874. {\
  10875.  {\
  10876.    {\
  10877.      16,\
  10878.      \" \",\
  10879.      1,\
  10880.    },\
  10881.    {\
  10882.      16,\
  10883.      \"F\",\
  10884.      32768,\
  10885.    },\
  10886.    {\
  10887.      16,\
  10888.      \" \",\
  10889.      1,\
  10890.    },\
  10891.  },\
  10892.  {\
  10893.    {\
  10894.      2,\
  10895.      \" \",\
  10896.      2,\
  10897.    },\
  10898.    {\
  10899.      16,\
  10900.      \"X\",\
  10901.      32768,\
  10902.    },\
  10903.    {\
  10904.      16,\
  10905.      \" \",\
  10906.      1,\
  10907.    },\
  10908.  },\
  10909.  {\
  10910.    {\
  10911.      2,\
  10912.      \" \",\
  10913.      2,\
  10914.    },\
  10915.    {\
  10916.      16,\
  10917.      \" \",\
  10918.      1,\
  10919.    },\
  10920.    {\
  10921.      16,\
  10922.      \" \",\
  10923.      1,\
  10924.    },\
  10925.  },\
  10926.  {},\
  10927.  [ 0 ] = {\
  10928.    {\
  10929.      16,\
  10930.      \" \",\
  10931.      1,\
  10932.    },\
  10933.    {\
  10934.      16,\
  10935.      \" \",\
  10936.      1,\
  10937.    },\
  10938.    {\
  10939.      16,\
  10940.      \" \",\
  10941.      1,\
  10942.    },\
  10943.  },\
  10944.  [ 14 ] = {},\
  10945.  [ 12 ] = {},\
  10946.  [ 24 ] = {},\
  10947.  [ 26 ] = {},\
  10948.  [ 13 ] = {},\
  10949. }",
  10950.     },
  10951.     [ "Edit.app" ] = {
  10952.       [ "permission.data" ] = "userTest",
  10953.       [ "Edit.ico" ] = "error('This is an image, not a program!')\
  10954. {\
  10955.  {\
  10956.    {\
  10957.      2048,\
  10958.      \"-\",\
  10959.      1,\
  10960.    },\
  10961.    {\
  10962.      2048,\
  10963.      \"-\",\
  10964.      1,\
  10965.    },\
  10966.    {\
  10967.      2048,\
  10968.      \"-\",\
  10969.      1,\
  10970.    },\
  10971.  },\
  10972.  {\
  10973.    {\
  10974.      2048,\
  10975.      \"-\",\
  10976.      1,\
  10977.    },\
  10978.    {\
  10979.      2048,\
  10980.      \"-\",\
  10981.      1,\
  10982.    },\
  10983.    {\
  10984.      2048,\
  10985.      \"-\",\
  10986.      1,\
  10987.    },\
  10988.  },\
  10989.  {\
  10990.    {\
  10991.      2048,\
  10992.      \"-\",\
  10993.      1,\
  10994.    },\
  10995.    {\
  10996.      2048,\
  10997.      \"-\",\
  10998.      1,\
  10999.    },\
  11000.    {\
  11001.      2048,\
  11002.      \"-\",\
  11003.      1,\
  11004.    },\
  11005.  },\
  11006.  [ 0 ] = {\
  11007.    {\
  11008.      128,\
  11009.      \"|\",\
  11010.      1,\
  11011.    },\
  11012.    {\
  11013.      128,\
  11014.      \"|\",\
  11015.      1,\
  11016.    },\
  11017.    {\
  11018.      128,\
  11019.      \"|\",\
  11020.      1,\
  11021.    },\
  11022.  },\
  11023. }",
  11024.       [ "Main.lua" ] = "-- Get file to edit\
  11025. local tArgs = { ... }\
  11026. if #tArgs == 0 then\
  11027.     term.setTextColour(colors.white)\
  11028.     term.setBackgroundColour(colors.black)\
  11029.     term.clear()\
  11030.    term.write(\"Path please!\")\
  11031.    tArgs[1] = \"OmniOS/Data/\"..read()\
  11032. end\
  11033. \
  11034. -- Error checking\
  11035. --local sPath = shell.resolve( tArgs[1] )\
  11036. local sPath = tArgs[1]\
  11037. local bReadOnly = fs.isReadOnly( sPath )\
  11038. if fs.exists( sPath ) and fs.isDir( sPath ) then\
  11039.     print( \"Cannot edit a directory.\" )\
  11040.     return\
  11041. end\
  11042. \
  11043. local x,y = 1,1\
  11044. local w,h = term.getSize()\
  11045. local scrollX, scrollY = 0,0\
  11046. \
  11047. local tLines = {}\
  11048. local bRunning = true\
  11049. \
  11050. -- Colours\
  11051. local highlightColour, keywordColour, commentColour, textColour, bgColour\
  11052. if term.isColour() then\
  11053.     bgColour = colours.black\
  11054.     textColour = colours.white\
  11055.     highlightColour = colours.yellow\
  11056.     keywordColour = colours.yellow\
  11057.     commentColour = colours.green\
  11058.     stringColour = colours.red\
  11059. else\
  11060.     bgColour = colours.black\
  11061.     textColour = colours.white\
  11062.     highlightColour = colours.white\
  11063.     keywordColour = colours.white\
  11064.     commentColour = colours.white\
  11065.     stringColour = colours.white\
  11066. end\
  11067. \
  11068. -- Menus\
  11069. local bMenu = false\
  11070. local nMenuItem = 1\
  11071. local tMenuItems\
  11072. if bReadOnly then\
  11073.     tMenuItems = { \"Exit\", \"Print\" }\
  11074. else\
  11075.     tMenuItems = { \"Save\", \"Exit\", \"Print\" }\
  11076. end\
  11077.     \
  11078. local sStatus = \"Press Ctrl to access menu\"\
  11079. \
  11080. local function load( _sPath )\
  11081.     tLines = {}\
  11082.     if fs.exists( _sPath ) then\
  11083.         local file = io.open( _sPath, \"r\" )\
  11084.         local sLine = file:read()\
  11085.         while sLine do\
  11086.             table.insert( tLines, sLine )\
  11087.             sLine = file:read()\
  11088.         end\
  11089.         file:close()\
  11090.     end\
  11091.     \
  11092.     if #tLines == 0 then\
  11093.         table.insert( tLines, \"\" )\
  11094.     end\
  11095. end\
  11096. \
  11097. local function save( _sPath )\
  11098.     -- Create intervening folder\
  11099.     local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )\
  11100.     if not fs.exists( sDir ) then\
  11101.         fs.makeDir( sDir )\
  11102.     end\
  11103. \
  11104.     -- Save\
  11105.     local file = nil\
  11106.     local function innerSave()\
  11107.         file = fs.open( _sPath, \"w\" )\
  11108.         if file then\
  11109.             for n, sLine in ipairs( tLines ) do\
  11110.                 file.write( sLine .. \"\\n\" )\
  11111.             end\
  11112.         else\
  11113.             error( \"Failed to open \".._sPath )\
  11114.         end\
  11115.     end\
  11116.     \
  11117.     local ok = pcall( innerSave )\
  11118.     if file then \
  11119.         file.close()\
  11120.     end\
  11121.     return ok\
  11122. end\
  11123. \
  11124. local tKeywords = {\
  11125.     [\"and\"] = true,\
  11126.     [\"break\"] = true,\
  11127.     [\"do\"] = true,\
  11128.     [\"else\"] = true,\
  11129.     [\"elseif\"] = true,\
  11130.     [\"end\"] = true,\
  11131.     [\"false\"] = true,\
  11132.     [\"for\"] = true,\
  11133.     [\"function\"] = true,\
  11134.     [\"if\"] = true,\
  11135.     [\"in\"] = true,\
  11136.     [\"local\"] = true,\
  11137.     [\"nil\"] = true,\
  11138.     [\"not\"] = true,\
  11139.     [\"or\"] = true,\
  11140.     [\"repeat\"] = true,\
  11141.     [\"return\"] = true,\
  11142.     [\"then\"] = true,\
  11143.     [\"true\"] = true,\
  11144.     [\"until\"]= true,\
  11145.     [\"while\"] = true,\
  11146. }\
  11147. \
  11148. local function tryWrite( sLine, regex, colour )\
  11149.     local match = string.match( sLine, regex )\
  11150.     if match then\
  11151.         if type(colour) == \"number\" then\
  11152.             term.setTextColour( colour )\
  11153.         else\
  11154.             term.setTextColour( colour(match) )\
  11155.         end\
  11156.         term.write( match )\
  11157.         term.setTextColour( textColour )\
  11158.         return string.sub( sLine, string.len(match) + 1 )\
  11159.     end\
  11160.     return nil\
  11161. end\
  11162. \
  11163. local function writeHighlighted( sLine )\
  11164.     while string.len(sLine) > 0 do  \
  11165.         sLine = \
  11166.             tryWrite( sLine, \"^%-%-%[%[.-%]%]\", commentColour ) or\
  11167.             tryWrite( sLine, \"^%-%-.*\", commentColour ) or\
  11168.             tryWrite( sLine, \"^\\\".-[^\\\\]\\\"\", stringColour ) or\
  11169.             tryWrite( sLine, \"^\\'.-[^\\\\]\\'\", stringColour ) or\
  11170.             tryWrite( sLine, \"^%[%[.-%]%]\", stringColour ) or\
  11171.             tryWrite( sLine, \"^[%w_]+\", function( match )\
  11172.                 if tKeywords[ match ] then\
  11173.                     return keywordColour\
  11174.                 end\
  11175.                 return textColour\
  11176.             end ) or\
  11177.             tryWrite( sLine, \"^[^%w_]\", textColour )\
  11178.     end\
  11179. end\
  11180. \
  11181. local function redrawText()\
  11182.     for y=1,h-1 do\
  11183.         term.setCursorPos( 1 - scrollX, y )\
  11184.         term.clearLine()\
  11185. \
  11186.         local sLine = tLines[ y + scrollY ]\
  11187.         if sLine ~= nil then\
  11188.             writeHighlighted( sLine )\
  11189.         end\
  11190.     end\
  11191.     term.setCursorPos( x - scrollX, y - scrollY )\
  11192. end\
  11193. \
  11194. local function redrawLine(_nY)\
  11195.     local sLine = tLines[_nY]\
  11196.     term.setCursorPos( 1 - scrollX, _nY - scrollY )\
  11197.     term.clearLine()\
  11198.     writeHighlighted( sLine )\
  11199.     term.setCursorPos( x - scrollX, _nY - scrollY )\
  11200. end\
  11201. \
  11202. local function redrawMenu()\
  11203.    -- Clear line\
  11204.    term.setCursorPos( 1, h )\
  11205.     term.clearLine()\
  11206. \
  11207.    -- Draw line numbers\
  11208.    term.setCursorPos( w - string.len( \"Ln \"..y ) + 1, h )\
  11209.    term.setTextColour( highlightColour )\
  11210.    term.write( \"Ln \" )\
  11211.    term.setTextColour( textColour )\
  11212.    term.write( y )\
  11213. \
  11214.    term.setCursorPos( 1, h )\
  11215.     if bMenu then\
  11216.        -- Draw menu\
  11217.         term.setTextColour( textColour )\
  11218.         for nItem,sItem in pairs( tMenuItems ) do\
  11219.             if nItem == nMenuItem then\
  11220.                 term.setTextColour( highlightColour )\
  11221.                 term.write( \"[\" )\
  11222.                 term.setTextColour( textColour )\
  11223.                 term.write( sItem )\
  11224.                 term.setTextColour( highlightColour )\
  11225.                 term.write( \"]\" )\
  11226.                 term.setTextColour( textColour )\
  11227.             else\
  11228.                 term.write( \" \"..sItem..\" \" )\
  11229.             end\
  11230.         end\
  11231.    else\
  11232.        -- Draw status\
  11233.        term.setTextColour( highlightColour )\
  11234.        term.write( sStatus )\
  11235.        term.setTextColour( textColour )\
  11236.    end\
  11237. \
  11238.     -- Reset cursor\
  11239.     term.setCursorPos( x - scrollX, y - scrollY )\
  11240. end\
  11241. \
  11242. local tMenuFuncs = { \
  11243.     Save=function()\
  11244.         if bReadOnly then\
  11245.             sStatus = \"Access denied\"\
  11246.         else\
  11247.             local ok, err = save( sPath )\
  11248.             if ok then\
  11249.                 sStatus=\"Saved to \"..sPath\
  11250.             else\
  11251.                 sStatus=\"Error saving to \"..sPath\
  11252.             end\
  11253.         end\
  11254.         redrawMenu()\
  11255.     end,\
  11256.     Print=function()\
  11257.         local printer = peripheral.find( \"printer\" )\
  11258.         if not printer then\
  11259.             sStatus = \"No printer attached\"\
  11260.             return\
  11261.         end\
  11262. \
  11263.         local nPage = 0\
  11264.         local sName = fs.getName( sPath )\
  11265.         if printer.getInkLevel() < 1 then\
  11266.             sStatus = \"Printer out of ink\"\
  11267.             return\
  11268.         elseif printer.getPaperLevel() < 1 then\
  11269.             sStatus = \"Printer out of paper\"\
  11270.             return\
  11271.         end\
  11272. \
  11273.         local screenTerminal = term.current()\
  11274.         local printerTerminal = {\
  11275.             getCursorPos = printer.getCursorPos,\
  11276.             setCursorPos = printer.setCursorPos,\
  11277.             getSize = printer.getPageSize,\
  11278.             write = printer.write,\
  11279.         }\
  11280.         printerTerminal.scroll = function()\
  11281.             if nPage == 1 then\
  11282.                 printer.setPageTitle( sName..\" (page \"..nPage..\")\" )            \
  11283.             end\
  11284.             \
  11285.             while not printer.newPage() do\
  11286.                 if printer.getInkLevel() < 1 then\
  11287.                     sStatus = \"Printer out of ink, please refill\"\
  11288.                 elseif printer.getPaperLevel() < 1 then\
  11289.                     sStatus = \"Printer out of paper, please refill\"\
  11290.                 else\
  11291.                     sStatus = \"Printer output tray full, please empty\"\
  11292.                 end\
  11293.     \
  11294.                 term.redirect( screenTerminal )\
  11295.                 redrawMenu()\
  11296.                 term.redirect( printerTerminal )\
  11297.                 \
  11298.                 local timer = os.startTimer(0.5)\
  11299.                 sleep(0.5)\
  11300.             end\
  11301. \
  11302.             nPage = nPage + 1\
  11303.             if nPage == 1 then\
  11304.                 printer.setPageTitle( sName )\
  11305.             else\
  11306.                 printer.setPageTitle( sName..\" (page \"..nPage..\")\" )\
  11307.             end\
  11308.         end\
  11309.         \
  11310.         bMenu = false\
  11311.         term.redirect( printerTerminal )\
  11312.         local ok, error = pcall( function()\
  11313.             term.scroll()\
  11314.             for n, sLine in ipairs( tLines ) do\
  11315.                 print( sLine )\
  11316.             end\
  11317.         end )\
  11318.        term.redirect( screenTerminal )\
  11319.         if not ok then\
  11320.             print( error )\
  11321.         end\
  11322.         \
  11323.         while not printer.endPage() do\
  11324.             sStatus = \"Printer output tray full, please empty\"\
  11325.             redrawMenu()\
  11326.             sleep( 0.5 )\
  11327.         end\
  11328.         bMenu = true\
  11329.             \
  11330.         if nPage > 1 then\
  11331.             sStatus = \"Printed \"..nPage..\" Pages\"\
  11332.         else\
  11333.             sStatus = \"Printed 1 Page\"\
  11334.         end\
  11335.         redrawMenu()\
  11336.     end,\
  11337.     Exit=function()\
  11338.         bRunning = false\
  11339.     end\
  11340. }\
  11341. \
  11342. local function doMenuItem( _n )\
  11343.     tMenuFuncs[tMenuItems[_n]]()\
  11344.     if bMenu then\
  11345.         bMenu = false\
  11346.         term.setCursorBlink( true )\
  11347.     end\
  11348.     redrawMenu()\
  11349. end\
  11350. \
  11351. local function setCursor( x, y )\
  11352.     local screenX = x - scrollX\
  11353.     local screenY = y - scrollY\
  11354.     \
  11355.     local bRedraw = false\
  11356.     if screenX < 1 then\
  11357.         scrollX = x - 1\
  11358.         screenX = 1\
  11359.         bRedraw = true\
  11360.     elseif screenX > w then\
  11361.         scrollX = x - w\
  11362.         screenX = w\
  11363.         bRedraw = true\
  11364.     end\
  11365.     \
  11366.     if screenY < 1 then\
  11367.         scrollY = y - 1\
  11368.         screenY = 1\
  11369.         bRedraw = true\
  11370.     elseif screenY > h-1 then\
  11371.         scrollY = y - (h-1)\
  11372.         screenY = h-1\
  11373.         bRedraw = true\
  11374.     end\
  11375.     \
  11376.     if bRedraw then\
  11377.         redrawText()\
  11378.     end\
  11379.     term.setCursorPos( screenX, screenY )\
  11380.     \
  11381.     -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.\
  11382.     redrawMenu()\
  11383. end\
  11384. \
  11385. -- Actual program functionality begins\
  11386. load(sPath)\
  11387. \
  11388. term.setBackgroundColour( bgColour )\
  11389. term.clear()\
  11390. term.setCursorPos(x,y)\
  11391. term.setCursorBlink( true )\
  11392. \
  11393. redrawText()\
  11394. redrawMenu()\
  11395. \
  11396. -- Handle input\
  11397. while bRunning do\
  11398.     local sEvent, param, param2, param3 = os.pullEvent()\
  11399.     if sEvent == \"key\" then\
  11400.         if param == keys.up then\
  11401.             -- Up\
  11402.             if not bMenu then\
  11403.                 if y > 1 then\
  11404.                     -- Move cursor up\
  11405.                     y = y - 1\
  11406.                     x = math.min( x, string.len( tLines[y] ) + 1 )\
  11407.                     setCursor( x, y )\
  11408.                 end\
  11409.             end\
  11410.         elseif param == keys.down then\
  11411.             -- Down\
  11412.             if not bMenu then\
  11413.                 -- Move cursor down\
  11414.                 if y < #tLines then\
  11415.                     y = y + 1\
  11416.                     x = math.min( x, string.len( tLines[y] ) + 1 )\
  11417.                     setCursor( x, y )\
  11418.                 end\
  11419.             end\
  11420.         elseif param == keys.tab then\
  11421.             -- Tab\
  11422.             if not bMenu and not bReadOnly then\
  11423.                 -- Indent line\
  11424.                 tLines[y]=\"  \"..tLines[y]\
  11425.                 x = x + 2\
  11426.                 setCursor( x, y )\
  11427.                 redrawLine(y)\
  11428.             end\
  11429.         elseif param == keys.pageUp then\
  11430.             -- Page Up\
  11431.             if not bMenu then\
  11432.                 -- Move up a page\
  11433.                 if y - (h - 1) >= 1 then\
  11434.                     y = y - (h - 1)\
  11435.                 else\
  11436.                     y = 1\
  11437.                 end\
  11438.                 x = math.min( x, string.len( tLines[y] ) + 1 )\
  11439.                 setCursor( x, y )\
  11440.             end\
  11441.         elseif param == keys.pageDown then\
  11442.             -- Page Down\
  11443.             if not bMenu then\
  11444.                 -- Move down a page\
  11445.                 if y + (h - 1) <= #tLines then\
  11446.                     y = y + (h - 1)\
  11447.                 else\
  11448.                     y = #tLines\
  11449.                 end\
  11450.                 x = math.min( x, string.len( tLines[y] ) + 1 )\
  11451.                 setCursor( x, y )\
  11452.             end\
  11453.         elseif param == keys.home then\
  11454.             -- Home\
  11455.             if not bMenu then\
  11456.                 -- Move cursor to the beginning\
  11457.                 x=1\
  11458.                 setCursor(x,y)\
  11459.             end\
  11460.         elseif param == keys[\"end\"] then\
  11461.             -- End\
  11462.             if not bMenu then\
  11463.                 -- Move cursor to the end\
  11464.                 x = string.len( tLines[y] ) + 1\
  11465.                 setCursor(x,y)\
  11466.             end\
  11467.         elseif param == keys.left then\
  11468.             -- Left\
  11469.             if not bMenu then\
  11470.                 if x > 1 then\
  11471.                     -- Move cursor left\
  11472.                     x = x - 1\
  11473.                 elseif x==1 and y>1 then\
  11474.                     x = string.len( tLines[y-1] ) + 1\
  11475.                     y = y - 1\
  11476.                 end\
  11477.                 setCursor( x, y )\
  11478.             else\
  11479.                 -- Move menu left\
  11480.                 nMenuItem = nMenuItem - 1\
  11481.                 if nMenuItem < 1 then\
  11482.                     nMenuItem = #tMenuItems\
  11483.                 end\
  11484.                 redrawMenu()\
  11485.             end\
  11486.         elseif param == keys.right then\
  11487.             -- Right\
  11488.             if not bMenu then\
  11489.                 if x < string.len( tLines[y] ) + 1 then\
  11490.                     -- Move cursor right\
  11491.                     x = x + 1\
  11492.                 elseif x==string.len( tLines[y] ) + 1 and y<#tLines then\
  11493.                     x = 1\
  11494.                     y = y + 1\
  11495.                 end\
  11496.                 setCursor( x, y )\
  11497.             else\
  11498.                 -- Move menu right\
  11499.                 nMenuItem = nMenuItem + 1\
  11500.                 if nMenuItem > #tMenuItems then\
  11501.                     nMenuItem = 1\
  11502.                 end\
  11503.                 redrawMenu()\
  11504.             end\
  11505.         elseif param == keys.delete then\
  11506.             -- Delete\
  11507.             if not bMenu and not bReadOnly then\
  11508.                 if  x < string.len( tLines[y] ) + 1 then\
  11509.                     local sLine = tLines[y]\
  11510.                     tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)\
  11511.                     redrawLine(y)\
  11512.                 elseif y<#tLines then\
  11513.                     tLines[y] = tLines[y] .. tLines[y+1]\
  11514.                     table.remove( tLines, y+1 )\
  11515.                     redrawText()\
  11516.                     redrawMenu()\
  11517.                 end\
  11518.             end\
  11519.         elseif param == keys.backspace then\
  11520.             -- Backspace\
  11521.             if not bMenu and not bReadOnly then\
  11522.                 if x > 1 then\
  11523.                     -- Remove character\
  11524.                     local sLine = tLines[y]\
  11525.                     tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)\
  11526.                     redrawLine(y)\
  11527.             \
  11528.                     x = x - 1\
  11529.                     setCursor( x, y )\
  11530.                 elseif y > 1 then\
  11531.                     -- Remove newline\
  11532.                     local sPrevLen = string.len( tLines[y-1] )\
  11533.                     tLines[y-1] = tLines[y-1] .. tLines[y]\
  11534.                     table.remove( tLines, y )\
  11535.                     redrawText()\
  11536.                 \
  11537.                     x = sPrevLen + 1\
  11538.                     y = y - 1\
  11539.                     setCursor( x, y )\
  11540.                 end\
  11541.             end\
  11542.         elseif param == keys.enter then\
  11543.             -- Enter\
  11544.             if not bMenu and not bReadOnly then\
  11545.                 -- Newline\
  11546.                 local sLine = tLines[y]\
  11547.                 local _,spaces=string.find(sLine,\"^[ ]+\")\
  11548.                 if not spaces then\
  11549.                     spaces=0\
  11550.                 end\
  11551.                 tLines[y] = string.sub(sLine,1,x-1)\
  11552.                 table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )\
  11553.                 redrawText()\
  11554.             \
  11555.                 x = spaces+1\
  11556.                 y = y + 1\
  11557.                 setCursor( x, y )\
  11558.             elseif bMenu then\
  11559.                 -- Menu selection\
  11560.                 doMenuItem( nMenuItem )\
  11561.             end\
  11562.         elseif param == keys.leftCtrl or param == keys.rightCtrl then\
  11563.             -- Menu toggle\
  11564.             bMenu = not bMenu\
  11565.             if bMenu then\
  11566.                 term.setCursorBlink( false )\
  11567.             else\
  11568.                 term.setCursorBlink( true )\
  11569.             end\
  11570.             redrawMenu()\
  11571.         end\
  11572.         \
  11573.     elseif sEvent == \"char\" then\
  11574.         if not bMenu and not bReadOnly then\
  11575.             -- Input text\
  11576.             local sLine = tLines[y]\
  11577.             tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\
  11578.             redrawLine(y)\
  11579.         \
  11580.             x = x + 1\
  11581.             setCursor( x, y )\
  11582.         elseif bMenu then\
  11583.             -- Select menu items\
  11584.             for n,sMenuItem in ipairs( tMenuItems ) do\
  11585.                 if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then\
  11586.                     doMenuItem( n )\
  11587.                     break\
  11588.                 end\
  11589.             end\
  11590.         end\
  11591. \
  11592.     elseif sEvent == \"paste\" then\
  11593.         if not bMenu and not bReadOnly then\
  11594.             -- Input text\
  11595.             local sLine = tLines[y]\
  11596.             tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\
  11597.             redrawLine(y)\
  11598. \
  11599.             x = x + string.len( param )\
  11600.             setCursor( x, y )\
  11601.         end\
  11602.         \
  11603.     elseif sEvent == \"mouse_click\" then\
  11604.         if not bMenu then\
  11605.             if param == 1 then\
  11606.                 -- Left click\
  11607.                 local cx,cy = param2, param3\
  11608.                 if cy < h then\
  11609.                     y = math.min( math.max( scrollY + cy, 1 ), #tLines )\
  11610.                     x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 )\
  11611.                     setCursor( x, y )\
  11612.                 end\
  11613.             end\
  11614.         end\
  11615.         \
  11616.     elseif sEvent == \"mouse_scroll\" then\
  11617.         if not bMenu then\
  11618.             if param == -1 then\
  11619.                 -- Scroll up\
  11620.                 if scrollY > 0 then\
  11621.                     -- Move cursor up\
  11622.                     scrollY = scrollY - 1\
  11623.                     redrawText()\
  11624.                 end\
  11625.             \
  11626.             elseif param == 1 then\
  11627.                 -- Scroll down\
  11628.                 local nMaxScroll = #tLines - (h-1)\
  11629.                 if scrollY < nMaxScroll then\
  11630.                     -- Move cursor down\
  11631.                     scrollY = scrollY + 1\
  11632.                     redrawText()\
  11633.                 end\
  11634.                 \
  11635.             end\
  11636.         end\
  11637. \
  11638.     elseif sEvent == \"term_resize\" then\
  11639.         w,h = term.getSize()\
  11640.        setCursor( x, y )\
  11641.        redrawMenu()\
  11642.        redrawText()\
  11643. \
  11644.     end\
  11645. end\
  11646. \
  11647. -- Cleanup\
  11648. term.clear()\
  11649. term.setCursorBlink( false )\
  11650. term.setCursorPos( 1, 1 )",
  11651.       OmniOS = {
  11652.         Data = {
  11653.           here = "hi",
  11654.         },
  11655.       },
  11656.     },
  11657.     [ "Calculator.app" ] = {
  11658.       [ "Calculator.ico" ] = "error('This is an image, not a program!')\
  11659. {\
  11660.  {\
  11661.    {\
  11662.      8192,\
  11663.      \"a\",\
  11664.      1,\
  11665.    },\
  11666.    {\
  11667.      8192,\
  11668.      \"+\",\
  11669.      1,\
  11670.    },\
  11671.    {\
  11672.      8192,\
  11673.      \"-\",\
  11674.      1,\
  11675.    },\
  11676.  },\
  11677.  {\
  11678.    {\
  11679.      8192,\
  11680.      \"l\",\
  11681.      1,\
  11682.    },\
  11683.    {\
  11684.      8192,\
  11685.      \"*\",\
  11686.      1,\
  11687.    },\
  11688.    {\
  11689.      8192,\
  11690.      \"/\",\
  11691.      1,\
  11692.    },\
  11693.  },\
  11694.  {\
  11695.    {\
  11696.      8192,\
  11697.      \"c\",\
  11698.      1,\
  11699.    },\
  11700.    {\
  11701.      8192,\
  11702.      \" \",\
  11703.      1,\
  11704.    },\
  11705.    {\
  11706.      8192,\
  11707.      \" \",\
  11708.      1,\
  11709.    },\
  11710.  },\
  11711.  [ 0 ] = {\
  11712.    {\
  11713.      8192,\
  11714.      \"C\",\
  11715.      1,\
  11716.    },\
  11717.    {\
  11718.      8192,\
  11719.      \" \",\
  11720.      1,\
  11721.    },\
  11722.    {\
  11723.      8192,\
  11724.      \" \",\
  11725.      1,\
  11726.    },\
  11727.  },\
  11728. }",
  11729.       [ "permission.data" ] = "user",
  11730.       [ "Main.lua" ] = "--[[\
  11731.     Calculator App\
  11732.     for OmniOS by\
  11733.     Creator\
  11734. ]]--\
  11735. \
  11736. --Varialbles--\
  11737. local gui = {}\
  11738. local path = OmniOS and \"OmniOS/Programs/Calculator.app/Data/\" or \"Calculator/\"\
  11739. local MainLayout = {}\
  11740. local env = {\
  11741.     deg = math.deg,\
  11742.     fmod = math.fmod,\
  11743.     random = math.random,\
  11744.     asin = math.asin,\
  11745.     max = math.max,\
  11746.     modf = math.modf,\
  11747.     log10 = math.log10,\
  11748.     floor = math.floor,\
  11749.     cosh = math.cosh,\
  11750.     ldexp = math.ldexp,\
  11751.     log = math.log,\
  11752.     pow = math.pow,\
  11753.     rndsd = math.randomseed,\
  11754.     frexp = math.frexp,\
  11755.     abs = math.abs,\
  11756.     tanh = math.tanh,\
  11757.     acos = math.acos,\
  11758.     atan2 = math.atan2,\
  11759.     tan = math.tan,\
  11760.     min = math.min,\
  11761.     ceil = math.ceil,\
  11762.     sinh = math.sinh,\
  11763.     sqrt = math.sqrt,\
  11764.     huge = math.huge,\
  11765.     rad = math.rad,\
  11766.     sin = math.sin,\
  11767.     exp = math.exp,\
  11768.     cos = math.cos,\
  11769.     atan = math.atan,\
  11770.     pi = math.pi,\
  11771. }\
  11772. \
  11773. --Functions--\
  11774. local function readLayoutFile(sLayout)\
  11775.     local func, err = loadfile(path..\"Layouts/\"..sLayout..\".layout\")\
  11776.     if err then\
  11777.         log.log(\"Calculator\",err)\
  11778.     end\
  11779.     setfenv(func,_G)\
  11780.     return func()\
  11781. end\
  11782. \
  11783. \
  11784. --Code--\
  11785. if not OmniOS or not Interact then\
  11786.     shell.run(\"pastebin --- Interact\")\
  11787.     os.loadAPI(\"Intearct\")\
  11788. end\
  11789. gui = NewInteract:Initialize()\
  11790. MainLayout = gui.Layout.new(readLayoutFile(\"Main\"))\
  11791. local input = gui.Text.new({name = \"input\",text = \"\",xPos = 1,yPos = 2,bgColor = colors.orange,fgColor = colors.white})\
  11792. \
  11793. MainLayout:draw()\
  11794. while true do\
  11795.     MainLayout.ColorField.Top:draw()\
  11796.     MainLayout.Button.Exit:draw()\
  11797.     MainLayout.Button.Clear:draw()\
  11798.     MainLayout.Button.Delete:draw()\
  11799.     MainLayout.Button.xxx:draw()\
  11800.     input:draw()\
  11801.     local MainLayoutEvent = gui.eventHandler(MainLayout)\
  11802.     if MainLayoutEvent[2] == \"=\" then\
  11803.         local fOutput = setfenv(loadstring(\"return \"..input.text),env)\
  11804.         local ok, output = pcall(fOutput)\
  11805.         if not ok then \
  11806.             log.log(\"Calculator\",output,\"Calculator\")\
  11807.         end\
  11808.         input.text = output\
  11809.         input:draw()\
  11810.     elseif MainLayoutEvent[2] == \"Exit\" then\
  11811.         break\
  11812.     elseif MainLayoutEvent[2] == \"Clear\" then\
  11813.         input.text = \"\"\
  11814.     elseif MainLayoutEvent[2] == \"Delete\" then\
  11815.         input.text = input.text:sub(1,-2)\
  11816.     else\
  11817.         input.text = input.text..MainLayoutEvent[2]\
  11818.         log.log(\"Calculator\",MainLayoutEvent[2])\
  11819.     end\
  11820. end",
  11821.       Data = {
  11822.         Layouts = {
  11823.           [ "Main.layout" ] = "local w,h = term.getSize()\
  11824. local tTable = {\
  11825.     BackgroundColor = colors.gray,\
  11826.     xPos = 1,\
  11827.     yPos = 1,\
  11828.     xLength = w,\
  11829.     yLength = h,\
  11830.     Button = {\
  11831.         Exit = {\
  11832.             name = \"Exit\",\
  11833.             label = \"x\",\
  11834.             xPos = w-1,\
  11835.             yPos = 2,\
  11836.             fgColor = colors.white,\
  11837.             bgColor = colors.orange,\
  11838.             xLength = 1,\
  11839.             yLength = 1,\
  11840.             returnValue = \"Exit\",\
  11841.             xTextPos = 1,\
  11842.             yTextPos = 1,\
  11843.         },\
  11844.         Clear = {\
  11845.             name = \"Clear\",\
  11846.             label = \"Clear\",\
  11847.             xPos = w-7,\
  11848.             yPos = 2,\
  11849.             fgColor = colors.white,\
  11850.             bgColor = colors.orange,\
  11851.             xLength = 5,\
  11852.             yLength = 1,\
  11853.             returnValue = \"Clear\",\
  11854.             xTextPos = 1,\
  11855.             yTextPos = 1,\
  11856.         },\
  11857.         Delete = {\
  11858.             name = \"Delete\",\
  11859.             label = \"<--\",\
  11860.             xPos = w-7,\
  11861.             yPos = 1,\
  11862.             fgColor = colors.white,\
  11863.             bgColor = colors.orange,\
  11864.             xLength = 5,\
  11865.             yLength = 1,\
  11866.             returnValue = \"Delete\",\
  11867.             xTextPos = 1,\
  11868.             yTextPos = 1,\
  11869.         },\
  11870.         xxx = {\
  11871.             name = \"xxx\",\
  11872.             label = \"xxx\",\
  11873.             xPos = w-11,\
  11874.             yPos = 1,\
  11875.             fgColor = colors.white,\
  11876.             bgColor = colors.orange,\
  11877.             xLength = 3,\
  11878.             yLength = 1,\
  11879.             returnValue = \"xxx\",\
  11880.             xTextPos = 1,\
  11881.             yTextPos = 1,\
  11882.         },\
  11883.     },\
  11884.     ColorField = {\
  11885.         Top = {\
  11886.             name = \"Top\",\
  11887.             xPos = 1,\
  11888.             yPos = 1,\
  11889.             xLength = 51, \
  11890.             yLength = 2,\
  11891.             color = colors.orange,\
  11892.         },\
  11893.     },\
  11894.     Layout  = {\
  11895.         Input = {\
  11896.             name = \"Input\",\
  11897.             xPos = 1,\
  11898.             yPos = 1,\
  11899.             xLength = w,\
  11900.             yLength = h,\
  11901.             BackgroundColor = colors.gray,\
  11902.             Button = {\
  11903.                 One = {\
  11904.                     name = \"One\",\
  11905.                     label = \"1\",\
  11906.                     xPos = 35,\
  11907.                     yPos = 4,\
  11908.                     fgColor = colors.white,\
  11909.                     bgColor = colors.orange,\
  11910.                     xLength = 3,\
  11911.                     yLength = 3,\
  11912.                     returnValue = \"1\",\
  11913.                     xTextPos = 2,\
  11914.                     yTextPos = 2,\
  11915.                 },\
  11916.                 Two = {\
  11917.                     name = \"Two\",\
  11918.                     label = \"2\",\
  11919.                     xPos = 39,\
  11920.                     yPos = 4,\
  11921.                     fgColor = colors.white,\
  11922.                     bgColor = colors.orange,\
  11923.                     xLength = 3,\
  11924.                     yLength = 3,\
  11925.                     returnValue = \"2\",\
  11926.                     xTextPos = 2,\
  11927.                     yTextPos = 2,\
  11928.                 },\
  11929.                 Three = {\
  11930.                     name = \"Three\",\
  11931.                     label = \"3\",\
  11932.                     xPos = 43,\
  11933.                     yPos = 4,\
  11934.                     fgColor = colors.white,\
  11935.                     bgColor = colors.orange,\
  11936.                     xLength = 3,\
  11937.                     yLength = 3,\
  11938.                     returnValue = \"3\",\
  11939.                     xTextPos = 2,\
  11940.                     yTextPos = 2,\
  11941.                 },\
  11942.                 Four = {\
  11943.                     name = \"Four\",\
  11944.                     label = \"4\",\
  11945.                     xPos = 35,\
  11946.                     yPos = 8,\
  11947.                     fgColor = colors.white,\
  11948.                     bgColor = colors.orange,\
  11949.                     xLength = 3,\
  11950.                     yLength = 3,\
  11951.                     returnValue = \"4\",\
  11952.                     xTextPos = 2,\
  11953.                     yTextPos = 2,\
  11954.                 },\
  11955.                 Five = {\
  11956.                     name = \"Five\",\
  11957.                     label = \"5\",\
  11958.                     xPos = 39,\
  11959.                     yPos = 8,\
  11960.                     fgColor = colors.white,\
  11961.                     bgColor = colors.orange,\
  11962.                     xLength = 3,\
  11963.                     yLength = 3,\
  11964.                     returnValue = \"5\",\
  11965.                     xTextPos = 2,\
  11966.                     yTextPos = 2,\
  11967.                 },\
  11968.                 Six = {\
  11969.                     name = \"Six\",\
  11970.                     label = \"6\",\
  11971.                     xPos = 43,\
  11972.                     yPos = 8,\
  11973.                     fgColor = colors.white,\
  11974.                     bgColor = colors.orange,\
  11975.                     xLength = 3,\
  11976.                     yLength = 3,\
  11977.                     returnValue = \"6\",\
  11978.                     xTextPos = 2,\
  11979.                     yTextPos = 2,\
  11980.                 },\
  11981.                 Seven = {\
  11982.                     name = \"Seven\",\
  11983.                     label = \"7\",\
  11984.                     xPos = 35,\
  11985.                     yPos = 12,\
  11986.                     fgColor = colors.white,\
  11987.                     bgColor = colors.orange,\
  11988.                     xLength = 3,\
  11989.                     yLength = 3,\
  11990.                     returnValue = \"7\",\
  11991.                     xTextPos = 2,\
  11992.                     yTextPos = 2,\
  11993.                 },\
  11994.                 Eight = {\
  11995.                     name = \"Eight\",\
  11996.                     label = \"8\",\
  11997.                     xPos = 39,\
  11998.                     yPos = 12,\
  11999.                     fgColor = colors.white,\
  12000.                     bgColor = colors.orange,\
  12001.                     xLength = 3,\
  12002.                     yLength = 3,\
  12003.                     returnValue = \"8\",\
  12004.                     xTextPos = 2,\
  12005.                     yTextPos = 2,\
  12006.                 },\
  12007.                 Nine = {\
  12008.                     name = \"Nine\",\
  12009.                     label = \"9\",\
  12010.                     xPos = 43,\
  12011.                     yPos = 12,\
  12012.                     fgColor = colors.white,\
  12013.                     bgColor = colors.orange,\
  12014.                     xLength = 3,\
  12015.                     yLength = 3,\
  12016.                     returnValue = \"9\",\
  12017.                     xTextPos = 2,\
  12018.                     yTextPos = 2,\
  12019.                 },\
  12020.                 Zero = {\
  12021.                     name = \"Zero\",\
  12022.                     label = \"0\",\
  12023.                     xPos = 35,\
  12024.                     yPos = 16,\
  12025.                     fgColor = colors.white,\
  12026.                     bgColor = colors.orange,\
  12027.                     xLength = 3,\
  12028.                     yLength = 3,\
  12029.                     returnValue = \"0\",\
  12030.                     xTextPos = 2,\
  12031.                     yTextPos = 2,\
  12032.                 },\
  12033.                 Equals = {\
  12034.                     name = \"Equals\",\
  12035.                     label = \"=\",\
  12036.                     xPos = 39,\
  12037.                     yPos = 16,\
  12038.                     fgColor = colors.white,\
  12039.                     bgColor = colors.lightGray,\
  12040.                     xLength = 7,\
  12041.                     yLength = 3,\
  12042.                     returnValue = \"=\",\
  12043.                     xTextPos = 4,\
  12044.                     yTextPos = 2,\
  12045.                 },\
  12046.                 Add = {\
  12047.                     name = \"Add\",\
  12048.                     label = \"+\",\
  12049.                     xPos = 47,\
  12050.                     yPos = 4,\
  12051.                     fgColor = colors.white,\
  12052.                     bgColor = colors.green,\
  12053.                     xLength = 3,\
  12054.                     yLength = 3,\
  12055.                     returnValue = \"+\",\
  12056.                     xTextPos = 2,\
  12057.                     yTextPos = 2,\
  12058.                 },\
  12059.                 Sub = {\
  12060.                     name = \"Sub\",\
  12061.                     label = \"-\",\
  12062.                     xPos = 47,\
  12063.                     yPos = 8,\
  12064.                     fgColor = colors.white,\
  12065.                     bgColor = colors.green,\
  12066.                     xLength = 3,\
  12067.                     yLength = 3,\
  12068.                     returnValue = \"-\",\
  12069.                     xTextPos = 2,\
  12070.                     yTextPos = 2,\
  12071.                 },\
  12072.                 Mul = {\
  12073.                     name = \"Mul\",\
  12074.                     label = \"*\",\
  12075.                     xPos = 47,\
  12076.                     yPos = 12,\
  12077.                     fgColor = colors.white,\
  12078.                     bgColor = colors.green,\
  12079.                     xLength = 3,\
  12080.                     yLength = 3,\
  12081.                     returnValue = \"*\",\
  12082.                     xTextPos = 2,\
  12083.                     yTextPos = 2,\
  12084.                 },\
  12085.                 Div = {\
  12086.                     name = \"Div\",\
  12087.                     label = \"/\",\
  12088.                     xPos = 47,\
  12089.                     yPos = 16,\
  12090.                     fgColor = colors.white,\
  12091.                     bgColor = colors.green,\
  12092.                     xLength = 3,\
  12093.                     yLength = 3,\
  12094.                     returnValue = \"/\",\
  12095.                     xTextPos = 2,\
  12096.                     yTextPos = 2,\
  12097.                 },\
  12098.                 LPar = {\
  12099.                     name = \"LPar\",\
  12100.                     label = \"(\",\
  12101.                     xPos = 31,\
  12102.                     yPos = 12,\
  12103.                     fgColor = colors.white,\
  12104.                     bgColor = colors.green,\
  12105.                     xLength = 3,\
  12106.                     yLength = 3,\
  12107.                     returnValue = \"(\",\
  12108.                     xTextPos = 2,\
  12109.                     yTextPos = 2,\
  12110.                 },\
  12111.                 RPar = {\
  12112.                     name = \"RPar\",\
  12113.                     label = \")\",\
  12114.                     xPos = 31,\
  12115.                     yPos = 16,\
  12116.                     fgColor = colors.white,\
  12117.                     bgColor = colors.green,\
  12118.                     xLength = 3,\
  12119.                     yLength = 3,\
  12120.                     returnValue = \")\",\
  12121.                     xTextPos = 2,\
  12122.                     yTextPos = 2,\
  12123.                 },\
  12124.                 Mod = {\
  12125.                     name = \"Mod\",\
  12126.                     label = \"%\",\
  12127.                     xPos = 31,\
  12128.                     yPos = 8,\
  12129.                     fgColor = colors.white,\
  12130.                     bgColor = colors.green,\
  12131.                     xLength = 3,\
  12132.                     yLength = 3,\
  12133.                     returnValue = \"%\",\
  12134.                     xTextPos = 2,\
  12135.                     yTextPos = 2,\
  12136.                 },\
  12137.                 Comma = {\
  12138.                     name = \"Comma\",\
  12139.                     label = \",\",\
  12140.                     xPos = 31,\
  12141.                     yPos = 4,\
  12142.                     fgColor = colors.white,\
  12143.                     bgColor = colors.green,\
  12144.                     xLength = 3,\
  12145.                     yLength = 3,\
  12146.                     returnValue = \",\",\
  12147.                     xTextPos = 2,\
  12148.                     yTextPos = 2,\
  12149.                 },\
  12150.                 Abs = {\
  12151.                     name = \"Abs\",\
  12152.                     label = \"abs\",\
  12153.                     xPos = 25,\
  12154.                     yPos = 4,\
  12155.                     fgColor = colors.white,\
  12156.                     bgColor = colors.lightGray,\
  12157.                     xLength = 5,\
  12158.                     yLength = 3,\
  12159.                     returnValue = \"abs(\",\
  12160.                     xTextPos = 2,\
  12161.                     yTextPos = 2,\
  12162.                 },\
  12163.                 Deg = {\
  12164.                     name = \"Deg\",\
  12165.                     label = \"deg\",\
  12166.                     xPos = 25,\
  12167.                     yPos = 8,\
  12168.                     fgColor = colors.white,\
  12169.                     bgColor = colors.lightGray,\
  12170.                     xLength = 5,\
  12171.                     yLength = 3,\
  12172.                     returnValue = \"deg(\",\
  12173.                     xTextPos = 2,\
  12174.                     yTextPos = 2,\
  12175.                 },\
  12176.                 Max = {\
  12177.                     name = \"Max\",\
  12178.                     label = \"max\",\
  12179.                     xPos = 25,\
  12180.                     yPos = 12,\
  12181.                     fgColor = colors.white,\
  12182.                     bgColor = colors.lightGray,\
  12183.                     xLength = 5,\
  12184.                     yLength = 3,\
  12185.                     returnValue = \"max(\",\
  12186.                     xTextPos = 2,\
  12187.                     yTextPos = 2,\
  12188.                 },\
  12189.                 Log = {\
  12190.                     name = \"Log\",\
  12191.                     label = \"log\",\
  12192.                     xPos = 25,\
  12193.                     yPos = 16,\
  12194.                     fgColor = colors.white,\
  12195.                     bgColor = colors.lightGray,\
  12196.                     xLength = 5,\
  12197.                     yLength = 3,\
  12198.                     returnValue = \"log(\",\
  12199.                     xTextPos = 2,\
  12200.                     yTextPos = 2,\
  12201.                 },\
  12202.                 Pow = {\
  12203.                     name = \"Pow\",\
  12204.                     label = \"pow\",\
  12205.                     xPos = 19,\
  12206.                     yPos = 4,\
  12207.                     fgColor = colors.white,\
  12208.                     bgColor = colors.lightGray,\
  12209.                     xLength = 5,\
  12210.                     yLength = 3,\
  12211.                     returnValue = \"pow(\",\
  12212.                     xTextPos = 2,\
  12213.                     yTextPos = 2,\
  12214.                 },\
  12215.                 Tan = {\
  12216.                     name = \"Tan\",\
  12217.                     label = \"tan\",\
  12218.                     xPos = 19,\
  12219.                     yPos = 8,\
  12220.                     fgColor = colors.white,\
  12221.                     bgColor = colors.lightGray,\
  12222.                     xLength = 5,\
  12223.                     yLength = 3,\
  12224.                     returnValue = \"tan(\",\
  12225.                     xTextPos = 2,\
  12226.                     yTextPos = 2,\
  12227.                 },\
  12228.                 Min = {\
  12229.                     name = \"Min\",\
  12230.                     label = \"min\",\
  12231.                     xPos = 19,\
  12232.                     yPos = 12,\
  12233.                     fgColor = colors.white,\
  12234.                     bgColor = colors.lightGray,\
  12235.                     xLength = 5,\
  12236.                     yLength = 3,\
  12237.                     returnValue = \"min(\",\
  12238.                     xTextPos = 2,\
  12239.                     yTextPos = 2,\
  12240.                 },\
  12241.                 Rad = {\
  12242.                     name = \"Rad\",\
  12243.                     label = \"rad\",\
  12244.                     xPos = 19,\
  12245.                     yPos = 16,\
  12246.                     fgColor = colors.white,\
  12247.                     bgColor = colors.lightGray,\
  12248.                     xLength = 5,\
  12249.                     yLength = 3,\
  12250.                     returnValue = \"rad(\",\
  12251.                     xTextPos = 2,\
  12252.                     yTextPos = 2,\
  12253.                 },\
  12254.                 Sin = {\
  12255.                     name = \"Sin\",\
  12256.                     label = \"sin\",\
  12257.                     xPos = 13,\
  12258.                     yPos = 4,\
  12259.                     fgColor = colors.white,\
  12260.                     bgColor = colors.lightGray,\
  12261.                     xLength = 5,\
  12262.                     yLength = 3,\
  12263.                     returnValue = \"sin(\",\
  12264.                     xTextPos = 2,\
  12265.                     yTextPos = 2,\
  12266.                 },\
  12267.                 Exp = {\
  12268.                     name = \"Exp\",\
  12269.                     label = \"exp\",\
  12270.                     xPos = 13,\
  12271.                     yPos = 8,\
  12272.                     fgColor = colors.white,\
  12273.                     bgColor = colors.lightGray,\
  12274.                     xLength = 5,\
  12275.                     yLength = 3,\
  12276.                     returnValue = \"exp(\",\
  12277.                     xTextPos = 2,\
  12278.                     yTextPos = 2,\
  12279.                 },\
  12280.                 Cos = {\
  12281.                     name = \"Cos\",\
  12282.                     label = \"cos\",\
  12283.                     xPos = 13,\
  12284.                     yPos = 12,\
  12285.                     fgColor = colors.white,\
  12286.                     bgColor = colors.lightGray,\
  12287.                     xLength = 5,\
  12288.                     yLength = 3,\
  12289.                     returnValue = \"cos(\",\
  12290.                     xTextPos = 2,\
  12291.                     yTextPos = 2,\
  12292.                 },\
  12293.                 Pi = {\
  12294.                     name = \"Pi\",\
  12295.                     label = \"pi\",\
  12296.                     xPos = 14,\
  12297.                     yPos = 16,\
  12298.                     fgColor = colors.white,\
  12299.                     bgColor = colors.lightGray,\
  12300.                     xLength = 4,\
  12301.                     yLength = 3,\
  12302.                     returnValue = \"pi\",\
  12303.                     xTextPos = 2,\
  12304.                     yTextPos = 2,\
  12305.                 },\
  12306.                 Atan = {\
  12307.                     name = \"Atan\",\
  12308.                     label = \"atan\",\
  12309.                     xPos = 7,\
  12310.                     yPos = 16,\
  12311.                     fgColor = colors.white,\
  12312.                     bgColor = colors.lightGray,\
  12313.                     xLength = 6,\
  12314.                     yLength = 3,\
  12315.                     returnValue = \"atan(\",\
  12316.                     xTextPos = 2,\
  12317.                     yTextPos = 2,\
  12318.                 },\
  12319.             },\
  12320.         }\
  12321.     }\
  12322. }\
  12323. \
  12324. return tTable",
  12325.         },
  12326.       },
  12327.     },
  12328.     [ "BetterPaint.app" ] = {
  12329.       [ "BetterPaint.ico" ] = "error('This is an image, not a program!')\
  12330. {\
  12331.  {\
  12332.    {\
  12333.      2,\
  12334.      \"D\",\
  12335.      1,\
  12336.    },\
  12337.    {\
  12338.      2,\
  12339.      \"E\",\
  12340.      1,\
  12341.    },\
  12342.    {\
  12343.      2,\
  12344.      \"F\",\
  12345.      1,\
  12346.    },\
  12347.  },\
  12348.  {\
  12349.    {\
  12350.      8192,\
  12351.      \"G\",\
  12352.      1,\
  12353.    },\
  12354.    {\
  12355.      8192,\
  12356.      \"H\",\
  12357.      1,\
  12358.    },\
  12359.    {\
  12360.      8192,\
  12361.      \"I\",\
  12362.      1,\
  12363.    },\
  12364.  },\
  12365.  {\
  12366.    {\
  12367.      2048,\
  12368.      \"J\",\
  12369.      1,\
  12370.    },\
  12371.    {\
  12372.      2048,\
  12373.      \"K\",\
  12374.      1,\
  12375.    },\
  12376.    {\
  12377.      2048,\
  12378.      \"L\",\
  12379.      1,\
  12380.    },\
  12381.  },\
  12382.  [ 0 ] = {\
  12383.    {\
  12384.      16384,\
  12385.      \"A\",\
  12386.      1,\
  12387.    },\
  12388.    {\
  12389.      16384,\
  12390.      \"B\",\
  12391.      1,\
  12392.    },\
  12393.    {\
  12394.      16384,\
  12395.      \"C\",\
  12396.      1,\
  12397.    },\
  12398.  },\
  12399. }",
  12400.       [ "main.lua" ] = "transparentIcon = \"-\"\
  12401. args = {...}\
  12402. tX, tY = term.getSize()\
  12403. \
  12404. function drawImage(file,xSet,ySet,redirection)\
  12405. init()\
  12406. lastImage = file\
  12407. lastX = xSet\
  12408. lastY = ySet\
  12409. lastRedirection = redirection\
  12410. if redirection then\
  12411.  current = term.current()\
  12412.  term.redirect(redirection)\
  12413. end\
  12414. drawData(xSet,ySet,file)\
  12415. if redirection then\
  12416.  term.redirect(current)\
  12417. end\
  12418. end\
  12419. \
  12420. function overWrite(textSet,xSet,ySet,colorSet)\
  12421. init()\
  12422. exists = true\
  12423. if not lastImage then\
  12424.  error(\"Use drawImage first!\")\
  12425. end\
  12426. if not writeBuffer then\
  12427.  writeBuffer = {}\
  12428. end\
  12429. if not writeBuffer[lastImage] then\
  12430.  writeBuffer[lastImage] = {}\
  12431. end\
  12432. plusPos = 0\
  12433. for char in string.gmatch(textSet,\".\") do\
  12434.  if not writeBuffer[lastImage][xSet+plusPos] then\
  12435.   writeBuffer[lastImage][xSet+plusPos] = {}\
  12436.  end\
  12437.  if not writeBuffer[lastImage][xSet+plusPos][ySet] then\
  12438.   writeBuffer[lastImage][xSet+plusPos][ySet] = {colors.black,\" \",colors.white}\
  12439.  end\
  12440.  writeBuffer[lastImage][xSet+plusPos][ySet][2] = char\
  12441.  writeBuffer[lastImage][xSet+plusPos][ySet][3] = colorSet\
  12442.  plusPos = plusPos + 1 \
  12443. end\
  12444. drawImage(lastImage,lastX,lastY,lastRedirection)\
  12445. end\
  12446. \
  12447. function init()\
  12448. function eventHandler()\
  12449. while true do\
  12450.  event = {os.pullEvent()}\
  12451.  if event[1] == \"key\" then\
  12452.   if event[2] == keys.leftCtrl or event[2] == 157 then\
  12453.    menuStatus = not menuStatus\
  12454.    writeMenuBar(menuStatus)\
  12455.   end\
  12456.   if menuStatus == true then\
  12457.    if event[2] == keys.right or event[2] == keys.left then\
  12458.     if menuItemSelected == 1 then\
  12459.      menuItemSelected = 2\
  12460.     else\
  12461.      menuItemSelected = 1\
  12462.     end\
  12463.     writeMenuBar(menuStatus)\
  12464.    elseif event[2] == keys.enter then\
  12465.     if menuItemSelected == 1 then\
  12466.      save()\
  12467.      writeMenuBar(false)\
  12468.     else\
  12469.      term.setTextColor(colors.yellow)\
  12470.      term.setBackgroundColor(colors.black)\
  12471.      term.clear()\
  12472.      term.setCursorPos(1,1)\
  12473.      error()\
  12474.     end\
  12475.    end\
  12476.   else   \
  12477.    if event[2] == keys.right then\
  12478.     drawData(offSetX-1,offSetY)\
  12479.     drawMenu()\
  12480.     writeMenuBar(menuStatus)\
  12481.    elseif event[2] == keys.left then\
  12482.     drawData(offSetX+1,offSetY)\
  12483.     drawMenu()\
  12484.     writeMenuBar(menuStatus)\
  12485.    elseif event[2] == keys.up then\
  12486.     drawData(offSetX,offSetY+1)\
  12487.     drawMenu()\
  12488.     writeMenuBar(menuStatus)\
  12489.    elseif event[2] == keys.down then\
  12490.     drawData(offSetX,offSetY-1)\
  12491.     drawMenu()\
  12492.     writeMenuBar(menuStatus)\
  12493.    end\
  12494.   end\
  12495.  end\
  12496.  if event[1] == \"mouse_click\" or event[1] == \"mouse_drag\" then\
  12497.   if event[3] > 2 and event[4] ~= tY then\
  12498.    insertItem(event[3],event[4],event[2])\
  12499.   elseif event[4] < 18 and event[4] > 1 then\
  12500.    if event[3] == 1 then\
  12501.     bgSelected = 2^(event[4]-2)\
  12502.    elseif event[3] == 2 then\
  12503.     tSelected = 2^(event[4]-2)\
  12504.    end\
  12505.    drawMenu()\
  12506.   elseif event[4] == tY - 1 and event[3] == 1 then\
  12507.    setLetter()\
  12508.    drawData(offSetX,offSetY)\
  12509.    drawMenu()\
  12510.   elseif event[3] == tX and event[4] == tY and menuStatus == false then\
  12511.    writeHelp()\
  12512.   end\
  12513.  end\
  12514.  if event[1] == \"char\" then\
  12515.   textSelected = string.sub(event[2],1,1)\
  12516.   drawMenu()\
  12517.  end\
  12518.  --drawData(offSetX,offSetY)\
  12519. end\
  12520. end\
  12521. \
  12522. function writeHelp()\
  12523. term.setBackgroundColor(colors.black)\
  12524. term.setTextColor(colors.green)\
  12525. term.clear()\
  12526. term.setCursorPos(1,1)\
  12527. term.write(\"Help:\")\
  12528. term.setTextColor(colors.white)\
  12529. term.setCursorPos(1,3)\
  12530. print(\"Usage:\")\
  12531. term.setTextColor(colors.lightGray)\
  12532. print(\"  Select color: Click on the color on the left\")\
  12533. print(\"  Change draw char: Press a key on the keyboard\")\
  12534. print(\"  Change transparent icon: Click on the icon's char in the menu\")\
  12535. print(\"  Change text color: Click on a color in the menu on the right side\")\
  12536. print(\"  Change background color: Click on a color in the menu on the left side\")\
  12537. term.setTextColor(colors.white)\
  12538. print()\
  12539. print(\"Controls:\")\
  12540. term.setTextColor(colors.lightGray)\
  12541. print(\"  Arrow keys to pan\")\
  12542. print(\"  Left mouse button to select and draw\")\
  12543. print(\"  Right mouse button to delete\")\
  12544. print(\"  Ctrl to open menu\")\
  12545. print()\
  12546. term.setTextColor(colors.white)\
  12547. term.write(\"Click a mouse button to exit.\")\
  12548. term.setTextColor(colors.orange)\
  12549. term.setCursorPos(tX-9,1)\
  12550. term.write(\"API help >\")\
  12551. event = {os.pullEvent(\"mouse_click\")}\
  12552. if event[3] > tX-10 and event[4] == 1 then\
  12553.  drawAPIhelp()\
  12554. end\
  12555. drawData(offSetX,offSetY)\
  12556. drawMenu()\
  12557. writeMenuBar(menuStatus)\
  12558. end\
  12559. \
  12560. function drawAPIhelp()\
  12561. term.clear()\
  12562. term.setCursorPos(1,1)\
  12563. term.setTextColor(colors.orange)\
  12564. print(\"API help menu:\")\
  12565. print()\
  12566. term.setTextColor(colors.white)\
  12567. print(\"Drawing an image: \")\
  12568. term.setTextColor(colors.lightGray)\
  12569. print(shell.getRunningProgram(),\".drawImage(<file name>,<x pos>,<y pos>,[redirection object])\")\
  12570. print()\
  12571. term.setTextColor(colors.white)\
  12572. print(\"Overlaying text on the last image:\")\
  12573. term.setTextColor(colors.lightGray)\
  12574. print(shell.getRunningProgram(),\".overWrite(<Text>,<x pos>,<y pos>,<text color>\")\
  12575. print()\
  12576. term.setTextColor(colors.red)\
  12577. print(\"Overwriting text will only work AFTER drawing an image!\")\
  12578. term.setTextColor(colors.white)\
  12579. print()\
  12580. print(\"Example:\")\
  12581. term.setTextColor(colors.lightGray)\
  12582. print(\"os.loadAPI(\\\"\",shell.getRunningProgram(),\"\\\")\")\
  12583. print(shell.getRunningProgram(),\".drawImage(\\\"myPicture\\\",1,1)\")\
  12584. print(shell.getRunningProgram(),\".overWrite(\\\"Hello!\\\",2,3,colors.orange)\")\
  12585. os.pullEvent(\"mouse_click\")\
  12586. end\
  12587. \
  12588. function setLetter()\
  12589. term.setBackgroundColor(colors.red)\
  12590. term.setTextColor(colors.black)\
  12591. for i=1,4 do\
  12592.  term.setCursorPos(tX/2-11,(tY/2-4)+i)\
  12593.  term.write(\"                     \")\
  12594. end\
  12595. term.setCursorPos(tX/2-10,tY/2-2)\
  12596. term.write(\"Change transparancy\")\
  12597. term.setCursorPos(tX/2-10,tY/2-1)\
  12598. term.write(\"character to: (key)\")\
  12599. event = {os.pullEvent(\"char\")}\
  12600. transparentIcon = event[2]\
  12601. end\
  12602. \
  12603. function insertItem(xPos,yPos,modeSet)\
  12604. if saved == true then\
  12605.  saved = false\
  12606.  writeMenuBar(false)\
  12607. end\
  12608. --bgSelected\
  12609. --tSelected\
  12610. --textSelected\
  12611. if not painted then\
  12612.  painted = {}\
  12613. end\
  12614. if not painted[xPos-offSetX] then\
  12615.  painted[xPos-offSetX] = {}\
  12616. end\
  12617. if modeSet == 1 then\
  12618.   if not textSelected then\
  12619.    textSelected = \" \"\
  12620.   end\
  12621.   TMPtextSelected = textSelected\
  12622.   painted[xPos-offSetX][yPos-offSetY] = {bgSelected,textSelected,tSelected}\
  12623.   term.setBackgroundColor(bgSelected)\
  12624.   term.setTextColor(tSelected)\
  12625.  else\
  12626.   TMPtextSelected = transparentIcon\
  12627.   term.setBackgroundColor(colors.black)\
  12628.   term.setTextColor(colors.gray)\
  12629.   painted[xPos-offSetX][yPos-offSetY] = nil\
  12630. end\
  12631. term.setCursorPos(xPos,yPos)\
  12632. term.write(TMPtextSelected)\
  12633. end\
  12634. \
  12635. --if #args ~= 1 then\
  12636. -- print(\"Usage: \"..shell.getRunningProgram()..\" <path>\")\
  12637. -- return\
  12638. --end\
  12639. \
  12640. if args[1] and fs.exists(args[1]) == true then\
  12641. buff = fs.open(args[1],\"r\")\
  12642. previousData = buff.readAll()\
  12643. buff.close()\
  12644. processed = string.sub(previousData,43)\
  12645. painted = textutils.unserialize(processed)\
  12646. else\
  12647. painted = {}\
  12648. end\
  12649. \
  12650. function save()\
  12651. file = fs.open(args[1],\"w\")\
  12652. file.write(\"error('This is an image, not a program!')\\n\"..textutils.serialize(painted))\
  12653. file.close()\
  12654. saved = true\
  12655. end\
  12656. \
  12657. function drawData(xStart, yStart, file)\
  12658. offSetX = xStart\
  12659. offSetY = yStart\
  12660. if not file then\
  12661.  term.setBackgroundColor(colors.black)\
  12662.  term.setTextColor(colors.gray)\
  12663.  transparentLine = \"\"\
  12664.  for x=1,tX-2 do\
  12665.   transparentLine = transparentIcon..transparentLine\
  12666.  end\
  12667.  for y=1,tY-1 do\
  12668.   term.setCursorPos(3,y)\
  12669.   term.write(transparentLine)\
  12670.  end\
  12671. else\
  12672.  if fs.exists(file) == false then\
  12673.   error(\"File given doesnt exists! file name: \"..file)\
  12674.  else\
  12675.   local fileD = fs.open(file,\"r\")\
  12676.   raw = fileD.readAll()\
  12677.   --ignoreL = string.len(fileD.readLine(1))\
  12678.   processed = string.sub(raw,43)\
  12679.   --term.redirect(term.native())\
  12680.  -- textutils.pagedPrint(processed)\
  12681.   painted = textutils.unserialize(processed)\
  12682.   fileD.close()\
  12683.  end\
  12684. end\
  12685. if not painted then\
  12686.  painted = {}\
  12687. end\
  12688. paintedF = painted\
  12689. count = 0\
  12690. repeat ---------\
  12691. count = count + 1\
  12692. for xPos,v in pairs(paintedF) do\
  12693.  for yPos in pairs (paintedF[xPos]) do\
  12694.    overWrite = true\
  12695.    if not lastImage or not writeBuffer or not writeBuffer[lastImage] then\
  12696.     overWrite = false\
  12697.    end\
  12698.    if overWrite == true then\
  12699.     if not writeBuffer[lastImage][xPos] then\
  12700.      overWrite = false\
  12701.     end\
  12702.    end\
  12703.    if overWrite == true then\
  12704.     if not writeBuffer[lastImage][xPos][yPos] then\
  12705.      overWrite = false\
  12706.     end\
  12707.    end\
  12708.    if overWrite == false then\
  12709.     bgColor = paintedF[xPos][yPos][1]\
  12710.     text = paintedF[xPos][yPos][2]\
  12711.     tColor = paintedF[xPos][yPos][3]\
  12712.    else\
  12713.     if painted and painted[xPos] and painted[xPos][yPos] and painted[xPos][yPos][1] then\
  12714.      bgColor = painted[xPos][yPos][1]\
  12715.      else\
  12716.      bgColor = colors.black\
  12717.     end\
  12718.     --if not bgColor then\
  12719.    --  bgColor = colors.black\
  12720.     --end\
  12721.     text = writeBuffer[lastImage][xPos][yPos][2]\
  12722.     tColor = writeBuffer[lastImage][xPos][yPos][3]\
  12723.    end\
  12724.    if not tColor then\
  12725.     tColor = colors.white\
  12726.    end\
  12727.    if not text then\
  12728.     text = \" \"\
  12729.    end\
  12730.    term.setCursorPos(xPos+xStart,yPos+yStart)\
  12731.    term.setBackgroundColor(bgColor)\
  12732.    term.setTextColor(tColor)\
  12733.    term.write(text)\
  12734.   end\
  12735.  end\
  12736.  if count == 1 and writeBuffer and lastImage then\
  12737.   paintedF = writeBuffer[lastImage]\
  12738.  elseif count == 1 and not lastImage or not writeBuffer then\
  12739.   count = 2\
  12740.  end\
  12741. until count == 2\
  12742. term.setCursorPos(1,tY)\
  12743. end\
  12744. \
  12745. function drawMenu()\
  12746. term.setCursorPos(1,1)\
  12747. term.setTextColor(colors.white)\
  12748. if not bgSelected then\
  12749.  bgSelected = colors.black\
  12750. elseif bgSelected == colors.white then\
  12751.  term.setTextColor(colors.black)\
  12752. end\
  12753. if not tSelected then\
  12754.  tSelected = colors.white\
  12755. elseif tSelected == colors.white then\
  12756.  term.setTextColor(colors.black)\
  12757. end\
  12758. if not textSelected then\
  12759.  textSelected = \" \"\
  12760. end\
  12761. term.setBackgroundColor(bgSelected)\
  12762. term.write(\"B\")\
  12763. term.setBackgroundColor(tSelected)\
  12764. term.write(\"T\")\
  12765. for i=1,16 do\
  12766.  i=i-1\
  12767.  term.setCursorPos(1,i+2)\
  12768.  term.setBackgroundColor(2^i)\
  12769.  term.write(\"  \")\
  12770. end\
  12771. term.setCursorPos(1,18)\
  12772. term.setBackgroundColor(colors.black)\
  12773. if not textSelected then\
  12774.  textSelected = \" \"\
  12775. elseif string.len(textSelected) > 1 then\
  12776.  textSelected = string.sub(textSelected,1,1)\
  12777. end\
  12778. term.setTextColor(colors.gray)\
  12779. term.setBackgroundColor(colors.black)\
  12780. term.write(transparentIcon)\
  12781. term.setTextColor(tSelected)\
  12782. term.setBackgroundColor(bgSelected)\
  12783. term.write(textSelected)\
  12784. end\
  12785. \
  12786. function writeMenuBar(booly)\
  12787. menuStatus = booly\
  12788. term.setBackgroundColor(colors.black)\
  12789. if booly == true then\
  12790.  term.setCursorPos(1,tY)\
  12791.  term.clearLine()\
  12792.  if not menuItemSelected then\
  12793.   menuItemSelected = 1\
  12794.  end\
  12795.  term.setTextColor(colors.white)\
  12796.  term.write(\" Save  Exit \")\
  12797.  term.setCursorPos(6*menuItemSelected-5,tY)\
  12798.  term.setTextColor(colors.yellow)\
  12799.  term.write(\"[\")\
  12800.  term.setCursorPos(6*menuItemSelected,tY)\
  12801.  term.write(\"]\")\
  12802. elseif booly == false then\
  12803.  term.setCursorPos(1,tY)\
  12804.  term.setTextColor(colors.yellow)\
  12805.  term.clearLine()\
  12806.  if saved == true then\
  12807.   term.write(\"Saved to \"..args[1])\
  12808.  else\
  12809.   term.write(\"Press Ctrl to access menu\")\
  12810.  end\
  12811.  term.setCursorPos(tX,tY)\
  12812.  term.setTextColor(colors.lightGray)\
  12813.  term.write(\"?\")\
  12814. end\
  12815. end\
  12816. end\
  12817. \
  12818. if #args > 0 then\
  12819.  init()\
  12820.  menuStatus = false\
  12821.  saved = false\
  12822.  writeMenuBar(menuStatus)\
  12823.  menuItemSelected = 1\
  12824.  drawData(3,0)\
  12825.  drawMenu()\
  12826.  eventHandler()\
  12827. else\
  12828.  term.setBackgroundColor(colors.black)\
  12829.  term.setTextColor(colors.white)\
  12830.  term.clear()\
  12831.  term.setCursorPos(1,1)\
  12832.  term.write(\"Do you want to create a new file? <y/n>\")\
  12833.  local answ = read()\
  12834.  if answ:sub(1,1) == \"y\" then\
  12835.    print()\
  12836.    term.write(\"Path please!\")\
  12837.    args[1] = \"OmniOS/Data/\"..read()\
  12838.     init()\
  12839.      menuStatus = false\
  12840.      saved = false\
  12841.      writeMenuBar(menuStatus)\
  12842.      menuItemSelected = 1\
  12843.      drawData(3,0)\
  12844.      drawMenu()\
  12845.      eventHandler()\
  12846.  end\
  12847. end",
  12848.       [ "permission.data" ] = "user",
  12849.     },
  12850.     [ "nPaintPro.app" ] = {
  12851.       [ "nPaintPro.ico" ] = "error('This is an image, not a program!')\
  12852. {\
  12853.  {\
  12854.    {\
  12855.      2048,\
  12856.      \"N\",\
  12857.      1,\
  12858.    },\
  12859.    {\
  12860.      2048,\
  12861.      \"p\",\
  12862.      1,\
  12863.    },\
  12864.    {\
  12865.      2048,\
  12866.      \"p\",\
  12867.      1,\
  12868.    },\
  12869.  },\
  12870.  {\
  12871.    {\
  12872.      2048,\
  12873.      \" \",\
  12874.      1,\
  12875.    },\
  12876.    {\
  12877.      2048,\
  12878.      \" \",\
  12879.      2048,\
  12880.    },\
  12881.    {\
  12882.      2048,\
  12883.      \" \",\
  12884.      2048,\
  12885.    },\
  12886.  },\
  12887.  {\
  12888.    {\
  12889.      2048,\
  12890.      \" \",\
  12891.      2048,\
  12892.    },\
  12893.    {\
  12894.      2048,\
  12895.      \" \",\
  12896.      2048,\
  12897.    },\
  12898.    {\
  12899.      2048,\
  12900.      \" \",\
  12901.      2048,\
  12902.    },\
  12903.  },\
  12904.  [ 0 ] = {\
  12905.    {\
  12906.      2048,\
  12907.      \" \",\
  12908.      2048,\
  12909.    },\
  12910.    {\
  12911.      2048,\
  12912.      \" \",\
  12913.      2048,\
  12914.    },\
  12915.    {\
  12916.      2048,\
  12917.      \" \",\
  12918.      2048,\
  12919.    },\
  12920.  },\
  12921. }",
  12922.       [ "main.lua" ] = "--[[\
  12923.         NPaintPro\
  12924.         By NitrogenFingers\
  12925. ]]--\
  12926. \
  12927. --The screen size\
  12928. local w,h = term.getSize()\
  12929. --Whether or not the program is currently waiting on user input\
  12930. local inMenu = false\
  12931. --Whether or not a drop down menu is active\
  12932. local inDropDown = false\
  12933. --Whether or not animation tools are enabled (use -a to turn them on)\
  12934. local animated = false\
  12935. --Whether or not \"blueprint\" display mode is on\
  12936. local blueprint = false\
  12937. --Whether or not the \"layer\" display is on\
  12938. local layerDisplay = false\
  12939. --Whether or not the \"direction\" display is on\
  12940. local printDirection = false\
  12941. --The tool/mode npaintpro is currently in. Default is \"paint\"\
  12942. --For a list of modes, check out the help file\
  12943. local state = \"paint\"\
  12944. --Whether or not the program is presently running\
  12945. local isRunning = true\
  12946. --The rednet address of the 3D printer, if one has been attached\
  12947. local printer = nil\
  12948. \
  12949. --The list of every frame, containing every image in the picture/animation\
  12950. --Note: nfp files always have the picture at frame 1\
  12951. local frames = { }\
  12952. --How many frames are currently in the given animation.\
  12953. local frameCount = 1\
  12954. --The Colour Picker column\
  12955. local column = {}\
  12956. --The currently selected left and right colours\
  12957. local lSel,rSel = colours.white,nil\
  12958. --The amount of scrolling on the X and Y axis\
  12959. local sx,sy = 0,0\
  12960. --The alpha channel colour\
  12961. --Change this to change default canvas colour\
  12962. local alphaC = colours.yellow\
  12963. --The currently selected frame. Default is 1\
  12964. local sFrame = 1\
  12965. --The contents of the image buffer- contains contents, width and height\
  12966. local buffer = nil\
  12967. --The position, width and height of the selection rectangle\
  12968. local selectrect = nil\
  12969. \
  12970. --The currently calculated required materials\
  12971. local requiredMaterials = {}\
  12972. --Whether or not required materials are being displayed in the pallette\
  12973. local requirementsDisplayed = false\
  12974. --A list of the rednet ID's all in-range printers located\
  12975. local printerList = { }\
  12976. --A list of the names of all in-range printers located. Same as the printerList in reference\
  12977. local printerNames = { }\
  12978. --The selected printer\
  12979. local selectedPrinter = 1\
  12980. --The X,Y,Z and facing of the printer\
  12981. local px,py,pz,pfx,pfz = 0,0,0,0,0\
  12982. --The form of layering used\
  12983. local layering = \"up\"\
  12984. \
  12985. --The animation state of the selection rectangle and image buffer \
  12986. local rectblink = 0\
  12987. --The ID for the timer\
  12988. local recttimer = nil\
  12989. --The radius of the brush tool\
  12990. local brushsize = 3\
  12991. --Whether or not \"record\" mode is activated (animation mode only)\
  12992. local record = false\
  12993. --The time between each frame when in play mode (animation mode only)\
  12994. local animtime = 0.3\
  12995. \
  12996. --A list of hexidecimal conversions from numbers to hex digits\
  12997. local hexnums = { [10] = \"a\", [11] = \"b\", [12] = \"c\", [13] = \"d\", [14] = \"e\" , [15] = \"f\" }\
  12998. --The NPaintPro logo (divine, isn't it?)\
  12999. local logo = {\
  13000. \"fcc              3   339\";\
  13001. \" fcc          9333    33\";\
  13002. \"  fcc        933 333  33\";\
  13003. \"   fcc       933  33  33\";\
  13004. \"    fcc      933   33 33\";\
  13005. \"     c88     333   93333\";\
  13006. \"     888     333    9333\";\
  13007. \"      333 3  333     939\";\
  13008. }\
  13009. --The Layer Up and Layer Forward printing icons\
  13010. local layerUpIcon = {\
  13011.     \"0000000\";\
  13012.     \"0088880\";\
  13013.     \"0888870\";\
  13014.     \"07777f0\";\
  13015.     \"0ffff00\";\
  13016.     \"0000000\";\
  13017. }\
  13018. local layerForwardIcon = {\
  13019.     \"0000000\";\
  13020.     \"000fff0\";\
  13021.     \"00777f0\";\
  13022.     \"0888700\";\
  13023.     \"0888000\";\
  13024.     \"0000000\";\
  13025. }\
  13026. --The available menu options in the ctrl menu\
  13027. local mChoices = {\"Save\",\"Exit\"}\
  13028. --The available modes from the dropdown menu- tables indicate submenus (include a name!)\
  13029. 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\" }\
  13030. --The available modes from the selection right-click menu\
  13031. local srModes = { \"cut\", \"copy\", \"paste\", \"clear\", \"hide\", name = \"selection\" }\
  13032. --The list of available help topics for each mode 127\
  13033. local helpTopics = {\
  13034.     [1] = {\
  13035.         name = \"Paint Mode\",\
  13036.         key = nil,\
  13037.         animonly = false,\
  13038.         message = \"The default mode for NPaintPro, for painting pixels.\"\
  13039.         ..\" Controls here that are not overridden will apply for all other modes. Leaving a mode by selecting that mode \"\
  13040.         ..\" again will always send the user back to paint mode.\",\
  13041.         controls = {\
  13042.             { \"Arrow keys\", \"Scroll the canvas\" },\
  13043.             { \"Left Click\", \"Paint/select left colour\" },\
  13044.             { \"Right Click\", \"Paint/select right colour\" },\
  13045.             { \"Z Key\", \"Clear image on screen\" },\
  13046.             { \"Tab Key\", \"Hide selection rectangle if visible\" },\
  13047.             { \"Q Key\", \"Set alpha mask to left colour\" },\
  13048.             { \"W Key\", \"Set alpha mask to right colour\" },\
  13049.             { \"Number Keys\", \"Swich between frames 1-9\" },\
  13050.             { \"</> keys\", \"Move to the next/last frame\" },\
  13051.             { \"R Key\", \"Removes every frame after the current frame\"}\
  13052.         }\
  13053.     },\
  13054.     [2] = {\
  13055.         name = \"Brush Mode\",\
  13056.         key = \"b\",\
  13057.         animonly = false,\
  13058.         message = \"Brush mode allows painting a circular area of variable diameter rather than a single pixel, working in \"..\
  13059.         \"the exact same way as paint mode in all other regards.\",\
  13060.         controls = {\
  13061.             { \"Left Click\", \"Paints a brush blob with the left colour\" },\
  13062.             { \"Right Click\", \"Paints a brush blob with the right colour\" },\
  13063.             { \"Number Keys\", \"Changes the radius of the brush blob from 2-9\" }\
  13064.         }\
  13065.     },\
  13066.     [3] = {\
  13067.         name = \"Pippette Mode\",\
  13068.         key = \"p\",\
  13069.         animonly = false,\
  13070.         message = \"Pippette mode allows the user to click the canvas and set the colour clicked to the left or right \"..\
  13071.         \"selected colour, for later painting.\",\
  13072.         controls = {\
  13073.             { \"Left Click\", \"Sets clicked colour to the left selected colour\" },\
  13074.             { \"Right Click\", \"Sets clicked colour to the right selected colour\" }\
  13075.         }\
  13076.     },\
  13077.     [4] = {\
  13078.         name = \"Move Mode\",\
  13079.         key = \"m\",\
  13080.         animonly = false,\
  13081.         message = \"Mode mode allows the moving of the entire image on the screen. This is especially useful for justifying\"..\
  13082.         \" the image to the top-left for animations or game assets.\",\
  13083.         controls = {\
  13084.             { \"Left/Right Click\", \"Moves top-left corner of image to selected square\" },\
  13085.             { \"Arrow keys\", \"Moves image one pixel in any direction\" }\
  13086.         }\
  13087.     },\
  13088.     [5] = {\
  13089.         name = \"Flood Mode (NYI)\",\
  13090.         key = \"f\",\
  13091.         animonly = false,\
  13092.         message = \"Flood mode allows the changing of an area of a given colour to that of the selected colour. \"..\
  13093.         \"The tool uses a flood4 algorithm and will not fill diagonally. Transparency cannot be flood filled.\",\
  13094.         controls = {\
  13095.             { \"Left Click\", \"Flood fills selected area to left colour\" },\
  13096.             { \"Right Click\", \"Flood fills selected area to right colour\" }\
  13097.         }\
  13098.     },\
  13099.     [6] = {\
  13100.         name = \"Select Mode\",\
  13101.         key = \"s\",\
  13102.         animonly = false,\
  13103.         message = \"Select mode allows the creation and use of the selection rectangle, to highlight specific areas on \"..\
  13104.         \"the screen and perform operations on the selected area of the image. The selection rectangle can contain an \"..\
  13105.         \"image on the clipboard- if it does, the image will flash inside the rectangle, and the rectangle edges will \"..\
  13106.         \"be light grey instead of dark grey.\",\
  13107.         controls = {\
  13108.             { \"C Key\", \"Copy: Moves selection into the clipboard\" },\
  13109.             { \"X Key\", \"Cut: Clears canvas under the rectangle, and moves it into the clipboard\" },\
  13110.             { \"V Key\", \"Paste: Copys clipboard to the canvas\" },\
  13111.             { \"Z Key\", \"Clears clipboard\" },\
  13112.             { \"Left Click\", \"Moves top-left corner of rectangle to selected pixel\" },\
  13113.             { \"Right Click\", \"Opens selection menu\" },\
  13114.             { \"Arrow Keys\", \"Moves rectangle one pixel in any direction\" }\
  13115.         }\
  13116.     },\
  13117.     [7] = {\
  13118.         name = \"Corner Select Mode\",\
  13119.         key = nil,\
  13120.         animonly = false,\
  13121.         message = \"If a selection rectangle isn't visible, this mode is selected automatically. It allows the \"..\
  13122.         \"defining of the corners of the rectangle- one the top-left and bottom-right corners have been defined, \"..\
  13123.         \"NPaintPro switches to selection mode. Note rectangle must be at least 2 pixels wide and high.\",\
  13124.         controls = {\
  13125.             { \"Left/Right Click\", \"Defines a corner of the selection rectangle\" }\
  13126.         }\
  13127.     },\
  13128.     [8] = {\
  13129.         name = \"Play Mode\",\
  13130.         key = \"space\",\
  13131.         animonly = true,\
  13132.         message = \"Play mode will loop through each frame in your animation at a constant rate. Editing tools are \"..\
  13133.         \"locked in this mode, and the coordinate display will turn green to indicate it is on.\",\
  13134.         controls = {\
  13135.             { \"</> Keys\", \"Increases/Decreases speed of the animation\" },\
  13136.             { \"Space Bar\", \"Returns to paint mode\" }\
  13137.         }\
  13138.     },\
  13139.     [9] = {\
  13140.         name = \"Record Mode\",\
  13141.         key = \"\\\\\",\
  13142.         animonly = true,\
  13143.         message = \"Record mode is not a true mode, but influences how other modes work. Changes made that modify the \"..\
  13144.         \"canvas in record mode will affect ALL frames in the animation. The coordinates will turn red to indicate that \"..\
  13145.         \"record mode is on.\",\
  13146.         controls = {\
  13147.             { \"\", \"Affects:\" },\
  13148.             { \"- Paint Mode\", \"\" },\
  13149.             { \"- Brush Mode\", \"\" },\
  13150.             { \"- Cut and Paste in Select Mode\", \"\"},\
  13151.             { \"- Move Mode\", \"\"}\
  13152.         }\
  13153.     },\
  13154.     [10] = {\
  13155.         name = \"Help Mode\",\
  13156.         key = \"h\",\
  13157.         animonly = false,\
  13158.         message = \"Displays this help screen. Clicking on options will display help on that topic. Clicking out of the screen\"..\
  13159.         \" will leave this mode.\",\
  13160.         controls = {\
  13161.             { \"Left/Right Click\", \"Displays a topic/Leaves the mode\" }\
  13162.         }\
  13163.     },\
  13164.     [11] = {\
  13165.         name = \"File Mode\",\
  13166.         keys = nil,\
  13167.         animonly = false,\
  13168.         message = \"Clicking on the mode display at the bottom of the screen will open the options menu. Here you can\"..\
  13169.         \" activate all of the modes in the program with a simple mouse click. Pressing left control will open up the\"..\
  13170.         \" file menu automatically.\",\
  13171.         controls = { \
  13172.             { \"leftCtrl\", \"Opens the file menu\" },\
  13173.             { \"leftAlt\", \"Opens the paint menu\" }\
  13174.             \
  13175.         }\
  13176.     }\
  13177. }\
  13178. --The \"bounds\" of the image- the first/last point on both axes where a pixel appears\
  13179. local toplim,botlim,leflim,riglim = nil,nil,nil,nil\
  13180. --The selected path\
  13181. local sPath = nil\
  13182. \
  13183. --[[  \
  13184.             Section:  Helpers       \
  13185. ]]--\
  13186. \
  13187. --[[Converts a colour parameter into a single-digit hex coordinate for the colour\
  13188.    Params: colour:int = The colour to be converted\
  13189.     Returns:string A string conversion of the colour\
  13190. ]]--\
  13191. local function getHexOf(colour)\
  13192.     if not colour or not tonumber(colour) then \
  13193.         return \" \" \
  13194.     end\
  13195.     local value = math.log(colour)/math.log(2)\
  13196.     if value > 9 then \
  13197.         value = hexnums[value] \
  13198.     end\
  13199.     return value\
  13200. end\
  13201. \
  13202. --[[Converts a hex digit into a colour value\
  13203.     Params: hex:?string = the hex digit to be converted\
  13204.     Returns:string A colour value corresponding to the hex, or nil if the character is invalid\
  13205. ]]--\
  13206. local function getColourOf(hex)\
  13207.     local value = tonumber(hex, 16)\
  13208.     if not value then return nil end\
  13209.     value = math.pow(2,value)\
  13210.     return value\
  13211. end\
  13212. \
  13213. --[[Finds the biggest and smallest bounds of the image- the outside points beyond which pixels do not appear\
  13214.     These values are assigned to the \"lim\" parameters for access by other methods\
  13215.     Params: forAllFrames:bool = True if all frames should be used to find bounds, otherwise false or nil\
  13216.     Returns:nil\
  13217. ]]--\
  13218. local function updateImageLims(forAllFrames)\
  13219.     local f,l = sFrame,sFrame\
  13220.     if forAllFrames == true then f,l = 1,framecount end\
  13221.     \
  13222.     toplim,botlim,leflim,riglim = nil,nil,nil,nil\
  13223.     for locf = f,l do\
  13224.         for y,_ in pairs(frames[locf]) do\
  13225.             for x,_ in pairs(frames[locf][y]) do\
  13226.                 if frames[locf][y][x] ~= nil then\
  13227.                     if leflim == nil or x < leflim then leflim = x end\
  13228.                     if toplim == nil or y < toplim then toplim = y end\
  13229.                     if riglim == nil or x > riglim then riglim = x end\
  13230.                     if botlim == nil or y > botlim then botlim = y end\
  13231.                 end\
  13232.             end\
  13233.         end\
  13234.     end\
  13235. end\
  13236. \
  13237. --[[Determines how much of each material is required for a print. Done each time printing is called.\
  13238.     Params: none\
  13239.     Returns:table A complete list of how much of each material is required.\
  13240. ]]--\
  13241. function calculateMaterials()\
  13242.     updateImageLims(animated)\
  13243.     requiredMaterials = {}\
  13244.     for i=1,16 do \
  13245.         requiredMaterials[i] = 0 \
  13246.     end\
  13247.     \
  13248.     if not toplim then return end\
  13249.     \
  13250.     for i=1,#frames do\
  13251.         for y = toplim, botlim do\
  13252.             for x = leflim, riglim do\
  13253.                 if type(frames[i][y][x]) == \"number\" then\
  13254.                     requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] = \
  13255.                         requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] + 1\
  13256.                 end \
  13257.             end\
  13258.         end\
  13259.     end\
  13260. end\
  13261. \
  13262. \
  13263. --[[Updates the rectangle blink timer. Should be called anywhere events are captured, along with a timer capture.\
  13264.     Params: nil\
  13265.     Returns:nil\
  13266. ]]--\
  13267. local function updateTimer(id)\
  13268.     if id == recttimer then\
  13269.         recttimer = os.startTimer(0.5)\
  13270.         rectblink = (rectblink % 2) + 1\
  13271.     end\
  13272. end\
  13273. \
  13274. --[[Constructs a message based on the state currently selected\
  13275.     Params: nil\
  13276.     Returns:string A message regarding the state of the application\
  13277. ]]--\
  13278. local function getStateMessage()\
  13279.     local msg = \" \"..string.upper(string.sub(state, 1, 1))..string.sub(state, 2, #state)..\" mode\"\
  13280.     if state == \"brush\" then msg = msg..\", size=\"..brushsize end\
  13281.     return msg\
  13282. end\
  13283. \
  13284. --[[Calls the rednet_message event, but also looks for timer events to keep then\
  13285.     system timer ticking.\
  13286.     Params: timeout:number how long before the event times out\
  13287.     Returns:number the id of the sender\
  13288.            :number the message send\
  13289. ]]--\
  13290. local function rsTimeReceive(timeout)\
  13291.     local timerID\
  13292.     if timeout then timerID = os.startTimer(timeout) end\
  13293.     \
  13294.     local id,key,msg = nil,nil\
  13295.     while true do\
  13296.         id,key,msg = os.pullEvent()\
  13297.         \
  13298.         if id == \"timer\" then\
  13299.             if key == timerID then return\
  13300.             else updateTimer(key) end\
  13301.         end\
  13302.         if id == \"rednet_message\" then \
  13303.             return key,msg\
  13304.         end\
  13305.     end\
  13306. end\
  13307. \
  13308. --[[Draws a picture, in paint table format on the screen\
  13309.     Params: image:table = the image to display\
  13310.             xinit:number = the x position of the top-left corner of the image\
  13311.             yinit:number = the y position of the top-left corner of the image\
  13312.             alpha:number = the color to display for the alpha channel. Default is white.\
  13313.     Returns:nil\
  13314. ]]--\
  13315. local function drawPictureTable(image, xinit, yinit, alpha)\
  13316.     if not alpha then alpha = 1 end\
  13317.     for y=1,#image do\
  13318.         for x=1,#image[y] do\
  13319.             term.setCursorPos(xinit + x-1, yinit + y-1)\
  13320.             local col = getColourOf(string.sub(image[y], x, x))\
  13321.             if not col then col = alpha end\
  13322.             term.setBackgroundColour(col)\
  13323.             term.write(\" \")\
  13324.         end\
  13325.     end\
  13326. end\
  13327. \
  13328. --[[  \
  13329.             Section: Loading  \
  13330. ]]-- \
  13331. \
  13332. --[[Loads a non-animted paint file into the program\
  13333.     Params: path:string = The path in which the file is located\
  13334.     Returns:nil\
  13335. ]]--\
  13336. local function loadNFP(path)\
  13337.     sFrame = 1\
  13338.     frames[sFrame] = { }\
  13339.     if fs.exists(path) then\
  13340.         local file = io.open(path, \"r\" )\
  13341.         local sLine = file:read()\
  13342.         local num = 1\
  13343.         while sLine do\
  13344.             table.insert(frames[sFrame], num, {})\
  13345.             for i=1,#sLine do\
  13346.                 frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))\
  13347.             end\
  13348.             num = num+1\
  13349.             sLine = file:read()\
  13350.         end\
  13351.         file:close()\
  13352.     end\
  13353. end\
  13354. \
  13355. --[[Saves a non-animated paint file to the specified path\
  13356.     Params: path:string = The path to save the file to\
  13357.     Returns:nil\
  13358. ]]--\
  13359. local function saveNFP(path)\
  13360.     local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))\
  13361.     if not fs.exists(sDir) then\
  13362.         fs.makeDir(sDir)\
  13363.     end\
  13364. \
  13365.     local file = io.open(path, \"w\")\
  13366.     updateImageLims(false)\
  13367.     if not toplim then \
  13368.         file:close()\
  13369.         return\
  13370.     end\
  13371.     for y=1,botlim do\
  13372.         local line = \"\"\
  13373.         if frames[sFrame][y] then \
  13374.             for x=1,riglim do\
  13375.                 line = line..getHexOf(frames[sFrame][y][x])\
  13376.             end\
  13377.         end\
  13378.         file:write(line..\"\\n\")\
  13379.     end\
  13380.     file:close()\
  13381. end\
  13382. \
  13383. --[[Loads an animated paint file into the program\
  13384.     Params: path:string = The path in which the file is located\
  13385.     Returns:nil\
  13386. ]]--\
  13387. local function loadNFA(path)\
  13388.     frames[sFrame] = { }\
  13389.     if fs.exists(path) then\
  13390.         local file = io.open(path, \"r\" )\
  13391.         local sLine = file:read()\
  13392.         local num = 1\
  13393.         while sLine do\
  13394.             table.insert(frames[sFrame], num, {})\
  13395.             if sLine == \"~\" then\
  13396.                 sFrame = sFrame + 1\
  13397.                 frames[sFrame] = { }\
  13398.                 num = 1\
  13399.             else\
  13400.                 for i=1,#sLine do\
  13401.                     frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))\
  13402.                 end\
  13403.                 num = num+1\
  13404.             end\
  13405.             sLine = file:read()\
  13406.         end\
  13407.         file:close()\
  13408.     end\
  13409.     framecount = sFrame\
  13410.     sFrame = 1\
  13411. end\
  13412. \
  13413. --[[Saves a animated paint file to the specified path\
  13414.     Params: path:string = The path to save the file to\
  13415.     Returns:nil\
  13416. ]]--\
  13417. local function saveNFA(path)\
  13418.     local file = io.open(path, \"w\")\
  13419.     updateImageLims(true)\
  13420.     if not toplim then \
  13421.         file:close()\
  13422.         return\
  13423.     end\
  13424.     for i=1,#frames do\
  13425.         for y=1,botlim do\
  13426.             local line = \"\"\
  13427.             if frames[i][y] then \
  13428.                 for x=1,riglim do\
  13429.                     line = line..getHexOf(frames[i][y][x])\
  13430.                 end\
  13431.             end\
  13432.             file:write(line..\"\\n\")\
  13433.         end\
  13434.         if i < #frames then file:write(\"~\\n\") end\
  13435.     end\
  13436.     file:close()\
  13437. end\
  13438. \
  13439. --[[Initializes the program, by loading in the paint file. Called at the start of each program.\
  13440.     Params: none\
  13441.     Returns:nil\
  13442. ]]--\
  13443. local function init()\
  13444.     if animated then \
  13445.         loadNFA(sPath)\
  13446.         table.insert(ddModes, #ddModes, { \"record\", \"play\", name = \"anim\" })\
  13447.         table.insert(ddModes, #ddModes, { \"go to\", \"remove\", name = \"frames\"})\
  13448.     else loadNFP(sPath) end\
  13449. \
  13450.     for i=0,15 do\
  13451.         table.insert(column, math.pow(2,i))\
  13452.     end\
  13453. end\
  13454. \
  13455. --[[  \
  13456.             Section: Drawing  \
  13457. ]]--\
  13458. \
  13459. \
  13460. --[[Draws the rather superflous logo. Takes about 1 second, before user is able to move to the\
  13461.     actual program.\
  13462.     Params: none\
  13463.     Returns:nil\
  13464. ]]--\
  13465. local function drawLogo()\
  13466.     term.setBackgroundColour(colours.white)\
  13467.     term.clear()\
  13468.     drawPictureTable(logo, w/2 - #logo[1]/2, h/2 - #logo/2, colours.white)\
  13469.     term.setBackgroundColour(colours.white)\
  13470.     term.setTextColour(colours.black)\
  13471.     local msg = \"NPaintPro\"\
  13472.     term.setCursorPos(w/2 - #msg/2, h-3)\
  13473.     term.write(msg)\
  13474.     msg = \"By NitrogenFingers\"\
  13475.     term.setCursorPos(w/2 - #msg/2, h-2)\
  13476.     term.write(msg)\
  13477.     msg = \"Thanks to faubiguy for testing\"\
  13478.     term.setCursorPos(w/2 - #msg/2, h)\
  13479.     term.write(msg)\
  13480.     \
  13481.     os.pullEvent()\
  13482. end\
  13483. \
  13484. --[[Clears the display to the alpha channel colour, draws the canvas, the image buffer and the selection\
  13485.     rectanlge if any of these things are present.\
  13486.     Params: none\
  13487.     Returns:nil\
  13488. ]]--\
  13489. local function drawCanvas()\
  13490.     --We have to readjust the position of the canvas if we're printing\
  13491.     turtlechar = \"@\"\
  13492.     if state == \"active print\" then\
  13493.         if layering == \"up\" then\
  13494.             if py >= 1 and py <= #frames then\
  13495.                 sFrame = py\
  13496.             end\
  13497.             if pz < sy then sy = pz\
  13498.             elseif pz > sy + h - 1 then sy = pz + h - 1 end\
  13499.             if px < sx then sx = px\
  13500.             elseif px > sx + w - 2 then sx = px + w - 2 end\
  13501.         else\
  13502.             if pz >= 1 and pz <= #frames then\
  13503.                 sFrame = pz\
  13504.             end\
  13505.             \
  13506.             if py < sy then sy = py\
  13507.             elseif py > sy + h - 1 then sy = py + h - 1 end\
  13508.             if px < sx then sx = px\
  13509.             elseif px > sx + w - 2 then sx = px + w - 2 end\
  13510.         end\
  13511.         \
  13512.         if pfx == 1 then turtlechar = \">\"\
  13513.         elseif pfx == -1 then turtlechar = \"<\"\
  13514.         elseif pfz == 1 then turtlechar = \"V\"\
  13515.         elseif pfz == -1 then turtlechar = \"^\"\
  13516.         end\
  13517.     end\
  13518. \
  13519.     --Picture next\
  13520.     local topLayer, botLayer\
  13521.     if layerDisplay then\
  13522.         topLayer = sFrame\
  13523.         botLayer = 1\
  13524.     else\
  13525.         topLayer,botLayer = sFrame,sFrame\
  13526.     end\
  13527.     \
  13528.     for currframe = botLayer,topLayer,1 do\
  13529.         for y=sy+1,sy+h-1 do\
  13530.             if frames[currframe][y] then \
  13531.                 for x=sx+1,sx+w-2 do\
  13532.                     term.setCursorPos(x-sx,y-sy)\
  13533.                     if frames[currframe][y][x] then\
  13534.                         term.setBackgroundColour(frames[currframe][y][x])\
  13535.                         term.write(\" \")\
  13536.                     else \
  13537.                         tileExists = false\
  13538.                         for i=currframe-1,botLayer,-1 do\
  13539.                             if frames[i][y][x] then\
  13540.                                 tileExists = true\
  13541.                                 break\
  13542.                             end\
  13543.                         end\
  13544.                         \
  13545.                         if not tileExists then\
  13546.                             if blueprint then\
  13547.                                 term.setBackgroundColour(colours.blue)\
  13548.                                 term.setTextColour(colours.white)\
  13549.                                 if x == sx+1 and y % 4 == 1 then\
  13550.                                     term.write(\"\"..((y/4) % 10))\
  13551.                                 elseif y == sy + 1 and x % 4 == 1 then\
  13552.                                     term.write(\"\"..((x/4) % 10))\
  13553.                                 elseif x % 2 == 1 and y % 2 == 1 then\
  13554.                                     term.write(\"+\")\
  13555.                                 elseif x % 2 == 1 then\
  13556.                                     term.write(\"|\")\
  13557.                                 elseif y % 2 == 1 then\
  13558.                                     term.write(\"-\")\
  13559.                                 else\
  13560.                                     term.write(\" \")\
  13561.                                 end\
  13562.                             else\
  13563.                                 term.setBackgroundColour(alphaC) \
  13564.                                 term.write(\" \")\
  13565.                             end\
  13566.                         end\
  13567.                     end\
  13568.                 end\
  13569.             else\
  13570.                 for x=sx+1,sx+w-2 do\
  13571.                     term.setCursorPos(x-sx,y-sy)\
  13572.                     \
  13573.                     tileExists = false\
  13574.                     for i=currframe-1,botLayer,-1 do\
  13575.                         if frames[i][y] and frames[i][y][x] then\
  13576.                             tileExists = true\
  13577.                             break\
  13578.                         end\
  13579.                     end\
  13580.                     \
  13581.                     if not tileExists then\
  13582.                         if blueprint then\
  13583.                             term.setBackgroundColour(colours.blue)\
  13584.                             term.setTextColour(colours.white)\
  13585.                             if x == sx+1 and y % 4 == 1 then\
  13586.                                 term.write(\"\"..((y/4) % 10))\
  13587.                             elseif y == sy + 1 and x % 4 == 1 then\
  13588.                                 term.write(\"\"..((x/4) % 10))\
  13589.                             elseif x % 2 == 1 and y % 2 == 1 then\
  13590.                                 term.write(\"+\")\
  13591.                             elseif x % 2 == 1 then\
  13592.                                 term.write(\"|\")\
  13593.                             elseif y % 2 == 1 then\
  13594.                                 term.write(\"-\")\
  13595.                             else\
  13596.                                 term.write(\" \")\
  13597.                             end\
  13598.                         else\
  13599.                             term.setBackgroundColour(alphaC) \
  13600.                             term.write(\" \")\
  13601.                         end\
  13602.                     end\
  13603.                 end\
  13604.             end\
  13605.         end\
  13606.     end\
  13607.     \
  13608.     --Then the printer, if he's on\
  13609.     if state == \"active print\" then\
  13610.         local bgColour = alphaC\
  13611.         if layering == \"up\" then\
  13612.             term.setCursorPos(px-sx,pz-sy)\
  13613.             if frames[sFrame] and frames[sFrame][pz-sy] and frames[sFrame][pz-sy][px-sx] then\
  13614.                 bgColour = frames[sFrame][pz-sy][px-sx]\
  13615.             elseif blueprint then bgColour = colours.blue end\
  13616.         else\
  13617.             term.setCursorPos(px-sx,py-sy)\
  13618.             if frames[sFrame] and frames[sFrame][py-sy] and frames[sFrame][py-sy][px-sx] then\
  13619.                 bgColour = frames[sFrame][py-sy][px-sx]\
  13620.             elseif blueprint then bgColour = colours.blue end\
  13621.         end\
  13622.         \
  13623.         term.setBackgroundColour(bgColour)\
  13624.         if bgColour == colours.black then term.setTextColour(colours.white)\
  13625.         else term.setTextColour(colours.black) end\
  13626.         \
  13627.         term.write(turtlechar)\
  13628.     end\
  13629.     \
  13630.     --Then the buffer\
  13631.     if selectrect then\
  13632.         if buffer and rectblink == 1 then\
  13633.         for y=selectrect.y1, math.min(selectrect.y2, selectrect.y1 + buffer.height-1) do\
  13634.             for x=selectrect.x1, math.min(selectrect.x2, selectrect.x1 + buffer.width-1) do\
  13635.                 if buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1] then\
  13636.                     term.setCursorPos(x+sx,y+sy)\
  13637.                     term.setBackgroundColour(buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1])\
  13638.                     term.write(\" \")\
  13639.                 end\
  13640.             end\
  13641.         end\
  13642.         end\
  13643.     \
  13644.         --This draws the \"selection\" box\
  13645.         local add = nil\
  13646.         if buffer then\
  13647.             term.setBackgroundColour(colours.lightGrey)\
  13648.         else \
  13649.             term.setBackgroundColour(colours.grey)\
  13650.         end\
  13651.         for i=selectrect.x1, selectrect.x2 do\
  13652.             add = (i + selectrect.y1 + rectblink) % 2 == 0\
  13653.             term.setCursorPos(i-sx,selectrect.y1-sy)\
  13654.             if add then term.write(\" \") end\
  13655.             add = (i + selectrect.y2 + rectblink) % 2 == 0\
  13656.             term.setCursorPos(i-sx,selectrect.y2-sy)\
  13657.             if add then term.write(\" \") end\
  13658.         end\
  13659.         for i=selectrect.y1 + 1, selectrect.y2 - 1 do\
  13660.             add = (i + selectrect.x1 + rectblink) % 2 == 0\
  13661.             term.setCursorPos(selectrect.x1-sx,i-sy)\
  13662.             if add then term.write(\" \") end\
  13663.             add = (i + selectrect.x2 + rectblink) % 2 == 0\
  13664.             term.setCursorPos(selectrect.x2-sx,i-sy)\
  13665.             if add then term.write(\" \") end\
  13666.         end\
  13667.     end\
  13668. end\
  13669. \
  13670. --[[Draws the colour picker on the right side of the screen, the colour pallette and the footer with any \
  13671.     messages currently being displayed\
  13672.     Params: none\
  13673.     Returns:nil\
  13674. ]]--\
  13675. local function drawInterface()\
  13676.     --Picker\
  13677.     for i=1,#column do\
  13678.         term.setCursorPos(w-1, i)\
  13679.         term.setBackgroundColour(column[i])\
  13680.         if state == \"print\" then\
  13681.             if i == 16 then\
  13682.                 term.setTextColour(colours.white)\
  13683.             else\
  13684.                 term.setTextColour(colours.black)\
  13685.             end\
  13686.             if requirementsDisplayed then\
  13687.                 if requiredMaterials[i] < 10 then term.write(\" \") end\
  13688.                 term.setCursorPos(w-#tostring(requiredMaterials[i])+1, i)\
  13689.                 term.write(requiredMaterials[i])\
  13690.             else\
  13691.                 if i < 10 then term.write(\" \") end\
  13692.                 term.write(i)\
  13693.             end\
  13694.         else\
  13695.             term.write(\"  \")\
  13696.         end\
  13697.     end\
  13698.     term.setCursorPos(w-1,#column+1)\
  13699.     term.setBackgroundColour(colours.black)\
  13700.     term.setTextColour(colours.red)\
  13701.     term.write(\"XX\")\
  13702.     --Pallette\
  13703.     term.setCursorPos(w-1,h-1)\
  13704.     if not lSel then\
  13705.         term.setBackgroundColour(colours.black)\
  13706.         term.setTextColour(colours.red)\
  13707.         term.write(\"X\")\
  13708.     else\
  13709.         term.setBackgroundColour(lSel)\
  13710.         term.setTextColour(lSel)\
  13711.         term.write(\" \")\
  13712.     end\
  13713.     if not rSel then\
  13714.         term.setBackgroundColour(colours.black)\
  13715.         term.setTextColour(colours.red)\
  13716.         term.write(\"X\")\
  13717.     else\
  13718.         term.setBackgroundColour(rSel)\
  13719.         term.setTextColour(rSel)\
  13720.         term.write(\" \")\
  13721.     end\
  13722.     --Footer\
  13723.     if inMenu then return end\
  13724.     \
  13725.     term.setCursorPos(1, h)\
  13726.     term.setBackgroundColour(colours.lightGrey)\
  13727.     term.setTextColour(colours.grey)\
  13728.     term.clearLine()\
  13729.     if inDropDown then\
  13730.         term.write(string.rep(\" \", 6))\
  13731.     else\
  13732.         term.setBackgroundColour(colours.grey)\
  13733.         term.setTextColour(colours.lightGrey)\
  13734.         term.write(\"menu  \")\
  13735.     end\
  13736.     term.setBackgroundColour(colours.lightGrey)\
  13737.     term.setTextColour(colours.grey)\
  13738.     term.write(getStateMessage())\
  13739.     \
  13740.     local coords=\"X:\"..sx..\" Y:\"..sy\
  13741.     if animated then coords = coords..\" Frame:\"..sFrame..\"/\"..framecount..\"   \" end\
  13742.     term.setCursorPos(w-#coords+1,h)\
  13743.     if state == \"play\" then term.setBackgroundColour(colours.lime)\
  13744.     elseif record then term.setBackgroundColour(colours.red) end\
  13745.     term.write(coords)\
  13746.     \
  13747.     if animated then\
  13748.         term.setCursorPos(w-1,h)\
  13749.         term.setBackgroundColour(colours.grey)\
  13750.         term.setTextColour(colours.lightGrey)\
  13751.         term.write(\"<>\")\
  13752.     end\
  13753. end\
  13754. \
  13755. --[[Runs an interface where users can select topics of help. Will return once the user quits the help screen.\
  13756.     Params: none\
  13757.     Returns:nil\
  13758. ]]--\
  13759. local function drawHelpScreen()\
  13760.     local selectedHelp = nil\
  13761.     while true do\
  13762.         term.setBackgroundColour(colours.lightGrey)\
  13763.         term.clear()\
  13764.         if not selectedHelp then\
  13765.             term.setCursorPos(4, 1)\
  13766.             term.setTextColour(colours.brown)\
  13767.             term.write(\"Available modes (click for info):\")\
  13768.             for i=1,#helpTopics do\
  13769.                 term.setCursorPos(2, 2 + i)\
  13770.                 term.setTextColour(colours.black)\
  13771.                 term.write(helpTopics[i].name)\
  13772.                 if helpTopics[i].key then\
  13773.                     term.setTextColour(colours.red)\
  13774.                     term.write(\" (\"..helpTopics[i].key..\")\")\
  13775.                 end\
  13776.             end\
  13777.             term.setCursorPos(4,h)\
  13778.             term.setTextColour(colours.black)\
  13779.             term.write(\"Press any key to exit\")\
  13780.         else\
  13781.             term.setCursorPos(4,1)\
  13782.             term.setTextColour(colours.brown)\
  13783.             term.write(helpTopics[selectedHelp].name)\
  13784.             if helpTopics[selectedHelp].key then\
  13785.                 term.setTextColour(colours.red)\
  13786.                 term.write(\" (\"..helpTopics[selectedHelp].key..\")\")\
  13787.             end\
  13788.             term.setCursorPos(1,3)\
  13789.             term.setTextColour(colours.black)\
  13790.             print(helpTopics[selectedHelp].message..\"\\n\")\
  13791.             for i=1,#helpTopics[selectedHelp].controls do\
  13792.                 term.setTextColour(colours.brown)\
  13793.                 term.write(helpTopics[selectedHelp].controls[i][1]..\" \")\
  13794.                 term.setTextColour(colours.black)\
  13795.                 print(helpTopics[selectedHelp].controls[i][2])\
  13796.             end\
  13797.         end\
  13798.         \
  13799.         local id,p1,p2,p3 = os.pullEvent()\
  13800.         \
  13801.         if id == \"timer\" then updateTimer(p1)\
  13802.         elseif id == \"key\" then \
  13803.             if selectedHelp then selectedHelp = nil\
  13804.             else break end\
  13805.         elseif id == \"mouse_click\" then\
  13806.             if not selectedHelp then \
  13807.                 if p3 >=3 and p3 <= 2+#helpTopics then\
  13808.                     selectedHelp = p3-2 \
  13809.                 else break end\
  13810.             else\
  13811.                 selectedHelp = nil\
  13812.             end\
  13813.         end\
  13814.     end\
  13815. end\
  13816. \
  13817. --[[Draws a message in the footer bar. A helper for DrawInterface, but can be called for custom messages, if the\
  13818.     inMenu paramter is set to true while this is being done (remember to set it back when done!)\
  13819.     Params: message:string = The message to be drawn\
  13820.     Returns:nil\
  13821. ]]--\
  13822. local function drawMessage(message)\
  13823.     term.setCursorPos(1,h)\
  13824.     term.setBackgroundColour(colours.lightGrey)\
  13825.     term.setTextColour(colours.grey)\
  13826.     term.clearLine()\
  13827.     term.write(message)\
  13828. end\
  13829. \
  13830. --[[\
  13831.             Section: Generic Interfaces\
  13832. ]]--\
  13833. \
  13834. \
  13835. --[[One of my generic text printing methods, printing a message at a specified position with width and offset.\
  13836.     No colour materials included.\
  13837.     Params: msg:string = The message to print off-center\
  13838.             height:number = The starting height of the message\
  13839.             width:number = The limit as to how many characters long each line may be\
  13840.             offset:number = The starting width offset of the message\
  13841.     Returns:number the number of lines used in printing the message\
  13842. ]]--\
  13843. local function wprintOffCenter(msg, height, width, offset)\
  13844.     local inc = 0\
  13845.     local ops = 1\
  13846.     while #msg - ops > width do\
  13847.         local nextspace = 0\
  13848.         while string.find(msg, \" \", ops + nextspace) and\
  13849.                 string.find(msg, \" \", ops + nextspace) - ops < width do\
  13850.             nextspace = string.find(msg, \" \", nextspace + ops) + 1 - ops\
  13851.         end\
  13852.         local ox,oy = term.getCursorPos()\
  13853.         term.setCursorPos(width/2 - (nextspace)/2 + offset, height + inc)\
  13854.         inc = inc + 1\
  13855.         term.write(string.sub(msg, ops, nextspace + ops - 1))\
  13856.         ops = ops + nextspace\
  13857.     end\
  13858.     term.setCursorPos(width/2 - #string.sub(msg, ops)/2 + offset, height + inc)\
  13859.     term.write(string.sub(msg, ops))\
  13860.     \
  13861.     return inc + 1\
  13862. end\
  13863. \
  13864. --[[Draws a message that must be clicked on or a key struck to be cleared. No options, so used for displaying\
  13865.     generic information.\
  13866.     Params: ctitle:string = The title of the confirm dialogue\
  13867.             msg:string = The message displayed in the dialogue\
  13868.     Returns:nil\
  13869. ]]--\
  13870. local function displayConfirmDialogue(ctitle, msg)\
  13871.     local dialogoffset = 8\
  13872.     --We actually print twice- once to get the lines, second time to print proper. Easier this way.\
  13873.     local lines = wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)\
  13874.     \
  13875.     term.setCursorPos(dialogoffset, 3)\
  13876.     term.setBackgroundColour(colours.grey)\
  13877.     term.setTextColour(colours.lightGrey)\
  13878.     term.write(string.rep(\" \", w - dialogoffset * 2))\
  13879.     term.setCursorPos(dialogoffset + (w - dialogoffset * 2)/2 - #ctitle/2, 3)\
  13880.     term.write(ctitle)\
  13881.     term.setTextColour(colours.grey)\
  13882.     term.setBackgroundColour(colours.lightGrey)\
  13883.     term.setCursorPos(dialogoffset, 4)\
  13884.     term.write(string.rep(\" \", w - dialogoffset * 2))\
  13885.     for i=5,5+lines do\
  13886.         term.setCursorPos(dialogoffset, i) \
  13887.         term.write(\" \"..string.rep(\" \", w - (dialogoffset) * 2 - 2)..\" \")\
  13888.     end\
  13889.     wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)\
  13890.     \
  13891.     --In the event of a message, the player hits anything to continue\
  13892.     while true do\
  13893.         local id,key = os.pullEvent()\
  13894.         if id == \"timer\" then updateTimer(key);\
  13895.         elseif id == \"key\" or id == \"mouse_click\" or id == \"mouse_drag\" then break end\
  13896.     end\
  13897. end\
  13898. \
  13899. --[[Produces a nice dropdown menu based on a table of strings. Depending on the position, this will auto-adjust the position\
  13900.     of the menu drawn, and allows nesting of menus and sub menus. Clicking anywhere outside the menu will cancel and return nothing\
  13901.     Params: x:int = the x position the menu should be displayed at\
  13902.             y:int = the y position the menu should be displayed at\
  13903.             options:table = the list of options available to the user, as strings or submenus (tables of strings, with a name parameter)\
  13904.     Returns:string the selected menu option.\
  13905. ]]--\
  13906. local function displayDropDown(x, y, options)\
  13907.     inDropDown = true\
  13908.     --Figures out the dimensions of our thing\
  13909.     local longestX = #options.name\
  13910.     for i=1,#options do\
  13911.         local currVal = options[i]\
  13912.         if type(currVal) == \"table\" then currVal = currVal.name end\
  13913.         \
  13914.         longestX = math.max(longestX, #currVal)\
  13915.     end\
  13916.     local xOffset = math.max(0, longestX - ((w-2) - x) + 1)\
  13917.     local yOffset = math.max(0, #options - ((h-1) - y))\
  13918.     \
  13919.     local clickTimes = 0\
  13920.     local tid = nil\
  13921.     local selection = nil\
  13922.     while clickTimes < 2 do\
  13923.         drawCanvas()\
  13924.         drawInterface()\
  13925.         \
  13926.         term.setCursorPos(x-xOffset,y-yOffset)\
  13927.         term.setBackgroundColour(colours.grey)\
  13928.         term.setTextColour(colours.lightGrey)\
  13929.         term.write(options.name..string.rep(\" \", longestX-#options.name + 2))\
  13930.     \
  13931.         for i=1,#options do\
  13932.             term.setCursorPos(x-xOffset, y-yOffset+i)\
  13933.             if i==selection and clickTimes % 2 == 0 then\
  13934.                 term.setBackgroundColour(colours.grey)\
  13935.                 term.setTextColour(colours.lightGrey)\
  13936.             else\
  13937.                 term.setBackgroundColour(colours.lightGrey)\
  13938.                 term.setTextColour(colours.grey)\
  13939.             end\
  13940.             local currVal = options[i]\
  13941.             if type(currVal) == \"table\" then \
  13942.                 term.write(currVal.name..string.rep(\" \", longestX-#currVal.name + 1))\
  13943.                 term.setBackgroundColour(colours.grey)\
  13944.                 term.setTextColour(colours.lightGrey)\
  13945.                 term.write(\">\")\
  13946.             else\
  13947.                 term.write(currVal..string.rep(\" \", longestX-#currVal + 2))\
  13948.             end\
  13949.         end\
  13950.         \
  13951.         local id, p1, p2, p3 = os.pullEvent()\
  13952.         if id == \"timer\" then\
  13953.             if p1 == tid then \
  13954.                 clickTimes = clickTimes + 1\
  13955.                 if clickTimes > 2 then \
  13956.                     break\
  13957.                 else \
  13958.                     tid = os.startTimer(0.1) \
  13959.                 end\
  13960.             else \
  13961.                 updateTimer(p1) \
  13962.                 drawCanvas()\
  13963.                 drawInterface()\
  13964.             end\
  13965.         elseif id == \"mouse_click\" then\
  13966.             if p2 >=x-xOffset and p2 <= x-xOffset + longestX + 1 and p3 >= y-yOffset+1 and p3 <= y-yOffset+#options then\
  13967.                 selection = p3-(y-yOffset)\
  13968.                 tid = os.startTimer(0.1)\
  13969.             else\
  13970.                 selection = \"\"\
  13971.                 break\
  13972.             end\
  13973.         end\
  13974.     end\
  13975.     \
  13976.     if type(selection) == \"number\" then\
  13977.         selection = options[selection]\
  13978.     end\
  13979.     \
  13980.     if type(selection) == \"string\" then \
  13981.         inDropDown = false\
  13982.         return selection\
  13983.     elseif type(selection) == \"table\" then \
  13984.         return displayDropDown(x, y, selection)\
  13985.     end\
  13986. end\
  13987. \
  13988. --[[A custom io.read() function with a few differences- it limits the number of characters being printed,\
  13989.     waits a 1/100th of a second so any keys still in the event library are removed before input is read and\
  13990.     the timer for the selectionrectangle is continuously updated during the process.\
  13991.     Params: lim:int = the number of characters input is allowed\
  13992.     Returns:string the inputted string, trimmed of leading and tailing whitespace\
  13993. ]]--\
  13994. local function readInput(lim)\
  13995.     term.setCursorBlink(true)\
  13996. \
  13997.     local inputString = \"\"\
  13998.     if not lim or type(lim) ~= \"number\" or lim < 1 then lim = w - ox end\
  13999.     local ox,oy = term.getCursorPos()\
  14000.     --We only get input from the footer, so this is safe. Change if recycling\
  14001.     term.setBackgroundColour(colours.lightGrey)\
  14002.     term.setTextColour(colours.grey)\
  14003.     term.write(string.rep(\" \", lim))\
  14004.     term.setCursorPos(ox, oy)\
  14005.     --As events queue immediately, we may get an unwanted key... this will solve that problem\
  14006.     local inputTimer = os.startTimer(0.01)\
  14007.     local keysAllowed = false\
  14008.     \
  14009.     while true do\
  14010.         local id,key = os.pullEvent()\
  14011.         \
  14012.         if keysAllowed then\
  14013.             if id == \"key\" and key == 14 and #inputString > 0 then\
  14014.                 inputString = string.sub(inputString, 1, #inputString-1)\
  14015.                 term.setCursorPos(ox + #inputString,oy)\
  14016.                 term.write(\" \")\
  14017.             elseif id == \"key\" and key == 28 and inputString ~= string.rep(\" \", #inputString) then \
  14018.                 break\
  14019.             elseif id == \"key\" and key == keys.leftCtrl then\
  14020.                 return \"\"\
  14021.             elseif id == \"char\" and #inputString < lim then\
  14022.                 inputString = inputString..key\
  14023.             end\
  14024.         end\
  14025.         \
  14026.         if id == \"timer\" then\
  14027.             if key == inputTimer then \
  14028.                 keysAllowed = true\
  14029.             else\
  14030.                 updateTimer(key)\
  14031.                 drawCanvas()\
  14032.                 drawInterface()\
  14033.                 term.setBackgroundColour(colours.lightGrey)\
  14034.                 term.setTextColour(colours.grey)\
  14035.             end\
  14036.         end\
  14037.         term.setCursorPos(ox,oy)\
  14038.         term.write(inputString)\
  14039.         term.setCursorPos(ox + #inputString, oy)\
  14040.     end\
  14041.     \
  14042.     while string.sub(inputString, 1, 1) == \" \" do\
  14043.         inputString = string.sub(inputString, 2, #inputString)\
  14044.     end\
  14045.     while string.sub(inputString, #inputString, #inputString) == \" \" do\
  14046.         inputString = string.sub(inputString, 1, #inputString-1)\
  14047.     end\
  14048.     term.setCursorBlink(false)\
  14049.     \
  14050.     return inputString\
  14051. end\
  14052. \
  14053. --[[  \
  14054.             Section: Image tools \
  14055. ]]--\
  14056. \
  14057. \
  14058. --[[Copies all pixels beneath the selection rectangle into the image buffer. Empty buffers are converted to nil.\
  14059.     Params: removeImage:bool = true if the image is to be erased after copying, false otherwise\
  14060.     Returns:nil\
  14061. ]]--\
  14062. local function copyToBuffer(removeImage)\
  14063.     buffer = { width = selectrect.x2 - selectrect.x1 + 1, height = selectrect.y2 - selectrect.y1 + 1, contents = { } }\
  14064.     \
  14065.     local containsSomething = false\
  14066.     for y=1,buffer.height do\
  14067.         buffer.contents[y] = { }\
  14068.         local f,l = sFrame,sFrame\
  14069.         if record then f,l = 1, framecount end\
  14070.         \
  14071.         for fra = f,l do\
  14072.             if frames[fra][selectrect.y1 + y - 1] then\
  14073.                 for x=1,buffer.width do\
  14074.                     buffer.contents[y][x] = frames[sFrame][selectrect.y1 + y - 1][selectrect.x1 + x - 1]\
  14075.                     if removeImage then frames[fra][selectrect.y1 + y - 1][selectrect.x1 + x - 1] = nil end\
  14076.                     if buffer.contents[y][x] then containsSomething = true end\
  14077.                 end\
  14078.             end\
  14079.         end\
  14080.     end\
  14081.     --I don't classify an empty buffer as a real buffer- confusing to the user.\
  14082.     if not containsSomething then buffer = nil end\
  14083. end\
  14084. \
  14085. --[[Replaces all pixels under the selection rectangle with the image buffer (or what can be seen of it). Record-dependent.\
  14086.     Params: removeBuffer:bool = true if the buffer is to be emptied after copying, false otherwise\
  14087.     Returns:nil\
  14088. ]]--\
  14089. local function copyFromBuffer(removeBuffer)\
  14090.     if not buffer then return end\
  14091. \
  14092.     for y = 1, math.min(buffer.height,selectrect.y2-selectrect.y1+1) do\
  14093.         local f,l = sFrame, sFrame\
  14094.         if record then f,l = 1, framecount end\
  14095.         \
  14096.         for fra = f,l do\
  14097.             if not frames[fra][selectrect.y1+y-1] then frames[fra][selectrect.y1+y-1] = { } end\
  14098.             for x = 1, math.min(buffer.width,selectrect.x2-selectrect.x1+1) do\
  14099.                 frames[fra][selectrect.y1+y-1][selectrect.x1+x-1] = buffer.contents[y][x]\
  14100.             end\
  14101.         end\
  14102.     end\
  14103.     \
  14104.     if removeBuffer then buffer = nil end\
  14105. end\
  14106. \
  14107. --[[Moves the entire image (or entire animation) to the specified coordinates. Record-dependent.\
  14108.     Params: newx:int = the X coordinate to move the image to\
  14109.             newy:int = the Y coordinate to move the image to\
  14110.     Returns:nil\
  14111. ]]--\
  14112. local function moveImage(newx,newy)\
  14113.     if not leflim or not toplim then return end\
  14114.     if newx <=0 or newy <=0 then return end\
  14115.     local f,l = sFrame,sFrame\
  14116.     if record then f,l = 1,framecount end\
  14117.     \
  14118.     for i=f,l do\
  14119.         local newlines = { }\
  14120.         for y,line in pairs(frames[i]) do\
  14121.             newlines[y-toplim+newy] = { }\
  14122.             for x,char in pairs(line) do\
  14123.                 newlines[y-toplim+newy][x-leflim+newx] = char\
  14124.             end\
  14125.         end\
  14126.         frames[i] = newlines\
  14127.     end\
  14128. end\
  14129. \
  14130. --[[Prompts the user to clear the current frame or all frames. Record-dependent.,\
  14131.     Params: none\
  14132.     Returns:nil\
  14133. ]]--\
  14134. local function clearImage()\
  14135.     inMenu = true\
  14136.     if not animated then\
  14137.         drawMessage(\"Clear image? Y/N: \")\
  14138.     elseif record then\
  14139.         drawMessage(\"Clear ALL frames? Y/N: \")\
  14140.     else\
  14141.         drawMessage(\"Clear current frame? Y/N :\")\
  14142.     end\
  14143.     if string.find(string.upper(readInput(1)), \"Y\") then\
  14144.         local f,l = sFrame,sFrame\
  14145.         if record then f,l = 1,framecount end\
  14146.         \
  14147.         for i=f,l do\
  14148.             frames[i] = { }\
  14149.         end\
  14150.     end\
  14151.     inMenu = false\
  14152. end\
  14153. \
  14154. --[[A recursively called method (watch out for big calls!) in which every pixel of a set colour is\
  14155.     changed to another colour. Does not work on the nil colour, for obvious reasons.\
  14156.     Params: x:int = The X coordinate of the colour to flood-fill\
  14157.             y:int = The Y coordinate of the colour to flood-fill\
  14158.             targetColour:colour = the colour that is being flood-filled\
  14159.             newColour:colour = the colour with which to replace the target colour\
  14160.     Returns:nil\
  14161. ]]--\
  14162. local function floodFill(x, y, targetColour, newColour)\
  14163.     if not newColour or not targetColour then return end\
  14164.     local nodeList = { }\
  14165.     \
  14166.     table.insert(nodeList, {x = x, y = y})\
  14167.     \
  14168.     while #nodeList > 0 do\
  14169.         local node = nodeList[1]\
  14170.         if frames[sFrame][node.y] and frames[sFrame][node.y][node.x] == targetColour then\
  14171.             frames[sFrame][node.y][node.x] = newColour\
  14172.             table.insert(nodeList, { x = node.x + 1, y = node.y})\
  14173.             table.insert(nodeList, { x = node.x, y = node.y + 1})\
  14174.             if x > 1 then table.insert(nodeList, { x = node.x - 1, y = node.y}) end\
  14175.             if y > 1 then table.insert(nodeList, { x = node.x, y = node.y - 1}) end\
  14176.         end\
  14177.         table.remove(nodeList, 1)\
  14178.     end\
  14179. end\
  14180. \
  14181. --[[  \
  14182.             Section: Animation Tools  \
  14183. ]]--\
  14184. \
  14185. --[[Enters play mode, allowing the animation to play through. Interface is restricted to allow this,\
  14186.     and method only leaves once the player leaves play mode.\
  14187.     Params: none\
  14188.     Returns:nil\
  14189. ]]--\
  14190. local function playAnimation()\
  14191.     state = \"play\"\
  14192.     selectedrect = nil\
  14193.     \
  14194.     local animt = os.startTimer(animtime)\
  14195.     repeat\
  14196.         drawCanvas()\
  14197.         drawInterface()\
  14198.         \
  14199.         local id,key,_,y = os.pullEvent()\
  14200.         \
  14201.         if id==\"timer\" then\
  14202.             if key == animt then\
  14203.                 animt = os.startTimer(animtime)\
  14204.                 sFrame = (sFrame % framecount) + 1\
  14205.             else\
  14206.                 updateTimer(key)\
  14207.             end\
  14208.         elseif id==\"key\" then\
  14209.             if key == keys.comma and animtime > 0.1 then animtime = animtime - 0.05\
  14210.             elseif key == keys.period and animtime < 0.5 then animtime = animtime + 0.05\
  14211.             elseif key == keys.space then state = \"paint\" end\
  14212.         elseif id==\"mouse_click\" and y == h then\
  14213.             state = \"paint\"\
  14214.         end\
  14215.     until state ~= \"play\"\
  14216.     os.startTimer(0.5)\
  14217. end\
  14218. \
  14219. --[[Changes the selected frame (sFrame) to the chosen frame. If this frame is above the framecount,\
  14220.     additional frames are created with a copy of the image on the selected frame.\
  14221.     Params: newframe:int = the new frame to move to\
  14222.     Returns:nil\
  14223. ]]--\
  14224. local function changeFrame(newframe)\
  14225.     inMenu = true\
  14226.     if not tonumber(newframe) then\
  14227.         term.setCursorPos(1,h)\
  14228.         term.setBackgroundColour(colours.lightGrey)\
  14229.         term.setTextColour(colours.grey)\
  14230.         term.clearLine()\
  14231.     \
  14232.         term.write(\"Go to frame: \")\
  14233.         newframe = tonumber(readInput(2))\
  14234.         if not newframe or newframe <= 0 then\
  14235.             inMenu = false\
  14236.             return \
  14237.         end\
  14238.     elseif newframe <= 0 then return end\
  14239.     \
  14240.     if newframe > framecount then\
  14241.         for i=framecount+1,newframe do\
  14242.             frames[i] = {}\
  14243.             for y,line in pairs(frames[sFrame]) do\
  14244.                 frames[i][y] = { }\
  14245.                 for x,v in pairs(line) do\
  14246.                     frames[i][y][x] = v\
  14247.                 end\
  14248.             end\
  14249.         end\
  14250.         framecount = newframe\
  14251.     end\
  14252.     sFrame = newframe\
  14253.     inMenu = false\
  14254. end\
  14255. \
  14256. --[[Removes every frame leading after the frame passed in\
  14257.     Params: frame:int the non-inclusive lower bounds of the delete\
  14258.     Returns:nil\
  14259. ]]--\
  14260. local function removeFramesAfter(frame)\
  14261.     inMenu = true\
  14262.     if frame==framecount then return end\
  14263.     drawMessage(\"Remove frames \"..(frame+1)..\"/\"..framecount..\"? Y/N :\")\
  14264.     local answer = string.upper(readInput(1))\
  14265.     \
  14266.     if string.find(answer, string.upper(\"Y\")) ~= 1 then \
  14267.         inMenu = false\
  14268.         return \
  14269.     end\
  14270.     \
  14271.     for i=frame+1, framecount do\
  14272.         frames[i] = nil\
  14273.     end\
  14274.     framecount = frame\
  14275.     inMenu = false\
  14276. end\
  14277. \
  14278. --[[\
  14279.             Section: Printing Tools\
  14280. ]]--\
  14281. \
  14282. --[[Constructs a new facing to the left of the current facing\
  14283.     Params: curx:number = The facing on the X axis\
  14284.             curz:number = The facing on the Z axis\
  14285.             hand:string = The hand of the axis (\"right\" or \"left\")\
  14286.     Returns:number,number = the new facing on the X and Z axis after a left turn\
  14287. ]]--\
  14288. local function getLeft(curx, curz)\
  14289.     local hand = \"left\"\
  14290.     if layering == \"up\" then hand = \"right\" end\
  14291.     \
  14292.     if hand == \"right\" then\
  14293.         if curx == 1 then return 0,-1 end\
  14294.         if curx == -1 then return 0,1 end\
  14295.         if curz == 1 then return 1,0 end\
  14296.         if curz == -1 then return -1,0 end\
  14297.     else\
  14298.         if curx == 1 then return 0,1 end\
  14299.         if curx == -1 then return 0,-1 end\
  14300.         if curz == 1 then return -1,0 end\
  14301.         if curz == -1 then return 1,0 end\
  14302.     end\
  14303. end\
  14304. \
  14305. --[[Constructs a new facing to the right of the current facing\
  14306.     Params: curx:number = The facing on the X axis\
  14307.             curz:number = The facing on the Z axis\
  14308.             hand:string = The hand of the axis (\"right\" or \"left\")\
  14309.     Returns:number,number = the new facing on the X and Z axis after a right turn\
  14310. ]]--\
  14311. local function getRight(curx, curz)\
  14312.     local hand = \"left\"\
  14313.     if layering == \"up\" then hand = \"right\" end\
  14314.     \
  14315.     if hand == \"right\" then\
  14316.         if curx == 1 then return 0,1 end\
  14317.         if curx == -1 then return 0,-1 end\
  14318.         if curz == 1 then return -1,0 end\
  14319.         if curz == -1 then return 1,0 end\
  14320.     else\
  14321.         if curx == 1 then return 0,-1 end\
  14322.         if curx == -1 then return 0,1 end\
  14323.         if curz == 1 then return 1,0 end\
  14324.         if curz == -1 then return -1,0 end\
  14325.     end\
  14326. end\
  14327. \
  14328. \
  14329. --[[Sends out a rednet signal requesting local printers, and will listen for any responses. Printers found are added to the\
  14330.     printerList (for ID's) and printerNames (for names)\
  14331.     Params: nil\
  14332.     Returns:nil\
  14333. ]]--\
  14334. local function locatePrinters()\
  14335.     printerList = { }\
  14336.     printerNames = { name = \"Printers\" }\
  14337.     local oldState = state\
  14338.     state = \"Locating printers, please wait...   \"\
  14339.     drawCanvas()\
  14340.     drawInterface()\
  14341.     state = oldState\
  14342.     \
  14343.     local modemOpened = false\
  14344.     for k,v in pairs(rs.getSides()) do\
  14345.         if peripheral.isPresent(v) and peripheral.getType(v) == \"modem\" then\
  14346.             rednet.open(v)\
  14347.             modemOpened = true\
  14348.             break\
  14349.         end\
  14350.     end\
  14351.     \
  14352.     if not modemOpened then\
  14353.         displayConfirmDialogue(\"Modem not found!\", \"No modem peripheral. Must have network modem to locate printers.\")\
  14354.         return false\
  14355.     end\
  14356.     \
  14357.     rednet.broadcast(\"$3DPRINT IDENTIFY\")\
  14358.     \
  14359.     while true do\
  14360.         local id, msg = rsTimeReceive(1)\
  14361.         \
  14362.         if not id then break end\
  14363.         if string.find(msg, \"$3DPRINT IDACK\") == 1 then\
  14364.             msg = string.gsub(msg, \"$3DPRINT IDACK \", \"\")\
  14365.             table.insert(printerList, id)\
  14366.             table.insert(printerNames, msg)\
  14367.         end\
  14368.     end\
  14369.     \
  14370.     if #printerList == 0 then\
  14371.         displayConfirmDialogue(\"Printers not found!\", \"No active printers found in proximity of this computer.\")\
  14372.         return false\
  14373.     else\
  14374.         return true\
  14375.     end\
  14376. end\
  14377. \
  14378. --[[Sends a request to the printer. Waits on a response and updates the state of the application accordingly.\
  14379.     Params: command:string the command to send\
  14380.             param:string a parameter to send, if any\
  14381.     Returns:nil\
  14382. ]]--\
  14383. local function sendPC(command,param)\
  14384.     local msg = \"$PC \"..command\
  14385.     if param then msg = msg..\" \"..param end\
  14386.     rednet.send(printerList[selectedPrinter], msg)\
  14387.     \
  14388.     while true do\
  14389.         local id,key = rsTimeReceive()\
  14390.         if id == printerList[selectedPrinter] then\
  14391.             if key == \"$3DPRINT ACK\" then\
  14392.                 break\
  14393.             elseif key == \"$3DPRINT DEP\" then\
  14394.                 displayConfirmDialogue(\"Printer Empty\", \"The printer has exhasted a material. Please refill slot \"..param..\
  14395.                     \", and click this message when ready to continue.\")\
  14396.                 rednet.send(printerList[selectedPrinter], msg)\
  14397.             end\
  14398.         end\
  14399.     end\
  14400.     \
  14401.     --Changes to position are handled after the event has been successfully completed\
  14402.     if command == \"FW\" then\
  14403.         px = px + pfx\
  14404.         pz = pz + pfz\
  14405.     elseif command == \"BK\" then\
  14406.         px = px - pfx\
  14407.         pz = pz - pfz\
  14408.     elseif command == \"UP\" then\
  14409.         if layering == \"up\" then\
  14410.             py = py + 1\
  14411.         else \
  14412.             py = py - 1\
  14413.         end\
  14414.     elseif command == \"DW\" then\
  14415.         if layering == \"up\" then\
  14416.             py = py - 1\
  14417.         else    \
  14418.             py = py + 1\
  14419.         end\
  14420.     elseif command == \"TL\" then\
  14421.         pfx,pfz = getLeft(pfx,pfz)\
  14422.     elseif command == \"TR\" then\
  14423.         pfx,pfz = getRight(pfx,pfz)\
  14424.     elseif command == \"TU\" then\
  14425.         pfx = -pfx\
  14426.         pfz = -pfz\
  14427.     end\
  14428.     \
  14429.     drawCanvas()\
  14430.     drawInterface()\
  14431. end\
  14432. \
  14433. --[[A printing function that commands the printer to turn to face the desired direction, if it is not already doing so\
  14434.     Params: desx:number = the normalized x direction to face\
  14435.             desz:number = the normalized z direction to face\
  14436.     Returns:nil\
  14437. ]]--\
  14438. local function turnToFace(desx,desz)\
  14439.     if desx ~= 0 then\
  14440.         if pfx ~= desx then\
  14441.             local temppfx,_ = getLeft(pfx,pfz)\
  14442.             if temppfx == desx then\
  14443.                 sendPC(\"TL\")\
  14444.             elseif temppfx == -desx then\
  14445.                 sendPC(\"TR\")\
  14446.             else\
  14447.                 sendPC(\"TU\")\
  14448.             end\
  14449.         end\
  14450.     else\
  14451.         print(\"on the z axis\")\
  14452.         if pfz ~= desz then\
  14453.             local _,temppfz = getLeft(pfx,pfz)\
  14454.             if temppfz == desz then\
  14455.                 sendPC(\"TL\")\
  14456.             elseif temppfz == -desz then\
  14457.                 sendPC(\"TR\")\
  14458.             else\
  14459.                 sendPC(\"TU\")\
  14460.             end\
  14461.         end\
  14462.     end\
  14463. end\
  14464. \
  14465. --[[Performs the print\
  14466.     Params: nil\
  14467.     Returns:nil\
  14468. ]]--\
  14469. local function performPrint()\
  14470.     state = \"active print\"\
  14471.     if layering == \"up\" then\
  14472.         --An up layering starts our builder bot on the bottom left corner of our build\
  14473.         px,py,pz = leflim, 0, botlim + 1\
  14474.         pfx,pfz = 0,-1\
  14475.         \
  14476.         --We move him forward and up a bit from his original position.\
  14477.         sendPC(\"FW\")\
  14478.         sendPC(\"UP\")\
  14479.         --For each layer that needs to be completed, we go up by one each time\
  14480.         for layers=1,#frames do\
  14481.             --We first decide if we're going forwards or back, depending on what side we're on\
  14482.             local rowbot,rowtop,rowinc = nil,nil,nil\
  14483.             if pz == botlim then\
  14484.                 rowbot,rowtop,rowinc = botlim,toplim,-1\
  14485.             else\
  14486.                 rowbot,rowtop,rowinc = toplim,botlim,1\
  14487.             end\
  14488.             \
  14489.             for rows = rowbot,rowtop,rowinc do\
  14490.                 --Then we decide if we're going left or right, depending on what side we're on\
  14491.                 local linebot,linetop,lineinc = nil,nil,nil\
  14492.                 if px == leflim then\
  14493.                     --Facing from the left side has to be easterly- it's changed here\
  14494.                     turnToFace(1,0)\
  14495.                     linebot,linetop,lineinc = leflim,riglim,1\
  14496.                 else\
  14497.                     --Facing from the right side has to be westerly- it's changed here\
  14498.                     turnToFace(-1,0)\
  14499.                     linebot,linetop,lineinc = riglim,leflim,-1\
  14500.                 end\
  14501.                 \
  14502.                 for lines = linebot,linetop,lineinc do\
  14503.                     --We move our turtle forward, placing the right material at each step\
  14504.                     local material = frames[py][pz][px]\
  14505.                     if material then\
  14506.                         material = math.log10(frames[py][pz][px])/math.log10(2) + 1\
  14507.                         sendPC(\"SS\", material)\
  14508.                         sendPC(\"PD\")\
  14509.                     end\
  14510.                     if lines ~= linetop then\
  14511.                         sendPC(\"FW\")\
  14512.                     end\
  14513.                 end\
  14514.                 \
  14515.                 --The printer then has to do a U-turn, depending on which way he's facing and\
  14516.                 --which way he needs to go\
  14517.                 local temppfx,temppfz = getLeft(pfx,pfz)\
  14518.                 if temppfz == rowinc and rows ~= rowtop then\
  14519.                     sendPC(\"TL\")\
  14520.                     sendPC(\"FW\")\
  14521.                     sendPC(\"TL\")\
  14522.                 elseif temppfz == -rowinc and rows ~= rowtop then\
  14523.                     sendPC(\"TR\")\
  14524.                     sendPC(\"FW\")\
  14525.                     sendPC(\"TR\")\
  14526.                 end\
  14527.             end\
  14528.             --Now at the end of a run he does a 180 and moves up to begin the next part of the print\
  14529.             sendPC(\"TU\")\
  14530.             if layers ~= #frames then\
  14531.                 sendPC(\"UP\")\
  14532.             end\
  14533.         end\
  14534.         --All done- now we head back to where we started.\
  14535.         if px ~= leflim then\
  14536.             turnToFace(-1,0)\
  14537.             while px ~= leflim do\
  14538.                 sendPC(\"FW\")\
  14539.             end\
  14540.         end\
  14541.         if pz ~= botlim then\
  14542.             turnToFace(0,-1)\
  14543.             while pz ~= botlim do\
  14544.                 sendPC(\"BK\")\
  14545.             end\
  14546.         end\
  14547.         turnToFace(0,-1)\
  14548.         sendPC(\"BK\")\
  14549.         while py > 0 do\
  14550.             sendPC(\"DW\")\
  14551.         end\
  14552.     else\
  14553.         --The front facing is at the top-left corner, facing south not north\
  14554.         px,py,pz = leflim, botlim, 1\
  14555.         pfx,pfz = 0,1\
  14556.         --We move the printer to the last layer- he prints from the back forwards\
  14557.         while pz < #frames do\
  14558.             sendPC(\"FW\")\
  14559.         end\
  14560.         \
  14561.         --For each layer in the frame we build our wall, the move back\
  14562.         for layers = 1,#frames do\
  14563.             --We first decide if we're going left or right based on our position\
  14564.             local rowbot,rowtop,rowinc = nil,nil,nil\
  14565.             if px == leflim then\
  14566.                 rowbot,rowtop,rowinc = leflim,riglim,1\
  14567.             else\
  14568.                 rowbot,rowtop,rowinc = riglim,leflim,-1\
  14569.             end\
  14570.             \
  14571.             for rows = rowbot,rowtop,rowinc do\
  14572.                 --Then we decide if we're going up or down, depending on our given altitude\
  14573.                 local linebot,linetop,lineinc = nil,nil,nil\
  14574.                 if py == botlim then\
  14575.                     linebot,linetop,lineinc = botlim,toplim,-1\
  14576.                 else\
  14577.                     linebot,linetop,lineinc = toplim,botlim,1\
  14578.                 end\
  14579.                 \
  14580.                 for lines = linebot,linetop,lineinc do\
  14581.                 --We move our turtle up/down, placing the right material at each step\
  14582.                     local material = frames[pz][py][px]\
  14583.                     if material then\
  14584.                         material = math.log10(frames[pz][py][px])/math.log10(2) + 1\
  14585.                         sendPC(\"SS\", material)\
  14586.                         sendPC(\"PF\")\
  14587.                     end\
  14588.                     if lines ~= linetop then\
  14589.                         if lineinc == 1 then sendPC(\"DW\")\
  14590.                         else sendPC(\"UP\") end\
  14591.                     end\
  14592.                 end\
  14593.                     \
  14594.                 if rows ~= rowtop then\
  14595.                     turnToFace(rowinc,0)\
  14596.                     sendPC(\"FW\")\
  14597.                     turnToFace(0,1)\
  14598.                 end\
  14599.             end\
  14600.             \
  14601.             if layers ~= #frames then\
  14602.                 sendPC(\"TU\")\
  14603.                 sendPC(\"FW\")\
  14604.                 sendPC(\"TU\")\
  14605.             end\
  14606.         end\
  14607.         --He's easy to reset\
  14608.         while px ~= leflim do\
  14609.             turnToFace(-1,0)\
  14610.             sendPC(\"FW\")\
  14611.         end\
  14612.         turnToFace(0,1)\
  14613.     end\
  14614.     \
  14615.     sendPC(\"DE\")\
  14616.     \
  14617.     displayConfirmDialogue(\"Print complete\", \"The 3D print was successful.\")\
  14618. end\
  14619. \
  14620. --[[  \
  14621.             Section: Interface  \
  14622. ]]--\
  14623. \
  14624. --[[Runs the printing interface. Allows users to find/select a printer, the style of printing to perform and to begin the operation\
  14625.     Params: none\
  14626.     Returns:boolean true if printing was started, false otherwse\
  14627. ]]--\
  14628. local function runPrintInterface()\
  14629.     if not locatePrinters() then\
  14630.         return false\
  14631.     end\
  14632.     \
  14633.     calculateMaterials()\
  14634.     layering = \"up\"\
  14635.     requirementsDisplayed = false\
  14636.     selectedPrinter = 1\
  14637.     while true do\
  14638.         drawCanvas()\
  14639.         term.setBackgroundColour(colours.lightGrey)\
  14640.         for i=1,10 do\
  14641.             term.setCursorPos(1,i)\
  14642.             term.clearLine()\
  14643.         end\
  14644.         drawInterface()\
  14645.         term.setBackgroundColour(colours.lightGrey)\
  14646.         term.setTextColour(colours.black)\
  14647.         \
  14648.         local msg = \"3D Printing\"\
  14649.         term.setCursorPos(w/2-#msg/2 - 2, 1)\
  14650.         term.write(msg)\
  14651.         term.setBackgroundColour(colours.grey)\
  14652.         term.setTextColour(colours.lightGrey)\
  14653.         if(requirementsDisplayed) then\
  14654.             msg = \"Count:\"\
  14655.         else\
  14656.             msg = \" Slot:\"\
  14657.         end\
  14658.         term.setCursorPos(w-3-#msg, 1)\
  14659.         term.write(msg)\
  14660.         term.setBackgroundColour(colours.lightGrey)\
  14661.         term.setTextColour(colours.black)\
  14662.         \
  14663.         term.setCursorPos(7, 2)\
  14664.         term.write(\"Layering\")\
  14665.         drawPictureTable(layerUpIcon, 3, 3, colours.white)\
  14666.         drawPictureTable(layerForwardIcon, 12, 3, colours.white)\
  14667.         if layering == \"up\" then\
  14668.             term.setBackgroundColour(colours.red)\
  14669.         else\
  14670.             term.setBackgroundColour(colours.lightGrey)\
  14671.         end\
  14672.         term.setCursorPos(3, 9)\
  14673.         term.write(\"Upwards\")\
  14674.         if layering == \"forward\" then\
  14675.             term.setBackgroundColour(colours.red)\
  14676.         else\
  14677.             term.setBackgroundColour(colours.lightGrey)\
  14678.         end\
  14679.         term.setCursorPos(12, 9)\
  14680.         term.write(\"Forward\")\
  14681.         \
  14682.         term.setBackgroundColour(colours.lightGrey)\
  14683.         term.setTextColour(colours.black)\
  14684.         term.setCursorPos(31, 2)\
  14685.         term.write(\"Printer ID\")\
  14686.         term.setCursorPos(33, 3)\
  14687.         if #printerList > 1 then\
  14688.             term.setBackgroundColour(colours.grey)\
  14689.             term.setTextColour(colours.lightGrey)\
  14690.         else\
  14691.             term.setTextColour(colours.red)\
  14692.         end\
  14693.         term.write(\" \"..printerNames[selectedPrinter]..\" \")\
  14694.         \
  14695.         term.setBackgroundColour(colours.grey)\
  14696.         term.setTextColour(colours.lightGrey)\
  14697.         term.setCursorPos(25, 10)\
  14698.         term.write(\" Cancel \")\
  14699.         term.setCursorPos(40, 10)\
  14700.         term.write(\" Print \")\
  14701.         \
  14702.         local id, p1, p2, p3 = os.pullEvent()\
  14703.         \
  14704.         if id == \"timer\" then\
  14705.             updateTimer(p1)\
  14706.         elseif id == \"mouse_click\" then\
  14707.             --Layering Buttons\
  14708.             if p2 >= 3 and p2 <= 9 and p3 >= 3 and p3 <= 9 then\
  14709.                 layering = \"up\"\
  14710.             elseif p2 >= 12 and p2 <= 18 and p3 >= 3 and p3 <= 9 then\
  14711.                 layering = \"forward\"\
  14712.             --Count/Slot\
  14713.             elseif p2 >= w - #msg - 3 and p2 <= w - 3 and p3 == 1 then\
  14714.                 requirementsDisplayed = not requirementsDisplayed\
  14715.             --Printer ID\
  14716.             elseif p2 >= 33 and p2 <= 33 + #printerNames[selectedPrinter] and p3 == 3 and #printerList > 1 then\
  14717.                 local chosenName = displayDropDown(33, 3, printerNames)\
  14718.                 for i=1,#printerNames do\
  14719.                     if printerNames[i] == chosenName then\
  14720.                         selectedPrinter = i\
  14721.                         break;\
  14722.                     end\
  14723.                 end\
  14724.             --Print and Cancel\
  14725.             elseif p2 >= 25 and p2 <= 32 and p3 == 10 then\
  14726.                 break\
  14727.             elseif p2 >= 40 and p2 <= 46 and p3 == 10 then\
  14728.                 rednet.send(printerList[selectedPrinter], \"$3DPRINT ACTIVATE\")\
  14729.                 ready = false\
  14730.                 while true do\
  14731.                     local id,msg = rsTimeReceive(10)\
  14732.                     \
  14733.                     if id == printerList[selectedPrinter] and msg == \"$3DPRINT ACTACK\" then\
  14734.                         ready = true\
  14735.                         break\
  14736.                     end\
  14737.                 end\
  14738.                 if ready then\
  14739.                     performPrint()\
  14740.                     break\
  14741.                 else\
  14742.                     displayConfirmDialogue(\"Printer Didn't Respond\", \"The printer didn't respond to the activation command. Check to see if it's online\")\
  14743.                 end\
  14744.             end\
  14745.         end\
  14746.     end\
  14747.     state = \"paint\"\
  14748. end\
  14749. \
  14750. --[[This function changes the current paint program to another tool or mode, depending on user input. Handles\
  14751.     any necessary changes in logic involved in that.\
  14752.     Params: mode:string = the name of the mode to change to\
  14753.     Returns:nil\
  14754. ]]--\
  14755. local function performSelection(mode)\
  14756.     if not mode or mode == \"\" then return\
  14757.     \
  14758.     elseif mode == \"help\" then\
  14759.         drawHelpScreen()\
  14760.         \
  14761.     elseif mode == \"blueprint on\" then\
  14762.         blueprint = true\
  14763.         ddModes[2][3] = \"blueprint off\"\
  14764.         \
  14765.     elseif mode == \"blueprint off\" then\
  14766.         blueprint = false\
  14767.         ddModes[2][3] = \"blueprint on\"\
  14768.         \
  14769.     elseif mode == \"layers on\" then\
  14770.         layerDisplay = true\
  14771.         ddModes[2][4] = \"layers off\"\
  14772.     \
  14773.     elseif mode == \"layers off\" then\
  14774.         layerDisplay = false\
  14775.         ddModes[2][4] = \"layers on\"\
  14776.     \
  14777.     elseif mode == \"direction on\" then\
  14778.         printDirection = true\
  14779.         ddModes[2][5] = \"direction off\"\
  14780.         \
  14781.     elseif mode == \"direction off\" then\
  14782.         printDirection = false\
  14783.         ddModes[2][5] = \"direction on\"\
  14784.     \
  14785.     elseif mode == \"go to\" then\
  14786.         changeFrame()\
  14787.     \
  14788.     elseif mode == \"remove\" then\
  14789.         removeFramesAfter(sFrame)\
  14790.     \
  14791.     elseif mode == \"play\" then\
  14792.         playAnimation()\
  14793.         \
  14794.     elseif mode == \"copy\" then\
  14795.         if selectrect and selectrect.x1 ~= selectrect.x2 then\
  14796.             copyToBuffer(false)\
  14797.         end\
  14798.     \
  14799.     elseif mode == \"cut\" then\
  14800.         if selectrect and selectrect.x1 ~= selectrect.x2 then \
  14801.             copyToBuffer(true)\
  14802.         end\
  14803.         \
  14804.     elseif mode == \"paste\" then\
  14805.         if selectrect and selectrect.x1 ~= selectrect.x2 then \
  14806.             copyFromBuffer(false)\
  14807.         end\
  14808.         \
  14809.     elseif mode == \"hide\" then\
  14810.         selectrect = nil\
  14811.         if state == \"select\" then state = \"corner select\" end\
  14812.         \
  14813.     elseif mode == \"alpha to left\" then\
  14814.         if lSel then alphaC = lSel end\
  14815.         \
  14816.     elseif mode == \"alpha to right\" then\
  14817.         if rSel then alphaC = rSel end\
  14818.         \
  14819.     elseif mode == \"record\" then\
  14820.         record = not record\
  14821.         \
  14822.     elseif mode == \"clear\" then\
  14823.         if state==\"select\" then buffer = nil\
  14824.         else clearImage() end\
  14825.     \
  14826.     elseif mode == \"select\" then\
  14827.         if state==\"corner select\" or state==\"select\" then\
  14828.             state = \"paint\"\
  14829.         elseif selectrect and selectrect.x1 ~= selectrect.x2 then\
  14830.             state = \"select\"\
  14831.         else\
  14832.             state = \"corner select\" \
  14833.         end\
  14834.         \
  14835.     elseif mode == \"print\" then\
  14836.         state = \"print\"\
  14837.         runPrintInterface()\
  14838.         state = \"paint\"\
  14839.         \
  14840.     elseif mode == \"save\" then\
  14841.         if animated then saveNFA(sPath)\
  14842.         else saveNFP(sPath) end\
  14843.         \
  14844.     elseif mode == \"exit\" then\
  14845.         isRunning = false\
  14846.     \
  14847.     elseif mode ~= state then state = mode\
  14848.     else state = \"paint\"\
  14849.     end\
  14850. end\
  14851. \
  14852. --[[The main function of the program, reads and handles all events and updates them accordingly. Mode changes,\
  14853.     painting to the canvas and general selections are done here.\
  14854.     Params: none\
  14855.     Returns:nil\
  14856. ]]--\
  14857. local function handleEvents()\
  14858.     recttimer = os.startTimer(0.5)\
  14859.     while isRunning do\
  14860.         drawCanvas()\
  14861.         drawInterface()\
  14862.         local id,p1,p2,p3 = os.pullEvent()\
  14863.         if id==\"timer\" then\
  14864.             updateTimer(p1)\
  14865.         elseif id==\"mouse_click\" or id==\"mouse_drag\" then\
  14866.             if p2 >=w-1 and p3 < #column+1 then\
  14867.                 if p1==1 then lSel = column[p3]\
  14868.                 else rSel = column[p3] end\
  14869.             elseif p2 >=w-1 and p3==#column+1 then\
  14870.                 if p1==1 then lSel = nil\
  14871.                 else rSel = nil end\
  14872.             elseif p2==w-1 and p3==h and animated then\
  14873.                 changeFrame(sFrame-1)\
  14874.             elseif p2==w and p3==h and animated then\
  14875.                 changeFrame(sFrame+1)\
  14876.             elseif p2 < w-10 and p3==h then\
  14877.                 local sel = displayDropDown(1, h-1, ddModes)\
  14878.                 performSelection(sel)\
  14879.             elseif p2 < w-1 and p3 <= h-1 then\
  14880.                 if state==\"pippette\" then\
  14881.                     if p1==1 then\
  14882.                         if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then\
  14883.                             lSel = frames[sFrame][p3+sy][p2+sx] \
  14884.                         end\
  14885.                     elseif p1==2 then\
  14886.                         if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then\
  14887.                             rSel = frames[sFrame][p3+sy][p2+sx] \
  14888.                         end\
  14889.                     end\
  14890.                 elseif state==\"move\" then\
  14891.                     updateImageLims(record)\
  14892.                     moveImage(p2,p3)\
  14893.                 elseif state==\"flood\" then\
  14894.                     if p1 == 1 and lSel and frames[sFrame][p3+sy]  then \
  14895.                         floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],lSel)\
  14896.                     elseif p1 == 2 and rSel and frames[sFrame][p3+sy] then \
  14897.                         floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],rSel)\
  14898.                     end\
  14899.                 elseif state==\"corner select\" then\
  14900.                     if not selectrect then\
  14901.                         selectrect = { x1=p2+sx, x2=p2+sx, y1=p3+sy, y2=p3+sy }\
  14902.                     elseif selectrect.x1 ~= p2+sx and selectrect.y1 ~= p3+sy then\
  14903.                         if p2+sx<selectrect.x1 then selectrect.x1 = p2+sx\
  14904.                         else selectrect.x2 = p2+sx end\
  14905.                         \
  14906.                         if p3+sy<selectrect.y1 then selectrect.y1 = p3+sy\
  14907.                         else selectrect.y2 = p3+sy end\
  14908.                         \
  14909.                         state = \"select\"\
  14910.                     end\
  14911.                 elseif state==\"select\" then\
  14912.                     if p1 == 1 then\
  14913.                         local swidth = selectrect.x2 - selectrect.x1\
  14914.                         local sheight = selectrect.y2 - selectrect.y1\
  14915.                     \
  14916.                         selectrect.x1 = p2 + sx\
  14917.                         selectrect.y1 = p3 + sy\
  14918.                         selectrect.x2 = p2 + swidth + sx\
  14919.                         selectrect.y2 = p3 + sheight + sy\
  14920.                     elseif p1 == 2 and p2 < w-2 and p3 < h-1 then\
  14921.                         inMenu = true\
  14922.                         local sel = displayDropDown(p2, p3, srModes) \
  14923.                         inMenu = false\
  14924.                         performSelection(sel)\
  14925.                     end\
  14926.                 else\
  14927.                     local f,l = sFrame,sFrame\
  14928.                     if record then f,l = 1,framecount end\
  14929.                     local bwidth = 0\
  14930.                     if state == \"brush\" then bwidth = brushsize-1 end\
  14931.                 \
  14932.                     for i=f,l do\
  14933.                         for x = math.max(1,p2+sx-bwidth),p2+sx+bwidth do\
  14934.                             for y = math.max(1,p3+sy-bwidth), p3+sy+bwidth do\
  14935.                                 if math.abs(x - (p2+sx)) + math.abs(y - (p3+sy)) <= bwidth then\
  14936.                                     if not frames[i][y] then frames[i][y] = {} end\
  14937.                                     if p1==1 then frames[i][y][x] = lSel\
  14938.                                     else frames[i][y][x] = rSel end\
  14939.                                 end\
  14940.                             end\
  14941.                         end\
  14942.                     end\
  14943.                 end\
  14944.             end\
  14945.         elseif id==\"key\" then\
  14946.             if p1==keys.leftCtrl then\
  14947.                 local sel = displayDropDown(1, h-1, ddModes[#ddModes]) \
  14948.                 performSelection(sel)\
  14949.             elseif p1==keys.leftAlt then\
  14950.                 local sel = displayDropDown(1, h-1, ddModes[1]) \
  14951.                 performSelection(sel)\
  14952.             elseif p1==keys.h then \
  14953.                 performSelection(\"help\")\
  14954.             elseif p1==keys.x then \
  14955.                 performSelection(\"cut\")\
  14956.             elseif p1==keys.c then\
  14957.                 performSelection(\"copy\")\
  14958.             elseif p1==keys.v then\
  14959.                 performSelection(\"paste\")\
  14960.             elseif p1==keys.z then\
  14961.                 performSelection(\"clear\")\
  14962.             elseif p1==keys.s then\
  14963.                 performSelection(\"select\")\
  14964.             elseif p1==keys.tab then\
  14965.                 performSelection(\"hide\")\
  14966.             elseif p1==keys.q then\
  14967.                 performSelection(\"alpha to left\")\
  14968.             elseif p1==keys.w then\
  14969.                 performSelection(\"alpha to right\")\
  14970.             elseif p1==keys.f then\
  14971.                 performSelection(\"flood\")\
  14972.             elseif p1==keys.b then\
  14973.                 performSelection(\"brush\")\
  14974.             elseif p1==keys.m then\
  14975.                 performSelection(\"move\")\
  14976.             elseif p1==keys.backslash and animated then\
  14977.                 performSelection(\"record\")\
  14978.             elseif p1==keys.p then\
  14979.                 performSelection(\"pippette\")\
  14980.             elseif p1==keys.g and animated then\
  14981.                 performSelection(\"go to\")\
  14982.             elseif p1==keys.period and animated then\
  14983.                 changeFrame(sFrame+1)\
  14984.             elseif p1==keys.comma and animated then\
  14985.                 changeFrame(sFrame-1)\
  14986.             elseif p1==keys.r and animated then\
  14987.                 performSelection(\"remove\")\
  14988.             elseif p1==keys.space and animated then\
  14989.                 performSelection(\"play\")\
  14990.             elseif p1==keys.left then\
  14991.                 if state == \"move\" then\
  14992.                     updateImageLims(record)\
  14993.                     moveImage(leflim-1,toplim)\
  14994.                 elseif state==\"select\" and selectrect.x1 > 1 then\
  14995.                     selectrect.x1 = selectrect.x1-1\
  14996.                     selectrect.x2 = selectrect.x2-1\
  14997.                 elseif sx > 0 then sx=sx-1 end\
  14998.             elseif p1==keys.right then\
  14999.                 if state == \"move\" then\
  15000.                     updateImageLims(record)\
  15001.                     moveImage(leflim+1,toplim)\
  15002.                 elseif state==\"select\" then\
  15003.                     selectrect.x1 = selectrect.x1+1\
  15004.                     selectrect.x2 = selectrect.x2+1\
  15005.                 else sx=sx+1 end\
  15006.             elseif p1==keys.up then\
  15007.                 if state == \"move\" then\
  15008.                     updateImageLims(record)\
  15009.                     moveImage(leflim,toplim-1)\
  15010.                 elseif state==\"select\" and selectrect.y1 > 1 then\
  15011.                     selectrect.y1 = selectrect.y1-1\
  15012.                     selectrect.y2 = selectrect.y2-1\
  15013.                 elseif sy > 0 then sy=sy-1 end\
  15014.             elseif p1==keys.down then \
  15015.                 if state == \"move\" then\
  15016.                     updateImageLims(record)\
  15017.                     moveImage(leflim,toplim+1)\
  15018.                 elseif state==\"select\" then\
  15019.                     selectrect.y1 = selectrect.y1+1\
  15020.                     selectrect.y2 = selectrect.y2+1\
  15021.                 else sy=sy+1 end\
  15022.             end\
  15023.         elseif id==\"char\" and tonumber(p1) then\
  15024.             if state==\"brush\" and tonumber(p1) > 1 then\
  15025.                 brushsize = tonumber(p1)\
  15026.             elseif tonumber(p1) > 0 then\
  15027.                 changeFrame(tonumber(p1))\
  15028.             end\
  15029.         end\
  15030.     end\
  15031. end\
  15032. \
  15033. --[[  \
  15034.             Section: Main  \
  15035. ]]--\
  15036. \
  15037. --Taken almost directly from edit (for consistency)\
  15038. local tArgs = {...}\
  15039. \
  15040. local ca = 1\
  15041. \
  15042. if tArgs[ca] == \"-a\" then\
  15043.     animated = true\
  15044.     ca = ca + 1\
  15045. end\
  15046. \
  15047. if #tArgs < ca then\
  15048.     print(\"Usage: npaintpro [-a] <path>\")\
  15049.     return\
  15050. end\
  15051. \
  15052. sPath = shell.resolve(tArgs[ca])\
  15053. local bReadOnly = fs.isReadOnly(sPath)\
  15054. if fs.exists(sPath) then\
  15055.     if fs.isDir(sPath) then\
  15056.         print(\"Cannot edit a directory.\")\
  15057.         return\
  15058.     elseif string.find(sPath, \".nfp\") ~= #sPath-3 and string.find(sPath, \".nfa\") ~= #sPath-3 then\
  15059.         print(\"Can only edit .nfp and nfa files:\",string.find(sPath, \".nfp\"),#sPath-3)\
  15060.         return\
  15061.     end\
  15062.     \
  15063.     if string.find(sPath, \".nfa\") == #sPath-3 then\
  15064.         animated = true\
  15065.     end\
  15066.     \
  15067.     if string.find(sPath, \".nfp\") == #sPath-3 and animated then\
  15068.         print(\"Convert to nfa? Y/N\")\
  15069.         if string.find(string.lower(io.read()), \"y\") then\
  15070.             local nsPath = string.sub(sPath, 1, #sPath-1)..\"a\"\
  15071.             fs.move(sPath, nsPath)\
  15072.             sPath = nsPath\
  15073.         else\
  15074.             animated = false\
  15075.         end\
  15076.     end\
  15077. else\
  15078.     if not animated and string.find(sPath, \".nfp\") ~= #sPath-3 then \
  15079.         sPath = sPath..\".nfp\"\
  15080.     elseif animated and string.find(sPath, \".nfa\") ~= #sPath-3 then \
  15081.         sPath = sPath..\".nfa\"\
  15082.     end\
  15083. end \
  15084. \
  15085. if not term.isColour() then\
  15086.     print(\"For colour computers only\")\
  15087.     return\
  15088. end\
  15089. \
  15090. drawLogo()\
  15091. init()\
  15092. handleEvents()\
  15093. \
  15094. term.setBackgroundColour(colours.black)\
  15095. shell.run(\"clear\")",
  15096.       [ "permission.data" ] = "",
  15097.     },
  15098.   },
  15099.   Languages = {
  15100.     [ "Boot_EN.lang" ] = "{\
  15101.     \"Loading API list...\",\
  15102.     \"Finished loading API list...\",\
  15103.     \"Loading APIs...\",\
  15104.     \"Finished loading APIs...\",\
  15105.     \"\",\
  15106. }",
  15107.   },
  15108.   Settings = {
  15109.     Language = {
  15110.       CurrentLang = "EN",
  15111.     },
  15112.     Users = {
  15113.       Admin = "8e7d6efe3995f32fa9481828d3d52f0777e740f2d8cb468a82506b9e5dc78f8a",
  15114.     },
  15115.   },
  15116. }
  15117.  
  15118.  
  15119.  
  15120.  
  15121.  
  15122.  
  15123.  
  15124.  
  15125. local function writeFile(path,content)
  15126.     local file = fs.open(path,"w")
  15127.     file.write(content)
  15128.     file.close()
  15129. end
  15130. function writeDown(input,dir)
  15131.         for i,v in pairs(input) do
  15132.         if type(v) == "table" then
  15133.             writeDown(v,dir.."/"..i)
  15134.         elseif type(v) == "string" then
  15135.             writeFile(dir.."/"..i,v)
  15136.         end
  15137.     end
  15138. end
  15139.  
  15140. args = {...}
  15141. if #args == 0 then
  15142.     print("Please input a destination folder.")
  15143. else
  15144.     writeDown(inputTable,args[1])
  15145. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement