/* -*-C++-*-	$NetBSD: hpcmenu.h,v 1.14 2008/04/28 20:23:20 martin Exp $	*/

/*-
 * Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by UCHIYAMA Yasushi.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _HPCBOOT_MENU_H_
#define	_HPCBOOT_MENU_H_

#include <hpcdefs.h>

// forward declaration.
class Console;
class HpcBootApp;
class RootWindow;
class BootButton;
class CancelButton;
class ProgressBar;
class TabWindowBase;
class MainTabWindow;
class OptionTabWindow;
class ConsoleTabWindow;
struct bootinfo;

// Application
class HpcBootApp {
public:
	HINSTANCE	_instance;
	HWND		_cmdbar;
	RootWindow	*_root;
	Console		*_cons;
	int		_cx_char, _cy_char; // 5, 14

private:
	void _get_font_size(void) {
		HDC hdc = GetDC(0);
		TEXTMETRIC tm;
		SelectObject(hdc, GetStockObject(SYSTEM_FONT));
		GetTextMetrics(hdc, &tm);
		_cx_char = tm.tmAveCharWidth;
		_cy_char = tm.tmHeight + tm.tmExternalLeading;
		ReleaseDC(0, hdc);
	}

public:
	explicit HpcBootApp(HINSTANCE instance) : _instance(instance) {
		_root	= 0;
		_cmdbar	= 0;
		_get_font_size();
	}
	virtual ~HpcBootApp(void) { /* NO-OP */ }

	BOOL registerClass(WNDPROC proc);
	int run(void);
};

// internal representation of user input.
class HpcMenuInterface
{
public:
	struct HpcMenuPreferences {
#define	HPCBOOT_MAGIC		0x177d5753
		int		_magic;
		int		_version;
		size_t	_size;	// size of HpcMenuPreferences structure.
		int		dir;
		BOOL	dir_user;
		TCHAR	dir_user_path[MAX_PATH];
		BOOL	kernel_user;
		TCHAR	kernel_user_file[MAX_PATH];
		unsigned	platid_hi;
		unsigned	platid_lo;
		int		rootfs;
		TCHAR	rootfs_file[MAX_PATH];
		// kernel options.
		BOOL	boot_serial;
		BOOL	boot_verbose;
		BOOL	boot_single_user;
		BOOL	boot_ask_for_name;
		BOOL	boot_debugger;
		// boot loader options.
		int		auto_boot;
		BOOL	reverse_video;
		BOOL	pause_before_boot;
		BOOL	load_debug_info;
		BOOL	safety_message;
		// serial console speed
		int	serial_speed;
#define	MAX_BOOT_STR 256
		TCHAR	boot_extra[MAX_BOOT_STR];
	};
	struct support_status {
		uint32_t cpu, machine;
		const TCHAR *cause;
	};
	static struct support_status _unsupported[];

	RootWindow		*_root;
	MainTabWindow		*_main;
	OptionTabWindow		*_option;
	ConsoleTabWindow	*_console;
	struct HpcMenuPreferences _pref;

	struct boot_hook_args {
		void(*func)(void *);
		void *arg;
	} _boot_hook;

	struct cons_hook_args {
		void(*func)(void *, unsigned char);
		void *arg;
	} _cons_hook [4];
	int _cons_parameter; // Console tab window check buttons.

private:
	static HpcMenuInterface *_instance;

	void _set_default_pref(void);
	enum _platform_op {
		_PLATFORM_OP_GET,
		_PLATFORM_OP_SET,
		_PLATFORM_OP_DEFAULT
	};
	void *_platform(int, enum _platform_op);

protected:
	HpcMenuInterface(void);
	virtual ~HpcMenuInterface(void) { /* NO-OP */ }

public:
	static HpcMenuInterface &Instance(void);
	static void Destroy(void);

	// preferences.
	BOOL load(void);
	BOOL save(void);

	// Boot button
	// when user click `boot button' inquires all options.
	void get_options(void);
	enum { MAX_KERNEL_ARGS = 16 };
	int setup_kernel_args(vaddr_t, paddr_t, size_t);
	void setup_bootinfo(struct bootinfo &bi);
	void register_boot_hook(struct boot_hook_args &arg) {
		_boot_hook = arg;
	}
	// call architecture dependent boot function.
	void boot(void);

	// Progress bar.
	void progress(const char * = NULL);
	void unprogress(void);

	// Console window interface.
	void print(TCHAR *);
	void register_cons_hook(struct cons_hook_args &arg, int id) {
		if (id >= 0 && id < 4)
			_cons_hook[id] = arg;
	}

	// Main window options
	TCHAR *dir(int);
	int dir_default(void);

	// platform
	TCHAR *platform_get(int n) {
		return reinterpret_cast <TCHAR *>
		    (_platform(n, _PLATFORM_OP_GET));
	}
	int platform_default(void) {
		return reinterpret_cast <int>
		    (_platform(0, _PLATFORM_OP_DEFAULT));
	}
	void platform_set(int n) { _platform(n, _PLATFORM_OP_SET); }
};

/* Global access macro */
#define	HPC_MENU	(HpcMenuInterface::Instance())
#define	HPC_PREFERENCE	(HPC_MENU._pref)

#endif // _HPCBOOT_MENU_H_
