<commit_before>/////////////////////////////////////////
//
//             OpenLieroX
//
// code under LGPL, based on JasonBs work,
// enhanced by Dark Charlie and Albert Zeyer
//
//
/////////////////////////////////////////

#include "SkinnedGUI/CGuiSkin.h"
#include "FindFile.h"
#include "StringUtils.h"
#include "AuxLib.h"
#include "Cursor.h"

#include "SkinnedGUI/CWidget.h"

// Widgets
#include "SkinnedGUI/CAnimation.h"
#include "SkinnedGUI/CButton.h"
#include "SkinnedGUI/CCheckbox.h"
#include "SkinnedGUI/CCombobox.h"
#include "SkinnedGUI/CDialog.h"
#include "SkinnedGUI/CGuiSkinnedLayout.h"
#include "SkinnedGUI/CImageButton.h"
#include "SkinnedGUI/CInputBox.h"
#include "SkinnedGUI/CLabel.h"
#include "SkinnedGUI/CLine.h"
#include "SkinnedGUI/CListview.h"
#include "SkinnedGUI/CMapEditor.h"
#include "SkinnedGUI/CMarquee.h"
#include "SkinnedGUI/CMenu.h"
#include "SkinnedGUI/CMinimap.h"
#include "SkinnedGUI/CProgressbar.h"
#include "SkinnedGUI/CScrollbar.h"
#include "SkinnedGUI/CSlider.h"
#include "SkinnedGUI/CTabControl.h"
#include "SkinnedGUI/CTextbox.h"
#include "SkinnedGUI/CToggleButton.h"

namespace SkinnedGUI {

CGuiSkin *cMainSkin = NULL;

#define SKIN_DIRECTORY (std::string("gui_skins/"))

///////////////
// Initialize skinning
bool InitializeGuiSkinning()
{
	if (!cMainSkin)
		cMainSkin = new CGuiSkin();

	if (tLXOptions)
		return cMainSkin->Load(tLXOptions->sSkinPath);
	return false;
}

//////////////////
// Shutdown skinning
void ShutdownGuiSkinning()
{
	if (cMainSkin)
		delete cMainSkin;
	cMainSkin = NULL;
}

/////////////
// Constructor
CGuiSkin::CGuiSkin()
{
	sPath = SKIN_DIRECTORY + "default";
	sName = "Default";
	sAuthor = "OpenLieroX Development Team";

	cActiveLayout = NULL;
	cPreviousLayout = NULL;

	iBufferCount = 1;

	// Listen to the events
	sdlEvents[SDL_KEYDOWN].handler() += getEventHandler(this, &CGuiSkin::SDL_OnKeyDown);
	sdlEvents[SDL_KEYUP].handler() += getEventHandler(this, &CGuiSkin::SDL_OnKeyUp);
	sdlEvents[SDL_MOUSEMOTION].handler() += getEventHandler(this, &CGuiSkin::SDL_OnMouseMotion);
	sdlEvents[SDL_MOUSEBUTTONDOWN].handler() += getEventHandler(this, &CGuiSkin::SDL_OnMouseButtonDown);
	sdlEvents[SDL_MOUSEBUTTONUP].handler() += getEventHandler(this, &CGuiSkin::SDL_OnMouseButtonUp);
	sdlEvents[SDL_MOUSEWHEEL].handler() += getEventHandler(this, &CGuiSkin::SDL_OnMouseWheel);

	onAddWidget.handler() = getEventHandler(this, &CGuiSkin::SDL_OnAddWidget);;
	onDestroyWidget.handler() = getEventHandler(this, &CGuiSkin::SDL_OnDestroyWidget);
}

//////////////
// Destructor
CGuiSkin::~CGuiSkin()
{
	sdlEvents[SDL_KEYDOWN].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnKeyDown);
	sdlEvents[SDL_KEYUP].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnKeyUp);
	sdlEvents[SDL_MOUSEMOTION].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnMouseMotion);
	sdlEvents[SDL_MOUSEBUTTONDOWN].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnMouseButtonDown);
	sdlEvents[SDL_MOUSEBUTTONUP].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnMouseButtonUp);
	sdlEvents[SDL_MOUSEWHEEL].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnMouseWheel);

	// No effects, just destroy
	if (cActiveLayout)
		delete cActiveLayout;
	if (cPreviousLayout)
		delete cPreviousLayout;
}

////////////////
// Load the GUI skin
bool CGuiSkin::Load(const std::string& skin)
{
	sPath = SKIN_DIRECTORY + skin;

	// TODO: author + name
	// TODO: verify that the important files exist

	return true;
}

//////////////////
// Open a layout
bool CGuiSkin::OpenLayout(const std::string &layout)
{
	// Because of the GUI effects we have to remember the old layout for a while
	if (cActiveLayout)  {
		cActiveLayout->Destroy();

		if (cPreviousLayout) // Another layout still effecting, just quit it
			delete cPreviousLayout;

		cPreviousLayout = cActiveLayout;
	}

	// Load the new layout
	cActiveLayout = new CGuiSkinnedLayout();
	if (cActiveLayout->Load(layout, *this))  {
		cActiveLayout->DoCreate();
		return true;
	}

	return false;
}

////////////////////
// Converts the path that is relative to the skin to path relative to OLX
std::string CGuiSkin::getSkinFilePath(const std::string& file)
{
	// Check
	if (!sPath.size())
		return file;

	return JoinPaths(sPath, file);
}

///////////////////////
// Opens a file from the current skin
FILE *CGuiSkin::OpenSkinFile(const std::string &filename, const char *mode)
{
	if (!filename.size())
		return NULL;

	return OpenGameFile(getSkinFilePath(filename), mode);
}

/////////////////////
// Creates a new widget based on the tag name, returns NULL for unknown widgets
CWidget *CGuiSkin::CreateWidgetByTagName(const std::string& tagname, CContainerWidget *parent, const std::string& id)
{
	if (stringcaseequal(tagname, CAnimation::tagName()))
		return new CAnimation(id, parent);
	else if (stringcaseequal(tagname, CButton::tagName()))
		return new CButton(id, parent);
	else if (stringcaseequal(tagname, CCheckbox::tagName()))
		return new CCheckbox(id, parent);
	else if (stringcaseequal(tagname, CCombobox::tagName()))
		return new CCombobox(id, parent);
	else if (stringcaseequal(tagname, CDialog::tagName()))
		return new CDialog(id, parent);
	else if (stringcaseequal(tagname, CGuiSkinnedLayout::tagName()))
		return new CGuiSkinnedLayout(id, parent);
	else if (stringcaseequal(tagname, CImageButton::tagName()))
		return new CImageButton(id, parent);
	else if (stringcaseequal(tagname, CInputbox::tagName()))
		return new CInputbox(id, parent);
	else if (stringcaseequal(tagname, CLabel::tagName()))
		return new CLabel(id, parent);
	else if (stringcaseequal(tagname, CLine::tagName()))
		return new CLine(id, parent);
	else if (stringcaseequal(tagname, CListview::tagName()))
		return new CListview(id, parent);
	else if (stringcaseequal(tagname, CMapEditor::tagName()))
		return new CMapEditor(id, parent);
	else if (stringcaseequal(tagname, CMarquee::tagName()))
		return new CMarquee(id, parent);
	else if (stringcaseequal(tagname, CMenu::tagName()))
		return new CMenu(id, parent);
	else if (stringcaseequal(tagname, CMinimap::tagName()))
		return new CMinimap(id, parent);
	else if (stringcaseequal(tagname, CProgressBar::tagName()))
		return new CProgressBar(id, parent);
	else if (stringcaseequal(tagname, CScrollbar::tagName()))
		return new CScrollbar(id, parent);
	else if (stringcaseequal(tagname, CSlider::tagName()))
		return new CSlider(id, parent);
	else if (stringcaseequal(tagname, CTabControl::tagName()))
		return new CTabControl(id, parent);
	else if (stringcaseequal(tagname, CTextbox::tagName()))
		return new CTextbox(id, parent);
	else if (stringcaseequal(tagname, CToggleButton::tagName()))
		return new CToggleButton(id, parent);
	else
		return NULL; // Unknown widget
}

//////////////////
// Draws the content and processes things
void CGuiSkin::Frame()
{
	// Reset the game cursor
	SetGameCursor(CUR_ARROW);

	if (cPreviousLayout)  {
		if (cPreviousLayout->needsRepaint())
			cPreviousLayout->DoRepaint();
		cPreviousLayout->Process();
		cPreviousLayout->Draw(VideoPostProcessor::videoSurface(), 0, 0);
	}

	cActiveLayout->Process();
	if (cActiveLayout->needsRepaint())
		cActiveLayout->DoRepaint();

	cActiveLayout->Draw(VideoPostProcessor::videoSurface(), 0, 0);
	DrawCursor(VideoPostProcessor::videoSurface());
	doVideoFrameInMainThread();
}

void CGuiSkin::SDL_OnKeyDown(SDL_Event *ev) {
	if(!cActiveLayout) return;
	// TODO: This is a hack and could not work later anymore. Please fix that.
	// (Any event handler should *never* depend on a state, like GetKeyboard().)
	const KeyboardEvent& key = GetKeyboard()->keyQueue[GetKeyboard()->queueLength - 1];
	cActiveLayout->DoKeyDown(key.ch, key.sym, key.state);
}

void CGuiSkin::SDL_OnKeyUp(SDL_Event *ev) {
	if(!cActiveLayout) return;
	// TODO: This is a hack and could not work later anymore. Please fix that.
	// (Any event handler should *never* depend on a state, like GetKeyboard().)
	const KeyboardEvent& key = GetKeyboard()->keyQueue[GetKeyboard()->queueLength - 1];
	cActiveLayout->DoKeyUp(key.ch, key.sym, key.state);
}

void CGuiSkin::SDL_OnMouseMotion(SDL_Event* ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoMouseMove(ev->motion.x, ev->motion.y, ev->motion.xrel, ev->motion.yrel,
		ev->motion.state != 0, SDLButtonStateToMouseButton(ev->motion.state), *GetCurrentModstate());
}

void CGuiSkin::SDL_OnMouseButtonDown(SDL_Event* ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoMouseDown(ev->button.x, ev->button.y, GetMouse()->deltaX, GetMouse()->deltaY,
		SDLButtonToMouseButton(ev->button.button), *GetCurrentModstate());
}

void CGuiSkin::SDL_OnMouseButtonUp(SDL_Event* ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoMouseUp(ev->button.x, ev->button.y, GetMouse()->deltaX, GetMouse()->deltaY,
		SDLButtonToMouseButton(ev->button.button), *GetCurrentModstate());
}

void CGuiSkin::SDL_OnMouseWheel(SDL_Event* ev) {
	if(!cActiveLayout) return;
	if(ev->wheel.y > 0)
		cActiveLayout->DoMouseWheelDown(GetMouse()->X, GetMouse()->Y, GetMouse()->deltaX, GetMouse()->deltaY, *GetCurrentModstate());
	else if(ev->wheel.y < 0)
		cActiveLayout->DoMouseWheelUp(GetMouse()->X, GetMouse()->Y, GetMouse()->deltaX, GetMouse()->deltaY, *GetCurrentModstate());
}

void CGuiSkin::SDL_OnAddWidget(WidgetData ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoChildAddEvent(ev.widget);
}

void CGuiSkin::SDL_OnDestroyWidget(WidgetData ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoChildDestroyEvent(ev.widget);
}

}; // namespace SkinnedGUI
<commit_msg>cleanup<commit_after>/////////////////////////////////////////
//
//             OpenLieroX
//
// code under LGPL, based on JasonBs work,
// enhanced by Dark Charlie and Albert Zeyer
//
//
/////////////////////////////////////////

#include "SkinnedGUI/CGuiSkin.h"
#include "FindFile.h"
#include "StringUtils.h"
#include "AuxLib.h"
#include "Cursor.h"

#include "SkinnedGUI/CWidget.h"

// Widgets
#include "SkinnedGUI/CAnimation.h"
#include "SkinnedGUI/CButton.h"
#include "SkinnedGUI/CCheckbox.h"
#include "SkinnedGUI/CCombobox.h"
#include "SkinnedGUI/CDialog.h"
#include "SkinnedGUI/CGuiSkinnedLayout.h"
#include "SkinnedGUI/CImageButton.h"
#include "SkinnedGUI/CInputBox.h"
#include "SkinnedGUI/CLabel.h"
#include "SkinnedGUI/CLine.h"
#include "SkinnedGUI/CListview.h"
#include "SkinnedGUI/CMapEditor.h"
#include "SkinnedGUI/CMarquee.h"
#include "SkinnedGUI/CMenu.h"
#include "SkinnedGUI/CMinimap.h"
#include "SkinnedGUI/CProgressbar.h"
#include "SkinnedGUI/CScrollbar.h"
#include "SkinnedGUI/CSlider.h"
#include "SkinnedGUI/CTabControl.h"
#include "SkinnedGUI/CTextbox.h"
#include "SkinnedGUI/CToggleButton.h"

namespace SkinnedGUI {

CGuiSkin *cMainSkin = NULL;

#define SKIN_DIRECTORY (std::string("gui_skins/"))

///////////////
// Initialize skinning
bool InitializeGuiSkinning()
{
	if (!cMainSkin)
		cMainSkin = new CGuiSkin();

	if (tLXOptions)
		return cMainSkin->Load(tLXOptions->sSkinPath);
	return false;
}

//////////////////
// Shutdown skinning
void ShutdownGuiSkinning()
{
	if (cMainSkin)
		delete cMainSkin;
	cMainSkin = NULL;
}

/////////////
// Constructor
CGuiSkin::CGuiSkin()
{
	sPath = SKIN_DIRECTORY + "default";
	sName = "Default";
	sAuthor = "OpenLieroX Development Team";

	cActiveLayout = NULL;
	cPreviousLayout = NULL;

	iBufferCount = 1;

	// Listen to the events
	sdlEvents[SDL_KEYDOWN].handler() += getEventHandler(this, &CGuiSkin::SDL_OnKeyDown);
	sdlEvents[SDL_KEYUP].handler() += getEventHandler(this, &CGuiSkin::SDL_OnKeyUp);
	sdlEvents[SDL_MOUSEMOTION].handler() += getEventHandler(this, &CGuiSkin::SDL_OnMouseMotion);
	sdlEvents[SDL_MOUSEBUTTONDOWN].handler() += getEventHandler(this, &CGuiSkin::SDL_OnMouseButtonDown);
	sdlEvents[SDL_MOUSEBUTTONUP].handler() += getEventHandler(this, &CGuiSkin::SDL_OnMouseButtonUp);
	sdlEvents[SDL_MOUSEWHEEL].handler() += getEventHandler(this, &CGuiSkin::SDL_OnMouseWheel);

	onAddWidget.handler() = getEventHandler(this, &CGuiSkin::SDL_OnAddWidget);;
	onDestroyWidget.handler() = getEventHandler(this, &CGuiSkin::SDL_OnDestroyWidget);
}

//////////////
// Destructor
CGuiSkin::~CGuiSkin()
{
	sdlEvents[SDL_KEYDOWN].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnKeyDown);
	sdlEvents[SDL_KEYUP].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnKeyUp);
	sdlEvents[SDL_MOUSEMOTION].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnMouseMotion);
	sdlEvents[SDL_MOUSEBUTTONDOWN].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnMouseButtonDown);
	sdlEvents[SDL_MOUSEBUTTONUP].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnMouseButtonUp);
	sdlEvents[SDL_MOUSEWHEEL].handler() -= getEventHandler(this, &CGuiSkin::SDL_OnMouseWheel);

	// No effects, just destroy
	if (cActiveLayout)
		delete cActiveLayout;
	if (cPreviousLayout)
		delete cPreviousLayout;
}

////////////////
// Load the GUI skin
bool CGuiSkin::Load(const std::string& skin)
{
	sPath = SKIN_DIRECTORY + skin;

	// TODO: author + name
	// TODO: verify that the important files exist

	return true;
}

//////////////////
// Open a layout
bool CGuiSkin::OpenLayout(const std::string &layout)
{
	// Because of the GUI effects we have to remember the old layout for a while
	if (cActiveLayout)  {
		cActiveLayout->Destroy();

		if (cPreviousLayout) // Another layout still effecting, just quit it
			delete cPreviousLayout;

		cPreviousLayout = cActiveLayout;
	}

	// Load the new layout
	cActiveLayout = new CGuiSkinnedLayout();
	if (cActiveLayout->Load(layout, *this))  {
		cActiveLayout->DoCreate();
		return true;
	}

	return false;
}

////////////////////
// Converts the path that is relative to the skin to path relative to OLX
std::string CGuiSkin::getSkinFilePath(const std::string& file)
{
	// Check
	if (!sPath.size())
		return file;

	return JoinPaths(sPath, file);
}

///////////////////////
// Opens a file from the current skin
FILE *CGuiSkin::OpenSkinFile(const std::string &filename, const char *mode)
{
	if (!filename.size())
		return NULL;

	return OpenGameFile(getSkinFilePath(filename), mode);
}

/////////////////////
// Creates a new widget based on the tag name, returns NULL for unknown widgets
CWidget *CGuiSkin::CreateWidgetByTagName(const std::string& tagname, CContainerWidget *parent, const std::string& id)
{
	if (stringcaseequal(tagname, CAnimation::tagName()))
		return new CAnimation(id, parent);
	else if (stringcaseequal(tagname, CButton::tagName()))
		return new CButton(id, parent);
	else if (stringcaseequal(tagname, CCheckbox::tagName()))
		return new CCheckbox(id, parent);
	else if (stringcaseequal(tagname, CCombobox::tagName()))
		return new CCombobox(id, parent);
	else if (stringcaseequal(tagname, CDialog::tagName()))
		return new CDialog(id, parent);
	else if (stringcaseequal(tagname, CGuiSkinnedLayout::tagName()))
		return new CGuiSkinnedLayout(id, parent);
	else if (stringcaseequal(tagname, CImageButton::tagName()))
		return new CImageButton(id, parent);
	else if (stringcaseequal(tagname, CInputbox::tagName()))
		return new CInputbox(id, parent);
	else if (stringcaseequal(tagname, CLabel::tagName()))
		return new CLabel(id, parent);
	else if (stringcaseequal(tagname, CLine::tagName()))
		return new CLine(id, parent);
	else if (stringcaseequal(tagname, CListview::tagName()))
		return new CListview(id, parent);
	else if (stringcaseequal(tagname, CMapEditor::tagName()))
		return new CMapEditor(id, parent);
	else if (stringcaseequal(tagname, CMarquee::tagName()))
		return new CMarquee(id, parent);
	else if (stringcaseequal(tagname, CMenu::tagName()))
		return new CMenu(id, parent);
	else if (stringcaseequal(tagname, CMinimap::tagName()))
		return new CMinimap(id, parent);
	else if (stringcaseequal(tagname, CProgressBar::tagName()))
		return new CProgressBar(id, parent);
	else if (stringcaseequal(tagname, CScrollbar::tagName()))
		return new CScrollbar(id, parent);
	else if (stringcaseequal(tagname, CSlider::tagName()))
		return new CSlider(id, parent);
	else if (stringcaseequal(tagname, CTabControl::tagName()))
		return new CTabControl(id, parent);
	else if (stringcaseequal(tagname, CTextbox::tagName()))
		return new CTextbox(id, parent);
	else if (stringcaseequal(tagname, CToggleButton::tagName()))
		return new CToggleButton(id, parent);
	else
		return NULL; // Unknown widget
}

//////////////////
// Draws the content and processes things
void CGuiSkin::Frame()
{
	// Reset the game cursor
	SetGameCursor(CUR_ARROW);

	if (cPreviousLayout)  {
		if (cPreviousLayout->needsRepaint())
			cPreviousLayout->DoRepaint();
		cPreviousLayout->Process();
		cPreviousLayout->Draw(VideoPostProcessor::videoSurface(), 0, 0);
	}

	cActiveLayout->Process();
	if (cActiveLayout->needsRepaint())
		cActiveLayout->DoRepaint();

	cActiveLayout->Draw(VideoPostProcessor::videoSurface(), 0, 0);
	DrawCursor(VideoPostProcessor::videoSurface());
	doVideoFrameInMainThread();
}

void CGuiSkin::SDL_OnKeyDown(SDL_Event *ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoKeyDown(0, ev->key.keysym.sym, ModifiersState()); // TODO ...
}

void CGuiSkin::SDL_OnKeyUp(SDL_Event *ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoKeyUp(0, ev->key.keysym.sym, ModifiersState()); // TODO ...
}

void CGuiSkin::SDL_OnMouseMotion(SDL_Event* ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoMouseMove(ev->motion.x, ev->motion.y, ev->motion.xrel, ev->motion.yrel,
		ev->motion.state != 0, SDLButtonStateToMouseButton(ev->motion.state), *GetCurrentModstate());
}

void CGuiSkin::SDL_OnMouseButtonDown(SDL_Event* ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoMouseDown(ev->button.x, ev->button.y, GetMouse()->deltaX, GetMouse()->deltaY,
		SDLButtonToMouseButton(ev->button.button), *GetCurrentModstate());
}

void CGuiSkin::SDL_OnMouseButtonUp(SDL_Event* ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoMouseUp(ev->button.x, ev->button.y, GetMouse()->deltaX, GetMouse()->deltaY,
		SDLButtonToMouseButton(ev->button.button), *GetCurrentModstate());
}

void CGuiSkin::SDL_OnMouseWheel(SDL_Event* ev) {
	if(!cActiveLayout) return;
	if(ev->wheel.y > 0)
		cActiveLayout->DoMouseWheelDown(GetMouse()->X, GetMouse()->Y, GetMouse()->deltaX, GetMouse()->deltaY, *GetCurrentModstate());
	else if(ev->wheel.y < 0)
		cActiveLayout->DoMouseWheelUp(GetMouse()->X, GetMouse()->Y, GetMouse()->deltaX, GetMouse()->deltaY, *GetCurrentModstate());
}

void CGuiSkin::SDL_OnAddWidget(WidgetData ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoChildAddEvent(ev.widget);
}

void CGuiSkin::SDL_OnDestroyWidget(WidgetData ev) {
	if(!cActiveLayout) return;
	cActiveLayout->DoChildDestroyEvent(ev.widget);
}

}; // namespace SkinnedGUI
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2013 lailongwei<lailongwei@126.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "llbc/common/Export.h"
#include "llbc/common/BeforeIncl.h"

#include "llbc/core/os/OS_Symbol.h"

__LLBC_NS_BEGIN

#if LLBC_CFG_OS_IMPL_SYMBOL

int LLBC_InitSymbol()
{
#if LLBC_TARGET_PLATFORM_WIN32
    if (::SymInitialize(::GetCurrentProcess(), NULL, TRUE) != TRUE)
    {
        LLBC_SetLastError(LLBC_ERROR_OSAPI);
        return LLBC_FAILED;
    }

    return LLBC_OK;
#endif // Win32
}

LLBC_String LLBC_CaptureStackBackTrace(size_t skipFrames, size_t captureFrames)
{
    LLBC_String backTrace;

    __LLBC_LibTls *libTls = __LLBC_GetLibTls();
    if (captureFrames == LLBC_INFINITE)
        captureFrames = LLBC_CFG_OS_SYMBOL_MAX_CAPTURE_FRAMES;
    else
        captureFrames = MIN(captureFrames, LLBC_CFG_OS_SYMBOL_MAX_CAPTURE_FRAMES);

    void **stack = libTls->coreTls.symbol.stack;

#if LLBC_TARGET_PLATFORM_WIN32
    DWORD displacement;
    HANDLE curProc = ::GetCurrentProcess();
    SYMBOL_INFO *symbol = libTls->coreTls.symbol.win32Symbol;
    const WORD frames = ::CaptureStackBackTrace(skipFrames + 1, captureFrames, stack, NULL);

    for (WORD frame = 0; frame != frames; frame++)
    {
        ::SymFromAddr(curProc, (DWORD64)stack[frame], 0, symbol);
        IMAGEHLP_LINE64 &imgHelpLine64 = libTls->coreTls.symbol.win32ImgHelpLine64;
        if (::SymGetLineFromAddr64(curProc, symbol->Address, &displacement, &imgHelpLine64) == TRUE)
        {
            backTrace.append_format("#%d 0x%x in %s at %s:%d", frames - frame - 1, (void *)symbol->Address,
                                    symbol->Name, imgHelpLine64.FileName, imgHelpLine64.LineNumber);
        }
        else
        {
            backTrace.append_format("#%d 0x%x in %s at %s:%d", frames - frame - 1,
                (void *)symbol->Address, symbol->Name, "", 0);
        }

        if (frame != frames - 1)
            backTrace.append(1, '\n');
    }
#else // Non-Win32
    const int frames = ::backtrace(stack, captureFrames + skipFrames);
    char **strs = ::backtrace_symbols(stack, frames);
    if (LIKELY(strs))
    {
        for (int i = skipFrames; i < frames; i++)
        {
            backTrace.append_format("#%d ", frames - i - 1);

            char *parenthesisEnd = NULL;
            char *parenthesisBeg = strchr(strs[i], '(');
            if (parenthesisBeg)
            {
                parenthesisBeg += 1;
                parenthesisEnd = strchr(parenthesisBeg, ')');
            }

            if (parenthesisEnd &&
                parenthesisBeg != parenthesisEnd)
            {
                char *addrOffsetBeg = strchr(parenthesisBeg, '+');
                if (addrOffsetBeg == NULL)
                    addrOffsetBeg= parenthesisEnd;

                const char oldAddrOffsetBegCh = *addrOffsetBeg;
                *addrOffsetBeg = '\0';

                int status = 0;
                size_t length = sizeof(libTls->commonTls.rtti);
                abi::__cxa_demangle(parenthesisBeg, libTls->commonTls.rtti, &length, &status);
                *addrOffsetBeg = oldAddrOffsetBegCh;
                if (status == 0)
                {
                    backTrace.append(strs[i], parenthesisBeg - strs[i]);
                    backTrace.append(libTls->commonTls.rtti);
                    backTrace.append(addrOffsetBeg);
                }
                else
                {
                    backTrace.append_format("%s", strs[i]);
                }
            }
            else
            {
                backTrace.append_format("%s", strs[i]);
            }

            if (i != frames - 1)
                backTrace.append(1, '\n');
        }

        free(strs);
    }
#endif // LLBC_TARGET_PLATFORM_WIN32

    return backTrace;
}

#endif // LLBC_CFG_OS_IMPL_SYMBOL

__LLBC_NS_END

#include "llbc/common/AfterIncl.h"
<commit_msg>Fix windows platform compile warning.<commit_after>// The MIT License (MIT)

// Copyright (c) 2013 lailongwei<lailongwei@126.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "llbc/common/Export.h"
#include "llbc/common/BeforeIncl.h"

#include "llbc/core/os/OS_Symbol.h"

__LLBC_NS_BEGIN

#if LLBC_CFG_OS_IMPL_SYMBOL

int LLBC_InitSymbol()
{
#if LLBC_TARGET_PLATFORM_WIN32
    if (::SymInitialize(::GetCurrentProcess(), NULL, TRUE) != TRUE)
    {
        LLBC_SetLastError(LLBC_ERROR_OSAPI);
        return LLBC_FAILED;
    }

    return LLBC_OK;
#endif // Win32
}

LLBC_String LLBC_CaptureStackBackTrace(size_t skipFrames, size_t captureFrames)
{
    LLBC_String backTrace;

    __LLBC_LibTls *libTls = __LLBC_GetLibTls();
    if (captureFrames == LLBC_INFINITE)
        captureFrames = LLBC_CFG_OS_SYMBOL_MAX_CAPTURE_FRAMES;
    else
        captureFrames = MIN(captureFrames, LLBC_CFG_OS_SYMBOL_MAX_CAPTURE_FRAMES);

    void **stack = libTls->coreTls.symbol.stack;

#if LLBC_TARGET_PLATFORM_WIN32
    DWORD displacement;
    HANDLE curProc = ::GetCurrentProcess();
    SYMBOL_INFO *symbol = libTls->coreTls.symbol.win32Symbol;
    const WORD frames = ::CaptureStackBackTrace(static_cast<DWORD>(skipFrames) + 1,
                                                static_cast<DWORD>(captureFrames),
                                                stack,
                                                NULL);

    for (WORD frame = 0; frame != frames; frame++)
    {
        ::SymFromAddr(curProc, (DWORD64)stack[frame], 0, symbol);
        IMAGEHLP_LINE64 &imgHelpLine64 = libTls->coreTls.symbol.win32ImgHelpLine64;
        if (::SymGetLineFromAddr64(curProc, symbol->Address, &displacement, &imgHelpLine64) == TRUE)
        {
            backTrace.append_format("#%d 0x%x in %s at %s:%d", frames - frame - 1, (void *)symbol->Address,
                                    symbol->Name, imgHelpLine64.FileName, imgHelpLine64.LineNumber);
        }
        else
        {
            backTrace.append_format("#%d 0x%x in %s at %s:%d", frames - frame - 1,
                (void *)symbol->Address, symbol->Name, "", 0);
        }

        if (frame != frames - 1)
            backTrace.append(1, '\n');
    }
#else // Non-Win32
    const int frames = ::backtrace(stack, captureFrames + skipFrames);
    char **strs = ::backtrace_symbols(stack, frames);
    if (LIKELY(strs))
    {
        for (int i = skipFrames; i < frames; i++)
        {
            backTrace.append_format("#%d ", frames - i - 1);

            char *parenthesisEnd = NULL;
            char *parenthesisBeg = strchr(strs[i], '(');
            if (parenthesisBeg)
            {
                parenthesisBeg += 1;
                parenthesisEnd = strchr(parenthesisBeg, ')');
            }

            if (parenthesisEnd &&
                parenthesisBeg != parenthesisEnd)
            {
                char *addrOffsetBeg = strchr(parenthesisBeg, '+');
                if (addrOffsetBeg == NULL)
                    addrOffsetBeg= parenthesisEnd;

                const char oldAddrOffsetBegCh = *addrOffsetBeg;
                *addrOffsetBeg = '\0';

                int status = 0;
                size_t length = sizeof(libTls->commonTls.rtti);
                abi::__cxa_demangle(parenthesisBeg, libTls->commonTls.rtti, &length, &status);
                *addrOffsetBeg = oldAddrOffsetBegCh;
                if (status == 0)
                {
                    backTrace.append(strs[i], parenthesisBeg - strs[i]);
                    backTrace.append(libTls->commonTls.rtti);
                    backTrace.append(addrOffsetBeg);
                }
                else
                {
                    backTrace.append_format("%s", strs[i]);
                }
            }
            else
            {
                backTrace.append_format("%s", strs[i]);
            }

            if (i != frames - 1)
                backTrace.append(1, '\n');
        }

        free(strs);
    }
#endif // LLBC_TARGET_PLATFORM_WIN32

    return backTrace;
}

#endif // LLBC_CFG_OS_IMPL_SYMBOL

__LLBC_NS_END

#include "llbc/common/AfterIncl.h"
<|endoftext|>


<commit_before>//
//  ZX8081.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 08/06/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include "ZX8081.hpp"

using namespace Storage::Data::ZX8081;

static uint16_t short_at(size_t address, const std::vector<uint8_t> &data) {
	return (uint16_t)(data[address] | (data[address + 1] << 8));
}

static std::shared_ptr<File> ZX80FileFromData(const std::vector<uint8_t> &data) {
	// Does this look like a ZX80 file?

	if(data.size() < 0x28) return nullptr;

//	uint16_t next_line_number = short_at(0x2, data);
//	uint16_t first_visible_line = short_at(0x13, data);

	uint16_t vars = short_at(0x8, data);
	uint16_t end_of_file = short_at(0xa, data);
	uint16_t display_address = short_at(0xc, data);

	// check that the end of file is contained within the supplied data
	if(end_of_file - 0x4000 > data.size()) return nullptr;

	// check for the proper ordering of buffers
	if(vars > end_of_file) return nullptr;
	if(end_of_file > display_address) return nullptr;

	// TODO: does it make sense to inspect the tokenised BASIC?
	// It starts at 0x4028 and proceeds as [16-bit line number] [tokens] [0x76],
	// but I'm as yet unable to find documentation of the tokens.

	// TODO: check that the line numbers declared above exist (?)

	std::shared_ptr<File> file(new File);
	file->data = data;
	file->isZX81 = false;
	return file;
}

static std::shared_ptr<File> ZX81FileFromData(const std::vector<uint8_t> &data) {
	// Does this look like a ZX81 file?

	// Look for a file name.
	size_t data_pointer = 0;
	int c = 11;
	while(c--) {
		if(data[data_pointer] & 0x80) break;
		data_pointer++;
	}
	if(!c) return nullptr;
	data_pointer++;

	if(data.size() < data_pointer + 0x405e - 0x4009) return nullptr;

	if(data[data_pointer]) return nullptr;

	uint16_t vars = short_at(data_pointer + 0x4010 - 0x4009, data);
	uint16_t end_of_file = short_at(data_pointer + 0x4014 - 0x4009, data);
//	uint16_t display_address = short_at(0x400c - 0x4009, data);

	// check that the end of file is contained within the supplied data
	if(data_pointer + end_of_file - 0x4009 > data.size()) return nullptr;

	// check for the proper ordering of buffers
	if(vars > end_of_file) return nullptr;
//	if(end_of_file > display_address) return nullptr;

	// TODO: does it make sense to inspect the tokenised BASIC?
	// It starts at 0x4028 and proceeds as [16-bit line number] [tokens] [0x76],
	// but I'm as yet unable to find documentation of the tokens.

	// TODO: check that the line numbers declared above exist (?)

	std::shared_ptr<File> file(new File);
	file->data = data;
	file->isZX81 = true;
	return file;
}

std::shared_ptr<File> Storage::Data::ZX8081::FileFromData(const std::vector<uint8_t> &data) {
	std::shared_ptr<Storage::Data::ZX8081::File> result = ZX81FileFromData(data);
	if(result) return result;
	return ZX80FileFromData(data);
}

#pragma mark - String conversion

std::wstring Storage::Data::ZX8081::StringFromData(const std::vector<uint8_t> &data, bool is_zx81) {
	std::wstring string;

	wchar_t zx80_map[64] = {
		' ',	u'\u2598',	u'\u259d',	u'\u2580',	u'\u2596',	u'\u258c',	u'\u259e',	u'\u259b',	u'\u2588',	u'\u2584',	u'\u2580',	'"',	u'£',	'$',	':',	'?',
		'(',	')',		'>',		'<',		'=',		'+',		'-',		'*',		'/',		';',		',',		'.',	'0',	'1',	'2',	'3',
		'4',	'5',		'6',		'7',		'8',		'9',		'A',		'B',		'C',		'D',		'E',		'F',	'G',	'H',	'I',	'J',
		'K',	'L',		'M',		'N',		'O',		'P',		'Q',		'R',		'S',		'T',		'U',		'V',	'W',	'X',	'Y',	'Z'
	};
	// TODO: the block character conversions shown here are in the wrong order
	wchar_t zx81_map[64] = {
		' ',	u'\u2598',	u'\u259d',	u'\u2580',	u'\u2596',	u'\u258c',	u'\u259e',	u'\u259b',	u'\u2588',	u'\u2584',	u'\u2580',	'"',	u'£',	'$',	':',	'?',
		'(',	')',		'-',		'+',		'*',		'/',		'=',		'>',		'<',		';',		',',		'.',	'0',	'1',	'2',	'3',
		'4',	'5',		'6',		'7',		'8',		'9',		'A',		'B',		'C',		'D',		'E',		'F',	'G',	'H',	'I',	'J',
		'K',	'L',		'M',		'N',		'O',		'P',		'Q',		'R',		'S',		'T',		'U',		'V',	'W',	'X',	'Y',	'Z'
	};
	wchar_t *map = is_zx81 ? zx81_map : zx80_map;

	for(uint8_t byte : data) {
		string.push_back(map[byte & 0x3f]);
	}

	return string;
}

std::vector<uint8_t> DataFromString(const std::wstring &string, bool is_zx81) {
	std::vector<uint8_t> data;

	// TODO

	return data;
}
<commit_msg>Further lightened up my file-is-ZX81 check.<commit_after>//
//  ZX8081.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 08/06/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include "ZX8081.hpp"

using namespace Storage::Data::ZX8081;

static uint16_t short_at(size_t address, const std::vector<uint8_t> &data) {
	return (uint16_t)(data[address] | (data[address + 1] << 8));
}

static std::shared_ptr<File> ZX80FileFromData(const std::vector<uint8_t> &data) {
	// Does this look like a ZX80 file?

	if(data.size() < 0x28) return nullptr;

//	uint16_t next_line_number = short_at(0x2, data);
//	uint16_t first_visible_line = short_at(0x13, data);

	uint16_t vars = short_at(0x8, data);
	uint16_t end_of_file = short_at(0xa, data);
	uint16_t display_address = short_at(0xc, data);

	// check that the end of file is contained within the supplied data
	if(end_of_file - 0x4000 > data.size()) return nullptr;

	// check for the proper ordering of buffers
	if(vars > end_of_file) return nullptr;
	if(end_of_file > display_address) return nullptr;

	// TODO: does it make sense to inspect the tokenised BASIC?
	// It starts at 0x4028 and proceeds as [16-bit line number] [tokens] [0x76],
	// but I'm as yet unable to find documentation of the tokens.

	// TODO: check that the line numbers declared above exist (?)

	std::shared_ptr<File> file(new File);
	file->data = data;
	file->isZX81 = false;
	return file;
}

static std::shared_ptr<File> ZX81FileFromData(const std::vector<uint8_t> &data) {
	// Does this look like a ZX81 file?

	// Look for a file name.
	size_t data_pointer = 0;
	int c = 11;
	while(c--) {
		if(data[data_pointer] & 0x80) break;
		data_pointer++;
	}
	if(!c) return nullptr;
	data_pointer++;

	if(data.size() < data_pointer + 0x405e - 0x4009) return nullptr;

//	if(data[data_pointer]) return nullptr;

	uint16_t vars = short_at(data_pointer + 0x4010 - 0x4009, data);
	uint16_t end_of_file = short_at(data_pointer + 0x4014 - 0x4009, data);
//	uint16_t display_address = short_at(0x400c - 0x4009, data);

	// check that the end of file is contained within the supplied data
	if(data_pointer + end_of_file - 0x4009 > data.size()) return nullptr;

	// check for the proper ordering of buffers
	if(vars > end_of_file) return nullptr;
//	if(end_of_file > display_address) return nullptr;

	// TODO: does it make sense to inspect the tokenised BASIC?
	// It starts at 0x4028 and proceeds as [16-bit line number] [tokens] [0x76],
	// but I'm as yet unable to find documentation of the tokens.

	// TODO: check that the line numbers declared above exist (?)

	std::shared_ptr<File> file(new File);
	file->data = data;
	file->isZX81 = true;
	return file;
}

std::shared_ptr<File> Storage::Data::ZX8081::FileFromData(const std::vector<uint8_t> &data) {
	std::shared_ptr<Storage::Data::ZX8081::File> result = ZX81FileFromData(data);
	if(result) return result;
	return ZX80FileFromData(data);
}

#pragma mark - String conversion

std::wstring Storage::Data::ZX8081::StringFromData(const std::vector<uint8_t> &data, bool is_zx81) {
	std::wstring string;

	wchar_t zx80_map[64] = {
		' ',	u'\u2598',	u'\u259d',	u'\u2580',	u'\u2596',	u'\u258c',	u'\u259e',	u'\u259b',	u'\u2588',	u'\u2584',	u'\u2580',	'"',	u'£',	'$',	':',	'?',
		'(',	')',		'>',		'<',		'=',		'+',		'-',		'*',		'/',		';',		',',		'.',	'0',	'1',	'2',	'3',
		'4',	'5',		'6',		'7',		'8',		'9',		'A',		'B',		'C',		'D',		'E',		'F',	'G',	'H',	'I',	'J',
		'K',	'L',		'M',		'N',		'O',		'P',		'Q',		'R',		'S',		'T',		'U',		'V',	'W',	'X',	'Y',	'Z'
	};
	// TODO: the block character conversions shown here are in the wrong order
	wchar_t zx81_map[64] = {
		' ',	u'\u2598',	u'\u259d',	u'\u2580',	u'\u2596',	u'\u258c',	u'\u259e',	u'\u259b',	u'\u2588',	u'\u2584',	u'\u2580',	'"',	u'£',	'$',	':',	'?',
		'(',	')',		'-',		'+',		'*',		'/',		'=',		'>',		'<',		';',		',',		'.',	'0',	'1',	'2',	'3',
		'4',	'5',		'6',		'7',		'8',		'9',		'A',		'B',		'C',		'D',		'E',		'F',	'G',	'H',	'I',	'J',
		'K',	'L',		'M',		'N',		'O',		'P',		'Q',		'R',		'S',		'T',		'U',		'V',	'W',	'X',	'Y',	'Z'
	};
	wchar_t *map = is_zx81 ? zx81_map : zx80_map;

	for(uint8_t byte : data) {
		string.push_back(map[byte & 0x3f]);
	}

	return string;
}

std::vector<uint8_t> DataFromString(const std::wstring &string, bool is_zx81) {
	std::vector<uint8_t> data;

	// TODO

	return data;
}
<|endoftext|>


<commit_before>//
//  ZX8081.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 08/06/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include "ZX8081.hpp"

using namespace Storage::Data::ZX8081;

static uint16_t short_at(size_t address, const std::vector<uint8_t> &data) {
	return (uint16_t)(data[address] | (data[address + 1] << 8));
}

static std::shared_ptr<File> ZX80FileFromData(const std::vector<uint8_t> &data) {
	// Does this look like a ZX80 file?

	if(data.size() < 0x28) return nullptr;

//	uint16_t next_line_number = short_at(0x2, data);
//	uint16_t first_visible_line = short_at(0x13, data);

	uint16_t vars = short_at(0x8, data);
	uint16_t end_of_file = short_at(0xa, data);
	uint16_t display_address = short_at(0xc, data);

	// check that the end of file is contained within the supplied data
	if(end_of_file - 0x4000 > data.size()) return nullptr;

	// check for the proper ordering of buffers
	if(vars > end_of_file) return nullptr;
	if(end_of_file > display_address) return nullptr;

	// TODO: does it make sense to inspect the tokenised BASIC?
	// It starts at 0x4028 and proceeds as [16-bit line number] [tokens] [0x76],
	// but I'm as yet unable to find documentation of the tokens.

	// TODO: check that the line numbers declared above exist (?)

	std::shared_ptr<File> file(new File);
	file->data = data;
	file->isZX81 = false;
	return file;
}

static std::shared_ptr<File> ZX81FileFromData(const std::vector<uint8_t> &data) {
	// Does this look like a ZX81 file?

	// Look for a file name.
	size_t data_pointer = 0;
	int c = 11;
	while(c--) {
		if(data[data_pointer] & 0x80) break;
		data_pointer++;
	}
	if(!c) return nullptr;
	data_pointer++;

	if(data.size() < data_pointer + 0x405e - 0x4009) return nullptr;

	if(data[data_pointer]) return nullptr;

	uint16_t vars = short_at(data_pointer + 0x4010 - 0x4009, data);
	uint16_t end_of_file = short_at(data_pointer + 0x4014 - 0x4009, data);
//	uint16_t display_address = short_at(0x400c - 0x4009, data);

	// check that the end of file is contained within the supplied data
	if(data_pointer + end_of_file - 0x4009 > data.size()) return nullptr;

	// check for the proper ordering of buffers
	if(vars > end_of_file) return nullptr;
//	if(end_of_file > display_address) return nullptr;

	// TODO: does it make sense to inspect the tokenised BASIC?
	// It starts at 0x4028 and proceeds as [16-bit line number] [tokens] [0x76],
	// but I'm as yet unable to find documentation of the tokens.

	// TODO: check that the line numbers declared above exist (?)

	std::shared_ptr<File> file(new File);
	file->data = data;
	file->isZX81 = true;
	return file;
}

std::shared_ptr<File> Storage::Data::ZX8081::FileFromData(const std::vector<uint8_t> &data) {
	std::shared_ptr<Storage::Data::ZX8081::File> result = ZX80FileFromData(data);
	if(result) return result;
	return ZX81FileFromData(data);
}

#pragma mark - String conversion

std::wstring Storage::Data::ZX8081::StringFromData(const std::vector<uint8_t> &data, bool is_zx81) {
	std::wstring string;

	wchar_t zx80_map[] = {
		' ',	u'\u2598',	u'\u259d',	u'\u2580',	u'\u2596',	u'\u258c',	u'\u259e',	u'\u259b',	u'\u2588',	u'\u2584',	u'\u2580',	'"',	u'£',	'$',	':',	'?',
		'(',	')',		'>',		'<',		'=',		'+',		'-',		'*',		'/',		';',		',',		'.',	'0',	'1',	'2',	'3',
		'4',	'5',		'6',		'7',		'8',		'9',		'A',		'B',		'C',		'D',		'E',		'F',	'G',	'H',	'I',	'J',
		'K',	'L',		'M',		'N',		'O',		'P',		'Q',		'R',		'S',		'T',		'U',		'V',	'W',	'X',	'Y',	'Z'
	};
	wchar_t zx81_map[] = {
		' ',	u'\u2598',	u'\u259d',	u'\u2580',	u'\u2596',	u'\u258c',	u'\u259e',	u'\u259b',	u'\u2588',	u'\u2584',	u'\u2580',	u'£',	'$',	':',	'?',
		'(',	')',		'-',		'+',		'*',		'/',		'=',		'>',		'<',		';',		',',		'.',	'0',	'1',	'2',	'3',
		'4',	'5',		'6',		'7',		'8',		'9',		'A',		'B',		'C',		'D',		'E',		'F',	'G',	'H',	'I',	'J',
		'K',	'L',		'M',		'N',		'O',		'P',		'Q',		'R',		'S',		'T',		'U',		'V',	'W',	'X',	'Y',	'Z'
	};
	wchar_t *map = is_zx81 ? zx81_map : zx80_map;

	for(uint8_t byte : data) {
		string.push_back(map[byte & 0x3f]);
	}

	return string;
}

std::vector<uint8_t> DataFromString(const std::wstring &string, bool is_zx81) {
	std::vector<uint8_t> data;

	// TODO

	return data;
}
<commit_msg>Adds an extra character for padding the ZX81 table.<commit_after>//
//  ZX8081.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 08/06/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include "ZX8081.hpp"

using namespace Storage::Data::ZX8081;

static uint16_t short_at(size_t address, const std::vector<uint8_t> &data) {
	return (uint16_t)(data[address] | (data[address + 1] << 8));
}

static std::shared_ptr<File> ZX80FileFromData(const std::vector<uint8_t> &data) {
	// Does this look like a ZX80 file?

	if(data.size() < 0x28) return nullptr;

//	uint16_t next_line_number = short_at(0x2, data);
//	uint16_t first_visible_line = short_at(0x13, data);

	uint16_t vars = short_at(0x8, data);
	uint16_t end_of_file = short_at(0xa, data);
	uint16_t display_address = short_at(0xc, data);

	// check that the end of file is contained within the supplied data
	if(end_of_file - 0x4000 > data.size()) return nullptr;

	// check for the proper ordering of buffers
	if(vars > end_of_file) return nullptr;
	if(end_of_file > display_address) return nullptr;

	// TODO: does it make sense to inspect the tokenised BASIC?
	// It starts at 0x4028 and proceeds as [16-bit line number] [tokens] [0x76],
	// but I'm as yet unable to find documentation of the tokens.

	// TODO: check that the line numbers declared above exist (?)

	std::shared_ptr<File> file(new File);
	file->data = data;
	file->isZX81 = false;
	return file;
}

static std::shared_ptr<File> ZX81FileFromData(const std::vector<uint8_t> &data) {
	// Does this look like a ZX81 file?

	// Look for a file name.
	size_t data_pointer = 0;
	int c = 11;
	while(c--) {
		if(data[data_pointer] & 0x80) break;
		data_pointer++;
	}
	if(!c) return nullptr;
	data_pointer++;

	if(data.size() < data_pointer + 0x405e - 0x4009) return nullptr;

	if(data[data_pointer]) return nullptr;

	uint16_t vars = short_at(data_pointer + 0x4010 - 0x4009, data);
	uint16_t end_of_file = short_at(data_pointer + 0x4014 - 0x4009, data);
//	uint16_t display_address = short_at(0x400c - 0x4009, data);

	// check that the end of file is contained within the supplied data
	if(data_pointer + end_of_file - 0x4009 > data.size()) return nullptr;

	// check for the proper ordering of buffers
	if(vars > end_of_file) return nullptr;
//	if(end_of_file > display_address) return nullptr;

	// TODO: does it make sense to inspect the tokenised BASIC?
	// It starts at 0x4028 and proceeds as [16-bit line number] [tokens] [0x76],
	// but I'm as yet unable to find documentation of the tokens.

	// TODO: check that the line numbers declared above exist (?)

	std::shared_ptr<File> file(new File);
	file->data = data;
	file->isZX81 = true;
	return file;
}

std::shared_ptr<File> Storage::Data::ZX8081::FileFromData(const std::vector<uint8_t> &data) {
	std::shared_ptr<Storage::Data::ZX8081::File> result = ZX80FileFromData(data);
	if(result) return result;
	return ZX81FileFromData(data);
}

#pragma mark - String conversion

std::wstring Storage::Data::ZX8081::StringFromData(const std::vector<uint8_t> &data, bool is_zx81) {
	std::wstring string;

	wchar_t zx80_map[64] = {
		' ',	u'\u2598',	u'\u259d',	u'\u2580',	u'\u2596',	u'\u258c',	u'\u259e',	u'\u259b',	u'\u2588',	u'\u2584',	u'\u2580',	'"',	u'£',	'$',	':',	'?',
		'(',	')',		'>',		'<',		'=',		'+',		'-',		'*',		'/',		';',		',',		'.',	'0',	'1',	'2',	'3',
		'4',	'5',		'6',		'7',		'8',		'9',		'A',		'B',		'C',		'D',		'E',		'F',	'G',	'H',	'I',	'J',
		'K',	'L',		'M',		'N',		'O',		'P',		'Q',		'R',		'S',		'T',		'U',		'V',	'W',	'X',	'Y',	'Z'
	};
	// TODO: the block character conversions shown here are in the wrong order
	wchar_t zx81_map[64] = {
		' ',	u'\u2598',	u'\u259d',	u'\u2580',	u'\u2596',	u'\u258c',	u'\u259e',	u'\u259b',	u'\u2588',	u'\u2584',	u'\u2580',	'"',	u'£',	'$',	':',	'?',
		'(',	')',		'-',		'+',		'*',		'/',		'=',		'>',		'<',		';',		',',		'.',	'0',	'1',	'2',	'3',
		'4',	'5',		'6',		'7',		'8',		'9',		'A',		'B',		'C',		'D',		'E',		'F',	'G',	'H',	'I',	'J',
		'K',	'L',		'M',		'N',		'O',		'P',		'Q',		'R',		'S',		'T',		'U',		'V',	'W',	'X',	'Y',	'Z'
	};
	wchar_t *map = is_zx81 ? zx81_map : zx80_map;

	for(uint8_t byte : data) {
		string.push_back(map[byte & 0x3f]);
	}

	return string;
}

std::vector<uint8_t> DataFromString(const std::wstring &string, bool is_zx81) {
	std::vector<uint8_t> data;

	// TODO

	return data;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: precompiled_bridges.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2007-05-10 15:13:42 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): Generated on 2006-09-01 17:49:31.967936

#ifdef PRECOMPILED_HEADERS
//---MARKER---
#include "boost/static_assert.hpp"

#include "com/sun/star/bridge/InvalidProtocolChangeException.hdl"
#include "com/sun/star/bridge/InvalidProtocolChangeException.hpp"
#include "com/sun/star/bridge/ProtocolProperty.hdl"
#include "com/sun/star/bridge/ProtocolProperty.hpp"
#include "com/sun/star/bridge/XBridge.hpp"
#include "com/sun/star/bridge/XBridgeFactory.hpp"
#include "com/sun/star/bridge/XInstanceProvider.hpp"
#include "com/sun/star/bridge/XProtocolProperties.hdl"
#include "com/sun/star/bridge/XProtocolProperties.hpp"
#include "com/sun/star/bridge/XUnoUrlResolver.hpp"
#include "com/sun/star/connection/ConnectionSetupException.hpp"
#include "com/sun/star/connection/NoConnectException.hpp"
#include "com/sun/star/connection/XAcceptor.hpp"
#include "com/sun/star/connection/XConnection.hpp"
#include "com/sun/star/connection/XConnector.hpp"
#include "com/sun/star/frame/XComponentLoader.hpp"
#include "com/sun/star/io/XInputStream.hpp"
#include "com/sun/star/io/XOutputStream.hpp"
#include "com/sun/star/lang/DisposedException.hdl"
#include "com/sun/star/lang/DisposedException.hpp"
#include "com/sun/star/lang/IllegalArgumentException.hpp"
#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
#include "com/sun/star/lang/XComponent.hpp"
#include "com/sun/star/lang/XInitialization.hpp"
#include "com/sun/star/lang/XMain.hpp"
#include "com/sun/star/lang/XMultiComponentFactory.hpp"
#include "com/sun/star/lang/XServiceInfo.hpp"
#include "com/sun/star/lang/XSingleComponentFactory.hpp"
#include "com/sun/star/registry/InvalidRegistryException.hpp"
#include "com/sun/star/registry/XImplementationRegistration.hpp"
#include "com/sun/star/registry/XRegistryKey.hpp"
#include "com/sun/star/text/XTextDocument.hpp"
#include "com/sun/star/uno/Any.h"
#include "com/sun/star/uno/Any.hxx"
#include "com/sun/star/uno/DeploymentException.hpp"
#include "com/sun/star/uno/Exception.hdl"
#include "com/sun/star/uno/Exception.hpp"
#include "com/sun/star/uno/Reference.h"
#include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/RuntimeException.hdl"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/Sequence.h"
#include "com/sun/star/uno/Sequence.hxx"
#include "com/sun/star/uno/Type.h"
#include "com/sun/star/uno/Type.hxx"
#include "com/sun/star/uno/TypeClass.hdl"
#include "com/sun/star/uno/XComponentContext.hpp"
#include "com/sun/star/uno/XInterface.hdl"
#include "com/sun/star/uno/XInterface.hpp"
#include "com/sun/star/uno/XNamingService.hpp"
#include "com/sun/star/uno/genfunc.hxx"

#include "cppu/macros.hxx"
#include "cppu/unotype.hxx"

#include "cppuhelper/factory.hxx"
#include "cppuhelper/implbase1.hxx"
#include "cppuhelper/implbase2.hxx"
#include "cppuhelper/implbase3.hxx"
#include "cppuhelper/implementationentry.hxx"
#include "cppuhelper/servicefactory.hxx"
#include "cppuhelper/weak.hxx"

#include "osl/conditn.h"
#include "osl/conditn.hxx"
#include "osl/diagnose.h"
#include "osl/doublecheckedlocking.h"
#include "osl/getglobalmutex.hxx"
#include "osl/interlck.h"
#include "osl/module.h"
#include "osl/module.hxx"
#include "osl/mutex.h"
#include "osl/mutex.hxx"
#include "osl/process.h"
#include "osl/semaphor.h"
#include "osl/thread.h"
#include "osl/thread.hxx"
#include "osl/time.h"

#include "rtl/alloc.h"
#include "rtl/byteseq.h"
#include "rtl/byteseq.hxx"
#include "rtl/instance.hxx"
#include "rtl/memory.h"
#include "rtl/process.h"
#include "rtl/random.h"
#include "rtl/strbuf.hxx"
#include "rtl/string.h"
#include "rtl/string.hxx"
#include "rtl/unload.h"
#include "rtl/ustrbuf.hxx"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "rtl/uuid.h"

#include "sal/alloca.h"
#include "sal/config.h"
#include "sal/types.h"

#include "sys/types.h"

#include "typelib/typeclass.h"
#include "typelib/typedescription.h"
#include "typelib/typedescription.hxx"

#include "uno/any2.h"
#include "uno/data.h"
#include "uno/dispatcher.h"
#include "uno/environment.h"
#include "uno/environment.hxx"
#include "uno/lbnames.h"
#include "uno/mapping.h"
#include "uno/mapping.hxx"
#include "uno/sequence2.h"
#include "uno/threadpool.h"
//---MARKER---
#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.3.54); FILE MERGED 2008/03/28 16:29:55 rt 1.3.54.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: precompiled_bridges.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): Generated on 2006-09-01 17:49:31.967936

#ifdef PRECOMPILED_HEADERS
//---MARKER---
#include "boost/static_assert.hpp"

#include "com/sun/star/bridge/InvalidProtocolChangeException.hdl"
#include "com/sun/star/bridge/InvalidProtocolChangeException.hpp"
#include "com/sun/star/bridge/ProtocolProperty.hdl"
#include "com/sun/star/bridge/ProtocolProperty.hpp"
#include "com/sun/star/bridge/XBridge.hpp"
#include "com/sun/star/bridge/XBridgeFactory.hpp"
#include "com/sun/star/bridge/XInstanceProvider.hpp"
#include "com/sun/star/bridge/XProtocolProperties.hdl"
#include "com/sun/star/bridge/XProtocolProperties.hpp"
#include "com/sun/star/bridge/XUnoUrlResolver.hpp"
#include "com/sun/star/connection/ConnectionSetupException.hpp"
#include "com/sun/star/connection/NoConnectException.hpp"
#include "com/sun/star/connection/XAcceptor.hpp"
#include "com/sun/star/connection/XConnection.hpp"
#include "com/sun/star/connection/XConnector.hpp"
#include "com/sun/star/frame/XComponentLoader.hpp"
#include "com/sun/star/io/XInputStream.hpp"
#include "com/sun/star/io/XOutputStream.hpp"
#include "com/sun/star/lang/DisposedException.hdl"
#include "com/sun/star/lang/DisposedException.hpp"
#include "com/sun/star/lang/IllegalArgumentException.hpp"
#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
#include "com/sun/star/lang/XComponent.hpp"
#include "com/sun/star/lang/XInitialization.hpp"
#include "com/sun/star/lang/XMain.hpp"
#include "com/sun/star/lang/XMultiComponentFactory.hpp"
#include "com/sun/star/lang/XServiceInfo.hpp"
#include "com/sun/star/lang/XSingleComponentFactory.hpp"
#include "com/sun/star/registry/InvalidRegistryException.hpp"
#include "com/sun/star/registry/XImplementationRegistration.hpp"
#include "com/sun/star/registry/XRegistryKey.hpp"
#include "com/sun/star/text/XTextDocument.hpp"
#include "com/sun/star/uno/Any.h"
#include "com/sun/star/uno/Any.hxx"
#include "com/sun/star/uno/DeploymentException.hpp"
#include "com/sun/star/uno/Exception.hdl"
#include "com/sun/star/uno/Exception.hpp"
#include "com/sun/star/uno/Reference.h"
#include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/RuntimeException.hdl"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/Sequence.h"
#include "com/sun/star/uno/Sequence.hxx"
#include "com/sun/star/uno/Type.h"
#include "com/sun/star/uno/Type.hxx"
#include "com/sun/star/uno/TypeClass.hdl"
#include "com/sun/star/uno/XComponentContext.hpp"
#include "com/sun/star/uno/XInterface.hdl"
#include "com/sun/star/uno/XInterface.hpp"
#include "com/sun/star/uno/XNamingService.hpp"
#include "com/sun/star/uno/genfunc.hxx"

#include "cppu/macros.hxx"
#include "cppu/unotype.hxx"

#include "cppuhelper/factory.hxx"
#include "cppuhelper/implbase1.hxx"
#include "cppuhelper/implbase2.hxx"
#include "cppuhelper/implbase3.hxx"
#include "cppuhelper/implementationentry.hxx"
#include "cppuhelper/servicefactory.hxx"
#include "cppuhelper/weak.hxx"

#include "osl/conditn.h"
#include "osl/conditn.hxx"
#include "osl/diagnose.h"
#include "osl/doublecheckedlocking.h"
#include "osl/getglobalmutex.hxx"
#include "osl/interlck.h"
#include "osl/module.h"
#include "osl/module.hxx"
#include "osl/mutex.h"
#include "osl/mutex.hxx"
#include "osl/process.h"
#include "osl/semaphor.h"
#include "osl/thread.h"
#include "osl/thread.hxx"
#include "osl/time.h"

#include "rtl/alloc.h"
#include "rtl/byteseq.h"
#include "rtl/byteseq.hxx"
#include "rtl/instance.hxx"
#include "rtl/memory.h"
#include "rtl/process.h"
#include "rtl/random.h"
#include "rtl/strbuf.hxx"
#include "rtl/string.h"
#include "rtl/string.hxx"
#include "rtl/unload.h"
#include "rtl/ustrbuf.hxx"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "rtl/uuid.h"

#include "sal/alloca.h"
#include "sal/config.h"
#include "sal/types.h"

#include "sys/types.h"

#include "typelib/typeclass.h"
#include "typelib/typedescription.h"
#include "typelib/typedescription.hxx"

#include "uno/any2.h"
#include "uno/data.h"
#include "uno/dispatcher.h"
#include "uno/environment.h"
#include "uno/environment.hxx"
#include "uno/lbnames.h"
#include "uno/mapping.h"
#include "uno/mapping.hxx"
#include "uno/sequence2.h"
#include "uno/threadpool.h"
//---MARKER---
#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: helper.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 15:59:10 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"
#include <rtl/alloc.h>
#include <osl/diagnose.h>

#include <bridges/remote/helper.hxx>

#include <bridges/remote/stub.hxx>
#include <bridges/remote/proxy.hxx>
#include <bridges/remote/remote.hxx>

#include <com/sun/star/uno/Sequence.hxx>

using namespace ::rtl;
using namespace ::com::sun::star::uno;

namespace bridges_remote
{

void SAL_CALL remote_createStub (
    remote_Interface **ppRemoteI,
    rtl_uString *pOid ,
    typelib_TypeDescriptionReference *pTypeRef,
    uno_Environment *pEnvRemote,
    ReleaseRemoteCallbackFunc releaseRemoteCallback )
{
    typelib_TypeDescription *pType = 0;
    typelib_typedescriptionreference_getDescription( &pType, pTypeRef );

    (void) pEnvRemote->pExtEnv->getRegisteredInterface(
        pEnvRemote->pExtEnv,
        (void **)ppRemoteI,
        pOid,
        (typelib_InterfaceTypeDescription* )pType );

    if( *ppRemoteI )
    {
        if( (*ppRemoteI)->acquire == acquireRemote2RemoteStub ) {

              if( releaseRemoteCallback )
              {
                  // use the callback handler, the bridge wants to send the call immeadiatly
                  releaseRemoteCallback( *ppRemoteI , pOid, pTypeRef , pEnvRemote );
              }
              else
              {
                ((::bridges_remote::Remote2RemoteStub *)*ppRemoteI)->releaseRemote();
              }
        }
        else
        {
            // Uno2RemoteStub
            // no release necessary
        }
    }
    else
    {
        remote_BridgeImpl *pImpl = ((remote_Context *)pEnvRemote->pContext)->m_pBridgeImpl;
        *ppRemoteI =
            new ::bridges_remote::Remote2RemoteStub(
                pOid,
                (typelib_InterfaceTypeDescription * ) pType,
                pEnvRemote,
                pImpl->m_sendRequest);

        // ppRemoteI may change during registration
        pEnvRemote->pExtEnv->registerProxyInterface(
            pEnvRemote->pExtEnv,
            (void **) ppRemoteI,
            freeRemote2RemoteStub,
            pOid,
            (typelib_InterfaceTypeDescription * ) pType );
    }

    typelib_typedescription_release( pType );
}

void SAL_CALL remote_sendQueryInterface(
    uno_Environment *pEnvRemote,
    remote_Interface **ppRemoteI,
    rtl_uString *pOid ,
    typelib_TypeDescriptionReference *pTypeRef,
    uno_Any **ppException
    )
{
    OSL_ASSERT( ppRemoteI );

    typelib_InterfaceTypeDescription *pType = 0;
    typelib_typedescriptionreference_getDescription( (typelib_TypeDescription ** )&pType, pTypeRef );

    if( *ppRemoteI )
    {
        (*ppRemoteI)->release( *ppRemoteI );
        (*ppRemoteI) = 0;
    }

    remote_BridgeImpl *pImpl = ((remote_Context *)pEnvRemote->pContext)->m_pBridgeImpl;

    Type type  = ::getCppuType( (Reference < XInterface > *)0 );

    // get type for queryInterface
    OUString sCompleteMethodName = type.getTypeName();
    sCompleteMethodName += OUString::createFromAscii("::queryInterface");

    typelib_InterfaceMemberTypeDescription *pMemberType = 0;
    typelib_typedescription_getByName(
        (typelib_TypeDescription **) &pMemberType,
        sCompleteMethodName.pData );

    OSL_ASSERT( pMemberType );

    uno_Any anyInterface;
    anyInterface.pType = 0;
    anyInterface.pData = 0;

    void *pReturn = &anyInterface;
    void *ppArgs[1];

    ppArgs[0] = 0;
    typelib_TypeDescriptionReference *pRef = 0;
    typelib_typedescriptionreference_new( &pRef ,
                                          pType->aBase.eTypeClass,
                                          pType->aBase.pTypeName);

    ppArgs[0] = &pRef;

//      uno_Any anyException;
//      uno_Any *pAnyException = &anyException;

    // do the queryInterface
    pImpl->m_sendRequest(
        pEnvRemote,
        (typelib_TypeDescription * ) pMemberType,
        pOid,
        pType,
        pReturn,
        ppArgs,
        ppException );

    // now release everything
    typelib_typedescriptionreference_release( pRef );
    typelib_typedescription_release( (typelib_TypeDescription * ) pMemberType );

    if( *ppException )
    {
        *ppRemoteI = 0;
    }
    else
    {
        // set out parameter
        if( typelib_TypeClass_INTERFACE == anyInterface.pType->eTypeClass )
        {
            *ppRemoteI = ( remote_Interface * )  anyInterface.pReserved;
        }
        typelib_typedescriptionreference_release( anyInterface.pType );
    }

    typelib_typedescription_release( (typelib_TypeDescription * ) pType );
}

void SAL_CALL remote_retrieveOidFromProxy(
    remote_Interface *pRemoteI,
    rtl_uString **ppOid )
{
    if( pRemoteI->acquire == acquireRemote2RemoteStub )
    {
        // Remote2RemoteStub
        ::bridges_remote::Remote2RemoteStub *pStub = (::bridges_remote::Remote2RemoteStub * ) pRemoteI;
        rtl_uString_newFromString( ppOid , pStub->m_sOid.pData );
    }
    else
    {
        // Uno2RemoteStub
        ::bridges_remote::Uno2RemoteStub *pStub = (::bridges_remote::Uno2RemoteStub * ) pRemoteI;
        rtl_uString_newFromString( ppOid , pStub->m_sOid.pData );
        pRemoteI->acquire( pRemoteI );
    }
}

}
<commit_msg>INTEGRATION: CWS changefileheader (1.7.100); FILE MERGED 2008/03/28 16:30:49 rt 1.7.100.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: helper.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_bridges.hxx"
#include <rtl/alloc.h>
#include <osl/diagnose.h>

