1 /* -*-C++-*- $NetBSD: menu.cpp,v 1.5 2002/03/25 17:23:19 uch Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <hpcmenu.h> 40 #include <hpcboot.h> 41 #include <res/resource.h> 42 #include <menu/window.h> 43 #include <menu/tabwindow.h> 44 #include <menu/rootwindow.h> 45 #include <machine/bootinfo.h> 46 #include <framebuffer.h> 47 #include <console.h> 48 49 #include <menu/menu.h> 50 51 TabWindow * 52 TabWindowBase::boot(int id) 53 { 54 TabWindow *w = NULL; 55 HpcMenuInterface &menu = HPC_MENU; 56 57 switch(id) { 58 default: 59 break; 60 case IDC_BASE_MAIN: 61 menu._main = new MainTabWindow(*this, IDC_BASE_MAIN); 62 w = menu._main; 63 break; 64 case IDC_BASE_OPTION: 65 menu._option = new OptionTabWindow(*this, IDC_BASE_OPTION); 66 w = menu._option; 67 break; 68 case IDC_BASE_CONSOLE: 69 menu._console = new ConsoleTabWindow(*this, IDC_BASE_CONSOLE); 70 w = menu._console; 71 break; 72 } 73 74 if (w) 75 w->create(0); 76 77 return w; 78 } 79 80 // 81 // Main window 82 // 83 void 84 MainTabWindow::_insert_item(HWND w, TCHAR *name, int id) 85 { 86 int idx = SendDlgItemMessage(w, id, CB_ADDSTRING, 0, 87 reinterpret_cast <LPARAM>(name)); 88 if (idx != CB_ERR) 89 SendDlgItemMessage(w, IDC_MAIN_DIR, CB_SETITEMDATA, 90 idx, _item_idx++); 91 } 92 93 void 94 MainTabWindow::init(HWND w) 95 { 96 HpcMenuInterface &menu = HPC_MENU; 97 struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE; 98 99 _window = w; 100 // insert myself to tab-control 101 TabWindow::init(w); 102 103 // setup child. 104 TCHAR *entry; 105 int i; 106 // kernel directory path 107 for (i = 0; entry = menu.dir(i); i++) 108 _insert_item(w, entry, IDC_MAIN_DIR); 109 SendDlgItemMessage(w, IDC_MAIN_DIR, CB_SETCURSEL, menu.dir_default(), 110 0); 111 // platform 112 for (i = 0; entry = menu.platform_get(i); i++) 113 _insert_item(w, entry, IDC_MAIN_PLATFORM); 114 SendDlgItemMessage(w, IDC_MAIN_PLATFORM, CB_SETCURSEL, 115 menu.platform_default(), 0); 116 // kernel file name. 117 Edit_SetText(GetDlgItem(w, IDC_MAIN_KERNEL), pref.kernel_user ? 118 pref.kernel_user_file : TEXT("netbsd.gz")); 119 120 // root file system. 121 int fs = pref.rootfs + IDC_MAIN_ROOT_; 122 _set_check(fs, TRUE); 123 124 _edit_md_root = GetDlgItem(w, IDC_MAIN_ROOT_MD_OPS); 125 Edit_SetText(_edit_md_root, pref.rootfs_file); 126 EnableWindow(_edit_md_root, fs == IDC_MAIN_ROOT_MD ? TRUE : FALSE); 127 128 // layout checkbox and editbox. 129 layout(); 130 131 // set default kernel boot options. 132 _set_check(IDC_MAIN_OPTION_A, pref.boot_ask_for_name); 133 _set_check(IDC_MAIN_OPTION_D, pref.boot_debugger); 134 _set_check(IDC_MAIN_OPTION_S, pref.boot_single_user); 135 _set_check(IDC_MAIN_OPTION_V, pref.boot_verbose); 136 _set_check(IDC_MAIN_OPTION_H, pref.boot_serial); 137 138 // serial console speed. 139 TCHAR *speed_tab[] = { L"9600", L"19200", L"115200", 0 }; 140 int sel = 0; 141 i = 0; 142 for (TCHAR **speed = speed_tab; *speed; speed++, i++) { 143 _insert_item(w, *speed, IDC_MAIN_OPTION_H_SPEED); 144 if (_wtoi(*speed) == pref.serial_speed) 145 sel = i; 146 } 147 _combobox_serial_speed = GetDlgItem(_window, IDC_MAIN_OPTION_H_SPEED); 148 SendDlgItemMessage(w, IDC_MAIN_OPTION_H_SPEED, CB_SETCURSEL, sel, 0); 149 EnableWindow(_combobox_serial_speed, pref.boot_serial); 150 } 151 152 void 153 MainTabWindow::layout() 154 { 155 // inquire display size. 156 HDC hdc = GetDC(0); 157 int width = GetDeviceCaps(hdc, HORZRES); 158 int height = GetDeviceCaps(hdc, VERTRES); 159 ReleaseDC(0, hdc); 160 161 // set origin 162 int x, y; 163 if (width <= 320) { 164 x = 5, y = 125; 165 } else if (height <= 240) { 166 x = 250, y = 5; 167 } else { 168 x = 5, y = 125; 169 } 170 171 HWND h; 172 h = GetDlgItem(_window, IDC_MAIN_OPTION_V); 173 SetWindowPos(h, HWND_TOP, x, y, 120, 10, TRUE); 174 h = GetDlgItem(_window, IDC_MAIN_OPTION_S); 175 SetWindowPos(h, HWND_TOP, x, y + 20, 120, 10, TRUE); 176 h = GetDlgItem(_window, IDC_MAIN_OPTION_A); 177 SetWindowPos(h, HWND_TOP, x, y + 40, 120, 10, TRUE); 178 h = GetDlgItem(_window, IDC_MAIN_OPTION_D); 179 SetWindowPos(h, HWND_TOP, x, y + 60, 120, 10, TRUE); 180 h = GetDlgItem(_window, IDC_MAIN_OPTION_H); 181 SetWindowPos(h, HWND_TOP, x, y + 80, 120, 10, TRUE); 182 h = GetDlgItem(_window, IDC_MAIN_OPTION_H_SPEED); 183 SetWindowPos(h, HWND_TOP, x + 100, y + 80, 120, 10, TRUE); 184 } 185 186 void 187 MainTabWindow::get() 188 { 189 HpcMenuInterface &menu = HPC_MENU; 190 struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE; 191 192 HWND w = GetDlgItem(_window, IDC_MAIN_DIR); 193 ComboBox_GetText(w, pref.dir_user_path, MAX_PATH); 194 pref.dir_user = TRUE; 195 w = GetDlgItem(_window, IDC_MAIN_KERNEL); 196 Edit_GetText(w, pref.kernel_user_file, MAX_PATH); 197 pref.kernel_user = TRUE; 198 199 int i = ComboBox_GetCurSel(GetDlgItem(_window, IDC_MAIN_PLATFORM)); 200 menu.platform_set(i); 201 202 if (_is_checked(IDC_MAIN_ROOT_WD)) 203 pref.rootfs = 0; 204 else if (_is_checked(IDC_MAIN_ROOT_SD)) 205 pref.rootfs = 1; 206 else if (_is_checked(IDC_MAIN_ROOT_MD)) 207 pref.rootfs = 2; 208 else if (_is_checked(IDC_MAIN_ROOT_NFS)) 209 pref.rootfs = 3; 210 211 pref.boot_ask_for_name = _is_checked(IDC_MAIN_OPTION_A); 212 pref.boot_debugger = _is_checked(IDC_MAIN_OPTION_D); 213 pref.boot_verbose = _is_checked(IDC_MAIN_OPTION_V); 214 pref.boot_single_user = _is_checked(IDC_MAIN_OPTION_S); 215 pref.boot_serial = _is_checked(IDC_MAIN_OPTION_H); 216 Edit_GetText(_edit_md_root, pref.rootfs_file, MAX_PATH); 217 218 TCHAR tmpbuf[8]; 219 ComboBox_GetText(_combobox_serial_speed, tmpbuf, 8); 220 pref.serial_speed = _wtoi(tmpbuf); 221 } 222 223 void 224 MainTabWindow::command(int id, int msg) 225 { 226 switch (id) { 227 case IDC_MAIN_OPTION_H: 228 EnableWindow(_combobox_serial_speed, 229 _is_checked(IDC_MAIN_OPTION_H)); 230 break; 231 case IDC_MAIN_ROOT_WD: 232 /* FALLTHROUGH */ 233 case IDC_MAIN_ROOT_SD: 234 /* FALLTHROUGH */ 235 case IDC_MAIN_ROOT_MD: 236 /* FALLTHROUGH */ 237 case IDC_MAIN_ROOT_NFS: 238 EnableWindow(_edit_md_root, _is_checked(IDC_MAIN_ROOT_MD)); 239 } 240 } 241 242 // 243 // Option window 244 // 245 void 246 OptionTabWindow::init(HWND w) 247 { 248 struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE; 249 250 _window = w; 251 252 TabWindow::init(_window); 253 _spin_edit = GetDlgItem(_window, IDC_OPT_AUTO_INPUT); 254 _spin = CreateUpDownControl(WS_CHILD | WS_BORDER | WS_VISIBLE | 255 UDS_SETBUDDYINT | UDS_ALIGNRIGHT, 80, 0, 50, 50, _window, 256 IDC_OPT_AUTO_UPDOWN, _app._instance, _spin_edit, 60, 1, 30); 257 BOOL onoff = pref.auto_boot ? TRUE : FALSE; 258 EnableWindow(_spin_edit, onoff); 259 EnableWindow(_spin, onoff); 260 261 SET_CHECK(AUTO, pref.auto_boot); 262 if (pref.auto_boot) { 263 TCHAR tmp[32]; 264 wsprintf(tmp, TEXT("%d"), pref.auto_boot); 265 Edit_SetText(_spin_edit, tmp); 266 } 267 SET_CHECK(VIDEO, pref.reverse_video); 268 SET_CHECK(PAUSE, pref.pause_before_boot); 269 SET_CHECK(DEBUG, pref.load_debug_info); 270 SET_CHECK(SAFETY, pref.safety_message); 271 Edit_SetText(GetDlgItem(w, IDC_OPT_EXTKOPT), pref.boot_extra); 272 } 273 274 void 275 OptionTabWindow::command(int id, int msg) 276 { 277 switch (id) { 278 case IDC_OPT_AUTO: 279 if (IS_CHECKED(AUTO)) { 280 EnableWindow(_spin_edit, TRUE); 281 EnableWindow(_spin, TRUE); 282 } else { 283 EnableWindow(_spin_edit, FALSE); 284 EnableWindow(_spin, FALSE); 285 } 286 break; 287 } 288 } 289 290 void 291 OptionTabWindow::get() 292 { 293 HWND w; 294 struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE; 295 if (IS_CHECKED(AUTO)) { 296 TCHAR tmp[32]; 297 Edit_GetText(_spin_edit, tmp, 32); 298 pref.auto_boot = _wtoi(tmp); 299 } else 300 pref.auto_boot = 0; 301 pref.reverse_video = IS_CHECKED(VIDEO); 302 pref.pause_before_boot = IS_CHECKED(PAUSE); 303 pref.load_debug_info = IS_CHECKED(DEBUG); 304 pref.safety_message = IS_CHECKED(SAFETY); 305 306 w = GetDlgItem(_window, IDC_OPT_EXTKOPT); 307 Edit_GetText(w, pref.boot_extra, MAX_BOOT_STR); 308 } 309 #undef IS_CHECKED 310 #undef SET_CHECK 311 312 313 // 314 // Console window 315 // 316 void 317 ConsoleTabWindow::print(TCHAR *buf, BOOL force_display) 318 { 319 int cr; 320 TCHAR *p; 321 322 if (force_display) 323 goto display; 324 325 if (_filesave) { 326 if (_logfile == INVALID_HANDLE_VALUE && !_open_log_file()) { 327 _filesave = FALSE; 328 _set_check(IDC_CONS_FILESAVE, _filesave); 329 EnableWindow(_filename_edit, _filesave); 330 goto display; 331 } 332 DWORD cnt; 333 char c; 334 for (int i = 0; *buf != TEXT('\0'); buf++) { 335 c = *buf & 0x7f; 336 WriteFile(_logfile, &c, 1, &cnt, 0); 337 } 338 FlushFileBuffers(_logfile); 339 return; 340 } 341 342 display: 343 // count # of '\n' 344 for (cr = 0, p = buf; p = wcschr(p, TEXT('\n')); cr++, p++) 345 ; 346 // total length of new buffer('\n' -> "\r\n" + '\0') 347 int ln = wcslen(buf) + cr + 1; 348 349 // get old buffer. 350 int lo = Edit_GetTextLength(_edit); 351 size_t sz =(lo + ln) * sizeof(TCHAR); 352 353 p = reinterpret_cast <TCHAR *>(malloc(sz)); 354 if (p == NULL) 355 return; 356 357 memset(p, 0, sz); 358 Edit_GetText(_edit, p, lo + 1); 359 360 // put new buffer to end of old buffer. 361 TCHAR *d = p + lo; 362 while (*buf != TEXT('\0')) { 363 TCHAR c = *buf++; 364 if (c == TEXT('\n')) 365 *d++ = TEXT('\r'); 366 *d++ = c; 367 } 368 *d = TEXT('\0'); 369 370 // display total buffer. 371 Edit_SetText(_edit, p); 372 // Edit_Scroll(_edit, Edit_GetLineCount(_edit), 0); 373 UpdateWindow(_edit); 374 375 free(p); 376 } 377 378 void 379 ConsoleTabWindow::init(HWND w) 380 { 381 // at this time _window is NULL. 382 // use argument of window procedure. 383 TabWindow::init(w); 384 _edit = GetDlgItem(w, IDC_CONS_EDIT); 385 MoveWindow(_edit, 5, 60, _rect.right - _rect.left - 10, 386 _rect.bottom - _rect.top - 60, TRUE); 387 Edit_FmtLines(_edit, TRUE); 388 389 // log file. 390 _filename_edit = GetDlgItem(w, IDC_CONS_FILENAME); 391 _filesave = FALSE; 392 Edit_SetText(_filename_edit, L"bootlog.txt"); 393 EnableWindow(_filename_edit, _filesave); 394 } 395 396 void 397 ConsoleTabWindow::command(int id, int msg) 398 { 399 HpcMenuInterface &menu = HPC_MENU; 400 struct HpcMenuInterface::cons_hook_args *hook = 0; 401 int bit; 402 403 switch(id) { 404 case IDC_CONS_FILESAVE: 405 _filesave = _is_checked(IDC_CONS_FILESAVE); 406 EnableWindow(_filename_edit, _filesave); 407 break; 408 case IDC_CONS_CHK0: 409 /* FALLTHROUGH */ 410 case IDC_CONS_CHK1: 411 /* FALLTHROUGH */ 412 case IDC_CONS_CHK2: 413 /* FALLTHROUGH */ 414 case IDC_CONS_CHK3: 415 /* FALLTHROUGH */ 416 case IDC_CONS_CHK4: 417 /* FALLTHROUGH */ 418 case IDC_CONS_CHK5: 419 /* FALLTHROUGH */ 420 case IDC_CONS_CHK6: 421 /* FALLTHROUGH */ 422 case IDC_CONS_CHK7: 423 bit = 1 << (id - IDC_CONS_CHK_); 424 if (SendDlgItemMessage(_window, id, BM_GETCHECK, 0, 0)) 425 menu._cons_parameter |= bit; 426 else 427 menu._cons_parameter &= ~bit; 428 break; 429 case IDC_CONS_BTN0: 430 /* FALLTHROUGH */ 431 case IDC_CONS_BTN1: 432 /* FALLTHROUGH */ 433 case IDC_CONS_BTN2: 434 /* FALLTHROUGH */ 435 case IDC_CONS_BTN3: 436 hook = &menu._cons_hook[id - IDC_CONS_BTN_]; 437 if (hook->func) 438 hook->func(hook->arg, menu._cons_parameter); 439 440 break; 441 } 442 } 443 444 BOOL 445 ConsoleTabWindow::_open_log_file() 446 { 447 TCHAR path[MAX_PATH]; 448 TCHAR filename[MAX_PATH]; 449 TCHAR filepath[MAX_PATH]; 450 451 if (!_find_pref_dir(path)) { 452 print(L"couldn't find temporary directory.\n", TRUE); 453 return FALSE; 454 } 455 456 Edit_GetText(_filename_edit, filename, MAX_PATH); 457 wsprintf(filepath, TEXT("\\%s\\%s"), path, filename); 458 _logfile = CreateFile(filepath, GENERIC_WRITE, 0, 0, 459 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 460 if (_logfile == INVALID_HANDLE_VALUE) 461 return FALSE; 462 463 wsprintf(path, TEXT("log file is %s\n"), filepath); 464 print(path, TRUE); 465 466 return TRUE; 467 } 468 469 // 470 // Common utility 471 // 472 BOOL 473 _find_pref_dir(TCHAR *path) 474 { 475 WIN32_FIND_DATA fd; 476 HANDLE find; 477 478 lstrcpy(path, TEXT("\\*.*")); 479 find = FindFirstFile(path, &fd); 480 481 if (find != INVALID_HANDLE_VALUE) { 482 do { 483 int attr = fd.dwFileAttributes; 484 if ((attr & FILE_ATTRIBUTE_DIRECTORY) && 485 (attr & FILE_ATTRIBUTE_TEMPORARY)) { 486 wcscpy(path, fd.cFileName); 487 FindClose(find); 488 return TRUE; 489 } 490 } while (FindNextFile(find, &fd)); 491 } 492 FindClose(find); 493 494 return FALSE; 495 } 496