Advertisement
HydrantHunter

ccDialer 1.5

Jun 4th, 2014
1,607
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 48.41 KB | None | 0 0
  1. --[[  LanteaCraft      ]]--
  2. --[[      and SGCraft  ]]--
  3. --[[     ccDialer      ]]--
  4. --[[      by Dog       ]]--
  5. --[[ aka HydrantHunter ]]--
  6. --[[ pastebin TUQvDbbm ]]--
  7. local ccDialVer = "1.5.02"
  8. --[[
  9. Tested with/requires:
  10.   - Minecraft 1.7.10
  11.   - LanteaCraft-1.7.10-70 || SGCraft1.95-mc1.7.10
  12.   - ComputerCraft 1.73, 1.74, 1.75
  13.     - An advanced wireless pocket computer
  14.     - ccDHD (with pSync turned ON) running on an Advanced Computer (with a wireless modem) or gateBuddy running on a Computer (standard or advanced with a wireless modem) or a wireless turtle (standard or advanced)
  15. ]]--
  16. --# AUTOMATIC/STATIC CONFIGURATION
  17. --# Peripherals
  18. local termX, termY = term.getSize() --# pocket 26x20 / tab 26x19
  19. local netSide = "none"
  20. --# Status Info
  21. local runState, thisGate = "init", "NO HOST"
  22. local drawCLI, drawRatingList, assignRating, assignColor, pSyncHost, tempState, pNum, currentEdit
  23. local pHosts, gateHosts = { }, { }
  24. --# Address Book
  25. local addressBook = { { name = "NO GATES", addr = "ADDRESS", rating = "U", iris = "none", note = "Short note", loc = { x = 99999, y = 99999, z = 99999, dim = "Overworld", }, }, }
  26. local gateChange = false
  27. local gatePages, gatePage = 1, 1
  28. --# Color Definitions
  29. local white = colors.white
  30. local silver = colors.lightGray
  31. local gray = colors.gray
  32. local black = colors.black
  33. local brown = colors.brown
  34. local yellow = colors.yellow
  35. local orange = colors.orange
  36. local red = colors.red
  37. local magenta = colors.magenta
  38. local purple = colors.purple
  39. local blue = colors.blue
  40. local sky = colors.lightBlue
  41. local cyan = colors.cyan
  42. local lime = colors.lime
  43. local green = colors.green
  44. --# END AUTOMATIC/STATIC CONFIGURATION
  45.  
  46. local function netSend(dataPack)
  47.   if not rednet.isOpen(netSide) then
  48.     rednet.open(netSide)
  49.   end
  50.   local data = { program = "pSync", gate = thisGate, command = dataPack }
  51.   if pSyncHost then
  52.     rednet.send(pSyncHost, data)
  53.   end
  54. end
  55.  
  56. local function mergeAddressBooks(newGates)
  57.   local matchFound = false                            --# use matchFound to indicate if a matching gate was found or not
  58.   for i = 1, #newGates do                             --# start cycling through the 'new' list of gates
  59.     for j = 1, #addressBook do                        --# search the address book for a matching address
  60.       if newGates[i].addr == addressBook[j].addr then --# if the gate is already in the address book...
  61.         matchFound = true                             --# ...set matchFound to true and...
  62.         break                                         --# stop the address book search loop and move on to the next gate in the 'new' list
  63.       end
  64.     end
  65.     if not matchFound then                            --# if a match wasn't found...
  66.       addressBook[#addressBook + 1] = { }             --# initialize a new address book entry
  67.       for k, v in pairs(newGates[i]) do               --# loop through the gate entries...
  68.         addressBook[#addressBook][k] = v              --# ...and add them to the new address book entry
  69.       end
  70.       if not addressBook[#addressBook].iris then
  71.         addressBook[#addressBook].iris = "none"
  72.       end
  73.       gateChange = true                               --# indicate that address book data has changed
  74.     else
  75.       matchFound = false                              --# if a match was found, reset the variable for the next iteration of the loop
  76.     end
  77.   end
  78.   gatePages = math.ceil(#addressBook / 14)            --# repaginate gates
  79. end
  80.  
  81. local function pSync(pushpull) --# Sync addressBook with ccDHD
  82.   if pSyncHost then
  83.     netSend(pushpull)
  84.   end
  85.   if pushpull == "pPull" then
  86.     local id, message = rednet.receive(1)
  87.     if id == pSyncHost then
  88.       mergeAddressBooks(message)
  89.     end
  90.   elseif pushpull == "pPush" then
  91.     sleep(0.1)
  92.     netSend(addressBook)
  93.   end
  94. end
  95.  
  96. local function shutDown()
  97.   if rednet.isOpen(netSide) then
  98.     rednet.close(netSide)
  99.   end
  100. end
  101.  
  102. local function saveData()
  103.   local dhdConfig = fs.open("/data/DHDgates", "w") or function() shutDown() error("saveData(): Cannot open /data/DHDgates for writing", 0) end
  104.   dhdConfig.write(textutils.serialize(addressBook))
  105.   dhdConfig.close()
  106.   gateChange = false
  107. end
  108.  
  109. local function ingestData()
  110.   if not fs.exists("/data/DHDgates") then return end
  111.   local dhdConfig = fs.open("/data/DHDgates", "r") or function() shutDown() error("ingestData(): Cannot open /data/DHDgates for reading", 0) end
  112.   addressBook = textutils.unserialize(dhdConfig.readAll())
  113.   dhdConfig.close()
  114.   gatePages = math.max(1, math.ceil(#addressBook / 14))
  115.   local resaveAB = false
  116.   for i = 1, #addressBook do
  117.     if not addressBook[i].name then
  118.       addressBook[i].name = addressBook[i].addr
  119.       resaveAB = true
  120.     end
  121.     if not addressBook[i].iris then
  122.       addressBook[i].iris = "none"
  123.       resaveAB = true
  124.     end
  125.   end
  126.   if resaveAB then saveData() end
  127. end
  128.  
  129. do
  130.   local colorBurst = {
  131.     B = { blue, "Base/Outpost/Hub" },
  132.     H = { sky, "Home/Camp" },
  133.     V = { brown, "Village" },
  134.     M = { purple, "Misc/Special" },
  135.     S = { green, "Safe/Secured" },
  136.     C = { orange, "Caution" },
  137.     D = { red, "Danger" },
  138.     U = { silver, "Unknown/Unclassified" }
  139.   }
  140.  
  141.   assignColor = function(gateNumber)
  142.     return colorBurst[addressBook[gateNumber].rating][1]
  143.   end
  144.  
  145.   assignRating = function(gateNumber)
  146.     return colorBurst[addressBook[gateNumber].rating][2]
  147.   end
  148. end
  149.  
  150. local function clearScreen(bgColor)
  151.   term.setBackgroundColor(bgColor or black)
  152.   term.clear()
  153. end
  154.  
  155. local function drawElement(x, y, w, h, txtColor, bgColor, text)
  156.   if bgColor then term.setBackgroundColor(bgColor) end
  157.   local deText = text and tostring(text) or ""
  158.   if w > #deText or h > 1 then        --# We're drawing something more than text
  159.     local line = string.rep(" ", w)   --# Define one line of the 'element' (box/rectange/line-seg)
  160.     for i = 1, h do
  161.       term.setCursorPos(x, y + i - 1) --# Increment the cursor position
  162.       term.write(line)                --# Draw 1 of h lines of the 'element' (box/rectangle/line-seg)
  163.     end
  164.   end
  165.   if deText ~= "" then
  166.     if txtColor then term.setTextColor(txtColor) end
  167.     w = math.max(w, #deText)          --# Ensure minimum length
  168.     local xW = (x + math.floor(w / 2)) - math.floor(#deText / 2) --# Center the text horizontally
  169.     local yH = y + math.floor(h / 2)  --# Center the text vertically
  170.     term.setCursorPos(xW, yH)         --# Set the cursor position
  171.     term.write(deText)                --# Write the text
  172.   end
  173. end
  174.  
  175. do
  176.   local ratings = {
  177.     [1] = { rating = "B", color = blue, desc = "Base/Outpost/Hub" },
  178.     [2] = { rating = "H", color = sky, desc = "Home/Camp" },
  179.     [3] = { rating = "V", color = brown, desc = "Village" },
  180.     [4] = { rating = "M", color = purple, desc = "Misc/Special" },
  181.     [5] = { rating = "S", color = green, desc = "Safe/Secured" },
  182.     [6] = { rating = "C", color = orange, desc = "Caution" },
  183.     [7] = { rating = "D", color = red, desc = "Danger" },
  184.     [8] = { rating = "U", color = silver, desc = "Unk/Unclassified" },
  185.   }
  186.  
  187.   drawRatingList = function(gRating)
  188.     local rColor
  189.     drawElement(7, 6, 19, 8, nil, gray, "")                  --# menu body
  190.     for i = 1, #ratings do
  191.       if gRating == ratings[i].rating then
  192.         rColor = gRating == "U" and white or ratings[i].color
  193.         drawElement(25, i + 5, 1, 1, nil, ratings[i].color, "") --# selected rating color pip
  194.       else
  195.         rColor = silver
  196.       end
  197.       drawElement(6, i + 5, 1, 1, nil, ratings[i].color, "") --# color pip
  198.       drawElement(8, i + 5, 1, 1, rColor, gray, ratings[i].desc)
  199.     end
  200.   end
  201. end
  202.  
  203. local function drawHeader()
  204.   --local title = "[ ] [ ]" .. string.rep(" ", math.floor(termX / 2) - 9) .. "ccDialer" .. string.rep(" ", math.ceil(termX / 2) - 9) .. "[ ]"
  205.   local title
  206.   if runState == "viewing" or runState == "Help" then
  207.     title = string.rep(" ", math.floor(termX / 2) - 4) .. "ccDialer" .. string.rep(" ", math.ceil(termX / 2) - 7) .. "[ ]"
  208.   else
  209.     title = "[ ] [ ]" .. string.rep(" ", math.floor(termX / 2) - 9) .. "ccDialer" .. string.rep(" ", math.ceil(termX / 2) - 9) .. "[ ]"
  210.   end
  211.   drawElement(1, 1, termX, 1, white, blue, title)                  --# title bar
  212.   if runState ~= "viewing" and runState ~= "Help" then
  213.     drawElement(2, 1, 1, 1, pSyncHost and green or gray, nil, "H") --# 'H' for pSync Hosts
  214.     drawElement(6, 1, 1, 1, pSyncHost and green or gray, nil, "I") --# 'I' for Iris control
  215.   end
  216.   drawElement(termX - 1, 1, 1, 1, red, nil, "X")                   --# 'X' for Exit
  217.   local hostName = thisGate
  218.   if runState == "Dial" or runState == "pSync" then
  219.     for i = 1, #addressBook do
  220.       if addressBook[i].addr == thisGate then
  221.         hostName = addressBook[i].name
  222.         break
  223.       end
  224.     end
  225.   end
  226.   if runState == "Dial" then
  227.     drawElement(1, 2, termX, 1, silver, gray, "Host:  " .. hostName)
  228.     drawElement(1, 3, 1, 1, white, cyan, "   pSync   ")
  229.     term.setBackgroundColor(green)
  230.     if gateChange then term.setTextColor(orange) end
  231.     term.write(" + ")
  232.     term.setBackgroundColor(red)
  233.     if gateChange then term.setTextColor(white) end --# change the text color back to white if it was changed to orange
  234.     term.write("  END Call  ")
  235.   elseif runState == "pSync" then
  236.     drawElement(1, 2, termX, 1, silver, gray, "Host:  " .. hostName)
  237.   elseif runState == "Help" then
  238.     drawElement(1, 2, termX, 1, silver, gray, "+ button")
  239.   elseif runState == "viewing" then
  240.     drawElement(1, 2, termX, 1, silver, gray, "Gate Information")
  241.   end
  242. end
  243.  
  244. local function drawHelpUI()
  245.   drawElement(1, 6, termX, 1, silver, gray, "Address Book")
  246.   drawElement(1, 11, termX, 1, nil, nil, "Header buttons")
  247.   drawElement(1, 16, termX, 1, nil, nil, "pSync button")
  248.   drawElement(1, termY, termX, 1, nil, nil, "version " .. ccDialVer)
  249.   drawElement(2, 3, 1, 1, black, white, "(L) click: Add address")
  250.   drawElement(2, 4, 1, 1, nil, nil, "(R) click: Save addr book")
  251.   drawElement(2, 7, 1, 1, nil, nil, "(L) click: dial address")
  252.   drawElement(2, 8, 1, 1, nil, nil, "(R) click: view or edit")
  253.   drawElement(2, 9, 1, 1, nil, nil, "(M) click: del. address")
  254.   drawElement(2, 12, 1, 1, nil, nil, "[H] = locate pSync host")
  255.   drawElement(2, 13, 1, 1, nil, nil, "[I] = open remote iris")
  256.   drawElement(2, 14, 1, 1, nil, nil, "[X] = Exit/Quit")
  257.   drawElement(2, 17, 1, 1, nil, nil, "(L) click: Send/Receive")
  258.   drawElement(13, 18, 1, 1, nil, nil, "address book")
  259. end
  260.  
  261. local function drawHostsUI()
  262.   drawElement(8, 5, 13, 1, white, blue, "pSync Hosts") --# Header
  263.   drawElement(8, 6, 13, 11, nil, gray, "")             --# Body
  264.   local curPos = 7
  265.   term.setBackgroundColor(silver)
  266.   term.setTextColor(white)
  267.   if gateHosts[1] then
  268.     local hostNames = { }
  269.     for i = 1, #gateHosts do
  270.       hostNames[i] = gateHosts[i]
  271.       for j = 1, #addressBook do
  272.         if addressBook[j].addr == gateHosts[i] then
  273.           hostNames[i] = addressBook[j].name
  274.           break
  275.         end
  276.       end
  277.     end
  278.     for i = 1, #hostNames do
  279.       term.setCursorPos(9, curPos)
  280.       term.write(" " .. hostNames[i] .. " ")           --# Gate host
  281.       if i == 5 then break end
  282.       curPos = curPos + 2
  283.     end
  284.   else
  285.     if runState ~= "init" then
  286.       runState = "Dial"
  287.       clearScreen()
  288.     end
  289.   end
  290. end
  291.  
  292. local function drawIrisPasswordUI()
  293.   drawElement(2, 5, termX - 2, 1, gray, black, "Remote iris password")
  294.   drawElement(6, 6, 16, 3, nil, silver, "")
  295.   drawElement(7, 7, 14, 1, nil, gray, "")
  296. end
  297.  
  298. local function drawPsyncUI()
  299.   drawElement(2, 5, termX - 2, 3, white, green, "GET Address Book")
  300.   drawElement(2, 9, termX - 2, 3, nil, orange, "SEND Address Book")
  301.   drawElement(2, 13, termX - 2, 3, nil, red, "C A N C E L")
  302. end
  303.  
  304. local function drawNaviUI()
  305.   pNum = tostring(gatePage) .. " of " .. tostring(gatePages)
  306.   drawElement((termX / 2) - 10, termY, 7, 1, gray, black, "<< <              > >>")
  307.   drawElement(math.floor(termX / 2) - (math.floor(#pNum / 2)) + 1, termY, 3, 1, silver, nil, pNum)
  308. end
  309.  
  310. local function drawAddressList() --# Gate Address Book (Dial / Edit / Trim)
  311.   local xPos, yPos = 3, 5
  312.   local magicNumber = ((gatePage - 1) * 13) + gatePage
  313.   for i = magicNumber, #addressBook do
  314.     if thisGate == addressBook[i].addr or addressBook[i].addr == thisGate:sub(1, 7) then --# Highlight this gate / Dial
  315.       term.setBackgroundColor(gray)
  316.       term.setTextColor(silver)
  317.     else
  318.       term.setBackgroundColor(assignColor(i))
  319.       term.setTextColor(white)
  320.     end
  321.     term.setCursorPos(xPos, yPos)
  322.     term.write(string.rep(" ", math.floor((9 - #addressBook[i].name) / 2)) .. addressBook[i].name .. string.rep(" ", math.ceil((9 - #addressBook[i].name) / 2))) --# Dial
  323.     yPos = yPos + 2
  324.     if yPos > 17 then xPos = xPos + 13 yPos = 5 end
  325.     if xPos > 17 then break end
  326.   end
  327. end
  328.  
  329. do
  330.   local stateTable = {
  331.     Dial = function() drawAddressList() drawNaviUI() end,
  332.     pSync = function() drawPsyncUI() end,
  333.     syncHosts = function() drawHostsUI() end,
  334.     gateHosts = function() drawHostsUI() end,
  335.     Help = function() drawHelpUI() end
  336.   }
  337.  
  338.   drawCLI = function() --# Client Interface 'decider'
  339.     drawHeader()
  340.     stateTable[runState]()
  341.   end
  342. end
  343.  
  344. local function flashDial(gate, gX, gY, gateNum)
  345.   local gColor = assignColor(gateNum)
  346.   local gLabel = string.rep(" ", math.floor((9 - #gate) / 2)) .. gate .. string.rep(" ", math.ceil((9 - #gate) / 2)) --# Address
  347.   drawElement(gX, gY, 9, 1, gColor, black, gLabel)
  348.   sleep(0.1)
  349.   drawElement(gX, gY, 9, 1, white, gColor, gLabel)
  350. end
  351.  
  352. local function flashChoice(x, y, tCo, bCo, label)
  353.   drawElement(x, y, 1, 1, tCo, bCo, label)
  354.   sleep(0.1)
  355. end
  356.  
  357. local function gateDataChange()
  358.   gateChange = true
  359.   drawElement(6, termY - 1, 6, 1, green, gray, "Save")
  360. end
  361.  
  362. local function deleteGate(gateNum)
  363.   if #addressBook > 1 then                   --# Don't delete if only 1 gate remaining
  364.     table.remove(addressBook, gateNum)
  365.     gateChange = true
  366.     gatePages = math.ceil(#addressBook / 14) --# Re-paginate gates
  367.     gatePage = math.min(gatePage, gatePages)
  368.     if gatePage == gatePages then
  369.       drawElement(2, 5, termX - 2, termY - 5, nil, black, "") --# Clear address book area of screen
  370.     end
  371.     drawElement(13, 3, 1, 1, orange, green, "+")
  372.     drawAddressList()
  373.     drawNaviUI()
  374.   end
  375. end
  376.  
  377. local function drawGateData()
  378.   local teColor = assignColor(currentEdit)
  379.   drawElement(2, 4, 1, 1, yellow, black, addressBook[currentEdit].name .. string.rep(" ", 9 - #addressBook[currentEdit].name)) --# Name
  380.   if thisGate == addressBook[currentEdit].addr or thisGate:sub(1, 7) == addressBook[currentEdit].addr then
  381.     drawElement(15, 6, 1, 1, gray, nil, "pSync Host")                    --# pSync Host
  382.   else
  383.     drawElement(15, 6, 1, 1, nil, nil, "          ")
  384.   end
  385.   drawElement(2, 6, #addressBook[currentEdit].addr, 1, teColor, nil, addressBook[currentEdit].addr .. "  ") --# Address
  386.   local ratingWord = assignRating(currentEdit)
  387.   drawElement(2, 8, 1, 1, silver, nil, "(" .. ratingWord .. ")              ")
  388.   drawElement(3, 8, 1, 1, teColor, nil, ratingWord)                      --# Classification
  389.   drawElement(21, 4, 1, 1, white, nil, currentEdit .. "     ")           --# Entry number ('#')
  390.   if #addressBook[currentEdit].note > 24 then                            --# Note
  391.     drawElement(2, 10, 1, 1, nil, nil, addressBook[currentEdit].note:sub(1, 24))
  392.     drawElement(2, 11, 1, 1, nil, nil, addressBook[currentEdit].note:sub(25, 43) .. string.rep(" ", 19 - #addressBook[currentEdit].note:sub(25, 43)))
  393.   else
  394.     drawElement(2, 10, 1, 1, nil, nil, addressBook[currentEdit].note .. string.rep(" ", 24 - #addressBook[currentEdit].note:sub(1,24)))
  395.   end
  396.   local xStr, yStr, zStr = tostring(addressBook[currentEdit].loc.x), tostring(addressBook[currentEdit].loc.y), tostring(addressBook[currentEdit].loc.z)
  397.   drawElement(7, 13, 1, 1, yellow, nil, addressBook[currentEdit].loc.dim .. string.rep(" ", 19 - #addressBook[currentEdit].loc.dim)) --# Dimension
  398.   drawElement(5, 14, 1, 1, silver, nil, xStr .. string.rep(" ", 9 - #xStr)) --# X
  399.   drawElement(5, 15, 1, 1, nil, nil, yStr .. string.rep(" ", 9 - #yStr))    --# Y
  400.   drawElement(5, 16, 1, 1, nil, nil, zStr .. string.rep(" ", 9 - #zStr))    --# Z
  401.   drawElement(15, termY - 1, 7, 1, red, gray, "Close")
  402.   drawElement(6, termY - 1, 6, 1, gateChange and green or silver, nil, "Save")
  403. end
  404.  
  405. local function drawGateLabels()
  406.   clearScreen()
  407.   drawHeader()
  408.   drawElement(19, 4, 1, 1, gray, black, "#")
  409.   drawElement(2, 13, 4, 1, nil, nil, "Dim:")
  410.   drawElement(2, 14, 2, 1, nil, nil, "x:")
  411.   drawElement(2, 15, 2, 1, nil, nil, "y:")
  412.   drawElement(2, 16, 2, 1, nil, nil, "z:")
  413.   drawGateData()
  414. end
  415.  
  416. local function addNewAddress(fast)
  417.   if #addressBook < 23976 then
  418.     if #addressBook == 1 and addressBook[1].name == "NO GATES" and addressBook[1].addr == "ADDRESS" then
  419.       addressBook[1].name = "Name"
  420.     else
  421.       local newGate = { name = "Name", addr = "ADDRESS", rating = "U", iris = "none", note = "short note", loc = { x = 99999, y = 99999, z = 99999, dim = "Overworld", }, }
  422.       table.insert(addressBook, newGate)
  423.     end
  424.     gateChange = true
  425.     gatePages = math.ceil(#addressBook / 14)              --# Re-paginate gates
  426.     if fast then                                          --# if the new gate is a quick-add....
  427.       if gatePage == gatePages then drawAddressList() end --# ...redraw the address list
  428.       drawNaviUI()
  429.     else
  430.       currentEdit = #addressBook                          --# currentEdit = new gate
  431.       drawGateLabels()
  432.     end
  433.   else
  434.     runState = "Dial"
  435.   end
  436. end
  437.  
  438. local function getGateAddress()
  439.   local id, message = rednet.receive(1)
  440.   if id == pSyncHost and type(message) == "string" then
  441.     local msgLen = #message
  442.     if msgLen == 7 or msgLen == 9 or message == "lockdown" then
  443.       thisGate = message
  444.     else
  445.       return
  446.     end
  447.   else
  448.     return
  449.   end
  450.   local gateMatch = false
  451.   for i = 1, #addressBook do
  452.     if thisGate and (thisGate == addressBook[i].addr or addressBook[i].addr == thisGate:sub(1, 7)) then gateMatch = true break end
  453.   end
  454.   if not gateMatch and thisGate ~= "lockdown" then
  455.     clearScreen()
  456.     if runState ~= "init" then drawHeader() end
  457.     local tempState = runState
  458.     runState = "newGate"
  459.     drawElement(4, 7, 19, 1, white, blue, "New Gate Detected") --# Header
  460.     drawElement(4, 8, 19, 5, nil, gray, "")                    --# Body
  461.     drawElement((termX / 2) - (#thisGate / 2) + 1, 9, 1, 1, silver, nil, thisGate)
  462.     drawElement(7, 11, 5, 1, white, green, "Add")
  463.     drawElement(14, 11, 6, 1, nil, orange, "Skip")
  464.     while true do
  465.       local _, button, mX, mY = os.pullEvent("mouse_click")
  466.       if mX > 6 and mX < 12 and mY == 11 then
  467.         if #addressBook == 1 and (addressBook[1].name == "NO GATES" or addressBook[1].name == "NEW GATE" or addressBook[1].name == "Name") and addressBook[1].addr == "ADDRESS" then table.remove(addressBook, 1) end
  468.         local newGate = { name = thisGate, addr = thisGate, rating = "U", iris = "none", note = "Discovered gate", loc = { x = 99999, y = 99999, z = 99999, dim = "Overworld", }, }
  469.         table.insert(addressBook, newGate)
  470.         saveData()
  471.         break
  472.       elseif mX > 13 and mX < 20 and mY == 11 then
  473.         break
  474.       end
  475.     end
  476.     runState = tempState
  477.     drawElement(4, 7, 19, 6, nil, black, "")                   --# Clear body
  478.   end
  479. end
  480.  
  481. local function selectHost()
  482.   local hostNames = { }
  483.   for i = 1, #gateHosts do
  484.     hostNames[i] = gateHosts[i]
  485.     for j = 1, #addressBook do
  486.       if addressBook[j].addr == gateHosts[i] then
  487.         hostNames[i] = addressBook[j].name
  488.         break
  489.       end
  490.     end
  491.   end
  492.   while gateHosts[1] do
  493.     local _, button, mX, mY = os.pullEvent("mouse_click")
  494.     if mX > 8 and mX < 20 and mY > 6 and mY < 16 then
  495.       local gCounter = 0
  496.       for i = 7, 15, 2 do
  497.         gCounter = gCounter + 1
  498.         if gCounter <= #pHosts then
  499.           if mY == i then
  500.             drawElement(9, i, 11, 1, black, white, hostNames[gCounter])
  501.             sleep(0.1)
  502.             drawElement(9, i, 11, 1, gray, silver, hostNames[gCounter])
  503.             pSyncHost = pHosts[gCounter]
  504.             thisGate = gateHosts[gCounter]
  505.             return
  506.           end
  507.         end
  508.       end
  509.     end
  510.   end
  511. end
  512.  
  513. local function findHosts()
  514.   for i = #pHosts, 1, -1 do                      --# clear pHosts table
  515.     pHosts[i] = nil
  516.   end
  517.   for i = #gateHosts, 1, -1 do                   --# clear gateHosts table
  518.     gateHosts[i] = nil
  519.   end
  520.   pSyncHost, thisGate = nil, "NO HOST"           --# clear pSyncHost and thisGate variables
  521.   pHosts = { rednet.lookup("pSync") }            --# populate pHosts table
  522.   if pHosts[1] then
  523.     for i = 1, #pHosts do                        --# process host list
  524.       pSyncHost = pHosts[i]                      --# set the host
  525.       thisGate = "NO HOST"                       --# reset gate information
  526.       netSend("QRY")                             --# query the host
  527.       getGateAddress()                           --# get gate information
  528.       gateHosts[i] = thisGate                    --# store gate address
  529.     end
  530.     pSyncHost, thisGate = nil, "NO HOST"         --# clear host info
  531.     for i = #pHosts, 1, -1 do                    --# process and sanitize host list
  532.       if gateHosts[i] == "lockdown" or gateHosts[i] == "NO HOST" then --# if gate is in lockdown or hasn't replied...
  533.         table.remove(pHosts, i)                  --# ...remove the host from the list and...
  534.         table.remove(gateHosts, i)               --# ...remove the gate address from the gateHosts table
  535.       end
  536.     end
  537.   end
  538.   if #pHosts > 1 then                            --# more than 1 host responds
  539.     if runState == "init" then
  540.       drawElement(2, 4, termX, termY, nil, black, "") --# clear most of screen
  541.       drawHostsUI()
  542.       selectHost()
  543.     else
  544.       drawElement(4, 7, 20, 4, nil, black, "")   --# clear 'searching for hosts' dialogue
  545.       drawCLI()
  546.     end
  547.   elseif #pHosts == 1 then                       --# only one host responds
  548.     pSyncHost = pHosts[1]                        --# set pSyncHost
  549.     thisGate = gateHosts[1]                      --# set gate address
  550.     if runState == "init" then
  551.        drawElement(5, 12, 1, 1, green, gray, "O")
  552.     else
  553.       runState = runState == "syncHosts" and "pSync" or "Dial"
  554.       drawElement(4, 7, 20, 4, nil, black, "")   --# clear pSync pop-up
  555.       drawCLI()
  556.     end
  557.   else                                           --# no hosts respond
  558.     if runState == "init" then
  559.       drawElement(5, 12, 1, 1, red, gray, "0")
  560.     else
  561.       runState = "Dial"
  562.       drawElement(4, 7, 20, 4, nil, black, "")   --# clear pSync pop-up
  563.       drawCLI()
  564.     end
  565.   end
  566. end
  567.  
  568. local function readInput(cX, cY, cO, bG, _limit, gField, mask) --# cursor X, Y, text color, bg color, character limit, limit characters to valid address characters, character mask
  569.   local symbols = { ["A"] = true, ["B"] = true, ["C"] = true, ["D"] = true, ["E"] = true , ["F"] = true, ["G"] = true, ["H"] = true, ["I"] = true, ["J"] = true, ["K"] = true, ["L"] = true, ["M"] = true, ["N"] = true, ["O"] = true, ["P"] = true, ["Q"] = true, ["R"] = true, ["S"] = true, ["T"] = true, ["U"] = true, ["V"] = true, ["W"] = true, ["X"] = true, ["Y"] = true, ["Z"] = true, ["0"] = true, ["1"] = true, ["2"] = true, ["3"] = true, ["4"] = true, ["5"] = true, ["6"] = true, ["7"] = true, ["8"] = true, ["9"] = true, ["-"] = true, ["+"] = true }
  570.   local word = ""
  571.   local wordA = nil
  572.   local curX, curY = cX, math.floor(cY)
  573.   local bCurX, bCurY = cX, math.floor(cY)
  574.   local pos = 0
  575.   _limit = (_limit and type(_limit) == "number" and _limit > 0) and _limit or 43
  576.   if type(mask) ~= "string" then mask = nil end
  577.   if bG then term.setBackgroundColor(bG) end
  578.   term.setTextColor(cO)
  579.   term.setCursorBlink(true)
  580.   term.setCursorPos(curX, curY)
  581.   while true do
  582.     local event, data, mX, mY = os.pullEvent()
  583.     if event == "key" then
  584.       if data == keys.backspace then
  585.         curX = curX - 1
  586.         pos = math.max(0, pos - 1)
  587.         if curX < bCurX and curY == bCurY then curX = bCurX end
  588.         if curX < bCurX and curY > bCurY then
  589.           curY = curY - 1
  590.           curX = termX
  591.           word = wordA
  592.           wordA = nil
  593.         end
  594.         word = (#word > 0) and word:sub(1, #word - 1) or ""
  595.         drawElement(curX, curY, 1, 1, nil, bG, " ")
  596.       elseif data == keys.enter or data == keys.numPadEnter then
  597.         break
  598.       end
  599.     elseif event == "char" and pos < _limit then
  600.       local goodData = false
  601.       if gField then
  602.         if symbols[data:upper()] then
  603.           goodData = true
  604.         end
  605.       else
  606.         goodData = true
  607.       end
  608.       if goodData then
  609.         if mask then
  610.           drawElement(curX, curY, 1, 1, cO, bG, mask)
  611.         else
  612.           drawElement(curX, curY, 1, 1, cO, bG, data)
  613.         end
  614.         word = word .. data
  615.         curX = curX + 1
  616.         pos = pos + 1
  617.       end
  618.       if curX > termX then
  619.         curY = curY + 1
  620.         curX = bCurX
  621.         wordA = word
  622.         word = ""
  623.       end
  624.     elseif event == "paste" and pos < _limit then
  625.       if pos + #data > _limit then
  626.         data = data:sub(1, _limit - pos)
  627.       end
  628.       if gField then
  629.         local newWord, glyph = { }, ""
  630.         for i = 1, #data do
  631.           glyph = string.upper(data:sub(i, i))
  632.           if symbols[glyph] then
  633.             newWord[i] = glyph
  634.           else
  635.             newWord[i] = "?"
  636.           end
  637.         end
  638.         data = table.concat(newWord)
  639.       end
  640.       if mask then
  641.         local maskTable = { }
  642.         for i = 1, #data do
  643.           maskTable[i] = mask
  644.         end
  645.         drawElement(curX, curY, 1, 1, cO, bG, table.concat(maskTable))
  646.       else
  647.         drawElement(curX, curY, 1, 1, cO, bG, data:sub(1, 24))
  648.         if #data > 24 then
  649.           drawElement(curX, curY + 1, 1, 1, cO, bG, data:sub(25, 43))
  650.         end
  651.       end
  652.       word = word .. data
  653.       curX = curX + #data
  654.       pos = pos + #data
  655.       if curX > termX then
  656.         curY = curY + 1
  657.         curX = bCurX
  658.         wordA = word:sub(1, 24)
  659.         word = word:sub(25, 43) .. ""
  660.       end
  661.     elseif event == "mouse_click" then
  662.       if mY ~= curY or mX < bCurX or mX >= bCurX + _limit then
  663.         break
  664.       end
  665.     elseif event == "mouse_scroll" and runState == "viewing" then
  666.       break
  667.     end
  668.     term.setCursorPos(curX, curY)
  669.   end
  670.   term.setCursorBlink(false)
  671.   if wordA then
  672.     word = wordA .. word
  673.     wordA = nil
  674.   end
  675.   return word
  676. end
  677.  
  678. local function requestIrisOpen()
  679.   if not rednet.isOpen(netSide) then
  680.     rednet.open(netSide)
  681.   end
  682.   drawElement(2, 4, termX, termY, nil, black, "")
  683.   drawIrisPasswordUI()
  684.   local irisPass = readInput(8, 7, white, gray, 12, nil, "*")
  685.   local data = { program = "pSync", password = irisPass }
  686.   rednet.send(pSyncHost, data)
  687.   runState = "Dial"
  688.   drawElement(2, 5, termX - 2, 5, nil, black, "")
  689.   drawCLI()
  690. end
  691.  
  692. local function goToPage()
  693.   runState = "goPage"                                                    --# temporarily set runState
  694.   drawElement((termX / 2) - 3, termY - 3, 8, 1, white, gray, " :Page: ") --# header
  695.   drawElement((termX / 2) - 3, termY - 2, 8, 2, nil, nil, "")            --# body
  696.   drawElement((termX / 2) - 2, termY - 2, 6, 1, nil, black, "")          --# input area bg
  697.   local newPage = tonumber(readInput((termX / 2 - 1), termY - 2, lime, nil, 4))  --# user input
  698.   drawElement((termX / 2) - 3, termY - 3, 8, 3, nil, nil, "")            --# clear 'Page' dialogue
  699.   gatePage = newPage or gatePage                                         --# set gate page
  700.   gatePage = math.max(1, gatePage)
  701.   gatePage = math.min(gatePage, gatePages)
  702.   if gatePage == gatePages and gatePages > 1 then                        --# if on the last page and there's more than one page...
  703.     drawElement(2, 4, termX, termY, nil, nil, "")                        --# ...clear the data area
  704.   end
  705.   runState = "Dial"                                                      --# restore runState
  706.   drawAddressList()
  707.   drawNaviUI()
  708. end
  709.  
  710. local function saveAndQuit()
  711.   drawElement((termX / 2) - 9, math.floor(termY / 2) - 2, 20, 1, white, blue, "Save Addr Book ?")
  712.   drawElement((termX / 2) - 9, math.floor(termY / 2) - 1, 20, 3, nil, gray, "")
  713.   drawElement((termX / 2) - 8, math.floor(termY / 2), 8, 1, nil, green, "Save")
  714.   drawElement((termX / 2) + 2, math.floor(termY / 2), 8, 1, nil, orange, "Quit")
  715.   while true do
  716.     local _, button, mX, mY = os.pullEvent("mouse_click")
  717.     if mX > (termX / 2) - 10 and mX < (termX / 2) + 9 and mY > math.floor(termY / 2) - 3 and mY < math.floor(termY / 2) + 2 and button == 1 then
  718.       if mX > (termX / 2) - 9 and mX < (termX / 2) - 1 and mY == math.floor(termY / 2) then
  719.         flashChoice((termX / 2) - 8, math.floor(termY / 2), green, white, "  Save  ")
  720.         saveData(gateData, "gate")
  721.         return true
  722.       elseif mX > (termX / 2) + 1 and mX < (termX / 2) + 9 and mY == math.floor(termY / 2) then
  723.         flashChoice((termX / 2) + 2, math.floor(termY / 2), orange, white, "  Quit  ")
  724.         return true
  725.       end
  726.     else
  727.       runState = "Dial"
  728.       drawElement(2, 5, termX - 2, termY - 7, nil, black, "") --# clear data area of screen
  729.       drawAddressList()
  730.       return false
  731.     end
  732.   end
  733. end
  734.  
  735. local function inputKey()
  736.   while true do
  737.     local _, thisKey = os.pullEvent("key")
  738.     if thisKey == keys.f1 and (runState == "Dial" or runState == "Help") then --# F1
  739.       runState = runState == "Dial" and "Help" or "Dial"
  740.       clearScreen(runState == "Dial" and black or white)
  741.       drawCLI()
  742.     end
  743.     if runState == "Dial" then
  744.       if thisKey == keys.home then
  745.         gatePage = 1
  746.         drawAddressList()
  747.         drawNaviUI()
  748.       elseif thisKey == keys.pageUp then
  749.         gatePage = math.max(1, gatePage - 1)
  750.         drawAddressList()
  751.         drawNaviUI()
  752.       elseif thisKey == keys.pageDown then
  753.         gatePage = math.min(gatePage + 1, gatePages)
  754.         if gatePage == gatePages and gatePages > 1 then
  755.           drawElement(2, 4, termX-2, termY-4, nil, black, "")
  756.         end
  757.         drawAddressList()
  758.         drawNaviUI()
  759.       elseif thisKey == keys["end"] then
  760.         gatePage = gatePages
  761.         if gatePages > 1 then
  762.           drawElement(2, 4, termX-2, termY-4, nil, black, "")
  763.         end
  764.         drawAddressList()
  765.         drawNaviUI()
  766.       end
  767.     end
  768.   end
  769. end
  770.  
  771. local function inputMouse()
  772.   while true do
  773.     local _, mButton, mcX, mcY = os.pullEvent("mouse_click")
  774.     if mcY == 1 and mButton == 1 then
  775.       if mcX > termX - 3 and mcX <= termX then            --# 'X' (exit button)
  776.         flashChoice(termX - 1, 1, white, blue, "X")
  777.         drawElement(termX - 1, 1, 1, 1, red, nil, "X")
  778.         if runState == "Dial" then
  779.           if gateChange then
  780.             if saveAndQuit() then return end
  781.           else
  782.             break
  783.           end
  784.         else
  785.           runState = "Dial"
  786.           clearScreen()
  787.           drawCLI()
  788.         end
  789.       elseif mcX < 4 and runState == "Dial" then          --# 'H' (hosts button)
  790.         drawElement(2, 1, 1, 1, gray, blue, "H")
  791.         drawElement(1, 3, termX, termY, nil, black, "")   --# clear most of screen
  792.         drawElement(4, 7, 20, 1, white, blue, "pSync")    --# pSync search header
  793.         drawElement(4, 8, 20, 3, nil, gray, "Locating host...") --# pSync search body
  794.         runState = "gateHosts"
  795.         findHosts()
  796.       elseif mcX > 4 and mcX < 8 and runState == "Dial" and thisGate ~= "NO HOST" then
  797.         runState = "Iris"
  798.         requestIrisOpen()
  799.       end
  800.     end
  801.     if runState == "viewing" then                         --# Gate Viewing / Editing
  802.       if mcY == 4 and mButton == 1 then
  803.         if mcX > 1 and mcX < 11 then                      --# Name
  804.           drawElement(2, 4, 1, 1, gray, black, addressBook[currentEdit].name)
  805.           local newGateName = readInput(2, 4, yellow, nil, 9)
  806.           if newGateName and newGateName ~= addressBook[currentEdit].name and newGateName ~= "" then
  807.             addressBook[currentEdit].name = newGateName
  808.             gateDataChange()
  809.           end
  810.           drawElement(2, 4, 1, 1, yellow, black, addressBook[currentEdit].name .. string.rep(" ", 9 - #addressBook[currentEdit].name))
  811.         elseif mcX > 20 and mcX < 21 + #tostring(currentEdit) then --# Position / reorder
  812.           drawElement(21, 4, 1, 1, gray, black, currentEdit)
  813.           local oldPos = currentEdit
  814.           local newPos = tonumber(readInput(21, 4, white, nil, 5))
  815.           if newPos and newPos > 0 and newPos <= #addressBook and newPos ~= oldPos then
  816.             local tempGateData = { }
  817.             for k, v in pairs(addressBook[currentEdit]) do
  818.               tempGateData[k] = v
  819.             end
  820.             table.remove(addressBook, currentEdit)
  821.             table.insert(addressBook, newPos, tempGateData)
  822.             currentEdit = newPos
  823.             gateDataChange()
  824.           end
  825.           drawElement(21, 4, 1, 1, white, black, currentEdit .. string.rep(" ", 5 - #tostring(currentEdit)))
  826.         end
  827.       elseif mcY == 6 and mButton == 1 then
  828.         if mcX > 1 and mcX < 11 then                      --# Address
  829.           drawElement(2, 6, 1, 1, gray, black, addressBook[currentEdit].addr)
  830.           local newGateAddress = string.upper(readInput(2, 6, yellow, nil, 9))
  831.           if newGateAddress and (#newGateAddress == 7 or #newGateAddress == 9) and newGateAddress ~= addressBook[currentEdit].addr then
  832.             addressBook[currentEdit].addr = newGateAddress
  833.             if addressBook[currentEdit].name == "Name" then
  834.               addressBook[currentEdit].name = newGateAddress
  835.               drawElement(2, 4, #addressBook[currentEdit].name, 1, yellow, nil, addressBook[currentEdit].name .. string.rep(" ", 9 - #addressBook[currentEdit].name))
  836.             end
  837.             gateDataChange()
  838.           end
  839.           drawElement(2, 6, #addressBook[currentEdit].addr, 1, assignColor(currentEdit), nil, addressBook[currentEdit].addr .. "  ")
  840.         end
  841.       elseif mcY == 8 and mButton == 1 then               --# Classification
  842.         if mcX > 1 and mcX < 4 + #assignRating(currentEdit) then
  843.           drawRatingList(addressBook[currentEdit].rating)
  844.           local selected = false
  845.           local gRatings = { "B", "H", "V", "M", "S", "C", "D", "U", }
  846.           while true do
  847.             local _, button, mX, mY = os.pullEvent("mouse_click")
  848.             if mX > 5 and mX < 25 and mY > 5 and mY < 14 then
  849.               for i = 1, #gRatings do
  850.                 if mY == i + 5 then
  851.                   if addressBook[currentEdit].rating ~= gRatings[i] then
  852.                     addressBook[currentEdit].rating = gRatings[i]
  853.                     gateDataChange()
  854.                   end
  855.                   selected = true
  856.                   break
  857.                 end
  858.               end
  859.               if selected then break end
  860.             else
  861.               break
  862.             end
  863.           end
  864.           drawGateLabels()
  865.         end
  866.       elseif mcY == 10 and mButton == 1 then              --# Note
  867.         if mcX > 1 and mcX < 2 + #addressBook[currentEdit].note:sub(1, 24) then
  868.           if #addressBook[currentEdit].note > 24 then
  869.             drawElement(2, 10, 1, 1, gray, black, addressBook[currentEdit].note:sub(1, 24))
  870.             drawElement(2, 11, 1, 1, nil, nil, addressBook[currentEdit].note:sub(25, 43))
  871.           else
  872.             drawElement(2, 10, 1, 1, gray, black, addressBook[currentEdit].note)
  873.           end
  874.           local getNewNote = readInput(2, 10, white, nil, 43)
  875.           if getNewNote and getNewNote ~= "" then
  876.             addressBook[currentEdit].note = getNewNote
  877.             gateDataChange()
  878.           end
  879.           if #addressBook[currentEdit].note > 24 then
  880.             drawElement(2, 10, 1, 1, white, nil, addressBook[currentEdit].note:sub(1, 24))
  881.             drawElement(2, 11, 1, 1, nil, nil, addressBook[currentEdit].note:sub(25, 43) .. string.rep(" ", 19 - #addressBook[currentEdit].note:sub(25, 43)))
  882.           else
  883.             drawElement(2, 10, 1, 1, white, nil, addressBook[currentEdit].note .. string.rep(" ", 24 - #addressBook[currentEdit].note))
  884.           end
  885.         end
  886.       elseif mcY == 13 and mButton == 1 then              --# Dimension
  887.         if mcX > 6 and mcX < 7 + #addressBook[currentEdit].loc.dim then
  888.           drawElement(7, 13, 1, 1, gray, black, addressBook[currentEdit].loc.dim)
  889.           local getNewDim = readInput(7, 13, yellow, nil, 19)
  890.           if getNewDim and getNewDim ~= "" then
  891.             addressBook[currentEdit].loc.dim = getNewDim
  892.             gateDataChange()
  893.           end
  894.           drawElement(7, 13, 1, 1, yellow, black, addressBook[currentEdit].loc.dim .. string.rep(" ", 19 - #addressBook[currentEdit].loc.dim))
  895.         end
  896.       elseif mcY == 14 and mButton == 1 then              --# X
  897.         if mcX > 4 and mcX < 5 + #tostring(addressBook[currentEdit].loc.x) then
  898.           drawElement(5, 14, 1, 1, gray, black, addressBook[currentEdit].loc.x)
  899.           local getNewX = tonumber(readInput(5, 14, silver, nil, 9))
  900.           if getNewX then
  901.             addressBook[currentEdit].loc.x = getNewX
  902.             gateDataChange()
  903.           end
  904.           drawElement(5, 14, 1, 1, silver, black, addressBook[currentEdit].loc.x .. string.rep(" ", 9 - #tostring(addressBook[currentEdit].loc.x)))
  905.         end
  906.       elseif mcY == 15 and mButton == 1 then              --# Y
  907.         if mcX > 4 and mcX < 5 + #tostring(addressBook[currentEdit].loc.y) then
  908.           drawElement(5, 15, 1, 1, gray, black, addressBook[currentEdit].loc.y)
  909.           local getNewY = tonumber(readInput(5, 15, silver, nil, 9))
  910.           if getNewY then
  911.             addressBook[currentEdit].loc.y = getNewY
  912.             gateDataChange()
  913.           end
  914.           drawElement(5, 15, 1, 1, silver, black, addressBook[currentEdit].loc.y .. string.rep(" ", 9 - #tostring(addressBook[currentEdit].loc.y)))
  915.         end
  916.       elseif mcY == 16 and mButton == 1 then              --# Z
  917.         if mcX > 4 and mcX < 5 + #tostring(addressBook[currentEdit].loc.z) then
  918.           drawElement(5, 16, 1, 1, gray, black, addressBook[currentEdit].loc.z)
  919.           local getNewZ = tonumber(readInput(5, 16, silver, nil, 9))
  920.           if getNewZ then
  921.             addressBook[currentEdit].loc.z = getNewZ
  922.             gateDataChange()
  923.           end
  924.           drawElement(5, 16, 1, 1, silver, black, addressBook[currentEdit].loc.z .. string.rep(" ", 9 - #tostring(addressBook[currentEdit].loc.z)))
  925.         end
  926.       elseif mcY == termY - 1 and mButton == 1 then       --# Save / Close
  927.         if mcX > 5 and mcX < 13 and gateChange then
  928.           flashChoice(6, termY - 1, white, green, " Save ")
  929.           drawElement(6, termY - 1, 6, 1, silver, gray, "Save")
  930.           saveData()
  931.         elseif mcX > 14 and mcX < 22 then
  932.           flashChoice(15, termY - 1, white, red, " Close ")
  933.           runState = "Dial"
  934.           drawElement(2, 4, termX, termY, nil, black, "")
  935.           drawCLI()
  936.         end
  937.       end
  938.     elseif runState == "Dial" then                        --# Dial
  939.       if mcY == 3 then
  940.         if mcX < 12 and mButton == 1 then                 --# pSync
  941.           flashChoice(1, 3, cyan, white, "   pSync   ")
  942.           drawElement(1, 3, 11, 1, white, cyan, "pSync")
  943.           drawElement(1, 3, termX, termY, nil, black, "")
  944.           drawElement(4, 7, 20, 1, nil, blue, "pSync")
  945.           drawElement(4, 8, 20, 3, nil, gray, "Locating host...")
  946.           runState = "syncHosts"
  947.           findHosts()
  948.         elseif mcX > 11 and mcX < 15 then                 --# Add Gate / Save Address Book
  949.           if mButton == 1 then                            --# Add gate
  950.             flashChoice(12, 3, green, white, " + ")
  951.             drawElement(12, 3, 1, 1, orange, green, " + ")
  952.             runState = "viewing"
  953.             addNewAddress()
  954.           elseif mButton == 2 and gateChange then         --# Save Address Book
  955.             flashChoice(12, 3, green, white, " + ")
  956.             drawElement(12, 3, 1, 1, white, green, " + ")
  957.             saveData()
  958.           elseif mButton == 3 then                        --# Quick-Add gate
  959.             flashChoice(12, 3, green, white, " + ")
  960.             drawElement(12, 3, 1, 1, orange, green, " + ")
  961.             addNewAddress(true)
  962.           end
  963.         elseif mcX > 14 and mButton == 1 then             --# End Call
  964.           flashChoice(15, 3, red, white, "  END Call  ")
  965.           drawElement(15, 3, 12, 1, white, red, "END Call")
  966.           netSend("endCall")
  967.         end
  968.        --# Dial a listed address, view it's info, or delete it
  969.       elseif mcY > 4 and mcY < 18 then
  970.         local magicNumber = ((gatePage - 1) * 13) + gatePage
  971.         local xPos, yPos = 3, 5
  972.         for i = magicNumber, #addressBook do
  973.           if mcX >= xPos and mcX <= xPos + 8 and mcY == yPos then
  974.             if mButton == 1 then
  975.               if addressBook[i].addr == thisGate or addressBook[i].addr == thisGate:sub(1, 7) then
  976.                 --# do nothing
  977.               else
  978.                 flashDial(addressBook[i].name, xPos, mcY, i)
  979.                 netSend(addressBook[i].addr)
  980.               end
  981.             elseif mButton == 2 then
  982.               flashDial(addressBook[i].name, xPos, mcY, i)
  983.               runState = "viewing"
  984.               currentEdit = i
  985.               drawGateLabels()
  986.             elseif mButton == 3 then
  987.               flashDial(addressBook[i].name, xPos, mcY, i)
  988.               deleteGate(i)
  989.             end
  990.             break
  991.           else
  992.             yPos = yPos + 2
  993.             if yPos >= termY - 2 then xPos = xPos + 13 yPos = 5 end
  994.             if xPos > 16 then break end
  995.           end
  996.         end
  997.        --# Page Navigation via click
  998.       elseif mcY == termY and mButton == 1 then
  999.         if mcX > 2 and mcX < 5 then                       --# Home
  1000.           gatePage = 1
  1001.           drawAddressList()
  1002.           drawNaviUI()
  1003.         elseif mcX > 5 and mcX < 7 then                   --# Page Back
  1004.           gatePage = math.max(1, gatePage - 1)
  1005.           drawAddressList()
  1006.           drawNaviUI()
  1007.         elseif mcX > (math.floor(termX / 2) - (math.floor(#pNum / 2))) and mcX < (math.floor(termX / 2) + (math.floor(#pNum / 2))) + 1 then --# Page Numbers (Go To Page dialogue)
  1008.           flashChoice((math.floor(termX / 2) - (math.floor(#pNum / 2))) + 1, termY, black, gray, pNum)
  1009.           drawElement((math.floor(termX / 2) - (math.floor(#pNum / 2))) + 1, termY, 1, 1, gray, black, pNum)
  1010.           goToPage()
  1011.         elseif mcX > 20 and mcX < 22 then                 --# Page Forward
  1012.           gatePage = math.min(gatePage + 1, gatePages)
  1013.           if gatePage == gatePages and gatePages > 1 then
  1014.             drawElement(2, 4, termX, termY, nil, black, "")
  1015.           end
  1016.           drawAddressList()
  1017.           drawNaviUI()
  1018.         elseif mcX > 22 and mcX < 25 then                 --# End
  1019.           gatePage = gatePages
  1020.           if gatePages > 1 then
  1021.             drawElement(2, 4, termX, termY, nil, black, "")
  1022.           end
  1023.           drawAddressList()
  1024.           drawNaviUI()
  1025.         end
  1026.       end
  1027.     elseif runState == "pSync" then                       --# pSync
  1028.       if mcX > 2 and mcX < termX - 2 and mButton == 1 then
  1029.         local followUp = false
  1030.         if mcY > 4 and mcY < 8 then                       --# Import
  1031.           drawElement(2, 5, termX - 2, 3, green, white, "GET Address Book")
  1032.           sleep(0.1)
  1033.           drawElement(2, 5, termX - 2, 3, white, green, "GET Address Book")
  1034.           pSync("pPull")
  1035.           saveData()
  1036.           followUp = true
  1037.         elseif mcY > 8 and mcY < 12 then                  --# Export
  1038.           drawElement(2, 9, termX - 2, 3, orange, white, "SEND Address Book")
  1039.           sleep(0.1)
  1040.           drawElement(2, 9, termX - 2, 3, white, orange, "SEND Address Book")
  1041.           pSync("pPush")
  1042.           followUp = true
  1043.         elseif mcY > 12 and mcY < 16 then                 --# Cancel
  1044.           drawElement(2, 13, termX - 2, 3, red, white, "C A N C E L")
  1045.           sleep(0.1)
  1046.           drawElement(2, 13, termX - 2, 3, white, red, "C A N C E L")
  1047.           followUp = true
  1048.         end
  1049.         if followUp then
  1050.           runState = "Dial"
  1051.           drawElement(2, 4, termX, termY, nil, black, "")
  1052.           drawCLI()
  1053.         end
  1054.       end
  1055.     elseif runState == "gateHosts" or runState == "syncHosts" then --# Hosts list
  1056.       local hostNames = { }
  1057.       for i = 1, #gateHosts do
  1058.         hostNames[i] = gateHosts[i]
  1059.         for j = 1, #addressBook do
  1060.           if addressBook[j].addr == gateHosts[i] then
  1061.             hostNames[i] = addressBook[j].name
  1062.             break
  1063.           end
  1064.         end
  1065.       end
  1066.       if mcX > 8 and mcX < 19 and mcY > 6 and mcY < 14 and mButton == 1 then
  1067.         local gSelect = false
  1068.         local gCounter = 0
  1069.         for i = 7, 15, 2 do
  1070.           gCounter = gCounter + 1
  1071.           if gCounter <= #pHosts then
  1072.             if mcY == i then
  1073.               drawElement(9, i, 11, 1, black, white, hostNames[gCounter])
  1074.               sleep(0.1)
  1075.               drawElement(9, i, 11, 1, gray, silver, hostNames[gCounter])
  1076.               pSyncHost = pHosts[gCounter]
  1077.               thisGate = gateHosts[gCounter]
  1078.               gSelect = true
  1079.               runState = runState == "gateHosts" and "Dial" or "pSync"
  1080.               break
  1081.             end
  1082.           else
  1083.             break
  1084.           end
  1085.         end
  1086.         if gSelect then
  1087.           drawElement(8, 5, 13, 12, nil, black, "")       --# Clear hosts UI
  1088.           drawCLI()
  1089.         end
  1090.       end
  1091.     end
  1092.   end
  1093. end
  1094.  
  1095. local function inputScroll()
  1096.   while true do
  1097.     local _, data = os.pullEvent("mouse_scroll")
  1098.     if runState == "Dial" then
  1099.       gatePage = data == 1 and math.min(gatePage + 1, gatePages) or math.max(1, gatePage - 1)
  1100.       if gatePage == gatePages and gatePages > 1 then
  1101.         drawElement(2, 4, termX, termY, nil, black, "") --# clear address book area
  1102.       end
  1103.       drawAddressList()
  1104.       drawNaviUI()
  1105.     elseif runState == "viewing" then
  1106.       currentEdit = data == 1 and math.min(currentEdit + 1, #addressBook) or math.max(1, currentEdit - 1)
  1107.       term.setCursorBlink(false)
  1108.       drawElement(2, 4, termX, termY, nil, black, "")
  1109.       drawGateLabels()
  1110.     end
  1111.   end
  1112. end
  1113.  
  1114. local function missingComponent(which)
  1115.   clearScreen()
  1116.   if which == "colorPDA" then
  1117.     drawElement(2, 2, 1, 1, white, black, "No advanced pocket")
  1118.     drawElement(2, 3, 1, 1, nil, nil, "computer detected!")
  1119.     drawElement(2, 5, 1, 1, nil, nil, "ccDialer REQUIRES an")
  1120.     drawElement(2, 6, 1, 1, nil, nil, "advanced pocket computer.")
  1121.   elseif which == "modem" then
  1122.     drawElement(2, 2, 1, 1, red, black, "No wireless")
  1123.     drawElement(2, 3, 1, 1, nil, nil, "modem detected!")
  1124.     drawElement(2, 5, 1, 1, nil, nil, "ccDialer REQUIRES")
  1125.     drawElement(2, 6, 1, 1, nil, nil, "a wireless modem.")
  1126.   end
  1127.   term.setCursorPos(1, 9)
  1128.   return false
  1129. end
  1130.  
  1131. local function initMe()
  1132.   if not term.isColor() or not pocket then return missingComponent("colorPDA") end
  1133.   clearScreen()
  1134.   drawElement(4, 4, 21, 1, white, blue, "ccDialer Init...")
  1135.   drawElement(4, 5, 21, 9, nil, gray, "")
  1136.   drawElement(7, 6, 1, 1, nil, nil, "Check CC label")
  1137.   drawElement(7, 8, 1, 1, silver, nil, "Harware Discovery")
  1138.   drawElement(7, 10, 1, 1, nil, nil, "Ingest gate data")
  1139.   drawElement(7, 12, 1, 1, nil, nil, "Locate pSync host")
  1140.   drawElement(5, 6, 1, 1, orange, nil, "0")
  1141.   drawElement(5, 8, 1, 1, red, nil, "0")
  1142.   drawElement(5, 10, 1, 1, nil, nil, "0")
  1143.   drawElement(5, 12, 1, 1, nil, nil, "0")
  1144.   local ccLabel = os.getComputerLabel()
  1145.   if ccLabel == nil or tostring(ccLabel) == "" then
  1146.     os.setComputerLabel("ccDialer")
  1147.   end
  1148.   drawElement(5, 6, 1, 1, green, nil, "O")
  1149.   drawElement(5, 8, 1, 1, orange, nil, "0")
  1150.   drawElement(7, 8, 1, 1, white, nil, "Harware Discovery")
  1151.   for _, side in ipairs(rs.getSides()) do
  1152.     if peripheral.isPresent(side) then
  1153.       local perp = peripheral.getType(side)
  1154.       if perp == "modem" and peripheral.call(side, "isWireless") then
  1155.         rednet.open(side)
  1156.         netSide = side
  1157.         break
  1158.       end
  1159.     end
  1160.   end
  1161.   if netSide == "none" then return missingComponent("modem") end
  1162.   drawElement(5, 8, 1, 1, green, nil, "O")
  1163.   drawElement(5, 10, 1, 1, orange, nil, "0")
  1164.   drawElement(7, 10, 1, 1, white, nil, "Ingest gate data")
  1165.   if not fs.exists("/data") then fs.makeDir("/data") end
  1166.   ingestData()
  1167.   drawElement(5, 10, 1, 1, green, nil, "O")
  1168.   drawElement(5, 12, 1, 1, orange, nil, "0")
  1169.   drawElement(7, 12, 1, 1, white, nil, "Locate pSync host")
  1170.   findHosts()
  1171.   runState = "Dial"
  1172.   clearScreen()
  1173.   drawCLI()
  1174.   return true
  1175. end
  1176.  
  1177. if not initMe() then return end
  1178.  
  1179. parallel.waitForAny(inputMouse, inputScroll, inputKey)
  1180.  
  1181. shutDown()
  1182. term.setBackgroundColor(black)
  1183. term.setTextColor(white)
  1184. term.clear()
  1185. term.setCursorPos(1, 1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement