#ifndef	ARCH_WINLIB_COMMON_H
#define	ARCH_WINLIB_COMMON_H

#include <../../libv/include/GL/gl.h>

DEQUE_STRUCT(event,ui_event_t)

DECLARE_DEQUE_API(event,V_CALL,ui_event_t)

typedef struct vidmode_s
{
	u32_t	width;
	u32_t	height;
	u32_t	bpp;		/* set correctly but not used under X11 */
	u32_t	refresh;	/* set correctly but not used under X11 */
	int		modeline;	/* not used under Win32 (FIXME - also needless under X11) */
}	vidmode_t, *vidmode_p;

#define	MAX_WINDOW_TITLE	128

#define	ARCH_COMMON_WINDOW_FIELDS \
	char	title[MAX_WINDOW_TITLE]; /* caption */ \
	u32_t	x, y; /* [left,top] */ \
	u32_t	width, height; \
	u32_t	root_width, root_height; \
	/* X11 - time of 1st input msg; Win32 - time of wnd creation */ \
	unsigned start_time; \
	vboolean focused; /* affected by winsystem | archWinFocus() */ \
	vboolean visible; /* affected by winsystem | archWinShow() */ \
	int pointer_hide_count; /* affected by archWinShowPointer() */ \
	int ms_grab_count; /* affected by archWinGrabMouse() */ \
	int kb_grab_count; /* affected by archWinGrabKeyboard() */ \
	int	current_vidmode; /* affected by archWinSetVidMode() */ \
	int saved_pointer_hide_count; /* affected by ui_win_loose_control() */ \
	int saved_ms_grab_count; /* affected by ui_win_loose_control() */ \
	int saved_kb_grab_count; /* affected by ui_win_loose_control() */ \
	int	saved_vidmode; /* affected by ui_win_loose_control() */ \
	/* last ms coords, client space, as returned by windowing system */ \
	int	last_mx, last_my; \
	/* last ms coords, client space, as tracked by library */ \
	int last_vmx, last_vmy; \
	unsigned last_key_state; /* keyboard modifiers of last input msg */ \
	unsigned last_button_state; /* mouse btns of last mouse msg */ \
	vboolean auto_repeat_disabled; /* !filter autorepeated keys */ \
	/* mouse pointer hidden, 'infinite' mouse mode */ \
	vboolean auto_warp_enabled; \
	int	auto_warp_saved_x, auto_warp_saved_y; \
	vboolean zap_next_mousemove; /* eat next MouseMove msg */ \
	u8_t keyboard_state[sc_maxcode]; /* 0 if sc_XXX key is released */ \
	event_deque_p msg_que; /* message deque */

#define	INIT_COMMON_WINDOW_FIELDS(winobj) \
	(winobj)->title[0] = 0; \
	(winobj)->x = (winobj)->y = 0; \
	(winobj)->width = (winobj)->height = 256; \
	(winobj)->root_width = (winobj)->root_height = 0; \
	(winobj)->start_time = 0; \
	(winobj)->visible = false; \
	(winobj)->focused = false; \
	(winobj)->pointer_hide_count = 0; \
	(winobj)->ms_grab_count = 0; \
	(winobj)->kb_grab_count = 0; \
	(winobj)->current_vidmode = -1; \
	(winobj)->saved_pointer_hide_count = 0; \
	(winobj)->saved_ms_grab_count = 0; \
	(winobj)->saved_kb_grab_count = 0; \
	(winobj)->saved_vidmode = -1; \
	(winobj)->auto_warp_enabled = false; \
	(winobj)->last_mx = (winobj)->last_my = 0; \
	(winobj)->last_key_state = (winobj)->last_button_state = 0; \
	(winobj)->auto_repeat_disabled = false; \
	(winobj)->zap_next_mousemove = false; \
	memZero((winobj)->keyboard_state,sc_maxcode); \
	(winobj)->msg_que = NULL;

