<commit_before>#define INSANITY_BUILDING_LIBRARY

#include "CWindowsWin32Window.hpp"

#if defined(PLATFORM_MSWINDOWS)

#include <IThread.hpp>
#include <IGarbageCollector.hpp>
#include <IApplication.hpp>
#include <IString.hpp>
#include <TRectangle.hpp>
#include <IConfigObject.hpp>

#include <windowsx.h>
#include <CommCtrl.h>

#include <iostream>

namespace Insanity
{
	IWindow * IWindow::Create(IWindow * ext, IConfigObject const * cfg)
	{
		return new CWindowsWin32Window(ext, cfg);
	}

	bool CWindowsWin32Window::s_windowClassRegistered = false;
	CWindowsWin32EventPumpTask * CWindowsWin32Window::s_pumpTask = nullptr;
	u64 CWindowsWin32Window::s_winCount = 0;

	u64 CWindowsWin32Window::GetWindowCount()
	{
		return s_winCount;
	}

	CWindowsWin32Window::CWindowsWin32Window(IWindow * ext, IConfigObject const * cfg) :
		_ext(ext), _rect(nullptr)
	{
		HMODULE hInst = GetModuleHandle(nullptr);

		_InitWindowClass(hInst);
		_InitEventPump();

		_InitWindow(hInst, cfg->GetProperty("title", ""));

		s_winCount++;
	}
	CWindowsWin32Window::~CWindowsWin32Window()
	{
		if(--s_winCount == 0)
		{
			s_pumpTask->Release(); //The windows don't need it anymore.
			//the pump task will not be deleted until it's dequeued from the thread task list.
		}

		//A comment on SetWindowSubclass says to remove the subclass before destroying the window.
		RemoveWindowSubclass(_win,WindowProc,0);
		DestroyWindow(_win);
		_rect->Release();
	}

	void CWindowsWin32Window::_InitWindowClass(HINSTANCE hInst)
	{
		if (!s_windowClassRegistered)
		{
			WNDCLASSEXW wcex;
			ZeroMemory(&wcex, sizeof(wcex));
			wcex.cbClsExtra = 0;						//Won't be able to access
			wcex.cbSize = sizeof(wcex);					//Constant
			wcex.cbWndExtra = 0;						//Won't be able to access
			wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW);//More or less constant.
			wcex.hCursor = (HCURSOR) LoadImage(hInst, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED); //Can be assigned later
			wcex.hIcon = (HICON) LoadImage(hInst, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED); //Can be assigned later
			wcex.hIconSm = (HICON) LoadImage(hInst, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED); //Can be assigned later
			wcex.hInstance = hInst;						//Constant
			wcex.lpfnWndProc = InitialWindowProc;		//Will assign WindowProc after window creation
			wcex.lpszClassName = L"InsanityWindowClass";//Constant
			wcex.lpszMenuName = nullptr;				//Can be assigned if/when a Menu is added.
			wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; //First two needed, third needed for uniformity with other platforms.

			RegisterClassExW(&wcex);

			s_windowClassRegistered = true;
		}
	}
	void CWindowsWin32Window::_InitWindow(HINSTANCE hInst, IConfigObject const * cfg)
	{
		//_rect stores the dimensions of the client area of the window.
		_rect = new TRectangle<s16, u16>(static_cast<s16>(cfg->GetProperty("dims.x", (s64)0)),
			static_cast<s16>(cfg->GetProperty("dims.y", (s64)0)),
			static_cast<u16>(cfg->GetProperty("dims.width", (s64)640)),
			static_cast<u16>(cfg->GetProperty("dims.height", (s64)480)));
		_rect->Retain();

		//Need to adjust for non-client area of window for CreateWindow.
		RECT adj;
		adj.left = _rect->GetLeft();
		adj.top = _rect->GetTop();
		adj.right = _rect->GetRight();
		adj.bottom = _rect->GetBottom();
		AdjustWindowRectEx(&adj, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_OVERLAPPEDWINDOW);

		//convert the title to a wchar_t string. Let the garbage collector take care of it.
		IString<wchar_t> * wtitle = IString<wchar_t>::Create(cfg->GetProperty("title", ""));

		_win = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,	//will either want this or options for fullscreen
			L"InsanityWindowClass",						//Constant
			wtitle->Array(),							//Good candidate for Config file
			WS_OVERLAPPEDWINDOW,						//as dwExStyle
			adj.left, adj.top,
			adj.right - adj.left, adj.bottom - adj.top,	//Dimensions are another good candidate
			HWND_DESKTOP,								//If in Config file, would need a way to specify another window
			NULL,										//Menu can be assigned later
			hInst,										//Constant
			nullptr);									//Constant (unused)

		SetWindowSubclass(_win, WindowProc, 0, reinterpret_cast<DWORD_PTR>(this));

		ShowWindow(_win, SW_SHOWDEFAULT);
	}
	void CWindowsWin32Window::_InitEventPump()
	{
		if (s_pumpTask == nullptr)
		{
			//creates a pump task, assigns it to the static pointer, and passes it to RegisterTask.
			IApplication::GetInstance()->RegisterTask(s_pumpTask = new CWindowsWin32EventPumpTask());
		}

		//Other platforms have to register an event procedure with the event pump task.
		//	Since that's basically an emulation of Windows' event setup, we use the native setup here.
	}

	LRESULT CALLBACK CWindowsWin32Window::InitialWindowProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
		//this will receive at least WM_NCCREATE, WM_NCCALCSIZE, and WM_CREATE before assigning WindowProc subclass.
		return DefWindowProcW(wnd,msg,wParam,lParam);
	}
	LRESULT CALLBACK CWindowsWin32Window::WindowProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uSubclassId, DWORD_PTR dwRefData)
	{
		//this is the main method for processing window messages.
		CWindowsWin32Window * self = reinterpret_cast<CWindowsWin32Window*>(dwRefData);
		self->Retain();

		IWindow * call = (self->_ext ? self->_ext : self);

		POINTS pt = MAKEPOINTS(lParam);
		WORD highWParam = HIWORD(wParam);

		switch(msg)
		{
		case WM_LBUTTONDOWN:
			call->MouseHandler(EMouseButton::Left, EMouseButtonState::Down, pt.x, pt.y);
			break;
		case WM_LBUTTONUP:
			call->MouseHandler(EMouseButton::Left, EMouseButtonState::Up, pt.x, pt.y);
			break;
		case WM_LBUTTONDBLCLK:
			call->MouseHandler(EMouseButton::Left, EMouseButtonState::DoubleClick, pt.x, pt.y);
			break;
		case WM_RBUTTONDOWN:
			call->MouseHandler(EMouseButton::Right, EMouseButtonState::Down, pt.x, pt.y);
			break;
		case WM_RBUTTONUP:
			call->MouseHandler(EMouseButton::Right, EMouseButtonState::Up, pt.x, pt.y);
			break;
		case WM_RBUTTONDBLCLK:
			call->MouseHandler(EMouseButton::Right, EMouseButtonState::DoubleClick, pt.x, pt.y);
			break;
		case WM_MBUTTONDOWN:
			call->MouseHandler(EMouseButton::Middle, EMouseButtonState::Down, pt.x, pt.y);
			break;
		case WM_MBUTTONUP:
			call->MouseHandler(EMouseButton::Middle, EMouseButtonState::Up, pt.x, pt.y);
			break;
		case WM_MBUTTONDBLCLK:
			call->MouseHandler(EMouseButton::Middle, EMouseButtonState::DoubleClick, pt.x, pt.y);
			break;
		case WM_XBUTTONDOWN:
			call->MouseHandler((highWParam == 1 ? EMouseButton::X1 : EMouseButton::X2), EMouseButtonState::Down, pt.x, pt.y);
			break;
		case WM_XBUTTONUP:
			call->MouseHandler((highWParam == 1 ? EMouseButton::X1 : EMouseButton::X2), EMouseButtonState::Up, pt.x, pt.y);
			break;
		case WM_XBUTTONDBLCLK:
			call->MouseHandler((highWParam == 1 ? EMouseButton::X1 : EMouseButton::X2), EMouseButtonState::DoubleClick, pt.x, pt.y);
			break;
		case WM_KEYUP:
			call->KeyHandler((EKey) wParam, EKeyState::Up);
			break;
		case WM_KEYDOWN:
			call->KeyHandler((EKey) wParam, EKeyState::Down);
			break;
		case WM_CLOSE:
			std::cout << "Close message received." << std::endl;
			call->CloseHandler();
			break;
		case WM_SHOWWINDOW:
			call->ShowHandler(wParam == TRUE);
			break;
		case WM_DESTROY:
			//should only be sent when the window object is destroyed.
			//should do any code on window destruction in the dtor, not here or a handler.
			break;
		case WM_MOVE:
			//coordinates reported are the upper-left corner of the client area in screen coordinates.
			call->MoveHandler(pt.x, pt.y);
			break;
		case WM_SIZE:
			call->ResizeHandler(pt.x, pt.y);
			break;
		case WM_MOUSEMOVE:
			call->MouseHandler(EMouseButton::Null, EMouseButtonState::Null, pt.x, pt.y);
			break;
		case WM_MOUSEWHEEL:
			{
				//need the sign from highWParam
				SHORT delta = (SHORT)highWParam;

				//the second parameter to ScrollHandler is a simple magnitude (unsigned), so take the absolute value.
				call->ScrollHandler((delta > 0 ? EMouseScrollDirection::Up : EMouseScrollDirection::Down), abs(delta / WHEEL_DELTA));
			}
			break;
		}

		self->Release();
		return DefSubclassProc(wnd,msg,wParam,lParam);
	}

	HWND CWindowsWin32Window::GetWindow() const
	{
		return _win;
	}

	//=====================================================
	//Interface: IWindow
	//=====================================================
	TRectangle<s16,u16> const * CWindowsWin32Window::GetRect() const
	{
		return _rect;
	}
	void CWindowsWin32Window::MouseHandler(EMouseButton button, EMouseButtonState state, u16 x, u16 y)
	{
	}
	void CWindowsWin32Window::KeyHandler(EKey key, EKeyState state)
	{
	}
	void CWindowsWin32Window::ScrollHandler(EMouseScrollDirection dir, u16 delta)
	{
	}
	void CWindowsWin32Window::ShowHandler(bool show)
	{
	}
	void CWindowsWin32Window::MoveHandler(s16 x, s16 y)
	{
		_rect->SetX(x);
		_rect->SetY(y);
	}
	void CWindowsWin32Window::ResizeHandler(u16 width, u16 height)
	{
		_rect->SetWidth(width);
		_rect->SetHeight(height);
	}
	void CWindowsWin32Window::CloseHandler()
	{
	}
	void CWindowsWin32Window::Mouse(EMouseButton button, EMouseButtonState state, u16 x, u16 y)
	{
		UINT msg = 0;
		WORD xButton = 0;
		switch (button)
		{
		case EMouseButton::Left:
			msg = WM_LBUTTONDOWN;
			break;
		case EMouseButton::Middle:
			msg = WM_MBUTTONDOWN;
			break;
		case EMouseButton::Right:
			msg = WM_RBUTTONDOWN;
			break;
		case EMouseButton::X1:
			xButton = 1;
			msg = WM_XBUTTONDOWN;
			break;
		case EMouseButton::X2:
			xButton = 2;
			msg = WM_XBUTTONDOWN;
			break;
		case EMouseButton::Null:
			msg = WM_MOUSEMOVE;
			break;
		}

		if (button != EMouseButton::Null) //ignore the state; should be Null, but don't count on it.
		{
			switch (state)
			{
			case EMouseButtonState::Down:
				//no-op, Down is already set.
				break;
			case EMouseButtonState::Up:
				msg += 1;
				break;
			case EMouseButtonState::DoubleClick:
				msg += 2;
				break;
			}
		}
		DWORD tmpX = x;
		DWORD tmpY = y;
		LPARAM lParam = (tmpY << 16) | tmpX;
		PostMessage(_win, msg, xButton << 16, lParam);
	}
	void CWindowsWin32Window::Key(EKey key, EKeyState state)
	{
		//LPARAM is a bunch of state flags we have no way of tracking, so ignore it.
		PostMessage(_win, (state == EKeyState::Down ? WM_KEYDOWN : WM_KEYUP), (WPARAM)key, 0);
	}
	void CWindowsWin32Window::Scroll(EMouseScrollDirection dir, u16 delta)
	{
		//mask off the sign bit (shouldn't cause problems)
		SHORT postDelta = delta & 0x7fff;
		postDelta *= (dir == EMouseScrollDirection::Up ? 1 : -1);

		//Last parameter should be the current mouse position, but that's not provided nor tracked internally.
		PostMessage(_win, WM_MOUSEWHEEL, (static_cast<DWORD>(postDelta)) << 16, 0);
	}
	void CWindowsWin32Window::Show(bool show)
	{
		ShowWindow(_win, (show ? SW_SHOWNORMAL : SW_HIDE));
	}
	void CWindowsWin32Window::Move(s16 x, s16 y)
	{
		MoveWindow(_win,x,y,0,0,TRUE);
	}
	void CWindowsWin32Window::Resize(u16 width, u16 height)
	{
		MoveWindow(_win,0,0,width,height,TRUE);
	}
	void CWindowsWin32Window::Close()
	{
		PostMessage(_win, WM_CLOSE, 0, 0);
	}
}

