2 -- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
3 -- Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
4 -- All rights reserved.
6 -- Redistribution and use in source and binary forms, with or without
7 -- modification, are permitted provided that the following conditions
9 -- 1. Redistributions of source code must retain the above copyright
10 -- notice, this list of conditions and the following disclaimer.
11 -- 2. Redistributions in binary form must reproduce the above copyright
12 -- notice, this list of conditions and the following disclaimer in the
13 -- documentation and/or other materials provided with the distribution.
15 -- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 -- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 -- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 -- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 -- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 -- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 -- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 -- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 -- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 -- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 local color = require("color")
31 local config = require("config")
32 local core = require("core")
33 local screen = require("screen")
43 local none_shifted = false
45 local menu_entry_name = function(drawing_menu, entry)
46 local name_handler = drawer.menu_name_handlers[entry.entry_type]
48 if name_handler ~= nil then
49 return name_handler(drawing_menu, entry)
51 if type(entry.name) == "function" then
57 local shift_brand_text = function(shift)
58 drawer.brand_position.x = drawer.brand_position.x + shift.x
59 drawer.brand_position.y = drawer.brand_position.y + shift.y
60 drawer.menu_position.x = drawer.menu_position.x + shift.x
61 drawer.menu_position.y = drawer.menu_position.y + shift.y
62 drawer.box_pos_dim.x = drawer.box_pos_dim.x + shift.x
63 drawer.box_pos_dim.y = drawer.box_pos_dim.y + shift.y
67 " ______ ____ _____ _____ ",
68 " | ____| | _ \\ / ____| __ \\ ",
69 " | |___ _ __ ___ ___ | |_) | (___ | | | |",
70 " | ___| '__/ _ \\/ _ \\| _ < \\___ \\| | | |",
71 " | | | | | __/ __/| |_) |____) | |__| |",
72 " | | | | | | || | | |",
73 " |_| |_| \\___|\\___||____/|_____/|_____/ "
80 " /- \027[37m_\027[31m `-/ '",
81 " (\027[37m/\\/ \\\027[31m \\ /\\",
82 " \027[37m/ / |\027[31m ` \\",
83 " \027[34mO O \027[37m) \027[31m/ |",
84 " \027[37m`-^--'\027[31m`< '",
88 " \027[33m<----.\027[31m __ / __ \\",
89 " \027[33m<----|====\027[31mO)))\027[33m==\027[31m) \\) /\027[33m====|",
90 " \027[33m<----'\027[31m `--' `.__,' \\",
93 " \027[36m______\027[31m( (_ / \\______/",
94 " \027[36m,' ,-----' |",
95 " `--{__________)\027[37m"
110 " <----. __ / __ \\",
111 " <----|====O)))==) \\) /====|",
112 " <----' `--' `.__,' \\",
115 " ______( (_ / \\______/",
122 " | ____| __ ___ ___ ",
123 " | |__ | '__/ _ \\/ _ \\",
124 " | __|| | | __/ __/",
126 " |_| |_| \\___|\\___|",
128 " | _ \\ / ____| __ \\",
129 " | |_) | (___ | | | |",
130 " | _ < \\___ \\| | | |",
131 " | |_) |____) | |__| |",
133 " |____/|_____/|_____/"
137 " \027[31m``` \027[31;1m`\027[31m",
138 " s` `.....---...\027[31;1m....--.``` -/\027[31m",
139 " +o .--` \027[31;1m/y:` +.\027[31m",
140 " yo`:. \027[31;1m:o `+-\027[31m",
141 " y/ \027[31;1m-/` -o/\027[31m",
142 " .- \027[31;1m::/sy+:.\027[31m",
143 " / \027[31;1m`-- /\027[31m",
144 " `: \027[31;1m:`\027[31m",
145 " `: \027[31;1m:`\027[31m",
146 " / \027[31;1m/\027[31m",
147 " .- \027[31;1m-.\027[31m",
148 " -- \027[31;1m-.\027[31m",
149 " `:` \027[31;1m`:`",
150 " \027[31;1m.-- `--.",
151 " .---.....----.\027[37m"
156 " s` `.....---.......--.``` -/",
175 drawer.menu_name_handlers = {
176 -- Menu name handlers should take the menu being drawn and entry being
177 -- drawn as parameters, and return the name of the item.
178 -- This is designed so that everything, including menu separators, may
179 -- have their names derived differently. The default action for entry
180 -- types not specified here is to use entry.name directly.
181 [core.MENU_SEPARATOR] = function(drawing_menu, entry)
182 if entry.name ~= nil then
183 if type(entry.name) == "function" then
190 [core.MENU_CAROUSEL_ENTRY] = function(drawing_menu, entry)
191 local carid = entry.carousel_id
192 local caridx = config.getCarouselIndex(carid)
193 local choices = entry.items
194 if type(choices) == "function" then
197 if #choices < caridx then
200 return entry.name(caridx, choices[caridx], choices)
204 drawer.brand_position = {x = 2, y = 1}
205 drawer.logo_position = {x = 46, y = 1}
206 drawer.menu_position = {x = 6, y = 11}
207 drawer.box_pos_dim = {x = 3, y = 10, w = 41, h = 11}
210 -- Indexed by valid values for loader_brand in loader.conf(5). Valid
211 -- keys are: graphic (table depicting graphic)
221 -- Indexed by valid values for loader_logo in loader.conf(5). Valid keys
222 -- are: requires_color (boolean), graphic (table depicting graphic), and
223 -- shift (table containing x and y).
225 requires_color = true,
226 graphic = beastie_color,
232 graphic = fbsd_logo_v,
233 shift = {x = 5, y = 4},
236 requires_color = true,
238 shift = {x = 2, y = 4},
242 shift = {x = 2, y = 4},
252 shift = {x = 17, y = 0},
256 function drawer.drawscreen(menu_opts)
257 -- drawlogo() must go first.
258 -- it determines the positions of other elements
262 return drawer.drawmenu(menu_opts)
265 function drawer.drawmenu(m)
266 x = drawer.menu_position.x
267 y = drawer.menu_position.y
269 -- print the menu and build the alias table
270 local alias_table = {}
272 local menu_entries = m.entries
273 if type(menu_entries) == "function" then
274 menu_entries = menu_entries()
276 for line_num, e in ipairs(menu_entries) do
277 -- Allow menu items to be conditionally visible by specifying
278 -- a visible function.
279 if e.visible ~= nil and not e.visible() then
282 if e.entry_type ~= core.MENU_SEPARATOR then
283 entry_num = entry_num + 1
284 screen.setcursor(x, y + line_num)
286 print(entry_num .. ". " .. menu_entry_name(m, e))
288 -- fill the alias table
289 alias_table[tostring(entry_num)] = e
290 if e.alias ~= nil then
291 for n, a in ipairs(e.alias) do
296 screen.setcursor(x, y + line_num)
297 print(menu_entry_name(m, e))
305 function drawer.drawbox()
306 x = drawer.box_pos_dim.x
307 y = drawer.box_pos_dim.y
308 w = drawer.box_pos_dim.w
309 h = drawer.box_pos_dim.h
311 local hl = string.char(0xCD)
312 local vl = string.char(0xBA)
314 local tl = string.char(0xC9)
315 local bl = string.char(0xC8)
316 local tr = string.char(0xBB)
317 local br = string.char(0xBC)
319 screen.setcursor(x, y); print(tl)
320 screen.setcursor(x, y+h); print(bl)
321 screen.setcursor(x+w, y); print(tr)
322 screen.setcursor(x+w, y+h); print(br)
325 screen.setcursor(x+i, y)
327 screen.setcursor(x+i, y+h)
332 screen.setcursor(x, y+i)
334 screen.setcursor(x+w, y+i)
338 screen.setcursor(x+(w/2)-9, y)
339 print("Welcome to FreeBSD")
342 function drawer.draw(x, y, logo)
344 screen.setcursor(x, y + i)
349 function drawer.drawbrand()
350 local x = tonumber(loader.getenv("loader_brand_x")) or
351 drawer.brand_position.x
352 local y = tonumber(loader.getenv("loader_brand_y")) or
353 drawer.brand_position.y
355 local graphic = drawer.branddefs[loader.getenv("loader_brand")]
356 if graphic == nil then
359 drawer.draw(x, y, graphic)
362 function drawer.drawlogo()
363 local x = tonumber(loader.getenv("loader_logo_x")) or
364 drawer.logo_position.x
365 local y = tonumber(loader.getenv("loader_logo_y")) or
366 drawer.logo_position.y
368 local logo = loader.getenv("loader_logo")
369 local colored = color.isEnabled()
372 local logodef = drawer.logodefs[logo]
374 if logodef ~= nil and logodef.graphic == none then
375 -- centre brand and text if no logo
376 if not none_shifted then
377 shift_brand_text(logodef.shift)
380 elseif logodef == nil or logodef.graphic == nil or
381 (not colored and logodef.requires_color) then
382 -- Choose a sensible default
384 logodef = drawer.logodefs["orb"]
386 logodef = drawer.logodefs["orbbw"]
389 if logodef.shift ~= nil then
390 x = x + logodef.shift.x
391 y = y + logodef.shift.y
393 drawer.draw(x, y, logodef.graphic)