Advertisement
lego11

Untitled

Jan 26th, 2019
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.12 KB | None | 0 0
  1.  
  2. -- Setup process switching
  3. local parentTerm = term.current()
  4. local w,h = parentTerm.getSize()
  5.  
  6. local tProcesses = {}
  7. local nCurrentProcess = nil
  8. local nRunningProcess = nil
  9. local bShowMenu = false
  10. local bWindowsResized = false
  11.  
  12. local function selectProcess( n )
  13. if nCurrentProcess ~= n then
  14. if nCurrentProcess then
  15. local tOldProcess = tProcesses[ nCurrentProcess ]
  16. tOldProcess.window.setVisible( false )
  17. end
  18. nCurrentProcess = n
  19. if nCurrentProcess then
  20. local tNewProcess = tProcesses[ nCurrentProcess ]
  21. tNewProcess.window.setVisible( true )
  22. tNewProcess.bInteracted = true
  23. end
  24. end
  25. end
  26.  
  27. local function setProcessTitle( n, sTitle )
  28. tProcesses[ n ].sTitle = sTitle
  29. end
  30.  
  31. local function resumeProcess( nProcess, sEvent, ... )
  32. local tProcess = tProcesses[ nProcess ]
  33. local sFilter = tProcess.sFilter
  34. if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then
  35. local nPreviousProcess = nRunningProcess
  36. nRunningProcess = nProcess
  37. term.redirect( tProcess.terminal )
  38. local ok, result = coroutine.resume( tProcess.co, sEvent, ... )
  39. tProcess.terminal = term.current()
  40. if ok then
  41. tProcess.sFilter = result
  42. else
  43. printError( result )
  44. end
  45. nRunningProcess = nPreviousProcess
  46. end
  47. end
  48.  
  49. local function launchProcess( tProgramEnv, sProgramPath, ... )
  50. local tProgramArgs = { ... }
  51. local nProcess = #tProcesses + 1
  52. local tProcess = {}
  53. tProcess.sTitle = fs.getName( sProgramPath )
  54. if bShowMenu then
  55. tProcess.window = window.create( parentTerm, 1, 2, w, h-1, false )
  56. else
  57. tProcess.window = window.create( parentTerm, 1, 1, w, h, false )
  58. end
  59. tProcess.co = coroutine.create( function()
  60. os.run( tProgramEnv, sProgramPath, unpack( tProgramArgs ) )
  61. if not tProcess.bInteracted then
  62. term.setCursorBlink( false )
  63. print( "Press any key to continue" )
  64. os.pullEvent( "char" )
  65. end
  66. end )
  67. tProcess.sFilter = nil
  68. tProcess.terminal = tProcess.window
  69. tProcess.bInteracted = false
  70. tProcesses[ nProcess ] = tProcess
  71. resumeProcess( nProcess )
  72. return nProcess
  73. end
  74.  
  75. local function cullProcess( nProcess )
  76. local tProcess = tProcesses[ nProcess ]
  77. if coroutine.status( tProcess.co ) == "dead" then
  78. if nCurrentProcess == nProcess then
  79. selectProcess( nil )
  80. end
  81. table.remove( tProcesses, nProcess )
  82. if nCurrentProcess == nil then
  83. if nProcess > 1 then
  84. selectProcess( nProcess - 1 )
  85. elseif #tProcesses > 0 then
  86. selectProcess( 1 )
  87. end
  88. end
  89. return true
  90. end
  91. return false
  92. end
  93.  
  94. local function cullProcesses()
  95. local culled = false
  96. for n=#tProcesses,1,-1 do
  97. culled = culled or cullProcess( n )
  98. end
  99. return culled
  100. end
  101.  
  102. -- Setup the main menu
  103. local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor
  104. if parentTerm.isColor() then
  105. menuMainTextColor, menuMainBgColor = colors.yellow, colors.black
  106. menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray
  107. else
  108. menuMainTextColor, menuMainBgColor = colors.white, colors.black
  109. menuOtherTextColor, menuOtherBgColor = colors.black, colors.white
  110. end
  111.  
  112. local function redrawMenu()
  113. if bShowMenu then
  114. -- Draw menu
  115. parentTerm.setCursorPos( 1, 1 )
  116. parentTerm.setBackgroundColor( menuOtherBgColor )
  117. parentTerm.clearLine()
  118. for n=1,#tProcesses do
  119. if n == nCurrentProcess then
  120. parentTerm.setTextColor( menuMainTextColor )
  121. parentTerm.setBackgroundColor( menuMainBgColor )
  122. else
  123. parentTerm.setTextColor( menuOtherTextColor )
  124. parentTerm.setBackgroundColor( menuOtherBgColor )
  125. end
  126. parentTerm.write( " " .. tProcesses[n].sTitle .. " " )
  127. end
  128.  
  129. -- Put the cursor back where it should be
  130. local tProcess = tProcesses[ nCurrentProcess ]
  131. if tProcess then
  132. tProcess.window.restoreCursor()
  133. end
  134. end
  135. end
  136.  
  137. local function resizeWindows()
  138. local windowY, windowHeight
  139. if bShowMenu then
  140. windowY = 2
  141. windowHeight = h-1
  142. else
  143. windowY = 1
  144. windowHeight = h
  145. end
  146. for n=1,#tProcesses do
  147. local tProcess = tProcesses[n]
  148. local window = tProcess.window
  149. local x,y = tProcess.window.getCursorPos()
  150. if y > windowHeight then
  151. tProcess.window.scroll( y - windowHeight )
  152. tProcess.window.setCursorPos( x, windowHeight )
  153. end
  154. tProcess.window.reposition( 1, windowY, w, windowHeight )
  155. end
  156. bWindowsResized = true
  157. end
  158.  
  159. local function setMenuVisible( bVis )
  160. if bShowMenu ~= bVis then
  161. bShowMenu = bVis
  162. resizeWindows()
  163. redrawMenu()
  164. end
  165. end
  166.  
  167. local multishell = {}
  168.  
  169. function multishell.getFocus()
  170. return nCurrentProcess
  171. end
  172.  
  173. function multishell.setFocus( n )
  174. if n >= 1 and n <= #tProcesses then
  175. selectProcess( n )
  176. redrawMenu()
  177. return true
  178. end
  179. return false
  180. end
  181.  
  182. function multishell.getTitle( n )
  183. if n >= 1 and n <= #tProcesses then
  184. return tProcesses[n].sTitle
  185. end
  186. return nil
  187. end
  188.  
  189. function multishell.setTitle( n, sTitle )
  190. if n >= 1 and n <= #tProcesses then
  191. setProcessTitle( n, sTitle )
  192. redrawMenu()
  193. end
  194. end
  195.  
  196. function multishell.getCurrent()
  197. return nRunningProcess
  198. end
  199.  
  200. function multishell.launch( tProgramEnv, sProgramPath, ... )
  201. local previousTerm = term.current()
  202. setMenuVisible( (#tProcesses + 1) >= 2 )
  203. local nResult = launchProcess( tProgramEnv, sProgramPath, ... )
  204. redrawMenu()
  205. term.redirect( previousTerm )
  206. return nResult
  207. end
  208.  
  209. function multishell.getCount()
  210. return #tProcesses
  211. end
  212.  
  213. -- Begin
  214. parentTerm.clear()
  215. setMenuVisible( false )
  216. selectProcess( launchProcess( {
  217. ["shell"] = shell,
  218. ["multishell"] = multishell,
  219. }, "/rom/programs/shell" ) )
  220. redrawMenu()
  221.  
  222. -- Run processes
  223. while #tProcesses > 0 do
  224. -- Get the event
  225. local tEventData = { os.pullEventRaw() }
  226. local sEvent = tEventData[1]
  227. if sEvent == "term_resize" then
  228. -- Resize event
  229. w,h = parentTerm.getSize()
  230. resizeWindows()
  231. redrawMenu()
  232.  
  233. elseif sEvent == "char" or sEvent == "key" or sEvent == "paste" or sEvent == "terminate" then
  234. -- Keyboard event
  235. -- Passthrough to current process
  236. resumeProcess( nCurrentProcess, unpack( tEventData ) )
  237. if cullProcess( nCurrentProcess ) then
  238. setMenuVisible( #tProcesses >= 2 )
  239. redrawMenu()
  240. end
  241.  
  242. elseif sEvent == "mouse_click" then
  243. -- Click event
  244. local button, x, y = tEventData[2], tEventData[3], tEventData[4]
  245. if bShowMenu and y == 1 then
  246. -- Switch process
  247. local tabStart = 1
  248. for n=1,#tProcesses do
  249. tabEnd = tabStart + string.len( tProcesses[n].sTitle ) + 1
  250. if x >= tabStart and x <= tabEnd then
  251. selectProcess( n )
  252. redrawMenu()
  253. break
  254. end
  255. tabStart = tabEnd + 1
  256. end
  257. else
  258. -- Passthrough to current process
  259. resumeProcess( nCurrentProcess, sEvent, button, x, (bShowMenu and y-1) or y )
  260. if cullProcess( nCurrentProcess ) then
  261. setMenuVisible( #tProcesses >= 2 )
  262. redrawMenu()
  263. end
  264. end
  265.  
  266. elseif sEvent == "mouse_drag" or sEvent == "mouse_scroll" then
  267. -- Other mouse event
  268. local p1, x, y = tEventData[2], tEventData[3], tEventData[4]
  269. if not (bShowMenu and y == 1) then
  270. -- Passthrough to current process
  271. resumeProcess( nCurrentProcess, sEvent, p1, x, (bShowMenu and y-1) or y )
  272. if cullProcess( nCurrentProcess ) then
  273. setMenuVisible( #tProcesses >= 2 )
  274. redrawMenu()
  275. end
  276. end
  277.  
  278. else
  279. -- Other event
  280. -- Passthrough to all processes
  281. local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event
  282. for n=1,nLimit do
  283. resumeProcess( n, unpack( tEventData ) )
  284. end
  285. if cullProcesses() then
  286. setMenuVisible( #tProcesses >= 2 )
  287. redrawMenu()
  288. end
  289. end
  290.  
  291. if bWindowsResized then
  292. -- Pass term_resize to all processes
  293. local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event
  294. for n=1,nLimit do
  295. resumeProcess( n, "term_resize" )
  296. end
  297. bWindowsResized = false
  298. if cullProcesses() then
  299. setMenuVisible( #tProcesses >= 2 )
  300. redrawMenu()
  301. end
  302. end
  303. end
  304.  
  305. -- Shutdown
  306. term.redirect( parentTerm )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement