<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2020 Scientific Computing and Imaging Institute,
   University of Utah.

   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 "ArcBall.hpp"
#include <glm/gtx/vec_swizzle.hpp>

namespace spire {

//------------------------------------------------------------------------------
  ArcBall::ArcBall(const glm::vec3& center, float radius, bool inverted, const glm::mat4& screenToTCS) :
    mScreenToTCS(screenToTCS),
    mCenter(center),
    mRadius(radius),
    invertHemisphere(inverted)
{
  // glm uses the following format for quaternions: w,x,y,z.
  //        w,    x,    y,    z
  glm::quat qOne(1.0, 0.0, 0.0, 0.0);
  glm::vec3 vZero(0.0, 0.0, 0.0);

  mQDown       = qOne;
  mQNow        = qOne;
  mVSphereDown = mouseOnSphere(vZero);
}

//------------------------------------------------------------------------------
glm::vec3 ArcBall::mouseOnSphere(const glm::vec3& tscMouse)
{
  glm::vec3 ballMouse(xy(tscMouse - mCenter) / mRadius, 0.0);

  float mag_sq = glm::dot(ballMouse, ballMouse);
  if (mag_sq > 1.0)
  {
    // Since we are outside of the sphere, map to the visible boundary of the sphere.
    ballMouse *= 1.0 / sqrtf(mag_sq);
  }
  else
  {
    // Essentially, we are normalizing the vector by adding the missing z component.
    ballMouse.z = sqrtf(1.0 - mag_sq);
  }

  if(invertHemisphere)
    ballMouse.z = -ballMouse.z;

  return ballMouse;
}

//------------------------------------------------------------------------------
void ArcBall::beginDrag(const glm::vec2& msc)
{
  mQDown       = mQNow;
  mVSphereDown = mouseOnSphere(xyz(mScreenToTCS * glm::vec4(msc, 0.0f, 1.0f)));
}

//------------------------------------------------------------------------------
void ArcBall::drag(const glm::vec2& msc)
{
  glm::vec3 mVSphereNow = mouseOnSphere(xyz(mScreenToTCS * glm::vec4(msc, 0.0f, 1.0f)));

  // Construct a quaternion from two points on the unit sphere.
  glm::quat mQDrag = quatFromUnitSphere(mVSphereDown, mVSphereNow);
  mQNow = mQDrag * mQDown;
  if(glm::dot(mVSphereDown, mVSphereNow) < 0.0)
    beginDrag(msc);
}

//------------------------------------------------------------------------------
void ArcBall::setLocationOnSphere(glm::vec3 location, glm::vec3 up)
{
  glm::mat4 mMatNow = glm::lookAt(location, glm::vec3(0.0f), up);
  mQNow = glm::quat_cast(mMatNow);
}

//------------------------------------------------------------------------------
glm::quat ArcBall::quatFromUnitSphere(const glm::vec3& from, const glm::vec3& to)
{
  //TODO: check if cross is 0 before normalize. Crashes on Windows
  auto c = glm::cross(from, to);
  if (c == glm::vec3(0, 0, 0))
    return {};

  glm::vec3 axis = glm::normalize(c);

  // Give arbitrary non-zero vector because no rotation
  if (std::isnan(axis[0]))
    axis = from;

  float angle = std::acos(glm::dot(from, to));

  if(angle <= 0.00001 || std::isnan(angle))
    return glm::quat(1.0, 0.0, 0.0, 0.0);

  return glm::angleAxis(angle, axis);
}

//------------------------------------------------------------------------------
glm::mat4 ArcBall::getTransformation() const
{
  return glm::mat4_cast(mQNow);
}

} // namespace spire
<commit_msg>Removed code causing arc ball issues<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2020 Scientific Computing and Imaging Institute,
   University of Utah.

   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 "ArcBall.hpp"
#include <glm/gtx/vec_swizzle.hpp>

namespace spire {

//------------------------------------------------------------------------------
  ArcBall::ArcBall(const glm::vec3& center, float radius, bool inverted, const glm::mat4& screenToTCS) :
    mScreenToTCS(screenToTCS),
    mCenter(center),
    mRadius(radius),
    invertHemisphere(inverted)
{
  // glm uses the following format for quaternions: w,x,y,z.
  //        w,    x,    y,    z
  glm::quat qOne(1.0, 0.0, 0.0, 0.0);
  glm::vec3 vZero(0.0, 0.0, 0.0);

  mQDown       = qOne;
  mQNow        = qOne;
  mVSphereDown = mouseOnSphere(vZero);
}

//------------------------------------------------------------------------------
glm::vec3 ArcBall::mouseOnSphere(const glm::vec3& tscMouse)
{
  glm::vec3 ballMouse(xy(tscMouse - mCenter) / mRadius, 0.0);

  float mag_sq = glm::dot(ballMouse, ballMouse);
  if (mag_sq > 1.0)
  {
    // Since we are outside of the sphere, map to the visible boundary of the sphere.
    ballMouse *= 1.0 / sqrtf(mag_sq);
  }
  else
  {
    // Essentially, we are normalizing the vector by adding the missing z component.
    ballMouse.z = sqrtf(1.0 - mag_sq);
  }

  if(invertHemisphere)
    ballMouse.z = -ballMouse.z;

  return ballMouse;
}

//------------------------------------------------------------------------------
void ArcBall::beginDrag(const glm::vec2& msc)
{
  mQDown       = mQNow;
  mVSphereDown = mouseOnSphere(xyz(mScreenToTCS * glm::vec4(msc, 0.0f, 1.0f)));
}

//------------------------------------------------------------------------------
void ArcBall::drag(const glm::vec2& msc)
{
  glm::vec3 mVSphereNow = mouseOnSphere(xyz(mScreenToTCS * glm::vec4(msc, 0.0f, 1.0f)));

  // Construct a quaternion from two points on the unit sphere.
  glm::quat mQDrag = quatFromUnitSphere(mVSphereDown, mVSphereNow);
  mQNow = mQDrag * mQDown;
}

//------------------------------------------------------------------------------
void ArcBall::setLocationOnSphere(glm::vec3 location, glm::vec3 up)
{
  glm::mat4 mMatNow = glm::lookAt(location, glm::vec3(0.0f), up);
  mQNow = glm::quat_cast(mMatNow);
}

//------------------------------------------------------------------------------
glm::quat ArcBall::quatFromUnitSphere(const glm::vec3& from, const glm::vec3& to)
{
  //TODO: check if cross is 0 before normalize. Crashes on Windows
  auto c = glm::cross(from, to);
  if (c == glm::vec3(0, 0, 0))
    return {};

  glm::vec3 axis = glm::normalize(c);

  // Give arbitrary non-zero vector because no rotation
  if (std::isnan(axis[0]))
    axis = from;

  float angle = std::acos(glm::dot(from, to));

  if(angle <= 0.00001 || std::isnan(angle))
    return glm::quat(1.0, 0.0, 0.0, 0.0);

  return glm::angleAxis(angle, axis);
}

//------------------------------------------------------------------------------
glm::mat4 ArcBall::getTransformation() const
{
  return glm::mat4_cast(mQNow);
}

} // namespace spire
<|endoftext|>


<commit_before>#include "ShadowRenderer.hpp"
#include <stdexcept>

WARN_GUARD_ON
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
WARN_GUARD_OFF

static const char* vShader = R"foo(
#version 330 core
layout (location = 0) in vec3 position;

uniform mat4 lightSpaceMatrix;
uniform mat4 model;

void main()
{
    gl_Position = lightSpaceMatrix * model * vec4(position, 1.0f);
}
)foo";

static const char* fShader = R"foo(
#version 330 core

void main()
{
    // gl_FragDepth = gl_FragCoord.z;
}
)foo";

void ShadowRenderer::Init(unsigned int width, unsigned int height)
{
    mWidth = width;
    mHeight = height;

    Shader vert(vShader, Shader::Type::Vertex);
    Shader frag(fShader, Shader::Type::Fragment);
    mProgram = std::make_unique<ShaderProgram>(vert.Id(), frag.Id());

    glGenTextures(1, &mDepthMapId);

    glBindTexture(GL_TEXTURE_2D, mDepthMapId);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glBindTexture(GL_TEXTURE_2D, 0);

    glGenFramebuffers(1, &mDepthMapFboId);

    glBindFramebuffer(GL_FRAMEBUFFER, mDepthMapFboId);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthMapId, 0);
    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    // Check if framebuffer is complete
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        throw std::runtime_error("OpenGL: Framebuffer incomplete!");
}

void ShadowRenderer::Shutdown()
{
    glDeleteTextures(1, &mDepthMapId);
    glDeleteFramebuffers(1, &mDepthMapFboId);
}

void ShadowRenderer::Render(float interpolation)
{
    glViewport(0, 0, mWidth, mHeight);
    glBindFramebuffer(GL_FRAMEBUFFER, mDepthMapFboId);
        glClear(GL_DEPTH_BUFFER_BIT);
        glUseProgram(mProgram->Id());

        // Calculate light space matrix
        glm::mat4 lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 1.0f, 7.5f);
        glm::mat4 lightView = glm::lookAt(mLightPos, glm::vec3(0.0f), glm::vec3(1.0));
        glm::mat4 lightSpaceMatrix = lightProjection * lightView;

        glUniformMatrix4fv(
            glGetUniformLocation(mProgram->Id(), "lightSpaceMatrix"),
            1,
            GL_FALSE,
            glm::value_ptr(lightSpaceMatrix)
        );

        for (const auto& gObj : mScene->GetNodes())
        {
            // Upload needed uniforms
            glm::mat4 model = gObj.second->GetTransformation().GetInterpolated(interpolation);
            glUniformMatrix4fv(glGetUniformLocation(mProgram->Id(), "model"), 1, GL_FALSE, glm::value_ptr(model));

            // Get the model
            ModelDescription* mdl = (*mModelStore)[gObj.second->GetModel()];
            if (mdl)
            {
                // Draw the model
                for (const auto& mesh : mdl->meshes)
                {
                    glBindVertexArray(mesh.vaoId);
                    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.eboId);
                    glDrawElements(GL_TRIANGLES, mesh.numIndices, GL_UNSIGNED_INT, 0);
                    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
                    glBindVertexArray(0);
                }
            }
        }

        glUseProgram(0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void ShadowRenderer::SetScene(const Scene* scene)
{
    mScene = scene;
}

void ShadowRenderer::SetModelStore(ModelStore* modelStore)
{
    mModelStore = modelStore;
}

void ShadowRenderer::SetLightPos(const glm::vec3& lightPos)
{
    mLightPos = lightPos;
}

GLuint ShadowRenderer::DepthMapId() const
{
    return mDepthMapId;
}
<commit_msg>ShadowRenderer changes cull face before creating the shadow map to prevent Peter Panning<commit_after>#include "ShadowRenderer.hpp"
#include <stdexcept>

WARN_GUARD_ON
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
WARN_GUARD_OFF

static const char* vShader = R"foo(
#version 330 core
layout (location = 0) in vec3 position;

uniform mat4 lightSpaceMatrix;
uniform mat4 model;

void main()
{
    gl_Position = lightSpaceMatrix * model * vec4(position, 1.0f);
}
)foo";