#define	CLEAR_COMMON_WINDOW_FIELDS(winobj) \
	eventDeqFree((winobj)->msg_que); \
	(winobj)->msg_que = NULL;

/*
 * We need complete definition of arch_window_t even for
 * portable part of windowing library.
 */
#ifdef	__WIN32__
#include "../win32/winlib.h"
#else	/* !__WIN32__ */
#include "../generic/winlib.h"
#endif	/* !__WIN32__ */

#ifdef	__cplusplus
extern "C" {
#endif
	/*
	 * Window management
	 */
	arch_window_p	V_CALL	archWinOpenNP(void_p osd_parent,void_p visinfo,
		char *title,u32_t left,u32_t top,u32_t width,u32_t height,
		vboolean caption, /* if false - set WS_POPUP | OverrideRedirect */
		vboolean allow_resize);
	void		V_CALL	archWinClose(arch_window_p aw);
	/* set mode_num to -1 for default mode */
	vboolean	V_CALL	archWinSetVidMode(arch_window_p aw,int mode_num);
	/* window configuration */
	vboolean	V_CALL	archWinShow(arch_window_p aw,vboolean show);
	void		V_CALL	archWinFocus(arch_window_p aw);
	vboolean	V_CALL	archWinMove(arch_window_p aw,s32_t x,s32_t y);
	vboolean	V_CALL	archWinSize(arch_window_p aw,s32_t width,s32_t height);
	/*
	 * Mouse pointer helper functions
	 */
	vboolean	V_CALL	archWinWarpPointer(arch_window_p aw,s32_t x,s32_t y);
	/* Returns 'true' if cursor is visible at exit. */
	vboolean	V_CALL	archWinShowPointer(arch_window_p aw,vboolean show);
	void		V_CALL	archWinGrabMouse(arch_window_p aw,vboolean grab);
	void		V_CALL	archWinGrabKeyboard(arch_window_p aw,vboolean grab);
	/* enables or disables keyboard autorepeat */
	void		V_CALL	archWinAutoRepeat(arch_window_p aw,vboolean enable);
	/*
	 * If 'enable': saves pointer position, hides pointer, starts
	 * incremental tracking of pointer coords (screen position of pointer
	 * _no more_ corresponds to window position, which can be arbitrary
	 * number between [-MAXLONG;MAXLONG]). If !'enable': restores
	 * pointer position, shows pointer. It is recommended to use deltas
	 * (i.e. msg->client_dx and msg->client_dy) instead of coords.
	 */
	void		V_CALL	archWinAutoWarp(arch_window_p aw,vboolean enable);
	/*
	 * Message queue management
	 */
	void		V_CALL	archWinPoll(arch_window_p wnd,vboolean block);
	/*
	 * archWinWaitMessages()
	 * Waits for events, but not longer than 'timeout' milliseconds.
	 * Retuns immediately with 'true' if there is at least one event pending.
	 * Returns 'false' if no event received within 'timeout'.
	 * Pass -1 as timeout for infinite wait.
	 */
	vboolean V_CALL	archWinWaitMessages(int timeout);
	/* Common stuff */
	vboolean V_CALL	ui_default_wnd_proc(arch_window_p aw,ui_event_p ev);
	void	V_CALL	ui_win_loose_control(arch_window_p aw,vboolean hiding);
	void	V_CALL	ui_make_default_key_event(ui_key_event_p ev);
	void	V_CALL	ui_set_configure_from_aw(arch_window_p aw,ui_configure_event_p ev);
	vec_t	V_CALL	ui_make_message_time(unsigned *start,unsigned current);
	/*
	 * OpenGL helper proc
	 */
	vboolean V_CALL vgl_load_proc(char *proc_name,void **ptr_ret,vboolean *terminate_ret);
#ifdef	__cplusplus
}
#endif

#endif	/* !ARCH_WINLIB_COMMON_H */
