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