#include <bridges/remote/helper.hxx>

#include <bridges/remote/stub.hxx>
#include <bridges/remote/proxy.hxx>
#include <bridges/remote/remote.hxx>

#include <com/sun/star/uno/Sequence.hxx>

using namespace ::rtl;
using namespace ::com::sun::star::uno;

namespace bridges_remote
{

void SAL_CALL remote_createStub (
    remote_Interface **ppRemoteI,
    rtl_uString *pOid ,
    typelib_TypeDescriptionReference *pTypeRef,
    uno_Environment *pEnvRemote,
    ReleaseRemoteCallbackFunc releaseRemoteCallback )
{
    typelib_TypeDescription *pType = 0;
    typelib_typedescriptionreference_getDescription( &pType, pTypeRef );

    (void) pEnvRemote->pExtEnv->getRegisteredInterface(
        pEnvRemote->pExtEnv,
        (void **)ppRemoteI,
        pOid,
        (typelib_InterfaceTypeDescription* )pType );

    if( *ppRemoteI )
    {
        if( (*ppRemoteI)->acquire == acquireRemote2RemoteStub ) {

              if( releaseRemoteCallback )
              {
                  // use the callback handler, the bridge wants to send the call immeadiatly
                  releaseRemoteCallback( *ppRemoteI , pOid, pTypeRef , pEnvRemote );
              }
              else
              {
                ((::bridges_remote::Remote2RemoteStub *)*ppRemoteI)->releaseRemote();
              }
        }
        else
        {
            // Uno2RemoteStub
            // no release necessary
        }
    }
    else
    {
        remote_BridgeImpl *pImpl = ((remote_Context *)pEnvRemote->pContext)->m_pBridgeImpl;
        *ppRemoteI =
            new ::bridges_remote::Remote2RemoteStub(
                pOid,
                (typelib_InterfaceTypeDescription * ) pType,
                pEnvRemote,
                pImpl->m_sendRequest);

        // ppRemoteI may change during registration
        pEnvRemote->pExtEnv->registerProxyInterface(
            pEnvRemote->pExtEnv,
            (void **) ppRemoteI,
            freeRemote2RemoteStub,
            pOid,
            (typelib_InterfaceTypeDescription * ) pType );
    }

    typelib_typedescription_release( pType );
}

void SAL_CALL remote_sendQueryInterface(
    uno_Environment *pEnvRemote,
    remote_Interface **ppRemoteI,
    rtl_uString *pOid ,
    typelib_TypeDescriptionReference *pTypeRef,
    uno_Any **ppException
    )
{
    OSL_ASSERT( ppRemoteI );

    typelib_InterfaceTypeDescription *pType = 0;
    typelib_typedescriptionreference_getDescription( (typelib_TypeDescription ** )&pType, pTypeRef );

    if( *ppRemoteI )
    {
        (*ppRemoteI)->release( *ppRemoteI );
        (*ppRemoteI) = 0;
    }

    remote_BridgeImpl *pImpl = ((remote_Context *)pEnvRemote->pContext)->m_pBridgeImpl;

    Type type  = ::getCppuType( (Reference < XInterface > *)0 );

    // get type for queryInterface
    OUString sCompleteMethodName = type.getTypeName();
    sCompleteMethodName += OUString::createFromAscii("::queryInterface");

    typelib_InterfaceMemberTypeDescription *pMemberType = 0;
    typelib_typedescription_getByName(
        (typelib_TypeDescription **) &pMemberType,
        sCompleteMethodName.pData );

    OSL_ASSERT( pMemberType );

    uno_Any anyInterface;
    anyInterface.pType = 0;
    anyInterface.pData = 0;

    void *pReturn = &anyInterface;
    void *ppArgs[1];

    ppArgs[0] = 0;
    typelib_TypeDescriptionReference *pRef = 0;
    typelib_typedescriptionreference_new( &pRef ,
                                          pType->aBase.eTypeClass,
                                          pType->aBase.pTypeName);

    ppArgs[0] = &pRef;

//      uno_Any anyException;
//      uno_Any *pAnyException = &anyException;

    // do the queryInterface
    pImpl->m_sendRequest(
        pEnvRemote,
        (typelib_TypeDescription * ) pMemberType,
        pOid,
        pType,
        pReturn,
        ppArgs,
        ppException );

    // now release everything
    typelib_typedescriptionreference_release( pRef );
    typelib_typedescription_release( (typelib_TypeDescription * ) pMemberType );

    if( *ppException )
    {
        *ppRemoteI = 0;
    }
    else
    {
        // set out parameter
        if( typelib_TypeClass_INTERFACE == anyInterface.pType->eTypeClass )
        {
            *ppRemoteI = ( remote_Interface * )  anyInterface.pReserved;
        }
        typelib_typedescriptionreference_release( anyInterface.pType );
    }

    typelib_typedescription_release( (typelib_TypeDescription * ) pType );
}

void SAL_CALL remote_retrieveOidFromProxy(
    remote_Interface *pRemoteI,
    rtl_uString **ppOid )
{
    if( pRemoteI->acquire == acquireRemote2RemoteStub )
    {
        // Remote2RemoteStub
        ::bridges_remote::Remote2RemoteStub *pStub = (::bridges_remote::Remote2RemoteStub * ) pRemoteI;
        rtl_uString_newFromString( ppOid , pStub->m_sOid.pData );
    }
    else
    {
        // Uno2RemoteStub
        ::bridges_remote::Uno2RemoteStub *pStub = (::bridges_remote::Uno2RemoteStub * ) pRemoteI;
        rtl_uString_newFromString( ppOid , pStub->m_sOid.pData );
        pRemoteI->acquire( pRemoteI );
    }
}

}
<|endoftext|>


<commit_before>#include "Character.h"

Character::Character():
	m_spriteCharater(new sf::Sprite()),
	m_textureCharacter(new sf::Texture())
{
	m_textureCharacter->loadFromFile("Ressources/sprites/spooky/sprite.png");
	m_spriteCharater->setTexture(*m_textureCharacter);
	m_spriteCharater->setTextureRect(sf::IntRect(0, 0, 32, 32));

	m_position = sf::Vector2f(1, 1.);
	m_spriteCharater->setPosition(sf::Vector2f(1, 1.));
}

Character::~Character()
{}

void Character::setAngle(int alpha)
{
	m_angleShot += alpha;
}

sf::Vector2f Character::getDirection()
{
	return sf::Vector2f(cos(m_angleShot), sin(m_angleShot));
}

void Character::jump()
{
	//TO DO
	//while(!obstacles)
	{
		this->m_position = m_spriteCharater->getPosition() + this->getDirection()*m_velocity;
		m_spriteCharater->move(this->getDirection()*m_velocity);
	}
	return;
}

void Character::draw(sf::RenderWindow *window) const
{
	window->draw(*m_spriteCharater);
	}

//A Ajouter dans le update
/*if (m_currentAnimation == StateAnimation::Left){
m_spriteCharater->setTextureRect(sf::IntRect(32, 0, 32, 32));
}
else if (m_currentAnimation == StateAnimation::Midle){
m_spriteCharater->setTextureRect(sf::IntRect(32, 32, 32, 32));
}
else if (m_currentAnimation == StateAnimation::Right){
m_spriteCharater->setTextureRect(sf::IntRect(32, 64, 32, 32));
}
*/<commit_msg> sprite character drawed<commit_after>#include "Character.h"

Character::Character():
	m_spriteCharater(new sf::Sprite()),
	m_textureCharacter(new sf::Texture())
{
	m_textureCharacter->loadFromFile("Build/Ressources/sprites/spooky/sprite.png");
	m_spriteCharater->setTexture(*m_textureCharacter);
	m_spriteCharater->setTextureRect(sf::IntRect(0, 0, 32, 32));

	m_position = sf::Vector2f(1, 1.);
	m_spriteCharater->setPosition(sf::Vector2f(1, 1.));
}

Character::~Character()
{}

void Character::setAngle(int alpha)
{
	m_angleShot += alpha;
}

sf::Vector2f Character::getDirection()
{
	return sf::Vector2f(cos(m_angleShot), sin(m_angleShot));
}

void Character::jump()
{
	//TO DO
	//while(!obstacles)
	{
		this->m_position = m_spriteCharater->getPosition() + this->getDirection()*m_velocity;
		m_spriteCharater->move(this->getDirection()*m_velocity);
	}
	return;
}

void Character::draw(sf::RenderWindow *window) const
{
	window->draw(*m_spriteCharater);
	}

void Character::update(){
	if (m_currentAnimation == StateAnimation::Left){
		m_spriteCharater->setTextureRect(sf::IntRect(32, 0, 32, 32));
		m_currentAnimation
	}
	else if (m_currentAnimation == StateAnimation::Midle){
		m_spriteCharater->setTextureRect(sf::IntRect(32, 32, 32, 32));
	}
	else if (m_currentAnimation == StateAnimation::Right){
		m_spriteCharater->setTextureRect(sf::IntRect(32, 64, 32, 32));
	}
}
<|endoftext|>


<commit_before>
// This file is part of lipstick, a QML desktop library
//
// Copyright (c) 2012 Jolla Ltd.
// Contact: Thomas Perl <thomas.perl@jolla.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation
// and appearing in the file LICENSE.LGPL included in the packaging
// of this file.
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.

#include "launchermonitor.h"

#include "launcheritem.h"

#include <QDir>

/**
 * Timeout (in milliseconds) to hold back sending updates, so that we can
 * combine multiple updates to icons and desktop file in one go. Also to
 * avoid doing extraneous updates in case files get added/changed/removed
 * in quick succession.
 **/
#define LAUNCHER_MONITOR_HOLDBACK_TIMEOUT_MS 2000

LauncherMonitor::LauncherMonitor(const QString &desktopFilesPath,
        const QString &iconFilesPath)
    : QObject()
    , m_watcher()
    , m_holdbackTimer()
    , m_knownFiles()
    , m_addedFiles()
    , m_modifiedFiles()
    , m_removedFiles()
    , m_desktopFilesPath(desktopFilesPath)
{
    m_holdbackTimer.setSingleShot(true);

    QObject::connect(&m_watcher, SIGNAL(directoryChanged(const QString &)),
            this, SLOT(onDirectoryChanged(const QString &)));
    QObject::connect(&m_watcher, SIGNAL(fileChanged(const QString &)),
            this, SLOT(onFileChanged(const QString &)));
    QObject::connect(&m_holdbackTimer, SIGNAL(timeout()),
            this, SLOT(onHoldbackTimerTimeout()));

    m_iconFilesPaths << iconFilesPath;

    m_watcher.addPaths(m_iconFilesPaths);
    m_watcher.addPath(m_desktopFilesPath);

    // Force initial scan of directories
    // Scan the desktop files first, so that the launcher items are already
    // available by the time the icons will be processed
    onDirectoryChanged(m_desktopFilesPath);
    onDirectoryChanged(iconFilesPath);
}