static const char* fShader = R"foo(
#version 330 core

void main()
{
    // gl_FragDepth = gl_FragCoord.z;
}
)foo";

void ShadowRenderer::Init(unsigned int width, unsigned int height)
{
    mWidth = width;
    mHeight = height;

    Shader vert(vShader, Shader::Type::Vertex);
    Shader frag(fShader, Shader::Type::Fragment);
    mProgram = std::make_unique<ShaderProgram>(vert.Id(), frag.Id());

    glGenTextures(1, &mDepthMapId);

    glBindTexture(GL_TEXTURE_2D, mDepthMapId);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glBindTexture(GL_TEXTURE_2D, 0);

    glGenFramebuffers(1, &mDepthMapFboId);

    glBindFramebuffer(GL_FRAMEBUFFER, mDepthMapFboId);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthMapId, 0);
    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    // Check if framebuffer is complete
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        throw std::runtime_error("OpenGL: Framebuffer incomplete!");
}

void ShadowRenderer::Shutdown()
{
    glDeleteTextures(1, &mDepthMapId);
    glDeleteFramebuffers(1, &mDepthMapFboId);
}

void ShadowRenderer::Render(float interpolation)
{
    glCullFace(GL_FRONT);
    glViewport(0, 0, mWidth, mHeight);
    glBindFramebuffer(GL_FRAMEBUFFER, mDepthMapFboId);
        glClear(GL_DEPTH_BUFFER_BIT);
        glUseProgram(mProgram->Id());

        // Calculate light space matrix
        glm::mat4 lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 1.0f, 7.5f);
        glm::mat4 lightView = glm::lookAt(mLightPos, glm::vec3(0.0f), glm::vec3(1.0));
        glm::mat4 lightSpaceMatrix = lightProjection * lightView;

        glUniformMatrix4fv(
            glGetUniformLocation(mProgram->Id(), "lightSpaceMatrix"),
            1,
            GL_FALSE,
            glm::value_ptr(lightSpaceMatrix)
        );

        for (const auto& gObj : mScene->GetNodes())
        {
            // Upload needed uniforms
            glm::mat4 model = gObj.second->GetTransformation().GetInterpolated(interpolation);
            glUniformMatrix4fv(glGetUniformLocation(mProgram->Id(), "model"), 1, GL_FALSE, glm::value_ptr(model));

            // Get the model
            ModelDescription* mdl = (*mModelStore)[gObj.second->GetModel()];
            if (mdl)
            {
                // Draw the model
                for (const auto& mesh : mdl->meshes)
                {
                    glBindVertexArray(mesh.vaoId);
                    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.eboId);
                    glDrawElements(GL_TRIANGLES, mesh.numIndices, GL_UNSIGNED_INT, 0);
                    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
                    glBindVertexArray(0);
                }
            }
        }

        glUseProgram(0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glCullFace(GL_BACK);
}

void ShadowRenderer::SetScene(const Scene* scene)
{
    mScene = scene;
}

void ShadowRenderer::SetModelStore(ModelStore* modelStore)
{
    mModelStore = modelStore;
}

void ShadowRenderer::SetLightPos(const glm::vec3& lightPos)
{
    mLightPos = lightPos;
}

GLuint ShadowRenderer::DepthMapId() const
{
    return mDepthMapId;
}
<|endoftext|>


<commit_before>// Deliberate ifdef even if we have #pragma once if anyone wants to auto-detect RPOCO with the define
#ifndef __INCLUDED_RPOCO_HPP__
#define __INCLUDED_RPOCO_HPP__

#pragma once

#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <utility>
#include <atomic>
#include <mutex>
#include <cctype>
#include <stdint.h>
#include <type_traits>
#include <functional>

// Thread safe typeinfo init (double checked lock)

