]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/lua/drawer.lua
MFV r316872: 7502 ztest should run zdb with -G (debug mode)
[FreeBSD/FreeBSD.git] / stand / lua / drawer.lua
1 --
2 -- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
3 -- Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
4 -- All rights reserved.
5 --
6 -- Redistribution and use in source and binary forms, with or without
7 -- modification, are permitted provided that the following conditions
8 -- are met:
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.
14 --
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
25 -- SUCH DAMAGE.
26 --
27 -- $FreeBSD$
28 --
29
30 local color = require("color");
31 local config = require("config");
32 local core = require("core");
33 local screen = require("screen");
34
35 local drawer = {};
36
37 local fbsd_logo;
38 local beastie_color;
39 local beastie;
40 local fbsd_logo_v;
41 local orb;
42 local none;
43 local none_shifted = false;
44
45 local menu_entry_name = function(drawing_menu, entry)
46         local name_handler = drawer.menu_name_handlers[entry.entry_type];
47
48         if (name_handler ~= nil) then
49                 return name_handler(drawing_menu, entry);
50         end
51         return entry.name();
52 end
53
54 local shift_brand_text = function(shift)
55         drawer.brand_position.x = drawer.brand_position.x + shift.x;
56         drawer.brand_position.y = drawer.brand_position.y + shift.y;
57         drawer.menu_position.x = drawer.menu_position.x + shift.x;
58         drawer.menu_position.y = drawer.menu_position.y + shift.y;
59         drawer.box_pos_dim.x = drawer.box_pos_dim.x + shift.x;
60         drawer.box_pos_dim.y = drawer.box_pos_dim.y + shift.y;
61 end
62
63 fbsd_logo = {
64         "  ______               ____   _____ _____  ",
65         " |  ____|             |  _ \\ / ____|  __ \\ ",
66         " | |___ _ __ ___  ___ | |_) | (___ | |  | |",
67         " |  ___| '__/ _ \\/ _ \\|  _ < \\___ \\| |  | |",
68         " | |   | | |  __/  __/| |_) |____) | |__| |",
69         " | |   | | |    |    ||     |      |      |",
70         " |_|   |_|  \\___|\\___||____/|_____/|_____/ "
71 };
72
73 beastie_color = {
74         "               \027[31m,        ,",
75         "              /(        )`",
76         "              \\ \\___   / |",
77         "              /- \027[37m_\027[31m  `-/  '",
78         "             (\027[37m/\\/ \\\027[31m \\   /\\",
79         "             \027[37m/ /   |\027[31m `    \\",
80         "             \027[34mO O   \027[37m) \027[31m/    |",
81         "             \027[37m`-^--'\027[31m`<     '",
82         "            (_.)  _  )   /",
83         "             `.___/`    /",
84         "               `-----' /",
85         "  \027[33m<----.\027[31m     __ / __   \\",
86         "  \027[33m<----|====\027[31mO)))\027[33m==\027[31m) \\) /\027[33m====|",
87         "  \027[33m<----'\027[31m    `--' `.__,' \\",
88         "               |        |",
89         "                \\       /       /\\",
90         "           \027[36m______\027[31m( (_  / \\______/",
91         "         \027[36m,'  ,-----'   |",
92         "         `--{__________)\027[37m"
93 };
94
95 beastie = {
96         "               ,        ,",
97         "              /(        )`",
98         "              \\ \\___   / |",
99         "              /- _  `-/  '",
100         "             (/\\/ \\ \\   /\\",
101         "             / /   | `    \\",
102         "             O O   ) /    |",
103         "             `-^--'`<     '",
104         "            (_.)  _  )   /",
105         "             `.___/`    /",
106         "               `-----' /",
107         "  <----.     __ / __   \\",
108         "  <----|====O)))==) \\) /====|",
109         "  <----'    `--' `.__,' \\",
110         "               |        |",
111         "                \\       /       /\\",
112         "           ______( (_  / \\______/",
113         "         ,'  ,-----'   |",
114         "         `--{__________)"
115 };
116
117 fbsd_logo_v = {
118         "  ______",
119         " |  ____| __ ___  ___ ",
120         " | |__ | '__/ _ \\/ _ \\",
121         " |  __|| | |  __/  __/",
122         " | |   | | |    |    |",
123         " |_|   |_|  \\___|\\___|",
124         "  ____   _____ _____",
125         " |  _ \\ / ____|  __ \\",
126         " | |_) | (___ | |  | |",
127         " |  _ < \\___ \\| |  | |",
128         " | |_) |____) | |__| |",
129         " |     |      |      |",
130         " |____/|_____/|_____/"
131 };
132
133 orb_color = {
134         "  \027[31m```                        \027[31;1m`\027[31m",
135         " s` `.....---...\027[31;1m....--.```   -/\027[31m",
136         " +o   .--`         \027[31;1m/y:`      +.\027[31m",
137         "  yo`:.            \027[31;1m:o      `+-\027[31m",
138         "   y/               \027[31;1m-/`   -o/\027[31m",
139         "  .-                  \027[31;1m::/sy+:.\027[31m",
140         "  /                     \027[31;1m`--  /\027[31m",
141         " `:                          \027[31;1m:`\027[31m",
142         " `:                          \027[31;1m:`\027[31m",
143         "  /                          \027[31;1m/\027[31m",
144         "  .-                        \027[31;1m-.\027[31m",
145         "   --                      \027[31;1m-.\027[31m",
146         "    `:`                  \027[31;1m`:`",
147         "      \027[31;1m.--             `--.",
148         "         .---.....----.\027[37m"
149 };
150
151 orb = {
152         "  ```                        `",
153         " s` `.....---.......--.```   -/",
154         " +o   .--`         /y:`      +.",
155         "  yo`:.            :o      `+-",
156         "   y/               -/`   -o/",
157         "  .-                  ::/sy+:.",
158         "  /                     `--  /",
159         " `:                          :`",
160         " `:                          :`",
161         "  /                          /",
162         "  .-                        -.",
163         "   --                      -.",
164         "    `:`                  `:`",
165         "      .--             `--.",
166         "         .---.....----."
167 };
168
169 none = {""};
170
171 -- Module exports
172 drawer.menu_name_handlers = {
173         -- Menu name handlers should take the menu being drawn and entry being
174         -- drawn as parameters, and return the name of the item.
175         -- This is designed so that everything, including menu separators, may
176         -- have their names derived differently. The default action for entry
177         -- types not specified here is to call and use entry.name().
178         [core.MENU_CAROUSEL_ENTRY] = function(drawing_menu, entry)
179                 local carid = entry.carousel_id;
180                 local caridx = config.getCarouselIndex(carid);
181                 local choices = entry.items();
182
183                 if (#choices < caridx) then
184                         caridx = 1;
185                 end
186                 return entry.name(caridx, choices[caridx], choices);
187         end,
188 };
189
190 drawer.brand_position = {x = 2, y = 1};
191 drawer.logo_position = {x = 46, y = 1};
192 drawer.menu_position = {x = 6, y = 11};
193 drawer.box_pos_dim = {x = 3, y = 10, w = 41, h = 11};
194
195 drawer.branddefs = {
196         -- Indexed by valid values for loader_brand in loader.conf(5). Valid
197         -- keys are: graphic (table depicting graphic)
198         ["fbsd"] = {
199                 graphic = fbsd_logo,
200         },
201         ["none"] = {
202                 graphic = none,
203         },
204 };
205
206 drawer.logodefs = {
207         -- Indexed by valid values for loader_logo in loader.conf(5). Valid keys
208         -- are: requires_color (boolean), graphic (table depicting graphic), and
209         -- shift (table containing x and y).
210         ["beastie"] = {
211                 requires_color = true,
212                 graphic = beastie_color,
213         },
214         ["beastiebw"] = {
215                 graphic = beastie,
216         },
217         ["fbsdbw"] = {
218                 graphic = fbsd_logo_v,
219                 shift = {x = 5, y = 4},
220         },
221         ["orb"] = {
222                 requires_color = true,
223                 graphic = orb_color,
224                 shift = {x = 2, y = 4},
225         },
226         ["orbbw"] = {
227                 graphic = orb,
228                 shift = {x = 2, y = 4},
229         },
230         ["tribute"] = {
231                 graphic = fbsd_logo,
232         },
233         ["tributebw"] = {
234                 graphic = fbsd_logo,
235         },
236         ["none"] = {
237                 graphic = none,
238                 shift = {x = 17, y = 0},
239         },
240 };
241
242 function drawer.drawscreen(menu_opts)
243         -- drawlogo() must go first.
244         -- it determines the positions of other elements
245         drawer.drawlogo();
246         drawer.drawbrand();
247         drawer.drawbox();
248         return drawer.drawmenu(menu_opts);
249 end
250
251 function drawer.drawmenu(m)
252         x = drawer.menu_position.x;
253         y = drawer.menu_position.y;
254
255         -- print the menu and build the alias table
256         local alias_table = {};
257         local entry_num = 0;
258         local menu_entries = m.entries;
259         if (type(menu_entries) == "function") then
260                 menu_entries = menu_entries();
261         end
262         for line_num, e in ipairs(menu_entries) do
263                 -- Allow menu items to be conditionally visible by specifying
264                 -- a visible function.
265                 if (e.visible ~= nil) and (not e.visible()) then
266                         goto continue;
267                 end
268                 if (e.entry_type ~= core.MENU_SEPARATOR) then
269                         entry_num = entry_num + 1;
270                         screen.setcursor(x, y + line_num);
271
272                         print(entry_num .. ". " .. menu_entry_name(m, e));
273
274                         -- fill the alias table
275                         alias_table[tostring(entry_num)] = e;
276                         if (e.alias ~= nil) then
277                                 for n, a in ipairs(e.alias) do
278                                         alias_table[a] = e;
279                                 end
280                         end
281                 else
282                         screen.setcursor(x, y + line_num);
283                         print(menu_entry_name(m, e));
284                 end
285                 ::continue::
286         end
287         return alias_table;
288 end
289
290
291 function drawer.drawbox()
292         x = drawer.box_pos_dim.x;
293         y = drawer.box_pos_dim.y;
294         w = drawer.box_pos_dim.w;
295         h = drawer.box_pos_dim.h;
296
297         local hl = string.char(0xCD);
298         local vl = string.char(0xBA);
299
300         local tl = string.char(0xC9);
301         local bl = string.char(0xC8);
302         local tr = string.char(0xBB);
303         local br = string.char(0xBC);
304
305         screen.setcursor(x, y); print(tl);
306         screen.setcursor(x, y+h); print(bl);
307         screen.setcursor(x+w, y); print(tr);
308         screen.setcursor(x+w, y+h); print(br);
309
310         for i = 1, w-1 do
311                 screen.setcursor(x+i, y);
312                 print(hl);
313                 screen.setcursor(x+i, y+h);
314                 print(hl);
315         end
316
317         for i = 1, h-1 do
318                 screen.setcursor(x, y+i);
319                 print(vl);
320                 screen.setcursor(x+w, y+i);
321                 print(vl);
322         end
323
324         screen.setcursor(x+(w/2)-9, y);
325         print("Welcome to FreeBSD");
326 end
327
328 function drawer.draw(x, y, logo)
329         for i = 1, #logo do
330                 screen.setcursor(x, y + i);
331                 print(logo[i]);
332         end
333 end
334
335 function drawer.drawbrand()
336         local x = tonumber(loader.getenv("loader_brand_x")) or
337             drawer.brand_position.x;
338         local y = tonumber(loader.getenv("loader_brand_y")) or
339             drawer.brand_position.y;
340
341         local graphic = drawer.branddefs[loader.getenv("loader_brand")];
342         if (graphic == nil) then
343                 graphic = fbsd_logo;
344         end
345         drawer.draw(x, y, graphic);
346 end
347
348 function drawer.drawlogo()
349         local x = tonumber(loader.getenv("loader_logo_x")) or
350             drawer.logo_position.x;
351         local y = tonumber(loader.getenv("loader_logo_y")) or
352             drawer.logo_position.y;
353
354         local logo = loader.getenv("loader_logo");
355         local colored = color.isEnabled();
356
357         -- Lookup
358         local logodef = drawer.logodefs[logo];
359
360         if (logodef ~= nil) and (logodef.graphic == none) then
361                 -- centre brand and text if no logo
362                 if (not none_shifted) then
363                         shift_brand_text(logodef.shift);
364                         none_shifted = true;
365                 end
366         elseif (logodef == nil) or (logodef.graphic == nil) or
367             ((not colored) and logodef.requires_color) then
368                 -- Choose a sensible default
369                 if (colored) then
370                         logodef = drawer.logodefs["orb"];
371                 else
372                         logodef = drawer.logodefs["orbbw"];
373                 end
374         end
375         if (logodef.shift ~= nil) then
376                 x = x + logodef.shift.x;
377                 y = y + logodef.shift.y;
378         end
379         drawer.draw(x, y, logodef.graphic);
380 end
381
382 return drawer;