#endif
<commit_msg>Pass the correct object to _InitWindow.<commit_after>#define INSANITY_BUILDING_LIBRARY

#include "CWindowsWin32Window.hpp"

#if defined(PLATFORM_MSWINDOWS)

#include <IThread.hpp>
#include <IGarbageCollector.hpp>
#include <IApplication.hpp>
#include <IString.hpp>
#include <TRectangle.hpp>
#include <IConfigObject.hpp>

#include <windowsx.h>
#include <CommCtrl.h>

#include <iostream>

namespace Insanity
{
	IWindow * IWindow::Create(IWindow * ext, IConfigObject const * cfg)
	{
		return new CWindowsWin32Window(ext, cfg);
	}

	bool CWindowsWin32Window::s_windowClassRegistered = false;
	CWindowsWin32EventPumpTask * CWindowsWin32Window::s_pumpTask = nullptr;
	u64 CWindowsWin32Window::s_winCount = 0;

	u64 CWindowsWin32Window::GetWindowCount()
	{
		return s_winCount;
	}

	CWindowsWin32Window::CWindowsWin32Window(IWindow * ext, IConfigObject const * cfg) :
		_ext(ext), _rect(nullptr)
	{
		HMODULE hInst = GetModuleHandle(nullptr);

		_InitWindowClass(hInst);
		_InitEventPump();

		_InitWindow(hInst, cfg);

		s_winCount++;
	}
	CWindowsWin32Window::~CWindowsWin32Window()
	{
		if(--s_winCount == 0)
		{
			s_pumpTask->Release(); //The windows don't need it anymore.
			//the pump task will not be deleted until it's dequeued from the thread task list.
		}

		//A comment on SetWindowSubclass says to remove the subclass before destroying the window.
		RemoveWindowSubclass(_win,WindowProc,0);
		DestroyWindow(_win);
		_rect->Release();
	}

	void CWindowsWin32Window::_InitWindowClass(HINSTANCE hInst)
	{
		if (!s_windowClassRegistered)
		{
			WNDCLASSEXW wcex;
			ZeroMemory(&wcex, sizeof(wcex));
			wcex.cbClsExtra = 0;						//Won't be able to access
			wcex.cbSize = sizeof(wcex);					//Constant
			wcex.cbWndExtra = 0;						//Won't be able to access
			wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW);//More or less constant.
			wcex.hCursor = (HCURSOR) LoadImage(hInst, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED); //Can be assigned later
			wcex.hIcon = (HICON) LoadImage(hInst, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED); //Can be assigned later
			wcex.hIconSm = (HICON) LoadImage(hInst, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED); //Can be assigned later
			wcex.hInstance = hInst;						//Constant
			wcex.lpfnWndProc = InitialWindowProc;		//Will assign WindowProc after window creation
			wcex.lpszClassName = L"InsanityWindowClass";//Constant
			wcex.lpszMenuName = nullptr;				//Can be assigned if/when a Menu is added.
			wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; //First two needed, third needed for uniformity with other platforms.

			RegisterClassExW(&wcex);

			s_windowClassRegistered = true;
		}
	}
	void CWindowsWin32Window::_InitWindow(HINSTANCE hInst, IConfigObject const * cfg)
	{
		//_rect stores the dimensions of the client area of the window.
		_rect = new TRectangle<s16, u16>(static_cast<s16>(cfg->GetProperty("dims.x", (s64)0)),
			static_cast<s16>(cfg->GetProperty("dims.y", (s64)0)),
			static_cast<u16>(cfg->GetProperty("dims.width", (s64)640)),
			static_cast<u16>(cfg->GetProperty("dims.height", (s64)480)));
		_rect->Retain();

		//Need to adjust for non-client area of window for CreateWindow.
		RECT adj;
		adj.left = _rect->GetLeft();
		adj.top = _rect->GetTop();
		adj.right = _rect->GetRight();
		adj.bottom = _rect->GetBottom();
		AdjustWindowRectEx(&adj, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_OVERLAPPEDWINDOW);

		//convert the title to a wchar_t string. Let the garbage collector take care of it.
		IString<wchar_t> * wtitle = IString<wchar_t>::Create(cfg->GetProperty("title", ""));

		_win = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,	//will either want this or options for fullscreen
			L"InsanityWindowClass",						//Constant
			wtitle->Array(),							//Good candidate for Config file
			WS_OVERLAPPEDWINDOW,						//as dwExStyle
			adj.left, adj.top,
			adj.right - adj.left, adj.bottom - adj.top,	//Dimensions are another good candidate
			HWND_DESKTOP,								//If in Config file, would need a way to specify another window
			NULL,										//Menu can be assigned later
			hInst,										//Constant
			nullptr);									//Constant (unused)

		SetWindowSubclass(_win, WindowProc, 0, reinterpret_cast<DWORD_PTR>(this));

		ShowWindow(_win, SW_SHOWDEFAULT);
	}
	void CWindowsWin32Window::_InitEventPump()
	{
		if (s_pumpTask == nullptr)
		{
			//creates a pump task, assigns it to the static pointer, and passes it to RegisterTask.
			IApplication::GetInstance()->RegisterTask(s_pumpTask = new CWindowsWin32EventPumpTask());
		}

		//Other platforms have to register an event procedure with the event pump task.
		//	Since that's basically an emulation of Windows' event setup, we use the native setup here.
	}

	LRESULT CALLBACK CWindowsWin32Window::InitialWindowProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
		//this will receive at least WM_NCCREATE, WM_NCCALCSIZE, and WM_CREATE before assigning WindowProc subclass.
		return DefWindowProcW(wnd,msg,wParam,lParam);
	}
	LRESULT CALLBACK CWindowsWin32Window::WindowProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uSubclassId, DWORD_PTR dwRefData)
	{
		//this is the main method for processing window messages.
		CWindowsWin32Window * self = reinterpret_cast<CWindowsWin32Window*>(dwRefData);
		self->Retain();

		IWindow * call = (self->_ext ? self->_ext : self);

		POINTS pt = MAKEPOINTS(lParam);
		WORD highWParam = HIWORD(wParam);

		switch(msg)
		{
		case WM_LBUTTONDOWN:
			call->MouseHandler(EMouseButton::Left, EMouseButtonState::Down, pt.x, pt.y);
			break;
		case WM_LBUTTONUP:
			call->MouseHandler(EMouseButton::Left, EMouseButtonState::Up, pt.x, pt.y);
			break;
		case WM_LBUTTONDBLCLK:
			call->MouseHandler(EMouseButton::Left, EMouseButtonState::DoubleClick, pt.x, pt.y);
			break;
		case WM_RBUTTONDOWN:
			call->MouseHandler(EMouseButton::Right, EMouseButtonState::Down, pt.x, pt.y);
			break;
		case WM_RBUTTONUP:
			call->MouseHandler(EMouseButton::Right, EMouseButtonState::Up, pt.x, pt.y);
			break;
		case WM_RBUTTONDBLCLK:
			call->MouseHandler(EMouseButton::Right, EMouseButtonState::DoubleClick, pt.x, pt.y);
			break;
		case WM_MBUTTONDOWN:
			call->MouseHandler(EMouseButton::Middle, EMouseButtonState::Down, pt.x, pt.y);
			break;
		case WM_MBUTTONUP:
			call->MouseHandler(EMouseButton::Middle, EMouseButtonState::Up, pt.x, pt.y);
			break;
		case WM_MBUTTONDBLCLK:
			call->MouseHandler(EMouseButton::Middle, EMouseButtonState::DoubleClick, pt.x, pt.y);
			break;
		case WM_XBUTTONDOWN:
			call->MouseHandler((highWParam == 1 ? EMouseButton::X1 : EMouseButton::X2), EMouseButtonState::Down, pt.x, pt.y);
			break;
		case WM_XBUTTONUP:
			call->MouseHandler((highWParam == 1 ? EMouseButton::X1 : EMouseButton::X2), EMouseButtonState::Up, pt.x, pt.y);
			break;
		case WM_XBUTTONDBLCLK:
			call->MouseHandler((highWParam == 1 ? EMouseButton::X1 : EMouseButton::X2), EMouseButtonState::DoubleClick, pt.x, pt.y);
			break;
		case WM_KEYUP:
			call->KeyHandler((EKey) wParam, EKeyState::Up);
			break;
		case WM_KEYDOWN:
			call->KeyHandler((EKey) wParam, EKeyState::Down);
			break;
		case WM_CLOSE:
			std::cout << "Close message received." << std::endl;
			call->CloseHandler();
			break;
		case WM_SHOWWINDOW:
			call->ShowHandler(wParam == TRUE);
			break;
		case WM_DESTROY:
			//should only be sent when the window object is destroyed.
			//should do any code on window destruction in the dtor, not here or a handler.
			break;
		case WM_MOVE:
			//coordinates reported are the upper-left corner of the client area in screen coordinates.
			call->MoveHandler(pt.x, pt.y);
			break;
		case WM_SIZE:
			call->ResizeHandler(pt.x, pt.y);
			break;
		case WM_MOUSEMOVE:
			call->MouseHandler(EMouseButton::Null, EMouseButtonState::Null, pt.x, pt.y);
			break;
		case WM_MOUSEWHEEL:
			{
				//need the sign from highWParam
				SHORT delta = (SHORT)highWParam;

				//the second parameter to ScrollHandler is a simple magnitude (unsigned), so take the absolute value.
				call->ScrollHandler((delta > 0 ? EMouseScrollDirection::Up : EMouseScrollDirection::Down), abs(delta / WHEEL_DELTA));
			}
			break;
		}

		self->Release();
		return DefSubclassProc(wnd,msg,wParam,lParam);
	}

	HWND CWindowsWin32Window::GetWindow() const
	{
		return _win;
	}

	//=====================================================
	//Interface: IWindow
	//=====================================================
	TRectangle<s16,u16> const * CWindowsWin32Window::GetRect() const
	{
		return _rect;
	}
	void CWindowsWin32Window::MouseHandler(EMouseButton button, EMouseButtonState state, u16 x, u16 y)
	{
	}
	void CWindowsWin32Window::KeyHandler(EKey key, EKeyState state)
	{
	}
	void CWindowsWin32Window::ScrollHandler(EMouseScrollDirection dir, u16 delta)
	{
	}
	void CWindowsWin32Window::ShowHandler(bool show)
	{
	}
	void CWindowsWin32Window::MoveHandler(s16 x, s16 y)
	{
		_rect->SetX(x);
		_rect->SetY(y);
	}
	void CWindowsWin32Window::ResizeHandler(u16 width, u16 height)
	{
		_rect->SetWidth(width);
		_rect->SetHeight(height);
	}
	void CWindowsWin32Window::CloseHandler()
	{
	}
	void CWindowsWin32Window::Mouse(EMouseButton button, EMouseButtonState state, u16 x, u16 y)
	{
		UINT msg = 0;
		WORD xButton = 0;
		switch (button)
		{
		case EMouseButton::Left:
			msg = WM_LBUTTONDOWN;
			break;
		case EMouseButton::Middle:
			msg = WM_MBUTTONDOWN;
			break;
		case EMouseButton::Right:
			msg = WM_RBUTTONDOWN;
			break;
		case EMouseButton::X1:
			xButton = 1;
			msg = WM_XBUTTONDOWN;
			break;
		case EMouseButton::X2:
			xButton = 2;
			msg = WM_XBUTTONDOWN;
			break;
		case EMouseButton::Null:
			msg = WM_MOUSEMOVE;
			break;
		}

		if (button != EMouseButton::Null) //ignore the state; should be Null, but don't count on it.
		{
			switch (state)
			{
			case EMouseButtonState::Down:
				//no-op, Down is already set.
				break;
			case EMouseButtonState::Up:
				msg += 1;
				break;
			case EMouseButtonState::DoubleClick:
				msg += 2;
				break;
			}
		}
		DWORD tmpX = x;
		DWORD tmpY = y;
		LPARAM lParam = (tmpY << 16) | tmpX;
		PostMessage(_win, msg, xButton << 16, lParam);
	}
	void CWindowsWin32Window::Key(EKey key, EKeyState state)
	{
		//LPARAM is a bunch of state flags we have no way of tracking, so ignore it.
		PostMessage(_win, (state == EKeyState::Down ? WM_KEYDOWN : WM_KEYUP), (WPARAM)key, 0);
	}
	void CWindowsWin32Window::Scroll(EMouseScrollDirection dir, u16 delta)
	{
		//mask off the sign bit (shouldn't cause problems)
		SHORT postDelta = delta & 0x7fff;
		postDelta *= (dir == EMouseScrollDirection::Up ? 1 : -1);

		//Last parameter should be the current mouse position, but that's not provided nor tracked internally.
		PostMessage(_win, WM_MOUSEWHEEL, (static_cast<DWORD>(postDelta)) << 16, 0);
	}
	void CWindowsWin32Window::Show(bool show)
	{
		ShowWindow(_win, (show ? SW_SHOWNORMAL : SW_HIDE));
	}
	void CWindowsWin32Window::Move(s16 x, s16 y)
	{
		MoveWindow(_win,x,y,0,0,TRUE);
	}
	void CWindowsWin32Window::Resize(u16 width, u16 height)
	{
		MoveWindow(_win,0,0,width,height,TRUE);
	}
	void CWindowsWin32Window::Close()
	{
		PostMessage(_win, WM_CLOSE, 0, 0);
	}
}

