View difference between Paste ID: HrrfptdS and rCRuxes0
SHOW: | | - or go back to the newest paste.
1
local arg={...}--command line arguments
2
quit = false
3
local oldPull = os.pullEvent;
4
os.pullEvent = os.pullEventRaw;
5
 
6
function quitProgram()
7
  local event, param1 = os.pullEvent("char")
8
  if param1 == "q" then
9
    quit = true
10
  end
11
end
12
 
13
term.setBackgroundColor(colours.white)
14
term.setTextColor(colours.black)
15
term.clear()
16
term.setCursorPos(1,1)
17
term.setCursorBlink(false)
18
version="TMNET Browser 1.2"
19
siteName=""
20
currentSite=""
21
siteID=-1
22
pageName=""
23
currentX=1
24
currentY=1
25
menuMode=false
26
ddns=true
27
ddnsID=-1
28
webType=0--0=no site, 1=normal site, 2=menu
29
-------------------------
30
--web related functions--
31
-------------------------
32
33
function whois(name)--returns ID if found, -1 if not on dns, and nil if no dns
34
	--prevent unnecessary communication
35
	if name~=currentSite then
36
		if ddns==true then rednet.send(ddnsID,"@whois "..name)
37
		else rednet.broadcast("@whois "..name) end
38
		_,webID=rednet.receive(1)
39
		siteID=tonumber(webID)--convert it to a number
40
		currentSite=name
41
	end
42
	return siteID
43
end
44
function getColour(value)
45
	--TODO prevent crashing on invalid number
46
	number=tonumber(value)
47
	if number==nil then--convert hexadecimal
48
		if value=="A" then
49
			number=10
50
		elseif value=="B" then
51
			number=11
52
		elseif value=="C" then
53
			number=12
54
		elseif value=="D" then
55
			number=13
56
		elseif value=="E" then
57
			number=14
58
		elseif value=="F" then
59
			number=15
60
		else
61
			return colours.black
62
		end
63
	end
64
	return bit.blshift(1,number)
65
end
66
function loadPage(webID,page)
67
	rednet.send(webID,page or "/home")
68
	pagetext=""
69
	for i=1,17 do
70
		from,text=rednet.receive(0.5)
71
		if text==nil then break end
72
		pagetext=pagetext..text.."\n"
73
	end
74
	
75
	--term.write(pagetext)--doesn't support newline apparently
76
	--print(pagetext)
77
	line=1
78
	term.setCursorPos(2,line)
79
	colourmode=0--1=^ detected 2=nextchar text 3=nextchar backround
80
	term.setBackgroundColor(colours.white)
81
	term.setTextColor(colours.black)
82
	--my slow and tedious method of rendering the page
83
	for current=1,string.len(pagetext) do
84
		letter=string.sub(pagetext,current,current)--TODO surely an easier way?
85
		if letter==nil then letter=" " end
86
		if colourmode==0 then --normal
87
			if letter=="^" then 
88
				colourmode=1
89
			elseif letter=="\n" then
90
				line=line+1--next line
91
				if line==17 then break end--too much! TODO tweak this value
92
				term.setCursorPos(2,line)
93
				term.setBackgroundColor(colours.white)
94
				term.setTextColor(colours.black)--reset colours for next line
95
			else
96
				term.write(letter)--nothing special
97
			end
98
		elseif colourmode==1 then --might be a colour
99
			if letter=="f" then--foreground colour
100
				colourmode=2--next char will set foreground
101
			elseif letter=="b" then--background colour
102
				colourmode=3--next char will set background
103
			else--not correct, probably not intended as a colour
104
				term.write("^"..letter)--put ^ back as well
105
			end
106
		elseif colourmode==2 then--set text colour
107
			--print(letter)--debug
108
			term.setTextColor(getColour(letter))
109
			colourmode=0--back to normal
110
		elseif colourmode==3 then--set background colour
111
			term.setBackgroundColor(getColour(letter))
112
			colourmode=0--back to normal
113
		end
114
	end
115
end
116
117
-----------------
118
--GUI functions--
119
-----------------
120
function drawError(text)
121
	term.setBackgroundColor(colours.white)
122
	term.setTextColor(colours.red)
123
	term.setCursorPos(2,1)
124
	term.write("ERROR:")
125
	term.setCursorPos(2,2)
126
	term.write(text)
127
	webType=0
128
end
129
function drawButton(x,y,text,conditionA,conditionB,active)
130
	term.setCursorPos(x,y)
