Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Name: Fusion OS
- Created By: DannySMc
- Platform: Lua Virtual Machine
- Creation Start: (on) 20/01/2015 (at) 22:00
- Creation Finish: (on) 26/01/2015 (at) 16:21
- Login
- Desktop
- Main Menu
- File Explorer
- Sketch
- Ink
- Email Client
- LuaIDE
- File Share
- Settings
- Help
- Folders:
- /core/
- /user/
- /<username>/
- /help/
- /Apps/
- /Users/
- /API/
- /Controls/
- /Tablet/
- /Credits/
- /License/
- /apps/
- /AppStore/
- /Chat/
- /Translate/
- /conf/
- /colours/
- /imgmaps/
- /settings/
- File Extensions:
- .fusa - Fusion App
- .fusi - Fusion Image
- .fusc - Fusion Config
- .fush - Fusion Help
- .fusu - Fusion User
- .fusp - Fusion Colour Palette
- .fuso - Fusion Operating System
- .fusd - Fusion Update File
- .fusb - Fusion Bios File
- .fusl - Fusion Link File
- .fuse - Fusion Encrypted File
- Program Arguments:
- fusion update -> Will attempt to update the console with an update file, this is used when the update function has been run.
- fusion devmode <app> -> Will load the console into a dev mode state that will load the taskbar and screen size and allow you to test apps.
- ]]
- -- Set Tables/Configuration/Variables
- local tArgs = {...}
- local nVersion = "1.0.5"
- local nAPIVersion = "4.5"
- local nSysCoreFolder = "/core/"
- local tColours = {
- "white",
- "blue",
- "cyan",
- "lightGrey",
- "pink",
- "lime",
- "orange",
- "green",
- }
- local tFolders = {
- "/core/",
- "/core/user/",
- "/core/apps/",
- "/core/conf/",
- "/core/xplore/",
- "/core/addons/",
- "/core/conf/colours/",
- "/core/conf/imgmaps/",
- "/core/conf/settings/",
- }
- local tExtensions = {
- App = ".fusa",
- Image = ".fusi",
- Config = ".fusc",
- Help = ".fush",
- User = ".fusu",
- Palette = ".fusp",
- OS = ".fuso",
- Update = ".fusd",
- Bios = ".fusb",
- Link = ".fusl",
- Encrypted = ".fuse",
- XplorePage = ".xpl"
- }
- -- Current defaults before overwriting
- maintc = "lightBlue"
- mainbc = "grey"
- texttc = "black"
- textbc = "white"
- currenttc = "lightGrey"
- timetc = "lime"
- titletc = "white"
- extratc = "red"
- local tUrls = {
- CCSystems = "https://dannysmc.com/files/php/emailsystem.php",
- FusionUpdate = "https://dannysmc.com/programs/fusion/fusion",
- FusionNews = "https://dannysmc.com/programs/fusion/news.fusa",
- FusionHelpFiles = "https://dannysmc.com/programs/fusion/help.fush",
- FusionFiles = "https://dannysmc.com/programs/fusion/imgmaps.fusc",
- FusionBugreport = "https://dannysmc.com/ccdb/email.php",
- FusionUserImage = "https://dannysmc.com/programs/fusion/core/conf/imgmaps/defuser.fusi"
- }
- if tArgs[1] == "devmode" then
- init("devmode")
- end
- function init(command)
- if command == "install" then
- -- Create folders
- col.screen("white", "white")
- drawScreen("taskbar", "Install", "Install Process", "Please Wait")
- col.set("cyan", "white")
- term.setCursorPos(1,5)
- print("Welcome to Fusion Graphical User Interface, we are going to attempt to install Fusion...")
- sleep(1)
- print("Creating Directories...")
- sleep(0.5)
- for _, v in ipairs(tFolders) do
- print("> Creating Folder: "..v)
- sleep(0.5)
- fs.makeDir(v)
- end
- print("> Downloading Default User Image Map...")
- local img = [[
- 33333333333
- 33377733333
- 33733373333
- 33333373333
- 33333733333
- 33337333333
- 33333333333
- ]]
- local tempimg = fs.open("/core/conf/imgmaps/defuser.fusi", "w")
- tempimg.write(img)
- tempimg.close()
- sleep(0.5)
- print("> Creating Settings File...")
- sleep(0.5)
- -- Create Config File
- local confFile = {
- {
- "Enable Rednet Connections",
- "Update Fusion System / API",
- "Uninstall Fusion System",
- "Empty Setting 4",
- "Empty Setting 5",
- "Empty Setting 6",
- "Empty Setting 7",
- },
- {
- false,
- false,
- false,
- false,
- false,
- false,
- false,
- },
- }
- local configFile = config.save(confFile, "/core/conf/settings/settings.fusc")
- print("> Creating Startup File...")
- sleep(0.5)
- local startFile = fs.open("startup", "w")
- startFile.write('shell.run("fusion")')
- startFile.close()
- print("> Starting Login...")
- sleep(1)
- -- Go to login
- login()
- elseif command == "uninstall" then
- col.screen("white", "white")
- drawScreen("taskbar", "Uninstall", "Uninstall Process", "Please Wait")
- col.set("cyan", "white")
- term.setCursorPos(1,5)
- print("> Uninstall Fusion, please wait")
- for _, v in ipairs(tFolders) do
- print("Deleting Folder: "..v)
- sleep(0.5)
- fs.delete(v)
- end
- print("> Deleting Startup File")
- fs.delete("startup")
- print("> Leaving The Fusion File...")
- sleep(0.5)
- print("> Rebooting...")
- sleep(1.5)
- os.reboot()
- elseif command == "devmode" then
- print("> Not Completed...")
- sleep(2)
- os.shutdown()
- end
- end
- function drawScreen(object, running, title, extra)
- if object == "boot" then
- elseif object == "option" then
- draw.box(8, 36, 7, 3, " ", "lightBlue", "lightBlue")
- draw.box(8, 36, 7, 3, " ", "lightBlue", "lightBlue")
- draw.textc(running, 7, false, "white", "lightBlue")
- draw.box(9, 34, 8, 1, " ", "white", "white")
- col.set("black", "white")
- term.setCursorPos(9,8)
- write("> ")
- local textinput = tostring(read())
- return textinput
- elseif object == "apps" then
- draw.texta("Download App", 5, 18, false, "grey", "white")
- draw.texta("Delete App", 37, 18, false, "grey", "white")
- elseif object == "login" then
- draw.texta("Register", 5, 18, false, "black", "white")
- draw.texta("Login", 42, 18, false, "red", "white")
- image.draw(21, 5, "/core/conf/imgmaps/defuser")
- draw.box(8, 36, 14, 1, " ", "lightBlue", "lightBlue")
- elseif object == "register" then
- draw.texta("Register", 5, 18, false, "red", "white")
- draw.texta("Login", 42, 18, false, "black", "white")
- draw.texta("Username:", 8, 6, false, "grey", "white")
- draw.texta("Password:", 8, 9, false, "grey", "white")
- draw.texta("Email:", 8, 12, false, "grey", "white")
- draw.box(8, 36, 7, 1, " ", "lightBlue", "lightBlue")
- draw.box(8, 36, 10, 1, " ", "lightBlue", "lightBlue")
- draw.box(8, 36, 13, 1, " ", "lightBlue", "lightBlue")
- elseif object == "desktop" then
- --// Draw File Explorer Shortcut
- draw.texta(" ", 5, 6, false, "orange", "orange")
- draw.texta("All FILES", 5, 7, false, "grey", "yellow")
- draw.texta(" ", 5, 8, false, "yellow", "yellow")
- --// Draw LuaIDE Shortcut
- draw.texta("1:", 16, 6, false, "lightBlue", "grey")
- draw.texta("2:", 16, 7, false, "lightBlue", "grey")
- draw.texta("3:", 16, 8, false, "lightBlue", "grey")
- draw.texta(" LuaIDE", 18, 6, false, "white", "lightGrey")
- draw.texta(" - - - ", 18, 7, false, "white", "lightGrey")
- draw.texta(" - - - ", 18, 8, false, "white", "lightGrey")
- --// Draw Ink Shortcut
- draw.box(27, 9, 6, 3, " ", "white", "grey")
- draw.texta(" INK ", 27, 6, false, "lightBlue", "grey")
- draw.texta("AaBbCc-", 28, 7, false, "white", "lightGrey")
- draw.texta("-------", 28, 8, false, "white", "lightGrey")
- --// Draw Sketch Shortcut
- draw.box(38, 9, 6, 3, " ", "white", "lightGrey")
- draw.box(38, 1, 6, 3, " ", "white", "blue")
- draw.box(39, 1, 6, 2, " ", "white", "yellow")
- draw.box(40, 2, 7, 2, " ", "white", "red")
- draw.box(42, 1, 6, 3, " ", "white", "pink")
- draw.box(43, 2, 6, 3, " ", "white", "orange")
- draw.box(45, 1, 6, 3, " ", "white", "green")
- draw.box(46, 1, 6, 3, " ", "white", "lightBlue")
- draw.texta("/", 39, 7, false, "cyan", "yellow")
- draw.texta("S", 40, 7, false, "lime", "red")
- draw.texta("K", 41, 7, false, "lime", "red")
- draw.texta("E", 42, 7, false, "red", "pink")
- draw.texta("T", 43, 7, false, "blue", "orange")
- draw.texta("C", 44, 7, false, "blue", "orange")
- draw.texta("H", 45, 7, false, "white", "green")
- --// Draw X-Plore Shortcut
- draw.box(5, 1, 11, 1, ">", "lime", "grey")
- draw.texta(" URL ", 6, 11, false, "white", "lightGrey")
- draw.texta(" ", 5, 12, false, "red", "lightBlue")
- draw.texta(" X-PLORE ", 5, 13, false, "red", "lightBlue")
- --// Draw Apps Shortcut
- draw.texta(" ", 16, 11, false, "orange", "orange")
- draw.texta(" >APPS ", 16, 12, false, "grey", "yellow")
- draw.texta(" ", 16, 13, false, "yellow", "yellow")
- --// Draw Settings Shortcut
- draw.texta(" C.Panel ", 27, 11, false, "white", "grey")
- draw.texta("[x] Touch", 27, 12, false, "white", "lightGrey")
- draw.texta("[o] Shell", 27, 13, false, "white", "lightGrey")
- --// Draw HelpFilesShortcut
- draw.texta(" ? ? ", 38, 11, false, "grey", "orange")
- draw.texta("HELP FILE", 38, 12, false, "grey", "yellow")
- draw.texta(" ? ? ", 38, 13, false, "grey", "yellow")
- draw.texta("System", 5, 18, false, "grey", "white")
- draw.texta("License", 22, 18, false, "grey", "white")
- draw.texta("Credits", 40, 18, false, "grey", "white")
- elseif object == "desktop2" then
- --// Draw Bug Report Shortcut
- draw.texta(" [ERROR] ", 5, 6, false, "red", "lightGrey")
- draw.texta("Bug Form:", 5, 7, false, "white", "grey")
- draw.texta(" ", 5, 8, false, "red", "lightGrey")
- --// Draw Addons Shortcut
- draw.texta(" ADDON ", 16, 6, false, "lime", "grey")
- draw.texta("1:", 16, 7, false, "lightBlue", "grey")
- draw.texta("2:", 16, 8, false, "lightBlue", "grey")
- draw.texta(" HTTPS ", 18, 7, false, "lightBlue", "lightGrey")
- draw.texta(" RUN ", 18, 8, false, "lightBlue", "lightGrey")
- --// Draw Fusion Shell Shortcut
- draw.texta(" Shell ", 27, 6, false, "white", "red")
- draw.texta("> Explode", 27, 7, false, "green", "pink")
- draw.texta("'BANG' -@", 27, 8, false, "green", "pink")
- --[[ // Draw App Store Shortcut
- draw.texta(" Fusions ", 38, 6, false, "white", "blue")
- draw.texta(" App ", 38, 7, false, "white", "lightBlue")
- draw.texta(" Store ", 38, 8, false, "white", "blue")
- draw.texta("System", 5, 18, false, "grey", "white")
- draw.texta("License", 22, 18, false, "grey", "white")
- draw.texta("Credits", 40, 18, false, "grey", "white")]]
- elseif object == "taskbar" then
- draw.box(1, 51, 1, 3, " ", maintc, mainbc)
- draw.box(1, 51, 2, 1, " ", maintc, mainbc)
- local tLetters = {"U", "S", "I", "O", "N", ":"}
- for k ,v in ipairs(tLetters) do
- if k == 1 then
- draw.texta("F", 1, 1, false, tColours[math.random(8)], mainbc)
- end
- draw.texta(v, k+1, 1, false, tColours[math.random(8)], mainbc)
- end
- draw.texta(running, 9, 1, false, currenttc, mainbc)
- draw.texta(misc.time(), 47, 1, false, timetc, mainbc)
- draw.textc(title, 2, false, titletc, mainbc)
- if extra then
- draw.textc(extra, 3, false, extratc, mainbc)
- end
- end
- end
- function infoScreen(object, pageID)
- if object == "system" then
- -- Show System Storage / Versions etc.
- col.screen("white", "white")
- drawScreen("taskbar", "System", "System Information", "Click Fusion to go back")
- local freeSpace = fs.getFreeSpace("/")
- local osSize = fs.getSize("fusion")
- if tostring(freeSpace) == "inf" then
- freeSpace = "Unlimited"
- end
- local applist = fs.list("/core/apps/")
- local appsize = 0
- for _, v in pairs(applist) do
- appsize = appsize + fs.getSize("/core/apps/"..v)
- end
- local osSize = fs.getSize("fusion")
- draw.texta("STORAGE", 7, 5, false, "black", "white")
- draw.texta("Free Space: ", 3, 7, false, "red", "white")
- draw.texta("Fusion Size: ", 3, 10, false, "red", "white")
- draw.texta("Apps Folder Size: ", 3, 13, false, "red", "white")
- draw.texta(tostring(freeSpace).." Bytes", 6, 8, false, "blue", "white")
- draw.texta(tostring(osSize).." Bytes", 6, 11, false, "blue", "white")
- draw.texta(tostring(appsize).." Bytes", 6, 14, false, "blue", "white")
- draw.texta("VERSION", 36, 5, false, "black", "white")
- draw.texta("Fusion Version: ", 32, 7, false, "red", "white")
- draw.texta("Fusion API Version: ", 32, 10, false, "red", "white")
- draw.texta("System Core Folder: ", 32, 13, false, "red", "white")
- draw.texta(nVersion, 35, 8, false, "blue", "white")
- draw.texta(nAPIVersion, 35, 11, false, "blue", "white")
- draw.texta(nSysCoreFolder, 35, 14, false, "blue", "white")
- col.set("green", "white")
- term.setCursorPos(1, 16)
- print("Please take note of these and include them in any")
- print("type of bug reports/fixes so I know what version")
- print("you are running.")
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawScreen("taskbar", "System", "System Information", "Click Fusion to go back")
- elseif args[1] == "mouse_click" then
- if (args[3] >= 1 and args[3] <= 8) and (args[4] == 1) then
- desktop()
- end
- end
- end
- elseif object == "license" then
- -- Show Fusion License
- col.screen("white", "white")
- drawScreen("taskbar", "License", "Fusion's License", "Click Fusion to go back")
- draw.box(1, 51, 19, 1, " ", "blue", "lightGrey")
- if pageID == 1 then
- draw.texta("< Back", 1, 19, false, "lightBlue", "lightGrey")
- draw.texta("Next >", 46, 19, false, "blue", "lightGrey")
- elseif pageID == 3 then
- draw.texta("< Back", 1, 19, false, "blue", "lightGrey")
- draw.texta("Next >", 46, 19, false, "lightBlue", "lightGrey")
- else
- draw.texta("< Back", 1, 19, false, "blue", "lightGrey")
- draw.texta("Next >", 46, 19, false, "blue", "lightGrey")
- end
- draw.textc(pageID.." / 3", 19, false, "blue", "lightGrey")
- if pageID == 1 then
- term.setCursorPos(1, 5)
- col.set("red", "white")
- print("This work is licensed under the Creative Commons")
- print("Attribution-NonCommercial-NoDerivatives 4.0")
- print("International License. To view a copy of this")
- print("license, visit:")
- col.set("cyan", "white")
- term.setCursorPos(1, 10)
- print("http://creativecommons.org/licenses/by-nc-nd/4.0/.")
- term.setCursorPos(1, 12)
- col.set("green", "white")
- print("You are free to:")
- col.set("blue", "white")
- write("Share ")
- col.set("grey", "white")
- print("- copy and redistribute the material in any")
- print("medium or format (The licensor cannot revoke these")
- print("freedoms as long as you follow the license terms.)")
- elseif pageID == 2 then
- term.setCursorPos(1, 5)
- col.set("green", "white")
- print("Under the following terms:")
- col.set("blue", "white")
- write("Attribution ")
- col.set("grey", "white")
- print("- You must give appropriate credit, ")
- print("provide a link to the license, and indicate if")
- print("changes were made. You may do so in any reasonable")
- print("manner, but not in any way that suggests the")
- print("licensor endorses you or your use.")
- term.setCursorPos(1, 13)
- col.set("blue", "white")
- write("NonCommercial ")
- col.set("grey", "white")
- print("- You may not use the material")
- print("for commercial purposes.")
- elseif pageID == 3 then
- term.setCursorPos(1, 5)
- col.set("blue", "white")
- write("NoDerivatives ")
- col.set("grey", "white")
- print("- If you remix, transform, or build")
- print("upon the material, you may not distribute the")
- print("modified material.")
- term.setCursorPos(1, 9)
- col.set("blue", "white")
- write("No additional restrictions ")
- col.set("grey", "white")
- print("- You may not apply")
- print("legal terms or technological measures that legally")
- print("restrict others from doing anything the license")
- print("permits.")
- end
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawScreen("taskbar", "License", "Fusion's License", "Click Fusion to go back")
- elseif args[1] == "mouse_click" then
- if (args[3] >= 1 and args[3] <= 8) and (args[4] == 1) then
- desktop()
- elseif (args[3] >= 1 and args[3] <= 6) and (args[4] == 19) then
- if pageID > 1 then
- pageID = pageID - 1
- infoScreen("license", pageID)
- break
- end
- elseif (args[3] >= 45 and args[3] <= 51) and (args[4] == 19) then
- if pageID < 3 then
- pageID = pageID + 1
- infoScreen("license", pageID)
- break
- end
- end
- end
- end
- elseif object == "credits" then
- -- Show Fusion Credits
- col.screen("white", "white")
- drawScreen("taskbar", "Credits", "All Credits", "Click Fusion to go back")
- col.set("black", "white")
- term.setCursorPos(1,5)
- print("Here are the credits for Fusion, these include")
- print("programs, code help and testers:")
- term.setCursorPos(1, 8)
- col.set("blue", "white")
- write("GravityScore ")
- col.set("red", "white")
- print("- For the LuaIDE program and of course")
- print("the Sublime Text 3 Package")
- term.setCursorPos(1, 11)
- col.set("blue", "white")
- write("OEED ")
- col.set("red", "white")
- print("- For the Sketch and Ink programs")
- term.setCursorPos(1, 13)
- col.set("blue", "white")
- write("Friends ")
- col.set("red", "white")
- print("- For testing it out before release.")
- term.setCursorPos(1, 15)
- col.set("blue", "white")
- write("wieselkatze ")
- col.set("red", "white")
- print("- For editing a code snippet to help with the file browser.")
- term.setCursorPos(1, 18)
- col.set("blue", "white")
- write("Fusion Users ")
- col.set("red", "white")
- term.setCursorPos(14, 18)
- write("- For actually using the OS and/or at")
- term.setCursorPos(1, 19)
- write("least testing it and giving me feedback.")
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawScreen("taskbar", "Credits", "All Credits", "Click Fusion to go back")
- elseif args[1] == "mouse_click" then
- if (args[3] >= 1 and args[3] <= 8) and (args[4] == 1) then
- desktop()
- end
- end
- end
- end
- end
- function fusionshell()
- col.screen("white", "white")
- drawScreen("taskbar", "Shell", "Fusion's Shell", "Type 'help' for the help menu")
- col.set("cyan", "white")
- term.setCursorPos(1,5)
- local tHistory = {}
- local helpdata = {
- {
- "delete",
- "move",
- "copy",
- "edit",
- "exit",
- "redraw",
- "dir",
- "help",
- "mkdir",
- "time",
- },
- {
- "This will delete a file using the argument you give it.",
- "This will move the file path given in the first argument, to the file path given in the second.",
- "This will copy a file with from the first argument path to the second argument path.",
- "Edit will automatically send you to LuaIDE (GravityScore).",
- "Exit will exit the shell and send you back to the desktop.",
- "This will redraw the shell as it may get mucked up due to the shell being printed on.",
- "This will get the current files at the specified path.",
- "This will display the help menu.",
- "This will make a folder at the specified path.",
- "This will print Minecraft's current time and day.",
- },
- }
- while true do
- write("> ")
- command = read()
- tCommand = {}
- for id in command:gmatch("%S+") do
- table.insert(tCommand, id)
- end
- if tCommand[1] == "help" then
- if #tCommand == 1 then
- print(table.concat(helpdata[1], ", "))
- print("Use: help <topic>")
- else
- for k, v in ipairs(helpdata[1]) do
- if tCommand[2] == v then
- print(helpdata[2][k])
- end
- end
- end
- elseif tCommand[1] == "delete" then
- if #tCommand >= 2 then
- fs.delete(tCommand[2])
- else
- print("Wrong Usage")
- end
- elseif tCommand[1] == "move" then
- if #tCommand >= 3 then
- fs.move(tCommand[2], tCommand[3])
- else
- print("Wrong Usage")
- end
- elseif tCommand[1] == "copy" then
- if #tCommand >= 3 then
- fs.copy(tCommand[2], tCommand[3])
- else
- print("Wrong Usage")
- end
- elseif tCommand[1] == "edit" then
- if #tCommand >= 2 then
- gravityscore_luaide()
- fusionshell()
- else
- print("Wrong Usage")
- end
- elseif tCommand[1] == "exit" then
- desktop(2)
- elseif tCommand[1] == "redraw" then
- fusionshell()
- elseif tCommand[1] == "dir" then
- if #tCommand >= 2 then
- local list = fs.list(tCommand[2])
- print(table.concat(list, ", "))
- else
- print("Wrong Usage")
- end
- elseif tCommand[1] == "mkdir" then
- if #tCommand >= 2 then
- fs.makeDir(tCommand[2])
- else
- print("Wrong Usage")
- end
- elseif tCommand[1] == "time" then
- print("Time: "..textutils.formatTime(os.time()))
- print("Day: "..os.day())
- else
- print("> Couldn't recognise that command...")
- end
- end
- end
- -- Program Code Start:
- function bugreport()
- -- Allows a user to report a bug
- col.screen("white", "white")
- drawScreen("taskbar", "Report", "Report A Bug Form")
- draw.box(8, 36, 6, 1, " ", "lightBlue", "lightBlue")
- draw.texta("Email Address*:", 8, 5, false, "grey", "white")
- draw.box(8, 36, 9, 1, " ", "lightBlue", "lightBlue")
- draw.texta("Program/Function*:", 8, 8, false, "grey", "white")
- draw.box(8, 36, 12, 1, " ", "lightBlue", "lightBlue")
- draw.texta("What was the bug*:", 8, 11, false, "grey", "white")
- draw.box(8, 36, 15, 1, " ", "lightBlue", "lightBlue")
- draw.texta("Error Code:", 8, 14, false, "grey", "white")
- draw.textc("SUBMIT", 17, false, "red", "lightBlue")
- draw.textc("* is required", 19, false, "lightGrey", "white")
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawScreen("taskbar", "Report", "Report A Bug Form")
- elseif args[1] == "mouse_click" then
- if (args[3] >= 1 and args[3] <= 8) and (args[4] == 1) then
- desktop(2)
- elseif (args[3] >= 8 and args[3] <= 44) and (args[4] == 6) then
- if bug_email then
- draw.box(8, 36, 6, 1, " ", "lightBlue", "lightBlue")
- end
- col.set("white", "lightBlue")
- term.setCursorPos(8, 6)
- write("> ")
- bug_email = tostring(read())
- elseif (args[3] >= 8 and args[3] <= 44) and (args[4] == 9) then
- if bug_prog then
- draw.box(8, 36, 9, 1, " ", "lightBlue", "lightBlue")
- end
- col.set("white", "lightBlue")
- term.setCursorPos(8, 9)
- write("> ")
- bug_prog = tostring(read())
- elseif (args[3] >= 8 and args[3] <= 44) and (args[4] == 12) then
- if bug_desc then
- draw.box(8, 36, 12, 1, " ", "lightBlue", "lightBlue")
- end
- col.set("white", "lightBlue")
- term.setCursorPos(8, 12)
- write("> ")
- bug_desc = tostring(read())
- elseif (args[3] >= 8 and args[3] <= 44) and (args[4] == 15) then
- if bug_error then
- draw.box(8, 36, 15, 1, " ", "lightBlue", "lightBlue")
- end
- col.set("white", "lightBlue")
- term.setCursorPos(8, 15)
- write("> ")
- bug_error = tostring(read())
- elseif (args[3] >= 8 and args[3] <= 44) and (args[4] == 17) then
- -- Submit
- ccsys.submitbug(bug_email, bug_prog, bug_desc, bug_error)
- sleep(0.5)
- desktop(2)
- end
- end
- end
- end
- function login()
- col.screen("white", "white")
- drawScreen("taskbar", "Login", "Login Screen", "Enter Username")
- drawScreen("login")
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawScreen("taskbar", "Login", "Login Screen", "Enter Username")
- elseif args[1] == "mouse_click" then
- if (args[3] >= 8 and args[3] <= 44) and (args[4] == 14) then
- col.set("black", "lightBlue")
- term.setCursorPos(8, 14)
- write("> ")
- local username = tostring(read())
- if fs.exists("/core/conf/imgmaps/"..username.."/profileimage.fusi") then
- image.draw(21, 5, "/core/conf/imgmaps/"..username.."/profileimage")
- end
- drawScreen("taskbar", "Login", "Login Screen", "Enter Password")
- draw.textc(" "..username, 12, false, "grey", "white")
- draw.box(8, 36, 14, 1, " ", "cyan", "cyan")
- col.set("black", "cyan")
- term.setCursorPos(8, 14)
- write("> ")
- local password = tostring(read("*"))
- local status = user.login(username, password)
- if status then
- sleep(0.5)
- desktop()
- break
- else
- sleep(0.5)
- draw.popup("Username and password invalid!")
- sleep(1.5)
- login()
- end
- elseif (args[3] >= 5 and args[3] <= 12) and (args[4] == 18) then
- register()
- elseif (args[3] >= 42 and args[3] <= 46) and (args[4] == 18) then
- login()
- end
- end
- end
- end
- function register()
- -- Allow users to register to the CCSystems User Database
- col.screen("white", "white")
- drawScreen("taskbar", "Register", "Register To CCSystems", "Enter Username")
- drawScreen("register")
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawScreen("taskbar", "Register", "Register To CCSystems", "Enter Username")
- elseif args[1] == "mouse_click" then
- if (args[3] >= 8 and args[3] <= 44) and (args[4] >= 7 and args[4] <= 13) then
- -- Set up register form
- col.set("black", "lightBlue")
- term.setCursorPos(8,7)
- write("> ")
- local username = tostring(read())
- drawScreen("taskbar", "Register", "Register To CCSystems", "Enter Password")
- term.setCursorPos(8,10)
- col.set("black", "lightBlue")
- write("> ")
- local password = tostring(read("*"))
- drawScreen("taskbar", "Register", "Register To CCSystems", "Enter Email Address")
- term.setCursorPos(8,13)
- col.set("black", "lightBlue")
- write("> ")
- local email = tostring(read())
- local status = user.register(username, password, email)
- if status then
- sleep(0.5)
- login()
- break
- else
- sleep(0.5)
- draw.popup("Problem with adding user...")
- sleep(1.5)
- login()
- end
- elseif (args[3] >= 5 and args[3] <= 12) and (args[4] == 18) then
- register()
- elseif (args[3] >= 42 and args[3] <= 46) and (args[4] == 18) then
- login()
- end
- end
- end
- end
- function desktop(screen)
- screens = 2
- if screen == nil then
- screen = 1
- end
- col.screen("white", "white")
- local csettings = config.load("/core/conf/settings/settings.fusc")
- if csettings[2][1] then
- if http then
- rednet.open(misc.find("modem"))
- end
- end
- if screen == 1 then
- drawScreen("taskbar", "Desktop", "Home ("..tostring(screen).."/"..screens..")")
- draw.texta("->", 50, 19, false, "grey", "white")
- elseif screen == 2 then
- drawScreen("taskbar", "Desktop", "Home ("..tostring(screen).."/"..screens..")")
- draw.texta("<-", 1, 19, false, "grey", "white")
- end
- if screen == 1 then
- drawScreen("desktop")
- elseif screen == 2 then
- drawScreen("desktop2")
- end
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- if screen == 1 then
- drawScreen("taskbar", "Desktop", "Home ("..tostring(screen).."/"..screens..")")
- draw.texta("->", 50, 19, false, "grey", "white")
- elseif screen == 2 then
- drawScreen("taskbar", "Desktop", "Home ("..tostring(screen).."/"..screens..")")
- draw.texta("<-", 1, 19, false, "grey", "white")
- end
- elseif args[1] == "mouse_click" then
- if screen == 1 then
- if (args[3] >= 50 and args[3] <= 51) and (args[4] == 19) then
- desktop(2)
- elseif (args[3] >= 1 and args[3] <= 8) and (args[4] >= 1 and args[4] <= 1) then
- desktop()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 5 and args[3] <= 13) and (args[4] >= 6 and args[4] <= 8) then
- finder()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 16 and args[3] <= 25) and (args[4] >= 6 and args[4] <= 8) then
- gravityscore_luaide()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 28 and args[3] <= 36) and (args[4] >= 6 and args[4] <= 8) then
- oeed_ink()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 39 and args[3] <= 47) and (args[4] >= 6 and args[4] <= 8) then
- oeed_sketch()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 5 and args[3] <= 13) and (args[4] >= 11 and args[4] <= 13) then
- Xplore()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 16 and args[3] <= 25) and (args[4] >= 11 and args[4] <= 13) then
- appslist()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 28 and args[3] <= 36) and (args[4] >= 11 and args[4] <= 13) then
- settings()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 39 and args[3] <= 47) and (args[4] >= 11 and args[4] <= 13) then
- helpcontent()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 5 and args[3] <= 10) and (args[4] >= 18 and args[4] <= 18) then
- infoScreen("system")
- sleep(0.5)
- desktop()
- elseif (args[3] >= 22 and args[3] <= 28) and (args[4] >= 18 and args[4] <= 18) then
- infoScreen("license", 1)
- sleep(0.5)
- desktop()
- elseif (args[3] >= 40 and args[3] <= 47) and (args[4] >= 18 and args[4] <= 18) then
- infoScreen("credits")
- sleep(0.5)
- desktop()
- end
- elseif screen == 2 then
- if (args[3] >= 1 and args[3] <= 2) and (args[4] == 19) then
- desktop(1)
- elseif (args[3] >= 1 and args[3] <= 8) and (args[4] >= 1 and args[4] <= 1) then
- desktop()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 5 and args[3] <= 13) and (args[4] >= 6 and args[4] <= 8) then
- -- OPTION 1
- bugreport()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 16 and args[3] <= 25) and (args[4] >= 6 and args[4] <= 8) then
- -- OPTION 2
- addons()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 28 and args[3] <= 36) and (args[4] >= 6 and args[4] <= 8) then
- -- OPTION 3
- fusionshell()
- sleep(0.5)
- desktop()
- elseif (args[3] >= 39 and args[3] <= 47) and (args[4] >= 6 and args[4] <= 8) then
- -- OPTION 4
- sleep(0.5)
- desktop()
- elseif (args[3] >= 5 and args[3] <= 13) and (args[4] >= 11 and args[4] <= 13) then
- -- OPTION 5
- sleep(0.5)
- desktop()
- elseif (args[3] >= 16 and args[3] <= 25) and (args[4] >= 11 and args[4] <= 13) then
- -- OPTION 6
- sleep(0.5)
- desktop()
- elseif (args[3] >= 28 and args[3] <= 36) and (args[4] >= 11 and args[4] <= 13) then
- -- OPTION 7
- sleep(0.5)
- desktop()
- elseif (args[3] >= 39 and args[3] <= 47) and (args[4] >= 11 and args[4] <= 13) then
- -- OPTION 8
- sleep(0.5)
- desktop()
- elseif (args[3] >= 5 and args[3] <= 10) and (args[4] >= 18 and args[4] <= 18) then
- infoScreen("system")
- sleep(0.5)
- desktop()
- elseif (args[3] >= 22 and args[3] <= 28) and (args[4] >= 18 and args[4] <= 18) then
- infoScreen("license", 1)
- sleep(0.5)
- desktop()
- elseif (args[3] >= 40 and args[3] <= 47) and (args[4] >= 18 and args[4] <= 18) then
- infoScreen("credits")
- sleep(0.5)
- desktop()
- end
- end
- elseif args[1] == "char" then
- if args[2] == "d" then
- local args = drawScreen("option", "Type Arguments to pass to Fusion")
- shell.run("fusion "..args)
- os.reboot()
- end
- end
- end
- end
- -- IF YOU MAKE AN ADDON READ THIS:
- --[[
- Addons have to be registered using the addons system, to do so, if one doesn't already exist, make a folder called: addons in the core folder and then add a file called tAddons.fusc and then it's a dual table, like so:
- {
- {
- "<Here add in the addon name>",
- },
- {
- "<Here out your username as you are the creator>",
- },
- }
- This will now show in the addons page.
- ]]
- function addons()
- col.screen("white", "white")
- drawScreen("taskbar", "Addons", "Installed Addons", "Addons will appear here if installed.")
- draw.textc("BACK", 18, false, "black", "white")
- if fs.exists("/core/addons/current.fusc") then
- local addondata = config.load("/core/addons/current.fusc")
- for k, v in ipairs(addondata[1]) do
- draw.texta(k..": "..v.." - "..addondata[2][k], 1, k + 4, false, "blue", "white")
- end
- end
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawScreen("taskbar", "Addons", "Installed Addons", "Addons will appear here if installed.")
- elseif args[1] == "mouse_click" then
- if (args[3] >= 1 and args[3] <= 8) and (args[4] == 1) then
- desktop(2)
- elseif (args[3] >= 20 and args[3] <= 31) and (args[4] == 18) then
- desktop(2)
- end
- end
- end
- end
- function appslist()
- col.screen("white", "white")
- local applist = fs.list("/core/apps/")
- drawScreen("taskbar", "Apps", "Installed Apps")
- drawScreen("apps")
- local intx = 4
- local intx1 = 1
- local inty = 4
- for k, v in ipairs(applist) do
- if inty == 17 then
- intx = 30
- intx1 = 26
- inty = 4
- elseif intx == 26 and inty == 17 then
- break
- end
- draw.texta(tostring(k), intx1, inty, false, "blue", "white")
- term.setCursorPos(intx, inty)
- col.set("grey", "white")
- print(v)
- inty = inty + 1
- end
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawScreen("taskbar", "Apps", "Installed Apps")
- elseif args[1] == "mouse_click" then
- if (args[3] >= 1 and args[3] <= 8) and (args[4] >= 1 and args[4] <= 1) then
- desktop()
- elseif (args[3] >= 5 and args[3] <= 17) and (args[4] == 18) then
- -- Download from pastebin/url
- local code = drawScreen("option", "Download Pastebin / URL App")
- local name = drawScreen("option", "App Name")
- if string.len(code) < 8 then
- draw.popup("8 Chars for pastebin, more for url")
- sleep(1.5)
- appslist()
- end
- if string.len(code) == 8 then
- shell.run("pastebin get "..code.." /core/apps/"..name)
- else
- local data = http.get(code)
- local tempapp = fs.open(name, "w")
- tempapp.write(data.readAll())
- tempapp.close()
- end
- appslist()
- elseif (args[3] >= 37 and args[3] <= 47) and (args[4] == 18) then
- -- Delete App
- drawScreen("taskbar", "Apps", "Installed Apps", "Click app to delete or click Fusion to exit")
- while true do
- local args1 = { os.pullEvent("mouse_click") }
- if (args1[3] >= 1 and args1[3] <= 8) and (args1[4] == 1) then
- break
- else
- if (args1[3] >= 1 and args1[3] <= 25) then
- args1[4] = args1[4] - 3
- if #applist >= args1[4] then
- fs.delete("/core/apps/"..applist[args1[4]])
- end
- appslist()
- elseif (args1[3] >= 26 and args1[3] <= 51) then
- args1[4] = args1[4] + 24
- if #applist >= args1[4] then
- fs.delete("/core/apps/"..applist[args1[4]])
- end
- appslist()
- end
- end
- end
- else
- while true do
- local args1 = { os.pullEvent("mouse_click") }
- if (args1[3] >= 1 and args1[3] <= 8) and (args1[4] == 1) then
- break
- else
- if (args1[3] >= 1 and args1[3] <= 25) then
- args1[4] = args1[4] - 3
- if #applist >= args1[4] then
- shell.run("/core/apps/"..applist[args1[4]])
- end
- appslist()
- elseif (args1[3] >= 26 and args1[3] <= 51) then
- args1[4] = args1[4] + 24
- if #applist >= args1[4] then
- shell.run("/core/apps/"..applist[args1[4]])
- end
- appslist()
- end
- end
- end
- end
- end
- end
- end
- function settings()
- col.screen("white", "white")
- drawScreen("taskbar", "Settings", "Control Panel", "Click the option to toggle")
- local configuration = config.load("/core/conf/settings/settings.fusc")
- draw.textc("Option statuses: lime = true, red = false", 19, false, "blue", "white")
- local inty = 5
- for k, v in ipairs(configuration[1]) do
- draw.box(2, 44, inty, 1, " ", "lightBlue", "lightBlue")
- draw.texta(" "..k..": "..v, 2, inty, false, "white", "lightBlue")
- if configuration[2][k] then
- draw.box(48, 3, inty, 1, " ", "lime", "lime")
- else
- draw.box(48, 3, inty, 1, " ", "red", "red")
- end
- inty = inty + 2
- end
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawScreen("taskbar", "Settings", "Control Panel", "Click the option to toggle")
- elseif args[1] == "mouse_click" then
- if (args[3] >= 1 and args[3] <= 8) and (args[4] == 1) then
- desktop(1)
- elseif (args[3] >= 1 and args[3] <= 40) then
- if args[4] == 5 then
- local configFile = config.load("/core/conf/settings/settings.fusc")
- if configFile[2][1] == true then
- configFile[2][1] = false
- else
- configFile[2][1] = true
- end
- config.save(configFile, "/core/conf/settings/settings.fusc")
- draw.popup("Setting Changed")
- sleep(0.5)
- settings()
- elseif args[4] == 7 then
- local configFile = config.load("/core/conf/settings/settings.fusc")
- col.screen("white", "white")
- drawScreen("taskbar", "Update", "Update Fusion", "Fusion is going to attempt to update")
- sleep(0.5)
- term.setCursorPos(1, 5)
- col.set("cyan", "white")
- print("Fusion is about to update, please don't touch or edit the file system.")
- print(" ")
- print("Downloading Fusion")
- local updatefile = http.get(tUrls["FusionUpdate"])
- local newFile = fs.open("fusionUpdate.fuso", "w")
- newFile.write(updatefile.readAll())
- newFile.close()
- print("File downloaded and ready, updating Fusion...")
- sleep(0.5)
- fs.delete("fusion")
- fs.move("fusionUpdate.fuso", "fusion")
- print("Rebooting, please wait...")
- sleep(1.5)
- os.reboot()
- elseif args[4] == 9 then
- init("uninstall")
- break
- elseif args[4] == 11 then
- local configFile = config.load("/core/conf/settings/settings.fusc")
- if configFile[2][4] == true then
- configFile[2][4] = false
- else
- configFile[2][4] = true
- end
- config.save(configFile, "/core/conf/settings/settings.fusc")
- draw.popup("Setting Changed")
- sleep(0.5)
- settings()
- elseif args[4] == 13 then
- local configFile = config.load("/core/conf/settings/settings.fusc")
- if configFile[2][5] == true then
- configFile[2][5] = false
- else
- configFile[2][5] = true
- end
- config.save(configFile, "/core/conf/settings/settings.fusc")
- draw.popup("Setting Changed")
- sleep(0.5)
- settings()
- elseif args[4] == 15 then
- local configFile = config.load("/core/conf/settings/settings.fusc")
- if configFile[2][6] == true then
- configFile[2][6] = false
- else
- configFile[2][6] = true
- end
- config.save(configFile, "/core/conf/settings/settings.fusc")
- draw.popup("Setting Changed")
- sleep(0.5)
- settings()
- elseif args[4] == 17 then
- local configFile = config.load("/core/conf/settings/settings.fusc")
- if configFile[2][7] == true then
- configFile[2][7] = false
- else
- configFile[2][7] = true
- end
- config.save(configFile, "/core/conf/settings/settings.fusc")
- draw.popup("Setting Changed")
- sleep(0.5)
- settings()
- end
- end
- end
- end
- end
- function helpcontent()
- col.screen("white", "white")
- drawScreen("taskbar", "Help", "Help Menu", "Choose a help item")
- local sText = "Choose a help item to display help information, please make sure your HTTP is enabled, as this all done using internet. This will just display some simple information for you to read. The Creating An App, will explain how to and/or to install them."
- local tText = data.wordwrap(sText, 22)
- local HelpItems = {"About Fusion", "Fusion Controls", "Using Logins", "Using Apps", "Creating An App", "Deleting Apps", "Fusion Addons"}
- local intx = 29
- local inty = 5
- for _,v in ipairs(tText) do
- draw.texta(v, intx, inty, false, "red", "white")
- inty = inty + 1
- end
- local inty = 5
- for k, v in ipairs(HelpItems) do
- draw.box(1, 27, inty, 1, " ", "lightBlue", "lightBlue")
- draw.texta(k..": "..v, 1, inty, false, "red", "lightBlue")
- inty = inty + 2
- end
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawScreen("taskbar", "Help", "Help Menu", "Choose a help item")
- elseif args[1] == "mouse_click" then
- if (args[3] >= 1 and args[3] <= 8) then
- desktop(1)
- elseif (args[3] >= 1 and args[3] <= 27) then
- if args[4] == 5 then
- getHelpContent("about")
- sleep(0.5)
- helpcontent()
- elseif args[4] == 7 then
- getHelpContent("controls")
- sleep(0.5)
- helpcontent()
- elseif args[4] == 9 then
- getHelpContent("logins")
- sleep(0.5)
- helpcontent()
- elseif args[4] == 11 then
- getHelpContent("apps")
- sleep(0.5)
- helpcontent()
- elseif args[4] == 13 then
- getHelpContent("creatingapps")
- sleep(0.5)
- helpcontent()
- elseif args[4] == 15 then
- getHelpContent("deletingapps")
- sleep(0.5)
- helpcontent()
- elseif args[4] == 17 then
- getHelpContent("addons")
- sleep(0.5)
- helpcontent()
- end
- end
- end
- end
- end
- function getHelpContent(helpcode)
- col.screen("white", "white")
- drawScreen("taskbar", "Help", "Help: About Fusion")
- draw.textc("Getting content, please wait", 8, false, "blue", "white")
- local content = http.get("https://dannysmc.com/files/fusion/help/"..helpcode..".fush")
- draw.textc("BACK", 18, false, "grey", "white")
- term.setCursorPos(1, 5)
- col.set("grey", "white")
- for _, v in ipairs(data.wordwrap(content.readAll(), 51)) do
- print(v)
- end
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawScreen("taskbar", "Help", "Help: About Fusion")
- elseif args[1] == "mouse_click" then
- if (args[3] >= 20 and args[3] <= 31) and (args[4] == 18) then
- helpcontent()
- elseif (args[3] >= 1 and args[3] <= 8) and (args[4] == 1) then
- desktop(1)
- end
- end
- end
- end
- function Xplore()
- -- Set Vars
- local url = "//:Home"
- local his = {"//:Home"}
- -- Draws URL Bar (w/ time)
- function drawurlbar()
- draw.box(1, 51, 1, 2, " ", "grey", "grey")
- draw.texta("Xplore", 3, 1, false, "white", "grey")
- draw.texta(misc.time(), 47, 1, false, timetc, mainbc)
- draw.box(5, 39, 2, 1, " ", "lightGrey", "lightGrey")
- draw.texta("URL:", 1, 2, false, "lightBlue", "grey")
- draw.texta(":<:", 45, 2, false, "lime", "lightGrey")
- draw.texta(":R:", 49, 2, false, "yellow", "lightGrey")
- draw.texta(his[#his], 5, 2, false, "red", "lightGrey")
- draw.texta("X", 1, 1, false, "lime", "red")
- end
- -- Main Browser
- function browser()
- col.screen("white", "white")
- drawurlbar()
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- drawurlbar()
- elseif args[1] == "mouse_click" then
- if (args[3] >= 5 and args[3] <= 44) and (args[4] == 2) then
- --// Enter URL
- draw.box(5, 39, 2, 1, " ", "lightGrey", "lightGrey")
- term.setCursorPos(5,2)
- col.set("red", "lightGrey")
- local newUrl = tostring(read())
- table.insert(his, newUrl)
- col.screen("white", "white")
- pagerequest(newUrl)
- drawurlbar()
- elseif (args[3] >= 45 and args[3] <= 47) and (args[4] == 2) then
- if #his == 0 then
- col.screen("white", "white")
- pagerequest("//:Home")
- drawurlbar()
- else
- col.screen("white", "white")
- table.remove(his)
- pagerequest(his[#his])
- drawurlbar()
- end
- elseif (args[3] >= 48 and args[3] <= 51) and (args[4] == 2) then
- col.screen("white", "white")
- pagerequest(his[#his])
- drawurlbar()
- elseif (args[3] ==1) and (args[4] == 1) then
- desktop()
- end
- end
- end
- end
- function pagerequest(url)
- if url == "//:Home" then
- url = url
- local pagedata = fs.open("/core/xplore/home.xpl", "r")
- local pagedata = pagedata.readAll()
- local tpagedata = data.wordwrap(pagedata, 51)
- term.setCursorPos(1, 3)
- col.set("black", "white")
- for _, v in ipairs(tpagedata) do
- print(v)
- end
- else
- local pagedata = http.get(url)
- local pagedata = pagedata.readAll()
- local tpagedata = data.wordwrap(pagedata, 51)
- term.setCursorPos(1, 3)
- col.set("black", "white")
- for _, v in ipairs(tpagedata) do
- print(v)
- end
- url = url
- end
- end
- browser()
- end
- function finder()
- -- Set Vars:
- scroll = 1
- histFold = {}
- table.insert(histFold, "/")
- function fb_getClick(sButton, nX, nY, scroll, sDir)
- if sButton == 1 then
- local tFilesClean = tFilesClean
- tFilesCount = #tFilesClean
- local count = nY - 2 - scroll
- oldDir = sDir
- if sDir == "/" then
- newDir = sDir..""..(tFilesClean[count])
- else
- newDir = sDir.."/"..tFilesClean[count]
- end
- sDir = newDir
- if fs.isDir(newDir) then
- table.insert(histFold, sDir)
- fb_finder(newDir)
- else
- fb_runFile(newDir, sDir)
- end
- elseif sButton == 2 then
- -- Do delete or edit
- if sOption == "delete" then
- local tFilesClean = tFilesClean
- tFilesCount = #tFilesClean
- local count = nY - 2 - scroll
- oldDir = sDir
- if sDir == "/" then
- newDir = sDir..""..(tFilesClean[count])
- else
- newDir = sDir.."/"..tFilesClean[count]
- end
- fs.delete(newDir)
- fb_finder(sDir)
- elseif sOption == "edit" then
- -- Empty
- else
- fb_drawOptions(nX, nY, sDir)
- end
- end
- end
- function fb_drawOptions(tempX, tempY, sDir)
- draw.box(tempX, 8, tempY, 2, " ", "black", "lightGrey")
- draw.texta("Delete", tempX, tempY, false, "black", "lightGrey")
- draw.texta("Edit", tempX, tempY + 1, false, "black", "lightGrey")
- while true do
- local args = { os.pullEvent() }
- if args[1] == "mouse_click" then
- if args[2] == 1 then
- if args[3] >= tempX and args[3] <= tempX + 8 then
- if args[4] == tempY then
- local tFilesClean = tFilesClean
- tFilesCount = #tFilesClean
- local count = tempY - 2 - scroll
- oldDir = sDir
- if sDir == "/" then
- newDir = sDir..""..(tFilesClean[count])
- else
- newDir = sDir.."/"..tFilesClean[count]
- end
- fs.delete(newDir)
- fb_finder(sDir)
- elseif args[4] == tempY + 1 then
- local tFilesClean = tFilesClean
- tFilesCount = #tFilesClean
- local count = tempY - 2 - scroll
- oldDir = sDir
- if sDir == "/" then
- newDir = sDir..""..(tFilesClean[count])
- else
- newDir = sDir.."/"..tFilesClean[count]
- end
- shell.run("edit "..newDir)
- fb_finder(sDir)
- else
- fb_finder(sDir)
- end
- else
- fb_finder(sDir)
- end
- else
- fb_finder(sDir)
- end
- end
- end
- end
- function fb_runFile(path, sDir)
- draw.cscreen()
- col.set("black", "white")
- shell.run(path)
- fb_finder(sDir)
- end
- function fb_drawMenu(sDir)
- -- Get files
- maintc = "blue"
- mainbc = "grey"
- mainbc2 = "lightGrey"
- texttc = "black"
- textbc = "white"
- dirtc = "red"
- xtc = "lime"
- sidetc = "white"
- sidebc = "cyan"
- sidetc1 = "lime"
- col.set("white", "white")
- draw.cscreen()
- draw.box(1, 51, 1, 1, " ", maintc, mainbc)
- draw.texta(" "..misc.time().." ", 44, 1, false, maintc, mainbc2)
- draw.texta("X", 1, 1, false, xtc, dirtc)
- draw.texta(" Path: ", 3, 1, false, texttc, mainbc2)
- draw.texta(sDir.." ", 10, 1, false, dirtc, mainbc2)
- draw.box(40, 12, 2, 18, " ", sidetc, sidebc)
- draw.box(41, 10, 3, 16, " ", sidetc, sidebc)
- draw.box(42, 8, 4, 14, " ", sidetc, sidebc)
- draw.box(43, 6, 5, 12, " ", sidetc, sidebc)
- draw.box(44, 4, 6, 10, " ", sidetc, sidebc)
- draw.box(45, 2, 7, 8, " ", sidetc, sidebc)
- draw.texta("< ..", 2, 3, false, "blue", "white")
- draw.texta("Create", 41, 3, false, sidetc1, sidebc)
- draw.texta("File", 43, 4, false, sidetc, sidebc)
- draw.texta("Folder", 43, 5, false, sidetc, sidebc)
- col.set(texttc, textbc)
- end
- function fb_finder(sDir)
- -- Get files
- fb_drawMenu(sDir)
- fb_drawDir(sDir, scroll)
- while true do
- local args = { os.pullEvent() }
- if args[1] == "timer" then
- fb_drawMenu(sDir)
- fb_drawDir(sDir, scroll)
- elseif args[1] == "mouse_scroll" then
- if args[2] == 1 then
- scroll = scroll + 1
- fb_drawMenu(sDir)
- fb_drawDir(sDir, scroll)
- elseif args[2] == -1 then
- scroll = scroll - 1
- fb_drawMenu(sDir)
- fb_drawDir(sDir, scroll)
- end
- elseif args[1] == "mouse_click" then
- if args[3] == 1 and args[4] == 1 then
- if RunningUnder == "Fusion" then
- desktop()
- else
- setCol("white", "black")
- break
- end
- elseif (args[3] >= 2 and args[3] <= 40) and (args[4] == 3) then
- table.remove(histFold)
- historyCount = #histFold
- sDir = histFold[historyCount]
- fb_finder(sDir)
- elseif (args[3] >= 2 and args[3] <= 40) and (args[4] >= 4 and args[4] <= 18) then
- fb_getClick(args[2], args[3], args[4], scroll, sDir)
- elseif (args[3] >= 43 and args[3] <= 50) then
- if args[4] == 4 then
- fb_drawInput("file", sDir)
- elseif args[4] == 5 then
- fb_drawInput("folder", sDir)
- end
- end
- end
- end
- end
- function fb_drawInput(object, sDir)
- poptc1 = "white"
- popbc1 = "red"
- poptc2 = "black"
- popbc2 = "white"
- if object == "file" then
- draw.box(6, 39, 6, 3, " ", poptc1, popbc1)
- draw.box(6, 39, 7, 1, " ", poptc1, popbc1)
- draw.box(7, 37, 7, 1, " ", poptc2, popbc2)
- draw.textc("Name For File:", 6, false, poptc1, popbc1)
- col.set(poptc2, popbc2)
- term.setCursorPos(7,7)
- write(": ")
- local newFileName = tostring(read())
- if sDir == "/" then
- fileDirName = "/"..newFileName
- else
- fileDirName = sDir.."/"..newFileName
- end
- shell.run("edit "..fileDirName)
- fb_finder(sDir)
- elseif object == "folder" then
- draw.box(6, 39, 6, 3, " ", poptc1, popbc1)
- draw.box(6, 39, 7, 1, " ", poptc1, popbc1)
- draw.box(7, 37, 7, 1, " ", poptc2, popbc2)
- draw.textc("Name For Folder:", 6, false, poptc1, popbc1)
- col.set(poptc2, popbc2)
- term.setCursorPos(7,7)
- write(": ")
- local newFolderName = tostring(read())
- if sDir == "/" then
- fileDirName = "/"..newFolderName
- else
- fileDirName = sDir.."/"..newFolderName
- end
- fs.makeDir(fileDirName)
- fb_finder(sDir)
- end
- end
- -- Code by: wieselkatze (Modified by dannysmc95)
- local function fb_getDir( sDir )
- sDir = ( "/" .. sDir .. "/" ):gsub( "\\+", "/" ):gsub( "/+", "/" )
- local folder, list = sDir:match( ".*/" ), {}
- tFilesClean = {}
- if not fs.isDir( sDir ) then
- return {}
- end
- for k, v in pairs( fs.list( sDir ) ) do
- if fs.isDir( folder .. v ) then
- table.insert( list, 1, "+ " .. v )
- table.insert( tFilesClean, 1, v)
- else
- list[ #list+1 ] = "- " .. v
- tFilesClean[ #tFilesClean + 1 ] = v
- end
- end
- return list
- end
- function fb_drawDir(sDir, scroll)
- local intX = 2
- local intY = 4
- tFiles = fb_getDir(sDir)
- for k, v in ipairs(tFiles) do
- if k >= scroll and k <= 15 then
- term.setCursorPos(intX, intY)
- if v:find("+") then
- col.set("blue", "white")
- print(v)
- else
- col.set("red", "white")
- print(v)
- end
- intY = intY + 1
- end
- end
- end
- function fb_main()
- if fs.exists("fusion") then
- RunningUnder = "Fusion"
- else
- RunningUnder = "Unknown"
- end
- fb_finder("/")
- end
- fb_main()
- end
- function gravityscore_luaide()
- --
- -- Lua IDE
- -- Made by GravityScore
- --
- -- -------- Variables
- -- Version
- local version = "1.0"
- local args = {}
- -- Editing
- local w, h = term.getSize()
- local tabWidth = 2
- local autosaveInterval = 20
- local allowEditorEvent = true
- local keyboardShortcutTimeout = 0.4
- -- Clipboard
- local clipboard = nil
- -- Theme
- local theme = {}
- -- Language
- local languages = {}
- local curLanguage = {}
- -- Events
- local event_distract = "luaide_distractionEvent"
- -- Locations
- local updateURL = "https://raw.github.com/GravityScore/LuaIDE/master/luaide.lua"
- local ideLocation = "/" .. shell.getRunningProgram()
- local themeLocation = "/.LuaIDE-Theme"
- local function isAdvanced() return term.isColor and term.isColor() end
- -- -------- Utilities
- local function modRead(properties)
- local w, h = term.getSize()
- local defaults = {replaceChar = nil, history = nil, visibleLength = nil, textLength = nil,
- liveUpdates = nil, exitOnKey = nil}
- if not properties then properties = {} end
- for k, v in pairs(defaults) do if not properties[k] then properties[k] = v end end
- if properties.replaceChar then properties.replaceChar = properties.replaceChar:sub(1, 1) end
- if not properties.visibleLength then properties.visibleLength = w end
- local sx, sy = term.getCursorPos()
- local line = ""
- local pos = 0
- local historyPos = nil
- local function redraw(repl)
- local scroll = 0
- if properties.visibleLength and sx + pos > properties.visibleLength + 1 then
- scroll = (sx + pos) - (properties.visibleLength + 1)
- end
- term.setCursorPos(sx, sy)
- local a = repl or properties.replaceChar
- if a then term.write(string.rep(a, line:len() - scroll))
- else term.write(line:sub(scroll + 1, -1)) end
- term.setCursorPos(sx + pos - scroll, sy)
- end
- local function sendLiveUpdates(event, ...)
- if type(properties.liveUpdates) == "function" then
- local ox, oy = term.getCursorPos()
- local a, data = properties.liveUpdates(line, event, ...)
- if a == true and data == nil then
- term.setCursorBlink(false)
- return line
- elseif a == true and data ~= nil then
- term.setCursorBlink(false)
- return data
- end
- term.setCursorPos(ox, oy)
- end
- end
- term.setCursorBlink(true)
- while true do
- local e, but, x, y, p4, p5 = os.pullEvent()
- if e == "char" then
- local s = false
- if properties.textLength and line:len() < properties.textLength then s = true
- elseif not properties.textLength then s = true end
- local canType = true
- if not properties.grantPrint and properties.refusePrint then
- local canTypeKeys = {}
- if type(properties.refusePrint) == "table" then
- for _, v in pairs(properties.refusePrint) do
- table.insert(canTypeKeys, tostring(v):sub(1, 1))
- end
- elseif type(properties.refusePrint) == "string" then
- for char in properties.refusePrint:gmatch(".") do
- table.insert(canTypeKeys, char)
- end
- end
- for _, v in pairs(canTypeKeys) do if but == v then canType = false end end
- elseif properties.grantPrint then
- canType = false
- local canTypeKeys = {}
- if type(properties.grantPrint) == "table" then
- for _, v in pairs(properties.grantPrint) do
- table.insert(canTypeKeys, tostring(v):sub(1, 1))
- end
- elseif type(properties.grantPrint) == "string" then
- for char in properties.grantPrint:gmatch(".") do
- table.insert(canTypeKeys, char)
- end
- end
- for _, v in pairs(canTypeKeys) do if but == v then canType = true end end
- end
- if s and canType then
- line = line:sub(1, pos) .. but .. line:sub(pos + 1, -1)
- pos = pos + 1
- redraw()
- end
- elseif e == "key" then
- if but == keys.enter then break
- elseif but == keys.left then if pos > 0 then pos = pos - 1 redraw() end
- elseif but == keys.right then if pos < line:len() then pos = pos + 1 redraw() end
- elseif (but == keys.up or but == keys.down) and properties.history then
- redraw(" ")
- if but == keys.up then
- if historyPos == nil and #properties.history > 0 then
- historyPos = #properties.history
- elseif historyPos > 1 then
- historyPos = historyPos - 1
- end
- elseif but == keys.down then
- if historyPos == #properties.history then historyPos = nil
- elseif historyPos ~= nil then historyPos = historyPos + 1 end
- end
- if properties.history and historyPos then
- line = properties.history[historyPos]
- pos = line:len()
- else
- line = ""
- pos = 0
- end
- redraw()
- local a = sendLiveUpdates("history")
- if a then return a end
- elseif but == keys.backspace and pos > 0 then
- redraw(" ")
- line = line:sub(1, pos - 1) .. line:sub(pos + 1, -1)
- pos = pos - 1
- redraw()
- local a = sendLiveUpdates("delete")
- if a then return a end
- elseif but == keys.home then
- pos = 0
- redraw()
- elseif but == keys.delete and pos < line:len() then
- redraw(" ")
- line = line:sub(1, pos) .. line:sub(pos + 2, -1)
- redraw()
- local a = sendLiveUpdates("delete")
- if a then return a end
- elseif but == keys["end"] then
- pos = line:len()
- redraw()
- elseif properties.exitOnKey then
- if but == properties.exitOnKey or (properties.exitOnKey == "control" and
- (but == 29 or but == 157)) then
- term.setCursorBlink(false)
- return nil
- end
- end
- end
- local a = sendLiveUpdates(e, but, x, y, p4, p5)
- if a then return a end
- end
- term.setCursorBlink(false)
- if line ~= nil then line = line:gsub("^%s*(.-)%s*$", "%1") end
- return line
- end
- -- -------- Themes
- local defaultTheme = {
- background = "gray",
- backgroundHighlight = "lightGray",
- prompt = "cyan",
- promptHighlight = "lightBlue",
- err = "red",
- errHighlight = "pink",
- editorBackground = "gray",
- editorLineHightlight = "lightBlue",
- editorLineNumbers = "gray",
- editorLineNumbersHighlight = "lightGray",
- editorError = "pink",
- editorErrorHighlight = "red",
- textColor = "white",
- conditional = "yellow",
- constant = "orange",
- ["function"] = "magenta",
- string = "red",
- comment = "lime"
- }
- local normalTheme = {
- background = "black",
- backgroundHighlight = "black",
- prompt = "black",
- promptHighlight = "black",
- err = "black",
- errHighlight = "black",
- editorBackground = "black",
- editorLineHightlight = "black",
- editorLineNumbers = "black",
- editorLineNumbersHighlight = "white",
- editorError = "black",
- editorErrorHighlight = "black",
- textColor = "white",
- conditional = "white",
- constant = "white",
- ["function"] = "white",
- string = "white",
- comment = "white"
- }
- local availableThemes = {
- {"Water (Default)", "https://raw.github.com/GravityScore/LuaIDE/master/themes/default.txt"},
- {"Fire", "https://raw.github.com/GravityScore/LuaIDE/master/themes/fire.txt"},
- {"Sublime Text 2", "https://raw.github.com/GravityScore/LuaIDE/master/themes/st2.txt"},
- {"Midnight", "https://raw.github.com/GravityScore/LuaIDE/master/themes/midnight.txt"},
- {"TheOriginalBIT", "https://raw.github.com/GravityScore/LuaIDE/master/themes/bit.txt"},
- {"Superaxander", "https://raw.github.com/GravityScore/LuaIDE/master/themes/superaxander.txt"},
- {"Forest", "https://raw.github.com/GravityScore/LuaIDE/master/themes/forest.txt"},
- {"Night", "https://raw.github.com/GravityScore/LuaIDE/master/themes/night.txt"},
- {"Original", "https://raw.github.com/GravityScore/LuaIDE/master/themes/original.txt"},
- }
- local function loadTheme(path)
- local f = io.open(path)
- local l = f:read("*l")
- local config = {}
- while l ~= nil do
- local k, v = string.match(l, "^(%a+)=(%a+)")
- if k and v then config[k] = v end
- l = f:read("*l")
- end
- f:close()
- return config
- end
- -- Load Theme
- if isAdvanced() then theme = defaultTheme
- else theme = normalTheme end
- -- -------- Drawing
- local function centerPrint(text, ny)
- if type(text) == "table" then for _, v in pairs(text) do centerPrint(v) end
- else
- local x, y = term.getCursorPos()
- local w, h = term.getSize()
- term.setCursorPos(w/2 - text:len()/2 + (#text % 2 == 0 and 1 or 0), ny or y)
- print(text)
- end
- end
- local function title(t)
- term.setTextColor(colors[theme.textColor])
- term.setBackgroundColor(colors[theme.background])
- term.clear()
- term.setBackgroundColor(colors[theme.backgroundHighlight])
- for i = 2, 4 do term.setCursorPos(1, i) term.clearLine() end
- term.setCursorPos(3, 3)
- term.write(t)
- end
- local function centerRead(wid, begt)
- local function liveUpdate(line, e, but, x, y, p4, p5)
- if isAdvanced() and e == "mouse_click" and x >= w/2 - wid/2 and x <= w/2 - wid/2 + 10
- and y >= 13 and y <= 15 then
- return true, ""
- end
- end
- if not begt then begt = "" end
- term.setTextColor(colors[theme.textColor])
- term.setBackgroundColor(colors[theme.promptHighlight])
- for i = 8, 10 do
- term.setCursorPos(w/2 - wid/2, i)
- term.write(string.rep(" ", wid))
- end
- if isAdvanced() then
- term.setBackgroundColor(colors[theme.errHighlight])
- for i = 13, 15 do
- term.setCursorPos(w/2 - wid/2 + 1, i)
- term.write(string.rep(" ", 10))
- end
- term.setCursorPos(w/2 - wid/2 + 2, 14)
- term.write("> Cancel")
- end
- term.setBackgroundColor(colors[theme.promptHighlight])
- term.setCursorPos(w/2 - wid/2 + 1, 9)
- term.write("> " .. begt)
- return modRead({visibleLength = w/2 + wid/2, liveUpdates = liveUpdate})
- end
- -- -------- Prompt
- local function prompt(list, dir, isGrid)
- local function draw(sel)
- for i, v in ipairs(list) do
- if i == sel then term.setBackgroundColor(v.highlight or colors[theme.promptHighlight])
- else term.setBackgroundColor(v.bg or colors[theme.prompt]) end
- term.setTextColor(v.tc or colors[theme.textColor])
- for i = -1, 1 do
- term.setCursorPos(v[2], v[3] + i)
- term.write(string.rep(" ", v[1]:len() + 4))
- end
- term.setCursorPos(v[2], v[3])
- if i == sel then
- term.setBackgroundColor(v.highlight or colors[theme.promptHighlight])
- term.write(" > ")
- else term.write(" - ") end
- term.write(v[1] .. " ")
- end
- end
- local key1 = dir == "horizontal" and 203 or 200
- local key2 = dir == "horizontal" and 205 or 208
- local sel = 1
- draw(sel)
- while true do
- local e, but, x, y = os.pullEvent()
- if e == "key" and but == 28 then
- return list[sel][1]
- elseif e == "key" and but == key1 and sel > 1 then
- sel = sel - 1
- draw(sel)
- elseif e == "key" and but == key2 and ((err == true and sel < #list - 1) or (sel < #list)) then
- sel = sel + 1
- draw(sel)
- elseif isGrid and e == "key" and but == 203 and sel > 2 then
- sel = sel - 2
- draw(sel)
- elseif isGrid and e == "key" and but == 205 and sel < 3 then
- sel = sel + 2
- draw(sel)
- elseif e == "mouse_click" then
- for i, v in ipairs(list) do
- if x >= v[2] - 1 and x <= v[2] + v[1]:len() + 3 and y >= v[3] - 1 and y <= v[3] + 1 then
- return list[i][1]
- end
- end
- end
- end
- end
- local function scrollingPrompt(list)
- local function draw(items, sel, loc)
- for i, v in ipairs(items) do
- local bg = colors[theme.prompt]
- local bghigh = colors[theme.promptHighlight]
- if v:find("Back") or v:find("Return") then
- bg = colors[theme.err]
- bghigh = colors[theme.errHighlight]
- end
- if i == sel then term.setBackgroundColor(bghigh)
- else term.setBackgroundColor(bg) end
- term.setTextColor(colors[theme.textColor])
- for x = -1, 1 do
- term.setCursorPos(3, (i * 4) + x + 4)
- term.write(string.rep(" ", w - 13))
- end
- term.setCursorPos(3, i * 4 + 4)
- if i == sel then
- term.setBackgroundColor(bghigh)
- term.write(" > ")
- else term.write(" - ") end
- term.write(v .. " ")
- end
- end
- local function updateDisplayList(items, loc, len)
- local ret = {}
- for i = 1, len do
- local item = items[i + loc - 1]
- if item then table.insert(ret, item) end
- end
- return ret
- end
- -- Variables
- local sel = 1
- local loc = 1
- local len = 3
- local disList = updateDisplayList(list, loc, len)
- draw(disList, sel, loc)
- -- Loop
- while true do
- local e, key, x, y = os.pullEvent()
- if e == "mouse_click" then
- for i, v in ipairs(disList) do
- if x >= 3 and x <= w - 11 and y >= i * 4 + 3 and y <= i * 4 + 5 then return v end
- end
- elseif e == "key" and key == 200 then
- if sel > 1 then
- sel = sel - 1
- draw(disList, sel, loc)
- elseif loc > 1 then
- loc = loc - 1
- disList = updateDisplayList(list, loc, len)
- draw(disList, sel, loc)
- end
- elseif e == "key" and key == 208 then
- if sel < len then
- sel = sel + 1
- draw(disList, sel, loc)
- elseif loc + len - 1 < #list then
- loc = loc + 1
- disList = updateDisplayList(list, loc, len)
- draw(disList, sel, loc)
- end
- elseif e == "mouse_scroll" then
- os.queueEvent("key", key == -1 and 200 or 208)
- elseif e == "key" and key == 28 then
- return disList[sel]
- end
- end
- end
- function monitorKeyboardShortcuts()
- local ta, tb = nil, nil
- local allowChar = false
- local shiftPressed = false
- while true do
- local event, char = os.pullEvent()
- if event == "key" and (char == 42 or char == 52) then
- shiftPressed = true
- tb = os.startTimer(keyboardShortcutTimeout)
- elseif event == "key" and (char == 29 or char == 157 or char == 219 or char == 220) then
- allowEditorEvent = false
- allowChar = true
- ta = os.startTimer(keyboardShortcutTimeout)
- elseif event == "key" and allowChar then
- local name = nil
- for k, v in pairs(keys) do
- if v == char then
- if shiftPressed then os.queueEvent("shortcut", "ctrl shift", k:lower())
- else os.queueEvent("shortcut", "ctrl", k:lower()) end
- sleep(0.005)
- allowEditorEvent = true
- end
- end
- if shiftPressed then os.queueEvent("shortcut", "ctrl shift", char)
- else os.queueEvent("shortcut", "ctrl", char) end
- elseif event == "timer" and char == ta then
- allowEditorEvent = true
- allowChar = false
- elseif event == "timer" and char == tb then
- shiftPressed = false
- end
- end
- end
- -- -------- Saving and Loading
- local function download(url, path)
- for i = 1, 3 do
- local response = http.get(url)
- if response then
- local data = response.readAll()
- response.close()
- if path then
- local f = io.open(path, "w")
- f:write(data)
- f:close()
- end
- return true
- end
- end
- return false
- end
- local function saveFile(path, lines)
- local dir = path:sub(1, path:len() - fs.getName(path):len())
- if not fs.exists(dir) then fs.makeDir(dir) end
- if not fs.isDir(path) and not fs.isReadOnly(path) then
- local a = ""
- for _, v in pairs(lines) do a = a .. v .. "\n" end
- local f = io.open(path, "w")
- f:write(a)
- f:close()
- return true
- else return false end
- end
- local function loadFile(path)
- if not fs.exists(path) then
- local dir = path:sub(1, path:len() - fs.getName(path):len())
- if not fs.exists(dir) then fs.makeDir(dir) end
- local f = io.open(path, "w")
- f:write("")
- f:close()
- end
- local l = {}
- if fs.exists(path) and not fs.isDir(path) then
- local f = io.open(path, "r")
- if f then
- local a = f:read("*l")
- while a do
- table.insert(l, a)
- a = f:read("*l")
- end
- f:close()
- end
- else return nil end
- if #l < 1 then table.insert(l, "") end
- return l
- end
- -- -------- Languages
- languages.lua = {}
- languages.brainfuck = {}
- languages.none = {}
- -- Lua
- languages.lua.helpTips = {
- "A function you tried to call doesn't exist.",
- "You made a typo.",
- "The index of an array is nil.",
- "The wrong variable type was passed.",
- "A function/variable doesn't exist.",
- "You missed an 'end'.",
- "You missed a 'then'.",
- "You declared a variable incorrectly.",
- "One of your variables is mysteriously nil."
- }
- languages.lua.defaultHelpTips = {
- 2, 5
- }
- languages.lua.errors = {
- ["Attempt to call nil."] = {1, 2},
- ["Attempt to index nil."] = {3, 2},
- [".+ expected, got .+"] = {4, 2, 9},
- ["'end' expected"] = {6, 2},
- ["'then' expected"] = {7, 2},
- ["'=' expected"] = {8, 2}
- }
- languages.lua.keywords = {
- ["and"] = "conditional",
- ["break"] = "conditional",
- ["do"] = "conditional",
- ["else"] = "conditional",
- ["elseif"] = "conditional",
- ["end"] = "conditional",
- ["for"] = "conditional",
- ["function"] = "conditional",
- ["if"] = "conditional",
- ["in"] = "conditional",
- ["local"] = "conditional",
- ["not"] = "conditional",
- ["or"] = "conditional",
- ["repeat"] = "conditional",
- ["return"] = "conditional",
- ["then"] = "conditional",
- ["until"] = "conditional",
- ["while"] = "conditional",
- ["true"] = "constant",
- ["false"] = "constant",
- ["nil"] = "constant",
- ["print"] = "function",
- ["write"] = "function",
- ["sleep"] = "function",
- ["pairs"] = "function",
- ["ipairs"] = "function",
- ["loadstring"] = "function",
- ["loadfile"] = "function",
- ["dofile"] = "function",
- ["rawset"] = "function",
- ["rawget"] = "function",
- ["setfenv"] = "function",
- ["getfenv"] = "function",
- }
- languages.lua.parseError = function(e)
- local ret = {filename = "unknown", line = -1, display = "Unknown!", err = ""}
- if e and e ~= "" then
- ret.err = e
- if e:find(":") then
- ret.filename = e:sub(1, e:find(":") - 1):gsub("^%s*(.-)%s*$", "%1")
- -- The "" is needed to circumvent a CC bug
- e = (e:sub(e:find(":") + 1) .. ""):gsub("^%s*(.-)%s*$", "%1")
- if e:find(":") then
- ret.line = e:sub(1, e:find(":") - 1)
- e = e:sub(e:find(":") + 2):gsub("^%s*(.-)%s*$", "%1") .. ""
- end
- end
- ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. "."
- end
- return ret
- end
- languages.lua.getCompilerErrors = function(code)
- code = "local function ee65da6af1cb6f63fee9a081246f2fd92b36ef2(...)\n\n" .. code .. "\n\nend"
- local fn, err = loadstring(code)
- if not err then
- local _, e = pcall(fn)
- if e then err = e end
- end
- if err then
- local a = err:find("]", 1, true)
- if a then err = "string" .. err:sub(a + 1, -1) end
- local ret = languages.lua.parseError(err)
- if tonumber(ret.line) then ret.line = tonumber(ret.line) end
- return ret
- else return languages.lua.parseError(nil) end
- end
- languages.lua.run = function(path, ar)
- local fn, err = loadfile(path)
- setfenv(fn, getfenv())
- if not err then
- _, err = pcall(function() fn(unpack(ar)) end)
- end
- return err
- end
- -- Brainfuck
- languages.brainfuck.helpTips = {
- "Well idk...",
- "Isn't this the whole point of the language?",
- "Ya know... Not being able to debug it?",
- "You made a typo."
- }
- languages.brainfuck.defaultHelpTips = {
- 1, 2, 3
- }
- languages.brainfuck.errors = {
- ["No matching '['"] = {1, 2, 3, 4}
- }
- languages.brainfuck.keywords = {}
- languages.brainfuck.parseError = function(e)
- local ret = {filename = "unknown", line = -1, display = "Unknown!", err = ""}
- if e and e ~= "" then
- ret.err = e
- ret.line = e:sub(1, e:find(":") - 1)
- e = e:sub(e:find(":") + 2):gsub("^%s*(.-)%s*$", "%1") .. ""
- ret.display = e:sub(1, 1):upper() .. e:sub(2, -1) .. "."
- end
- return ret
- end
- languages.brainfuck.mapLoops = function(code)
- -- Map loops
- local loopLocations = {}
- local loc = 1
- local line = 1
- for let in string.gmatch(code, ".") do
- if let == "[" then
- loopLocations[loc] = true
- elseif let == "]" then
- local found = false
- for i = loc, 1, -1 do
- if loopLocations[i] == true then
- loopLocations[i] = loc
- found = true
- end
- end
- if not found then
- return line .. ": No matching '['"
- end
- end
- if let == "\n" then line = line + 1 end
- loc = loc + 1
- end
- return loopLocations
- end
- languages.brainfuck.getCompilerErrors = function(code)
- local a = languages.brainfuck.mapLoops(code)
- if type(a) == "string" then return languages.brainfuck.parseError(a)
- else return languages.brainfuck.parseError(nil) end
- end
- languages.brainfuck.run = function(path)
- -- Read from file
- local f = io.open(path, "r")
- local content = f:read("*a")
- f:close()
- -- Define environment
- local dataCells = {}
- local dataPointer = 1
- local instructionPointer = 1
- -- Map loops
- local loopLocations = languages.brainfuck.mapLoops(content)
- if type(loopLocations) == "string" then return loopLocations end
- -- Execute code
- while true do
- local let = content:sub(instructionPointer, instructionPointer)
- if let == ">" then
- dataPointer = dataPointer + 1
- if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
- elseif let == "<" then
- if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
- dataPointer = dataPointer - 1
- if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
- elseif let == "+" then
- if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
- dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] + 1
- elseif let == "-" then
- if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
- dataCells[tostring(dataPointer)] = dataCells[tostring(dataPointer)] - 1
- elseif let == "." then
- if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
- if term.getCursorPos() >= w then print("") end
- write(string.char(math.max(1, dataCells[tostring(dataPointer)])))
- elseif let == "," then
- if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
- term.setCursorBlink(true)
- local e, but = os.pullEvent("char")
- term.setCursorBlink(false)
- dataCells[tostring(dataPointer)] = string.byte(but)
- if term.getCursorPos() >= w then print("") end
- write(but)
- elseif let == "/" then
- if not dataCells[tostring(dataPointer)] then dataCells[tostring(dataPointer)] = 0 end
- if term.getCursorPos() >= w then print("") end
- write(dataCells[tostring(dataPointer)])
- elseif let == "[" then
- if dataCells[tostring(dataPointer)] == 0 then
- for k, v in pairs(loopLocations) do
- if k == instructionPointer then instructionPointer = v end
- end
- end
- elseif let == "]" then
- for k, v in pairs(loopLocations) do
- if v == instructionPointer then instructionPointer = k - 1 end
- end
- end
- instructionPointer = instructionPointer + 1
- if instructionPointer > content:len() then print("") break end
- end
- end
- -- None
- languages.none.helpTips = {}
- languages.none.defaultHelpTips = {}
- languages.none.errors = {}
- languages.none.keywords = {}
- languages.none.parseError = function(err)
- return {filename = "", line = -1, display = "", err = ""}
- end
- languages.none.getCompilerErrors = function(code)
- return languages.none.parseError(nil)
- end
- languages.none.run = function(path) end
- -- Load language
- curLanguage = languages.lua
- -- -------- Run GUI
- local function viewErrorHelp(e)
- title("LuaIDE - Error Help")
- local tips = nil
- for k, v in pairs(curLanguage.errors) do
- if e.display:find(k) then tips = v break end
- end
- term.setBackgroundColor(colors[theme.err])
- for i = 6, 8 do
- term.setCursorPos(5, i)
- term.write(string.rep(" ", 35))
- end
- term.setBackgroundColor(colors[theme.prompt])
- for i = 10, 18 do
- term.setCursorPos(5, i)
- term.write(string.rep(" ", 46))
- end
- if tips then
- term.setBackgroundColor(colors[theme.err])
- term.setCursorPos(6, 7)
- term.write("Error Help")
- term.setBackgroundColor(colors[theme.prompt])
- for i, v in ipairs(tips) do
- term.setCursorPos(7, i + 10)
- term.write("- " .. curLanguage.helpTips[v])
- end
- else
- term.setBackgroundColor(colors[theme.err])
- term.setCursorPos(6, 7)
- term.write("No Error Tips Available!")
- term.setBackgroundColor(colors[theme.prompt])
- term.setCursorPos(6, 11)
- term.write("There are no error tips available, but")
- term.setCursorPos(6, 12)
- term.write("you could see if it was any of these:")
- for i, v in ipairs(curLanguage.defaultHelpTips) do
- term.setCursorPos(7, i + 12)
- term.write("- " .. curLanguage.helpTips[v])
- end
- end
- prompt({{"Back", w - 8, 7}}, "horizontal")
- end
- local function run(path, lines, useArgs)
- local ar = {}
- if useArgs then
- title("LuaIDE - Run " .. fs.getName(path))
- local s = centerRead(w - 13, fs.getName(path) .. " ")
- for m in string.gmatch(s, "[^ \t]+") do ar[#ar + 1] = m:gsub("^%s*(.-)%s*$", "%1") end
- end
- saveFile(path, lines)
- term.setCursorBlink(false)
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1, 1)
- local err = curLanguage.run(path, ar)
- term.setBackgroundColor(colors.black)
- print("\n")
- if err then
- if isAdvanced() then term.setTextColor(colors.red) end
- centerPrint("The program has crashed!")
- end
- term.setTextColor(colors.white)
- centerPrint("Press any key to return to LuaIDE...")
- while true do
- local e = os.pullEvent()
- if e == "key" then break end
- end
- -- To prevent key from showing up in editor
- os.queueEvent(event_distract)
- os.pullEvent()
- if err then
- if curLanguage == languages.lua and err:find("]") then
- err = fs.getName(path) .. err:sub(err:find("]", 1, true) + 1, -1)
- end
- while true do
- title("LuaIDE - Error!")
- term.setBackgroundColor(colors[theme.err])
- for i = 6, 8 do
- term.setCursorPos(3, i)
- term.write(string.rep(" ", w - 5))
- end
- term.setCursorPos(4, 7)
- term.write("The program has crashed!")
- term.setBackgroundColor(colors[theme.prompt])
- for i = 10, 14 do
- term.setCursorPos(3, i)
- term.write(string.rep(" ", w - 5))
- end
- local formattedErr = curLanguage.parseError(err)
- term.setCursorPos(4, 11)
- term.write("Line: " .. formattedErr.line)
- term.setCursorPos(4, 12)
- term.write("Error:")
- term.setCursorPos(5, 13)
- local a = formattedErr.display
- local b = nil
- if a:len() > w - 8 then
- for i = a:len(), 1, -1 do
- if a:sub(i, i) == " " then
- b = a:sub(i + 1, -1)
- a = a:sub(1, i)
- break
- end
- end
- end
- term.write(a)
- if b then
- term.setCursorPos(5, 14)
- term.write(b)
- end
- local opt = prompt({{"Error Help", w/2 - 15, 17}, {"Go To Line", w/2 + 2, 17}},
- "horizontal")
- if opt == "Error Help" then
- viewErrorHelp(formattedErr)
- elseif opt == "Go To Line" then
- -- To prevent key from showing up in editor
- os.queueEvent(event_distract)
- os.pullEvent()
- return "go to", tonumber(formattedErr.line)
- end
- end
- end
- end
- -- -------- Functions
- local function goto()
- term.setBackgroundColor(colors[theme.backgroundHighlight])
- term.setCursorPos(2, 1)
- term.clearLine()
- term.write("Line: ")
- local line = modRead({visibleLength = w - 2})
- local num = tonumber(line)
- if num and num > 0 then return num
- else
- term.setCursorPos(2, 1)
- term.clearLine()
- term.write("Not a line number!")
- sleep(1.6)
- return nil
- end
- end
- local function setsyntax()
- local opts = {
- "[Lua] Brainfuck None ",
- " Lua [Brainfuck] None ",
- " Lua Brainfuck [None]"
- }
- local sel = 1
- term.setCursorBlink(false)
- term.setBackgroundColor(colors[theme.backgroundHighlight])
- term.setCursorPos(2, 1)
- term.clearLine()
- term.write(opts[sel])
- while true do
- local e, but, x, y = os.pullEvent("key")
- if but == 203 then
- sel = math.max(1, sel - 1)
- term.setCursorPos(2, 1)
- term.clearLine()
- term.write(opts[sel])
- elseif but == 205 then
- sel = math.min(#opts, sel + 1)
- term.setCursorPos(2, 1)
- term.clearLine()
- term.write(opts[sel])
- elseif but == 28 then
- if sel == 1 then curLanguage = languages.lua
- elseif sel == 2 then curLanguage = languages.brainfuck
- elseif sel == 3 then curLanguage = languages.none end
- term.setCursorBlink(true)
- return
- end
- end
- end
- -- -------- Re-Indenting
- local tabWidth = 2
- local comments = {}
- local strings = {}
- local increment = {
- "if%s+.+%s+then%s*$",
- "for%s+.+%s+do%s*$",
- "while%s+.+%s+do%s*$",
- "repeat%s*$",
- "function%s+[a-zA-Z_0-9](.*)%s*$"
- }
- local decrement = {
- "end",
- "until%s+.+"
- }
- local special = {
- "else%s*$",
- "elseif%s+.+%s+then%s*$"
- }
- local function check(func)
- for _, v in pairs(func) do
- local cLineStart = v["lineStart"]
- local cLineEnd = v["lineEnd"]
- local cCharStart = v["charStart"]
- local cCharEnd = v["charEnd"]
- if line >= cLineStart and line <= cLineEnd then
- if line == cLineStart then return cCharStart < charNumb
- elseif line == cLineEnd then return cCharEnd > charNumb
- else return true end
- end
- end
- end
- local function isIn(line, loc)
- if check(comments) then return true end
- if check(strings) then return true end
- return false
- end
- local function setComment(ls, le, cs, ce)
- comments[#comments + 1] = {}
- comments[#comments].lineStart = ls
- comments[#comments].lineEnd = le
- comments[#comments].charStart = cs
- comments[#comments].charEnd = ce
- end
- local function setString(ls, le, cs, ce)
- strings[#strings + 1] = {}
- strings[#strings].lineStart = ls
- strings[#strings].lineEnd = le
- strings[#strings].charStart = cs
- strings[#strings].charEnd = ce
- end
- local function map(contents)
- local inCom = false
- local inStr = false
- for i = 1, #contents do
- if content[i]:find("%-%-%[%[") and not inStr and not inCom then
- local cStart = content[i]:find("%-%-%[%[")
- setComment(i, nil, cStart, nil)
- inCom = true
- elseif content[i]:find("%-%-%[=%[") and not inStr and not inCom then
- local cStart = content[i]:find("%-%-%[=%[")
- setComment(i, nil, cStart, nil)
- inCom = true
- elseif content[i]:find("%[%[") and not inStr and not inCom then
- local cStart = content[i]:find("%[%[")
- setString(i, nil, cStart, nil)
- inStr = true
- elseif content[i]:find("%[=%[") and not inStr and not inCom then
- local cStart = content[i]:find("%[=%[")
- setString(i, nil, cStart, nil)
- inStr = true
- end
- if content[i]:find("%]%]") and inStr and not inCom then
- local cStart, cEnd = content[i]:find("%]%]")
- strings[#strings].lineEnd = i
- strings[#strings].charEnd = cEnd
- inStr = false
- elseif content[i]:find("%]=%]") and inStr and not inCom then
- local cStart, cEnd = content[i]:find("%]=%]")
- strings[#strings].lineEnd = i
- strings[#strings].charEnd = cEnd
- inStr = false
- end
- if content[i]:find("%]%]") and not inStr and inCom then
- local cStart, cEnd = content[i]:find("%]%]")
- comments[#comments].lineEnd = i
- comments[#comments].charEnd = cEnd
- inCom = false
- elseif content[i]:find("%]=%]") and not inStr and inCom then
- local cStart, cEnd = content[i]:find("%]=%]")
- comments[#comments].lineEnd = i
- comments[#comments].charEnd = cEnd
- inCom = false
- end
- if content[i]:find("%-%-") and not inStr and not inCom then
- local cStart = content[i]:find("%-%-")
- setComment(i, i, cStart, -1)
- elseif content[i]:find("'") and not inStr and not inCom then
- local cStart, cEnd = content[i]:find("'")
- local nextChar = content[i]:sub(cEnd + 1, string.len(content[i]))
- local _, cEnd = nextChar:find("'")
- setString(i, i, cStart, cEnd)
- elseif content[i]:find('"') and not inStr and not inCom then
- local cStart, cEnd = content[i]:find('"')
- local nextChar = content[i]:sub(cEnd + 1, string.len(content[i]))
- local _, cEnd = nextChar:find('"')
- setString(i, i, cStart, cEnd)
- end
- end
- end
- local function reindent(contents)
- local err = nil
- if curLanguage ~= languages.lua then
- err = "Cannot indent languages other than Lua!"
- elseif curLanguage.getCompilerErrors(table.concat(contents, "\n")).line ~= -1 then
- err = "Cannot indent a program with errors!"
- end
- if err then
- term.setCursorBlink(false)
- term.setCursorPos(2, 1)
- term.setBackgroundColor(colors[theme.backgroundHighlight])
- term.clearLine()
- term.write(err)
- sleep(1.6)
- return contents
- end
- local new = {}
- local level = 0
- for k, v in pairs(contents) do
- local incrLevel = false
- local foundIncr = false
- for _, incr in pairs(increment) do
- if v:find(incr) and not isIn(k, v:find(incr)) then
- incrLevel = true
- end
- if v:find(incr:sub(1, -2)) and not isIn(k, v:find(incr)) then
- foundIncr = true
- end
- end
- local decrLevel = false
- if not incrLevel then
- for _, decr in pairs(decrement) do
- if v:find(decr) and not isIn(k, v:find(decr)) and not foundIncr then
- level = math.max(0, level - 1)
- decrLevel = true
- end
- end
- end
- if not decrLevel then
- for _, sp in pairs(special) do
- if v:find(sp) and not isIn(k, v:find(sp)) then
- incrLevel = true
- level = math.max(0, level - 1)
- end
- end
- end
- new[k] = string.rep(" ", level * tabWidth) .. v
- if incrLevel then level = level + 1 end
- end
- return new
- end
- -- -------- Menu
- local menu = {
- [1] = {"File",
- -- "About",
- -- "Settings",
- -- "",
- "New File ^+N",
- "Open File ^+O",
- "Save File ^+S",
- "Close ^+W",
- "Print ^+P",
- "Quit ^+Q"
- }, [2] = {"Edit",
- "Cut Line ^+X",
- "Copy Line ^+C",
- "Paste Line ^+V",
- "Delete Line",
- "Clear Line"
- }, [3] = {"Functions",
- "Go To Line ^+G",
- "Re-Indent ^+I",
- "Set Syntax ^+E",
- "Start of Line ^+<",
- "End of Line ^+>"
- }, [4] = {"Run",
- "Run Program ^+R",
- "Run w/ Args ^+Shift+R"
- }
- }
- local shortcuts = {
- -- File
- ["ctrl n"] = "New File ^+N",
- ["ctrl o"] = "Open File ^+O",
- ["ctrl s"] = "Save File ^+S",
- ["ctrl w"] = "Close ^+W",
- ["ctrl p"] = "Print ^+P",
- ["ctrl q"] = "Quit ^+Q",
- -- Edit
- ["ctrl x"] = "Cut Line ^+X",
- ["ctrl c"] = "Copy Line ^+C",
- ["ctrl v"] = "Paste Line ^+V",
- -- Functions
- ["ctrl g"] = "Go To Line ^+G",
- ["ctrl i"] = "Re-Indent ^+I",
- ["ctrl e"] = "Set Syntax ^+E",
- ["ctrl 203"] = "Start of Line ^+<",
- ["ctrl 205"] = "End of Line ^+>",
- -- Run
- ["ctrl r"] = "Run Program ^+R",
- ["ctrl shift r"] = "Run w/ Args ^+Shift+R"
- }
- local menuFunctions = {
- -- File
- -- ["About"] = function() end,
- -- ["Settings"] = function() end,
- ["New File ^+N"] = function(path, lines) saveFile(path, lines) return "new" end,
- ["Open File ^+O"] = function(path, lines) saveFile(path, lines) return "open" end,
- ["Save File ^+S"] = function(path, lines) saveFile(path, lines) end,
- ["Close ^+W"] = function(path, lines) saveFile(path, lines) return "menu" end,
- ["Print ^+P"] = function(path, lines) saveFile(path, lines) return nil end,
- ["Quit ^+Q"] = function(path, lines) saveFile(path, lines) return "exit" end,
- -- Edit
- ["Cut Line ^+X"] = function(path, lines, y)
- clipboard = lines[y] table.remove(lines, y) return nil, lines end,
- ["Copy Line ^+C"] = function(path, lines, y) clipboard = lines[y] end,
- ["Paste Line ^+V"] = function(path, lines, y)
- if clipboard then table.insert(lines, y, clipboard) end return nil, lines end,
- ["Delete Line"] = function(path, lines, y) table.remove(lines, y) return nil, lines end,
- ["Clear Line"] = function(path, lines, y) lines[y] = "" return nil, lines, "cursor" end,
- -- Functions
- ["Go To Line ^+G"] = function() return nil, "go to", goto() end,
- ["Re-Indent ^+I"] = function(path, lines)
- local a = reindent(lines) saveFile(path, lines) return nil, a
- end,
- ["Set Syntax ^+E"] = function(path, lines)
- setsyntax()
- if curLanguage == languages.brainfuck and lines[1] ~= "-- Syntax: Brainfuck" then
- table.insert(lines, 1, "-- Syntax: Brainfuck")
- return nil, lines
- end
- end,
- ["Start of Line ^+<"] = function() os.queueEvent("key", 199) end,
- ["End of Line ^+>"] = function() os.queueEvent("key", 207) end,
- -- Run
- ["Run Program ^+R"] = function(path, lines)
- saveFile(path, lines)
- return nil, run(path, lines, false)
- end,
- ["Run w/ Args ^+Shift+R"] = function(path, lines)
- saveFile(path, lines)
- return nil, run(path, lines, true)
- end,
- }
- local function drawMenu(open)
- term.setCursorPos(1, 1)
- term.setTextColor(colors[theme.textColor])
- term.setBackgroundColor(colors[theme.backgroundHighlight])
- term.clearLine()
- local curX = 0
- for _, v in pairs(menu) do
- term.setCursorPos(3 + curX, 1)
- term.write(v[1])
- curX = curX + v[1]:len() + 3
- end
- if open then
- local it = {}
- local x = 1
- for _, v in pairs(menu) do
- if open == v[1] then
- it = v
- break
- end
- x = x + v[1]:len() + 3
- end
- x = x + 1
- local items = {}
- for i = 2, #it do
- table.insert(items, it[i])
- end
- local len = 1
- for _, v in pairs(items) do if v:len() + 2 > len then len = v:len() + 2 end end
- for i, v in ipairs(items) do
- term.setCursorPos(x, i + 1)
- term.write(string.rep(" ", len))
- term.setCursorPos(x + 1, i + 1)
- term.write(v)
- end
- term.setCursorPos(x, #items + 2)
- term.write(string.rep(" ", len))
- return items, len
- end
- end
- local function triggerMenu(cx, cy)
- -- Determine clicked menu
- local curX = 0
- local open = nil
- for _, v in pairs(menu) do
- if cx >= curX + 3 and cx <= curX + v[1]:len() + 2 then
- open = v[1]
- break
- end
- curX = curX + v[1]:len() + 3
- end
- local menux = curX + 2
- if not open then return false end
- -- Flash menu item
- term.setCursorBlink(false)
- term.setCursorPos(menux, 1)
- term.setBackgroundColor(colors[theme.background])
- term.write(string.rep(" ", open:len() + 2))
- term.setCursorPos(menux + 1, 1)
- term.write(open)
- sleep(0.1)
- local items, len = drawMenu(open)
- local ret = true
- -- Pull events on menu
- local ox, oy = term.getCursorPos()
- while type(ret) ~= "string" do
- local e, but, x, y = os.pullEvent()
- if e == "mouse_click" then
- -- If clicked outside menu
- if x < menux - 1 or x > menux + len - 1 then break
- elseif y > #items + 2 then break
- elseif y == 1 then break end
- for i, v in ipairs(items) do
- if y == i + 1 and x >= menux and x <= menux + len - 2 then
- -- Flash when clicked
- term.setCursorPos(menux, y)
- term.setBackgroundColor(colors[theme.background])
- term.write(string.rep(" ", len))
- term.setCursorPos(menux + 1, y)
- term.write(v)
- sleep(0.1)
- drawMenu(open)
- -- Return item
- ret = v
- break
- end
- end
- end
- end
- term.setCursorPos(ox, oy)
- term.setCursorBlink(true)
- return ret
- end
- -- -------- Editing
- local standardsCompletions = {
- "if%s+.+%s+then%s*$",
- "for%s+.+%s+do%s*$",
- "while%s+.+%s+do%s*$",
- "repeat%s*$",
- "function%s+[a-zA-Z_0-9]?(.*)%s*$",
- "=%s*function%s*(.*)%s*$",
- "else%s*$",
- "elseif%s+.+%s+then%s*$"
- }
- local liveCompletions = {
- ["("] = ")",
- ["{"] = "}",
- ["["] = "]",
- ["\""] = "\"",
- ["'"] = "'",
- }
- local x, y = 0, 0
- local edw, edh = 0, h - 1
- local offx, offy = 0, 1
- local scrollx, scrolly = 0, 0
- local lines = {}
- local liveErr = curLanguage.parseError(nil)
- local displayCode = true
- local lastEventClock = os.clock()
- local function attemptToHighlight(line, regex, col)
- local match = string.match(line, regex)
- if match then
- if type(col) == "number" then term.setTextColor(col)
- elseif type(col) == "function" then term.setTextColor(col(match)) end
- term.write(match)
- term.setTextColor(colors[theme.textColor])
- return line:sub(match:len() + 1, -1)
- end
- return nil
- end
- local function writeHighlighted(line)
- if curLanguage == languages.lua then
- while line:len() > 0 do
- line = attemptToHighlight(line, "^%-%-%[%[.-%]%]", colors[theme.comment]) or
- attemptToHighlight(line, "^%-%-.*", colors[theme.comment]) or
- attemptToHighlight(line, "^\".*[^\\]\"", colors[theme.string]) or
- attemptToHighlight(line, "^\'.*[^\\]\'", colors[theme.string]) or
- attemptToHighlight(line, "^%[%[.-%]%]", colors[theme.string]) or
- attemptToHighlight(line, "^[%w_]+", function(match)
- if curLanguage.keywords[match] then
- return colors[theme[curLanguage.keywords[match]]]
- end
- return colors[theme.textColor]
- end) or
- attemptToHighlight(line, "^[^%w_]", colors[theme.textColor])
- end
- else term.write(line) end
- end
- local function draw()
- -- Menu
- term.setTextColor(colors[theme.textColor])
- term.setBackgroundColor(colors[theme.editorBackground])
- term.clear()
- drawMenu()
- -- Line numbers
- offx, offy = tostring(#lines):len() + 1, 1
- edw, edh = w - offx, h - 1
- -- Draw text
- for i = 1, edh do
- local a = lines[scrolly + i]
- if a then
- local ln = string.rep(" ", offx - 1 - tostring(scrolly + i):len()) .. tostring(scrolly + i)
- local l = a:sub(scrollx + 1, edw + scrollx + 1)
- ln = ln .. ":"
- if liveErr.line == scrolly + i then ln = string.rep(" ", offx - 2) .. "!:" end
- term.setCursorPos(1, i + offy)
- term.setBackgroundColor(colors[theme.editorBackground])
- if scrolly + i == y then
- if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then
- term.setBackgroundColor(colors[theme.editorErrorHighlight])
- else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
- term.clearLine()
- elseif scrolly + i == liveErr.line then
- term.setBackgroundColor(colors[theme.editorError])
- term.clearLine()
- end
- term.setCursorPos(1 - scrollx + offx, i + offy)
- if scrolly + i == y then
- if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then
- term.setBackgroundColor(colors[theme.editorErrorHighlight])
- else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
- elseif scrolly + i == liveErr.line then term.setBackgroundColor(colors[theme.editorError])
- else term.setBackgroundColor(colors[theme.editorBackground]) end
- if scrolly + i == liveErr.line then
- if displayCode then term.write(a)
- else term.write(liveErr.display) end
- else writeHighlighted(a) end
- term.setCursorPos(1, i + offy)
- if scrolly + i == y then
- if scrolly + i == liveErr.line and os.clock() - lastEventClock > 3 then
- term.setBackgroundColor(colors[theme.editorError])
- else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end
- elseif scrolly + i == liveErr.line then
- term.setBackgroundColor(colors[theme.editorErrorHighlight])
- else term.setBackgroundColor(colors[theme.editorLineNumbers]) end
- term.write(ln)
- end
- end
- term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
- end
- local function drawLine(...)
- local ls = {...}
- offx = tostring(#lines):len() + 1
- for _, ly in pairs(ls) do
- local a = lines[ly]
- if a then
- local ln = string.rep(" ", offx - 1 - tostring(ly):len()) .. tostring(ly)
- local l = a:sub(scrollx + 1, edw + scrollx + 1)
- ln = ln .. ":"
- if liveErr.line == ly then ln = string.rep(" ", offx - 2) .. "!:" end
- term.setCursorPos(1, (ly - scrolly) + offy)
- term.setBackgroundColor(colors[theme.editorBackground])
- if ly == y then
- if ly == liveErr.line and os.clock() - lastEventClock > 3 then
- term.setBackgroundColor(colors[theme.editorErrorHighlight])
- else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
- elseif ly == liveErr.line then
- term.setBackgroundColor(colors[theme.editorError])
- end
- term.clearLine()
- term.setCursorPos(1 - scrollx + offx, (ly - scrolly) + offy)
- if ly == y then
- if ly == liveErr.line and os.clock() - lastEventClock > 3 then
- term.setBackgroundColor(colors[theme.editorErrorHighlight])
- else term.setBackgroundColor(colors[theme.editorLineHightlight]) end
- elseif ly == liveErr.line then term.setBackgroundColor(colors[theme.editorError])
- else term.setBackgroundColor(colors[theme.editorBackground]) end
- if ly == liveErr.line then
- if displayCode then term.write(a)
- else term.write(liveErr.display) end
- else writeHighlighted(a) end
- term.setCursorPos(1, (ly - scrolly) + offy)
- if ly == y then
- if ly == liveErr.line and os.clock() - lastEventClock > 3 then
- term.setBackgroundColor(colors[theme.editorError])
- else term.setBackgroundColor(colors[theme.editorLineNumbersHighlight]) end
- elseif ly == liveErr.line then
- term.setBackgroundColor(colors[theme.editorErrorHighlight])
- else term.setBackgroundColor(colors[theme.editorLineNumbers]) end
- term.write(ln)
- end
- end
- term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
- end
- local function cursorLoc(x, y, force)
- local sx, sy = x - scrollx, y - scrolly
- local redraw = false
- if sx < 1 then
- scrollx = x - 1
- sx = 1
- redraw = true
- elseif sx > edw then
- scrollx = x - edw
- sx = edw
- redraw = true
- end if sy < 1 then
- scrolly = y - 1
- sy = 1
- redraw = true
- elseif sy > edh then
- scrolly = y - edh
- sy = edh
- redraw = true
- end if redraw or force then draw() end
- term.setCursorPos(sx + offx, sy + offy)
- end
- local function executeMenuItem(a, path)
- if type(a) == "string" and menuFunctions[a] then
- local opt, nl, gtln = menuFunctions[a](path, lines, y)
- if type(opt) == "string" then term.setCursorBlink(false) return opt end
- if type(nl) == "table" then
- if #lines < 1 then table.insert(lines, "") end
- y = math.min(y, #lines)
- x = math.min(x, lines[y]:len() + 1)
- lines = nl
- elseif type(nl) == "string" then
- if nl == "go to" and gtln then
- x, y = 1, math.min(#lines, gtln)
- cursorLoc(x, y)
- end
- end
- end
- term.setCursorBlink(true)
- draw()
- term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
- end
- local function edit(path)
- -- Variables
- x, y = 1, 1
- offx, offy = 0, 1
- scrollx, scrolly = 0, 0
- lines = loadFile(path)
- if not lines then return "menu" end
- -- Enable brainfuck
- if lines[1] == "-- Syntax: Brainfuck" then
- curLanguage = languages.brainfuck
- end
- -- Clocks
- local autosaveClock = os.clock()
- local scrollClock = os.clock() -- To prevent redraw flicker
- local liveErrorClock = os.clock()
- local hasScrolled = false
- -- Draw
- draw()
- term.setCursorPos(x + offx, y + offy)
- term.setCursorBlink(true)
- -- Main loop
- local tid = os.startTimer(3)
- while true do
- local e, key, cx, cy = os.pullEvent()
- if e == "key" and allowEditorEvent then
- if key == 200 and y > 1 then
- -- Up
- x, y = math.min(x, lines[y - 1]:len() + 1), y - 1
- drawLine(y, y + 1)
- cursorLoc(x, y)
- elseif key == 208 and y < #lines then
- -- Down
- x, y = math.min(x, lines[y + 1]:len() + 1), y + 1
- drawLine(y, y - 1)
- cursorLoc(x, y)
- elseif key == 203 and x > 1 then
- -- Left
- x = x - 1
- local force = false
- if y - scrolly + offy < offy + 1 then force = true end
- cursorLoc(x, y, force)
- elseif key == 205 and x < lines[y]:len() + 1 then
- -- Right
- x = x + 1
- local force = false
- if y - scrolly + offy < offy + 1 then force = true end
- cursorLoc(x, y, force)
- elseif (key == 28 or key == 156) and (displayCode and true or y + scrolly - 1 ==
- liveErr.line) then
- -- Enter
- local f = nil
- for _, v in pairs(standardsCompletions) do
- if lines[y]:find(v) then f = v end
- end
- local _, spaces = lines[y]:find("^[ ]+")
- if not spaces then spaces = 0 end
- if f then
- table.insert(lines, y + 1, string.rep(" ", spaces + 2))
- if not f:find("else", 1, true) and not f:find("elseif", 1, true) then
- table.insert(lines, y + 2, string.rep(" ", spaces) ..
- (f:find("repeat", 1, true) and "until " or f:find("{", 1, true) and "}" or
- "end"))
- end
- x, y = spaces + 3, y + 1
- cursorLoc(x, y, true)
- else
- local oldLine = lines[y]
- lines[y] = lines[y]:sub(1, x - 1)
- table.insert(lines, y + 1, string.rep(" ", spaces) .. oldLine:sub(x, -1))
- x, y = spaces + 1, y + 1
- cursorLoc(x, y, true)
- end
- elseif key == 14 and (displayCode and true or y + scrolly - 1 == liveErr.line) then
- -- Backspace
- if x > 1 then
- local f = false
- for k, v in pairs(liveCompletions) do
- if lines[y]:sub(x - 1, x - 1) == k then f = true end
- end
- lines[y] = lines[y]:sub(1, x - 2) .. lines[y]:sub(x + (f and 1 or 0), -1)
- drawLine(y)
- x = x - 1
- cursorLoc(x, y)
- elseif y > 1 then
- local prevLen = lines[y - 1]:len() + 1
- lines[y - 1] = lines[y - 1] .. lines[y]
- table.remove(lines, y)
- x, y = prevLen, y - 1
- cursorLoc(x, y, true)
- end
- elseif key == 199 then
- -- Home
- x = 1
- local force = false
- if y - scrolly + offy < offy + 1 then force = true end
- cursorLoc(x, y, force)
- elseif key == 207 then
- -- End
- x = lines[y]:len() + 1
- local force = false
- if y - scrolly + offy < offy + 1 then force = true end
- cursorLoc(x, y, force)
- elseif key == 211 and (displayCode and true or y + scrolly - 1 == liveErr.line) then
- -- Forward Delete
- if x < lines[y]:len() + 1 then
- lines[y] = lines[y]:sub(1, x - 1) .. lines[y]:sub(x + 1)
- local force = false
- if y - scrolly + offy < offy + 1 then force = true end
- drawLine(y)
- cursorLoc(x, y, force)
- elseif y < #lines then
- lines[y] = lines[y] .. lines[y + 1]
- table.remove(lines, y + 1)
- draw()
- cursorLoc(x, y)
- end
- elseif key == 15 and (displayCode and true or y + scrolly - 1 == liveErr.line) then
- -- Tab
- lines[y] = string.rep(" ", tabWidth) .. lines[y]
- x = x + 2
- local force = false
- if y - scrolly + offy < offy + 1 then force = true end
- drawLine(y)
- cursorLoc(x, y, force)
- elseif key == 201 then
- -- Page up
- y = math.min(math.max(y - edh, 1), #lines)
- x = math.min(lines[y]:len() + 1, x)
- cursorLoc(x, y, true)
- elseif key == 209 then
- -- Page down
- y = math.min(math.max(y + edh, 1), #lines)
- x = math.min(lines[y]:len() + 1, x)
- cursorLoc(x, y, true)
- end
- elseif e == "char" and allowEditorEvent and (displayCode and true or
- y + scrolly - 1 == liveErr.line) then
- local shouldIgnore = false
- for k, v in pairs(liveCompletions) do
- if key == v and lines[y]:find(k, 1, true) and lines[y]:sub(x, x) == v then
- shouldIgnore = true
- end
- end
- local addOne = false
- if not shouldIgnore then
- for k, v in pairs(liveCompletions) do
- if key == k and lines[y]:sub(x, x) ~= k then key = key .. v addOne = true end
- end
- lines[y] = lines[y]:sub(1, x - 1) .. key .. lines[y]:sub(x, -1)
- end
- x = x + (addOne and 1 or key:len())
- local force = false
- if y - scrolly + offy < offy + 1 then force = true end
- drawLine(y)
- cursorLoc(x, y, force)
- elseif e == "mouse_click" and key == 1 then
- if cy > 1 then
- if cx <= offx and cy - offy == liveErr.line - scrolly then
- displayCode = not displayCode
- drawLine(liveErr.line)
- else
- local oldy = y
- y = math.min(math.max(scrolly + cy - offy, 1), #lines)
- x = math.min(math.max(scrollx + cx - offx, 1), lines[y]:len() + 1)
- if oldy ~= y then drawLine(oldy, y) end
- cursorLoc(x, y)
- end
- else
- local a = triggerMenu(cx, cy)
- if a then
- local opt = executeMenuItem(a, path)
- if opt then return opt end
- end
- end
- elseif e == "shortcut" then
- local a = shortcuts[key .. " " .. cx]
- if a then
- local parent = nil
- local curx = 0
- for i, mv in ipairs(menu) do
- for _, iv in pairs(mv) do
- if iv == a then
- parent = menu[i][1]
- break
- end
- end
- if parent then break end
- curx = curx + mv[1]:len() + 3
- end
- local menux = curx + 2
- -- Flash menu item
- term.setCursorBlink(false)
- term.setCursorPos(menux, 1)
- term.setBackgroundColor(colors[theme.background])
- term.write(string.rep(" ", parent:len() + 2))
- term.setCursorPos(menux + 1, 1)
- term.write(parent)
- sleep(0.1)
- drawMenu()
- -- Execute item
- local opt = executeMenuItem(a, path)
- if opt then return opt end
- end
- elseif e == "mouse_scroll" then
- if key == -1 and scrolly > 0 then
- scrolly = scrolly - 1
- if os.clock() - scrollClock > 0.0005 then
- draw()
- term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
- end
- scrollClock = os.clock()
- hasScrolled = true
- elseif key == 1 and scrolly < #lines - edh then
- scrolly = scrolly + 1
- if os.clock() - scrollClock > 0.0005 then
- draw()
- term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
- end
- scrollClock = os.clock()
- hasScrolled = true
- end
- elseif e == "timer" and key == tid then
- drawLine(y)
- tid = os.startTimer(3)
- end
- -- Draw
- if hasScrolled and os.clock() - scrollClock > 0.1 then
- draw()
- term.setCursorPos(x - scrollx + offx, y - scrolly + offy)
- hasScrolled = false
- end
- -- Autosave
- if os.clock() - autosaveClock > autosaveInterval then
- saveFile(path, lines)
- autosaveClock = os.clock()
- end
- -- Errors
- if os.clock() - liveErrorClock > 1 then
- local prevLiveErr = liveErr
- liveErr = curLanguage.parseError(nil)
- local code = ""
- for _, v in pairs(lines) do code = code .. v .. "\n" end
- liveErr = curLanguage.getCompilerErrors(code)
- liveErr.line = math.min(liveErr.line - 2, #lines)
- if liveErr ~= prevLiveErr then draw() end
- liveErrorClock = os.clock()
- end
- end
- return "menu"
- end
- -- -------- Open File
- local function newFile()
- local wid = w - 13
- -- Get name
- title("Lua IDE - New File")
- local name = centerRead(wid, "/")
- if not name or name == "" then return "menu" end
- name = "/" .. name
- -- Clear
- title("Lua IDE - New File")
- term.setTextColor(colors[theme.textColor])
- term.setBackgroundColor(colors[theme.promptHighlight])
- for i = 8, 10 do
- term.setCursorPos(w/2 - wid/2, i)
- term.write(string.rep(" ", wid))
- end
- term.setCursorPos(1, 9)
- if fs.isDir(name) then
- centerPrint("Cannot Edit a Directory!")
- sleep(1.6)
- return "menu"
- elseif fs.exists(name) then
- centerPrint("File Already Exists!")
- local opt = prompt({{"Open", w/2 - 9, 14}, {"Cancel", w/2 + 2, 14}}, "horizontal")
- if opt == "Open" then return "edit", name
- elseif opt == "Cancel" then return "menu" end
- else return "edit", name end
- end
- local function openFile()
- local wid = w - 13
- -- Get name
- title("Lua IDE - Open File")
- local name = centerRead(wid, "/")
- if not name or name == "" then return "menu" end
- name = "/" .. name
- -- Clear
- title("Lua IDE - New File")
- term.setTextColor(colors[theme.textColor])
- term.setBackgroundColor(colors[theme.promptHighlight])
- for i = 8, 10 do
- term.setCursorPos(w/2 - wid/2, i)
- term.write(string.rep(" ", wid))
- end
- term.setCursorPos(1, 9)
- if fs.isDir(name) then
- centerPrint("Cannot Open a Directory!")
- sleep(1.6)
- return "menu"
- elseif not fs.exists(name) then
- centerPrint("File Doesn't Exist!")
- local opt = prompt({{"Create", w/2 - 11, 14}, {"Cancel", w/2 + 2, 14}}, "horizontal")
- if opt == "Create" then return "edit", name
- elseif opt == "Cancel" then return "menu" end
- else return "edit", name end
- end
- -- -------- Settings
- local function update()
- local function draw(status)
- title("LuaIDE - Update")
- term.setBackgroundColor(colors[theme.prompt])
- term.setTextColor(colors[theme.textColor])
- for i = 8, 10 do
- term.setCursorPos(w/2 - (status:len() + 4), i)
- write(string.rep(" ", status:len() + 4))
- end
- term.setCursorPos(w/2 - (status:len() + 4), 9)
- term.write(" - " .. status .. " ")
- term.setBackgroundColor(colors[theme.errHighlight])
- for i = 8, 10 do
- term.setCursorPos(w/2 + 2, i)
- term.write(string.rep(" ", 10))
- end
- term.setCursorPos(w/2 + 2, 9)
- term.write(" > Cancel ")
- end
- if not http then
- draw("HTTP API Disabled!")
- sleep(1.6)
- return "settings"
- end
- draw("Updating...")
- local tID = os.startTimer(10)
- http.request(updateURL)
- while true do
- local e, but, x, y = os.pullEvent()
- if (e == "key" and but == 28) or
- (e == "mouse_click" and x >= w/2 + 2 and x <= w/2 + 12 and y == 9) then
- draw("Cancelled")
- sleep(1.6)
- break
- elseif e == "http_success" and but == updateURL then
- local new = x.readAll()
- local curf = io.open(ideLocation, "r")
- local cur = curf:read("*a")
- curf:close()
- if cur ~= new then
- draw("Update Found")
- sleep(1.6)
- local f = io.open(ideLocation, "w")
- f:write(new)
- f:close()
- draw("Click to Exit")
- while true do
- local e = os.pullEvent()
- if e == "mouse_click" or (not isAdvanced() and e == "key") then break end
- end
- return "exit"
- else
- draw("No Updates Found!")
- sleep(1.6)
- break
- end
- elseif e == "http_failure" or (e == "timer" and but == tID) then
- draw("Update Failed!")
- sleep(1.6)
- break
- end
- end
- return "settings"
- end
- local function changeTheme()
- title("LuaIDE - Theme")
- if isAdvanced() then
- local disThemes = {"Back"}
- for _, v in pairs(availableThemes) do table.insert(disThemes, v[1]) end
- local t = scrollingPrompt(disThemes)
- local url = nil
- for _, v in pairs(availableThemes) do if v[1] == t then url = v[2] end end
- if not url then return "settings" end
- if t == "Dawn (Default)" then
- term.setBackgroundColor(colors[theme.backgroundHighlight])
- term.setCursorPos(3, 3)
- term.clearLine()
- term.write("LuaIDE - Loaded Theme!")
- sleep(1.6)
- fs.delete(themeLocation)
- theme = defaultTheme
- return "menu"
- end
- term.setBackgroundColor(colors[theme.backgroundHighlight])
- term.setCursorPos(3, 3)
- term.clearLine()
- term.write("LuaIDE - Downloading...")
- fs.delete("/.LuaIDE_temp_theme_file")
- download(url, "/.LuaIDE_temp_theme_file")
- local a = loadTheme("/.LuaIDE_temp_theme_file")
- term.setCursorPos(3, 3)
- term.clearLine()
- if a then
- term.write("LuaIDE - Loaded Theme!")
- fs.delete(themeLocation)
- fs.move("/.LuaIDE_temp_theme_file", themeLocation)
- theme = a
- sleep(1.6)
- return "menu"
- end
- term.write("LuaIDE - Could Not Load Theme!")
- fs.delete("/.LuaIDE_temp_theme_file")
- sleep(1.6)
- return "settings"
- else
- term.setCursorPos(1, 8)
- centerPrint("Themes are not available on")
- centerPrint("normal computers!")
- end
- end
- local function settings()
- title("LuaIDE - Settings")
- local opt = prompt({{"Change Theme", w/2 - 17, 8}, {"Return to Menu", w/2 - 22, 13},
- {"Check for Updates", w/2 + 2, 8}, {"Exit IDE", w/2 + 2, 13, bg = colors[theme.err],
- highlight = colors[theme.errHighlight]}}, "vertical", true)
- if opt == "Change Theme" then return changeTheme()
- elseif opt == "Check for Updates" then return update()
- elseif opt == "Return to Menu" then return "menu"
- elseif opt == "Exit IDE" then return "exit" end
- end
- -- -------- Menu
- local function menu()
- title("Welcome to LuaIDE " .. version)
- local opt = prompt({{"New File", w/2 - 13, 8}, {"Open File", w/2 - 14, 13},
- {"Settings", w/2 + 2, 8}, {"Exit IDE", w/2 + 2, 13, bg = colors[theme.err],
- highlight = colors[theme.errHighlight]}}, "vertical", true)
- if opt == "New File" then return "new"
- elseif opt == "Open File" then return "open"
- elseif opt == "Settings" then return "settings"
- elseif opt == "Exit IDE" then return "exit" end
- end
- -- -------- Main
- local function main(arguments)
- local opt, data = "menu", nil
- -- Check arguments
- if type(arguments) == "table" and #arguments > 0 then
- local f = "/" .. shell.resolve(arguments[1])
- if fs.isDir(f) then print("Cannot edit a directory.") end
- opt, data = "edit", f
- end
- -- Main run loop
- while true do
- -- Menu
- if opt == "menu" then opt = menu() end
- -- Other
- if opt == "new" then opt, data = newFile()
- elseif opt == "open" then opt, data = openFile()
- elseif opt == "settings" then opt = settings()
- end if opt == "exit" then break end
- -- Edit
- if opt == "edit" and data then opt = edit(data) end
- end
- end
- -- Load Theme
- if fs.exists(themeLocation) then theme = loadTheme(themeLocation) end
- if not theme and isAdvanced() then theme = defaultTheme
- elseif not theme then theme = normalTheme end
- -- Run
- local _, err = pcall(function()
- parallel.waitForAny(function() main(args) end, monitorKeyboardShortcuts)
- end)
- -- Catch errors
- if err and not err:find("Terminated") then
- term.setCursorBlink(false)
- title("LuaIDE - Crash! D:")
- term.setBackgroundColor(colors[theme.err])
- for i = 6, 8 do
- term.setCursorPos(5, i)
- term.write(string.rep(" ", 36))
- end
- term.setCursorPos(6, 7)
- term.write("LuaIDE Has Crashed! D:")
- term.setBackgroundColor(colors[theme.background])
- term.setCursorPos(2, 10)
- print(err)
- term.setBackgroundColor(colors[theme.prompt])
- local _, cy = term.getCursorPos()
- for i = cy + 1, cy + 4 do
- term.setCursorPos(5, i)
- term.write(string.rep(" ", 36))
- end
- term.setCursorPos(6, cy + 2)
- term.write("Please report this error to")
- term.setCursorPos(6, cy + 3)
- term.write("GravityScore! ")
- term.setBackgroundColor(colors[theme.background])
- if isAdvanced() then centerPrint("Click to Exit...", h - 1)
- else centerPrint("Press Any Key to Exit...", h - 1) end
- while true do
- local e = os.pullEvent()
- if e == "mouse_click" or (not isAdvanced() and e == "key") then break end
- end
- -- Prevent key from being shown
- os.queueEvent(event_distract)
- os.pullEvent()
- end
- -- Exit
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1, 1)
- centerPrint("Thank You for Using Lua IDE " .. version)
- centerPrint("Made by GravityScore")
- sleep(1)
- end
- function oeed_sketch()
- if OneOS then
- --running under OneOS
- OneOS.ToolBarColour = colours.grey
- OneOS.ToolBarTextColour = colours.white
- end
- colours.transparent = -1
- colors.transparent = -1
- --APIS--
- --This is my drawing API, is is pretty much identical to what drives OneOS, PearOS, etc.
- local _w, _h = term.getSize()
- local round = function(num, idp)
- local mult = 10^(idp or 0)
- return math.floor(num * mult + 0.5) / mult
- end
- Clipboard = {
- Content = nil,
- Type = nil,
- IsCut = false,
- Empty = function()
- Clipboard.Content = nil
- Clipboard.Type = nil
- Clipboard.IsCut = false
- end,
- isEmpty = function()
- return Clipboard.Content == nil
- end,
- Copy = function(content, _type)
- Clipboard.Content = content
- Clipboard.Type = _type or 'generic'
- Clipboard.IsCut = false
- end,
- Cut = function(content, _type)
- Clipboard.Content = content
- Clipboard.Type = _type or 'generic'
- Clipboard.IsCut = true
- end,
- Paste = function()
- local c, t = Clipboard.Content, Clipboard.Type
- if Clipboard.IsCut then
- Clipboard.Empty()
- end
- return c, t
- end
- }
- if OneOS and OneOS.Clipboard then
- Clipboard = OneOS.Clipboard
- end
- Drawing = {
- Screen = {
- Width = _w,
- Height = _h
- },
- DrawCharacters = function (x, y, characters, textColour,bgColour)
- Drawing.WriteStringToBuffer(x, y, characters, textColour, bgColour)
- end,
- DrawBlankArea = function (x, y, w, h, colour)
- Drawing.DrawArea (x, y, w, h, " ", 1, colour)
- end,
- DrawArea = function (x, y, w, h, character, textColour, bgColour)
- --width must be greater than 1, other wise we get a stack overflow
- if w < 0 then
- w = w * -1
- elseif w == 0 then
- w = 1
- end
- for ix = 1, w do
- local currX = x + ix - 1
- for iy = 1, h do
- local currY = y + iy - 1
- Drawing.WriteToBuffer(currX, currY, character, textColour, bgColour)
- end
- end
- end,
- DrawImage = function(_x,_y,tImage, w, h)
- if tImage then
- for y = 1, h do
- if not tImage[y] then
- break
- end
- for x = 1, w do
- if not tImage[y][x] then
- break
- end
- local bgColour = tImage[y][x]
- local textColour = tImage.textcol[y][x] or colours.white
- local char = tImage.text[y][x]
- Drawing.WriteToBuffer(x+_x-1, y+_y-1, char, textColour, bgColour)
- end
- end
- elseif w and h then
- Drawing.DrawBlankArea(x, y, w, h, colours.green)
- end
- end,
- --using .nft
- LoadImage = function(path)
- local image = {
- text = {},
- textcol = {}
- }
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if _fs.exists(path) then
- local _open = io.open
- if OneOS then
- _open = OneOS.IO.open
- end
- local file = _open(path, "r")
- local sLine = file:read()
- local num = 1
- while sLine do
- table.insert(image, num, {})
- table.insert(image.text, num, {})
- table.insert(image.textcol, num, {})
- --As we're no longer 1-1, we keep track of what index to write to
- local writeIndex = 1
- --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour
- local bgNext, fgNext = false, false
- --The current background and foreground colours
- local currBG, currFG = nil,nil
- for i=1,#sLine do
- local nextChar = string.sub(sLine, i, i)
- if nextChar:byte() == 30 then
- bgNext = true
- elseif nextChar:byte() == 31 then
- fgNext = true
- elseif bgNext then
- currBG = Drawing.GetColour(nextChar)
- bgNext = false
- elseif fgNext then
- currFG = Drawing.GetColour(nextChar)
- fgNext = false
- else
- if nextChar ~= " " and currFG == nil then
- currFG = colours.white
- end
- image[num][writeIndex] = currBG
- image.textcol[num][writeIndex] = currFG
- image.text[num][writeIndex] = nextChar
- writeIndex = writeIndex + 1
- end
- end
- num = num+1
- sLine = file:read()
- end
- file:close()
- end
- return image
- end,
- DrawCharactersCenter = function(x, y, w, h, characters, textColour,bgColour)
- w = w or Drawing.Screen.Width
- h = h or Drawing.Screen.Height
- x = x or 0
- y = y or 0
- x = math.ceil((w - #characters) / 2) + x
- y = math.floor(h / 2) + y
- Drawing.DrawCharacters(x, y, characters, textColour, bgColour)
- end,
- GetColour = function(hex)
- if hex == ' ' then
- return colours.transparent
- end
- local value = tonumber(hex, 16)
- if not value then return nil end
- value = math.pow(2,value)
- return value
- end,
- Clear = function (_colour)
- _colour = _colour or colours.black
- Drawing.ClearBuffer()
- Drawing.DrawBlankArea(1, 1, Drawing.Screen.Width, Drawing.Screen.Height, _colour)
- end,
- Buffer = {},
- BackBuffer = {},
- DrawBuffer = function()
- for y,row in pairs(Drawing.Buffer) do
- for x,pixel in pairs(row) do
- local shouldDraw = true
- local hasBackBuffer = true
- if Drawing.BackBuffer[y] == nil or Drawing.BackBuffer[y][x] == nil or #Drawing.BackBuffer[y][x] ~= 3 then
- hasBackBuffer = false
- end
- if hasBackBuffer and Drawing.BackBuffer[y][x][1] == Drawing.Buffer[y][x][1] and Drawing.BackBuffer[y][x][2] == Drawing.Buffer[y][x][2] and Drawing.BackBuffer[y][x][3] == Drawing.Buffer[y][x][3] then
- shouldDraw = false
- end
- if shouldDraw then
- term.setBackgroundColour(pixel[3])
- term.setTextColour(pixel[2])
- term.setCursorPos(x, y)
- term.write(pixel[1])
- end
- end
- end
- Drawing.BackBuffer = Drawing.Buffer
- Drawing.Buffer = {}
- term.setCursorPos(1,1)
- end,
- ClearBuffer = function()
- Drawing.Buffer = {}
- end,
- WriteStringToBuffer = function (x, y, characters, textColour,bgColour)
- for i = 1, #characters do
- local character = characters:sub(i,i)
- Drawing.WriteToBuffer(x + i - 1, y, character, textColour, bgColour)
- end
- end,
- WriteToBuffer = function(x, y, character, textColour,bgColour)
- x = round(x)
- y = round(y)
- if bgColour == colours.transparent then
- Drawing.Buffer[y] = Drawing.Buffer[y] or {}
- Drawing.Buffer[y][x] = Drawing.Buffer[y][x] or {"", colours.white, colours.black}
- Drawing.Buffer[y][x][1] = character
- Drawing.Buffer[y][x][2] = textColour
- else
- Drawing.Buffer[y] = Drawing.Buffer[y] or {}
- Drawing.Buffer[y][x] = {character, textColour, bgColour}
- end
- end,
- }
- --Colour Deffitions--
- UIColours = {
- Toolbar = colours.grey,
- ToolbarText = colours.lightGrey,
- ToolbarSelected = colours.lightBlue,
- ControlText = colours.white,
- ToolbarItemTitle = colours.black,
- Background = colours.lightGrey,
- MenuBackground = colours.white,
- MenuText = colours.black,
- MenuSeparatorText = colours.grey,
- MenuDisabledText = colours.lightGrey,
- Shadow = colours.grey,
- TransparentBackgroundOne = colours.white,
- TransparentBackgroundTwo = colours.lightGrey,
- MenuBarActive = colours.white
- }
- --Lists--
- Current = {
- Artboard = nil,
- Layer = nil,
- Tool = nil,
- ToolSize = 1,
- Toolbar = nil,
- Colour = colours.lightBlue,
- Menu = nil,
- MenuBar = nil,
- Window = nil,
- Input = nil,
- CursorPos = {1,1},
- CursorColour = colours.black,
- InterfaceVisible = true,
- Selection = {},
- SelectionDrawTimer = nil,
- HandDragStart = {},
- Modified = false,
- }
- local isQuitting = false
- function PrintCentered(text, y)
- local w, h = term.getSize()
- x = math.ceil(math.ceil((w / 2) - (#text / 2)), 0)+1
- term.setCursorPos(x, y)
- print(text)
- end
- function DoVanillaClose()
- term.setBackgroundColour(colours.black)
- term.setTextColour(colours.white)
- term.clear()
- term.setCursorPos(1, 1)
- PrintCentered("Thanks for using Sketch!", (Drawing.Screen.Height/2)-1)
- term.setTextColour(colours.lightGrey)
- PrintCentered("Photoshop Inspired Image Editor for ComputerCraft", (Drawing.Screen.Height/2))
- term.setTextColour(colours.white)
- PrintCentered("(c) oeed 2013 - 2014", (Drawing.Screen.Height/2)+3)
- term.setCursorPos(1, Drawing.Screen.Height)
- desktop()
- end
- function Close()
- if isQuitting or not Current.Artboard or not Current.Modified then
- if not OneOS then
- DoVanillaClose()
- end
- return true
- else
- local _w = ButtonDialougeWindow:Initialise('Quit Sketch?', 'You have unsaved changes, do you want to quit anyway?', 'Quit', 'Cancel', function(window, success)
- if success then
- if OneOS then
- OneOS.Close(true)
- else
- DoVanillaClose()
- end
- end
- window:Close()
- Draw()
- end):Show()
- --it's hacky but it works
- os.queueEvent('mouse_click', 1, _w.X, _w.Y)
- return false
- end
- end
- if OneOS then
- OneOS.CanClose = function()
- return Close()
- end
- end
- Lists = {
- Artboards = {},
- Interface = {
- Toolbars = {}
- }
- }
- Events = {
- }
- --Setters--
- function SetColour(colour)
- Current.Colour = colour
- Draw()
- end
- function SetTool(tool)
- if tool and tool.Select and tool:Select() then
- Current.Input = nil
- Current.Tool = tool
- return true
- end
- return false
- end
- function GetAbsolutePosition(object)
- local obj = object
- local i = 0
- local x = 1
- local y = 1
- while true do
- x = x + obj.X - 1
- y = y + obj.Y - 1
- if not obj.Parent then
- return {X = x, Y = y}
- end
- obj = obj.Parent
- if i > 32 then
- return {X = 1, Y = 1}
- end
- i = i + 1
- end
- end
- --Object Defintions--
- Pixel = {
- TextColour = colours.black,
- BackgroundColour = colours.white,
- Character = " ",
- Layer = nil,
- Draw = function(self, x, y)
- if self.BackgroundColour ~= colours.transparent or self.Character ~= ' ' then
- Drawing.WriteToBuffer(self.Layer.Artboard.X + x - 1, self.Layer.Artboard.Y + y - 1, self.Character, self.TextColour, self.BackgroundColour)
- end
- end,
- Initialise = function(self, textColour, backgroundColour, character, layer)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.TextColour = textColour or self.TextColour
- new.BackgroundColour = backgroundColour or self.BackgroundColour
- new.Character = character or self.Character
- new.Layer = layer
- return new
- end,
- Set = function(self, textColour, backgroundColour, character)
- self.TextColour = textColour or self.TextColour
- self.BackgroundColour = backgroundColour or self.BackgroundColour
- self.Character = character or self.Character
- end
- }
- Layer = {
- Name = "",
- Pixels = {
- },
- Artboard = nil,
- BackgroundColour = colours.white,
- Visible = true,
- Index = 1,
- Draw = function(self)
- if self.Visible then
- for x = 1, self.Artboard.Width do
- for y = 1, self.Artboard.Height do
- self.Pixels[x][y]:Draw(x, y)
- end
- end
- end
- end,
- Remove = function(self)
- for i, v in ipairs(self.Artboard.Layers) do
- if v == Current.Layer then
- Current.Artboard.Layers[i] = nil
- Current.Layer = Current.Artboard.Layers[1]
- ModuleNamed('Layers'):Update()
- end
- end
- end,
- Initialise = function(self, name, backgroundColour, artboard, index, pixels)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Name = name
- new.Pixels = {}
- new.BackgroundColour = backgroundColour
- new.Artboard = artboard
- new.Index = index or #artboard.Layers + 1
- if not pixels then
- new:MakeAllBlankPixels()
- else
- new:MakeAllBlankPixels()
- for x, col in ipairs(pixels) do
- for y, pixel in ipairs(col) do
- new:SetPixel(x, y, pixel.TextColour, pixel.BackgroundColour, pixel.Character)
- end
- end
- end
- return new
- end,
- SetPixel = function(self, x, y, textColour, backgroundColour, character)
- textColour = textColour or Current.Colour
- backgroundColour = backgroundColour or Current.Colour
- character = character or " "
- if x < 1 or y < 1 or x > self.Artboard.Width or y > self.Artboard.Height then
- return
- end
- if self.Pixels[x][y] then
- self.Pixels[x][y]:Set(textColour, backgroundColour, character)
- self.Pixels[x][y]:Draw(x,y)
- end
- end,
- MakePixel = function(self, x, y, backgroundColour)
- backgroundColour = backgroundColour or self.BackgroundColour
- self.Pixels[x][y] = Pixel:Initialise(nil, backgroundColour, nil, self)
- end,
- MakeColumn = function(self, x)
- self.Pixels[x] = {}
- end,
- MakeAllBlankPixels = function(self)
- for x = 1, self.Artboard.Width do
- if not self.Pixels[x] then
- self:MakeColumn(x)
- end
- for y = 1, self.Artboard.Height do
- if not self.Pixels[x][y] then
- self:MakePixel(x, y)
- end
- end
- end
- end,
- PixelsInSelection = function(self, cut)
- local pixels = {}
- if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- local point1 = Current.Selection[1]
- local point2 = Current.Selection[2]
- local size = point2 - point1
- local cornerX = point1.x
- local cornerY = point1.y
- for x = 1, size.x + 1 do
- for y = 1, size.y + 1 do
- if not pixels[x] then
- pixels[x] = {}
- end
- if not self.Pixels[cornerX + x - 1] or not self.Pixels[cornerX + x - 1][cornerY + y - 1] then
- break
- end
- local pixel = self.Pixels[cornerX + x - 1][cornerY + y - 1]
- pixels[x][y] = Pixel:Initialise(pixel.TextColour, pixel.BackgroundColour, pixel.Character, Current.Layer)
- if cut then
- Current.Layer:SetPixel(cornerX + x - 1, cornerY + y - 1, nil, Current.Layer.BackgroundColour, nil)
- end
- end
- end
- end
- return pixels
- end,
- EraseSelection = function(self)
- if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- local point1 = Current.Selection[1]
- local point2 = Current.Selection[2]
- local size = point2 - point1
- local cornerX = point1.x
- local cornerY = point1.y
- for x = 1, size.x + 1 do
- for y = 1, size.y + 1 do
- Current.Layer:SetPixel(cornerX + x - 1, cornerY + y - 1, nil, Current.Layer.BackgroundColour, nil)
- end
- end
- end
- end,
- InsertPixels = function(self, pixels)
- local cornerX = Current.Selection[1].x
- local cornerY = Current.Selection[1].y
- for x, col in ipairs(pixels) do
- for y, pixel in ipairs(col) do
- Current.Layer:SetPixel(cornerX + x - 1, cornerY + y - 1, pixel.TextColour, pixel.BackgroundColour, pixel.Character)
- end
- end
- end
- }
- Artboard = {
- X = 0,
- Y = 0,
- Name = "",
- Path = "",
- Width = 1,
- Height = 1,
- Layers = {},
- Format = nil,
- SelectionIsBlack = true,
- Draw = function(self)
- Drawing.DrawBlankArea(self.X + 1, self.Y + 1, self.Width, self.Height, UIColours.Shadow)
- local odd
- for x = 1, self.Width do
- odd = x % 2
- if odd == 1 then
- odd = true
- else
- odd = false
- end
- for y = 1, self.Height do
- if odd then
- Drawing.WriteToBuffer(self.X + x - 1, self.Y + y - 1, ":", UIColours.TransparentBackgroundTwo, UIColours.TransparentBackgroundOne)
- else
- Drawing.WriteToBuffer(self.X + x - 1, self.Y + y - 1, ":", UIColours.TransparentBackgroundOne, UIColours.TransparentBackgroundTwo)
- end
- odd = not odd
- end
- end
- for i, layer in ipairs(self.Layers) do
- layer:Draw()
- end
- if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- local point1 = Current.Selection[1]
- local point2 = Current.Selection[2]
- local size = point2 - point1
- local isBlack = self.SelectionIsBlack
- local function c()
- local c = colours.white
- if isBlack then
- c = colours.black
- end
- isBlack = not isBlack
- return c
- end
- function horizontal(y)
- Drawing.WriteToBuffer(self.X - 1 + point1.x, self.Y - 1 + y, '+', c(), colours.transparent)
- if size.x > 0 then
- for i = 1, size.x - 1 do
- Drawing.WriteToBuffer(self.X - 1 + point1.x + i, self.Y - 1 + y, '-', c(), colours.transparent)
- end
- else
- for i = 1, (-1 * size.x) - 1 do
- Drawing.WriteToBuffer(self.X - 1 + point1.x - i, self.Y - 1 + y, '-', c(), colours.transparent)
- end
- end
- Drawing.WriteToBuffer(self.X - 1 + point1.x + size.x, self.Y - 1 + y, '+', c(), colours.transparent)
- end
- function vertical(x)
- if size.y < 0 then
- for i = 1, (-1 * size.y) - 1 do
- Drawing.WriteToBuffer(self.X - 1 + x, self.Y - 1 + point1.y - i, '|', c(), colours.transparent)
- end
- else
- for i = 1, size.y - 1 do
- Drawing.WriteToBuffer(self.X - 1 + x, self.Y - 1 + point1.y + i, '|', c(), colours.transparent)
- end
- end
- end
- horizontal(point1.y)
- vertical(point1.x)
- horizontal(point1.y + size.y)
- vertical(point1.x + size.x)
- end
- end,
- Initialise = function(self, name, path, width, height, format, backgroundColour, layers)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Y = 3
- new.X = 2
- new.Name = name
- new.Path = path
- new.Width = width
- new.Height = height
- new.Format = format
- new.Layers = {}
- if not layers then
- new:MakeLayer('Background', backgroundColour)
- else
- for i, layer in ipairs(layers) do
- new:MakeLayer(layer.Name, layer.BackgroundColour, layer.Index, layer.Pixels)
- new.Layers[i].Visible = layer.Visible
- end
- Current.Layer = new.Layers[#new.Layers]
- end
- return new
- end,
- Resize = function(self, top, bottom, left, right)
- self.Height = self.Height + top + bottom
- self.Width = self.Width + left + right
- for i, layer in ipairs(self.Layers) do
- if left < 0 then
- for x = 1, -left do
- table.remove(layer.Pixels, 1)
- end
- end
- if right < 0 then
- for x = 1, -right do
- table.remove(layer.Pixels, #layer.Pixels)
- end
- end
- for x = 1, left do
- table.insert(layer.Pixels, 1, {})
- for y = 1, self.Height do
- layer:MakePixel(1, y)
- end
- end
- for x = 1, right do
- table.insert(layer.Pixels, {})
- for y = 1, self.Height do
- layer:MakePixel(#layer.Pixels, y)
- end
- end
- for y = 1, top do
- for x = 1, self.Width do
- table.insert(layer.Pixels[x], 1, {})
- layer:MakePixel(x, 1)
- end
- end
- for y = 1, bottom do
- for x = 1, self.Width do
- table.insert(layer.Pixels[x], {})
- layer:MakePixel(x, #layer.Pixels[x])
- end
- end
- if top < 0 then
- for y = 1, -top do
- for x = 1, self.Width do
- table.remove(layer.Pixels[x], 1)
- end
- end
- end
- if bottom < 0 then
- for y = 1, -bottom do
- for x = 1, self.Width do
- table.remove(layer.Pixels[x], #layer.Pixels[x])
- end
- end
- end
- end
- end,
- MakeLayer = function(self, name, backgroundColour, index, pixels)
- backgroundColour = backgroundColour or colours.white
- name = name or "Layer"
- local layer = Layer:Initialise(name, backgroundColour, self, index, pixels)
- table.insert(self.Layers, layer)
- Current.Layer = layer
- ModuleNamed('Layers'):Update()
- return layer
- end,
- New = function(self, name, path, width, height, format, backgroundColour, layers)
- local new = self:Initialise(name, path, width, height, format, backgroundColour, layers)
- table.insert(Lists.Artboards, new)
- Current.Artboard = new
- --new:Save()
- return new
- end,
- Save = function(self, path)
- Current.Artboard = self
- path = path or self.Path
- local _open = io.open
- if OneOS then
- _open = OneOS.IO.open
- end
- local file = _open(path, "w", true)
- if self.Format == '.skch' then
- file:write(textutils.serialize(SaveSKCH()))
- else
- local lines = {}
- if self.Format == '.nfp' then
- lines = SaveNFP()
- elseif self.Format == '.nft' then
- lines = SaveNFT()
- end
- for i, line in ipairs(lines) do
- file:write(line.."\n")
- end
- end
- file:close()
- Current.Modified = false
- end,
- Click = function(self, side, x, y, drag)
- if Current.Tool and Current.Layer and Current.Layer.Visible then
- Current.Tool:Use(x, y, side, drag)
- Current.Modified = true
- return true
- end
- end
- }
- Toolbar = {
- X = 0,
- Y = 0,
- Width = 0,
- ExpandedWidth = 14,
- ClosedWidth = 2,
- Height = 0,
- Expanded = true,
- ToolbarItems = {},
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- self:CalculateToolbarItemPositions()
- --Drawing.DrawArea(self.X - 1, self.Y, 1, self.Height, "|", UIColours.ToolbarText, UIColours.Background)
- --if not Current.Window then
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.Toolbar)
- --else
- -- Drawing.DrawArea(self.X, self.Y, self.Width, self.Height, '|', colours.lightGrey, UIColours.Toolbar)
- --end
- for i, toolbarItem in ipairs(self.ToolbarItems) do
- toolbarItem:Draw()
- end
- end,
- Initialise = function(self, side, expanded)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Expanded = expanded
- if expanded then
- new.Width = new.ExpandedWidth
- else
- new.Width = new.ClosedWidth
- end
- if side == 'right' then
- new.X = Drawing.Screen.Width - new.Width + 1
- end
- if side == 'right' or side == 'left' then
- new.Height = Drawing.Screen.Width
- end
- new.Y = 1
- return new
- end,
- AddToolbarItem = function(self, item)
- table.insert(self.ToolbarItems, item)
- self:CalculateToolbarItemPositions()
- end,
- CalculateToolbarItemPositions = function(self)
- local currY = 1
- for i, toolbarItem in ipairs(self.ToolbarItems) do
- toolbarItem.Y = currY
- currY = currY + toolbarItem.Height
- end
- end,
- Update = function(self)
- for i, toolbarItem in ipairs(self.ToolbarItems) do
- if toolbarItem.Module.Update then
- toolbarItem.Module:Update(toolbarItem)
- end
- end
- end,
- New = function(self, side, expanded)
- local new = self:Initialise(side, expanded)
- --new:AddToolbarItem(ToolbarItem:Initialise("Colours", nil, true, new))
- --new:AddToolbarItem(ToolbarItem:Initialise("IDK", true, new))
- table.insert(Lists.Interface.Toolbars, new)
- return new
- end,
- Click = function(self, side, x, y)
- return false
- end
- }
- ToolbarItem = {
- X = 0,
- Y = 0,
- Width = 0,
- Height = 0,
- ExpandedHeight = 5,
- Expanded = true,
- Toolbar = nil,
- Title = "",
- MenuIcon = "=",
- ExpandedIcon = "+",
- ContractIcon = "-",
- ContentView = nil,
- Module = nil,
- MenuItems = nil,
- Draw = function(self)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, UIColours.ToolbarItemTitle)
- Drawing.DrawCharacters(self.X + 1, self.Y, self.Title, UIColours.ToolbarText, UIColours.ToolbarItemTitle)
- Drawing.DrawCharacters(self.X + self.Width - 1, self.Y, self.MenuIcon, UIColours.ToolbarText, UIColours.ToolbarItemTitle)
- local expandContractIcon = self.ContractIcon
- if not self.Expanded then
- expandContractIcon = self.ExpandedIcon
- end
- if self.Expanded and self.ContentView then
- self.ContentView:Draw()
- end
- Drawing.DrawCharacters(self.X + self.Width - 2, self.Y, expandContractIcon, UIColours.ToolbarText, UIColours.ToolbarItemTitle)
- end,
- Initialise = function(self, module, height, expanded, toolbar, menuItems)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Expanded = expanded
- new.Title = module.Title
- new.Width = toolbar.Width
- new.Height = height or 5
- new.Module = module
- new.MenuItems = menuItems or {}
- table.insert(new.MenuItems,
- {
- Title = 'Shrink',
- Click = function()
- new:ToggleExpanded()
- end
- })
- new.ExpandedHeight = height or 5
- new.Y = 1
- new.X = toolbar.X
- new.ContentView = ContentView:Initialise(1, 2, new.Width, new.Height - 1, nil, new)
- new.Toolbar = toolbar
- return new
- end,
- ToggleExpanded = function(self)
- self.Expanded = not self.Expanded
- if self.Expanded then
- self.Height = self.ExpandedHeight
- else
- self.Height = 1
- end
- end,
- Click = function(self, side, x, y)
- local pos = GetAbsolutePosition(self)
- if x == self.Width and y == 1 then
- local expandContract = "Shrink"
- if not self.Expanded then
- expandContract = "Expand"
- end
- self.MenuItems[#self.MenuItems].Title = expandContract
- Menu:New(pos.X + x, pos.Y + y, self.MenuItems, self)
- return true
- elseif x == self.Width - 1 and y == 1 then
- self:ToggleExpanded()
- return true
- elseif y ~= 1 then
- return self.ContentView:Click(side, x - self.ContentView.X + 1, y - self.ContentView.Y + 1)
- end
- return false
- end
- }
- ContentView = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- Parent = nil,
- Views = {},
- AbsolutePosition = function(self)
- return self.Parent:AbsolutePosition()
- end,
- Draw = function(self)
- for i, view in ipairs(self.Views) do
- view:Draw()
- end
- end,
- Initialise = function(self, x, y, width, height, views, parent)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = width
- new.Height = height
- new.Y = y
- new.X = x
- new.Views = views or {}
- new.Parent = parent
- return new
- end,
- Click = function(self, side, x, y)
- for k, view in pairs(self.Views) do
- if DoClick(view, side, x, y) then
- return true
- end
- end
- end
- }
- Button = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- BackgroundColour = colours.lightGrey,
- TextColour = colours.white,
- ActiveBackgroundColour = colours.lightGrey,
- Text = "",
- Parent = nil,
- _Click = nil,
- Toggle = nil,
- AbsolutePosition = function(self)
- return self.Parent:AbsolutePosition()
- end,
- Draw = function(self)
- local bg = self.BackgroundColour
- local tc = self.TextColour
- if type(bg) == 'function' then
- bg = bg()
- end
- if self.Toggle then
- tc = UIColours.MenuBarActive
- bg = self.ActiveBackgroundColour
- end
- local pos = GetAbsolutePosition(self)
- Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, bg)
- Drawing.DrawCharactersCenter(pos.X, pos.Y, self.Width, self.Height, self.Text, tc, bg)
- end,
- Initialise = function(self, x, y, width, height, backgroundColour, parent, click, text, textColour, toggle, activeBackgroundColour)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- height = height or 1
- new.Width = width or #text + 2
- new.Height = height
- new.Y = y
- new.X = x
- new.Text = text or ""
- new.BackgroundColour = backgroundColour or colours.lightGrey
- new.TextColour = textColour or colours.white
- new.ActiveBackgroundColour = activeBackgroundColour or colours.lightGrey
- new.Parent = parent
- new._Click = click
- new.Toggle = toggle
- return new
- end,
- Click = function(self, side, x, y)
- if self._Click then
- if self:_Click(side, x, y, not self.Toggle) ~= false and self.Toggle ~= nil then
- self.Toggle = not self.Toggle
- Draw()
- end
- return true
- else
- return false
- end
- end
- }
- TextBox = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- BackgroundColour = colours.lightGrey,
- TextColour = colours.black,
- Parent = nil,
- TextInput = nil,
- AbsolutePosition = function(self)
- return self.Parent:AbsolutePosition()
- end,
- Draw = function(self)
- local pos = GetAbsolutePosition(self)
- Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, self.BackgroundColour)
- local text = self.TextInput.Value
- if #text > (self.Width - 2) then
- text = text:sub(#text-(self.Width - 3))
- if Current.Input == self.TextInput then
- Current.CursorPos = {pos.X + 1 + self.Width-2, pos.Y}
- end
- else
- if Current.Input == self.TextInput then
- Current.CursorPos = {pos.X + 1 + self.TextInput.CursorPos, pos.Y}
- end
- end
- Drawing.DrawCharacters(pos.X + 1, pos.Y, text, self.TextColour, self.BackgroundColour)
- term.setCursorBlink(true)
- Current.CursorColour = self.TextColour
- end,
- Initialise = function(self, x, y, width, height, parent, text, backgroundColour, textColour, done, numerical)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- height = height or 1
- new.Width = width or #text + 2
- new.Height = height
- new.Y = y
- new.X = x
- new.TextInput = TextInput:Initialise(text or '', function(key)
- if done then
- done(key)
- end
- Draw()
- end, numerical)
- new.BackgroundColour = backgroundColour or colours.lightGrey
- new.TextColour = textColour or colours.black
- new.Parent = parent
- return new
- end,
- Click = function(self, side, x, y)
- Current.Input = self.TextInput
- self:Draw()
- end
- }
- TextInput = {
- Value = "",
- Change = nil,
- CursorPos = nil,
- Numerical = false,
- Initialise = function(self, value, change, numerical)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Value = value
- new.Change = change
- new.CursorPos = #value
- new.Numerical = numerical
- return new
- end,
- Char = function(self, char)
- if self.Numerical then
- char = tostring(tonumber(char))
- end
- if char == 'nil' then
- return
- end
- self.Value = string.sub(self.Value, 1, self.CursorPos ) .. char .. string.sub( self.Value, self.CursorPos + 1 )
- self.CursorPos = self.CursorPos + 1
- self.Change(key)
- end,
- Key = function(self, key)
- if key == keys.enter then
- self.Change(key)
- elseif key == keys.left then
- -- Left
- if self.CursorPos > 0 then
- self.CursorPos = self.CursorPos - 1
- self.Change(key)
- end
- elseif key == keys.right then
- -- Right
- if self.CursorPos < string.len(self.Value) then
- self.CursorPos = self.CursorPos + 1
- self.Change(key)
- end
- elseif key == keys.backspace then
- -- Backspace
- if self.CursorPos > 0 then
- self.Value = string.sub( self.Value, 1, self.CursorPos - 1 ) .. string.sub( self.Value, self.CursorPos + 1 )
- self.CursorPos = self.CursorPos - 1
- end
- self.Change(key)
- elseif key == keys.home then
- -- Home
- self.CursorPos = 0
- self.Change(key)
- elseif key == keys.delete then
- if self.CursorPos < string.len(self.Value) then
- self.Value = string.sub( self.Value, 1, self.CursorPos ) .. string.sub( self.Value, self.CursorPos + 2 )
- self.Change(key)
- end
- elseif key == keys["end"] then
- -- End
- self.CursorPos = string.len(self.Value)
- self.Change(key)
- end
- end
- }
- LayerItem = {
- X = 1,
- Y = 1,
- Parent = nil,
- Layer = nil,
- Draw = function(self)
- self.Y = self.Layer.Index
- local pos = GetAbsolutePosition(self)
- local tc = colours.lightGrey
- if Current.Layer == self.Layer then
- tc = colours.white
- end
- Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, UIColours.Toolbar)
- Drawing.DrawCharacters(pos.X + 3, pos.Y, self.Layer.Name, tc, UIColours.Toolbar)
- if self.Layer.Visible then
- Drawing.DrawCharacters(pos.X + 1, pos.Y, "@", tc, UIColours.Toolbar)
- else
- Drawing.DrawCharacters(pos.X + 1, pos.Y, "X", tc, UIColours.Toolbar)
- end
- end,
- Initialise = function(self, layer, parent)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = parent.Width
- new.Height = 1
- new.Y = 1
- new.X = 1
- new.Layer = layer
- new.Parent = parent
- return new
- end,
- Click = function(self, side, x, y)
- if x == 2 then
- self.Layer.Visible = not self.Layer.Visible
- else
- Current.Layer = self.Layer
- end
- return true
- end
- }
- Menu = {
- X = 0,
- Y = 0,
- Width = 0,
- Height = 0,
- Owner = nil,
- Items = {},
- RemoveTop = false,
- Draw = function(self)
- Drawing.DrawBlankArea(self.X + 1, self.Y + 1, self.Width, self.Height, UIColours.Shadow)
- if not self.RemoveTop then
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
- for i, item in ipairs(self.Items) do
- if item.Separator then
- Drawing.DrawArea(self.X, self.Y + i, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
- else
- local textColour = UIColours.MenuText
- if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
- textColour = UIColours.MenuDisabledText
- end
- Drawing.DrawCharacters(self.X + 1, self.Y + i, item.Title, textColour, UIColours.MenuBackground)
- end
- end
- else
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
- for i, item in ipairs(self.Items) do
- if item.Separator then
- Drawing.DrawArea(self.X, self.Y + i - 1, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
- else
- local textColour = UIColours.MenuText
- if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
- textColour = UIColours.MenuDisabledText
- end
- Drawing.DrawCharacters(self.X + 1, self.Y + i - 1, item.Title, textColour, UIColours.MenuBackground)
- Drawing.DrawCharacters(self.X - 1 + self.Width-#item.KeyName, self.Y + i - 1, item.KeyName, textColour, UIColours.MenuBackground)
- end
- end
- end
- end,
- NameForKey = function(self, key)
- if key == keys.leftCtrl then
- return '^'
- elseif key == keys.tab then
- return 'Tab'
- elseif key == keys.delete then
- return 'Delete'
- elseif key == keys.n then
- return 'N'
- elseif key == keys.s then
- return 'S'
- elseif key == keys.o then
- return 'O'
- elseif key == keys.z then
- return 'Z'
- elseif key == keys.y then
- return 'Y'
- elseif key == keys.c then
- return 'C'
- elseif key == keys.x then
- return 'X'
- elseif key == keys.v then
- return 'V'
- elseif key == keys.r then
- return 'R'
- elseif key == keys.l then
- return 'L'
- elseif key == keys.t then
- return 'T'
- elseif key == keys.h then
- return 'H'
- elseif key == keys.e then
- return 'E'
- elseif key == keys.p then
- return 'P'
- elseif key == keys.f then
- return 'F'
- elseif key == keys.m then
- return 'M'
- else
- return '?'
- end
- end,
- Initialise = function(self, x, y, items, owner, removeTop)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- if not owner then
- return
- end
- local keyNames = {}
- for i, v in ipairs(items) do
- items[i].KeyName = ''
- if v.Keys then
- for _i, key in ipairs(v.Keys) do
- items[i].KeyName = items[i].KeyName .. self:NameForKey(key)
- end
- end
- if items[i].KeyName ~= '' then
- table.insert(keyNames, items[i].KeyName)
- end
- end
- local keysLength = LongestString(keyNames)
- if keysLength > 0 then
- keysLength = keysLength + 2
- end
- new.Width = LongestString(items, 'Title') + 2 + keysLength
- if new.Width < 10 then
- new.Width = 10
- end
- new.Height = #items + 2
- new.RemoveTop = removeTop or false
- if removeTop then
- new.Height = new.Height - 1
- end
- if y < 1 then
- y = 1
- end
- if x < 1 then
- x = 1
- end
- if y + new.Height > Drawing.Screen.Height + 1 then
- y = Drawing.Screen.Height - new.Height
- end
- if x + new.Width > Drawing.Screen.Width + 1 then
- x = Drawing.Screen.Width - new.Width
- end
- new.Y = y
- new.X = x
- new.Items = items
- new.Owner = owner
- return new
- end,
- New = function(self, x, y, items, owner, removeTop)
- if Current.Menu and Current.Menu.Owner == owner then
- Current.Menu = nil
- return
- end
- local new = self:Initialise(x, y, items, owner, removeTop)
- Current.Menu = new
- return new
- end,
- Click = function(self, side, x, y)
- local i = y-1
- if self.RemoveTop then
- i = y
- end
- if i >= 1 and y < self.Height then
- if not ((self.Items[i].Enabled and type(self.Items[i].Enabled) == 'function' and self.Items[i].Enabled() == false) or self.Items[i].Enabled == false) and self.Items[i].Click then
- self.Items[i]:Click()
- if Current.Menu.Owner and Current.Menu.Owner.Toggle then
- Current.Menu.Owner.Toggle = false
- end
- Current.Menu = nil
- self = nil
- end
- return true
- end
- end
- }
- MenuBar = {
- X = 1,
- Y = 1,
- Width = Drawing.Screen.Width,
- Height = 1,
- MenuBarItems = {},
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- --Drawing.DrawArea(self.X - 1, self.Y, 1, self.Height, "|", UIColours.ToolbarText, UIColours.Background)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.Toolbar)
- for i, button in ipairs(self.MenuBarItems) do
- button:Draw()
- end
- end,
- Initialise = function(self, items)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.X = 1
- new.Y = 1
- new.MenuBarItems = items
- return new
- end,
- AddToolbarItem = function(self, item)
- table.insert(self.ToolbarItems, item)
- self:CalculateToolbarItemPositions()
- end,
- CalculateToolbarItemPositions = function(self)
- local currY = 1
- for i, toolbarItem in ipairs(self.ToolbarItems) do
- toolbarItem.Y = currY
- currY = currY + toolbarItem.Height
- end
- end,
- Click = function(self, side, x, y)
- for i, item in ipairs(self.MenuBarItems) do
- if item.X <= x and item.X + item.Width > x then
- if item:Click(item, side, x - item.X + 1, 1) then
- break
- end
- end
- end
- return false
- end
- }
- --Modules--
- Modules = {
- {
- Title = "Colours",
- ToolbarItem = nil,
- Initialise = function(self)
- self.ToolbarItem = ToolbarItem:Initialise(self, nil, true, Current.Toolbar)
- local buttons = {}
- local i = 0
- local coloursWidth = 8
- local _colours = {
- colours.brown,
- colours.yellow,
- colours.orange,
- colours.red,
- colours.green,
- colours.lime,
- colours.magenta,
- colours.pink,
- colours.purple,
- colours.blue,
- colours.cyan,
- colours.lightBlue,
- colours.lightGrey,
- colours.grey,
- colours.black,
- colours.white
- }
- for k, colour in pairs(_colours) do
- if type(colour) == 'number' and colour ~= -1 then
- i = i + 1
- local y = math.floor(i/(coloursWidth/2))
- local x = (i%(coloursWidth/2))
- if x == 0 then
- x = (coloursWidth/2)
- y = y -1
- end
- table.insert(buttons,
- {
- X = x*2 - 2 + self.ToolbarItem.Width - coloursWidth,
- Y = y+1,
- Width = 2,
- Height = 1,
- BackgroundColour = colour,
- Click = function(self, side, x, y)
- SetColour(self.BackgroundColour)
- end
- }
- )
- end
- end
- for i, button in ipairs(buttons) do
- table.insert(self.ToolbarItem.ContentView.Views,
- Button:Initialise(button.X, button.Y, button.Width, button.Height, button.BackgroundColour, self.ToolbarItem.ContentView, button.Click))
- end
- table.insert(self.ToolbarItem.ContentView.Views,
- Button:Initialise(1, 1, 4, 3, function()return Current.Colour end, self.ToolbarItem.ContentView, nil))
- Current.Toolbar:AddToolbarItem(self.ToolbarItem)
- end
- },
- {
- Title = "Tools",
- ToolbarItem = nil,
- Update = function(self)
- for i, view in ipairs(self.ToolbarItem.ContentView.Views) do
- if (Current.Tool and Current.Tool.Name == view.Text) then
- view.TextColour = colours.white
- else
- view.TextColour = colours.lightGrey
- end
- end
- self.ToolbarItem.ContentView.Views[1].Text = 'Size: '..Current.ToolSize
- end,
- Initialise = function(self)
- self.ToolbarItem = ToolbarItem:Initialise(self, #Tools+2, true, Current.Toolbar,
- {{
- Title = "Change Tool Size",
- Click = function()
- DisplayToolSizeWindow()
- end,
- }})
- table.insert(self.ToolbarItem.ContentView.Views, Button:Initialise(1, 1, self.ToolbarItem.Width, 1, UIColours.Toolbar, self.ToolbarItem.ContentView, DisplayToolSizeWindow, 'Size: '..Current.ToolSize))
- local y = 2
- for i, tool in ipairs(Tools) do
- table.insert(self.ToolbarItem.ContentView.Views, Button:Initialise(1, y, self.ToolbarItem.Width, 1, UIColours.Toolbar, self.ToolbarItem.ContentView, function() SetTool(tool) self:Update(self.ToolbarItem) end, tool.Name))
- y = y + 1
- end
- self:Update(self.ToolbarItem)
- Current.Toolbar:AddToolbarItem(self.ToolbarItem)
- end
- },
- {
- Title = "Layers",
- ToolbarItem = nil,
- Update = function(self)
- if Current.Artboard then
- self.ToolbarItem.ContentView.Views = {}
- for i = 1, #Current.Artboard.Layers do
- table.insert(self.ToolbarItem.ContentView.Views, LayerItem:Initialise(Current.Artboard.Layers[#Current.Artboard.Layers-i+1], self.ToolbarItem.ContentView))
- end
- end
- end,
- Initialise = function(self)
- self.ToolbarItem = ToolbarItem:Initialise(self, nil, true, Current.Toolbar,
- {{
- Title = "New Layer",
- Click = function()
- MakeNewLayer()
- end,
- Enabled = function()
- return CheckOpenArtboard()
- end
- },
- {
- Title = 'Delete Layer',
- Click = function()
- DeleteLayer()
- end,
- Enabled = function()
- return CheckSelectedLayer()
- end
- },
- {
- Title = 'Rename Layer...',
- Click = function()
- RenameLayer()
- end,
- Enabled = function()
- return CheckSelectedLayer()
- end
- }})
- self:Update()
- Current.Toolbar:AddToolbarItem(self.ToolbarItem)
- end
- }
- }
- function ModuleNamed(name)
- for i, v in ipairs(Modules) do
- if v.Title == name then
- return v
- end
- end
- end
- --Tools--
- function ToolAffectedPixels(x, y)
- if not CheckSelectedLayer() then
- return {}
- end
- if Current.ToolSize == 1 then
- if Current.Layer.Pixels[x] and Current.Layer.Pixels[x][y] then
- return {{Current.Layer.Pixels[x][y], x, y}}
- end
- else
- local pixels = {}
- local cornerX = x - math.ceil(Current.ToolSize/2)
- local cornerY = y - math.ceil(Current.ToolSize/2)
- for _x = 1, Current.ToolSize do
- for _y = 1, Current.ToolSize do
- if Current.Layer.Pixels[cornerX + _x] and Current.Layer.Pixels[cornerX + _x][cornerY + _y] then
- table.insert(pixels, {Current.Layer.Pixels[cornerX + _x][cornerY + _y], cornerX + _x, cornerY + _y})
- end
- end
- end
- return pixels
- end
- end
- local moveStartPoint = {}
- Tools = {
- {
- Name = "Hand",
- Use = function(self, x, y, side, drag)
- Current.Input = nil
- if drag and Current.HandDragStart and Current.HandDragStart[1] and Current.HandDragStart[2] then
- local deltaX = x - Current.HandDragStart[1]
- local deltaY = y - Current.HandDragStart[2]
- Current.Artboard.X = Current.Artboard.X + deltaX
- Current.Artboard.Y = Current.Artboard.Y + deltaY
- else
- Current.HandDragStart = {x, y}
- end
- sleep(0)
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Pencil",
- Use = function(self, _x, _y, side, artboard)
- Current.Input = nil
- for i, pixel in ipairs(ToolAffectedPixels(_x, _y)) do
- if side == 1 then
- pixel[1].BackgroundColour = Current.Colour
- elseif side == 2 then
- pixel[1].TextColour = Current.Colour
- end
- pixel[1]:Draw(pixel[2], pixel[3])
- end
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Eraser",
- Use = function(self, x, y, side)
- Current.Input = nil
- Current.Layer:SetPixel(x, y, nil, Current.Layer.BackgroundColour, nil)
- for i, pixel in ipairs(ToolAffectedPixels(x, y)) do
- Current.Layer:SetPixel(pixel[2], pixel[3], nil, Current.Layer.BackgroundColour, nil)
- end
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Fill Bucket",
- Use = function(self, x, y, side)
- local replaceColour = Current.Layer.Pixels[x][y].BackgroundColour
- if side == 2 then
- replaceColour = Current.Layer.Pixels[x][y].TextColour
- end
- local nodes = {{X = x, Y = y}}
- while #nodes > 0 do
- local node = nodes[1]
- if Current.Layer.Pixels[node.X] and Current.Layer.Pixels[node.X][node.Y] then
- local replacing = Current.Layer.Pixels[node.X][node.Y].BackgroundColour
- if side == 2 then
- replacing = Current.Layer.Pixels[node.X][node.Y].TextColour
- end
- if replacing == replaceColour and replacing ~= Current.Colour then
- if side == 1 then
- Current.Layer.Pixels[node.X][node.Y].BackgroundColour = Current.Colour
- elseif side == 2 then
- Current.Layer.Pixels[node.X][node.Y].TextColour = Current.Colour
- end
- table.insert(nodes, {X = node.X, Y = node.Y + 1})
- table.insert(nodes, {X = node.X + 1, Y = node.Y})
- if x > 1 then
- table.insert(nodes, {X = node.X - 1, Y = node.Y})
- end
- if y > 1 then
- table.insert(nodes, {X = node.X, Y = node.Y - 1})
- end
- end
- end
- table.remove(nodes, 1)
- end
- Draw()
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Select",
- Use = function(self, x, y, side, drag)
- Current.Input = nil
- if not drag then
- Current.Selection[1] = vector.new(x, y, 0)
- Current.Selection[2] = nil
- else
- Current.Selection[2] = vector.new(x, y, 0)
- end
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Move",
- Use = function(self, x, y, side, drag)
- Current.Input = nil
- if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- if drag and moveStartPoint then
- local pixels = Current.Layer:PixelsInSelection(true)
- local size = Current.Selection[1] - Current.Selection[2]
- Current.Selection[1] = vector.new(x-moveStartPoint[1], y-moveStartPoint[2], 0)
- Current.Selection[2] = vector.new(x-moveStartPoint[1]-size.x, y-moveStartPoint[2]-size.y, 0)
- Current.Layer:InsertPixels(pixels)
- else
- moveStartPoint = {x-Current.Selection[1].x, y-Current.Selection[1].y}
- end
- end
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Text",
- Use = function(self, x, y)
- Current.Input = TextInput:Initialise('', function(key)
- if key == keys.delete or key == keys.backspace then
- if #Current.Input.Value == 0 then
- if Current.Layer.Pixels[x] and Current.Layer.Pixels[x][y] then
- Current.Layer.Pixels[x][y]:Set(nil, nil, ' ')
- local newPos = Current.CursorPos[1] - Current.Artboard.X
- if newPos < Current.Artboard.X - 1 then
- newPos = Current.Artboard.X - 1
- end
- Current.Tool:Use(newPos, Current.CursorPos[2] - Current.Artboard.Y + 1)
- Draw()
- end
- return
- else
- if Current.Layer.Pixels[x+#Current.Input.Value] and Current.Layer.Pixels[x+#Current.Input.Value][y] then
- Current.Layer.Pixels[x+#Current.Input.Value][y]:Set(nil, nil, ' ')
- end
- end
- else
- local i = #Current.Input.Value
- if Current.Layer.Pixels[x+i-1] then
- Current.Layer.Pixels[x+i-1][y]:Set(Current.Colour, nil, Current.Input.Value:sub(i,i))
- Current.Layer.Pixels[x+i-1][y]:Draw(x+i-1, y)
- end
- end
- local newPos = x+Current.Input.CursorPos
- if newPos > Current.Artboard.Width then
- Current.Input.CursorPos = Current.Input.CursorPos - 1
- end
- Current.CursorPos = {x+Current.Input.CursorPos + Current.Artboard.X - 1, y + Current.Artboard.Y - 1}
- Current.CursorColour = Current.Colour
- Draw()
- end)
- Current.CursorPos = {x + Current.Artboard.X - 1, y + Current.Artboard.Y - 1}
- Current.CursorColour = Current.Colour
- end,
- Select = function(self)
- if Current.Artboard.Format == '.nfp' then
- ButtonDialougeWindow:Initialise('NFP does not support text!', 'The format you are using, NFP, does not support text. Use NFT or SKCH to use text.', 'Ok', nil, function(window)
- window:Close()
- end):Show()
- return false
- else
- return true
- end
- end
- }
- }
- function ToolNamed(name)
- for i, v in ipairs(Tools) do
- if v.Name == name then
- return v
- end
- end
- end
- --Windows--
- NewDocumentWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- Return = nil,
- OkButton = nil,
- Format = '.skch',
- ImageBackgroundColour = colours.white,
- NameLabelHighlight = false,
- SizeLabelHighlight = false,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- local nameLabelColour = colours.black
- if self.NameLabelHighlight then
- nameLabelColour = colours.red
- end
- Drawing.DrawCharacters(self.X+1, self.Y+2, "Name", nameLabelColour, colours.white)
- Drawing.DrawCharacters(self.X+1, self.Y+4, "Type", colours.black, colours.white)
- local sizeLabelColour = colours.black
- if self.SizeLabelHighlight then
- sizeLabelColour = colours.red
- end
- Drawing.DrawCharacters(self.X+1, self.Y+6, "Size", sizeLabelColour, colours.white)
- Drawing.DrawCharacters(self.X+11, self.Y+6, "x", colours.black, colours.white)
- Drawing.DrawCharacters(self.X+1, self.Y+8, "Background", colours.black, colours.white)
- self.OkButton:Draw()
- self.CancelButton:Draw()
- self.SKCHButton:Draw()
- self.NFTButton:Draw()
- self.NFPButton:Draw()
- self.PathTextBox:Draw()
- self.WidthTextBox:Draw()
- self.HeightTextBox:Draw()
- self.WhiteButton:Draw()
- self.BlackButton:Draw()
- self.TransparentButton:Draw()
- end,
- Initialise = function(self, returnFunc)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 32
- new.Height = 13
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = 'New Document'
- new.Visible = true
- new.NameLabelHighlight = false
- new.SizeLabelHighlight = false
- new.Format = '.skch'
- new.OkButton = Button:Initialise(new.Width - 4, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- local path = new.PathTextBox.TextInput.Value
- local ok = true
- new.NameLabelHighlight = false
- new.SizeLabelHighlight = false
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if path:sub(-1) == '/' or _fs.isDir(path) or #path == 0 then
- ok = false
- new.NameLabelHighlight = true
- end
- if #new.WidthTextBox.TextInput.Value == 0 or tonumber(new.WidthTextBox.TextInput.Value) <= 0 then
- ok = false
- new.SizeLabelHighlight = true
- end
- if #new.HeightTextBox.TextInput.Value == 0 or tonumber(new.HeightTextBox.TextInput.Value) <= 0 then
- ok = false
- new.SizeLabelHighlight = true
- end
- if ok then
- returnFunc(new, true, path, tonumber(new.WidthTextBox.TextInput.Value), tonumber(new.HeightTextBox.TextInput.Value), new.Format, new.ImageBackgroundColour)
- else
- Draw()
- end
- end, 'Ok', colours.black)
- new.CancelButton = Button:Initialise(new.Width - 13, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)returnFunc(new, false)end, 'Cancel', colours.black)
- new.SKCHButton = Button:Initialise(7, 5, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.NFTButton.Toggle = false
- new.NFPButton.Toggle = false
- self.Toggle = false
- new.Format = '.skch'
- end, '.skch', colours.black, true, colours.lightBlue)
- new.NFTButton = Button:Initialise(15, 5, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.SKCHButton.Toggle = false
- new.NFPButton.Toggle = false
- self.Toggle = false
- new.Format = '.nft'
- end, '.nft', colours.black, false, colours.lightBlue)
- new.NFPButton = Button:Initialise(22, 5, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.SKCHButton.Toggle = false
- new.NFTButton.Toggle = false
- self.Toggle = false
- new.Format = '.nfp'
- end, '.nfp', colours.black, false, colours.lightBlue)
- local path = ''
- if OneOS then
- path = '/Desktop/'
- end
- new.PathTextBox = TextBox:Initialise(7, 3, new.Width - 7, 1, new, path, nil, nil, function(key)
- if key == keys.enter or key == keys.tab then
- Current.Input = new.WidthTextBox.TextInput
- end
- end)
- new.WidthTextBox = TextBox:Initialise(7, 7, 4, 1, new, tostring(15), nil, nil, function()
- if key == keys.enter or key == keys.tab then
- Current.Input = new.HeightTextBox.TextInput
- end
- end, true)
- new.HeightTextBox = TextBox:Initialise(14, 7, 4, 1, new, tostring(10), nil, nil, function()
- if key == keys.enter or key == keys.tab then
- Current.Input = new.PathTextBox.TextInput
- end
- end, true)
- Current.Input = new.PathTextBox.TextInput
- new.WhiteButton = Button:Initialise(2, 10, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.TransparentButton.Toggle = false
- new.BlackButton.Toggle = false
- self.Toggle = false
- new.ImageBackgroundColour = colours.white
- end, 'White', colours.black, true, colours.lightBlue)
- new.BlackButton = Button:Initialise(10, 10, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.TransparentButton.Toggle = false
- new.WhiteButton.Toggle = false
- self.Toggle = false
- new.ImageBackgroundColour = colours.black
- end, 'Black', colours.black, false, colours.lightBlue)
- new.TransparentButton = Button:Initialise(18, 10, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.WhiteButton.Toggle = false
- new.BlackButton.Toggle = false
- self.Toggle = false
- new.ImageBackgroundColour = colours.transparent
- end, 'Transparent', colours.black, false, colours.lightBlue)
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Input = nil
- Current.Window = nil
- self = nil
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- ButtonClick = function(self, button, x, y)
- if button.X <= x and button.Y <= y and button.X + button.Width > x and button.Y + button.Height > y then
- button:Click()
- end
- end,
- Click = function(self, side, x, y)
- local items = {self.OkButton, self.CancelButton, self.SKCHButton, self.NFTButton, self.NFPButton, self.PathTextBox, self.WidthTextBox, self.HeightTextBox, self.WhiteButton, self.BlackButton, self.TransparentButton}
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- end
- end
- return true
- end
- }
- local TidyPath = function(path)
- path = '/'..path
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if _fs.isDir(path) then
- path = path .. '/'
- end
- path, n = path:gsub("//", "/")
- while n > 0 do
- path, n = path:gsub("//", "/")
- end
- return path
- end
- local WrapText = function(text, maxWidth)
- local lines = {''}
- for word, space in text:gmatch('(%S+)(%s*)') do
- local temp = lines[#lines] .. word .. space:gsub('\n','')
- if #temp > maxWidth then
- table.insert(lines, '')
- end
- if space:find('\n') then
- lines[#lines] = lines[#lines] .. word
- space = space:gsub('\n', function()
- table.insert(lines, '')
- return ''
- end)
- else
- lines[#lines] = lines[#lines] .. word .. space
- end
- end
- return lines
- end
- OpenDocumentWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- Return = nil,
- OpenButton = nil,
- PathTextBox = nil,
- CurrentDirectory = '/',
- Scroll = 0,
- MaxScroll = 0,
- GoUpButton = nil,
- SelectedFile = '',
- Files = {},
- Typed = false,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 3, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-6, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y + self.Height - 5, self.Width, 5, colours.lightGrey)
- self:DrawFiles()
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if (_fs.exists(self.PathTextBox.TextInput.Value)) or (self.SelectedFile and #self.SelectedFile > 0 and _fs.exists(self.CurrentDirectory .. self.SelectedFile)) then
- self.OpenButton.TextColour = colours.black
- else
- self.OpenButton.TextColour = colours.lightGrey
- end
- self.PathTextBox:Draw()
- self.OpenButton:Draw()
- self.CancelButton:Draw()
- self.GoUpButton:Draw()
- end,
- DrawFiles = function(self)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- for i, file in ipairs(self.Files) do
- if i > self.Scroll and i - self.Scroll <= 11 then
- if file == self.SelectedFile then
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.white, colours.lightBlue)
- elseif string.find(file, '%.skch') or string.find(file, '%.nft') or string.find(file, '%.nfp') or _fs.isDir(self.CurrentDirectory .. file) then
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.black, colours.white)
- else
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.grey, colours.white)
- end
- end
- end
- self.MaxScroll = #self.Files - 11
- if self.MaxScroll < 0 then
- self.MaxScroll = 0
- end
- end,
- Initialise = function(self, returnFunc)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 32
- new.Height = 17
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = 'Open Document'
- new.Visible = true
- new.CurrentDirectory = '/'
- new.SelectedFile = nil
- if OneOS then
- new.CurrentDirectory = '/Desktop/'
- end
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- new.OpenButton = Button:Initialise(new.Width - 6, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- if _fs.exists(new.PathTextBox.TextInput.Value) and self.TextColour == colours.black and not _fs.isDir(new.PathTextBox.TextInput.Value) then
- returnFunc(new, true, TidyPath(new.PathTextBox.TextInput.Value))
- elseif new.SelectedFile and self.TextColour == colours.black and _fs.isDir(new.CurrentDirectory .. new.SelectedFile) then
- new:GoToDirectory(new.CurrentDirectory .. new.SelectedFile)
- elseif new.SelectedFile and self.TextColour == colours.black then
- returnFunc(new, true, TidyPath(new.CurrentDirectory .. '/' .. new.SelectedFile))
- end
- end, 'Open', colours.black)
- new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- returnFunc(new, false)
- end, 'Cancel', colours.black)
- new.GoUpButton = Button:Initialise(2, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- local folderName = _fs.getName(new.CurrentDirectory)
- local parentDirectory = new.CurrentDirectory:sub(1, #new.CurrentDirectory-#folderName-1)
- new:GoToDirectory(parentDirectory)
- end, 'Go Up', colours.black)
- new.PathTextBox = TextBox:Initialise(2, new.Height - 3, new.Width - 2, 1, new, new.CurrentDirectory, colours.white, colours.black)
- new:GoToDirectory(new.CurrentDirectory)
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Input = nil
- Current.Window = nil
- self = nil
- end,
- GoToDirectory = function(self, path)
- path = TidyPath(path)
- self.CurrentDirectory = path
- self.Scroll = 0
- self.SelectedFile = nil
- self.Typed = false
- self.PathTextBox.TextInput.Value = path
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- self.Files = _fs.list(self.CurrentDirectory)
- Draw()
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- Click = function(self, side, x, y)
- local items = {self.OpenButton, self.CancelButton, self.PathTextBox, self.GoUpButton}
- local found = false
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- found = true
- end
- end
- if not found then
- if y <= 12 then
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- self.SelectedFile = _fs.list(self.CurrentDirectory)[y-1]
- self.PathTextBox.TextInput.Value = TidyPath(self.CurrentDirectory .. '/' .. self.SelectedFile)
- Draw()
- end
- end
- return true
- end
- }
- ButtonDialougeWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- CancelButton = nil,
- OkButton = nil,
- Lines = {},
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- for i, text in ipairs(self.Lines) do
- Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
- end
- self.OkButton:Draw()
- if self.CancelButton then
- self.CancelButton:Draw()
- end
- end,
- Initialise = function(self, title, message, okText, cancelText, returnFunc)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 28
- new.Lines = WrapText(message, new.Width - 2)
- new.Height = 5 + #new.Lines
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = title
- new.Visible = true
- new.Visible = true
- new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
- returnFunc(new, true)
- end, okText)
- if cancelText then
- new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
- returnFunc(new, false)
- end, cancelText)
- end
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Window = nil
- self = nil
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- Click = function(self, side, x, y)
- local items = {self.OkButton, self.CancelButton}
- local found = false
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- found = true
- end
- end
- return true
- end
- }
- TextDialougeWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- CancelButton = nil,
- OkButton = nil,
- Lines = {},
- TextInput = nil,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- for i, text in ipairs(self.Lines) do
- Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y + self.Height - 4, self.Width - 2, 1, colours.lightGrey)
- Drawing.DrawCharacters(self.X + 2, self.Y + self.Height - 4, self.TextInput.Value, colours.black, colours.lightGrey)
- Current.CursorPos = {self.X + 2 + self.TextInput.CursorPos, self.Y + self.Height - 4}
- Current.CursorColour = colours.black
- self.OkButton:Draw()
- if self.CancelButton then
- self.CancelButton:Draw()
- end
- end,
- Initialise = function(self, title, message, okText, cancelText, returnFunc, numerical)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 28
- new.Lines = WrapText(message, new.Width - 2)
- new.Height = 7 + #new.Lines
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = title
- new.Visible = true
- new.Visible = true
- new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
- if #new.TextInput.Value > 0 then
- returnFunc(new, true, new.TextInput.Value)
- end
- end, okText)
- if cancelText then
- new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
- returnFunc(new, false)
- end, cancelText)
- end
- new.TextInput = TextInput:Initialise('', function(enter)
- if enter then
- new.OkButton:Click()
- end
- Draw()
- end, numerical)
- Current.Input = new.TextInput
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Window = nil
- Current.Input = nil
- self = nil
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- Click = function(self, side, x, y)
- local items = {self.OkButton, self.CancelButton}
- local found = false
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- found = true
- end
- end
- return true
- end
- }
- ResizeDocumentWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- Return = nil,
- OkButton = nil,
- AnchorPosition = 5,
- WidthLabelHighlight = false,
- HeightLabelHighlight = false,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- Drawing.DrawCharacters(self.X+1, self.Y+2, "New Size", colours.lightGrey, colours.white)
- if (#self.WidthTextBox.TextInput.Value > 0 and tonumber(self.WidthTextBox.TextInput.Value) < Current.Artboard.Width) or (#self.HeightTextBox.TextInput.Value > 0 and tonumber(self.HeightTextBox.TextInput.Value) < Current.Artboard.Height) then
- Drawing.DrawCharacters(self.X+1, self.Y+8, "Clipping will occur!", colours.red, colours.white)
- end
- local widthLabelColour = colours.black
- if self.WidthLabelHighlight then
- widthLabelColour = colours.red
- end
- local heightLabelColour = colours.black
- if self.HeightLabelHighlight then
- heightLabelColour = colours.red
- end
- Drawing.DrawCharacters(self.X+1, self.Y+4, "Width", widthLabelColour, colours.white)
- Drawing.DrawCharacters(self.X+1, self.Y+6, "Height", heightLabelColour, colours.white)
- Drawing.DrawCharacters(self.X+14, self.Y+2, "Anchor", colours.lightGrey, colours.white)
- self.WidthTextBox:Draw()
- self.HeightTextBox:Draw()
- self.OkButton:Draw()
- self.Anchor1:Draw()
- self.Anchor2:Draw()
- self.Anchor3:Draw()
- self.Anchor4:Draw()
- self.Anchor5:Draw()
- self.Anchor6:Draw()
- self.Anchor7:Draw()
- self.Anchor8:Draw()
- self.Anchor9:Draw()
- end,
- Initialise = function(self, returnFunc)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 27
- new.Height = 10
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = 'Resize Document'
- new.Visible = true
- new.WidthTextBox = TextBox:Initialise(9, 5, 4, 1, new, tostring(Current.Artboard.Width), nil, nil, function()
- new:UpdateAnchorButtons()
- end, true)
- new.HeightTextBox = TextBox:Initialise(9, 7, 4, 1, new, tostring(Current.Artboard.Height), nil, nil, function()
- new:UpdateAnchorButtons()
- end, true)
- new.OkButton = Button:Initialise(new.Width - 4, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- local ok = true
- new.WidthLabelHighlight = false
- new.HeightLabelHighlight = false
- if #new.WidthTextBox.TextInput.Value == 0 or tonumber(new.WidthTextBox.TextInput.Value) <= 0 then
- ok = false
- new.WidthLabelHighlight = true
- end
- if #new.HeightTextBox.TextInput.Value == 0 or tonumber(new.HeightTextBox.TextInput.Value) <= 0 then
- ok = false
- new.HeightLabelHighlight = true
- end
- if ok then
- returnFunc(new, tonumber(new.WidthTextBox.TextInput.Value), tonumber(new.HeightTextBox.TextInput.Value), new.AnchorPosition)
- else
- Draw()
- end
- end, 'Ok', colours.black)
- local anchorX = 15
- local anchorY = 5
- new.Anchor1 = Button:Initialise(anchorX, anchorY, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 1 new:UpdateAnchorButtons() end, ' ', colours.black)
- new.Anchor2 = Button:Initialise(anchorX+1, anchorY, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 2 new:UpdateAnchorButtons() end, '^', colours.black)
- new.Anchor3 = Button:Initialise(anchorX+2, anchorY, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 3 new:UpdateAnchorButtons() end, ' ', colours.black)
- new.Anchor4 = Button:Initialise(anchorX, anchorY+1, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 4 new:UpdateAnchorButtons() end, '<', colours.black)
- new.Anchor5 = Button:Initialise(anchorX+1, anchorY+1, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 5 new:UpdateAnchorButtons() end, '#', colours.black)
- new.Anchor6 = Button:Initialise(anchorX+2, anchorY+1, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 6 new:UpdateAnchorButtons() end, '>', colours.black)
- new.Anchor7 = Button:Initialise(anchorX, anchorY+2, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 7 new:UpdateAnchorButtons() end, ' ', colours.black)
- new.Anchor8 = Button:Initialise(anchorX+1, anchorY+2, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 8 new:UpdateAnchorButtons() end, 'v', colours.black)
- new.Anchor9 = Button:Initialise(anchorX+2, anchorY+2, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 9 new:UpdateAnchorButtons() end, ' ', colours.black)
- return new
- end,
- UpdateAnchorButtons = function(self)
- local anchor1 = ' '
- local anchor2 = ' '
- local anchor3 = ' '
- local anchor4 = ' '
- local anchor5 = ' '
- local anchor6 = ' '
- local anchor7 = ' '
- local anchor8 = ' '
- local anchor9 = ' '
- self.AnchorPosition = self.AnchorPosition or 5
- if self.AnchorPosition == 1 then
- anchor1 = '#'
- anchor2 = '>'
- anchor4 = 'v'
- elseif self.AnchorPosition == 2 then
- anchor1 = '<'
- anchor2 = '#'
- anchor3 = '>'
- anchor5 = 'v'
- elseif self.AnchorPosition == 3 then
- anchor2 = '<'
- anchor3 = '#'
- anchor6 = 'v'
- elseif self.AnchorPosition == 4 then
- anchor1 = '^'
- anchor4 = '#'
- anchor5 = '>'
- anchor7 = 'v'
- elseif self.AnchorPosition == 5 then
- anchor2 = '^'
- anchor4 = '<'
- anchor5 = '#'
- anchor6 = '>'
- anchor8 = 'v'
- elseif self.AnchorPosition == 6 then
- anchor3 = '^'
- anchor6 = '#'
- anchor5 = '<'
- anchor9 = 'v'
- elseif self.AnchorPosition == 7 then
- anchor4 = '^'
- anchor7 = '#'
- anchor8 = '>'
- elseif self.AnchorPosition == 8 then
- anchor5 = '^'
- anchor8 = '#'
- anchor7 = '<'
- anchor9 = '>'
- elseif self.AnchorPosition == 9 then
- anchor6 = '^'
- anchor9 = '#'
- anchor8 = '<'
- end
- if #self.HeightTextBox.TextInput.Value > 0 and Current.Artboard.Height > tonumber(self.HeightTextBox.TextInput.Value) then
- local r = function(str)
- if string.find(str, "%^") then
- str = str:gsub('%^','v')
- elseif string.find(str, "v") then
- str = str:gsub('v','%^')
- end
- return str
- end
- anchor1 = r(anchor1)
- anchor2 = r(anchor2)
- anchor3 = r(anchor3)
- anchor4 = r(anchor4)
- anchor5 = r(anchor5)
- anchor6 = r(anchor6)
- anchor7 = r(anchor7)
- anchor8 = r(anchor8)
- anchor9 = r(anchor9)
- end
- if #self.WidthTextBox.TextInput.Value > 0 and Current.Artboard.Width > tonumber(self.WidthTextBox.TextInput.Value) then
- local r = function(str)
- if string.find(str, ">") then
- str = str:gsub('>','<')
- elseif string.find(str, "<") then
- str = str:gsub('<','>')
- end
- return str
- end
- anchor1 = r(anchor1)
- anchor2 = r(anchor2)
- anchor3 = r(anchor3)
- anchor4 = r(anchor4)
- anchor5 = r(anchor5)
- anchor6 = r(anchor6)
- anchor7 = r(anchor7)
- anchor8 = r(anchor8)
- anchor9 = r(anchor9)
- end
- self.Anchor1.Text = anchor1
- self.Anchor2.Text = anchor2
- self.Anchor3.Text = anchor3
- self.Anchor4.Text = anchor4
- self.Anchor5.Text = anchor5
- self.Anchor6.Text = anchor6
- self.Anchor7.Text = anchor7
- self.Anchor8.Text = anchor8
- self.Anchor9.Text = anchor9
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Input = nil
- Current.Window = nil
- self = nil
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- ButtonClick = function(self, button, x, y)
- if button.X <= x and button.Y <= y and button.X + button.Width > x and button.Y + button.Height > y then
- button:Click()
- end
- end,
- Click = function(self, side, x, y)
- local items = {self.OkButton, self.WidthTextBox, self.HeightTextBox, self.Anchor1, self.Anchor2, self.Anchor3, self.Anchor4, self.Anchor5, self.Anchor6, self.Anchor7, self.Anchor8, self.Anchor9}
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- end
- end
- return true
- end
- }
- ----------------------
- function CheckOpenArtboard()
- if Current.Artboard then
- return true
- else
- return false
- end
- end
- function CheckSelectedLayer()
- if Current.Artboard and Current.Layer then
- return true
- else
- return false
- end
- end
- function DisplayNewDocumentWindow()
- NewDocumentWindow:Initialise(function(self, success, path, width, height, format, backgroundColour)
- if success then
- if path:sub(-4) ~= format then
- path = path .. format
- end
- local oldWindow = self
- Current.Input = nil
- Current.Window = nil
- makeDocument = function()oldWindow:Close()NewDocument(path, width, height, format, backgroundColour)end
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if _fs.exists(path) then
- ButtonDialougeWindow:Initialise('File Exists', path..' already exists! Use a different name and try again.', 'Ok', nil, function(window, ok)
- window:Close()
- oldWindow:Show()
- end):Show()
- elseif format == '.nfp' then
- Current.Window = nil
- ButtonDialougeWindow:Initialise('Use NFP?', 'The NFT format does not support text or layers, if you use it you will only be able to use 1 layer and not have any text.', 'Use NFP', 'Cancel', function(window, ok)
- window:Close()
- if ok then
- makeDocument()
- else
- oldWindow:Show()
- end
- end):Show()
- elseif format == '.nft' then
- ButtonDialougeWindow:Initialise('Use NFT?', 'The NFT format does not support layers, if you use it you will only be able to use 1 layer.', 'Use NFT', 'Cancel', function(window, ok)
- window:Close()
- if ok then
- makeDocument()
- else
- oldWindow:Show()
- end
- end):Show()
- else
- makeDocument()
- end
- else
- self:Close()
- end
- end):Show()
- end
- function NewDocument(path, width, height, format, backgroundColour)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- ab = Artboard:New(_fs.getName(path), path, width, height, format, backgroundColour)
- Current.Tool = Tools[2]
- Current.Toolbar:Update()
- Current.Modified = false
- Draw()
- end
- function DisplayToolSizeWindow()
- if not CheckOpenArtboard() then
- return
- end
- TextDialougeWindow:Initialise('Change Tool Size', 'Enter the new tool size you\'d like to use.', 'Ok', 'Cancel', function(window, success, value)
- if success then
- Current.ToolSize = math.ceil(tonumber(value))
- if Current.ToolSize < 1 then
- Current.ToolSize = 1
- elseif Current.ToolSize > 50 then
- Current.ToolSize = 50
- end
- ModuleNamed('Tools'):Update()
- end
- window:Close()
- end, true):Show()
- end
- --[[
- Attempt to figure out what format the image is if it doesn't have an extension
- ]]--
- function GetFormat(path)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- local file = _fs.open(path, 'r')
- local content = file.readAll()
- file.close()
- if type(textutils.unserialize(content)) == 'table' then
- -- It's a serlized table, asume sketch
- return '.skch'
- elseif string.find(content, string.char(30)) or string.find(content, string.char(31)) then
- -- Contains the characters that set colours, asume nft
- return '.nft'
- else
- -- Otherwise asume nfp
- return '.nfp'
- end
- end
- function DisplayOpenDocumentWindow()
- OpenDocumentWindow:Initialise(function(self, success, path)
- self:Close()
- if success then
- OpenDocument(path)
- end
- end):Show()
- end
- local function Extension(path, addDot)
- if not path then
- return nil
- elseif not string.find(fs.getName(path), '%.') then
- if not addDot then
- return fs.getName(path)
- else
- return ''
- end
- else
- local _path = path
- if path:sub(#path) == '/' then
- _path = path:sub(1,#path-1)
- end
- local extension = _path:gmatch('[0-9a-z]+$')()
- if extension then
- extension = extension:sub(2)
- else
- --extension = nil
- return ''
- end
- if addDot then
- extension = '.'..extension
- end
- return extension:lower()
- end
- end
- local RemoveExtension = function(path)
- if path:sub(1,1) == '.' then
- return path
- end
- local extension = Extension(path)
- if extension == path then
- return fs.getName(path)
- end
- return string.gsub(path, extension, ''):sub(1, -2)
- end
- --[[
- Open a documet at a given path
- ]]--
- function OpenDocument(path)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if _fs.exists(path) and not _fs.isDir(path) then
- local format = Extension(path, true)
- if (not format or format == '') and (format ~= '.nfp' and format ~= '.nft' and format ~= '.skch') then
- format = GetFormat(path)
- end
- local layers = {}
- if format == '.nfp' then
- layers = ReadNFP(path)
- elseif format == '.nft' then
- layers = ReadNFT(path)
- elseif format == '.skch' then
- layers = ReadSKCH(path)
- end
- for i, layer in ipairs(layers) do
- if layer.Visible == nil then
- layer.Visible = true
- end
- if layer.Index == nil then
- layer.Index = 1
- end
- if layer.Name == nil then
- if layer.Index == 1 then
- layer.Name = 'Background'
- else
- layer.Name = 'Layer'
- end
- end
- if layer.BackgroundColour == nil then
- layer.BackgroundColour = colours.white
- end
- end
- if not layers[1] then
- --log('File could not be read.')
- return
- end
- local width = #layers[1].Pixels
- local height = #layers[1].Pixels[1]
- Current.Artboard = nil
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- ab = Artboard:New(_fs.getName('Image'), path, width, height, format, nil, layers)
- Current.Tool = Tools[2]
- Current.Toolbar:Update()
- Current.Modified = false
- Draw()
- end
- end
- function MakeNewLayer()
- if not CheckOpenArtboard() then
- return
- end
- if Current.Artboard.Format == '.skch' then
- TextDialougeWindow:Initialise('New Layer Name', 'Enter the name you want for the next layer.', 'Ok', 'Cancel', function(window, success, value)
- if success then
- Current.Artboard:MakeLayer(value, colours.transparent)
- end
- window:Close()
- end):Show()
- else
- local format = 'NFP'
- if Current.Artboard.Format == '.nft' then
- format = 'NFT'
- end
- ButtonDialougeWindow:Initialise(format..' does not support layers!', 'The format you are using, '..format..', does not support multiple layers. Use SKCH to have more than one layer.', 'Ok', nil, function(window)
- window:Close()
- end):Show()
- end
- end
- function ResizeDocument()
- if not CheckOpenArtboard() then
- return
- end
- ResizeDocumentWindow:Initialise(function(window, width, height, anchor)
- window:Close()
- local topResize = 0
- local rightResize = 0
- local bottomResize = 0
- local leftResize = 0
- if anchor == 1 then
- rightResize = 1
- bottomResize = 1
- elseif anchor == 2 then
- rightResize = 0.5
- leftResize = 0.5
- bottomResize = 1
- elseif anchor == 3 then
- leftResize = 1
- bottomResize = 1
- elseif anchor == 4 then
- rightResize = 1
- bottomResize = 0.5
- topResize = 0.5
- elseif anchor == 5 then
- rightResize = 0.5
- leftResize = 0.5
- bottomResize = 0.5
- topResize = 0.5
- elseif anchor == 6 then
- leftResize = 1
- bottomResize = 0.5
- topResize = 0.5
- elseif anchor == 7 then
- rightResize = 1
- topResize = 1
- elseif anchor == 8 then
- rightResize = 0.5
- leftResize = 0.5
- topResize = 1
- elseif anchor == 9 then
- leftResize = 1
- topResize = 1
- end
- topResize = topResize * (height - Current.Artboard.Height)
- if topResize > 0 then
- topResize = math.floor(topResize)
- else
- topResize = math.ceil(topResize)
- end
- bottomResize = bottomResize * (height - Current.Artboard.Height)
- if bottomResize > 0 then
- bottomResize = math.ceil(bottomResize)
- else
- bottomResize = math.floor(bottomResize)
- end
- leftResize = leftResize * (width - Current.Artboard.Width)
- if leftResize > 0 then
- leftResize = math.floor(leftResize)
- else
- leftResize = math.ceil(leftResize)
- end
- rightResize = rightResize * (width - Current.Artboard.Width)
- if rightResize > 0 then
- rightResize = math.ceil(rightResize)
- else
- rightResize = math.floor(rightResize)
- end
- Current.Artboard:Resize(topResize, bottomResize, leftResize, rightResize)
- end):Show()
- end
- function RenameLayer()
- if not CheckOpenArtboard() then
- return
- end
- if Current.Artboard.Format == '.skch' then
- TextDialougeWindow:Initialise("Rename Layer '"..Current.Layer.Name.."'", 'Enter the new name you want the layer to be called.', 'Ok', 'Cancel', function(window, success, value)
- if success then
- Current.Layer.Name = value
- end
- window:Close()
- end):Show()
- else
- local format = 'NFP'
- if Current.Artboard.Format == '.nft' then
- format = 'NFT'
- end
- ButtonDialougeWindow:Initialise(format..' does not support layers!', 'The format you are using, '..format..', does not support renaming layers. Use SKCH to rename layers.', 'Ok', nil, function(window)
- window:Close()
- end):Show()
- end
- end
- function DeleteLayer()
- if not CheckOpenArtboard() then
- return
- end
- if Current.Artboard.Format == '.skch' then
- if #Current.Artboard.Layers > 1 then
- ButtonDialougeWindow:Initialise("Delete Layer '"..Current.Layer.Name.."'?", 'Are you sure you want delete the layer?', 'Ok', 'Cancel', function(window, success)
- if success then
- Current.Layer:Remove()
- end
- window:Close()
- end):Show()
- else
- ButtonDialougeWindow:Initialise('Can not delete layer!', 'You can not delete the last layer of an image! Make another layer to delete this one.', 'Ok', nil, function(window)
- window:Close()
- end):Show()
- end
- else
- local format = 'NFP'
- if Current.Artboard.Format == '.nft' then
- format = 'NFT'
- end
- ButtonDialougeWindow:Initialise(format..' does not support layers!', 'The format you are using, '..format..', does not support deleting layers. Use SKCH to deleting layers.', 'Ok', nil, function(window)
- window:Close()
- end):Show()
- end
- end
- needsDraw = false
- isDrawing = false
- function Draw()
- if isDrawing then
- needsDraw = true
- return
- end
- needsDraw = false
- isDrawing = true
- if not Current.Window then
- Drawing.Clear(UIColours.Background)
- else
- Drawing.DrawArea(1, 2, Drawing.Screen.Width, Drawing.Screen.Height, '|', colours.black, colours.lightGrey)
- end
- if Current.Artboard then
- ab:Draw()
- end
- if Current.InterfaceVisible then
- Current.MenuBar:Draw()
- Current.Toolbar.Width = Current.Toolbar.ExpandedWidth
- Current.Toolbar:Draw()
- else
- Current.Toolbar.Width = Current.Toolbar.ExpandedWidth
- end
- if Current.InterfaceVisible and Current.Menu then
- Current.Menu:Draw()
- end
- if Current.Window then
- Current.Window:Draw()
- end
- if not Current.InterfaceVisible then
- ShowInterfaceButton:Draw()
- end
- Drawing.DrawBuffer()
- if Current.Input and not Current.Menu then
- term.setCursorPos(Current.CursorPos[1], Current.CursorPos[2])
- term.setCursorBlink(true)
- term.setTextColour(Current.CursorColour)
- else
- term.setCursorBlink(false)
- end
- if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- Current.SelectionDrawTimer = os.startTimer(0.5)
- end
- isDrawing = false
- if needsDraw then
- Draw()
- end
- end
- function LoadMenuBar()
- Current.MenuBar = MenuBar:Initialise({
- Button:Initialise(1, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if toggle then
- Menu:New(1, 2, {
- {
- Title = "New...",
- Click = function()
- DisplayNewDocumentWindow()
- end,
- Keys = {
- keys.leftCtrl,
- keys.n
- }
- },
- {
- Title = 'Open...',
- Click = function()
- DisplayOpenDocumentWindow()
- end,
- Keys = {
- keys.leftCtrl,
- keys.o
- }
- },
- {
- Separator = true
- },
- {
- Title = 'Save...',
- Click = function()
- Current.Artboard:Save()
- end,
- Keys = {
- keys.leftCtrl,
- keys.s
- },
- Enabled = function()
- return CheckOpenArtboard()
- end
- },
- {
- Separator = true
- },
- {
- Title = 'Quit',
- Click = function()
- if Close() then
- OneOS.Close()
- end
- end
- },
- --[[
- {
- Title = 'Save As...',
- Click = function()
- end
- }
- ]]--
- }, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'File', colours.lightGrey, false),
- Button:Initialise(7, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if not self.Toggle then
- Menu:New(7, 2, {
- --[[
- {
- Title = "Undo",
- Click = function()
- end,
- Keys = {
- keys.leftCtrl,
- keys.z
- },
- Enabled = function()
- return false
- end
- },
- {
- Title = 'Redo',
- Click = function()
- end,
- Keys = {
- keys.leftCtrl,
- keys.y
- },
- Enabled = function()
- return false
- end
- },
- {
- Separator = true
- },
- ]]--
- {
- Title = 'Cut',
- Click = function()
- Clipboard.Cut(Current.Layer:PixelsInSelection(true), 'sketchpixels')
- end,
- Keys = {
- keys.leftCtrl,
- keys.x
- },
- Enabled = function()
- return Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
- end
- },
- {
- Title = 'Copy',
- Click = function()
- Clipboard.Copy(Current.Layer:PixelsInSelection(), 'sketchpixels')
- end,
- Keys = {
- keys.leftCtrl,
- keys.c
- },
- Enabled = function()
- return Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
- end
- },
- {
- Title = 'Paste',
- Click = function()
- Current.Layer:InsertPixels(Clipboard.Paste())
- end,
- Keys = {
- keys.leftCtrl,
- keys.v
- },
- Enabled = function()
- return (not Clipboard.isEmpty()) and Clipboard.Type == 'sketchpixels'
- end
- }
- }, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'Edit', colours.lightGrey, false),
- Button:Initialise(13, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if toggle then
- Menu:New(13, 2, {
- {
- Title = "Resize...",
- Click = function()
- ResizeDocument()
- end,
- Keys = {
- keys.leftCtrl,
- keys.r
- },
- Enabled = function()
- return CheckOpenArtboard()
- end
- },
- {
- Title = "Crop",
- Click = function()
- local top = 0
- local left = 0
- local bottom = 0
- local right = 0
- if Current.Selection[1].x < Current.Selection[2].x then
- left = Current.Selection[1].x - 1
- right = Current.Artboard.Width - Current.Selection[2].x
- else
- left = Current.Selection[2].x - 1
- right = Current.Artboard.Width - Current.Selection[1].x
- end
- if Current.Selection[1].y < Current.Selection[2].y then
- top = Current.Selection[1].y - 1
- bottom = Current.Artboard.Height - Current.Selection[2].y
- else
- top = Current.Selection[2].y - 1
- bottom = Current.Artboard.Height - Current.Selection[1].y
- end
- Current.Artboard:Resize(-1*top, -1*bottom, -1*left, -1*right)
- Current.Selection[2] = nil
- end,
- Enabled = function()
- if CheckSelectedLayer() and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- return true
- else
- return false
- end
- end
- },
- {
- Separator = true
- },
- {
- Title = 'New Layer...',
- Click = function()
- MakeNewLayer()
- end,
- Keys = {
- keys.leftCtrl,
- keys.l
- },
- Enabled = function()
- return CheckOpenArtboard()
- end
- },
- {
- Title = 'Delete Layer',
- Click = function()
- DeleteLayer()
- end,
- Enabled = function()
- return CheckSelectedLayer()
- end
- },
- {
- Title = 'Rename Layer...',
- Click = function()
- RenameLayer()
- end,
- Enabled = function()
- return CheckSelectedLayer()
- end
- },
- {
- Separator = true
- },
- {
- Title = 'Erase Selection',
- Click = function()
- Current.Layer:EraseSelection()
- end,
- Keys = {
- keys.delete
- },
- Enabled = function()
- if CheckSelectedLayer() and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- return true
- else
- return false
- end
- end
- },
- {
- Separator = true
- },
- {
- Title = 'Hide Interface',
- Click = function()
- Current.InterfaceVisible = not Current.InterfaceVisible
- end,
- Keys = {
- keys.tab
- }
- }
- }, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'Image', colours.lightGrey, false),
- Button:Initialise(20, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if toggle then
- local menuItems = {{
- Title = "Change Size",
- Click = function()
- DisplayToolSizeWindow()
- end,
- Keys = {
- keys.leftCtrl,
- keys.t
- }
- },
- {
- Separator = true
- }
- }
- local _keys = {'h','p','e','f','s','m','t'}
- for i, tool in ipairs(Tools) do
- table.insert(menuItems, {
- Title = tool.Name,
- Click = function()
- SetTool(tool)
- local m = ModuleNamed('Tools')
- m:Update(m.ToolbarItem)
- end,
- Keys = {
- keys[_keys[i]]
- },
- Enabled = function()
- return CheckOpenArtboard()
- end
- })
- end
- Menu:New(20, 2, menuItems, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'Tools', colours.lightGrey, false),
- })
- end
- function Timer(event, timer)
- if timer == Current.ControlPressedTimer then
- Current.ControlPressedTimer = nil
- elseif timer == Current.SelectionDrawTimer then
- if Current.Artboard then
- Current.Artboard.SelectionIsBlack = not Current.Artboard.SelectionIsBlack
- Draw()
- end
- end
- end
- function Initialise(arg)
- if not OneOS then
- SplashScreen()
- end
- EventRegister('mouse_click', TryClick)
- EventRegister('mouse_drag', function(event, side, x, y)TryClick(event, side, x, y, true)end)
- EventRegister('mouse_scroll', Scroll)
- EventRegister('key', HandleKey)
- EventRegister('char', HandleKey)
- EventRegister('timer', Timer)
- EventRegister('terminate', function(event) if Close() then error( "Terminated", 0 ) end end)
- Current.Toolbar = Toolbar:New('right', true)
- for k, v in pairs(Modules) do
- v:Initialise()
- end
- --term.setBackgroundColour(UIColours.Background)
- --term.clear()
- LoadMenuBar()
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if arg and _fs.exists(arg) then
- OpenDocument(arg)
- else
- DisplayNewDocumentWindow()
- Current.Window.Visible = false
- end
- ShowInterfaceButton = Button:Initialise(Drawing.Screen.Width - 15, 1, nil, 1, colours.grey, nil, function(self)
- Current.InterfaceVisible = true
- Draw()
- end, 'Show Interface')
- Draw()
- if Current.Window then
- Current.Window.Visible = true
- Draw()
- end
- EventHandler()
- end
- function SplashScreen()
- local splashIcon = {{1,1,1,256,256,256,256,256,256,256,256,1,1,1,},{1,256,256,8,8,8,8,8,8,8,8,256,256,1,},{256,8,8,8,8,8,8,8,8,8,8,8,8,256,},{256,256,256,8,8,8,8,8,8,8,8,256,256,256,},{256,256,256,256,256,256,256,256,256,256,256,256,256,256,},{2048,2048,256,256,256,256,256,256,256,256,256,256,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{256,256,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,256,256,},{1,256,256,256,256,256,256,256,256,256,256,256,256,1,},{1,1,1,256,256,256,256,256,256,256,256,1,1,1,},["text"]={{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," ","S","k","e","t","c","h"," "," "," "," ",},{" "," "," "," "," "," ","b","y"," "," "," "," "," "," ",},{" "," "," "," "," ","o","e","e","d"," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},},["textcol"]={{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,256,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,1,1,1,1,1,1,32768,32768,32768,32768,},{32768,32768,32768,32768,8,8,8,8,8,8,8,32768,32768,32768,},{32768,32768,32768,32768,1,1,1,1,1,32768,8,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},},}
- Drawing.Clear(colours.white)
- Drawing.DrawImage((Drawing.Screen.Width - 14)/2, (Drawing.Screen.Height - 13)/2, splashIcon, 14, 13)
- Drawing.DrawBuffer()
- parallel.waitForAny(function()sleep(1)end, function()os.pullEvent('mouse_click')end)
- end
- LongestString = function(input, key)
- local length = 0
- for i = 1, #input do
- local value = input[i]
- if key then
- if value[key] then
- value = value[key]
- else
- value = ''
- end
- end
- local titleLength = string.len(value)
- if titleLength > length then
- length = titleLength
- end
- end
- return length
- end
- function HandleKey(...)
- local args = {...}
- local event = args[1]
- local keychar = args[2]
- if event == 'key' and Current.Tool and Current.Tool.Name == 'Text' and Current.Input and (keychar == keys.up or keychar == keys.down or keychar == keys.left or keychar == keys.right) then
- local currentPos = {Current.CursorPos[1] - Current.Artboard.X + 1, Current.CursorPos[2] - Current.Artboard.Y + 1}
- if keychar == keys.up then
- currentPos[2] = currentPos[2] - 1
- elseif keychar == keys.down then
- currentPos[2] = currentPos[2] + 1
- elseif keychar == keys.left then
- currentPos[1] = currentPos[1] - 1
- elseif keychar == keys.right then
- currentPos[1] = currentPos[1] + 1
- end
- if currentPos[1] < 1 then
- currentPos[1] = 1
- end
- if currentPos[1] > Current.Artboard.Width then
- currentPos[1] = Current.Artboard.Width
- end
- if currentPos[2] < 1 then
- currentPos[2] = 1
- end
- if currentPos[2] > Current.Artboard.Height then
- currentPos[2] = Current.Artboard.Height
- end
- Current.Tool:Use(currentPos[1], currentPos[2])
- Current.Modified = true
- Draw()
- elseif Current.Input then
- if event == 'char' then
- Current.Input:Char(keychar)
- elseif event == 'key' then
- Current.Input:Key(keychar)
- end
- elseif event == 'key' then
- CheckKeyboardShortcut(keychar)
- end
- end
- function Scroll(event, direction, x, y)
- if Current.Window and Current.Window.OpenButton then
- Current.Window.Scroll = Current.Window.Scroll + direction
- if Current.Window.Scroll < 0 then
- Current.Window.Scroll = 0
- elseif Current.Window.Scroll > Current.Window.MaxScroll then
- Current.Window.Scroll = Current.Window.MaxScroll
- end
- end
- Draw()
- end
- function CheckKeyboardShortcut(key)
- local shortcuts = {}
- if key == keys.leftCtrl then
- Current.ControlPressedTimer = os.startTimer(0.5)
- return
- end
- if Current.ControlPressedTimer then
- shortcuts[keys.n] = function() DisplayNewDocumentWindow() end
- shortcuts[keys.o] = function() DisplayOpenDocumentWindow() end
- shortcuts[keys.s] = function() Current.Artboard:Save() end
- shortcuts[keys.x] = function() if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then Clipboard.Cut(Current.Layer:PixelsInSelection(true), 'sketchpixels') end end
- shortcuts[keys.c] = function() if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then Clipboard.Copy(Current.Layer:PixelsInSelection(), 'sketchpixels') end end
- shortcuts[keys.v] = function() if (not Clipboard.isEmpty()) and Clipboard.Type == 'sketchpixels' then Current.Layer:InsertPixels(Clipboard.Paste()) end end
- shortcuts[keys.r] = function() ResizeDocument() end
- shortcuts[keys.l] = function() MakeNewLayer() end
- end
- shortcuts[keys.delete] = function() if CheckSelectedLayer() and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then Current.Layer:EraseSelection() Draw() end end
- shortcuts[keys.backspace] = shortcuts[keys.delete]
- shortcuts[keys.tab] = function() Current.InterfaceVisible = not Current.InterfaceVisible Draw() end
- shortcuts[keys.h] = function() SetTool(ToolNamed('Hand')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.e] = function() SetTool(ToolNamed('Eraser')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.p] = function() SetTool(ToolNamed('Pencil')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.f] = function() SetTool(ToolNamed('Fill Bucket')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.m] = function() SetTool(ToolNamed('Move')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.s] = function() SetTool(ToolNamed('Select')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.t] = function() SetTool(ToolNamed('Text')) ModuleNamed('Tools'):Update() Draw() end
- if shortcuts[key] then
- shortcuts[key]()
- return true
- else
- return false
- end
- end
- --[[
- Check if the given object falls under the click coordinates
- ]]--
- function CheckClick(object, x, y)
- if object.X <= x and object.Y <= y and object.X + object.Width > x and object.Y + object.Height > y then
- return true
- end
- end
- --[[
- Attempt to clicka given object
- ]]--
- function DoClick(object, side, x, y, drag)
- if object and CheckClick(object, x, y) then
- return object:Click(side, x - object.X + 1, y - object.Y + 1, drag)
- end
- end
- --[[
- Try to click at the given coordinates
- ]]--
- function TryClick(event, side, x, y, drag)
- if Current.InterfaceVisible and Current.Menu then
- if DoClick(Current.Menu, side, x, y, drag) then
- Draw()
- return
- else
- if Current.Menu.Owner and Current.Menu.Owner.Toggle then
- Current.Menu.Owner.Toggle = false
- end
- Current.Menu = nil
- Draw()
- return
- end
- elseif Current.Window then
- if DoClick(Current.Window, side, x, y, drag) then
- Draw()
- return
- else
- Current.Window:Flash()
- return
- end
- end
- local interfaceElements = {}
- if Current.InterfaceVisible then
- table.insert(interfaceElements, Current.MenuBar)
- else
- table.insert(interfaceElements, ShowInterfaceButton)
- end
- for i, v in ipairs(Lists.Interface.Toolbars) do
- for i, v2 in ipairs(v.ToolbarItems) do
- table.insert(interfaceElements, v2)
- end
- table.insert(interfaceElements, v)
- end
- table.insert(interfaceElements, Current.Artboard)
- for i, object in ipairs(interfaceElements) do
- if DoClick(object, side, x, y, drag) then
- Draw()
- return
- end
- end
- Draw()
- end
- --[[
- Registers functions to run on certain events
- ]]--
- function EventRegister(event, func)
- if not Events[event] then
- Events[event] = {}
- end
- table.insert(Events[event], func)
- end
- --[[
- The main loop event handler, runs registered event functinos
- ]]--
- function EventHandler()
- while true do
- local event, arg1, arg2, arg3, arg4 = os.pullEventRaw()
- if Events[event] then
- for i, e in ipairs(Events[event]) do
- e(event, arg1, arg2, arg3, arg4)
- end
- end
- end
- end
- --[[
- Thanks to NitrogenFingers for the colour functions and NFT + NFP read/write functions
- ]]--
- --[[
- Gets the hex value from a colour
- ]]--
- local hexnums = { [10] = "a", [11] = "b", [12] = "c", [13] = "d", [14] = "e" , [15] = "f" }
- local function getHexOf(colour)
- if colour == colours.transparent or not colour or not tonumber(colour) then
- return " "
- end
- local value = math.log(colour)/math.log(2)
- if value > 9 then
- value = hexnums[value]
- end
- return value
- end
- --[[
- Gets the colour from a hex value
- ]]--
- local function getColourOf(hex)
- if hex == ' ' then
- return colours.transparent
- end
- local value = tonumber(hex, 16)
- if not value then return nil end
- value = math.pow(2,value)
- return value
- end
- --[[
- Saves the current artboard in .skch format
- ]]--
- function SaveSKCH()
- local layers = {}
- for i, l in ipairs(Current.Artboard.Layers) do
- local pixels = SaveNFT(i)
- local layer = {
- Name = l.Name,
- Pixels = pixels,
- BackgroundColour = l.BackgroundColour,
- Visible = l.Visible,
- Index = l.Index,
- }
- table.insert(layers, layer)
- end
- return layers
- end
- --[[
- Saves the current artboard in .nft format
- ]]--
- function SaveNFT(layer)
- layer = layer or 1
- local lines = {}
- local width = Current.Artboard.Width
- local height = Current.Artboard.Height
- for y = 1, height do
- local line = ''
- local currentBackgroundColour = nil
- local currentTextColour = nil
- for x = 1, width do
- local pixel = Current.Artboard.Layers[layer].Pixels[x][y]
- if pixel.BackgroundColour ~= currentBackgroundColour then
- line = line..string.char(30)..getHexOf(pixel.BackgroundColour)
- currentBackgroundColour = pixel.BackgroundColour
- end
- if pixel.TextColour ~= currentTextColour then
- line = line..string.char(31)..getHexOf(pixel.TextColour)
- currentTextColour = pixel.TextColour
- end
- line = line .. pixel.Character
- end
- table.insert(lines, line)
- end
- return lines
- end
- --[[
- Saves the current artboard in .nfp format
- ]]--
- function SaveNFP()
- local lines = {}
- local width = Current.Artboard.Width
- local height = Current.Artboard.Height
- for y = 1, height do
- local line = ''
- for x = 1, width do
- line = line .. getHexOf(Current.Artboard.Layers[1].Pixels[x][y].BackgroundColour)
- end
- table.insert(lines, line)
- end
- return lines
- end
- --[[
- Reads a .nfp file from the given path
- ]]--
- function ReadNFP(path)
- local pixels = {}
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- local file = _fs.open(path, 'r')
- local line = file.readLine()
- local y = 1
- while line do
- for x = 1, #line do
- if not pixels[x] then
- pixels[x] = {}
- end
- pixels[x][y] = {BackgroundColour = getColourOf(line:sub(x,x))}
- end
- y = y + 1
- line = file.readLine()
- end
- file.close()
- return {{Pixels = pixels}}
- end
- --[[
- Reads a .nft file from the given path
- ]]--
- function ReadNFT(path)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- local file = _fs.open(path, 'r')
- local line = file.readLine()
- local lines = {}
- while line do
- table.insert(lines, line)
- line = file.readLine()
- end
- file.close()
- return {{Pixels = ParseNFT(lines)}}
- end
- --[[
- Converts the lines of an .nft document to readble pixel data
- ]]--
- function ParseNFT(lines)
- local pixels = {}
- for y, line in ipairs(lines) do
- local bgNext, fgNext = false, false
- local currBG, currFG = nil,nil
- local writePosition = 1
- for x = 1, #line do
- if not pixels[writePosition] then
- pixels[writePosition] = {}
- end
- local nextChar = string.sub(line, x, x)
- if nextChar:byte() == 30 then
- bgNext = true
- elseif nextChar:byte() == 31 then
- fgNext = true
- elseif bgNext then
- currBG = getColourOf(nextChar)
- if currBG == nil then
- currBG = colours.transparent
- end
- bgNext = false
- elseif fgNext then
- currFG = getColourOf(nextChar)
- fgNext = false
- else
- if nextChar ~= " " and currFG == nil then
- currFG = colours.white
- end
- pixels[writePosition][y] = {BackgroundColour = currBG, TextColour = currFG, Character = nextChar}
- writePosition = writePosition + 1
- end
- end
- end
- return pixels
- end
- --[[
- Read a .skch file from the given path
- ]]--
- function ReadSKCH(path)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- local file = _fs.open(path, 'r')
- local _layers = textutils.unserialize(file.readAll())
- file.close()
- local layers = {}
- for i, l in ipairs(_layers) do
- local layer = {
- Name = l.Name,
- Pixels = ParseNFT(l.Pixels),
- BackgroundColour = l.BackgroundColour,
- Visible = l.Visible,
- Index = l.Index,
- }
- table.insert(layers, layer)
- end
- return layers
- end
- --[[
- Start the program after all functions and tables are loaded
- ]]--
- if term.isColor and term.isColor() then
- Initialise()
- else
- print('Sorry, but Sketch only works on Advanced (gold) Computers')
- end
- end
- function oeed_ink()
- tArgs = {}
- if OneOS then
- --running under OneOS
- OneOS.ToolBarColour = colours.grey
- OneOS.ToolBarTextColour = colours.white
- end
- local _w, _h = term.getSize()
- local round = function(num, idp)
- local mult = 10^(idp or 0)
- return math.floor(num * mult + 0.5) / mult
- end
- UIColours = {
- Toolbar = colours.grey,
- ToolbarText = colours.lightGrey,
- ToolbarSelected = colours.lightBlue,
- ControlText = colours.white,
- ToolbarItemTitle = colours.black,
- Background = colours.lightGrey,
- MenuBackground = colours.white,
- MenuText = colours.black,
- MenuSeparatorText = colours.grey,
- MenuDisabledText = colours.lightGrey,
- Shadow = colours.grey,
- TransparentBackgroundOne = colours.white,
- TransparentBackgroundTwo = colours.lightGrey,
- MenuBarActive = colours.white
- }
- local getNames = peripheral.getNames or function()
- local tResults = {}
- for n,sSide in ipairs( rs.getSides() ) do
- if peripheral.isPresent( sSide ) then
- table.insert( tResults, sSide )
- local isWireless = false
- if not pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then
- isWireless = true
- end
- if peripheral.getType( sSide ) == "modem" and not isWireless then
- local tRemote = peripheral.call( sSide, "getNamesRemote" )
- for n,sName in ipairs( tRemote ) do
- table.insert( tResults, sName )
- end
- end
- end
- end
- return tResults
- end
- Peripheral = {
- GetPeripheral = function(_type)
- for i, p in ipairs(Peripheral.GetPeripherals()) do
- if p.Type == _type then
- return p
- end
- end
- end,
- Call = function(type, ...)
- local tArgs = {...}
- local p = Peripheral.GetPeripheral(type)
- peripheral.call(p.Side, unpack(tArgs))
- end,
- GetPeripherals = function(filterType)
- local peripherals = {}
- for i, side in ipairs(getNames()) do
- local name = peripheral.getType(side):gsub("^%l", string.upper)
- local code = string.upper(side:sub(1,1))
- if side:find('_') then
- code = side:sub(side:find('_')+1)
- end
- local dupe = false
- for i, v in ipairs(peripherals) do
- if v[1] == name .. ' ' .. code then
- dupe = true
- end
- end
- if not dupe then
- local _type = peripheral.getType(side)
- local isWireless = false
- if _type == 'modem' then
- if not pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then
- isWireless = true
- end
- if isWireless then
- _type = 'wireless_modem'
- name = 'W '..name
- end
- end
- if not filterType or _type == filterType then
- table.insert(peripherals, {Name = name:sub(1,8) .. ' '..code, Fullname = name .. ' ('..side:sub(1, 1):upper() .. side:sub(2, -1)..')', Side = side, Type = _type, Wireless = isWireless})
- end
- end
- end
- return peripherals
- end,
- PresentNamed = function(name)
- return peripheral.isPresent(name)
- end,
- CallType = function(type, ...)
- local tArgs = {...}
- local p = GetPeripheral(type)
- return peripheral.call(p.Side, unpack(tArgs))
- end,
- CallNamed = function(name, ...)
- local tArgs = {...}
- return peripheral.call(name, unpack(tArgs))
- end
- }
- TextLine = {
- Text = "",
- Alignment = AlignmentLeft,
- Initialise = function(self, text, alignment)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Text = text
- new.Alignment = alignment or AlignmentLeft
- return new
- end
- }
- local StripColours = function(str)
- return str:gsub('['..string.char(14)..'-'..string.char(29)..']','')
- end
- Printer = {
- Name = nil,
- PeripheralType = 'printer',
- paperLevel = function(self)
- return Peripheral.CallNamed(self.Name, 'getPaperLevel')
- end,
- newPage = function(self)
- return Peripheral.CallNamed(self.Name, 'newPage')
- end,
- endPage = function(self)
- return Peripheral.CallNamed(self.Name, 'endPage')
- end,
- pageWrite = function(self, text)
- return Peripheral.CallNamed(self.Name, 'write', text)
- end,
- setPageTitle = function(self, title)
- return Peripheral.CallNamed(self.Name, 'setPageTitle', title)
- end,
- inkLevel = function(self)
- return Peripheral.CallNamed(self.Name, 'getInkLevel')
- end,
- getCursorPos = function(self)
- return Peripheral.CallNamed(self.Name, 'getCursorPos')
- end,
- setCursorPos = function(self, x, y)
- return Peripheral.CallNamed(self.Name, 'setCursorPos', x, y)
- end,
- pageSize = function(self)
- return Peripheral.CallNamed(self.Name, 'getPageSize')
- end,
- Present = function()
- if Peripheral.GetPeripheral(Printer.PeripheralType) == nil then
- return false
- else
- return true
- end
- end,
- PrintLines = function(self, lines, title, copies)
- local pages = {}
- local pageLines = {}
- for i, line in ipairs(lines) do
- table.insert(pageLines, TextLine:Initialise(StripColours(line)))
- if i % 25 == 0 then
- table.insert(pages, pageLines)
- pageLines = {}
- end
- end
- if #pageLines ~= 0 then
- table.insert(pages, pageLines)
- end
- return self:PrintPages(pages, title, copies)
- end,
- PrintPages = function(self, pages, title, copies)
- copies = copies or 1
- for c = 1, copies do
- for p, page in ipairs(pages) do
- if self:paperLevel() < #pages * copies then
- return 'Add more paper to the printer'
- end
- if self:inkLevel() < #pages * copies then
- return 'Add more ink to the printer'
- end
- self:newPage()
- for i, line in ipairs(page) do
- self:setCursorPos(1, i)
- self:pageWrite(StripColours(line.Text))
- end
- if title then
- self:setPageTitle(title)
- end
- self:endPage()
- end
- end
- end,
- Initialise = function(self, name)
- if Printer.Present() then --fix
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- if name and Peripheral.PresentNamed(name) then
- new.Name = name
- else
- new.Name = Peripheral.GetPeripheral(Printer.PeripheralType).Side
- end
- return new
- end
- end
- }
- Clipboard = {
- Content = nil,
- Type = nil,
- IsCut = false,
- Empty = function()
- Clipboard.Content = nil
- Clipboard.Type = nil
- Clipboard.IsCut = false
- end,
- isEmpty = function()
- return Clipboard.Content == nil
- end,
- Copy = function(content, _type)
- Clipboard.Content = content
- Clipboard.Type = _type or 'generic'
- Clipboard.IsCut = false
- end,
- Cut = function(content, _type)
- Clipboard.Content = content
- Clipboard.Type = _type or 'generic'
- Clipboard.IsCut = true
- end,
- Paste = function()
- local c, t = Clipboard.Content, Clipboard.Type
- if Clipboard.IsCut then
- Clipboard.Empty()
- end
- return c, t
- end
- }
- if OneOS and OneOS.Clipboard then
- Clipboard = OneOS.Clipboard
- end
- Drawing = {
- Screen = {
- Width = _w,
- Height = _h
- },
- DrawCharacters = function (x, y, characters, textColour,bgColour)
- Drawing.WriteStringToBuffer(x, y, characters, textColour, bgColour)
- end,
- DrawBlankArea = function (x, y, w, h, colour)
- Drawing.DrawArea (x, y, w, h, " ", 1, colour)
- end,
- DrawArea = function (x, y, w, h, character, textColour, bgColour)
- --width must be greater than 1, other wise we get a stack overflow
- if w < 0 then
- w = w * -1
- elseif w == 0 then
- w = 1
- end
- for ix = 1, w do
- local currX = x + ix - 1
- for iy = 1, h do
- local currY = y + iy - 1
- Drawing.WriteToBuffer(currX, currY, character, textColour, bgColour)
- end
- end
- end,
- DrawImage = function(_x,_y,tImage, w, h)
- if tImage then
- for y = 1, h do
- if not tImage[y] then
- break
- end
- for x = 1, w do
- if not tImage[y][x] then
- break
- end
- local bgColour = tImage[y][x]
- local textColour = tImage.textcol[y][x] or colours.white
- local char = tImage.text[y][x]
- Drawing.WriteToBuffer(x+_x-1, y+_y-1, char, textColour, bgColour)
- end
- end
- elseif w and h then
- Drawing.DrawBlankArea(x, y, w, h, colours.green)
- end
- end,
- --using .nft
- LoadImage = function(path)
- local image = {
- text = {},
- textcol = {}
- }
- local fs = fs
- if OneOS then
- fs = OneOS.FS
- end
- if fs.exists(path) then
- local _open = io.open
- if OneOS then
- _open = OneOS.IO.open
- end
- local file = _open(path, "r")
- local sLine = file:read()
- local num = 1
- while sLine do
- table.insert(image, num, {})
- table.insert(image.text, num, {})
- table.insert(image.textcol, num, {})
- --As we're no longer 1-1, we keep track of what index to write to
- local writeIndex = 1
- --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour
- local bgNext, fgNext = false, false
- --The current background and foreground colours
- local currBG, currFG = nil,nil
- for i=1,#sLine do
- local nextChar = string.sub(sLine, i, i)
- if nextChar:byte() == 30 then
- bgNext = true
- elseif nextChar:byte() == 31 then
- fgNext = true
- elseif bgNext then
- currBG = Drawing.GetColour(nextChar)
- bgNext = false
- elseif fgNext then
- currFG = Drawing.GetColour(nextChar)
- fgNext = false
- else
- if nextChar ~= " " and currFG == nil then
- currFG = colours.white
- end
- image[num][writeIndex] = currBG
- image.textcol[num][writeIndex] = currFG
- image.text[num][writeIndex] = nextChar
- writeIndex = writeIndex + 1
- end
- end
- num = num+1
- sLine = file:read()
- end
- file:close()
- end
- return image
- end,
- DrawCharactersCenter = function(x, y, w, h, characters, textColour,bgColour)
- w = w or Drawing.Screen.Width
- h = h or Drawing.Screen.Height
- x = x or 0
- y = y or 0
- x = math.ceil((w - #characters) / 2) + x
- y = math.floor(h / 2) + y
- Drawing.DrawCharacters(x, y, characters, textColour, bgColour)
- end,
- GetColour = function(hex)
- if hex == ' ' then
- return colours.transparent
- end
- local value = tonumber(hex, 16)
- if not value then return nil end
- value = math.pow(2,value)
- return value
- end,
- Clear = function (_colour)
- _colour = _colour or colours.black
- Drawing.ClearBuffer()
- Drawing.DrawBlankArea(1, 1, Drawing.Screen.Width, Drawing.Screen.Height, _colour)
- end,
- Buffer = {},
- BackBuffer = {},
- DrawBuffer = function()
- for y,row in pairs(Drawing.Buffer) do
- for x,pixel in pairs(row) do
- local shouldDraw = true
- local hasBackBuffer = true
- if Drawing.BackBuffer[y] == nil or Drawing.BackBuffer[y][x] == nil or #Drawing.BackBuffer[y][x] ~= 3 then
- hasBackBuffer = false
- end
- if hasBackBuffer and Drawing.BackBuffer[y][x][1] == Drawing.Buffer[y][x][1] and Drawing.BackBuffer[y][x][2] == Drawing.Buffer[y][x][2] and Drawing.BackBuffer[y][x][3] == Drawing.Buffer[y][x][3] then
- shouldDraw = false
- end
- if shouldDraw then
- term.setBackgroundColour(pixel[3])
- term.setTextColour(pixel[2])
- term.setCursorPos(x, y)
- term.write(pixel[1])
- end
- end
- end
- Drawing.BackBuffer = Drawing.Buffer
- Drawing.Buffer = {}
- term.setCursorPos(1,1)
- end,
- ClearBuffer = function()
- Drawing.Buffer = {}
- end,
- WriteStringToBuffer = function (x, y, characters, textColour,bgColour)
- for i = 1, #characters do
- local character = characters:sub(i,i)
- Drawing.WriteToBuffer(x + i - 1, y, character, textColour, bgColour)
- end
- end,
- WriteToBuffer = function(x, y, character, textColour,bgColour)
- x = round(x)
- y = round(y)
- if bgColour == colours.transparent then
- Drawing.Buffer[y] = Drawing.Buffer[y] or {}
- Drawing.Buffer[y][x] = Drawing.Buffer[y][x] or {"", colours.white, colours.black}
- Drawing.Buffer[y][x][1] = character
- Drawing.Buffer[y][x][2] = textColour
- else
- Drawing.Buffer[y] = Drawing.Buffer[y] or {}
- Drawing.Buffer[y][x] = {character, textColour, bgColour}
- end
- end,
- }
- Current = {
- Document = nil,
- TextInput = nil,
- CursorPos = {1,1},
- CursorColour = colours.black,
- Selection = {8, 36},
- Window = nil,
- Modified = false,
- }
- local isQuitting = false
- function OrderSelection()
- if Current.Selection then
- if Current.Selection[1] <= Current.Selection[2] then
- return Current.Selection
- else
- return {Current.Selection[2], Current.Selection[1]}
- end
- end
- end
- function StripColours(str)
- return str:gsub('['..string.char(14)..'-'..string.char(29)..']','')
- end
- function FindColours(str)
- local _, count = str:gsub('['..string.char(14)..'-'..string.char(29)..']','')
- return count
- end
- ColourFromCharacter = function(character)
- local n = character:byte() - 14
- if n > 16 then
- return nil
- else
- return 2^n
- end
- end
- CharacterFromColour = function(colour)
- return string.char(math.floor(math.log(colour)/math.log(2))+14)
- end
- Events = {}
- Button = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- BackgroundColour = colours.lightGrey,
- TextColour = colours.white,
- ActiveBackgroundColour = colours.lightGrey,
- Text = "",
- Parent = nil,
- _Click = nil,
- Toggle = nil,
- AbsolutePosition = function(self)
- return self.Parent:AbsolutePosition()
- end,
- Draw = function(self)
- local bg = self.BackgroundColour
- local tc = self.TextColour
- if type(bg) == 'function' then
- bg = bg()
- end
- if self.Toggle then
- tc = UIColours.MenuBarActive
- bg = self.ActiveBackgroundColour
- end
- local pos = GetAbsolutePosition(self)
- Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, bg)
- Drawing.DrawCharactersCenter(pos.X, pos.Y, self.Width, self.Height, self.Text, tc, bg)
- end,
- Initialise = function(self, x, y, width, height, backgroundColour, parent, click, text, textColour, toggle, activeBackgroundColour)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- height = height or 1
- new.Width = width or #text + 2
- new.Height = height
- new.Y = y
- new.X = x
- new.Text = text or ""
- new.BackgroundColour = backgroundColour or colours.lightGrey
- new.TextColour = textColour or colours.white
- new.ActiveBackgroundColour = activeBackgroundColour or colours.lightGrey
- new.Parent = parent
- new._Click = click
- new.Toggle = toggle
- return new
- end,
- Click = function(self, side, x, y)
- if self._Click then
- if self:_Click(side, x, y, not self.Toggle) ~= false and self.Toggle ~= nil then
- self.Toggle = not self.Toggle
- Draw()
- end
- return true
- else
- return false
- end
- end
- }
- TextBox = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- BackgroundColour = colours.lightGrey,
- TextColour = colours.black,
- Parent = nil,
- TextInput = nil,
- Placeholder = '',
- AbsolutePosition = function(self)
- return self.Parent:AbsolutePosition()
- end,
- Draw = function(self)
- local pos = GetAbsolutePosition(self)
- Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, self.BackgroundColour)
- local text = self.TextInput.Value
- if #tostring(text) > (self.Width - 2) then
- text = text:sub(#text-(self.Width - 3))
- if Current.TextInput == self.TextInput then
- Current.CursorPos = {pos.X + 1 + self.Width-2, pos.Y}
- end
- else
- if Current.TextInput == self.TextInput then
- Current.CursorPos = {pos.X + 1 + self.TextInput.CursorPos, pos.Y}
- end
- end
- if #tostring(text) == 0 then
- Drawing.DrawCharacters(pos.X + 1, pos.Y, self.Placeholder, colours.lightGrey, self.BackgroundColour)
- else
- Drawing.DrawCharacters(pos.X + 1, pos.Y, text, self.TextColour, self.BackgroundColour)
- end
- term.setCursorBlink(true)
- Current.CursorColour = self.TextColour
- end,
- Initialise = function(self, x, y, width, height, parent, text, backgroundColour, textColour, done, numerical)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- height = height or 1
- new.Width = width or #text + 2
- new.Height = height
- new.Y = y
- new.X = x
- new.TextInput = TextInput:Initialise(text or '', function(key)
- if done then
- done(key)
- end
- Draw()
- end, numerical)
- new.BackgroundColour = backgroundColour or colours.lightGrey
- new.TextColour = textColour or colours.black
- new.Parent = parent
- return new
- end,
- Click = function(self, side, x, y)
- Current.Input = self.TextInput
- self:Draw()
- end
- }
- TextInput = {
- Value = "",
- Change = nil,
- CursorPos = nil,
- Numerical = false,
- IsDocument = nil,
- Initialise = function(self, value, change, numerical, isDocument)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Value = tostring(value)
- new.Change = change
- new.CursorPos = #tostring(value)
- new.Numerical = numerical
- new.IsDocument = isDocument or false
- return new
- end,
- Insert = function(self, str)
- if self.Numerical then
- str = tostring(tonumber(str))
- end
- local selection = OrderSelection()
- if self.IsDocument and selection then
- self.Value = string.sub(self.Value, 1, selection[1]-1) .. str .. string.sub( self.Value, selection[2]+2)
- self.CursorPos = selection[1]
- Current.Selection = nil
- else
- local _, newLineAdjust = string.gsub(self.Value:sub(1, self.CursorPos), '\n','')
- self.Value = string.sub(self.Value, 1, self.CursorPos + newLineAdjust) .. str .. string.sub( self.Value, self.CursorPos + 1 + newLineAdjust)
- self.CursorPos = self.CursorPos + 1
- end
- self.Change(key)
- end,
- Extract = function(self, remove)
- local selection = OrderSelection()
- if self.IsDocument and selection then
- local _, newLineAdjust = string.gsub(self.Value:sub(selection[1], selection[2]), '\n','')
- local str = string.sub(self.Value, selection[1], selection[2]+1+newLineAdjust)
- if remove then
- self.Value = string.sub(self.Value, 1, selection[1]-1) .. string.sub( self.Value, selection[2]+2+newLineAdjust)
- self.CursorPos = selection[1] - 1
- Current.Selection = nil
- end
- return str
- end
- end,
- Char = function(self, char)
- if char == 'nil' then
- return
- end
- self:Insert(char)
- end,
- Key = function(self, key)
- if key == keys.enter then
- if self.IsDocument then
- self.Value = string.sub(self.Value, 1, self.CursorPos ) .. '\n' .. string.sub( self.Value, self.CursorPos + 1 )
- self.CursorPos = self.CursorPos + 1
- end
- self.Change(key)
- elseif key == keys.left then
- -- Left
- if self.CursorPos > 0 then
- local colShift = FindColours(string.sub( self.Value, self.CursorPos, self.CursorPos))
- self.CursorPos = self.CursorPos - 1 - colShift
- self.Change(key)
- end
- elseif key == keys.right then
- -- Right
- if self.CursorPos < string.len(self.Value) then
- local colShift = FindColours(string.sub( self.Value, self.CursorPos+1, self.CursorPos+1))
- self.CursorPos = self.CursorPos + 1 + colShift
- self.Change(key)
- end
- elseif key == keys.backspace then
- -- Backspace
- if self.IsDocument and Current.Selection then
- self:Extract(true)
- self.Change(key)
- elseif self.CursorPos > 0 then
- local colShift = FindColours(string.sub( self.Value, self.CursorPos, self.CursorPos))
- local _, newLineAdjust = string.gsub(self.Value:sub(1, self.CursorPos), '\n','')
- self.Value = string.sub( self.Value, 1, self.CursorPos - 1 - colShift + newLineAdjust) .. string.sub( self.Value, self.CursorPos + 1 - colShift + newLineAdjust)
- self.CursorPos = self.CursorPos - 1 - colShift
- self.Change(key)
- end
- elseif key == keys.home then
- -- Home
- self.CursorPos = 0
- self.Change(key)
- elseif key == keys.delete then
- if self.IsDocument and Current.Selection then
- self:Extract(true)
- self.Change(key)
- elseif self.CursorPos < string.len(self.Value) then
- self.Value = string.sub( self.Value, 1, self.CursorPos ) .. string.sub( self.Value, self.CursorPos + 2 )
- self.Change(key)
- end
- elseif key == keys["end"] then
- -- End
- self.CursorPos = string.len(self.Value)
- self.Change(key)
- elseif key == keys.up and self.IsDocument then
- -- Up
- if Current.Document.CursorPos then
- local page = Current.Document.Pages[Current.Document.CursorPos.Page]
- self.CursorPos = page:GetCursorPosFromPoint(Current.Document.CursorPos.Collum + page.MarginX, Current.Document.CursorPos.Line - page.MarginY - 1 + Current.Document.ScrollBar.Scroll, true)
- self.Change(key)
- end
- elseif key == keys.down and self.IsDocument then
- -- Down
- if Current.Document.CursorPos then
- local page = Current.Document.Pages[Current.Document.CursorPos.Page]
- self.CursorPos = page:GetCursorPosFromPoint(Current.Document.CursorPos.Collum + page.MarginX, Current.Document.CursorPos.Line - page.MarginY + 1 + Current.Document.ScrollBar.Scroll, true)
- self.Change(key)
- end
- end
- end
- }
- Menu = {
- X = 0,
- Y = 0,
- Width = 0,
- Height = 0,
- Owner = nil,
- Items = {},
- RemoveTop = false,
- Draw = function(self)
- Drawing.DrawBlankArea(self.X + 1, self.Y + 1, self.Width, self.Height, UIColours.Shadow)
- if not self.RemoveTop then
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
- for i, item in ipairs(self.Items) do
- if item.Separator then
- Drawing.DrawArea(self.X, self.Y + i, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
- else
- local textColour = item.Colour or UIColours.MenuText
- if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
- textColour = UIColours.MenuDisabledText
- end
- Drawing.DrawCharacters(self.X + 1, self.Y + i, item.Title, textColour, UIColours.MenuBackground)
- end
- end
- else
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
- for i, item in ipairs(self.Items) do
- if item.Separator then
- Drawing.DrawArea(self.X, self.Y + i - 1, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
- else
- local textColour = item.Colour or UIColours.MenuText
- if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
- textColour = UIColours.MenuDisabledText
- end
- Drawing.DrawCharacters(self.X + 1, self.Y + i - 1, item.Title, textColour, UIColours.MenuBackground)
- Drawing.DrawCharacters(self.X - 1 + self.Width-#item.KeyName, self.Y + i - 1, item.KeyName, textColour, UIColours.MenuBackground)
- end
- end
- end
- end,
- NameForKey = function(self, key)
- if key == keys.leftCtrl then
- return '^'
- elseif key == keys.tab then
- return 'Tab'
- elseif key == keys.delete then
- return 'Delete'
- elseif key == keys.n then
- return 'N'
- elseif key == keys.a then
- return 'A'
- elseif key == keys.s then
- return 'S'
- elseif key == keys.o then
- return 'O'
- elseif key == keys.z then
- return 'Z'
- elseif key == keys.y then
- return 'Y'
- elseif key == keys.c then
- return 'C'
- elseif key == keys.x then
- return 'X'
- elseif key == keys.v then
- return 'V'
- elseif key == keys.r then
- return 'R'
- elseif key == keys.l then
- return 'L'
- elseif key == keys.t then
- return 'T'
- elseif key == keys.h then
- return 'H'
- elseif key == keys.e then
- return 'E'
- elseif key == keys.p then
- return 'P'
- elseif key == keys.f then
- return 'F'
- elseif key == keys.m then
- return 'M'
- elseif key == keys.q then
- return 'Q'
- else
- return '?'
- end
- end,
- Initialise = function(self, x, y, items, owner, removeTop)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- if not owner then
- return
- end
- local keyNames = {}
- for i, v in ipairs(items) do
- items[i].KeyName = ''
- if v.Keys then
- for _i, key in ipairs(v.Keys) do
- items[i].KeyName = items[i].KeyName .. self:NameForKey(key)
- end
- end
- if items[i].KeyName ~= '' then
- table.insert(keyNames, items[i].KeyName)
- end
- end
- local keysLength = LongestString(keyNames)
- if keysLength > 0 then
- keysLength = keysLength + 2
- end
- new.Width = LongestString(items, 'Title') + 2 + keysLength
- if new.Width < 10 then
- new.Width = 10
- end
- new.Height = #items + 2
- new.RemoveTop = removeTop or false
- if removeTop then
- new.Height = new.Height - 1
- end
- if y < 1 then
- y = 1
- end
- if x < 1 then
- x = 1
- end
- if y + new.Height > Drawing.Screen.Height + 1 then
- y = Drawing.Screen.Height - new.Height
- end
- if x + new.Width > Drawing.Screen.Width + 1 then
- x = Drawing.Screen.Width - new.Width
- end
- new.Y = y
- new.X = x
- new.Items = items
- new.Owner = owner
- return new
- end,
- New = function(self, x, y, items, owner, removeTop)
- if Current.Menu and Current.Menu.Owner == owner then
- Current.Menu = nil
- return
- end
- local new = self:Initialise(x, y, items, owner, removeTop)
- Current.Menu = new
- return new
- end,
- Click = function(self, side, x, y)
- local i = y-1
- if self.RemoveTop then
- i = y
- end
- if i >= 1 and y < self.Height then
- if not ((self.Items[i].Enabled and type(self.Items[i].Enabled) == 'function' and self.Items[i].Enabled() == false) or self.Items[i].Enabled == false) and self.Items[i].Click then
- self.Items[i]:Click()
- if Current.Menu.Owner and Current.Menu.Owner.Toggle then
- Current.Menu.Owner.Toggle = false
- end
- Current.Menu = nil
- self = nil
- end
- return true
- end
- end
- }
- MenuBar = {
- X = 1,
- Y = 1,
- Width = Drawing.Screen.Width,
- Height = 1,
- MenuBarItems = {},
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- --Drawing.DrawArea(self.X - 1, self.Y, 1, self.Height, "|", UIColours.ToolbarText, UIColours.Background)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, colours.grey)
- for i, button in ipairs(self.MenuBarItems) do
- button:Draw()
- end
- end,
- Initialise = function(self, items)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.X = 1
- new.Y = 1
- new.MenuBarItems = items
- return new
- end,
- AddToolbarItem = function(self, item)
- table.insert(self.ToolbarItems, item)
- self:CalculateToolbarItemPositions()
- end,
- CalculateToolbarItemPositions = function(self)
- local currY = 1
- for i, toolbarItem in ipairs(self.ToolbarItems) do
- toolbarItem.Y = currY
- currY = currY + toolbarItem.Height
- end
- end,
- Click = function(self, side, x, y)
- for i, item in ipairs(self.MenuBarItems) do
- if item.X <= x and item.X + item.Width > x then
- if item:Click(item, side, x - item.X + 1, 1) then
- return true
- end
- end
- end
- return false
- end
- }
- TextFormatPlainText = 1
- TextFormatInkText = 2
- Document = {
- X = 1,
- Y = 1,
- PageSize = {Width = 25, Height = 21},
- TextInput = nil,
- Pages = {},
- Format = TextFormatPlainText,
- Title = '',
- Path = nil,
- ScrollBar = nil,
- Lines = {},
- CursorPos = nil,
- CalculateLineWrapping = function(self)
- local limit = self.PageSize.Width
- local text = self.TextInput.Value
- local lines = {''}
- local words = {}
- for word, space in text:gmatch('(%S+)(%s*)') do
- for i = 1, math.ceil(#word/limit) do
- local _space = ''
- if i == math.ceil(#word/limit) then
- _space = space
- end
- table.insert(words, {word:sub(1+limit*(i-1), limit*i), _space})
- end
- end
- for i, ws in ipairs(words) do
- local word = ws[1]
- local space = ws[2]
- local temp = lines[#lines] .. word .. space:gsub('\n','')
- if #temp > limit then
- table.insert(lines, '')
- end
- if space:find('\n') then
- lines[#lines] = lines[#lines] .. word
- space = space:gsub('\n', function()
- table.insert(lines, '')
- return ''
- end)
- else
- lines[#lines] = lines[#lines] .. word .. space
- end
- end
- return lines
- end,
- CalculateCursorPos = function(self)
- local passedCharacters = 0
- Current.CursorPos = nil
- for p, page in ipairs(self.Pages) do
- page:Draw()
- if not Current.CursorPos then
- for i, line in ipairs(page.Lines) do
- local relCursor = self.TextInput.CursorPos - FindColours(self.TextInput.Value:sub(1,self.TextInput.CursorPos))
- if passedCharacters + #StripColours(line.Text:gsub('\n','')) >= relCursor then
- Current.CursorPos = {self.X + page.MarginX + (relCursor - passedCharacters), page.Y + 1 + i}
- self.CursorPos = {Page = p, Line = i, Collum = relCursor - passedCharacters - FindColours(self.TextInput.Value:sub(1,self.TextInput.CursorPos-1))}
- break
- end
- passedCharacters = passedCharacters + #StripColours(line.Text:gsub('\n',''))
- end
- end
- end
- end,
- Draw = function(self)
- self:CalculatePages()
- self:CalculateCursorPos()
- self.ScrollBar:Draw()
- end,
- CalculatePages = function(self)
- self.Pages = {}
- local lines = self:CalculateLineWrapping()
- self.Lines = lines
- local pageLines = {}
- local totalPageHeight = (3 + self.PageSize.Height + 2 * Page.MarginY)
- for i, line in ipairs(lines) do
- table.insert(pageLines, TextLine:Initialise(line))
- if i % self.PageSize.Height == 0 then
- table.insert(self.Pages, Page:Initialise(self, pageLines, 3 - self.ScrollBar.Scroll + totalPageHeight*(#self.Pages)))
- pageLines = {}
- end
- end
- if #pageLines ~= 0 then
- table.insert(self.Pages, Page:Initialise(self, pageLines, 3 - self.ScrollBar.Scroll + totalPageHeight*(#self.Pages)))
- end
- self.ScrollBar.MaxScroll = totalPageHeight*(#self.Pages) - Drawing.Screen.Height + 1
- end,
- ScrollToCursor = function(self)
- self:CalculateCursorPos()
- if Current.CursorPos and
- (Current.CursorPos[2] > Drawing.Screen.Height
- or Current.CursorPos[2] < 2) then
- self.ScrollBar:DoScroll(Current.CursorPos[2] - Drawing.Screen.Height)
- end
- end,
- SetSelectionColour = function(self, colour)
- local selection = OrderSelection()
- local text = self.TextInput:Extract(true)
- local colChar = CharacterFromColour(colour)
- local precedingColour = ''
- if FindColours(self.TextInput.Value:sub(self.TextInput.CursorPos+1, self.TextInput.CursorPos+1)) == 0 then
- for i = 1, self.TextInput.CursorPos do
- local c = self.TextInput.Value:sub(self.TextInput.CursorPos - i,self.TextInput.CursorPos - i)
- if FindColours(c) == 1 then
- precedingColour = c
- break
- end
- end
- if precedingColour == '' then
- precedingColour = CharacterFromColour(colours.black)
- end
- end
- self.TextInput:Insert(colChar..StripColours(text)..precedingColour)
- --text = text:gsub('['..string.char(14)..'-'..string.char(29)..']','')
- end,
- Initialise = function(self, text, title, path)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Title = title or 'New Document'
- new.Path = path
- new.X = (Drawing.Screen.Width - (new.PageSize.Width + 2*(Page.MarginX)))/2
- new.Y = 2
- new.TextInput = TextInput:Initialise(text, function()
- new:ScrollToCursor()
- Current.Modified = true
- Draw()
- end, false, true)
- new.ScrollBar = ScrollBar:Initialise(Drawing.Screen.Width, new.Y, Drawing.Screen.Height-1, 0, nil, nil, nil, function()end)
- Current.TextInput = new.TextInput
- Current.ScrollBar = new.ScrollBar
- return new
- end
- }
- ScrollBar = {
- X = 1,
- Y = 1,
- Width = 1,
- Height = 1,
- BackgroundColour = colours.grey,
- BarColour = colours.lightBlue,
- Parent = nil,
- Change = nil,
- Scroll = 0,
- MaxScroll = 0,
- ClickPoint = nil,
- AbsolutePosition = function(self)
- return self.Parent:AbsolutePosition()
- end,
- Draw = function(self)
- local pos = GetAbsolutePosition(self)
- local barHeight = self.Height - self.MaxScroll
- if barHeight < 3 then
- barHeight = 3
- end
- local percentage = (self.Scroll/self.MaxScroll)
- Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, self.BackgroundColour)
- Drawing.DrawBlankArea(pos.X, pos.Y + round(self.Height*percentage - barHeight*percentage), self.Width, barHeight, self.BarColour)
- end,
- Initialise = function(self, x, y, height, maxScroll, backgroundColour, barColour, parent, change)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 1
- new.Height = height
- new.Y = y
- new.X = x
- new.BackgroundColour = backgroundColour or colours.grey
- new.BarColour = barColour or colours.lightBlue
- new.Parent = parent
- new.Change = change or function()end
- new.MaxScroll = maxScroll
- new.Scroll = 0
- return new
- end,
- DoScroll = function(self, amount)
- amount = round(amount)
- if self.Scroll < 0 or self.Scroll > self.MaxScroll then
- return false
- end
- self.Scroll = self.Scroll + amount
- if self.Scroll < 0 then
- self.Scroll = 0
- elseif self.Scroll > self.MaxScroll then
- self.Scroll = self.MaxScroll
- end
- self.Change()
- return true
- end,
- Click = function(self, side, x, y, drag)
- local percentage = (self.Scroll/self.MaxScroll)
- local barHeight = (self.Height - self.MaxScroll)
- if barHeight < 3 then
- barHeight = 3
- end
- local relScroll = (self.MaxScroll*(y + barHeight*percentage)/self.Height)
- if not drag then
- self.ClickPoint = self.Scroll - relScroll + 1
- end
- if self.Scroll-1 ~= relScroll then
- self:DoScroll(relScroll-self.Scroll-1 + self.ClickPoint)
- end
- return true
- end
- }
- AlignmentLeft = 1
- AlignmentCentre = 2
- AlignmentRight = 3
- TextLine = {
- Text = "",
- Alignment = AlignmentLeft,
- Initialise = function(self, text, alignment)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Text = text
- new.Alignment = alignment or AlignmentLeft
- return new
- end
- }
- local clickPos = 1
- Page = {
- X = 1,
- Y = 1,
- Width = 1,
- Height = 1,
- MarginX = 3,
- MarginY = 2,
- BackgroundColour = colours.white,
- TextColour = colours.white,
- ActiveBackgroundColour = colours.lightGrey,
- Lines = {},
- Parent = nil,
- AbsolutePosition = function(self)
- return self.Parent:AbsolutePosition()
- end,
- Draw = function(self)
- local pos = GetAbsolutePosition(self)
- if pos.Y > Drawing.Screen.Height or pos.Y + self.Height < 1 then
- return
- end
- Drawing.DrawBlankArea(pos.X+self.Width,pos.Y -1 + 1, 1, self.Height, UIColours.Shadow)
- Drawing.DrawBlankArea(pos.X+1, pos.Y -1 + self.Height, self.Width, 1, UIColours.Shadow)
- Drawing.DrawBlankArea(pos.X, pos.Y -1, self.Width, self.Height, self.BackgroundColour)
- local textColour = self.TextColour
- if not Current.Selection then
- for i, line in ipairs(self.Lines) do
- local _c = 1
- for c = 1, #line.Text do
- local col = ColourFromCharacter(line.Text:sub(c,c))
- if col then
- textColour = col
- else
- Drawing.WriteToBuffer(pos.X + self.MarginX - 1 + _c, pos.Y -2 + i + self.MarginY, line.Text:sub(c,c), textColour, self.BackgroundColour)
- _c = _c + 1
- end
- end
- end
- else
- local selection = OrderSelection()
- local char = 1
- local textColour = self.TextColour
- for i, line in ipairs(self.Lines) do
- local _c = 1
- for c = 1, #line.Text do
- local col = ColourFromCharacter(line.Text:sub(c,c))
- if col then
- textColour = col
- else
- local tc = textColour
- local colour = colours.white
- if char >= selection[1] and char <= selection[2] then
- colour = colours.lightBlue
- tc = colours.white
- end
- Drawing.WriteToBuffer(pos.X + self.MarginX - 1 + _c, pos.Y -2 + i + self.MarginY, line.Text:sub(c,c), tc, colour)
- _c = _c + 1
- end
- char = char + 1
- end
- end
- end
- end,
- Initialise = function(self, parent, lines, y)
- local new = {} -- the new instanc
- setmetatable( new, {__index = self} )
- new.Height = parent.PageSize.Height + 2 * self.MarginY
- new.Width = parent.PageSize.Width + 2 * self.MarginX
- new.X = 1
- new.Y = y or 1
- new.Lines = lines or {}
- new.BackgroundColour = colours.white
- new.TextColour = colours.black
- new.Parent = parent
- new.ClickPos = 1
- return new
- end,
- GetCursorPosFromPoint = function(self, x, y, rel)
- local pos = GetAbsolutePosition(self)
- if rel then
- pos = {Y = 0, X = 0}
- end
- local row = y - pos.Y + self.MarginY - self.Parent.ScrollBar.Scroll
- local col = x - self.MarginX - pos.X + 1
- local cursorPos = 0
- if row <= 0 or col <= 0 then
- return 0
- end
- if row > #self.Lines then
- for i, v in ipairs(self.Lines) do
- cursorPos = cursorPos + #v.Text-- - FindColours(v.Text)
- end
- return cursorPos
- end
- --term.setCursorPos(1,3)
- local prevLineCount = 0
- for i, v in ipairs(self.Lines) do
- if i == row then
- if col > #v.Text then
- col = #v.Text-- + FindColours(v.Text)
- else
- col = col + FindColours(v.Text:sub(1, col))
- end
- --term.setCursorPos(1,2)
- --print(prevLineCount)
- cursorPos = cursorPos + col + 2 - i - prevLineCount
- break
- else
- prevLineCount = FindColours(v.Text)
- if prevLineCount ~= 0 then
- prevLineCount = prevLineCount
- end
- cursorPos = cursorPos + #v.Text + 2 - i + FindColours(v.Text)
- end
- end
- return cursorPos - 2
- end,
- Click = function(self, side, x, y, drag)
- local cursorPos = self:GetCursorPosFromPoint(x, y)
- self.Parent.TextInput.CursorPos = cursorPos
- if drag == nil then
- Current.Selection = nil
- clickPos = x
- else
- local relCursor = cursorPos-- - FindColours(self.Parent.TextInput.Value:sub(1,cursorPos)) + 1
- if not Current.Selection then
- local adder = 1
- if clickPos and clickPos < x then
- adder = 0
- end
- Current.Selection = {relCursor + adder, relCursor + 1 + adder}
- else
- Current.Selection[2] = relCursor + 1
- end
- end
- Draw()
- return true
- end
- }
- function GetAbsolutePosition(object)
- local obj = object
- local i = 0
- local x = 1
- local y = 1
- while true do
- x = x + obj.X - 1
- y = y + obj.Y - 1
- if not obj.Parent then
- return {X = x, Y = y}
- end
- obj = obj.Parent
- if i > 32 then
- return {X = 1, Y = 1}
- end
- i = i + 1
- end
- end
- function Draw()
- if not Current.Window then
- Drawing.Clear(colours.lightGrey)
- else
- Drawing.DrawArea(1, 2, Drawing.Screen.Width, Drawing.Screen.Height, '|', colours.black, colours.lightGrey)
- end
- if Current.Document then
- Current.Document:Draw()
- end
- Current.MenuBar:Draw()
- if Current.Window then
- Current.Window:Draw()
- end
- if Current.Menu then
- Current.Menu:Draw()
- end
- Drawing.DrawBuffer()
- if Current.TextInput and Current.CursorPos and not Current.Menu and not(Current.Window and Current.Document and Current.TextInput == Current.Document.TextInput) and Current.CursorPos[2] > 1 then
- term.setCursorPos(Current.CursorPos[1], Current.CursorPos[2])
- term.setCursorBlink(true)
- term.setTextColour(Current.CursorColour)
- else
- term.setCursorBlink(false)
- end
- end
- MainDraw = Draw
- LongestString = function(input, key)
- local length = 0
- for i = 1, #input do
- local value = input[i]
- if key then
- if value[key] then
- value = value[key]
- else
- value = ''
- end
- end
- local titleLength = string.len(value)
- if titleLength > length then
- length = titleLength
- end
- end
- return length
- end
- function LoadMenuBar()
- Current.MenuBar = MenuBar:Initialise({
- Button:Initialise(1, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if toggle then
- Menu:New(1, 2, {
- {
- Title = "New...",
- Click = function()
- Current.Document = Document:Initialise('')
- end,
- Keys = {
- keys.leftCtrl,
- keys.n
- }
- },
- {
- Title = 'Open...',
- Click = function()
- DisplayOpenDocumentWindow()
- end,
- Keys = {
- keys.leftCtrl,
- keys.o
- }
- },
- {
- Separator = true
- },
- {
- Title = 'Save...',
- Click = function()
- SaveDocument()
- end,
- Keys = {
- keys.leftCtrl,
- keys.s
- },
- Enabled = function()
- return true
- end
- },
- {
- Separator = true
- },
- {
- Title = 'Print...',
- Click = function()
- PrintDocument()
- end,
- Keys = {
- keys.leftCtrl,
- keys.p
- },
- Enabled = function()
- return true
- end
- },
- {
- Separator = true
- },
- {
- Title = 'Quit',
- Click = function()
- Close()
- end
- },
- --[[
- {
- Title = 'Save As...',
- Click = function()
- end
- }
- ]]--
- }, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'File', colours.lightGrey, false),
- Button:Initialise(7, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if not self.Toggle then
- Menu:New(7, 2, {
- --[[
- {
- Title = "Undo",
- Click = function()
- end,
- Keys = {
- keys.leftCtrl,
- keys.z
- },
- Enabled = function()
- return false
- end
- },
- {
- Title = 'Redo',
- Click = function()
- end,
- Keys = {
- keys.leftCtrl,
- keys.y
- },
- Enabled = function()
- return false
- end
- },
- {
- Separator = true
- },
- ]]--
- {
- Title = 'Cut',
- Click = function()
- Clipboard.Cut(Current.Document.TextInput:Extract(true), 'text')
- end,
- Keys = {
- keys.leftCtrl,
- keys.x
- },
- Enabled = function()
- return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
- end
- },
- {
- Title = 'Copy',
- Click = function()
- Clipboard.Copy(Current.Document.TextInput:Extract(), 'text')
- end,
- Keys = {
- keys.leftCtrl,
- keys.c
- },
- Enabled = function()
- return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
- end
- },
- {
- Title = 'Paste',
- Click = function()
- local paste = Clipboard.Paste()
- Current.Document.TextInput:Insert(paste)
- Current.Document.TextInput.CursorPos = Current.Document.TextInput.CursorPos + #paste - 1
- end,
- Keys = {
- keys.leftCtrl,
- keys.v
- },
- Enabled = function()
- return Current.Document ~= nil and (not Clipboard.isEmpty()) and Clipboard.Type == 'text'
- end
- },
- {
- Separator = true,
- },
- {
- Title = 'Select All',
- Click = function()
- Current.Selection = {1, #Current.Document.TextInput.Value:gsub('\n','')}
- end,
- Keys = {
- keys.leftCtrl,
- keys.a
- },
- Enabled = function()
- return Current.Document ~= nil
- end
- }
- }, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'Edit', colours.lightGrey, false)
- })
- end
- function LoadMenuBar()
- Current.MenuBar = MenuBar:Initialise({
- Button:Initialise(1, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if toggle then
- Menu:New(1, 2, {
- {
- Title = "New...",
- Click = function()
- Current.Document = Document:Initialise('')
- end,
- Keys = {
- keys.leftCtrl,
- keys.n
- }
- },
- {
- Title = 'Open...',
- Click = function()
- DisplayOpenDocumentWindow()
- end,
- Keys = {
- keys.leftCtrl,
- keys.o
- }
- },
- {
- Separator = true
- },
- {
- Title = 'Save...',
- Click = function()
- SaveDocument()
- end,
- Keys = {
- keys.leftCtrl,
- keys.s
- },
- Enabled = function()
- return Current.Document ~= nil
- end
- },
- {
- Separator = true
- },
- {
- Title = 'Print...',
- Click = function()
- PrintDocument()
- end,
- Keys = {
- keys.leftCtrl,
- keys.p
- },
- Enabled = function()
- return true
- end
- },
- {
- Separator = true
- },
- {
- Title = 'Quit',
- Click = function()
- if Close() and OneOS then
- OneOS.Close()
- end
- end,
- Keys = {
- keys.leftCtrl,
- keys.q
- }
- },
- --[[
- {
- Title = 'Save As...',
- Click = function()
- end
- }
- ]]--
- }, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'File', colours.lightGrey, false),
- Button:Initialise(7, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if not self.Toggle then
- Menu:New(7, 2, {
- --[[
- {
- Title = "Undo",
- Click = function()
- end,
- Keys = {
- keys.leftCtrl,
- keys.z
- },
- Enabled = function()
- return false
- end
- },
- {
- Title = 'Redo',
- Click = function()
- end,
- Keys = {
- keys.leftCtrl,
- keys.y
- },
- Enabled = function()
- return false
- end
- },
- {
- Separator = true
- },
- ]]--
- {
- Title = 'Cut',
- Click = function()
- Clipboard.Cut(Current.Document.TextInput:Extract(true), 'text')
- end,
- Keys = {
- keys.leftCtrl,
- keys.x
- },
- Enabled = function()
- return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
- end
- },
- {
- Title = 'Copy',
- Click = function()
- Clipboard.Copy(Current.Document.TextInput:Extract(), 'text')
- end,
- Keys = {
- keys.leftCtrl,
- keys.c
- },
- Enabled = function()
- return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
- end
- },
- {
- Title = 'Paste',
- Click = function()
- local paste = Clipboard.Paste()
- Current.Document.TextInput:Insert(paste)
- Current.Document.TextInput.CursorPos = Current.Document.TextInput.CursorPos + #paste - 1
- end,
- Keys = {
- keys.leftCtrl,
- keys.v
- },
- Enabled = function()
- return Current.Document ~= nil and (not Clipboard.isEmpty()) and Clipboard.Type == 'text'
- end
- },
- {
- Separator = true,
- },
- {
- Title = 'Select All',
- Click = function()
- Current.Selection = {1, #Current.Document.TextInput.Value:gsub('\n','')}
- end,
- Keys = {
- keys.leftCtrl,
- keys.a
- },
- Enabled = function()
- return Current.Document ~= nil
- end
- }
- }, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'Edit', colours.lightGrey, false),
- Button:Initialise(13, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if not self.Toggle then
- Menu:New(13, 2, {
- {
- Title = 'Red',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.red,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Orange',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.orange,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Yellow',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.yellow,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Pink',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.pink,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Magenta',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.magenta,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Purple',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.purple,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Light Blue',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.lightBlue,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Cyan',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.cyan,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Blue',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.blue,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Green',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.green,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Light Grey',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.lightGrey,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Grey',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.grey,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Black',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.black,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- },
- {
- Title = 'Brown',
- Click = function(item)
- Current.Document:SetSelectionColour(item.Colour)
- end,
- Colour = colours.brown,
- Enabled = function()
- return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
- end
- }
- }, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'Colour', colours.lightGrey, false)
- })
- end
- function SplashScreen()
- local w = colours.white
- local b = colours.black
- local u = colours.blue
- local lb = colours.lightBlue
- local splashIcon = {{w,w,w,b,w,w,w,b,w,w,w,},{w,w,w,b,w,w,w,b,w,w,w,},{w,w,w,b,u,u,u,b,w,w,w,},{w,b,b,u,u,u,u,u,b,b,w,},{b,u,u,lb,lb,u,u,u,u,u,b,},{b,u,lb,lb,u,u,u,u,u,u,b,},{b,u,lb,lb,u,u,u,u,u,u,b,},{b,u,u,u,u,u,u,u,u,u,b,},{w,b,b,b,b,b,b,b,b,b,w,},
- ["text"]={{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," ","I","n","k"," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," ","b","y"," ","o","e","e","d"," "," "},{" "," "," "," "," "," "," "," "," "," "," ",},},
- ["textcol"]={{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{lb,lb,lb,lb,lb,lb,lb,lb,lb,lb,lb,},{w,w,w,w,w,w,w,w,w,w,w,},},}
- Drawing.Clear(colours.white)
- Drawing.DrawImage((Drawing.Screen.Width - 11)/2, (Drawing.Screen.Height - 9)/2, splashIcon, 11, 9)
- Drawing.DrawBuffer()
- Drawing.Clear(colours.black)
- parallel.waitForAny(function()sleep(1)end, function()os.pullEvent('mouse_click')end)
- end
- function Initialise(arg)
- if OneOS then
- fs = OneOS.FS
- end
- if not OneOS then
- SplashScreen()
- end
- EventRegister('mouse_click', TryClick)
- EventRegister('mouse_drag', function(event, side, x, y)TryClick(event, side, x, y, true)end)
- EventRegister('mouse_scroll', Scroll)
- EventRegister('key', HandleKey)
- EventRegister('char', HandleKey)
- EventRegister('timer', Timer)
- EventRegister('terminate', function(event) if Close() then error( "Terminated", 0 ) end end)
- LoadMenuBar()
- --Current.Document = Document:Initialise('abcdefghijklmnopqrtuvwxy')--'Hello everybody!')
- if tArgs[1] then
- if fs.exists(tArgs[1]) then
- OpenDocument(tArgs[1])
- else
- --new
- end
- else
- Current.Document = Document:Initialise('')--'Hello everybody!')
- end
- --[[
- if arg and fs.exists(arg) then
- OpenDocument(arg)
- else
- DisplayNewDocumentWindow()
- end
- ]]--
- Draw()
- EventHandler()
- end
- local isControlPushed = false
- controlPushedTimer = nil
- closeWindowTimer = nil
- function Timer(event, timer)
- if timer == closeWindowTimer then
- if Current.Window then
- Current.Window:Close()
- end
- Draw()
- elseif timer == controlPushedTimer then
- isControlPushed = false
- end
- end
- local ignoreNextChar = false
- function HandleKey(...)
- local args = {...}
- local event = args[1]
- local keychar = args[2]
- --Mac left command character
- if event == 'key' and keychar == keys.leftCtrl or keychar == keys.rightCtrl or keychar == 219 then
- isControlPushed = true
- controlPushedTimer = os.startTimer(0.5)
- elseif isControlPushed then
- if event == 'key' then
- if CheckKeyboardShortcut(keychar) then
- isControlPushed = false
- ignoreNextChar = true
- end
- end
- elseif ignoreNextChar then
- ignoreNextChar = false
- elseif Current.TextInput then
- if event == 'char' then
- Current.TextInput:Char(keychar)
- elseif event == 'key' then
- Current.TextInput:Key(keychar)
- end
- end
- end
- function CheckKeyboardShortcut(key)
- local shortcuts = {}
- shortcuts[keys.n] = function() Current.Document = Document:Initialise('') end
- shortcuts[keys.o] = function() DisplayOpenDocumentWindow() end
- shortcuts[keys.s] = function() if Current.Document ~= nil then SaveDocument() end end
- shortcuts[keys.left] = function() if Current.TextInput then Current.TextInput:Key(keys.home) end end
- shortcuts[keys.right] = function() if Current.TextInput then Current.TextInput:Key(keys["end"]) end end
- -- shortcuts[keys.q] = function() DisplayOpenDocumentWindow() end
- if Current.Document ~= nil then
- shortcuts[keys.s] = function() SaveDocument() end
- shortcuts[keys.p] = function() PrintDocument() end
- if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- shortcuts[keys.x] = function() Clipboard.Cut(Current.Document.TextInput:Extract(true), 'text') end
- shortcuts[keys.c] = function() Clipboard.Copy(Current.Document.TextInput:Extract(), 'text') end
- end
- if (not Clipboard.isEmpty()) and Clipboard.Type == 'text' then
- shortcuts[keys.v] = function() local paste = Clipboard.Paste()
- Current.Document.TextInput:Insert(paste)
- Current.Document.TextInput.CursorPos = Current.Document.TextInput.CursorPos + #paste - 1
- end
- end
- shortcuts[keys.a] = function() Current.Selection = {1, #Current.Document.TextInput.Value:gsub('\n','')} end
- end
- if shortcuts[key] then
- shortcuts[key]()
- Draw()
- return true
- else
- return false
- end
- end
- --[[
- Check if the given object falls under the click coordinates
- ]]--
- function CheckClick(object, x, y)
- if object.X <= x and object.Y <= y and object.X + object.Width > x and object.Y + object.Height > y then
- return true
- end
- end
- --[[
- Attempt to clicka given object
- ]]--
- function DoClick(object, side, x, y, drag)
- local obj = GetAbsolutePosition(object)
- obj.Width = object.Width
- obj.Height = object.Height
- if object and CheckClick(obj, x, y) then
- return object:Click(side, x - object.X + 1, y - object.Y + 1, drag)
- end
- end
- --[[
- Try to click at the given coordinates
- ]]--
- function TryClick(event, side, x, y, drag)
- if Current.Menu then
- if DoClick(Current.Menu, side, x, y, drag) then
- Draw()
- return
- else
- if Current.Menu.Owner and Current.Menu.Owner.Toggle then
- Current.Menu.Owner.Toggle = false
- end
- Current.Menu = nil
- Draw()
- return
- end
- elseif Current.Window then
- if DoClick(Current.Window, side, x, y, drag) then
- Draw()
- return
- else
- Current.Window:Flash()
- return
- end
- end
- local interfaceElements = {}
- table.insert(interfaceElements, Current.MenuBar)
- table.insert(interfaceElements, Current.ScrollBar)
- for i, page in ipairs(Current.Document.Pages) do
- table.insert(interfaceElements, page)
- end
- for i, object in ipairs(interfaceElements) do
- if DoClick(object, side, x, y, drag) then
- Draw()
- return
- end
- end
- Draw()
- end
- function Scroll(event, direction, x, y)
- if Current.Window and Current.Window.OpenButton then
- Current.Document.Scroll = Current.Document.Scroll + direction
- if Current.Window.Scroll < 0 then
- Current.Window.Scroll = 0
- elseif Current.Window.Scroll > Current.Window.MaxScroll then
- Current.Window.Scroll = Current.Window.MaxScroll
- end
- Draw()
- elseif Current.ScrollBar then
- if Current.ScrollBar:DoScroll(direction*2) then
- Draw()
- end
- end
- end
- --[[
- Registers functions to run on certain events
- ]]--
- function EventRegister(event, func)
- if not Events[event] then
- Events[event] = {}
- end
- table.insert(Events[event], func)
- end
- --[[
- The main loop event handler, runs registered event functinos
- ]]--
- function EventHandler()
- while true do
- local event, arg1, arg2, arg3, arg4 = os.pullEventRaw()
- if Events[event] then
- for i, e in ipairs(Events[event]) do
- e(event, arg1, arg2, arg3, arg4)
- end
- end
- end
- end
- local function Extension(path, addDot)
- if not path then
- return nil
- elseif not string.find(fs.getName(path), '%.') then
- if not addDot then
- return fs.getName(path)
- else
- return ''
- end
- else
- local _path = path
- if path:sub(#path) == '/' then
- _path = path:sub(1,#path-1)
- end
- local extension = _path:gmatch('%.[0-9a-z]+$')()
- if extension then
- extension = extension:sub(2)
- else
- --extension = nil
- return ''
- end
- if addDot then
- extension = '.'..extension
- end
- return extension:lower()
- end
- end
- local RemoveExtension = function(path)
- if path:sub(1,1) == '.' then
- return path
- end
- local extension = Extension(path)
- if extension == path then
- return fs.getName(path)
- end
- return string.gsub(path, extension, ''):sub(1, -2)
- end
- local acknowledgedColour = false
- function PrintDocument()
- if OneOS then
- OneOS.LoadAPI('/System/API/Helpers.lua')
- OneOS.LoadAPI('/System/API/Peripheral.lua')
- OneOS.LoadAPI('/System/API/Printer.lua')
- end
- local doPrint = function()
- local window = PrintDocumentWindow:Initialise():Show()
- end
- if Peripheral.GetPeripheral('printer') == nil then
- ButtonDialougeWindow:Initialise('No Printer Found', 'Please place a printer next to your computer. Ensure you also insert dye (left slot) and paper (top slots)', 'Ok', nil, function(window, ok)
- window:Close()
- end):Show()
- elseif not acknowledgedColour and FindColours(Current.Document.TextInput.Value) ~= 0 then
- ButtonDialougeWindow:Initialise('Important', 'Due to the way printers work, you can\'t print in more than one colour. The dye you use will be the colour of the text.', 'Ok', nil, function(window, ok)
- acknowledgedColour = true
- window:Close()
- doPrint()
- end):Show()
- else
- doPrint()
- end
- end
- function SaveDocument()
- local function save()
- local h = fs.open(Current.Document.Path, 'w')
- if h then
- if Current.Document.Format == TextFormatPlainText then
- h.write(Current.Document.TextInput.Value)
- else
- local lines = {}
- for p, page in ipairs(Current.Document.Pages) do
- for i, line in ipairs(page.Lines) do
- table.insert(lines, line)
- end
- end
- h.write(textutils.serialize(lines))
- end
- Current.Modified = false
- else
- ButtonDialougeWindow:Initialise('Error', 'An error occured while saving the file, try again.', 'Ok', nil, function(window, ok)
- window:Close()
- end):Show()
- end
- h.close()
- end
- if not Current.Document.Path then
- SaveDocumentWindow:Initialise(function(self, success, path)
- self:Close()
- if success then
- local extension = ''
- if Current.Document.Format == TextFormatPlainText then
- extension = '.txt'
- elseif Current.Document.Format == TextFormatInkText then
- extension = '.ink'
- end
- if path:sub(-4) ~= extension then
- path = path .. extension
- end
- Current.Document.Path = path
- Current.Document.Title = fs.getName(path)
- save()
- end
- if Current.Document then
- Current.TextInput = Current.Document.TextInput
- end
- end):Show()
- else
- save()
- end
- end
- function DisplayOpenDocumentWindow()
- OpenDocumentWindow:Initialise(function(self, success, path)
- self:Close()
- if success then
- OpenDocument(path)
- end
- end):Show()
- end
- function OpenDocument(path)
- Current.Selection = nil
- local h = fs.open(path, 'r')
- if h then
- Current.Document = Document:Initialise(h.readAll(), RemoveExtension(fs.getName(path)), path)
- else
- ButtonDialougeWindow:Initialise('Error', 'An error occured while opening the file, try again.', 'Ok', nil, function(window, ok)
- window:Close()
- if Current.Document then
- Current.TextInput = Current.Document.TextInput
- end
- end):Show()
- end
- h.close()
- end
- local TidyPath = function(path)
- path = '/'..path
- local fs = fs
- if OneOS then
- fs = OneOS.FS
- end
- if fs.isDir(path) then
- path = path .. '/'
- end
- path, n = path:gsub("//", "/")
- while n > 0 do
- path, n = path:gsub("//", "/")
- end
- return path
- end
- OpenDocumentWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- Return = nil,
- OpenButton = nil,
- PathTextBox = nil,
- CurrentDirectory = '/',
- Scroll = 0,
- MaxScroll = 0,
- GoUpButton = nil,
- SelectedFile = '',
- Files = {},
- Typed = false,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 3, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-6, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y + self.Height - 5, self.Width, 5, colours.lightGrey)
- self:DrawFiles()
- if (fs.exists(self.PathTextBox.TextInput.Value)) or (self.SelectedFile and #self.SelectedFile > 0 and fs.exists(self.CurrentDirectory .. self.SelectedFile)) then
- self.OpenButton.TextColour = colours.black
- else
- self.OpenButton.TextColour = colours.lightGrey
- end
- self.PathTextBox:Draw()
- self.OpenButton:Draw()
- self.CancelButton:Draw()
- self.GoUpButton:Draw()
- end,
- DrawFiles = function(self)
- for i, file in ipairs(self.Files) do
- if i > self.Scroll and i - self.Scroll <= 11 then
- if file == self.SelectedFile then
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.white, colours.lightBlue)
- elseif string.find(file, '%.txt') or string.find(file, '%.text') or string.find(file, '%.ink') or fs.isDir(self.CurrentDirectory .. file) then
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.black, colours.white)
- else
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.grey, colours.white)
- end
- end
- end
- self.MaxScroll = #self.Files - 11
- if self.MaxScroll < 0 then
- self.MaxScroll = 0
- end
- end,
- Initialise = function(self, returnFunc)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 32
- new.Height = 17
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = 'Open Document'
- new.Visible = true
- new.CurrentDirectory = '/'
- new.SelectedFile = nil
- if OneOS and fs.exists('/Desktop/Documents/') then
- new.CurrentDirectory = '/Desktop/Documents/'
- end
- new.OpenButton = Button:Initialise(new.Width - 6, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- if fs.exists(new.PathTextBox.TextInput.Value) and self.TextColour == colours.black and not fs.isDir(new.PathTextBox.TextInput.Value) then
- returnFunc(new, true, TidyPath(new.PathTextBox.TextInput.Value))
- elseif new.SelectedFile and self.TextColour == colours.black and fs.isDir(new.CurrentDirectory .. new.SelectedFile) then
- new:GoToDirectory(new.CurrentDirectory .. new.SelectedFile)
- elseif new.SelectedFile and self.TextColour == colours.black then
- returnFunc(new, true, TidyPath(new.CurrentDirectory .. '/' .. new.SelectedFile))
- end
- end, 'Open', colours.black)
- new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- returnFunc(new, false)
- end, 'Cancel', colours.black)
- new.GoUpButton = Button:Initialise(2, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- local folderName = fs.getName(new.CurrentDirectory)
- local parentDirectory = new.CurrentDirectory:sub(1, #new.CurrentDirectory-#folderName-1)
- new:GoToDirectory(parentDirectory)
- end, 'Go Up', colours.black)
- new.PathTextBox = TextBox:Initialise(2, new.Height - 3, new.Width - 2, 1, new, new.CurrentDirectory, colours.white, colours.black)
- new:GoToDirectory(new.CurrentDirectory)
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Input = nil
- Current.Window = nil
- self = nil
- end,
- GoToDirectory = function(self, path)
- path = TidyPath(path)
- self.CurrentDirectory = path
- self.Scroll = 0
- self.SelectedFile = nil
- self.Typed = false
- self.PathTextBox.TextInput.Value = path
- local fs = fs
- if OneOS then
- fs = OneOS.FS
- end
- self.Files = fs.list(self.CurrentDirectory)
- Draw()
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- Click = function(self, side, x, y)
- local items = {self.OpenButton, self.CancelButton, self.PathTextBox, self.GoUpButton}
- local found = false
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- found = true
- end
- end
- if not found then
- if y <= 12 then
- local fs = fs
- if OneOS then
- fs = OneOS.FS
- end
- self.SelectedFile = fs.list(self.CurrentDirectory)[y-1]
- self.PathTextBox.TextInput.Value = TidyPath(self.CurrentDirectory .. '/' .. self.SelectedFile)
- Draw()
- end
- end
- return true
- end
- }
- PrintDocumentWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- Return = nil,
- PrintButton = nil,
- CopiesTextBox = nil,
- Scroll = 0,
- MaxScroll = 0,
- PrinterSelectButton = nil,
- Title = '',
- Status = 0, --0 = neutral, 1 = good, -1 = error
- StatusText = '',
- SelectedPrinter = nil,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- self.PrinterSelectButton:Draw()
- Drawing.DrawCharactersCenter(self.X, self.Y + self.PrinterSelectButton.Y - 2, self.Width, 1, 'Printer', colours.black, colours.white)
- Drawing.DrawCharacters(self.X + self.Width - 3, self.Y + self.PrinterSelectButton.Y - 1, '\\/', colours.black, colours.lightGrey)
- Drawing.DrawCharacters(self.X + 1, self.Y + self.CopiesTextBox.Y - 1, 'Copies', colours.black, colours.white)
- local statusColour = colours.grey
- if self.Status == -1 then
- statusColour = colours.red
- elseif self.Status == 1 then
- statusColour = colours.green
- end
- Drawing.DrawCharacters(self.X + 1, self.Y + self.CopiesTextBox.Y + 1, self.StatusText, statusColour, colours.white)
- self.CopiesTextBox:Draw()
- self.PrintButton:Draw()
- self.CancelButton:Draw()
- end,
- Initialise = function(self)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 32
- new.Height = 11
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = 'Print Document'
- new.Visible = true
- new.PrintButton = Button:Initialise(new.Width - 7, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- local doPrint = true
- if new.SelectedPrinter == nil then
- local p = Peripheral.GetPeripheral('printer')
- if p then
- new.SelectedPrinter = p.Side
- new.PrinterSelectButton.Text = p.Fullname
- else
- new.StatusText = 'No Connected Printer'
- new.Status = -1
- doPrint = false
- end
- end
- if doPrint then
- local printer = Printer:Initialise(new.SelectedPrinter)
- local err = printer:PrintLines(Current.Document.Lines, Current.Document.Title, tonumber(new.CopiesTextBox.TextInput.Value))
- if not err then
- new.StatusText = 'Document Printed!'
- new.Status = 1
- closeWindowTimer = os.startTimer(1)
- else
- new.StatusText = err
- new.Status = -1
- end
- end
- end, 'Print', colours.black)
- new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new:Close()
- Draw()
- end, 'Close', colours.black)
- new.PrinterSelectButton = Button:Initialise(2, 4, new.Width - 2, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- local printers = {
- {
- Title = "Automatic",
- Click = function()
- new.SelectedPrinter = nil
- new.PrinterSelectButton.Text = 'Automatic'
- end
- },
- {
- Separator = true
- }
- }
- for i, p in ipairs(Peripheral.GetPeripherals('printer')) do
- table.insert(printers, {
- Title = p.Fullname,
- Click = function(self)
- new.SelectedPrinter = p.Side
- new.PrinterSelectButton.Text = p.Fullname
- end
- })
- end
- Current.Menu = Menu:New(x, y+4, printers, self, true)
- end, 'Automatic', colours.black)
- new.CopiesTextBox = TextBox:Initialise(9, 6, 4, 1, new, 1, colours.lightGrey, colours.black, nil, true)
- Current.TextInput = new.CopiesTextBox.TextInput
- new.StatusText = 'Waiting...'
- new.Status = 0
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Input = nil
- Current.Window = nil
- self = nil
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- Click = function(self, side, x, y)
- local items = {self.PrintButton, self.CancelButton, self.CopiesTextBox, self.PrinterSelectButton}
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- end
- end
- return true
- end
- }
- SaveDocumentWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- Return = nil,
- SaveButton = nil,
- PathTextBox = nil,
- CurrentDirectory = '/',
- Scroll = 0,
- MaxScroll = 0,
- ScrollBar = nil,
- GoUpButton = nil,
- Files = {},
- Typed = false,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 3, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-6, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y + self.Height - 5, self.Width, 5, colours.lightGrey)
- Drawing.DrawCharacters(self.X + 1, self.Y + self.Height - 5, self.CurrentDirectory, colours.grey, colours.lightGrey)
- self:DrawFiles()
- if (self.PathTextBox.TextInput.Value) then
- self.SaveButton.TextColour = colours.black
- else
- self.SaveButton.TextColour = colours.lightGrey
- end
- self.PathTextBox:Draw()
- self.SaveButton:Draw()
- self.CancelButton:Draw()
- self.GoUpButton:Draw()
- end,
- DrawFiles = function(self)
- for i, file in ipairs(self.Files) do
- if i > self.Scroll and i - self.Scroll <= 10 then
- if file == self.SelectedFile then
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.white, colours.lightBlue)
- elseif fs.isDir(self.CurrentDirectory .. file) then
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.black, colours.white)
- else
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.lightGrey, colours.white)
- end
- end
- end
- self.MaxScroll = #self.Files - 11
- if self.MaxScroll < 0 then
- self.MaxScroll = 0
- end
- end,
- Initialise = function(self, returnFunc)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 32
- new.Height = 16
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = 'Save Document'
- new.Visible = true
- new.CurrentDirectory = '/'
- if OneOS and fs.exists('/Desktop/Documents/') then
- new.CurrentDirectory = '/Desktop/Documents/'
- end
- new.SaveButton = Button:Initialise(new.Width - 6, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- if self.TextColour == colours.black and not fs.isDir(new.CurrentDirectory ..'/' .. new.PathTextBox.TextInput.Value) then
- returnFunc(new, true, TidyPath(new.CurrentDirectory ..'/' .. new.PathTextBox.TextInput.Value))
- elseif new.SelectedFile and self.TextColour == colours.black and fs.isDir(new.CurrentDirectory .. new.SelectedFile) then
- new:GoToDirectory(new.CurrentDirectory .. new.SelectedFile)
- end
- end, 'Save', colours.black)
- new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- returnFunc(new, false)
- end, 'Cancel', colours.black)
- new.GoUpButton = Button:Initialise(2, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- local folderName = fs.getName(new.CurrentDirectory)
- local parentDirectory = new.CurrentDirectory:sub(1, #new.CurrentDirectory-#folderName-1)
- new:GoToDirectory(parentDirectory)
- end, 'Go Up', colours.black)
- new.PathTextBox = TextBox:Initialise(2, new.Height - 3, new.Width - 2, 1, new, '', colours.white, colours.black, function(key)
- if key == keys.enter then
- new.SaveButton:Click()
- end
- end)
- new.PathTextBox.Placeholder = 'Document Name'
- Current.TextInput = new.PathTextBox.TextInput
- new:GoToDirectory(new.CurrentDirectory)
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Input = nil
- Current.Window = nil
- self = nil
- end,
- GoToDirectory = function(self, path)
- path = TidyPath(path)
- self.CurrentDirectory = path
- self.Scroll = 0
- self.Typed = false
- local fs = fs
- if OneOS then
- fs = OneOS.FS
- end
- self.Files = fs.list(self.CurrentDirectory)
- Draw()
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- Click = function(self, side, x, y)
- local items = {self.SaveButton, self.CancelButton, self.PathTextBox, self.GoUpButton}
- local found = false
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- found = true
- end
- end
- if not found then
- if y <= 11 then
- local files = fs.list(self.CurrentDirectory)
- if files[y-1] then
- self:GoToDirectory(self.CurrentDirectory..files[y-1])
- Draw()
- end
- end
- end
- return true
- end
- }
- local WrapText = function(text, maxWidth)
- local lines = {''}
- for word, space in text:gmatch('(%S+)(%s*)') do
- local temp = lines[#lines] .. word .. space:gsub('\n','')
- if #temp > maxWidth then
- table.insert(lines, '')
- end
- if space:find('\n') then
- lines[#lines] = lines[#lines] .. word
- space = space:gsub('\n', function()
- table.insert(lines, '')
- return ''
- end)
- else
- lines[#lines] = lines[#lines] .. word .. space
- end
- end
- return lines
- end
- ButtonDialougeWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- CancelButton = nil,
- OkButton = nil,
- Lines = {},
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- for i, text in ipairs(self.Lines) do
- Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
- end
- self.OkButton:Draw()
- if self.CancelButton then
- self.CancelButton:Draw()
- end
- end,
- Initialise = function(self, title, message, okText, cancelText, returnFunc)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 28
- new.Lines = WrapText(message, new.Width - 2)
- new.Height = 5 + #new.Lines
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = title
- new.Visible = true
- new.Visible = true
- new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
- returnFunc(new, true)
- end, okText)
- if cancelText then
- new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
- returnFunc(new, false)
- end, cancelText)
- end
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Window = nil
- self = nil
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- Click = function(self, side, x, y)
- local items = {self.OkButton, self.CancelButton}
- local found = false
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- found = true
- end
- end
- return true
- end
- }
- TextDialougeWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- CancelButton = nil,
- OkButton = nil,
- Lines = {},
- TextInput = nil,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- for i, text in ipairs(self.Lines) do
- Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y + self.Height - 4, self.Width - 2, 1, colours.lightGrey)
- Drawing.DrawCharacters(self.X + 2, self.Y + self.Height - 4, self.TextInput.Value, colours.black, colours.lightGrey)
- Current.CursorPos = {self.X + 2 + self.TextInput.CursorPos, self.Y + self.Height - 4}
- Current.CursorColour = colours.black
- self.OkButton:Draw()
- if self.CancelButton then
- self.CancelButton:Draw()
- end
- end,
- Initialise = function(self, title, message, okText, cancelText, returnFunc, numerical)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 28
- new.Lines = WrapText(message, new.Width - 2)
- new.Height = 7 + #new.Lines
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = title
- new.Visible = true
- new.Visible = true
- new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
- if #new.TextInput.Value > 0 then
- returnFunc(new, true, new.TextInput.Value)
- end
- end, okText)
- if cancelText then
- new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
- returnFunc(new, false)
- end, cancelText)
- end
- new.TextInput = TextInput:Initialise('', function(enter)
- if enter then
- new.OkButton:Click()
- end
- Draw()
- end, numerical)
- Current.Input = new.TextInput
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Window = nil
- Current.Input = nil
- self = nil
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- Click = function(self, side, x, y)
- local items = {self.OkButton, self.CancelButton}
- local found = false
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- found = true
- end
- end
- return true
- end
- }
- function PrintCentered(text, y)
- local w, h = term.getSize()
- x = math.ceil(math.ceil((w / 2) - (#text / 2)), 0)+1
- term.setCursorPos(x, y)
- print(text)
- end
- function DoVanillaClose()
- term.setBackgroundColour(colours.black)
- term.setTextColour(colours.white)
- term.clear()
- term.setCursorPos(1, 1)
- PrintCentered("Thanks for using Ink!", (Drawing.Screen.Height/2)-1)
- term.setTextColour(colours.lightGrey)
- PrintCentered("Word Proccessor for ComputerCraft", (Drawing.Screen.Height/2))
- term.setTextColour(colours.white)
- PrintCentered("(c) oeed 2014", (Drawing.Screen.Height/2)+3)
- term.setCursorPos(1, Drawing.Screen.Height)
- desktop()
- end
- function Close()
- if isQuitting or not Current.Document or not Current.Modified then
- if not OneOS then
- DoVanillaClose()
- end
- return true
- else
- local _w = ButtonDialougeWindow:Initialise('Quit Ink?', 'You have unsaved changes, do you want to quit anyway?', 'Quit', 'Cancel', function(window, success)
- if success then
- if OneOS then
- OneOS.Close(true)
- else
- DoVanillaClose()
- end
- end
- window:Close()
- Draw()
- end):Show()
- --it's hacky but it works
- os.queueEvent('mouse_click', 1, _w.X, _w.Y)
- return false
- end
- end
- if OneOS then
- OneOS.CanClose = function()
- return Close()
- end
- end
- Initialise()
- end
- --[[###################################################################################################################################################
- ########################################### END OF PROGRAM CODE ###############################################
- #####################################################################################################################################################]]
- --[[
- APPLICATION PROGRAMMING INTERFACE INTERNALLY BASED
- ]]
- draw = {}
- draw.__index = draw
- config = {}
- config.__index = config
- db = {}
- db.__index = db
- crypt = {}
- crypt.__index = crypt
- col = {}
- col.__index = col
- misc = {}
- misc.__index = misc
- data = {}
- data.__index = data
- help = {}
- help.__index = help
- user = {}
- user.__index = user
- email = {}
- email.__index = email
- chat = {}
- chat.__index = chat
- image = {}
- image.__index = image
- ccsys = {}
- ccsys.__index = ccsys
- function user.login(user, pass)
- local pass = crypt.sha256(pass)
- local req = http.post("http://api.dannysmc.com/user.php", "cmd="..textutils.urlEncode(tostring("login")).."&username="..textutils.urlEncode(tostring(user)).."&password="..textutils.urlEncode(tostring(pass)))
- local req = textutils.unserialize(req.readAll())
- if req.status then
- return true
- else
- return false
- end
- end
- function user.register(user, pass, email)
- local pass = crypt.sha256(pass)
- local req = http.post("http://api.dannysmc.com/user.php", "cmd="..textutils.urlEncode(tostring("register")).."&username="..textutils.urlEncode(tostring(user)).."&password="..textutils.urlEncode(tostring(pass)).."&email="..textutils.urlEncode(tostring(email)))
- local req = textutils.unserialize(req.readAll())
- if req.status then
- return true
- else
- return false
- end
- end
- function ccsys.submitbug(email, prog, desc, code)
- local req = http.post(tUrls["FusionBugreport"], "username="..textutils.urlEncode(tostring(email)).."&".."emailto="..textutils.urlEncode(tostring("danny.smc95@gmail.com")).."&".."emailsubject="..textutils.urlEncode(tostring(prog)).."&".."emailmessage="..textutils.urlEncode(tostring("DESC: "..desc..". Code: "..code)))
- end
- function config.save(table, file)
- fConfig = fs.open(file, "w") or error("Cannot open file "..file, 2)
- fConfig.write(textutils.serialize(table))
- fConfig.close()
- end
- function config.load(file)
- fConfig = fs.open(file, "r")
- ret = textutils.unserialize(fConfig.readAll())
- return ret
- end
- function image.draw(intx, inty, imgpath)
- local tempImage = paintutils.loadImage(imgpath..".fusi")
- paintutils.drawImage(tempImage, intx, inty)
- end
- function draw.cscreen()
- term.clear()
- term.setCursorPos(1,1)
- return
- end
- function draw.textc(Text, Line, NextLine, Color, BkgColor)
- local x, y = term.getSize()
- x = x/2 - #Text/2
- term.setCursorPos(x, Line)
- if Color then
- col.set(Color, BkgColor)
- end
- term.write(Text)
- if NextLine then
- term.setCursorPos(1, NextLine)
- end
- if Color then
- col.reset(Color, BkgColor)
- end
- return true
- end
- function draw.texta(Text, xx, yy, NextLine, Color, BkgColor)
- term.setCursorPos(xx,yy)
- if Color then
- col.set(Color, BkgColor)
- end
- term.write(Text)
- if NextLine then
- term.setCursorPos(1, NextLine)
- end
- if Color then
- col.reset(Color, BkgColor)
- end
- return true
- end
- function draw.cline(Line, NextLine)
- local x, y = term.getSize()
- for i = 1, x do
- term.setCursorPos(i, Line)
- term.write(" ")
- end
- if not NextLine then
- x, y = term.getCursorPos()
- term.setCursorPos(1, y+1)
- end
- return true
- end
- function draw.popup(text)
- draw.box(1, 51, 8, 1, " ", "lime", "red")
- draw.textc(text, 8, false, "lime", "red")
- sleep(1.5)
- end
- function draw.box(StartX, lengthX, StartY, lengthY, Text, Color, BkgColor)
- local x, y = term.getSize()
- if Color then
- col.set(Color, BkgColor)
- end
- if not Text then
- Text = "*"
- end
- lengthX = lengthX - 1
- lengthY = lengthY - 1
- EndX = StartX + lengthX
- EndY = StartY + lengthY
- term.setCursorPos(StartX, StartY)
- term.write(string.rep(Text, lengthX))
- term.setCursorPos(StartX, EndY)
- term.write(string.rep(Text, lengthX))
- for i = StartY, EndY do
- term.setCursorPos(StartX, i)
- term.write(Text)
- term.setCursorPos(EndX, i)
- term.write(Text)
- end
- col.reset(Color, BkgColor)
- return true
- end
- function db.delete(Filename)
- if fs.exists(Filename) then
- fs.delete(Filename)
- return true
- end
- return false
- end
- function db.load(Filename)
- if not fs.exists(Filename) then
- local F = fs.open(Filename, "w")
- F.write("{}")
- F.close()
- end
- local F = fs.open(Filename, "r")
- local Data = F.readAll()
- F.close()
- Data = textutils.unserialize(Data)
- return Data
- end
- function db.save(Filename, ATable)
- local Data = textutils.serialize(ATable)
- local F = fs.open(Filename, "w")
- F.write(Data)
- F.close()
- return true
- end
- function db.search(searchstring, ATable)
- for i, V in pairs(ATable) do
- if tostring(ATable[i]) == tostring(searchstring) then
- return i
- end
- end
- return 0
- end
- function db.removeString(Filename, AString)
- local TempT = db.load(Filename)
- if type(TempT) ~= "table" then
- return false
- end
- local Pos = db.search(AString, TempT)
- if Pos > 0 then
- table.remove(TempT, Pos)
- db.save(Filename, TempT)
- return true
- else
- return false
- end
- end
- function db.insertString(Filename, AString)
- local TempT = db.load(Filename)
- if type(TempT) ~= "table" then
- TempT = {}
- end
- table.insert(TempT, AString)
- db.save(Filename, TempT)
- return true
- end
- local MOD = 2^32
- local MODM = MOD-1
- local function memoize(f)
- local mt = {}
- local t = setmetatable({}, mt)
- function mt:__index(k)
- local v = f(k)
- t[k] = v
- return v
- end
- return t
- end
- local function make_bitop_uncached(t, m)
- local function bitop(a, b)
- local res,p = 0,1
- while a ~= 0 and b ~= 0 do
- local am, bm = a % m, b % m
- res = res + t[am][bm] * p
- a = (a - am) / m
- b = (b - bm) / m
- p = p*m
- end
- res = res + (a + b) * p
- return res
- end
- return bitop
- end
- local function make_bitop(t)
- local op1 = make_bitop_uncached(t,2^1)
- local op2 = memoize(function(a) return memoize(function(b) return op1(a, b) end) end)
- return make_bitop_uncached(op2, 2 ^ (t.n or 1))
- end
- local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})
- local function bxor(a, b, c, ...)
- local z = nil
- if b then
- a = a % MOD
- b = b % MOD
- z = bxor1(a, b)
- if c then z = bxor(z, c, ...) end
- return z
- elseif a then return a % MOD
- else return 0 end
- end
- local function band(a, b, c, ...)
- local z
- if b then
- a = a % MOD
- b = b % MOD
- z = ((a + b) - bxor1(a,b)) / 2
- if c then z = bit32_band(z, c, ...) end
- return z
- elseif a then return a % MOD
- else return MODM end
- end
- local function bnot(x) return (-1 - x) % MOD end
- local function rshift1(a, disp)
- if disp < 0 then return lshift(a,-disp) end
- return math.floor(a % 2 ^ 32 / 2 ^ disp)
- end
- local function rshift(x, disp)
- if disp > 31 or disp < -31 then return 0 end
- return rshift1(x % MOD, disp)
- end
- local function lshift(a, disp)
- if disp < 0 then return rshift(a,-disp) end
- return (a * 2 ^ disp) % 2 ^ 32
- end
- local function rrotate(x, disp)
- x = x % MOD
- disp = disp % 32
- local low = band(x, 2 ^ disp - 1)
- return rshift(x, disp) + lshift(low, 32 - disp)
- end
- local k = {
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
- 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
- 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
- 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
- 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
- }
- local function str2hexa(s)
- return (string.gsub(s, ".", function(c) return string.format("%02x", string.byte(c)) end))
- end
- local function num2s(l, n)
- local s = ""
- for i = 1, n do
- local rem = l % 256
- s = string.char(rem) .. s
- l = (l - rem) / 256
- end
- return s
- end
- local function s232num(s, i)
- local n = 0
- for i = i, i + 3 do n = n*256 + string.byte(s, i) end
- return n
- end
- local function preproc(msg, len)
- local extra = 64 - ((len + 9) % 64)
- len = num2s(8 * len, 8)
- msg = msg .. "\128" .. string.rep("\0", extra) .. len
- assert(#msg % 64 == 0)
- return msg
- end
- local function initH256(H)
- H[1] = 0x6a09e667
- H[2] = 0xbb67ae85
- H[3] = 0x3c6ef372
- H[4] = 0xa54ff53a
- H[5] = 0x510e527f
- H[6] = 0x9b05688c
- H[7] = 0x1f83d9ab
- H[8] = 0x5be0cd19
- return H
- end
- local function digestblock(msg, i, H)
- local w = {}
- for j = 1, 16 do w[j] = s232num(msg, i + (j - 1)*4) end
- for j = 17, 64 do
- local v = w[j - 15]
- local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3))
- v = w[j - 2]
- w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10))
- end
- local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
- for i = 1, 64 do
- local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))
- local maj = bxor(band(a, b), band(a, c), band(b, c))
- local t2 = s0 + maj
- local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))
- local ch = bxor (band(e, f), band(bnot(e), g))
- local t1 = h + s1 + ch + k[i] + w[i]
- h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2
- end
- H[1] = band(H[1] + a)
- H[2] = band(H[2] + b)
- H[3] = band(H[3] + c)
- H[4] = band(H[4] + d)
- H[5] = band(H[5] + e)
- H[6] = band(H[6] + f)
- H[7] = band(H[7] + g)
- H[8] = band(H[8] + h)
- end
- function crypt.sha256(msg)
- msg = preproc(msg, #msg)
- local H = initH256({})
- for i = 1, #msg, 64 do digestblock(msg, i, H) end
- return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) ..
- num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4))
- end
- local function zfill(N)
- N=string.format("%X",N)
- Zs=""
- if #N==1 then
- Zs="0"
- end
- return Zs..N
- end
- local function serializeImpl(t)
- local sType = type(t)
- if sType == "table" then
- local lstcnt=0
- for k,v in pairs(t) do
- lstcnt = lstcnt + 1
- end
- local result = "{"
- local aset=1
- for k,v in pairs(t) do
- if k==aset then
- result = result..serializeImpl(v)..","
- aset=aset+1
- else
- result = result..("["..serializeImpl(k).."]="..serializeImpl(v)..",")
- end
- end
- result = result.."}"
- return result
- elseif sType == "string" then
- return string.format("%q",t)
- elseif sType == "number" or sType == "boolean" or sType == "nil" then
- return tostring(t)
- elseif sType == "function" then
- local status,data=pcall(string.dump,t)
- if status then
- return 'func('..string.format("%q",data)..')'
- else
- error()
- end
- else
- error()
- end
- end
- local function split(T,func)
- if func then
- T=func(T)
- end
- local Out={}
- if type(T)=="table" then
- for k,v in pairs(T) do
- Out[split(k)]=split(v)
- end
- else
- Out=T
- end
- return Out
- end
- local function serialize( t )
- t=split(t)
- return serializeImpl( t, tTracking )
- end
- local function unserialize( s )
- local func, e = loadstring( "return "..s, "serialize" )
- local funcs={}
- if not func then
- return e
- end
- setfenv( func, {
- func=function(S)
- local new={}
- funcs[new]=S
- return new
- end,
- })
- return split(func(),function(val)
- if funcs[val] then
- return loadstring(funcs[val])
- else
- return val
- end
- end)
- end
- local function sure(N,n)
- if (l2-n)<1 then N="0" end
- return N
- end
- local function splitnum(S)
- Out=""
- for l1=1,#S,2 do
- l2=(#S-l1)+1
- CNum=tonumber("0x"..sure(string.sub(S,l2-1,l2-1),1) .. sure(string.sub(S,l2,l2),0))
- Out=string.char(CNum)..Out
- end
- return Out
- end
- local function wrap(N)
- return N-(math.floor(N/256)*256)
- end
- function checksum(S,num) -- args strInput and intPassNumber
- local sum=0
- for char in string.gmatch(S,".") do
- for l1=1,(num or 1) do
- math.randomseed(string.byte(char)+sum)
- sum=sum+math.random(0,9999)
- end
- end
- math.randomseed(sum)
- return sum
- end
- local function genkey(len,psw)
- checksum(psw)
- local key={}
- local tKeys={}
- for l1=1,len do
- local num=math.random(1,len)
- while tKeys[num] do
- num=math.random(1,len)
- end
- tKeys[num]=true
- key[l1]={num,math.random(0,255)}
- end
- return key
- end
- function crypt.encrypt(data,psw) -- args strInput and strPassword
- data=serialize(data)
- local chs=checksum(data)
- local key=genkey(#data,psw)
- local out={}
- local cnt=1
- for char in string.gmatch(data,".") do
- table.insert(out,key[cnt][1],zfill(wrap(string.byte(char)+key[cnt][2])),chars)
- cnt=cnt+1
- end
- return string.sub(serialize({chs,table.concat(out)}),2,-3)
- end
- function crypt.decrypt(data,psw) -- args strInput and strPassword
- local oData=data
- data=unserialize("{"..data.."}")
- if type(data)~="table" then
- return oData
- end
- local chs=data[1]
- data=data[2]
- local key=genkey((#data)/2,psw)
- local sKey={}
- for k,v in pairs(key) do
- sKey[v[1]]={k,v[2]}
- end
- local str=splitnum(data)
- local cnt=1
- local out={}
- for char in string.gmatch(str,".") do
- table.insert(out,sKey[cnt][1],string.char(wrap(string.byte(char)-sKey[cnt][2])))
- cnt=cnt+1
- end
- out=table.concat(out)
- if checksum(out or "")==chs then
- return unserialize(out)
- end
- return oData,out,chs
- end
- function col.set(textColour, backgroundColour)
- if textColour and backgroundColour then
- if term.isColour() then
- term.setTextColour(colours[textColour])
- term.setBackgroundColour(colours[backgroundColour])
- return true
- else
- return false
- end
- else
- return false
- end
- end
- function col.screen(txtCol, bkgCol)
- intX = 1
- intY = 1
- col.set(txtCol, bkgCol)
- repeat
- intX = 1
- repeat
- term.setCursorPos(intX, intY)
- write(" ")
- intX = intX + 1
- until intX == 52
- intY = intY + 1
- until intY == 20
- end
- function col.reset()
- if term.isColour then
- term.setTextColour(colours.white)
- term.setBackgroundColour(colours.black)
- return true
- else
- return false
- end
- end
- function misc.find(Perihp)
- for _,s in ipairs(rs.getSides()) do
- if peripheral.isPresent(s) and peripheral.getType(s) == Perihp then
- return s
- end
- end
- return false
- end
- function misc.serialgen(digits)
- local serial
- for i = 1, digits do
- if i == 1 then
- serial = math.random(9)
- else
- serial = serial.. math.random(9)
- end
- end
- serial = tonumber(serial)
- return serial
- end
- function misc.time()
- local nTime = textutils.formatTime(os.time(), true)
- if string.len(nTime) == 4 then
- nTime = "0"..nTime
- end
- os.startTimer(1)
- return nTime
- end
- function data.wordwrap(str, limit)
- limit = limit or 72
- local here = 1
- local buf = ""
- local t = {}
- str:gsub("(%s*)()(%S+)()",
- function(sp, st, word, fi)
- if fi-here > limit then
- --# Break the line
- here = st
- table.insert(t, buf)
- buf = word
- else
- buf = buf..sp..word --# Append
- end
- end)
- --# Tack on any leftovers
- if(buf ~= "") then
- table.insert(t, buf)
- end
- return t
- end
- -- Start Program Inititator:
- if fs.exists("/core/") then
- login()
- else
- init("install")
- end
Add Comment
Please, Sign In to add comment