#endif
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C $         */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* EKB Project                                                            */
/*                                                                        */
/* COPYRIGHT 2015,2016                                                    */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit_mc.C
/// @brief Initialize the memory controller to take over the DRAM
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <mss.H>

#include "p9_mss_draminit_mc.H"

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;

extern "C"
{
///
/// @brief Initialize the MC now that DRAM is up
/// @param[in] i_target, the McBIST of the ports
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_draminit_mc( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        auto l_mca = i_target.getChildren<TARGET_TYPE_MCA>();

        FAPI_INF("Start draminit MC");

        // If we don't have any ports, lets go.
        if (l_mca.size() == 0)
        {
            FAPI_INF("No ports? %s", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // While we're doing the scominit in here, lets do it for all ports before we dump the MCS regs.
        for (auto p : i_target.getChildren<TARGET_TYPE_MCA>())
        {
            mss::mc<TARGET_TYPE_MCS> l_mc;

            // Don't do this yet - leverage the sim inits for the moment
#if 0
            // All the scominit for this MCA
            l_mc.scominit(p);
#endif
            // Setup the MC port/dimm address translation registers
            FAPI_TRY( l_mc.setup_xlate_map(p) );
        }

        for (auto p : l_mca)
        {

            // Set the IML Complete bit MBSSQ(3) (SCOM Addr: 0x02011417) to indicate that IML has completed
            // Can't find MBSSQ or the iml_complete bit - asked Steve. Gary VH created this bit as a scratch
            // 'you are hre bit' and it was removed for Nimbus. Gary VH asked for it to be put back in. Not
            // sure if that happened yet. BRS (2/16).

            // Reset addr_mux_sel to “0” to allow the MCA to take control of the DDR interface over from CCS.
            // (Note: this step must remain in this procedure to ensure that data path is placed into mainline
            // mode prior to running memory diagnostics. When Advanced DRAM Training executes, this step
            // becomes superfluous but not harmful. However, it's not guaranteed that Advanced DRAM Training
            // will be executed on every system configuration.)
            // Note: addr_mux_sel is set low in p9_mss_draminit(), however that might be a work-around so we
            // set it low here kind of like belt-and-suspenders. BRS
            FAPI_TRY( mss::change_addr_mux_sel(p, mss::LOW) );

            // Step Two.1: Check RCD protect time on RDIMM and LRDIMM
            // Step Two.2: Enable address inversion on each MBA for ALL CARDS

            // Start the refresh engines by setting MBAREF0Q(0) = “1”. Note that the remaining bits in
            // MBAREF0Q should retain their initialization values.
            FAPI_TRY( mss::change_refresh_enable(p, mss::HIGH) );

            // Power management is handled in the init file. (or should be BRS)

            // Enabling periodic calibration
            FAPI_TRY( mss::enable_periodic_cal(p) );

            // Step Six: Setup Control Bit ECC
            FAPI_TRY( mss::enable_read_ecc(p) );

            // At this point the DDR interface must be monitored for memory errors. Memory related FIRs should be unmasked.

            // Cram a fast write, followed by a read in here for giggles
            {
                mss::mcbist::program<TARGET_TYPE_MCBIST> l_program;
                uint64_t l_start = 0;
                uint64_t l_end = 0;
                uint64_t l_pattern = 0;

                // Write
                {
                    // Uses address register set 0
                    mss::mcbist::subtest_t<TARGET_TYPE_MCBIST> l_fw_subtest =
                        mss::mcbist::write_subtest<TARGET_TYPE_MCBIST>();
                    l_fw_subtest.enable_port(mss::index(p));

                    // HACK: We only need to worry about the DIMM in slot 0 right now
                    l_fw_subtest.enable_dimm(0);
                    l_program.iv_subtests.push_back(l_fw_subtest);
                }

                // Read
                {
                    // Uses address register set 0
                    mss::mcbist::subtest_t<TARGET_TYPE_MCBIST> l_fr_subtest =
                        mss::mcbist::read_subtest<TARGET_TYPE_MCBIST>();
                    l_fr_subtest.enable_port(mss::index(p));

                    // HACK: We only need to worry about the DIMM in slot 0 right now
                    l_fr_subtest.enable_dimm(0);
                    l_program.iv_subtests.push_back(l_fr_subtest);
                }

                FAPI_TRY( mss::mcbist_start_addr(p, l_start) );
                FAPI_TRY( mss::mcbist_end_addr(p, l_end) );

                // TK: calculate proper polling based on address range

                // Setup a nice pattern for writing
                FAPI_TRY( mss::mcbist_write_data(i_target, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD0Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD1Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD2Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD3Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD4Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD5Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD6Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD7Q, l_pattern) );

                // Sanity check - can't do much if end is before start.
                // This is either a programming error or a mistake in attribute settings. So we'll just assert.
                if (l_end < l_start)
                {
                    FAPI_ERR("mcbist end address is less than mcbist starting address. s: 0x%x e: 0x%x", l_start, l_end);
                    fapi2::Assert(false);
                }

                // By default we're in maint address mode so we do a start + len and the 'BIST increments for us.
                // By default, the write subtest uses the 0'th address start/end registers.
                mss::mcbist::config_address_range0(i_target, l_start, l_end - l_start);

                // Just one port for now. Per Shelton we need to set this in maint adress mode
                // even tho we specify the port/dimm in the subtest.
                fapi2::buffer<uint8_t> l_port;
                l_port.setBit(mss::pos(p));
                l_program.select_ports(l_port >> 4);

                // Kick it off, wait for a result
                FAPI_TRY( mss::mcbist::execute(i_target, l_program) );

                // Just because the program executed and no MCBIST failure was reported, it is poosible that
                // there were address errors. An address error in the only address in a range causes the
                // 'BIST to skip that command. Since it's the only address, the subtest (or program) can
                // complete succedssfully even though nothing actually happend.
                // For now, just dump the registers and vgrep for errors. BRS
                FAPI_TRY( mss::dump_regs<TARGET_TYPE_MCBIST>(i_target) );
            }
        }

    fapi_try_exit:
        FAPI_INF("End draminit MC");
        return fapi2::current_err;
    }
}
<commit_msg>Add read pointer delay config<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C $         */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* EKB Project                                                            */
/*                                                                        */
/* COPYRIGHT 2015,2016                                                    */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit_mc.C
/// @brief Initialize the memory controller to take over the DRAM
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <mss.H>

#include "p9_mss_draminit_mc.H"

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;

extern "C"
{
///
/// @brief Initialize the MC now that DRAM is up
/// @param[in] i_target, the McBIST of the ports
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_draminit_mc( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        auto l_mca = i_target.getChildren<TARGET_TYPE_MCA>();

        FAPI_INF("Start draminit MC");

        // If we don't have any ports, lets go.
        if (l_mca.size() == 0)
        {
            FAPI_INF("No ports? %s", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // While we're doing the scominit in here, lets do it for all ports before we dump the MCS regs.
        for (auto p : i_target.getChildren<TARGET_TYPE_MCA>())
        {
            mss::mc<TARGET_TYPE_MCS> l_mc;

            // Don't do this yet - leverage the sim inits for the moment
#if 0
            // All the scominit for this MCA
            l_mc.scominit(p);
#endif
            // Setup the MC port/dimm address translation registers
            FAPI_TRY( l_mc.setup_xlate_map(p) );
        }

        // Setup the read_pointer_delay
        // TK: Do we need to do this in general or is this a place holder until the
        // init file gets here?
        {
            fapi2::buffer<uint64_t> l_data;
            FAPI_TRY( mss::getScom(i_target, MCBIST_MBSEC0Q, l_data) );
            l_data.insertFromRight<MCA_RECR_MBSECCQ_READ_POINTER_DELAY, MCA_RECR_MBSECCQ_READ_POINTER_DELAY_LEN>(0x1);
            FAPI_DBG("writing read pointer delay 0x%016lx", l_data);
            FAPI_TRY( mss::putScom(i_target, MCBIST_MBSEC0Q, l_data) );
        }

        for (auto p : l_mca)
        {

            // Set the IML Complete bit MBSSQ(3) (SCOM Addr: 0x02011417) to indicate that IML has completed
            // Can't find MBSSQ or the iml_complete bit - asked Steve. Gary VH created this bit as a scratch
            // 'you are hre bit' and it was removed for Nimbus. Gary VH asked for it to be put back in. Not
            // sure if that happened yet. BRS (2/16).

            // Reset addr_mux_sel to “0” to allow the MCA to take control of the DDR interface over from CCS.
            // (Note: this step must remain in this procedure to ensure that data path is placed into mainline
            // mode prior to running memory diagnostics. When Advanced DRAM Training executes, this step
            // becomes superfluous but not harmful. However, it's not guaranteed that Advanced DRAM Training
            // will be executed on every system configuration.)
            // Note: addr_mux_sel is set low in p9_mss_draminit(), however that might be a work-around so we
            // set it low here kind of like belt-and-suspenders. BRS
            FAPI_TRY( mss::change_addr_mux_sel(p, mss::LOW) );

            // Step Two.1: Check RCD protect time on RDIMM and LRDIMM
            // Step Two.2: Enable address inversion on each MBA for ALL CARDS

            // Start the refresh engines by setting MBAREF0Q(0) = “1”. Note that the remaining bits in
            // MBAREF0Q should retain their initialization values.
            FAPI_TRY( mss::change_refresh_enable(p, mss::HIGH) );

            // Power management is handled in the init file. (or should be BRS)

            // Enabling periodic calibration
            FAPI_TRY( mss::enable_periodic_cal(p) );

            // Step Six: Setup Control Bit ECC
            FAPI_TRY( mss::enable_read_ecc(p) );

            // At this point the DDR interface must be monitored for memory errors. Memory related FIRs should be unmasked.

            // Cram a fast write, followed by a read in here for giggles
            {
                mss::mcbist::program<TARGET_TYPE_MCBIST> l_program;
                uint64_t l_start = 0;
                uint64_t l_end = 0;
                uint64_t l_pattern = 0;

                // Write
                {
                    // Uses address register set 0
                    mss::mcbist::subtest_t<TARGET_TYPE_MCBIST> l_fw_subtest =
                        mss::mcbist::write_subtest<TARGET_TYPE_MCBIST>();
                    l_fw_subtest.enable_port(mss::index(p));

                    // HACK: We only need to worry about the DIMM in slot 0 right now
                    l_fw_subtest.enable_dimm(0);
                    l_program.iv_subtests.push_back(l_fw_subtest);
                }

                // Read
                {
                    // Uses address register set 0
                    mss::mcbist::subtest_t<TARGET_TYPE_MCBIST> l_fr_subtest =
                        mss::mcbist::read_subtest<TARGET_TYPE_MCBIST>();
                    l_fr_subtest.enable_port(mss::index(p));

                    // HACK: We only need to worry about the DIMM in slot 0 right now
                    l_fr_subtest.enable_dimm(0);
                    l_program.iv_subtests.push_back(l_fr_subtest);
                }

                FAPI_TRY( mss::mcbist_start_addr(p, l_start) );
                FAPI_TRY( mss::mcbist_end_addr(p, l_end) );

                // TK: calculate proper polling based on address range

                // Setup a nice pattern for writing
                FAPI_TRY( mss::mcbist_write_data(i_target, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD0Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD1Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD2Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD3Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD4Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD5Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD6Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD7Q, l_pattern) );

                // Sanity check - can't do much if end is before start.
                // This is either a programming error or a mistake in attribute settings. So we'll just assert.
                if (l_end < l_start)
                {
                    FAPI_ERR("mcbist end address is less than mcbist starting address. s: 0x%x e: 0x%x", l_start, l_end);
                    fapi2::Assert(false);
                }

                // By default we're in maint address mode so we do a start + len and the 'BIST increments for us.
                // By default, the write subtest uses the 0'th address start/end registers.
                mss::mcbist::config_address_range0(i_target, l_start, l_end - l_start);

                // Just one port for now. Per Shelton we need to set this in maint adress mode
                // even tho we specify the port/dimm in the subtest.
                fapi2::buffer<uint8_t> l_port;
                l_port.setBit(mss::pos(p));
                l_program.select_ports(l_port >> 4);

                // Kick it off, wait for a result
                FAPI_TRY( mss::mcbist::execute(i_target, l_program) );

                // Just because the program executed and no MCBIST failure was reported, it is poosible that
                // there were address errors. An address error in the only address in a range causes the
                // 'BIST to skip that command. Since it's the only address, the subtest (or program) can
                // complete succedssfully even though nothing actually happend.
                // For now, just dump the registers and vgrep for errors. BRS
                FAPI_TRY( mss::dump_regs<TARGET_TYPE_MCBIST>(i_target) );
            }
        }

    fapi_try_exit:
        FAPI_INF("End draminit MC");
        return fapi2::current_err;
    }
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
/**
 *
 * @author David N. Bertoni (david_n_bertoni@lotus.com)
 * */

// Base class header file.
#include "ProblemListenerDefault.hpp"

#include <XalanDOM/XalanNode.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/PrintWriter.hpp>

#include <XSLT/ElemTemplateElement.hpp>

static const char* const	errorHeader = "error: ";
static const char* const	warningHeader = "warning: ";

static const char* const	xslHeader = "XSLT ";
static const char* const	xmlHeader = "XML ";
static const char* const	xpathHeader = "XPath ";

static const char* const	styleTreeNodeHeader = ", style tree node: ";
static const char* const	sourceTreeNodeHeader = ", source tree node: ";
static const char* const	locationOpen = " (";
static const char* const	uriHeader = "";
static const char* const	lineNoHeader = ", line ";
static const char* const	charOffsetHeader = ", column ";
static const char* const	locationClose = ")";

ProblemListenerDefault::ProblemListenerDefault(PrintWriter*		pw) :
	ProblemListener(),
	m_pw(pw)
{
}

ProblemListenerDefault::~ProblemListenerDefault()
{
}

void
ProblemListenerDefault::setPrintWriter(PrintWriter*		pw)
{
	m_pw = pw;
}

void
ProblemListenerDefault::problem(
			eProblemSource			where,
			eClassification			classification,
			const XalanNode*		sourceNode,
			const XalanNode*		styleNode,
			const XalanDOMString&	msg,
			const XalanDOMChar*		uri,
			int						lineNo,
			int						charOffset)
{
	if (m_pw != 0)
	{
		problem(*m_pw, where, classification, sourceNode, styleNode, msg, uri, lineNo, charOffset);
	}
}

void
ProblemListenerDefault::problem(
			PrintWriter&			pw,
			eProblemSource			where,
			eClassification			classification,
			const XalanNode*		sourceNode,
			const XalanNode*		styleNode,
			const XalanDOMString&	msg,
			const XalanDOMChar*		uri,
			int						lineNo,
			int						charOffset)
{
	if (eXMLPARSER == where)
	{
		pw.print(xmlHeader);
	}
	else if (eXPATH == where)
	{
		pw.print(xpathHeader);
	}
	else
	{
		pw.print(xslHeader);
	}

	if (eERROR == classification)
	{
		pw.print(errorHeader);
	}
	else
	{
		pw.print(warningHeader);
	}

	pw.print(msg);

	if (0 != styleNode)
	{
		pw.print(styleTreeNodeHeader);
		pw.print(styleNode->getNodeName());
	}

	if (0 != sourceNode)
	{
		pw.print(sourceTreeNodeHeader);
		pw.print(sourceNode->getNodeName());
	}

	pw.print(locationOpen);

	if (0 != uri)
	{
		pw.print(uriHeader);
		pw.print(uri);
	}

	pw.print(lineNoHeader);
	pw.print(lineNo);

	pw.print(charOffsetHeader);
	pw.print(charOffset);

	pw.print(locationClose);

	pw.println();
}
<commit_msg>Added new header for message classification.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
/**
 *
 * @author David N. Bertoni (david_n_bertoni@lotus.com)
 * */

// Base class header file.
#include "ProblemListenerDefault.hpp"

#include <XalanDOM/XalanNode.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/PrintWriter.hpp>

#include <XSLT/ElemTemplateElement.hpp>

static const char* const	errorHeader = "error: ";
static const char* const	warningHeader = "warning: ";
static const char* const	messageHeader = "message: ";

static const char* const	xslHeader = "XSLT ";
static const char* const	xmlHeader = "XML ";
static const char* const	xpathHeader = "XPath ";

static const char* const	styleTreeNodeHeader = ", style tree node: ";
static const char* const	sourceTreeNodeHeader = ", source tree node: ";
static const char* const	locationOpen = " (";
static const char* const	uriHeader = "";
static const char* const	lineNoHeader = ", line ";
static const char* const	charOffsetHeader = ", column ";
static const char* const	locationClose = ")";

ProblemListenerDefault::ProblemListenerDefault(PrintWriter*		pw) :
	ProblemListener(),
	m_pw(pw)
{
}

ProblemListenerDefault::~ProblemListenerDefault()
{
}

void
ProblemListenerDefault::setPrintWriter(PrintWriter*		pw)
{
	m_pw = pw;
}

void
ProblemListenerDefault::problem(
			eProblemSource			where,
			eClassification			classification,
			const XalanNode*		sourceNode,
			const XalanNode*		styleNode,
			const XalanDOMString&	msg,
			const XalanDOMChar*		uri,
			int						lineNo,
			int						charOffset)
{
	if (m_pw != 0)
	{
		problem(*m_pw, where, classification, sourceNode, styleNode, msg, uri, lineNo, charOffset);
	}
}

void
ProblemListenerDefault::problem(
			PrintWriter&			pw,
			eProblemSource			where,
			eClassification			classification,
			const XalanNode*		sourceNode,
			const XalanNode*		styleNode,
			const XalanDOMString&	msg,
			const XalanDOMChar*		uri,
			int						lineNo,
			int						charOffset)
{
	if (eXMLPARSER == where)
	{
		pw.print(xmlHeader);
	}
	else if (eXPATH == where)
	{
		pw.print(xpathHeader);
	}
	else
	{
		pw.print(xslHeader);
	}

	if (eERROR == classification)
	{
		pw.print(errorHeader);
	}
	else if (eWARNING == classification)
	{
		pw.print(warningHeader);
	}
	else
	{
		pw.print(messageHeader);
	}

	pw.print(msg);

	if (0 != styleNode)
	{
		pw.print(styleTreeNodeHeader);
		pw.print(styleNode->getNodeName());
	}

	if (0 != sourceNode)
	{
		pw.print(sourceTreeNodeHeader);
		pw.print(sourceNode->getNodeName());
	}

	pw.print(locationOpen);

	if (0 != uri)
	{
		pw.print(uriHeader);
		pw.print(uri);
	}

	pw.print(lineNoHeader);
	pw.print(lineNo);

	pw.print(charOffsetHeader);
	pw.print(charOffset);

	pw.print(locationClose);

	pw.println();
}
<|endoftext|>


<commit_before>/*
 * XMLLoadHandler.cpp
 *
 *  Created on: 29.05.2017
 *      Author: Alexander
 */

#include "persistence/xml/XMLLoadHandler.hpp"

#include <sstream> // used for getLevel()
#include <boost/algorithm/string.hpp> // used for string splitting

#include "boost/exception/to_string.hpp"

#include "ecore/EObject.hpp"
#include "ecore/EStructuralFeature.hpp"

#include "xerces/XStr.hpp"
#include "xerces/WStr.hpp"
#include "xercesc/dom/DOMNamedNodeMap.hpp"

namespace persistence
{
namespace xml
{

XMLLoadHandler::XMLLoadHandler ()
{
	m_doc = nullptr;
	m_currentElement = nullptr;
}

XMLLoadHandler::~XMLLoadHandler ()
{
	if ( m_doc )
	{
		m_doc->release();
	}
}

/**/

DOMDocument *XMLLoadHandler::getDOMDocument ()
{
	return m_doc;
}

void XMLLoadHandler::setDOMDocument ( DOMDocument * doc )
{
	assert( doc );
	if ( doc == nullptr )
	{
		MSG_ERROR( MSG_FLF << " Current DOMDocument 'doc' is empty." );
		return;
	}
	m_doc = doc;
	m_rootObject = nullptr;
	m_currentElement = m_doc->getDocumentElement(); // get root element

	if ( !m_currentElement )
	{
		MSG_ERROR( MSG_FLF << " Current DOMElement (root) does not exist." );
		assert( m_currentElement );
	}

	std::string rootTagName = W(m_currentElement->getTagName());
	std::cout << "rootTagName:  " <<  rootTagName << std::endl;
	unsigned int index = rootTagName.find(':');
	if (index != std::string::npos)
	{
		m_rootPrefix = rootTagName.substr(0, index);
		m_rootName = rootTagName.substr(index+1, rootTagName.size()-index);

		std::string id = W(m_currentElement->getAttribute(X("xmi:id")));
		std::cout << "root has xmi:id " << id << std::endl;
		m_isXSIMode = id.empty();
	}
	else
	{
		MSG_ERROR(MSG_FLF << " root prefix could not be selected from root tag name '" << rootTagName << "'");
	}

	if ( m_currentElement->getNodeType() == DOMNode::ELEMENT_NODE )
	{
		m_currentElements.push_back( m_currentElement );
	}
	else
	{
		MSG_ERROR( MSG_FLF << " Current DOMElement (root) is not a DOMNode::ELEMENT_NODE." );
	}
}

unsigned int XMLLoadHandler::getNumOfChildNodes ()
{
	DOMNode *child;
	unsigned int count = 0;

	for ( child = m_currentElement->getLastChild(); child != 0; child = child->getPreviousSibling() )
	{
		if ( child->getNodeType() == DOMNode::ELEMENT_NODE )
		{
			++count;
		}
	}
	if ( count != m_currentElement->getChildElementCount() )
	{
		MSG_ERROR( MSG_FLF << "Different Number of Children" );
	}
	return count;
}

std::string XMLLoadHandler::getNextNodeName ()
{
	std::string nodeName;
	DOMNode *child;

	if ( m_currentElements.size() == 0 )
	{
		nodeName = "";
	}
	else
	{
		m_currentElement = (DOMElement*) m_currentElements.back();

		nodeName = W( m_currentElement->getNodeName() );

		m_currentElements.pop_back();

		for ( child = m_currentElement->getLastChild(); child != 0; child = child->getPreviousSibling() )
		{
			if ( child->getNodeType() == DOMNode::ELEMENT_NODE )
			{
				m_currentElements.push_back( child );
			}
		}

#if 0
		std::cout << "| DEBUG    | " << "Node-List: " << std::endl << "|          | ";
		for ( auto current_elem : m_currentElements )
		{
			std::cout << "<" << W( current_elem->getNodeName() ) << "> ";
		}
		std::cout << std::endl;
#endif
	}
	//MSG_DEBUG("NodeName: " << nodeName);

	return nodeName;
}

std::map<std::string, std::string> XMLLoadHandler::getAttributeList ()
{
	std::map<std::string, std::string> attributeList;

	DOMAttr *pAttributeNode;
	std::string aName;
	std::string aValue;

	DOMNamedNodeMap *pAttributes = m_currentElement->getAttributes();
	const XMLSize_t nSize = pAttributes->getLength();

	//MSG_DEBUG("\t" << "Attributes:");
	//MSG_DEBUG("\t" << "-----------");

	for ( XMLSize_t i = 0; i < nSize; ++i )
	{
		pAttributeNode = (DOMAttr*) pAttributes->item( i );
		// get attribute name
		aName = W( pAttributeNode->getName() );

		// get attribute type
		aValue = W( pAttributeNode->getValue() );

		// Print Attribute Name and Value
		//MSG_DEBUG"\t" << aName << "=" << aValue);

		attributeList.insert( std::pair<std::string, std::string>( aName, aValue ) );
	}

	return attributeList;
}

std::string XMLLoadHandler::getCurrentXSITypeName ()
{
	DOMAttr *pAttributeNode;
	std::string aName;

	DOMNamedNodeMap *pAttributes = m_currentElement->getAttributes();
	const XMLSize_t nSize = pAttributes->getLength();

	for ( XMLSize_t i = 0; i < nSize; ++i )
	{
		pAttributeNode = (DOMAttr*) pAttributes->item( i );
		// get attribute name
		aName = W( pAttributeNode->getName() );

		if (aName == "xsi:type" or aName == "xmi:type")
		{
			std::string _type = W(pAttributeNode->getValue());
			size_t const double_dot = _type.find(L':', 0);
			std::string _type_ns = _type.substr(0, double_dot); // TODO '_type_ns' is not used in this case
			std::string _type_name = _type.substr(double_dot + 1);
			return _type_name;
		}
	}

	return "";
}

std::string XMLLoadHandler::getCurrentXMIID()
{
	DOMAttr *pAttributeNode;
	std::string aName;

	DOMNamedNodeMap *pAttributes = m_currentElement->getAttributes();
	const XMLSize_t nSize = pAttributes->getLength();

	for ( XMLSize_t i = 0; i < nSize; ++i )
	{
		pAttributeNode = (DOMAttr*) pAttributes->item( i );
		// get attribute name
		aName = W( pAttributeNode->getName() );

		if (aName == "xmi:id")
		{
			std::string id = W(pAttributeNode->getValue());
			return id;
		}
	}

	return "";
}

std::shared_ptr<ecore::EObject> XMLLoadHandler::checkNodeType(std::shared_ptr<ecore::EObject> object)
{
	DOMNodeList* dom = m_currentElement->getChildNodes();
	const XMLSize_t size = dom->getLength();

	for (XMLSize_t i=0; i<size; i++)
	{
		DOMNode* node = dom->item(i);
		std::string nodeName = W(node->getNodeName());
		if (nodeName == "type")
		{
			std::string type = "";
			std::string href = "";
			DOMNamedNodeMap* attrListNode = node->getAttributes();
			const XMLSize_t sizeAttrList = attrListNode->getLength();

			for (XMLSize_t i = 0; i < sizeAttrList; ++i)
			{
				DOMAttr* attributeNode = (DOMAttr*) attrListNode->item( i );
				// get attribute name
				std::string aName = W( attributeNode->getName() );

				if (aName == "xmi:type")
				{
					type = W(attributeNode->getValue());
				}
				if (aName == "href")
				{
					href = W(attributeNode->getValue());
				}
			}

			type = type + " " + href;
			auto iter = m_refToObject_map.find(type);
			if (iter != m_refToObject_map.end())
			{
				return iter->second;
			}
			else
			{

				loadTypes(type);
				auto iter = m_refToObject_map.find(type);
				if (iter != m_refToObject_map.end())
				{
					return iter->second;
				}
			}
		}
	}
	return nullptr;
}

std::shared_ptr<std::string> XMLLoadHandler::getChildText()
{
	std::string value = W(m_currentElement->getTextContent());
	std::shared_ptr<std::string> valuePtr(new std::string(value));
	return valuePtr;
}

} /* namespace xml */
} /* namespace persistence */
<commit_msg>[persistence] modify namespace declaration<commit_after>/*
 * XMLLoadHandler.cpp
 *
 *  Created on: 29.05.2017
 *      Author: Alexander
 */

#include "persistence/xml/XMLLoadHandler.hpp"

#include <sstream> // used for getLevel()
#include <boost/algorithm/string.hpp> // used for string splitting

#include "boost/exception/to_string.hpp"

#include "ecore/EObject.hpp"
#include "ecore/EStructuralFeature.hpp"

#include "xerces/XStr.hpp"
#include "xerces/WStr.hpp"
#include "xercesc/dom/DOMNamedNodeMap.hpp"

using namespace persistence::xml;

XMLLoadHandler::XMLLoadHandler ()
{
	m_doc = nullptr;
	m_currentElement = nullptr;
}

XMLLoadHandler::~XMLLoadHandler ()
{
	if ( m_doc )
	{
		m_doc->release();
	}
}

/**/

DOMDocument *XMLLoadHandler::getDOMDocument ()
{
	return m_doc;
}

void XMLLoadHandler::setDOMDocument ( DOMDocument * doc )
{
	assert( doc );
	if ( doc == nullptr )
	{
		MSG_ERROR( MSG_FLF << " Current DOMDocument 'doc' is empty." );
		return;
	}
	m_doc = doc;
	m_rootObject = nullptr;
	m_currentElement = m_doc->getDocumentElement(); // get root element

	if ( !m_currentElement )
	{
		MSG_ERROR( MSG_FLF << " Current DOMElement (root) does not exist." );
		assert( m_currentElement );
	}

	std::string rootTagName = W(m_currentElement->getTagName());
	std::cout << "rootTagName:  " <<  rootTagName << std::endl;
	unsigned int index = rootTagName.find(':');
	if (index != std::string::npos)
	{
		m_rootPrefix = rootTagName.substr(0, index);
		m_rootName = rootTagName.substr(index+1, rootTagName.size()-index);

		std::string id = W(m_currentElement->getAttribute(X("xmi:id")));
		std::cout << "root has xmi:id " << id << std::endl;
		m_isXSIMode = id.empty();
	}
	else
	{
		MSG_ERROR(MSG_FLF << " root prefix could not be selected from root tag name '" << rootTagName << "'");
	}

	if ( m_currentElement->getNodeType() == DOMNode::ELEMENT_NODE )
	{
		m_currentElements.push_back( m_currentElement );
	}
	else
	{
		MSG_ERROR( MSG_FLF << " Current DOMElement (root) is not a DOMNode::ELEMENT_NODE." );
	}
}

unsigned int XMLLoadHandler::getNumOfChildNodes ()
{
	DOMNode *child;
	unsigned int count = 0;

	for ( child = m_currentElement->getLastChild(); child != 0; child = child->getPreviousSibling() )
	{
		if ( child->getNodeType() == DOMNode::ELEMENT_NODE )
		{
			++count;
		}
	}
	if ( count != m_currentElement->getChildElementCount() )
	{
		MSG_ERROR( MSG_FLF << "Different Number of Children" );
	}
	return count;
}

std::string XMLLoadHandler::getNextNodeName ()
{
	std::string nodeName;
	DOMNode *child;

	if ( m_currentElements.size() == 0 )
	{
		nodeName = "";
	}
	else
	{
		m_currentElement = (DOMElement*) m_currentElements.back();

		nodeName = W( m_currentElement->getNodeName() );

		m_currentElements.pop_back();

		for ( child = m_currentElement->getLastChild(); child != 0; child = child->getPreviousSibling() )
		{
			if ( child->getNodeType() == DOMNode::ELEMENT_NODE )
			{
				m_currentElements.push_back( child );
			}
		}

#if 0
		std::cout << "| DEBUG    | " << "Node-List: " << std::endl << "|          | ";
		for ( auto current_elem : m_currentElements )
		{
			std::cout << "<" << W( current_elem->getNodeName() ) << "> ";
		}
		std::cout << std::endl;
#endif
	}
	//MSG_DEBUG("NodeName: " << nodeName);

	return nodeName;
}

std::map<std::string, std::string> XMLLoadHandler::getAttributeList ()
{
	std::map<std::string, std::string> attributeList;

	DOMAttr *pAttributeNode;
	std::string aName;
	std::string aValue;

	DOMNamedNodeMap *pAttributes = m_currentElement->getAttributes();
	const XMLSize_t nSize = pAttributes->getLength();

	//MSG_DEBUG("\t" << "Attributes:");
	//MSG_DEBUG("\t" << "-----------");

	for ( XMLSize_t i = 0; i < nSize; ++i )
	{
		pAttributeNode = (DOMAttr*) pAttributes->item( i );
		// get attribute name
		aName = W( pAttributeNode->getName() );

		// get attribute type
		aValue = W( pAttributeNode->getValue() );

		// Print Attribute Name and Value
		//MSG_DEBUG"\t" << aName << "=" << aValue);

		attributeList.insert( std::pair<std::string, std::string>( aName, aValue ) );
	}

	return attributeList;
}

std::string XMLLoadHandler::getCurrentXSITypeName ()
{
	DOMAttr *pAttributeNode;
	std::string aName;

	DOMNamedNodeMap *pAttributes = m_currentElement->getAttributes();
	const XMLSize_t nSize = pAttributes->getLength();

	for ( XMLSize_t i = 0; i < nSize; ++i )
	{
		pAttributeNode = (DOMAttr*) pAttributes->item( i );
		// get attribute name
		aName = W( pAttributeNode->getName() );

		if (aName == "xsi:type" or aName == "xmi:type")
		{
			std::string _type = W(pAttributeNode->getValue());
			size_t const double_dot = _type.find(L':', 0);
			std::string _type_ns = _type.substr(0, double_dot); // TODO '_type_ns' is not used in this case
			std::string _type_name = _type.substr(double_dot + 1);
			return _type_name;
		}
	}

	return "";
}

std::string XMLLoadHandler::getCurrentXMIID()
{
	DOMAttr *pAttributeNode;
	std::string aName;

	DOMNamedNodeMap *pAttributes = m_currentElement->getAttributes();
	const XMLSize_t nSize = pAttributes->getLength();

	for ( XMLSize_t i = 0; i < nSize; ++i )
	{
		pAttributeNode = (DOMAttr*) pAttributes->item( i );
		// get attribute name
		aName = W( pAttributeNode->getName() );

		if (aName == "xmi:id")
		{
			std::string id = W(pAttributeNode->getValue());
			return id;
		}
	}

	return "";
}

std::shared_ptr<ecore::EObject> XMLLoadHandler::checkNodeType(std::shared_ptr<ecore::EObject> object)
{
	DOMNodeList* dom = m_currentElement->getChildNodes();
	const XMLSize_t size = dom->getLength();

	for (XMLSize_t i=0; i<size; i++)
	{
		DOMNode* node = dom->item(i);
		std::string nodeName = W(node->getNodeName());
		if (nodeName == "type")
		{
			std::string type = "";
			std::string href = "";
			DOMNamedNodeMap* attrListNode = node->getAttributes();
			const XMLSize_t sizeAttrList = attrListNode->getLength();

			for (XMLSize_t i = 0; i < sizeAttrList; ++i)
			{
				DOMAttr* attributeNode = (DOMAttr*) attrListNode->item( i );
				// get attribute name
				std::string aName = W( attributeNode->getName() );

				if (aName == "xmi:type")
				{
					type = W(attributeNode->getValue());
				}
				if (aName == "href")
				{
					href = W(attributeNode->getValue());
				}
			}

			type = type + " " + href;
			auto iter = m_refToObject_map.find(type);
			if (iter != m_refToObject_map.end())
			{
				return iter->second;
			}
			else
			{

				loadTypes(type);
				auto iter = m_refToObject_map.find(type);
				if (iter != m_refToObject_map.end())
				{
					return iter->second;
				}
			}
		}
	}
	return nullptr;
}

std::shared_ptr<std::string> XMLLoadHandler::getChildText()
{
	std::string value = W(m_currentElement->getTextContent());
	std::shared_ptr<std::string> valuePtr(new std::string(value));
	return valuePtr;
}
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "@FUNCTIONALITY_NAME@.h"
#include "@FUNCTIONALITY_NAME@Controls.h"
#include <qaction.h>
#include "icon.xpm"
#include "QmitkTreeNodeSelector.h"
#include "QmitkStdMultiWidget.h"

@FUNCTIONALITY_NAME@::@FUNCTIONALITY_NAME@(QObject *parent, const char *name, QmitkStdMultiWidget *mitkStdMultiWidget, mitk::DataTreeIteratorBase* it)
    : QmitkFunctionality(parent, name, it), m_MultiWidget(mitkStdMultiWidget), m_Controls(NULL)
{
  SetAvailability(true);
}

@FUNCTIONALITY_NAME@::~@FUNCTIONALITY_NAME@()
{}

QWidget * @FUNCTIONALITY_NAME@::CreateMainWidget(QWidget *parent)
{
  if ( m_MultiWidget == NULL )
  {
    m_MultiWidget = new QmitkStdMultiWidget( parent );
  }
  return m_MultiWidget;
}

QWidget * @FUNCTIONALITY_NAME@::CreateControlWidget(QWidget *parent)
{
  if (m_Controls == NULL)
  {
    m_Controls = new @FUNCTIONALITY_NAME@Controls(parent);
  }
  return m_Controls;
}

void @FUNCTIONALITY_NAME@::CreateConnections()
{
  if ( m_Controls )
  {
    connect( (QObject*)(m_Controls->m_TreeNodeSelector), SIGNAL(Activated(mitk::DataTreeIteratorClone)),(QObject*) this, SLOT(ImageSelected(mitk::DataTreeIteratorClone)) );
  }
}

QAction * @FUNCTIONALITY_NAME@::CreateAction(QActionGroup *parent)
{
  QAction* action;
  action = new QAction( tr( "ToolTip" ), QPixmap((const char**)icon_xpm), tr( "MenueEintrag" ), 0, parent, "@FUNCTIONALITY_NAME@" );
  return action;
}

void @FUNCTIONALITY_NAME@::TreeChanged()
{
  m_Controls->m_TreeNodeSelector->SetDataTreeNodeIterator(this->GetDataTreeIterator());
}

void @FUNCTIONALITY_NAME@::Activated()
{
  QmitkFunctionality::Activated();
}

void @FUNCTIONALITY_NAME@::ImageSelected(mitk::DataTreeIteratorClone imageIt)
{
  std::string name;
  if (imageIt->Get()->GetName(name))
  {
    std::cout << "Tree node selected with name '" << name << "'" << std::endl;
  }
}
<commit_msg>play a bit more safe/explicit in the image-selected-procedure<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "@FUNCTIONALITY_NAME@.h"
#include "@FUNCTIONALITY_NAME@Controls.h"
#include <qaction.h>
#include "icon.xpm"
#include "QmitkTreeNodeSelector.h"
#include "QmitkStdMultiWidget.h"

@FUNCTIONALITY_NAME@::@FUNCTIONALITY_NAME@(QObject *parent, const char *name, QmitkStdMultiWidget *mitkStdMultiWidget, mitk::DataTreeIteratorBase* it)
    : QmitkFunctionality(parent, name, it), m_MultiWidget(mitkStdMultiWidget), m_Controls(NULL)
{
  SetAvailability(true);
}

@FUNCTIONALITY_NAME@::~@FUNCTIONALITY_NAME@()
{}

QWidget * @FUNCTIONALITY_NAME@::CreateMainWidget(QWidget *parent)
{
  if ( m_MultiWidget == NULL )
  {
    m_MultiWidget = new QmitkStdMultiWidget( parent );
  }
  return m_MultiWidget;
}

QWidget * @FUNCTIONALITY_NAME@::CreateControlWidget(QWidget *parent)
{
  if (m_Controls == NULL)
  {
    m_Controls = new @FUNCTIONALITY_NAME@Controls(parent);
  }
  return m_Controls;
}

void @FUNCTIONALITY_NAME@::CreateConnections()
{
  if ( m_Controls )
  {
    connect( (QObject*)(m_Controls->m_TreeNodeSelector), SIGNAL(Activated(mitk::DataTreeIteratorClone)),(QObject*) this, SLOT(ImageSelected(mitk::DataTreeIteratorClone)) );
  }
}

QAction * @FUNCTIONALITY_NAME@::CreateAction(QActionGroup *parent)
{
  QAction* action;
  action = new QAction( tr( "ToolTip" ), QPixmap((const char**)icon_xpm), tr( "MenueEintrag" ), 0, parent, "@FUNCTIONALITY_NAME@" );
  return action;
}

void @FUNCTIONALITY_NAME@::TreeChanged()
{
  m_Controls->m_TreeNodeSelector->SetDataTreeNodeIterator(this->GetDataTreeIterator());
}

void @FUNCTIONALITY_NAME@::Activated()
{
  QmitkFunctionality::Activated();
}

void @FUNCTIONALITY_NAME@::ImageSelected(mitk::DataTreeIteratorClone imageIt)
{
  assert( imageIt.IsNotNull() ); // should never fail, the selection widget cares for that

  mitk::DataTreeNode* node = imageIt->Get();
  if ( node )
  {
    // here we have a valid mitk::DataTreeNode
    std::string name;
    if (node->GetName(name))
    {
      // a property called "name" was found for this DataTreeNode
      std::cout << "Tree node selected with name '" << name << "'" << std::endl;
    }

    // a node itself is not very useful, we need its data item
    mitk::BaseData* data = node->GetData();
    if (data)
    {
      // test if this data item is an image or not (could also be a surface or something totally different)
      mitk::Image* image = dynamic_cast<mitk::Image*>( data );
      if (image)
      {
        std::cout << "Surprise: this node contains a real image dataset." << std::endl;
      }
    }
  }
}

<|endoftext|>


<commit_before>#pragma once
#include <cstdint>
#include <limits>
#include "type.hpp"

namespace spn {
	//! 表現に何ビット使うか計算
	/*! +1すればMSBの取得にもつかえる */
	template <unsigned int N>
	struct NBits {
		enum { result=1+NBits<((N)>>1)>::result };
	};
	template <>
	struct NBits<0> {
		enum { result=1 };
	};
	template <>
	struct NBits<1> {
		enum { result=1 };
	};

	//! NをLで何回割れるか(と、その余り)
	template <int N, int L, int N2=N>
	struct NDivide {
		typedef NDivide<N/L,L,N> Lower;
		enum { result=Lower::result + ((N>=L) ? 1 : 0),
				sum=N + Lower::sum,
				odd=Lower::odd };
	};
	template <int L, int N2>
	struct NDivide<0, L, N2> {
		enum { result=0,
				sum=0,
				odd=N2 };
	};

	//! コンパイル時累乗
	template <int N, int P>
	struct NPow {
		enum { result=NPow<N,P-1>::result * N };
	};
	template <int N>
	struct NPow<N,0> {
		enum { result=1 };
	};

	//! 引数のペアを全てXORしたものをORする
	inline int X_OrArgs() { return 0; }
	template <class T, class... Args>
	inline T X_OrArgs(const T& t0, const T& t1, Args... args) {
		return (t0^t1) | X_OrArgs(args...);
	}

	//! 定数Nの使用ビット
	template <int N>
	struct BitLength {
		enum { length = BitLength<(N>>1)>::length + 1 };
	};
	template <>
	struct BitLength<0> {
		enum { length = 0 };
	};

	//! ビットフィールド定義用
	template <int OFS, int LEN>
	struct BitF {
		enum { offset=OFS,
		length=LEN };
	};
	//! 特定のビットを対象として値を取得 & 代入
	/*! \param T 値を保持する型 (unsigned)
	 * 	\param OFS ビットオフセット
	 * 	\param LEN ビット長 */
	template <class T, int OFS, int LEN>
	class BitOp {
		enum { offset=OFS,
		length=LEN };
		T&	_value;
		constexpr static T MASKLOW = ((1 << LEN) - 1),
		MASK =  MASKLOW << OFS;
		// Tが非数値型だったりsignedな型ならコンパイルエラーを起こす
		using Limits = std::numeric_limits<T>;
		constexpr static int Dummy[Limits::is_specialized && Limits::is_integer && !Limits::is_signed ? 0 : -1] = {};

	public:
		template <class P>
		BitOp(P* ptr): _value(*(T*)ptr) {}
		BitOp(T* ptr): _value(*ptr) {}
		BitOp(T& ref): _value(ref) {}

		template <class V>
		BitOp& operator = (const V v) {
			// ビットクリア
			_value &= ~MASK;
			_value |= (T(v)<<OFS & MASK);
			return *this;
		}

		operator T () const {
			return (_value >> OFS) & MASKLOW;
		}
	};
	//! ワードに対するビット操作
	/*! \param WORD 値を保持する型
	 * 	\param OFS 下位ビット位置
	 * 	\param LEN 処理対象ビット幅 */
	template <class WORD, int OFS, int LEN>
	class BitSub {
		const static WORD MASKLOW = ((1 << LEN) - 1),
		MASK =  MASKLOW << OFS;
		using Word = WORD;
		Word&	_word;

	public:
		BitSub(Word& w): _word(w) {}

		template <class V>
		BitSub& operator = (const V v) {
			// ビットクリア
			_word &= ~MASK;
			_word |= (Word(v)<<OFS & MASK);
			return *this;
		}
		operator Word() const {
			return get(_word);
		}
		static Word get(const Word& w) {
			return (w >> OFS) & MASKLOW;
		}
		//! 違う基本型やビット位置でも交換可能だが、サイズ違いは駄目
		template <class T_WORD, int T_OFS>
		void swap(BitSub<T_WORD, T_OFS, LEN>& bs) noexcept {
			Word val0(*this);
			(*this) = Word(bs);
			bs = val0;
		}
	};
	//! テンプレートにてビットフィールドを定義
	/*! \param T 値を保持する型
	 \*param Args ビットフィールドを定義するBitOpクラス */
	template <class T, class... Ts>
	struct BitDef : CType<Ts...> {
		// Tが非数値型だったりsignedな型ならコンパイルエラーを起こす
		using Limits = std::numeric_limits<T>;
		constexpr static int UnsignedCheck[Limits::is_specialized && Limits::is_integer && !Limits::is_signed ? 0 : -1] = {};

		using Word = T;
	};
	//! ビットフィールドテンプレートクラス
	/*! \example
		struct MyDef : BitDef<uint32_t, BitF<0,14>, BitF<14,6>, BitF<20,12>> {

				enum { VAL0, VAL1, VAL2 }; };

		using Value = BitField<MyDef>;

		Value value;

		value.at<Value::VAL0>() = 128;

		int toGet = value.at<Value::VAL0>();

		\param BF BitDefクラス */
	template <class BF>
	struct BitField : BF {
		// BF(CTypes)から総サイズとオフセット計算
		constexpr static int maxbit = BF::template Size<>::maxbit,
							buffsize = ((maxbit-1)/8)+1;
		using Word = typename BF::Word;
		constexpr static int WordCheck[buffsize > sizeof(Word) ? -1 : 0] = {};

		Word _word;

		BitField() = default;
		BitField(const BitField& bf): _word(bf.value()) {}
		BitField(const Word& w): _word(w) {}
		Word& value() { return _word; }
		const Word& value() const { return _word; }

		template <int N>
		using BFAt = typename BF::template At<N>::type;
		template <int N>
		using BitSubT = BitSub<Word, BFAt<N>::offset, BFAt<N>::length>;

		//! ビット領域参照
		template <int N>
		BitSubT<N> at() {
			return BitSubT<N>(_word);
		}
		//! ビットフィールド値取得
		template <int N>
		Word at() const {
			return BitSubT<N>::get(_word);
		}
		//! ビット幅マスク取得
		template <int N>
		static Word length_mask() {
			return (Word(1) << BFAt<N>::length) - 1;
		}
		//! ビットマスク取得
		template <int N>
		static Word mask() {
			auto ret = length_mask<N>();
			return ret << BFAt<N>::offset;
		}

		//! ビットフィールドで使う場所以外をゼロクリアした値を取得
		Word cleanedValue() const {
			constexpr Word msk = (1 << maxbit)-1;
			return value() & msk;
		}
		bool operator == (const BitField& bf) const { return cleanedValue() == bf.cleanedValue(); }
		bool operator != (const BitField& bf) const { return !(this->operator == (bf)); }
		bool operator < (const BitField& bf) const {
			return cleanedValue() < bf.cleanedValue();
		}
	};

	struct Bit {
		static bool Check(uint32_t val, uint32_t flag) {
			return val & flag;
		}
		static void Clear(uint32_t& val, uint32_t flag) {
			val &= ~flag;
		}
		static void Set(uint32_t& val, uint32_t flag) {
			val |= flag;
		}
		//! ビットチェックした結果を返し、ビットは消去する
		static bool ChClear(uint32_t& val, uint32_t flag) {
			bool bRet = Check(val, flag);
			Clear(val, flag);
			return bRet;
		}
		//! 入力値の一番左のビットだけを残す
		static uint32_t LowClear(uint32_t x) {
			x = x | (x >> 1);
			x = x | (x >> 2);
			x = x | (x >> 4);
			x = x | (x >> 8);
			x = x | (x >>16);
			return x & ~(x>>1);
		}
		//! ビットが幾つ立っているか数える
		static int Count(uint32_t v) {
			uint32_t tmp = v & 0xaaaaaaaa;
			v &= 0x55555555;
			v = v + (tmp >> 1);
			tmp = v & 0xcccccccc;
			v &= 0x33333333;
			v = v + (tmp >> 2);
			tmp = v & 0xf0f0f0f0;
			v &= 0x0f0f0f0f;
			v = v + (tmp >> 4);
			tmp = v & 0xff00ff00;
			v &= 0x00ff00ff;
			v = v + (tmp >> 8);
			tmp = v & 0xffff0000;
			v &= 0x0000ffff;
			v = v + (tmp >> 16);
			return v;
		}
		//! 入力値が0なら0, それ以外は~0を返す
		static int32_t ZeroOrFull(int32_t v) {
			return (v | -v) >> 31;
		}

		// ビットの位置を計算
		#ifdef USEASM_BITSEARCH
			static uint32_t MSB_N(uint32_t x) {
				uint32_t ret;
				asm("movl %1, %%eax;"
					"orl $0x01, %%eax;"
					"bsrl %%eax, %0;"
					:"=r" (ret)
					:"r" (x)
					:"%eax"
				);
				return ret;
			}
			static uint32_t LSB_N(uint32_t x) {
				uint32_t ret;
				asm("movl %1, %%eax;"
					"orl $0x80000000, %%eax;"
					"bsfl %%eax, %0;"
					:"=r" (ret)
					:"r" (x)
					:"%eax"
				);
				return ret;
			}
		#else
			const static char NLRZ_TABLE[33];
			//! most significant bit を取得
			/*! もし入力値が0の場合は0を返す */
			static uint32_t MSB_N(uint32_t x) {
				return NLRZ_TABLE[0x0aec7cd2U * LowClear(x) >> 27];
			}
			//! least significant bit を取得
			/*! もし入力値が0の場合は31を返す */
			static uint32_t LSB_N(uint32_t x) {
				return NLRZ_TABLE[0x0aec7cd2U * (x & -x) >> 27];
			}
		#endif

		//! 32bit値のエンディアン変換 [little -> bit]
		static uint32_t LtoB32(uint32_t v) {
			uint32_t a = v<<24,
				b = (v&0xff00)<<8,
				c = (v>>8)&0xff00,
				d = v>>24;
			return a|b|c|d;
		}
		//! 16bit値のエンディアン変換 [little -> bit]
		static uint32_t LtoB16(uint32_t v) {
			uint32_t a = (v>>8)&0xff,
				b = (v&0xff)<<8;
			return a|b;
		}
	};
}
namespace std {
	template <class W0, int OFS0, class W1, int OFS1, int LEN>
	inline void swap(spn::BitSub<W0,OFS0,LEN>&& b0, spn::BitSub<W1,OFS1,LEN>&& b1) { b0.swap(b1); }
	template <class W0, int OFS0, class W1, int OFS1, int LEN>
	inline void swap(spn::BitSub<W0,OFS0,LEN>&& b0, spn::BitSub<W1,OFS1,LEN>& b1) { b0.swap(b1); }
	template <class W0, int OFS0, class W1, int OFS1, int LEN>
	inline void swap(spn::BitSub<W0,OFS0,LEN>& b0, spn::BitSub<W1,OFS1,LEN>&& b1) { b0.swap(b1); }
}
<commit_msg>Bit::LowClear() をテンプレート対応にした<commit_after>#pragma once
#include <cstdint>
#include <limits>
#include "type.hpp"

namespace spn {
	//! 表現に何ビット使うか計算
	/*! +1すればMSBの取得にもつかえる */
	template <unsigned int N>
	struct NBits {
		enum { result=1+NBits<((N)>>1)>::result };
	};
	template <>
	struct NBits<0> {
		enum { result=1 };
	};
	template <>
	struct NBits<1> {
		enum { result=1 };
	};

	//! NをLで何回割れるか(と、その余り)
	template <int N, int L, int N2=N>
	struct NDivide {
		typedef NDivide<N/L,L,N> Lower;
		enum { result=Lower::result + ((N>=L) ? 1 : 0),
				sum=N + Lower::sum,
				odd=Lower::odd };
	};
	template <int L, int N2>
	struct NDivide<0, L, N2> {
		enum { result=0,
				sum=0,
				odd=N2 };
	};

	//! コンパイル時累乗
	template <int N, int P>
	struct NPow {
		enum { result=NPow<N,P-1>::result * N };
	};
	template <int N>
	struct NPow<N,0> {
		enum { result=1 };
	};

	//! 引数のペアを全てXORしたものをORする
	inline int X_OrArgs() { return 0; }
	template <class T, class... Args>
	inline T X_OrArgs(const T& t0, const T& t1, Args... args) {
		return (t0^t1) | X_OrArgs(args...);
	}

	//! 定数Nの使用ビット
	template <int N>
	struct BitLength {
		enum { length = BitLength<(N>>1)>::length + 1 };
	};
	template <>
	struct BitLength<0> {
		enum { length = 0 };
	};

	//! ビットフィールド定義用
	template <int OFS, int LEN>
	struct BitF {
		enum { offset=OFS,
		length=LEN };
	};
	//! 特定のビットを対象として値を取得 & 代入
	/*! \param T 値を保持する型 (unsigned)
	 * 	\param OFS ビットオフセット
	 * 	\param LEN ビット長 */
	template <class T, int OFS, int LEN>
	class BitOp {
		enum { offset=OFS,
		length=LEN };
		T&	_value;
		constexpr static T MASKLOW = ((1 << LEN) - 1),
		MASK =  MASKLOW << OFS;
		// Tが非数値型だったりsignedな型ならコンパイルエラーを起こす
		using Limits = std::numeric_limits<T>;
		constexpr static int Dummy[Limits::is_specialized && Limits::is_integer && !Limits::is_signed ? 0 : -1] = {};

	public:
		template <class P>
		BitOp(P* ptr): _value(*(T*)ptr) {}
		BitOp(T* ptr): _value(*ptr) {}
		BitOp(T& ref): _value(ref) {}

		template <class V>
		BitOp& operator = (const V v) {
			// ビットクリア
			_value &= ~MASK;
			_value |= (T(v)<<OFS & MASK);
			return *this;
		}

		operator T () const {
			return (_value >> OFS) & MASKLOW;
		}
	};
	//! ワードに対するビット操作
	/*! \param WORD 値を保持する型
	 * 	\param OFS 下位ビット位置
	 * 	\param LEN 処理対象ビット幅 */
	template <class WORD, int OFS, int LEN>
	class BitSub {
		const static WORD MASKLOW = ((1 << LEN) - 1),
		MASK =  MASKLOW << OFS;
		using Word = WORD;
		Word&	_word;

	public:
		BitSub(Word& w): _word(w) {}

		template <class V>
		BitSub& operator = (const V v) {
			// ビットクリア
			_word &= ~MASK;
			_word |= (Word(v)<<OFS & MASK);
			return *this;
		}
		operator Word() const {
			return get(_word);
		}
		static Word get(const Word& w) {
			return (w >> OFS) & MASKLOW;
		}
		//! 違う基本型やビット位置でも交換可能だが、サイズ違いは駄目
		template <class T_WORD, int T_OFS>
		void swap(BitSub<T_WORD, T_OFS, LEN>& bs) noexcept {
			Word val0(*this);
			(*this) = Word(bs);
			bs = val0;
		}
	};
	//! テンプレートにてビットフィールドを定義
	/*! \param T 値を保持する型
	 \*param Args ビットフィールドを定義するBitOpクラス */
	template <class T, class... Ts>
	struct BitDef : CType<Ts...> {
		// Tが非数値型だったりsignedな型ならコンパイルエラーを起こす
		using Limits = std::numeric_limits<T>;
		constexpr static int UnsignedCheck[Limits::is_specialized && Limits::is_integer && !Limits::is_signed ? 0 : -1] = {};

		using Word = T;
	};
	//! ビットフィールドテンプレートクラス
	/*! \example
		struct MyDef : BitDef<uint32_t, BitF<0,14>, BitF<14,6>, BitF<20,12>> {

				enum { VAL0, VAL1, VAL2 }; };

		using Value = BitField<MyDef>;

		Value value;

		value.at<Value::VAL0>() = 128;

		int toGet = value.at<Value::VAL0>();

		\param BF BitDefクラス */
	template <class BF>
	struct BitField : BF {
		// BF(CTypes)から総サイズとオフセット計算
		constexpr static int maxbit = BF::template Size<>::maxbit,
							buffsize = ((maxbit-1)/8)+1;
		using Word = typename BF::Word;
		constexpr static int WordCheck[buffsize > sizeof(Word) ? -1 : 0] = {};

		Word _word;

		BitField() = default;
		BitField(const BitField& bf): _word(bf.value()) {}
		BitField(const Word& w): _word(w) {}
		Word& value() { return _word; }
		const Word& value() const { return _word; }

		template <int N>
		using BFAt = typename BF::template At<N>::type;
		template <int N>
		using BitSubT = BitSub<Word, BFAt<N>::offset, BFAt<N>::length>;

		//! ビット領域参照
		template <int N>
		BitSubT<N> at() {
			return BitSubT<N>(_word);
		}
		//! ビットフィールド値取得
		template <int N>
		Word at() const {
			return BitSubT<N>::get(_word);
		}
		//! ビット幅マスク取得
		template <int N>
		static Word length_mask() {
			return (Word(1) << BFAt<N>::length) - 1;
		}
		//! ビットマスク取得
		template <int N>
		static Word mask() {
			auto ret = length_mask<N>();
			return ret << BFAt<N>::offset;
		}

		//! ビットフィールドで使う場所以外をゼロクリアした値を取得
		Word cleanedValue() const {
			constexpr Word msk = (1 << maxbit)-1;
			return value() & msk;
		}
		bool operator == (const BitField& bf) const { return cleanedValue() == bf.cleanedValue(); }
		bool operator != (const BitField& bf) const { return !(this->operator == (bf)); }
		bool operator < (const BitField& bf) const {
			return cleanedValue() < bf.cleanedValue();
		}
	};

	struct Bit {
		static bool Check(uint32_t val, uint32_t flag) {
			return val & flag;
		}
		static void Clear(uint32_t& val, uint32_t flag) {
			val &= ~flag;
		}
		static void Set(uint32_t& val, uint32_t flag) {
			val |= flag;
		}
		//! ビットチェックした結果を返し、ビットは消去する
		static bool ChClear(uint32_t& val, uint32_t flag) {
			bool bRet = Check(val, flag);
			Clear(val, flag);
			return bRet;
		}
		//! 入力値の一番左のビットだけを残す
		template <class T, class=typename std::enable_if<std::is_unsigned<T>::value>::type*>
		static T LowClear(T x) {
			x = x | (x >> 1);
			x = x | (x >> 2);
			x = x | (x >> 4);
			x = x | (x >> 8);
			x = x | (x >>16);
			return x & ~(x>>1);
		}
		//! ビットが幾つ立っているか数える
		static int Count(uint32_t v) {
			uint32_t tmp = v & 0xaaaaaaaa;
			v &= 0x55555555;
			v = v + (tmp >> 1);
			tmp = v & 0xcccccccc;
			v &= 0x33333333;
			v = v + (tmp >> 2);
			tmp = v & 0xf0f0f0f0;
			v &= 0x0f0f0f0f;
			v = v + (tmp >> 4);
			tmp = v & 0xff00ff00;
			v &= 0x00ff00ff;
			v = v + (tmp >> 8);
			tmp = v & 0xffff0000;
			v &= 0x0000ffff;
			v = v + (tmp >> 16);
			return v;
		}
		//! 入力値が0なら0, それ以外は~0を返す
		static int32_t ZeroOrFull(int32_t v) {
			return (v | -v) >> 31;
		}

		// ビットの位置を計算
		#ifdef USEASM_BITSEARCH
			static uint32_t MSB_N(uint32_t x) {
				uint32_t ret;
				asm("movl %1, %%eax;"
					"orl $0x01, %%eax;"
					"bsrl %%eax, %0;"
					:"=r" (ret)
					:"r" (x)
					:"%eax"
				);
				return ret;
			}
			static uint32_t LSB_N(uint32_t x) {
				uint32_t ret;
				asm("movl %1, %%eax;"
					"orl $0x80000000, %%eax;"
					"bsfl %%eax, %0;"
					:"=r" (ret)
					:"r" (x)
					:"%eax"
				);
				return ret;
			}
		#else
			const static char NLRZ_TABLE[33];
			//! most significant bit を取得
			/*! もし入力値が0の場合は0を返す */
			static uint32_t MSB_N(uint32_t x) {
				return NLRZ_TABLE[0x0aec7cd2U * LowClear(x) >> 27];
			}
			//! least significant bit を取得
			/*! もし入力値が0の場合は31を返す */
			static uint32_t LSB_N(uint32_t x) {
				return NLRZ_TABLE[0x0aec7cd2U * (x & -x) >> 27];
			}
		#endif

		//! 32bit値のエンディアン変換 [little -> bit]
		static uint32_t LtoB32(uint32_t v) {
			uint32_t a = v<<24,
				b = (v&0xff00)<<8,
				c = (v>>8)&0xff00,
				d = v>>24;
			return a|b|c|d;
		}
		//! 16bit値のエンディアン変換 [little -> bit]
		static uint32_t LtoB16(uint32_t v) {
			uint32_t a = (v>>8)&0xff,
				b = (v&0xff)<<8;
			return a|b;
		}
	};
}
namespace std {
	template <class W0, int OFS0, class W1, int OFS1, int LEN>
	inline void swap(spn::BitSub<W0,OFS0,LEN>&& b0, spn::BitSub<W1,OFS1,LEN>&& b1) { b0.swap(b1); }
	template <class W0, int OFS0, class W1, int OFS1, int LEN>
	inline void swap(spn::BitSub<W0,OFS0,LEN>&& b0, spn::BitSub<W1,OFS1,LEN>& b1) { b0.swap(b1); }
	template <class W0, int OFS0, class W1, int OFS1, int LEN>
	inline void swap(spn::BitSub<W0,OFS0,LEN>& b0, spn::BitSub<W1,OFS1,LEN>&& b1) { b0.swap(b1); }
}
<|endoftext|>


<commit_before>/*
 * storeBCDvalueOfVxInsrtruction.cpp
 *
 *  Created on: Jul 23, 2016
 *      Author: Tomas Stibrany
 */
#include "storeBCDvalueOfVxInstruction.hpp"
#include "../cpu.hpp"

using namespace chip8::core::cpu::instructions;
using namespace chip8::core::cpu;

StoreBCDvalueOfVxInstruction::StoreBCDvalueOfVxInstruction(u8 registerXindex, CPU *cpu) : IInstruction()
{
	SetRegisterXindex(registerXindex);
	this->cpu = cpu;
}

StoreBCDvalueOfVxInstruction::~StoreBCDvalueOfVxInstruction()
{
}

void StoreBCDvalueOfVxInstruction::Execute()
{
	u8 registerXvalue = this->cpu->ReadFromGeneralPurposeRegister(this->registerXindex);
	// Calculate BCD
	u8 bcdHundreds = registerXvalue / 100;
	u8 bcdTens = (registerXvalue - bcdHundreds) / 10;
	u8 bcdOnes = (registerXvalue - bcdHundreds - bcdTens);
	// Store BCD
	u16 address = this->cpu->ReadFromIndexRegister();
	this->cpu->WriteToMemory(bcdHundreds);

	this->cpu->WriteToIndexRegister(address + 1);
	this->cpu->WriteToMemory(bcdTens);

	this->cpu->WriteToIndexRegister(address + 2);
	this->cpu->WriteToMemory(bcdOnes);
}

void StoreBCDvalueOfVxInstruction::SetRegisterXindex(u8 registerIndex)
{
	this->registerXindex = registerIndex;
}

<commit_msg>[CHG] StoreBCD instructions restores Index register value<commit_after>/*
 * storeBCDvalueOfVxInsrtruction.cpp
 *
 *  Created on: Jul 23, 2016
 *      Author: Tomas Stibrany
 */
#include "storeBCDvalueOfVxInstruction.hpp"
#include "../cpu.hpp"

using namespace chip8::core::cpu::instructions;
using namespace chip8::core::cpu;

StoreBCDvalueOfVxInstruction::StoreBCDvalueOfVxInstruction(u8 registerXindex, CPU *cpu) : IInstruction()
{
	SetRegisterXindex(registerXindex);
	this->cpu = cpu;
}

StoreBCDvalueOfVxInstruction::~StoreBCDvalueOfVxInstruction()
{
}

void StoreBCDvalueOfVxInstruction::Execute()
{
	u8 registerXvalue = this->cpu->ReadFromGeneralPurposeRegister(this->registerXindex);
	// Calculate BCD
	u8 bcdHundreds = registerXvalue / 100;
	u8 bcdTens = (registerXvalue - bcdHundreds) / 10;
	u8 bcdOnes = (registerXvalue - bcdHundreds - bcdTens);
	// Store BCD
	u16 address = this->cpu->ReadFromIndexRegister();
	this->cpu->WriteToMemory(bcdHundreds);

	this->cpu->WriteToIndexRegister(address + 1);
	this->cpu->WriteToMemory(bcdTens);

	this->cpu->WriteToIndexRegister(address + 2);
	this->cpu->WriteToMemory(bcdOnes);
	// Restore Index register
	this->cpu->WriteToIndexRegister(address);
}

void StoreBCDvalueOfVxInstruction::SetRegisterXindex(u8 registerIndex)
{
	this->registerXindex = registerIndex;
}

<|endoftext|>


<commit_before>#include "Timer.h"

namespace fse
{
	Timer::Timer(Scene* scene) : FSEObject(scene)
	{

	}

	Timer::~Timer()
	{

	}

	void Timer::update(float deltaTime)
	{
		if (active_)
		{
			elapsed_time_ += deltaTime;
			while (elapsed_time_ * 1000 >= interval_)
			{
				elapsed_time_ -= interval_*0.001f;
				timeout_();
				if (single_shot_)
				{
					active_ = false;
					getScene()->destroyFSEObject(this);
					break;
				}
			}

		}
	}

	void Timer::draw(sf::RenderTarget & target)
	{
	}

	void Timer::spawned()
	{
	}

	void Timer::stop()
	{
		active_ = false;
	}

	void Timer::setInterval(int msecs)
	{
		interval_ = msecs;
	}

	bool Timer::isActive() const
	{
		return active_;
	}

	void Timer::setSingleShot(bool singleShot)
	{
		single_shot_ = singleShot;
	}

}

#include <rttr/registration>
RTTR_REGISTRATION
{
	using namespace rttr;

	registration::class_<fse::Timer>("fse::Timer")
	.constructor<>([](fse::Scene* scene)
	{
		scene->createFSEObject<fse::Timer>();
		return nullptr;
	})
	(
		parameter_names("scene"),
		metadata("CHAI_CTOR", true)
	)
	.constructor<>([](fse::Scene* scene, std::function<void(fse::FSEObject*)> func)
	{
		scene->createFSEObject<fse::Timer>(func);
		return nullptr;
	})
	(
		parameter_names("scene", "spawnedSlot"),
		metadata("CHAI_CTOR", true)
	)
	.property_readonly("active_", &fse::Timer::active_)
	.property("single_shot_", &fse::Timer::single_shot_)
	.property("interval_", &fse::Timer::interval_)
	//.method("start", [](fse::Timer* timer, auto slot) { timer->start(slot); })
	.method("stop", &fse::Timer::stop)
	;
}
<commit_msg>Timer: catch chaiscript exceptions<commit_after>#include "Timer.h"

#include "../Application.h"
#include <regex>

namespace fse
{
	Timer::Timer(Scene* scene) : FSEObject(scene)
	{

	}

	Timer::~Timer()
	{

	}

	void Timer::update(float deltaTime)
	{
		if (active_)
		{
			elapsed_time_ += deltaTime;
			while (elapsed_time_ * 1000 >= interval_)
			{
				elapsed_time_ -= interval_*0.001f;
				//since chaiscript functions can be run, we have to catch chai exceptions
				try
				{
					timeout_();
				} catch(chaiscript::exception::eval_error& e) {
					const std::string evalString = "puts(\"" + std::regex_replace(e.pretty_print(), std::regex("(\")"), "\\\"") + "\");";
					scene_->getApplication()->getChai()->eval(evalString);
				} catch (std::exception& e) {
					const std::string evalString = "puts(\"" + std::regex_replace(e.what(), std::regex("(\")"), "\\\"") + "\");";
				} catch (...) {

				}
				if (single_shot_)
				{
					active_ = false;
					getScene()->destroyFSEObject(this);
					break;
				}
			}

		}
	}

	void Timer::draw(sf::RenderTarget & target)
	{
	}

	void Timer::spawned()
	{
	}

	void Timer::stop()
	{
		active_ = false;
	}

	void Timer::setInterval(int msecs)
	{
		interval_ = msecs;
	}

	bool Timer::isActive() const
	{
		return active_;
	}

	void Timer::setSingleShot(bool singleShot)
	{
		single_shot_ = singleShot;
	}

}

#include <rttr/registration>
RTTR_REGISTRATION
{
	using namespace rttr;

	registration::class_<fse::Timer>("fse::Timer")
	.constructor<>([](fse::Scene* scene)
	{
		scene->createFSEObject<fse::Timer>();
		return nullptr;
	})
	(
		parameter_names("scene"),
		metadata("CHAI_CTOR", true)
	)
	.constructor<>([](fse::Scene* scene, std::function<void(fse::FSEObject*)> func)
	{
		scene->createFSEObject<fse::Timer>(func);
		return nullptr;
	})
	(
		parameter_names("scene", "spawnedSlot"),
		metadata("CHAI_CTOR", true)
	)
	.property_readonly("active_", &fse::Timer::active_)
	.property("single_shot_", &fse::Timer::single_shot_)
	.property("interval_", &fse::Timer::interval_)
	//.method("start", [](fse::Timer* timer, auto slot) { timer->start(slot); })
	.method("stop", &fse::Timer::stop)
	;
}
<|endoftext|>