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 18 const char *kNormalColor = "\33[0m"; 19 const char *kDisabledColor = "\33[31m"; // red 20 const char *kTitleColor = "\33[34m"; // blue 21 22 23 extern RootFileSystem *gRoot; 24 bool gShowMenu = false; 25 26 27 static void 28 print_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 66 static void 67 draw_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 96 bool 97 dump_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 127 void 128 platform_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 143 void 144 platform_update_menu_item(Menu *menu, MenuItem *item) 145 { 146 } 147 148 149 void 150 platform_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 203 size_t 204 platform_get_user_input_text(Menu* menu, MenuItem* item, char* buffer, 205 size_t bufferSize) 206 { 207 return 0; 208 } 209