1 /* -*-C++-*- $NetBSD: menu.cpp,v 1.4 2001/05/21 15:55:04 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 } 272 273 void 274 OptionTabWindow::command(int id, int msg) 275 { 276 switch (id) { 277 case IDC_OPT_AUTO: 278 if (IS_CHECKED(AUTO)) { 279 EnableWindow(_spin_edit, TRUE); 280 EnableWindow(_spin, TRUE); 281 } else { 282 EnableWindow(_spin_edit, FALSE); 283 EnableWindow(_spin, FALSE); 284 } 285 break; 286 } 287 } 288 289 void 290 OptionTabWindow::get() 291 { 292 struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE; 293 if (IS_CHECKED(AUTO)) { 294 TCHAR tmp[32]; 295 Edit_GetText(_spin_edit, tmp, 32); 296 pref.auto_boot = _wtoi(tmp); 297 } else 298 pref.auto_boot = 0; 299 pref.reverse_video = IS_CHECKED(VIDEO); 300 pref.pause_before_boot = IS_CHECKED(PAUSE); 301 pref.load_debug_info = IS_CHECKED(DEBUG); 302 pref.safety_message = IS_CHECKED(SAFETY); 303 } 304 #undef IS_CHECKED 305 #undef SET_CHECK 306 307 308 // 309 // Console window 310 // 311 void 312 ConsoleTabWindow::print(TCHAR *buf, BOOL force_display) 313 { 314 int cr; 315 TCHAR *p; 316 317 if (force_display) 318 goto display; 319 320 if (_filesave) { 321 if (_logfile == INVALID_HANDLE_VALUE && !_open_log_file()) { 322 _filesave = FALSE; 323 _set_check(IDC_CONS_FILESAVE, _filesave); 324 EnableWindow(_filename_edit, _filesave); 325 goto display; 326 } 327 DWORD cnt; 328 char c; 329 for (int i = 0; *buf != TEXT('\0'); buf++) { 330 c = *buf & 0x7f; 331 WriteFile(_logfile, &c, 1, &cnt, 0); 332 } 333 FlushFileBuffers(_logfile); 334 return; 335 } 336 337 display: 338 // count # of '\n' 339 for (cr = 0, p = buf; p = wcschr(p, TEXT('\n')); cr++, p++) 340 ; 341 // total length of new buffer('\n' -> "\r\n" + '\0') 342 int ln = wcslen(buf) + cr + 1; 343 344 // get old buffer. 345 int lo = Edit_GetTextLength(_edit); 346 size_t sz =(lo + ln) * sizeof(TCHAR); 347 348 p = reinterpret_cast <TCHAR *>(malloc(sz)); 349 if (p == NULL) 350 return; 351 352 memset(p, 0, sz); 353 Edit_GetText(_edit, p, lo + 1); 354 355 // put new buffer to end of old buffer. 356 TCHAR *d = p + lo; 357 while (*buf != TEXT('\0')) { 358 TCHAR c = *buf++; 359 if (c == TEXT('\n')) 360 *d++ = TEXT('\r'); 361 *d++ = c; 362 } 363 *d = TEXT('\0'); 364 365 // display total buffer. 366 Edit_SetText(_edit, p); 367 // Edit_Scroll(_edit, Edit_GetLineCount(_edit), 0); 368 UpdateWindow(_edit); 369 370 free(p); 371 } 372 373 void 374 ConsoleTabWindow::init(HWND w) 375 { 376 // at this time _window is NULL. 377 // use argument of window procedure. 378 TabWindow::init(w); 379 _edit = GetDlgItem(w, IDC_CONS_EDIT); 380 MoveWindow(_edit, 5, 60, _rect.right - _rect.left - 10, 381 _rect.bottom - _rect.top - 60, TRUE); 382 Edit_FmtLines(_edit, TRUE); 383 384 // log file. 385 _filename_edit = GetDlgItem(w, IDC_CONS_FILENAME); 386 _filesave = FALSE; 387 Edit_SetText(_filename_edit, L"bootlog.txt"); 388 EnableWindow(_filename_edit, _filesave); 389 } 390 391 void 392 ConsoleTabWindow::command(int id, int msg) 393 { 394 HpcMenuInterface &menu = HPC_MENU; 395 struct HpcMenuInterface::cons_hook_args *hook = 0; 396 int bit; 397 398 switch(id) { 399 case IDC_CONS_FILESAVE: 400 _filesave = _is_checked(IDC_CONS_FILESAVE); 401 EnableWindow(_filename_edit, _filesave); 402 break; 403 case IDC_CONS_CHK0: 404 /* FALLTHROUGH */ 405 case IDC_CONS_CHK1: 406 /* FALLTHROUGH */ 407 case IDC_CONS_CHK2: 408 /* FALLTHROUGH */ 409 case IDC_CONS_CHK3: 410 /* FALLTHROUGH */ 411 case IDC_CONS_CHK4: 412 /* FALLTHROUGH */ 413 case IDC_CONS_CHK5: 414 /* FALLTHROUGH */ 415 case IDC_CONS_CHK6: 416 /* FALLTHROUGH */ 417 case IDC_CONS_CHK7: 418 bit = 1 << (id - IDC_CONS_CHK_); 419 if (SendDlgItemMessage(_window, id, BM_GETCHECK, 0, 0)) 420 menu._cons_parameter |= bit; 421 else 422 menu._cons_parameter &= ~bit; 423 break; 424 case IDC_CONS_BTN0: 425 /* FALLTHROUGH */ 426 case IDC_CONS_BTN1: 427 /* FALLTHROUGH */ 428 case IDC_CONS_BTN2: 429 /* FALLTHROUGH */ 430 case IDC_CONS_BTN3: 431 hook = &menu._cons_hook[id - IDC_CONS_BTN_]; 432 if (hook->func) 433 hook->func(hook->arg, menu._cons_parameter); 434 435 break; 436 } 437 } 438 439 BOOL 440 ConsoleTabWindow::_open_log_file() 441 { 442 TCHAR path[MAX_PATH]; 443 TCHAR filename[MAX_PATH]; 444 TCHAR filepath[MAX_PATH]; 445 446 if (!_find_pref_dir(path)) { 447 print(L"couldn't find temporary directory.\n", TRUE); 448 return FALSE; 449 } 450 451 Edit_GetText(_filename_edit, filename, MAX_PATH); 452 wsprintf(filepath, TEXT("\\%s\\%s"), path, filename); 453 _logfile = CreateFile(filepath, GENERIC_WRITE, 0, 0, 454 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 455 if (_logfile == INVALID_HANDLE_VALUE) 456 return FALSE; 457 458 wsprintf(path, TEXT("log file is %s\n"), filepath); 459 print(path, TRUE); 460 461 return TRUE; 462 } 463 464 // 465 // Common utility 466 // 467 BOOL 468 _find_pref_dir(TCHAR *path) 469 { 470 WIN32_FIND_DATA fd; 471 HANDLE find; 472 473 lstrcpy(path, TEXT("\\*.*")); 474 find = FindFirstFile(path, &fd); 475 476 if (find != INVALID_HANDLE_VALUE) { 477 do { 478 int attr = fd.dwFileAttributes; 479 if ((attr & FILE_ATTRIBUTE_DIRECTORY) && 480 (attr & FILE_ATTRIBUTE_TEMPORARY)) { 481 wcscpy(path, fd.cFileName); 482 FindClose(find); 483 return TRUE; 484 } 485 } while (FindNextFile(find, &fd)); 486 } 487 FindClose(find); 488 489 return FALSE; 490 } 491