SHOW:
|
|
- or go back to the newest paste.
1 | -- usage: | |
2 | -- taco | |
3 | -- taco filename | |
4 | ||
5 | local tArgs = {...} | |
6 | local betaKey = "" | |
7 | local currentFile = "" | |
8 | local isSaved = true | |
9 | local isChanged = false | |
10 | local fileLinesArr = {""} | |
11 | local curLine,curCol,lastCol=1,0,0 | |
12 | local menus = {} | |
13 | local inMenu=false | |
14 | local selectedMenu = 1 | |
15 | local selectedSubMenu = 1 | |
16 | local running = true | |
17 | local config = {isFullScreen = false, clipboard=""} | |
18 | local showFirstTimeMessage = false | |
19 | local showAboutBox=false | |
20 | local collectedInputs = {file="My Input Data"} | |
21 | local collectedInputsCursor = {file=1} | |
22 | local collectedInputsOffsets = {file=0} | |
23 | local collectedInputsSize = {file=0} | |
24 | local w,h = term.getSize() | |
25 | local scrollOffsetX,scrollOffsetY = 0,0 | |
26 | local isBlinking = false | |
27 | local state = "edit" | |
28 | local message = {} | |
29 | local showingMessage=false | |
30 | local showingFileDialog = false | |
31 | local selectedMessageOption=1 | |
32 | local lastBlinkTime = 0 | |
33 | sleep(0.1) | |
34 | local timer = os.startTimer(0) | |
35 | ||
36 | local function setColors(monitor, bg, fg, bg2, fg2) | |
37 | if monitor then | |
38 | if monitor.isColor() then | |
39 | monitor.setBackgroundColor(bg) | |
40 | monitor.setTextColor(fg) | |
41 | else | |
42 | monitor.setBackgroundColor(bg2) | |
43 | monitor.setTextColor(fg2) | |
44 | end | |
45 | end | |
46 | end | |
47 | ||
48 | local function checkLinePosition() | |
49 | local maxLines = #fileLinesArr | |
50 | if curLine < 1 then | |
51 | curLine = 1 | |
52 | elseif curLine > #fileLinesArr then | |
53 | curLine = maxLines | |
54 | end | |
55 | local yOffset = 2 | |
56 | if config.isFullScreen then | |
57 | yOffset = 0 | |
58 | end | |
59 | if scrollOffsetY > h-yOffset-curLine then | |
60 | scrollOffsetY=h-yOffset-curLine | |
61 | elseif scrollOffsetY < 1-curLine then | |
62 | scrollOffsetY=1-curLine | |
63 | end | |
64 | end | |
65 | local function checkColPosition() | |
66 | if curCol < 0 then | |
67 | curCol = 0 | |
68 | elseif curCol > string.len(fileLinesArr[curLine]) then | |
69 | curCol = string.len(fileLinesArr[curLine]) | |
70 | end | |
71 | local total = h-3 --todo: possible bug | |
72 | if #fileLinesArr < total then | |
73 | total = #fileLinesArr | |
74 | end | |
75 | local padWidth = string.len(tostring(total)) | |
76 | local workingWidth = w - padWidth - 1 | |
77 | ||
78 | if scrollOffsetX >= workingWidth - curCol-1 then | |
79 | scrollOffsetX=workingWidth-curCol-1 | |
80 | elseif scrollOffsetX < 0-curCol then | |
81 | scrollOffsetX=0-curCol | |
82 | end | |
83 | end | |
84 | local function checkMenuPositions() | |
85 | if selectedMenu < 1 then | |
86 | selectedMenu = #menus | |
87 | elseif selectedMenu > #menus then | |
88 | selectedMenu = 1 | |
89 | end | |
90 | if selectedSubMenu < 1 then | |
91 | selectedSubMenu = #menus[selectedMenu].items | |
92 | elseif selectedSubMenu > #menus[selectedMenu].items then | |
93 | selectedSubMenu = 1 | |
94 | end | |
95 | end | |
96 | local function checkMessageOptionPositions() | |
97 | if selectedMessageOption < 1 then | |
98 | selectedMessageOption = #message.footer | |
99 | elseif selectedMessageOption > #message.footer then | |
100 | selectedMessageOption = 1 | |
101 | end | |
102 | end | |
103 | local function loadFile(file) | |
104 | if fs.exists(file) and not fs.isDir(file) then | |
105 | local tmpArr = {} | |
106 | local h = fs.open(file, "r") | |
107 | while true do | |
108 | local data = h.readLine() | |
109 | if data == nil then break end | |
110 | table.insert(tmpArr, data) | |
111 | end | |
112 | h.close() | |
113 | return tmpArr | |
114 | end | |
115 | return null | |
116 | end | |
117 | local function openFile(file) | |
118 | local data = loadFile(file) | |
119 | if data then | |
120 | fileLinesArr = {""} | |
121 | currentFile = file | |
122 | isSaved = false | |
123 | isChanged = false | |
124 | scrollOffsetX,scrollOffsetY=0,0 | |
125 | if data then | |
126 | fileLinesArr = data | |
127 | isSaved = true | |
128 | end | |
129 | curLine,curCol,lastCol=1,0,0 | |
130 | checkLinePosition() | |
131 | checkColPosition() | |
132 | return true | |
133 | end | |
134 | return false | |
135 | end | |
136 | local function saveFile(file, dataArr) | |
137 | local tmpArr = {} | |
138 | local h = fs.open(file, "w") | |
139 | if h then | |
140 | for i=1, #dataArr do | |
141 | h.writeLine(dataArr[i]) | |
142 | end | |
143 | h.close() | |
144 | isSaved = true | |
145 | isChanged = false | |
146 | return true | |
147 | end | |
148 | return false | |
149 | end | |
150 | local function loadSettings() | |
151 | if fs.exists("taco.db") then | |
152 | local cfg | |
153 | local h = fs.open("taco.db", "r") | |
154 | while true do | |
155 | data = h.readLine() | |
156 | if data == nil then break end | |
157 | if data == "--[[CONFIG:" then | |
158 | local tmpCfg = h.readAll() | |
159 | cfg=textutils.unserialize(string.sub(tmpCfg,1,string.len(tmpCfg)-2)) | |
160 | end | |
161 | end | |
162 | h.close() | |
163 | if cfg then | |
164 | if cfg.isFullScreen then | |
165 | config.isFullScreen = cfg.isFullScreen | |
166 | end | |
167 | if cfg.clipboard then | |
168 | config.clipboard = cfg.clipboard | |
169 | end | |
170 | end | |
171 | else | |
172 | showFirstTimeMessage = true | |
173 | end | |
174 | end | |
175 | local function saveSettings() | |
176 | settingsStr=textutils.serialize(config) | |
177 | local h = fs.open("taco.db", "w") | |
178 | h.writeLine('print("This is a settings file for TACO :)")') | |
179 | h.writeLine('--[[CONFIG:') | |
180 | h.writeLine(settingsStr) | |
181 | h.writeLine(']]') | |
182 | h.close() | |
183 | end | |
184 | local function newFile() | |
185 | currentFile = "" | |
186 | fileLinesArr={""} | |
187 | curLine,curCol,lastCol=1,0,0 | |
188 | checkLinePosition() | |
189 | checkColPosition() | |
190 | isSaved = true | |
191 | isChanged = false | |
192 | end | |
193 | ||
194 | table.insert(menus, { | |
195 | name="File", | |
196 | hotkey=keys.f, | |
197 | items={ | |
198 | {"New", "N", "new_file", true}, | |
199 | {"Open..", "O", "open_file", true}, | |
200 | {"Save", "S", "save_file", false}, | |
201 | {"Save As..", "A", "saveas_file", false}, | |
202 | {"--"}, | |
203 | {"Revert", "R", "revert_file", false}, | |
204 | --{"Print..", "P", "print_file", false}, | |
205 | --{"Run Script", "E", "run_file", false}, | |
206 | {"--"}, | |
207 | {"Exit", "X", "exit_app", true} | |
208 | } | |
209 | }) | |
210 | table.insert(menus, { | |
211 | name="Edit", | |
212 | hotkey=keys.e, | |
213 | items={ | |
214 | --{"Cut", "X", "cut_selection", false}, | |
215 | --{"Copy", "C", "copy_selection", false}, | |
216 | --{"Paste", "V", "paste_selection", false}, | |
217 | --{"--"}, | |
218 | --{"Delete", "D", "clear_selection", false}, | |
219 | --{"--"}, | |
220 | {"Cut Line", "K", "cut_line", false}, | |
221 | {"Copy Line", "J", "copy_line", false}, | |
222 | {"Paste Line", "U", "paste_line", false}, | |
223 | {"--"}, | |
224 | {"Delete Line", "R", "delete_line", false}, | |
225 | {"--"}, | |
226 | {"Clone Line", "R", "clone_line", false}, | |
227 | } | |
228 | }) | |
229 | --[[ | |
230 | table.insert(menus, { | |
231 | name="Search", | |
232 | hotkey=keys.s, | |
233 | items={ | |
234 | {"Find..", "F", "find_text", false}, | |
235 | {"Replace..", "R", "replace_text", false} | |
236 | } | |
237 | })]] | |
238 | table.insert(menus, { | |
239 | name="Options", | |
240 | hotkey=keys.o, | |
241 | items={ | |
242 | {"Full Screen Mode", "F", "fullscreen_toggle", false}, | |
243 | --{"Settings..", "S", "show_settings", false} | |
244 | } | |
245 | }) | |
246 | table.insert(menus, { | |
247 | name="Help", | |
248 | hotkey=keys.h, | |
249 | items={ | |
250 | --{"Help", "H", "show_help", true}, | |
251 | {"Grab Updates", "U", "perform_update", true}, | |
252 | {"--"}, | |
253 | {"About TACO", "A", "show_about", true}, | |
254 | } | |
255 | }) | |
256 | local function lpad(str, len, char) | |
257 | if char == nil then char = ' ' end | |
258 | local i = len - #str | |
259 | if i >= 0 then | |
260 | return string.rep(char, i) .. str | |
261 | else | |
262 | return str | |
263 | end | |
264 | end | |
265 | local function rpad(str, len, char) | |
266 | if char == nil then char = ' ' end | |
267 | local i = len - #str | |
268 | if i >= 0 then | |
269 | return str .. string.rep(char, i) | |
270 | else | |
271 | return str | |
272 | end | |
273 | end | |
274 | local function getMenuOffset(menu) | |
275 | local menuOffset = 3 | |
276 | ||
277 | for i = 1, selectedMenu - 1 do | |
278 | menuOffset = menuOffset + string.len(menus[i].name) + 2 | |
279 | end | |
280 | ||
281 | return menuOffset | |
282 | end | |
283 | local function getMenuWidth(menu) | |
284 | menuWidth = 1 | |
285 | ||
286 | for i = 1, #menus[selectedMenu].items do | |
287 | local len = string.len(menus[selectedMenu].items[i][1]) + 2 | |
288 | ||
289 | if len > menuWidth then | |
290 | menuWidth = len | |
291 | end | |
292 | end | |
293 | ||
294 | return menuWidth | |
295 | end | |
296 | local function getMenuHeight(menu) | |
297 | return #menus[selectedMenu].items | |
298 | end | |
299 | local function drawScreen(monitor) | |
300 | w,h = monitor.getSize() | |
301 | monitor.setBackgroundColor(colors.black) | |
302 | monitor.clear() | |
303 | --header bar | |
304 | local guiOffset = 1 | |
305 | local lineTotalOffset = 2 | |
306 | if config.isFullScreen then | |
307 | guiOffset = 0 | |
308 | lineTotalOffset = 0 | |
309 | end | |
310 | --editor area | |
311 | local ii=1 | |
312 | local total = h-lineTotalOffset-scrollOffsetY+curLine | |
313 | if #fileLinesArr < total then | |
314 | total = #fileLinesArr | |
315 | end | |
316 | local padWidth = string.len(tostring(total)) | |
317 | for i=1+guiOffset, h-(guiOffset/2) do | |
318 | local currentLineIndex = ii-scrollOffsetY | |
319 | local workingWidth = w - padWidth - 1 | |
320 | if 1==2 then | |
321 | workingWidth=workingWidth-1 --scrollbar | |
322 | end | |
323 | monitor.setCursorPos(1,i) | |
324 | setColors(monitor, colors.blue, colors.lightGray, colors.black, colors.white) | |
325 | monitor.write(string.rep(" ", w)) --subtract the two "+"'s | |
326 | if currentLineIndex <= #fileLinesArr then | |
327 | local currentLine = fileLinesArr[currentLineIndex] | |
328 | setColors(monitor, colors.white, colors.red, colors.white, colors.black) | |
329 | monitor.setCursorPos(1,i) | |
330 | monitor.write(lpad(tostring(currentLineIndex), padWidth, " ")) | |
331 | if curLine == currentLineIndex then | |
332 | setColors(monitor, colors.lightBlue, colors.white, colors.black, colors.white) | |
333 | else | |
334 | setColors(monitor, colors.blue, colors.lightGray, colors.black, colors.white) | |
335 | end | |
336 | monitor.setCursorPos(padWidth+1,ii+guiOffset) | |
337 | currentLineFit = currentLine | |
338 | if currentLineFit then | |
339 | currentLineFit = string.sub(currentLineFit, -scrollOffsetX+1, string.len(currentLineFit)) | |
340 | if string.len(currentLineFit) > workingWidth then | |
341 | currentLineFit = string.sub(currentLineFit, 1, workingWidth) | |
342 | end | |
343 | monitor.write(" "..rpad(currentLineFit, workingWidth, " ").." ") | |
344 | end | |
345 | if curLine == currentLineIndex and (isBlinking or inMenu) then | |
346 | monitor.setCursorPos(padWidth+2+curCol+scrollOffsetX,i) | |
347 | setColors(monitor, colors.white, colors.lightBlue, colors.white, colors.black) | |
348 | local msg = string.sub(currentLineFit,curCol+scrollOffsetX+1,curCol+scrollOffsetX+1) | |
349 | if msg == "" then msg = " " end | |
350 | monitor.write(msg) | |
351 | end | |
352 | end | |
353 | ii=ii+1 | |
354 | end | |
355 | ||
356 | if not config.isFullScreen or inMenu then | |
357 | --footer bar | |
358 | setColors(monitor, colors.lightGray, colors.black, colors.white, colors.black) | |
359 | monitor.setCursorPos(1,h) | |
360 | monitor.write(string.rep(" ", w)) | |
361 | ||
362 | monitor.setCursorPos(1,h) | |
363 | if not isSaved or isChanged then | |
364 | setColors(monitor, colors.lightGray, colors.red, colors.white, colors.black) | |
365 | monitor.write("*") | |
366 | end | |
367 | if currentFile == "" then | |
368 | setColors(monitor, colors.lightGray, colors.green, colors.white, colors.black) | |
369 | monitor.write("new_file") | |
370 | else | |
371 | monitor.write(currentFile) | |
372 | end | |
373 | ||
374 | setColors(monitor, colors.lightGray, colors.black, colors.white, colors.black) | |
375 | local footerMsg = "Ln "..curLine..":"..#fileLinesArr.." Col "..(curCol+1) --.." XOff="..scrollOffsetX | |
376 | monitor.setCursorPos(w-string.len(footerMsg)+1,h) | |
377 | monitor.write(footerMsg) | |
378 | ||
379 | --header bar | |
380 | monitor.setCursorPos(1,1) | |
381 | setColors(monitor, colors.lightGray, colors.black, colors.white, colors.black) | |
382 | monitor.write(string.rep(" ", w)) | |
383 | monitor.setCursorPos(2,1) | |
384 | for i=1, #menus do | |
385 | if inMenu and i == selectedMenu then | |
386 | setColors(monitor, colors.black, colors.white, colors.black, colors.white) | |
387 | else | |
388 | setColors(monitor, colors.lightGray, colors.black, colors.white, colors.black) | |
389 | end | |
390 | monitor.write(" "..menus[i].name.." ") | |
391 | end | |
392 | ||
393 | -- Time | |
394 | local time = os.time() | |
395 | local timeFmt = textutils.formatTime(time, false) | |
396 | local timeLen = string.len(timeFmt) | |
397 | monitor.setCursorPos(w-timeLen,1) | |
398 | setColors(monitor, colors.lightGray, colors.black, colors.white, colors.black) | |
399 | monitor.write(timeFmt) | |
400 | end | |
401 | ||
402 | if inMenu then | |
403 | monitor.setCursorPos(1,1) | |
404 | setColors(monitor, colors.lightGray, colors.black, colors.white, colors.black) | |
405 | local menuWidth = getMenuWidth(selectedMenu) | |
406 | local menuOffset = getMenuOffset(selectedMenu) | |
407 | for i=1, #menus[selectedMenu].items do | |
408 | if i == selectedSubMenu then | |
409 | setColors(monitor, colors.black, colors.white, colors.black, colors.white) | |
410 | else | |
411 | setColors(monitor, colors.lightGray, colors.black, colors.white, colors.black) | |
412 | end | |
413 | posX = menuOffset | |
414 | posY = i + 1 | |
415 | monitor.setCursorPos(posX,posY) | |
416 | monitor.write(string.rep(" ", menuWidth)) | |
417 | monitor.setCursorPos(posX,posY) | |
418 | local str = menus[selectedMenu].items[i][1] | |
419 | if str == "--" then | |
420 | if monitor.isColor() then | |
421 | monitor.setTextColor(colors.gray) | |
422 | else | |
423 | monitor.setTextColor(colors.black) | |
424 | end | |
425 | monitor.write(string.rep("-", menuWidth)) | |
426 | else | |
427 | monitor.write(" "..str.." ") | |
428 | end | |
429 | end | |
430 | end | |
431 | ||
432 | end | |
433 | ||
434 | function updateAllTheThings() | |
435 | shell.run("market get gjdh1m taco "..betaKey.." y") | |
436 | end | |
437 | local function resetBlink() | |
438 | lastBlinkTime = os.clock()+.5 | |
439 | isBlinking = true | |
440 | end | |
441 | local function centerText(monitor, tY, tText) | |
442 | local offX = (w+1)/2 - (string.len(tText)-1)/2 | |
443 | monitor.setCursorPos(offX, tY) | |
444 | monitor.write(tText) | |
445 | end | |
446 | local function centerTextWidth(monitor, tX, tY, width, tText) | |
447 | local offX = (width+1)/2 - (string.len(tText)-1)/2 | |
448 | monitor.setCursorPos(offX+tX, tY) | |
449 | monitor.write(tText) | |
450 | end | |
451 | local logo = { | |
452 | " 1111111111 "; | |
453 | " 11115e454e5e11 "; | |
454 | " 11545e5111111111"; | |
455 | "1154e411111111111"; | |
456 | "1e455111111111111"; | |
457 | "15ec5111111111111"; | |
458 | "1cccc1111111111 "; | |
459 | "1cccc111111 "; | |
460 | " 111111 "; | |
461 | } | |
462 | --[[Stolen Shamelessly from nPaintPro - http://pastebin.com/4QmTuJGU]] | |
463 | local function getColourOf(hex) | |
464 | local value = tonumber(hex, 16) | |
465 | if not value then return nil end | |
466 | value = math.pow(2,value) | |
467 | return value | |
468 | end | |
469 | local function drawPictureTable(mon, image, xinit, yinit, alpha) | |
470 | if not alpha then alpha = 1 end | |
471 | for y=1,#image do | |
472 | for x=1,#image[y] do | |
473 | mon.setCursorPos(xinit + x-1, yinit + y-1) | |
474 | local col = getColourOf(string.sub(image[y], x, x)) | |
475 | if not col then col = alpha end | |
476 | if term.isColor() then | |
477 | mon.setBackgroundColour(col) | |
478 | else | |
479 | local pixel = string.sub(image[y], x, x) | |
480 | if pixel == "c" or pixel == "5" or pixel == " " then | |
481 | mon.setBackgroundColour(colors.white) | |
482 | else | |
483 | mon.setBackgroundColour(colors.black) | |
484 | end | |
485 | end | |
486 | mon.write(" ") | |
487 | end | |
488 | end | |
489 | end | |
490 | --[[End Theft]] | |
491 | local function trySaveFileFromDialog() | |
492 | currentFile = collectedInputs.file | |
493 | if saveFile(currentFile, fileLinesArr) then | |
494 | showingFileDialog=false | |
495 | else | |
496 | messageBox("Error!", {"Couldn't save file!", "Try another name.."}, {{"OK",null}}) | |
497 | end | |
498 | end | |
499 | local function tryOpenFileFromDialog() | |
500 | if openFile(collectedInputs.file) then | |
501 | showingFileDialog=false | |
502 | else | |
503 | messageBox("Error!", {"Couldn't open file!"}, {{"OK",null}}) | |
504 | end | |
505 | end | |
506 | local function hideFileDialog() | |
507 | showingFileDialog=false | |
508 | end | |
509 | local fileDialog={} | |
510 | fileDialog.title="Open File" | |
511 | fileDialog.basePath="/" | |
512 | fileDialog.currentTab=1 | |
513 | fileDialog.currentTabMax=4 | |
514 | fileDialog.dirScrollOffset=0 | |
515 | fileDialog.fileScrollOffset=0 | |
516 | fileDialog.dirSelected=1 | |
517 | fileDialog.fileSelected=1 | |
518 | fileDialog.currentPathFiles={} | |
519 | fileDialog.currentPathFolders={} | |
520 | fileDialog.selectedFooterOption=1 | |
521 | fileDialog.footer={} | |
522 | local function addSlashIfNeeded(path) | |
523 | local len = string.len(path) | |
524 | if string.sub(path, len, len) ~= "/" then | |
525 | return path.."/" | |
526 | else | |
527 | return path | |
528 | end | |
529 | end | |
530 | local function addSlashIfNeededLeft(path) | |
531 | if string.sub(path, 1,1) ~= "/" then | |
532 | return "/"..path | |
533 | else | |
534 | return path | |
535 | end | |
536 | end | |
537 | local function getFilePath(file) | |
538 | local fName = fs.getName(file) | |
539 | local lenBpath = string.len(file) | |
540 | local lenFname = string.len(fName) | |
541 | return string.sub(file, 1, lenBpath - lenFname-1) | |
542 | end | |
543 | local function prepareDialog() | |
544 | local tmpList = fs.list(fileDialog.basePath) | |
545 | local tmpFileArr,tmpFolderArr={},{} | |
546 | fileDialog.basePath = addSlashIfNeeded(fileDialog.basePath) | |
547 | if fileDialog.basePath ~= "/" then | |
548 | table.insert(tmpFolderArr, {"..", getFilePath(fileDialog.basePath)}) | |
549 | end | |
550 | for key, file in ipairs(tmpList) do | |
551 | local len = string.len(fileDialog.basePath) | |
552 | file = addSlashIfNeeded(fileDialog.basePath)..file | |
553 | if fs.isDir(file) then | |
554 | table.insert(tmpFolderArr, {fs.getName(file), file.."/"}) | |
555 | else | |
556 | table.insert(tmpFileArr, {fs.getName(file), file}) | |
557 | end | |
558 | end | |
559 | fileDialog.currentPathFiles = tmpFileArr | |
560 | fileDialog.currentPathFolders = tmpFolderArr | |
561 | fileDialog.dirScrollOffset=0 | |
562 | fileDialog.fileScrollOffset=0 | |
563 | checkDialogLimits() | |
564 | end | |
565 | function dialogReset() | |
566 | fileDialog.currentTab=1 | |
567 | fileDialog.dirScrollOffset=0 | |
568 | fileDialog.fileScrollOffset=0 | |
569 | fileDialog.dirSelected=1 | |
570 | fileDialog.fileSelected=1 | |
571 | end | |
572 | local dirFileListHeight = 1 | |
573 | function checkDialogLimits() | |
574 | if fileDialog.selectedFooterOption < 1 then | |
575 | fileDialog.selectedFooterOption = #fileDialog.footer | |
576 | end | |
577 | if fileDialog.selectedFooterOption > #fileDialog.footer then | |
578 | fileDialog.selectedFooterOption = 1 | |
579 | end | |
580 | ||
581 | if fileDialog.dirSelected < 1 then | |
582 | fileDialog.dirSelected = 1 | |
583 | end | |
584 | if fileDialog.fileSelected < 1 then | |
585 | fileDialog.fileSelected = 1 | |
586 | end | |
587 | if fileDialog.fileSelected > #fileDialog.currentPathFiles then | |
588 | fileDialog.fileSelected = #fileDialog.currentPathFiles | |
589 | end | |
590 | if fileDialog.dirSelected > #fileDialog.currentPathFolders then | |
591 | fileDialog.dirSelected = #fileDialog.currentPathFolders | |
592 | end | |
593 | ||
594 | if fileDialog.dirScrollOffset > dirFileListHeight-fileDialog.dirSelected+1 then | |
595 | fileDialog.dirScrollOffset=dirFileListHeight-fileDialog.dirSelected+1 | |
596 | elseif fileDialog.dirScrollOffset < 1-fileDialog.dirSelected then | |
597 | fileDialog.dirScrollOffset=1-fileDialog.dirSelected | |
598 | end | |
599 | ||
600 | if fileDialog.fileScrollOffset > dirFileListHeight-fileDialog.fileSelected+1 then | |
601 | fileDialog.fileScrollOffset=dirFileListHeight-fileDialog.fileSelected+1 | |
602 | elseif fileDialog.fileScrollOffset < 1-fileDialog.fileSelected then | |
603 | fileDialog.fileScrollOffset=1-fileDialog.fileSelected | |
604 | end | |
605 | ||
606 | ||
607 | ||
608 | if collectedInputsCursor.file < 0 then | |
609 | collectedInputsCursor.file = 0 | |
610 | elseif collectedInputsCursor.file > string.len(collectedInputs.file) then | |
611 | collectedInputsCursor.file = string.len(collectedInputs.file) | |
612 | end | |
613 | if collectedInputsOffsets.file >= collectedInputsSize.file - collectedInputsCursor.file-1 then | |
614 | collectedInputsOffsets.file=collectedInputsSize.file-collectedInputsCursor.file-1 | |
615 | elseif collectedInputsOffsets.file < 0-collectedInputsCursor.file then | |
616 | collectedInputsOffsets.file=0-collectedInputsCursor.file | |
617 | end | |
618 | end | |
619 | function showFileSaveAsDialog() | |
620 | if fs.exists(currentFile) and not fs.isDir(currentFile) then | |
621 | fileDialog.basePath=addSlashIfNeededLeft(shell.resolve(getFilePath(currentFile))) | |
622 | else | |
623 | --fileDialog.basePath=addSlashIfNeededLeft(shell.resolve("")) | |
624 | end | |
625 | prepareDialog() | |
626 | dialogReset() | |
627 | fileDialog.title="Save File As.." | |
628 | collectedInputs.file = addSlashIfNeededLeft(shell.resolve(currentFile)) | |
629 | collectedInputsCursor.file = string.len(collectedInputs.file) | |
630 | collectedInputsOffsets.file = 0 | |
631 | collectedInputsSize.file = 0 | |
632 | fileDialog.footer={{"Save",trySaveFileFromDialog},{"Cancel",hideFileDialog}} | |
633 | showingFileDialog = true | |
634 | end | |
635 | function showFileOpenDialog() | |
636 | if fs.exists(currentFile) and not fs.isDir(currentFile) then | |
637 | fileDialog.basePath=addSlashIfNeededLeft(shell.resolve(getFilePath(currentFile))) | |
638 | else | |
639 | --fileDialog.basePath=addSlashIfNeededLeft(shell.resolve("")) | |
640 | end | |
641 | prepareDialog() | |
642 | dialogReset() | |
643 | fileDialog.title="Open File" | |
644 | collectedInputs.file = addSlashIfNeededLeft(shell.resolve(currentFile)) | |
645 | collectedInputsCursor.file = string.len(collectedInputs.file) | |
646 | collectedInputsOffsets.file = 0 | |
647 | collectedInputsSize.file = 0 | |
648 | fileDialog.footer={{"Open",tryOpenFileFromDialog},{"Cancel",hideFileDialog}} | |
649 | showingFileDialog = true | |
650 | end | |
651 | function drawFileDialog(monitor) | |
652 | w,h = monitor.getSize() | |
653 | local height = h-2 | |
654 | local width = w-4 | |
655 | local offX = (w+1)/2 - (width-1)/2 | |
656 | local offY = (h+1)/2 - (height-1)/2 | |
657 | local footerMsg = "" | |
658 | for o=1, #fileDialog.footer do | |
659 | local item = fileDialog.footer[o][1] | |
660 | if fileDialog.selectedFooterOption == o then | |
661 | item = "["..item.."]" | |
662 | else | |
663 | item = " "..item.." " | |
664 | end | |
665 | if o > 1 then | |
666 | item = " "..item | |
667 | end | |
668 | footerMsg=footerMsg..item | |
669 | end | |
670 | if monitor.isColor() then | |
671 | monitor.setBackgroundColor(colors.cyan) | |
672 | else | |
673 | monitor.setBackgroundColor(colors.black) | |
674 | end | |
675 | monitor.clear() | |
676 | for i=1, height do | |
677 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
678 | monitor.setCursorPos(offX, offY+i-1) | |
679 | if i == 1 or i == height then | |
680 | monitor.write("+") | |
681 | monitor.write(string.rep("-", width-2)) | |
682 | monitor.write("+") | |
683 | if i == 1 then | |
684 | setColors(monitor, colors.black, colors.yellow, colors.white, colors.black) | |
685 | centerText(monitor, offY+i-1, " "..fileDialog.title.." ") | |
686 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
687 | elseif i == height then | |
688 | if fileDialog.currentTab == 4 then | |
689 | setColors(monitor, colors.black, colors.white, colors.black, colors.white) | |
690 | else | |
691 | setColors(monitor, colors.lightGray, colors.white, colors.white, colors.black) | |
692 | end | |
693 | centerText(monitor, offY+i-1, " "..footerMsg.." ") | |
694 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
695 | end | |
696 | else | |
697 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
698 | monitor.write("|") | |
699 | setColors(monitor, colors.white, colors.black, colors.white, colors.black) | |
700 | monitor.write(string.rep(" ", width-2)) | |
701 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
702 | monitor.write("|") | |
703 | end | |
704 | end | |
705 | setColors(monitor, colors.white, colors.gray, colors.white, colors.black) | |
706 | monitor.setCursorPos(offX + 2, offY + 2) | |
707 | monitor.write("File: ") | |
708 | if fileDialog.currentTab == 1 then | |
709 | setColors(monitor, colors.black, colors.white, colors.black, colors.white) | |
710 | else | |
711 | setColors(monitor, colors.lightGray, colors.white, colors.black, colors.white) | |
712 | end | |
713 | local workingWidth = width - 10 | |
714 | local textWidth = workingWidth | |
715 | collectedInputsSize.file = textWidth | |
716 | monitor.write(string.rep(" ", workingWidth)) | |
717 | monitor.setCursorPos(offX + 8, offY + 2) | |
718 | ||
719 | currentLineFit = collectedInputs.file | |
720 | inputCursor = collectedInputsCursor.file | |
721 | inputOffsetX = collectedInputsOffsets.file | |
722 | if currentLineFit then | |
723 | currentLineFit = string.sub(currentLineFit, -inputOffsetX+1, string.len(currentLineFit)) | |
724 | if string.len(currentLineFit) > textWidth then | |
725 | currentLineFit = string.sub(currentLineFit, 1, textWidth) | |
726 | end | |
727 | monitor.write(rpad(currentLineFit, textWidth, " ")) | |
728 | end | |
729 | if fileDialog.currentTab == 1 and isBlinking then | |
730 | monitor.setCursorPos(offX+8+inputCursor+inputOffsetX,offY + 2) | |
731 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
732 | local msg = string.sub(currentLineFit,inputCursor+inputOffsetX+1,inputCursor+inputOffsetX+1) | |
733 | if msg == "" then msg = " " end | |
734 | monitor.write(msg) | |
735 | end | |
736 | ||
737 | ||
738 | local fileStart = 15 | |
739 | setColors(monitor, colors.white, colors.gray, colors.white, colors.black) | |
740 | monitor.setCursorPos(offX + 2, offY + 4) | |
741 | monitor.write("Dir: ") | |
742 | monitor.setCursorPos(offX + fileStart, offY + 4) | |
743 | monitor.write("Files: "..fileDialog.basePath) | |
744 | ||
745 | dirFileListHeight = height - offY - 6 | |
746 | for i=0, dirFileListHeight do | |
747 | local dirIndex = i+1-fileDialog.dirScrollOffset | |
748 | local fileIndex = i+1-fileDialog.fileScrollOffset | |
749 | ||
750 | if fileDialog.currentTab == 2 then | |
751 | setColors(monitor, colors.black, colors.white, colors.black, colors.white) | |
752 | else | |
753 | setColors(monitor, colors.lightGray, colors.white, colors.black, colors.white) | |
754 | end | |
755 | monitor.setCursorPos(offX + 2, offY + 5+i) | |
756 | monitor.write(string.rep(" ", fileStart - offX)) | |
757 | if fileDialog.currentPathFolders[dirIndex] then | |
758 | if fileDialog.currentTab == 2 and dirIndex == fileDialog.dirSelected then | |
759 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
760 | end | |
761 | monitor.setCursorPos(offX + 2, offY + 5+i) | |
762 | monitor.write(fileDialog.currentPathFolders[dirIndex][1]) | |
763 | end | |
764 | ||
765 | if fileDialog.currentTab == 3 then | |
766 | setColors(monitor, colors.black, colors.white, colors.black, colors.white) | |
767 | else | |
768 | setColors(monitor, colors.lightGray, colors.white, colors.black, colors.white) | |
769 | end | |
770 | monitor.setCursorPos(offX + fileStart, offY + 5+i) | |
771 | monitor.write(string.rep(" ", width - fileStart - 2)) | |
772 | if fileDialog.currentPathFiles[fileIndex] then | |
773 | if fileDialog.currentTab == 3 and fileIndex == fileDialog.fileSelected then | |
774 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
775 | end | |
776 | monitor.setCursorPos(offX + fileStart, offY + 5+i) | |
777 | monitor.write(fileDialog.currentPathFiles[fileIndex][1]) | |
778 | end | |
779 | end | |
780 | ||
781 | --gui debug | |
782 | --monitor.setCursorPos(1,1) | |
783 | --monitor.write("ICur="..collectedInputsCursor.file.." IOff="..collectedInputsOffsets.file.." ISize="..collectedInputsSize.file.." IValSize="..string.len(collectedInputs.file)) | |
784 | end | |
785 | function drawAbout(monitor) | |
786 | w,h = monitor.getSize() | |
787 | local height = 13 | |
788 | local width = 39 | |
789 | local offX = (w+1)/2 - (width-1)/2 | |
790 | local offY = (h+1)/2 - (height-1)/2 | |
791 | if monitor.isColor() then | |
792 | monitor.setBackgroundColor(colors.cyan) | |
793 | else | |
794 | monitor.setBackgroundColor(colors.black) | |
795 | end | |
796 | monitor.clear() | |
797 | for i=1, height do | |
798 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
799 | monitor.setCursorPos(offX, offY+i-1) | |
800 | if i == 1 or i == height then | |
801 | monitor.write("+") | |
802 | monitor.write(string.rep("-", width-2)) | |
803 | monitor.write("+") | |
804 | if i == 1 then | |
805 | setColors(monitor, colors.black, colors.yellow, colors.black, colors.white) | |
806 | centerText(monitor, offY+i-1, " About TACO BETA ") | |
807 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
808 | end | |
809 | else | |
810 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
811 | monitor.write("|") | |
812 | setColors(monitor, colors.white, colors.black, colors.white, colors.black) | |
813 | monitor.write(string.rep(" ", width-2)) | |
814 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
815 | monitor.write("|") | |
816 | end | |
817 | end | |
818 | drawPictureTable(monitor, logo, offX + 2, offY + 2, colours.white) | |
819 | setColors(monitor, colors.white, colors.orange, colors.white, colors.black) | |
820 | centerTextWidth(monitor, offX + 14, offY+3, width - ((offX*2) + 10), "=TACO BETA=") | |
821 | setColors(monitor, colors.white, colors.gray, colors.white, colors.black) | |
822 | centerTextWidth(monitor, offX + 14, offY+4, width - ((offX*2) + 10), "Edit with flavor!") | |
823 | setColors(monitor, colors.white, colors.lightGray, colors.white, colors.black) | |
824 | centerTextWidth(monitor, offX + 14, offY+6, width - ((offX*2) + 10), "By: da404lewzer") | |
825 | centerTextWidth(monitor, offX + 14, offY+8, width - ((offX*2) + 10), "TurtleScripts.com") | |
826 | centerTextWidth(monitor, offX + 14, offY+9, width - ((offX*2) + 10), "Project #gjdh01") | |
827 | end | |
828 | function drawMessage(monitor) | |
829 | w,h = monitor.getSize() | |
830 | local height = #message.body + 2 + 2 --2 for header/footer, 2 for border | |
831 | local width = 1 | |
832 | for i=1, #message.body do | |
833 | if string.len(message.body[i])+4 > width then | |
834 | width = string.len(message.body[i])+4 | |
835 | end | |
836 | end | |
837 | local footerMsg = "" | |
838 | for o=1, #message.footer do | |
839 | local item = message.footer[o][1] | |
840 | if selectedMessageOption == o then | |
841 | item = "["..item.."]" | |
842 | else | |
843 | item = " "..item.." " | |
844 | end | |
845 | if o > 1 then | |
846 | item = " "..item | |
847 | end | |
848 | footerMsg=footerMsg..item | |
849 | end | |
850 | if string.len(message.title)+4 > width then | |
851 | width = string.len(message.title)+4 | |
852 | end | |
853 | if string.len(footerMsg)+4 > width then | |
854 | width = string.len(footerMsg)+4 | |
855 | end | |
856 | local offX = (w+1)/2 - (width-1)/2 | |
857 | local offY = (h+1)/2 - (height-1)/2 | |
858 | for i=1, height do | |
859 | setColors(monitor, colors.orange, colors.black, colors.black, colors.white) | |
860 | monitor.setCursorPos(offX, offY+i-1) | |
861 | if i == 1 or i == height then | |
862 | monitor.write("+") | |
863 | monitor.write(string.rep("-", width-2)) | |
864 | monitor.write("+") | |
865 | if i == 1 then | |
866 | setColors(monitor, colors.black, colors.yellow, colors.black, colors.white) | |
867 | centerText(monitor, offY+i-1, " "..message.title.." ") | |
868 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
869 | elseif i == height then | |
870 | setColors(monitor, colors.black, colors.white, colors.black, colors.white) | |
871 | centerText(monitor, offY+i-1, " "..footerMsg.." ") | |
872 | setColors(monitor, colors.orange, colors.black, colors.white, colors.black) | |
873 | end | |
874 | else | |
875 | setColors(monitor, colors.orange, colors.black, colors.black, colors.white) | |
876 | monitor.write("|") | |
877 | setColors(monitor, colors.white, colors.black, colors.white, colors.black) | |
878 | monitor.write(string.rep(" ", width-2)) | |
879 | setColors(monitor, colors.orange, colors.black, colors.black, colors.white) | |
880 | monitor.write("|") | |
881 | if i-2 > 0 and i-2 <= #message.body then | |
882 | setColors(monitor, colors.white, colors.black, colors.white, colors.black) | |
883 | centerText(monitor, offY+i-1, message.body[i-2]) | |
884 | end | |
885 | ||
886 | end | |
887 | end | |
888 | end | |
889 | function messageBox(title, bodyArr, footer) | |
890 | message.title = title | |
891 | message.body = bodyArr | |
892 | message.footer = footer | |
893 | showingMessage = true | |
894 | end | |
895 | local function trySaveFileAs() | |
896 | showFileSaveAsDialog() | |
897 | end | |
898 | local function stopEditor() | |
899 | running = false | |
900 | end | |
901 | local function trySaveFile() | |
902 | if currentFile == ""then | |
903 | trySaveFileAs() | |
904 | else | |
905 | saveFile(currentFile, fileLinesArr) | |
906 | end | |
907 | end | |
908 | local function trySaveFileThenNew() | |
909 | if currentFile == ""then | |
910 | trySaveFileAs() | |
911 | else | |
912 | saveFile(currentFile, fileLinesArr) | |
913 | if isSaved and not isChanged then | |
914 | newFile() | |
915 | end | |
916 | end | |
917 | end | |
918 | local function trySaveFileThenOpen() | |
919 | if currentFile == ""then | |
920 | trySaveFileAs() | |
921 | else | |
922 | saveFile(currentFile, fileLinesArr) | |
923 | if isSaved and not isChanged then | |
924 | showFileOpenDialog() | |
925 | end | |
926 | end | |
927 | end | |
928 | local function trySaveFileThenExit() | |
929 | if currentFile == ""then | |
930 | trySaveFileAs() | |
931 | else | |
932 | saveFile(currentFile, fileLinesArr) | |
933 | if isSaved and not isChanged then | |
934 | stopEditor() | |
935 | end | |
936 | end | |
937 | end | |
938 | local function tryExitEditor() | |
939 | if isSaved and not isChanged then | |
940 | stopEditor() | |
941 | else | |
942 | messageBox( "Exit Editor?", | |
943 | { | |
944 | "The current file isn't saved, save it first?" | |
945 | }, | |
946 | {{"YES", trySaveFileThenExit}, {"NO", stopEditor}, {"CANCEL", null}} | |
947 | ) | |
948 | end | |
949 | end | |
950 | local function tryOpenFile() | |
951 | if isSaved and not isChanged then | |
952 | showFileOpenDialog() | |
953 | else | |
954 | messageBox( "Create New File..", | |
955 | { | |
956 | "The current file isn't saved, save it first?" | |
957 | }, | |
958 | {{"YES", trySaveFileThenOpen}, {"NO", showFileOpenDialog}, {"CANCEL", null}} | |
959 | ) | |
960 | end | |
961 | end | |
962 | local function tryNewFile() | |
963 | if isSaved and not isChanged then | |
964 | newFile() | |
965 | else | |
966 | messageBox( "Create New File..", | |
967 | { | |
968 | "The current file isn't saved, save it first?" | |
969 | }, | |
970 | {{"YES", trySaveFileThenNew}, {"NO", newFile}, {"CANCEL", null}} | |
971 | ) | |
972 | end | |
973 | end | |
974 | local function revertFile() | |
975 | if currentFile == "" then | |
976 | fileLinesArr = {""} | |
977 | isChanged = false | |
978 | else | |
979 | if not openFile(currentFile) then | |
980 | messageBox("Error!", {"Couldn't revert file!"}, {{"OK",null}}) | |
981 | end | |
982 | end | |
983 | end | |
984 | local function tryRevertFile() | |
985 | messageBox( "Revert file?", | |
986 | { | |
987 | "This cannot be done, sure?" | |
988 | }, | |
989 | {{"YES", revertFile}, {"NO", null}} | |
990 | ) | |
991 | end | |
992 | local function doFileDialogDefaultOption() | |
993 | local item = fileDialog.footer[1][2] | |
994 | if item then | |
995 | item() | |
996 | end | |
997 | fileDialog.selectedFooterOption = 1 | |
998 | end | |
999 | local function doFileDialogMessageOption() | |
1000 | local item = fileDialog.footer[fileDialog.selectedFooterOption][2] | |
1001 | if item then | |
1002 | item() | |
1003 | end | |
1004 | fileDialog.selectedFooterOption = 1 | |
1005 | end | |
1006 | local function doMessageOption() | |
1007 | local item = message.footer[selectedMessageOption][2] | |
1008 | if item then | |
1009 | item() | |
1010 | end | |
1011 | selectedMessageOption = 1 | |
1012 | end | |
1013 | local function doMenuAction(action) | |
1014 | if action == "exit_app" then | |
1015 | tryExitEditor() | |
1016 | elseif action == "new_file" then | |
1017 | tryNewFile() | |
1018 | elseif action == "open_file" then | |
1019 | tryOpenFile() | |
1020 | elseif action == "revert_file" then | |
1021 | tryRevertFile() | |
1022 | elseif action == "save_file" then | |
1023 | trySaveFile() | |
1024 | elseif action == "saveas_file" then | |
1025 | trySaveFileAs() | |
1026 | elseif action == "paste_line" then | |
1027 | table.insert(fileLinesArr, curLine, config.clipboard) | |
1028 | isChanged=true | |
1029 | elseif action == "clone_line" then | |
1030 | table.insert(fileLinesArr, curLine, fileLinesArr[curLine]) | |
1031 | isChanged=true | |
1032 | elseif action == "copy_line" then | |
1033 | config.clipboard = fileLinesArr[curLine] | |
1034 | elseif action == "cut_line" then | |
1035 | config.clipboard = fileLinesArr[curLine] | |
1036 | table.remove(fileLinesArr, curLine) | |
1037 | if #fileLinesArr == 0 then | |
1038 | fileLinesArr = {""} | |
1039 | end | |
1040 | isChanged=true | |
1041 | elseif action == "delete_line" then | |
1042 | table.remove(fileLinesArr, curLine) | |
1043 | if #fileLinesArr == 0 then | |
1044 | fileLinesArr = {""} | |
1045 | end | |
1046 | isChanged=true | |
1047 | elseif action == "perform_update" then | |
1048 | setColors(temp, colors.black, colors.white, colors.black, colors.white) | |
1049 | term.clear() | |
1050 | term.setCursorPos(1,1) | |
1051 | updateAllTheThings() | |
1052 | messageBox("Downloaded Latest", | |
1053 | { | |
1054 | "Restart TACO to complete :)" | |
1055 | }, | |
1056 | {{"OK", null}}) | |
1057 | timer = os.startTimer(0.01) | |
1058 | elseif action == "show_about" then | |
1059 | showAboutBox = true | |
1060 | elseif action == "fullscreen_toggle" then | |
1061 | config.isFullScreen = not config.isFullScreen | |
1062 | checkLinePosition() | |
1063 | checkColPosition() | |
1064 | else | |
1065 | --show_help | |
1066 | --show_settings | |
1067 | --replace_text | |
1068 | --find_text | |
1069 | --delete_line | |
1070 | --paste_line | |
1071 | --copy_line | |
1072 | --cut_line | |
1073 | --clear_selection | |
1074 | --paste_selection | |
1075 | --cut_selection | |
1076 | --copy_selection | |
1077 | --print_file | |
1078 | --revert_file | |
1079 | --open_file | |
1080 | ||
1081 | end | |
1082 | selectedMenu = 1 | |
1083 | selectedSubMenu = 1 | |
1084 | end | |
1085 | ||
1086 | ||
1087 | loadSettings() | |
1088 | ||
1089 | if #tArgs > 0 then | |
1090 | --openFile(tArgs[1]) | |
1091 | if not openFile(addSlashIfNeededLeft(shell.resolve(getFilePath(tArgs[1])))) then | |
1092 | messageBox("Error!", {"Couldn't open file!"}, {{"OK",null}}) | |
1093 | end | |
1094 | end | |
1095 | prepareDialog() | |
1096 | if showFirstTimeMessage then | |
1097 | messageBox("Welcome to TACO BETA", | |
1098 | { | |
1099 | "Welcome to the editor with flavor!", | |
1100 | "This is BETA sorry if you find bugs :(", | |
1101 | "", | |
1102 | "Presse ENTER to continue,", | |
1103 | "Press CONTROL to access menus :)" | |
1104 | }, | |
1105 | {{"OK", null}}) | |
1106 | end | |
1107 | while running do | |
1108 | local event, p1,p2,p3 = os.pullEvent() | |
1109 | if event == "mouse_scroll" then | |
1110 | if not showingMessage and not showAboutBox and not inMenu then | |
1111 | curLine=curLine+p1 | |
1112 | checkLinePosition() | |
1113 | checkColPosition() | |
1114 | resetBlink() | |
1115 | end | |
1116 | elseif event == "mouse_click" then | |
1117 | if not showingMessage and not showAboutBox and not showingFileDialog then-- and not inMenu | |
1118 | local padWidth = string.len(tostring(#fileLinesArr)) | |
1119 | local offsetY = 1 | |
1120 | if config.isFullScreen then offsetY = 0 end | |
1121 | if p1 == 1 then | |
1122 | if p3 <= 1 then | |
1123 | pos = 1 | |
1124 | prevPos = pos | |
1125 | ||
1126 | for i = 1, #menus do | |
1127 | pos = pos + string.len(menus[i].name) + 2 | |
1128 | ||
1129 | if p2 > prevPos and p2 <= pos then | |
1130 | if i == selectedMenu and inMenu then | |
1131 | inMenu = false | |
1132 | else | |
1133 | inMenu = true | |
1134 | selectedMenu = i | |
1135 | selectedSubMenu = 1 | |
1136 | end | |
1137 | ||
1138 | break | |
1139 | end | |
1140 | ||
1141 | prevpos = pos | |
1142 | end | |
1143 | end | |
1144 | ||
1145 | if inMenu and p3 > 1 then | |
1146 | menuOffset = getMenuOffset(selectedMenu) | |
1147 | ||
1148 | if p2 > menuOffset - 1 and p2 < menuOffset + getMenuWidth(selectedMenu) and p3 <= getMenuHeight(selectedMenu) + 1 then | |
1149 | items = menus[selectedMenu].items | |
1150 | itemCount = #items | |
1151 | ||
1152 | for i = 1, itemCount do | |
1153 | if p3 - 1 == i then | |
1154 | if items[i][1] == "--" then | |
1155 | if i >= itemCount then | |
1156 | if i == 1 then | |
1157 | selectedSubMenu = 1 | |
1158 | else | |
1159 | selectedSubMenu = i - 1 | |
1160 | end | |
1161 | else | |
1162 | selectedSubMenu = i + 1 | |
1163 | end | |
1164 | else | |
1165 | selectedSubMenu = i | |
1166 | doMenuAction(menus[selectedMenu].items[selectedSubMenu][3]) | |
1167 | inMenu = false | |
1168 | end | |
1169 | end | |
1170 | end | |
1171 | else | |
1172 | inMenu = false | |
1173 | end | |
1174 | elseif not inMenu and p3 > 1 then | |
1175 | curCol=p2-padWidth-scrollOffsetX-2 | |
1176 | curLine=p3-offsetY-scrollOffsetY | |
1177 | checkLinePosition() | |
1178 | checkColPosition() | |
1179 | resetBlink() | |
1180 | end | |
1181 | end | |
1182 | elseif showingMessage then | |
1183 | height = #message.body + 4 | |
1184 | posY = (((h + 1) / 2) - ((height - 1) / 2)) + height - 1 | |
1185 | ||
1186 | footerWidth = 1 | |
1187 | ||
1188 | for i = 1, #message.footer do | |
1189 | item = message.footer[i][1] | |
1190 | footerWidth = footerWidth + string.len(item) + 2 | |
1191 | ||
1192 | if i > 1 then | |
1193 | footerWidth = footerWidth + 1 | |
1194 | end | |
1195 | end | |
1196 | ||
1197 | posX = ((w + 1) / 2) - ((footerWidth - 1) / 2) -- + 1 for space before buttons | |
1198 | ||
1199 | if p3 == posY then | |
1200 | pos = posX | |
1201 | prevPos = pos | |
1202 | ||
1203 | for i = 1, #message.footer do | |
1204 | pos = pos + string.len(message.footer[i][1]) + 2 | |
1205 | ||
1206 | if p2 >= prevPos and p2 < pos then | |
1207 | selectedMessageOption = i | |
1208 | showingMessage = false | |
1209 | doMessageOption() | |
1210 | break | |
1211 | end | |
1212 | ||
1213 | pos = pos + 1 | |
1214 | prevPos = pos | |
1215 | end | |
1216 | end | |
1217 | elseif showingFileDialog then | |
1218 | if p3 == 4 and p2 > 10 and p2 <= w - 4 then -- File textbox | |
1219 | fileDialog.currentTab = 1 | |
1220 | collectedInputsCursor.file = p2 - collectedInputsOffsets.file - 11 | |
1221 | checkDialogLimits() | |
1222 | elseif p3 > 6 and p3 <= h - 3 then -- Dir and File horizontal area | |
1223 | if p2 > 4 and p2 <= 16 then | |
1224 | fileDialog.currentTab = 2 | |
1225 | fileDialog.dirSelected = fileDialog.dirScrollOffset + (p3 - 6) | |
1226 | checkDialogLimits() | |
1227 | fileDialog.basePath = fileDialog.currentPathFolders[fileDialog.dirSelected][2] | |
1228 | fileDialog.dirScrollOffset = 1 | |
1229 | fileDialog.dirSelected = 1 | |
1230 | prepareDialog() | |
1231 | elseif p2 > 17 and p2 <= w - 4 then | |
1232 | fileDialog.currentTab = 3 | |
1233 | fileDialog.fileSelected = fileDialog.fileScrollOffset + (p3 - 6) | |
1234 | checkDialogLimits() | |
1235 | collectedInputs.file = fileDialog.currentPathFiles[fileDialog.fileSelected][2] | |
1236 | end | |
1237 | elseif p3 == h - 1 then | |
1238 | footerWidth = 1 | |
1239 | ||
1240 | for i = 1, #fileDialog.footer do | |
1241 | item = fileDialog.footer[i][1] | |
1242 | footerWidth = footerWidth + string.len(item) + 2 | |
1243 | ||
1244 | if i > 1 then | |
1245 | footerWidth = footerWidth + 1 | |
1246 | end | |
1247 | end | |
1248 | ||
1249 | footerOffset = ((w + 1) / 2) - (footerWidth / 2) | |
1250 | ||
1251 | if p2 >= footerOffset and p2 <= footerOffset + footerWidth then | |
1252 | fileDialog.currentTab = 4 | |
1253 | end | |
1254 | ||
1255 | pos = footerOffset + 1 | |
1256 | prevPos = pos | |
1257 | ||
1258 | for i = 1, #fileDialog.footer do | |
1259 | pos = pos + string.len(fileDialog.footer[i][1]) + 2 | |
1260 | ||
1261 | if p2 >= prevPos and p2 < pos then | |
1262 | fileDialog.selectedFooterOption = i | |
1263 | doFileDialogMessageOption() | |
1264 | break | |
1265 | end | |
1266 | ||
1267 | pos = pos + 1 | |
1268 | prevPos = pos | |
1269 | end | |
1270 | end | |
1271 | elseif showAboutBox then | |
1272 | showAboutBox = false | |
1273 | end | |
1274 | elseif event == "key" then | |
1275 | if showingMessage then | |
1276 | if p1 == keys.enter then | |
1277 | showingMessage = false | |
1278 | doMessageOption() | |
1279 | elseif p1 == keys.left or p1 == keys.up then | |
1280 | selectedMessageOption=selectedMessageOption-1 | |
1281 | checkMessageOptionPositions() | |
1282 | elseif p1 == keys.right or p1 == keys.down then | |
1283 | selectedMessageOption=selectedMessageOption+1 | |
1284 | checkMessageOptionPositions() | |
1285 | end | |
1286 | elseif showAboutBox then | |
1287 | if p1 == keys.enter then | |
1288 | showAboutBox = false | |
1289 | end | |
1290 | elseif showingFileDialog then | |
1291 | if p1 == keys.enter then | |
1292 | if fileDialog.currentTab == 1 then | |
1293 | doFileDialogDefaultOption() | |
1294 | elseif fileDialog.currentTab == 2 then | |
1295 | fileDialog.basePath = fileDialog.currentPathFolders[fileDialog.dirSelected][2] | |
1296 | prepareDialog() | |
1297 | elseif fileDialog.currentTab == 3 then | |
1298 | collectedInputs.file = fileDialog.currentPathFiles[fileDialog.fileSelected][2] | |
1299 | fileDialog.currentTab = 4 | |
1300 | prepareDialog() | |
1301 | elseif fileDialog.currentTab == 4 then | |
1302 | doFileDialogMessageOption() | |
1303 | end | |
1304 | elseif p1 == keys.tab then | |
1305 | fileDialog.currentTab=fileDialog.currentTab+1 | |
1306 | if fileDialog.currentTab > fileDialog.currentTabMax then | |
1307 | fileDialog.currentTab = 1 | |
1308 | end | |
1309 | elseif p1 == keys.home then | |
1310 | if fileDialog.currentTab == 1 then | |
1311 | collectedInputsCursor.file=0 | |
1312 | end | |
1313 | checkDialogLimits() | |
1314 | elseif p1 == keys["end"] then | |
1315 | if fileDialog.currentTab == 1 then | |
1316 | collectedInputsCursor.file=string.len(collectedInputs.file)+1 | |
1317 | end | |
1318 | checkDialogLimits() | |
1319 | ||
1320 | elseif p1 == keys.backspace then | |
1321 | if fileDialog.currentTab == 1 then | |
1322 | if collectedInputsCursor.file > 0 then | |
1323 | local leftSide = string.sub(collectedInputs.file, 1, collectedInputsCursor.file-1) | |
1324 | local rightSide = string.sub(collectedInputs.file, collectedInputsCursor.file+1) | |
1325 | collectedInputs.file = leftSide..rightSide | |
1326 | collectedInputsCursor.file=collectedInputsCursor.file-1 | |
1327 | end | |
1328 | end | |
1329 | checkDialogLimits() | |
1330 | elseif p1 == keys.delete then | |
1331 | if fileDialog.currentTab == 1 then | |
1332 | if collectedInputsCursor.file <= string.len(collectedInputs.file) then | |
1333 | local leftSide = string.sub(collectedInputs.file, 1, collectedInputsCursor.file) | |
1334 | local rightSide = string.sub(collectedInputs.file, collectedInputsCursor.file+2) | |
1335 | collectedInputs.file = leftSide..rightSide | |
1336 | end | |
1337 | end | |
1338 | checkDialogLimits() | |
1339 | elseif p1 == keys.up or p1 == keys.left then | |
1340 | if fileDialog.currentTab == 1 then | |
1341 | collectedInputsCursor.file=collectedInputsCursor.file-1 | |
1342 | elseif fileDialog.currentTab == 2 then | |
1343 | fileDialog.dirSelected=fileDialog.dirSelected-1 | |
1344 | elseif fileDialog.currentTab == 3 then | |
1345 | fileDialog.fileSelected=fileDialog.fileSelected-1 | |
1346 | elseif fileDialog.currentTab == 4 then | |
1347 | fileDialog.selectedFooterOption=fileDialog.selectedFooterOption-1 | |
1348 | end | |
1349 | checkDialogLimits() | |
1350 | elseif p1 == keys.down or p1 == keys.right then | |
1351 | if fileDialog.currentTab == 1 then | |
1352 | collectedInputsCursor.file=collectedInputsCursor.file+1 | |
1353 | elseif fileDialog.currentTab == 2 then | |
1354 | fileDialog.dirSelected=fileDialog.dirSelected+1 | |
1355 | elseif fileDialog.currentTab == 3 then | |
1356 | fileDialog.fileSelected=fileDialog.fileSelected+1 | |
1357 | elseif fileDialog.currentTab == 4 then | |
1358 | fileDialog.selectedFooterOption=fileDialog.selectedFooterOption+1 | |
1359 | end | |
1360 | checkDialogLimits() | |
1361 | end | |
1362 | else | |
1363 | if state == "edit" then | |
1364 | if p1 == 29 or p1 == 157 then | |
1365 | inMenu = not inMenu | |
1366 | end | |
1367 | if inMenu then | |
1368 | if p1 == keys.up then | |
1369 | selectedSubMenu=selectedSubMenu-1 | |
1370 | checkMenuPositions() | |
1371 | if menus[selectedMenu].items[selectedSubMenu][1] == "--" then | |
1372 | selectedSubMenu=selectedSubMenu-1 | |
1373 | checkMenuPositions() | |
1374 | end | |
1375 | elseif p1 == keys.down then | |
1376 | selectedSubMenu=selectedSubMenu+1 | |
1377 | checkMenuPositions() | |
1378 | if menus[selectedMenu].items[selectedSubMenu][1] == "--" then | |
1379 | selectedSubMenu=selectedSubMenu+1 | |
1380 | checkMenuPositions() | |
1381 | end | |
1382 | elseif p1 == keys.left then | |
1383 | selectedSubMenu = 1 | |
1384 | selectedMenu=selectedMenu-1 | |
1385 | checkMenuPositions() | |
1386 | elseif p1 == keys.right then | |
1387 | selectedSubMenu = 1 | |
1388 | selectedMenu=selectedMenu+1 | |
1389 | checkMenuPositions() | |
1390 | elseif p1 == keys.enter then | |
1391 | doMenuAction(menus[selectedMenu].items[selectedSubMenu][3]) | |
1392 | inMenu = false | |
1393 | end | |
1394 | else | |
1395 | if p1 == keys.up then | |
1396 | curLine=curLine-1 | |
1397 | elseif p1 == keys.down then | |
1398 | curLine=curLine+1 | |
1399 | elseif p1 == 201 then -- page up | |
1400 | curLine=curLine-(h-2) | |
1401 | elseif p1 == 209 then --page down | |
1402 | curLine=curLine+(h-2) | |
1403 | elseif p1 == keys.left then | |
1404 | curCol=curCol-1 | |
1405 | elseif p1 == keys.right then | |
1406 | curCol=curCol+1 | |
1407 | elseif p1 == keys.home then | |
1408 | curCol=0 | |
1409 | elseif p1 == keys["end"] then | |
1410 | curCol=string.len(fileLinesArr[curLine])+1 | |
1411 | elseif p1 == keys.tab then | |
1412 | isChanged=true | |
1413 | local leftSide = string.sub(fileLinesArr[curLine], 1, curCol) | |
1414 | local rightSide = string.sub(fileLinesArr[curLine], curCol+1) | |
1415 | fileLinesArr[curLine] = leftSide.." "..rightSide | |
1416 | curCol=curCol+2 | |
1417 | resetBlink() | |
1418 | checkLinePosition() | |
1419 | checkColPosition() | |
1420 | elseif p1 == keys.enter then | |
1421 | isChanged=true | |
1422 | if curCol == string.len(fileLinesArr[curLine]) then | |
1423 | curLine=curLine+1 | |
1424 | curCol=0 | |
1425 | table.insert(fileLinesArr, curLine, "") | |
1426 | elseif curCol == 0 then | |
1427 | table.insert(fileLinesArr, curLine, "") | |
1428 | curLine=curLine+1 | |
1429 | else | |
1430 | local leftSide = string.sub(fileLinesArr[curLine], 1, curCol) | |
1431 | local rightSide = string.sub(fileLinesArr[curLine], curCol+1) | |
1432 | fileLinesArr[curLine] = leftSide | |
1433 | table.insert(fileLinesArr, curLine+1, rightSide) | |
1434 | curLine=curLine+1 | |
1435 | curCol=0 | |
1436 | end | |
1437 | elseif p1 == keys.backspace then | |
1438 | isChanged=true | |
1439 | if curCol > 0 then | |
1440 | local leftSide = string.sub(fileLinesArr[curLine], 1, curCol-1) | |
1441 | local rightSide = string.sub(fileLinesArr[curLine], curCol+1) | |
1442 | fileLinesArr[curLine] = leftSide..rightSide | |
1443 | curCol=curCol-1 | |
1444 | elseif curCol == 0 and curLine > 1 then | |
1445 | local newCurCol = string.len(fileLinesArr[curLine-1]) | |
1446 | fileLinesArr[curLine-1] = fileLinesArr[curLine-1] .. fileLinesArr[curLine] | |
1447 | table.remove(fileLinesArr, curLine) | |
1448 | curLine = curLine -1 | |
1449 | curCol = newCurCol | |
1450 | end | |
1451 | elseif p1 == keys.delete then | |
1452 | isChanged=true | |
1453 | if curCol < string.len(fileLinesArr[curLine]) then | |
1454 | local leftSide = string.sub(fileLinesArr[curLine], 1, curCol) | |
1455 | local rightSide = string.sub(fileLinesArr[curLine], curCol+2) | |
1456 | fileLinesArr[curLine] = leftSide..rightSide | |
1457 | elseif curCol == string.len(fileLinesArr[curLine]) and curLine < #fileLinesArr then | |
1458 | fileLinesArr[curLine] = fileLinesArr[curLine] .. fileLinesArr[curLine+1] | |
1459 | table.remove(fileLinesArr, curLine+1) | |
1460 | end | |
1461 | end | |
1462 | checkLinePosition() | |
1463 | checkColPosition() | |
1464 | end | |
1465 | resetBlink() | |
1466 | elseif state == "msg" then | |
1467 | if p1 == keys.enter then | |
1468 | state = "edit" | |
1469 | end | |
1470 | end | |
1471 | end | |
1472 | elseif event == "char" then | |
1473 | if showingMessage then | |
1474 | elseif showAboutBox then | |
1475 | elseif showingFileDialog then | |
1476 | if fileDialog.currentTab == 1 then | |
1477 | local leftSide = string.sub(collectedInputs.file, 1, collectedInputsCursor.file) | |
1478 | local rightSide = string.sub(collectedInputs.file, collectedInputsCursor.file+1) | |
1479 | collectedInputs.file=leftSide..p1..rightSide | |
1480 | collectedInputsCursor.file=collectedInputsCursor.file+1 | |
1481 | checkDialogLimits() | |
1482 | end | |
1483 | else | |
1484 | if state == "edit" then | |
1485 | isChanged=true | |
1486 | local leftSide = string.sub(fileLinesArr[curLine], 1, curCol) | |
1487 | local rightSide = string.sub(fileLinesArr[curLine], curCol+1) | |
1488 | fileLinesArr[curLine] = leftSide..p1..rightSide | |
1489 | curCol=curCol+1 | |
1490 | resetBlink() | |
1491 | checkLinePosition() | |
1492 | checkColPosition() | |
1493 | end | |
1494 | end | |
1495 | elseif event == "timer" and p1 == timer then | |
1496 | if state == "edit" then | |
1497 | drawScreen(term) | |
1498 | elseif state == "additem" then | |
1499 | --displayAddItem() | |
1500 | elseif state == "msg" then | |
1501 | --displayMsg(currentMessage) | |
1502 | end | |
1503 | if showingFileDialog then | |
1504 | drawFileDialog(term) | |
1505 | end | |
1506 | if showingMessage then | |
1507 | drawMessage(term) | |
1508 | end | |
1509 | if showAboutBox then | |
1510 | drawAbout(term) | |
1511 | end | |
1512 | timer = os.startTimer(0.01) | |
1513 | end | |
1514 | if os.clock() - lastBlinkTime > 0.5 then | |
1515 | lastBlinkTime = os.clock() | |
1516 | isBlinking = not isBlinking | |
1517 | end | |
1518 | end | |
1519 | ||
1520 | saveSettings() | |
1521 | setColors(term, colors.black, colors.white, colors.black, colors.white) | |
1522 | term.clear() | |
1523 | term.setCursorPos(1,1) |