xref: /freebsd/stand/lua/drawer.lua (revision c2ba66d4d01f23303352bfe3cbd50ff5d9a05947)
1088b4f5fSWarner Losh--
24d846d26SWarner Losh-- SPDX-License-Identifier: BSD-2-Clause
372e39d71SKyle Evans--
4088b4f5fSWarner Losh-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
5df74a61fSKyle Evans-- Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
6088b4f5fSWarner Losh-- All rights reserved.
7088b4f5fSWarner Losh--
8088b4f5fSWarner Losh-- Redistribution and use in source and binary forms, with or without
9088b4f5fSWarner Losh-- modification, are permitted provided that the following conditions
10088b4f5fSWarner Losh-- are met:
11088b4f5fSWarner Losh-- 1. Redistributions of source code must retain the above copyright
12088b4f5fSWarner Losh--    notice, this list of conditions and the following disclaimer.
13088b4f5fSWarner Losh-- 2. Redistributions in binary form must reproduce the above copyright
14088b4f5fSWarner Losh--    notice, this list of conditions and the following disclaimer in the
15088b4f5fSWarner Losh--    documentation and/or other materials provided with the distribution.
16088b4f5fSWarner Losh--
17088b4f5fSWarner Losh-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18088b4f5fSWarner Losh-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19088b4f5fSWarner Losh-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20088b4f5fSWarner Losh-- ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21088b4f5fSWarner Losh-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22088b4f5fSWarner Losh-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23088b4f5fSWarner Losh-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24088b4f5fSWarner Losh-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25088b4f5fSWarner Losh-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26088b4f5fSWarner Losh-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27088b4f5fSWarner Losh-- SUCH DAMAGE.
28088b4f5fSWarner Losh--
29088b4f5fSWarner Losh
30aedd6be5SKyle Evanslocal color = require("color")
31aedd6be5SKyle Evanslocal config = require("config")
32aedd6be5SKyle Evanslocal core = require("core")
33aedd6be5SKyle Evanslocal screen = require("screen")
34088b4f5fSWarner Losh
35aedd6be5SKyle Evanslocal drawer = {}
36c8518398SKyle Evans
371091c8feSKyle Evanslocal fbsd_brand
38aedd6be5SKyle Evanslocal none
3902122e53SKyle Evans
40a9edc01bSKyle Evanslocal menu_name_handlers
41a9edc01bSKyle Evanslocal branddefs
42a9edc01bSKyle Evanslocal logodefs
43a9edc01bSKyle Evanslocal brand_position
44a9edc01bSKyle Evanslocal logo_position
45a9edc01bSKyle Evanslocal menu_position
46a9edc01bSKyle Evanslocal frame_size
47a9edc01bSKyle Evanslocal default_shift
48a9edc01bSKyle Evanslocal shift
49a9edc01bSKyle Evans
500fd98b8aSWarner Losh-- Make this code compatible with older loader binaries. We moved the term_*
510fd98b8aSWarner Losh-- functions from loader to the gfx. if we're running on an older loader that
520fd98b8aSWarner Losh-- has these functions, create aliases for them in gfx. The loader binary might
530fd98b8aSWarner Losh-- be so old as to not have them, but in that case, we want to copy the nil
540fd98b8aSWarner Losh-- values. The new loader will provide loader.* versions of all the gfx.*
550fd98b8aSWarner Losh-- functions for backwards compatibility, so we only define the functions we use
560fd98b8aSWarner Losh-- here.
570fd98b8aSWarner Loshif gfx == nil then
580fd98b8aSWarner Losh	gfx = {}
590fd98b8aSWarner Losh	gfx.term_drawrect = loader.term_drawrect
600fd98b8aSWarner Losh	gfx.term_putimage = loader.term_putimage
610fd98b8aSWarner Loshend
620fd98b8aSWarner Losh
63322a2dddSKyle Evanslocal function menuEntryName(drawing_menu, entry)
64a9edc01bSKyle Evans	local name_handler = menu_name_handlers[entry.entry_type]
65e15abd1fSKyle Evans
669f71d421SKyle Evans	if name_handler ~= nil then
67aedd6be5SKyle Evans		return name_handler(drawing_menu, entry)
68e15abd1fSKyle Evans	end
69a51f9f0cSKyle Evans	if type(entry.name) == "function" then
70aedd6be5SKyle Evans		return entry.name()
71e15abd1fSKyle Evans	end
72a51f9f0cSKyle Evans	return entry.name
73a51f9f0cSKyle Evansend
74e15abd1fSKyle Evans
75546f18f3SKyle Evanslocal function processFile(gfxname)
76546f18f3SKyle Evans	if gfxname == nil then
77546f18f3SKyle Evans		return false, "Missing filename"
78546f18f3SKyle Evans	end
79546f18f3SKyle Evans
80546f18f3SKyle Evans	local ret = try_include('gfx-' .. gfxname)
81546f18f3SKyle Evans	if ret == nil then
82546f18f3SKyle Evans		return false, "Failed to include gfx-" .. gfxname
83546f18f3SKyle Evans	end
84546f18f3SKyle Evans
85546f18f3SKyle Evans	-- Legacy format
86546f18f3SKyle Evans	if type(ret) ~= "table" then
87546f18f3SKyle Evans		return true
88546f18f3SKyle Evans	end
89546f18f3SKyle Evans
90546f18f3SKyle Evans	for gfxtype, def in pairs(ret) do
91546f18f3SKyle Evans		if gfxtype == "brand" then
92546f18f3SKyle Evans			drawer.addBrand(gfxname, def)
93546f18f3SKyle Evans		elseif gfxtype == "logo" then
94546f18f3SKyle Evans			drawer.addLogo(gfxname, def)
95546f18f3SKyle Evans		else
96546f18f3SKyle Evans			return false, "Unknown graphics type '" .. gfxtype ..
97546f18f3SKyle Evans			    "'"
98546f18f3SKyle Evans		end
99546f18f3SKyle Evans	end
100546f18f3SKyle Evans
101546f18f3SKyle Evans	return true
102546f18f3SKyle Evansend
103546f18f3SKyle Evans
104e21e1dbeSKyle Evanslocal function getBranddef(brand)
105e21e1dbeSKyle Evans	if brand == nil then
106e21e1dbeSKyle Evans		return nil
107e21e1dbeSKyle Evans	end
108e21e1dbeSKyle Evans	-- Look it up
109a9edc01bSKyle Evans	local branddef = branddefs[brand]
110e21e1dbeSKyle Evans
111e21e1dbeSKyle Evans	-- Try to pull it in
112e21e1dbeSKyle Evans	if branddef == nil then
113546f18f3SKyle Evans		local res, err = processFile(brand)
114546f18f3SKyle Evans		if not res then
115546f18f3SKyle Evans			-- This fallback should go away after FreeBSD 13.
116e21e1dbeSKyle Evans			try_include('brand-' .. brand)
117546f18f3SKyle Evans			-- If the fallback also failed, print whatever error
118546f18f3SKyle Evans			-- we encountered in the original processing.
119546f18f3SKyle Evans			if branddefs[brand] == nil then
120546f18f3SKyle Evans				print(err)
121546f18f3SKyle Evans				return nil
122546f18f3SKyle Evans			end
123546f18f3SKyle Evans		end
124546f18f3SKyle Evans
125a9edc01bSKyle Evans		branddef = branddefs[brand]
126e21e1dbeSKyle Evans	end
127e21e1dbeSKyle Evans
128e21e1dbeSKyle Evans	return branddef
129e21e1dbeSKyle Evansend
130e21e1dbeSKyle Evans
1311091c8feSKyle Evanslocal function getLogodef(logo)
132bbb516aeSKyle Evans	if logo == nil then
133bbb516aeSKyle Evans		return nil
134bbb516aeSKyle Evans	end
1351091c8feSKyle Evans	-- Look it up
136a9edc01bSKyle Evans	local logodef = logodefs[logo]
1371091c8feSKyle Evans
1381091c8feSKyle Evans	-- Try to pull it in
1391091c8feSKyle Evans	if logodef == nil then
140546f18f3SKyle Evans		local res, err = processFile(logo)
141546f18f3SKyle Evans		if not res then
142546f18f3SKyle Evans			-- This fallback should go away after FreeBSD 13.
1431091c8feSKyle Evans			try_include('logo-' .. logo)
144546f18f3SKyle Evans			-- If the fallback also failed, print whatever error
145546f18f3SKyle Evans			-- we encountered in the original processing.
146546f18f3SKyle Evans			if logodefs[logo] == nil then
147546f18f3SKyle Evans				print(err)
148546f18f3SKyle Evans				return nil
149546f18f3SKyle Evans			end
150546f18f3SKyle Evans		end
151546f18f3SKyle Evans
152a9edc01bSKyle Evans		logodef = logodefs[logo]
1531091c8feSKyle Evans	end
1541091c8feSKyle Evans
1551091c8feSKyle Evans	return logodef
1561091c8feSKyle Evansend
1571091c8feSKyle Evans
1586112ee09SKyle Evanslocal function draw(x, y, logo)
1596112ee09SKyle Evans	for i = 1, #logo do
1606112ee09SKyle Evans		screen.setcursor(x, y + i - 1)
1616112ee09SKyle Evans		printc(logo[i])
1626112ee09SKyle Evans	end
1636112ee09SKyle Evansend
1646112ee09SKyle Evans
16512eaa305SKyle Evanslocal function drawmenu(menudef)
166a9edc01bSKyle Evans	local x = menu_position.x
167a9edc01bSKyle Evans	local y = menu_position.y
16812eaa305SKyle Evans
169a9edc01bSKyle Evans	x = x + shift.x
170a9edc01bSKyle Evans	y = y + shift.y
17112eaa305SKyle Evans
17212eaa305SKyle Evans	-- print the menu and build the alias table
17312eaa305SKyle Evans	local alias_table = {}
17412eaa305SKyle Evans	local entry_num = 0
17512eaa305SKyle Evans	local menu_entries = menudef.entries
17612eaa305SKyle Evans	local effective_line_num = 0
17712eaa305SKyle Evans	if type(menu_entries) == "function" then
17812eaa305SKyle Evans		menu_entries = menu_entries()
17912eaa305SKyle Evans	end
18012eaa305SKyle Evans	for _, e in ipairs(menu_entries) do
18112eaa305SKyle Evans		-- Allow menu items to be conditionally visible by specifying
18212eaa305SKyle Evans		-- a visible function.
18312eaa305SKyle Evans		if e.visible ~= nil and not e.visible() then
18412eaa305SKyle Evans			goto continue
18512eaa305SKyle Evans		end
18612eaa305SKyle Evans		effective_line_num = effective_line_num + 1
18712eaa305SKyle Evans		if e.entry_type ~= core.MENU_SEPARATOR then
18812eaa305SKyle Evans			entry_num = entry_num + 1
18912eaa305SKyle Evans			screen.setcursor(x, y + effective_line_num)
19012eaa305SKyle Evans
19112eaa305SKyle Evans			printc(entry_num .. ". " .. menuEntryName(menudef, e))
19212eaa305SKyle Evans
19312eaa305SKyle Evans			-- fill the alias table
19412eaa305SKyle Evans			alias_table[tostring(entry_num)] = e
19512eaa305SKyle Evans			if e.alias ~= nil then
19612eaa305SKyle Evans				for _, a in ipairs(e.alias) do
19712eaa305SKyle Evans					alias_table[a] = e
19812eaa305SKyle Evans				end
19912eaa305SKyle Evans			end
20012eaa305SKyle Evans		else
20112eaa305SKyle Evans			screen.setcursor(x, y + effective_line_num)
20212eaa305SKyle Evans			printc(menuEntryName(menudef, e))
20312eaa305SKyle Evans		end
20412eaa305SKyle Evans		::continue::
20512eaa305SKyle Evans	end
20612eaa305SKyle Evans	return alias_table
20712eaa305SKyle Evansend
20812eaa305SKyle Evans
20990a25417SKyle Evanslocal function defaultframe()
21090a25417SKyle Evans	if core.isSerialConsole() then
21190a25417SKyle Evans		return "ascii"
21290a25417SKyle Evans	end
21390a25417SKyle Evans	return "double"
21490a25417SKyle Evansend
21590a25417SKyle Evans
2163630506bSToomas Soomelocal function drawframe()
217a9edc01bSKyle Evans	local x = menu_position.x - 3
218a9edc01bSKyle Evans	local y = menu_position.y - 1
219a9edc01bSKyle Evans	local w = frame_size.w
220a9edc01bSKyle Evans	local h = frame_size.h
22112eaa305SKyle Evans
22290a25417SKyle Evans	local framestyle = loader.getenv("loader_menu_frame") or defaultframe()
22312eaa305SKyle Evans	local framespec = drawer.frame_styles[framestyle]
22412eaa305SKyle Evans	-- If we don't have a framespec for the current frame style, just don't
22512eaa305SKyle Evans	-- draw a box.
22612eaa305SKyle Evans	if framespec == nil then
2273630506bSToomas Soome		return false
22812eaa305SKyle Evans	end
22912eaa305SKyle Evans
23012eaa305SKyle Evans	local hl = framespec.horizontal
23112eaa305SKyle Evans	local vl = framespec.vertical
23212eaa305SKyle Evans
23312eaa305SKyle Evans	local tl = framespec.top_left
23412eaa305SKyle Evans	local bl = framespec.bottom_left
23512eaa305SKyle Evans	local tr = framespec.top_right
23612eaa305SKyle Evans	local br = framespec.bottom_right
23712eaa305SKyle Evans
238a9edc01bSKyle Evans	x = x + shift.x
239a9edc01bSKyle Evans	y = y + shift.y
24012eaa305SKyle Evans
2410fd98b8aSWarner Losh	if core.isFramebufferConsole() and gfx.term_drawrect ~= nil then
2420fd98b8aSWarner Losh		gfx.term_drawrect(x, y, x + w, y + h)
2433630506bSToomas Soome		return true
2443630506bSToomas Soome	end
2453630506bSToomas Soome
24612eaa305SKyle Evans	screen.setcursor(x, y); printc(tl)
24712eaa305SKyle Evans	screen.setcursor(x, y + h); printc(bl)
24812eaa305SKyle Evans	screen.setcursor(x + w, y); printc(tr)
24912eaa305SKyle Evans	screen.setcursor(x + w, y + h); printc(br)
25012eaa305SKyle Evans
25112eaa305SKyle Evans	screen.setcursor(x + 1, y)
25212eaa305SKyle Evans	for _ = 1, w - 1 do
25312eaa305SKyle Evans		printc(hl)
25412eaa305SKyle Evans	end
25512eaa305SKyle Evans
25612eaa305SKyle Evans	screen.setcursor(x + 1, y + h)
25712eaa305SKyle Evans	for _ = 1, w - 1 do
25812eaa305SKyle Evans		printc(hl)
25912eaa305SKyle Evans	end
26012eaa305SKyle Evans
26112eaa305SKyle Evans	for i = 1, h - 1 do
26212eaa305SKyle Evans		screen.setcursor(x, y + i)
26312eaa305SKyle Evans		printc(vl)
26412eaa305SKyle Evans		screen.setcursor(x + w, y + i)
26512eaa305SKyle Evans		printc(vl)
26612eaa305SKyle Evans	end
2673630506bSToomas Soome	return true
2683630506bSToomas Soomeend
26912eaa305SKyle Evans
2703630506bSToomas Soomelocal function drawbox()
2713630506bSToomas Soome	local x = menu_position.x - 3
2723630506bSToomas Soome	local y = menu_position.y - 1
2733630506bSToomas Soome	local w = frame_size.w
27412eaa305SKyle Evans	local menu_header = loader.getenv("loader_menu_title") or
27512eaa305SKyle Evans	    "Welcome to FreeBSD"
27612eaa305SKyle Evans	local menu_header_align = loader.getenv("loader_menu_title_align")
27712eaa305SKyle Evans	local menu_header_x
27812eaa305SKyle Evans
2793630506bSToomas Soome	x = x + shift.x
2803630506bSToomas Soome	y = y + shift.y
2813630506bSToomas Soome
2823630506bSToomas Soome	if drawframe(x, y, w) == false then
2833630506bSToomas Soome		return
2843630506bSToomas Soome	end
2853630506bSToomas Soome
28612eaa305SKyle Evans	if menu_header_align ~= nil then
28712eaa305SKyle Evans		menu_header_align = menu_header_align:lower()
28812eaa305SKyle Evans		if menu_header_align == "left" then
28912eaa305SKyle Evans			-- Just inside the left border on top
29012eaa305SKyle Evans			menu_header_x = x + 1
29112eaa305SKyle Evans		elseif menu_header_align == "right" then
29212eaa305SKyle Evans			-- Just inside the right border on top
29312eaa305SKyle Evans			menu_header_x = x + w - #menu_header
29412eaa305SKyle Evans		end
29512eaa305SKyle Evans	end
29612eaa305SKyle Evans	if menu_header_x == nil then
297994e1f40SKyle Evans		menu_header_x = x + (w // 2) - (#menu_header // 2)
29812eaa305SKyle Evans	end
29962ffcaabSToomas Soome	screen.setcursor(menu_header_x - 1, y)
3004ba91fa0SToomas Soome	if menu_header ~= "" then
30162ffcaabSToomas Soome		printc(" " .. menu_header .. " ")
30212eaa305SKyle Evans	end
30312eaa305SKyle Evans
3044ba91fa0SToomas Soomeend
3054ba91fa0SToomas Soome
30612eaa305SKyle Evanslocal function drawbrand()
30712eaa305SKyle Evans	local x = tonumber(loader.getenv("loader_brand_x")) or
308a9edc01bSKyle Evans	    brand_position.x
30912eaa305SKyle Evans	local y = tonumber(loader.getenv("loader_brand_y")) or
310a9edc01bSKyle Evans	    brand_position.y
31112eaa305SKyle Evans
31212eaa305SKyle Evans	local branddef = getBranddef(loader.getenv("loader_brand"))
31312eaa305SKyle Evans
31412eaa305SKyle Evans	if branddef == nil then
31512eaa305SKyle Evans		branddef = getBranddef(drawer.default_brand)
31612eaa305SKyle Evans	end
31712eaa305SKyle Evans
31812eaa305SKyle Evans	local graphic = branddef.graphic
31912eaa305SKyle Evans
320a9edc01bSKyle Evans	x = x + shift.x
321a9edc01bSKyle Evans	y = y + shift.y
322e19d9a9bSKyle Evans	if branddef.shift ~= nil then
323e19d9a9bSKyle Evans		x = x +	branddef.shift.x
324e19d9a9bSKyle Evans		y = y + branddef.shift.y
325e19d9a9bSKyle Evans	end
326e19d9a9bSKyle Evans
3273630506bSToomas Soome	if core.isFramebufferConsole() and
3280fd98b8aSWarner Losh	    gfx.term_putimage ~= nil and
3293630506bSToomas Soome	    branddef.image ~= nil then
3300fd98b8aSWarner Losh		if gfx.term_putimage(branddef.image, 1, 1, 0, 7, 0)
3313630506bSToomas Soome		then
3323630506bSToomas Soome			return true
3333630506bSToomas Soome		end
3343630506bSToomas Soome	end
33512eaa305SKyle Evans	draw(x, y, graphic)
33612eaa305SKyle Evansend
33712eaa305SKyle Evans
33812eaa305SKyle Evanslocal function drawlogo()
33912eaa305SKyle Evans	local x = tonumber(loader.getenv("loader_logo_x")) or
340a9edc01bSKyle Evans	    logo_position.x
34112eaa305SKyle Evans	local y = tonumber(loader.getenv("loader_logo_y")) or
342a9edc01bSKyle Evans	    logo_position.y
34312eaa305SKyle Evans
34412eaa305SKyle Evans	local logo = loader.getenv("loader_logo")
34512eaa305SKyle Evans	local colored = color.isEnabled()
34612eaa305SKyle Evans
34712eaa305SKyle Evans	local logodef = getLogodef(logo)
34812eaa305SKyle Evans
34912eaa305SKyle Evans	if logodef == nil or logodef.graphic == nil or
35012eaa305SKyle Evans	    (not colored and logodef.requires_color) then
35112eaa305SKyle Evans		-- Choose a sensible default
35212eaa305SKyle Evans		if colored then
3532c690e2aSKyle Evans			logodef = getLogodef(drawer.default_color_logodef)
35412eaa305SKyle Evans		else
3552c690e2aSKyle Evans			logodef = getLogodef(drawer.default_bw_logodef)
35612eaa305SKyle Evans		end
3576697f577SKyle Evans
3586697f577SKyle Evans		-- Something has gone terribly wrong.
3596697f577SKyle Evans		if logodef == nil then
3606697f577SKyle Evans			logodef = getLogodef(drawer.default_fallback_logodef)
3616697f577SKyle Evans		end
36212eaa305SKyle Evans	end
36312eaa305SKyle Evans
36412eaa305SKyle Evans	if logodef ~= nil and logodef.graphic == none then
365a9edc01bSKyle Evans		shift = logodef.shift
36612eaa305SKyle Evans	else
367a9edc01bSKyle Evans		shift = default_shift
36812eaa305SKyle Evans	end
36912eaa305SKyle Evans
370a9edc01bSKyle Evans	x = x + shift.x
371a9edc01bSKyle Evans	y = y + shift.y
37212eaa305SKyle Evans
37312eaa305SKyle Evans	if logodef ~= nil and logodef.shift ~= nil then
37412eaa305SKyle Evans		x = x + logodef.shift.x
37512eaa305SKyle Evans		y = y + logodef.shift.y
37612eaa305SKyle Evans	end
37712eaa305SKyle Evans
3783630506bSToomas Soome	if core.isFramebufferConsole() and
3790fd98b8aSWarner Losh	    gfx.term_putimage ~= nil and
3803630506bSToomas Soome	    logodef.image ~= nil then
3813630506bSToomas Soome		local y1 = 15
3823630506bSToomas Soome
3833630506bSToomas Soome		if logodef.image_rl ~= nil then
3843630506bSToomas Soome			y1 = logodef.image_rl
3853630506bSToomas Soome		end
3860fd98b8aSWarner Losh		if gfx.term_putimage(logodef.image, x, y, 0, y + y1, 0)
3873630506bSToomas Soome		then
3883630506bSToomas Soome			return true
3893630506bSToomas Soome		end
3903630506bSToomas Soome	end
39112eaa305SKyle Evans	draw(x, y, logodef.graphic)
39212eaa305SKyle Evansend
39312eaa305SKyle Evans
3943630506bSToomas Soomelocal function drawitem(func)
3953630506bSToomas Soome	local console = loader.getenv("console")
3963630506bSToomas Soome
3973630506bSToomas Soome	for c in string.gmatch(console, "%w+") do
3983630506bSToomas Soome		loader.setenv("console", c)
3993630506bSToomas Soome		func()
4003630506bSToomas Soome	end
4013630506bSToomas Soome	loader.setenv("console", console)
4023630506bSToomas Soomeend
4033630506bSToomas Soome
4041091c8feSKyle Evansfbsd_brand = {
405088b4f5fSWarner Losh"  ______               ____   _____ _____  ",
406088b4f5fSWarner Losh" |  ____|             |  _ \\ / ____|  __ \\ ",
407088b4f5fSWarner Losh" | |___ _ __ ___  ___ | |_) | (___ | |  | |",
408088b4f5fSWarner Losh" |  ___| '__/ _ \\/ _ \\|  _ < \\___ \\| |  | |",
409088b4f5fSWarner Losh" | |   | | |  __/  __/| |_) |____) | |__| |",
410088b4f5fSWarner Losh" | |   | | |    |    ||     |      |      |",
411088b4f5fSWarner Losh" |_|   |_|  \\___|\\___||____/|_____/|_____/ "
412aedd6be5SKyle Evans}
413aedd6be5SKyle Evansnone = {""}
414088b4f5fSWarner Losh
415a9edc01bSKyle Evansmenu_name_handlers = {
416b5746545SKyle Evans	-- Menu name handlers should take the menu being drawn and entry being
417b5746545SKyle Evans	-- drawn as parameters, and return the name of the item.
418b5746545SKyle Evans	-- This is designed so that everything, including menu separators, may
419b5746545SKyle Evans	-- have their names derived differently. The default action for entry
420a51f9f0cSKyle Evans	-- types not specified here is to use entry.name directly.
421e2df27e3SKyle Evans	[core.MENU_SEPARATOR] = function(_, entry)
422dd65496aSKyle Evans		if entry.name ~= nil then
423a51f9f0cSKyle Evans			if type(entry.name) == "function" then
424dd65496aSKyle Evans				return entry.name()
425dd65496aSKyle Evans			end
426a51f9f0cSKyle Evans			return entry.name
427a51f9f0cSKyle Evans		end
428dd65496aSKyle Evans		return ""
429dd65496aSKyle Evans	end,
430e2df27e3SKyle Evans	[core.MENU_CAROUSEL_ENTRY] = function(_, entry)
431aedd6be5SKyle Evans		local carid = entry.carousel_id
432aedd6be5SKyle Evans		local caridx = config.getCarouselIndex(carid)
4334f437f9eSKyle Evans		local choices = entry.items
4344f437f9eSKyle Evans		if type(choices) == "function" then
4354f437f9eSKyle Evans			choices = choices()
4364f437f9eSKyle Evans		end
4379f71d421SKyle Evans		if #choices < caridx then
438aedd6be5SKyle Evans			caridx = 1
439b5746545SKyle Evans		end
440aedd6be5SKyle Evans		return entry.name(caridx, choices[caridx], choices)
441b5746545SKyle Evans	end,
442aedd6be5SKyle Evans}
443b5746545SKyle Evans
444a9edc01bSKyle Evansbranddefs = {
445699578a6SKyle Evans	-- Indexed by valid values for loader_brand in loader.conf(5). Valid
446699578a6SKyle Evans	-- keys are: graphic (table depicting graphic)
44729aa5794SKyle Evans	["fbsd"] = {
4481091c8feSKyle Evans		graphic = fbsd_brand,
4493630506bSToomas Soome		image = "/boot/images/freebsd-brand-rev.png",
45029aa5794SKyle Evans	},
45129aa5794SKyle Evans	["none"] = {
45229aa5794SKyle Evans		graphic = none,
45329aa5794SKyle Evans	},
454aedd6be5SKyle Evans}
45529aa5794SKyle Evans
456a9edc01bSKyle Evanslogodefs = {
457bb26c57dSKyle Evans	-- Indexed by valid values for loader_logo in loader.conf(5). Valid keys
458752b2d40SKyle Evans	-- are: requires_color (boolean), graphic (table depicting graphic), and
459bb26c57dSKyle Evans	-- shift (table containing x and y).
460bb26c57dSKyle Evans	["tribute"] = {
4611091c8feSKyle Evans		graphic = fbsd_brand,
462bb26c57dSKyle Evans	},
463bb26c57dSKyle Evans	["tributebw"] = {
4641091c8feSKyle Evans		graphic = fbsd_brand,
465bb26c57dSKyle Evans	},
466bb26c57dSKyle Evans	["none"] = {
467752b2d40SKyle Evans		graphic = none,
468bb26c57dSKyle Evans		shift = {x = 17, y = 0},
469bb26c57dSKyle Evans	},
470aedd6be5SKyle Evans}
471bb26c57dSKyle Evans
472a9edc01bSKyle Evansbrand_position = {x = 2, y = 1}
473a9edc01bSKyle Evanslogo_position = {x = 46, y = 4}
474a9edc01bSKyle Evansmenu_position = {x = 5, y = 10}
475101afbc6SWarner Loshframe_size = {w = 42, h = 14}
476a9edc01bSKyle Evansdefault_shift = {x = 0, y = 0}
477a9edc01bSKyle Evansshift = default_shift
478a9edc01bSKyle Evans
479a9edc01bSKyle Evans-- Module exports
480a9edc01bSKyle Evansdrawer.default_brand = 'fbsd'
4812c690e2aSKyle Evansdrawer.default_color_logodef = 'orb'
4822c690e2aSKyle Evansdrawer.default_bw_logodef = 'orbbw'
4836697f577SKyle Evans-- For when things go terribly wrong; this def should be present here in the
4846697f577SKyle Evans-- drawer module in case it's a filesystem issue.
4856697f577SKyle Evansdrawer.default_fallback_logodef = 'none'
486a9edc01bSKyle Evans
487546f18f3SKyle Evans-- These should go away after FreeBSD 13; only available for backwards
488546f18f3SKyle Evans-- compatibility with old logo- files.
489a9edc01bSKyle Evansfunction drawer.addBrand(name, def)
490a9edc01bSKyle Evans	branddefs[name] = def
491a9edc01bSKyle Evansend
492a9edc01bSKyle Evans
493a9edc01bSKyle Evansfunction drawer.addLogo(name, def)
494a9edc01bSKyle Evans	logodefs[name] = def
495a9edc01bSKyle Evansend
496a9edc01bSKyle Evans
497379e652eSKyle Evansdrawer.frame_styles = {
498379e652eSKyle Evans	-- Indexed by valid values for loader_menu_frame in loader.conf(5).
499379e652eSKyle Evans	-- All of the keys appearing below must be set for any menu frame style
500379e652eSKyle Evans	-- added to drawer.frame_styles.
501379e652eSKyle Evans	["ascii"] = {
502379e652eSKyle Evans		horizontal	= "-",
503379e652eSKyle Evans		vertical	= "|",
504379e652eSKyle Evans		top_left	= "+",
505379e652eSKyle Evans		bottom_left	= "+",
506379e652eSKyle Evans		top_right	= "+",
507379e652eSKyle Evans		bottom_right	= "+",
508379e652eSKyle Evans	},
509*c2ba66d4SWarner Losh}
510*c2ba66d4SWarner Losh
511*c2ba66d4SWarner Loshif core.hasUnicode() then
512*c2ba66d4SWarner Losh	-- unicode based framing characters
513*c2ba66d4SWarner Losh	drawer.frame_styles["single"] = {
51456758831SToomas Soome		horizontal	= "\xE2\x94\x80",
51556758831SToomas Soome		vertical	= "\xE2\x94\x82",
51656758831SToomas Soome		top_left	= "\xE2\x94\x8C",
51756758831SToomas Soome		bottom_left	= "\xE2\x94\x94",
51856758831SToomas Soome		top_right	= "\xE2\x94\x90",
51956758831SToomas Soome		bottom_right	= "\xE2\x94\x98",
520*c2ba66d4SWarner Losh	}
521*c2ba66d4SWarner Losh	drawer.frame_styles["double"] = {
52256758831SToomas Soome		horizontal	= "\xE2\x95\x90",
52356758831SToomas Soome		vertical	= "\xE2\x95\x91",
52456758831SToomas Soome		top_left	= "\xE2\x95\x94",
52556758831SToomas Soome		bottom_left	= "\xE2\x95\x9A",
52656758831SToomas Soome		top_right	= "\xE2\x95\x97",
52756758831SToomas Soome		bottom_right	= "\xE2\x95\x9D",
528379e652eSKyle Evans	}
529*c2ba66d4SWarner Loshelse
530*c2ba66d4SWarner Losh	-- non-unicode cons25-style framing characters
531*c2ba66d4SWarner Losh	drawer.frame_styles["single"] = {
532*c2ba66d4SWarner Losh		horizontal	= "\xC4",
533*c2ba66d4SWarner Losh		vertical	= "\xB3",
534*c2ba66d4SWarner Losh		top_left	= "\xDA",
535*c2ba66d4SWarner Losh		bottom_left	= "\xC0",
536*c2ba66d4SWarner Losh		top_right	= "\xBF",
537*c2ba66d4SWarner Losh		bottom_right	= "\xD9",
538*c2ba66d4SWarner Losh        }
539*c2ba66d4SWarner Losh	drawer.frame_styles["double"] = {
540*c2ba66d4SWarner Losh		horizontal	= "\xCD",
541*c2ba66d4SWarner Losh		vertical	= "\xBA",
542*c2ba66d4SWarner Losh		top_left	= "\xC9",
543*c2ba66d4SWarner Losh		bottom_left	= "\xC8",
544*c2ba66d4SWarner Losh		top_right	= "\xBB",
545*c2ba66d4SWarner Losh		bottom_right	= "\xBC",
546*c2ba66d4SWarner Losh	}
547*c2ba66d4SWarner Loshend
548379e652eSKyle Evans
54912eaa305SKyle Evansfunction drawer.drawscreen(menudef)
550088b4f5fSWarner Losh	-- drawlogo() must go first.
551088b4f5fSWarner Losh	-- it determines the positions of other elements
5523630506bSToomas Soome	drawitem(drawlogo)
5533630506bSToomas Soome	drawitem(drawbrand)
5543630506bSToomas Soome	drawitem(drawbox)
55512eaa305SKyle Evans	return drawmenu(menudef)
556088b4f5fSWarner Loshend
557088b4f5fSWarner Losh
558aedd6be5SKyle Evansreturn drawer
559