#define RPOCO(...) \
	void rpoco_type_info_expand(rpoco::type_info *ti,std::vector<std::string>& names,int idx) {} \
	template<typename H,typename... R> \
	void rpoco_type_info_expand(rpoco::type_info *ti,std::vector<std::string>& names,int idx,H&& head,R&&... rest) {\
		ptrdiff_t off=(ptrdiff_t) (  ((uintptr_t)&head)-((uintptr_t)this) ); \
		ti->add(new rpoco::field< std::remove_reference<H>::type >(names[idx],off) );\
		rpoco_type_info_expand(ti,names,idx+1,rest...); \
	} \
	rpoco::type_info* rpoco_type_info_get() { \
		static rpoco::type_info ti; \
		if(!ti.is_init()) { \
			ti.init([this](rpoco::type_info *ti) { \
				std::vector<std::string> names=rpoco::extract_macro_names(#__VA_ARGS__); \
				rpoco_type_info_expand(ti,names,0,__VA_ARGS__); \
			} ); \
		} \
		return &ti; \
	}

// Write JSON:
// beginObject
// [] visitField
// endObject

// beginArray
// visitField (no fieldbase?)
// endArray

// Read JSON
// beginObject
// []locatefield
// endObject

// beginArray

namespace rpoco {
	class fieldbase;
	class field_provider;

	enum visit_type {
		object,
		array
	};

	struct visitor {
		virtual bool visit_start(visit_type vt)=0;
		virtual void visit_end(visit_type vt)=0;
		virtual void visit_end(visit_type vt,std::function<void(std::string&)> out)=0;
		virtual void visit(int& x)=0;
		virtual void visit(std::string &k)=0;
		virtual void visit_null()=0;
		virtual bool has_data()=0;
		//virtual void visit(field_provider *ti,void *p)=0;
	};

	template<typename F>
	struct visit { visit(visitor &v,F &f) {
		field_provider *fp=f.rpoco_type_info_get();
		if (v.visit_start(object)) {
			for (int i=0;i<fp->size();i++) {
				v.visit((*fp)[i]->name());
				(*fp)[i]->visit(v,(void*)&f);
			}
			v.visit_end(object);
		} else {
			v.visit_end(object,[&v,fp,f](std::string& n){
				if (! fp->has(n))
					return;
				(*fp)[n]->visit(v,(void*)&f);
			});
		}
		//v.visit(f?f->rpoco_type_info_get():0,f);
	}};

	template<typename F>
	struct visit<std::map<std::string,F>> { visit(visitor &v,std::map<std::string,F> *vp) {
		if (*mp) {
			v.visit_null();
			return;
		}
		if (v.visit_start(object)) {
			// serialization
			for (std::pair<std::string,F> &p:*mp) {
				rpoco::visit(&p.first);
				rpoco::visit(&p.second);
			}
			v.visit_end(object);
		} else {
			v.visit_end(object,[&v,mp](std::string& x) {
				 deserialization
				rpoco::visit( (*mp)[x] );
			});
		}
	}};

	template<typename F>
	struct visit<std::vector<F>> { visit(visitor &v,std::vector<F> &vp) {
		if (v.visit_start(array)) {
			// serialization
			for (F &f:vp) {
				rpoco::visit<F>(v,f);
			}
			v.visit_end(array);
		} else {
			v.visit_end(array,[&v,&vp](std::string& x) {
				// deserialization
				vp.emplace_back();
				rpoco::visit<F>(v,vp.back());
			});
		}
	}};

	template<typename F>
	struct visit<F*> { visit(visitor &v,F *& fp) {
		if (v.has_data() && !fp) {
			fp=new F();
		}
		if (fp)
			visit<F>(v,*fp);
		else
			v.visit_null();
	}};

	template<>
	struct visit<int> { visit (visitor &v,int &ip) {
		v.visit(ip);
	}};

	template<>
	struct visit<std::string> { visit(visitor &v,std::string &str) {
		v.visit(str);
	}};

	class fieldbase {
	public:
	protected:
		std::string m_name;
		ptrdiff_t m_offset;
	public:
		fieldbase(std::string name,ptrdiff_t offset) {
			this->m_name=name;
			this->m_offset=offset;
		}
		std::string& name() {
			return m_name;
		}
		ptrdiff_t offset() {
			return m_offset;
		}
		virtual void visit(visitor &v,void *p)=0;
	};

	template<typename F>
	class field : public fieldbase {
	public:
		field(std::string name,ptrdiff_t off) : fieldbase(name,off) {}
		virtual void visit(visitor &v,void *p) {
			rpoco::visit<F>(v,*(F*)( (uintptr_t)p+(ptrdiff_t)m_offset ));
		}
	};

	class field_provider {
	public:
		virtual int size()=0;
		virtual bool has(std::string id)=0;
		virtual fieldbase*& operator[](int idx)=0;
		virtual fieldbase*& operator[](std::string id)=0;
	};

	class type_info : public field_provider {
		std::vector<fieldbase*> fields;
		std::unordered_map<std::string,fieldbase*> m_named_fields;
		std::atomic<int> m_is_init;
		std::mutex init_mutex;
	public:
		virtual int size() {
			return fields.size();
		}
		virtual bool has(std::string id) {
			return m_named_fields.end()!=m_named_fields.find(id);
		}
		virtual fieldbase*& operator[](int idx) {
			return fields[idx];
		}
		virtual fieldbase*& operator[](std::string id) {
			return m_named_fields[id];
		}
		int is_init() {
			return m_is_init.load();
		}
		void init(std::function<void (type_info *ti)> initfun) {
			std::lock_guard<std::mutex> lock(init_mutex);\
			if (!m_is_init.load()) {
				initfun(this);
				m_is_init.store(1);
			}
		}
		void add(fieldbase *fb) {
			//printf("Gotten field:%s at %p\n",fb->name().c_str(),fb->offset());
			fields.push_back(fb);
			m_named_fields[fb->name()]=fb;
		}
	};

	std::vector<std::string> extract_macro_names(const char *t) {
		// skip spaces and commas
		while(*t&&(std::isspace(*t)||*t==',')) { t++; }
		// token start pos
		const char *s=t;
		std::vector<std::string> out;
		while(*t) {
			if (*t==','||std::isspace(*t)) {
				out.push_back(std::string(s,t-s));
				// skip spaces and commas
				while(*t&&(std::isspace(*t)||*t==',')) { t++; }
				s=t;
			} else {
				t++;
			}
		}
		if (s!=t)
			out.push_back(std::string(s,t-s));
		return out;
	}
};

#endif // __INCLUDED_RPOCO_HPP__
<commit_msg>* renamed fieldbase to member<commit_after>// Deliberate ifdef even if we have #pragma once if anyone wants to auto-detect RPOCO with the define
#ifndef __INCLUDED_RPOCO_HPP__
#define __INCLUDED_RPOCO_HPP__

#pragma once

#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <utility>
#include <atomic>
#include <mutex>
#include <cctype>
#include <stdint.h>
#include <type_traits>
#include <functional>

// Use the RPOCO macro within a compound definition to create
// automatic serialization information upon the specified members.
// RPOCO has thread safe typeinfo init (double checked lock) so using
// functions dependant of the functionality from multiple threads should
// be safe.

#define RPOCO(...) \
	void rpoco_type_info_expand(rpoco::type_info *ti,std::vector<std::string>& names,int idx) {} \
	template<typename H,typename... R> \
	void rpoco_type_info_expand(rpoco::type_info *ti,std::vector<std::string>& names,int idx,H&& head,R&&... rest) {\
		ptrdiff_t off=(ptrdiff_t) (  ((uintptr_t)&head)-((uintptr_t)this) ); \
		ti->add(new rpoco::field< std::remove_reference<H>::type >(names[idx],off) );\
		rpoco_type_info_expand(ti,names,idx+1,rest...); \
	} \
	rpoco::type_info* rpoco_type_info_get() { \
		static rpoco::type_info ti; \
		if(!ti.is_init()) { \
			ti.init([this](rpoco::type_info *ti) { \
				std::vector<std::string> names=rpoco::extract_macro_names(#__VA_ARGS__); \
				rpoco_type_info_expand(ti,names,0,__VA_ARGS__); \
			} ); \
		} \
		return &ti; \
	}

namespace rpoco {
	class member;
	class member_provider;

	enum visit_type {
		object,
		array
	};

	struct visitor {
		virtual bool visit_start(visit_type vt)=0;
		virtual void visit_end(visit_type vt)=0;
		virtual void visit_end(visit_type vt,std::function<void(std::string&)> out)=0;
		virtual void visit(int& x)=0;
		virtual void visit(std::string &k)=0;
		virtual void visit_null()=0;
		virtual bool has_data()=0;
	};

	template<typename F>
	struct visit { visit(visitor &v,F &f) {
		member_provider *fp=f.rpoco_type_info_get();
		if (v.visit_start(object)) {
			for (int i=0;i<fp->size();i++) {
				v.visit((*fp)[i]->name());
				(*fp)[i]->visit(v,(void*)&f);
			}
			v.visit_end(object);
		} else {
			v.visit_end(object,[&v,fp,f](std::string& n){
				if (! fp->has(n))
					return;
				(*fp)[n]->visit(v,(void*)&f);
			});
		}
		//v.visit(f?f->rpoco_type_info_get():0,f);
	}};

	template<typename F>
	struct visit<std::map<std::string,F>> { visit(visitor &v,std::map<std::string,F> *vp) {
		if (*mp) {
			v.visit_null();
			return;
		}
		if (v.visit_start(object)) {
			// serialization
			for (std::pair<std::string,F> &p:*mp) {
				rpoco::visit(&p.first);
				rpoco::visit(&p.second);
			}
			v.visit_end(object);
		} else {
			v.visit_end(object,[&v,mp](std::string& x) {
				 deserialization
				rpoco::visit( (*mp)[x] );
			});
		}
	}};

	template<typename F>
	struct visit<std::vector<F>> { visit(visitor &v,std::vector<F> &vp) {
		if (v.visit_start(array)) {
			// serialization
			for (F &f:vp) {
				rpoco::visit<F>(v,f);
			}
			v.visit_end(array);
		} else {
			v.visit_end(array,[&v,&vp](std::string& x) {
				// deserialization
				vp.emplace_back();
				rpoco::visit<F>(v,vp.back());
			});
		}
	}};

	template<typename F>
	struct visit<F*> { visit(visitor &v,F *& fp) {
		if (v.has_data() && !fp) {
			fp=new F();
		}
		if (fp)
			visit<F>(v,*fp);
		else
			v.visit_null();
	}};

	template<> struct visit<int> { visit (visitor &v,int &ip) {
		v.visit(ip);
	}};

	template<> struct visit<std::string> { visit(visitor &v,std::string &str) {
		v.visit(str);
	}};

	class member {
	public:
	protected:
		std::string m_name;
	public:
		member(std::string name) {
			this->m_name=name;
		}
		std::string& name() {
			return m_name;
		}
		virtual void visit(visitor &v,void *p)=0;
	};

	template<typename F>
	class field : public member {
		ptrdiff_t m_offset;
	public:
		field(std::string name,ptrdiff_t off) : member(name) {
			this->m_offset=off;
		}
		ptrdiff_t offset() {
			return m_offset;
		}
		virtual void visit(visitor &v,void *p) {
			rpoco::visit<F>(v,*(F*)( (uintptr_t)p+(ptrdiff_t)m_offset ));
		}
	};

	class member_provider {
	public:
		virtual int size()=0;
		virtual bool has(std::string id)=0;
		virtual member*& operator[](int idx)=0;
		virtual member*& operator[](std::string id)=0;
	};

	class type_info : public member_provider {
		std::vector<member*> fields;
		std::unordered_map<std::string,member*> m_named_fields;
		std::atomic<int> m_is_init;
		std::mutex init_mutex;
	public:
		virtual int size() {
			return fields.size();
		}
		virtual bool has(std::string id) {
			return m_named_fields.end()!=m_named_fields.find(id);
		}
		virtual member*& operator[](int idx) {
			return fields[idx];
		}
		virtual member*& operator[](std::string id) {
			return m_named_fields[id];
		}
		int is_init() {
			return m_is_init.load();
		}
		void init(std::function<void (type_info *ti)> initfun) {
			std::lock_guard<std::mutex> lock(init_mutex);\
			if (!m_is_init.load()) {
				initfun(this);
				m_is_init.store(1);
			}
		}
		void add(member *fb) {
			fields.push_back(fb);
			m_named_fields[fb->name()]=fb;
		}
	};

	std::vector<std::string> extract_macro_names(const char *t) {
		// skip spaces and commas
		while(*t&&(std::isspace(*t)||*t==',')) { t++; }
		// token start pos
		const char *s=t;
		std::vector<std::string> out;
		while(*t) {
			if (*t==','||std::isspace(*t)) {
				out.push_back(std::string(s,t-s));
				// skip spaces and commas
				while(*t&&(std::isspace(*t)||*t==',')) { t++; }
				s=t;
			} else {
				t++;
			}
		}
		if (s!=t)
			out.push_back(std::string(s,t-s));
		return out;
	}
};

#endif // __INCLUDED_RPOCO_HPP__
<|endoftext|>


<commit_before>// kbusyptr.cpp

#include "kbusyptr.h"

#include <qapplication.h>
#include <qcursor.h>

//-----------------------------------------------------------------------------
KBusyPtr :: KBusyPtr ()
    : busyLevel( 0 )
{
  busyLevel  = 0;
}

//-----------------------------------------------------------------------------
KBusyPtr :: ~KBusyPtr()
{
  while (busyLevel) idle();
}

//-----------------------------------------------------------------------------
void KBusyPtr :: busy (void)
{
  if (busyLevel <= 0)
  {
      QApplication::setOverrideCursor( QCursor(QCursor::WaitCursor) );
  }
  busyLevel++;
}

//-----------------------------------------------------------------------------
void KBusyPtr :: idle (void)
{
  busyLevel--;
  if (busyLevel < 0) busyLevel = 0;

  if (busyLevel <= 0)
  {
    QApplication::restoreOverrideCursor();
  }
}

//-----------------------------------------------------------------------------
bool KBusyPtr :: isBusy (void)
{
  return (busyLevel != 0);
}

#include "kbusyptr.moc"
<commit_msg>compile<commit_after>// kbusyptr.cpp

#include "kbusyptr.h"

#include <qapplication.h>
#include <qcursor.h>

//-----------------------------------------------------------------------------
KBusyPtr :: KBusyPtr ()
    : busyLevel( 0 )
{
  busyLevel  = 0;
}

//-----------------------------------------------------------------------------
KBusyPtr :: ~KBusyPtr()
{
  while (busyLevel) idle();
}

//-----------------------------------------------------------------------------
void KBusyPtr :: busy (void)
{
  if (busyLevel <= 0)
  {
      QApplication::setOverrideCursor( QCursor(QCursor::WaitCursor) );
  }
  busyLevel++;
}

//-----------------------------------------------------------------------------
void KBusyPtr :: idle (void)
{
  busyLevel--;
  if (busyLevel < 0) busyLevel = 0;

  if (busyLevel <= 0)
  {
    QApplication::restoreOverrideCursor();
  }
}

//-----------------------------------------------------------------------------
bool KBusyPtr :: isBusy (void)
{
  return (busyLevel != 0);
}

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: wkb.hpp 39 2005-04-10 20:39:53Z pavlenko $

#ifndef WKB_HPP
#define WKB_HPP

#include "geometry.hpp"
#include "ctrans.hpp"

namespace mapnik
{
    class geometry_utils
    {
    public:
	static geometry_ptr from_wkb(const char* wkb, unsigned size,int srid);
    private:
	geometry_utils();
	geometry_utils(const geometry_utils&);
	geometry_utils& operator=(const geometry_utils&);
    };
}
#endif                                            //WKB_HPP
<commit_msg>export symbols from wkb<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: wkb.hpp 39 2005-04-10 20:39:53Z pavlenko $

#ifndef WKB_HPP
#define WKB_HPP

#include "geometry.hpp"
#include "ctrans.hpp"

namespace mapnik
{
    class MAPNIK_DECL geometry_utils
    {
    public:
	static geometry_ptr from_wkb(const char* wkb, unsigned size,int srid);
    private:
	geometry_utils();
	geometry_utils(const geometry_utils&);
	geometry_utils& operator=(const geometry_utils&);
    };
}
#endif                                            //WKB_HPP
<|endoftext|>


<commit_before><commit_msg>qt: Fix an rfc2253 parser flaw<commit_after><|endoftext|>


<commit_before>#include "ctrl_statusbar.h"
#include <numeric>
#include <vector>

#include <CommCtrl.h>

namespace Win {
	void StatusBar::Add(StatusBarPart& newPart) {
		m_parts.push_back(&newPart);
		newPart.AttachTo(this);
	}

	StatusBar::StatusBar() {}

	HWND StatusBar::PerformDynamicCreate() {
		return CreateWindowEx(
			0,
			STATUSCLASSNAME,
			L"",
			WS_CHILD | WS_VISIBLE,
			50,
			50,
			50,
			50,
			DialogHandle(),
			0,
			GetModuleHandle(0),
			0);
	}

	void StatusBar::Update() {
		struct SumNonShared {
			int operator()(int lhs, StatusBarPart* rhs) {
				return lhs + (rhs->AutoSize()==StatusBarPart::AutoSizeShare?0:rhs->Width());
			}
		};
		struct IsSharedSize {
			bool operator()(StatusBarPart* v) {
				return v->AutoSize() == StatusBarPart::AutoSizeShare;
			}
		};
		int numShared = std::count_if(m_parts.begin(), m_parts.end(), IsSharedSize());
		int perShared = Position().Width() - std::accumulate(m_parts.begin(), m_parts.end(), 0, SumNonShared())
			/ (numShared==0?1:numShared);

		int currLeft = 0;
		std::vector<int> sizes;
		for(auto* p: m_parts) {
			int currWidth = (p->AutoSize() == StatusBarPart::AutoSizeShare?perShared:p->Width());
			sizes.push_back(currLeft + currWidth);
			currLeft += currWidth;
		}
		SendMessage(Handle(), SB_SETPARTS, sizes.size(), reinterpret_cast<LPARAM>(&sizes[0]));

		int i=0;
		for(auto* p: m_parts)
			SendMessage(Handle(), SB_SETTEXT, i++, reinterpret_cast<LPARAM>(p->Text().c_str()));
	}
}
<commit_msg>Use wide strings in winapi calls<commit_after>#include "ctrl_statusbar.h"
#include <numeric>
#include <vector>

#include <CommCtrl.h>

namespace Win {
	void StatusBar::Add(StatusBarPart& newPart) {
		m_parts.push_back(&newPart);
		newPart.AttachTo(this);
	}

	StatusBar::StatusBar() {}

	HWND StatusBar::PerformDynamicCreate() {
		return CreateWindowEx(
			0,
			STATUSCLASSNAME,
			L"",
			WS_CHILD | WS_VISIBLE,
			50,
			50,
			50,
			50,
			DialogHandle(),
			0,
			GetModuleHandle(0),
			0);
	}

	void StatusBar::Update() {
		struct SumNonShared {
			int operator()(int lhs, StatusBarPart* rhs) {
				return lhs + (rhs->AutoSize()==StatusBarPart::AutoSizeShare?0:rhs->Width());
			}
		};
		struct IsSharedSize {
			bool operator()(StatusBarPart* v) {
				return v->AutoSize() == StatusBarPart::AutoSizeShare;
			}
		};
		int numShared = std::count_if(m_parts.begin(), m_parts.end(), IsSharedSize());
		int perShared = Position().Width() - std::accumulate(m_parts.begin(), m_parts.end(), 0, SumNonShared())
			/ (numShared==0?1:numShared);

		int currLeft = 0;
		std::vector<int> sizes;
		for(auto* p: m_parts) {
			int currWidth = (p->AutoSize() == StatusBarPart::AutoSizeShare?perShared:p->Width());
			sizes.push_back(currLeft + currWidth);
			currLeft += currWidth;
		}
		SendMessage(Handle(), SB_SETPARTS, sizes.size(), reinterpret_cast<LPARAM>(&sizes[0]));

		int i=0;
		for(auto* p: m_parts)
			SendMessage(Handle(), SB_SETTEXT, i++, reinterpret_cast<LPARAM>(UTF8ToWString(p->Text()).c_str()));
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: rtl_old_testostring.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: ihi $ $Date: 2007-11-20 19:50:01 $
 *
 *  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_sal.hxx"

// LLA:
// this file is converted to use with testshl2
// original was placed in sal/test/textenc.cxx

// -----------------------------------------------------------------------------
#include <string.h>
#include <stdio.h>

// #ifndef _OSL_DIAGNOSE_H_
// #include <osl/diagnose.h>
// #endif

#ifndef _RTL_STRING_HXX
#include <rtl/string.hxx>
#endif

#include <cppunit/simpleheader.hxx>

#define TEST_ENSURE(c, m) CPPUNIT_ASSERT_MESSAGE((m), (c))

// #if OSL_DEBUG_LEVEL > 0
// #define TEST_ENSHURE(c, m)   OSL_ENSURE(c, m)
// #else
// #define TEST_ENSHURE(c, m)   OSL_VERIFY(c)
// #endif

using namespace rtl;

// -----------------------------------------------------------------------------
namespace rtl_OString
{
    class oldtests : public CppUnit::TestFixture
    {
    public:
        void test_OString();

        CPPUNIT_TEST_SUITE( oldtests );
        CPPUNIT_TEST( test_OString );
        CPPUNIT_TEST_SUITE_END( );
    };

#ifdef WNT
#pragma warning( disable : 4723 )
#endif

void oldtests::test_OString()
{
    TEST_ENSURE( sal_True, "_USENAMEPSACE defined");

    //          "Mein erster RTL OString\n"
    //           |    |    |    |    |
    //  Index    0    5    10   15   20
    OString s1("Mein erster RTL OString\n");
    TEST_ENSURE( s1 == "Mein erster RTL OString\n", "test_OString error 1");
    TEST_ENSURE( s1.getLength() == 24, "test_OString error 2");

    OString s2 = s1;
    TEST_ENSURE( s2[16] == 'O', "test_OString error 3");
    TEST_ENSURE( s2.equals(s1), "test_OString error 4");
    TEST_ENSURE( s2.indexOf('O') == 16, "test_OString error 5");
    TEST_ENSURE( s2.indexOf('O', 5) == 16, "test_OString error 5a");
    TEST_ENSURE( s2.lastIndexOf('r') == 19, "test_OString error 6");
    TEST_ENSURE( s2[19] == 'r', "test_OString error 7");
    TEST_ENSURE( s2[23] == '\n', "test_OString error 8");
    TEST_ENSURE( s2.lastIndexOf('\n') == 23, "test_OString error 9");
    TEST_ENSURE( s2.lastIndexOf('M') == 0, "test_OString error 10");
    TEST_ENSURE( s2.lastIndexOf('t', s2.getLength() - 8) == 8, "test_OString error 9");

    //          "Mein erster RTL OString ist ein String aus der RTL Library\n"
    //           |    |    |    |    |    |    |    |    |    |    |    |
    //  Index    0    5    10   15   20   25   30   35   40   45   50   55
    OString s3 = s2.copy(0, s2.getLength() - 1);
    OString s4 = s3.concat(" ist ein String aus der RTL Library\n");
    TEST_ENSURE( s4.getLength() == 59, "test_OString error 11");

    s1 = s4.copy(0, 38);
    OString s5;
    s5 = s1 + " aus der RTL Library\n";
    TEST_ENSURE( s5.compareTo(s4) == 0 , "test_OString error 12");
    TEST_ENSURE( s5.indexOf("RTL") == 12, "test_OString error 13");
    TEST_ENSURE( s5.lastIndexOf("RTL") == 47, "test_OString error 13");

    sal_Bool b = sal_False;
    OString s6 = s5.valueOf(b);
    TEST_ENSURE( s6.compareTo("false") == 0, "test_OString error 14");
    s6 = s5.valueOf('H');
    TEST_ENSURE( s6.compareTo("H") == 0, "test_OString error 15");
    sal_Int32 n = 123456789L;
    s6 = s5.valueOf(n);
    TEST_ENSURE( s6.compareTo("123456789") == 0, "test_OString error 16");

#ifndef SAL_OS2
#ifdef SAL_UNX
    sal_Int64 m = -3223372036854775807LL;
#elif defined(SAL_OS2)
    sal_Int64 m;
    sal_setInt64(&m, 3965190145L, -750499787L);
#else
    sal_Int64 m = -3223372036854775807;
#endif
    s6 = s5.valueOf(m);
    TEST_ENSURE( s6.compareTo("-3223372036854775807") == 0, "test_OString error 17");
#endif

    OString s7("HaLLo");
    s7 = s7.toAsciiLowerCase();
    TEST_ENSURE( s7 == "hallo", "test_OString error 19");
    s7 = s7.toAsciiUpperCase();
    TEST_ENSURE( s7 == "HALLO", "test_OString error 20");

    OString s8("HaLLo ICH BIn eIn StRiNg");
    s7 = s8.toAsciiLowerCase();

    TEST_ENSURE( s8.equalsIgnoreAsciiCase(s7), "test_OString error 21");

    s8 = s7.toAsciiUpperCase();
    TEST_ENSURE( s8 == "HALLO ICH BIN EIN STRING", "test_OString error 22");

    s7 = "          ";
    s8 = s7 + s8 + "          ";
    TEST_ENSURE( s8 == "          HALLO ICH BIN EIN STRING          ",
                  "test_OString error 23");

    s7 = s8.trim();
    TEST_ENSURE( s7 == "HALLO ICH BIN EIN STRING", "test_OString error 24");
    TEST_ENSURE( strcmp(s7.getStr(), "HALLO ICH BIN EIN STRING") == 0,
                  "test_OString error 25");

    s7 = "Hallo";
    s8 = "aber Hallo";

    TEST_ENSURE( s7 < s8, "test_OString error 26");
    TEST_ENSURE( s8 > s7, "test_OString error 27");
    TEST_ENSURE( s7 != s8, "test_OString error 28");
    TEST_ENSURE( s7 != "blabla", "test_OString error 29");
    TEST_ENSURE( "blabla" != s7, "test_OString error 30");

    s8 = "Hallo";
    TEST_ENSURE( s7 <= s8, "test_OString error 31");
    TEST_ENSURE( s7 >= s8, "test_OString error 32");

    s8 = s8.replace('l', 'r');
    TEST_ENSURE( s8 == "Harro", "test_OString error 33");

    sal_Int32 nIndex = 0;
    s8 = "|hallo1|hallo2|hallo3|hallo4|hallo5|hallo6|hallo7|hallo8|";
    TEST_ENSURE( s8.getToken(3,'|', nIndex) == "hallo3", "test_OString error 40");

    char* Tokens[10] = { "", "hallo1", "hallo2", "hallo3", "hallo4",
                         "hallo5", "hallo6", "hallo7", "hallo8", "" };

    nIndex = 0;
    sal_Int32 i = 0;
    do
    {
        TEST_ENSURE( s8.getToken(0,'|',nIndex) == Tokens[i], "test_OString error 40e");
        i++;
    }
    while ( nIndex >= 0 );

    s7 = "";
    s7 += s8;
    TEST_ENSURE( s7 == s8, "test_OString error 41");

    s7 = s8.replaceAt(8, 6, "mmmmmmmmmm");
    TEST_ENSURE( s7.getLength() == 61, "test_OString error 42");

    s8 = s7.replaceAt(8, 11, "");
    TEST_ENSURE( s8.getLength() == 50, "test_OString error 43");

    s7 = s8.replaceAt(8, 0, "hallo2|");
    TEST_ENSURE( s7.getLength() == 57, "test_OString error 44");

    sal_Int32 pos = 0;
    while ((pos = s7.indexOf("|")) >= 0)
    {
        s8 = s7.replaceAt(pos, 1, "**");
        s7 = s8;
    }
    TEST_ENSURE( s7.getLength() == 66, "test_OString error 45");

    TEST_ENSURE( OString( "aaa" ).compareTo( OString( "bbb" ) ) < 0, "test_OString error 46" );
    TEST_ENSURE( OString( "aaa" ).compareTo( OString( "aaa" ) ) == 0, "test_OString error 47" );
    TEST_ENSURE( OString( "bbb" ).compareTo( OString( "aaa" ) ) > 0, "test_OString error 48" );
    TEST_ENSURE( OString( "aaaa" ).compareTo( OString( "bbb" ) ) < 0, "test_OString error 49" );
    TEST_ENSURE( OString( "aaa" ).compareTo( OString( "bbbb" ) ) < 0, "test_OString error 50" );
    TEST_ENSURE( OString( "aaa" ).compareTo( OString( "aaaa" ) ) < 0, "test_OString error 51" );
    TEST_ENSURE( OString( "aaaa" ).compareTo( OString( "aaa" ) ) > 0, "test_OString error 52" );
    TEST_ENSURE( OString( "bbbb" ).compareTo( OString( "bbb" ) ) > 0, "test_OString error 53" );
    TEST_ENSURE( OString( "bbb" ) == OString( "bbb" ), "test_OString error 54" );
    TEST_ENSURE( OString( "bbb" ) == "bbb", "test_OString error 55" );

/*
 * As clarified in #104229#, calling copy with invalid arguments causes
 * undefined behaviour, so the following test does no longer work:

    s7 = "Hallo jetzt komm ich";
    s8 = s7.copy(0, s7.indexOf(':'));
    TEST_ENSURE( s8.getLength() == 0, "test_OString error 56");
    TEST_ENSURE( s8.compareTo("") == 0, "test_OString error 57");
*/

    double f = OString("1.7e-10").toDouble();
    TEST_ENSURE(f > 1E-10 && f < 2E-10, "1.7e-10 problem");
    f = OString("1.7e+10").toDouble();
    TEST_ENSURE(f > 1E10 && f < 2E10, "1.7e+10 problem");
    f = OString("1.7e10").toDouble();
    TEST_ENSURE(f > 1E10 && f < 2E10, "1.7e308 problem");

    {
        float f0 = 0;
        float f1 = 1;
        float fInf = f1 / f0;
        OString aStr1(OString::valueOf(fInf));
        OString aStr2("1.#INF");
        bool bSuccess = aStr1 == aStr2;
        if (!bSuccess)
            printf("ERROR: OString::valueOf(1f/0f): %s\n", aStr1.getStr());
        TEST_ENSURE(bSuccess, "OString::valueOf(1f/0f)");
    }

    printf("test_OString OK !!!\n");
    return;
}

} // namespace rtl_OString

// -----------------------------------------------------------------------------
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( rtl_OString::oldtests, "rtl_OString" );

// -----------------------------------------------------------------------------
NOADDITIONAL;

<commit_msg>INTEGRATION: CWS changefileheader (1.6.64); FILE MERGED 2008/03/31 13:23:59 rt 1.6.64.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: rtl_old_testostring.cxx,v $
 * $Revision: 1.7 $
 *
 * 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_sal.hxx"

// LLA:
// this file is converted to use with testshl2
// original was placed in sal/test/textenc.cxx

// -----------------------------------------------------------------------------
#include <string.h>
#include <stdio.h>

// #ifndef _OSL_DIAGNOSE_H_
// #include <osl/diagnose.h>
// #endif

#ifndef _RTL_STRING_HXX
#include <rtl/string.hxx>
#endif

#include <cppunit/simpleheader.hxx>

#define TEST_ENSURE(c, m) CPPUNIT_ASSERT_MESSAGE((m), (c))

// #if OSL_DEBUG_LEVEL > 0
// #define TEST_ENSHURE(c, m)   OSL_ENSURE(c, m)
// #else
// #define TEST_ENSHURE(c, m)   OSL_VERIFY(c)
// #endif

using namespace rtl;

// -----------------------------------------------------------------------------
namespace rtl_OString
{
    class oldtests : public CppUnit::TestFixture
    {
    public:
        void test_OString();

        CPPUNIT_TEST_SUITE( oldtests );
        CPPUNIT_TEST( test_OString );
        CPPUNIT_TEST_SUITE_END( );
    };

#ifdef WNT
#pragma warning( disable : 4723 )
#endif

void oldtests::test_OString()
{
    TEST_ENSURE( sal_True, "_USENAMEPSACE defined");

    //          "Mein erster RTL OString\n"
    //           |    |    |    |    |
    //  Index    0    5    10   15   20
    OString s1("Mein erster RTL OString\n");
    TEST_ENSURE( s1 == "Mein erster RTL OString\n", "test_OString error 1");
    TEST_ENSURE( s1.getLength() == 24, "test_OString error 2");

    OString s2 = s1;
    TEST_ENSURE( s2[16] == 'O', "test_OString error 3");
    TEST_ENSURE( s2.equals(s1), "test_OString error 4");
    TEST_ENSURE( s2.indexOf('O') == 16, "test_OString error 5");
    TEST_ENSURE( s2.indexOf('O', 5) == 16, "test_OString error 5a");
    TEST_ENSURE( s2.lastIndexOf('r') == 19, "test_OString error 6");
    TEST_ENSURE( s2[19] == 'r', "test_OString error 7");
    TEST_ENSURE( s2[23] == '\n', "test_OString error 8");
    TEST_ENSURE( s2.lastIndexOf('\n') == 23, "test_OString error 9");
    TEST_ENSURE( s2.lastIndexOf('M') == 0, "test_OString error 10");
    TEST_ENSURE( s2.lastIndexOf('t', s2.getLength() - 8) == 8, "test_OString error 9");

    //          "Mein erster RTL OString ist ein String aus der RTL Library\n"
    //           |    |    |    |    |    |    |    |    |    |    |    |
    //  Index    0    5    10   15   20   25   30   35   40   45   50   55
    OString s3 = s2.copy(0, s2.getLength() - 1);
    OString s4 = s3.concat(" ist ein String aus der RTL Library\n");
    TEST_ENSURE( s4.getLength() == 59, "test_OString error 11");

    s1 = s4.copy(0, 38);
    OString s5;
    s5 = s1 + " aus der RTL Library\n";
    TEST_ENSURE( s5.compareTo(s4) == 0 , "test_OString error 12");
    TEST_ENSURE( s5.indexOf("RTL") == 12, "test_OString error 13");
    TEST_ENSURE( s5.lastIndexOf("RTL") == 47, "test_OString error 13");

    sal_Bool b = sal_False;
    OString s6 = s5.valueOf(b);
    TEST_ENSURE( s6.compareTo("false") == 0, "test_OString error 14");
    s6 = s5.valueOf('H');
    TEST_ENSURE( s6.compareTo("H") == 0, "test_OString error 15");
    sal_Int32 n = 123456789L;
    s6 = s5.valueOf(n);
    TEST_ENSURE( s6.compareTo("123456789") == 0, "test_OString error 16");

#ifndef SAL_OS2
#ifdef SAL_UNX
    sal_Int64 m = -3223372036854775807LL;
#elif defined(SAL_OS2)
    sal_Int64 m;
    sal_setInt64(&m, 3965190145L, -750499787L);
#else
    sal_Int64 m = -3223372036854775807;
#endif
    s6 = s5.valueOf(m);
    TEST_ENSURE( s6.compareTo("-3223372036854775807") == 0, "test_OString error 17");
#endif

    OString s7("HaLLo");
    s7 = s7.toAsciiLowerCase();
    TEST_ENSURE( s7 == "hallo", "test_OString error 19");
    s7 = s7.toAsciiUpperCase();
    TEST_ENSURE( s7 == "HALLO", "test_OString error 20");

    OString s8("HaLLo ICH BIn eIn StRiNg");
    s7 = s8.toAsciiLowerCase();

    TEST_ENSURE( s8.equalsIgnoreAsciiCase(s7), "test_OString error 21");

    s8 = s7.toAsciiUpperCase();
    TEST_ENSURE( s8 == "HALLO ICH BIN EIN STRING", "test_OString error 22");

    s7 = "          ";
    s8 = s7 + s8 + "          ";
    TEST_ENSURE( s8 == "          HALLO ICH BIN EIN STRING          ",
                  "test_OString error 23");

    s7 = s8.trim();
    TEST_ENSURE( s7 == "HALLO ICH BIN EIN STRING", "test_OString error 24");
    TEST_ENSURE( strcmp(s7.getStr(), "HALLO ICH BIN EIN STRING") == 0,
                  "test_OString error 25");

    s7 = "Hallo";
    s8 = "aber Hallo";

    TEST_ENSURE( s7 < s8, "test_OString error 26");
    TEST_ENSURE( s8 > s7, "test_OString error 27");
    TEST_ENSURE( s7 != s8, "test_OString error 28");
    TEST_ENSURE( s7 != "blabla", "test_OString error 29");
    TEST_ENSURE( "blabla" != s7, "test_OString error 30");

    s8 = "Hallo";
    TEST_ENSURE( s7 <= s8, "test_OString error 31");
    TEST_ENSURE( s7 >= s8, "test_OString error 32");

    s8 = s8.replace('l', 'r');
    TEST_ENSURE( s8 == "Harro", "test_OString error 33");

    sal_Int32 nIndex = 0;
    s8 = "|hallo1|hallo2|hallo3|hallo4|hallo5|hallo6|hallo7|hallo8|";
    TEST_ENSURE( s8.getToken(3,'|', nIndex) == "hallo3", "test_OString error 40");

    char* Tokens[10] = { "", "hallo1", "hallo2", "hallo3", "hallo4",
                         "hallo5", "hallo6", "hallo7", "hallo8", "" };

    nIndex = 0;
    sal_Int32 i = 0;
    do
    {
        TEST_ENSURE( s8.getToken(0,'|',nIndex) == Tokens[i], "test_OString error 40e");
        i++;
    }
    while ( nIndex >= 0 );

    s7 = "";
    s7 += s8;
    TEST_ENSURE( s7 == s8, "test_OString error 41");

    s7 = s8.replaceAt(8, 6, "mmmmmmmmmm");
    TEST_ENSURE( s7.getLength() == 61, "test_OString error 42");

    s8 = s7.replaceAt(8, 11, "");
    TEST_ENSURE( s8.getLength() == 50, "test_OString error 43");

    s7 = s8.replaceAt(8, 0, "hallo2|");
    TEST_ENSURE( s7.getLength() == 57, "test_OString error 44");

    sal_Int32 pos = 0;
    while ((pos = s7.indexOf("|")) >= 0)
    {
        s8 = s7.replaceAt(pos, 1, "**");
        s7 = s8;
    }
    TEST_ENSURE( s7.getLength() == 66, "test_OString error 45");

    TEST_ENSURE( OString( "aaa" ).compareTo( OString( "bbb" ) ) < 0, "test_OString error 46" );
    TEST_ENSURE( OString( "aaa" ).compareTo( OString( "aaa" ) ) == 0, "test_OString error 47" );
    TEST_ENSURE( OString( "bbb" ).compareTo( OString( "aaa" ) ) > 0, "test_OString error 48" );
    TEST_ENSURE( OString( "aaaa" ).compareTo( OString( "bbb" ) ) < 0, "test_OString error 49" );
    TEST_ENSURE( OString( "aaa" ).compareTo( OString( "bbbb" ) ) < 0, "test_OString error 50" );
    TEST_ENSURE( OString( "aaa" ).compareTo( OString( "aaaa" ) ) < 0, "test_OString error 51" );
    TEST_ENSURE( OString( "aaaa" ).compareTo( OString( "aaa" ) ) > 0, "test_OString error 52" );
    TEST_ENSURE( OString( "bbbb" ).compareTo( OString( "bbb" ) ) > 0, "test_OString error 53" );
    TEST_ENSURE( OString( "bbb" ) == OString( "bbb" ), "test_OString error 54" );
    TEST_ENSURE( OString( "bbb" ) == "bbb", "test_OString error 55" );

/*
 * As clarified in #104229#, calling copy with invalid arguments causes
 * undefined behaviour, so the following test does no longer work:

    s7 = "Hallo jetzt komm ich";
    s8 = s7.copy(0, s7.indexOf(':'));
    TEST_ENSURE( s8.getLength() == 0, "test_OString error 56");
    TEST_ENSURE( s8.compareTo("") == 0, "test_OString error 57");
*/

    double f = OString("1.7e-10").toDouble();
    TEST_ENSURE(f > 1E-10 && f < 2E-10, "1.7e-10 problem");
    f = OString("1.7e+10").toDouble();
    TEST_ENSURE(f > 1E10 && f < 2E10, "1.7e+10 problem");
    f = OString("1.7e10").toDouble();
    TEST_ENSURE(f > 1E10 && f < 2E10, "1.7e308 problem");

    {
        float f0 = 0;
        float f1 = 1;
        float fInf = f1 / f0;
        OString aStr1(OString::valueOf(fInf));
        OString aStr2("1.#INF");
        bool bSuccess = aStr1 == aStr2;
        if (!bSuccess)
            printf("ERROR: OString::valueOf(1f/0f): %s\n", aStr1.getStr());
        TEST_ENSURE(bSuccess, "OString::valueOf(1f/0f)");
    }

    printf("test_OString OK !!!\n");
    return;
}

} // namespace rtl_OString

// -----------------------------------------------------------------------------
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( rtl_OString::oldtests, "rtl_OString" );

// -----------------------------------------------------------------------------
NOADDITIONAL;

<|endoftext|>


<commit_before>#define DEBUG 1

/**
 * File    : D2.cpp
 * Author  : Kazune Takahashi
 * Created : 5/23/2019, 11:22:03 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(10101010));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, K;
string S;
vector<int> V;
vector<int> W;

int main()
{
  cin >> N >> K >> S;
  int now = 1;
  int cnt = 0;
  for (auto i = 0; i < N; i++)
  {
    if (S[i] == ('0' + now))
    {
      cnt++;
    }
    else
    {
      V.push_back(cnt);
      cnt = 1;
      now = 1 - now;
    }
  }
  if (cnt > 0)
  {
    V.push_back(cnt);
  }
  if (V.size() % 2 == 0)
  {
    V.push_back(0);
  }
  W = vector<int>(V.size() + 1, 0);
  for (auto i = 0; i < (int)V.size(); i++)
  {
    W[i + 1] = W[i] + V[i];
  }
  int ans = 0;
  for (auto i = 0; i < (int)W.size(); i += 2)
  {
    int start = i;
    int goal = i + 2 * K + 1;
    if (goal < (int)W.size())
    {
      ans = max(ans, W[goal] - W[start]);
    }
  }
  cout << ans << endl;
}<commit_msg>tried D2.cpp to 'D'<commit_after>#define DEBUG 1

/**
 * File    : D2.cpp
 * Author  : Kazune Takahashi
 * Created : 5/23/2019, 11:22:03 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(10101010));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, K;
string S;
vector<int> V;
vector<int> W;

int main()
{
  cin >> N >> K >> S;
  int now = 1;
  int cnt = 0;
  for (auto i = 0; i < N; i++)
  {
    if (S[i] == ('0' + now))
    {
      cnt++;
    }
    else
    {
      V.push_back(cnt);
      cnt = 1;
      now = 1 - now;
    }
  }
  if (cnt > 0)
  {
    V.push_back(cnt);
  }
  if (V.size() % 2 == 0)
  {
    V.push_back(0);
  }
  W = vector<int>(V.size() + 1, 0);
  for (auto i = 0; i < (int)V.size(); i++)
  {
    W[i + 1] = W[i] + V[i];
  }
  int ans = 0;
  for (auto i = 0; i < (int)W.size(); i += 2)
  {
    int start = i;
    int goal = min(i + 2 * K + 1, (int)W.size());
    ans = max(ans, W[goal] - W[start]);
  }
  cout << ans << endl;
}<|endoftext|>


<commit_before>// @file AesopDemo.cpp
// @brief A small test application for the Aesop library.

#include <stdio.h>
#include <stdarg.h>

#include "AesopDemo.h"
#include "AesopObjects.h"
#include "AesopPredicates.h"
#include "AesopActionSet.h"
#include "AesopWorldState.h"
#include "AesopReverseAstar.h"

namespace ae = Aesop;

void printPlan(const ae::Plan &plan, const ae::ActionSet &actions)
{
   printf("The plan:\n");
   ae::Plan::const_iterator it;
   for(it = plan.begin(); it != plan.end(); it++)
   {
      printf("   %s", actions.repr(it->action).c_str());
      if(it->parameters.size())
      {
         ae::WorldState::paramlist::const_iterator pl;
         for(pl = it->parameters.begin(); pl != it->parameters.end(); pl++)
            printf(" %d", *pl);
      }
      putchar('\n');
   }
}

void complexTest()
{
}

void STRIPSTest()
{
}

void subSTRIPSTest()
{
   // --------------------
   // STEP 1. The Domain.
/*
   // 1.1. Define the types of objects that can exist.
   ae::NamedTypes types;
   types.add("object");
   ae::Types::typeID place = types.add("place");

   // 1.2. Create predicates that describe the physics of our problem.
   ae::AesopPredicates preds;

   // A physical object can be at a place
   preds.create("at");
   preds.parameter("place");
   preds.add();

   preds.create("box-at");
   preds.parameter("place");
   preds.add();

   preds.create("high");
   ae::Predicates::predicateID high = preds.add();

   // 1.3. Define actions we can use to modify the world state.
   ae::SingleParamActionSet actions;

   actions.create("move");
   actions.parameter(place);
   actions.add();

   actions.create("move-box");
   actions.parameter(place);
   actions.add();

   actions.create("climb-box");
   preds.effect(high);
   actions.add();

   // --------------------
   // STEP 2. The Problem.

   // 2.1. Create some objects.
   ae::Objects objects(types);
   objects.add("roomA", place);
   objects.add("roomB", place);
   objects.add("roomC", place);
*/
   // 2.2. Create initial and goal world states.
}

void simpleTest()
{
   // --------------------
   // STEP 1. The Domain.

   // 1.1. Create predicates that describe the physics of our problem.
   ae::SimplePredicates preds;

   enum {
      gunLoaded,
      gunEquipped,
      haveGun,
      inTurret,
      haveTarget,
      targetDead,
      NUMPREDS
   };

   // Define all predicates.
   preds.define(NUMPREDS);

   // 1.2. Create actions to modify the world state.
   ae::SimpleActionSet actions(preds);

   actions.create("attackRanged");
   actions.condition(haveTarget, true);
   actions.condition(gunLoaded, true);
   actions.condition(targetDead, false);
   actions.effect(targetDead, true);
   actions.effect(gunLoaded, false);
   actions.add();

   actions.create("attackMelee");
   actions.condition(haveTarget, true);
   actions.condition(targetDead, false);
   //actions.condition();
   actions.effect(targetDead, true);
   //actions.add();

   actions.create("attackTurret");
   actions.condition(haveTarget, true);
   actions.condition(inTurret, true);
   actions.condition(targetDead, false);
   //actions.condition();
   actions.effect(targetDead, true);
   actions.add();

   actions.create("loadGun");
   actions.condition(gunEquipped, true);
   actions.condition(gunLoaded, false);
   actions.effect(gunLoaded, true);
   actions.add();

   actions.create("drawGun");
   actions.condition(haveGun, true);
   actions.condition(gunEquipped, false);
   actions.effect(gunEquipped, true);
   actions.add();

   actions.create("findGun");
   actions.condition(haveGun, false);
   actions.effect(haveGun, true);
   actions.add();

   actions.create("findTurret");
   actions.condition(inTurret, false);
   actions.effect(inTurret, true);
   //actions.add();

   // --------------------
   // STEP 2. The Problem.

   // 2.1. Create initial and goal world states.
   ae::SimpleWorldState init(preds), goal(preds);

   init.set(haveTarget);

   goal.set(targetDead);

   // --------------------
   // STEP 3. The Solution.
   ae::Plan plan;
   ae::FileWriterContext context(*stdout);
   if(ae::ReverseAstarSolve(init, goal, actions, ae::NoObjects, plan, context))
      printPlan(plan, actions);
   else
      printf("No valid plan was found.\n");
}

int main(int argc, char **argv)
{
   simpleTest();
   return 0;
}
<commit_msg>Added more actions related to melee weapons.<commit_after>// @file AesopDemo.cpp
// @brief A small test application for the Aesop library.

#include <stdio.h>
#include <stdarg.h>

#include "AesopDemo.h"
#include "AesopObjects.h"
#include "AesopPredicates.h"
#include "AesopActionSet.h"
#include "AesopWorldState.h"
#include "AesopReverseAstar.h"

namespace ae = Aesop;

void printPlan(const ae::Plan &plan, const ae::ActionSet &actions)
{
   printf("The plan:\n");
   ae::Plan::const_iterator it;
   for(it = plan.begin(); it != plan.end(); it++)
   {
      printf("   %s", actions.repr(it->action).c_str());
      if(it->parameters.size())
      {
         ae::WorldState::paramlist::const_iterator pl;
         for(pl = it->parameters.begin(); pl != it->parameters.end(); pl++)
            printf(" %d", *pl);
      }
      putchar('\n');
   }
}

void complexTest()
{
}

void STRIPSTest()
{
}

void subSTRIPSTest()
{
   // --------------------
   // STEP 1. The Domain.
/*
   // 1.1. Define the types of objects that can exist.
   ae::NamedTypes types;
   types.add("object");
   ae::Types::typeID place = types.add("place");

   // 1.2. Create predicates that describe the physics of our problem.
   ae::AesopPredicates preds;

   // A physical object can be at a place
   preds.create("at");
   preds.parameter("place");
   preds.add();

   preds.create("box-at");
   preds.parameter("place");
   preds.add();

   preds.create("high");
   ae::Predicates::predicateID high = preds.add();

   // 1.3. Define actions we can use to modify the world state.
   ae::SingleParamActionSet actions;

   actions.create("move");
   actions.parameter(place);
   actions.add();

   actions.create("move-box");
   actions.parameter(place);
   actions.add();

   actions.create("climb-box");
   preds.effect(high);
   actions.add();

   // --------------------
   // STEP 2. The Problem.

   // 2.1. Create some objects.
   ae::Objects objects(types);
   objects.add("roomA", place);
   objects.add("roomB", place);
   objects.add("roomC", place);
*/
   // 2.2. Create initial and goal world states.
}

void simpleTest()
{
   // --------------------
   // STEP 1. The Domain.

   // 1.1. Create predicates that describe the physics of our problem.
   ae::SimplePredicates preds;

   enum {
      gunLoaded,
      gunEquipped,
      haveGun,
      haveMelee,
      meleeEquipped,
      inTurret,
      haveTarget,
      targetDead,
      NUMPREDS
   };

   // Define all predicates.
   preds.define(NUMPREDS);

   // 1.2. Create actions to modify the world state.
   ae::SimpleActionSet actions(preds);

   actions.create("attackRanged");
   actions.condition(haveTarget, true);
   actions.condition(gunLoaded, true);
   actions.condition(targetDead, false);
   actions.effect(targetDead, true);
   actions.effect(gunLoaded, false);
   actions.add();

   actions.create("attackMelee");
   actions.condition(haveTarget, true);
   actions.condition(targetDead, false);
   actions.condition(meleeEquipped, true);
   //actions.condition();
   actions.effect(targetDead, true);
   actions.add();

   actions.create("attackTurret");
   actions.condition(haveTarget, true);
   actions.condition(inTurret, true);
   actions.condition(targetDead, false);
   //actions.condition();
   actions.effect(targetDead, true);
   actions.add();

   actions.create("loadGun");
   actions.condition(gunEquipped, true);
   actions.condition(gunLoaded, false);
   actions.effect(gunLoaded, true);
   actions.add();

   actions.create("drawGun");
   actions.condition(haveGun, true);
   actions.condition(gunEquipped, false);
   actions.effect(gunEquipped, true);
   actions.add();

   actions.create("findGun");
   actions.condition(haveGun, false);
   actions.effect(haveGun, true);
   actions.add();

   actions.create("drawMelee");
   actions.condition(haveMelee, true);
   actions.condition(meleeEquipped, false);
   actions.effect(meleeEquipped, true);
   actions.add();

   actions.create("findMelee");
   actions.condition(haveMelee, false);
   actions.effect(haveMelee, true);
   actions.add();

   actions.create("findTurret");
   actions.condition(inTurret, false);
   actions.effect(inTurret, true);
   //actions.add();

   // --------------------
   // STEP 2. The Problem.

   // 2.1. Create initial and goal world states.
   ae::SimpleWorldState init(preds), goal(preds);

   init.set(haveTarget);

   goal.set(targetDead);

   // --------------------
   // STEP 3. The Solution.
   ae::Plan plan;
   ae::FileWriterContext context(*stdout);
   if(ae::ReverseAstarSolve(init, goal, actions, ae::NoObjects, plan, context))
      printPlan(plan, actions);
   else
      printf("No valid plan was found.\n");
}

int main(int argc, char **argv)
{
   simpleTest();
   return 0;
}
<|endoftext|>


<commit_before>// AltTabber.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "AltTabber.h"

#define MAX_LOADSTRING 100

#define MY_NOTIFICATION_ICON 2
#define MY_NOTIFY_ICON_MESSAGE_ID (WM_USER + 88)
#define MY_CLOSE_BTN_ID (WM_USER + 89)

extern void log(LPTSTR fmt, ...);
extern MonitorGeom_t GetMonitorGeometry();
extern void SynchronizeWithRegistry();
extern void ActivateSwitcher();
extern void SelectCurrent();
extern void MoveNext(DWORD);
extern void SelectByMouse(DWORD);
extern void QuitOverlay();
extern void PurgeThumbnails();
extern void CreateThumbnails(std::wstring const&);
extern void SetThumbnails();
extern void OnPaint(HDC);

ProgramState_t g_programState = {
    FALSE,
    NULL,
    -1,
    FALSE,
    NULL,
    { MOD_ALT | MOD_CONTROL, '3' },
};

// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

     // TODO: Place code here.
    MSG msg;
    HACCEL hAccelTable;

    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_ALTTABBER, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_ALTTABBER));

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style            = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ALTTABBER));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = NULL; //MAKEINTRESOURCE(IDC_ALTTABBER);
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    HWND hWnd;

    hInst = hInstance; // Store instance handle in our global variable

    auto geom = GetMonitorGeometry();
    // SetWindowPos(hWnd, HWND_TOPMOST, geom.x, geom.y, geom.cx, geom.cy);

    hWnd = CreateWindowEx(
            WS_EX_TOPMOST | WS_EX_COMPOSITED,
            szWindowClass,
            szTitle,
            WS_POPUP,
            geom.r.left, geom.r.top,
            geom.r.right - geom.r.left, geom.r.bottom - geom.r.top,
            NULL,
            NULL,
            hInstance,
            NULL);

    if (!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, SW_HIDE);
    UpdateWindow(hWnd);

    SynchronizeWithRegistry();

    if(RegisterHotKey(
                hWnd,
                1,
                g_programState.hotkey.modifiers,
                g_programState.hotkey.key))
    {
        log(_T("win+caps registered\n"));
    }

    g_programState.hWnd = hWnd;

    NOTIFYICONDATA nid = {};
    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
    nid.cbSize = sizeof(NOTIFYICONDATA);
    nid.uID = MY_NOTIFICATION_ICON;
    nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE ;
    nid.hWnd = hWnd;
    nid.uCallbackMessage = MY_NOTIFY_ICON_MESSAGE_ID;
