View difference between Paste ID: q9XwaJaK and bVH5gv5Y
SHOW: | | - or go back to the newest paste.
1
local tArgs = {...}
2
local ver = "1.0"
3
local sTitle = "Apoc Browser"
4
local bugTest, norun, dir, showAll
5
local _tArgs = {}
6
local config = "mouse.cfg"
7
8
local temp
9
if shell and shell.getRunningProgram then
10
	temp = shell.getRunningProgram()
11
end
12
13
temp = temp or "/bla"
14
local localPath = string.sub(temp,1,#temp-string.len(fs.getName(temp)))
15
temp = nil -- just because not needed
16
17
-- load config file
18
19
local configSet = {}
20
local cnf = {}
21
22
if fs.exists(localPath.."/"..config) then
23
	local file = fs.open(localPath.."/"..config,"r")
24
	if file then
25
		local item = file.readLine()
26
		while item do
27
			table.insert(cnf,item)
28
			item = file.readLine()
29
		end
30
		file.close()
31
	end	
32
end
33
34
for i = 1,10 do
35
	local test,data = pcall(textutils.unserialize,cnf[i])
36
	if test then
37
		configSet[i] = data
38
	else
39
		configSet[i] = nil
40
	end
41
end
42
cnf = nil
43
44
-- color configuration work in progress
45
local titleBar = configSet[1] or {txt = colors.black,back = colors.blue}
46
local addressBar = configSet[2] or {txt = colors.black,back = colors.lightGray}
47
local itemWindo = configSet[3] or {txt = colors.black,back = colors.cyan}
48
local rcmList = configSet[4] or {txt = colors.black,back = colors.lightGray} -- rcm = Right Click Menu List
49
local rcmTitle = configSet[5] or {txt = colors.black,back = colors.blue}
50
local dialogTitle = configSet[6] or {txt = colors.black,back = colors.blue}
51
local dialogWindo = configSet[7] or {txt = colors.black,back = colors.white}
52
local scrollCol = configSet[8] or {off = colors.gray, button = colors.gray,back = colors.lightGray}
53
54
local tIcons = configSet[9] or {
55
	back = {tCol = "lightGray",bCol = "blue",txt = " < "},
56
	disk = {tCol = "lime",bCol = "green",txt = "[*]"},
57
	audio = {tCol = "yellow",bCol = "red",txt = "(o)"},
58
	folder = {tCol = "lightGray",bCol = "blue",txt = "[=]"},
59
	file = {tCol = nil ,bCol = nil ,txt = nil}
60
}
61
62
local customLaunch = configSet[10] or {
63
	["Edit"] = "rom/programs/edit",
64
	["Paint"] = "rom/programs/color/paint"
65
}
66
67
local function saveCFG(overWrite)
68
	if not fs.exists(localPath.."/"..config) or overWrite then
69
		local cnf = {}
70
		local file = fs.open(localPath.."/"..config,"w")
71
		if file then
72
			file.write(textutils.serialize(titleBar).."\n")
73
			file.write(textutils.serialize(addressBar).."\n")
74
			file.write(textutils.serialize(itemWindo).."\n")
75
			file.write(textutils.serialize(rcmList).."\n")
76
			file.write(textutils.serialize(rcmTitle).."\n")
77
			file.write(textutils.serialize(dialogTitle).."\n")
78
			file.write(textutils.serialize(dialogWindo).."\n")
79
			file.write(textutils.serialize(scrollCol).."\n")
80
			file.write(textutils.serialize(tIcons).."\n")
81
			file.write(textutils.serialize(customLaunch).."\n")
82
			file.close()
83
		elseif overWrite then
84
		end
85
	end
86
end
87
88
saveCFG()
89
90
-- end configuration
91
92
local function help()
93
	print([[Usage: browser [-d] [-h] [-a] [-u] [--debug] [--help] [--dir <dir>] [--all] [--update]
94
--debug or -d: enable debug mode
95
--help or -h: display this screen
96
--dir: define initial directory
97
--all or -a: show hidden files
98
--update -u: update]])
99
end
100
101
local function inBouwndry(clickX,clickY,boxX,boxY,width,hight)
102
	return ( clickX >= boxX and clickX < boxX + width and clickY >= boxY and clickY < boxY + hight )
103
end
104
105
for a = 1, #tArgs do
106
	if tArgs[a]:sub(1,2) == "--" then
107
		local cmd = tArgs[a]:sub(3):lower()
108
		if cmd == "debug" then
109
			bugTest = true
110
		elseif cmd == "help" then
111
			help()
112
			norun = true
113
		elseif cmd == "dir" then
114
			dir = tArgs[a+1]
115
			a = a + 1
116
		elseif cmd == "all" then
117
			showAll = true
118
		elseif cmd == "update" then
119
			update()
120
		end
121
	elseif tArgs[a]:sub(1,1) == "-" then
122
		for b = 2, #tArgs[a] do
123
			cmd = tArgs[a]:sub(b, b)
124
			if cmd == "d" then
125
				bugTest = true
126
			elseif cmd == "h" then
127
				help()
128
				norun = true
129
			elseif cmd == "p" then
130
				dir = tArgs[a+1]
131
				a = a + 1
132
			elseif cmd == "a" then
133
				showAll = true
134
			elseif cmd == "u" then
135
				update()
136
			end
137
		end
138
	else
139
		table.insert(_tArgs, tArgs[a])
140
	end
141
end
142
143
if (not dir) and shell and shell.dir then
144
	dir = shell.dir()
145
end
146
147
if dir and shell and shell.resolve then
148
	dir = shell.resolve(dir)
149
end
150
151
dir = dir or "/"
152
153
if bugTest then -- this is that the var is for testing
154
	print("Dir: "..dir)
155
	os.startTimer(4)
156
	os.pullEvent()
157
end
158
159
local function clear()
160
	term.setBackgroundColor(colors.black)
161
	term.setTextColor(colors.white)
162
	term.clear()
163
	term.setCursorBlink(false)
164
	term.setCursorPos(1,1)
165
end
166
167
local function fixArgs(...)
168
	local tReturn={}
169
	local str=table.concat({...}," ")
170
	local sMatch
171
	while str and #str>0 do
172
		if string.sub(str,1,1)=="\"" then
173
			sMatch, str=string.match(str, "\"(.-)\"%s*(.*)")
174
		else
175
			sMatch, str=string.match(str, "(%S+)%s*(.*)")
176
		end
177
		table.insert(tReturn,sMatch)
178
	end
179
	return tReturn
180
end
181
182
local function readMOD( _sReplaceChar, _tHistory,_wdth)
183
	local sLine = ""
184
	term.setCursorBlink( true )
185
186
	local nHistoryPos = nil
187
	local nPos = 0
188
    if _sReplaceChar then
189
		_sReplaceChar = string.sub( _sReplaceChar, 1, 1 )
190
	end
191
	
192
	local sx, sy = term.getCursorPos()	
193
194
	local w, h = term.getSize()
195
	if _wdth and type(_wdth) == "number" then
196
		w = sx + _wdth - 1
197
	end
198
	
199
	local function redraw( _sCustomReplaceChar )
200
		local nScroll = 0
201
		if sx + nPos >= w then
202
			nScroll = (sx + nPos) - w
203
		end
204
			
205
		term.setCursorPos( sx + _wdth - 1, sy )
206
		term.write(" ")
207
		term.setCursorPos( sx, sy )
208
		local sReplace = _sCustomReplaceChar or _sReplaceChar
209
		if sReplace then
210
			term.write( string.rep(sReplace,_wdth) )
211
		else
212
			term.write( string.sub( sLine, nScroll + 1 ,nScroll + _wdth) )
213
		end
214
		term.setCursorPos( sx + nPos - nScroll, sy )
215
	end
216
	
217
	while true do
218
		local sEvent, param = os.pullEvent()
219
		if sEvent == "char" then
220
			sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
221
			nPos = nPos + 1
222
			redraw()
223
			
224
		elseif sEvent == "key" then
225
			
226
			if param == keys.left then
227
				-- Left
228
				if nPos > 0 then
229
					nPos = nPos - 1
230
					redraw()
231
				end
232
				
233
			elseif param == keys.right then
234
				-- Right				
235
				if nPos < string.len(sLine) then
236
					nPos = nPos + 1
237
					redraw()
238
				end
239
			
240
			elseif param == keys.up or param == keys.down then
241
                -- Up or down
242
				if _tHistory then
243
					redraw(" ");
244
					if param == keys.up then
245
						-- Up
246
						if nHistoryPos == nil then
247
							if #_tHistory > 0 then
248
								nHistoryPos = #_tHistory
249
							end
250
						elseif nHistoryPos > 1 then
251
							nHistoryPos = nHistoryPos - 1
252
						end
253
					else
254
						-- Down
255
						if nHistoryPos == #_tHistory then
256
							nHistoryPos = nil
257
						elseif nHistoryPos ~= nil then
258
							nHistoryPos = nHistoryPos + 1
259
						end						
260
					end
261
					
262
					if nHistoryPos then
263
                    	sLine = _tHistory[nHistoryPos]
264
                    	nPos = string.len( sLine ) 
265
                    else
266
						sLine = ""
267
						nPos = 0
268
					end
269
					redraw()
270
                end
271
			elseif param == keys.backspace then
272
				-- Backspace
273
				if nPos > 0 then
274
					redraw(" ");
275
					sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
276
					nPos = nPos - 1					
277
					redraw()
278
				end
279
			elseif param == keys.home then
280
				-- Home
281
				nPos = 0
282
				redraw()		
283
			elseif param == keys.delete then
284
				if nPos < string.len(sLine) then
285
					redraw(" ");
286
					sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )				
