SHARE
TWEET

Quest

Oeed Oct 25th, 2014 (edited) 4,107 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --  Hideously Smashed Together by Compilr, a Hideous Smash-Stuff-Togetherer, (c) 2014 oeed  --
  2.  
  3. --  This file REALLLLLLLY isn't suitable to be used for anything other than being executed --
  4.  
  5. --  To extract all the files, run: "<filename> --extract" in the Shell --
  6. local files = {["Wireless"]="--This is just the OneOS Wireless API\
  7. \
  8. --OneOS uses channels between 4200 and 4300, avoid use where possible\
  9. \
  10. Channels = {\
  11.         Ignored = 4299,\
  12.         Ping = 4200,\
  13.         PingReply = 4201,\
  14.         QuestServerRequest = 4250,\
  15.         QuestServerRequestReply = 4251,\
  16.         QuestServerNameAvailable = 4252,\
  17.         QuestServerNameAvailableReply = 4253,\
  18. }\
  19. \
  20. local function isOpen(channel)\
  21.         return Peripheral.CallType('wireless_modem', 'isOpen', channel)\
  22. end\
  23. \
  24. local function open(channel)\
  25.         if not isOpen(channel) then\
  26.                 Peripheral.CallType('wireless_modem', 'open', channel)\
  27.         end\
  28. end\
  29. \
  30. Open = open\
  31. \
  32. local function close(channel)\
  33.         Peripheral.CallType('wireless_modem', 'close', channel)\
  34. end\
  35. \
  36. local function closeAll()\
  37.         Peripheral.CallType('wireless_modem', 'closeAll')\
  38. end\
  39. \
  40. local function transmit(channel, replyChannel, message)\
  41.         Peripheral.CallType('wireless_modem', 'transmit', channel, replyChannel, textutils.serialize(message))\
  42. end\
  43. \
  44. function Present()\
  45.         if Peripheral.GetPeripheral('wireless_modem') == nil then\
  46.                 return false\
  47.         else\
  48.                 return true\
  49.         end\
  50. end\
  51. \
  52. local function FormatMessage(message, messageID, destinationID)\
  53.         return {\
  54.                 content = textutils.serialize(message),\
  55.                 senderID = os.getComputerID(),\
  56.                 senderName = os.getComputerLabel(),\
  57.                 channel = channel,\
  58.                 replyChannel = reply,\
  59.                 messageID = messageID or math.random(10000),\
  60.                 destinationID = destinationID\
  61.         }\
  62. end\
  63. \
  64. local Timeout = function(func, time)\
  65.         time = time or 1\
  66.         parallel.waitForAny(func, function()\
  67.                 sleep(time)\
  68.                 --log('Timeout!'..time)\
  69.         end)\
  70. end\
  71. \
  72. RecieveMessage = function(_channel, messageID, timeout)\
  73.         open(_channel)\
  74.         local done = false\
  75.         local event, side, channel, replyChannel, message = nil\
  76.         Timeout(function()\
  77.                 while not done do\
  78.                         event, side, channel, replyChannel, message = os.pullEvent('modem_message')\
  79.                         if channel ~= _channel then\
  80.                                 event, side, channel, replyChannel, message = nil\
  81.                         else\
  82.                                 message = textutils.unserialize(message)\
  83.                                 message.content = textutils.unserialize(message.content)\
  84.                                 if messageID and messageID ~= message.messageID or (message.destinationID ~= nil and message.destinationID ~= os.getComputerID()) then\
  85.                                         event, side, channel, replyChannel, message = nil\
  86.                                 else\
  87.                                         done = true\
  88.                                 end\
  89.                         end\
  90.                 end\
  91.         end,\
  92.         timeout)\
  93.         return event, side, channel, replyChannel, message\
  94. end\
  95. \
  96. Initialise = function()\
  97.         if Present() then\
  98.                 for i, c in pairs(Channels) do\
  99.                         open(c)\
  100.                 end\
  101.         end\
  102. end\
  103. \
  104. HandleMessage = function(event, side, channel, replyChannel, message, distance)\
  105.         message = textutils.unserialize(message)\
  106.         message.content = textutils.unserialize(message.content)\
  107. \
  108.         if channel == Channels.Ping then\
  109.                 if message.content == 'Ping!' then\
  110.                         SendMessage(replyChannel, 'Pong!', nil, message.messageID)\
  111.                 end\
  112.         elseif message.destinationID ~= nil and message.destinationID ~= os.getComputerID() then\
  113.         elseif Wireless.Responder then\
  114.                 Wireless.Responder(event, side, channel, replyChannel, message, distance)\
  115.         end\
  116. end\
  117. \
  118. SendMessage = function(channel, message, reply, messageID, destinationID)\
  119.         reply = reply or channel + 1\
  120.         open(channel)\
  121.         open(reply)\
  122.         local _message = FormatMessage(message, messageID, destinationID)\
  123.         transmit(channel, reply, _message)\
  124.         return _message\
  125. end\
  126. \
  127. Ping = function()\
  128.         local message = SendMessage(Channels.Ping, 'Ping!', Channels.PingReply)\
  129.         RecieveMessage(Channels.PingReply, message.messageID)\
  130. end",["parser"]="--[[\
  131.    This API was not created by myself, it was copied from https://github.com/voidfiles/webscript-lua-modules/tree/master/html\
  132. \
  133.    It has been modified slightly to be more suitable for CCML (removed unused tags, cleaned up returned table a little, etc)\
  134. \
  135.    Original License:\
  136. \
  137.    Copyright (c) 2007 T. Kobayashi\
  138. \
  139.    Permission is hereby granted, free of charge, to any person obtaining a \
  140.    copy of this software and associated documentation files (the \
  141.    \"Software\"), to deal in the Software without restriction, including \
  142.    without limitation the rights to use, copy, modify, merge, publish, \
  143.    distribute, sublicense, and/or sell copies of the Software, and to \
  144.    permit persons to whom the Software is furnished to do so, subject to \
  145.    the following conditions: \
  146. \
  147.    The above copyright notice and this permission notice shall be included \
  148.    in all copies or substantial portions of the Software. \
  149. \
  150.    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \
  151.    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF \
  152.    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. \
  153.    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY \
  154.    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \
  155.    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE \
  156.    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \
  157. \
  158. ]]\
  159. \
  160. entity = {\
  161.  nbsp = \" \",\
  162.  lt = \"<\",\
  163.  gt = \">\",\
  164.  quot = \"\\\"\",\
  165.  amp = \"&\",\
  166. }\
  167. \
  168. -- keep unknown entity as is\
  169. setmetatable(entity, {\
  170.  __index = function (t, key)\
  171.    return \"&\" .. key .. \";\"\
  172.  end\
  173. })\
  174. \
  175. block = {\
  176.  \"address\",\
  177.  \"blockquote\",\
  178.  \"center\",\
  179.  \"dir\", \"div\", \"dl\",\
  180.  \"fieldset\", \"form\",\
  181.  \"h\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"hr\", \
  182.  \"isindex\",\
  183.  \"menu\",\
  184.  \"noframes\",\
  185.  \"ol\",\
  186.  \"p\",\
  187.  \"pre\",\
  188.  \"table\",\
  189.  \"ul\",\
  190. }\
  191. \
  192. inline = {\
  193.  \"a\", \"abbr\", \"acronym\", \"applet\",\
  194.  \"b\", \"basefont\", \"bdo\", \"big\", \"br\", \"button\",\
  195.  \"cite\", \"code\",\
  196.  \"dfn\",\
  197.  \"em\",\
  198.  \"font\",\
  199.  \"i\", \"iframe\", \"img\", \"input\",\
  200.  \"kbd\",\
  201.  \"label\",\
  202.  \"map\",\
  203.  \"object\",\
  204.  \"q\",\
  205.  \"s\", \"samp\", \"select\", \"small\", \"span\", \"strike\", \"strong\", \"sub\", \"sup\",\
  206.  \"textarea\", \"tt\",\
  207.  \"u\",\
  208.  \"var\",\
  209. }\
  210. \
  211. tags = {\
  212.  a = { empty = false },\
  213.  abbr = {empty = false} ,\
  214.  acronym = {empty = false} ,\
  215.  address = {empty = false} ,\
  216.  applet = {empty = false} ,\
  217.  area = {empty = true} ,\
  218.  b = {empty = false} ,\
  219.  base = {empty = true} ,\
  220.  basefont = {empty = true} ,\
  221.  bdo = {empty = false} ,\
  222.  big = {empty = false} ,\
  223.  blockquote = {empty = false} ,\
  224.  body = { empty = false, },\
  225.  br = {empty = true} ,\
  226.  button = {empty = false} ,\
  227.  caption = {empty = false} ,\
  228.  center = {empty = false} ,\
  229.  cite = {empty = false} ,\
  230.  code = {empty = false} ,\
  231.  col = {empty = true} ,\
  232.  colgroup = {\
  233.    empty = false,\
  234.    optional_end = true,\
  235.    child = {\"col\",},\
  236.  },\
  237.  dd = {empty = false} ,\
  238.  del = {empty = false} ,\
  239.  dfn = {empty = false} ,\
  240.  dir = {empty = false} ,\
  241.  div = {empty = false} ,\
  242.  dl = {empty = false} ,\
  243.  dt = {\
  244.    empty = false,\
  245.    optional_end = true,\
  246.    child = {\
  247.      inline,\
  248.      \"del\",\
  249.      \"ins\",\
  250.      \"noscript\",\
  251.      \"script\",\
  252.    },\
  253.  },\
  254.  em = {empty = false} ,\
  255.  fieldset = {empty = false} ,\
  256.  font = {empty = false} ,\
  257.  form = {empty = false} ,\
  258.  frame = {empty = true} ,\
  259.  frameset = {empty = false} ,\
  260.  h1 = {empty = false} ,\
  261.  h2 = {empty = false} ,\
  262.  h3 = {empty = false} ,\
  263.  h4 = {empty = false} ,\
  264.  h5 = {empty = false} ,\
  265.  h6 = {empty = false} ,\
  266.  head = {empty = false} ,\
  267.  hr = {empty = true} ,\
  268.  html = {empty = false} ,\
  269.  i = {empty = false} ,\
  270.  iframe = {empty = false} ,\
  271.  img = {empty = true} ,\
  272.  input = {empty = true} ,\
  273.  ins = {empty = false} ,\
  274.  isindex = {empty = true} ,\
  275.  kbd = {empty = false} ,\
  276.  label = {empty = false} ,\
  277.  legend = {empty = false} ,\
  278.  li = {\
  279.    empty = false,\
  280.    optional_end = true,\
  281.    child = {\
  282.      inline,\
  283.      block,\
  284.      \"del\",\
  285.      \"ins\",\
  286.      \"noscript\",\
  287.      \"script\",\
  288.    },\
  289.  },\
  290.  link = {empty = true} ,\
  291.  map = {empty = false} ,\
  292.  menu = {empty = false} ,\
  293.  meta = {empty = true} ,\
  294.  noframes = {empty = false} ,\
  295.  noscript = {empty = false} ,\
  296.  object = {empty = false} ,\
  297.  ol = {empty = false} ,\
  298.  optgroup = {empty = false} ,\
  299.  option = {\
  300.    empty = false,\
  301.    optional_end = true,\
  302.    child = {},\
  303.  },\
  304.  p = {\
  305.    empty = false,\
  306.    optional_end = true,\
  307.    child = {\
  308.      inline,\
  309.      \"del\",\
  310.      \"ins\",\
  311.      \"noscript\",\
  312.      \"script\",\
  313.    },\
  314.  } ,\
  315.  param = {empty = true} ,\
  316.  pre = {empty = false} ,\
  317.  q = {empty = false} ,\
  318.  s =  {empty = false} ,\
  319.  samp = {empty = false} ,\
  320.  script = {empty = false} ,\
  321.  select = {empty = false} ,\
  322.  small = {empty = false} ,\
  323.  span = {empty = false} ,\
  324.  strike = {empty = false} ,\
  325.  strong = {empty = false} ,\
  326.  style = {empty = false} ,\
  327.  sub = {empty = false} ,\
  328.  sup = {empty = false} ,\
  329.  table = {empty = false} ,\
  330.  tbody = {empty = false} ,\
  331.  td = {\
  332.    empty = false,\
  333.    optional_end = true,\
  334.    child = {\
  335.      inline,\
  336.      block,\
  337.      \"del\",\
  338.      \"ins\",\
  339.      \"noscript\",\
  340.      \"script\",\
  341.    },\
  342.  },\
  343.  textarea = {empty = false} ,\
  344.  tfoot = {\
  345.    empty = false,\
  346.    optional_end = true,\
  347.    child = {\"tr\",},\
  348.  },\
  349.  th = {\
  350.    empty = false,\
  351.    optional_end = true,\
  352.    child = {\
  353.      inline,\
  354.      block,\
  355.      \"del\",\
  356.      \"ins\",\
  357.      \"noscript\",\
  358.      \"script\",\
  359.    },\
  360.  },\
  361.  thead = {\
  362.    empty = false,\
  363.    optional_end = true,\
  364.    child = {\"tr\",},\
  365.  },\
  366.  title = {empty = false} ,\
  367.  tr = {\
  368.    empty = false,\
  369.    optional_end = true,\
  370.    child = {\
  371.      \"td\", \"th\",\
  372.    },\
  373.  },\
  374.  tt = {empty = false} ,\
  375.  u = {empty = false} ,\
  376.  ul = {empty = false} ,\
  377.  var = {empty = false} ,\
  378. }\
  379. \
  380. setmetatable(tags, {\
  381.  __index = function (t, key)\
  382.    return {empty = false}\
  383.  end\
  384. })\
  385. \
  386. -- string buffer implementation\
  387. function newbuf ()\
  388.  local buf = {\
  389.    _buf = {},\
  390.    clear =   function (self) self._buf = {}; return self end,\
  391.    content = function (self) return table.concat(self._buf) end,\
  392.    append =  function (self, s)\
  393.      self._buf[#(self._buf) + 1] = s\
  394.      return self\
  395.    end,\
  396.    set =     function (self, s) self._buf = {s}; return self end,\
  397.  }\
  398.  return buf\
  399. end\
  400. \
  401. -- unescape character entities\
  402. function unescape (s)\
  403.  function entity2string (e)\
  404.    return entity[e]\
  405.  end\
  406.  return s.gsub(s, \"&(#?%w+);\", entity2string)\
  407. end\
  408. \
  409. -- iterator factory\
  410. function makeiter (f)\
  411.  local co = coroutine.create(f)\
  412.  return function ()\
  413.    local code, res = coroutine.resume(co)\
  414.    return res\
  415.  end\
  416. end\
  417. \
  418. -- constructors for token\
  419. function Tag (s) \
  420.  return string.find(s, \"^</\") and\
  421.    {type = \"End\",   value = s} or\
  422.    {type = \"Start\", value = s}\
  423. end\
  424. \
  425. function Text (s)\
  426.  local unescaped = unescape(s) \
  427.  return {type = \"Text\", value = unescaped} \
  428. end\
  429. \
  430. -- lexer: text mode\
  431. function text (f, buf)\
  432.  local c = f:read(1)\
  433.  if c == \"<\" then\
  434.    if buf:content() ~= \"\" then coroutine.yield(Text(buf:content())) end\
  435.    buf:set(c)\
  436.    return tag(f, buf)\
  437.  elseif c then\
  438.    buf:append(c)\
  439.    return text(f, buf)\
  440.  else\
  441.    if buf:content() ~= \"\" then coroutine.yield(Text(buf:content())) end\
  442.  end\
  443. end\
  444. \
  445. -- lexer: tag mode\
  446. function tag (f, buf)\
  447.  local c = f:read(1)\
  448.  if c == \">\" then\
  449.    coroutine.yield(Tag(buf:append(c):content()))\
  450.    buf:clear()\
  451.    return text(f, buf)\
  452.  elseif c then\
  453.    buf:append(c)\
  454.    return tag(f, buf)\
  455.  else\
  456.    if buf:content() ~= \"\" then coroutine.yield(Tag(buf:content())) end\
  457.  end\
  458. end\
  459. \
  460. function parse_starttag(tag)\
  461.  local tagname = string.match(tag, \"<%s*(%w+)\")\
  462.  local elem = {_attr = {}}\
  463.  elem._tag = tagname\
  464.  for key, _, val in string.gmatch(tag, \"(%w+)%s*=%s*([\\\"'])(.-)%2\", i) do\
  465.    local unescaped = unescape(val)\
  466.    elem._attr[key] = unescaped\
  467.  end\
  468.  return elem\
  469. end\
  470. \
  471. function parse_endtag(tag)\
  472.  local tagname = string.match(tag, \"<%s*/%s*(%w+)\")\
  473.  return tagname\
  474. end\
  475. \
  476. -- find last element that satisfies given predicate\
  477. function rfind(t, pred)\
  478.  local length = #t\
  479.  for i=length,1,-1 do\
  480.    if pred(t[i]) then\
  481.      return i, t[i]\
  482.    end\
  483.  end\
  484. end\
  485. \
  486. function flatten(t, acc)\
  487.  acc = acc or {}\
  488.  for i,v in ipairs(t) do\
  489.    if type(v) == \"table\" then\
  490.      flatten(v, acc)\
  491.    else\
  492.      acc[#acc + 1] = v\
  493.    end\
  494.  end\
  495.  return acc\
  496. end\
  497. \
  498. function optional_end_p(elem)\
  499.  if tags[elem._tag].optional_end then\
  500.    return true\
  501.  else\
  502.    return false\
  503.  end\
  504. end\
  505. \
  506. function valid_child_p(child, parent)\
  507.  local schema = tags[parent._tag].child\
  508.  if not schema then return true end\
  509. \
  510.  for i,v in ipairs(flatten(schema)) do\
  511.    if v == child._tag then\
  512.      return true\
  513.    end\
  514.  end\
  515. \
  516.  return false\
  517. end\
  518. \
  519. -- tree builder\
  520. function parse(f)\
  521.  local root = {_tag = \"#document\", _attr = {}}\
  522.  local stack = {root}\
  523.  for i in makeiter(function () return text(f, newbuf()) end) do\
  524.    if i.type == \"Start\" then\
  525.      local new = parse_starttag(i.value)\
  526.      local top = stack[#stack]\
  527. \
  528.      while\
  529.        top._tag ~= \"#document\" and \
  530.        optional_end_p(top) and\
  531.        not valid_child_p(new, top)\
  532.      do\
  533.        stack[#stack] = nil \
  534.        top = stack[#stack]\
  535.      end\
  536. \
  537.      top[#top+1] = new -- appendchild\
  538.      if not tags[new._tag].empty then \
  539.        stack[#stack+1] = new -- push\
  540.      end\
  541.    elseif i.type == \"End\" then\
  542.      local tag = parse_endtag(i.value)\
  543.      local openingpos = rfind(stack, function(v) \
  544.          if v._tag == tag then\
  545.            return true\
  546.          else\
  547.            return false\
  548.          end\
  549.        end)\
  550.      if openingpos then\
  551.        local length = #stack\
  552.        for j=length,openingpos,-1 do\
  553.          table.remove(stack, j)\
  554.        end\
  555.      end\
  556.    else -- Text\
  557.        if #string.gsub(string.gsub(i.value, \"%s+\", \"\"), '\\n', '') ~= 0 then\
  558.            local top = stack[#stack]\
  559.            top[#top+1] = i.value\
  560.        end\
  561.    end\
  562.  end\
  563.  return root\
  564. end\
  565. \
  566. function parsestr(s)\
  567.  local handle = {\
  568.    _content = s,\
  569.    _pos = 1,\
  570.    read = function (self, length)\
  571.      if self._pos > string.len(self._content) then return end\
  572.      local ret = string.sub(self._content, self._pos, self._pos + length - 1)\
  573.      self._pos = self._pos + length\
  574.      return ret\
  575.    end\
  576.  }\
  577.  return parse(handle)\
  578. end",["Elements"]={["SecureTextInput.lua"]="Inherit = 'TextInput'\
  579. \
  580. UpdateValue = function(self)\
  581.         self.Value = hash.sha256(self.Object.Text)\
  582. end\
  583. \
  584. OnCreateObject = function(self, parentObject, y)\
  585.         return {\
  586.                 Element = self,\
  587.                 Y = y,\
  588.                 X = 1,\
  589.                 Width = self.Width,\
  590.                 Type = \"SecureTextBox\",\
  591.                 Text = self.Value,\
  592.                 TextColour = self.TextColour,\
  593.                 BackgroundColour = self.BackgroundColour,\
  594.                 SelectedBackgroundColour = self.SelectedBackgroundColour,\
  595.                 SelectedTextColour = self.SelectedTextColour,\
  596.                 PlaceholderTextColour = self.PlaceholderTextColour,\
  597.                 Placeholder = self.Placeholder,\
  598.                 InputName = self.InputName,\
  599.                 OnChange = function(_self, event, keychar)\
  600.                         if keychar == keys.tab or keychar == keys.enter then\
  601.                                 local form = self\
  602.                                 local step = 0\
  603.                                 while form.Tag ~= 'form' and step < 50 do\
  604.                                         form = form.Parent\
  605.                                 end\
  606.                                 if keychar == keys.tab then\
  607.                                         if form and form.Object and form.Object.OnTab then\
  608.                                                 form.Object:OnTab()\
  609.                                         end\
  610.                                 else\
  611.                                         if form and form.Submit then\
  612.                                                 form:Submit(true)\
  613.                                         end\
  614.                                 end\
  615.                         end\
  616.                 end\
  617.         }\
  618. end",["Image.lua"]="URL = nil\
  619. Format = nil\
  620. \
  621. OnInitialise = function(self, node)\
  622.         local attr = self.Attributes\
  623.         if attr.src then\
  624.                 self.URL = attr.src\
  625.         end\
  626. \
  627.         if attr.type then\
  628.                 self.Format = attr.type\
  629.         end\
  630. \
  631.         if attr.height then\
  632.                 self.Height = attr.height\
  633.         end\
  634. \
  635.         if attr.width then\
  636.                 self.Width = attr.width\
  637.         end\
  638. end\
  639. \
  640. OnCreateObject = function(self, parentObject, y)\
  641.         return {\
  642.                 Element = self,\
  643.                 Y = y,\
  644.                 X = 1,\
  645.                 Width = self.Width,\
  646.                 Height = self.Height,\
  647.                 URL = self.URL,\
  648.                 Format = self.Format,\
  649.                 Type = \"WebImageView\"\
  650.         }\
  651. end",["Script.lua"]="Text = nil\
  652. URL = nil\
  653. \
  654. OnInitialise = function(self, node)\
  655.         local attr = self.Attributes\
  656.         self.Text = table.concat(node, '\\n')\
  657. \
  658.         if attr.src then\
  659.                 self.URL = attr.src\
  660.                 self.Text = nil\
  661.         end\
  662. end\
  663. \
  664. InsertScript = function(self, webView)\
  665.         if self.Text then\
  666.                 webView:LoadScript(self.Text)\
  667.         elseif self.URL then\
  668.                 fetchHTTPAsync(resolveFullUrl(self.URL), function(ok, event, response)\
  669.                         if ok then\
  670.                                 self.Text = response.readAll()\
  671.                                 webView:LoadScript(self.Text)\
  672.                         end\
  673.                 end)\
  674. \
  675.         end\
  676.         return nil\
  677. end",["Select.lua"]="Width = 20\
  678. InputName = ''\
  679. \
  680. OnInitialise = function(self, node)\
  681.         if attr.value then\
  682.                 new.Text = attr.value\
  683.         end\
  684. \
  685.         if attr.name then\
  686.                 new.InputName = attr.name\
  687.         end\
  688. end\
  689. \
  690. UpdateValue = function(self)\
  691.         self.Value = self.Object.MenuItems[self.Object.Selected].Value\
  692. end\
  693. \
  694. OnCreateObject = function(self, parentObject, y)\
  695.         return {\
  696.                 Element = self,\
  697.                 Y = y,\
  698.                 X = 1,\
  699.                 Width = self.Width,\
  700.                 Type = \"SelectView\",\
  701.                 TextColour = self.TextColour,\
  702.                 BackgroundColour = self.BackgroundColour,\
  703.                 InputName = self.InputName,\
  704.         }\
  705. end",["Paragraph.lua"]="Align = \"Left\"\
  706. \
  707. OnInitialise = function(self, node)\
  708.         local attr = self.Attributes\
  709.         self.Text = self.Text or ''\
  710.         if attr.align then\
  711.                 if attr.align:lower() == 'left' or attr.align:lower() == 'center' or attr.align:lower() == 'right' then\
  712.                         self.Align = attr.align:lower():gsub(\"^%l\", string.upper)\
  713.                 end\
  714.         end\
  715. end\
  716. \
  717. OnCreateObject = function(self, parentObject, y)\
  718.         return {\
  719.                 Element = self,\
  720.                 Y = y,\
  721.                 X = 1,\
  722.                 Width = self.Width,\
  723.                 Height = self.Height,\
  724.                 Align = self.Align,\
  725.                 Type = \"Label\",\
  726.                 Text = self.Text,\
  727.                 TextColour = self.TextColour,\
  728.                 BackgroundColour = self.BackgroundColour,\
  729.                 OnUpdate = function(_self, value)\
  730.                     if value == 'Text' then\
  731.                         if not self.Attributes.height then\
  732.                         _self.Height = #_self.Bedrock.Helpers.WrapText(_self.Text, _self.Width)\
  733.                                         _self.Bedrock:GetObject('WebView'):RepositionLayout()\
  734.                         end\
  735.                     end\
  736.                 end\
  737.         }\
  738. end",["HiddenInput.lua"]="InputName = ''\
  739. \
  740. OnInitialise = function(self, node)\
  741.         local attr = self.Attributes\
  742.         if attr.value then\
  743.                 self.Value = attr.value\
  744.         end\
  745. \
  746.         if attr.name then\
  747.                 self.InputName = attr.name\
  748.         end\
  749. end",["ButtonInput.lua"]="BackgroundColour = colours.lightGrey\
  750. TextColour = colours.black\
  751. Text = 'Submit'\
  752. InputName = ''\
  753. \
  754. OnInitialise = function(self, node)\
  755.         local attr = self.Attributes\
  756.         if attr.value then\
  757.                 self.Text = attr.value\
  758.         end\
  759. \
  760.         if attr.name then\
  761.                 self.InputName = attr.name\
  762.         end\
  763. \
  764.         if not attr.width then\
  765.                 self.Width = #self.Text + 2\
  766.         end\
  767. end\
  768. \
  769. UpdateValue = function(self, force)\
  770.         if force then\
  771.                 self.Value = self.Object.Text\
  772.         end\
  773. end\
  774. \
  775. CreateObject = function(self, parentObject, y)\
  776.         return parentObject:AddObject({\
  777.                 Element = self,\
  778.                 Y = y,\
  779.                 X = 1,\
  780.                 Width = self.Width,\
  781.                 Type = \"Button\",\
  782.                 Text = self.Text,\
  783.                 TextColour = self.TextColour,\
  784.                 BackgroundColour = self.BackgroundColour,\
  785.                 InputName = self.InputName,\
  786.                 OnClick = function(_self, event, side, x, y)\
  787.                         local form = self\
  788.                         local step = 0\
  789.                         while form.Tag ~= 'form' and step < 50 do\
  790.                                 form = form.Parent\
  791.                         end\
  792.                         self.Value = _self.Text\
  793.                         if form and form.Submit then\
  794.                                 form:Submit()\
  795.                         end\
  796.                 end\
  797.         })\
  798. end",["Float.lua"]="Align = \"Left\"\
  799. \
  800. OnInitialise = function(self, node)\
  801.         local attr = self.Attributes\
  802.         if attr.align then\
  803.                 if attr.align:lower() == 'left' or attr.align:lower() == 'right' then\
  804.                         self.Align = attr.align:lower():gsub(\"^%l\", string.upper)\
  805.                 end\
  806.         end\
  807. end\
  808. \
  809. OnCreateObject = function(self, parentObject, y)\
  810.         return {\
  811.                 Element = self,\
  812.                 Y = y,\
  813.                 X = 1,\
  814.                 Width = self.Width,\
  815.                 Height = self.Height,\
  816.                 Align = self.Align,\
  817.                 BackgroundColour = self.BackgroundColour,\
  818.                 Type = \"FloatView\"\
  819.         }\
  820. end",["Element.lua"]="HasChildren = true\
  821. Children = nil\
  822. Tag = nil\
  823. TextColour = colours.black\
  824. BackgroundColour = colours.transparent\
  825. Text = nil\
  826. Attributes = nil\
  827. Width = \"100%\"\
  828. \
  829. Initialise = function(self, node)\
  830.         local new = {}    -- the new instance\
  831.         setmetatable( new, {__index = self} )\
  832.         local attr = node._attr\
  833.         new.Tag = node._tag\
  834.         new.Attributes = attr\
  835.         if new.HasChildren then\
  836.                 new.Children = {}\
  837.         end\
  838. \
  839.         if type(node[1]) == 'string' then\
  840.                 new.Text = node[1]\
  841.         end\
  842.         \
  843.         if attr.colour then\
  844.                 new.TextColour = self:ParseColour(attr.colour)\
  845.         elseif attr.color then\
  846.                 new.TextColour = self:ParseColour(attr.color)\
  847.         end\
  848. \
  849.         if attr.bgcolour then\
  850.                 new.BackgroundColour = self:ParseColour(attr.bgcolour)\
  851.         elseif attr.bgcolor then\
  852.                 new.BackgroundColour = self:ParseColour(attr.bgcolor)\
  853.         end\
  854. \
  855.         if attr.height then\
  856.                 new.Height = attr.height\
  857.         end\
  858. \
  859.         if attr.width then\
  860.                 new.Width = attr.width\
  861.         end\
  862. \
  863.         if new.OnInitialise then\
  864.                 new:OnInitialise(node)\
  865.         end\
  866. \
  867.         return new\
  868. end\
  869. \
  870. ParseColour = function(self, str)\
  871.         if str and type(str) == 'string' then\
  872.                 if colours[str] and type(colours[str]) == 'number' then\
  873.                         return colours[str]\
  874.                 elseif colors[str] and type(colors[str]) == 'number' then\
  875.                         return colors[str]\
  876.                 end\
  877.         end\
  878. end\
  879. \
  880. CreateObject = function(self, parentObject, y)\
  881.         local object\
  882.         if self.OnCreateObject then\
  883.                 object = self:OnCreateObject()\
  884.         else\
  885.                 object = {\
  886.                         Element = self,\
  887.                         Y = y,\
  888.                         X = 1,\
  889.                         Width = self.Width,\
  890.                         Height = self.Height,\
  891.                         BackgroundColour = self.BackgroundColour,\
  892.                         Type = \"View\"\
  893.                 }\
  894.         end\
  895. \
  896.         if object then\
  897.                 return parentObject:AddObject(object, parentObject, y)\
  898.         end\
  899. end",["Divider.lua"]="Char = nil\
  900. \
  901. OnInitialise = function(self, node)\
  902.         local attr = self.Attributes\
  903.         self.Text = self.Text or ''\
  904.         if attr.char then\
  905.                 if #attr.char == 1 then\
  906.                         self.Char = attr.char\
  907.                 end\
  908.         end\
  909. end\
  910. \
  911. OnCreateObject = function(self, parentObject, y)\
  912.         return {\
  913.                 Element = self,\
  914.                 Y = y,\
  915.                 X = 1,\
  916.                 Width = self.Width,\
  917.                 Height = self.Height,\
  918.                 BackgroundColour = self.BackgroundColour,\
  919.                 TextColour = self.TextColour,\
  920.                 Type = \"DividerView\",\
  921.                 Char = self.Char\
  922.         }\
  923. end",["Link.lua"]="Align = 'Left'\
  924. Width = \"100%\"\
  925. TextColour = colours.blue\
  926. UnderlineColour = nil\
  927. UnderlineVisible = true\
  928. URL = nil\
  929. \
  930. OnInitialise = function(self, node)\
  931.         local attr = self.Attributes\
  932.         if attr.href then\
  933.                 self.URL = attr.href\
  934.         end\
  935.         \
  936.         if attr.ulcolour then\
  937.                 if attr.ulcolour == 'none' then\
  938.                         self.UnderlineVisible = false\
  939.                 else\
  940.                         self.UnderlineColour = self:ParseColour(attr.ulcolour)\
  941.                 end\
  942.         elseif attr.ulcolor then\
  943.                 if attr.ulcolor == 'none' then\
  944.                         self.UnderlineVisible = false\
  945.                 else\
  946.                         self.UnderlineColour = self:ParseColour(attr.ulcolor)\
  947.                 end\
  948.         end\
  949. \
  950.         if attr.align then\
  951.                 if attr.align:lower() == 'left' or attr.align:lower() == 'center' or attr.align:lower() == 'right' then\
  952.                         self.Align = attr.align:lower():gsub(\"^%l\", string.upper)\
  953.                 end\
  954.         end\
  955. end\
  956. \
  957. OnCreateObject = function(self, parentObject, y)\
  958.         return {\
  959.                 Element = self,\
  960.                 Y = y,\
  961.                 X = 1,\
  962.                 Width = self.Width,\
  963.                 Align = self.Align,\
  964.                 Type = \"LinkView\",\
  965.                 Text = self.Text,\
  966.                 TextColour = self.TextColour,\
  967.                 UnderlineColour = self.UnderlineColour,\
  968.                 BackgroundColour = self.BackgroundColour,\
  969.                 URL = resolveFullUrl(self.URL),\
  970.                 UnderlineVisible = self.UnderlineVisible\
  971.         }\
  972. end",["Center.lua"]="OnCreateObject = function(self, parentObject, y)\
  973.         return {\
  974.                 Element = self,\
  975.                 Y = y,\
  976.                 X = 1,\
  977.                 Width = \"100%\",\
  978.                 Height = self.Height,\
  979.                 BackgroundColour = self.BackgroundColour,\
  980.                 Type = \"CenterView\"\
  981.         }\
  982. end",["Form.lua"]="Submit = function(self, onEnter)\
  983.         local values = {}\
  984.         \
  985.         local node = false\
  986.         node = function(elem)\
  987.                 if (elem.Tag == 'input' or elem.Tag == 'select') and elem.InputName then\
  988.                         local findSubmit = (onEnter and elem.Attributes and elem.Attributes.type == 'submit')\
  989.                         if elem.UpdateValue then\
  990.                                 elem:UpdateValue(findSubmit)\
  991.                         end\
  992. \
  993.                         if findSubmit then\
  994.                                 onEnter = false\
  995.                         end\
  996. \
  997.                         if elem.Value then\
  998.                                 values[elem.InputName] = elem.Value\
  999.                         end\
  1000.                 end\
  1001. \
  1002.                 if elem.Children then\
  1003.                         for i, child in ipairs(elem.Children) do\
  1004.                                 node(child)\
  1005.                         end\
  1006.                 end\
  1007.         end\
  1008. \
  1009.         node(self)\
  1010. \
  1011.         local url = false\
  1012.         if self.Attributes.action and #self.Attributes.action > 0 then\
  1013.                 url = resolveFullUrl(self.Attributes.action) --TODO: this needs to show the fake url to the user\
  1014.         else\
  1015.                 url = getCurrentFakeUrl()\
  1016.         end\
  1017.         local data = ''\
  1018.         for k, v in pairs(values) do\
  1019.                 data = data .. textutils.urlEncode(k) .. '=' .. textutils.urlEncode(v) .. '&'\
  1020.         end\
  1021.         data = data:sub(1, #data - 1)\
  1022. \
  1023.         if self.Attributes.method and self.Attributes.method:lower() == 'post' then\
  1024.                 goToUrl(url, data)\
  1025.         else\
  1026.                 goToUrl(url .. '?' .. data)\
  1027.         end\
  1028. end\
  1029. \
  1030. OnCreateObject = function(self, parentObject, y)\
  1031.         return {\
  1032.                 Element = self,\
  1033.                 Y = y,\
  1034.                 X = 1,\
  1035.                 Width = \"100%\",\
  1036.                 Height = self.Height,\
  1037.                 Type = \"FormView\"\
  1038.         }\
  1039. end",["FileInput.lua"]="BackgroundColour = colours.lightGrey\
  1040. TextColour = colours.black\
  1041. Text = 'Choose File...'\
  1042. InputName = ''\
  1043. FilePath = 'test'\
  1044. \
  1045. OnInitialise = function(self, node)\
  1046.         local attr = self.Attributes\
  1047.         if attr.value then\
  1048.                 self.Text = attr.value\
  1049.         end\
  1050. \
  1051.         if attr.name then\
  1052.                 self.InputName = attr.name\
  1053.         end\
  1054. \
  1055.         if not attr.width then\
  1056.                 self.Width = #self.Text + 2\
  1057.         end\
  1058. end\
  1059. \
  1060. UpdateValue = function(self, force)\
  1061.         if self.FilePath then\
  1062.                 local f = fs.open(self.FilePath, 'r')\
  1063.                 if f then\
  1064.                         local content = f.readAll()\
  1065.                         self.Value = '{\"name\": \"' .. fs.getName(self.FilePath):gsub('\"', '\\\\\"') .. '\", \"content\": \"' .. content:gsub('\"', '\\\\\"') .. '\"}'\
  1066.                         f.close()\
  1067.                 end\
  1068.         end\
  1069. end\
  1070. \
  1071. CreateObject = function(self, parentObject, y)\
  1072.         return parentObject:AddObject({\
  1073.                 Element = self,\
  1074.                 Y = y,\
  1075.                 X = 1,\
  1076.                 Width = self.Width,\
  1077.                 Type = \"Button\",\
  1078.                 Text = self.Text,\
  1079.                 TextColour = self.TextColour,\
  1080.                 BackgroundColour = self.BackgroundColour,\
  1081.                 InputName = self.InputName,\
  1082.                 OnClick = function(_self, event, side, x, y)\
  1083.                         _self.Bedrock:DisplayOpenFileWindow(nil, function(success, path)\
  1084.                                 if success then\
  1085.                                         self.FilePath = path\
  1086.                                         _self.Text = 'File: '..fs.getName(path)\
  1087.                                         _self.Align = 'Left'\
  1088.                                 end\
  1089.                         end)\
  1090.                 end\
  1091.         })\
  1092. end",["Heading.lua"]="Align = \"Center\"\
  1093. \
  1094. OnInitialise = function(self, node)\
  1095.         local attr = self.Attributes\
  1096.         self.Text = self.Text or ''\
  1097.         if attr.align then\
  1098.                 if attr.align:lower() == 'left' or attr.align:lower() == 'center' or attr.align:lower() == 'right' then\
  1099.                         self.Align = attr.align:lower():gsub(\"^%l\", string.upper)\
  1100.                 end\
  1101.         end\
  1102. end\
  1103. \
  1104. OnCreateObject = function(self, parentObject, y)\
  1105.         return {\
  1106.                 Element = self,\
  1107.                 Y = y,\
  1108.                 X = 1,\
  1109.                 Width = \"100%\",\
  1110.                 Align = self.Align,\
  1111.                 Type = \"HeadingView\",\
  1112.                 Text = self.Text,\
  1113.                 TextColour = self.TextColour,\
  1114.                 BackgroundColour = self.BackgroundColour\
  1115.         }\
  1116. end",["TextInput.lua"]="SelectedBackgroundColour = colours.blue\
  1117. SelectedTextColour = colours.white\
  1118. PlaceholderTextColour = colours.grey\
  1119. Placeholder = ''\
  1120. Value = nil\
  1121. Attributes = nil\
  1122. Children = nil\
  1123. Tag = nil\
  1124. Width = 20\
  1125. InputName = ''\
  1126. \
  1127. OnInitialise = function(self, node)\
  1128.         local attr = self.Attributes\
  1129.         if attr.selbgcolour then\
  1130.                 self.SelectedBackgroundColour = self:ParseColour(attr.selbgcolour)\
  1131.         elseif attr.selbgcolor then\
  1132.                 self.SelectedBackgroundColour = self:ParseColour(attr.selbgcolor)\
  1133.         end\
  1134. \
  1135.         if attr.selcolour then\
  1136.                 self.SelectedTextColour = self:ParseColour(attr.selcolour)\
  1137.         elseif attr.selcolor then\
  1138.                 self.SelectedTextColour = self:ParseColour(attr.selcolor)\
  1139.         end\
  1140. \
  1141.         if attr.plcolour then\
  1142.                 self.PlaceholderTextColour = self:ParseColour(attr.plcolour)\
  1143.         elseif attr.plcolour then\
  1144.                 self.PlaceholderTextColour = self:ParseColour(attr.plcolour)\
  1145.         end\
  1146. \
  1147.         if attr.value then\
  1148.                 self.Value = attr.value\
  1149.         end\
  1150. \
  1151.         if attr.placeholder then\
  1152.                 self.Placeholder = attr.placeholder\
  1153.         end\
  1154. \
  1155.         if attr.name then\
  1156.                 self.InputName = attr.name\
  1157.         end\
  1158. end\
  1159. \
  1160. UpdateValue = function(self)\
  1161.         self.Value = self.Object.Text\
  1162. end\
  1163. \
  1164. OnCreateObject = function(self, parentObject, y)\
  1165.         return {\
  1166.                 Element = self,\
  1167.                 Y = y,\
  1168.                 X = 1,\
  1169.                 Width = self.Width,\
  1170.                 Type = \"TextBox\",\
  1171.                 Text = self.Value,\
  1172.                 TextColour = self.TextColour,\
  1173.                 BackgroundColour = self.BackgroundColour,\
  1174.                 SelectedBackgroundColour = self.SelectedBackgroundColour,\
  1175.                 SelectedTextColour = self.SelectedTextColour,\
  1176.                 PlaceholderTextColour = self.PlaceholderTextColour,\
  1177.                 Placeholder = self.Placeholder,\
  1178.                 InputName = self.InputName,\
  1179.                 OnChange = function(_self, event, keychar)\
  1180.                         if keychar == keys.tab or keychar == keys.enter then\
  1181.                                 local form = self\
  1182.                                 local step = 0\
  1183.                                 while form.Tag ~= 'form' and step < 50 do\
  1184.                                         form = form.Parent\
  1185.                                 end\
  1186.                                 if keychar == keys.tab then\
  1187.                                         if form and form.Object and form.Object.OnTab then\
  1188.                                                 form.Object:OnTab()\
  1189.                                         end\
  1190.                                 else\
  1191.                                         if form and form.Submit then\
  1192.                                                 form:Submit(true)\
  1193.                                         end\
  1194.                                 end\
  1195.                         end\
  1196.                 end\
  1197.         }\
  1198. end",["ElementTree.lua"]="Tree = nil\
  1199. FailHandler = nil\
  1200. \
  1201. Initialise = function(self, html)\
  1202.         local new = {}    -- the new instance\
  1203.         setmetatable( new, {__index = self} )\
  1204.         local err = nil\
  1205.         if html:sub(1,15) ~= '<!DOCTYPE ccml>' then\
  1206.                 err = Errors.InvalidDoctype\
  1207.         end\
  1208. \
  1209.         html = html:gsub(\"<!%-%-*.-%-%->\",\"\")\
  1210. \
  1211.         local rawTree\
  1212.         if not err then\
  1213.                 rawTree = parser.parsestr(html)[1]\
  1214.         end\
  1215. \
  1216.         if not err then\
  1217.                 _, notok = pcall(function() new:LoadTree(rawTree) end)\
  1218.                 if notok then\
  1219.                         error(notok)\
  1220.                         err = Errors.ParseFailed\
  1221.                 end\
  1222.         end\
  1223. \
  1224.         if err then\
  1225.                 return nil, err\
  1226.         end\
  1227.         return new\
  1228. end\
  1229. \
  1230. LoadTree = function(self, rawTree)\
  1231.         local tree = {}\
  1232.         local node = true\
  1233.         node = function (tbl, tr, parent)\
  1234.                 for i, v in ipairs(tbl) do\
  1235.                         if type(v) == 'table' and v._tag then\
  1236.                                 local class = self:GetElementClass(v._tag, v._attr)\
  1237.                                 if not class or not class.Initialise then\
  1238.                                         error('Unknown class: '..v._attr.type)\
  1239.                                 end\
  1240.                                 local element = class:Initialise(v)\
  1241.                                 element.Parent = parent\
  1242.                                 table.insert(tr, element)\
  1243.                                 if element.Children then\
  1244.                                         node(v, element.Children, element)\
  1245.                                 end\
  1246.                         end\
  1247.                 end\
  1248.         end\
  1249. \
  1250.         node(rawTree, tree)\
  1251.         self.Tree = tree\
  1252. end\
  1253. \
  1254. GetElement = function(self, tag)\
  1255.         local node = true\
  1256.         node = function(tbl)\
  1257.                 for i,v in ipairs(tbl) do\
  1258.                         if type(v) == 'table' and v.Tag then\
  1259.                                 if v.Tag == tag then\
  1260.                                         return v\
  1261.                                 end\
  1262.                                 if v.Children then\
  1263.                                         local r = node(v.Children)\
  1264.                                         if r then\
  1265.                                                 return r\
  1266.                                         end\
  1267.                                 end\
  1268.                         end\
  1269.                 end\
  1270.         end\
  1271.         return node(self.Tree)\
  1272. end\
  1273. \
  1274. GetElementClass = function(self, tag, attr)\
  1275.         if tag == 'h' then\
  1276.                 return Heading\
  1277.         elseif tag == 'div' then\
  1278.                 return Divider\
  1279.         elseif tag == 'p' then\
  1280.                 return Paragraph\
  1281.         elseif tag == 'center' then\
  1282.                 return Center\
  1283.         elseif tag == 'img' then\
  1284.                 return Image\
  1285.         elseif tag == 'a' then\
  1286.                 return Link\
  1287.         elseif tag == 'float' then\
  1288.                 return Float\
  1289.         elseif tag == 'br' then\
  1290.                 return Element\
  1291.         elseif tag == 'input' then\
  1292.                 if attr.type == 'text' then\
  1293.                         return TextInput\
  1294.                 elseif attr.type == 'password' then\
  1295.                         return SecureTextInput\
  1296.                 elseif attr.type == 'submit' or attr.type == 'button' then\
  1297.                         return ButtonInput\
  1298.                 elseif attr.type == 'file' then\
  1299.                         return FileInput\
  1300.                 elseif attr.type == 'hidden' then\
  1301.                         return HiddenInput\
  1302.                 else\
  1303.                         return Element\
  1304.                 end\
  1305.         elseif tag == 'select' then\
  1306.                 return Select\
  1307.         elseif tag == 'option' then\
  1308.                 return SelectOption\
  1309.         elseif tag == 'form' then\
  1310.                 return Form\
  1311.         elseif tag == 'script' then\
  1312.                 return Script\
  1313.         else\
  1314.                 return Element\
  1315.         end\
  1316. end",["SelectOption.lua"]="Value = nil\
  1317. \
  1318. OnInitialise = function(self, node)\
  1319.         if attr.value then\
  1320.                 new.Value = attr.value\
  1321.         end\
  1322. end\
  1323. \
  1324. OnCreateObject = function(self, parentObject, y)\
  1325.         if parentObject.AddMenuItem then\
  1326.                 parentObject:AddMenuItem({\
  1327.                         Value = self.Value,\
  1328.                         Text = self.Text,\
  1329.                         Type = \"Button\"\
  1330.                 })\
  1331.         end\
  1332. end",},["startup"]="local QuestVersion = 'v0.9.0 Private Beta'\
  1333. if OneOS then\
  1334.         QuestVersion = QuestVersion .. '-OneOS ' .. OneOS.Version\
  1335. end\
  1336. \
  1337. -- TODO: have a much simpler API loader... not a 70+ line one\
  1338. local Extension = function(path, addDot)\
  1339.         if not path then\
  1340.                 return nil\
  1341.         elseif not string.find(fs.getName(path), '%.') then\
  1342.                 if not addDot then\
  1343.                         return fs.getName(path)\
  1344.                 else\
  1345.                         return ''\
  1346.                 end\
  1347.         else\
  1348.                 local _path = path\
  1349.                 if path:sub(#path) == '/' then\
  1350.                         _path = path:sub(1,#path-1)\
  1351.                 end\
  1352.                 local extension = _path:gmatch('%.[0-9a-z]+$')()\
  1353.                 if extension then\
  1354.                         extension = extension:sub(2)\
  1355.                 else\
  1356.                         --extension = nil\
  1357.                         return ''\
  1358.                 end\
  1359.                 if addDot then\
  1360.                         extension = '.'..extension\
  1361.                 end\
  1362.                 return extension:lower()\
  1363.         end\
  1364. end\
  1365. \
  1366. local RemoveExtension = function(path)\
  1367.         if path:sub(1,1) == '.' then\
  1368.                 return path\
  1369.         end\
  1370.         local extension = Extension(path)\
  1371.         if extension == path then\
  1372.                 return fs.getName(path)\
  1373.         end\
  1374.         return string.gsub(path, extension, ''):sub(1, -2)\
  1375. end\
  1376. \
  1377. local tAPIsLoading = {}\
  1378. local function LoadAPI(_sPath)\
  1379.         local sName = RemoveExtension(fs.getName( _sPath ))\
  1380.         if tAPIsLoading[sName] == true then\
  1381.         end\
  1382.         tAPIsLoading[sName] = true\
  1383.                 \
  1384.         local tEnv = {isStartup = true }\
  1385.         setmetatable( tEnv, { __index = getfenv()} )\
  1386.         local fnAPI, err = loadfile( _sPath )\
  1387.         if fnAPI then\
  1388.                 setfenv( fnAPI, tEnv )\
  1389.                 fnAPI()\
  1390.         else\
  1391.                 printError( err )\
  1392.                 log('Error: '..err)\
  1393.        tAPIsLoading[sName] = nil\
  1394.                 return false\
  1395.         end\
  1396.         \
  1397.         local tAPI = {}\
  1398.         for k,v in pairs( tEnv ) do\
  1399.                 tAPI[k] =  v\
  1400.         end\
  1401.         \
  1402.         _G[sName] = tAPI\
  1403. end\
  1404. \
  1405. _G.Errors = {\
  1406.         Unknown = 1,\
  1407.         InvalidDoctype = 2,\
  1408.         ParseFailed = 3,\
  1409.         NotFound = 404,\
  1410.         TimeoutStop = 408,\
  1411. }\
  1412. \
  1413. local bedrockPath='/' if OneOS then OneOS.LoadAPI('/System/API/Bedrock.lua', false)elseif fs.exists(bedrockPath..'/Bedrock')then os.loadAPI(bedrockPath..'/Bedrock')else if http then print('Downloading Bedrock...')local h=http.get('http://pastebin.com/raw.php?i=0MgKNqpN')if h then local f=fs.open(bedrockPath..'/Bedrock','w')f.write(h.readAll())f.close()h.close()os.loadAPI(bedrockPath..'/Bedrock')else error('Failed to download Bedrock. Is your internet working?') end else error('This program needs to download Bedrock to work. Please enable HTTP.') end end if Bedrock then Bedrock.BasePath = bedrockPath Bedrock.ProgramPath = shell.getRunningProgram() end\
  1414. \
  1415. os.loadAPI('parser')\
  1416. os.loadAPI('hash')\
  1417. os.loadAPI('lQuery')\
  1418. os.loadAPI('Peripheral')\
  1419. os.loadAPI('Wireless')\
  1420. \
  1421. LoadAPI('Elements/Element.lua')\
  1422. \
  1423. LoadAPI('Elements/ElementTree.lua')\
  1424. \
  1425. local elements = {\
  1426.         'Script',\
  1427.         'Center',\
  1428.         'Link',\
  1429.         'Image',\
  1430.         'Divider',\
  1431.         'Heading',\
  1432.         'Paragraph',\
  1433.         'Float',\
  1434.         'TextInput',\
  1435.         'FileInput',\
  1436.         'SecureTextInput',\
  1437.         'Select',\
  1438.         'Form',\
  1439.         'SelectOption',\
  1440.         'ButtonInput',\
  1441.         'HiddenInput',\
  1442. }\
  1443. \
  1444. for i, v in ipairs(elements) do\
  1445.         LoadAPI('Elements/' .. v .. '.lua')\
  1446.         local env = getfenv()\
  1447.         local super = Element\
  1448.         if env[v].Inherit then\
  1449.                 super = env[env[v].Inherit]\
  1450.         end\
  1451.         env[v].__index = super\
  1452.         setmetatable(env[v], env[v])\
  1453. end\
  1454. \
  1455. local program = Bedrock:Initialise()\
  1456. \
  1457. local function split(str, pat)\
  1458.   local t = {}\
  1459.   local fpat = \"(.-)\" .. pat\
  1460.   local last_end = 1\
  1461.   local s, e, cap = str:find(fpat, 1)\
  1462.   while s do\
  1463.      if s ~= 1 or cap ~= \"\" then\
  1464.          table.insert(t,cap)\
  1465.      end\
  1466.      last_end = e+1\
  1467.      s, e, cap = str:find(fpat, last_end)\
  1468.   end\
  1469.   if last_end <= #str then\
  1470.      cap = str:sub(last_end)\
  1471.      table.insert(t, cap)\
  1472.   end\
  1473.   return t\
  1474. end\
  1475. \
  1476. local httpQueue = {}\
  1477. \
  1478. program:RegisterEvent('http_success', function(self, event, url, response)\
  1479.         for i, request in ipairs(httpQueue) do\
  1480.                 if request[3] == url then\
  1481.                         request[2](true, url, response)\
  1482.                         table.remove(httpQueue, i)\
  1483.                         break\
  1484.                 end\
  1485.         end\
  1486. end)\
  1487. \
  1488. program:RegisterEvent('http_failure', function(self, event, url)\
  1489.         for i, request in ipairs(httpQueue) do\
  1490.                 if request[3] == url then\
  1491.                         request[2](false, Errors.Unknown)\
  1492.                         table.remove(httpQueue, i)\
  1493.                         break\
  1494.                 end\
  1495.         end\
  1496. end)\
  1497. \
  1498. program:RegisterEvent('modem_message', function(self, event, side, channel, replyChannel, message, distance)\
  1499.         Wireless.HandleMessage(event, side, channel, replyChannel, message, distance)\
  1500. end)\
  1501. \
  1502. local wifiQueue = {}\
  1503. \
  1504. Wireless.Responder = function(event, side, channel, replyChannel, message, distance)\
  1505.         if channel == Wireless.Channels.QuestServerRequestReply then\
  1506.                 for i, request in ipairs(wifiQueue) do\
  1507.                         if request[1] == message.content.url then\
  1508.                                 if message.content.content then\
  1509.                                         local line = 0\
  1510.                                         local lines = split(message.content.content, '\\n')\
  1511.                                         local handle = {\
  1512.                                                 readAll = function()return message.content.content end,\
  1513.                                                 readLine = function()\
  1514.                                                         line = line + 1\
  1515.                                                         return lines[line]\
  1516.                                                 end,\
  1517.                                                 close = function()end\
  1518.                                         }\
  1519.                                         request[2](true, message.content.url, handle)\
  1520.                                 else\
  1521.                                         request[2](false, 404)\
  1522.                                 end\
  1523.                                 table.remove(wifiQueue, i)\
  1524.                                 break\
  1525.                         end\
  1526.                 end\
  1527.         end\
  1528. end\
  1529. \
  1530. local function cancelHTTPAsync(url)\
  1531.         for i, request in ipairs(httpQueue) do\
  1532.                 if request[1] == url then\
  1533.                         request[2](false, Errors.TimeoutStop)\
  1534.                         table.remove(httpQueue, i)\
  1535.                         break\
  1536.                 end\
  1537.         end\
  1538. end\
  1539. \
  1540. local settings = false\
  1541. \
  1542. local function fetchHTTPAsync(url, callback, post)\
  1543.         local components = urlComponents(url)\
  1544.         if components.protocol == 'quest' then\
  1545.                 local file = fs.open(program.ProgramPath .. '/Pages/' .. components.filepathsansget, 'r')\
  1546.                 callback(true, url, file)\
  1547.         elseif components.protocol == 'file' then\
  1548.                 local file = fs.open(components.sansprotocol, 'r')\
  1549.                 if file then\
  1550.                         callback(true, url, file)\
  1551.                 else\
  1552.                         callback(false)\
  1553.                 end\
  1554.         elseif components.protocol == 'wifi' then\
  1555.                 if Wireless.Present() then\
  1556.                         table.insert(wifiQueue, {url, callback})\
  1557.                         Wireless.SendMessage(Wireless.Channels.QuestServerRequest, url)\
  1558.                 else\
  1559.                         callback(false, 7)\
  1560.                 end\
  1561.         elseif components.protocol == 'http' then\
  1562.                 local _url = resolveQuestHostUrl(url)\
  1563.                 table.insert(httpQueue, {url, callback, _url})\
  1564. \
  1565.                 if not post then\
  1566.                         post = 'questClientIdentifier=' .. textutils.urlEncode(settings.ClientIdentifier)\
  1567.                 else\
  1568.                         post = post .. '&questClientIdentifier=' .. textutils.urlEncode(settings.ClientIdentifier)\
  1569.                 end\
  1570.                 http.request(_url, post, {\
  1571.                         ['User-Agent'] = 'Quest/'..QuestVersion\
  1572.                 })\
  1573.         end\
  1574. end\
  1575. \
  1576. local questHost = 'http://quest.net76.net/sites/'\
  1577. \
  1578. local function findLast(haystack, needle)\
  1579.    local i=haystack:match(\".*\"..needle..\"()\")\
  1580.    if i==nil then return nil else return i-1 end\
  1581. end\
  1582. \
  1583. local hex_to_char = function(x)\
  1584.  return string.char(tonumber(x, 16))\
  1585. end\
  1586. \
  1587. local function urlUnencode( str )\
  1588.         -- essentially reverses textutils.urlDecode\
  1589.    if str then\
  1590.        str = string.gsub(str, \"+\", \" \")\
  1591.        str = string.gsub(str, \"\\r\\n\", \"\\n\")\
  1592.        term.setTextColor(colors.black)\
  1593.        str = str:gsub(\"%%(%x%x)\", hex_to_char)\
  1594.    end\
  1595.    return str    \
  1596. end\
  1597. \
  1598. local function urlComponents(url)\
  1599.         if url then\
  1600.                 urlUnencode(textutils.urlEncode(url))\
  1601.                 local components = {}\
  1602.                 local parts = split(url, '[\\\\/]+')\
  1603.                 if url:find('://') and parts[1]:sub(#parts[1]) == ':' then\
  1604.                         components.protocol = parts[1]:sub(1, #parts[1]-1)\
  1605.                         components.sansprotocol = url:sub(#components.protocol + 4)\
  1606.                         components.host = parts[2]\
  1607.                         components.fullhost = components.protocol .. '://' .. parts[2] .. '/'\
  1608.                         components.filepath = url:sub(#components.fullhost)\
  1609.                         if components.filepath:sub(#components.filepath) ~= '/' and components.filepath:find('?') then\
  1610.                                 components.filename = fs.getName(components.filepath:sub(1, components.filepath:find('?') - 1))\
  1611.                         else\
  1612.                                 components.filename = fs.getName(components.filepath)\
  1613.                         end\
  1614.                         if components.filename == 'root' or components.filename == components.host then\
  1615.                                 components.filename = ''\
  1616.                         end\
  1617.                         components.base = url:sub(1, findLast(url, '/'))\
  1618.                         components.get = {}\
  1619.                         components.filepathsansget = components.sansprotocol\
  1620.                         if url:find('?') then\
  1621.                                 local start = url:find('?')\
  1622.                                 components.filepathsansget = url:sub(#components.protocol + 4, start - 1)\
  1623.                                 local getString = url:sub(start + 1)\
  1624.                                 local values = split(getString, '&')\
  1625.                                 for i, v in ipairs(values) do\
  1626.                                         local keyvalue = split(v, '=')\
  1627.                                         components.get[keyvalue[1]] =  urlUnencode(keyvalue[2])\
  1628.                                 end\
  1629.                         end\
  1630.                         return components\
  1631.                 end\
  1632.         end\
  1633. end\
  1634. \
  1635. local function resolveQuestHostUrl(url)\
  1636.         local components = urlComponents(url)\
  1637.         local hostParts = split(components.host, '%.')\
  1638.         local tld = hostParts[#hostParts]\
  1639.         if tld == 'qst' and #hostParts == 2 then\
  1640.                 return questHost .. hostParts[1] .. components.filepath\
  1641.         end\
  1642.         return url\
  1643. end\
  1644. \
  1645. local function resolveFullUrl(url)\
  1646.         if url and type(url) ~= 'string' then\
  1647.         elseif url:find('://') then\
  1648.                 return url\
  1649.         else\
  1650.                 local components = urlComponents(program:GetObject('WebView').URL)\
  1651.                 if components then\
  1652.                         if url:sub(1,1) == '/' then\
  1653.                                 return components.fullhost .. url:sub(2)\
  1654.                         else\
  1655.                                 return components.base .. url\
  1656.                         end\
  1657.                 end\
  1658.         end\
  1659. end\
  1660. \
  1661. local function getCurrentUrl()\
  1662.         return program:GetObject('WebView').URL\
  1663. end\
  1664. \
  1665. local function getCurrentFakeUrl()\
  1666.         return program:GetObject('WebView').FakeURL\
  1667. end\
  1668. \
  1669. local function goToUrl(url, post)\
  1670.         program:GetObject('WebView'):GoToURL(url, nil, nil, post)\
  1671. end\
  1672. \
  1673. --      Yes, it's evil and terrible, etc. But I'll hopefully change it later.\
  1674. _G.cancelHTTPAsync = cancelHTTPAsync\
  1675. _G.fetchHTTPAsync = fetchHTTPAsync\
  1676. _G.resolveFullUrl = resolveFullUrl\
  1677. _G.resolveQuestHostUrl = resolveQuestHostUrl\
  1678. _G.getCurrentUrl = getCurrentUrl\
  1679. _G.getCurrentFakeUrl = getCurrentFakeUrl\
  1680. _G.goToUrl = goToUrl\
  1681. _G.split = split\
  1682. _G.urlComponents = urlComponents\
  1683. _G.QuestVersion = QuestVersion\
  1684. \
  1685. local history = {}\
  1686. local historyItem = 0\
  1687. \
  1688. local function updateHistoryButtons()\
  1689.         if history[historyItem-1] then\
  1690.                 program:GetObject('BackButton').Enabled = true\
  1691.         else\
  1692.                 program:GetObject('BackButton').Enabled = false\
  1693.         end\
  1694. \
  1695.         if history[historyItem+1] then\
  1696.                 program:GetObject('ForwardButton').Enabled = true\
  1697.         else\
  1698.                 program:GetObject('ForwardButton').Enabled = false\
  1699.         end\
  1700. end\
  1701. \
  1702. local function addHistoryURL(url)\
  1703.         for i, v in ipairs(history) do\
  1704.                 if i > historyItem then\
  1705.                         history[i] = nil\
  1706.                 end\
  1707.         end\
  1708.         table.insert(history, url)\
  1709.         historyItem = #history\
  1710.         updateHistoryButtons()\
  1711. end\
  1712. \
  1713. local defaultSettings = {\
  1714.         Home = 'http://thehub.qst/',\
  1715.         ClientIdentifier = nil\
  1716. }\
  1717. \
  1718. local function quit()\
  1719.         term.setBackgroundColour(colors.black)\
  1720.         shell.run('clear')\
  1721.         print('Thanks for using Quest, created by oeed.')\
  1722.         program:Quit()\
  1723. end\
  1724. \
  1725. local function goHome()\
  1726.         goToUrl(settings.Home)\
  1727. end\
  1728. \
  1729. local function saveSettings()\
  1730.         local f = fs.open('.Quest.settings', 'w')\
  1731.         if f then\
  1732.                 f.write(textutils.serialize(settings))\
  1733.                 f.close()\
  1734.         end\
  1735. end\
  1736. \
  1737. local function generateClientIdentifier()\
  1738.         program:DisplayWindow({\
  1739.                 Children = {{\
  1740.                         X = 2,\
  1741.                         Y = 2,\
  1742.                         Type = \"Label\",\
  1743.                         Width = \"100%,-2\",\
  1744.                         Height = 2,\
  1745.                         Text = \"Registering computer with central server...\"\
  1746.                 }},\
  1747.                 Width = 28,\
  1748.                 Height = 4\
  1749.         }, \"Please Wait\", false)\
  1750.         program:Draw()\
  1751.         local h = http.get('http://quest.net76.net/registerClient.php')\
  1752.         program.Window:Close()\
  1753. \
  1754.         if h then\
  1755.                 settings.ClientIdentifier = h.readAll()\
  1756.                 saveSettings()\
  1757.                 h.close()\
  1758.                 goHome()\
  1759.         else\
  1760.                 program:DisplayAlertWindow(\"Register Failed\", \"Quest couldn't register your computer. There was something wrong with your internet connection. Please quit and try again.\", {'Quit'}, function(value)\
  1761.                         quit()\
  1762.                 end)\
  1763.         end\
  1764. \
  1765. end\
  1766. \
  1767. local function loadSettings()\
  1768.         if fs.exists('.Quest.settings') then\
  1769.                 local f = fs.open('.Quest.settings', 'r')\
  1770.                 if f then\
  1771.                         settings = textutils.unserialize(f.readAll())\
  1772.                         if not settings.ClientIdentifier then\
  1773.                                 generateClientIdentifier()\
  1774.                         end\
  1775.                         return settings\
  1776.                 end\
  1777.         end\
  1778. \
  1779.         settings = defaultSettings\
  1780.         generateClientIdentifier()\
  1781. end\
  1782. \
  1783. program:Run(function()\
  1784.         local timeoutTimer = false\
  1785. \
  1786.         program:LoadView('main')\
  1787. \
  1788.         Wireless.Initialise()\
  1789. \
  1790.         loadSettings()\
  1791. \
  1792.         program:GetObject('BackButton').OnClick = function(self)\
  1793.                 if history[historyItem-1] then\
  1794.                         historyItem = historyItem - 1\
  1795.                         program:GetObject('WebView'):GoToURL(history[historyItem], nil, true)\
  1796.                         updateHistoryButtons()\
  1797.                 end\
  1798.         end\
  1799. \
  1800.         program:GetObject('ForwardButton').OnClick = function(self)\
  1801.                 if history[historyItem+1] then\
  1802.                         historyItem = historyItem + 1\
  1803.                         program:GetObject('WebView'):GoToURL(history[historyItem], nil, true)\
  1804.                         updateHistoryButtons()\
  1805.                 end\
  1806.         end\
  1807. \
  1808.         program:GetObject('URLTextBox').OnChange = function(self, event, keychar)\
  1809.                 if keychar == keys.enter then\
  1810.                         local url = self.Text\
  1811.                         if not url:find('://') then\
  1812.                                 if url:find(' ') or not url:find('%.') then\
  1813.                                         url = 'http://thehub.qst/search.php?q='..textutils.urlEncode(url)\
  1814.                                 else\
  1815.                                         url = 'http://' .. url \
  1816.                                 end\
  1817.                                 self.Text = url\
  1818.                         end\
  1819.                         program:GetObject('WebView'):GoToURL(url)\
  1820.                 end\
  1821.         end\
  1822. \
  1823.         program:GetObject('OptionsButton').OnClick = function(self, event, side, x, y)\
  1824.                 if self:ToggleMenu('optionsmenu', x, y) then\
  1825.                         program:GetObject('StopMenuItem').OnClick = function(self, event, side, x, y)\
  1826.                                 program:GetObject('WebView'):Stop()\
  1827.                         end\
  1828. \
  1829.                         program:GetObject('ReloadMenuItem').OnClick = function(self, event, side, x, y)\
  1830.                                 program:GetObject('WebView'):GoToURL(program:GetObject('WebView').URL)\
  1831.                         end\
  1832. \
  1833.                         program:GetObject('GoHomeMenuItem').OnClick = function(self, event, side, x, y)\
  1834.                                 goHome()\
  1835.                         end\
  1836. \
  1837.                         program:GetObject('SetHomeMenuItem').OnClick = function(self, event, side, x, y)\
  1838.                                 settings.Home = program:GetObject('WebView').FakeURL\
  1839.                                 saveSettings()\
  1840.                         end\
  1841. \
  1842.                         program:GetObject('QuitMenuItem').OnClick = function(self, event, side, x, y)\
  1843.                                 quit()\
  1844.                         end\
  1845.                 end\
  1846.         end\
  1847. \
  1848.         program:GetObject('WebView').OnPageLoadStart = function(self, url)\
  1849.                 program:SetActiveObject()\
  1850.                 -- program:GetObject('GoButton').Text = 'x'\
  1851.                 program:GetObject('URLTextBox').Visible = false\
  1852.                 program:GetObject('LoadingLabel').Visible = true\
  1853.                 program:GetObject('PageTitleLabel').Text = ''\
  1854. \
  1855.                 if url:find('http://') or url:find('https://') then\
  1856.                         timeoutTimer = program:StartTimer(function()\
  1857.                                 program:GetObject('WebView'):Stop()\
  1858.                         end, 20)\
  1859.                 else\
  1860.                         timeoutTimer = program:StartTimer(function()\
  1861.                                 program:GetObject('WebView'):Stop()\
  1862.                         end, 1)\
  1863.                 end\
  1864.         end\
  1865. \
  1866.         program:GetObject('WebView').OnPageLoadEnd = function(self, url, noHistory)\
  1867.                 program:GetObject('URLTextBox').Text = url\
  1868.                 program:GetObject('URLTextBox').Visible = true\
  1869.                 program:GetObject('LoadingLabel').Visible = false\
  1870. \
  1871.                 if self.Tree:GetElement('title') then\
  1872.                         program:GetObject('PageTitleLabel').Text = self.Tree:GetElement('title').Text\
  1873.                 end\
  1874. \
  1875.                 if not noHistory then\
  1876.                         addHistoryURL(url)\
  1877.                 end\
  1878. \
  1879.                 program.Timers[timeoutTimer] = nil\
  1880.         end\
  1881. \
  1882.         program:GetObject('WebView').OnPageLoadFailed = function(self, url, _error, noHistory)\
  1883.                 program:GetObject('URLTextBox').Text = url\
  1884.                 program:GetObject('URLTextBox').Visible = true\
  1885.                 program:GetObject('LoadingLabel').Visible = false\
  1886.                 program.Timers[timeoutTimer] = nil\
  1887. \
  1888.                 if not noHistory then\
  1889.                         addHistoryURL(url)\
  1890.                 end\
  1891. \
  1892.                 local get = ''\
  1893.                 _error = _error or 1\
  1894.                 if type(_error) == 'string' then\
  1895.                         get = '?reason='..textutils.urlEncode(_error)\
  1896.                         _error = 'text'\
  1897.                 end\
  1898. \
  1899.                 program:GetObject('WebView'):GoToURL('quest://'.._error..'.ccml'..get, true, true)\
  1900.         end\
  1901. \
  1902.         program:GetObject('Toolbar').OnClick = function(self, event, side, x, y)\
  1903.                 program:SetActiveObject()\
  1904.         end\
  1905. \
  1906.         program:GetObject('WebView').OnClick = function(self, event, side, x, y)\
  1907.                 program:SetActiveObject()\
  1908.         end\
  1909. \
  1910.         if settings.ClientIdentifier then\
  1911.                 goHome()\
  1912.         end\
  1913. end)\
  1914. \
  1915. ",["Bedrock"]="--Bedrock Build: 262\
  1916. --This code is squished down in to one, rather hard to read file.\
  1917. --As such it is not much good for anything other than being loaded as an API.\
  1918. --If you want to look at the code to learn from it, copy parts or just take a look,\
  1919. --you should go to the GitHub repo. http://github.com/oeed/Bedrock/\
  1920. \
  1921. --\
  1922. --              Bedrock is the core program framework used by all OneOS and OneCode programs.\
  1923. --                                                      Inspired by Apple's Cocoa framework.\
  1924. --                                                                         (c) oeed 2014\
  1925. --\
  1926. --                For documentation see the Bedrock wiki, github.com/oeed/Bedrock/wiki/\
  1927. --\
  1928. \
  1929. local apis = {\
  1930. [\"Drawing\"] = [[\
  1931. local round = function(num, idp)\
  1932.         local mult = 10^(idp or 0)\
  1933.         return math.floor(num * mult + 0.5) / mult\
  1934. end\
  1935. \
  1936. local _w, _h = term.getSize()\
  1937. local copyBuffer = nil\
  1938. \
  1939. Screen = {\
  1940.         Width = _w,\
  1941.         Height = _h\
  1942. }\
  1943. \
  1944. Constraints = {\
  1945.         \
  1946. }\
  1947. \
  1948. CurrentConstraint = {1,1,_w,_h}\
  1949. IgnoreConstraint = false\
  1950. \
  1951. function AddConstraint(x, y, width, height)\
  1952.         local x2 = x + width - 1\
  1953.         local y2 = y + height - 1\
  1954.         table.insert(Drawing.Constraints, {x, y, x2, y2})\
  1955.         Drawing.GetConstraint()\
  1956. end\
  1957. \
  1958. function RemoveConstraint()\
  1959.         --table.remove(Drawing.Constraints, #Drawing.Constraints)\
  1960.         Drawing.Constraints[#Drawing.Constraints] = nil\
  1961.         Drawing.GetConstraint()\
  1962. end\
  1963. \
  1964. function GetConstraint()\
  1965.         local x = 1\
  1966.         local y = 1\
  1967.         local x2 = Drawing.Screen.Width\
  1968.         local y2 = Drawing.Screen.Height\
  1969.         for i, c in ipairs(Drawing.Constraints) do\
  1970.                 if x < c[1] then\
  1971.                         x = c[1]\
  1972.                 end\
  1973.                 if y < c[2] then\
  1974.                         y = c[2]\
  1975.                 end\
  1976.                 if x2 > c[3] then\
  1977.                         x2 = c[3]\
  1978.                 end\
  1979.                 if y2 > c[4] then\
  1980.                         y2 = c[4]\
  1981.                 end\
  1982.         end\
  1983.         Drawing.CurrentConstraint = {x, y, x2, y2}\
  1984. end\
  1985. \
  1986. function WithinContraint(x, y)\
  1987.         return Drawing.IgnoreConstraint or\
  1988.                   (x >= Drawing.CurrentConstraint[1] and\
  1989.                    y >= Drawing.CurrentConstraint[2] and\
  1990.                    x <= Drawing.CurrentConstraint[3] and\
  1991.                    y <= Drawing.CurrentConstraint[4])\
  1992. end\
  1993. \
  1994. colours.transparent = 0\
  1995. colors.transparent = 0\
  1996. \
  1997. DrawCharacters = function (x, y, characters, textColour, bgColour)\
  1998.         Drawing.WriteStringToBuffer(x, y, tostring(characters), textColour, bgColour)\
  1999. end\
  2000. \
  2001. DrawBlankArea = function (x, y, w, h, colour)\
  2002.         if colour ~= colours.transparent then\
  2003.                 Drawing.DrawArea (x, y, w, h, \" \", 1, colour)\
  2004.         end\
  2005. end\
  2006. \
  2007. DrawArea = function (x, y, w, h, character, textColour, bgColour)\
  2008.         --width must be greater than 1, otherwise we get problems\
  2009.         if w < 0 then\
  2010.                 w = w * -1\
  2011.         elseif w == 0 then\
  2012.                 w = 1\
  2013.         end\
  2014. \
  2015.         for ix = 1, w do\
  2016.                 local currX = x + ix - 1\
  2017.                 for iy = 1, h do\
  2018.                         local currY = y + iy - 1\
  2019.                         Drawing.WriteToBuffer(currX, currY, character, textColour, bgColour)\
  2020.                 end\
  2021.         end\
  2022. end\
  2023. \
  2024. DrawImage = function(_x,_y,tImage, w, h)\
  2025.         if tImage then\
  2026.                 for y = 1, h do\
  2027.                         if not tImage[y] then\
  2028.                                 break\
  2029.                         end\
  2030.                         for x = 1, w do\
  2031.                                 if not tImage[y][x] then\
  2032.                                         break\
  2033.                                 end\
  2034.                                 local bgColour = tImage[y][x]\
  2035.                     local textColour = tImage.textcol[y][x] or colours.white\
  2036.                     local char = tImage.text[y][x]\
  2037.                     Drawing.WriteToBuffer(x+_x-1, y+_y-1, char, textColour, bgColour)\
  2038.                         end\
  2039.                 end\
  2040.         elseif w and h then\
  2041.                 Drawing.DrawBlankArea(_x, _y, w, h, colours.lightGrey)\
  2042.         end\
  2043. end\
  2044. \
  2045. --using .nft\
  2046. LoadImage = function(path, global)\
  2047.         local image = {\
  2048.                 text = {},\
  2049.                 textcol = {}\
  2050.         }\
  2051.         if fs.exists(path) then\
  2052.                 local _io = io\
  2053.                 if OneOS and global then\
  2054.                         _io = OneOS.IO\
  2055.                 end\
  2056.        local file = _io.open(path, \"r\")\
  2057.        if not file then\
  2058.                 error('Error Occured. _io:'..tostring(_io)..' OneOS: '..tostring(OneOS)..' OneOS.IO'..tostring(OneOS.IO)..' io: '..tostring(io))\
  2059.        end\
  2060.        local sLine = file:read()\
  2061.        local num = 1\
  2062.        while sLine do  \
  2063.            table.insert(image, num, {})\
  2064.            table.insert(image.text, num, {})\
  2065.            table.insert(image.textcol, num, {})\
  2066.                                        \
  2067.            --As we're no longer 1-1, we keep track of what index to write to\
  2068.            local writeIndex = 1\
  2069.            --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour\
  2070.            local bgNext, fgNext = false, false\
  2071.            --The current background and foreground colours\
  2072.            local currBG, currFG = nil,nil\
  2073.            for i=1,#sLine do\
  2074.                    local nextChar = string.sub(sLine, i, i)\
  2075.                    if nextChar:byte() == 30 then\
  2076.                            bgNext = true\
  2077.                    elseif nextChar:byte() == 31 then\
  2078.                            fgNext = true\
  2079.                    elseif bgNext then\
  2080.                            currBG = Drawing.GetColour(nextChar)\
  2081.                                     if currBG == nil then\
  2082.                                         currBG = colours.transparent\
  2083.                                     end\
  2084.                            bgNext = false\
  2085.                    elseif fgNext then\
  2086.                            currFG = Drawing.GetColour(nextChar)\
  2087.                                     if currFG == nil or currFG == colours.transparent then\
  2088.                                         currFG = colours.white\
  2089.                                     end\
  2090.                            fgNext = false\
  2091.                    else\
  2092.                            if nextChar ~= \" \" and currFG == nil then\
  2093.                                    currFG = colours.white\
  2094.                            end\
  2095.                            image[num][writeIndex] = currBG\
  2096.                            image.textcol[num][writeIndex] = currFG\
  2097.                            image.text[num][writeIndex] = nextChar\
  2098.                            writeIndex = writeIndex + 1\
  2099.                    end\
  2100.            end\
  2101.            num = num+1\
  2102.            sLine = file:read()\
  2103.        end\
  2104.        file:close()\
  2105.    else\
  2106.         return nil\
  2107.         end\
  2108.         return image\
  2109. end\
  2110. \
  2111. DrawCharactersCenter = function(x, y, w, h, characters, textColour,bgColour)\
  2112.         w = w or Drawing.Screen.Width\
  2113.         h = h or Drawing.Screen.Height\
  2114.         x = x or 0\
  2115.         y = y or 0\
  2116.         x = math.floor((w - #characters) / 2) + x\
  2117.         y = math.floor(h / 2) + y\
  2118. \
  2119.         Drawing.DrawCharacters(x, y, characters, textColour, bgColour)\
  2120. end\
  2121. \
  2122. GetColour = function(hex)\
  2123.         if hex == ' ' then\
  2124.                 return colours.transparent\
  2125.         end\
  2126.    local value = tonumber(hex, 16)\
  2127.    if not value then return nil end\
  2128.    value = math.pow(2,value)\
  2129.    return value\
  2130. end\
  2131. \
  2132. Clear = function (_colour)\
  2133.         _colour = _colour or colours.black\
  2134.         Drawing.DrawBlankArea(1, 1, Drawing.Screen.Width, Drawing.Screen.Height, _colour)\
  2135. end\
  2136. \
  2137. Buffer = {}\
  2138. BackBuffer = {}\
  2139. \
  2140. TryRestore = false\
  2141. \
  2142. \
  2143. --TODO: make this quicker\
  2144. -- maybe sort the pixels in order of colour so it doesn't have to set the colour each time\
  2145. DrawBuffer = function()\
  2146.         if TryRestore and Restore then\
  2147.                 Restore()\
  2148.         end\
  2149. \
  2150.         for y,row in pairs(Drawing.Buffer) do\
  2151.                 for x,pixel in pairs(row) do\
  2152.                         local shouldDraw = true\
  2153.                         local hasBackBuffer = true\
  2154.                         if Drawing.BackBuffer[y] == nil or Drawing.BackBuffer[y][x] == nil or #Drawing.BackBuffer[y][x] ~= 3 then\
  2155.                                 hasBackBuffer = false\
  2156.                         end\
  2157.                         if hasBackBuffer and Drawing.BackBuffer[y][x][1] == Drawing.Buffer[y][x][1] and Drawing.BackBuffer[y][x][2] == Drawing.Buffer[y][x][2] and Drawing.BackBuffer[y][x][3] == Drawing.Buffer[y][x][3] then\
  2158.                                 shouldDraw = false\
  2159.                         end\
  2160.                         if shouldDraw then\
  2161.                                 term.setBackgroundColour(pixel[3])\
  2162.                                 term.setTextColour(pixel[2])\
  2163.                                 term.setCursorPos(x, y)\
  2164.                                 term.write(pixel[1])\
  2165.                         end\
  2166.                 end\
  2167.         end\
  2168.         Drawing.BackBuffer = Drawing.Buffer\
  2169.         Drawing.Buffer = {}\
  2170. end\
  2171. \
  2172. ClearBuffer = function()\
  2173.         Drawing.Buffer = {}\
  2174. end\
  2175. \
  2176. WriteStringToBuffer = function (x, y, characters, textColour,bgColour)\
  2177.         for i = 1, #characters do\
  2178.                 local character = characters:sub(i,i)\
  2179.                 Drawing.WriteToBuffer(x + i - 1, y, character, textColour, bgColour)\
  2180.         end\
  2181. end\
  2182. \
  2183. WriteToBuffer = function(x, y, character, textColour,bgColour, cached)\
  2184.         if not cached and not Drawing.WithinContraint(x, y) then\
  2185.                 return\
  2186.         end\
  2187.         x = round(x)\
  2188.         y = round(y)\
  2189. \
  2190.         if textColour == colours.transparent then\
  2191.                 character = ' '\
  2192.         end\
  2193. \
  2194.         if bgColour == colours.transparent then\
  2195.                 Drawing.Buffer[y] = Drawing.Buffer[y] or {}\
  2196.                 Drawing.Buffer[y][x] = Drawing.Buffer[y][x] or {\"\", colours.white, colours.black}\
  2197.                 Drawing.Buffer[y][x][1] = character\
  2198.                 Drawing.Buffer[y][x][2] = textColour\
  2199.         else\
  2200.                 Drawing.Buffer[y] = Drawing.Buffer[y] or {}\
  2201.                 Drawing.Buffer[y][x] = {character, textColour, bgColour}\
  2202.         end\
  2203. \
  2204.         if copyBuffer then\
  2205.                 copyBuffer[y] = copyBuffer[y] or {}\
  2206.                 copyBuffer[y][x] = {character, textColour, bgColour}            \
  2207.         end\
  2208. end\
  2209. \
  2210. DrawCachedBuffer = function(buffer)\
  2211.         for y, row in pairs(buffer) do\
  2212.                 for x, pixel in pairs(row) do\
  2213.                         WriteToBuffer(x, y, pixel[1], pixel[2], pixel[3], true)\
  2214.                 end\
  2215.         end\
  2216. end\
  2217. \
  2218. StartCopyBuffer = function()\
  2219.         copyBuffer = {}\
  2220. end\
  2221. \
  2222. EndCopyBuffer = function()\
  2223.         local tmpCopy = copyBuffer\
  2224.         copyBuffer = nil\
  2225.         return tmpCopy\
  2226. end\
  2227. ]],\
  2228. [\"Helpers\"] = [[\
  2229. LongestString = function(input, key, isKey)\
  2230.         local length = 0\
  2231.         if isKey then\
  2232.                 for k, v in pairs(input) do\
  2233.                         local titleLength = string.len(k)\
  2234.                         if titleLength > length then\
  2235.                                 length = titleLength\
  2236.                         end\
  2237.                 end\
  2238.         else\
  2239.                 for i = 1, #input do\
  2240.                         local value = input[i]\
  2241.                         if key then\
  2242.                                 if value[key] then\
  2243.                                         value = value[key]\
  2244.                                 else\
  2245.                                         value = ''\
  2246.                                 end\
  2247.                         end\
  2248.                         local titleLength = string.len(value)\
  2249.                         if titleLength > length then\
  2250.                                 length = titleLength\
  2251.                         end\
  2252.                 end\
  2253.         end\
  2254.         return length\
  2255. end\
  2256. \
  2257. Split = function(str,sep)\
  2258.    sep=sep or'/'\
  2259.    return str:match(\"(.*\"..sep..\")\")\
  2260. end\
  2261. \
  2262. Extension = function(path, addDot)\
  2263.         if not path then\
  2264.                 return nil\
  2265.         elseif not string.find(fs.getName(path), '%.') then\
  2266.                 if not addDot then\
  2267.                         return fs.getName(path)\
  2268.                 else\
  2269.                         return ''\
  2270.                 end\
  2271.         else\
  2272.                 local _path = path\
  2273.                 if path:sub(#path) == '/' then\
  2274.                         _path = path:sub(1,#path-1)\
  2275.                 end\
  2276.                 local extension = _path:gmatch('%.[0-9a-z]+$')()\
  2277.                 if extension then\
  2278.                         extension = extension:sub(2)\
  2279.                 else\
  2280.                         --extension = nil\
  2281.                         return ''\
  2282.                 end\
  2283.                 if addDot then\
  2284.                         extension = '.'..extension\
  2285.                 end\
  2286.                 return extension:lower()\
  2287.         end\
  2288. end\
  2289. \
  2290. RemoveExtension = function(path)\
  2291. --local name = string.match(fs.getName(path), '(%a+)%.?.-')\
  2292.         if path:sub(1,1) == '.' then\
  2293.                 return path\
  2294.         end\
  2295.         local extension = Helpers.Extension(path)\
  2296.         if extension == path then\
  2297.                 return fs.getName(path)\
  2298.         end\
  2299.         return string.gsub(path, extension, ''):sub(1, -2)\
  2300. end\
  2301. \
  2302. RemoveFileName = function(path)\
  2303.         if string.sub(path, -1) == '/' then\
  2304.                 path = string.sub(path, 1, -2)\
  2305.         end\
  2306.         local v = string.match(path, \"(.-)([^\\\\/]-%.?([^%.\\\\/]*))$\")\
  2307.         if type(v) == 'string' then\
  2308.                 return v\
  2309.         end\
  2310.         return v[1]\
  2311. end\
  2312. \
  2313. TruncateString = function(sString, maxLength)\
  2314.         if #sString > maxLength then\
  2315.                 sString = sString:sub(1,maxLength-3)\
  2316.                 if sString:sub(-1) == ' ' then\
  2317.                         sString = sString:sub(1,maxLength-4)\
  2318.                 end\
  2319.                 sString = sString  .. '...'\
  2320.         end\
  2321.         return sString\
  2322. end\
  2323. \
  2324. TruncateStringStart = function(sString, maxLength)\
  2325.         local len = #sString\
  2326.         if #sString > maxLength then\
  2327.                 sString = sString:sub(len - maxLength, len - 3)\
  2328.                 if sString:sub(-1) == ' ' then\
  2329.                         sString = sString:sub(len - maxLength, len - 4)\
  2330.                 end\
  2331.                 sString = '...' .. sString\
  2332.         end\
  2333.         return sString\
  2334. end\
  2335. \
  2336. WrapText = function(text, maxWidth)\
  2337.         local lines = {''}\
  2338.    for word, space in text:gmatch('(%S+)(%s*)') do\
  2339.            local temp = lines[#lines] .. word .. space:gsub('\\n','')\
  2340.            if #temp > maxWidth then\
  2341.                    table.insert(lines, '')\
  2342.            end\
  2343.            if space:find('\\n') then\
  2344.                    lines[#lines] = lines[#lines] .. word\
  2345.                    \
  2346.                    space = space:gsub('\\n', function()\
  2347.                            table.insert(lines, '')\
  2348.                            return ''\
  2349.                    end)\
  2350.            else\
  2351.                    lines[#lines] = lines[#lines] .. word .. space\
  2352.            end\
  2353.    end\
  2354.         return lines\
  2355. end\
  2356. \
  2357. TidyPath = function(path)\
  2358.         path = '/'..path\
  2359.         if fs.exists(path) and fs.isDir(path) then\
  2360.                 path = path .. '/'\
  2361.         end\
  2362. \
  2363.         path, n = path:gsub(\"//\", \"/\")\
  2364.         while n > 0 do\
  2365.                 path, n = path:gsub(\"//\", \"/\")\
  2366.         end\
  2367.         return path\
  2368. end\
  2369. \
  2370. Capitalise = function(str)\
  2371.         return str:sub(1, 1):upper() .. str:sub(2, -1)\
  2372. end\
  2373. \
  2374. Round = function(num, idp)\
  2375.         local mult = 10^(idp or 0)\
  2376.         return math.floor(num * mult + 0.5) / mult\
  2377. end\
  2378. ]],\
  2379. [\"Object\"] = [[\
  2380. X = 1\
  2381. Y = 1\
  2382. Width = 1\
  2383. Height = 1\
  2384. Parent = nil\
  2385. OnClick = nil\
  2386. Visible = true\
  2387. IgnoreClick = false\
  2388. Name = nil \
  2389. ClipDrawing = true\
  2390. UpdateDrawBlacklist = {}\
  2391. Fixed = false\
  2392. \
  2393. DrawCache = {}\
  2394. \
  2395. NeedsDraw = function(self)\
  2396.         if not self.Visible then\
  2397.                 return false\
  2398.         end\
  2399.         \
  2400.         if not self.DrawCache.Buffer or self.DrawCache.AlwaysDraw or self.DrawCache.NeedsDraw then\
  2401.                 return true\
  2402.         end\
  2403. \
  2404.         if self.OnNeedsUpdate then\
  2405.                 if self.OnNeedsUpdate() then\
  2406.                         return true\
  2407.                 end\
  2408.         end\
  2409. \
  2410.         if self.Children then\
  2411.                 for i, v in ipairs(self.Children) do\
  2412.                         if v:NeedsDraw() then\
  2413.                                 return true\
  2414.                         end\
  2415.                 end\
  2416.         end\
  2417. end\
  2418. \
  2419. GetPosition = function(self)\
  2420.         return self.Bedrock:GetAbsolutePosition(self)\
  2421. end\
  2422. \
  2423. GetOffsetPosition = function(self)\
  2424.         if not self.Parent then\
  2425.                 return {X = 1, Y = 1}\
  2426.         end\
  2427. \
  2428.         local offset = {X = 0, Y = 0}\
  2429.         if not self.Fixed and self.Parent.ChildOffset then\
  2430.                 offset = self.Parent.ChildOffset\
  2431.         end\
  2432. \
  2433.         return {X = self.X + offset.X, Y = self.Y + offset.Y}\
  2434. end\
  2435. \
  2436. Draw = function(self)\
  2437.         if not self.Visible then\
  2438.                 return\
  2439.         end\
  2440. \
  2441.         self.DrawCache.NeedsDraw = false\
  2442.         local pos = self:GetPosition()\
  2443.         Drawing.StartCopyBuffer()\
  2444. \
  2445.         if self.ClipDrawing then\
  2446.                 Drawing.AddConstraint(pos.X, pos.Y, self.Width, self.Height)\
  2447.         end\
  2448. \
  2449.         if self.OnDraw then\
  2450.                 self:OnDraw(pos.X, pos.Y)\
  2451.         end\
  2452. \
  2453.         self.DrawCache.Buffer = Drawing.EndCopyBuffer()\
  2454.         \
  2455.         if self.Children then\
  2456.                 for i, child in ipairs(self.Children) do\
  2457.                         local pos = child:GetOffsetPosition()\
  2458.                         if pos.Y + self.Height > 1 and pos.Y <= self.Height and pos.X + self.Width > 1 and pos.X <= self.Width then\
  2459.                                 child:Draw()\
  2460.                         end\
  2461.                 end\
  2462.         end\
  2463. \
  2464.         if self.ClipDrawing then\
  2465.                 Drawing.RemoveConstraint()\
  2466.         end     \
  2467. end\
  2468. \
  2469. ForceDraw = function(self, ignoreChildren, ignoreParent, ignoreBedrock)\
  2470.         if not ignoreBedrock and self.Bedrock then\
  2471.                 self.Bedrock:ForceDraw()\
  2472.         end\
  2473.         self.DrawCache.NeedsDraw = true\
  2474.         if not ignoreParent and self.Parent then\
  2475.                 self.Parent:ForceDraw(true, nil, true)\
  2476.         end\
  2477.         if not ignoreChildren and self.Children then\
  2478.                 for i, child in ipairs(self.Children) do\
  2479.                         child:ForceDraw(nil, true, true)\
  2480.                 end\
  2481.         end\
  2482. end\
  2483. \
  2484. OnRemove = function(self)\
  2485.         if self == self.Bedrock:GetActiveObject() then\
  2486.                 self.Bedrock:SetActiveObject()\
  2487.         end\
  2488. end\
  2489. \
  2490. local function ParseColour(value)\
  2491.         if type(value) == 'string' then\
  2492.                 if colours[value] and type(colours[value]) == 'number' then\
  2493.                         return colours[value]\
  2494.                 elseif colors[value] and type(colors[value]) == 'number' then\
  2495.                         return colors[value]\
  2496.                 end\
  2497.         elseif type(value) == 'number' and (value == colours.transparent or (value >= colours.white and value <= colours.black)) then\
  2498.                 return value\
  2499.         end\
  2500.         error('Invalid colour: \"'..tostring(value)..'\"')\
  2501. end\
  2502. \
  2503. Initialise = function(self, values)\
  2504.         local _new = values    -- the new instance\
  2505.         _new.DrawCache = {\
  2506.                 NeedsDraw = true,\
  2507.                 AlwaysDraw = false,\
  2508.                 Buffer = nil\
  2509.         }\
  2510.         setmetatable(_new, {__index = self} )\
  2511. \
  2512.         local new = {} -- the proxy\
  2513.         setmetatable(new, {\
  2514.                 __index = function(t, k)\
  2515.                         if k:find('Color') then\
  2516.                                 k = k:gsub('Color', 'Colour')\
  2517.                         end\
  2518. \
  2519.                         if k:find('Colour') then\
  2520.                                 if _new[k] then\
  2521.                                         return ParseColour(_new[k])\
  2522.                                 end\
  2523.                         elseif _new[k] ~= nil then\
  2524.                                 return _new[k]\
  2525.                         end\
  2526.                 end,\
  2527. \
  2528.                 __newindex = function (t,k,v)\
  2529.                         if k:find('Color') then\
  2530.                                 k = k:gsub('Color', 'Colour')\
  2531.                         end\
  2532. \
  2533.                         if k == 'Width' or k == 'X' or k == 'Height' or k == 'Y' then\
  2534.                                 v = new.Bedrock:ParseStringSize(new.Parent, k, v)\
  2535.                         end\
  2536. \
  2537.                         if v ~= _new[k] then\
  2538.                                 _new[k] = v\
  2539.                                 if t.OnUpdate then\
  2540.                                         t:OnUpdate(k)\
  2541.                                 end\
  2542. \
  2543.                                 if t.UpdateDrawBlacklist[k] == nil then\
  2544.                                         t:ForceDraw()\
  2545.                                 end\
  2546.                         end\
  2547.                 end\
  2548.         })\
  2549.         if new.OnInitialise then\
  2550.                 new:OnInitialise()\
  2551.         end\
  2552. \
  2553.         return new\
  2554. end\
  2555. \
  2556. Click = function(self, event, side, x, y)\
  2557.         if self.Visible and not self.IgnoreClick then\
  2558.                 if event == 'mouse_click' and self.OnClick and self:OnClick(event, side, x, y) ~= false then\
  2559.                         return true\
  2560.                 elseif event == 'mouse_drag' and self.OnDrag and self:OnDrag(event, side, x, y) ~= false then\
  2561.                         return true\
  2562.                 elseif event == 'mouse_scroll' and self.OnScroll and self:OnScroll(event, side, x, y) ~= false then\
  2563.                         return true\
  2564.                 else\
  2565.                         return false\
  2566.                 end\
  2567.         else\
  2568.                 return false\
  2569.         end\
  2570. \
  2571. end\
  2572. \
  2573. ToggleMenu = function(self, name, x, y)\
  2574.         return self.Bedrock:ToggleMenu(name, self, x, y)\
  2575. end\
  2576. \
  2577. function OnUpdate(self, value)\
  2578.         if value == 'Z' then\
  2579.                 self.Bedrock:ReorderObjects()\
  2580.         end\
  2581. end\
  2582. ]],\
  2583. }\
  2584. local objects = {\
  2585. [\"Button\"] = [[\
  2586. BackgroundColour = colours.lightGrey\
  2587. ActiveBackgroundColour = colours.blue\
  2588. ActiveTextColour = colours.white\
  2589. TextColour = colours.black\
  2590. DisabledTextColour = colours.lightGrey\
  2591. Text = \"\"\
  2592. Toggle = nil\
  2593. Momentary = true\
  2594. AutoWidthAutoWidth = true\
  2595. Align = 'Center'\
  2596. Enabled = true\
  2597. \
  2598. OnUpdate = function(self, value)\
  2599.         if value == 'Text' and self.AutoWidth then\
  2600.                 self.Width = #self.Text + 2\
  2601.         end\
  2602. end\
  2603. \
  2604. OnDraw = function(self, x, y)\
  2605.         local bg = self.BackgroundColour\
  2606. \
  2607.         if self.Toggle then\
  2608.                 bg = self.ActiveBackgroundColour\
  2609.         end\
  2610. \
  2611.         local txt = self.TextColour\
  2612.         if self.Toggle then\
  2613.                 txt = self.ActiveTextColour\
  2614.         end\
  2615.         if not self.Enabled then\
  2616.                 txt = self.DisabledTextColour\
  2617.         end\
  2618.         Drawing.DrawBlankArea(x, y, self.Width, self.Height, bg)\
  2619. \
  2620.         local _x = 1\
  2621.    if self.Align == 'Right' then\
  2622.        _x = self.Width - #self.Text - 1\
  2623.    elseif self.Align == 'Center' then\
  2624.        _x = math.floor((self.Width - #self.Text) / 2)\
  2625.    end\
  2626.         Drawing.DrawCharacters(x + _x, y, self.Text, txt, bg)\
  2627. end\
  2628. \
  2629. OnLoad = function(self)\
  2630.         if self.Toggle ~= nil then\
  2631.                 self.Momentary = false\
  2632.         end\
  2633. end\
  2634. \
  2635. Click = function(self, event, side, x, y)\
  2636.         if self.Visible and not self.IgnoreClick and self.Enabled and event ~= 'mouse_scroll' then\
  2637.                 if self.OnClick then\
  2638.                         if self.Momentary then\
  2639.                                 self.Toggle = true\
  2640.                                 self.Bedrock:StartTimer(function()self.Toggle = false end,0.25)\
  2641.                         elseif self.Toggle ~= nil then\
  2642.                                 self.Toggle = not self.Toggle\
  2643.                         end\
  2644. \
  2645.                         self:OnClick(event, side, x, y, self.Toggle)\
  2646.                 else\
  2647.                         self.Toggle = not self.Toggle\
  2648.                 end\
  2649.                 return true\
  2650.         else\
  2651.                 return false\
  2652.         end\
  2653. end\
  2654. ]],\
  2655. [\"CollectionView\"] = [[\
  2656. Inherit = 'ScrollView'\
  2657. UpdateDrawBlacklist = {['NeedsItemUpdate']=true}\
  2658. \
  2659. TextColour = colours.black\
  2660. BackgroundColour = colours.white\
  2661. Items = false\
  2662. NeedsItemUpdate = false\
  2663. SpacingX = 2\
  2664. SpacingY = 1\
  2665. \
  2666. OnDraw = function(self, x, y)\
  2667.         if self.NeedsItemUpdate then\
  2668.                 self:UpdateItems()\
  2669.                 self.NeedsItemUpdate = false\
  2670.         end\
  2671.         Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
  2672. end\
  2673. \
  2674. local function MaxIcons(self, obj)\
  2675.         local x, y = 2, 1\
  2676.         if not obj.Height or not obj.Width then\
  2677.                 error('You must provide each object\\'s height when adding to a CollectionView.')\
  2678.         end\
  2679.         local slotHeight = obj.Height + self.SpacingY\
  2680.         local slotWidth = obj.Width + self.SpacingX\
  2681.         local maxX = math.floor((self.Width - 2) / slotWidth)\
  2682.         return x, y, maxX, slotWidth, slotHeight\
  2683. end\
  2684. \
  2685. local function IconLocation(self, obj, i)\
  2686.         local x, y, maxX, slotWidth, slotHeight = MaxIcons(self, obj)\
  2687.         local rowPos = ((i - 1) % maxX)\
  2688.         local colPos = math.ceil(i / maxX) - 1\
  2689.         x = x + (slotWidth * rowPos)\
  2690.         y = y + colPos * slotHeight\
  2691.         return x, y\
  2692. end\
  2693. \
  2694. local function AddItem(self, v, i)\
  2695.         local toggle = false\
  2696.         if not self.CanSelect then\
  2697.                 toggle = nil\
  2698.         end\
  2699.         local x, y = IconLocation(self, v, i)\
  2700.         local item = {\
  2701.                 [\"X\"]=x,\
  2702.                 [\"Y\"]=y,\
  2703.                 [\"Name\"]=\"CollectionViewItem\",\
  2704.                 [\"Type\"]=\"View\",\
  2705.                 [\"TextColour\"]=self.TextColour,\
  2706.                 [\"BackgroundColour\"]=0F,\
  2707.                 OnClick = function(itm)\
  2708.                         if self.CanSelect then\
  2709.                                 for i2, _v in ipairs(self.Children) do\
  2710.                                         _v.Toggle = false\
  2711.                                 end\
  2712.                                 self.Selected = itm\
  2713.                         end\
  2714.                 end\
  2715.    }\
  2716.         for k, _v in pairs(v) do\
  2717.                 item[k] = _v\
  2718.         end\
  2719.         self:AddObject(item)\
  2720. end\
  2721. \
  2722. \
  2723. UpdateItems = function(self)\
  2724.         self:RemoveAllObjects()\
  2725.         local groupMode = false\
  2726.         for k, v in pairs(self.Items) do\
  2727.                 if type(k) == 'string' then\
  2728.                         groupMode = true\
  2729.                         break\
  2730.                 end\
  2731.         end\
  2732. \
  2733.         for i, v in ipairs(self.Items) do\
  2734.                 AddItem(self, v, i)\
  2735.         end\
  2736.         self:UpdateScroll()\
  2737. end\
  2738. \
  2739. OnUpdate = function(self, value)\
  2740.         if value == 'Items' then\
  2741.                 self.NeedsItemUpdate = true\
  2742.         end\
  2743. end\
  2744. ]],\
  2745. [\"ImageView\"] = [[\
  2746. Image = false\
  2747. \
  2748. OnDraw = function(self, x, y)\
  2749.         Drawing.DrawImage(x, y, self.Image, self.Width, self.Height)\
  2750. end\
  2751. \
  2752. OnLoad = function(self)\
  2753.         if self.Path and fs.exists(self.Path) then\
  2754.                 self.Image = Drawing.LoadImage(self.Path)\
  2755.         end\
  2756. end\
  2757. \
  2758. OnUpdate = function(self, value)\
  2759.         if value == 'Path' then\
  2760.                 if self.Path and fs.exists(self.Path) then\
  2761.                         self.Image = Drawing.LoadImage(self.Path)\
  2762.                 end\
  2763.         end\
  2764. end\
  2765. ]],\
  2766. [\"Label\"] = [[\
  2767. TextColour = colours.black\
  2768. BackgroundColour = colours.transparent\
  2769. Text = \"\"\
  2770. AutoWidth = false\
  2771. Align = 'Left'\
  2772. \
  2773. local wrapText = function(text, maxWidth)\
  2774.    local lines = {''}\
  2775.    for word, space in text:gmatch('(%S+)(%s*)') do\
  2776.        local temp = lines[#lines] .. word .. space:gsub('\\n','')\
  2777.        if #temp > maxWidth then\
  2778.            table.insert(lines, '')\
  2779.        end\
  2780.        if space:find('\\n') then\
  2781.            lines[#lines] = lines[#lines] .. word\
  2782.            \
  2783.            space = space:gsub('\\n', function()\
  2784.                    table.insert(lines, '')\
  2785.                    return ''\
  2786.            end)\
  2787.        else\
  2788.            lines[#lines] = lines[#lines] .. word .. space\
  2789.        end\
  2790.    end\
  2791.    if #lines[1] == 0 then\
  2792.        table.remove(lines,1)\
  2793.    end\
  2794.    return lines\
  2795. end\
  2796. \
  2797. OnUpdate = function(self, value)\
  2798.    if value == 'Text' then\
  2799.        if self.AutoWidth then\
  2800.            self.Width = #self.Text\
  2801.        else\
  2802.            self.Height = #wrapText(self.Text, self.Width)\
  2803.        end\
  2804.    end\
  2805. end\
  2806. \
  2807. OnDraw = function(self, x, y)\
  2808.         for i, v in ipairs(wrapText(self.Text, self.Width)) do\
  2809.        local _x = 0\
  2810.        if self.Align == 'Right' then\
  2811.            _x = self.Width - #v\
  2812.        elseif self.Align == 'Center' then\
  2813.            _x = math.floor((self.Width - #v) / 2)\
  2814.        end\
  2815.                 Drawing.DrawCharacters(x + _x, y + i - 1, v, self.TextColour, self.BackgroundColour)\
  2816.         end\
  2817. end\
  2818. ]],\
  2819. [\"ListView\"] = [[\
  2820. Inherit = 'ScrollView'\
  2821. UpdateDrawBlacklist = {['NeedsItemUpdate']=true}\
  2822. \
  2823. TextColour = colours.black\
  2824. BackgroundColour = colours.white\
  2825. HeadingColour = colours.lightGrey\
  2826. SelectionBackgroundColour = colours.blue\
  2827. SelectionTextColour = colours.white\
  2828. Items = false\
  2829. CanSelect = false\
  2830. Selected = nil\
  2831. NeedsItemUpdate = false\
  2832. ItemMargin = 1\
  2833. HeadingMargin = 0\
  2834. TopMargin = 0\
  2835. \
  2836. OnDraw = function(self, x, y)\
  2837.         if self.NeedsItemUpdate then\
  2838.                 self:UpdateItems()\
  2839.         end\
  2840.         Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
  2841. end\
  2842. \
  2843. local function AddItem(self, v, x, y, group)\
  2844.         local toggle = false\
  2845.         if not self.CanSelect then\
  2846.                 toggle = nil\
  2847.         elseif v.Selected then\
  2848.                 toggle = true\
  2849.         end\
  2850.         local item = {\
  2851.                 [\"Width\"]=self.Width,\
  2852.                 [\"X\"]=x,\
  2853.                 [\"Y\"]=y,\
  2854.                 [\"Name\"]=\"ListViewItem\",\
  2855.                 [\"Type\"]=\"Button\",\
  2856.                 [\"TextColour\"]=self.TextColour,\
  2857.                 [\"BackgroundColour\"]=0,\
  2858.                 [\"ActiveTextColour\"]=self.SelectionTextColour,\
  2859.                 [\"ActiveBackgroundColour\"]=self.SelectionBackgroundColour,\
  2860.                 [\"Align\"]='Left',\
  2861.                 [\"Toggle\"]=toggle,\
  2862.                 [\"Group\"]=group,\
  2863.                 OnClick = function(itm)\
  2864.                         if self.CanSelect then\
  2865.                                 self:SelectItem(itm)\
  2866.                         elseif self.OnSelect then\
  2867.                                 self:OnSelect(itm.Text)\
  2868.                         end\
  2869.                 end\
  2870.    }\
  2871.    if type(v) == 'table' then\
  2872.         for k, _v in pairs(v) do\
  2873.                 item[k] = _v\
  2874.         end\
  2875.    else\
  2876.                 item.Text = v\
  2877.    end\
  2878.         \
  2879.         local itm = self:AddObject(item)\
  2880.         if v.Selected then\
  2881.                 self:SelectItem(itm)\
  2882.         end\
  2883. end\
  2884. \
  2885. UpdateItems = function(self)\
  2886.         if not self.Items or type(self.Items) ~= 'table' then\
  2887.                 self.Items = {}\
  2888.         end\
  2889.         self.Selected = nil\
  2890.         self:RemoveAllObjects()\
  2891.         local groupMode = false\
  2892.         for k, v in pairs(self.Items) do\
  2893.                 if type(k) == 'string' then\
  2894.                         groupMode = true\
  2895.                         break\
  2896.                 end\
  2897.         end\
  2898. \
  2899.         if not groupMode then\
  2900.                 for i, v in ipairs(self.Items) do\
  2901.                         AddItem(self, v, self.ItemMargin, i)\
  2902.                 end\
  2903.         else\
  2904.                 local y = self.TopMargin\
  2905.                 for k, v in pairs(self.Items) do\
  2906.                         y = y + 1\
  2907.                         AddItem(self, {Text = k, TextColour = self.HeadingColour, IgnoreClick = true}, self.HeadingMargin, y)\
  2908.                         for i, _v in ipairs(v) do\
  2909.                                 y = y + 1\
  2910.                                 AddItem(self, _v, 1, y, k)\
  2911.                         end\
  2912.                         y = y + 1\
  2913.                 end\
  2914.         end\
  2915.         self:UpdateScroll()\
  2916.         self.NeedsItemUpdate = false\
  2917. end\
  2918. \
  2919. OnKeyChar = function(self, event, keychar)\
  2920.         if keychar == keys.up or keychar == keys.down then\
  2921.                 local n = self:GetIndex(self.Selected)\
  2922.                 if keychar == keys.up then\
  2923.                         n = n - 1\
  2924.                 else\
  2925.                         n = n + 1\
  2926.                 end\
  2927.                 local new = self:GetNth(n)\
  2928.                 if new then\
  2929.                         self:SelectItem(new)\
  2930.                 end\
  2931.         elseif keychar == keys.enter and self.Selected then\
  2932.                 self.Selected:Click('mouse_click', 1, 1, 1)\
  2933.         end\
  2934. end\
  2935. \
  2936. --returns the index/'n' of the given item\
  2937. GetIndex = function(self, obj)\
  2938.         local n = 1\
  2939.         for i, v in ipairs(self.Children) do\
  2940.                 if not v.IgnoreClick then\
  2941.                         if obj == v then\
  2942.                                 return n\
  2943.                         end\
  2944.                         n = n + 1\
  2945.                 end\
  2946.         end\
  2947. end\
  2948. \
  2949. --gets the 'nth' list item (does not include headings)\
  2950. GetNth = function(self, n)\
  2951.         local _n = 1\
  2952.         for i, v in ipairs(self.Children) do\
  2953.                 if not v.IgnoreClick then\
  2954.                         if n == _n then\
  2955.                                 return v\
  2956.                         end\
  2957.                         _n = _n + 1\
  2958.                 end\
  2959.         end\
  2960. end\
  2961. \
  2962. SelectItem = function(self, item)\
  2963.         for i, v in ipairs(self.Children) do\
  2964.                 v.Toggle = false\
  2965.         end\
  2966.         self.Selected = item\
  2967.         item.Toggle = true\
  2968.         if self.OnSelect then\
  2969.                 self:OnSelect(item.Text)\
  2970.         end\
  2971. end\
  2972. \
  2973. OnUpdate = function(self, value)\
  2974.         if value == 'Items' then\
  2975.                 self.NeedsItemUpdate = true\
  2976.         end\
  2977. end\
  2978. ]],\
  2979. [\"Menu\"] = [[\
  2980. Inherit = 'View'\
  2981. \
  2982. TextColour = colours.black\
  2983. BackgroundColour = colours.white\
  2984. HideTop = false\
  2985. \
  2986. OnDraw = function(self, x, y)\
  2987.         Drawing.IgnoreConstraint = true\
  2988.         Drawing.DrawBlankArea(x + 1, y + (self.HideTop and 0 or 1), self.Width, self.Height + (self.HideTop and 1 or 0), colours.grey)\
  2989.         Drawing.IgnoreConstraint = false\
  2990.         Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
  2991. end\
  2992. \
  2993. OnLoad = function(self)\
  2994.         local owner = self.Owner\
  2995.         if type(owner) == 'string' then\
  2996.                 owner = self.Bedrock:GetObject(self.Owner)\
  2997.         end\
  2998. \
  2999.         if owner then\
  3000.                 if self.X == 0 and self.Y == 0 then\
  3001.                         local pos = owner:GetPosition()\
  3002.                         self.X = pos.X\
  3003.                         self.Y = pos.Y + owner.Height\
  3004.                 end\
  3005.                 self.Owner = owner\
  3006.         else\
  3007.                 self.Owner = nil\
  3008.         end\
  3009. end\
  3010. \
  3011. OnUpdate = function(self, value)\
  3012.         if value == 'Children' then\
  3013.                 self.Width = self.Bedrock.Helpers.LongestString(self.Children, 'Text') + 2\
  3014.                 self.Height = #self.Children + 1 + (self.HideTop and 0 or 1)\
  3015.                 if not self.BaseY then\
  3016.                         self.BaseY = self.Y\
  3017.                 end\
  3018. \
  3019.                 for i, v in ipairs(self.Children) do\
  3020.                         if v.TextColour then\
  3021.                                 v.TextColour = self.TextColour\
  3022.                         end\
  3023.                         if v.BackgroundColour then\
  3024.                                 v.BackgroundColour = colours.transparent\
  3025.                         end\
  3026.                         if v.Colour then\
  3027.                                 v.Colour = colours.lightGrey\
  3028.                         end\
  3029.                         v.Align = 'Left'\
  3030.                         v.X = 1\
  3031.                         v.Y = i + (self.HideTop and 0 or 1)\
  3032.                         v.Width = self.Width\
  3033.                         v.Height = 1\
  3034.                 end\
  3035. \
  3036.                 self.Y = self.BaseY\
  3037.                 local pos = self:GetPosition()\
  3038.                 if pos.Y + self.Height + 1 > Drawing.Screen.Height then\
  3039.                         self.Y = self.BaseY - ((self.Height +  pos.Y) - Drawing.Screen.Height)\
  3040.                 end\
  3041.                 \
  3042.                 if pos.X + self.Width > Drawing.Screen.Width then\
  3043.                         self.X = Drawing.Screen.Width - self.Width\
  3044.                 end\
  3045.         end\
  3046. end\
  3047. \
  3048. Close = function(self, isBedrockCall)\
  3049.         self.Bedrock.Menu = nil\
  3050.         self.Parent:RemoveObject(self)\
  3051.         if self.Owner and self.Owner.Toggle then\
  3052.                 self.Owner.Toggle = false\
  3053.         end\
  3054.         self.Parent:ForceDraw()\
  3055.         self = nil\
  3056. end\
  3057. \
  3058. OnChildClick = function(self, child, event, side, x, y)\
  3059.         self:Close()\
  3060. end\
  3061. ]],\
  3062. [\"ProgressBar\"] = [[\
  3063. BackgroundColour = colours.lightGrey\
  3064. BarColour = colours.blue\
  3065. TextColour = colours.white\
  3066. ShowText = false\
  3067. Value = 0\
  3068. Maximum = 1\
  3069. Indeterminate = false\
  3070. AnimationStep = 0\
  3071. \
  3072. OnDraw = function(self, x, y)\
  3073.         Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
  3074. \
  3075.         -- if self.Indeterminate then\
  3076.         --      for i = 1, self.Width do\
  3077.         --              local s = x + i - 1 + self.AnimationStep\
  3078.         --              if s % 4 == 1 or s % 4 == 2 then\
  3079.         --                      Drawing.DrawBlankArea(s, y, 1, self.Height, self.BarColour)\
  3080.         --              end\
  3081.         --      end\
  3082.         --      self.AnimationStep = self.AnimationStep + 1\
  3083.         --      if self.AnimationStep >= 4 then\
  3084.         --              self.AnimationStep = 0\
  3085.         --      end\
  3086.         --      self.Bedrock:StartTimer(function()\
  3087.         --              self:Draw()\
  3088.         --      end, 0.25)\
  3089.         -- else\
  3090.                 local values = self.Value\
  3091.                 local barColours = self.BarColour\
  3092.                 if type(values) == 'number' then\
  3093.                         values = {values}\
  3094.                 end\
  3095.                 if type(barColours) == 'number' then\
  3096.                         barColours = {barColours}\
  3097.                 end\
  3098.                 local total = 0\
  3099.                 local _x = x\
  3100.                 for i, v in ipairs(values) do\
  3101.                         local width = self.Bedrock.Helpers.Round((v / self.Maximum) * self.Width)\
  3102.                         total = total + v\
  3103.                         Drawing.DrawBlankArea(_x, y, width, self.Height, barColours[((i-1)%#barColours)+1])\
  3104.                         _x = _x + width\
  3105.                 end\
  3106. \
  3107.                 if self.ShowText then\
  3108.                         local text = self.Bedrock.Helpers.Round((total / self.Maximum) * 100) .. '%'\
  3109.                         Drawing.DrawCharactersCenter(x, y, self.Width, self.Height, text, self.TextColour, colours.transparent)\
  3110.                 end\
  3111.         -- end\
  3112. end\
  3113. ]],\
  3114. [\"ScrollBar\"] = [[\
  3115. BackgroundColour = colours.lightGrey\
  3116. BarColour = colours.lightBlue\
  3117. Scroll = 0\
  3118. MaxScroll = 0\
  3119. ClickPoint = nil\
  3120. Fixed = true\
  3121. \
  3122. OnUpdate = function(self, value)\
  3123.         if value == 'Text' and self.AutoWidth then\
  3124.                 self.Width = #self.Text + 2\
  3125.         end\
  3126. end\
  3127. \
  3128. OnDraw = function(self, x, y)\
  3129.         local barHeight = self.Height * (self.Height / (self.Height + self.MaxScroll))\
  3130.    if barHeight < 3 then\
  3131.      barHeight = 3\
  3132.    end\
  3133.    local percentage = (self.Scroll/self.MaxScroll)\
  3134. \
  3135.    Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
  3136.    Drawing.DrawBlankArea(x, y + math.ceil(self.Height*percentage - barHeight*percentage), self.Width, barHeight, self.BarColour)\
  3137. end\
  3138. \
  3139. OnScroll = function(self, event, direction, x, y)\
  3140.         if event == 'mouse_scroll' then\
  3141.                 direction = self.Bedrock.Helpers.Round(direction * 3)\
  3142.         end\
  3143.         if self.Scroll < 0 or self.Scroll > self.MaxScroll then\
  3144.                 return false\
  3145.         end\
  3146.         local old = self.Scroll\
  3147.         self.Scroll = self.Bedrock.Helpers.Round(self.Scroll + direction)\
  3148.         if self.Scroll < 0 then\
  3149.                 self.Scroll = 0\
  3150.         elseif self.Scroll > self.MaxScroll then\
  3151.                 self.Scroll = self.MaxScroll\
  3152.         end\
  3153. \
  3154.         if self.Scroll ~= old and self.OnChange then\
  3155.                 self:OnChange()\
  3156.         end\
  3157. end\
  3158. \
  3159. OnClick = function(self, event, side, x, y)\
  3160.         if event == 'mouse_click' then\
  3161.                 self.ClickPoint = y\
  3162.         else\
  3163.                 local gapHeight = self.Height - (self.Height * (self.Height / (self.Height + self.MaxScroll)))\
  3164.                 local barHeight = self.Height * (self.Height / (self.Height + self.MaxScroll))\
  3165.                 --local delta = (self.Height + self.MaxScroll) * ((y - self.ClickPoint) / barHeight)\
  3166.                 local delta = ((y - self.ClickPoint)/gapHeight)*self.MaxScroll\
  3167.                 --l(((y - self.ClickPoint)/gapHeight))\
  3168.                 --l(delta)\
  3169.                 self.Scroll = self.Bedrock.Helpers.Round(delta)\
  3170.                 --l(self.Scroll)\
  3171.                 --l('----')\
  3172.                 if self.Scroll < 0 then\
  3173.                         self.Scroll = 0\
  3174.                 elseif self.Scroll > self.MaxScroll then\
  3175.                         self.Scroll = self.MaxScroll\
  3176.                 end\
  3177.                 if self.OnChange then\
  3178.                         self:OnChange()\
  3179.                 end\
  3180.         end\
  3181. \
  3182.         local relScroll = self.MaxScroll * ((y-1)/self.Height)\
  3183.         if y == self.Height then\
  3184.                 relScroll = self.MaxScroll\
  3185.         end\
  3186.         self.Scroll = self.Bedrock.Helpers.Round(relScroll)\
  3187. \
  3188. \
  3189. end\
  3190. \
  3191. OnDrag = OnClick\
  3192. ]],\
  3193. [\"ScrollView\"] = [[\
  3194. Inherit = 'View'\
  3195. ChildOffset = false\
  3196. ContentWidth = 0\
  3197. ContentHeight = 0\
  3198. \
  3199. CalculateContentSize = function(self)\
  3200.         local function calculateObject(obj)\
  3201.                 local pos = obj:GetPosition()\
  3202.                 local x2 = pos.X + obj.Width - 1\
  3203.                 local y2 = pos.Y + obj.Height - 1\
  3204.                 if obj.Children then\
  3205.                         for i, child in ipairs(obj.Children) do\
  3206.                                 local _x2, _y2 = calculateObject(child)\
  3207.                                 if _x2 > x2 then\
  3208.                                         x2 = _x2\
  3209.                                 end\
  3210.                                 if _y2 > y2 then\
  3211.                                         y2 = _y2\
  3212.                                 end\
  3213.                         end\
  3214.                 end\
  3215.                 return x2, y2\
  3216.         end\
  3217. \
  3218.         local pos = self:GetPosition()\
  3219.         local x2, y2 = calculateObject(self)\
  3220.         self.ContentWidth = x2 - pos.X + 1\
  3221.         self.ContentHeight = y2 - pos.Y + 1\
  3222. end\
  3223. \
  3224. UpdateScroll = function(self)\
  3225.         self.ChildOffset.Y = 0\
  3226.         self:CalculateContentSize()\
  3227.         if self.ContentHeight > self.Height then\
  3228.                 if not self:GetObject('ScrollViewScrollBar') then\
  3229.                         local _scrollBar = self:AddObject({\
  3230.                                 [\"Name\"] = 'ScrollViewScrollBar',\
  3231.                                 [\"Type\"] = 'ScrollBar',\
  3232.                                 [\"X\"] = self.Width,\
  3233.                                 [\"Y\"] = 1,\
  3234.                                 [\"Width\"] = 1,\
  3235.                                 [\"Height\"] = self.Height,\
  3236.                                 [\"Z\"]=999\
  3237.                         })\
  3238. \
  3239.                         _scrollBar.OnChange = function(scrollBar)\
  3240.                                 self.ChildOffset.Y = -scrollBar.Scroll\
  3241.                                 for i, child in ipairs(self.Children) do\
  3242.                                         child:ForceDraw()\
  3243.                                 end\
  3244.                         end\
  3245.                 end\
  3246.                 self:GetObject('ScrollViewScrollBar').MaxScroll = self.ContentHeight - self.Height\
  3247.         else\
  3248.                 self:RemoveObject('ScrollViewScrollBar')\
  3249.         end\
  3250. end\
  3251. \
  3252. OnScroll = function(self, event, direction, x, y)\
  3253.         if self:GetObject('ScrollViewScrollBar') then\
  3254.                 self:GetObject('ScrollViewScrollBar'):OnScroll(event, direction, x, y)\
  3255.         end\
  3256. end\
  3257. \
  3258. OnLoad = function(self)\
  3259.         if not self.ChildOffset or not self.ChildOffset.X or not self.ChildOffset.Y then\
  3260.                 self.ChildOffset = {X = 0, Y = 0}\
  3261.         end\
  3262. end\
  3263. ]],\
  3264. [\"SecureTextBox\"] = [[\
  3265. Inherit = 'TextBox'\
  3266. MaskCharacter = '*'\
  3267. \
  3268. OnDraw = function(self, x, y)\
  3269.         Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
  3270.         if self.CursorPos > #self.Text then\
  3271.                 self.CursorPos = #self.Text\
  3272.         elseif self.CursorPos < 0 then\
  3273.                 self.CursorPos = 0\
  3274.         end\
  3275.         local text = ''\
  3276. \
  3277.         for i = 1, #self.Text do\
  3278.                 text = text .. self.MaskCharacter\
  3279.         end\
  3280. \
  3281.         if self.Bedrock:GetActiveObject() == self then\
  3282.                 if #text > (self.Width - 2) then\
  3283.                         text = text:sub(#text-(self.Width - 3))\
  3284.                         self.Bedrock.CursorPos = {x + 1 + self.Width-2, y}\
  3285.                 else\
  3286.                         self.Bedrock.CursorPos = {x + 1 + self.CursorPos, y}\
  3287.                 end\
  3288.                 self.Bedrock.CursorColour = self.TextColour\
  3289.         end\
  3290. \
  3291.         if #tostring(text) == 0 then\
  3292.                 Drawing.DrawCharacters(x + 1, y, self.Placeholder, self.PlaceholderTextColour, self.BackgroundColour)\
  3293.         else\
  3294.                 if not self.Selected then\
  3295.                         Drawing.DrawCharacters(x + 1, y, text, self.TextColour, self.BackgroundColour)\
  3296.                 else\
  3297.                         for i = 1, #text do\
  3298.                                 local char = text:sub(i, i)\
  3299.                                 local textColour = self.TextColour\
  3300.                                 local backgroundColour = self.BackgroundColour\
  3301.                                 if i > self.DragStart and i - 1 <= self.CursorPos then\
  3302.                                         textColour = self.SelectedTextColour\
  3303.                                         backgroundColour = self.SelectedBackgroundColour\
  3304.                                 end\
  3305.                                 Drawing.DrawCharacters(x + i, y, char, textColour, backgroundColour)\
  3306.                         end\
  3307.                 end\
  3308.         end\
  3309. end\
  3310. ]],\
  3311. [\"Separator\"] = [[\
  3312. Colour = colours.grey\
  3313. \
  3314. OnDraw = function(self, x, y)\
  3315.         local char = \"|\"\
  3316.         if self.Width > self.Height then\
  3317.                 char = '-'\
  3318.         end\
  3319.         Drawing.DrawArea(x, y, self.Width, self.Height, char, self.Colour, colours.transparent)\
  3320. end\
  3321. ]],\
  3322. [\"TextBox\"] = [[\
  3323. BackgroundColour = colours.lightGrey\
  3324. SelectedBackgroundColour = colours.blue\
  3325. SelectedTextColour = colours.white\
  3326. TextColour = colours.black\
  3327. PlaceholderTextColour = colours.grey\
  3328. Placeholder = ''\
  3329. AutoWidth = false\
  3330. Text = \"\"\
  3331. CursorPos = nil\
  3332. Numerical = false\
  3333. DragStart = nil\
  3334. Selected = false\
  3335. SelectOnClick = false\
  3336. ActualDragStart = nil\
  3337. \
  3338. OnDraw = function(self, x, y)\
  3339.         Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
  3340.         if self.CursorPos > #self.Text then\
  3341.                 self.CursorPos = #self.Text\
  3342.         elseif self.CursorPos < 0 then\
  3343.                 self.CursorPos = 0\
  3344.         end\
  3345.         local text = self.Text\
  3346.         local offset = self:TextOffset()\
  3347.         if #text > (self.Width - 2) then\
  3348.                 text = text:sub(offset+1, offset + self.Width - 2)\
  3349.                 -- self.Bedrock.CursorPos = {x + 1 + self.Width-2, y}\
  3350.         -- else\
  3351.         end\
  3352.         if self.Bedrock:GetActiveObject() == self then\
  3353.                 self.Bedrock.CursorPos = {x + 1 + self.CursorPos - offset, y}\
  3354.                 self.Bedrock.CursorColour = self.TextColour\
  3355.         else\
  3356.                 self.Selected = false\
  3357.         end\
  3358. \
  3359.         if #tostring(text) == 0 then\
  3360.                 Drawing.DrawCharacters(x + 1, y, self.Placeholder, self.PlaceholderTextColour, self.BackgroundColour)\
  3361.         else\
  3362.                 if not self.Selected then\
  3363.                         Drawing.DrawCharacters(x + 1, y, text, self.TextColour, self.BackgroundColour)\
  3364.                 else\
  3365.                         local startPos = self.DragStart - offset\
  3366.                         local endPos = self.CursorPos - offset\
  3367.                         if startPos > endPos then\
  3368.                                 startPos = self.CursorPos - offset\
  3369.                                 endPos = self.DragStart - offset\
  3370.                         end\
  3371.                         for i = 1, #text do\
  3372.                                 local char = text:sub(i, i)\
  3373.                                 local textColour = self.TextColour\
  3374.                                 local backgroundColour = self.BackgroundColour\
  3375. \
  3376.                                 if i > startPos and i - 1 <= endPos then\
  3377.                                         textColour = self.SelectedTextColour\
  3378.                                         backgroundColour = self.SelectedBackgroundColour\
  3379.                                 end\
  3380.                                 Drawing.DrawCharacters(x + i, y, char, textColour, backgroundColour)\
  3381.                         end\
  3382.                 end\
  3383.         end\
  3384. end\
  3385. \
  3386. TextOffset = function(self)\
  3387.         if #self.Text < (self.Width - 2) then\
  3388.                 return 0\
  3389.         elseif self.Bedrock:GetActiveObject() ~= self then\
  3390.                 return 0\
  3391.         else\
  3392.                 local textWidth = (self.Width - 2)\
  3393.                 local offset = self.CursorPos - textWidth\
  3394.                 if offset < 0 then\
  3395.                         offset = 0\
  3396.                 end\
  3397.                 return offset\
  3398.         end\
  3399. end\
  3400. \
  3401. OnLoad = function(self)\
  3402.         if not self.CursorPos then\
  3403.                 self.CursorPos = #self.Text\
  3404.         end\
  3405. end\
  3406. \
  3407. OnClick = function(self, event, side, x, y)\
  3408.         if self.Bedrock:GetActiveObject() ~= self and self.SelectOnClick then\
  3409.                 self.CursorPos = #self.Text - 1\
  3410.                 self.DragStart = 0\
  3411.                 self.ActualDragStart = x - 2 + self:TextOffset()\
  3412.                 self.Selected = true\
  3413.         else\
  3414.                 self.CursorPos = x - 2 + self:TextOffset()\
  3415.                 self.DragStart = self.CursorPos\
  3416.                 self.Selected = false\
  3417.         end\
  3418.         self.Bedrock:SetActiveObject(self)\
  3419. end\
  3420. \
  3421. OnDrag = function(self, event, side, x, y)\
  3422.         self.CursorPos = x - 2 + self:TextOffset()\
  3423.         if self.ActualDragStart then\
  3424.                 self.DragStart = self.ActualDragStart\
  3425.                 self.ActualDragStart = nil\
  3426.         end\
  3427.         if self.DragStart then\
  3428.                 self.Selected = true\
  3429.         end\
  3430. end\
  3431. \
  3432. OnKeyChar = function(self, event, keychar)\
  3433.         local deleteSelected = function()\
  3434.                 if self.Selected then\
  3435.                         local startPos = self.DragStart\
  3436.                         local endPos = self.CursorPos\
  3437.                         if startPos > endPos then\
  3438.                                 startPos = self.CursorPos\
  3439.                                 endPos = self.DragStart\
  3440.                         end\
  3441.                         self.Text = self.Text:sub(1, startPos) .. self.Text:sub(endPos + 2)\
  3442.                         self.CursorPos = startPos\
  3443.                         self.DragStart = nil\
  3444.                         self.Selected = false\
  3445.                         return true\
  3446.                 end\
  3447.         end\
  3448. \
  3449.         if event == 'char' then\
  3450.                 deleteSelected()\
  3451.                 if self.Numerical then\
  3452.                         keychar = tostring(tonumber(keychar))\
  3453.                 end\
  3454.                 if keychar == 'nil' then\
  3455.                         return\
  3456.                 end\
  3457.                 self.Text = string.sub(self.Text, 1, self.CursorPos ) .. keychar .. string.sub( self.Text, self.CursorPos + 1 )\
  3458.                 if self.Numerical then\
  3459.                         self.Text = tostring(tonumber(self.Text))\
  3460.                         if self.Text == 'nil' then\
  3461.                                 self.Text = '1'\
  3462.                         end\
  3463.                 end\
  3464.                 \
  3465.                 self.CursorPos = self.CursorPos + 1\
  3466.                 if self.OnChange then\
  3467.                         self:OnChange(event, keychar)\
  3468.                 end\
  3469.                 return false\
  3470.         elseif event == 'key' then\
  3471.                 if keychar == keys.enter then\
  3472.                         if self.OnChange then\
  3473.                                 self:OnChange(event, keychar)\
  3474.                         end\
  3475.                 elseif keychar == keys.left then\
  3476.                         -- Left\
  3477.                         if self.CursorPos > 0 then\
  3478.                                 if self.Selected then\
  3479.                                         self.CursorPos = self.DragStart\
  3480.                                         self.DragStart = nil\
  3481.                                         self.Selected = false\
  3482.                                 else\
  3483.                                         self.CursorPos = self.CursorPos - 1\
  3484.                                 end\
  3485.                                 if self.OnChange then\
  3486.                                         self:OnChange(event, keychar)\
  3487.                                 end\
  3488.                         end\
  3489.                         \
  3490.                 elseif keychar == keys.right then\
  3491.                         -- Right                                \
  3492.                         if self.CursorPos < string.len(self.Text) then\
  3493.                                 if self.Selected then\
  3494.                                         self.CursorPos = self.CursorPos\
  3495.                                         self.DragStart = nil\
  3496.                                         self.Selected = false\
  3497.                                 else\
  3498.                                         self.CursorPos = self.CursorPos + 1\
  3499.                                 end\
  3500.                                 if self.OnChange then\
  3501.                                         self:OnChange(event, keychar)\
  3502.                                 end\
  3503.                         end\
  3504.                 \
  3505.                 elseif keychar == keys.backspace then\
  3506.                         -- Backspace\
  3507.                         if not deleteSelected() and self.CursorPos > 0 then\
  3508.                                 self.Text = string.sub( self.Text, 1, self.CursorPos - 1 ) .. string.sub( self.Text, self.CursorPos + 1 )\
  3509.                                 self.CursorPos = self.CursorPos - 1                                     \
  3510.                                 if self.Numerical then\
  3511.                                         self.Text = tostring(tonumber(self.Text))\
  3512.                                         if self.Text == 'nil' then\
  3513.                                                 self.Text = '1'\
  3514.                                         end\
  3515.                                 end\
  3516.                                 if self.OnChange then\
  3517.                                         self:OnChange(event, keychar)\
  3518.                                 end\
  3519.                         end\
  3520.                 elseif keychar == keys.home then\
  3521.                         -- Home\
  3522.                         self.CursorPos = 0\
  3523.                         if self.OnChange then\
  3524.                                 self:OnChange(event, keychar)\
  3525.                         end\
  3526.                 elseif keychar == keys.delete then\
  3527.                         if not deleteSelected() and self.CursorPos < string.len(self.Text) then\
  3528.                                 self.Text = string.sub( self.Text, 1, self.CursorPos ) .. string.sub( self.Text, self.CursorPos + 2 )           \
  3529.                                 if self.Numerical then\
  3530.                                         self.Text = tostring(tonumber(self.Text))\
  3531.                                         if self.Text == 'nil' then\
  3532.                                                 self.Text = '1'\
  3533.                                         end\
  3534.                                 end\
  3535.                                 if self.OnChange then\
  3536.                                         self:OnChange(keychar)\
  3537.                                 end\
  3538.                         end\
  3539.                 elseif keychar == keys[\"end\"] then\
  3540.                         -- End\
  3541.                         self.CursorPos = string.len(self.Text)\
  3542.                 else\
  3543.                         if self.OnChange then\
  3544.                                 self:OnChange(event, keychar)\
  3545.                         end\
  3546.                         return false\
  3547.                 end\
  3548.         end\
  3549. end\
  3550. ]],\
  3551. [\"View\"] = [[\
  3552. BackgroundColour = colours.transparent\
  3553. Children = {}\
  3554. \
  3555. OnDraw = function(self, x, y)\
  3556.         if self.BackgroundColour then\
  3557.                 Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
  3558.         end\
  3559. end\
  3560. \
  3561. OnInitialise = function(self)\
  3562.         self.Children = {}\
  3563. end\
  3564. \
  3565. InitialiseFile = function(self, bedrock, file, name)\
  3566.         local _new = {}\
  3567.         _new.X = 1\
  3568.         _new.Y = 1\
  3569.         _new.Width = Drawing.Screen.Width\
  3570.         _new.Height = Drawing.Screen.Height\
  3571.         _new.BackgroundColour = file.BackgroundColour\
  3572.         _new.Name = name\
  3573.         _new.Children = {}\
  3574.         _new.Bedrock = bedrock\
  3575.         local new = self:Initialise(_new)\
  3576.         for i, obj in ipairs(file.Children) do\
  3577.                 local view = bedrock:ObjectFromFile(obj, new)\
  3578.                 if not view.Z then\
  3579.                         view.Z = i\
  3580.                 end\
  3581.                 view.Parent = new\
  3582.                 table.insert(new.Children, view)\
  3583.         end\
  3584.         return new\
  3585. end\
  3586. \
  3587. function CheckClick(self, object, x, y)\
  3588.         local offset = {X = 0, Y = 0}\
  3589.         if not object.Fixed and self.ChildOffset then\
  3590.                 offset = self.ChildOffset\
  3591.         end\
  3592.         if object.X + offset.X <= x and object.Y + offset.Y <= y and  object.X + offset.X + object.Width > x and object.Y + offset.Y + object.Height > y then\
  3593.                 return true\
  3594.         end\
  3595. end\
  3596. \
  3597. function DoClick(self, object, event, side, x, y)\
  3598.         if object then\
  3599.                 if self:CheckClick(object, x, y) then\
  3600.                         local offset = {X = 0, Y = 0}\
  3601.                         if not object.Fixed and self.ChildOffset then\
  3602.                                 offset = self.ChildOffset\
  3603.                         end\
  3604.                         return object:Click(event, side, x - object.X - offset.X + 1, y - object.Y + 1 - offset.Y)\
  3605.                 end\
  3606.         end     \
  3607. end\
  3608. \
  3609. Click = function(self, event, side, x, y, z)\
  3610.         if self.Visible and not self.IgnoreClick then\
  3611.                 for i = #self.Children, 1, -1 do --children are ordered from smallest Z to highest, so this is done in reverse\
  3612.                         local child = self.Children[i]\
  3613.                         if self:DoClick(child, event, side, x, y) then\
  3614.                                 if self.OnChildClick then\
  3615.                                         self:OnChildClick(child, event, side, x, y)\
  3616.                                 end\
  3617.                                 return true\
  3618.                         end\
  3619.                 end\
  3620.                 if event == 'mouse_click' and self.OnClick and self:OnClick(event, side, x, y) ~= false then\
  3621.                         return true\
  3622.                 elseif event == 'mouse_drag' and self.OnDrag and self:OnDrag(event, side, x, y) ~= false then\
  3623.                         return true\
  3624.                 elseif event == 'mouse_scroll' and self.OnScroll and self:OnScroll(event, side, x, y) ~= false then\
  3625.                         return true\
  3626.                 else\
  3627.                         return false\
  3628.                 end\
  3629.         else\
  3630.                 return false\
  3631.         end\
  3632. end\
  3633. \
  3634. OnRemove = function(self)\
  3635.         if self == self.Bedrock:GetActiveObject() then\
  3636.                 self.Bedrock:SetActiveObject()\
  3637.         end\
  3638.         for i, child in ipairs(self.Children) do\
  3639.                 child:OnRemove()\
  3640.         end\
  3641. end\
  3642. \
  3643. local function findObjectNamed(view, name, minI)\
  3644.         local minI = minI or 0\
  3645.         if view and view.Children then\
  3646.                 for i, child in ipairs(view.Children) do\
  3647.                         if child.Name == name or child == name then\
  3648.                                 return child, i, view\
  3649.                         elseif child.Children then\
  3650.                                 local found, index, foundView = findObjectNamed(child, name)\
  3651.                                 if found and minI <= index then\
  3652.                                         return found, index, foundView\
  3653.                                 end\
  3654.                         end\
  3655.                 end\
  3656.         end\
  3657. end\
  3658. \
  3659. function AddObject(self, info, extra)\
  3660.         if type(info) == 'string' then\
  3661.                 local h = fs.open(self.Bedrock.ViewPath..info..'.view', 'r')\
  3662.                 if h then\
  3663.                         info = textutils.unserialize(h.readAll())\
  3664.                         h.close()\
  3665.                 else\
  3666.                         error('Error in opening object: '..info)\
  3667.                 end\
  3668.         end\
  3669. \
  3670.         if extra then\
  3671.                 for k, v in pairs(extra) do\
  3672.                         if v then\
  3673.                                 info[k] = v\
  3674.                         end\
  3675.                 end\
  3676.         end\
  3677. \
  3678.         local view = self.Bedrock:ObjectFromFile(info, self)\
  3679.         if not view.Z then\
  3680.                 view.Z = #self.Children + 1\
  3681.         end\
  3682.         \
  3683.         table.insert(self.Children, view)\
  3684.         if self.Bedrock.View then\
  3685.                 self.Bedrock:ReorderObjects()\
  3686.         end\
  3687.         self:ForceDraw()\
  3688.         return view\
  3689. end\
  3690. \
  3691. function GetObject(self, name)\
  3692.         return findObjectNamed(self, name)\
  3693. end\
  3694. \
  3695. local function findObjects(view, name)\
  3696.         local objects = {}\
  3697.         if view and view.Children then\
  3698.                 for i, child in ipairs(view.Children) do\
  3699.                         if child.Name == name or child == name then\
  3700.                                 table.insert(objects, child)\
  3701.                         elseif child.Children then\
  3702.                                 local objs = findObjects(child, name)\
  3703.                                 if objs then\
  3704.                                         for i2, v in ipairs(objs) do\
  3705.                                                 table.insert(objects, v)\
  3706.                                         end\
  3707.                                 end\
  3708.                         end\
  3709.                 end\
  3710.         end\
  3711.         return objects\
  3712. end\
  3713. \
  3714. function GetObjects(self, name)\
  3715.         return findObjects(self, name)\
  3716. end\
  3717. \
  3718. function RemoveObject(self, name)\
  3719.         local obj, index, view = findObjectNamed(self, name, minI)\
  3720.         if index then\
  3721.                 view.Children[index]:OnRemove()\
  3722.                 table.remove(view.Children, index)\
  3723.                 if view.OnUpdate then\
  3724.                         view:OnUpdate('Children')\
  3725.                 end\
  3726.                 return true\
  3727.         end\
  3728.         return false\
  3729. end\
  3730. \
  3731. function RemoveObjects(self, name)\
  3732.         local i = 1\
  3733.         while self:RemoveObject(name) and i < 100 do\
  3734.                 i = i + 1\
  3735.         end\
  3736.         \
  3737. end\
  3738. \
  3739. function RemoveAllObjects(self)\
  3740.         for i, child in ipairs(self.Children) do\
  3741.                 child:OnRemove()\
  3742.                 self.Children[i] = nil\
  3743.         end\
  3744.         self:ForceDraw()\
  3745. end\
  3746. ]],\
  3747. [\"Window\"] = [[\
  3748. Inherit = 'View'\
  3749. \
  3750. ToolBarColour = colours.lightGrey\
  3751. ToolBarTextColour = colours.black\
  3752. ShadowColour = colours.grey\
  3753. Title = ''\
  3754. Flashing = false\
  3755. CanClose = true\
  3756. OnCloseButton = nil\
  3757. \
  3758. OnLoad = function(self)\
  3759.         --self:GetObject('View') = self.Bedrock:ObjectFromFile({Type = 'View',Width = 10, Height = 5, BackgroundColour = colours.red}, self)\
  3760. end\
  3761. \
  3762. LoadView = function(self)\
  3763.         local view = self:GetObject('View')\
  3764.         if view.ToolBarColour then\
  3765.                 window.ToolBarColour = view.ToolBarColour\
  3766.         end\
  3767.         if view.ToolBarTextColour then\
  3768.                 window.ToolBarTextColour = view.ToolBarTextColour\
  3769.         end\
  3770.         view.X = 1\
  3771.         view.Y = 2\
  3772. \
  3773.         view:ForceDraw()\
  3774.         self:OnUpdate('View')\
  3775.         if self.OnViewLoad then\
  3776.                 self.OnViewLoad(view)\
  3777.         end\
  3778.         self.Bedrock:SetActiveObject(view)\
  3779. end\
  3780. \
  3781. SetView = function(self, view)\
  3782.         self:RemoveObject('View')\
  3783.         table.insert(self.Children, view)\
  3784.         view.Parent = self\
  3785.         self:LoadView()\
  3786. end\
  3787. \
  3788. Flash = function(self)\
  3789.         self.Flashing = true\
  3790.         self:ForceDraw()\
  3791.         self.Bedrock:StartTimer(function()self.Flashing = false end, 0.4)\
  3792. end\
  3793. \
  3794. OnDraw = function(self, x, y)\
  3795.         local toolBarColour = (self.Flashing and colours.white or self.ToolBarColour)\
  3796.         local toolBarTextColour = (self.Flashing and colours.black or self.ToolBarTextColour)\
  3797.         if toolBarColour then\
  3798.                 Drawing.DrawBlankArea(x, y, self.Width, 1, toolBarColour)\
  3799.         end\
  3800.         if toolBarTextColour then\
  3801.                 local title = self.Bedrock.Helpers.TruncateString(self.Title, self.Width - 2)\
  3802.                 Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, title, toolBarTextColour, toolBarColour)\
  3803.         end\
  3804.         Drawing.IgnoreConstraint = true\
  3805.         Drawing.DrawBlankArea(x + 1, y + 1, self.Width, self.Height, self.ShadowColour)\
  3806.         Drawing.IgnoreConstraint = false\
  3807. end\
  3808. \
  3809. Close = function(self)\
  3810.         self.Bedrock.Window = nil\
  3811.         self.Bedrock:RemoveObject(self)\
  3812.         if self.OnClose then\
  3813.                 self:OnClose()\
  3814.         end\
  3815.         self = nil\
  3816. end\
  3817. \
  3818. OnUpdate = function(self, value)\
  3819.         if value == 'View' and self:GetObject('View') then\
  3820.                 self.Width = self:GetObject('View').Width\
  3821.                 self.Height = self:GetObject('View').Height + 1\
  3822.                 self.X = math.ceil((Drawing.Screen.Width - self.Width) / 2)\
  3823.                 self.Y = math.ceil((Drawing.Screen.Height - self.Height) / 2)\
  3824.         elseif value == 'CanClose' then\
  3825.                 self:RemoveObject('CloseButton')\
  3826.                 if self.CanClose then\
  3827.                         local button = self:AddObject({X = 1, Y = 1, Width = 1, Height = 1, Type = 'Button', BackgroundColour = colours.red, TextColour = colours.white, Text = 'x', Name = 'CloseButton'})\
  3828.                         button.OnClick = function(btn)\
  3829.                                 if self.OnCloseButton then\
  3830.                                         self:OnCloseButton()\
  3831.                                 end\
  3832.                                 self:Close()\
  3833.                         end\
  3834.                 end\
  3835.         end\
  3836. end\
  3837. ]],\
  3838. }\
  3839. \
  3840. BasePath = ''\
  3841. ProgramPath = nil\
  3842. \
  3843. -- Program functions...\
  3844. \
  3845. local function main(...)\
  3846.         -- Code here...\
  3847. end\
  3848. \
  3849. -- Run\
  3850. local args = {...}\
  3851. local _, err = pcall(function() main(unpack(args)) end)\
  3852. if err then\
  3853.         -- Make a nice error handling screen here...\
  3854.         term.setBackgroundColor(colors.black)\
  3855.         term.setTextColor(colors.white)\
  3856.         term.clear()\
  3857.         term.setCursorPos(1, 3)\
  3858.         print(\" An Error Has Occured! D:\\n\\n\")\
  3859.         print(\" \" .. tostring(err) .. \"\\n\\n\")\
  3860.         print(\" Press any key to exit...\")\
  3861.         os.pullEvent(\"key\")\
  3862. end\
  3863. \
  3864. \
  3865. \
  3866. function LoadAPIs(self)\
  3867.         local function loadAPI(name, content)\
  3868.                 local env = setmetatable({}, { __index = getfenv() })\
  3869.                 local func, err = loadstring(content, name..' (Bedrock API)')\
  3870.                 if not func then\
  3871.                         return false, printError(err)\
  3872.                 end\
  3873.                 setfenv(func, env)\
  3874.                 func()\
  3875.                 local api = {}\
  3876.                 for k,v in pairs(env) do\
  3877.                         api[k] = v\
  3878.                 end\
  3879.                 _G[name] = api\
  3880.                 return true\
  3881.         end\
  3882. \
  3883.         local env = getfenv()\
  3884.         local function loadObject(name, content)\
  3885.                 loadAPI(name, content)\
  3886.                 if env[name].Inherit then\
  3887.                         if not getfenv()[env[name].Inherit] then        \
  3888.                                 if objects[env[name].Inherit] then\
  3889.                                         loadObject(env[name].Inherit, objects[env[name].Inherit])\
  3890.                                 elseif fs.exists(self.ProgramPath..'/Objects/'..env[name].Inherit..'.lua') then\
  3891.                                 end\
  3892.                         end\
  3893.                         env[name].__index = getfenv()[env[name].Inherit]\
  3894.                 else\
  3895.                         env[name].__index = Object\
  3896.                 end\
  3897.                 setmetatable(env[name], env[name])\
  3898.         end\
  3899. \
  3900.         for k, v in pairs(apis) do\
  3901.                 loadAPI(k, v)\
  3902.                 if k == 'Helpers' then\
  3903.                         self.Helpers = Helpers\
  3904.                 end\
  3905.         end\
  3906. \
  3907.         for k, v in pairs(objects) do\
  3908.                 loadObject(k, v)\
  3909.         end\
  3910.         \
  3911.         local privateObjPath = self.ProgramPath..'/Objects/'\
  3912.         if fs.exists(privateObjPath) and fs.isDir(privateObjPath) then\
  3913.                 for i, v in ipairs(fs.list(privateObjPath)) do\
  3914.                         if v ~= '.DS_Store' then\
  3915.                                 local name = string.match(v, '(%a+)%.?.-')\
  3916.                                 local h = fs.open(privateObjPath..v, 'r')\
  3917.                                 loadObject(name, h.readAll())\
  3918.                                 h.close()\
  3919.                         end\
  3920.                 end\
  3921.         end\
  3922. end\
  3923. \
  3924. AllowTerminate = true\
  3925. \
  3926. View = nil\
  3927. Menu = nil\
  3928. \
  3929. ActiveObject = nil\
  3930. \
  3931. DrawTimer = nil\
  3932. DrawTimerExpiry = 0\
  3933. \
  3934. IsDrawing = false\
  3935. \
  3936. Running = true\
  3937. \
  3938. DefaultView = 'main'\
  3939. \
  3940. EventHandlers = {\
  3941.         \
  3942. }\
  3943. \
  3944. ObjectClickHandlers = {\
  3945.         \
  3946. }\
  3947. \
  3948. ObjectUpdateHandlers = {\
  3949.         \
  3950. }\
  3951. \
  3952. Timers = {\
  3953.         \
  3954. }\
  3955. \
  3956. function Initialise(self, programPath)\
  3957.         self.ProgramPath = programPath or self.ProgramPath\
  3958.         if not programPath then\
  3959.                 if self.ProgramPath then\
  3960.                         local prgPath = self.ProgramPath\
  3961.                         local prgName = fs.getName(prgPath)\
  3962.                         if prgPath:find('/') then \
  3963.                                 self.ProgramPath = prgPath:sub(1, #prgPath-#prgName-1)\
  3964.                                 self.ProgramPath = prgPath:sub(1, #prgPath-#prgName-1) \
  3965.                         else \
  3966.                                 self.ProgramPath = '' \
  3967.                         end\
  3968.                 else\
  3969.                         self.ProgramPath = ''\
  3970.                 end\
  3971.         end\
  3972.         self:LoadAPIs()\
  3973.         self.ViewPath = self.ProgramPath .. '/Views/'\
  3974.         --first, check that the barebones APIs are available\
  3975.         local requiredApis = {\
  3976.                 'Drawing',\
  3977.                 'View'\
  3978.         }\
  3979.         local env = getfenv()\
  3980.         for i,v in ipairs(requiredApis) do\
  3981.                 if not env[v] then\
  3982.                         error('The API: '..v..' is not loaded. Please make sure you load it to use Bedrock.')\
  3983.                 end\
  3984.         end\
  3985. \
  3986.         local copy = { }\
  3987.         for k, v in pairs(self) do\
  3988.                 if k ~= 'Initialise' then\
  3989.                         copy[k] = v\
  3990.                 end\
  3991.         end\
  3992.         return setmetatable(copy, getmetatable(self))\
  3993. end\
  3994. \
  3995. function HandleClick(self, event, side, x, y)\
  3996.         if self.Window then\
  3997.                 if not self.View:CheckClick(self.Window, x, y) then\
  3998.                         self.Window:Flash()\
  3999.                 else\
  4000.                         self.View:DoClick(self.Window, event, side, x, y)\
  4001.                 end\
  4002.         elseif self.Menu then\
  4003.                 if not self.View:DoClick(self.Menu, event, side, x, y) then\
  4004.                         self.Menu:Close()\
  4005.                 end\
  4006.         elseif self.View then\
  4007.                 if self.View:Click(event, side, x, y) ~= false then\
  4008.                 end             \
  4009.         end\
  4010. end\
  4011. \
  4012. function HandleKeyChar(self, event, keychar)\
  4013.         if self:GetActiveObject() then\
  4014.                 local activeObject = self:GetActiveObject()\
  4015.                 if activeObject.OnKeyChar then\
  4016.                         if activeObject:OnKeyChar(event, keychar) ~= false then\
  4017.                                 --self:Draw()\
  4018.                         end\
  4019.                 end\
  4020.         end\
  4021. end\
  4022. \
  4023. function ToggleMenu(self, name, owner, x, y)\
  4024.         if self.Menu then\
  4025.                 self.Menu:Close()\
  4026.                 return false\
  4027.         else\
  4028.                 self:SetMenu(name, owner, x, y)\
  4029.                 return true\
  4030.         end\
  4031. end\
  4032. \
  4033. function SetMenu(self, menu, owner, x, y)\
  4034.         x = x or 1\
  4035.         y = y or 1\
  4036.         if self.Menu then\
  4037.                 self.Menu:Close()\
  4038.         end     \
  4039.         if menu then\
  4040.                 local pos = owner:GetPosition()\
  4041.                 self.Menu = self:AddObject(menu, {Type = 'Menu', Owner = owner, X = pos.X + x - 1, Y = pos.Y + y})\
  4042.         end\
  4043. end\
  4044. \
  4045. function ObjectClick(self, name, func)\
  4046.         self.ObjectClickHandlers[name] = func\
  4047. end\
  4048. \
  4049. function ClickObject(self, object, event, side, x, y)\
  4050.         if self.ObjectClickHandlers[object.Name] then\
  4051.                 return self.ObjectClickHandlers[object.Name](object, event, side, x, y)\
  4052.         end\
  4053.         return false\
  4054. end\
  4055. \
  4056. function ObjectUpdate(self, name, func)\
  4057.         self.ObjectUpdateHandlers[name] = func\
  4058. end\
  4059. \
  4060. function UpdateObject(self, object, ...)\
  4061.         if self.ObjectUpdateHandlers[object.Name] then\
  4062.                 self.ObjectUpdateHandlers[object.Name](object, ...)\
  4063.                 --self:Draw()\
  4064.         end\
  4065. end\
  4066. \
  4067. function GetAbsolutePosition(self, obj)\
  4068.         if not obj.Parent then\
  4069.                 return {X = obj.X, Y = obj.Y}\
  4070.         else\
  4071.                 local pos = self:GetAbsolutePosition(obj.Parent)\
  4072.                 local x = pos.X + obj.X - 1\
  4073.                 local y = pos.Y + obj.Y - 1\
  4074.                 if not obj.Fixed and obj.Parent.ChildOffset then\
  4075.                         x = x + obj.Parent.ChildOffset.X\
  4076.                         y = y + obj.Parent.ChildOffset.Y\
  4077.                 end\
  4078.                 return {X = x, Y = y}\
  4079.         end\
  4080. end\
  4081. \
  4082. function LoadView(self, name, draw)\
  4083.         if self.View and self.OnViewClose then\
  4084.                 self.OnViewClose(self.View.Name)\
  4085.         end\
  4086.         if self.View then\
  4087.                 self.View:OnRemove()\
  4088.         end\
  4089.         local success = false\
  4090. \
  4091.         if not fs.exists(self.ViewPath..name..'.view') then\
  4092.                 error('The view: '..name..'.view does not exist.')\
  4093.         end\
  4094. \
  4095.         local h = fs.open(self.ViewPath..name..'.view', 'r')\
  4096.         if h then\
  4097.                 local view = textutils.unserialize(h.readAll())\
  4098.                 h.close()\
  4099.                 if view then\
  4100.                         self.View = View:InitialiseFile(self, view, name)\
  4101.                         self:ReorderObjects()\
  4102. \
  4103.                         if OneOS and view.ToolBarColour then\
  4104.                                 OneOS.ToolBarColour = view.ToolBarColour\
  4105.                         end\
  4106.                         if OneOS and view.ToolBarTextColour then\
  4107.                                 OneOS.ToolBarTextColour = view.ToolBarTextColour\
  4108.                         end\
  4109.                         if not self:GetActiveObject() then\
  4110.                                 self:SetActiveObject()\
  4111.                         end\
  4112.                         success = true\
  4113.                 end\
  4114.         end\
  4115. \
  4116.         if success and self.OnViewLoad then\
  4117.                 self.OnViewLoad(name)\
  4118.         end\
  4119. \
  4120.         if draw ~= false then\
  4121.                 self:Draw()\
  4122.         end\
  4123. \
  4124.         if not success then\
  4125.                 error('Failed to load view: '..name..'. It probably isn\\'t formatted correctly. Did you forget a } or ,?')\
  4126.         end\
  4127. \
  4128.         return success\
  4129. end\
  4130. \
  4131. function InheritFile(self, file, name)\
  4132.         local h = fs.open(self.ViewPath..name..'.view', 'r')\
  4133.         if h then\
  4134.                 local super = textutils.unserialize(h.readAll())\
  4135.                 if super then\
  4136.                         if type(super) ~= 'table' then\
  4137.                                 error('View: \"'..name..'.view\" is not formatted correctly.')\
  4138.                         end\
  4139. \
  4140.                         for k, v in pairs(super) do\
  4141.                                 if not file[k] then\
  4142.                                         file[k] = v\
  4143.                                 end\
  4144.                         end\
  4145.                         return file\
  4146.                 end\
  4147.         end\
  4148.         return file\
  4149. end\
  4150. \
  4151. function ParseStringSize(self, parent, k, v)\
  4152.                 local parentSize = parent.Width\
  4153.                 if k == 'Height' or k == 'Y' then\
  4154.                         parentSize = parent.Height\
  4155.                 end\
  4156.                 local parts = {v}\
  4157.                 if type(v) == 'string' and string.find(v, ',') then\
  4158.                         parts = {}\
  4159.                         for word in string.gmatch(v, '([^,]+)') do\
  4160.                             table.insert(parts, word)\
  4161.                         end\
  4162.                 end\
  4163. \
  4164.                 v = 0\
  4165.                 for i2, part in ipairs(parts) do\
  4166.                         if type(part) == 'string' and part:sub(#part) == '%' then\
  4167.                                 v = v + math.ceil(parentSize * (tonumber(part:sub(1, #part-1)) / 100))\
  4168.                         else\
  4169.                                 v = v + tonumber(part)\
  4170.                         end\
  4171.                 end\
  4172.                 return v\
  4173. end\
  4174. \
  4175. function ObjectFromFile(self, file, view)\
  4176.         local env = getfenv()\
  4177.         if env[file.Type] then\
  4178.                 if not env[file.Type].Initialise then\
  4179.                         error('Malformed Object: '..file.Type)\
  4180.                 end\
  4181.                 local object = {}\
  4182. \
  4183.                 if file.InheritView then\
  4184.                         file = self:InheritFile(file, file.InheritView)\
  4185.                 end\
  4186.                 \
  4187.                 object.AutoWidth = true\
  4188.                 for k, v in pairs(file) do\
  4189.                         if k == 'Width' or k == 'X' or k == 'Height' or k == 'Y' then\
  4190.                                 v = self:ParseStringSize(view, k, v)\
  4191.                         end\
  4192. \
  4193.                         if k == 'Width' then\
  4194.                                 object.AutoWidth = false\
  4195.                         end\
  4196.                         if k ~= 'Children' then\
  4197.                                 object[k] = v\
  4198.                         else\
  4199.                                 object[k] = {}\
  4200.                         end\
  4201.                 end\
  4202. \
  4203.                 object.Parent = view\
  4204.                 object.Bedrock = self\
  4205.                 if not object.Name then\
  4206.                         object.Name = file.Type\
  4207.                 end\
  4208. \
  4209.                 object = env[file.Type]:Initialise(object)\
  4210. \
  4211.                 if file.Children then\
  4212.                         for i, obj in ipairs(file.Children) do\
  4213.                                 local _view = self:ObjectFromFile(obj, object)\
  4214.                                 if not _view.Z then\
  4215.                                         _view.Z = i\
  4216.                                 end\
  4217.                                 _view.Parent = object\
  4218.                                 table.insert(object.Children, _view)\
  4219.                         end\
  4220.                 end\
  4221. \
  4222.                 if not object.OnClick then\
  4223.                         object.OnClick = function(...) return self:ClickObject(...) end\
  4224.                 end\
  4225.                 --object.OnUpdate = function(...) self:UpdateObject(...) end\
  4226. \
  4227.                 if object.OnUpdate then\
  4228.                         for k, v in pairs(env[file.Type]) do\
  4229.                                 object:OnUpdate(k)\
  4230.                         end\
  4231. \
  4232.                         for k, v in pairs(object.__index) do\
  4233.                                 object:OnUpdate(k)\
  4234.                         end\
  4235.                 end\
  4236. \
  4237.                 if object.Active then\
  4238.                         object.Bedrock:SetActiveObject(object)\
  4239.                 end\
  4240.                 if object.OnLoad then\
  4241.                         object:OnLoad()\
  4242.                 end\
  4243.                 return object\
  4244.         elseif not file.Type then\
  4245.                 error('No object type specified. (e.g. Type = \"Button\")')\
  4246.         else\
  4247.                 error('No Object: '..file.Type..'. The API probably isn\\'t loaded')\
  4248.         end\
  4249. end\
  4250. \
  4251. function ReorderObjects(self)\
  4252.         if self.View and self.View.Children then\
  4253.                 table.sort(self.View.Children, function(a,b)\
  4254.                         return a.Z < b.Z \
  4255.                 end)\
  4256.         end\
  4257. end\
  4258. \
  4259. function AddObject(self, info, extra)\
  4260.         return self.View:AddObject(info, extra)\
  4261. end\
  4262. \
  4263. function GetObject(self, name)\
  4264.         return self.View:GetObject(name)\
  4265. end\
  4266. \
  4267. function GetObjects(self, name)\
  4268.         return self.View:GetObjects(name)\
  4269. end\
  4270. \
  4271. function RemoveObject(self, name)\
  4272.         return self.View:RemoveObject(name)\
  4273. end\
  4274. \
  4275. function RemoveObjects(self, name)\
  4276.         return self.View:RemoveObjects(name)\
  4277. end\
  4278. \
  4279. function ForceDraw(self)\
  4280.         if not self.DrawTimer or self.DrawTimerExpiry <= os.clock() then\
  4281.                 self.DrawTimer = self:StartTimer(function()\
  4282.                         self.DrawTimer = nil\
  4283.                         self:Draw()\
  4284.                 end, 0.05)\
  4285.                 self.DrawTimerExpiry = os.clock() + 0.1\
  4286.         end\
  4287. end\
  4288. \
  4289. function DisplayWindow(self, _view, title, canClose)\
  4290.         if canClose == nil then\
  4291.                 canClose = true\
  4292.         end\
  4293.         if type(_view) == 'string' then\
  4294.                 local h = fs.open(self.ViewPath.._view..'.view', 'r')\
  4295.                 if h then\
  4296.                         _view = textutils.unserialize(h.readAll())\
  4297.                         h.close()\
  4298.                 end\
  4299.         end\
  4300. \
  4301.         self.Window = self:AddObject({Type = 'Window', Z = 999, Title = title, CanClose = canClose})\
  4302.         _view.Type = 'View'\
  4303.         _view.Name = 'View'\
  4304.         _view.BackgroundColour = _view.BackgroundColour or colours.white\
  4305.         self.Window:SetView(self:ObjectFromFile(_view, self.Window))\
  4306. end\
  4307. \
  4308. function DisplayAlertWindow(self, title, text, buttons, callback)\
  4309.         local func = function(btn)\
  4310.                 self.Window:Close()\
  4311.                 if callback then\
  4312.                         callback(btn.Text)\
  4313.                 end\
  4314.         end\
  4315.         local children = {}\
  4316.         local usedX = -1\
  4317.         if buttons then\
  4318.                 for i, text in ipairs(buttons) do\
  4319.                         usedX = usedX + 3 + #text\
  4320.                         table.insert(children, {\
  4321.                                 [\"Y\"]=\"100%,-1\",\
  4322.                                 [\"X\"]=\"100%,-\"..usedX,\
  4323.                                 [\"Name\"]=text..\"Button\",\
  4324.                                 [\"Type\"]=\"Button\",\
  4325.                                 [\"Text\"]=text,\
  4326.                                 OnClick = func\
  4327.                         })\
  4328.                 end\
  4329.         end\
  4330. \
  4331.         local width = usedX + 2\
  4332.         if width < 28 then\
  4333.                 width = 28\
  4334.         end\
  4335. \
  4336.         local canClose = true\
  4337.         if buttons and #buttons~=0 then\
  4338.                 canClose = false\
  4339.         end\
  4340. \
  4341.         local height = 0\
  4342.         if text then\
  4343.                 height = #Helpers.WrapText(text, width - 2)\
  4344.                 table.insert(children, {\
  4345.                         [\"Y\"]=2,\
  4346.                         [\"X\"]=2,\
  4347.                         [\"Width\"]=\"100%,-2\",\
  4348.                         [\"Height\"]=height,\
  4349.                         [\"Name\"]=\"Label\",\
  4350.                         [\"Type\"]=\"Label\",\
  4351.                         [\"Text\"]=text\
  4352.                 })\
  4353.         end\
  4354.         local view = {\
  4355.                 Children = children,\
  4356.                 Width=width,\
  4357.                 Height=3+height+(canClose and 0 or 1),\
  4358.                 OnKeyChar = function(_view, keychar)\
  4359.                         func({Text=buttons[1]})\
  4360.                 end\
  4361.         }\
  4362.         self:DisplayWindow(view, title, canClose)\
  4363. end\
  4364. \
  4365. function DisplayTextBoxWindow(self, title, text, callback, textboxText, cursorAtEnd)\
  4366.         textboxText = textboxText or ''\
  4367.         local func = function(btn)\
  4368.                 self.Window:Close()\
  4369.                 if callback then\
  4370.                         callback(btn.Text)\
  4371.                 end\
  4372.         end\
  4373.         local children = {\
  4374.                 {\
  4375.                         [\"Y\"]=\"100%,-1\",\
  4376.                         [\"X\"]=\"100%,-4\",\
  4377.                         [\"Name\"]=\"OkButton\",\
  4378.                         [\"Type\"]=\"Button\",\
  4379.                         [\"Text\"]=\"Ok\",\
  4380.                         OnClick = function()\
  4381.                                 local text = self.Window:GetObject('TextBox').Text\
  4382.                                 self.Window:Close()\
  4383.                                 callback(true, text)\
  4384.                         end\
  4385.                 },\
  4386.                 {\
  4387.                         [\"Y\"]=\"100%,-1\",\
  4388.                         [\"X\"]=\"100%,-13\",\
  4389.                         [\"Name\"]=\"CancelButton\",\
  4390.                         [\"Type\"]=\"Button\",\
  4391.                         [\"Text\"]=\"Cancel\",\
  4392.                         OnClick = function()\
  4393.                                 self.Window:Close()\
  4394.                                 callback(false)\
  4395.                         end\
  4396.                 }\
  4397.         }\
  4398. \
  4399.         local height = -1\
  4400.         if text and #text ~= 0 then\
  4401.                 height = #Helpers.WrapText(text, 26)\
  4402.                 table.insert(children, {\
  4403.                         [\"Y\"]=2,\
  4404.                         [\"X\"]=2,\
  4405.                         [\"Width\"]=\"100%,-2\",\
  4406.                         [\"Height\"]=height,\
  4407.                         [\"Name\"]=\"Label\",\
  4408.                         [\"Type\"]=\"Label\",\
  4409.                         [\"Text\"]=text\
  4410.                 })\
  4411.         end\
  4412.         table.insert(children,\
  4413.                 {\
  4414.                         [\"Y\"]=3+height,\
  4415.                         [\"X\"]=2,\
  4416.                         [\"Width\"]=\"100%,-2\",\
  4417.                         [\"Name\"]=\"TextBox\",\
  4418.                         [\"Type\"]=\"TextBox\",\
  4419.                         [\"Text\"]=textboxText,\
  4420.                         [\"CursorPos\"]=(cursorAtEnd and 0 or nil)\
  4421.                 })\
  4422.         local view = {\
  4423.                 Children = children,\
  4424.                 Width=28,\
  4425.                 Height=5+height+(canClose and 0 or 1),\
  4426.         }\
  4427.         self:DisplayWindow(view, title)\
  4428.         self.Window:GetObject('TextBox').OnUpdate = function(txtbox, keychar)\
  4429.                 if keychar == keys.enter then\
  4430.                         self.Window:Close()\
  4431.                         callback(true, txtbox.Text)\
  4432.                 end\
  4433.         end\
  4434.         self:SetActiveObject(self.Window:GetObject('TextBox'))\
  4435.         self.Window.OnCloseButton = function()callback(false)end\
  4436. end\
  4437. \
  4438. function DisplayOpenFileWindow(self, title, callback)\
  4439.         title = title or 'Open File'\
  4440.         local func = function(btn)\
  4441.                 self.Window:Close()\
  4442.                 if callback then\
  4443.                         callback(btn.Text)\
  4444.                 end\
  4445.         end\
  4446. \
  4447.         local sidebarItems = {}\
  4448. \
  4449.         --this is a really, really super bad way of doing it\
  4450.         local separator = '                               !'\
  4451. \
  4452.         local function addFolder(path, level)\
  4453.                 for i, v in ipairs(fs.list(path)) do\
  4454.                         local fPath = path .. '/' .. v\
  4455.                         if fPath ~= '/rom' and fs.isDir(fPath) then\
  4456.                                 table.insert(sidebarItems, level .. v..separator..fPath)\
  4457.                                 addFolder(fPath, level .. '  ')\
  4458.                         end\
  4459.                 end\
  4460.         end\
  4461.         addFolder('','')\
  4462. \
  4463.         local currentFolder = ''\
  4464.         local selectedPath = nil\
  4465. \
  4466.         local goToFolder = nil\
  4467. \
  4468.         local children = {\
  4469.                 {\
  4470.                         [\"Y\"]=\"100%,-2\",\
  4471.                         [\"X\"]=1,\
  4472.                         [\"Height\"]=3,\
  4473.                         [\"Width\"]=\"100%\",\
  4474.                         [\"BackgroundColour\"]=colours.lightGrey,\
  4475.                         [\"Name\"]=\"SidebarListView\",\
  4476.                         [\"Type\"]=\"View\"\
  4477.                 },\
  4478.                 {\
  4479.                         [\"Y\"]=\"100%,-1\",\
  4480.                         [\"X\"]=\"100%,-4\",\
  4481.                         [\"Name\"]=\"OkButton\",\
  4482.                         [\"Type\"]=\"Button\",\
  4483.                         [\"Text\"]=\"Ok\",\
  4484.                         [\"BackgroundColour\"]=colours.white,\
  4485.                         [\"Enabled\"]=false,\
  4486.                         OnClick = function()\
  4487.                                 if selectedPath then\
  4488.                                         self.Window:Close()\
  4489.                                         callback(true, Helpers.TidyPath(selectedPath))\
  4490.                                 end\
  4491.                         end\
  4492.                 },\
  4493.                 {\
  4494.                         [\"Y\"]=\"100%,-1\",\
  4495.                         [\"X\"]=\"100%,-13\",\
  4496.                         [\"Name\"]=\"CancelButton\",\
  4497.                         [\"Type\"]=\"Button\",\
  4498.                         [\"Text\"]=\"Cancel\",\
  4499.                         [\"BackgroundColour\"]=colours.white,\
  4500.                         OnClick = function()\
  4501.                                 self.Window:Close()\
  4502.                                 callback(false)\
  4503.                         end\
  4504.                 },\
  4505.                 {\
  4506.                         [\"Y\"]=1,\
  4507.                         [\"X\"]=1,\
  4508.                         [\"Height\"]=\"100%,-3\",\
  4509.                         [\"Width\"]=\"40%,-1\",\
  4510.                         [\"Name\"]=\"SidebarListView\",\
  4511.                         [\"Type\"]=\"ListView\",\
  4512.                         [\"CanSelect\"]=true,\
  4513.                         [\"Items\"]={\
  4514.                                 [\"Computer\"] = sidebarItems\
  4515.                         },\
  4516.                         OnSelect = function(listView, text)\
  4517.                                 local _,s = text:find(separator)\
  4518.                                 if s then\
  4519.                                         local path = text:sub(s + 1)\
  4520.                                         goToFolder(path)\
  4521.                                 end\
  4522.                         end,\
  4523.                         OnClick = function(listView, event, side, x, y)\
  4524.                                 if y == 1 then\
  4525.                                         goToFolder('/')\
  4526.                                 end\
  4527.                         end\
  4528.                 },\
  4529.                 {\
  4530.                         [\"Y\"]=1,\
  4531.                         [\"X\"]=\"40%\",\
  4532.                         [\"Height\"]=\"100%,-3\",\
  4533.                         [\"Width\"]=1,\
  4534.                         [\"Type\"]=\"Separator\"\
  4535.                 },\
  4536.                 {\
  4537.                         [\"Y\"]=1,\
  4538.                         [\"X\"]=\"40%,2\",\
  4539.                         [\"Width\"]=\"65%,-3\",\
  4540.                         [\"Height\"]=1,\
  4541.                         [\"Type\"]=\"Label\",\
  4542.                         [\"Name\"]=\"PathLabel\",\
  4543.                         [\"TextColour\"]=colours.lightGrey,\
  4544.                         [\"Text\"]='/hello/there'\
  4545.                 },\
  4546.                 {\
  4547.                         [\"Y\"]=2,\
  4548.                         [\"X\"]=\"40%,1\",\
  4549.                         [\"Height\"]=\"100%,-4\",\
  4550.                         [\"Width\"]=\"65%,-1\",\
  4551.                         [\"Name\"]=\"FilesListView\",\
  4552.                         [\"Type\"]=\"ListView\",\
  4553.                         [\"CanSelect\"]=true,\
  4554.                         [\"Items\"]={},\
  4555.                         OnSelect = function(listView, text)\
  4556.                                 selectedPath = Helpers.TidyPath(currentFolder .. '/' .. text)\
  4557.                                 self.Window:GetObject('OkButton').Enabled = true\
  4558.                         end,\
  4559.                         OnClick = function(listView, event, side, x, y)\
  4560.                                 if y == 1 then\
  4561.                                         goToFolder('/')\
  4562.                                 end\
  4563.                         end\
  4564.                 },\
  4565.         }\
  4566.         local view = {\
  4567.                 Children = children,\
  4568.                 Width=40,\
  4569.                 Height= Drawing.Screen.Height - 4\
  4570.         }\
  4571.         self:DisplayWindow(view, title)\
  4572. \
  4573.         goToFolder = function(path)\
  4574.                 path = Helpers.TidyPath(path)\
  4575.                 self.Window:GetObject('PathLabel').Text = path\
  4576.                 currentFolder = path\
  4577. \
  4578.                 local filesListItems = {}\
  4579.                 for i, v in ipairs(fs.list(path)) do\
  4580.                         if not fs.isDir(currentFolder .. v) then\
  4581.                                 table.insert(filesListItems, v)\
  4582.                         end\
  4583.                 end\
  4584.                 self.Window:GetObject('OkButton').Enabled = false\
  4585.                 selectedPath = nil\
  4586.                 self.Window:GetObject('FilesListView').Items = filesListItems\
  4587. \
  4588.         end\
  4589. \
  4590.         goToFolder('')\
  4591. \
  4592.         self.Window.OnCloseButton = function()callback(false)end\
  4593. end\
  4594. \
  4595. function RegisterEvent(self, event, func)\
  4596.         if not self.EventHandlers[event] then\
  4597.                 self.EventHandlers[event] = {}\
  4598.         end\
  4599.         table.insert(self.EventHandlers[event], func)\
  4600. end\
  4601. \
  4602. function StartRepeatingTimer(self, func, interval)\
  4603.         local int = interval\
  4604.         if type(int) == 'function' then\
  4605.                 int = int()\
  4606.         end\
  4607.         if not int or int <= 0 then\
  4608.                 return\
  4609.         end\
  4610.         local timer = os.startTimer(int)\
  4611. \
  4612.         self.Timers[timer] = {func, true, interval}\
  4613.         return timer\
  4614. end\
  4615. \
  4616. function StartTimer(self, func, delay)\
  4617.         local timer = os.startTimer(delay)\
  4618.         self.Timers[timer] = {func, false}\
  4619.         return timer\
  4620. end\
  4621. \
  4622. function StopTimer(self, timer)\
  4623.         if self.Timers[timer] then\
  4624.                 self.Timers[timer] = nil\
  4625.         end\
  4626. end\
  4627. \
  4628. function HandleTimer(self, event, timer)\
  4629.         if self.Timers[timer] then\
  4630.                 local oldTimer = self.Timers[timer]\
  4631.                 self.Timers[timer] = nil\
  4632.                 local new = nil\
  4633.                 if oldTimer[2] then\
  4634.                         new = self:StartRepeatingTimer(oldTimer[1], oldTimer[3])\
  4635.                 end\
  4636.                 if oldTimer and oldTimer[1] then\
  4637.                         oldTimer[1](new)\
  4638.                 end\
  4639.         elseif self.OnTimer then\
  4640.                 self.OnTimer(self, event, timer)\
  4641.         end\
  4642. end\
  4643. \
  4644. function SetActiveObject(self, object)\
  4645.         if object then\
  4646.                 if object ~= self.ActiveObject then\
  4647.                         self.ActiveObject = object\
  4648.                         object:ForceDraw()\
  4649.                 end\
  4650.         elseif self.ActiveObject ~= nil then\
  4651.                 self.ActiveObject = nil\
  4652.                 self.CursorPos = nil\
  4653.                 self.View:ForceDraw()\
  4654.         end\
  4655. end\
  4656. \
  4657. function GetActiveObject(self)\
  4658.         return self.ActiveObject\
  4659. end\
  4660. \
  4661. OnTimer = nil\
  4662. OnClick = nil\
  4663. OnKeyChar = nil\
  4664. OnDrag = nil\
  4665. OnScroll = nil\
  4666. OnViewLoad = nil\
  4667. OnViewClose = nil\
  4668. OnDraw = nil\
  4669. OnQuit = nil\
  4670. \
  4671. local eventFuncs = {\
  4672.         OnClick = {'mouse_click'},\
  4673.         OnKeyChar = {'key', 'char'},\
  4674.         OnDrag = {'mouse_drag'},\
  4675.         OnScroll = {'mouse_scroll'},\
  4676.         HandleClick = {'mouse_click', 'mouse_drag', 'mouse_scroll'},\
  4677.         HandleKeyChar = {'key', 'char'},\
  4678.         HandleTimer = {'timer'}\
  4679. }\
  4680. \
  4681. local drawCalls = 0\
  4682. local ignored = 0\
  4683. function Draw(self)\
  4684.         self.IsDrawing = true\
  4685.         if self.OnDraw then\
  4686.                 self:OnDraw()\
  4687.         end\
  4688. \
  4689.         if self.View and self.View:NeedsDraw() then\
  4690.                 self.View:Draw()\
  4691.                 Drawing.DrawBuffer()\
  4692.                 if isDebug then\
  4693.                         drawCalls = drawCalls + 1\
  4694.                 end\
  4695.         elseif not self.View then\
  4696.                 print('No loaded view. You need to do program:LoadView first.')\
  4697.         end     \
  4698. \
  4699.         if self:GetActiveObject() and self.CursorPos and type(self.CursorPos[1]) == 'number' and type(self.CursorPos[2]) == 'number' then\
  4700.                 term.setCursorPos(self.CursorPos[1], self.CursorPos[2])\
  4701.                 term.setTextColour(self.CursorColour)\
  4702.                 term.setCursorBlink(true)\
  4703.         else\
  4704.                 term.setCursorBlink(false)\
  4705.         end\
  4706. \
  4707.         self.IsDrawing = false\
  4708. end\
  4709. \
  4710. function EventHandler(self)\
  4711.         local event = { os.pullEventRaw() }\
  4712.         \
  4713.         if self.EventHandlers[event[1]] then\
  4714.                 for i, e in ipairs(self.EventHandlers[event[1]]) do\
  4715.                         e(self, unpack(event))\
  4716.                 end\
  4717.         end\
  4718. end\
  4719. \
  4720. function Quit(self)\
  4721.         self.Running = false\
  4722.         if self.OnQuit then\
  4723.                 self:OnQuit()\
  4724.         end\
  4725.         if OneOS then\
  4726.                 OneOS.Close()\
  4727.         end\
  4728. end\
  4729. \
  4730. function Run(self, ready)\
  4731.         for name, events in pairs(eventFuncs) do\
  4732.                 if self[name] then\
  4733.                         for i, event in ipairs(events) do\
  4734.                                 self:RegisterEvent(event, self[name])\
  4735.                         end\
  4736.                 end\
  4737.         end\
  4738. \
  4739.         if self.AllowTerminate then\
  4740.                 self:RegisterEvent('terminate', function()error('Terminated', 0) end)\
  4741.         end\
  4742. \
  4743.         if self.DefaultView and self.DefaultView ~= '' and fs.exists(self.ViewPath..self.DefaultView..'.view') then\
  4744.                 self:LoadView(self.DefaultView)\
  4745.         end\
  4746. \
  4747.         if ready then\
  4748.                 ready()\
  4749.         end\
  4750.         \
  4751.         self:Draw()\
  4752. \
  4753.         while self.Running do\
  4754.                 self:EventHandler()\
  4755.         end\
  4756. end",[".gitignore"]=".DS_Store\
  4757. .Desktop.settings\
  4758. .OneOS.settings\
  4759. *.settings\
  4760. \
  4761. Desktop/.Desktop.settings\
  4762. \
  4763. .version",["hash"]="--\
  4764. --  Thanks to GravityScore for this!\
  4765. --  http://www.computercraft.info/forums2/index.php?/topic/8169-sha-256-in-pure-lua/\
  4766. --\
  4767. --  This is used to hash passwords sent with the secure text field. It just reduces the chance of people getting hacked.\
  4768. --\
  4769. \
  4770. --  \
  4771. --  Adaptation of the Secure Hashing Algorithm (SHA-244/256)\
  4772. --  Found Here: http://lua-users.org/wiki/SecureHashAlgorithm\
  4773. --  \
  4774. --  Using an adapted version of the bit library\
  4775. --  Found Here: https://bitbucket.org/Boolsheet/bslf/src/1ee664885805/bit.lua\
  4776. --  \
  4777. \
  4778. local MOD = 2^32\
  4779. local MODM = MOD-1\
  4780. \
  4781. local function memoize(f)\
  4782.         local mt = {}\
  4783.         local t = setmetatable({}, mt)\
  4784.         function mt:__index(k)\
  4785.                 local v = f(k)\
  4786.                 t[k] = v\
  4787.                 return v\
  4788.         end\
  4789.         return t\
  4790. end\
  4791. \
  4792. local function make_bitop_uncached(t, m)\
  4793.         local function bitop(a, b)\
  4794.                 local res,p = 0,1\
  4795.                 while a ~= 0 and b ~= 0 do\
  4796.                         local am, bm = a % m, b % m\
  4797.                         res = res + t[am][bm] * p\
  4798.                         a = (a - am) / m\
  4799.                         b = (b - bm) / m\
  4800.                         p = p*m\
  4801.                 end\
  4802.                 res = res + (a + b) * p\
  4803.                 return res\
  4804.         end\
  4805.         return bitop\
  4806. end\
  4807. \
  4808. local function make_bitop(t)\
  4809.         local op1 = make_bitop_uncached(t,2^1)\
  4810.         local op2 = memoize(function(a) return memoize(function(b) return op1(a, b) end) end)\
  4811.         return make_bitop_uncached(op2, 2 ^ (t.n or 1))\
  4812. end\
  4813. \
  4814. local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})\
  4815. \
  4816. local function bxor(a, b, c, ...)\
  4817.         local z = nil\
  4818.         if b then\
  4819.                 a = a % MOD\
  4820.                 b = b % MOD\
  4821.                 z = bxor1(a, b)\
  4822.                 if c then z = bxor(z, c, ...) end\
  4823.                 return z\
  4824.         elseif a then return a % MOD\
  4825.         else return 0 end\
  4826. end\
  4827. \
  4828. local function band(a, b, c, ...)\
  4829.         local z\
  4830.         if b then\
  4831.                 a = a % MOD\
  4832.                 b = b % MOD\
  4833.                 z = ((a + b) - bxor1(a,b)) / 2\
  4834.                 if c then z = bit32_band(z, c, ...) end\
  4835.                 return z\
  4836.         elseif a then return a % MOD\
  4837.         else return MODM end\
  4838. end\
  4839. \
  4840. local function bnot(x) return (-1 - x) % MOD end\
  4841. \
  4842. local function rshift1(a, disp)\
  4843.         if disp < 0 then return lshift(a,-disp) end\
  4844.         return math.floor(a % 2 ^ 32 / 2 ^ disp)\
  4845. end\
  4846. \
  4847. local function rshift(x, disp)\
  4848.         if disp > 31 or disp < -31 then return 0 end\
  4849.         return rshift1(x % MOD, disp)\
  4850. end\
  4851. \
  4852. local function lshift(a, disp)\
  4853.         if disp < 0 then return rshift(a,-disp) end \
  4854.         return (a * 2 ^ disp) % 2 ^ 32\
  4855. end\
  4856. \
  4857. local function rrotate(x, disp)\
  4858.    x = x % MOD\
  4859.    disp = disp % 32\
  4860.    local low = band(x, 2 ^ disp - 1)\
  4861.    return rshift(x, disp) + lshift(low, 32 - disp)\
  4862. end\
  4863. \
  4864. local k = {\
  4865.         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,\
  4866.         0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\
  4867.         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\
  4868.         0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\
  4869.         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,\
  4870.         0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\
  4871.         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,\
  4872.         0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\
  4873.         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\
  4874.         0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\
  4875.         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,\
  4876.         0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\
  4877.         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,\
  4878.         0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\
  4879.         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\
  4880.         0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\
  4881. }\
  4882. \
  4883. local function str2hexa(s)\
  4884.         return (string.gsub(s, \".\", function(c) return string.format(\"%02x\", string.byte(c)) end))\
  4885. end\
  4886. \
  4887. local function num2s(l, n)\
  4888.         local s = \"\"\
  4889.         for i = 1, n do\
  4890.                 local rem = l % 256\
  4891.                 s = string.char(rem) .. s\
  4892.                 l = (l - rem) / 256\
  4893.         end\
  4894.         return s\
  4895. end\
  4896. \
  4897. local function s232num(s, i)\
  4898.         local n = 0\
  4899.         for i = i, i + 3 do n = n*256 + string.byte(s, i) end\
  4900.         return n\
  4901. end\
  4902. \
  4903. local function preproc(msg, len)\
  4904.         local extra = 64 - ((len + 9) % 64)\
  4905.         len = num2s(8 * len, 8)\
  4906.         msg = msg .. \"\\128\" .. string.rep(\"\\0\", extra) .. len\
  4907.         assert(#msg % 64 == 0)\
  4908.         return msg\
  4909. end\
  4910. \
  4911. local function initH256(H)\
  4912.         H[1] = 0x6a09e667\
  4913.         H[2] = 0xbb67ae85\
  4914.         H[3] = 0x3c6ef372\
  4915.         H[4] = 0xa54ff53a\
  4916.         H[5] = 0x510e527f\
  4917.         H[6] = 0x9b05688c\
  4918.         H[7] = 0x1f83d9ab\
  4919.         H[8] = 0x5be0cd19\
  4920.         return H\
  4921. end\
  4922. \
  4923. local function digestblock(msg, i, H)\
  4924.         local w = {}\
  4925.         for j = 1, 16 do w[j] = s232num(msg, i + (j - 1)*4) end\
  4926.         for j = 17, 64 do\
  4927.                 local v = w[j - 15]\
  4928.                 local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3))\
  4929.                 v = w[j - 2]\
  4930.                 w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10))\
  4931.         end\
  4932. \
  4933.         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]\
  4934.         for i = 1, 64 do\
  4935.                 local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))\
  4936.                 local maj = bxor(band(a, b), band(a, c), band(b, c))\
  4937.                 local t2 = s0 + maj\
  4938.                 local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))\
  4939.                 local ch = bxor (band(e, f), band(bnot(e), g))\
  4940.                 local t1 = h + s1 + ch + k[i] + w[i]\
  4941.                 h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2\
  4942.         end\
  4943. \
  4944.         H[1] = band(H[1] + a)\
  4945.         H[2] = band(H[2] + b)\
  4946.         H[3] = band(H[3] + c)\
  4947.         H[4] = band(H[4] + d)\
  4948.         H[5] = band(H[5] + e)\
  4949.         H[6] = band(H[6] + f)\
  4950.         H[7] = band(H[7] + g)\
  4951.         H[8] = band(H[8] + h)\
  4952. end\
  4953. \
  4954. function sha256(msg)\
  4955.         msg = preproc(msg, #msg)\
  4956.         local H = initH256({})\
  4957.         for i = 1, #msg, 64 do digestblock(msg, i, H) end\
  4958.         return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) ..\
  4959.                 num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4))\
  4960. end",["Pages"]={["404.ccml"]="<!DOCTYPE ccml>\
  4961. <html>\
  4962.         <head>\
  4963.           <title>Page Not Found</title>\
  4964.         </head>\
  4965.         <body>\
  4966.                 <br/>\
  4967.                 <br/>\
  4968.                 <h colour=\"red\">404 Page Not Found</h>\
  4969.                 <br/>\
  4970.                 <center>\
  4971.                         <p width=\"38\" align=\"center\">The page was not found on the server. Check the address and try again.</p>\
  4972.                 </center>\
  4973.         </body>\
  4974. </html>",["6.ccml"]="<!DOCTYPE ccml>\
  4975. <html>\
  4976.         <head>\
  4977.           <title>Download Failed</title>\
  4978.         </head>\
  4979.         <body>\
  4980.                 <br/>\
  4981.                 <br/>\
  4982.                 <h colour=\"red\">Download Failed</h>\
  4983.                 <br/>\
  4984.                 <center>\
  4985.                         <br>\
  4986.                         <p width=\"38\" align=\"center\">The file you wanted failed to download. Try again or contact the file owner.</p>\
  4987.                 </center>\
  4988.         </body>\
  4989. </html>",["7.ccml"]="<!DOCTYPE ccml>\
  4990. <html>\
  4991.         <head>\
  4992.           <title>No Modem Connected</title>\
  4993.         </head>\
  4994.         <body>\
  4995.                 <br/>\
  4996.                 <br/>\
  4997.                 <h colour=\"red\">No Modem Connected</h>\
  4998.                 <br/>\
  4999.                 <center>\
  5000.                         <br>\
  5001.                         <p width=\"38\" align=\"center\">Please attach a wirelss modem and restart Quest.</p>\
  5002.                 </center>\
  5003.         </body>\
  5004. </html>",["download.ccml"]="<!DOCTYPE ccml>\
  5005. <html>\
  5006.         <head>\
  5007.                 <title>Downloading File</title>\
  5008.             <script type=\"lua\">\
  5009.                 if window.get.path then\
  5010.                         l('p').text('Quest is downloading your file to ' .. window.get.path .. '. Please wait a moment. Leaving this page will cancel the download.')\
  5011.                 end\
  5012.             </script>\
  5013.         </head>\
  5014.         <body>\
  5015.                 <br/>\
  5016.                 <br/>\
  5017.                 <h colour=\"blue\">Downloading File</h>\
  5018. \
  5019.                 <center>\
  5020.                         <br>\
  5021.                         <p width=\"48\" align=\"center\"></p>\
  5022.                 </center>\
  5023.         </body>\
  5024. </html>",["408.ccml"]="<!DOCTYPE ccml>\
  5025. <html>\
  5026.         <head>\
  5027.           <title>Page Not Found</title>\
  5028.         </head>\
  5029.         <body>\
  5030.                 <br/>\
  5031.                 <br/>\
  5032.                 <h colour=\"red\">Page Load Cancelled</h>\
  5033.                 <br/>\
  5034.                 <center>\
  5035.                         <p width=\"38\" align=\"center\">The page either took too long to load or you cancelled loading it.</p>\
  5036.                 </center>\
  5037.         </body>\
  5038. </html>",["text.ccml"]="<!DOCTYPE ccml>\
  5039. <html>\
  5040.         <head>\
  5041.                 <title>An Error Occured</title>\
  5042.             <script type=\"lua\">\
  5043.                 if window.get.reason then\
  5044.                         l('p').text(window.get.reason)\
  5045.                 end\
  5046.             </script>\
  5047.         </head>\
  5048.         <body>\
  5049.                 <br/>\
  5050.                 <br/>\
  5051.                 <h colour=\"red\">An Error Occured</h>\
  5052.                 <br/>\
  5053.                 <center>\
  5054.                         <br>\
  5055.                         <p width=\"48\" align=\"center\">Unknown Reason</p>\
  5056.                 </center>\
  5057.         </body>\
  5058. </html>",["downloaded.ccml"]="<!DOCTYPE ccml>\
  5059. <html>\
  5060.         <head>\
  5061.                 <title>Download Complete</title>\
  5062.             <script type=\"lua\">\
  5063.                 if window.get.path then\
  5064.                         l('p').text('Your file has been saved to ' .. window.get.path .. '. You can now leave this page (use the back button).')\
  5065.                 end\
  5066.             </script>\
  5067.         </head>\
  5068.         <body>\
  5069.                 <br/>\
  5070.                 <br/>\
  5071.                 <h colour=\"blue\">Download Complete</h>\
  5072. \
  5073.                 <center>\
  5074.                         <br>\
  5075.                         <p width=\"48\" align=\"center\"></p>\
  5076.                 </center>\
  5077.         </body>\
  5078. </html>",["1.ccml"]="<!DOCTYPE ccml>\
  5079. <html>\
  5080.         <head>\
  5081.           <title>Failed to Download Page</title>\
  5082.         </head>\
  5083.         <body>\
  5084.                 <br/>\
  5085.                 <br/>\
  5086.                 <h colour=\"red\">Failed to Download Page</h>\
  5087.                 <br/>\
  5088.                 <center>\
  5089.                         <br>\
  5090.                         <p width=\"38\" align=\"center\">The page you requested failed to download. The page may not exist, the server may be experiencing problems or you have connection issues.</p>\
  5091.                 </center>\
  5092.         </body>\
  5093. </html>",["2.ccml"]="<!DOCTYPE ccml>\
  5094. <html>\
  5095.         <head>\
  5096.           <title>Doctype Incorrect</title>\
  5097.         </head>\
  5098.         <body>\
  5099.                 <br/>\
  5100.                 <br/>\
  5101.                 <h colour=\"red\">Doctype Incorrect</h>\
  5102.                 <br/>\
  5103.                 <center>\
  5104.                         <br>\
  5105.                         <p width=\"38\" align=\"center\">This page has an incorrect doctype and can not be rendered. Quest can not view standard web pages.</p>\
  5106.                         <br>\
  5107.                         <p width=\"38\" align=\"center\" color=\"grey\">If you made this page make sure the file starts with \"&lt;!DOCTYPE ccml&gt;\"</p>\
  5108.                 </center>\
  5109.         </body>\
  5110. </html>",["3.ccml"]="<!DOCTYPE ccml>\
  5111. <html>\
  5112.         <head>\
  5113.           <title>Failed to Parse Page</title>\
  5114.         </head>\
  5115.         <body>\
  5116.                 <br/>\
  5117.                 <br/>\
  5118.                 <h colour=\"red\">Failed to Parse Page</h>\
  5119.                 <br/>\
  5120.                 <center>\
  5121.                         <br>\
  5122.                         <p width=\"38\" align=\"center\">The page you requested failed to parse. It is either malformed or your browser is out of date.</p>\
  5123.                 </center>\
  5124.         </body>\
  5125. </html>",["4.ccml"]="<!DOCTYPE ccml>\
  5126. <html>\
  5127.         <head>\
  5128.           <title>HTTP Not Enabled</title>\
  5129.         </head>\
  5130.         <body>\
  5131.                 <br/>\
  5132.                 <br/>\
  5133.                 <h colour=\"red\">HTTP Not Enabled</h>\
  5134.                 <br/>\
  5135.                 <center>\
  5136.                         <br>\
  5137.                         <p width=\"38\" align=\"center\">You haven't enabled the HTTP API. To do so, take a look on the HTTP API page on the wiki for a link to a tutorial.</p>\
  5138.                 </center>\
  5139.         </body>\
  5140. </html>",["5.ccml"]="<!DOCTYPE ccml>\
  5141. <html>\
  5142.         <head>\
  5143.           <title>Page Not Whitelisted</title>\
  5144.         </head>\
  5145.         <body>\
  5146.                 <br/>\
  5147.                 <br/>\
  5148.                 <h colour=\"red\">Page Not Whitelisted</h>\
  5149.                 <br/>\
  5150.                 <center>\
  5151.                         <br>\
  5152.                         <p width=\"38\" align=\"center\">The page you are trying to open isn't whitelisted. Please take a look on the forums or the wiki as to how to fix this.</p>\
  5153.                 </center>\
  5154.         </body>\
  5155. </html>",},["lQuery"]="function fn(selector)\
  5156.         if not selector then\
  5157.         else\
  5158.                 local elements = lQuery.webView:ResolveElements(selector)\
  5159.                 local function relayout()\
  5160.                         lQuery.webView:RepositionLayout()\
  5161.                 end\
  5162.                 if elements and #elements > 0 then\
  5163.                         local each = function(func)\
  5164.                                 for i, v in ipairs(elements) do\
  5165.                                         func(v, i)\
  5166.                                 end\
  5167.                         end\
  5168. \
  5169.                         local response = {\
  5170.                                 text = function(text)\
  5171.                                         each(function(elem)\
  5172.                                                 if elem.Text then\
  5173.                                                         elem.Text = tostring(text)\
  5174.                                                 end\
  5175.                                         end)\
  5176.                                 end,\
  5177. \
  5178.                                 width = function(width)\
  5179.                                         if type(width) == 'number' then\
  5180.                                                 each(function(elem)\
  5181.                                                         elem.Width = width\
  5182.                                                 end)\
  5183.                                                 relayout()\
  5184.                                         end\
  5185.                                 end,\
  5186. \
  5187.                                 height = function(height)\
  5188.                                         if type(height) == 'number' then\
  5189.                                                 each(function(elem)\
  5190.                                                         elem.Height = height\
  5191.                                                 end)\
  5192.                                                 relayout()\
  5193.                                         end\
  5194.                                 end,\
  5195. \
  5196.                                 colour = function(colour)\
  5197.                                         if type(colour) == 'number' then\
  5198.                                                 each(function(elem)\
  5199.                                                         if elem.TextColour then\
  5200.                                                                 elem.TextColour = colour\
  5201.                                                         end\
  5202.                                                 end)\
  5203.                                         end\
  5204.                                 end,\
  5205. \
  5206.                                 bgcolour = function(bgcolour)\
  5207.                                         if type(bgcolour) == 'number' then\
  5208.                                                 each(function(elem)\
  5209.                                                         if elem.BackgroundColour then\
  5210.                                                                 elem.BackgroundColour = bgcolour\
  5211.                                                         end\
  5212.                                                 end)\
  5213.                                         end\
  5214.                                 end,\
  5215. \
  5216.                                 align = function(align)\
  5217.                                         if type(align) == 'string' and align:lower() == 'left' or align:lower() == 'center' or align:lower() == 'right'  then\
  5218.                                                 each(function(elem)\
  5219.                                                         if elem.Align then\
  5220.                                                                 elem.Align = align:lower():gsub(\"^%l\", string.upper)\
  5221.                                                         end\
  5222.                                                 end)\
  5223.                                         end\
  5224.                                 end,\
  5225. \
  5226.                                 attr = function(name)\
  5227.                                         local values = {}\
  5228.                                         each(function(elem)\
  5229.                                                 if elem.Element.Attributes and elem.Element.Attributes[name] then\
  5230.                                                         table.insert(values, elem.Element.Attributes[name])\
  5231.                                                 end\
  5232.                                         end)\
  5233.                                         return values\
  5234.                                 end,\
  5235. \
  5236.                                 remove = function()\
  5237.                                         each(function(elem)\
  5238.                                                 lQuery.webView:RemoveElement(elem)\
  5239.                                                 relayout()\
  5240.                                         end)\
  5241.                                 end,\
  5242. \
  5243.                                 focus = function()\
  5244.                                         each(function(elem)\
  5245.                                                 elem.Bedrock:SetActiveObject(elem)\
  5246.                                         end)\
  5247.                                 end\
  5248.                         }\
  5249.                         response.color = response.colour\
  5250.                         response.bgcolor = response.bgcolour\
  5251. \
  5252.                         return response\
  5253.                 end\
  5254.         end\
  5255. end",["Peripheral"]="GetPeripheral = function(_type)\
  5256.         for i, p in ipairs(GetPeripherals()) do\
  5257.                 if p.Type == _type then\
  5258.                         return p\
  5259.                 end\
  5260.         end\
  5261. end\
  5262. \
  5263. Call = function(type, ...)\
  5264.         local tArgs = {...}\
  5265.         local p = GetPeripheral(type)\
  5266.         peripheral.call(p.Side, unpack(tArgs))\
  5267. end\
  5268. \
  5269. local getNames = peripheral.getNames or function()\
  5270.         local tResults = {}\
  5271.         for n,sSide in ipairs( rs.getSides() ) do\
  5272.                 if peripheral.isPresent( sSide ) then\
  5273.                         table.insert( tResults, sSide )\
  5274.                         local isWireless = false\
  5275.                         if pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then\
  5276.                                 isWireless = true\
  5277.                         end     \
  5278.                         if peripheral.getType( sSide ) == \"modem\" and not isWireless then\
  5279.                                 local tRemote = peripheral.call( sSide, \"getNamesRemote\" )\
  5280.                                 for n,sName in ipairs( tRemote ) do\
  5281.                                         table.insert( tResults, sName )\
  5282.                                 end\
  5283.                         end\
  5284.                 end\
  5285.         end\
  5286.         return tResults\
  5287. end\
  5288. \
  5289. GetPeripherals = function(filterType)\
  5290.         local peripherals = {}\
  5291.         for i, side in ipairs(getNames()) do\
  5292.                 local name = peripheral.getType(side):gsub(\"^%l\", string.upper)\
  5293.                 local code = string.upper(side:sub(1,1))\
  5294.                 if side:find('_') then\
  5295.                         code = side:sub(side:find('_')+1)\
  5296.                 end\
  5297. \
  5298.                 local dupe = false\
  5299.                 for i, v in ipairs(peripherals) do\
  5300.                         if v[1] == name .. ' ' .. code then\
  5301.                                 dupe = true\
  5302.                         end\
  5303.                 end\
  5304. \
  5305.                 if not dupe then\
  5306.                         local _type = peripheral.getType(side)\
  5307.                         local formattedType = _type:sub(1, 1):upper() .. _type:sub(2, -1)\
  5308.                         local isWireless = false\
  5309.                         if _type == 'modem' then\
  5310.                                 if not pcall(function()isWireless = peripheral.call(side, 'isWireless') end) then\
  5311.                                         isWireless = true\
  5312.                                 end     \
  5313.                                 if isWireless then\
  5314.                                         _type = 'wireless_modem'\
  5315.                                         formattedType = 'Wireless Modem'\
  5316.                                         name = 'W '..name\
  5317.                                 end\
  5318.                         end\
  5319.                         if not filterType or _type == filterType then\
  5320.                                 table.insert(peripherals, {Name = name:sub(1,8) .. ' '..code, Fullname = name .. ' ('..side:sub(1, 1):upper() .. side:sub(2, -1)..')', Side = side, Type = _type, Wireless = isWireless, FormattedType = formattedType})\
  5321.                         end\
  5322.                 end\
  5323.         end\
  5324.         return peripherals\
  5325. end\
  5326. \
  5327. GetSide = function(side)\
  5328.         for i, p in ipairs(GetPeripherals()) do\
  5329.                 if p.Side == side then\
  5330.                         return p\
  5331.                 end\
  5332.         end\
  5333. end\
  5334. \
  5335. PresentNamed = function(name)\
  5336.         return peripheral.isPresent(name)\
  5337. end\
  5338. \
  5339. CallType = function(type, ...)\
  5340.         local tArgs = {...}\
  5341.         local p = GetPeripheral(type)\
  5342.         return peripheral.call(p.Side, unpack(tArgs))\
  5343. end\
  5344. \
  5345. CallNamed = function(name, ...)\
  5346.         local tArgs = {...}\
  5347.         return peripheral.call(name, unpack(tArgs))\
  5348. end\
  5349. \
  5350. GetInfo = function(p)\
  5351.         local info = {}\
  5352.         local buttons = {}\
  5353.         if p.Type == 'computer' then\
  5354.                 local id = peripheral.call(p.Side:lower(),'getID')\
  5355.                 if id then\
  5356.                         info = {\
  5357.                                 ID = tostring(id)\
  5358.                         }\
  5359.                 else\
  5360.                         info = {}\
  5361.                 end\
  5362.         elseif p.Type == 'drive' then\
  5363.                 local discType = 'No Disc'\
  5364.                 local discID = nil\
  5365.                 local mountPath = nil\
  5366.                 local discLabel = nil\
  5367.                 local songName = nil\
  5368.                 if peripheral.call(p.Side:lower(), 'isDiskPresent') then\
  5369.                         if peripheral.call(p.Side:lower(), 'hasData') then\
  5370.                                 discType = 'Data'\
  5371.                                 discID = peripheral.call(p.Side:lower(), 'getDiskID')\
  5372.                                 if discID then\
  5373.                                         discID = tostring(discID)\
  5374.                                 else\
  5375.                                         discID = 'None'\
  5376.                                 end\
  5377.                                 mountPath = '/'..peripheral.call(p.Side:lower(), 'getMountPath')..'/'\
  5378.                                 discLabel = peripheral.call(p.Side:lower(), 'getDiskLabel')\
  5379.                         else\
  5380.                                 discType = 'Audio'\
  5381.                                 songName = peripheral.call(p.Side:lower(), 'getAudioTitle')\
  5382.                         end\
  5383.                 end\
  5384.                 if mountPath then\
  5385.                         table.insert(buttons, {Text = 'View Files', OnClick = function(self, event, side, x, y)GoToPath(mountPath)end})\
  5386.                 elseif discType == 'Audio' then\
  5387.                         table.insert(buttons, {Text = 'Play', OnClick = function(self, event, side, x, y)\
  5388.                                 if self.Text == 'Play' then\
  5389.                                         disk.playAudio(p.Side:lower())\
  5390.                                         self.Text = 'Stop'\
  5391.                                 else\
  5392.                                         disk.stopAudio(p.Side:lower())\
  5393.                                         self.Text = 'Play'\
  5394.                                 end\
  5395.                         end})\
  5396.                 else\
  5397.                         diskOpenButton = nil\
  5398.                 end\
  5399.                 if discType ~= 'No Disc' then\
  5400.                         table.insert(buttons, {Text = 'Eject', OnClick = function(self, event, side, x, y)disk.eject(p.Side:lower()) sleep(0) RefreshFiles() end})\
  5401.                 end\
  5402. \
  5403.                 info = {\
  5404.                         ['Disc Type'] = discType,\
  5405.                         ['Disc Label'] = discLabel,\
  5406.                         ['Song Title'] = songName,\
  5407.                         ['Disc ID'] = discID,\
  5408.                         ['Mount Path'] = mountPath\
  5409.                 }\
  5410.         elseif p.Type == 'printer' then\
  5411.                 local pageSize = 'No Loaded Page'\
  5412.                 local _, err = pcall(function() return tostring(peripheral.call(p.Side:lower(), 'getPgaeSize')) end)\
  5413.                 if not err then\
  5414.                         pageSize = tostring(peripheral.call(p.Side:lower(), 'getPageSize'))\
  5415.                 end\
  5416.                 info = {\
  5417.                         ['Paper Level'] = tostring(peripheral.call(p.Side:lower(), 'getPaperLevel')),\
  5418.                         ['Paper Size'] = pageSize,\
  5419.                         ['Ink Level'] = tostring(peripheral.call(p.Side:lower(), 'getInkLevel'))\
  5420.                 }\
  5421.         elseif p.Type == 'modem' then\
  5422.                 info = {\
  5423.                         ['Connected Peripherals'] = tostring(#peripheral.call(p.Side:lower(), 'getNamesRemote'))\
  5424.                 }\
  5425.         elseif p.Type == 'monitor' then\
  5426.                 local w, h = peripheral.call(p.Side:lower(), 'getSize')\
  5427.                 local screenType = 'Black and White'\
  5428.                 if peripheral.call(p.Side:lower(), 'isColour') then\
  5429.                         screenType = 'Colour'\
  5430.                 end\
  5431.                 local buttonTitle = 'Use as Screen'\
  5432.                 if OneOS.Settings:GetValues()['Monitor'] == p.Side:lower() then\
  5433.                         buttonTitle = 'Use Computer Screen'\
  5434.                 end\
  5435.                 table.insert(buttons, {Text = buttonTitle, OnClick = function(self, event, side, x, y)\
  5436.                                 self.Bedrock:DisplayAlertWindow('Reboot Required', \"To change screen you'll need to reboot your computer.\", {'Reboot', 'Cancel'}, function(value)\
  5437.                                         if value == 'Reboot' then\
  5438.                                                 if buttonTitle == 'Use Computer Screen' then\
  5439.                                                         OneOS.Settings:SetValue('Monitor', nil)\
  5440.                                                 else\
  5441.                                                         OneOS.Settings:SetValue('Monitor', p.Side:lower())\
  5442.                                                 end\
  5443.                                                 OneOS.Reboot()\
  5444.                                         end\
  5445.                                 end)\
  5446.                         end\
  5447.                 })\
  5448.                 info = {\
  5449.                         ['Type'] = screenType,\
  5450.                         ['Width'] = tostring(w),\
  5451.                         ['Height'] = tostring(h),\
  5452.                 }\
  5453.         end\
  5454.         info.Buttons = buttons\
  5455.         return info\
  5456. end",["Objects"]={["HeadingView.lua"]="Inherit = 'View'\
  5457. Height = 3\
  5458. \
  5459. OnLoad = function(self)\
  5460.         self:OnUpdate('Text')\
  5461. end\
  5462. \
  5463. OnUpdate = function(self, value)\
  5464.         if value == 'Text' then\
  5465.                 self:RemoveAllObjects()\
  5466.                 self:AddObject({\
  5467.                         Y = 1,\
  5468.                         X = 1,\
  5469.                         Width = \"100%\",\
  5470.                         Align = \"Center\",\
  5471.                         Type = \"Label\",\
  5472.                         Text = self.Text,\
  5473.                         TextColour = self.TextColour,\
  5474.                         BackgroundColour = self.BackgroundColour\
  5475.                 })\
  5476. \
  5477.                 local underline = ''\
  5478.                 for i = 1, #self.Text + 2 do\
  5479.                         underline = underline .. '='\
  5480.                 end\
  5481.                 self:AddObject({\
  5482.                         Y = 2,\
  5483.                         X = 1,\
  5484.                         Width = \"100%\",\
  5485.                         Align = \"Center\",\
  5486.                         Type = \"Label\",\
  5487.                         Text = underline,\
  5488.                         TextColour = self.TextColour,\
  5489.                         BackgroundColour = self.BackgroundColour\
  5490.                 })\
  5491.         end\
  5492. end",["WebImageView.lua"]="URL = false\
  5493. Image = false\
  5494. \
  5495. OnDraw = function(self, x, y)\
  5496.         if not self.Image then\
  5497.                 Drawing.DrawBlankArea(x, y, self.Width, self.Height, colours.lightGrey)\
  5498.         elseif self.Format == 'nft' then\
  5499.                 Drawing.DrawImage(x, y, self.Image, self.Width, self.Height)\
  5500.         elseif self.Format == 'nfp' or self.Format == 'paint' then\
  5501.                 for _x, col in ipairs(self.Image) do\
  5502.                         for _y, colour in ipairs(col) do\
  5503.                     Drawing.WriteToBuffer(x+_x-1, y+_y-1, ' ', colours.white, colour)\
  5504.                         end\
  5505.                 end\
  5506.         elseif self.Format == 'skch' or self.Format == 'sketch' then\
  5507.                 Drawing.DrawImage(x, y, self.Image, self.Width, self.Height)\
  5508.         end\
  5509. end\
  5510. \
  5511. OnUpdate = function(self, value)\
  5512.         if value == 'URL' and self.URL then\
  5513.                 fetchHTTPAsync(resolveFullUrl(self.URL), function(ok, event, response)\
  5514.                         if ok then\
  5515.                                 local width, height = self.Width, self.Height\
  5516. \
  5517.                                 local lines = {}\
  5518.                                 for line in response.readLine do\
  5519.                                         table.insert(lines, line)\
  5520.                                 end\
  5521.                                 response.close()\
  5522.                                 local content = table.concat(lines, '\\n')\
  5523. \
  5524.                                 if not self.Format then\
  5525.                                         self.Format = self:DetermineFormat(content)\
  5526.                                 end\
  5527. \
  5528.                                 if self.Format == 'nft' then\
  5529.                                         self.Image, self.Width, self.Height = self:ReadNFT(lines)\
  5530.                                 elseif self.Format == 'nfp' or self.Format == 'paint' then\
  5531.                                         self.Image, self.Width, self.Height = self:ReadNFP(lines)\
  5532.                                 elseif self.Format == 'skch' or self.Format == 'sketch' then\
  5533.                                         self.Image, self.Width, self.Height = self:ReadSKCH(content)\
  5534.                                 end\
  5535.                                 if (width ~= self.Width or height ~= self.Height) then\
  5536.                                         self.Bedrock:GetObject('WebView'):RepositionLayout()\
  5537.                                 end\
  5538.                         end\
  5539.                 end)\
  5540.         end\
  5541. end\
  5542. \
  5543. DetermineFormat = function(self, content)\
  5544.         if type(textutils.unserialize(content)) == 'table' then\
  5545.                 -- It's a serlized table, asume sketch\
  5546.                 return 'skch'\
  5547.         elseif string.find(content, string.char(30)) or string.find(content, string.char(31)) then\
  5548.                 -- Contains the characters that set colours, asume nft\
  5549.                 return 'nft'\
  5550.         else\
  5551.                 -- Otherwise asume nfp\
  5552.                 return 'nfp'\
  5553.         end\
  5554. end\
  5555. \
  5556. ReadSKCH = function(self, content)\
  5557.         local _layers = textutils.unserialize(content)\
  5558.         local layers = {}\
  5559. \
  5560.         local width, height = 1, 1\
  5561. \
  5562.         for i, layer in ipairs(_layers) do\
  5563.                 if layer.Visible then\
  5564.                         local nft, w, h = self:ReadNFT(layer.Pixels)\
  5565.                         if w > width then\
  5566.                                 width = w\
  5567.                         end\
  5568.                         if h > height then\
  5569.                                 height = h\
  5570.                         end\
  5571.                         table.insert(layers, nft)\
  5572.                 end\
  5573.         end\
  5574. \
  5575.         --flatten the layers\
  5576.         local image = {\
  5577.                 text = {},\
  5578.                 textcol = {}\
  5579.         }\
  5580. \
  5581.         for i, layer in ipairs(layers) do\
  5582.                 for y, row in ipairs(layer) do\
  5583.                         if not image[y] then\
  5584.                                 image[y] = {}\
  5585.                         end\
  5586.                         for x, pixel in ipairs(row) do\
  5587.                                 if not image[y][x] or pixel ~= colours.transparent then\
  5588.                                         image[y][x] = pixel\
  5589.                                 end\
  5590.                         end\
  5591.                 end\
  5592.                 for y, row in ipairs(layer.text) do\
  5593.                         if not image.text[y] then\
  5594.                                 image.text[y] = {}\
  5595.                         end\
  5596.                         for x, pixel in ipairs(row) do\
  5597.                                 if not image.text[y][x] or pixel ~= ' ' then\
  5598.                                         image.text[y][x] = pixel\
  5599.                                 end\
  5600.                         end\
  5601.                 end\
  5602.                 for y, row in ipairs(layer.textcol) do\
  5603.                         if not image.textcol[y] then\
  5604.                                 image.textcol[y] = {}\
  5605.                         end\
  5606.                         for x, pixel in ipairs(row) do\
  5607.                                 if not image.textcol[y][x] or layer.text[y][x] ~= ' ' then\
  5608.                                         image.textcol[y][x] = pixel\
  5609.                                 end\
  5610.                         end\
  5611.                 end\
  5612.         end\
  5613. \
  5614.         return image, width, height\
  5615. end\
  5616. \
  5617. local function getColourOf(hex)\
  5618.         if hex == ' ' then\
  5619.                 return colours.transparent\
  5620.         end\
  5621.    local value = tonumber(hex, 16)\
  5622.    if not value then return nil end\
  5623.    value = math.pow(2,value)\
  5624.    return value\
  5625. end\
  5626. \
  5627. ReadNFP = function(self, lines)\
  5628.         local image = {}\
  5629.         local y = 1\
  5630.         for y, line in ipairs(lines) do\
  5631.                 for x = 1, #line do\
  5632.                         if not image[x] then\
  5633.                                 image[x] = {}\
  5634.                         end\
  5635.                         image[x][y] = getColourOf(line:sub(x,x))\
  5636.                 end\
  5637.                 line = file.readLine()\
  5638.         end\
  5639.         file.close()\
  5640.         return image, #image, #image[1]\
  5641. end\
  5642. \
  5643. ReadNFT = function(self, lines)\
  5644.         local image = {\
  5645.                 text = {},\
  5646.                 textcol = {}\
  5647.         }\
  5648.         for num, sLine in ipairs(lines) do\
  5649.        table.insert(image, num, {})\
  5650.        table.insert(image.text, num, {})\
  5651.        table.insert(image.textcol, num, {})\
  5652.        local writeIndex = 1\
  5653.        local bgNext, fgNext = false, false\
  5654.        local currBG, currFG = nil,nil\
  5655.        for i=1,#sLine do\
  5656.                local nextChar = string.sub(sLine, i, i)\
  5657.                if nextChar:byte() == 30 then\
  5658.                        bgNext = true\
  5659.                elseif nextChar:byte() == 31 then\
  5660.                        fgNext = true\
  5661.                elseif bgNext then\
  5662.                        currBG = Drawing.GetColour(nextChar)\
  5663.                             if currBG == nil then\
  5664.                                 currBG = colours.transparent\
  5665.                             end\
  5666.                        bgNext = false\
  5667.                elseif fgNext then\
  5668.                        currFG = Drawing.GetColour(nextChar)\
  5669.                             if currFG == nil or currFG == colours.transparent then\
  5670.                                 currFG = colours.white\
  5671.                             end\
  5672.                        fgNext = false\
  5673.                else\
  5674.                        if nextChar ~= \" \" and currFG == nil then\
  5675.                                currFG = colours.white\
  5676.                        end\
  5677.                        image[num][writeIndex] = currBG\
  5678.                        image.textcol[num][writeIndex] = currFG\
  5679.                        image.text[num][writeIndex] = nextChar\
  5680.                        writeIndex = writeIndex + 1\
  5681.                end\
  5682.        end\
  5683.    end\
  5684.         return image, #image[1], #image\
  5685. end",["CenterView.lua"]="Inherit = 'View'\
  5686. \
  5687. OnUpdate = function(self, value)\
  5688.         if value == 'Children' or value == 'Width' then\
  5689.                 local y = 1\
  5690.                 for i, v in ipairs(self.Children) do\
  5691.                         v.Y = y\
  5692.                         y = y + v.Height\
  5693.                         v.X = math.floor((self.Width - v.Width) / 2) + 1\
  5694.                 end\
  5695.                 self.Height = y - 1\
  5696.         end\
  5697. end",["DividerView.lua"]="Inherit = 'View'\
  5698. Char = nil\
  5699. \
  5700. OnDraw = function(self, x, y)\
  5701.         if self.BackgroundColour then\
  5702.                 if self.Char then\
  5703.                         Drawing.DrawArea (x, y, self.Width, self.Height, self.Char, self.TextColour, self.BackgroundColour)\
  5704.                 else\
  5705.                         Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
  5706.                 end\
  5707.         end\
  5708. end",["LinkView.lua"]="Inherit = 'View'\
  5709. Height = 2\
  5710. UnderlineColour = colours.blue\
  5711. UnderlineVisible = true\
  5712. \
  5713. OnLoad = function(self)\
  5714.         if self.Text and #self.Text > 0 then\
  5715.                 self:AddObject({\
  5716.                         Y = 1,\
  5717.                         X = 1,\
  5718.                         Width = self.Width,\
  5719.                         Align = self.Align,\
  5720.                         Type = \"Label\",\
  5721.                         Text = self.Text,\
  5722.                         TextColour = self.TextColour,\
  5723.                         BackgroundColour = self.BackgroundColour\
  5724.                 })\
  5725.         end\
  5726. end\
  5727. \
  5728. OnRecalculateStart = function(self)\
  5729.         self:RemoveObject('UnderlineLabel')\
  5730. end\
  5731. \
  5732. OnRecalculateEnd = function(self, currentY)\
  5733.         if self.UnderlineVisible then\
  5734.                 local underline = ''\
  5735.                 local len = self.Width\
  5736.                 if self.Text then\
  5737.                         len = #self.Text\
  5738.                 end\
  5739. \
  5740.                 for i = 1, len do\
  5741.                         underline = underline .. '-'\
  5742.                 end\
  5743.                 local col = self.UnderlineColour\
  5744.                 if self.UnderlineColour == nil then\
  5745.                         col = self.TextColour\
  5746.                 end\
  5747. \
  5748.                 local ul = self:AddObject({\
  5749.                         Y = currentY,\
  5750.                         X = 1,\
  5751.                         Width = self.Width,\
  5752.                         Align = self.Align,\
  5753.                         Type = \"Label\",\
  5754.                         Name = \"UnderlineLabel\",\
  5755.                         Text = underline,\
  5756.                         TextColour = col,\
  5757.                         BackgroundColour = self.BackgroundColour\
  5758.                 })      \
  5759.                 return currentY + 1\
  5760.         else\
  5761.                 return currentY\
  5762.         end\
  5763. end\
  5764. \
  5765. OnClick = function(self)\
  5766.         self.Bedrock:GetObject('WebView'):GoToURL(self.URL)\
  5767. end",["SelectView.lua"]="Inherit = 'Button'\
  5768. MenuItems = nil\
  5769. Children = {}\
  5770. Selected = nil\
  5771. \
  5772. OnUpdate = function(self, value)\
  5773.         if value == 'Height' and self.Height ~= 1 then\
  5774.                 self.Height = 1\
  5775.         end\
  5776. end\
  5777. \
  5778. Select = function(self, index)\
  5779.         if self.MenuItems[index] then\
  5780.                 local text = self.MenuItems[index].Text\
  5781.                 for i = 1, self.Width - 3 - #text do\
  5782.                         text = text .. ' '\
  5783.                 end\
  5784.                 text = text .. 'V'\
  5785.                 self.Text = text\
  5786.                 self.Selected = index\
  5787.         end\
  5788. end\
  5789. \
  5790. OnInitialise = function(self)\
  5791.         self:ClearMenuItems()\
  5792. end\
  5793. \
  5794. ClearMenuItems = function(self)\
  5795.         self.MenuItems = {}\
  5796. end\
  5797. \
  5798. AddMenuItem = function(self, item)\
  5799.         table.insert(self.MenuItems, item)\
  5800.         if not self.Selected then\
  5801.                 if #self.MenuItems ~= 0 then\
  5802.                         self:Select(1)\
  5803.                 end\
  5804.         end\
  5805. end\
  5806. \
  5807. OnClick = function(self, event, side, x, y)\
  5808.         if self:ToggleMenu({\
  5809.                 Type = \"Menu\",\
  5810.                 HideTop = true,\
  5811.                 Children = self.MenuItems\
  5812.         }, x, 1) then\
  5813.                 for i, child in ipairs(self.Bedrock.Menu.Children) do\
  5814.                         child.OnClick = function(_self, event, side, x, y)\
  5815.                                 self:Select(i)\
  5816.                         end\
  5817.                 end\
  5818.         end\
  5819. end",["WebView.lua"]="Inherit = 'ScrollView'\
  5820. URL = nil\
  5821. FakeURL = nil\
  5822. LoadingURL = nil\
  5823. Tree = nil\
  5824. BackgroundColour = colours.white\
  5825. ScriptEnvironment = nil\
  5826. Timers = nil\
  5827. Download = nil\
  5828. \
  5829. -- TODO: strip this down to remove positioning stuff\
  5830. UpdateLayout = function(self)\
  5831.         self:RemoveAllObjects()\
  5832.         self.BackgroundColour = colours.white\
  5833.         local body = self.Tree:GetElement('body')\
  5834. \
  5835.         --TODO: check that body exists, if not redirect to an error page\
  5836. \
  5837.         if body.BackgroundColour then\
  5838.                 self.BackgroundColour = body.BackgroundColour\
  5839.         end\
  5840. \
  5841.         local node = true\
  5842.         node = function(children, parentObject)\
  5843.                 local currentY = 1\
  5844.                 for i, v in ipairs(children) do\
  5845.                         local object = v:CreateObject(parentObject, currentY)\
  5846.                         if object then\
  5847.                                 v.Object = object\
  5848.                                 if v.Children and #v.Children > 0 and object.Children then\
  5849.                                         local usedY = node(v.Children, object)\
  5850.                                         if not v.Attributes.height then\
  5851.                                                 object.Height = usedY\
  5852.                                         end\
  5853.                                         object:OnUpdate('Children')\
  5854.                                 end\
  5855.                                 -- if not object.Height then\
  5856.                                 --      for k, v in pairs(object) do\
  5857.                                 --              error(v)\
  5858.                                 --      end     \
  5859.                                 --      error('Nope')\
  5860.                                 -- end\
  5861.                                 currentY = currentY + object.Height\
  5862.                         end\
  5863.                 end\
  5864.                 return currentY - 1\
  5865.         end\
  5866.         node(body.Children, self)\
  5867.         \
  5868.         self:RepositionLayout()\
  5869. \
  5870.         local head = self.Tree:GetElement('head')\
  5871.         if head then\
  5872.                 for i, child in ipairs(head.Children) do\
  5873.                         if child.Tag == 'script' then\
  5874.                                 child:InsertScript(self)\
  5875.                         end\
  5876.                 end\
  5877.         end\
  5878. end\
  5879. \
  5880. RepositionLayout = function(self)\
  5881.         local node = true\
  5882.         node = function(children, isFloat, parent)\
  5883.                 if parent.OnRecalculateStart then\
  5884.                         parent:OnRecalculateStart()\
  5885.                 end\
  5886. \
  5887.                 local currentY = 1\
  5888.                 local currentX = 1\
  5889.                 local tallestChild = 1\
  5890.                 for i, child in ipairs(children) do\
  5891.                         if child.Type ~= 'ScrollBar' then\
  5892.                                 if isFloat then\
  5893.                                         if currentX ~= 1 and parent.Width - currentX + 1 < child.Width then\
  5894.                                                 currentX = 1\
  5895.                                                 currentY = currentY + tallestChild\
  5896.                                                 tallestChild = 1\
  5897.                                         end\
  5898. \
  5899.                                         if parent.Align == \"Left\" then\
  5900.                                                 child.X = currentX\
  5901.                                         elseif parent.Align == \"Right\" then\
  5902.                                                 child.X = parent.Width - currentX - child.Width + 2\
  5903.                                         end\
  5904.                                 end\
  5905.                                 child.Y = currentY\
  5906. \
  5907.                                 if child.Children and #child.Children > 0 then\
  5908.                                         local usedY = node(child.Children, child.IsFloat, child)\
  5909.                                         child:OnUpdate('Children')\
  5910.                                         if not child.Element.Attributes.height then\
  5911.                                                 child.Height = usedY\
  5912.                                         end\
  5913.                                 end\
  5914. \
  5915.                                 if child.Height > tallestChild then\
  5916.                                         tallestChild = child.Height\
  5917.                                 end\
  5918. \
  5919.                                 if isFloat then\
  5920.                                         currentX = currentX + child.Width\
  5921.                                 else\
  5922.                                         currentY = currentY + child.Height\
  5923.                                 end\
  5924.                         end\
  5925.                 end\
  5926.                 if isFloat then\
  5927.                         currentY = currentY + tallestChild\
  5928.                 end\
  5929.                 if parent.OnRecalculateEnd then\
  5930.                         currentY = parent:OnRecalculateEnd(currentY)\
  5931.                 end\
  5932.                 return currentY - 1\
  5933.         end\
  5934.         node(self.Children, self.IsFloat, self)\
  5935. \
  5936.         self:UpdateScroll()\
  5937. end\
  5938. \
  5939. GoToURL = function(self, url, nonVerbose, noHistory, post)\
  5940.         self.BackgroundColour = colours.white\
  5941.         self:RemoveAllObjects()\
  5942.         if self.OnPageLoadStart and not nonVerbose then\
  5943.                 self:OnPageLoadStart(url, noHistory)\
  5944.         end\
  5945.         self.LoadingURL = url\
  5946.         self.FakeURL = url\
  5947.         self:InitialiseScriptEnvironment()\
  5948. \
  5949.         if not http and url:find('http://') then\
  5950.                 if self.OnPageLoadFailed then\
  5951.                         self:OnPageLoadFailed(url, 4, noHistory)\
  5952.                 end\
  5953.                 return\
  5954.         end\
  5955. \
  5956.         -- error(fs.getName(url))\
  5957.         local parts = urlComponents(url)\
  5958.         -- if url:sub(#url) ~= '/' and url:find('?') then\
  5959.         --      fileName = fs.getName(url:sub(1, url:find('?') - 1))\
  5960.         -- else\
  5961.         --      fileName = fs.getName(url)\
  5962.         -- end\
  5963. \
  5964.         local fileName = parts.filename\
  5965.         local extension\
  5966.         if fileName == '' or url:sub(#url) == '/' then\
  5967.                 extension = true\
  5968.         else\
  5969.                 extension = fileName:match('%.[0-9a-z%?%%]+$')\
  5970.                 if extension then\
  5971.                         extension = extension:sub(2)\
  5972.                 end\
  5973.         end\
  5974. \
  5975.         if not url:find('quest://download.ccml') and not url:find('quest://downloaded.ccml') then\
  5976.                 self.Download = nil\
  5977.         else\
  5978.                 extension = true\
  5979.         end\
  5980. \
  5981.         -- TODO: 404s are counted as downloads\
  5982. \
  5983.         if not extension or (extension ~= true and extension ~= '' and extension ~= 'ccml' and extension ~= 'html' and extension ~= 'php' and extension ~= 'asp' and extension ~= 'aspx' and extension ~= 'jsp' and extension ~= 'qst' and extension ~= 'com' and extension ~= 'me' and extension ~= 'net' and extension ~= 'info' and extension ~= 'au' and extension ~= 'nz') then\
  5984.                 local downloadsFolder = '/Downloads/'\
  5985.                 if OneOS then\
  5986.                         downloadsFolder = '/Desktop/Documents/Downloads/'\
  5987.                 end\
  5988.                 if not fs.exists(downloadsFolder) then\
  5989.                         fs.makeDir(downloadsFolder)\
  5990.                 end\
  5991. \
  5992.                 local downloadPath = downloadsFolder..fileName\
  5993.                 local i = 1\
  5994.                 while fs.exists(downloadPath) do\
  5995.                         i = i + 1\
  5996.                         downloadPath = downloadsFolder..fileName .. ' (' .. i .. ')'\
  5997.                 end\
  5998. \
  5999.                 self.Download = url\
  6000.                 fetchHTTPAsync(url, function(ok, event, response)\
  6001.                         if self.Download == url then\
  6002.                                 self.Download = nil\
  6003.                                 if ok then\
  6004.                                         if response.getResponseCode then\
  6005.                                                 local code = response.getResponseCode()\
  6006.                                                 if code ~= 200 then\
  6007.                                                         self:OnPageLoadFailed(url, 6, noHistory)\
  6008.                                                         response.close()\
  6009.                                                         return\
  6010.                                                 end\
  6011.                                         end\
  6012.                                         local f = fs.open(downloadPath, 'w')\
  6013.                                         if f then\
  6014.                                                 f.write(response.readAll())\
  6015.                                                 f.close()\
  6016.                                                 self:GoToURL('quest://downloaded.ccml?path='..textutils.urlEncode(downloadPath), true, true)\
  6017.                                         else\
  6018.                                                 self:OnPageLoadFailed(url, 6, noHistory)\
  6019.                                         end\
  6020.                                         response.close()\
  6021.                                 else\
  6022.                                         self:OnPageLoadFailed(url, 6, noHistory)\
  6023.                                 end\
  6024.                         end\
  6025.                 end)\
  6026. \
  6027.                 self:GoToURL('quest://download.ccml?path='..textutils.urlEncode(downloadPath), true, true)\
  6028.                 self:OnPageLoadEnd(url, noHistory)\
  6029.         else\
  6030.                 fetchHTTPAsync(url, function(ok, event, response)\
  6031.                         self.LoadingURL = nil\
  6032.                         if ok then\
  6033.                                 if response.getResponseCode then\
  6034.                                         local code = response.getResponseCode()\
  6035.                                         if code ~= 200 then\
  6036.                                                 if self.OnPageLoadFailed then\
  6037.                                                         self:OnPageLoadFailed(url, code, noHistory)\
  6038.                                                 end\
  6039.                                                 response.close()\
  6040.                                                 return\
  6041.                                         end\
  6042.                                 end\
  6043. \
  6044.                                 self.Tree, err = ElementTree:Initialise(response.readAll())\
  6045.                                 response.close()\
  6046.                                 if not err then\
  6047.                                         self.URL = url\
  6048.                                         self:UpdateLayout()\
  6049.                                         if self.OnPageLoadEnd and not nonVerbose then\
  6050.                                                 self:OnPageLoadEnd(url, noHistory)\
  6051.                                         end\
  6052.                                 else\
  6053.                                         if self.OnPageLoadFailed then\
  6054.                                                 self:OnPageLoadFailed(url, err, noHistory)\
  6055.                                         end\
  6056.                                 end\
  6057.                         elseif self.OnPageLoadFailed and not nonVerbose then\
  6058.                                 self:OnPageLoadFailed(url, event, noHistory)\
  6059.                         end\
  6060.                 end, post)\
  6061.         end\
  6062. end\
  6063. \
  6064. Stop = function(self)\
  6065.         cancelHTTPAsync(self.LoadingURL)\
  6066.         if self.OnPageLoadFailed then\
  6067.                 self:OnPageLoadFailed(url, Errors.TimeoutStop)\
  6068.         end\
  6069. end\
  6070. \
  6071. ResolveElements = function(self, selector)\
  6072.         local elements = {}\
  6073.         local node = true\
  6074.         local isClass = false\
  6075.         if selector:sub(1,1) == '.' then\
  6076.                 isClass = true\
  6077.         end\
  6078. \
  6079.         node = function(tbl)\
  6080.                 for i,v in ipairs(tbl) do\
  6081.                         if type(v) == 'table' and v.Tag then\
  6082.                                 if not isClass and v.Tag:lower() == selector:lower() then\
  6083.                                         table.insert(elements, v.Object)\
  6084.                                 elseif isClass and v.Attributes.class and v.Attributes.class:lower() == selector:lower():sub(2) then\
  6085.                                         table.insert(elements, v.Object)\
  6086.                                 end\
  6087.                                 if v.Children then\
  6088.                                         local r = node(v.Children)\
  6089.                                 end\
  6090.                         end\
  6091.                 end\
  6092.         end\
  6093.         node(self.Tree.Tree)\
  6094.         return elements\
  6095. end\
  6096. \
  6097. InitialiseScriptEnvironment = function(self)\
  6098.         lQuery.webView = self\
  6099.         if self.Timers then\
  6100.                 for i, timer in ipairs(self.Timers) do\
  6101.                         -- error('clear '..timer)\
  6102.                         self.Bedrock.Timers[timer] = nil\
  6103.                 end\
  6104.         end\
  6105.         self.Timers = {}\
  6106. \
  6107.         local getValues = urlComponents(self.LoadingURL).get\
  6108. \
  6109.         self.ScriptEnvironment = {\
  6110.                 keys = keys,\
  6111.                 printError = printError, -- maybe don't have this\
  6112.                 assert = assert,\
  6113.                 getfenv = getfenv,\
  6114.                 bit = bit,\
  6115.                 rawset = rawset,\
  6116.                 tonumber = tonumber,\
  6117.                 loadstring = loadstring,\
  6118.                 error = error, -- maybe don't have this\
  6119.                 tostring = tostring,\
  6120.                 type = type,\
  6121.                 coroutine = coroutine,\
  6122.                 next = next,\
  6123.                 unpack = unpack,\
  6124.                 colours = colours,\
  6125.                 pcall = pcall,\
  6126.                 math = math,\
  6127.                 pairs = pairs,\
  6128.                 rawget = rawget,\
  6129.                 _G = _G,\
  6130.                 __inext = __inext,\
  6131.                 read = read,\
  6132.                 ipairs = ipairs,\
  6133.                 xpcall = xpcall,\
  6134.                 rawequal = rawequal,\
  6135.                 setfenv = setfenv,\
  6136.                 http = http, --create an ajax thing to replace this\
  6137.                 string = string,\
  6138.                 setmetatable = setmetatable,\
  6139.                 getmetatable = getmetatable,\
  6140.                 table = table,\
  6141.                 parallel = parallel, -- this mightn't work properly\
  6142.                 textutils = textutils,\
  6143.                 colors = colors,\
  6144.                 vector = vector,\
  6145.                 select = select,\
  6146.                 os = {\
  6147.                         version = os.version,\
  6148.                         getComputerID = os.getComputerID,\
  6149.                         getComputerLabel = os.getComputerLabel,\
  6150.                         clock = os.clock,\
  6151.                         time = os.time,\
  6152.                         day = os.day,\
  6153.                 },\
  6154.                 lQuery = lQuery.fn,\
  6155.                 l = lQuery.fn,\
  6156.                 setTimeout = function(func, delay)\
  6157.                         if type(func) == 'function' and type(delay) == 'number' then\
  6158.                                 local t = self.Bedrock:StartTimer(func, delay)\
  6159.                                 table.insert(self.Timers, t)\
  6160.                                 return t\
  6161.                         end\
  6162.                 end,\
  6163.                 setInterval = function(func, interval)\
  6164.                         if type(func) == 'function' and type(interval) == 'number' then\
  6165.                                 local t = self.Bedrock:StartRepeatingTimer(function(timer)\
  6166.                                         table.insert(self.Timers, timer)\
  6167.                                         func()\
  6168.                                 end, interval)\
  6169.                                 table.insert(self.Timers, t)\
  6170.                                 return t\
  6171.                         end\
  6172.                 end,\
  6173.                 clearTimeout = function(timer)\
  6174.                         self.Bedrock.Timers[timer] = nil\
  6175.                 end,\
  6176.                 clearInterval = function(timer)\
  6177.                         self.Bedrock.Timers[timer] = nil\
  6178.                 end,\
  6179.                 window = {\
  6180.                         location = self.URL,\
  6181.                         realLocation = self.LoadingURL,\
  6182.                         get = getValues,\
  6183.                         version = QuestVersion\
  6184.                 }\
  6185.         }\
  6186. end\
  6187. \
  6188. LoadScript = function(self, script)\
  6189.         local fn, err = loadstring(script, 'Script Tag Error: '..self.URL)\
  6190.         if fn then\
  6191.                 setfenv(fn, self.ScriptEnvironment)\
  6192.                 fn()\
  6193.         else\
  6194.                 local start = err:find(': ')\
  6195.                 self:OnPageLoadFailed(url, err:sub(start + 2), noHistory)\
  6196.         end\
  6197. end\
  6198. \
  6199. RemoveElement = function(self, elem)\
  6200.         local elements = {}\
  6201.         local node = true\
  6202.         node = function(tbl)\
  6203.                 for i,v in ipairs(tbl) do\
  6204.                         if type(v) == 'table' then\
  6205.                                 if v == elem.Element then\
  6206.                                         elem.Parent:RemoveObject(elem)\
  6207.                                         v = nil\
  6208.                                         return\
  6209.                                 end\
  6210.                                 if v.Children then\
  6211.                                         local r = node(v.Children)\
  6212.                                 end\
  6213.                         end\
  6214.                 end\
  6215.         end\
  6216.         node(self.Tree.Tree)\
  6217. end",["FloatView.lua"]="Inherit = 'View'\
  6218. IsFloat = true\
  6219. Align = \"Left\"",["FormView.lua"]="Inherit = 'View'\
  6220. \
  6221. OnTab = function(self)\
  6222.         local active = self.Bedrock:GetActiveObject()\
  6223.         local selected = nil\
  6224.         local selectNext = false\
  6225.         local function node(tree)\
  6226.                 for i, v in ipairs(tree) do\
  6227.                         if selectNext then\
  6228.                                 if v.Type == 'TextBox' or v.Type == 'SecureTextBox' then\
  6229.                                         selected = v\
  6230.                                         return\
  6231.                                 end\
  6232.                         elseif v == active then\
  6233.                                 selectNext = true\
  6234.                         end\
  6235.                         if v.Children then\
  6236.                                 node(v.Children)\
  6237.                         end\
  6238.                 end\
  6239.         end\
  6240.         node(self.Children)\
  6241. \
  6242.         if selected then\
  6243.                 self.Bedrock:SetActiveObject(selected)\
  6244.         end\
  6245. end",},["Views"]={["main.view"]="{\
  6246.  [\"Children\"]={\
  6247.    [1]={\
  6248.      [\"Y\"]=1,\
  6249.      [\"X\"]=1,\
  6250.      [\"Name\"]=\"Toolbar\",\
  6251.      [\"Type\"]=\"View\",\
  6252.      [\"InheritView\"]=\"toolbar\"\
  6253.    },\
  6254.    [2]={\
  6255.      [\"Y\"]=4,\
  6256.      [\"X\"]=1,\
  6257.      [\"Height\"]=\"100%,-3\",\
  6258.      [\"Width\"]=\"100%\",\
  6259.      [\"Name\"]=\"WebView\",\
  6260.      [\"Type\"]=\"WebView\"\
  6261.    },\
  6262.    [3]={\
  6263.      [\"Y\"]=1,\
  6264.      [\"X\"]=1,\
  6265.      [\"Height\"]=1,\
  6266.      [\"Width\"]=\"100%\",\
  6267.      [\"Name\"]=\"PageTitleLabel\",\
  6268.      [\"Type\"]=\"Label\",\
  6269.      [\"Align\"]=\"Center\",\
  6270.      [\"TextColour\"]=128,\
  6271.    },\
  6272.  },\
  6273.  [\"BackgroundColour\"]=1,\
  6274.  [\"ToolBarColour\"]=256,\
  6275.  [\"ToolBarTextColour\"]=1\
  6276. }",["optionsmenu.view"]="{\
  6277.  [\"Type\"]=\"Menu\",\
  6278.  [\"Owner\"]=\"OptionsButton\",\
  6279.  [\"Children\"]={\
  6280.    [1]={\
  6281.      [\"Name\"]=\"StopMenuItem\",\
  6282.      [\"Type\"]=\"Button\",\
  6283.      [\"Text\"]=\"Stop\"\
  6284.    },\
  6285.    [2]={\
  6286.      [\"Name\"]=\"ReloadMenuItem\",\
  6287.      [\"Type\"]=\"Button\",\
  6288.      [\"Text\"]=\"Reload\"\
  6289.    },\
  6290.    [3]={\
  6291.      [\"Name\"]=\"GoHomeMenuItem\",\
  6292.      [\"Type\"]=\"Button\",\
  6293.      [\"Text\"]=\"Go Home\"\
  6294.    },\
  6295.    [4]={\
  6296.      [\"Name\"]=\"SetHomeMenuItem\",\
  6297.      [\"Type\"]=\"Button\",\
  6298.      [\"Text\"]=\"Set Home\"\
  6299.    },\
  6300.    [5]={\
  6301.      [\"Name\"]=\"Separator\",\
  6302.      [\"Type\"]=\"Separator\"\
  6303.    },\
  6304.    [6]={\
  6305.      [\"Name\"]=\"QuitMenuItem\",\
  6306.      [\"Type\"]=\"Button\",\
  6307.      [\"Text\"]=\"Quit\"\
  6308.    }\
  6309.  },\
  6310. }",["toolbar.view"]="{\
  6311.  [\"Width\"]=\"100%\",\
  6312.  [\"Height\"]=3,\
  6313.  [\"Type\"]=\"View\",\
  6314.  [\"BackgroundColour\"]=256,\
  6315.  [\"Children\"]={\
  6316.    [1]={\
  6317.      [\"Y\"]=2,\
  6318.      [\"X\"]=2,\
  6319.      [\"Name\"]=\"BackButton\",\
  6320.      [\"Type\"]=\"Button\",\
  6321.      [\"Enabled\"]=false,\
  6322.      [\"TextColour\"]=128,\
  6323.      [\"Text\"]=\"<\",\
  6324.      [\"BackgroundColour\"]=1\
  6325.    },\
  6326.    [2]={\
  6327.      [\"Y\"]=2,\
  6328.      [\"X\"]=6,\
  6329.      [\"Name\"]=\"ForwardButton\",\
  6330.      [\"Type\"]=\"Button\",\
  6331.      [\"Enabled\"]=false,\
  6332.      [\"TextColour\"]=128,\
  6333.      [\"Text\"]=\">\",\
  6334.      [\"BackgroundColour\"]=1\
  6335.    },\
  6336.    [3]={\
  6337.      [\"Y\"]=2,\
  6338.      [\"X\"]=10,\
  6339.      [\"Width\"]=\"100%,-14\",\
  6340.      [\"Type\"]=\"View\",\
  6341.      [\"BackgroundColour\"]=1\
  6342.    },\
  6343.    [4]={\
  6344.      [\"Y\"]=2,\
  6345.      [\"X\"]=10,\
  6346.      [\"Width\"]=\"100%,-14\",\
  6347.      [\"Name\"]=\"URLTextBox\",\
  6348.      [\"Type\"]=\"TextBox\",\
  6349.      [\"TextColour\"]=128,\
  6350.      [\"Placeholder\"]=\"Website URL...\",\
  6351.      [\"PlaceholderTextColour\"]=256,\
  6352.      [\"BackgroundColour\"]=0,\
  6353.      [\"SelectOnClick\"]=true\
  6354.    },\
  6355.    [5]={\
  6356.      [\"Y\"]=2,\
  6357.      [\"X\"]=10,\
  6358.      [\"Width\"]=\"100%,-14\",\
  6359.      [\"Name\"]=\"LoadingLabel\",\
  6360.      [\"Type\"]=\"Label\",\
  6361.      [\"TextColour\"]=256,\
  6362.      [\"Text\"]=\"Loading...\",\
  6363.      [\"BackgroundColour\"]=1,\
  6364.      [\"Align\"]=\"Center\",\
  6365.      [\"Visible\"]=false\
  6366.    },\
  6367.    [6]={\
  6368.      [\"Y\"]=2,\
  6369.      [\"X\"]=\"100%,-3\",\
  6370.      [\"Name\"]=\"OptionsButton\",\
  6371.      [\"Type\"]=\"Button\",\
  6372.      [\"Text\"]=\"V\",\
  6373.      [\"TextColour\"]=128,\
  6374.      [\"BackgroundColour\"]=1\
  6375.    },\
  6376.  },\
  6377. }",},}
  6378.  
  6379. local function run(tArgs)
  6380.  
  6381.   local fnFile, err = loadstring(files['startup'], 'startup')
  6382.   if err then
  6383.     error(err)
  6384.   end
  6385.  
  6386.   local function split(str, pat)
  6387.      local t = {}
  6388.      local fpat = "(.-)" .. pat
  6389.      local last_end = 1
  6390.      local s, e, cap = str:find(fpat, 1)
  6391.      while s do
  6392.         if s ~= 1 or cap ~= "" then
  6393.      table.insert(t,cap)
  6394.         end
  6395.         last_end = e+1
  6396.         s, e, cap = str:find(fpat, last_end)
  6397.      end
  6398.      if last_end <= #str then
  6399.         cap = str:sub(last_end)
  6400.         table.insert(t, cap)
  6401.      end
  6402.      return t
  6403.   end
  6404.  
  6405.   local function resolveTreeForPath(path, single)
  6406.     local _files = files
  6407.     local parts = split(path, '/')
  6408.     if parts then
  6409.       for i, v in ipairs(parts) do
  6410.         if #v > 0 then
  6411.           if _files[v] then
  6412.             _files = _files[v]
  6413.           else
  6414.             _files = nil
  6415.             break
  6416.           end
  6417.         end
  6418.       end
  6419.     elseif #path > 0 and path ~= '/' then
  6420.       _files = _files[path]
  6421.     end
  6422.     if not single or type(_files) == 'string' then
  6423.       return _files
  6424.     end
  6425.   end
  6426.  
  6427.   local oldFs = fs
  6428.   local env
  6429.   env = {
  6430.     fs = {
  6431.       list = function(path)
  6432.               local list = {}
  6433.               if fs.exists(path) then
  6434.             list = fs.list(path)
  6435.               end
  6436.         for k, v in pairs(resolveTreeForPath(path)) do
  6437.           if not fs.exists(path .. '/' ..k) then
  6438.             table.insert(list, k)
  6439.           end
  6440.         end
  6441.         return list
  6442.       end,
  6443.  
  6444.       exists = function(path)
  6445.         if fs.exists(path) then
  6446.           return true
  6447.         elseif resolveTreeForPath(path) then
  6448.           return true
  6449.         else
  6450.           return false
  6451.         end
  6452.       end,
  6453.  
  6454.       isDir = function(path)
  6455.         if fs.isDir(path) then
  6456.           return true
  6457.         else
  6458.           local tree = resolveTreeForPath(path)
  6459.           if tree and type(tree) == 'table' then
  6460.             return true
  6461.           else
  6462.             return false
  6463.           end
  6464.         end
  6465.       end,
  6466.  
  6467.       isReadOnly = function(path)
  6468.         if not fs.isReadOnly(path) then
  6469.           return false
  6470.         else
  6471.           return true
  6472.         end
  6473.       end,
  6474.  
  6475.       getName = fs.getName,
  6476.  
  6477.       getSize = fs.getSize,
  6478.  
  6479.       getFreespace = fs.getFreespace,
  6480.  
  6481.       makeDir = fs.makeDir,
  6482.  
  6483.       move = fs.move,
  6484.  
  6485.       copy = fs.copy,
  6486.  
  6487.       delete = fs.delete,
  6488.  
  6489.       combine = fs.combine,
  6490.  
  6491.       open = function(path, mode)
  6492.         if fs.exists(path) then
  6493.           return fs.open(path, mode)
  6494.         elseif type(resolveTreeForPath(path)) == 'string' then
  6495.           local handle = {close = function()end}
  6496.           if mode == 'r' then
  6497.             local content = resolveTreeForPath(path)
  6498.             handle.readAll = function()
  6499.               return content
  6500.             end
  6501.  
  6502.             local line = 1
  6503.             local lines = split(content, '\n')
  6504.             handle.readLine = function()
  6505.               if line > #lines then
  6506.                 return nil
  6507.               else
  6508.                 return lines[line]
  6509.               end
  6510.               line = line + 1
  6511.             end
  6512.                       return handle
  6513.           else
  6514.             error('Cannot write to read-only file (compilr archived).')
  6515.           end
  6516.         else
  6517.           return fs.open(path, mode)
  6518.         end
  6519.       end
  6520.     },
  6521.  
  6522.     loadfile = function( _sFile )
  6523.         local file = env.fs.open( _sFile, "r" )
  6524.         if file then
  6525.             local func, err = loadstring( file.readAll(), fs.getName( _sFile ) )
  6526.             file.close()
  6527.             return func, err
  6528.         end
  6529.         return nil, "File not found: ".._sFile
  6530.     end,
  6531.  
  6532.     dofile = function( _sFile )
  6533.         local fnFile, e = env.loadfile( _sFile )
  6534.         if fnFile then
  6535.             setfenv( fnFile, getfenv(2) )
  6536.             return fnFile()
  6537.         else
  6538.             error( e, 2 )
  6539.         end
  6540.     end
  6541.   }
  6542.  
  6543.   setmetatable( env, { __index = _G } )
  6544.  
  6545.   local tAPIsLoading = {}
  6546.   env.os.loadAPI = function( _sPath )
  6547.       local sName = fs.getName( _sPath )
  6548.       if tAPIsLoading[sName] == true then
  6549.           printError( "API "..sName.." is already being loaded" )
  6550.           return false
  6551.       end
  6552.       tAPIsLoading[sName] = true
  6553.          
  6554.       local tEnv = {}
  6555.       setmetatable( tEnv, { __index = env } )
  6556.       local fnAPI, err = env.loadfile( _sPath )
  6557.       if fnAPI then
  6558.           setfenv( fnAPI, tEnv )
  6559.           fnAPI()
  6560.       else
  6561.           printError( err )
  6562.           tAPIsLoading[sName] = nil
  6563.           return false
  6564.       end
  6565.      
  6566.       local tAPI = {}
  6567.       for k,v in pairs( tEnv ) do
  6568.           tAPI[k] =  v
  6569.       end
  6570.      
  6571.       env[sName] = tAPI    
  6572.       tAPIsLoading[sName] = nil
  6573.       return true
  6574.   end
  6575.  
  6576.   env.shell = shell
  6577.  
  6578.   setfenv( fnFile, env )
  6579.   fnFile(unpack(tArgs))
  6580. end
  6581.  
  6582. local function extract()
  6583.     local function node(path, tree)
  6584.         if type(tree) == 'table' then
  6585.             fs.makeDir(path)
  6586.             for k, v in pairs(tree) do
  6587.                 node(path .. '/' .. k, v)
  6588.             end
  6589.         else
  6590.             local f = fs.open(path, 'w')
  6591.             if f then
  6592.                 f.write(tree)
  6593.                 f.close()
  6594.             end
  6595.         end
  6596.     end
  6597.     node('', files)
  6598. end
  6599.  
  6600. local tArgs = {...}
  6601. if #tArgs == 1 and tArgs[1] == '--extract' then
  6602.   extract()
  6603. else
  6604.   run(tArgs)
  6605. end
RAW Paste Data