No empty .Rs/.Re
[netbsd-mini2440.git] / sys / arch / hpc / stand / hpcboot / menu / menu.cpp
blobf70d0e1f75ff98542191cbd18683162d201db626
1 /* -*-C++-*- $NetBSD: menu.cpp,v 1.10 2005/12/11 12:17:28 christos Exp $ */
3 /*-
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by UCHIYAMA Yasushi.
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <hpcmenu.h>
33 #include <hpcboot.h>
34 #include <res/resource.h>
35 #include <menu/window.h>
36 #include <menu/tabwindow.h>
37 #include <menu/rootwindow.h>
38 #include <machine/bootinfo.h>
39 #include <framebuffer.h>
40 #include <console.h>
42 #include <menu/menu.h>
44 TabWindow *
45 TabWindowBase::boot(int id)
47 TabWindow *w = NULL;
48 HpcMenuInterface &menu = HPC_MENU;
50 switch(id) {
51 default:
52 break;
53 case IDC_BASE_MAIN:
54 menu._main = new MainTabWindow(*this, IDC_BASE_MAIN);
55 w = menu._main;
56 break;
57 case IDC_BASE_OPTION:
58 menu._option = new OptionTabWindow(*this, IDC_BASE_OPTION);
59 w = menu._option;
60 break;
61 case IDC_BASE_CONSOLE:
62 menu._console = new ConsoleTabWindow(*this, IDC_BASE_CONSOLE);
63 w = menu._console;
64 break;
67 if (w)
68 w->create(0);
70 return w;
74 // Main window
76 void
77 MainTabWindow::_insert_item(HWND w, TCHAR *name, int id)
79 int idx = SendDlgItemMessage(w, id, CB_ADDSTRING, 0,
80 reinterpret_cast <LPARAM>(name));
81 if (idx != CB_ERR)
82 SendDlgItemMessage(w, IDC_MAIN_DIR, CB_SETITEMDATA,
83 idx, _item_idx++);
86 void
87 MainTabWindow::init(HWND w)
89 HpcMenuInterface &menu = HPC_MENU;
90 struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE;
92 _window = w;
93 // insert myself to tab-control
94 TabWindow::init(w);
96 // setup child.
97 TCHAR *entry;
98 int i;
99 // kernel directory path
100 for (i = 0; entry = menu.dir(i); i++)
101 _insert_item(w, entry, IDC_MAIN_DIR);
102 SendDlgItemMessage(w, IDC_MAIN_DIR, CB_SETCURSEL, menu.dir_default(),
104 // platform
105 _sort_platids(w);
106 // kernel file name.
107 Edit_SetText(GetDlgItem(w, IDC_MAIN_KERNEL), pref.kernel_user ?
108 pref.kernel_user_file : TEXT("netbsd.gz"));
110 // root file system.
111 int fs = pref.rootfs + IDC_MAIN_ROOT_;
112 _set_check(fs, TRUE);
114 _edit_md_root = GetDlgItem(w, IDC_MAIN_ROOT_MD_OPS);
115 Edit_SetText(_edit_md_root, pref.rootfs_file);
116 EnableWindow(_edit_md_root, fs == IDC_MAIN_ROOT_MD ? TRUE : FALSE);
118 // layout checkbox and editbox.
119 layout();
121 // set default kernel boot options.
122 _set_check(IDC_MAIN_OPTION_A, pref.boot_ask_for_name);
123 _set_check(IDC_MAIN_OPTION_D, pref.boot_debugger);
124 _set_check(IDC_MAIN_OPTION_S, pref.boot_single_user);
125 _set_check(IDC_MAIN_OPTION_V, pref.boot_verbose);
126 _set_check(IDC_MAIN_OPTION_H, pref.boot_serial);
128 // serial console speed.
129 TCHAR *speed_tab[] = { L"9600", L"19200", L"115200", 0 };
130 int sel = 0;
131 i = 0;
132 for (TCHAR **speed = speed_tab; *speed; speed++, i++) {
133 _insert_item(w, *speed, IDC_MAIN_OPTION_H_SPEED);
134 if (_wtoi(*speed) == pref.serial_speed)
135 sel = i;
137 _combobox_serial_speed = GetDlgItem(_window, IDC_MAIN_OPTION_H_SPEED);
138 SendDlgItemMessage(w, IDC_MAIN_OPTION_H_SPEED, CB_SETCURSEL, sel, 0);
139 EnableWindow(_combobox_serial_speed, pref.boot_serial);
143 MainTabWindow::_platcmp(const void *a, const void *b)
145 const MainTabWindow::PlatMap *pa =
146 reinterpret_cast <const MainTabWindow::PlatMap *>(a);
147 const MainTabWindow::PlatMap *pb =
148 reinterpret_cast <const MainTabWindow::PlatMap *>(b);
150 return wcscmp(pa->name, pb->name);
153 void
154 MainTabWindow::_sort_platids(HWND w)
156 HpcMenuInterface &menu = HPC_MENU;
157 MainTabWindow::PlatMap *p;
158 TCHAR *entry;
159 int nids;
160 int i;
162 for (nids = 0; menu.platform_get(nids); ++nids)
163 continue;
165 _platmap = reinterpret_cast <MainTabWindow::PlatMap *>
166 (malloc(nids * sizeof(MainTabWindow::PlatMap)));
168 if (_platmap == NULL) {
169 // can't sort, present in the order of definition
170 for (i = 0; entry = menu.platform_get(i); i++)
171 _insert_item(w, entry, IDC_MAIN_PLATFORM);
172 SendDlgItemMessage(w, IDC_MAIN_PLATFORM, CB_SETCURSEL,
173 menu.platform_default(), 0);
174 return;
177 for (i = 0, p = _platmap; i < nids; ++i, ++p) {
178 p->id = i;
179 p->name = menu.platform_get(i);
182 qsort(_platmap, nids, sizeof(MainTabWindow::PlatMap),
183 MainTabWindow::_platcmp);
185 int defid = menu.platform_default();
186 int defitem = 0;
187 for (i = 0; i < nids; ++i) {
188 if (_platmap[i].id == defid)
189 defitem = i;
190 _insert_item(w, _platmap[i].name, IDC_MAIN_PLATFORM);
192 SendDlgItemMessage(w, IDC_MAIN_PLATFORM, CB_SETCURSEL, defitem, 0);
196 MainTabWindow::_item_to_platid(int idx)
198 if (_platmap == NULL)
199 return idx;
200 else
201 return _platmap[idx].id;
204 void
205 MainTabWindow::layout()
207 // inquire display size.
208 HDC hdc = GetDC(0);
209 int width = GetDeviceCaps(hdc, HORZRES);
210 int height = GetDeviceCaps(hdc, VERTRES);
211 ReleaseDC(0, hdc);
213 // set origin
214 int x, y;
215 if (width <= 320) {
216 x = 5, y = 125;
217 } else if (height <= 240) {
218 x = 250, y = 5;
219 } else {
220 x = 5, y = 125;
223 HWND h;
224 h = GetDlgItem(_window, IDC_MAIN_OPTION_V);
225 SetWindowPos(h, 0, x, y, 120, 10, SWP_NOSIZE | SWP_NOZORDER);
226 h = GetDlgItem(_window, IDC_MAIN_OPTION_S);
227 SetWindowPos(h, 0, x, y + 20, 120, 10, SWP_NOSIZE | SWP_NOZORDER);
228 h = GetDlgItem(_window, IDC_MAIN_OPTION_A);
229 SetWindowPos(h, 0, x, y + 40, 120, 10, SWP_NOSIZE | SWP_NOZORDER);
230 h = GetDlgItem(_window, IDC_MAIN_OPTION_D);
231 SetWindowPos(h, 0, x, y + 60, 120, 10, SWP_NOSIZE | SWP_NOZORDER);
232 h = GetDlgItem(_window, IDC_MAIN_OPTION_H);
233 SetWindowPos(h, 0, x, y + 80, 120, 10, SWP_NOSIZE | SWP_NOZORDER);
234 h = GetDlgItem(_window, IDC_MAIN_OPTION_H_SPEED);
235 SetWindowPos(h, 0, x + 100, y + 80, 120, 10, SWP_NOSIZE | SWP_NOZORDER);
238 void
239 MainTabWindow::get()
241 HpcMenuInterface &menu = HPC_MENU;
242 struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE;
244 HWND w = GetDlgItem(_window, IDC_MAIN_DIR);
245 ComboBox_GetText(w, pref.dir_user_path, MAX_PATH);
246 pref.dir_user = TRUE;
247 w = GetDlgItem(_window, IDC_MAIN_KERNEL);
248 Edit_GetText(w, pref.kernel_user_file, MAX_PATH);
249 pref.kernel_user = TRUE;
251 int i = ComboBox_GetCurSel(GetDlgItem(_window, IDC_MAIN_PLATFORM));
252 menu.platform_set(_item_to_platid(i));
254 if (_is_checked(IDC_MAIN_ROOT_WD))
255 pref.rootfs = 0;
256 else if (_is_checked(IDC_MAIN_ROOT_SD))
257 pref.rootfs = 1;
258 else if (_is_checked(IDC_MAIN_ROOT_MD))
259 pref.rootfs = 2;
260 else if (_is_checked(IDC_MAIN_ROOT_NFS))
261 pref.rootfs = 3;
263 pref.boot_ask_for_name = _is_checked(IDC_MAIN_OPTION_A);
264 pref.boot_debugger = _is_checked(IDC_MAIN_OPTION_D);
265 pref.boot_verbose = _is_checked(IDC_MAIN_OPTION_V);
266 pref.boot_single_user = _is_checked(IDC_MAIN_OPTION_S);
267 pref.boot_serial = _is_checked(IDC_MAIN_OPTION_H);
268 Edit_GetText(_edit_md_root, pref.rootfs_file, MAX_PATH);
270 TCHAR tmpbuf[8];
271 ComboBox_GetText(_combobox_serial_speed, tmpbuf, 8);
272 pref.serial_speed = _wtoi(tmpbuf);
275 void
276 MainTabWindow::command(int id, int msg)
278 switch (id) {
279 case IDC_MAIN_OPTION_H:
280 EnableWindow(_combobox_serial_speed,
281 _is_checked(IDC_MAIN_OPTION_H));
282 break;
283 case IDC_MAIN_ROOT_WD:
284 /* FALLTHROUGH */
285 case IDC_MAIN_ROOT_SD:
286 /* FALLTHROUGH */
287 case IDC_MAIN_ROOT_MD:
288 /* FALLTHROUGH */
289 case IDC_MAIN_ROOT_NFS:
290 EnableWindow(_edit_md_root, _is_checked(IDC_MAIN_ROOT_MD));
295 // Option window
297 void
298 OptionTabWindow::init(HWND w)
300 struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE;
302 _window = w;
304 TabWindow::init(_window);
305 _spin_edit = GetDlgItem(_window, IDC_OPT_AUTO_INPUT);
306 _spin = CreateUpDownControl(WS_CHILD | WS_BORDER | WS_VISIBLE |
307 UDS_SETBUDDYINT | UDS_ALIGNRIGHT, 80, 0, 50, 50, _window,
308 IDC_OPT_AUTO_UPDOWN, _app._instance, _spin_edit, 60, 1, 30);
309 BOOL onoff = pref.auto_boot ? TRUE : FALSE;
310 EnableWindow(_spin_edit, onoff);
311 EnableWindow(_spin, onoff);
313 SET_CHECK(AUTO, pref.auto_boot);
314 if (pref.auto_boot) {
315 TCHAR tmp[32];
316 wsprintf(tmp, TEXT("%d"), pref.auto_boot);
317 Edit_SetText(_spin_edit, tmp);
319 SET_CHECK(VIDEO, pref.reverse_video);
320 SET_CHECK(PAUSE, pref.pause_before_boot);
321 SET_CHECK(DEBUG, pref.load_debug_info);
322 SET_CHECK(SAFETY, pref.safety_message);
323 Edit_SetText(GetDlgItem(w, IDC_OPT_EXTKOPT), pref.boot_extra);
326 void
327 OptionTabWindow::command(int id, int msg)
329 switch (id) {
330 case IDC_OPT_AUTO:
331 if (IS_CHECKED(AUTO)) {
332 EnableWindow(_spin_edit, TRUE);
333 EnableWindow(_spin, TRUE);
334 } else {
335 EnableWindow(_spin_edit, FALSE);
336 EnableWindow(_spin, FALSE);
338 break;
342 void
343 OptionTabWindow::get()
345 HWND w;
346 struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE;
347 if (IS_CHECKED(AUTO)) {
348 TCHAR tmp[32];
349 Edit_GetText(_spin_edit, tmp, 32);
350 pref.auto_boot = _wtoi(tmp);
351 } else
352 pref.auto_boot = 0;
353 pref.reverse_video = IS_CHECKED(VIDEO);
354 pref.pause_before_boot = IS_CHECKED(PAUSE);
355 pref.load_debug_info = IS_CHECKED(DEBUG);
356 pref.safety_message = IS_CHECKED(SAFETY);
358 w = GetDlgItem(_window, IDC_OPT_EXTKOPT);
359 Edit_GetText(w, pref.boot_extra, MAX_BOOT_STR);
361 #undef IS_CHECKED
362 #undef SET_CHECK
366 // Console window
368 void
369 ConsoleTabWindow::print(TCHAR *buf, BOOL force_display)
371 int cr;
372 TCHAR *p;
374 if (force_display)
375 goto display;
377 if (_filesave) {
378 if (_logfile == INVALID_HANDLE_VALUE && !_open_log_file()) {
379 _filesave = FALSE;
380 _set_check(IDC_CONS_FILESAVE, _filesave);
381 EnableWindow(_filename_edit, _filesave);
382 goto display;
384 DWORD cnt;
385 char c;
386 for (int i = 0; *buf != TEXT('\0'); buf++) {
387 c = *buf & 0x7f;
388 WriteFile(_logfile, &c, 1, &cnt, 0);
390 FlushFileBuffers(_logfile);
391 return;
394 display:
395 // count number of '\n'
396 for (cr = 0, p = buf; p = wcschr(p, TEXT('\n')); cr++, p++)
397 continue;
399 // total length of new buffer ('\n' -> "\r\n" + '\0')
400 size_t sz = (wcslen(buf) + cr + 1) * sizeof(TCHAR);
402 p = reinterpret_cast <TCHAR *>(malloc(sz));
403 if (p == NULL)
404 return;
406 // convert newlines
407 TCHAR *d = p;
408 while (*buf != TEXT('\0')) {
409 TCHAR c = *buf++;
410 if (c == TEXT('\n'))
411 *d++ = TEXT('\r');
412 *d++ = c;
414 *d = TEXT('\0');
416 // append the text and scroll
417 int end = Edit_GetTextLength(_edit);
418 Edit_SetSel(_edit, end, end);
419 Edit_ReplaceSel(_edit, p);
420 Edit_ScrollCaret(_edit);
421 UpdateWindow(_edit);
423 free(p);
426 void
427 ConsoleTabWindow::init(HWND w)
429 // at this time _window is NULL.
430 // use argument of window procedure.
431 TabWindow::init(w);
432 _edit = GetDlgItem(w, IDC_CONS_EDIT);
433 MoveWindow(_edit, 5, 60, _rect.right - _rect.left - 10,
434 _rect.bottom - _rect.top - 60, TRUE);
435 Edit_FmtLines(_edit, TRUE);
437 // log file.
438 _filename_edit = GetDlgItem(w, IDC_CONS_FILENAME);
439 _filesave = FALSE;
440 Edit_SetText(_filename_edit, L"bootlog.txt");
441 EnableWindow(_filename_edit, _filesave);
444 void
445 ConsoleTabWindow::command(int id, int msg)
447 HpcMenuInterface &menu = HPC_MENU;
448 struct HpcMenuInterface::cons_hook_args *hook = 0;
449 int bit;
451 switch(id) {
452 case IDC_CONS_FILESAVE:
453 _filesave = _is_checked(IDC_CONS_FILESAVE);
454 EnableWindow(_filename_edit, _filesave);
455 break;
456 case IDC_CONS_CHK0:
457 /* FALLTHROUGH */
458 case IDC_CONS_CHK1:
459 /* FALLTHROUGH */
460 case IDC_CONS_CHK2:
461 /* FALLTHROUGH */
462 case IDC_CONS_CHK3:
463 /* FALLTHROUGH */
464 case IDC_CONS_CHK4:
465 /* FALLTHROUGH */
466 case IDC_CONS_CHK5:
467 /* FALLTHROUGH */
468 case IDC_CONS_CHK6:
469 /* FALLTHROUGH */
470 case IDC_CONS_CHK7:
471 bit = 1 << (id - IDC_CONS_CHK_);
472 if (SendDlgItemMessage(_window, id, BM_GETCHECK, 0, 0))
473 menu._cons_parameter |= bit;
474 else
475 menu._cons_parameter &= ~bit;
476 break;
477 case IDC_CONS_BTN0:
478 /* FALLTHROUGH */
479 case IDC_CONS_BTN1:
480 /* FALLTHROUGH */
481 case IDC_CONS_BTN2:
482 /* FALLTHROUGH */
483 case IDC_CONS_BTN3:
484 hook = &menu._cons_hook[id - IDC_CONS_BTN_];
485 if (hook->func)
486 hook->func(hook->arg, menu._cons_parameter);
488 break;
492 BOOL
493 ConsoleTabWindow::_open_log_file()
495 TCHAR path[MAX_PATH];
496 TCHAR filename[MAX_PATH];
497 TCHAR filepath[MAX_PATH];
499 if (!_find_pref_dir(path)) {
500 print(L"couldn't find temporary directory.\n", TRUE);
501 return FALSE;
504 Edit_GetText(_filename_edit, filename, MAX_PATH);
505 wsprintf(filepath, TEXT("\\%s\\%s"), path, filename);
506 _logfile = CreateFile(filepath, GENERIC_WRITE, 0, 0,
507 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
508 if (_logfile == INVALID_HANDLE_VALUE)
509 return FALSE;
511 wsprintf(path, TEXT("log file is %s\n"), filepath);
512 print(path, TRUE);
514 return TRUE;
518 // Common utility
520 BOOL
521 _find_pref_dir(TCHAR *path)
523 WIN32_FIND_DATA fd;
524 HANDLE find;
526 lstrcpy(path, TEXT("\\*.*"));
527 find = FindFirstFile(path, &fd);
529 if (find != INVALID_HANDLE_VALUE) {
530 do {
531 int attr = fd.dwFileAttributes;
532 if ((attr & FILE_ATTRIBUTE_DIRECTORY) &&
533 (attr & FILE_ATTRIBUTE_TEMPORARY)) {
534 wcscpy(path, fd.cFileName);
535 FindClose(find);
536 return TRUE;
538 } while (FindNextFile(find, &fd));
540 FindClose(find);
542 return FALSE;