287
					redraw()
288
				end
289
			elseif param == keys["end"] then
290
				-- End
291
				nPos = string.len(sLine)
292
				redraw()
293
			end
294
		elseif sEvent == "redraw" then
295
			redraw()
296
		elseif sEvent == "return" then
297
			term.setCursorBlink( false )
298
			return sLine
299
		end
300
	end
301
	
302
	term.setCursorBlink( false )
303
	
304
	return sLine
305
end
306
307
local function printC(posX,posY,textCol,backCol,text)
308
	term.setCursorPos(posX,posY)
309
	term.setTextColor(colors[textCol] or textCol)
310
	term.setBackgroundColor(colors[backCol] or backCol)
311
	term.write(text)
312
end
313
314
local function InputBox(title)
315
	local boxW,boxH = 26,3
316
	local termX,termY = term.getSize()
317
	local ofsX,ofsY = math.ceil((termX/2) - (boxW/2)) , math.ceil((termY/2) - (boxH/2)) -- offset from top left
318
	local options = {"ok","cancel"}
319
	
320
	local selected = 1
321
	local space = 0
322
	local range = {}
323
	for i = 1,#options do
324
		range[i] = {s = space,f = space + string.len(options[i])}
325
		space = space + string.len(options[i])+3
326
	end
327
	local ofC = (boxW/2) - (space/2)