#define TIP (_T("AltTabber\n- Ctrl-Alt-3 to open overlay\n- Alt-F4 when overlay is active to quit"))
    _tcsncpy_s(nid.szTip, TIP, _tcslen(TIP));
#undef TIP
    nid.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SMALL));
    HRESULT sniHr = Shell_NotifyIcon(NIM_ADD, &nid);

    return TRUE;
}

static inline void Cleanup()
{
    PurgeThumbnails();

    if(g_programState.freopened != NULL) fclose(g_programState.freopened);
}

static void ShowContextMenu(int x, int y)
{
    if(g_programState.activeSlot >= 0
        && (unsigned long)g_programState.activeSlot < g_programState.slots.size())
    {
        HMENU ctxMenu = CreatePopupMenu();
        AppendMenu(ctxMenu, MF_STRING, MY_CLOSE_BTN_ID, _T("Close"));
        auto hr = TrackPopupMenu(ctxMenu,
            TPM_RIGHTBUTTON,
            x, y,
            0, g_programState.hWnd, NULL);
        DestroyMenu(ctxMenu);
    }
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND    - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY    - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case MY_NOTIFY_ICON_MESSAGE_ID: {
        auto what = LOWORD(lParam);
        switch(what) {
        case WM_LBUTTONUP:
            ActivateSwitcher();
            break;
        }
        break; }
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        case MY_CLOSE_BTN_ID:
            if(g_programState.activeSlot >= 0) {
                auto& slot = g_programState.slots[g_programState.activeSlot];
                PostMessage(slot.hwnd, WM_SYSCOMMAND, SC_CLOSE, -1);
                // clear the filter because of use case
                if(g_programState.slots.size() <= 2) {
                    g_programState.filter = L"";
                }
                // rebuild thumbnails because filter was changed
                // and there are maybe dangling slots
                CreateThumbnails(g_programState.filter);
                SetThumbnails();
                // force redraw window (the labels)
                RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE);
            }
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT: {
        hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code here...
        if(g_programState.showing)
        {
            HGDIOBJ original = NULL;
            original = SelectObject(hdc, GetStockObject(DC_PEN));
            HPEN pen = CreatePen(PS_SOLID, 5, RGB(0, 255, 0));
            SelectObject(hdc, pen);
            MoveToEx(hdc, 0, 0, NULL);
            auto mi = GetMonitorGeometry();
            LineTo(hdc, mi.r.right - mi.r.left, mi.r.bottom - mi.r.top);
            SelectObject(hdc, original);

            OnPaint(hdc);
        }
        EndPaint(hWnd, &ps);
        break; }
    case WM_DESTROY:
        Cleanup();
        PostQuitMessage(0);
        break;
    case WM_HOTKEY:
        // only waiting for one, so skip over trying to decode it
        // even if multiple keys are registered as hotkeys, they'd
        // all do the same thing anyway
        log(_T("hotkey pressed\n"));
        if(g_programState.showing) {
            SelectCurrent();
        } else {
            ActivateSwitcher();
        }
        break;
    case WM_MOUSEWHEEL: {
        int amount = GET_WHEEL_DELTA_WPARAM(wParam);
        if(amount > 0) MoveNext(VK_BACK);
        else MoveNext(VK_TAB);
        break; }
    case WM_RBUTTONUP:
        if(!g_programState.showing) break;
        SelectByMouse(lParam);
        {
            POINT p = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
            ClientToScreen(g_programState.hWnd, &p);
            ShowContextMenu(p.x, p.y);
        }
        break;
    case WM_LBUTTONUP:
        if(!g_programState.showing) break;
        SelectByMouse(lParam);
        break;
    case WM_LBUTTONDBLCLK:
    case WM_RBUTTONDBLCLK:
        if(!g_programState.showing) break;
        SelectByMouse(lParam);
        SelectCurrent();
        break;
    case WM_CHAR:
        switch(wParam) {
        case 0x1B: // esc
        case 0x08: // backspace
        case 0x09: // tab
        case 0x0D: // enter
        // case 0x0A: // LF
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        g_programState.filter += (wchar_t)wParam;
        log(_T("got filter %ls\n"), g_programState.filter.c_str());
        CreateThumbnails(g_programState.filter);
        SetThumbnails();
        RedrawWindow(g_programState.hWnd, NULL, NULL, RDW_INVALIDATE);
        break;
    case WM_KEYDOWN:
        switch(wParam) {
        case VK_APPS: // menu key
            if(g_programState.activeSlot >= 0) {
                RECT r = g_programState.slots[g_programState.activeSlot].r;
                ShowContextMenu(r.left, r.top);
            }
            break;
        case VK_ESCAPE:
            QuitOverlay();
            break;
        case VK_TAB:
            if(GetAsyncKeyState(VK_SHIFT)) {
                MoveNext(VK_BACK);
            } else {
                MoveNext(VK_TAB);
            }
            break;
        case VK_RIGHT:
        case VK_UP:
        case VK_DOWN:
        case VK_LEFT:
            MoveNext(wParam);
            break;
        case VK_RETURN:
            SelectCurrent();
            break;
        case VK_F1:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case VK_F2:
            g_programState.logging = !g_programState.logging;
            break;
        case VK_BACK:
            if(!g_programState.filter.empty()) {
                g_programState.filter =
                    g_programState.filter.substr(
                            0, g_programState.filter.size() - 1);

                CreateThumbnails(g_programState.filter);
                SetThumbnails();
                RedrawWindow(g_programState.hWnd, NULL, NULL, RDW_INVALIDATE);
            }
            break;
#if 0
        default: {
            INT hr = (INT)MapVirtualKey(wParam, MAPVK_VK_TO_CHAR);
            if(hr > 0) {
                g_programState.filter += (wchar_t)hr;
                log(_T("got filter %ls\n"), g_programState.filter.c_str());
                CreateThumbnails(g_programState.filter);
                SetThumbnails();
                RedrawWindow(g_programState.hWnd, NULL, NULL, RDW_INVALIDATE);
            }
            break; }
#else
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
#endif
        }
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}
<commit_msg>Show error dialog&exit it hotkey is taken<commit_after>// AltTabber.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "AltTabber.h"