131
	if conditionA==conditionB and active then
132
		term.setBackgroundColor(colours.grey)
133
		term.write("[")
134
	else
135
		term.setBackgroundColor(colours.lightGrey)
136
		term.write(" ")
137
	end
138
	
139
	term.write(text)
140
	
141
	if conditionA==conditionB and active then
142
		term.write("]")
143
	else
144
		--term.write(" ")
145
	end
146
end
147
148
function renderGUI()
149
	--draw left bar
150
	term.setTextColor(colours.white)
151
	term.setBackgroundColor(colours.lightGrey)
152
	for line=1,18 do
153
		term.setCursorPos(1,line)
154
		term.write(" ")
155
	end
156
	--draw right cursor
157
	if menuMode==false then
158
		term.setCursorPos(1,currentY)
159
		term.setBackgroundColor(colours.grey)
160
		term.write(">")
161
	end
162
	--draw bottom bar
163
	term.setBackgroundColor(colours.lightGrey)
164
	term.setCursorPos(1,19)
165
	for line=1,51 do
166
		term.write(" ")
167
	end
168
	--term.setCursorPos(1,19)
169
	--term.write(siteName..pageName)
170
	--draw menu bar items
171
	drawButton(42,19,"Refresh",currentX,3,menuMode)
172
	drawButton(36,19,"Menu",currentX,2,menuMode)
173
	drawButton(1,19,siteName..pageName,currentX,1,menuMode)
174
end
175
176
function popup(text)--a nice GUI popup asking for text
177
	term.setTextColor(colours.white)
178
	term.setCursorPos(7,5)
179
	term.setBackgroundColor(colours.blue)
180
	for y=5,13 do
181
		term.setCursorPos(7,y)
182
		for x=7,47 do
183
			if y==8 then--user input row
184
				if x==7 or x== 47 then
185
					term.setBackgroundColor(colours.lightGrey)
186
				else
187
					term.setBackgroundColor(colours.grey)
188
				end
189
			end
190
			term.write(" ")
191
		end
192
		term.setBackgroundColor(colours.lightGrey)
193
	end
194
	--finished drawing window. add text
195
	term.setBackgroundColor(colours.blue)
196
	term.setCursorPos(7,5)--TODO: center text
197
	term.write(text)
198
	term.setBackgroundColor(colours.grey)
199
	term.setCursorPos(8,8)
200
	return io.read()
201
end
202
203
function refresh()
204
	webType=1--website
205
	term.setTextColor(colours.black)
206
	term.setBackgroundColor(colours.white)
207
	
208
	term.clear()
209
	term.setCursorPos(1,1)
210
	
211
	renderGUI()
212
	
213
	webID=whois(siteName)
214
	if webID==nil or webID==-1 then--find what went wrong
215
		    if webID==nil and ddns==false then drawError("Server Not Found (Spelling?)")
216
		elseif webID==nil and ddns==true then drawError("No Response from DDNS")
217
		elseif webID==-1 and ddns==true then drawError("Site Not Found on DDNS (Spelling?)")
218
		else drawError("Unknown Error, Contact TMNET Support") end
219
		
220
	else loadPage(webID,pageName) end
221
	
222
	renderGUI()
223
end
224
-------------------
225
--other functions--
226
-------------------
227
function getDeviceSide(deviceType)
228
  -- List of all sides
229
  local lstSides = {"left","right","top","bottom","front","back"};
230
  -- Now loop through all the sides
231
  for i, side in pairs(lstSides) do
232
    if (peripheral.isPresent(side)) then
233
      -- Yup, there is something on this side
234
      if (peripheral.getType(side) == string.lower(deviceType)) then
235
        -- Yes, this is the device type we need, so return the side
236
        return side;
237
      end
238
    end
239
  end
240
  --nothing found, return nill
241
  return nil;
242
end
243
function split(text,splitAt)
244
	state=false
245
	outA=""
246
	outB=""
247
	for i=1,string.len(text) do 
248
		if string.sub(text,i,i)==splitAt then
249
			state=true
250
		end
251
		if state==false then
252
			outA=outA..string.sub(text,i,i)
253
		else
254
			outB=outB..string.sub(text,i,i)
255
		end
256
	end
257
	return outA,outB
258
end
259
--like split, but removes extra char
260
function split2(text,splitAt)
261
	outA,outB=split(text,splitAt)
