Home | History | Annotate | Line # | Download | only in menu
      1 /* -*-C++-*-	$NetBSD: menu.cpp,v 1.13 2011/11/23 15:49:58 nonaka 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  *
     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.
     30  */
     31 
     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>
     41 
     42 #include <menu/menu.h>
     43 
     44 #define SCALEX(x) (((x) * dpix) / 96/*DPI*/)
     45 #define SCALEY(y) (((y) * dpiy) / 96/*DPI*/)
     46 #define UNSCALEX(x) (((x) * 96) / dpix)
     47 #define UNSCALEY(y) (((y) * 96) / dpiy)
     48 
     49 TabWindow *
     50 TabWindowBase::boot(int id)
     51 {
     52 	TabWindow *w = NULL;
     53 	HpcMenuInterface &menu = HPC_MENU;
     54 
     55 	switch(id) {
     56 	default:
     57 		break;
     58 	case IDC_BASE_MAIN:
     59 		menu._main = new MainTabWindow(*this, IDC_BASE_MAIN);
     60 		w = menu._main;
     61 		break;
     62 	case IDC_BASE_OPTION:
     63 		menu._option = new OptionTabWindow(*this, IDC_BASE_OPTION);
     64 		w = menu._option;
     65 		break;
     66 	case IDC_BASE_CONSOLE:
     67 		menu._console = new ConsoleTabWindow(*this, IDC_BASE_CONSOLE);
     68 		w = menu._console;
     69 		break;
     70 	}
     71 
     72 	if (w)
     73 		w->create(0);
     74 
     75 	return w;
     76 }
     77 
     78 //
     79 // Main window
     80 //
     81 void
     82 MainTabWindow::_insert_item(HWND w, TCHAR *name, int id)
     83 {
     84 	int idx = SendDlgItemMessage(w, id, CB_ADDSTRING, 0,
     85 	    reinterpret_cast <LPARAM>(name));
     86 	if (idx != CB_ERR)
     87 		SendDlgItemMessage(w, IDC_MAIN_DIR, CB_SETITEMDATA,
     88 		    idx, _item_idx++);
     89 }
     90 
     91 void
     92 MainTabWindow::init(HWND w)
     93 {
     94 	HpcMenuInterface &menu = HPC_MENU;
     95 	struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE;
     96 
     97 	_window = w;
     98 	// insert myself to tab-control
     99 	TabWindow::init(w);
    100 
    101 	// setup child.
    102 	TCHAR *entry;
    103 	int i;
    104 	// kernel directory path
    105 	for (i = 0; entry = menu.dir(i); i++)
    106 		_insert_item(w, entry, IDC_MAIN_DIR);
    107 	SendDlgItemMessage(w, IDC_MAIN_DIR, CB_SETCURSEL, menu.dir_default(),
    108 	    0);
    109 	// platform
    110 	_sort_platids(w);
    111 	// kernel file name.
    112 	Edit_SetText(GetDlgItem(w, IDC_MAIN_KERNEL), pref.kernel_user ?
    113 	    pref.kernel_user_file : TEXT("netbsd.gz"));
    114 
    115 	// root file system.
    116 	int fs = pref.rootfs + IDC_MAIN_ROOT_;
    117 	_set_check(fs, TRUE);
    118 
    119 	_edit_md_root = GetDlgItem(w, IDC_MAIN_ROOT_MD_OPS);
    120 	Edit_SetText(_edit_md_root, pref.rootfs_file);
    121 	EnableWindow(_edit_md_root, fs == IDC_MAIN_ROOT_MD ? TRUE : FALSE);
    122 
    123 	// layout checkbox and editbox.
    124 	layout();
    125 
    126 	// set default kernel boot options.
    127 	_set_check(IDC_MAIN_OPTION_A, pref.boot_ask_for_name);
    128 	_set_check(IDC_MAIN_OPTION_D, pref.boot_debugger);
    129 	_set_check(IDC_MAIN_OPTION_S, pref.boot_single_user);
    130 	_set_check(IDC_MAIN_OPTION_V, pref.boot_verbose);
    131 	_set_check(IDC_MAIN_OPTION_H, pref.boot_serial);
    132 
    133 	// serial console speed.
    134 	TCHAR *speed_tab[] = { L"9600", L"19200", L"115200", 0 };
    135 	int sel = 0;
    136 	i = 0;
    137 	for (TCHAR **speed = speed_tab; *speed; speed++, i++) {
    138 		_insert_item(w, *speed, IDC_MAIN_OPTION_H_SPEED);
    139 		if (_wtoi(*speed) == pref.serial_speed)
    140 			sel = i;
    141 	}
    142 	_combobox_serial_speed = GetDlgItem(_window, IDC_MAIN_OPTION_H_SPEED);
    143 	SendDlgItemMessage(w, IDC_MAIN_OPTION_H_SPEED, CB_SETCURSEL, sel, 0);
    144 	EnableWindow(_combobox_serial_speed, pref.boot_serial);
    145 }
    146 
    147 int
    148 MainTabWindow::_platcmp(const void *a, const void *b)
    149 {
    150 	const MainTabWindow::PlatMap *pa =
    151 		reinterpret_cast <const MainTabWindow::PlatMap *>(a);
    152 	const MainTabWindow::PlatMap *pb =
    153 		reinterpret_cast <const MainTabWindow::PlatMap *>(b);
    154 
    155 	return wcscmp(pa->name, pb->name);
    156 }
    157 
    158 void
    159 MainTabWindow::_sort_platids(HWND w)
    160 {
    161 	HpcMenuInterface &menu = HPC_MENU;
    162 	MainTabWindow::PlatMap *p;
    163 	TCHAR *entry;
    164 	int nids;
    165 	int i;
    166 
    167 	for (nids = 0; menu.platform_get(nids); ++nids)
    168 		continue;
    169 
    170 	_platmap = reinterpret_cast <MainTabWindow::PlatMap *>
    171 		(malloc(nids * sizeof(MainTabWindow::PlatMap)));
    172 
    173 	if (_platmap == NULL) {
    174 		// can't sort, present in the order of definition
    175 		for (i = 0; entry = menu.platform_get(i); i++)
    176 			_insert_item(w, entry, IDC_MAIN_PLATFORM);
    177 		SendDlgItemMessage(w, IDC_MAIN_PLATFORM, CB_SETCURSEL,
    178 				   menu.platform_default(), 0);
    179 		return;
    180 	}
    181 
    182 	for (i = 0, p = _platmap; i < nids; ++i, ++p) {
    183 		p->id = i;
    184 		p->name = menu.platform_get(i);
    185 	}
    186 
    187 	qsort(_platmap, nids, sizeof(MainTabWindow::PlatMap),
    188 	      MainTabWindow::_platcmp);
    189 
    190 	int defid = menu.platform_default();
    191 	int defitem = 0;
    192 	for (i = 0; i < nids; ++i) {
    193 		if (_platmap[i].id == defid)
    194 			defitem = i;
    195 		_insert_item(w, _platmap[i].name, IDC_MAIN_PLATFORM);
    196 	}
    197 	SendDlgItemMessage(w, IDC_MAIN_PLATFORM, CB_SETCURSEL, defitem, 0);
    198 }
    199 
    200 int
    201 MainTabWindow::_item_to_platid(int idx)
    202 {
    203 	if (_platmap == NULL)
    204 		return idx;
    205 	else
    206 		return _platmap[idx].id;
    207 }
    208 
    209 void
    210 MainTabWindow::layout()
    211 {
    212 	// inquire display size.
    213 	HDC hdc = GetDC(0);
    214 	int width = GetDeviceCaps(hdc, HORZRES);
    215 	int height = GetDeviceCaps(hdc, VERTRES);
    216 	int dpix = GetDeviceCaps(hdc, LOGPIXELSX);
    217 	int dpiy = GetDeviceCaps(hdc, LOGPIXELSY);
    218 	ReleaseDC(0, hdc);
    219 
    220 	// set origin
    221 	int x, y;
    222 	if (width <= 320) {
    223 		x = 5, y = 140;
    224 	} else if (height <= 240) {
    225 		x = 250, y = 5;
    226 	} else {
    227 		x = 5, y = 140;
    228 	}
    229 
    230 	HWND h;
    231 	h = GetDlgItem(_window, IDC_MAIN_OPTION_V);
    232 	SetWindowPos(h, 0, SCALEX(x), SCALEY(y),
    233 	    SCALEX(120), SCALEY(10), SWP_NOSIZE | SWP_NOZORDER);
    234 	h = GetDlgItem(_window, IDC_MAIN_OPTION_S);
    235 	SetWindowPos(h, 0, SCALEX(x), SCALEY(y + 20),
    236             SCALEX(120), SCALEY(10), SWP_NOSIZE | SWP_NOZORDER);
    237 	h = GetDlgItem(_window, IDC_MAIN_OPTION_A);
    238 	SetWindowPos(h, 0, SCALEX(x), SCALEY(y + 40),
    239 	    SCALEX(120), SCALEY(10), SWP_NOSIZE | SWP_NOZORDER);
    240 	h = GetDlgItem(_window, IDC_MAIN_OPTION_D);
    241 	SetWindowPos(h, 0, SCALEX(x), SCALEY(y + 60),
    242 	    SCALEX(120), SCALEY(10), SWP_NOSIZE | SWP_NOZORDER);
    243 	h = GetDlgItem(_window, IDC_MAIN_OPTION_H);
    244 	SetWindowPos(h, 0, SCALEX(x), SCALEY(y + 80),
    245 	    SCALEX(120), SCALEY(10), SWP_NOSIZE | SWP_NOZORDER);
    246 	h = GetDlgItem(_window, IDC_MAIN_OPTION_H_SPEED);
    247 	SetWindowPos(h, 0, SCALEX(x + 100), SCALEY(y + 80),
    248 	    SCALEX(120), SCALEY(10), SWP_NOSIZE | SWP_NOZORDER);
    249 }
    250 
    251 void
    252 MainTabWindow::get()
    253 {
    254 	HpcMenuInterface &menu = HPC_MENU;
    255 	struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE;
    256 
    257 	HWND w = GetDlgItem(_window, IDC_MAIN_DIR);
    258 	ComboBox_GetText(w, pref.dir_user_path, MAX_PATH);
    259 	pref.dir_user = TRUE;
    260 	w = GetDlgItem(_window, IDC_MAIN_KERNEL);
    261 	Edit_GetText(w, pref.kernel_user_file, MAX_PATH);
    262 	pref.kernel_user = TRUE;
    263 
    264 	int i = ComboBox_GetCurSel(GetDlgItem(_window, IDC_MAIN_PLATFORM));
    265 	menu.platform_set(_item_to_platid(i));
    266 
    267 	if (_is_checked(IDC_MAIN_ROOT_WD))
    268 		pref.rootfs = 0;
    269 	else if (_is_checked(IDC_MAIN_ROOT_SD))
    270 		pref.rootfs = 1;
    271 	else if (_is_checked(IDC_MAIN_ROOT_MD))
    272 		pref.rootfs = 2;
    273 	else if (_is_checked(IDC_MAIN_ROOT_NFS))
    274 		pref.rootfs = 3;
    275 	else if (_is_checked(IDC_MAIN_ROOT_DK))
    276 		pref.rootfs = 4;
    277 	else if (_is_checked(IDC_MAIN_ROOT_LD))
    278 		pref.rootfs = 5;
    279 
    280 	pref.boot_ask_for_name	= _is_checked(IDC_MAIN_OPTION_A);
    281 	pref.boot_debugger	= _is_checked(IDC_MAIN_OPTION_D);
    282 	pref.boot_verbose	= _is_checked(IDC_MAIN_OPTION_V);
    283 	pref.boot_single_user	= _is_checked(IDC_MAIN_OPTION_S);
    284 	pref.boot_serial	= _is_checked(IDC_MAIN_OPTION_H);
    285 	Edit_GetText(_edit_md_root, pref.rootfs_file, MAX_PATH);
    286 
    287 	TCHAR tmpbuf[8];
    288 	ComboBox_GetText(_combobox_serial_speed, tmpbuf, 8);
    289 	pref.serial_speed = _wtoi(tmpbuf);
    290 }
    291 
    292 void
    293 MainTabWindow::command(int id, int msg)
    294 {
    295 	switch (id) {
    296 	case IDC_MAIN_OPTION_H:
    297 		EnableWindow(_combobox_serial_speed,
    298 		    _is_checked(IDC_MAIN_OPTION_H));
    299 		break;
    300 	case IDC_MAIN_ROOT_WD:
    301 		/* FALLTHROUGH */
    302 	case IDC_MAIN_ROOT_SD:
    303 		/* FALLTHROUGH */
    304 	case IDC_MAIN_ROOT_MD:
    305 		/* FALLTHROUGH */
    306 	case IDC_MAIN_ROOT_NFS:
    307 		/* FALLTHROUGH */
    308 	case IDC_MAIN_ROOT_DK:
    309 		/* FALLTHROUGH */
    310 	case IDC_MAIN_ROOT_LD:
    311 		EnableWindow(_edit_md_root, _is_checked(IDC_MAIN_ROOT_MD));
    312 	}
    313 }
    314 
    315 //
    316 // Option window
    317 //
    318 void
    319 OptionTabWindow::init(HWND w)
    320 {
    321 	struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE;
    322 	HDC hdc = GetDC(0);
    323 	int dpix = GetDeviceCaps(hdc, LOGPIXELSX);
    324 	int dpiy = GetDeviceCaps(hdc, LOGPIXELSY);
    325 	ReleaseDC(0, hdc);
    326 
    327 	_window = w;
    328 
    329 	TabWindow::init(_window);
    330 	_spin_edit = GetDlgItem(_window, IDC_OPT_AUTO_INPUT);
    331 	_spin = CreateUpDownControl(WS_CHILD | WS_BORDER | WS_VISIBLE |
    332 	    UDS_SETBUDDYINT | UDS_ALIGNRIGHT,
    333 	    SCALEX(80), SCALEY(0), SCALEX(50), SCALEY(50), _window,
    334 	    IDC_OPT_AUTO_UPDOWN, _app._instance, _spin_edit, 60, 1, 30);
    335 	BOOL onoff = pref.auto_boot ? TRUE : FALSE;
    336 	EnableWindow(_spin_edit, onoff);
    337 	EnableWindow(_spin, onoff);
    338 
    339 	SET_CHECK(AUTO, pref.auto_boot);
    340 	if (pref.auto_boot) {
    341 		TCHAR tmp[32];
    342 		wsprintf(tmp, TEXT("%d"), pref.auto_boot);
    343 		Edit_SetText(_spin_edit, tmp);
    344 	}
    345 	SET_CHECK(VIDEO,	pref.reverse_video);
    346 	SET_CHECK(PAUSE,	pref.pause_before_boot);
    347 	SET_CHECK(DEBUG,	pref.load_debug_info);
    348 	SET_CHECK(SAFETY,	pref.safety_message);
    349 	Edit_SetText(GetDlgItem(w, IDC_OPT_EXTKOPT), pref.boot_extra);
    350 }
    351 
    352 void
    353 OptionTabWindow::command(int id, int msg)
    354 {
    355 	switch (id) {
    356 	case IDC_OPT_AUTO:
    357 		if (IS_CHECKED(AUTO)) {
    358 			EnableWindow(_spin_edit, TRUE);
    359 			EnableWindow(_spin, TRUE);
    360 		} else {
    361 			EnableWindow(_spin_edit, FALSE);
    362 			EnableWindow(_spin, FALSE);
    363 		}
    364 		break;
    365 	}
    366 }
    367 
    368 void
    369 OptionTabWindow::get()
    370 {
    371 	HWND w;
    372 	struct HpcMenuInterface::HpcMenuPreferences &pref = HPC_PREFERENCE;
    373 	if (IS_CHECKED(AUTO)) {
    374 		TCHAR tmp[32];
    375 		Edit_GetText(_spin_edit, tmp, 32);
    376 		pref.auto_boot = _wtoi(tmp);
    377 	} else
    378 		pref.auto_boot = 0;
    379 	pref.reverse_video	= IS_CHECKED(VIDEO);
    380 	pref.pause_before_boot	= IS_CHECKED(PAUSE);
    381 	pref.load_debug_info	= IS_CHECKED(DEBUG);
    382 	pref.safety_message	= IS_CHECKED(SAFETY);
    383 
    384 	w = GetDlgItem(_window, IDC_OPT_EXTKOPT);
    385 	Edit_GetText(w, pref.boot_extra, MAX_BOOT_STR);
    386 }
    387 #undef IS_CHECKED
    388 #undef SET_CHECK
    389 
    390 
    391 //
    392 // Console window
    393 //
    394 void
    395 ConsoleTabWindow::print(TCHAR *buf, BOOL force_display)
    396 {
    397 	int cr;
    398 	TCHAR *p;
    399 
    400 	if (force_display)
    401 		goto display;
    402 
    403 	if (_filesave) {
    404 		if (_logfile == INVALID_HANDLE_VALUE && !_open_log_file()) {
    405 			_filesave = FALSE;
    406 			_set_check(IDC_CONS_FILESAVE, _filesave);
    407 			EnableWindow(_filename_edit, _filesave);
    408 			goto display;
    409 		}
    410 		DWORD cnt;
    411 		char c;
    412 		for (int i = 0; *buf != TEXT('\0'); buf++) {
    413 			c = *buf & 0x7f;
    414 			WriteFile(_logfile, &c, 1, &cnt, 0);
    415 		}
    416 		FlushFileBuffers(_logfile);
    417 		return;
    418 	}
    419 
    420  display:
    421 	// count number of '\n'
    422 	for (cr = 0, p = buf; p = wcschr(p, TEXT('\n')); cr++, p++)
    423 		continue;
    424 
    425 	// total length of new buffer ('\n' -> "\r\n" + '\0')
    426 	size_t sz = (wcslen(buf) + cr + 1) * sizeof(TCHAR);
    427 
    428 	p = reinterpret_cast <TCHAR *>(malloc(sz));
    429 	if (p == NULL)
    430 		return;
    431 
    432 	// convert newlines
    433 	TCHAR *d = p;
    434 	while (*buf != TEXT('\0')) {
    435 		TCHAR c = *buf++;
    436 		if (c == TEXT('\n'))
    437 			*d++ = TEXT('\r');
    438 		*d++ = c;
    439 	}
    440 	*d = TEXT('\0');
    441 
    442 	// append the text and scroll
    443 	int end = Edit_GetTextLength(_edit);
    444 	Edit_SetSel(_edit, end, end);
    445 	Edit_ReplaceSel(_edit, p);
    446 	Edit_ScrollCaret(_edit);
    447 	UpdateWindow(_edit);
    448 
    449 	free(p);
    450 }
    451 
    452 void
    453 ConsoleTabWindow::init(HWND w)
    454 {
    455 	HDC hdc = GetDC(0);
    456 	int dpix = GetDeviceCaps(hdc, LOGPIXELSX);
    457 	int dpiy = GetDeviceCaps(hdc, LOGPIXELSY);
    458 	ReleaseDC(0, hdc);
    459 
    460 	// at this time _window is NULL.
    461 	// use argument of window procedure.
    462 	TabWindow::init(w);
    463 	_edit = GetDlgItem(w, IDC_CONS_EDIT);
    464 	MoveWindow(_edit, SCALEX(5), SCALEY(60),
    465 	    SCALEX(UNSCALEX(_rect.right - _rect.left) - 10),
    466 	    SCALEY(UNSCALEY(_rect.bottom - _rect.top) - 60), TRUE);
    467 	Edit_FmtLines(_edit, TRUE);
    468 
    469 	// log file.
    470 	_filename_edit = GetDlgItem(w, IDC_CONS_FILENAME);
    471 	_filesave = FALSE;
    472 	Edit_SetText(_filename_edit, L"bootlog.txt");
    473 	EnableWindow(_filename_edit, _filesave);
    474 }
    475 
    476 void
    477 ConsoleTabWindow::command(int id, int msg)
    478 {
    479 	HpcMenuInterface &menu = HPC_MENU;
    480 	struct HpcMenuInterface::cons_hook_args *hook = 0;
    481 	int bit;
    482 
    483 	switch(id) {
    484 	case IDC_CONS_FILESAVE:
    485 		_filesave = _is_checked(IDC_CONS_FILESAVE);
    486 		EnableWindow(_filename_edit, _filesave);
    487 		break;
    488 	case IDC_CONS_CHK0:
    489 		/* FALLTHROUGH */
    490 	case IDC_CONS_CHK1:
    491 		/* FALLTHROUGH */
    492 	case IDC_CONS_CHK2:
    493 		/* FALLTHROUGH */
    494 	case IDC_CONS_CHK3:
    495 		/* FALLTHROUGH */
    496 	case IDC_CONS_CHK4:
    497 		/* FALLTHROUGH */
    498 	case IDC_CONS_CHK5:
    499 		/* FALLTHROUGH */
    500 	case IDC_CONS_CHK6:
    501 		/* FALLTHROUGH */
    502 	case IDC_CONS_CHK7:
    503 		bit = 1 << (id - IDC_CONS_CHK_);
    504 		if (SendDlgItemMessage(_window, id, BM_GETCHECK, 0, 0))
    505 			menu._cons_parameter |= bit;
    506 		else
    507 			menu._cons_parameter &= ~bit;
    508 		break;
    509 	case IDC_CONS_BTN0:
    510 		/* FALLTHROUGH */
    511 	case IDC_CONS_BTN1:
    512 		/* FALLTHROUGH */
    513 	case IDC_CONS_BTN2:
    514 		/* FALLTHROUGH */
    515 	case IDC_CONS_BTN3:
    516 		hook = &menu._cons_hook[id - IDC_CONS_BTN_];
    517 		if (hook->func)
    518 			hook->func(hook->arg, menu._cons_parameter);
    519 
    520 		break;
    521 	}
    522 }
    523 
    524 BOOL
    525 ConsoleTabWindow::_open_log_file()
    526 {
    527 	TCHAR path[MAX_PATH];
    528 	TCHAR filename[MAX_PATH];
    529 	TCHAR filepath[MAX_PATH];
    530 
    531 	if (!_find_pref_dir(path)) {
    532 		print(L"couldn't find temporary directory.\n", TRUE);
    533 		return FALSE;
    534 	}
    535 
    536 	Edit_GetText(_filename_edit, filename, MAX_PATH);
    537 	wsprintf(filepath, TEXT("\\%s\\%s"), path, filename);
    538 	_logfile = CreateFile(filepath, GENERIC_WRITE, 0, 0,
    539 	    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    540 	if (_logfile == INVALID_HANDLE_VALUE)
    541 		return FALSE;
    542 
    543 	wsprintf(path, TEXT("log file is %s\n"), filepath);
    544 	print(path, TRUE);
    545 
    546 	return TRUE;
    547 }
    548 
    549 //
    550 // Common utility
    551 //
    552 static BOOL
    553 is_ignore_directory(TCHAR *filename)
    554 {
    555 	static const TCHAR *dirs[] = {
    556 		// Network (in Japanese)
    557 		(const TCHAR *)"\xcd\x30\xc3\x30\xc8\x30\xef\x30\xfc\x30\xaf\x30\x00\x00",
    558 	};
    559 
    560 	for (int i = 0; i < sizeof(dirs) / sizeof(dirs[0]); i++) {
    561 		if (wcscmp(filename, dirs[i]) == 0) {
    562 			return TRUE;
    563 		}
    564 	}
    565 	return FALSE;
    566 }
    567 
    568 BOOL
    569 _find_pref_dir(TCHAR *path)
    570 {
    571 	WIN32_FIND_DATA fd;
    572 	HANDLE find;
    573 
    574 	lstrcpy(path, TEXT("\\*.*"));
    575 	find = FindFirstFile(path, &fd);
    576 
    577 	if (find != INVALID_HANDLE_VALUE) {
    578 		do {
    579 			int attr = fd.dwFileAttributes;
    580 			if ((attr & FILE_ATTRIBUTE_DIRECTORY) &&
    581 			    (attr & FILE_ATTRIBUTE_TEMPORARY) &&
    582 			    !is_ignore_directory(fd.cFileName)) {
    583 				wcscpy(path, fd.cFileName);
    584 				FindClose(find);
    585 				return TRUE;
    586 			}
    587 		} while (FindNextFile(find, &fd));
    588 	}
    589 	FindClose(find);
    590 
    591 	return FALSE;
    592 }
    593