#define MAX_LOADSTRING 100

#define MY_NOTIFICATION_ICON 2
#define MY_NOTIFY_ICON_MESSAGE_ID (WM_USER + 88)
#define MY_CLOSE_BTN_ID (WM_USER + 89)

extern void log(LPTSTR fmt, ...);
extern MonitorGeom_t GetMonitorGeometry();
extern void SynchronizeWithRegistry();
extern void ActivateSwitcher();
extern void SelectCurrent();
extern void MoveNext(DWORD);
extern void SelectByMouse(DWORD);
extern void QuitOverlay();
extern void PurgeThumbnails();
extern void CreateThumbnails(std::wstring const&);
extern void SetThumbnails();
extern void OnPaint(HDC);

ProgramState_t g_programState = {
    FALSE,
    NULL,
    -1,
    FALSE,
    NULL,
    { MOD_ALT | MOD_CONTROL, '3' },
};

// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

     // TODO: Place code here.
    MSG msg;
    HACCEL hAccelTable;

    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_ALTTABBER, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_ALTTABBER));

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

static inline void Cleanup()
{
    PurgeThumbnails();

    if(g_programState.freopened != NULL) fclose(g_programState.freopened);
}

//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style            = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ALTTABBER));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = NULL; //MAKEINTRESOURCE(IDC_ALTTABBER);
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    HWND hWnd;

    hInst = hInstance; // Store instance handle in our global variable

    auto geom = GetMonitorGeometry();
    // SetWindowPos(hWnd, HWND_TOPMOST, geom.x, geom.y, geom.cx, geom.cy);

    hWnd = CreateWindowEx(
            WS_EX_TOPMOST | WS_EX_COMPOSITED,
            szWindowClass,
            szTitle,
            WS_POPUP,
            geom.r.left, geom.r.top,
            geom.r.right - geom.r.left, geom.r.bottom - geom.r.top,
            NULL,
            NULL,
            hInstance,
            NULL);

    if (!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, SW_HIDE);
    UpdateWindow(hWnd);

    SynchronizeWithRegistry();

    if(RegisterHotKey(
                hWnd,
                1,
                g_programState.hotkey.modifiers,
                g_programState.hotkey.key))
    {
        log(_T("hotkey registered successfully\n"));
    }
    else
    {
        log(_T("failed to register hotkey\n"));
        MessageBox(hWnd,
                _T("Failed to register hotkey.\n"                           )
                _T("\n"                                                     )
                _T("This usually means that there is already a program\n"   )
                _T("running that has registered the same hotkey.\n"         )
                _T("\n"                                                     )
                _T("Possible resolutions:\n"                                )
                _T("- Close the already running instance of AltTabber\n"    )
                _T("- If there is another application that has registered\n")
                _T("  the current hotkey, change it in that application\n"  )
                _T("- Change AltTabber's hotkey by editing the registry\n"  )
                _T("  Refer to the README.md document (which you can find\n")
                _T("  at http://github.com/alzwded/AltTabber ) on how to\n" )
                _T("  accomplish this.\n"                                   )
                _T("\n"                                                     )
                _T("The application will now exit"                          )
            ,
            _T("AltTabber - Failed to register hotkey"),
            MB_OK | MB_ICONERROR);
        Cleanup();
        PostQuitMessage(0);
    }

    g_programState.hWnd = hWnd;

    NOTIFYICONDATA nid = {};
    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
    nid.cbSize = sizeof(NOTIFYICONDATA);
    nid.uID = MY_NOTIFICATION_ICON;
    nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE ;
    nid.hWnd = hWnd;
    nid.uCallbackMessage = MY_NOTIFY_ICON_MESSAGE_ID;