262
	outB=string.sub(outB,2,-1)--remove first char (= to splitAt)
263
	return outA,outB
264
end
265
266
function interpret(text)
267
	command,args=split2(text,":")
268
	if command=="glob" then
269
		siteName,pageName=split2(args,"/")
270
		pageName="/"..pageName
271
		refresh()
272
	end
273
	if command=="loc" then
274
		pageName="/"..args
275
		refresh()
276
	end
277
	if command=="ref" then
278
		refresh()
279
	end
280
	if command=="ask" then
281
		arg1,arg2=split2(args,":")--expected format: ask:cookie:question
282
		rednet.send(siteID,"ans:"..arg1..":"..popup(arg2))
283
		print("please wait...")--TODO place this nicely in the text entry field
284
		--note: server should send refresh as soon as it is done
285
	end
286
	--TODO add input command
287
end
288
function enterPage()
289
	siteName,pageName=split(popup("web address"),"/")
290
	if pageName==nil or pageName=="" then
291
		pageName="/home"
292
	end
293
	refresh()
294
end
295
function renderMenu()
296
	term.setTextColor(colours.black)
297
	term.setBackgroundColor(colours.white)
298
299
	term.clear()
300
	term.setCursorPos(1,1)
301
	--add one space before every line due to side bar
302
	print(" "..version)
303
	print(" Designed by Train Master Network Systems, Inc.")
304
	print("")
305
	if ddnsID~=nil then print(" ID of Dedicated DNS: "..ddnsID) end
306
	if siteID~=nil then print(" ID of Current Website: "..siteID) end
307
	print(" Using Modem on Side: "..portSide)
308
	renderGUI()
309
end
310
function handleSelect()
311
	if menuMode==true then
312
		--edit web adress
313
		if currentX==1 then
314
			enterPage()
315
		end
316
		if currentX==2 then
317
			renderMenu()
318
		end
319
		--refresh
320
		if currentX==3 then
321
			refresh()
322
		end
323
	else--clicked on site
324
		if webType==1 then 
325
			rednet.send(siteID,"exec:"..pageName..":"..currentY)
326
		end
327
		--TODO add interactive menu
328
	end
329
end
330
-----------------------
331
--program begins here--
332
-----------------------
333
portSide=getDeviceSide("modem")
334
if portSide==nil then
335
	print("No Modems Found!")
336
end
337
rednet.open(portSide)
338
rednet.broadcast("@ddns")--search for dedicated dns
339
ddnsID,result=rednet.receive(1)
340
if result==nil then
341
ddns=false 
342
print(" Warning: No DDNS Found")
343
end
344
renderGUI()
345
enterPage()
346
renderGUI()
347
while true do
348
    parallel.waitForAny(quitProgram, otherStuff)
349
    if quit then
350
      print("Quitting....")
351
      break
352
    end
353
	event, p1, p2, p3 = os.pullEventRaw()
354
	if event=="key" or event=="char" then
355
		--up
356
		if p1==200 then
357
			if currentY~=1 then currentY=currentY-1 end
358
			menuMode=false
359
		end
360
		--down
361
		if p1==208  then
362
			if currentY~=18 then currentY=currentY+1 end
363
			menuMode=false
364
		end
365
		
366
		--left
367
		if p1==203 then
368
			if currentX~=1 then currentX=currentX-1 end
369
			menuMode=true
370
		end
371
		--right
372
		if p1==205 then
373
			if currentX~=3 then currentX=currentX+1 end
374
			menuMode=true
375
		end
376
		--enter or space (select)
377
		if p1==28 or p1==" "  then --removed 57
378
			handleSelect()
379
		end
380
		renderGUI()
381
	elseif event=="mouse_click" then
382
		if p3==19 then
383
			menuMode=true
384
			currentX=1--default if below is false
385
			if p2>36 then currentX=2 end
386
			if p2>42 then currentX=3 end
387
		else
388
			menuMode=false
389
			currentY=p3
390-
end
390+
391
		handleSelect()
392
		renderGUI()
393
	--only receive messages from current website
394
	elseif event=="rednet_message" and p1==siteID then
395
		interpret(p2)
396
	elseif event=="terminate" then
397
		term.setBackgroundColor(colours.black)
398
		term.setTextColor(colours.white)
399
		term.clear()
400
		term.setCursorPos(1,1)
401
	break
402
	end
403
	--TODO make an options menu
404
	--TODO add error handling
405
end
406
os.pullEvent = oldPull;