//============================================================
//
//	winutils.c - Generic Win32 utility code
//
//============================================================

// Needed for better file dialog
#define _WIN32_WINNT 0x500

// standard windows headers
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commdlg.h>
#include <tchar.h>

// MESS headers
#include "winutils.h"
#include "strconv.h"


//============================================================
//	win_get_file_name_dialog - sanitize all of the ugliness
//	in invoking GetOpenFileName() and GetSaveFileName()
//============================================================

BOOL win_get_file_name_dialog(win_open_file_name *ofn)
{
	BOOL result = FALSE;
	BOOL dialog_result;
	OSVERSIONINFO vers;
	OPENFILENAME os_ofn;
	DWORD os_ofn_size;
	LPTSTR t_filter = NULL;
	LPTSTR t_file = NULL;
	DWORD t_file_size = 0;
	LPTSTR t_initial_directory = NULL;
	LPTSTR buffer;
	char *utf8_file;
	int i;

	// determine the version of Windows
	memset(&vers, 0, sizeof(vers));
	vers.dwOSVersionInfoSize = sizeof(vers);
	GetVersionEx(&vers);

	// based on the version of Windows, determine the correct struct size
	if (vers.dwMajorVersion >= 5)
	{
		os_ofn_size = sizeof(os_ofn);
	}
	else
	{
#ifdef __GNUC__
		os_ofn_size = 76;	// MinGW does not define OPENFILENAME_NT4
#else
		os_ofn_size = sizeof(OPENFILENAME_NT4);
#endif
	}

	// do we have to translate the filter?
	if (ofn->filter != NULL)
	{
		buffer = tstring_from_utf8(ofn->filter);
		if (!buffer)
			goto done;

		// convert a pipe-char delimited string into a NUL delimited string
		t_filter = (LPTSTR) alloca((_tcslen(buffer) + 2) * sizeof(*t_filter));
		for (i = 0; buffer[i] != '\0'; i++)
			t_filter[i] = (buffer[i] != '|') ? buffer[i] : '\0';
		t_filter[i++] = '\0';
		t_filter[i++] = '\0';
		free(buffer);
	}

	// do we need to translate the file parameter?
	if (ofn->filename != NULL)
	{
		buffer = tstring_from_utf8(ofn->filename);
		if (!buffer)
			goto done;

		t_file_size = MAX(_tcslen(buffer) + 1, MAX_PATH);
		t_file = (LPTSTR) alloca(t_file_size * sizeof(*t_file));
		_tcscpy(t_file, buffer);
		free(buffer);
	}

	// do we need to translate the initial directory?
	if (ofn->initial_directory != NULL)
	{
		t_initial_directory = tstring_from_utf8(ofn->initial_directory);
		if (t_initial_directory == NULL)
			goto done;
	}

	// translate our custom structure to a native Win32 structure
	memset(&os_ofn, 0, sizeof(os_ofn));
	os_ofn.lStructSize = os_ofn_size;
	os_ofn.hwndOwner = ofn->owner;
	os_ofn.hInstance = ofn->instance;
	os_ofn.lpstrFilter = t_filter;
	os_ofn.nFilterIndex = ofn->filter_index;
	os_ofn.lpstrFile = t_file;
	os_ofn.nMaxFile = t_file_size;
	os_ofn.lpstrInitialDir = t_initial_directory;
	os_ofn.Flags = ofn->flags;
	os_ofn.lCustData = ofn->custom_data;
	os_ofn.lpfnHook = ofn->hook;
	os_ofn.lpTemplateName = ofn->template_name;

	// invoke the correct Win32 call
	switch(ofn->type)
	{
		case WIN_FILE_DIALOG_OPEN:
			dialog_result = GetOpenFileName(&os_ofn);
			break;

		case WIN_FILE_DIALOG_SAVE:
			dialog_result = GetSaveFileName(&os_ofn);
			break;

		default:
			// should not reach here
			dialog_result = FALSE;
			break;
	}

	// copy data out
	ofn->filter_index = os_ofn.nFilterIndex;
	ofn->flags = os_ofn.Flags;

	// copy file back out into passed structure
	if (t_file != NULL)
	{
		utf8_file = utf8_from_tstring(t_file);
		if (!utf8_file)
			goto done;

		snprintf(ofn->filename, ARRAY_LENGTH(ofn->filename), "%s", utf8_file);
		free(utf8_file);
	}

	// we've completed the process
	result = dialog_result;

done:
	if (t_initial_directory != NULL)
		free(t_initial_directory);
	return result;
}



//============================================================
//	win_scroll_window
//============================================================

void win_scroll_window(HWND window, WPARAM wparam, int scroll_bar, int scroll_delta_line)
{
	SCROLLINFO si;
	int scroll_pos;

	// retrieve vital info about the scroll bar
	memset(&si, 0, sizeof(si));
	si.cbSize = sizeof(si);
	si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
	GetScrollInfo(window, scroll_bar, &si);

	scroll_pos = si.nPos;

	// change scroll_pos in accordance with this message
	switch(LOWORD(wparam))
	{
		case SB_BOTTOM:
			scroll_pos = si.nMax;
			break;
		case SB_LINEDOWN:
			scroll_pos += scroll_delta_line;
			break;
		case SB_LINEUP:
			scroll_pos -= scroll_delta_line;
			break;
		case SB_PAGEDOWN:
			scroll_pos += scroll_delta_line;
			break;
		case SB_PAGEUP:
			scroll_pos -= scroll_delta_line;
			break;
		case SB_THUMBPOSITION:
		case SB_THUMBTRACK:
			scroll_pos = HIWORD(wparam);
			break;
		case SB_TOP:
			scroll_pos = si.nMin;
			break;
	}

	// max out the scroll bar value
	if (scroll_pos < si.nMin)
		scroll_pos = si.nMin;
	else if (scroll_pos > (si.nMax - si.nPage))
		scroll_pos = (si.nMax - si.nPage);

	// if the value changed, set the scroll position
	if (scroll_pos != si.nPos)
	{
		SetScrollPos(window, scroll_bar, scroll_pos, TRUE);
		ScrollWindowEx(window, 0, si.nPos - scroll_pos, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
	}
}



//============================================================
//	win_get_file_attributes_utf8
//============================================================

DWORD win_get_file_attributes_utf8(const char *filename)
{
	DWORD result = ~0;
	LPTSTR t_filename;

	t_filename = tstring_from_utf8(filename);
	if (t_filename != NULL)
	{
		result = GetFileAttributes(t_filename);
		free(t_filename);
	}
	return result;
}