#define TIP (_T("AltTabber\n- Ctrl-Alt-3 to open overlay\n- Alt-F4 when overlay is active to quit"))
    _tcsncpy_s(nid.szTip, TIP, _tcslen(TIP));
#undef TIP
    nid.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SMALL));
    HRESULT sniHr = Shell_NotifyIcon(NIM_ADD, &nid);

    return TRUE;
}

static void ShowContextMenu(int x, int y)
{
    if(g_programState.activeSlot >= 0
        && (unsigned long)g_programState.activeSlot < g_programState.slots.size())
    {
        HMENU ctxMenu = CreatePopupMenu();
        AppendMenu(ctxMenu, MF_STRING, MY_CLOSE_BTN_ID, _T("Close"));
        auto hr = TrackPopupMenu(ctxMenu,
            TPM_RIGHTBUTTON,
            x, y,
            0, g_programState.hWnd, NULL);
        DestroyMenu(ctxMenu);
    }
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND    - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY    - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case MY_NOTIFY_ICON_MESSAGE_ID: {
        auto what = LOWORD(lParam);
        switch(what) {
        case WM_LBUTTONUP:
            ActivateSwitcher();
            break;
        }
        break; }
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        case MY_CLOSE_BTN_ID:
            if(g_programState.activeSlot >= 0) {
                auto& slot = g_programState.slots[g_programState.activeSlot];
                PostMessage(slot.hwnd, WM_SYSCOMMAND, SC_CLOSE, -1);
                // clear the filter because of use case
                if(g_programState.slots.size() <= 2) {
                    g_programState.filter = L"";
                }
                // rebuild thumbnails because filter was changed
                // and there are maybe dangling slots
                CreateThumbnails(g_programState.filter);
                SetThumbnails();
                // force redraw window (the labels)
                RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE);
            }
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT: {
        hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code here...
        if(g_programState.showing)
        {
            HGDIOBJ original = NULL;
            original = SelectObject(hdc, GetStockObject(DC_PEN));
            HPEN pen = CreatePen(PS_SOLID, 5, RGB(0, 255, 0));
            SelectObject(hdc, pen);
            MoveToEx(hdc, 0, 0, NULL);
            auto mi = GetMonitorGeometry();
            LineTo(hdc, mi.r.right - mi.r.left, mi.r.bottom - mi.r.top);
            SelectObject(hdc, original);

            OnPaint(hdc);
        }
        EndPaint(hWnd, &ps);
        break; }
    case WM_DESTROY:
        Cleanup();
        PostQuitMessage(0);
        break;
    case WM_HOTKEY:
        // only waiting for one, so skip over trying to decode it
        // even if multiple keys are registered as hotkeys, they'd
        // all do the same thing anyway
        log(_T("hotkey pressed\n"));
        if(g_programState.showing) {
            SelectCurrent();
        } else {
            ActivateSwitcher();
        }
        break;
    case WM_MOUSEWHEEL: {
        int amount = GET_WHEEL_DELTA_WPARAM(wParam);
        if(amount > 0) MoveNext(VK_BACK);
        else MoveNext(VK_TAB);
        break; }
    case WM_RBUTTONUP:
        if(!g_programState.showing) break;
        SelectByMouse(lParam);
        {
            POINT p = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
            ClientToScreen(g_programState.hWnd, &p);
            ShowContextMenu(p.x, p.y);
        }
        break;
    case WM_LBUTTONUP:
        if(!g_programState.showing) break;
        SelectByMouse(lParam);
        break;
    case WM_LBUTTONDBLCLK:
    case WM_RBUTTONDBLCLK:
        if(!g_programState.showing) break;
        SelectByMouse(lParam);
        SelectCurrent();
        break;
    case WM_CHAR:
        switch(wParam) {
        case 0x1B: // esc
        case 0x08: // backspace
        case 0x09: // tab
        case 0x0D: // enter
        // case 0x0A: // LF
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        g_programState.filter += (wchar_t)wParam;
        log(_T("got filter %ls\n"), g_programState.filter.c_str());
        CreateThumbnails(g_programState.filter);
        SetThumbnails();
        RedrawWindow(g_programState.hWnd, NULL, NULL, RDW_INVALIDATE);
        break;
    case WM_KEYDOWN:
        switch(wParam) {
        case VK_APPS: // menu key
            if(g_programState.activeSlot >= 0) {
                RECT r = g_programState.slots[g_programState.activeSlot].r;
                ShowContextMenu(r.left, r.top);
            }
            break;
        case VK_ESCAPE:
            QuitOverlay();
            break;
        case VK_TAB:
            if(GetAsyncKeyState(VK_SHIFT)) {
                MoveNext(VK_BACK);
            } else {
                MoveNext(VK_TAB);
            }
            break;
        case VK_RIGHT:
        case VK_UP:
        case VK_DOWN:
        case VK_LEFT:
            MoveNext(wParam);
            break;
        case VK_RETURN:
            SelectCurrent();
            break;
        case VK_F1:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case VK_F2:
            g_programState.logging = !g_programState.logging;
            break;
        case VK_BACK:
            if(!g_programState.filter.empty()) {
                g_programState.filter =
                    g_programState.filter.substr(
                            0, g_programState.filter.size() - 1);

                CreateThumbnails(g_programState.filter);
                SetThumbnails();
                RedrawWindow(g_programState.hWnd, NULL, NULL, RDW_INVALIDATE);
            }
            break;
#if 0
        default: {
            INT hr = (INT)MapVirtualKey(wParam, MAPVK_VK_TO_CHAR);
            if(hr > 0) {
                g_programState.filter += (wchar_t)hr;
                log(_T("got filter %ls\n"), g_programState.filter.c_str());
                CreateThumbnails(g_programState.filter);
                SetThumbnails();
                RedrawWindow(g_programState.hWnd, NULL, NULL, RDW_INVALIDATE);
            }
            break; }
#else
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
#endif
        }
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}
<|endoftext|>