LauncherMonitor::~LauncherMonitor()
{
}

void LauncherMonitor::start()
{
    // Manually force sending an update (this should be called when signals are
    // hooked up and the model is ready to receive update events)
    m_holdbackTimer.stop();
    onHoldbackTimerTimeout();
}

QStringList LauncherMonitor::directories() const
{
    QStringList result;
    // Right now, we only monitor one directory for .desktop files
    result.append(m_desktopFilesPath);
    return result;
}

QStringList LauncherMonitor::iconDirectories() const
{
    return m_iconFilesPaths;
}

void LauncherMonitor::setIconDirectories(const QStringList &dirs)
{
    QStringList newPaths;
    QStringList::ConstIterator it = dirs.begin();
    while (it != dirs.end()) {
        if (!m_iconFilesPaths.contains(*it)) {
            newPaths << *it;
        } else {
            m_iconFilesPaths.removeAll(*it);
        }
        ++it;
    }

    m_watcher.removePaths(m_iconFilesPaths);

    m_iconFilesPaths = dirs;
    m_watcher.addPaths(newPaths);
    foreach (QString path, newPaths)
        onDirectoryChanged(path);
}

void LauncherMonitor::onDirectoryChanged(const QString &path)
{
    QDir dir(path);
    QStringList seen = dir.entryList();
    QStringList added;
    QStringList removed;
    QStringList &knownFiles = m_knownFiles[path];

    // Calculate added and removed files
    foreach (const QString &filename, knownFiles) {
        if (filename.startsWith(".")) {
            continue;
        }

        if (!seen.contains(filename)) {
            removed.append(dir.filePath(filename));
        }
    }
    foreach (const QString &filename, seen) {
        if (filename.startsWith(".")) {
            continue;
        }

        if (!knownFiles.contains(filename)) {
            added.append(dir.filePath(filename));
        }
    }

    // First, stop monitoring all removed files and then tell interested
    // parties that these files have gone.
    // After that, do the same thing for added files.
    if (!removed.isEmpty()) {
        m_watcher.removePaths(removed);

        foreach (const QString &filename, removed) {
            m_modifiedFiles.removeAll(filename);
            if (m_addedFiles.contains(filename)) {
                // We have an "added" notification that's not sent out yet
                // Just remove this notification, as if nothing happened
                //
                // (=> the file has been added and quickly removed again)
                m_addedFiles.removeAll(filename);
            } else {
                m_removedFiles.append(filename);
            }
        }
    }

    if (!added.isEmpty()) {
        m_watcher.addPaths(added);

        foreach (const QString &filename, added) {
            m_modifiedFiles.removeAll(filename);
            if (m_removedFiles.contains(filename)) {
                // We have a "removed" notification that's not sent out yet
                // Just remove this notification, as if nothing happened
                //
                // (=> the file has vanished and re-appeared quickly)
                m_removedFiles.removeAll(filename);
            } else {
                m_addedFiles.append(filename);
            }
        }
    }

    // Schedule updating the launcher icons
    m_holdbackTimer.start(LAUNCHER_MONITOR_HOLDBACK_TIMEOUT_MS);

    knownFiles = seen;
}

void LauncherMonitor::onFileChanged(const QString &path)
{
    m_modifiedFiles.append(path);
    // Schedule updating the launcher icons
    m_holdbackTimer.start(LAUNCHER_MONITOR_HOLDBACK_TIMEOUT_MS);
}

void LauncherMonitor::onHoldbackTimerTimeout()
{
    QStringList modifiedCandidates = m_modifiedFiles;
    foreach (const QString &filename, modifiedCandidates) {
        // This takes care of avoiding sending modifications for two cases:
        //   1. The file was added and then modified
        //   2. The file was modified and then removed
        if (m_addedFiles.contains(filename) || m_removedFiles.contains(filename)) {
            m_modifiedFiles.removeOne(filename);
        }
    }

    if (m_addedFiles.isEmpty() && m_modifiedFiles.isEmpty() && m_removedFiles.isEmpty()) {
        // Nothing to update
        return;
    }

    LAUNCHER_DEBUG("=========");
    LAUNCHER_DEBUG("Added:" << m_addedFiles);
    LAUNCHER_DEBUG("Modified:" << m_modifiedFiles);
    LAUNCHER_DEBUG("Removed:" << m_removedFiles);
    LAUNCHER_DEBUG("=========");

    emit filesUpdated(m_addedFiles, m_modifiedFiles, m_removedFiles);
    m_addedFiles.clear();
    m_modifiedFiles.clear();
    m_removedFiles.clear();
}
<commit_msg>[lipstick] Don't try to remove an empty set of paths from a QFileSystemWatcher<commit_after>
// This file is part of lipstick, a QML desktop library
//
// Copyright (c) 2012 Jolla Ltd.
// Contact: Thomas Perl <thomas.perl@jolla.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation
// and appearing in the file LICENSE.LGPL included in the packaging
// of this file.
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.

#include "launchermonitor.h"

#include "launcheritem.h"

#include <QDir>

/**
 * Timeout (in milliseconds) to hold back sending updates, so that we can
 * combine multiple updates to icons and desktop file in one go. Also to
 * avoid doing extraneous updates in case files get added/changed/removed
 * in quick succession.
 **/
#define LAUNCHER_MONITOR_HOLDBACK_TIMEOUT_MS 2000

LauncherMonitor::LauncherMonitor(const QString &desktopFilesPath,
        const QString &iconFilesPath)
    : QObject()
    , m_watcher()
    , m_holdbackTimer()
    , m_knownFiles()
    , m_addedFiles()
    , m_modifiedFiles()
    , m_removedFiles()
    , m_desktopFilesPath(desktopFilesPath)
{
    m_holdbackTimer.setSingleShot(true);

    QObject::connect(&m_watcher, SIGNAL(directoryChanged(const QString &)),
            this, SLOT(onDirectoryChanged(const QString &)));
    QObject::connect(&m_watcher, SIGNAL(fileChanged(const QString &)),
            this, SLOT(onFileChanged(const QString &)));
    QObject::connect(&m_holdbackTimer, SIGNAL(timeout()),
            this, SLOT(onHoldbackTimerTimeout()));

    m_iconFilesPaths << iconFilesPath;

    m_watcher.addPaths(m_iconFilesPaths);
    m_watcher.addPath(m_desktopFilesPath);

    // Force initial scan of directories
    // Scan the desktop files first, so that the launcher items are already
    // available by the time the icons will be processed
    onDirectoryChanged(m_desktopFilesPath);
    onDirectoryChanged(iconFilesPath);
}

LauncherMonitor::~LauncherMonitor()
{
}

void LauncherMonitor::start()
{
    // Manually force sending an update (this should be called when signals are
    // hooked up and the model is ready to receive update events)
    m_holdbackTimer.stop();
    onHoldbackTimerTimeout();
}

QStringList LauncherMonitor::directories() const
{
    QStringList result;
    // Right now, we only monitor one directory for .desktop files
    result.append(m_desktopFilesPath);
    return result;
}

QStringList LauncherMonitor::iconDirectories() const
{
    return m_iconFilesPaths;
}

void LauncherMonitor::setIconDirectories(const QStringList &dirs)
{
    QStringList newPaths;
    QStringList::ConstIterator it = dirs.begin();
    while (it != dirs.end()) {
        if (!m_iconFilesPaths.contains(*it)) {
            newPaths << *it;
        } else {
            m_iconFilesPaths.removeAll(*it);
        }
        ++it;
    }

    if (!m_iconFilesPaths.isEmpty()) {
        m_watcher.removePaths(m_iconFilesPaths);
    }

    m_iconFilesPaths = dirs;
    m_watcher.addPaths(newPaths);
    foreach (QString path, newPaths)
        onDirectoryChanged(path);
}

void LauncherMonitor::onDirectoryChanged(const QString &path)
{
    QDir dir(path);
    QStringList seen = dir.entryList();
    QStringList added;
    QStringList removed;
    QStringList &knownFiles = m_knownFiles[path];

    // Calculate added and removed files
    foreach (const QString &filename, knownFiles) {
        if (filename.startsWith(".")) {
            continue;
        }

        if (!seen.contains(filename)) {
            removed.append(dir.filePath(filename));
        }
    }
    foreach (const QString &filename, seen) {
        if (filename.startsWith(".")) {
            continue;
        }

        if (!knownFiles.contains(filename)) {
            added.append(dir.filePath(filename));
        }
    }

    // First, stop monitoring all removed files and then tell interested
    // parties that these files have gone.
    // After that, do the same thing for added files.
    if (!removed.isEmpty()) {
        m_watcher.removePaths(removed);

        foreach (const QString &filename, removed) {
            m_modifiedFiles.removeAll(filename);
            if (m_addedFiles.contains(filename)) {
                // We have an "added" notification that's not sent out yet
                // Just remove this notification, as if nothing happened
                //
                // (=> the file has been added and quickly removed again)
                m_addedFiles.removeAll(filename);
            } else {
                m_removedFiles.append(filename);
            }
        }
    }

    if (!added.isEmpty()) {
        m_watcher.addPaths(added);

        foreach (const QString &filename, added) {
            m_modifiedFiles.removeAll(filename);
            if (m_removedFiles.contains(filename)) {
                // We have a "removed" notification that's not sent out yet
                // Just remove this notification, as if nothing happened
                //
                // (=> the file has vanished and re-appeared quickly)
                m_removedFiles.removeAll(filename);
            } else {
                m_addedFiles.append(filename);
            }
        }
    }

    // Schedule updating the launcher icons
    m_holdbackTimer.start(LAUNCHER_MONITOR_HOLDBACK_TIMEOUT_MS);

    knownFiles = seen;
}

void LauncherMonitor::onFileChanged(const QString &path)
{
    m_modifiedFiles.append(path);
    // Schedule updating the launcher icons
    m_holdbackTimer.start(LAUNCHER_MONITOR_HOLDBACK_TIMEOUT_MS);
}

void LauncherMonitor::onHoldbackTimerTimeout()
{
    QStringList modifiedCandidates = m_modifiedFiles;
    foreach (const QString &filename, modifiedCandidates) {
        // This takes care of avoiding sending modifications for two cases:
        //   1. The file was added and then modified
        //   2. The file was modified and then removed
        if (m_addedFiles.contains(filename) || m_removedFiles.contains(filename)) {
            m_modifiedFiles.removeOne(filename);
        }
    }

    if (m_addedFiles.isEmpty() && m_modifiedFiles.isEmpty() && m_removedFiles.isEmpty()) {
        // Nothing to update
        return;
    }

    LAUNCHER_DEBUG("=========");
    LAUNCHER_DEBUG("Added:" << m_addedFiles);
    LAUNCHER_DEBUG("Modified:" << m_modifiedFiles);
    LAUNCHER_DEBUG("Removed:" << m_removedFiles);
    LAUNCHER_DEBUG("=========");

    emit filesUpdated(m_addedFiles, m_modifiedFiles, m_removedFiles);
    m_addedFiles.clear();
    m_modifiedFiles.clear();
    m_removedFiles.clear();
}
<|endoftext|>