328
	
329
	local function drawBox()
330
		printC(ofsX,ofsY,colors.black,colors.blue,string.rep(" ",boxW))
331
		printC(ofsX+1,ofsY,colors.black,colors.blue,(title or "User Input"))
332
		printC(ofsX,ofsY+1,colors.black,colors.white,string.rep(" ",boxW))
333
		printC(ofsX,ofsY+2,colors.black,colors.white,string.rep(" ",boxW))
334
		printC(ofsX,ofsY+3,colors.black,colors.white,string.rep(" ",boxW))
335
		
336
		for i = 1,#options do
337
			if i == selected then
338
				term.setBackgroundColor(colors.lightGray)
339
				term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)
340
				term.write("["..options[i].."]")
341
				term.setBackgroundColor(colors.white)
342
				term.write(" ")
343
			else
344
				term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)
345
				term.write(" "..options[i].." ")
346
			end
347
		end
348
		
349
		printC(ofsX+2,ofsY+2,colors.black,colors.lightGray,string.rep(" ",boxW-4))
350
	end
351
	drawBox()
352
	term.setCursorPos(ofsX+2,ofsY+2)
353
	local co = coroutine.create(function() return readMOD(nil,nil,boxW - 4) end)
354
	while true do
355
		local event = {os.pullEvent()}
356
		if event[1] == "key" or event[1] == "char" then
357
			if event[2] == 28 then
358
				local test,data = coroutine.resume(co,"return")
359
				return data
360
			else
361
				coroutine.resume(co,unpack(event))
362
			end
363
		elseif event[1] == "mouse_click" then
364
			if event[4] == ofsY + 3 then
365
				for i = 1,#options do
366
					if event[3] >= range[i].s + ofC + ofsX - 1 and event[3] <= range[i].f + ofC + ofsX then
367
						if options[i] == "ok" then
368
							local test,data = coroutine.resume(co,"return")
369
							return data
370
						elseif options[i] == "cancel" then
371
							return false
372
						end
373
					end
374
				end
375
			end
376
		end
377
	end
378
end
379
380
local function dialogBox(title,message,options, h, w)
381
	term.setCursorBlink(false)
382
	local selected = 1
383
	title = title or ""
384
	message = message or ""
385
	options = options or {}
386
	local boxW,boxH = (w or 26), (h or 3)
387
	local termX,termY = term.getSize()
388
	local ofsX,ofsY = math.ceil((termX/2) - (boxW/2)) , math.ceil((termY/2) - (boxH/2)) -- offset from top left
389
	
390
	local space = 0
391
	local range = {}
392
	for i = 1,#options do
393
		range[i] = {s = space,f = space + string.len(options[i])}
394
		space = space + string.len(options[i])+3
395
	end
396
	local ofC = math.ceil((boxW/2)) - math.ceil((space/2))
397
	
398
	local function drawBox()
399
		printC(ofsX,ofsY,dialogTitle.txt,dialogTitle.back," "..title..string.rep(" ",boxW-#title-5).."_[]")
400
		term.setBackgroundColor(colors.red)
401
		term.setTextColor(colors.white)
402
		term.write("X")
403
		printC(ofsX,ofsY+1,dialogWindo.txt,dialogWindo.back,string.sub(" "..message..string.rep(" ",boxW),1,boxW))
404
		term.setCursorPos(ofsX,ofsY+2)
405
		term.write(string.rep(" ",boxW))
406
		term.setCursorPos(ofsX,ofsY+3)
407
		term.write(string.rep(" ",boxW))
408
		for i = 1,#options do
409
			if i == selected then
410
				printC(range[i].s + ofC + ofsX - 1,ofsY + 3,"black","lightGray","["..options[i].."]")
411
				term.setBackgroundColor(dialogWindo.back)
412
				term.setTextColor(dialogWindo.txt)
413
				term.write(" ")
414
			else
415
				term.setCursorPos(range[i].s + ofC + ofsX - 1,ofsY + 3)
416
				term.write(" "..options[i].." ")
417
			end
418
		end
419
		term.setCursorPos(ofsX + ofC + space,ofsY + 3)
420
		term.write(string.rep(" ",boxW - (ofC + space)))
421
		term.setBackgroundColor(colors.black)
422
		term.setTextColor(colors.white)			
423
	end
424
	while true do
425
		drawBox()
426
		event = {os.pullEvent()}
427
		if event[1] == "key" then
428
			if event[2] == 203 then -- left
429
				selected = selected - 1
430
				if selected < 1 then
431
					selected = #options
432
				end
433
			elseif event[2] == 205 then -- right
434
				selected = selected + 1
435
				if selected > #options then
436
					selected = 1
437
				end
438
			elseif event[2] == 28 then -- enter
439
				return selected , options[selected]
440
			end
441
		elseif event[1] == "mouse_click" then
442
			
443
			if bugTest then term.write("M "..event[2].." X "..event[3].." Y "..event[4].."    ") end
444
			
445
			if event[2] == 1 then
446
				if event[4] == ofsY + 3 then
447
					for i = 1,#options do
448
						if event[3] >= range[i].s + ofC + ofsX - 1 and event[3] <= range[i].f + ofC + ofsX then
449
							return i , options[i]
450
						end
451
					end
452
				end
453
			end
454
		end
455
	end
456
end
457
458
local flag = true
459
local fSlash = "/"
460
local path = {dir:match("[^/]+")}
461
local function stringPath()
462
	return fSlash..table.concat(path,fSlash)
463
end
464
465
local function osRunSpaces(sFileLocation,...)
466
	clear()
467
	if os.newThread then
468
		os.newThread(false,...)
469
	else
470
	local fProg,probblem = loadfile(sFileLocation)
471
		if fProg then
472
			local tEnv = {["shell"] = {}}
473
			setmetatable(tEnv.shell,{ __index = shell})
474
			tEnv.shell.getRunningProgram = function()
475
				return sFileLocation
476
			end
477
			setmetatable(tEnv,{ __index = _G})
478
			setfenv(fProg,tEnv)
479
			local test,probblem = pcall(fProg,...)
480
			if not test then
481
				print(probblem)
482
				dialogBox("ERROR",tostring(probblem),{"ok"},3,30)
483
			else
484
				return true
485
			end
486
		else
487
			print(probblem)
488
			dialogBox("ERROR",tostring(probblem),{"ok"},3,30)
489
		end
490
	end
491
end
492
493
local function rClickMenu(title,tList,tItem,posX,posY)
494
495
	term.setCursorBlink(false)
496
	local BoxTitle = title
497
	local choices = {}
498
	local termX,termY = term.getSize()
499
	local offX,offY
500
	
501
	local width = #BoxTitle + 2
502
	local hight
503
	
504
	for k,v in pairs(tList) do
505
		if v ~= nil then
506
			table.insert(choices,k)
507
		end
508
		if width < #k + 2 then
509
			width = #k + 2
510
		end
511
	end
512
	
513
	if #choices == 0 then
514
		return
515
	end
516
	
517
	hight = #choices + 1
518
	table.sort(choices)
519
	
520
	offX,offY = math.ceil((termX/2) - (width/2)),math.ceil((termY/2) - (hight/2))
521
	
522
	if posX and posY then -- offX,offY = posX,posY
523
		if posX >= termX - width - 1 then
524
			offX = termX - width - 1
525
		else
526
			offX = posX
527
		end
528
		if posY >= termY - hight then
529
			offY = termY - hight
530
		else
531
			offY = posY
532
		end
533
	end
534
	
535
	local function reDrawer()
536
		printC(offX,offY,rcmTitle.txt,rcmTitle.back," "..BoxTitle..string.rep(" ",width - #BoxTitle - 1))
537
		for i = 1,#choices do
538
			printC(offX,offY + i,rcmList.txt,rcmList.back," "..choices[i]..string.rep(" ",width - #choices[i] - 1))
539
		end
540
	end
541
	
542
	while true do
543
		reDrawer()
544
		local event = {os.pullEvent()}
545
		if event[1] == "mouse_click" then
546
			if event[2] == 1 then -- event[3] = x event[4] = y
547
				if event[4] > offY and event[4] < hight + offY and event[3] >= offX and event[3] < width + offX then
548
					--dialogBox("ERROR:",type(tList[choices[event[4] - offY]]),{"ok"})
549
					if type(tList[choices[event[4] - offY]]) == "function" then
550
						return tList[choices[event[4] - offY]](tItem)
551
					elseif type(tList[choices[event[4] - offY]]) == "table" then
552
						return rClickMenu("Options",tList[choices[event[4] - offY]],tItem,event[3],event[4])
553
					elseif type(tList[choices[event[4] - offY]]) == "string" then
554
						return osRunSpaces(
555
								unpack(
556
									fixArgs(
557
										tList[choices[event[4] - offY]].." \""..stringPath()..fSlash..tItem.n.."\""
558
									)
559
								)
560
							)
561
					else
562
						dialogBox("ERROR:","somthing up with new rMenu",{"ok"})
563
					end
564
				else
565
					return
566
				end
567
			elseif event[2] == 2 then
568
				return
569
			end
570
		end
571
	end
572
	
573
end
574
575
local function preferences()
576
	local tItem = {
577
		{txt = "Title Bar",it = titleBar},
578
		{txt = "Address Bar",it = addressBar},
579
		{txt = "Item Windo", it = itemWindo},
580
		{txt = "Title Right Click Title",it = rcmTitle},
581
		{txt = "Right Click Menu",it = rcmList},
582
		{txt = "Title Dialog Box",it = dialogTitle},
583
		{txt = "Dialog Box",it = dialogWindo},
584
		{txt = "Scroll Bar",it = scrollCol}
585
	}
586
	local topL,topR = 13,5
587
	local width,hight = 23,6
588
	local bottomL,bottomR = topL + width,topR + hight
589
	
590
	local listOffset = 0
591
	local sel = 1
592
	local otherSel = 1
593
	local otherItems = {}
594
	
595
	if tItem[sel] then
596
		for k,v in pairs(tItem[sel].it) do
597
			table.insert(otherItems,{txt = k,it = v})
598
		end
599
	end
600
	
601
	local function draw()
602
		printC(topL,topR,titleBar.txt,titleBar.back,string.sub(" Preferences "..string.rep(" ",width),1,width))
603
		for i = 0,12,4 do
604
			for a = 1,4 do
605
				--printC(topL + (a*12)-12 ,topR + ((i+4)/4),4,2^(a+i-1)," "..tostring(2^(a+i-1)))
606
				printC(topL + a-1 ,topR + ((i+4)/4),4,2^(a+i-1)," ")
607
			end
608
		end
609
		local sSel = " "
610
		for i = 1,hight - 2 do
611
			if i == sel - listOffset then
612
				sSel = ">"
613
			end
614
			if tItem[i+listOffset] then
615
				printC(topL + 4 ,topR + i,colors.black,colors.white,string.sub(sSel..tItem[i+listOffset].txt..string.rep(" ",width),1,width - 4))
616
			else
617
				printC(topL + 4 ,topR + i,colors.black,colors.white,sSel..string.rep(" ",width-5))
618
			end
619
			if i == sel - listOffset then
620
				sSel = " "
621
			end
622
		end
623
		term.setCursorPos(topL,topR + hight - 1)
624
		local loop = 1
625
		local length = 0
626
			for i = 1,#otherItems do
627
				if otherSel == i then
628
					sSel = ">"
629
				end
630
				if colors.black == otherItems[i].it or colors.gray == otherItems[i].it then
631
					term.setTextColor(colors.white)
632
				else
633
					term.setTextColor(colors.black)
634
				end
635
				term.setBackgroundColor(otherItems[i].it)
636
				term.write(sSel..tostring(otherItems[i].txt).." ")
637
				length = length + #otherItems[i].txt + 2
638
				if otherSel == i then
639
					sSel = " "
640
				end
641
				loop = loop+1
642
			end
643
		term.setBackgroundColor(colors.white)
644
		term.write(string.rep(" ",width - length))
645
	end
646
	while true do
647
		draw()
648
		local event = {os.pullEvent()}
649
		if event[1] == "mouse_click" and event[2] == 1 then
650
			if inBouwndry(event[3],event[4],topL,topR,width,hight) then
651
				local inSideX,inSideY = event[3] - topL,event[4] - topR
652
				if inBouwndry(inSideX+1,inSideY,1,1,4,4) and tItem[sel] then
653
					--[[
654
					term.setCursorPos(1,1)
655
					term.setBackgroundColor(2^(inSideX + ((inSideY*4)-4)))
656
					print(2^(inSideX + ((inSideY*4)-4))," ",inSideX + ((inSideY*4)-4),"     ")
657
					]]--
658
					tItem[sel]["it"][otherItems[otherSel].txt] = (2^(inSideX + ((inSideY*4)-4)))
659
				end
660
			end
661
		elseif event[1] == "key" then
662
			if event[2] == 200 then
663
				sel = sel - 1
664
			elseif event[2] == 208 then
665
				sel = sel + 1
666
			elseif event[2] == 203 then
667
				otherSel = otherSel - 1
668
			elseif event[2] == 205 then
669
				otherSel = otherSel + 1
670
			elseif event[2] == 28 then
671
				if dialogBox("Confirm","Save prefrences?",{"Yes","No"}) == 1 then
672
					saveCFG(true)
673
				end
674
				return
675
			end
676
		end
677
		if sel < 1 then
678
			sel = 1
679
		elseif sel > #tItem then
680
			sel = #tItem
681
		end
682
		if sel > listOffset + hight - 2 then
683
			listOffset = listOffset + 1
684
		elseif sel - listOffset < 1 then
685
			listOffset = listOffset - 1
686
		end
687
		
688
		otherItems = {}
689
		if tItem[sel] then
690
			for k,v in pairs(tItem[sel].it) do
691
				table.insert(otherItems,{txt = k,it = v})
692
			end
693
		end
694
		
695
		if otherSel < 1 then
696
			otherSel = 1
697
		elseif otherSel > #otherItems then
698
			otherSel = #otherItems
699
		end
700
		
701
		if bugTest then
702
			term.setBackgroundColor(colors.black)
703
			term.setTextColor(colors.white)
704
			term.setCursorPos(1,1)
705
			term.clearLine()
706
			term.write("sel "..sel.." offset "..listOffset)
707
		end
708
	end
709
end
710
711
local function fileSelect(mode) -- save_file open_file browse < not yet implemented
712
	
713
	local title = sTitle.." "..ver
714
	local bRun = true
715
	local clipboard = nil
716
	local cut = false
717
	
718
	local termX,termY = term.getSize()
719
	local offsetX,offsetY = 1,1
720
	local hight,width = math.ceil(termY-2),math.ceil(termX-2)
721
	local oldHight,oldWidth
722
	
723
	-- offsets
724
	local boxOffX,boxOffY = offsetX,offsetY + 2
725
	local boxH,boxW = hight - 2 ,width - 2
726
	
727
	local barX,barY = offsetX + 1,offsetY + 2
728
	local barH,barW = 1,width - 1
729
	
730
	local tbarX,tbarY = offsetX + 1,offsetY + 1
731
	local tbarH,tbarW = 1,width - 1
732
	
733
	local exitX,exitY = offsetX + width - 1 ,offsetY + 1
734
	
735
	local pading = string.rep(" ",boxW)
736
	local list
737
	
738
	local listOff = 0
739
	
740
	local sPath
741
	local tItemList = {}
742
	
743
	local function newList()
744
		listOff = 0
745
		flag = true
746
		tItemList = {{n = "..", id = "back"}} -- adds a back item at top of list
747
		sPath = stringPath()
748
		local folders = {}
749
		local files = {}
750
		local disks = {}
751
		if not fs.exists(sPath) then
752
			path = {}
753
			sPath = stringPath()
754
			dialogBox("ERROR:","Path no longer exists",{"ok"})
755
		end
756
		local test,list = pcall(fs.list,sPath) -- stopes fs.list crash
757
		if list == nil then
758
			list = {}
759
			dialogBox("ERROR : ","fs.list crashed",{"ok"})
760
		end
761
		if #path == 0 then
762
			for i,v in pairs(rs.getSides()) do
763
				if disk.isPresent(v) then
764
					if disk.hasData(v) then
765
						table.insert(tItemList,{n = disk.getMountPath(v), id = "disk",s = v})
766
						disks[disk.getMountPath(v)] = true
767
					elseif disk.hasAudio(v) then
768
						table.insert(tItemList,{n = disk.getAudioTitle(v), id = "audio",s = v})
769
					end
770
				end
771
			end
772
		end
773
		for i,v in pairs(list) do
774
			if fs.isDir(sPath..fSlash..v) then
775
				table.insert(folders,v)
776
			else
777
				table.insert(files,v)
778
			end
779
		end
780
		table.sort(folders)
781
		table.sort(files)
782
		for i,v in pairs(folders) do
783
			if disks[v] == nil then
784
				table.insert(tItemList,{n = v, id = "folder"})
785
			end
786
		end
787
		for i,v in pairs(files) do
788
			table.insert(tItemList,{n = v, id = "file"})
789
		end
790
	end
791
	
792
	local function paste()
793
		if cut then
794
			local s, m = pcall(
795
				function()
796
					fs.move(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash..clipboard[2])
797
					cut = false
798
					clipboard = nil
799
				end)
800
			if not s then
801
				dialogBox("Error", (m or "Couldn't move"), {"ok"}, 4, 30)
802
			end
803
			if bugTest then
804
				local x, y = term.getCursorPos()
805
				term.setCursorPos(1, ({term.getSize()})[2])
806
				write("from "..clipboard[1]..fSlash..clipboard[2].." to "..stringPath()..fSlash..clipboard[2])
807
			end
808
		else
809
			local s, m = pcall(function()
810
				if fs.exists(stringPath()..fSlash..clipboard[2]) then
811
					fs.copy(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash.."copy-"..clipboard[2])
812
				else
813
					fs.copy(clipboard[1]..fSlash..clipboard[2], stringPath()..fSlash..clipboard[2])
814
				end
815
			end)
816
			if not s then
817
				dialogBox("Error", (m or "Couldn't copy"), {"ok"}, 4, 30)
818
			end
819
			if bugTest then
820
				local x, y = term.getCursorPos()
821
				term.setCursorPos(1, ({term.getSize()})[2])
822
				write("from "..clipboard[1]..fSlash..clipboard[2].." to "..stringPath()..fSlash..clipboard[2])
823
			end
824
		end
825
		newList()
826
	end
827
	
828
	-- this section below handles the right click menu
829
	
830
	local tmenu = {
831
		disk = {
832
			["Open"] = function(tItem)
833
				table.insert(path,tItem.n)
834
				newList()
835
			end,
836
			["Copy"] = function(tItem)
837
				clipboard = {stringPath(), tItem.n}
838
				cut = false
839
			end,
840
			["Eject"] = function(tItem)
841
				if dialogBox("Confirm","Eject "..fSlash..tItem.n.." "..tItem.s,{"yes","no"}) == 1 then
842
					disk.eject(tItem.s)
843
					newList()
844
				end
845
			end,
846
			["ID label"] = function(tItem)
847
				dialogBox("ID label",disk.getDiskID(tItem.s).." "..tostring(disk.getLabel(tItem.s)),{"ok"})
848
			end,
849
			["Set label"] = function(tItem)
850
				local name = InputBox("Label?")
851
				if name then
852
					disk.setLabel(tItem.s,name)
853
				end
854
			end,
855
			["Clear label"] = function(tItem)
856
				if dialogBox("Confirm","Cleal Label from "..tItem.s,{"yes","no"}) == 1 then
857
					disk.setLabel(tItem.s)
858
				end
859
			end
860
		},
861
		folder = {
862
			["Open"] = function(temp)
863
				table.insert(path,temp.n)
864
				newList()
865
			end,
866
			["Copy"] = function(tItem)
867
				clipboard = {stringPath(), tItem.n}
868
				cut = false
869
			end,
870
			["Cut"] = function(tItem)
871
				clipboard = {stringPath(), tItem.n}
872
				cut = true
873
			end,
874
			["Delete"] = function(tItem)
875
				if dialogBox("Confirm","Delete "..tItem.id.." "..tItem.n,{"yes","no"}) == 1 then
876
					if fs.isReadOnly(stringPath()..fSlash..tItem.n) then
877
						dialogBox("ERROR",tItem.id.." Is read Only",{"ok"})
878
					else
879
						fs.delete(stringPath()..fSlash..tItem.n)
880
						newList()
881
					end
882
				end
883
			end,
884
			["Rename"] = function(tItem)
885
				local sName = InputBox("New Name")
886
				if type(sName) == "string" and sName ~= "" then
887
					local s, m = pcall(function()
888
						fs.move(stringPath()..fSlash..tItem.n,stringPath()..fSlash..sName)
889
					end)
890
					if not s then
891
						dialogBox("Error", (m or "Rename failed"), {"ok"})
892
					end
893
				end
894
				newList()
895
			end
896
		},
897
		file = {
898
			["Run"] = {
899
				["Run"] = function(tItem)
900
					osRunSpaces(stringPath()..fSlash..tItem.n)
901
				end,
902
				["Run CMD"] = function(tItem)
903
					local cmd = InputBox("Commands")
904
					if cmd then
905
						osRunSpaces(stringPath()..fSlash..tItem.n,unpack(fixArgs(cmd)))
906
					end
907
				end,
908
			},
909
			["Open With"] = customLaunch,
910
			["Rename"] = function(tItem)
911
				local sName = InputBox("New Name")
912
				if type(sName) == "string" and sName ~= "" then
913
					local s, m = pcall(function()
914
						fs.move(stringPath()..fSlash..tItem.n,stringPath()..fSlash..sName)
915
					end)
916
					if not s then
917
						dialogBox("Error", (m or "Rename failed"), {"ok"})
918
					end
919
				end
920
				newList()
921
			end,
922
			["Delete"] = function(tItem)
923
				if dialogBox("Confirm","Delete "..tItem.id.." "..tItem.n,{"yes","no"}) == 1 then
924
					if fs.isReadOnly(stringPath()..fSlash..tItem.n) then
925
						dialogBox("ERROR",tItem.id.." Is read Only",{"ok"})
926
					else
927
						fs.delete(stringPath()..fSlash..tItem.n)
928
						newList()
929
					end
930
				end
931
			end,
932
			["Cut"] = function(tItem)
933
				clipboard = {stringPath(), tItem.n}
934
				cut = true
935
			end,
936
			["Copy"] = function(tItem)
937
				clipboard = {stringPath(), tItem.n}
938
				cut = false
939
			end
940
		},
941
		audio = {
942
			["Play"] = 1,
943
			["Eject"] = 1
944
		},
945
		back = {
946
		},
947
		blank = { -- tmenu.blank.Paste = 
948
			["Paste"] = nil,
949
			["New File"] = function()
950
				local name = InputBox()
951
				if name then
952
					if fs.exists(stringPath()..fSlash..name) then
953
						dialogBox("ERROR","Name exists",{"ok"})
954
					else
955
						local file = fs.open(stringPath()..fSlash..name,"w")
956
						if file then
957
							file.write("")
958
							file.close()
959
							newList()
960
						else
961
							dialogBox("ERROR","File not created",{"ok"})
962
						end
963
					end
964
				end
965
			end,
966
			["New Folder"] = function()
967
				local name = InputBox()
968
				if name then
969
					if fs.exists(stringPath()..fSlash..name) then
970
						dialogBox("ERROR","Name exists",{"ok"})
971
					else
972
						if pcall(fs.makeDir,stringPath()..fSlash..name) then
973
							newList()
974
						else
975
							dialogBox("ERROR","Access Denied",{"ok"})
976
						end
977
					end
978
				end
979
			end,
980
			["Preferences"] = preferences
981
		},
982
	}
983
	
984
	-- end right click menu
985
	
986
	local function scrollBar(posX,posY)
987
		if posX == boxOffX+boxW+1 and posY > boxOffY and posY <= boxOffY+boxH then
988
			if #tItemList > boxH then
989
				if posY == boxOffY + 1 then
990
					listOff = 0
991
				elseif posY == boxOffY+boxH then
992
					listOff = #tItemList + 1 - boxH
993
				else
994
					listOff = math.ceil((posY - boxOffY - 1 )*(((#tItemList - boxH+2)/boxH)))
995
				end
996
				flag = true
997
			end
998
		end
999
	end
1000
	
1001
	newList()
1002
	
1003
	while bRun do
1004
		if flag then
1005
			flag = false
1006
			-- clear
1007
			if oldHight ~= hight and oldWidth ~= width then
1008
				term.setBackgroundColor(colors.black)
1009
				term.clear()
1010
				oldHight,oldWidth = hight,width
1011
			end
1012
			-- draw top title bar
1013
			local b = tbarW - #title -2
1014
			if b < 0 then
1015
				b = 0
1016
			end
1017
			printC(tbarX,tbarY,titleBar.txt,titleBar.back,string.sub(" "..title,1,tbarW)..string.rep(" ",b))
1018
			term.setTextColor(colors.white)
1019
			term.setBackgroundColor(colors.red)
1020
			term.write("X")
1021
			
1022
			-- draw location bar
1023
			local a = barW - #sPath - 1
1024
			if a < 0 then
1025
				a = 0
1026
			end
1027
			local tmppath = sPath
1028
			if shell and shell.getDisplayName then
1029
				tmppath = shell.getDisplayName(sPath)
1030
				--dialogBox("yay")
1031
			else
1032
				--dialogBox("moop")
1033
			end
1034
			tmppath = tmppath or sPath
1035
			local a = barW - #tmppath - 1
1036
			if a < 0 then
1037
				a = 0
1038
			end
1039
			printC(barX,barY,addressBar.txt,addressBar.back,string.sub(" "..tmppath,1,barW)..string.rep(" ",a))
1040
			
1041
			-- draw scroll bar
1042
			if #tItemList > boxH then
1043
				term.setBackgroundColor(scrollCol.back)
1044
				for i = 1,boxH do
1045
					term.setCursorPos(boxOffX+boxW+1,i + boxOffY)
1046
					local scroll = math.floor( boxH* (listOff/(#tItemList-boxH+2)) )+1
1047
					if i == scroll then
1048
						term.setBackgroundColor(scrollCol.button)
1049
						term.write(" ")
1050
						term.setBackgroundColor(scrollCol.back)
1051
					else
1052
						term.write(" ")
1053
					end
1054
				end
1055
			else
1056
				term.setBackgroundColor(scrollCol.off)
1057
				for i = 1,boxH do
1058
					term.setCursorPos(boxOffX+boxW+1,i + boxOffY)
1059
					term.write(" ")
1060
				end
1061
			end
1062
			
1063
			-- draw main section
1064
1065
			for i = 1,boxH do -- listOff
1066
				local sel = i+listOff
1067
				if tItemList[sel] then
1068
					printC(1+boxOffX,i+boxOffY,(tIcons[tItemList[sel].id].tCol or itemWindo.txt),(tIcons[tItemList[sel].id].bCol or itemWindo.back),( tIcons[tItemList[sel].id].txt or "   "))
1069
					printC(4+boxOffX,i+boxOffY,itemWindo.txt,itemWindo.back,string.sub(" "..tItemList[sel].n..pading,1,boxW-3))
1070
				else
1071
					printC(1+boxOffX,i+boxOffY,itemWindo.txt,itemWindo.back,pading)
1072
				end
1073
			end
1074
			
1075
			if bugTest then
1076
				printC(1,1,"black","white",listOff.." "..boxOffY.." "..boxH)
1077
			end
1078
			
1079
		end
1080
		
1081
		-- react to events
1082
		local event = {os.pullEvent()}
1083
		
1084
		if event[1] == "mouse_click" then
1085
			if inBouwndry(event[3],event[4],boxOffX+1,boxOffY+1,boxW,boxH) then
1086
				local selected = tItemList[event[4]+listOff-boxOffY]
1087
				if selected and inBouwndry(event[3],event[4],boxOffX+1,event[4],#selected.n + 4,1) then
1088
					if event[2] == 1 then -- left mouse
1089
						if selected.id == "back" then
1090
							table.remove(path,#path)
1091
							newList()
1092
						elseif selected.id == "folder" or selected.id == "disk" then
1093
							table.insert(path,selected.n)
1094
							newList()
1095
						elseif selected.id == "file" then
1096
							if dialogBox("Run file ?",selected.n,{"yes","no"}) == 1 then
1097
								osRunSpaces(stringPath()..fSlash..selected.n)
1098
							end
1099
						flag = true
1100
						end
1101
					elseif event[2] == 2 then -- right mouse
1102
						rClickMenu("Options",tmenu[selected.id],selected,event[3],event[4])
1103
						flag = true
1104
					end
1105
				elseif event[2] == 2 then -- right clicking not on object
1106
					if clipboard then
1107
						tmenu.blank.Paste = paste
1108
					else
1109
						tmenu.blank.Paste = nil
1110
					end
1111
					rClickMenu("Options",tmenu["blank"],selected,event[3],event[4])
1112
					flag = true
1113
				end
1114
			elseif event[2] == 1 and event[3] == exitX and event[4] == exitY then
1115
				if dialogBox("Confirm","Exit application",{"yes","no"}) == 1 then
1116
					bRun = false
1117
				end
1118
				flag = true
1119
			elseif event[2] == 1 then
1120
				scrollBar(event[3],event[4])
1121
			end
1122
		elseif event[1] == "mouse_scroll" then -- flag this needs new math
1123
			local old = listOff
1124
			listOff = listOff + event[2]
1125
			if listOff < 0 then
1126
				listOff = 0
1127
			end
1128
			if #tItemList + 1 - boxH > 0 and listOff > #tItemList + 1 - boxH then
1129
				listOff = #tItemList + 1 - boxH
1130
			elseif listOff > 0 and #tItemList + 1 - boxH < 0 then
1131
				listOff = 0
1132
			end
1133
			if listOff ~= old then
1134
				flag = true
1135
			end
1136
		
1137
		elseif event[1] == "mouse_drag" then -- scroll bar
1138
			scrollBar(event[3],event[4])
1139
		elseif event[1] == "disk" or event[1] == "disk_eject" then
1140
			newList()
1141
		elseif event[1] == "window_resize" then
1142
			termX,termY = term.getSize()
1143
			offsetX,offsetY = 1,1
1144
			hight,width = math.ceil(termY-2),math.ceil(termX-2)
1145
			
1146
			boxOffX,boxOffY = offsetX,offsetY + 2
1147
			boxH,boxW = hight - 2 ,width - 2
1148
			
1149
			barX,barY = offsetX + 1,offsetY + 2
1150
			barH,barW = 1,width - 1
1151
			
1152
			tbarX,tbarY = offsetX + 1,offsetY + 1
1153
			tbarH,tbarW = 1,width - 1
1154
			
1155
			exitX,exitY = offsetX + width - 1 ,offsetY + 1
1156
			pading = string.rep(" ",boxW)
1157
			
1158
			flag = true
1159
		elseif event[1] == "redraw" then
1160
			flag = true
1161
		end
1162
	end
1163
end
1164
1165
local function main()
1166
	if term.isColor() then
1167
		clear()
1168
		fileSelect()
1169
		clear()
1170
	else
1171
		error("Not an Advanced Computer")
1172
	end
1173
end
1174
1175
local trash = (norun or main())