Advertisement
LDDestroier

STD-GUI (ComputerCraft)

Apr 21st, 2016
6,544
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 47.92 KB | None | 0 0
  1. --[[
  2.     STD Graphical User Interface! (STD-GUI)!
  3.     Made by LDDestroier/EldidiStroyrr (same guy)
  4.  
  5.     This program is a standalone GUI for Super Text Downloader, or STD for short.
  6.     It has category sorting, program searching, smooth scrolling, and run support (not just download)
  7.     This will tell you if you're overwriting a file, so no worry.
  8.  
  9.     pastebin get P9dDhQ2m stdgui
  10.     std PB P9dDhQ2m stdgui
  11.     wget https://github.com/LDDestroier/STD-GUI/raw/master/stdgui.lua
  12.     std ld stdgui stdgui
  13.  
  14.     This is a stable release. You fool!
  15. --]]
  16.  
  17. local useSetVisible = false
  18.  
  19. local tsv = function(visible)
  20.     if term.current().setVisible and useSetVisible then
  21.         term.current().setVisible(visible) -- comment out if you are debugging
  22.     end
  23. end
  24.  
  25. local isBeta = false -- changes the update URL
  26. if type(std) ~= "table" then std = {} end
  27.  
  28. std.updateURL = {
  29.     ["stable"]  = "https://raw.githubusercontent.com/LDDestroier/STD-GUI/master/stdgui.lua",
  30.     ["beta"]    = "https://raw.githubusercontent.com/LDDestroier/STD-GUI/beta/stdgui.lua"
  31. }
  32.  
  33. if not http then
  34.     return false, printError("HTTP must be enabled to use STD. Contact an administrator for assistance.")
  35. else
  36.     if not http.checkURL("http://github.com") then
  37.         return false, printError("For some reason, Github.com is whitelisted. Abort.")
  38.     end
  39. end
  40. local scr_x, scr_y = term.getSize()
  41.  
  42. local doDisplayTitle = false
  43. local relativePath = false
  44. local doColorize = true
  45.  
  46. std.std_version = 101 -- to prevent updating to std command line
  47.  
  48. local overrideNoOS = false  -- prevent custom OS installer functionality
  49.  
  50. std.channel = "STD"
  51. std.prevChannel = std.channel
  52.  
  53. std.channelURLs = { --special pastebin URLs for getting a list of files.
  54.     ["STD"] = "https://raw.githubusercontent.com/LDDestroier/STD-GUI/master/list.lua", -- default store list on github, more updated
  55. --  ["STD PB"] = "http://pastebin.com/raw/zVws7eLq",    -- default store list on pastebin, but just use github, man
  56.     ["Discover"] = "http://pastebin.com/raw/9bXfCz6M",  -- owned by dannysmc95
  57. --  ["OnlineAPPS"] = "http://pastebin.com/raw/g2EnDYLp",    -- owned by Twijn, but discontinued.
  58.     ["STD-Media"] = "https://pastebin.com/raw/3JZHXTGL",    -- list of pictures and music
  59. }
  60. local palate -- yes I know shut up
  61. palate = {
  62.     pleasewait = {
  63.         txt = colors.lightGray,
  64.         bg = colors.black,
  65.     },
  66.     store = {
  67.         bg = colors.black,
  68.         txt = colors.white,
  69.         bgchar = " ",
  70.         entrybg = colors.gray,
  71.         entrytxt = colors.white,
  72.         entryasterisk = colors.lightGray,
  73.         closetxt = colors.white,
  74.         closebg = colors.red,
  75.         previewtxt = colors.white,
  76.         previewbg = colors.cyan,
  77.         findbg = colors.white,
  78.         findtxt = colors.black,
  79.         indicatetxt = colors.black,
  80.         indicatebg = colors.white,
  81.         theendtxt = colors.gray,
  82.         scrollbar = {
  83.             knobbg = colors.black,
  84.             knobtxt = colors.gray,
  85.             knobchar = "|",
  86.             barbg = colors.lightGray,
  87.             bartxt = colors.gray,
  88.             barchar = "|",
  89.         }
  90.     },
  91.     item = {
  92.         bg = colors.gray,
  93.         txt = colors.white,
  94.         specialtxt = colors.yellow,
  95.         previewtxt = colors.white,
  96.         previewbg = colors.black,
  97.         forumtxt = colors.lightGray,
  98.         forumbg = colors.gray,
  99.         closetxt = colors.white,
  100.         closebg = colors.red,
  101.         runtxt = colors.white,
  102.         runbg = colors.green,
  103.         downloadtxt = colors.white,
  104.         downloadbg = colors.green,
  105.     },
  106.     menubar = {
  107.         bg = colors.black,
  108.         categorytxt = colors.lightGray,
  109.         categorybg = colors.black,
  110.         channeltxt = colors.lightGray,
  111.         channelbg = colors.black,
  112.         hotkeytxt = colors.gray,
  113.         categorymenu = {
  114.             selecttxt = colors.lightGray,
  115.             selectbg = colors.black,
  116.             bg = colors.black,
  117.             txt = colors.lightGray,
  118.             orbtxt = colors.black,
  119.             cursortxt = colors.black,
  120.             cursorbg = colors.lightGray,
  121.             borderbg = colors.black,
  122.         },
  123.         channelmenu = {
  124.             selecttxt = colors.lightGray,
  125.             selectbg = colors.black,
  126.             bg = colors.lightGray,
  127.             txt = colors.lightGray,
  128.             orbtxt = colors.black,
  129.             cursortxt = colors.black,
  130.             cursorbg = colors.lightGray,
  131.             borderbg = colors.black,
  132.         }
  133.     }
  134. }
  135.  
  136. local getEvents = function(...)     -- basically os.pullEvent() but with multiple filters
  137.     local arg, output = table.pack(...)
  138.     while true do
  139.         output = {os.pullEvent()}
  140.         for a = 1, #arg do
  141.             if type(arg[a]) == "boolean" then
  142.                 if doRender == arg[a] then
  143.                     return {}
  144.                 end
  145.             elseif output[1] == arg[a] then
  146.                 return unpack(output)
  147.             end
  148.         end
  149.     end
  150. end
  151.  
  152. local charClear = function(char)
  153.     local cx,cy = term.getCursorPos()
  154.     for y = 1, scr_y do
  155.         term.setCursorPos(1,y)
  156.         term.write(char:sub(1,1):rep(scr_x))
  157.     end
  158.     term.setCursorPos(cx,cy)
  159. end
  160.  
  161. std.channelNames = {}
  162. for k,v in pairs(std.channelURLs) do
  163.     table.insert(std.channelNames,k)
  164. end
  165.  
  166. std.stdList = "."..std.channel:lower().."_list"
  167.  
  168. std.currentOS = "CraftOS" -- enables integration into operating systems
  169. if not overrideNoOS then
  170.     if (fs.isDir("SimSoft/Data") and fs.isDir("SimSoft/SappS")) then -- checks if SimSoft is installed
  171.         std.currentOS = "SimSoft"
  172.  
  173.     elseif (fs.exists("Axiom/sys.lua") or fs.exists("Axiom/sys.axs")) then  -- checks if Axiom is installed
  174.         std.currentOS = "AxiomUI"
  175.  
  176.     elseif (fs.isDir("sys") and fs.isDir("usr") and fs.exists("sys/kernel.lua") and fs.exists("sys/boot/opus.boot")) then
  177.         std.currentOS = "OpusOS"
  178.  
  179.     elseif (fs.isDir("Nova") and fs.isDir("Nova/apps")) then
  180.         std.currentOS = "NovaHorizon"
  181.     end
  182. end
  183.  
  184. local cprint = function(txt,y)
  185.     local cX,cY = term.getCursorPos()
  186.     term.setCursorPos(math.ceil(scr_x/2)-math.floor(#txt/2),y or cY)
  187.     term.write(txt)
  188. end
  189.  
  190. local scroll = 1    -- one is the loneliest number...weeb
  191. local scrollX = 1   -- to view longer program names
  192. local maxScroll
  193.  
  194. local setMaxScroll = function(catagory)
  195.     local output = 0
  196.     for k,v in pairs(std.storeURLs) do
  197.         if (v.catagory == catagory) or catagory == 0 then
  198.             output = output + 1
  199.         end
  200.     end
  201.     return (output*4)-(scr_y-4)
  202. end
  203. local catag = 0
  204.  
  205. local pleaseWait = function(text)
  206.     term.setBackgroundColor(palate.pleasewait.bg)
  207.     term.setTextColor(palate.pleasewait.txt)
  208.     term.clear()
  209.     cprint(text or "Getting list...please wait",scr_y/2)
  210. end
  211.  
  212. local coolPleaseWait = function()
  213.     local scr_x, scr_y = term.getSize()
  214.     local cols = "f7"
  215.     local length = scr_x/2
  216.     local render = function(col1,col2,prog,forwards)
  217.         term.setCursorPos(1,1)
  218.         local screen = (col1:rep(prog)..col2:rep(length-prog)):rep(scr_x*scr_y):sub(1,(scr_x*scr_y))
  219.         local line
  220.         for a = forwards and 1 or scr_y, forwards and scr_y or 1, forwards and 1 or -1 do
  221.             line = screen:sub((a-1)*scr_x+1,a*scr_x)
  222.             term.setCursorPos(1,a)
  223.             term.blit(("L"):rep(#line),line,line)
  224.         end
  225.     end
  226.     local pos1 = 2
  227.     local pos2 = pos1 - 1
  228.     local forwards = true
  229.     local reverse = false
  230.     while true do
  231.         for a = reverse and length or 1, reverse and 1 or length, reverse and -1 or 1 do
  232.             render(cols:sub(pos1,pos1),cols:sub(pos2,pos2),a,forwards)
  233.             sleep(0.0)
  234.         end
  235.            forwards = not forwards
  236.         reverse = not reverse
  237.         pos1 = (pos1 + 1)
  238.         pos2 = (pos2 + 1)
  239.         if pos1 > #cols then pos1 = 1 end
  240.         if pos2 > #cols then pos2 = 1 end
  241.     end
  242. end
  243.  
  244. local setDefaultColors = function()
  245.     term.setBackgroundColor(palate.store.bg)
  246.     term.setTextColor(palate.store.txt)
  247. end
  248.  
  249. local displayHelp = function(cli)
  250.     local helptext = [[
  251. This is a graphical interface to the STD downloader program.
  252. Use 'stdgui update' to update the list, or use 'F5'.
  253. If you want your program on it, PM LDDestroier on the CC forums.
  254. Hotkeys:
  255.     'Q' quit or back
  256.     'F5' refresh
  257.     'F1' set category
  258.     'F3' set channel
  259.     'F' or 'F6' search
  260.     'F12' update STDGUI
  261.     if normal computer, press 0-9 to select store item
  262. ]]
  263.     if cli then
  264.         return print(helptext)
  265.     else
  266.         setDefaultColors()
  267.         term.clear()
  268.         term.setCursorPos(2,2)
  269.         print(helptext)
  270.         sleep(0)
  271.         print("\nPress a key to go back.")
  272.         os.pullEvent("key")
  273.         return
  274.     end
  275. end
  276.  
  277. local getTableSize = function(tbl)
  278.     local amnt = 0
  279.     for k,v in pairs(tbl) do
  280.         amnt = amnt + 1
  281.     end
  282.     return amnt
  283. end
  284.  
  285. local colors_names = {
  286.     ["0"] = colors.white,
  287.     ["1"] = colors.orange,
  288.     ["2"] = colors.magenta,
  289.     ["3"] = colors.lightBlue,
  290.     ["4"] = colors.yellow,
  291.     ["5"] = colors.lime,
  292.     ["6"] = colors.pink,
  293.     ["7"] = colors.gray,
  294.     ["8"] = colors.lightGray,
  295.     ["9"] = colors.cyan,
  296.     ["a"] = colors.purple,
  297.     ["b"] = colors.blue,
  298.     ["c"] = colors.brown,
  299.     ["d"] = colors.green,
  300.     ["e"] = colors.red,
  301.     ["f"] = colors.black,
  302. }
  303.  
  304. local blit_names = {}
  305. for k,v in pairs(colors_names) do
  306.     blit_names[v] = k
  307. end
  308.  
  309. local codeNames = { -- just for checking, not for any translation
  310.     ["r"] = "reset",
  311.     ["{"] = "stopFormatting",
  312.     ["}"] = "startFormatting",
  313. }
  314.  
  315. local explode = function(div,str)
  316.     if (div=='') then return false end
  317.     local pos,arr = 0,{}
  318.     for st,sp in function() return string.find(str,div,pos,true) end do
  319.         table.insert(arr,string.sub(str,pos,st-1))
  320.         pos = sp + 1
  321.     end
  322.     table.insert(arr,string.sub(str,pos))
  323.     return arr
  324. end
  325.  
  326. local blitWrap = function(text,txt,bg)
  327.     local allIssues = ""
  328.     if not text then allIssues = allIssues.."no text, " end
  329.     if not txt then allIssues = allIssues.."no txt, " end
  330.     if not bg then allIssues = allIssues.."no bg, " end
  331.     if not (#text == #txt and #txt == #bg) then allIssues = allIssues.."incongruent lengths" end
  332.     if #allIssues > 0 then error(allIssues) end
  333.     local wordNo = 1
  334.     local words = explode(" ",text)
  335.     local lines = 0
  336.     local scr_x, scr_y = term.getSize()
  337.     local cx,cy
  338.     for a = 1, #text do
  339.         cx,cy = term.getCursorPos()
  340.         if text:sub(a,a) == " " and text:sub(a-1,a-1) ~= " " and a > 1 then
  341.             wordNo = wordNo + 1
  342.             if cx + #words[wordNo] > scr_x then
  343.                 term.setCursorPos(1,cy+1)
  344.                 lines = lines + 1
  345.             end
  346.         end
  347.         cx,cy = term.getCursorPos()
  348.         if text:sub(a,a) == "\n" then
  349.             term.setCursorPos(1,cy+1)
  350.             lines = lines + 1
  351.         elseif not (cx == 1 and text:sub(a,a) == " ") then
  352.             term.blit(text:sub(a,a),txt:sub(a,a),bg:sub(a,a))
  353.         end
  354.         if cx == scr_x then
  355.             term.setCursorPos(1,cy+1)
  356.             lines = lines + 1
  357.         end
  358.     end
  359.     return lines
  360. end
  361.  
  362. local moveOn, textToBlit
  363. textToBlit = function(str,substart,substop)
  364.     local p = 1
  365.     local output = ""
  366.     local txcolorout = ""
  367.     local bgcolorout = ""
  368.     local txcode = "&"
  369.     local bgcode = "~"
  370.     local doFormatting = true
  371.     local usedformats = {}
  372.     local txcol,bgcol = blit_names[term.getTextColor()], blit_names[term.getBackgroundColor()]
  373.     local origTX,origBG = blit_names[term.getTextColor()], blit_names[term.getBackgroundColor()]
  374.     local cx,cy,barestr
  375.     substart = substart or 0
  376.     substop = substop or #str
  377.     if not (substart == 0 and substop == #str) then
  378.         barestr = textToBlit(str)
  379.     else
  380.         if substart < 0 then
  381.             substart = #realstr - substart
  382.         end
  383.         if substop < 0 then
  384.             substop = #realstr - substop
  385.         end
  386.     end
  387.     moveOn = function(tx,bg)
  388.         if p >= substart and p <= substop then
  389.             output = output..str:sub(p,p)
  390.             txcolorout = txcolorout..tx
  391.             bgcolorout = bgcolorout..bg
  392.         end
  393.     end
  394.     while p <= #str do
  395.         if str:sub(p,p) == txcode then
  396.             if colors_names[str:sub(p+1,p+1)] and doFormatting then
  397.                 txcol = str:sub(p+1,p+1)
  398.                 usedformats.txcol = true
  399.                 p = p + 1
  400.             elseif codeNames[str:sub(p+1,p+1)] then
  401.                 if str:sub(p+1,p+1) == "r" and doFormatting then
  402.                     txcol = blit_names[term.getTextColor()]
  403.                     p = p + 1
  404.                 elseif str:sub(p+1,p+1) == "{" and doFormatting then
  405.                     doFormatting = false
  406.                     p = p + 1
  407.                 elseif str:sub(p+1,p+1) == "}" and (not doFormatting) then
  408.                     doFormatting = true
  409.                     p = p + 1
  410.                 else
  411.                     moveOn(txcol,bgcol)
  412.                 end
  413.             else
  414.                 moveOn(txcol,bgcol)
  415.             end
  416.             p = p + 1
  417.         elseif str:sub(p,p) == bgcode then
  418.             if colors_names[str:sub(p+1,p+1)] and doFormatting then
  419.                 bgcol = str:sub(p+1,p+1)
  420.                 usedformats.bgcol = true
  421.                 p = p + 1
  422.             elseif codeNames[str:sub(p+1,p+1)] and (str:sub(p+1,p+1) == "r") and doFormatting then
  423.                 bgcol = blit_names[term.getBackgroundColor()]
  424.                 p = p + 1
  425.             else
  426.                 moveOn(txcol,bgcol)
  427.             end
  428.             p = p + 1
  429.         else
  430.             moveOn(txcol,bgcol)
  431.             p = p + 1
  432.         end
  433.     end
  434.     return output, txcolorout, bgcolorout, usedformats
  435. end
  436.  
  437. local writef = function(txt,noWrite,substart,substop)
  438.     local cx,cy
  439.     if doColorize then
  440.         local text, textCol, bgCol, usedformats = textToBlit(txt,substart,substop)
  441.         local out = blitWrap(text,textCol,bgCol,noWrite)
  442.         return out, #text, usedformats
  443.     else
  444.         if noWrite then
  445.             cx,cy = term.getCursorPos()
  446.             return math.floor((cx+#cf(txt))/scr_x), #cf(txt), {} -- this is approximate, and might mess up with multiline strings
  447.         else
  448.             return write(txt), #txt, {}
  449.         end
  450.     end
  451. end
  452.  
  453. local printf = function(txt,noWrite)
  454.     return writef(tostring(txt.."\n"),noWrite)
  455. end
  456.  
  457. local runURL = function(url, ...)
  458.     local program = http.get(url)
  459.     if not program then return false end
  460.     program = program.readAll()
  461.     return load(program, nil, nil, _ENV)(...)
  462. end
  463.  
  464. local bow = function()
  465.     term.setBackgroundColor(palate.store.findbg)
  466.     term.setTextColor(palate.store.findtxt)
  467. end
  468.  
  469. local strless = function(str,txt,bg)
  470.     local x,y = 0,0
  471.     local shiftDown = false
  472.     local str = explode("\n",str or "")
  473.     local render = function()
  474.         term.setBackgroundColor(bg)
  475.         term.setTextColor(txt)
  476.         for i = y+1, (scr_y+y)-1 do
  477.             term.setCursorPos(math.max(1,-x),i-y)
  478.             term.clearLine()
  479.             if str[i] then
  480.                 term.write(str[i]:sub(math.max(1,x+1)))
  481.             end
  482.         end
  483.         term.setCursorPos(1,scr_y)
  484.         term.setBackgroundColor(colors.gray)
  485.         term.setTextColor(colors.white)
  486.         term.clearLine()
  487.         term.write("(Q)uit, Goto (L)ine")
  488.         local ting = "Ln."..math.min(math.max(y+1,0),#str)
  489.         term.setCursorPos((scr_x-#ting)+1,scr_y)
  490.         term.write(ting)
  491.     end
  492.     render()
  493.     maxY = (#str-scr_y)+1
  494.     while true do
  495.         local evt, key, mx, my = os.pullEvent()
  496.         local oldY = y
  497.         local oldX = x
  498.         if evt == "key" then
  499.             if key == keys.leftShift then
  500.                 shiftDown = true
  501.             elseif key == keys.up then
  502.                 y = y-1
  503.             elseif key == keys.down then
  504.                 y = y+1
  505.             elseif key == keys.pageUp then
  506.                 y = y-(scr_y-1)
  507.             elseif key == keys.pageDown then
  508.                 y = y+(scr_y-1)
  509.             elseif key == keys.left then
  510.                 x = x-1
  511.             elseif key == keys.right then
  512.                 x = x+1
  513.             elseif key == keys.home then
  514.                 y = 0
  515.             elseif key == keys["end"] then
  516.                 y = maxY
  517.             elseif (key == keys.q) or (key == keys.x) then
  518.                 sleep(0)
  519.                 break
  520.             elseif (key == keys.l) then
  521.                 term.setCursorPos(1,scr_y)
  522.                 term.setBackgroundColor(colors.gray)
  523.                 term.setTextColor(colors.white)
  524.                 term.clearLine()
  525.                 term.write("Line #:")
  526.                 sleep(0)
  527.                 y = (tonumber(read()) or (y+1)) - 1
  528.             end
  529.         elseif evt == "key_up" then
  530.             if key == keys.leftShift then
  531.                 shiftDown = false
  532.             end
  533.         elseif evt == "mouse_scroll" then
  534.             if shiftDown then
  535.                 x = x + key
  536.             else
  537.                 y = y + key
  538.             end
  539.         elseif evt == "mouse_click" and key == 1 then
  540.             if my == scr_y and (mx >= 1 and mx <= 11) then
  541.                 sleep(0)
  542.                 break
  543.             end
  544.         end
  545.         if x < 0 then x = 0 end
  546.         if y < 0 then y = 0 end
  547.         if y > maxY then y = maxY end
  548.         if (x ~= oldX) or (y ~= oldY) or (key == keys.l) then
  549.             render()
  550.         end
  551.     end
  552. end
  553. local contentsFile = function(url)
  554.     local prog = http.get(url)
  555.     if prog then return prog.readAll()
  556.     else return false, "could not connect" end
  557. end
  558. local getFile = function(filename,url)
  559.     if fs.isReadOnly(filename) then
  560.         return false, "access denied"
  561.     end
  562.     local prog
  563.     if type(url) == "table" then
  564.         prog = setfenv(url[1], _ENV)(filename)
  565.     else
  566.         prog = http.get(url)
  567.         if not prog then
  568.             return false, "could not connect"
  569.         end
  570.         prog = prog.readAll()
  571.         local fyle = fs.open(filename,"w")
  572.         fyle.write(prog)
  573.         fyle.close()
  574.     end
  575.     if type(url) == "table" then
  576.         return true, 0
  577.     else
  578.         return true, fs.getSize(filename)
  579.     end
  580. end
  581. local runFile = function(path, ...)
  582.     if not fs.exists(path) then
  583.         return false, "No such file!"
  584.     end
  585.     local file = fs.open(path,"r")
  586.     local contents = file.readAll()
  587.     file.close()
  588.     local func = load(contents, nil, nil, _ENV)
  589.     return func(...)
  590. end
  591. std.getSTDList = function(prevChannel)
  592.     catag = 0
  593.     local url = std.channelURLs[std.channel] --URL of URL list for whatever channel you have selected.
  594.     pleaseWait()
  595.     local outcome, size = getFile(std.stdList, std.channelURLs[std.channel])
  596.     if not outcome then
  597.         if shell then
  598.             print("Couldn't update list!")
  599.         end
  600.         return false, "Couldn't update list!"
  601.     else
  602.         local outcome = runFile(std.stdList)
  603.         if outcome == false then
  604.             term.setBackgroundColor(colors.black)
  605.             term.setTextColor(term.isColor() and colors.red or colors.lightGray)
  606.             term.clear()
  607.             cprint("STD channel \""..std.channel.."\" is down right now.",2)
  608.             term.setTextColor(colors.white)
  609.             cprint("Either try again later,",4)
  610.             cprint("contact LDDestroier on the CC forums,",5)
  611.             cprint("or tell the owner of the channel.",6)
  612.             cprint("Press a key to go back.",8)
  613.             term.setTextColor(colors.gray)
  614.             cprint("Sorry bout that!",scr_y)
  615.             std.channel = prevChannel
  616.             sleep(0.1)
  617.             os.pullEvent("char")
  618.             pleaseWait("Changing list...please wait...")
  619.             return std.getSTDList("STD")
  620.         end
  621.         local output
  622.         if not fs.isReadOnly(std.stdList) then
  623.             output = "Downloaded to "..std.stdList
  624.         else
  625.             output = "Got store codes."
  626.         end
  627.         maxScroll = setMaxScroll(catag)
  628.         return true, output
  629.     end
  630. end
  631.  
  632. local cisf = function(str,fin)
  633.     fin = fin:gsub("%[","%%["):gsub("%(","%%("):gsub("%]","%%]"):gsub("%)","%%)")
  634.     return string.find(str:lower(),fin:lower())
  635. end
  636.  
  637. local clearMostline = function(length,char)
  638.     local pX,pY = term.getCursorPos()
  639.     term.setCursorPos(1,pY)
  640.     term.write(string.rep(char or " ",length or (scr_x-1)))
  641.     term.setCursorPos(pX,pY)
  642. end
  643.  
  644. local dotY
  645. local doScrollBar = false
  646.  
  647. local renderStore = function(list,filter,scrollY,namescroll,fixedDotY,buttonIndicate)
  648.     local fullrend = {}
  649.     local visiblerend = {}
  650.     local amnt = 0
  651.     local output = {}
  652.     local colors_output = {}
  653.     local num = 0
  654.     if tsv then tsv(false) end
  655.     for k,v in pairs(list) do
  656.         if (v.catagory == filter) or filter == 0 then
  657.             fullrend[1+#fullrend] = {table.concat({" &", blit_names[palate.store.entryasterisk], "*&", blit_names[palate.store.entrytxt], v.title}), v}
  658.             fullrend[1+#fullrend] = {" by &r"..v.creator,v}
  659.             fullrend[1+#fullrend] = {" Category: "..std.storeCatagoryNames[v.catagory],v,v.catagory}
  660.             fullrend[1+#fullrend] = "nilline"
  661.         end
  662.     end
  663.     fullrend[1+#fullrend] = ""
  664.     dotY = fixedDotY or math.floor((scr_y-2)*((scroll-1)/(maxScroll-1)))+2
  665.    
  666.     for a = scrollY, (scr_y+scrollY)-1 do
  667.         if type(fullrend[a]) == "table" then
  668.            
  669.             visiblerend[1+#visiblerend] = fullrend[a][1]
  670.             output[1+#output] = fullrend[a][2]
  671.            
  672.             colors_output[1+#colors_output] = fullrend[a][3] and fullrend[a][3] or false
  673.         else
  674.             visiblerend[1+#visiblerend] = fullrend[a]
  675.             output[1+#output] = {}
  676.             colors_output[1+#colors_output] = false
  677.         end
  678.     end
  679.    
  680.     setDefaultColors()
  681.     charClear(palate.store.bgchar)
  682.    
  683.     for a = 1, #visiblerend do
  684.         term.setCursorPos(2-namescroll,1+a)
  685.         if visiblerend[a] == "nilline" then
  686.             setDefaultColors()
  687.             clearMostline()
  688.         else
  689.             if a < #visiblerend then
  690.                 if term.isColor() then
  691.                     if colors_output[a] then
  692.                         term.setBackgroundColor(std.storeCatagoryColors[colors_output[a]].bg)
  693.                         term.setTextColor(std.storeCatagoryColors[colors_output[a]].txt)
  694.                     else
  695.                         term.setBackgroundColor(palate.store.entrybg)
  696.                         term.setTextColor(palate.store.entrytxt)
  697.                     end
  698.                 else
  699.                     term.setBackgroundColor(colors.gray)
  700.                     term.setTextColor(colors.white)
  701.                 end
  702.                 clearMostline()
  703.                 writef(visiblerend[a])
  704.             else
  705.                 term.setBackgroundColor(palate.store.bg)
  706.                 term.setTextColor(palate.store.theendtxt)
  707.                 cprint("That's them all!")
  708.             end
  709.         end
  710.     end
  711.     local b
  712.     for a = 2, scr_y do
  713.         term.setCursorPos(scr_x,a)
  714.         if a == dotY then
  715.             term.setTextColor(palate.store.scrollbar.knobtxt)
  716.             term.setBackgroundColor(palate.store.scrollbar.knobbg)
  717.             term.write(palate.store.scrollbar.knobchar)
  718.         else
  719.             term.setTextColor(palate.store.scrollbar.bartxt)
  720.             term.setBackgroundColor(palate.store.scrollbar.barbg)
  721.             term.write(palate.store.scrollbar.barchar)
  722.         end
  723.         if buttonIndicate then
  724.             term.setCursorPos(scr_x-4,a)
  725.             term.setBackgroundColor(palate.store.indicatebg)
  726.             term.setTextColor(palate.store.indicatetxt)
  727.             b = (a+1)/4
  728.             if (b == math.floor(b)) and (visiblerend[a] and visiblerend[a] ~= "nilline") then
  729.                 term.write(" "..tostring(b):sub(#tostring(b)).." ")
  730.             end
  731.         end
  732.     end
  733.     if tsv then tsv(true) end
  734.     return output
  735. end
  736.  
  737. local simSoftInstall = function(obj, objname, appname)
  738.     local installSystemName = "STD App Distribution (sad...)"
  739.     appname = appname or objname
  740.     local getFromURL = function(url)
  741.         local fuck
  742.         if type(url) == "table" then
  743.             fuck = setfenv(url[1], _ENV)(filename)
  744.             return nil
  745.         else
  746.             fuck = http.get(url)
  747.         end
  748.         if not fuck then
  749.             return shit
  750.         else
  751.             if type(url) == "table" then
  752.                 return fuck.readAll(), false
  753.             else
  754.                 return fuck.readAll(), (string.find(url,"://pastebin.com/raw/") and (url:sub(-9):gsub("/","")) or false)
  755.             end
  756.         end
  757.     end
  758.     local mainpath = fs.combine("/SimSoft/SappS",objname)
  759.     local cont,pbcode = getFromURL(obj.url)
  760.     local file = fs.open("\""..fs.combine(mainpath,pbcode or "program").."\"","w")
  761.     file.write(cont)
  762.     file.close()
  763.     local file = fs.open(fs.combine(mainpath,"SappS"),"w")
  764.     file.writeLine(installSystemName)
  765.     file.writeLine("\""..fs.combine(mainpath,pbcode or "program").."\"")
  766.     file.writeLine(appname:sub(1,9))
  767.     file.close()
  768.     return true, "Installed!"
  769. end
  770.  
  771. local getFindList = function(name)
  772.     local output = {}
  773.     for k,v in pairs(std.storeURLs) do
  774.         if cisf(k,name) or cisf(textToBlit(v.title),name) or cisf(textToBlit(v.creator),name) then
  775.             output[k] = v
  776.         end
  777.         if output[k] ~= v and v.keywords then
  778.             for a = 1, #v.keywords do
  779.                 if cisf(v.keywords[a],name) then
  780.                     output[k] = v
  781.                     break
  782.                 end
  783.             end
  784.         end
  785.     end
  786.     return output
  787. end
  788.  
  789. local doFindFunc = function(name)
  790.     scroll = 1
  791.     maxScroll = setMaxScroll(catag)
  792.     renderStore( getFindList(name) ,catag, scroll, scrollX, _, not term.isColor() )
  793.     term.setCursorPos(1,1)
  794.     bow()
  795.     term.clearLine()
  796.     write("Find: ")
  797. end
  798.  
  799. local funcread = function(repchar, rHistory, doFunc, noNewLine)
  800.     local scr_x,scr_y = term.getSize()
  801.     local sx,sy = term.getCursorPos()
  802.     local cursor = 1
  803.     rHistory = rHistory or {}
  804.     local rCursor = #rHistory+1
  805.     local output = ""
  806.     term.setCursorBlink(true)
  807.     while true do
  808.         local evt,key = os.pullEvent()
  809.         local cx,cy = term.getCursorPos()
  810.         if evt == "key" then
  811.             if key == keys.enter then
  812.                 if not noNewLine then
  813.                     write("\n")
  814.                 end
  815.                 term.setCursorBlink(false)
  816.                 return output
  817.             elseif key == keys.left then
  818.                 if cursor-1 >= 1 then
  819.                     cursor = cursor - 1
  820.                 end
  821.             elseif key == keys.right then
  822.                 if cursor <= #output then
  823.                     cursor = cursor + 1
  824.                 end
  825.             elseif key == keys.up then
  826.                 if rCursor > 1 then
  827.                     rCursor = rCursor - 1
  828.                     term.setCursorPos(sx,sy)
  829.                     term.write((" "):rep(#output))
  830.                     output = rHistory[rCursor] or ""
  831.                     cursor = #output+1
  832.                     pleaseDoFunc = true
  833.                 end
  834.             elseif key == keys.down then
  835.                 term.setCursorPos(sx,sy)
  836.                 term.write((" "):rep(#output))
  837.                 if rCursor < #rHistory then
  838.                     rCursor = rCursor + 1
  839.                     output = rHistory[rCursor] or ""
  840.                     cursor = #output+1
  841.                     pleaseDoFunc = true
  842.                 else
  843.                     rCursor = #rHistory+1
  844.                     output = ""
  845.                     cursor = 1
  846.                 end
  847.             elseif key == keys.backspace then
  848.                 if cursor > 1 and #output > 0 then
  849.                     output = output:sub(1,cursor-2)..output:sub(cursor)
  850.                     cursor = cursor - 1
  851.                     pleaseDoFunc = true
  852.                 end
  853.             elseif key == keys.delete then
  854.                 if #output:sub(cursor,cursor) == 1 then
  855.                     output = output:sub(1,cursor-1)..output:sub(cursor+1)
  856.                     pleaseDoFunc = true
  857.                 end
  858.             end
  859.         elseif evt == "char" or evt == "paste" then
  860.             output = output:sub(1,cursor-1)..key..output:sub(cursor+(#key-1))
  861.             cursor = cursor + #key
  862.             pleaseDoFunc = true
  863.         end
  864.         if pleaseDoFunc then
  865.             pleaseDoFunc = false
  866.             if type(doFunc) == "function" then
  867.                 doFunc(output)
  868.             end
  869.             term.setCursorPos(sx,sy)
  870.             local pOut = output
  871.             if #output >= scr_x-(sx-2) then
  872.                 pOut = output:sub((#output+(sx))-scr_x)
  873.             end
  874.             if repchar then
  875.                 term.write(repchar:sub(1,1):rep(#pOut).." ")
  876.             else
  877.                 term.write(pOut.." ")
  878.             end
  879.             local cx,cy = term.getCursorPos()
  880.         end
  881.         term.setCursorPos(sx+cursor-1,cy)
  882.     end
  883. end
  884.  
  885. local prevList
  886. local findPrompt = function()
  887.     local cX,cY = term.getCursorPos()
  888.     sleep(0)
  889.     if prevList then std.storeURLs = prevList end
  890.     doFindFunc("")
  891.     prevList = std.storeURLs
  892.     std.storeURLs = getFindList(funcread(nil,{},doFindFunc,false))
  893.     term.setCursorBlink(false)
  894.     maxScroll = setMaxScroll(catag)
  895. end
  896.  
  897. local displayTitle = function()
  898.     local title = {{},{},{},{},{0,0,0,0,0,1,1,1,1,1,0,0,2,2,2,2,2,2,2,0,2,2,2,2,0,0,32768,},{0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,2,0,0,0,0,0,2,0,2,2,0,32768,},{0,0,0,0,1,0,0,0,0,0,1,0,0,0,2,2,0,0,0,0,2,2,0,0,2,0,32768,},{0,0,0,0,1,1,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,2,0,32768,},{0,0,0,0,0,1,1,1,1,1,0,0,0,0,2,0,0,0,0,2,2,0,0,2,2,0,32768,},{0,0,0,0,0,0,0,0,0,1,0,0,0,2,2,0,0,0,2,2,0,0,2,2,0,0,32768,},{0,0,0,1,1,0,0,0,1,1,0,0,2,2,0,0,0,2,2,0,0,2,2,0,0,32768,1,},{0,0,0,0,1,1,1,1,1,0,0,0,2,0,0,0,2,2,2,2,2,2,0,0,32768,1,1,},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32768,1,1,1,},{0,0,0,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,1,1,1,1}}
  899.     setDefaultColors()
  900.     term.clear()
  901.     paintutils.drawImage(title,-1,1)
  902.     setDefaultColors()
  903.     term.setCursorPos(4,16)
  904.     term.write("STD-GUI "..(isBeta and "beta" or "stable"))
  905.     sleep(0)
  906.     local evt
  907.     repeat
  908.         evt = os.pullEvent()
  909.     until evt == "mouse_click" or evt == "key"
  910.     sleep(0)
  911. end
  912.  
  913. local fixDotY
  914.  
  915. local renderStoreItem = function(obj) --now being experimented on...
  916.     if not obj.title then return false end
  917.     local showPostURL = false
  918.     local bruffer
  919.     local scroll = 1
  920.     local doRedraw = true
  921.     local extraLines
  922.     while true do
  923.         bruffer = {
  924.             "",
  925.             table.concat({" &", blit_names[palate.item.specialtxt], obj.title}),
  926.             table.concat({" &", blit_names[palate.item.txt], "by &", blit_names[palate.item.specialtxt], obj.creator}),
  927.             table.concat({" &", blit_names[palate.item.txt], "Category: ", std.storeCatagoryNames[obj.catagory]}),
  928.             "",
  929.             table.concat({"&", blit_names[palate.item.txt], obj.description,})
  930.         }
  931.         if showPostURL and obj.forumPost then
  932.             local post = table.concat({" &", blit_names[palate.item.forumtxt], "~", blit_names[palate.item.forumbg], obj.forumPost:gsub("http://www.",""):sub(1,-2)})
  933.             bruffer[#bruffer+1] = "&8Forum URL: "..post
  934.         end
  935.         if doRedraw then
  936.             term.setBackgroundColor(palate.item.bg)
  937.             term.clear()
  938.             term.setCursorPos(1,(-scroll)+2)
  939.             extraLines = 0
  940.             for y = 1, #bruffer do
  941.                 if not bruffer[y] then break end
  942.                 extraLines = extraLines + printf(bruffer[y])
  943.             end
  944.            
  945.             term.setCursorPos(1,scr_y)
  946.             if term.isColor() then
  947.                 term.setTextColor(palate.item.closetxt)
  948.                 term.setBackgroundColor(palate.item.closebg)
  949.             else
  950.                 term.setTextColor(colors.black)
  951.                 term.setBackgroundColor(colors.white)
  952.             end
  953.             term.clearLine()
  954.             if term.isColor() then
  955.                 term.write("CLOSE")
  956.             else
  957.                 term.write("(Q) to CLOSE")
  958.             end
  959.             if term.isColor() then
  960.                 term.setTextColor(palate.store.previewtxt)
  961.                 term.setBackgroundColor(palate.store.previewbg)
  962.                 term.setCursorPos((scr_x-16),scr_y)
  963.                 term.write("VIEW")
  964.                 term.setTextColor(palate.item.runtxt)
  965.                 term.setBackgroundColor(palate.item.runbg)
  966.                 term.setCursorPos((scr_x-11),scr_y)
  967.                 term.write("RUN")
  968.             else
  969.                 term.setTextColor(colors.black)
  970.                 term.setBackgroundColor(colors.white)
  971.                 term.setCursorPos((scr_x-22),scr_y)
  972.                 term.write("(V)IEW")
  973.                 term.setTextColor(colors.black)
  974.                 term.setBackgroundColor(colors.white)
  975.                 term.setCursorPos((scr_x-15),scr_y)
  976.                 term.write("(R)UN")
  977.             end
  978.             local txt
  979.             if std.currentOS ~= "CraftOS" then
  980.                 if term.isColor() then
  981.                     term.setTextColor(palate.item.downloadtxt)
  982.                     term.setBackgroundColor(palate.item.downloadbg)
  983.                     txt = "INSTALL!"
  984.                 else
  985.                     txt = "(I)NSTALL"
  986.                 end
  987.             else
  988.                 if term.isColor() then
  989.                     term.setTextColor(palate.item.downloadtxt)
  990.                     term.setBackgroundColor(palate.item.downloadbg)
  991.                     txt = "DOWNLOAD"
  992.                 else
  993.                     txt = "(D)OWNLOAD"
  994.                 end
  995.             end
  996.             term.setCursorPos((scr_x-(#txt-1)),scr_y)
  997.             term.write(txt)
  998.             doRedraw = false
  999.         end
  1000.         local evt = {getEvents("key","mouse_click","mouse_scroll","term_resize")}
  1001.         if evt[1] == "key" then
  1002.             if evt[2] == keys.f then
  1003.                 showPostURL = not showPostURL
  1004.                 doRedraw = true
  1005.             elseif evt[2] == keys.d or evt[2] == keys.i or evt[2] == keys.r or evt[2] == keys.q or evt[2] == keys.v then
  1006.                 return unpack(evt)
  1007.             end
  1008.         elseif evt[1] == "mouse_click" then
  1009.             if evt[4] == scr_y then
  1010.                 return unpack(evt)
  1011.             end
  1012.         elseif evt[1] == "mouse_scroll" then
  1013.             if scroll+evt[2] >= 1 and scroll+evt[2] <= (#bruffer+extraLines)-(scr_y-8) then
  1014.                 scroll = scroll + evt[2]
  1015.                 doRedraw = true
  1016.             end
  1017.         elseif evt[1] == "term_resize" then
  1018.             doRedraw = true
  1019.             scr_x,scr_y = term.getSize()
  1020.         end
  1021.     end
  1022. end
  1023.  
  1024. local renderCatagoryMenu = function(expanded,cursor)
  1025.     if expanded then
  1026.         term.setCursorPos(1,1)
  1027.         term.setBackgroundColor(palate.menubar.bg)
  1028.         term.clearLine()
  1029.         term.setBackgroundColor(palate.menubar.categorymenu.selectbg)
  1030.         term.setTextColor(palate.menubar.categorymenu.selecttxt)
  1031.         if term.isColor() then
  1032.             if cursor == 0 then
  1033.                 term.setTextColor(palate.menubar.categorymenu.txt)
  1034.                 term.write(" No category")
  1035.             else
  1036.                 term.write("Select category:")
  1037.             end
  1038.         else
  1039.             term.setCursorPos(1,1)
  1040.             if cursor == 0 then
  1041.                 term.setTextColor(palate.menubar.categorymenu.txt)
  1042.                 term.write(" No category")
  1043.             else
  1044.                 term.write(" Pick category with up/down:")
  1045.             end
  1046.         end
  1047.         term.setTextColor(palate.menubar.categorymenu.txt)
  1048.         term.setBackgroundColor(palate.menubar.categorymenu.bg)
  1049.         local yposes = {}
  1050.         local longestLen = 0
  1051.         for a = 1, #std.storeCatagoryNames do
  1052.             if #std.storeCatagoryNames[a]+2 > longestLen then
  1053.                 longestLen = #std.storeCatagoryNames[a]+2
  1054.             end
  1055.         end
  1056.         longestLen = longestLen+1
  1057.         for a = 0, #std.storeCatagoryNames do
  1058.             term.setCursorPos(1,a+1)
  1059.             if term.isColor() then
  1060.                 term.setTextColor(palate.menubar.categorymenu.orbtxt)
  1061.                 term.setBackgroundColor(palate.menubar.categorymenu.bg)
  1062.                 if type(std.storeCatagoryColors) == "table" then
  1063.                     if std.storeCatagoryColors[a] then
  1064.                         term.setTextColor(std.storeCatagoryColors[a].txt)
  1065.                         term.setBackgroundColor(std.storeCatagoryColors[a].bg)
  1066.                     end
  1067.                 end
  1068.             else
  1069.                 term.setTextColor(colors.black)
  1070.                 term.setBackgroundColor(colors.lightGray)
  1071.             end
  1072.             if a > 0 then
  1073.                 clearMostline(longestLen+2)
  1074.             end
  1075.             if a == cursor then
  1076.                 if type(std.storeCatagoryColors) ~= "table" then
  1077.                     if term.isColor() then
  1078.                         if cursor == 0 then
  1079.                             term.setTextColor(palate.menubar.categorymenu.txt)
  1080.                             term.setBackgroundColor(palate.menubar.categorymenu.bg)
  1081.                         else
  1082.                             term.setTextColor(palate.menubar.categorymenu.cursortxt)
  1083.                             term.setBackgroundColor(palate.menubar.categorymenu.cursorbg)
  1084.                         end
  1085.                     else
  1086.                         term.setTextColor(colors.black)
  1087.                         term.setBackgroundColor(colors.lightGray)
  1088.                     end
  1089.                 elseif cursor == 0 then
  1090.                     term.setBackgroundColor(colors.black)
  1091.                 end
  1092.                 write(">")
  1093.             elseif a > 0 then
  1094.                 write(" ")
  1095.             end
  1096.             if a > 0 then
  1097.                 if type(std.storeCatagoryColors) ~= "table" then
  1098.                     term.setTextColor(palate.menubar.categorymenu.orbtxt)
  1099.                     term.setBackgroundColor(palate.menubar.categorymenu.bg)
  1100.                 end
  1101.                 if a == catag then
  1102.                     write("@ ")
  1103.                 else
  1104.                     write("O ")
  1105.                 end
  1106.                 write(std.storeCatagoryNames[a])
  1107.                 if term.isColor() then
  1108.                     term.setBackgroundColor(palate.menubar.categorymenu.borderbg)
  1109.                 else
  1110.                     term.setBackgroundColor(colors.black)
  1111.                 end
  1112.                 term.setCursorPos(longestLen+2,a+1)
  1113.                 term.write(" ")
  1114.                 yposes[#yposes+1] = 1+a
  1115.             end
  1116.         end
  1117.         term.setCursorPos(1,#std.storeCatagoryNames+2)
  1118.         term.write((" "):rep(longestLen+2))
  1119.         return yposes,longestLen+2
  1120.     else
  1121.         term.setCursorPos(1,1)
  1122.         term.setBackgroundColor(palate.menubar.bg)
  1123.         term.clearLine()
  1124.         term.setTextColor(palate.menubar.categorytxt)
  1125.         term.setBackgroundColor(palate.menubar.categorybg)
  1126.         term.write("Cat.")
  1127.         term.setTextColor(palate.menubar.hotkeytxt)
  1128.         term.write("F1")
  1129.         term.setCursorPos(8,1)
  1130.         term.setTextColor(palate.menubar.channeltxt)
  1131.         term.setBackgroundColor(palate.menubar.channelbg)
  1132.         term.write("Chan.")
  1133.         term.setTextColor(palate.menubar.hotkeytxt)
  1134.         term.write("F3")
  1135.         term.setCursorPos(16,1)
  1136.         term.setTextColor(palate.menubar.categorytxt)  
  1137.         term.write("("..std.currentOS..")")
  1138.     end
  1139.     if term.isColor() then
  1140.         term.setCursorPos(scr_x-4,1)
  1141.         term.setBackgroundColor(palate.store.closebg)
  1142.         term.setTextColor(palate.store.closetxt)
  1143.         term.write("CLOSE")
  1144.     else
  1145.         term.setCursorPos(scr_x-11,1)
  1146.         term.setBackgroundColor(colors.black)
  1147.         term.setTextColor(colors.white)
  1148.         term.write("'Q' to CLOSE")
  1149.     end
  1150.     setDefaultColors()
  1151. end
  1152.  
  1153. local renderChannelMenu = function(cursor)
  1154.     term.setCursorPos(1,1)
  1155.     term.setBackgroundColor(palate.menubar.bg)
  1156.     term.clearLine()
  1157.     term.setBackgroundColor(palate.menubar.channelmenu.selectbg)
  1158.     term.setTextColor(palate.menubar.channelmenu.selecttxt)
  1159.     term.write("Select channel:")
  1160.     term.setTextColor(palate.menubar.channelmenu.txt)
  1161.     term.setBackgroundColor(palate.menubar.channelmenu.bg)
  1162.     local yposes = {}
  1163.     local longestLen = 0
  1164.     for a = 1, #std.channelNames do
  1165.         if #std.channelNames[a] > longestLen then
  1166.             longestLen = #std.channelNames[a]
  1167.         end
  1168.     end
  1169.     longestLen = longestLen + 4
  1170.     for a = 1, #std.channelNames do
  1171.         term.setBackgroundColor(palate.menubar.channelmenu.bg)
  1172.         term.setCursorPos(1,a+1)
  1173.         clearMostline(longestLen+2)
  1174.         if a == cursor then
  1175.             term.setTextColor(palate.menubar.channelmenu.cursortxt)
  1176.             term.setBackgroundColor(palate.menubar.channelmenu.cursorbg)
  1177.             write(">")
  1178.         else
  1179.             write(" ")
  1180.         end
  1181.         term.setTextColor(palate.menubar.channelmenu.orbtxt)
  1182.         term.setBackgroundColor(palate.menubar.channelmenu.bg)
  1183.         if std.channel == std.channelNames[a] then
  1184.             write("@ ")
  1185.         else
  1186.             write("O ")
  1187.         end
  1188.         term.write(" "..std.channelNames[a])
  1189.         if term.isColor() then
  1190.             term.setBackgroundColor(palate.menubar.channelmenu.borderbg)
  1191.         else
  1192.             term.setBackgroundColor(colors.black)
  1193.         end
  1194.         term.setCursorPos(longestLen+2,a+1)
  1195.         term.write(" ")
  1196.         yposes[1+#yposes] = {a+1,std.channelNames[a],std.channelURLs[std.channelNames[a]]}
  1197.     end
  1198.     term.setCursorPos(1,#std.channelNames+2)
  1199.     term.write((" "):rep(longestLen+2))
  1200.     return yposes,longestLen+2
  1201. end
  1202.  
  1203. local tArg = {...}
  1204.  
  1205. if tArg[1] == "help" then
  1206.     return displayHelp(true)
  1207. elseif tArg[1] == "upgrade" then
  1208.     local updateURL = std.updateURL[isBeta and "beta" or "stable"]
  1209.     local res, outcome = getFile(shell.getRunningProgram(),updateURL)
  1210.     if not res then
  1211.         error(outcome)
  1212.     else
  1213.         print("Updated STD-GUI to latest "..(isBeta and "beta." or "stable.").." ("..outcome.." bytes)")
  1214.         return
  1215.     end
  1216. end
  1217.  
  1218. local res, outcome
  1219. if tArg[1] == "update" then
  1220.     res, outcome = std.getSTDList(std.prevChannel)
  1221.     print(outcome)
  1222.     return
  1223. else
  1224.     if not std.storeURLs then
  1225.         pleaseWait() -- he said please
  1226.         res, outcome = std.getSTDList(std.prevChannel)
  1227.     end
  1228. end
  1229.  
  1230. local cleanExit = function()
  1231.     term.setTextColor(colors.white)
  1232.     term.setBackgroundColor(colors.black)
  1233.     term.clear()
  1234.     local out
  1235.     if pocket then
  1236.         out = "Thanks for using STD!"
  1237.     else
  1238.         out = "Thank you for using STD-GUI!"
  1239.     end
  1240.     if std.currentOS ~= "CraftOS" then
  1241.         term.setCursorBlink(false)
  1242.     end
  1243.     cprint(out,scr_y/2)
  1244.     term.setCursorPos(1,scr_y)
  1245.     sleep(0)
  1246.     return true, "This shouldn't be an error."
  1247. end
  1248.  
  1249. local STDdownloadPrompt = function(item, itname, savepath)
  1250.     term.setCursorPos(1,scr_y)
  1251.     if not itname then
  1252.         for k,v in pairs(std.storeURLs) do
  1253.             if item.url == v.url then
  1254.                 itname = k
  1255.                 break
  1256.             end
  1257.         end
  1258.     end
  1259.     if not savepath then
  1260.         bow()
  1261.         term.clearLine()
  1262.         write("Save as: ")
  1263.         savepath = funcread(nil,{},nil,true)
  1264.     end
  1265.     term.setCursorBlink(false)
  1266.     if savepath:gsub(" ","") == "" then
  1267.         sleep(0)
  1268.         return
  1269.     else
  1270.         if relativePath then
  1271.             savepath = fs.combine(shell.dir(),savepath)
  1272.         end
  1273.         if fs.exists(savepath) then
  1274.             term.setCursorPos(1,scr_y)
  1275.             term.clearLine()
  1276.             write("Overwrite? (Y/N)")
  1277.             local key
  1278.             repeat
  1279.                 _,key = os.pullEvent("char")
  1280.             until string.find("yn",key)
  1281.             if key == "n" then
  1282.                 sleep(0)
  1283.                 return
  1284.             end
  1285.         end
  1286.         term.setCursorPos(1,scr_y)
  1287.         term.clearLine()
  1288.         term.write("Downloading...")
  1289.         local res, outcome = getFile(savepath,item.url)
  1290.         term.setCursorPos(1,scr_y)
  1291.         term.clearLine()
  1292.         if not res then
  1293.             term.write(outcome)
  1294.             sleep(0.6)
  1295.         else
  1296.             term.write("Downloaded! ("..outcome.." bytes)")
  1297.             sleep(0.7)
  1298.         end
  1299.     end
  1300.     return
  1301. end
  1302.  
  1303. SimSoftDownloadPrompt = function(object)
  1304.     local itname
  1305.     for k,v in pairs(std.storeURLs) do
  1306.         if object.url == v.url then
  1307.             itname = k
  1308.             break
  1309.         end
  1310.     end
  1311.     term.setCursorPos(1,scr_y)
  1312.     bow()
  1313.     term.clearLine()
  1314.     write("Label?:")
  1315.     local custLabel = funcread(_,_,_,true)
  1316.     if #custLabel:gsub("%s","") == 0 then
  1317.         custLabel = nil
  1318.     else
  1319.         custLabel = custLabel:sub(1,9)
  1320.     end
  1321.     term.setCursorPos(1,scr_y)
  1322.     term.clearLine()
  1323.     term.write("Downloading...")
  1324.     local res, outcome = simSoftInstall(object, itname or object.title:gsub(" ","-"), custLabel)
  1325.     term.setCursorPos(1,scr_y)
  1326.     term.clearLine()
  1327.     term.write(outcome)
  1328.     sleep(#outcome/13)
  1329. end
  1330.  
  1331. local customInstaller = function(OS, item)
  1332.     for k,v in pairs(std.storeURLs) do
  1333.         if item.url == v.url then
  1334.             itname = k
  1335.             break
  1336.         end
  1337.     end
  1338.     local savepath
  1339.     local installers = {
  1340.         ["CraftOS"] = function(item)
  1341.             return STDdownloadPrompt(item, itname, nil)
  1342.         end,
  1343.         ["AxiomUI"] = function(item)
  1344.             if std.storeURLs[itname].catagory == 8 then
  1345.                 savepath = fs.combine("/home/APIs", itname)
  1346.             else
  1347.                 savepath = fs.combine("/Axiom/programs", itname) .. ".app"
  1348.             end
  1349.             -- creates a desktop shortcut for all users if *not* an API
  1350.             if std.storeURLs[itname].catagory ~= 8 then
  1351.                 if fs.isDir("home/Desktop") then
  1352.                     local file = fs.open(fs.combine("home/Desktop", itname)..".lnk", "w")
  1353.                     file.write(savepath)
  1354.                     file.close()
  1355.                 else
  1356.                     local users = fs.list("home")
  1357.                     for i = 1, #users do
  1358.                         if users[i] ~= "prg" then
  1359.                             local file = fs.open(fs.combine("home/" .. users[i] .. "/Desktop",itname)..".lnk", "w")
  1360.                             file.write(savepath)
  1361.                             file.close()
  1362.                         end
  1363.                     end
  1364.                 end
  1365.             end
  1366.             return STDdownloadPrompt(item, itname, savepath)
  1367.         end,
  1368.         ["SimSoft"] = function(item)
  1369.             return SimSoftDownloadPrompt(item)
  1370.         end,
  1371.         ["OpusOS"] = function(item)
  1372.             -- changes path if an API
  1373.             if std.storeURLs[itname].catagory == 8 then
  1374.                 savepath = fs.combine("/sys/apis", itname)
  1375.             else
  1376.                 savepath = fs.combine("/usr/apps", itname)
  1377.             end
  1378.             return STDdownloadPrompt(item, itname, savepath)
  1379.         end,
  1380.         ["NovaHorizon"] = function(item)
  1381.             return STDdownloadPrompt(item, itname, "Nova/apps")
  1382.         end
  1383.     }
  1384.     return installers[OS](item)
  1385. end
  1386.  
  1387. local doCategoryMenu = function()
  1388.     local mcursor = catag -- (not term.isColor()) and (catag or 0) or false
  1389.     local cats,longth = renderCatagoryMenu(true,mcursor)
  1390.     local evt,butt,x,y
  1391.     while true do
  1392.         local evt,butt,x,y = os.pullEvent()
  1393.         if evt == "mouse_click" or (evt == "mouse_up" and y ~= 1) then
  1394.             doRedraw = true
  1395.             if y == 1 then
  1396.                 catag = 0
  1397.                 break
  1398.             else
  1399.                 for a = 1, #cats do
  1400.                     if cats[a] == y and x <= longth then
  1401.                         catag = a
  1402.                         scroll = 1
  1403.                     end
  1404.                 end
  1405.                 break
  1406.             end
  1407.         elseif evt == "key" then
  1408.             if butt == keys.f1 then
  1409.                 break
  1410.             elseif mcursor then
  1411.                 if (butt == keys.up) and (mcursor > 0) then
  1412.                     mcursor = mcursor - 1
  1413.                     doRedraw = true
  1414.                 elseif (butt == keys.down) and (mcursor < #std.storeCatagoryNames) then
  1415.                     mcursor = mcursor + 1
  1416.                     doRedraw = true
  1417.                 elseif (butt == keys.enter) or (butt == keys.space) then
  1418.                     os.queueEvent("mouse_click",1,2,mcursor+1)
  1419.                 end
  1420.             end
  1421.         end
  1422.         if doRedraw then
  1423.             renderCatagoryMenu(true,mcursor)
  1424.             doRedraw = false
  1425.         end
  1426.     end
  1427.     maxScroll = setMaxScroll(catag)
  1428. end
  1429.  
  1430. local doChannelMenu = function()
  1431.     local mcursor = 1 -- (not term.isColor()) and 1 or false
  1432.     local yposes, longth = renderChannelMenu(mcursor)
  1433.     local evt,butt,x,y
  1434.     while true do
  1435.         local evt,butt,x,y = os.pullEvent()
  1436.         if evt == "mouse_click" or (evt == "mouse_up" and y ~= 1) then
  1437.             if y == 1 then break else
  1438.                 for a = 1, #yposes do
  1439.                     if (yposes[a][1] == y) and (x <= longth) then
  1440.                         if std.channel ~= yposes[a][2] then
  1441.                             std.prevChannel = std.channel
  1442.                             std.channel = yposes[a][2]
  1443.                             scroll = 1
  1444.                             std.getSTDList(std.prevChannel)
  1445.                         end
  1446.                         break
  1447.                     end
  1448.                 end
  1449.                 break
  1450.             end
  1451.         elseif evt == "key" then
  1452.             if butt == keys.f3 then
  1453.                 break
  1454.             elseif mcursor then
  1455.                 if (butt == keys.up) and (mcursor > 1) then
  1456.                     mcursor = mcursor - 1
  1457.                 elseif (butt == keys.down) and (mcursor < #std.channelNames) then
  1458.                     mcursor = mcursor + 1
  1459.                 elseif (butt == keys.enter) or (butt == keys.space) then
  1460.                     os.queueEvent("mouse_click",1,2,mcursor+1)
  1461.                 end
  1462.             end
  1463.         end
  1464.         renderChannelMenu(mcursor)
  1465.     end
  1466.     maxScroll = setMaxScroll(catag)
  1467. end
  1468.  
  1469. local STDViewEntry = function(url)
  1470.     local contents, outcome = contentsFile(url)
  1471.     if not contents then
  1472.         term.write(outcome)
  1473.         sleep(0.6)
  1474.         return
  1475.     else
  1476.         strless(contents,palate.item.previewtxt,palate.item.previewbg)
  1477.     end
  1478. end
  1479.  
  1480. local doEverything = function() -- do I have to do EVERYTHING?
  1481.     if not std.storeURLs then
  1482.         pleaseWait()
  1483.         std.getSTDList(std.prevChannel)
  1484.     end
  1485.     maxScroll = setMaxScroll(catag)
  1486.     local yposes
  1487.     while true do
  1488.         if scroll > maxScroll then
  1489.             scroll = maxScroll
  1490.         end
  1491.         if scroll < 1 then
  1492.             scroll = 1
  1493.         end
  1494.         if (-1 + scroll % 4 ~= 0) and (not term.isColor()) then
  1495.             scroll = scroll - ((scroll-1) % 4)
  1496.         end
  1497.         local mcursor = (not term.isColor()) and 1 or false
  1498.         yposes = renderStore(std.storeURLs,catag,scroll,scrollX,fixDotY,not term.isColor())
  1499.         renderCatagoryMenu(false,mcursor)
  1500.         local evt = {getEvents("mouse_scroll","mouse_click","mouse_up","key","mouse_drag","char")}
  1501.         scr_x, scr_y = term.getSize()
  1502.         if evt[1] == "mouse_scroll" then
  1503.             if scroll+evt[2] >= 1 and scroll+evt[2] <= maxScroll then
  1504.                 scroll = scroll+evt[2]
  1505.                 doRedraw = true
  1506.             end
  1507.         elseif evt[1] == "mouse_click" and (evt[2] == 1) and (evt[4] <= scr_y) and (evt[4] >= 1) then --left click only! must deport right mouse buttons!
  1508.             if evt[3] == scr_x and evt[4] == math.floor(dotY) then
  1509.                 doScrollBar = true
  1510.             end
  1511.             if evt[4] == 1 then
  1512.                 if evt[3] >= scr_x-4 then
  1513.                     return cleanExit()
  1514.                 else
  1515.                     if evt[3] >= 1 and evt[3] <= 6 then
  1516.                         doCategoryMenu()
  1517.                     elseif evt[3] >= 8 and evt[3] <= 14 then
  1518.                         doChannelMenu()
  1519.                     end
  1520.                 end
  1521.             elseif yposes[evt[4]-1] and evt[3] ~= scr_x then
  1522.                 local y = evt[4]-1
  1523.                 local showPostURL = false
  1524.                 local guud = yposes[y].title
  1525.                 scrollX = 1
  1526.                 while true do
  1527.                     if not guud then break end
  1528.                     local event,butt,cx,cy = renderStoreItem(yposes[y],showPostURL)
  1529.                     if event == "key" then
  1530.                         if butt == keys.q then
  1531.                             sleep(0)
  1532.                             break
  1533.                         elseif butt == keys.d then
  1534.                             sleep(0)
  1535.                             STDdownloadPrompt(yposes[y])
  1536.                         elseif butt == keys.v then
  1537.                             sleep(0)
  1538.                             STDViewEntry(yposes[y].url)
  1539.                         elseif (butt == keys.i) then
  1540.                             sleep(0)
  1541.                             customInstaller(std.currentOS, yposes[y])
  1542.                         end
  1543.                     elseif event == "mouse_click" then
  1544.                         if cy == scr_y then
  1545.                             if (cx < scr_x-7) or (cx > scr_x) then
  1546.                                 if cx >= scr_x-11 and cx < scr_x-8 then
  1547.                                     term.setCursorPos(1,scr_y)
  1548.                                     bow()
  1549.                                     term.clearLine()
  1550.                                     if pocket or turtle then
  1551.                                         write("Args.: ")
  1552.                                     else
  1553.                                         write("Arguments:")
  1554.                                     end
  1555.                                     local arguments = explode(" ",funcread(nil,{},nil,true)) or {}
  1556.                                     term.setTextColor(colors.white)
  1557.                                     term.setBackgroundColor(colors.black)
  1558.                                     term.clear()
  1559.                                     term.setCursorPos(1,1)
  1560.                                     local oldcpath
  1561.                                     if shell then
  1562.                                         oldcpath = shell.dir()
  1563.                                         shell.setDir("")
  1564.                                     end
  1565.                                     if #arguments == 0 then
  1566.                                         runURL(yposes[y].url)
  1567.                                     else
  1568.                                         runURL(yposes[y].url,unpack(arguments))
  1569.                                     end
  1570.                                     if shell then
  1571.                                         shell.setDir(oldcpath or "")
  1572.                                     end
  1573.                                     sleep(0)
  1574.                                     write("[press a key]")
  1575.                                     os.pullEvent("key")
  1576.                                 elseif cx >= scr_x-16 and cx < scr_x-12 then
  1577.                                     STDViewEntry(yposes[y].url)
  1578.                                 end
  1579.                                 sleep(0)
  1580.                                 break
  1581.                             else
  1582.                                 term.setCursorPos(1,scr_y)
  1583.                                 bow()
  1584.                                 term.clearLine()
  1585.                                 customInstaller(std.currentOS, yposes[y])
  1586.                                 break
  1587.                             end
  1588.                         end
  1589.                     end
  1590.                 end
  1591.             end
  1592.         elseif evt[1] == "mouse_up" then
  1593.             doScrollBar = false
  1594.             fixDotY = nil
  1595.         elseif evt[1] == "mouse_drag" then
  1596.             if doScrollBar then
  1597.                 local my = evt[4]
  1598.                 if my > scr_y then -- operating systems might allow this to be true
  1599.                     my = scr_y
  1600.                 elseif my < 1 then -- this too
  1601.                     my = 1
  1602.                 end
  1603.                 if my > 1 then
  1604.                     scroll = math.floor( (my-2)/(scr_y-2) * (maxScroll)) + 1
  1605.                     fixDotY = my
  1606.                 end
  1607.             end
  1608.         elseif evt[1] == "key" then
  1609.             if evt[2] == keys.q then
  1610.                 return cleanExit()
  1611.             elseif evt[2] == keys.down then
  1612.                 scroll = scroll + 4
  1613.             elseif evt[2] == keys.up then
  1614.                 scroll = scroll - 4
  1615.             elseif evt[2] == keys.pageDown then
  1616.                 scroll = scroll + (scr_y-1)
  1617.             elseif evt[2] == keys.pageUp then
  1618.                 scroll = scroll - (scr_y-1)
  1619.             elseif evt[2] == keys.home then
  1620.                 scroll = 1
  1621.             elseif evt[2] == keys['end'] then
  1622.                 scroll = maxScroll
  1623.             elseif evt[2] == keys.h then -- help screen!
  1624.                 displayHelp(false)
  1625.             elseif evt[2] == keys.right then
  1626.                 scrollX = scrollX + 1
  1627.             elseif evt[2] == keys.left then
  1628.                 if scrollX > 1 then
  1629.                     scrollX = scrollX - 1
  1630.                 end
  1631.             elseif (evt[2] == keys.numPadAdd) or (evt[2] == keys.rightBracket) then
  1632.                 catag = catag + 1
  1633.                 if catag > #std.storeCatagoryNames then
  1634.                     catag = 0
  1635.                 end
  1636.                 scroll = 1
  1637.                 maxScroll = setMaxScroll(catag)
  1638.             elseif (evt[2] == keys.minus) or (evt[2] == keys.leftBracket) then
  1639.                 catag = catag - 1
  1640.                 if catag < 0 then
  1641.                     catag = #std.storeCatagoryNames
  1642.                 end
  1643.                 scroll = 1
  1644.                 maxScroll = setMaxScroll(catag)
  1645.             elseif evt[2] == keys.f5 then
  1646.                 pleaseWait()
  1647.                 std.getSTDList(std.prevChannel)
  1648.             elseif (evt[2] == keys.f12) and (std.currentOS ~= "CraftOS") then
  1649.                 local updateURL = std.updateURL[isBeta and "beta" or "stable"]
  1650.                 getFile(shell.getRunningProgram(),updateURL)
  1651.                 local flashes = {
  1652.                     colors.black,
  1653.                     colors.white,
  1654.                     colors.lightGray,
  1655.                     colors.gray,
  1656.                     colors.black,
  1657.                 }
  1658.                 for a = 1, #flashes do
  1659.                     term.setBackgroundColor(flashes[a])
  1660.                     term.clear()
  1661.                     sleep(0)
  1662.                 end
  1663.                 return
  1664.             elseif evt[2] == keys.f1 then
  1665.                 doCategoryMenu()
  1666.             elseif evt[2] == keys.f or evt[2] == keys.f6 then
  1667.                 -- runFile(std.stdList)
  1668.                 findPrompt()
  1669.             elseif evt[2] == keys.f3 then
  1670.                 doChannelMenu()
  1671.             end
  1672.         elseif evt[1] == "char" then
  1673.             if tonumber(evt[2]) then
  1674.                 local a = tonumber(evt[2]) ~= "0" and tonumber(evt[2]) or "10"
  1675.                 local b = (a*4)-1
  1676.                 os.queueEvent("mouse_click",1,scr_x-3,b)
  1677.             end
  1678.         end
  1679.     end
  1680. end
  1681.  
  1682. if doDisplayTitle then
  1683.     displayTitle()
  1684. end
  1685.  
  1686. if std.storeURLs then std.storeURLs = getFindList("") end
  1687.  
  1688. local errorHandler = function()
  1689.     local success, message = pcall(doEverything)
  1690.     if success then
  1691.         return true
  1692.     end
  1693.     if message == "Terminated" then
  1694.         term.setBackgroundColor(colors.black)
  1695.         term.scroll(2)
  1696.         term.setCursorPos(1, scr_y-1)
  1697.         printError(message)
  1698.         return false, message
  1699.     else
  1700.         term.setBackgroundColor(colors.white)
  1701.         for a = 1, math.ceil(scr_y/2) do
  1702.             term.scroll(2)
  1703.         end
  1704.         term.setTextColor(colors.black)
  1705.         cprint("STD-GUI has encountered an error!",2)
  1706.         term.setCursorPos(1,4)
  1707.         term.setTextColor(term.isColor() and colors.red or colors.gray)
  1708.         print(message or "".."\n")
  1709.         term.setTextColor(colors.black)
  1710.         print(" Please contact LDDestroier/EldidiStroyrr on either the ComputerCraft forums, or through other means.")
  1711.         sleep(0.5)
  1712.         print("\nPush a key.")
  1713.         os.pullEvent("key")
  1714.         term.setCursorPos(1,scr_y)
  1715.         term.setBackgroundColor(colors.black)
  1716.         term.setTextColor(colors.white)
  1717.         term.clearLine()
  1718.         return false, message
  1719.     end
  1720. end
  1721.  
  1722. return errorHandler()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement