1/*
2 * Copyright 2004-2012, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "RootFileSystem.h"
8
9#include <boot/platform.h>
10#include <boot/vfs.h>
11#include <boot/menu.h>
12
13#include <fcntl.h>
14#include <stdio.h>
15#include <stdlib.h>
16
17
18const char *kNormalColor = "\33[0m";
19const char *kDisabledColor = "\33[31m";	// red
20const char *kTitleColor = "\33[34m";	// blue
21
22
23extern RootFileSystem *gRoot;
24bool gShowMenu = false;
25
26
27static void
28print_item_at(int32 line, MenuItem *item, bool clearHelp = true)
29{
30	if (!item->IsEnabled())
31		printf("%s    ", kDisabledColor);
32	else
33		printf("%2ld. ", line);
34
35	if (item->Type() == MENU_ITEM_MARKABLE) {
36		printf(" [");
37		printf("%c", item->IsMarked() ? 'x' : ' ');
38		printf("] ");
39	} else
40		printf(" ");
41
42	printf(item->Label());
43
44	if (item->Submenu() && item->Submenu()->Type() == CHOICE_MENU) {
45		// show the current choice (if any)
46		Menu *subMenu = item->Submenu();
47		MenuItem *subItem = NULL;
48
49		for (int32 i = subMenu->CountItems(); i-- > 0; ) {
50			subItem = subMenu->ItemAt(i);
51			if (subItem != NULL && subItem->IsMarked())
52				break;
53		}
54
55		printf(" (Current: ");
56		printf(subItem != NULL ? subItem->Label() : "None");
57		putchar(')');
58	}
59
60	if (!item->IsEnabled())
61		printf(kNormalColor);
62	putchar('\n');
63}
64
65
66static void
67draw_menu(Menu *menu)
68{
69	printf("\n %s--- ", kTitleColor);
70	if (menu->Title())
71		printf("%s", menu->Title());
72	else
73		printf("Welcome To The Haiku Bootloader");
74	printf(" ---%s\n\n", kNormalColor);
75
76	MenuItemIterator iterator = menu->ItemIterator();
77	MenuItem *item;
78	int32 i = 0;
79
80	while ((item = iterator.Next()) != NULL) {
81		if (item->Type() == MENU_ITEM_SEPARATOR) {
82			putchar('\n');
83			i++;
84			continue;
85		}
86
87		print_item_at(i++, item, false);
88	}
89
90	int32 selected = -1;
91	menu->FindSelected(&selected);
92	printf("\n[%ld]? ", selected);
93}
94
95
96bool
97dump_devices_hook(Menu *menu, MenuItem *item)
98{
99	puts("List of known root directories:");
100
101	void *cookie;
102	if (gRoot->Open(&cookie, O_RDONLY) == B_OK) {
103		Directory *directory;
104		while (gRoot->GetNextNode(cookie, (Node **)&directory) == B_OK) {
105			char name[256];
106			if (directory->GetName(name, sizeof(name)) == B_OK)
107				printf("%s:: %s (%p)%s\n", kTitleColor, name, directory, kNormalColor);
108
109			void *subCookie;
110			if (directory->Open(&subCookie, O_RDONLY) == B_OK) {
111				while (directory->GetNextEntry(subCookie, name, sizeof(name)) == B_OK) {
112					printf("\t%s\n", name);
113				}
114				directory->Close(subCookie);
115			}
116		}
117		gRoot->Close(cookie);
118	}
119
120	return false;
121}
122
123
124//	#pragma mark -
125
126
127void
128platform_add_menus(Menu *menu)
129{
130	MenuItem *item;
131
132	switch (menu->Type()) {
133		case MAIN_MENU:
134			menu->AddItem(item = new MenuItem("Dump all recognized volumes"));
135			item->SetTarget(dump_devices_hook);
136			break;
137		default:
138			break;
139	}
140}
141
142
143void
144platform_update_menu_item(Menu *menu, MenuItem *item)
145{
146}
147
148
149void
150platform_run_menu(Menu *menu)
151{
152	// Get selected entry, or select the last one, if there is none
153	int32 selected;
154	MenuItem *item = menu->FindSelected(&selected);
155	if (item == NULL) {
156		selected = menu->CountItems() - 1;
157		item = menu->ItemAt(selected);
158		if (item != NULL)
159			item->Select(true);
160	}
161
162	while (true) {
163		draw_menu(menu);
164
165		char buffer[32];
166		if (fgets(buffer, sizeof(buffer), stdin) == NULL)
167			return;
168
169		if (buffer[0] != '\n')
170			selected = atoi(buffer);
171
172		item = menu->ItemAt(selected);
173		if (item == NULL) {
174			printf("Invalid choice.");
175			continue;
176		}
177
178		item->Select(true);
179
180		// leave the menu
181		if (item->Submenu() != NULL) {
182			menu->Hide();
183
184			platform_run_menu(item->Submenu());
185			if (item->Target() != NULL)
186				(*item->Target())(menu, item);
187
188			// restore current menu
189			menu->FindSelected(&selected);
190			menu->Show();
191		} else if (item->Type() == MENU_ITEM_MARKABLE) {
192			// toggle state
193			item->SetMarked(!item->IsMarked());
194
195			if (item->Target() != NULL)
196				(*item->Target())(menu, item);
197		} else if (item->Target() == NULL || (*item->Target())(menu, item))
198			break;
199	}
200}
201
202
203size_t
204platform_get_user_input_text(Menu* menu, MenuItem* item, char* buffer,
205	size_t bufferSize)
206{
207	return 0;
208}
209