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