<commit_before>#include "render_pipeline/rpcore/util/primitives.hpp"

#include <geomVertexWriter.h>
#include <geomTriangles.h>
#include <geomNode.h>
#include <materialAttrib.h>

#include "render_pipeline/rpcore/util/rpmaterial.hpp"

namespace rpcore {

static NodePath create_geom_node(const std::string& name, Geom* geom)
{
    // default material
    CPT(RenderState) state = RenderState::make_empty();
    state = state->add_attrib(MaterialAttrib::make(RPMaterial().get_material()));

    PT(GeomNode) geom_node = new GeomNode(name);
    geom_node->add_geom(geom, state);

    return NodePath(geom_node);
}

NodePath create_cube(const std::string& name)
{
    // create vertices
    PT(GeomVertexData) vdata = new GeomVertexData(name, GeomVertexFormat::get_v3n3t2(), Geom::UsageHint::UH_static);
    vdata->unclean_set_num_rows(24);

    GeomVertexWriter vertex(vdata, InternalName::get_vertex());
    GeomVertexWriter normal(vdata, InternalName::get_normal());
    GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());

    vertex.add_data3f(-0.5f, -0.5f, -0.5f);     normal.add_data3f(0.0f, 0.0f, -1.0f);   texcoord.add_data2f(0.25f, 1/3.0f);     // 0
    vertex.add_data3f(-0.5f, -0.5f, -0.5f);     normal.add_data3f(0.0f, -1.0f, 0.0f);   texcoord.add_data2f(0.25f, 1/3.0f);     // 1
    vertex.add_data3f(-0.5f, -0.5f, -0.5f);     normal.add_data3f(-1.0f, 0.0f, 0.0f);   texcoord.add_data2f(0.25f, 1/3.0f);     // 2
    vertex.add_data3f(+0.5f, -0.5f, -0.5f);     normal.add_data3f(0.0f, 0.0f, -1.0f);   texcoord.add_data2f(0.5f, 1/3.0f);      // 3
    vertex.add_data3f(+0.5f, -0.5f, -0.5f);     normal.add_data3f(0.0f, -1.0f, 0.0f);   texcoord.add_data2f(0.5f, 1/3.0f);      // 4
    vertex.add_data3f(+0.5f, -0.5f, -0.5f);     normal.add_data3f(1.0f, 0.0f, 0.0f);    texcoord.add_data2f(0.5f, 1/3.0f);      // 5
    vertex.add_data3f(+0.5f, +0.5f, -0.5f);     normal.add_data3f(0.0f, 0.0f, -1.0f);   texcoord.add_data2f(0.5f, 0.0f);        // 6
    vertex.add_data3f(+0.5f, +0.5f, -0.5f);     normal.add_data3f(0.0f, 1.0f, 0.0f);    texcoord.add_data2f(0.75f, 1/3.0f);     // 7
    vertex.add_data3f(+0.5f, +0.5f, -0.5f);     normal.add_data3f(1.0f, 0.0f, 0.0f);    texcoord.add_data2f(0.75f, 1/3.0f);     // 8
    vertex.add_data3f(-0.5f, +0.5f, -0.5f);     normal.add_data3f(0.0f, 0.0f, -1.0f);   texcoord.add_data2f(0.25f, 0.0f);       // 9
    vertex.add_data3f(-0.5f, +0.5f, -0.5f);     normal.add_data3f(0.0f, 1.0f, 0.0f);    texcoord.add_data2f(1.0f, 1/3.0f);      // 10
    vertex.add_data3f(-0.5f, +0.5f, -0.5f);     normal.add_data3f(-1.0f, 0.0f, 0.0f);   texcoord.add_data2f(0.0f, 1/3.0f);      // 11
    vertex.add_data3f(-0.5f, -0.5f, +0.5f);     normal.add_data3f(0.0f, 0.0f, 1.0f);    texcoord.add_data2f(0.25f, 2/3.0f);     // 12
    vertex.add_data3f(-0.5f, -0.5f, +0.5f);     normal.add_data3f(0.0f, -1.0f, 0.0f);   texcoord.add_data2f(0.25f, 2/3.0f);     // 13
    vertex.add_data3f(-0.5f, -0.5f, +0.5f);     normal.add_data3f(-1.0f, 0.0f, 0.0f);   texcoord.add_data2f(0.25f, 2/3.0f);     // 14
    vertex.add_data3f(+0.5f, -0.5f, +0.5f);     normal.add_data3f(0.0f, 0.0f, 1.0f);    texcoord.add_data2f(0.5f, 2/3.0f);      // 15
    vertex.add_data3f(+0.5f, -0.5f, +0.5f);     normal.add_data3f(0.0f, -1.0f, 0.0f);   texcoord.add_data2f(0.5f, 2/3.0f);      // 16
    vertex.add_data3f(+0.5f, -0.5f, +0.5f);     normal.add_data3f(1.0f, 0.0f, 0.0f);    texcoord.add_data2f(0.5f, 2/3.0f);      // 17
    vertex.add_data3f(+0.5f, +0.5f, +0.5f);     normal.add_data3f(0.0f, 0.0f, 1.0f);    texcoord.add_data2f(0.5f, 1.0f);        // 18
    vertex.add_data3f(+0.5f, +0.5f, +0.5f);     normal.add_data3f(0.0f, 1.0f, 0.0f);    texcoord.add_data2f(0.75f, 2/3.0f);     // 19
    vertex.add_data3f(+0.5f, +0.5f, +0.5f);     normal.add_data3f(1.0f, 0.0f, 0.0f);    texcoord.add_data2f(0.75f, 2/3.0f);     // 20
    vertex.add_data3f(-0.5f, +0.5f, +0.5f);     normal.add_data3f(0.0f, 0.0f, 1.0f);    texcoord.add_data2f(0.25f, 1.0f);       // 21
    vertex.add_data3f(-0.5f, +0.5f, +0.5f);     normal.add_data3f(0.0f, 1.0f, 0.0f);    texcoord.add_data2f(1.0f, 2/3.0f);      // 22
    vertex.add_data3f(-0.5f, +0.5f, +0.5f);     normal.add_data3f(-1.0f, 0.0f, 0.0f);   texcoord.add_data2f(0.0f, 2/3.0f);      // 23

    // create indices
    PT(GeomTriangles) prim = new GeomTriangles(Geom::UsageHint::UH_static);
    prim->reserve_num_vertices(36);
    prim->add_vertices(0, 6, 3);
    prim->add_vertices(0, 9, 6);
    prim->add_vertices(12, 15, 18);
    prim->add_vertices(12, 18, 21);
    prim->add_vertices(22, 19, 7);
    prim->add_vertices(22, 7, 10);
    prim->add_vertices(13, 4, 16);
    prim->add_vertices(13, 1, 4);
    prim->add_vertices(14, 23, 11);
    prim->add_vertices(14, 11, 2);
    prim->add_vertices(17, 5, 8);
    prim->add_vertices(17, 8, 20);
    prim->close_primitive();

    PT(Geom) geom = new Geom(vdata);
    geom->add_primitive(prim);

    return create_geom_node(name, geom);
}

NodePath create_sphere(const std::string& name, unsigned int latitude, unsigned int longitude)
{
    latitude = (std::max)(1u, latitude);
    longitude = (std::max)(1u, longitude);

    // create vertices
    PT(GeomVertexData) vdata = new GeomVertexData(name, GeomVertexFormat::get_v3n3t2(), Geom::UsageHint::UH_static);
    vdata->unclean_set_num_rows((latitude + 1)*(longitude + 1));

    GeomVertexWriter vertex(vdata, InternalName::get_vertex());
    GeomVertexWriter normal(vdata, InternalName::get_normal());
    GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());

    const double pi = std::acos(-1);
    for (unsigned int i = 0; i <= latitude; ++i)
    {
        const double theta = i * pi / double(latitude);
        for (unsigned int j = 0; j <= longitude; ++j)
        {
            const double phi = j * 2.0 * pi / double(longitude);
            const double sin_theta = std::sin(theta);
            const double x = std::cos(phi) * sin_theta;
            const double y = std::sin(phi) * sin_theta;
            const double z = std::cos(theta);

            vertex.add_data3f(x, y, z);
            normal.add_data3f(x, y, z);
            texcoord.add_data2f(j / double(longitude), 1.0 - i / double(latitude));
        }
    }

    // create indices
    PT(GeomTriangles) prim = new GeomTriangles(Geom::UsageHint::UH_static);
    prim->reserve_num_vertices(longitude * latitude * 6);

    for (unsigned int i = 0; i < latitude; ++i)
    {
        for (unsigned int j = 0; j < longitude; ++j)
        {
            const int a = i * (longitude + 1) + j;
            const int b = a + (longitude + 1);

            prim->add_vertices(a, b, a+1);
            prim->add_vertices(b, b+1, a+1);
        }
    }
    prim->close_primitive();

    PT(Geom) geom = new Geom(vdata);
    geom->add_primitive(prim);

    return create_geom_node(name, geom);
}

}
<commit_msg>Fix cube vertices and indices.<commit_after>#include "render_pipeline/rpcore/util/primitives.hpp"

#include <geomVertexWriter.h>
#include <geomTriangles.h>
#include <geomNode.h>
#include <materialAttrib.h>

#include "render_pipeline/rpcore/util/rpmaterial.hpp"

namespace rpcore {

static NodePath create_geom_node(const std::string& name, Geom* geom)
{
    // default material
    CPT(RenderState) state = RenderState::make_empty();
    state = state->add_attrib(MaterialAttrib::make(RPMaterial().get_material()));

    PT(GeomNode) geom_node = new GeomNode(name);
    geom_node->add_geom(geom, state);

    return NodePath(geom_node);
}

NodePath create_cube(const std::string& name)
{
    // create vertices
    PT(GeomVertexData) vdata = new GeomVertexData(name, GeomVertexFormat::get_v3n3t2(), Geom::UsageHint::UH_static);
    vdata->unclean_set_num_rows(24);

    GeomVertexWriter vertex(vdata, InternalName::get_vertex());
    GeomVertexWriter normal(vdata, InternalName::get_normal());
    GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());

    // top
    vertex.add_data3f(+0.5f, +0.5f, +0.5f);     normal.add_data3f( 0.0f,  0.0f,  1.0f);     texcoord.add_data2f(0.5f, 1.0f);        // 0
    vertex.add_data3f(-0.5f, +0.5f, +0.5f);     normal.add_data3f( 0.0f,  0.0f,  1.0f);     texcoord.add_data2f(0.25f, 1.0f);       // 1
    vertex.add_data3f(+0.5f, -0.5f, +0.5f);     normal.add_data3f( 0.0f,  0.0f,  1.0f);     texcoord.add_data2f(0.5f, 2/3.0f);      // 2
    vertex.add_data3f(-0.5f, -0.5f, +0.5f);     normal.add_data3f( 0.0f,  0.0f,  1.0f);     texcoord.add_data2f(0.25f, 2/3.0f);     // 3

    // right
    vertex.add_data3f(+0.5f, +0.5f, -0.5f);     normal.add_data3f( 1.0f,  0.0f,  0.0f);     texcoord.add_data2f(0.75f, 1/3.0f);     // 4
    vertex.add_data3f(+0.5f, +0.5f, +0.5f);     normal.add_data3f( 1.0f,  0.0f,  0.0f);     texcoord.add_data2f(0.75f, 2/3.0f);     // 5
    vertex.add_data3f(+0.5f, -0.5f, -0.5f);     normal.add_data3f( 1.0f,  0.0f,  0.0f);     texcoord.add_data2f(0.5f, 1/3.0f);      // 6
    vertex.add_data3f(+0.5f, -0.5f, +0.5f);     normal.add_data3f( 1.0f,  0.0f,  0.0f);     texcoord.add_data2f(0.5f, 2/3.0f);      // 7

    // back
    vertex.add_data3f(-0.5f, +0.5f, -0.5f);     normal.add_data3f( 0.0f,  1.0f,  0.0f);     texcoord.add_data2f(1.0f, 1/3.0f);      // 8
    vertex.add_data3f(-0.5f, +0.5f, +0.5f);     normal.add_data3f( 0.0f,  1.0f,  0.0f);     texcoord.add_data2f(1.0f, 2/3.0f);      // 9
    vertex.add_data3f(+0.5f, +0.5f, +0.5f);     normal.add_data3f( 0.0f,  1.0f,  0.0f);     texcoord.add_data2f(0.75f, 2/3.0f);     // 10
    vertex.add_data3f(+0.5f, +0.5f, -0.5f);     normal.add_data3f( 0.0f,  1.0f,  0.0f);     texcoord.add_data2f(0.75f, 1/3.0f);     // 11

    // bottom
    vertex.add_data3f(-0.5f, -0.5f, -0.5f);     normal.add_data3f( 0.0f,  0.0f, -1.0f);     texcoord.add_data2f(0.25f, 1/3.0f);     // 12
    vertex.add_data3f(-0.5f, +0.5f, -0.5f);     normal.add_data3f( 0.0f,  0.0f, -1.0f);     texcoord.add_data2f(0.25f, 0.0f);       // 13
    vertex.add_data3f(+0.5f, -0.5f, -0.5f);     normal.add_data3f( 0.0f,  0.0f, -1.0f);     texcoord.add_data2f(0.5f, 1/3.0f);      // 14
    vertex.add_data3f(+0.5f, +0.5f, -0.5f);     normal.add_data3f( 0.0f,  0.0f, -1.0f);     texcoord.add_data2f(0.5f, 0.0f);        // 15

    // front
    vertex.add_data3f(-0.5f, -0.5f, -0.5f);     normal.add_data3f( 0.0f, -1.0f,  0.0f);     texcoord.add_data2f(0.25f, 1/3.0f);     // 16
    vertex.add_data3f(+0.5f, -0.5f, -0.5f);     normal.add_data3f( 0.0f, -1.0f,  0.0f);     texcoord.add_data2f(0.5f, 1/3.0f);      // 17
    vertex.add_data3f(-0.5f, -0.5f, +0.5f);     normal.add_data3f( 0.0f, -1.0f,  0.0f);     texcoord.add_data2f(0.25f, 2/3.0f);     // 18
    vertex.add_data3f(+0.5f, -0.5f, +0.5f);     normal.add_data3f( 0.0f, -1.0f,  0.0f);     texcoord.add_data2f(0.5f, 2/3.0f);      // 19

    // left
    vertex.add_data3f(-0.5f, -0.5f, -0.5f);     normal.add_data3f(-1.0f,  0.0f,  0.0f);     texcoord.add_data2f(0.25f, 1/3.0f);     // 20
    vertex.add_data3f(-0.5f, -0.5f, +0.5f);     normal.add_data3f(-1.0f,  0.0f,  0.0f);     texcoord.add_data2f(0.25f, 2/3.0f);     // 21
    vertex.add_data3f(-0.5f, +0.5f, -0.5f);     normal.add_data3f(-1.0f,  0.0f,  0.0f);     texcoord.add_data2f(0.0f, 1/3.0f);      // 22
    vertex.add_data3f(-0.5f, +0.5f, +0.5f);     normal.add_data3f(-1.0f,  0.0f,  0.0f);     texcoord.add_data2f(0.0f, 2/3.0f);      // 23

    // create indices
    PT(GeomTriangles) prim = new GeomTriangles(Geom::UsageHint::UH_static);
    prim->reserve_num_vertices(36);
    prim->add_vertices(0, 1, 2);
    prim->add_vertices(3, 2, 1);
    prim->add_vertices(4, 5, 7);
    prim->add_vertices(6, 4, 7);
    prim->add_vertices(10, 11, 9);
    prim->add_vertices(8, 9, 11);
    prim->add_vertices(12, 13, 14);
    prim->add_vertices(15, 14, 13);
    prim->add_vertices(16, 17, 18);
    prim->add_vertices(19, 18, 17);
    prim->add_vertices(20, 21, 22);
    prim->add_vertices(23, 22, 21);
    prim->close_primitive();

    PT(Geom) geom = new Geom(vdata);
    geom->add_primitive(prim);

    return create_geom_node(name, geom);
}

NodePath create_sphere(const std::string& name, unsigned int latitude, unsigned int longitude)
{
    latitude = (std::max)(1u, latitude);
    longitude = (std::max)(1u, longitude);

    // create vertices
    PT(GeomVertexData) vdata = new GeomVertexData(name, GeomVertexFormat::get_v3n3t2(), Geom::UsageHint::UH_static);
    vdata->unclean_set_num_rows((latitude + 1)*(longitude + 1));

    GeomVertexWriter vertex(vdata, InternalName::get_vertex());
    GeomVertexWriter normal(vdata, InternalName::get_normal());
    GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());

    const double pi = std::acos(-1);
    for (unsigned int i = 0; i <= latitude; ++i)
    {
        const double theta = i * pi / double(latitude);
        for (unsigned int j = 0; j <= longitude; ++j)
        {
            const double phi = j * 2.0 * pi / double(longitude);
            const double sin_theta = std::sin(theta);
            const double x = std::cos(phi) * sin_theta;
            const double y = std::sin(phi) * sin_theta;
            const double z = std::cos(theta);

            vertex.add_data3f(x, y, z);
            normal.add_data3f(x, y, z);
            texcoord.add_data2f(j / double(longitude), 1.0 - i / double(latitude));
        }
    }

    // create indices
    PT(GeomTriangles) prim = new GeomTriangles(Geom::UsageHint::UH_static);
    prim->reserve_num_vertices(longitude * latitude * 6);

    for (unsigned int i = 0; i < latitude; ++i)
    {
        for (unsigned int j = 0; j < longitude; ++j)
        {
            const int a = i * (longitude + 1) + j;
            const int b = a + (longitude + 1);

            prim->add_vertices(a, b, a+1);
            prim->add_vertices(b, b+1, a+1);
        }
    }
    prim->close_primitive();

    PT(Geom) geom = new Geom(vdata);
    geom->add_primitive(prim);

    return create_geom_node(name, geom);
}

}
<|endoftext|>


<commit_before>#include <cstdio>
#include <random>
#include <cmath>
#include <string>
#include <cstring>
#include <stdexcept>
#include <cassert>

//------------------------------------------------------------------------------
namespace base91
{
static const unsigned base=91;
static const unsigned char_bits=8;
static const unsigned digit_bits=13;
static const unsigned digit_size=0x2000;
static const unsigned digit_mask=0x1FFF;

void encode(const std::vector<unsigned char> & in,std::string & out)
{
	out.clear();
	out.reserve(digit_bits*in.size()/char_bits+2);
	unsigned acc=0;
	int bitacc=0;

	for (auto & n:in)
	{
		acc <<= char_bits;
		acc |= n;
		bitacc+=char_bits;
		while(digit_bits>=bitacc)
		{
			const unsigned cod = digit_mask & acc;
			out.push_back(lo[cod]);
			out.push_back(hi[cod]);
			acc>>=digit_bits;
			bitacc-=digit_bits;
		}
	}

	while(0 < bitacc)
	{
		const unsigned cod = digit_mask & acc;
		out.push_back(lo[cod]);
		out.push_back(hi[cod]);
		acc>>=digit_bits;
		bitacc-=digit_bits;
	}

	return;
}
void decode(const std::string & in,std::vector<unsigned char> & out)
{
	return;
}
}
//------------------------------------------------------------------------------

int main()
{
	std::vector<unsigned char> in{0,0,0,0,0,0,0,0,0};
	std::string out;
	base91::encode(in,out);
	std::cout<<out<<std::endl;

	return 0;
}

//------------------------------------------------------------------------------

<commit_msg>commit and sleep<commit_after>#include <cstdio>
#include <random>
#include <cmath>
#include <string>
#include <cstring>
#include <stdexcept>
#include <cassert>
#include <iostream>

//------------------------------------------------------------------------------
namespace base91
{
static const unsigned base=91;
static const unsigned char_bits=8;
static const unsigned digit_bits=13;
static const unsigned digit_size=0x2000;
static const unsigned digit_mask=0x1FFF;

char hi[digit_size]={'~',};
char lo[digit_size]={'~',};

unsigned short hilo[base][base]={0,};

void encode(const std::vector<unsigned char> & in,std::string & out)
{
	out.clear();
	out.reserve(digit_bits*in.size()/char_bits+2);
	unsigned acc=0;
	int bitacc=0;

	for (auto & n:in)
	{
		acc <<= char_bits;
		acc |= n;
		bitacc+=char_bits;
		while(digit_bits>=bitacc)
		{
			const unsigned cod = digit_mask & acc;
			out.push_back(lo[cod]);
			out.push_back(hi[cod]);
			acc>>=digit_bits;
			bitacc-=digit_bits;
		}
	}

	if(0 < bitacc)
	{
		const unsigned cod = digit_mask & acc;
		out.push_back(lo[cod]);
		if(bitacc>=7)
			out.push_back(hi[cod]);
	}

	return;
}
void decode(const std::string & in,std::vector<unsigned char> & out)
{
	out.clear();
	out.reserve(char_bits*in.size()/digit_bits);

	unsigned acc=0;
	int bitacc=0;
	short lower=-1;

	for (auto & n:in)
	{
		if(-1==lower)
		{
			lower=n-'!';
			continue;
		}
		acc<<=digit_bits;
		acc|=hilo[n-'!'][lower];
		bitacc+=digit_bits;
		lower=-1;

		while(char_bits<=bitacc)
		{
			out.push_back(0xFF & acc);
			acc>>=char_bits;
			bitacc-=char_bits;
		}
	}

	if(-1!=lower)
	{
		acc<<=digit_bits;
		acc|=hilo[0][lower];
		bitacc+=7;
	}

	while(char_bits<=bitacc)
	{
		out.push_back(0xFF & acc);
		acc>>=char_bits;
		bitacc-=char_bits;
	}

	return;
}
}
//------------------------------------------------------------------------------

int main()
{
	for(unsigned n=0, hi=0,lo=0;n<base91::digit_size;++n)
	{
		base91::lo[n]='!'+lo;
		base91::hi[n]='!'+hi;
		base91::hilo[hi][lo]=n;
		if(base91::base==(++lo))
		{
			hi++;
			lo=0;
		}
	}

	std::vector<unsigned char> in{0,1,2,3,0,0,1,2,0};
	std::string out;
	base91::encode(in,out);
	std::cout<<out<<std::endl;

	std::vector<unsigned char> test;
	base91::decode(out,test);

	for(auto n:test)
		std::cout<<":"<<(short)n;
	std::cout<<out<<std::endl;

	for(auto n:in)
		std::cout<<":"<<(short)n;
	std::cout<<out<<std::endl;

	return 0;
}

//------------------------------------------------------------------------------

<|endoftext|>


<commit_before>#include <windows.h>
#include <tchar.h>
#include <Shlwapi.h>
#include "resource.h"
#include <vector>

#pragma comment(lib, "Shlwapi.lib")

#ifndef UNICODE
#error "Must be compiled with unicode support."
#endif

#define USE_TASKBAR_API (_WIN32_WINNT >= _WIN32_WINNT_WIN7)

#define XP (_WIN32_WINNT < _WIN32_WINNT_VISTA)

#define MB_TITLE L"Cmder Launcher"
#define SHELL_MENU_REGISTRY_PATH_BACKGROUND L"Directory\\Background\\shell\\Cmder"
#define SHELL_MENU_REGISTRY_PATH_LISTITEM L"Directory\\shell\\Cmder"

#define streqi(a, b) (_wcsicmp((a), (b)) == 0)

#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFUNCTION__ WIDEN(__FUNCTION__)

#define FAIL_ON_ERROR(x) { DWORD ec; if ((ec = (x)) != ERROR_SUCCESS) { ShowErrorAndExit(ec, __WFUNCTION__, __LINE__); } }

void ShowErrorAndExit(DWORD ec, const wchar_t * func, int line)
{
	wchar_t * buffer;
	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL, ec, 0, (LPWSTR) &buffer, 0, NULL) == 0)
	{
		buffer = L"Unknown error. FormatMessage failed.";
	}

	wchar_t message[1024];
	swprintf_s(message, L"%s\nFunction: %s\nLine: %d", buffer, func, line);
	LocalFree(buffer);

	MessageBox(NULL, message, MB_TITLE, MB_OK | MB_ICONERROR);
	exit(1);
}

typedef struct _option
{
	std::wstring name;
	bool hasVal;
	std::wstring value;
	bool set;
} option;

typedef std::pair<std::wstring, std::wstring> optpair;

optpair GetOption()
{
	wchar_t * cmd = GetCommandLine();
	int argc;
	wchar_t ** argv = CommandLineToArgvW(cmd, &argc);
	optpair pair;

	if (argc == 1)
	{
		// no commandline argument...
		pair = optpair(L"/START", L"");
	}
	else if (argc == 2 && argv[1][0] != L'/')
	{
		// only a single argument: this should be a path...
		pair = optpair(L"/START", argv[1]);
	}
	else
	{
		pair = optpair(argv[1], argc > 2 ? argv[2] : L"");
	}

	LocalFree(argv);

	return pair;
}

bool FileExists(const wchar_t * filePath)
{
	HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

	if (hFile != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hFile);
		return true;
	}

	return false;
}

void StartCmder(std::wstring path, bool is_single_mode)
{
#if USE_TASKBAR_API
	wchar_t appId[MAX_PATH] = { 0 };
#endif
	wchar_t exeDir[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };
	wchar_t cfgPath[MAX_PATH] = { 0 };
	wchar_t oldCfgPath[MAX_PATH] = { 0 };
	wchar_t conEmuPath[MAX_PATH] = { 0 };
	wchar_t args[MAX_PATH * 2 + 256] = { 0 };

	GetModuleFileName(NULL, exeDir, sizeof(exeDir));

#if USE_TASKBAR_API
	wcscpy_s(appId, exeDir);
#endif

	PathRemoveFileSpec(exeDir);

	PathCombine(icoPath, exeDir, L"icons\\cmder.ico");

	// Check for machine-specific config file.
	PathCombine(oldCfgPath, exeDir, L"config\\ConEmu-%COMPUTERNAME%.xml");
	ExpandEnvironmentStrings(oldCfgPath, oldCfgPath, sizeof(oldCfgPath) / sizeof(oldCfgPath[0]));
	if (!PathFileExists(oldCfgPath)) {
		PathCombine(oldCfgPath, exeDir, L"config\\ConEmu.xml");
	}

	// Check for machine-specific config file.
	PathCombine(cfgPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu-%COMPUTERNAME%.xml");
	ExpandEnvironmentStrings(cfgPath, cfgPath, sizeof(cfgPath) / sizeof(cfgPath[0]));
	if (!PathFileExists(cfgPath)) {
		PathCombine(cfgPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.xml");
	}

	PathCombine(conEmuPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.exe");

	if (FileExists(oldCfgPath) && !FileExists(cfgPath))
	{
		if (!CopyFile(oldCfgPath, cfgPath, FALSE))
		{
			MessageBox(NULL,
				(GetLastError() == ERROR_ACCESS_DENIED)
				? L"Failed to copy ConEmu.xml file to new location! Restart cmder as administrator."
				: L"Failed to copy ConEmu.xml file to new location!", MB_TITLE, MB_ICONSTOP);
			exit(1);
		}
	}

	if (is_single_mode)
	{
		swprintf_s(args, L"/single /Icon \"%s\" /Title Cmder", icoPath);
	}
	else
	{
		swprintf_s(args, L"/Icon \"%s\" /Title Cmder", icoPath);
	}

	SetEnvironmentVariable(L"CMDER_ROOT", exeDir);
	if (!streqi(path.c_str(), L""))
	{
		SetEnvironmentVariable(L"CMDER_START", path.c_str());
	}
	else
	{
		static char buff[MAX_PATH];
		GetEnvironmentVariable(L"USER_PROFILE", buff, MAX_PATH);
		SetEnvironmentVariable(L"CMDER_START", buff);
	}

	STARTUPINFO si = { 0 };
	si.cb = sizeof(STARTUPINFO);
#if USE_TASKBAR_API
	si.lpTitle = appId;
	si.dwFlags = STARTF_TITLEISAPPID;
#endif

	PROCESS_INFORMATION pi;

	CreateProcess(conEmuPath, args, NULL, NULL, false, 0, NULL, NULL, &si, &pi);
}

bool IsUserOnly(std::wstring opt)
{
	bool userOnly;

	if (streqi(opt.c_str(), L"ALL"))
	{
		userOnly = false;
	}
	else if (streqi(opt.c_str(), L"USER"))
	{
		userOnly = true;
	}
	else
	{
		MessageBox(NULL, L"Unrecognized option for /REGISTER or /UNREGISTER. Must be either ALL or USER.", MB_TITLE, MB_OK);
		exit(1);
	}

	return userOnly;
}

HKEY GetRootKey(std::wstring opt)
{
	HKEY root;

	if (IsUserOnly(opt))
	{
		FAIL_ON_ERROR(RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, NULL,
			REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &root, NULL));
	}
	else
	{
		root = HKEY_CLASSES_ROOT;
	}

	return root;
}

void RegisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	// First, get the paths we will use

	wchar_t exePath[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };

	GetModuleFileName(NULL, exePath, sizeof(exePath));

	wchar_t commandStr[MAX_PATH + 20] = { 0 };
	swprintf_s(commandStr, L"\"%s\" \"%%V\"", exePath);

	// Now that we have `commandStr`, it's OK to change `exePath`...
	PathRemoveFileSpec(exePath);

	PathCombine(icoPath, exePath, L"icons\\cmder.ico");

	// Now set the registry keys

	HKEY root = GetRootKey(opt);

	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));

	FAIL_ON_ERROR(RegSetValue(cmderKey, L"", REG_SZ, L"Cmder Here", NULL));
	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"NoWorkingDirectory", 0, REG_SZ, (BYTE *)L"", 2));

	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"Icon", 0, REG_SZ, (BYTE *)icoPath, wcslen(icoPath) * sizeof(wchar_t)));

	HKEY command;
	FAIL_ON_ERROR(
		RegCreateKeyEx(cmderKey, L"command", 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &command, NULL));

	FAIL_ON_ERROR(RegSetValue(command, L"", REG_SZ, commandStr, NULL));

	RegCloseKey(command);
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

void UnregisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	HKEY root = GetRootKey(opt);
	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));
#if XP
	FAIL_ON_ERROR(SHDeleteKey(cmderKey, NULL));
#else
	FAIL_ON_ERROR(RegDeleteTree(cmderKey, NULL));
#endif
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

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

	optpair opt = GetOption();

	if (streqi(opt.first.c_str(), L"/START"))
	{
		StartCmder(opt.second, false);
	}
	else if (streqi(opt.first.c_str(), L"/SINGLE"))
	{
		StartCmder(opt.second, true);
	}
	else if (streqi(opt.first.c_str(), L"/REGISTER"))
	{
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else if (streqi(opt.first.c_str(), L"/UNREGISTER"))
	{
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else
	{
		MessageBox(NULL, L"Unrecognized parameter.\n\nValid options:\n  /START <path>\n  /SINGLE <path>\n  /REGISTER [USER/ALL]\n  /UNREGISTER [USER/ALL]", MB_TITLE, MB_OK);
		return 1;
	}

	return 0;
}
<commit_msg>Use the correct type and initialise it.<commit_after>#include <windows.h>
#include <tchar.h>
#include <Shlwapi.h>
#include "resource.h"
#include <vector>

#pragma comment(lib, "Shlwapi.lib")

#ifndef UNICODE
#error "Must be compiled with unicode support."
#endif

#define USE_TASKBAR_API (_WIN32_WINNT >= _WIN32_WINNT_WIN7)

#define XP (_WIN32_WINNT < _WIN32_WINNT_VISTA)

#define MB_TITLE L"Cmder Launcher"
#define SHELL_MENU_REGISTRY_PATH_BACKGROUND L"Directory\\Background\\shell\\Cmder"
#define SHELL_MENU_REGISTRY_PATH_LISTITEM L"Directory\\shell\\Cmder"

#define streqi(a, b) (_wcsicmp((a), (b)) == 0)

#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFUNCTION__ WIDEN(__FUNCTION__)

#define FAIL_ON_ERROR(x) { DWORD ec; if ((ec = (x)) != ERROR_SUCCESS) { ShowErrorAndExit(ec, __WFUNCTION__, __LINE__); } }

void ShowErrorAndExit(DWORD ec, const wchar_t * func, int line)
{
	wchar_t * buffer;
	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL, ec, 0, (LPWSTR) &buffer, 0, NULL) == 0)
	{
		buffer = L"Unknown error. FormatMessage failed.";
	}

	wchar_t message[1024];
	swprintf_s(message, L"%s\nFunction: %s\nLine: %d", buffer, func, line);
	LocalFree(buffer);

	MessageBox(NULL, message, MB_TITLE, MB_OK | MB_ICONERROR);
	exit(1);
}

typedef struct _option
{
	std::wstring name;
	bool hasVal;
	std::wstring value;
	bool set;
} option;

typedef std::pair<std::wstring, std::wstring> optpair;

optpair GetOption()
{
	wchar_t * cmd = GetCommandLine();
	int argc;
	wchar_t ** argv = CommandLineToArgvW(cmd, &argc);
	optpair pair;

	if (argc == 1)
	{
		// no commandline argument...
		pair = optpair(L"/START", L"");
	}
	else if (argc == 2 && argv[1][0] != L'/')
	{
		// only a single argument: this should be a path...
		pair = optpair(L"/START", argv[1]);
	}
	else
	{
		pair = optpair(argv[1], argc > 2 ? argv[2] : L"");
	}

	LocalFree(argv);

	return pair;
}

bool FileExists(const wchar_t * filePath)
{
	HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

	if (hFile != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hFile);
		return true;
	}

	return false;
}

void StartCmder(std::wstring path, bool is_single_mode)
{
#if USE_TASKBAR_API
	wchar_t appId[MAX_PATH] = { 0 };
#endif
	wchar_t exeDir[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };
	wchar_t cfgPath[MAX_PATH] = { 0 };
	wchar_t oldCfgPath[MAX_PATH] = { 0 };
	wchar_t conEmuPath[MAX_PATH] = { 0 };
	wchar_t args[MAX_PATH * 2 + 256] = { 0 };

	GetModuleFileName(NULL, exeDir, sizeof(exeDir));

#if USE_TASKBAR_API
	wcscpy_s(appId, exeDir);
#endif

	PathRemoveFileSpec(exeDir);

	PathCombine(icoPath, exeDir, L"icons\\cmder.ico");

	// Check for machine-specific config file.
	PathCombine(oldCfgPath, exeDir, L"config\\ConEmu-%COMPUTERNAME%.xml");
	ExpandEnvironmentStrings(oldCfgPath, oldCfgPath, sizeof(oldCfgPath) / sizeof(oldCfgPath[0]));
	if (!PathFileExists(oldCfgPath)) {
		PathCombine(oldCfgPath, exeDir, L"config\\ConEmu.xml");
	}

	// Check for machine-specific config file.
	PathCombine(cfgPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu-%COMPUTERNAME%.xml");
	ExpandEnvironmentStrings(cfgPath, cfgPath, sizeof(cfgPath) / sizeof(cfgPath[0]));
	if (!PathFileExists(cfgPath)) {
		PathCombine(cfgPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.xml");
	}

	PathCombine(conEmuPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.exe");

	if (FileExists(oldCfgPath) && !FileExists(cfgPath))
	{
		if (!CopyFile(oldCfgPath, cfgPath, FALSE))
		{
			MessageBox(NULL,
				(GetLastError() == ERROR_ACCESS_DENIED)
				? L"Failed to copy ConEmu.xml file to new location! Restart cmder as administrator."
				: L"Failed to copy ConEmu.xml file to new location!", MB_TITLE, MB_ICONSTOP);
			exit(1);
		}
	}

	if (is_single_mode)
	{
		swprintf_s(args, L"/single /Icon \"%s\" /Title Cmder", icoPath);
	}
	else
	{
		swprintf_s(args, L"/Icon \"%s\" /Title Cmder", icoPath);
	}

	SetEnvironmentVariable(L"CMDER_ROOT", exeDir);
	if (!streqi(path.c_str(), L""))
	{
		SetEnvironmentVariable(L"CMDER_START", path.c_str());
	}
	else
	{
		static wchar_t buff[MAX_PATH] = { 0 };
		GetEnvironmentVariable(L"USER_PROFILE", buff, MAX_PATH);
		SetEnvironmentVariable(L"CMDER_START", buff);
	}

	STARTUPINFO si = { 0 };
	si.cb = sizeof(STARTUPINFO);
#if USE_TASKBAR_API
	si.lpTitle = appId;
	si.dwFlags = STARTF_TITLEISAPPID;
#endif

	PROCESS_INFORMATION pi;

	CreateProcess(conEmuPath, args, NULL, NULL, false, 0, NULL, NULL, &si, &pi);
}

bool IsUserOnly(std::wstring opt)
{
	bool userOnly;

	if (streqi(opt.c_str(), L"ALL"))
	{
		userOnly = false;
	}
	else if (streqi(opt.c_str(), L"USER"))
	{
		userOnly = true;
	}
	else
	{
		MessageBox(NULL, L"Unrecognized option for /REGISTER or /UNREGISTER. Must be either ALL or USER.", MB_TITLE, MB_OK);
		exit(1);
	}

	return userOnly;
}

HKEY GetRootKey(std::wstring opt)
{
	HKEY root;

	if (IsUserOnly(opt))
	{
		FAIL_ON_ERROR(RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, NULL,
			REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &root, NULL));
	}
	else
	{
		root = HKEY_CLASSES_ROOT;
	}

	return root;
}

void RegisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	// First, get the paths we will use

	wchar_t exePath[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };

	GetModuleFileName(NULL, exePath, sizeof(exePath));

	wchar_t commandStr[MAX_PATH + 20] = { 0 };
	swprintf_s(commandStr, L"\"%s\" \"%%V\"", exePath);

	// Now that we have `commandStr`, it's OK to change `exePath`...
	PathRemoveFileSpec(exePath);

	PathCombine(icoPath, exePath, L"icons\\cmder.ico");

	// Now set the registry keys

	HKEY root = GetRootKey(opt);

	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));

	FAIL_ON_ERROR(RegSetValue(cmderKey, L"", REG_SZ, L"Cmder Here", NULL));
	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"NoWorkingDirectory", 0, REG_SZ, (BYTE *)L"", 2));

	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"Icon", 0, REG_SZ, (BYTE *)icoPath, wcslen(icoPath) * sizeof(wchar_t)));

	HKEY command;
	FAIL_ON_ERROR(
		RegCreateKeyEx(cmderKey, L"command", 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &command, NULL));

	FAIL_ON_ERROR(RegSetValue(command, L"", REG_SZ, commandStr, NULL));

	RegCloseKey(command);
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

void UnregisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	HKEY root = GetRootKey(opt);
	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));
#if XP
	FAIL_ON_ERROR(SHDeleteKey(cmderKey, NULL));
#else
	FAIL_ON_ERROR(RegDeleteTree(cmderKey, NULL));
#endif
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

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

	optpair opt = GetOption();

	if (streqi(opt.first.c_str(), L"/START"))
	{
		StartCmder(opt.second, false);
	}
	else if (streqi(opt.first.c_str(), L"/SINGLE"))
	{
		StartCmder(opt.second, true);
	}
	else if (streqi(opt.first.c_str(), L"/REGISTER"))
	{
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else if (streqi(opt.first.c_str(), L"/UNREGISTER"))
	{
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else
	{
		MessageBox(NULL, L"Unrecognized parameter.\n\nValid options:\n  /START <path>\n  /SINGLE <path>\n  /REGISTER [USER/ALL]\n  /UNREGISTER [USER/ALL]", MB_TITLE, MB_OK);
		return 1;
	}

	return 0;
}
<|endoftext|>


<commit_before>#include <windows.h>
#include <tchar.h>
#include <Shlwapi.h>
#include "resource.h"
#include <vector>

#pragma comment(lib, "Shlwapi.lib")

#ifndef UNICODE
#error "Must be compiled with unicode support."
#endif

#define USE_TASKBAR_API (_WIN32_WINNT >= _WIN32_WINNT_WIN7)

#define XP (_WIN32_WINNT < _WIN32_WINNT_VISTA)

#define MB_TITLE L"Cmder Launcher"
#define SHELL_MENU_REGISTRY_PATH_BACKGROUND L"Directory\\Background\\shell\\Cmder"
#define SHELL_MENU_REGISTRY_PATH_LISTITEM L"Directory\\shell\\Cmder"

#define streqi(a, b) (_wcsicmp((a), (b)) == 0)

#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFUNCTION__ WIDEN(__FUNCTION__)

#define FAIL_ON_ERROR(x) { DWORD ec; if ((ec = (x)) != ERROR_SUCCESS) { ShowErrorAndExit(ec, __WFUNCTION__, __LINE__); } }

void ShowErrorAndExit(DWORD ec, const wchar_t * func, int line)
{
	wchar_t * buffer;
	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL, ec, 0, (LPWSTR) &buffer, 0, NULL) == 0)
	{
		buffer = L"Unknown error. FormatMessage failed.";
	}

	wchar_t message[1024];
	swprintf_s(message, L"%s\nFunction: %s\nLine: %d", buffer, func, line);
	LocalFree(buffer);

	MessageBox(NULL, message, MB_TITLE, MB_OK | MB_ICONERROR);
	exit(1);
}

typedef struct _option
{
	std::wstring name;
	bool hasVal;
	std::wstring value;
	bool set;
} option;

typedef std::pair<std::wstring, std::wstring> optpair;

optpair GetOption()
{
	wchar_t * cmd = GetCommandLine();
	int argc;
	wchar_t ** argv = CommandLineToArgvW(cmd, &argc);
	optpair pair;

	if (argc == 1)
	{
		// no commandline argument...
		pair = optpair(L"/START", L"");
	}
	else if (argc == 2 && argv[1][0] != L'/')
	{
		// only a single argument: this should be a path...
		pair = optpair(L"/START", argv[1]);
	}
	else
	{
		pair = optpair(argv[1], argc > 2 ? argv[2] : L"");
	}

	LocalFree(argv);

	return pair;
}

bool FileExists(const wchar_t * filePath)
{
	HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

	if (hFile != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hFile);
		return true;
	}

	return false;
}

void StartCmder(std::wstring path, bool is_single_mode)
{
#if USE_TASKBAR_API
	wchar_t appId[MAX_PATH] = { 0 };
#endif
	wchar_t exeDir[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };
	wchar_t cfgPath[MAX_PATH] = { 0 };
	wchar_t oldCfgPath[MAX_PATH] = { 0 };
	wchar_t conEmuPath[MAX_PATH] = { 0 };
	wchar_t args[MAX_PATH * 2 + 256] = { 0 };

	GetModuleFileName(NULL, exeDir, sizeof(exeDir));

#if USE_TASKBAR_API
	wcscpy_s(appId, exeDir);
#endif

	PathRemoveFileSpec(exeDir);

	PathCombine(icoPath, exeDir, L"icons\\cmder.ico");

	// Check for machine-specific config file.
	PathCombine(oldCfgPath, exeDir, L"config\\ConEmu-%COMPUTERNAME%.xml");
	ExpandEnvironmentStrings(oldCfgPath, oldCfgPath, sizeof(oldCfgPath) / sizeof(oldCfgPath[0]));
	if (!PathFileExists(oldCfgPath)) {
		PathCombine(oldCfgPath, exeDir, L"config\\ConEmu.xml");
	}

	// Check for machine-specific config file.
	PathCombine(cfgPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu-%COMPUTERNAME%.xml");
	ExpandEnvironmentStrings(cfgPath, cfgPath, sizeof(cfgPath) / sizeof(cfgPath[0]));
	if (!PathFileExists(cfgPath)) {
		PathCombine(cfgPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.xml");
	}

	PathCombine(conEmuPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.exe");

	if (FileExists(oldCfgPath) && !FileExists(cfgPath))
	{
		if (!CopyFile(oldCfgPath, cfgPath, FALSE))
		{
			MessageBox(NULL,
				(GetLastError() == ERROR_ACCESS_DENIED)
				? L"Failed to copy ConEmu.xml file to new location! Restart cmder as administrator."
				: L"Failed to copy ConEmu.xml file to new location!", MB_TITLE, MB_ICONSTOP);
			exit(1);
		}
	}

	if (is_single_mode)
	{
		swprintf_s(args, L"/single /Icon \"%s\" /Title Cmder", icoPath);
	}
	else
	{
		swprintf_s(args, L"/Icon \"%s\" /Title Cmder", icoPath);
	}

	SetEnvironmentVariable(L"CMDER_ROOT", exeDir);
	if (!streqi(path.c_str(), L""))
	{
		if (!SetEnvironmentVariable(L"CMDER_START", path.c_str())) {
			MessageBox(NULL, _T("Error trying to set CMDER_START to given path!"), _T("Error"), MB_OK);
		}
	}
	// Ensure EnvironmentVariables are propagated.
	SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_ABORTIFHUNG, 5000, NULL);
	SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) L"Environment", SMTO_ABORTIFHUNG, 5000, NULL); // For Windows >= 8

	STARTUPINFO si = { 0 };
	si.cb = sizeof(STARTUPINFO);
#if USE_TASKBAR_API
	si.lpTitle = appId;
	si.dwFlags = STARTF_TITLEISAPPID;
#endif

	PROCESS_INFORMATION pi;
	if (!CreateProcess(conEmuPath, args, NULL, NULL, false, 0, NULL, NULL, &si, &pi)) {
		MessageBox(NULL, _T("Unable to create the ConEmu Process!"), _T("Error"), MB_OK);
		return;
	}
}

bool IsUserOnly(std::wstring opt)
{
	bool userOnly;

	if (streqi(opt.c_str(), L"ALL"))
	{
		userOnly = false;
	}
	else if (streqi(opt.c_str(), L"USER"))
	{
		userOnly = true;
	}
	else
	{
		MessageBox(NULL, L"Unrecognized option for /REGISTER or /UNREGISTER. Must be either ALL or USER.", MB_TITLE, MB_OK);
		exit(1);
	}

	return userOnly;
}

HKEY GetRootKey(std::wstring opt)
{
	HKEY root;

	if (IsUserOnly(opt))
	{
		FAIL_ON_ERROR(RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, NULL,
			REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &root, NULL));
	}
	else
	{
		root = HKEY_CLASSES_ROOT;
	}

	return root;
}

void RegisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	// First, get the paths we will use

	wchar_t exePath[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };

	GetModuleFileName(NULL, exePath, sizeof(exePath));

	wchar_t commandStr[MAX_PATH + 20] = { 0 };
	swprintf_s(commandStr, L"\"%s\" \"%%V\"", exePath);

	// Now that we have `commandStr`, it's OK to change `exePath`...
	PathRemoveFileSpec(exePath);

	PathCombine(icoPath, exePath, L"icons\\cmder.ico");

	// Now set the registry keys

	HKEY root = GetRootKey(opt);

	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));

	FAIL_ON_ERROR(RegSetValue(cmderKey, L"", REG_SZ, L"Cmder Here", NULL));
	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"NoWorkingDirectory", 0, REG_SZ, (BYTE *)L"", 2));

	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"Icon", 0, REG_SZ, (BYTE *)icoPath, wcslen(icoPath) * sizeof(wchar_t)));

	HKEY command;
	FAIL_ON_ERROR(
		RegCreateKeyEx(cmderKey, L"command", 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &command, NULL));

	FAIL_ON_ERROR(RegSetValue(command, L"", REG_SZ, commandStr, NULL));

	RegCloseKey(command);
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

void UnregisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	HKEY root = GetRootKey(opt);
	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));
#if XP
	FAIL_ON_ERROR(SHDeleteKey(cmderKey, NULL));
#else
	FAIL_ON_ERROR(RegDeleteTree(cmderKey, NULL));
#endif
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

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

	optpair opt = GetOption();

	if (streqi(opt.first.c_str(), L"/START"))
	{
		StartCmder(opt.second, false);
	}
	else if (streqi(opt.first.c_str(), L"/SINGLE"))
	{
		StartCmder(opt.second, true);
	}
	else if (streqi(opt.first.c_str(), L"/REGISTER"))
	{
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else if (streqi(opt.first.c_str(), L"/UNREGISTER"))
	{
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else
	{
		MessageBox(NULL, L"Unrecognized parameter.\n\nValid options:\n  /START <path>\n  /SINGLE <path>\n  /REGISTER [USER/ALL]\n  /UNREGISTER [USER/ALL]", MB_TITLE, MB_OK);
		return 1;
	}

	return 0;
}
<commit_msg>make launcher run ConEmu64 on 64-bit Windows<commit_after>#include <windows.h>
#include <tchar.h>
#include <Shlwapi.h>
#include "resource.h"
#include <vector>

#pragma comment(lib, "Shlwapi.lib")

#ifndef UNICODE
#error "Must be compiled with unicode support."
#endif

#define USE_TASKBAR_API (_WIN32_WINNT >= _WIN32_WINNT_WIN7)

#define XP (_WIN32_WINNT < _WIN32_WINNT_VISTA)

#define MB_TITLE L"Cmder Launcher"
#define SHELL_MENU_REGISTRY_PATH_BACKGROUND L"Directory\\Background\\shell\\Cmder"
#define SHELL_MENU_REGISTRY_PATH_LISTITEM L"Directory\\shell\\Cmder"

#define streqi(a, b) (_wcsicmp((a), (b)) == 0)

#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFUNCTION__ WIDEN(__FUNCTION__)

#define FAIL_ON_ERROR(x) { DWORD ec; if ((ec = (x)) != ERROR_SUCCESS) { ShowErrorAndExit(ec, __WFUNCTION__, __LINE__); } }

void ShowErrorAndExit(DWORD ec, const wchar_t * func, int line)
{
	wchar_t * buffer;
	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL, ec, 0, (LPWSTR) &buffer, 0, NULL) == 0)
	{
		buffer = L"Unknown error. FormatMessage failed.";
	}

	wchar_t message[1024];
	swprintf_s(message, L"%s\nFunction: %s\nLine: %d", buffer, func, line);
	LocalFree(buffer);

	MessageBox(NULL, message, MB_TITLE, MB_OK | MB_ICONERROR);
	exit(1);
}

typedef struct _option
{
	std::wstring name;
	bool hasVal;
	std::wstring value;
	bool set;
} option;

typedef std::pair<std::wstring, std::wstring> optpair;

optpair GetOption()
{
	wchar_t * cmd = GetCommandLine();
	int argc;
	wchar_t ** argv = CommandLineToArgvW(cmd, &argc);
	optpair pair;

	if (argc == 1)
	{
		// no commandline argument...
		pair = optpair(L"/START", L"");
	}
	else if (argc == 2 && argv[1][0] != L'/')
	{
		// only a single argument: this should be a path...
		pair = optpair(L"/START", argv[1]);
	}
	else
	{
		pair = optpair(argv[1], argc > 2 ? argv[2] : L"");
	}

	LocalFree(argv);

	return pair;
}

bool FileExists(const wchar_t * filePath)
{
	HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

	if (hFile != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hFile);
		return true;
	}

	return false;
}

void StartCmder(std::wstring path, bool is_single_mode)
{
#if USE_TASKBAR_API
	wchar_t appId[MAX_PATH] = { 0 };
#endif
	wchar_t exeDir[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };
	wchar_t cfgPath[MAX_PATH] = { 0 };
	wchar_t oldCfgPath[MAX_PATH] = { 0 };
	wchar_t conEmuPath[MAX_PATH] = { 0 };
	wchar_t args[MAX_PATH * 2 + 256] = { 0 };

	GetModuleFileName(NULL, exeDir, sizeof(exeDir));

#if USE_TASKBAR_API
	wcscpy_s(appId, exeDir);
#endif

	PathRemoveFileSpec(exeDir);

	PathCombine(icoPath, exeDir, L"icons\\cmder.ico");

	// Check for machine-specific config file.
	PathCombine(oldCfgPath, exeDir, L"config\\ConEmu-%COMPUTERNAME%.xml");
	ExpandEnvironmentStrings(oldCfgPath, oldCfgPath, sizeof(oldCfgPath) / sizeof(oldCfgPath[0]));
	if (!PathFileExists(oldCfgPath)) {
		PathCombine(oldCfgPath, exeDir, L"config\\ConEmu.xml");
	}

	// Check for machine-specific config file.
	PathCombine(cfgPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu-%COMPUTERNAME%.xml");
	ExpandEnvironmentStrings(cfgPath, cfgPath, sizeof(cfgPath) / sizeof(cfgPath[0]));
	if (!PathFileExists(cfgPath)) {
		PathCombine(cfgPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.xml");
	}

	SYSTEM_INFO sysInfo;
	GetNativeSystemInfo(&sysInfo);
	if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
		PathCombine(conEmuPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu64.exe");
	}
	else {
		PathCombine(conEmuPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.exe");
	}

	if (FileExists(oldCfgPath) && !FileExists(cfgPath))
	{
		if (!CopyFile(oldCfgPath, cfgPath, FALSE))
		{
			MessageBox(NULL,
				(GetLastError() == ERROR_ACCESS_DENIED)
				? L"Failed to copy ConEmu.xml file to new location! Restart cmder as administrator."
				: L"Failed to copy ConEmu.xml file to new location!", MB_TITLE, MB_ICONSTOP);
			exit(1);
		}
	}

	if (is_single_mode)
	{
		swprintf_s(args, L"/single /Icon \"%s\" /Title Cmder", icoPath);
	}
	else
	{
		swprintf_s(args, L"/Icon \"%s\" /Title Cmder", icoPath);
	}

	SetEnvironmentVariable(L"CMDER_ROOT", exeDir);
	if (!streqi(path.c_str(), L""))
	{
		if (!SetEnvironmentVariable(L"CMDER_START", path.c_str())) {
			MessageBox(NULL, _T("Error trying to set CMDER_START to given path!"), _T("Error"), MB_OK);
		}
	}
	// Ensure EnvironmentVariables are propagated.
	SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_ABORTIFHUNG, 5000, NULL);
	SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) L"Environment", SMTO_ABORTIFHUNG, 5000, NULL); // For Windows >= 8

	STARTUPINFO si = { 0 };
	si.cb = sizeof(STARTUPINFO);
#if USE_TASKBAR_API
	si.lpTitle = appId;
	si.dwFlags = STARTF_TITLEISAPPID;
#endif

	PROCESS_INFORMATION pi;
	if (!CreateProcess(conEmuPath, args, NULL, NULL, false, 0, NULL, NULL, &si, &pi)) {
		MessageBox(NULL, _T("Unable to create the ConEmu Process!"), _T("Error"), MB_OK);
		return;
	}
}

bool IsUserOnly(std::wstring opt)
{
	bool userOnly;

	if (streqi(opt.c_str(), L"ALL"))
	{
		userOnly = false;
	}
	else if (streqi(opt.c_str(), L"USER"))
	{
		userOnly = true;
	}
	else
	{
		MessageBox(NULL, L"Unrecognized option for /REGISTER or /UNREGISTER. Must be either ALL or USER.", MB_TITLE, MB_OK);
		exit(1);
	}

	return userOnly;
}

HKEY GetRootKey(std::wstring opt)
{
	HKEY root;

	if (IsUserOnly(opt))
	{
		FAIL_ON_ERROR(RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, NULL,
			REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &root, NULL));
	}
	else
	{
		root = HKEY_CLASSES_ROOT;
	}

	return root;
}

void RegisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	// First, get the paths we will use

	wchar_t exePath[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };

	GetModuleFileName(NULL, exePath, sizeof(exePath));

	wchar_t commandStr[MAX_PATH + 20] = { 0 };
	swprintf_s(commandStr, L"\"%s\" \"%%V\"", exePath);

	// Now that we have `commandStr`, it's OK to change `exePath`...
	PathRemoveFileSpec(exePath);

	PathCombine(icoPath, exePath, L"icons\\cmder.ico");

	// Now set the registry keys

	HKEY root = GetRootKey(opt);

	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));

	FAIL_ON_ERROR(RegSetValue(cmderKey, L"", REG_SZ, L"Cmder Here", NULL));
	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"NoWorkingDirectory", 0, REG_SZ, (BYTE *)L"", 2));

	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"Icon", 0, REG_SZ, (BYTE *)icoPath, wcslen(icoPath) * sizeof(wchar_t)));

	HKEY command;
	FAIL_ON_ERROR(
		RegCreateKeyEx(cmderKey, L"command", 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &command, NULL));

	FAIL_ON_ERROR(RegSetValue(command, L"", REG_SZ, commandStr, NULL));

	RegCloseKey(command);
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

void UnregisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	HKEY root = GetRootKey(opt);
	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));
#if XP
	FAIL_ON_ERROR(SHDeleteKey(cmderKey, NULL));
#else
	FAIL_ON_ERROR(RegDeleteTree(cmderKey, NULL));
#endif
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

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

	optpair opt = GetOption();

	if (streqi(opt.first.c_str(), L"/START"))
	{
		StartCmder(opt.second, false);
	}
	else if (streqi(opt.first.c_str(), L"/SINGLE"))
	{
		StartCmder(opt.second, true);
	}
	else if (streqi(opt.first.c_str(), L"/REGISTER"))
	{
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else if (streqi(opt.first.c_str(), L"/UNREGISTER"))
	{
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else
	{
		MessageBox(NULL, L"Unrecognized parameter.\n\nValid options:\n  /START <path>\n  /SINGLE <path>\n  /REGISTER [USER/ALL]\n  /UNREGISTER [USER/ALL]", MB_TITLE, MB_OK);
		return 1;
	}

	return 0;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "audio/voip/voip_core.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "api/audio_codecs/audio_format.h"
#include "rtc_base/logging.h"

namespace webrtc {

namespace {

// For Windows, use specific enum type to initialize default audio device as
// defined in AudioDeviceModule::WindowsDeviceType.
#if defined(WEBRTC_WIN)
constexpr AudioDeviceModule::WindowsDeviceType kAudioDeviceId =
    AudioDeviceModule::WindowsDeviceType::kDefaultCommunicationDevice;
#else
constexpr uint16_t kAudioDeviceId = 0;
#endif  // defined(WEBRTC_WIN)

// Maximum value range limit on ChannelId. This can be increased without any
// side effect and only set at this moderate value for better readability for
// logging.
static constexpr int kMaxChannelId = 100000;

}  // namespace

bool VoipCore::Init(rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
                    rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
                    std::unique_ptr<TaskQueueFactory> task_queue_factory,
                    rtc::scoped_refptr<AudioDeviceModule> audio_device_module,
                    rtc::scoped_refptr<AudioProcessing> audio_processing) {
  encoder_factory_ = std::move(encoder_factory);
  decoder_factory_ = std::move(decoder_factory);
  task_queue_factory_ = std::move(task_queue_factory);
  audio_device_module_ = std::move(audio_device_module);

  process_thread_ = ProcessThread::Create("ModuleProcessThread");
  audio_mixer_ = AudioMixerImpl::Create();

  if (audio_processing) {
    audio_processing_ = std::move(audio_processing);
    AudioProcessing::Config apm_config = audio_processing_->GetConfig();
    apm_config.echo_canceller.enabled = true;
    audio_processing_->ApplyConfig(apm_config);
  }

  // AudioTransportImpl depends on audio mixer and audio processing instances.
  audio_transport_ = std::make_unique<AudioTransportImpl>(
      audio_mixer_.get(), audio_processing_.get());

  // Initialize ADM.
  if (audio_device_module_->Init() != 0) {
    RTC_LOG(LS_ERROR) << "Failed to initialize the ADM.";
    return false;
  }

  // Note that failures on initializing default recording/speaker devices are
  // not considered to be fatal here. In certain case, caller may not care about
  // recording device functioning (e.g webinar where only speaker is available).
  // It's also possible that there are other audio devices available that may
  // work.
  // TODO(natim@webrtc.org): consider moving this part out of initialization.

  // Initialize default speaker device.
  if (audio_device_module_->SetPlayoutDevice(kAudioDeviceId) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set playout device.";
  }
  if (audio_device_module_->InitSpeaker() != 0) {
    RTC_LOG(LS_WARNING) << "Unable to access speaker.";
  }

  // Initialize default recording device.
  if (audio_device_module_->SetRecordingDevice(kAudioDeviceId) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set recording device.";
  }
  if (audio_device_module_->InitMicrophone() != 0) {
    RTC_LOG(LS_WARNING) << "Unable to access microphone.";
  }

  // Set number of channels on speaker device.
  bool available = false;
  if (audio_device_module_->StereoPlayoutIsAvailable(&available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to query stereo playout.";
  }
  if (audio_device_module_->SetStereoPlayout(available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set mono/stereo playout mode.";
  }

  // Set number of channels on recording device.
  available = false;
  if (audio_device_module_->StereoRecordingIsAvailable(&available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to query stereo recording.";
  }
  if (audio_device_module_->SetStereoRecording(available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set stereo recording mode.";
  }

  if (audio_device_module_->RegisterAudioCallback(audio_transport_.get()) !=
      0) {
    RTC_LOG(LS_WARNING) << "Unable to register audio callback.";
  }

  return true;
}

absl::optional<ChannelId> VoipCore::CreateChannel(
    Transport* transport,
    absl::optional<uint32_t> local_ssrc) {
  absl::optional<ChannelId> channel;

  // Set local ssrc to random if not set by caller.
  if (!local_ssrc) {
    Random random(rtc::TimeMicros());
    local_ssrc = random.Rand<uint32_t>();
  }

  rtc::scoped_refptr<AudioChannel> audio_channel =
      new rtc::RefCountedObject<AudioChannel>(
          transport, local_ssrc.value(), task_queue_factory_.get(),
          process_thread_.get(), audio_mixer_.get(), decoder_factory_);

  {
    MutexLock lock(&lock_);

    channel = static_cast<ChannelId>(next_channel_id_);
    channels_[*channel] = audio_channel;
    next_channel_id_++;
    if (next_channel_id_ >= kMaxChannelId) {
      next_channel_id_ = 0;
    }
  }

  // Set ChannelId in audio channel for logging/debugging purpose.
  audio_channel->SetId(*channel);

  return channel;
}

void VoipCore::ReleaseChannel(ChannelId channel) {
  // Destroy channel outside of the lock.
  rtc::scoped_refptr<AudioChannel> audio_channel;
  {
    MutexLock lock(&lock_);

    auto iter = channels_.find(channel);
    if (iter != channels_.end()) {
      audio_channel = std::move(iter->second);
      channels_.erase(iter);
    }
  }
  if (!audio_channel) {
    RTC_LOG(LS_WARNING) << "Channel " << channel << " not found";
  }
}

rtc::scoped_refptr<AudioChannel> VoipCore::GetChannel(ChannelId channel) {
  rtc::scoped_refptr<AudioChannel> audio_channel;
  {
    MutexLock lock(&lock_);
    auto iter = channels_.find(channel);
    if (iter != channels_.end()) {
      audio_channel = iter->second;
    }
  }
  if (!audio_channel) {
    RTC_LOG(LS_ERROR) << "Channel " << channel << " not found";
  }
  return audio_channel;
}

bool VoipCore::UpdateAudioTransportWithSenders() {
  std::vector<AudioSender*> audio_senders;

  // Gather a list of audio channel that are currently sending along with
  // highest sampling rate and channel numbers to configure into audio
  // transport.
  int max_sampling_rate = 8000;
  size_t max_num_channels = 1;
  {
    MutexLock lock(&lock_);
    // Reserve to prevent run time vector re-allocation.
    audio_senders.reserve(channels_.size());
    for (auto kv : channels_) {
      rtc::scoped_refptr<AudioChannel>& channel = kv.second;
      if (channel->IsSendingMedia()) {
        auto encoder_format = channel->GetEncoderFormat();
        if (!encoder_format) {
          RTC_LOG(LS_ERROR)
              << "channel " << channel->GetId() << " encoder is not set";
          continue;
        }
        audio_senders.push_back(channel->GetAudioSender());
        max_sampling_rate =
            std::max(max_sampling_rate, encoder_format->clockrate_hz);
        max_num_channels =
            std::max(max_num_channels, encoder_format->num_channels);
      }
    }
  }

  audio_transport_->UpdateAudioSenders(audio_senders, max_sampling_rate,
                                       max_num_channels);

  // Depending on availability of senders, turn on or off ADM recording.
  if (!audio_senders.empty()) {
    if (!audio_device_module_->Recording()) {
      if (audio_device_module_->InitRecording() != 0) {
        RTC_LOG(LS_ERROR) << "InitRecording failed";
        return false;
      }
      if (audio_device_module_->StartRecording() != 0) {
        RTC_LOG(LS_ERROR) << "StartRecording failed";
        return false;
      }
    }
  } else {
    if (audio_device_module_->Recording() &&
        audio_device_module_->StopRecording() != 0) {
      RTC_LOG(LS_ERROR) << "StopRecording failed";
      return false;
    }
  }
  return true;
}

bool VoipCore::StartSend(ChannelId channel) {
  auto audio_channel = GetChannel(channel);
  if (!audio_channel || !audio_channel->StartSend()) {
    return false;
  }

  return UpdateAudioTransportWithSenders();
}

bool VoipCore::StopSend(ChannelId channel) {
  auto audio_channel = GetChannel(channel);
  if (!audio_channel) {
    return false;
  }

  audio_channel->StopSend();

  return UpdateAudioTransportWithSenders();
}

bool VoipCore::StartPlayout(ChannelId channel) {
  auto audio_channel = GetChannel(channel);
  if (!audio_channel || !audio_channel->StartPlay()) {
    return false;
  }

  if (!audio_device_module_->Playing()) {
    if (audio_device_module_->InitPlayout() != 0) {
      RTC_LOG(LS_ERROR) << "InitPlayout failed";
      return false;
    }
    if (audio_device_module_->StartPlayout() != 0) {
      RTC_LOG(LS_ERROR) << "StartPlayout failed";
      return false;
    }
  }
  return true;
}

bool VoipCore::StopPlayout(ChannelId channel) {
  auto audio_channel = GetChannel(channel);
  if (!audio_channel) {
    return false;
  }

  audio_channel->StopPlay();

  bool stop_device = true;
  {
    MutexLock lock(&lock_);
    for (auto kv : channels_) {
      rtc::scoped_refptr<AudioChannel>& channel = kv.second;
      if (channel->IsPlaying()) {
        stop_device = false;
        break;
      }
    }
  }

  if (stop_device && audio_device_module_->Playing()) {
    if (audio_device_module_->StopPlayout() != 0) {
      RTC_LOG(LS_ERROR) << "StopPlayout failed";
      return false;
    }
  }
  return true;
}

void VoipCore::ReceivedRTPPacket(ChannelId channel,
                                 rtc::ArrayView<const uint8_t> rtp_packet) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    audio_channel->ReceivedRTPPacket(rtp_packet);
  }
}

void VoipCore::ReceivedRTCPPacket(ChannelId channel,
                                  rtc::ArrayView<const uint8_t> rtcp_packet) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    audio_channel->ReceivedRTCPPacket(rtcp_packet);
  }
}

void VoipCore::SetSendCodec(ChannelId channel,
                            int payload_type,
                            const SdpAudioFormat& encoder_format) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    auto encoder = encoder_factory_->MakeAudioEncoder(
        payload_type, encoder_format, absl::nullopt);
    audio_channel->SetEncoder(payload_type, encoder_format, std::move(encoder));
  }
}

void VoipCore::SetReceiveCodecs(
    ChannelId channel,
    const std::map<int, SdpAudioFormat>& decoder_specs) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    audio_channel->SetReceiveCodecs(decoder_specs);
  }
}

void VoipCore::RegisterTelephoneEventType(ChannelId channel,
                                          int rtp_payload_type,
                                          int sample_rate_hz) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    audio_channel->RegisterTelephoneEventType(rtp_payload_type, sample_rate_hz);
  }
}

bool VoipCore::SendDtmfEvent(ChannelId channel,
                             DtmfEvent dtmf_event,
                             int duration_ms) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    return audio_channel->SendTelephoneEvent(static_cast<int>(dtmf_event),
                                             duration_ms);
  }
  return false;
}

}  // namespace webrtc
<commit_msg>Removing logic forcing AEC within VoIP core<commit_after>/*
 *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "audio/voip/voip_core.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "api/audio_codecs/audio_format.h"
#include "rtc_base/logging.h"

namespace webrtc {

namespace {

// For Windows, use specific enum type to initialize default audio device as
// defined in AudioDeviceModule::WindowsDeviceType.
#if defined(WEBRTC_WIN)
constexpr AudioDeviceModule::WindowsDeviceType kAudioDeviceId =
    AudioDeviceModule::WindowsDeviceType::kDefaultCommunicationDevice;
#else
constexpr uint16_t kAudioDeviceId = 0;
#endif  // defined(WEBRTC_WIN)

// Maximum value range limit on ChannelId. This can be increased without any
// side effect and only set at this moderate value for better readability for
// logging.
static constexpr int kMaxChannelId = 100000;

}  // namespace

bool VoipCore::Init(rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
                    rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
                    std::unique_ptr<TaskQueueFactory> task_queue_factory,
                    rtc::scoped_refptr<AudioDeviceModule> audio_device_module,
                    rtc::scoped_refptr<AudioProcessing> audio_processing) {
  encoder_factory_ = std::move(encoder_factory);
  decoder_factory_ = std::move(decoder_factory);
  task_queue_factory_ = std::move(task_queue_factory);
  audio_device_module_ = std::move(audio_device_module);
  audio_processing_ = std::move(audio_processing);

  process_thread_ = ProcessThread::Create("ModuleProcessThread");
  audio_mixer_ = AudioMixerImpl::Create();

  // AudioTransportImpl depends on audio mixer and audio processing instances.
  audio_transport_ = std::make_unique<AudioTransportImpl>(
      audio_mixer_.get(), audio_processing_.get());

  // Initialize ADM.
  if (audio_device_module_->Init() != 0) {
    RTC_LOG(LS_ERROR) << "Failed to initialize the ADM.";
    return false;
  }

  // Note that failures on initializing default recording/speaker devices are
  // not considered to be fatal here. In certain case, caller may not care about
  // recording device functioning (e.g webinar where only speaker is available).
  // It's also possible that there are other audio devices available that may
  // work.
  // TODO(natim@webrtc.org): consider moving this part out of initialization.

  // Initialize default speaker device.
  if (audio_device_module_->SetPlayoutDevice(kAudioDeviceId) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set playout device.";
  }
  if (audio_device_module_->InitSpeaker() != 0) {
    RTC_LOG(LS_WARNING) << "Unable to access speaker.";
  }

  // Initialize default recording device.
  if (audio_device_module_->SetRecordingDevice(kAudioDeviceId) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set recording device.";
  }
  if (audio_device_module_->InitMicrophone() != 0) {
    RTC_LOG(LS_WARNING) << "Unable to access microphone.";
  }

  // Set number of channels on speaker device.
  bool available = false;
  if (audio_device_module_->StereoPlayoutIsAvailable(&available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to query stereo playout.";
  }
  if (audio_device_module_->SetStereoPlayout(available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set mono/stereo playout mode.";
  }

  // Set number of channels on recording device.
  available = false;
  if (audio_device_module_->StereoRecordingIsAvailable(&available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to query stereo recording.";
  }
  if (audio_device_module_->SetStereoRecording(available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set stereo recording mode.";
  }

  if (audio_device_module_->RegisterAudioCallback(audio_transport_.get()) !=
      0) {
    RTC_LOG(LS_WARNING) << "Unable to register audio callback.";
  }

  return true;
}

absl::optional<ChannelId> VoipCore::CreateChannel(
    Transport* transport,
    absl::optional<uint32_t> local_ssrc) {
  absl::optional<ChannelId> channel;

  // Set local ssrc to random if not set by caller.
  if (!local_ssrc) {
    Random random(rtc::TimeMicros());
    local_ssrc = random.Rand<uint32_t>();
  }

  rtc::scoped_refptr<AudioChannel> audio_channel =
      new rtc::RefCountedObject<AudioChannel>(
          transport, local_ssrc.value(), task_queue_factory_.get(),
          process_thread_.get(), audio_mixer_.get(), decoder_factory_);

  {
    MutexLock lock(&lock_);

    channel = static_cast<ChannelId>(next_channel_id_);
    channels_[*channel] = audio_channel;
    next_channel_id_++;
    if (next_channel_id_ >= kMaxChannelId) {
      next_channel_id_ = 0;
    }
  }

  // Set ChannelId in audio channel for logging/debugging purpose.
  audio_channel->SetId(*channel);

  return channel;
}

void VoipCore::ReleaseChannel(ChannelId channel) {
  // Destroy channel outside of the lock.
  rtc::scoped_refptr<AudioChannel> audio_channel;
  {
    MutexLock lock(&lock_);

    auto iter = channels_.find(channel);
    if (iter != channels_.end()) {
      audio_channel = std::move(iter->second);
      channels_.erase(iter);
    }
  }
  if (!audio_channel) {
    RTC_LOG(LS_WARNING) << "Channel " << channel << " not found";
  }
}

rtc::scoped_refptr<AudioChannel> VoipCore::GetChannel(ChannelId channel) {
  rtc::scoped_refptr<AudioChannel> audio_channel;
  {
    MutexLock lock(&lock_);
    auto iter = channels_.find(channel);
    if (iter != channels_.end()) {
      audio_channel = iter->second;
    }
  }
  if (!audio_channel) {
    RTC_LOG(LS_ERROR) << "Channel " << channel << " not found";
  }
  return audio_channel;
}

bool VoipCore::UpdateAudioTransportWithSenders() {
  std::vector<AudioSender*> audio_senders;

  // Gather a list of audio channel that are currently sending along with
  // highest sampling rate and channel numbers to configure into audio
  // transport.
  int max_sampling_rate = 8000;
  size_t max_num_channels = 1;
  {
    MutexLock lock(&lock_);
    // Reserve to prevent run time vector re-allocation.
    audio_senders.reserve(channels_.size());
    for (auto kv : channels_) {
      rtc::scoped_refptr<AudioChannel>& channel = kv.second;
      if (channel->IsSendingMedia()) {
        auto encoder_format = channel->GetEncoderFormat();
        if (!encoder_format) {
          RTC_LOG(LS_ERROR)
              << "channel " << channel->GetId() << " encoder is not set";
          continue;
        }
        audio_senders.push_back(channel->GetAudioSender());
        max_sampling_rate =
            std::max(max_sampling_rate, encoder_format->clockrate_hz);
        max_num_channels =
            std::max(max_num_channels, encoder_format->num_channels);
      }
    }
  }

  audio_transport_->UpdateAudioSenders(audio_senders, max_sampling_rate,
                                       max_num_channels);

  // Depending on availability of senders, turn on or off ADM recording.
  if (!audio_senders.empty()) {
    if (!audio_device_module_->Recording()) {
      if (audio_device_module_->InitRecording() != 0) {
        RTC_LOG(LS_ERROR) << "InitRecording failed";
        return false;
      }
      if (audio_device_module_->StartRecording() != 0) {
        RTC_LOG(LS_ERROR) << "StartRecording failed";
        return false;
      }
    }
  } else {
    if (audio_device_module_->Recording() &&
        audio_device_module_->StopRecording() != 0) {
      RTC_LOG(LS_ERROR) << "StopRecording failed";
      return false;
    }
  }
  return true;
}

bool VoipCore::StartSend(ChannelId channel) {
  auto audio_channel = GetChannel(channel);
  if (!audio_channel || !audio_channel->StartSend()) {
    return false;
  }

  return UpdateAudioTransportWithSenders();
}

bool VoipCore::StopSend(ChannelId channel) {
  auto audio_channel = GetChannel(channel);
  if (!audio_channel) {
    return false;
  }

  audio_channel->StopSend();

  return UpdateAudioTransportWithSenders();
}

bool VoipCore::StartPlayout(ChannelId channel) {
  auto audio_channel = GetChannel(channel);
  if (!audio_channel || !audio_channel->StartPlay()) {
    return false;
  }

  if (!audio_device_module_->Playing()) {
    if (audio_device_module_->InitPlayout() != 0) {
      RTC_LOG(LS_ERROR) << "InitPlayout failed";
      return false;
    }
    if (audio_device_module_->StartPlayout() != 0) {
      RTC_LOG(LS_ERROR) << "StartPlayout failed";
      return false;
    }
  }
  return true;
}

bool VoipCore::StopPlayout(ChannelId channel) {
  auto audio_channel = GetChannel(channel);
  if (!audio_channel) {
    return false;
  }

  audio_channel->StopPlay();

  bool stop_device = true;
  {
    MutexLock lock(&lock_);
    for (auto kv : channels_) {
      rtc::scoped_refptr<AudioChannel>& channel = kv.second;
      if (channel->IsPlaying()) {
        stop_device = false;
        break;
      }
    }
  }

  if (stop_device && audio_device_module_->Playing()) {
    if (audio_device_module_->StopPlayout() != 0) {
      RTC_LOG(LS_ERROR) << "StopPlayout failed";
      return false;
    }
  }
  return true;
}

void VoipCore::ReceivedRTPPacket(ChannelId channel,
                                 rtc::ArrayView<const uint8_t> rtp_packet) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    audio_channel->ReceivedRTPPacket(rtp_packet);
  }
}

void VoipCore::ReceivedRTCPPacket(ChannelId channel,
                                  rtc::ArrayView<const uint8_t> rtcp_packet) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    audio_channel->ReceivedRTCPPacket(rtcp_packet);
  }
}

void VoipCore::SetSendCodec(ChannelId channel,
                            int payload_type,
                            const SdpAudioFormat& encoder_format) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    auto encoder = encoder_factory_->MakeAudioEncoder(
        payload_type, encoder_format, absl::nullopt);
    audio_channel->SetEncoder(payload_type, encoder_format, std::move(encoder));
  }
}

void VoipCore::SetReceiveCodecs(
    ChannelId channel,
    const std::map<int, SdpAudioFormat>& decoder_specs) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    audio_channel->SetReceiveCodecs(decoder_specs);
  }
}

void VoipCore::RegisterTelephoneEventType(ChannelId channel,
                                          int rtp_payload_type,
                                          int sample_rate_hz) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    audio_channel->RegisterTelephoneEventType(rtp_payload_type, sample_rate_hz);
  }
}

bool VoipCore::SendDtmfEvent(ChannelId channel,
                             DtmfEvent dtmf_event,
                             int duration_ms) {
  // Failure to locate channel is logged internally in GetChannel.
  if (auto audio_channel = GetChannel(channel)) {
    return audio_channel->SendTelephoneEvent(static_cast<int>(dtmf_event),
                                             duration_ms);
  }
  return false;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Hallgrimur H. Gunnarsson.  All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <vector>

static int format = 0;
static unsigned int depth = 0;
static int tagpath[128];

enum
{
	CLASS_MASK	= 0xC0,
	TYPE_MASK	= 0x20,
	TAG_MASK	= 0x1F,
	LEN_XTND	= 0x80,
	LEN_MASK	= 0x7F
};

struct tag
{
	int cls;
	int isPrimitive;
	int id;
	int tag;
	int nbytes;
};

struct length
{
	unsigned int length;
	unsigned int nbytes;
};

struct TLV
{
	struct tag tag;
	struct length length;
	unsigned int nbytes;
	unsigned int depth;
	unsigned char *value;
	std::vector<struct TLV *> children;
};

int readTag(FILE *fp, struct tag *tag)
{
	memset(tag, 0, sizeof(struct tag));

	int b = fgetc(fp);

	if (b == EOF)
		return 1;

	tag->nbytes = 1;

	tag->tag = b;
	tag->cls = b & CLASS_MASK;
	tag->isPrimitive = (b & TYPE_MASK) == 0;

	tag->id = b & TAG_MASK;

	if (tag->id == TAG_MASK)
	{
		// Long tag, encoded as a sequence of 7-bit values

		tag->id = 0;

		do
		{
			b = fgetc(fp);

			if (b == EOF)
				return 1;

			tag->nbytes++;
			tag->id = (tag->id << 7) | (b & LEN_MASK);

		} while ((b & LEN_XTND) == LEN_XTND);
	}

	return 0;
}

int readLen(FILE *fp, struct length *length)
{
	int b, i;

	memset(length, 0, sizeof(struct length));

	b = fgetc(fp);

	if (b == EOF)
		return 1;

	length->nbytes = 1;
	length->length = b;

	if ((length->length & LEN_XTND) == LEN_XTND)
	{
		int numoct = length->length & LEN_MASK;

		length->length = 0;

		if (numoct == 0)
			return 0;

		for (i = 0; i < numoct; i++)
		{
			b = fgetc(fp);

			if (b == EOF)
				return 1;

			length->length = (length->length << 8) | b;
			length->nbytes++;
		}
	}

	return 0;
}

int readTLV(FILE *fp, struct TLV *tlv, unsigned int limit)
{
	int n = 0;
	int i;

	memset(tlv, 0, sizeof(struct TLV));

	if (readTag(fp, &tlv->tag))
		return 1;

	tlv->nbytes += tlv->tag.nbytes;

	if (tlv->nbytes >= limit)
		return 1;

	if (readLen(fp, &tlv->length))
		return 1;

	tlv->nbytes += tlv->length.nbytes;
	tlv->depth = depth;

	int length = tlv->length.length;

	if (tlv->nbytes >= limit)
	{
		if (length == 0)
			return 0;

		return 1;
	}

	if (tlv->tag.isPrimitive)
	{
		// Primitive definite-length method

		if (length == 0)
			return 0;

		tlv->value = (unsigned char *)malloc(length);

		if (!fread(tlv->value, length, 1, fp))
			return 1;

		tlv->nbytes += length;

		return 0;
	}

	if (length > 0)
	{
		// Constructed definite-length method

		struct TLV *child;
		i = 0;

		while (i < length)
		{
			depth++;

			child = (struct TLV *)malloc(sizeof(struct TLV));

			if (readTLV(fp, child, length-i))
			{
				depth--;
				return 1;
			}

			depth--;

			i += child->nbytes;
			tlv->nbytes += child->nbytes;
			tlv->children.push_back(child);
		}

		return 0;
	}

	// Constructed indefinite-length method

	struct TLV *child;

	while (1)
	{
		depth++;

		child = (struct TLV *)malloc(sizeof(struct TLV));

		n = readTLV(fp, child, limit-tlv->nbytes);

		depth--;

		tlv->nbytes += child->nbytes;

		if (n == 1)
			return 1;

		if (child->tag.tag == 0 && child->length.length == 0)
			break;

		tlv->children.push_back(child);
	}

	return 0;
}

void print(struct TLV *tlv)
{
	unsigned int i;

	for (i = 0; i < tlv->depth; i++)
		printf("  ");

	if (tlv->value)
	{
		printf("[%d] ", tlv->tag.id);

		for (i = 0; i < tlv->length.length; i++)
		{
			printf("%02x", tlv->value[i]);
		}

		printf("\n");

	} else
	{
		printf("[%d] {\n", tlv->tag.id);

		for (i = 0; i < tlv->children.size(); i++)
			print(tlv->children[i]);

		for (i = 0; i < tlv->depth; i++)
			printf("  ");

		printf("}\n");
	}
}

void printCSV(struct TLV *tlv, int printPath)
{
	unsigned int i;

	if (tlv->tag.isPrimitive)
	{
		tagpath[tlv->depth] = tlv->tag.id;

		if (printPath)
		{
			for (i = 0; i <= tlv->depth; i++)
			{
				if (i == 0)
					printf("%d", tagpath[i]);
				else
					printf(",%d", tagpath[i]);
			}
		} else
		{
			printf("%d", tlv->tag.id);
		}

		printf("|");

		for (i = 0; i < tlv->length.length; i++)
		{
			printf("%02x", tlv->value[i]);
		}

		printf("\n");

	} else
	{
		tagpath[tlv->depth] = tlv->tag.id;

		if (printPath)
		{
			for (i = 0; i <= tlv->depth; i++)
			{
				if (i == 0)
					printf("%d", tagpath[i]);
				else
					printf(",%d", tagpath[i]);
			}
		} else
		{
			printf("%d", tlv->tag.id);
		}

		printf("|BEGIN\n");

		for (i = 0; i < tlv->children.size(); i++)
			printCSV(tlv->children[i], printPath);

		if (printPath)
		{
			for (i = 0; i <= tlv->depth; i++)
			{
				if (i == 0)
					printf("%d", tagpath[i]);
				else
					printf(",%d", tagpath[i]);
			}
		} else
		{
			printf("%d", tlv->tag.id);
		}

		printf("|END\n");
	}
}

void dump(FILE *fp)
{
	struct TLV root;

	while (1)
	{
		if (feof(fp) || ferror(fp))
			break;

		if (readTLV(fp, &root, 1048576))
			break;

		memset(tagpath, 0, sizeof(tagpath));

		switch (format)
		{
			case 0:
				print(&root);
				break;
			case 1:
				printCSV(&root, 0);
				break;
			case 2:
				printCSV(&root, 1);
				break;
		}
	}
}

static void usage(void)
{
	fprintf(stderr, "usage: berdump [options] <files>\n");
	fprintf(stderr, "options:\n");
	fprintf(stderr, "  -f <N> : output format\n");
	fprintf(stderr, "output formats:\n");
	fprintf(stderr, "  -f0	  : Pretty tree structure\n");
	fprintf(stderr, "  -f1	  : CSV tag|value\n");
	fprintf(stderr, "  -f2	  : CSV tag|value with full tag path\n");
}

int main(int argc, char *argv[])
{
	int c, i;

	while ((c = getopt(argc, argv, "f:h?")) != -1)
	{
		switch (c)
		{
			case 'f':
				format = atoi(optarg);
				break;
			case '?':
				if (optopt == 'c')
					fprintf (stderr, "Option -%c requires an argument.\n", optopt);
				else if (isprint (optopt))
					fprintf (stderr, "Unknown option `-%c'.\n", optopt);
				else
					fprintf (stderr,
							"Unknown option character `\\x%x'.\n",
							optopt);
				return 1;
			case 'h':
			default:
				usage();
				return 0;
		}
	}

	argc -= optind;
	argv += optind;

	if (argc < 1)
	{
		dump(stdin);
		return 0;
	}

	for (i = 0; i < argc; i++)
	{
		if (strlen(argv[i]) == 1 && argv[i][0] == '-')
		{
			dump(stdin);
			continue;
		}

		FILE *fp = fopen(argv[i], "r");

		if (fp == NULL)
		{
			fprintf(stderr, "error opening %s: %s\n", argv[i], strerror(errno));
			continue;
		}

		dump(fp);

		fclose(fp);
	}
}

<commit_msg>Added error checking<commit_after>/*
 * Copyright 2011 Hallgrimur H. Gunnarsson.  All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <err.h>
#include <vector>

static int format = 0;
static unsigned int depth = 0;
static int tagpath[128];

enum
{
	CLASS_MASK	= 0xC0,
	TYPE_MASK	= 0x20,
	TAG_MASK	= 0x1F,
	LEN_XTND	= 0x80,
	LEN_MASK	= 0x7F
};

struct tag
{
	int cls;
	int isPrimitive;
	int id;
	int tag;
	int nbytes;
};

struct length
{
	unsigned int length;
	unsigned int nbytes;
};

struct TLV
{
	struct tag tag;
	struct length length;
	unsigned int nbytes;
	unsigned int depth;
	unsigned char *value;
	std::vector<struct TLV *> children;
};

int readTag(FILE *fp, struct tag *tag)
{
	memset(tag, 0, sizeof(struct tag));

	int b = fgetc(fp);

	if (b == EOF)
		return 1;

	tag->nbytes = 1;

	tag->tag = b;
	tag->cls = b & CLASS_MASK;
	tag->isPrimitive = (b & TYPE_MASK) == 0;

	tag->id = b & TAG_MASK;

	if (tag->id == TAG_MASK)
	{
		// Long tag, encoded as a sequence of 7-bit values

		tag->id = 0;

		do
		{
			b = fgetc(fp);

			if (b == EOF)
				return 1;

			tag->nbytes++;
			tag->id = (tag->id << 7) | (b & LEN_MASK);

		} while ((b & LEN_XTND) == LEN_XTND);
	}

	return 0;
}

int readLen(FILE *fp, struct length *length)
{
	int b, i;

	memset(length, 0, sizeof(struct length));

	b = fgetc(fp);

	if (b == EOF)
		return 1;

	length->nbytes = 1;
	length->length = b;

	if ((length->length & LEN_XTND) == LEN_XTND)
	{
		int numoct = length->length & LEN_MASK;

		length->length = 0;

		if (numoct == 0)
			return 0;

		for (i = 0; i < numoct; i++)
		{
			b = fgetc(fp);

			if (b == EOF)
				return 1;

			length->length = (length->length << 8) | b;
			length->nbytes++;
		}
	}

	return 0;
}

int readTLV(FILE *fp, struct TLV *tlv, unsigned int limit)
{
	int n = 0;
	int i;

	memset(tlv, 0, sizeof(struct TLV));

	if (readTag(fp, &tlv->tag))
		return 1;

	tlv->nbytes += tlv->tag.nbytes;

	if (tlv->nbytes >= limit)
		return 1;

	if (readLen(fp, &tlv->length))
		return 1;

	tlv->nbytes += tlv->length.nbytes;
	tlv->depth = depth;

	int length = tlv->length.length;

	if (tlv->nbytes >= limit)
	{
		if (length == 0)
			return 0;

		return 1;
	}

	if (tlv->tag.isPrimitive)
	{
		// Primitive definite-length method

		if (length == 0)
			return 0;

		tlv->value = (unsigned char *)malloc(length);

		if (tlv->value == NULL)
			err(1, "malloc");

		if (!fread(tlv->value, length, 1, fp))
			return 1;

		tlv->nbytes += length;

		return 0;
	}

	if (length > 0)
	{
		// Constructed definite-length method

		struct TLV *child;
		i = 0;

		while (i < length)
		{
			depth++;

			child = (struct TLV *)malloc(sizeof(struct TLV));

			if (child == NULL)
				err(1, "malloc");

			if (readTLV(fp, child, length-i))
			{
				depth--;
				return 1;
			}

			depth--;

			i += child->nbytes;
			tlv->nbytes += child->nbytes;
			tlv->children.push_back(child);
		}

		return 0;
	}

	// Constructed indefinite-length method

	struct TLV *child;

	while (1)
	{
		depth++;

		child = (struct TLV *)malloc(sizeof(struct TLV));

		if (child == NULL)
			err(1, "malloc");

		n = readTLV(fp, child, limit-tlv->nbytes);

		depth--;

		tlv->nbytes += child->nbytes;

		if (n == 1)
			return 1;

		if (child->tag.tag == 0 && child->length.length == 0)
			break;

		tlv->children.push_back(child);
	}

	return 0;
}

void print(struct TLV *tlv)
{
	unsigned int i;

	for (i = 0; i < tlv->depth; i++)
		printf("  ");

	if (tlv->value)
	{
		printf("[%d] ", tlv->tag.id);

		for (i = 0; i < tlv->length.length; i++)
		{
			printf("%02x", tlv->value[i]);
		}

		printf("\n");

	} else
	{
		printf("[%d] {\n", tlv->tag.id);

		for (i = 0; i < tlv->children.size(); i++)
			print(tlv->children[i]);

		for (i = 0; i < tlv->depth; i++)
			printf("  ");

		printf("}\n");
	}
}

void printCSV(struct TLV *tlv, int printPath)
{
	unsigned int i;

	if (tlv->tag.isPrimitive)
	{
		tagpath[tlv->depth] = tlv->tag.id;

		if (printPath)
		{
			for (i = 0; i <= tlv->depth; i++)
			{
				if (i == 0)
					printf("%d", tagpath[i]);
				else
					printf(",%d", tagpath[i]);
			}
		} else
		{
			printf("%d", tlv->tag.id);
		}

		printf("|");

		for (i = 0; i < tlv->length.length; i++)
		{
			printf("%02x", tlv->value[i]);
		}

		printf("\n");

	} else
	{
		tagpath[tlv->depth] = tlv->tag.id;

		if (printPath)
		{
			for (i = 0; i <= tlv->depth; i++)
			{
				if (i == 0)
					printf("%d", tagpath[i]);
				else
					printf(",%d", tagpath[i]);
			}
		} else
		{
			printf("%d", tlv->tag.id);
		}

		printf("|BEGIN\n");

		for (i = 0; i < tlv->children.size(); i++)
			printCSV(tlv->children[i], printPath);

		if (printPath)
		{
			for (i = 0; i <= tlv->depth; i++)
			{
				if (i == 0)
					printf("%d", tagpath[i]);
				else
					printf(",%d", tagpath[i]);
			}
		} else
		{
			printf("%d", tlv->tag.id);
		}

		printf("|END\n");
	}
}

void dump(FILE *fp)
{
	struct TLV root;

	while (1)
	{
		if (feof(fp) || ferror(fp))
			break;

		if (readTLV(fp, &root, 1048576))
			break;

		memset(tagpath, 0, sizeof(tagpath));

		switch (format)
		{
			case 0:
				print(&root);
				break;
			case 1:
				printCSV(&root, 0);
				break;
			case 2:
				printCSV(&root, 1);
				break;
		}
	}
}

static void usage(void)
{
	fprintf(stderr, "usage: berdump [options] <files>\n");
	fprintf(stderr, "options:\n");
	fprintf(stderr, "  -f <N> : output format\n");
	fprintf(stderr, "output formats:\n");
	fprintf(stderr, "  -f0	  : Pretty tree structure\n");
	fprintf(stderr, "  -f1	  : CSV tag|value\n");
	fprintf(stderr, "  -f2	  : CSV tag|value with full tag path\n");
}

int main(int argc, char *argv[])
{
	int c, i;

	while ((c = getopt(argc, argv, "f:h?")) != -1)
	{
		switch (c)
		{
			case 'f':
				format = atoi(optarg);
				break;
			case '?':
				if (optopt == 'c')
					fprintf (stderr, "Option -%c requires an argument.\n", optopt);
				else if (isprint (optopt))
					fprintf (stderr, "Unknown option `-%c'.\n", optopt);
				else
					fprintf (stderr,
							"Unknown option character `\\x%x'.\n",
							optopt);
				return 1;
			case 'h':
			default:
				usage();
				return 0;
		}
	}

	argc -= optind;
	argv += optind;

	if (argc < 1)
	{
		dump(stdin);
		return 0;
	}

	for (i = 0; i < argc; i++)
	{
		if (strlen(argv[i]) == 1 && argv[i][0] == '-')
		{
			dump(stdin);
			continue;
		}

		FILE *fp = fopen(argv[i], "r");

		if (fp == NULL)
		{
			fprintf(stderr, "error opening %s: %s\n", argv[i], strerror(errno));
			continue;
		}

		dump(fp);

		fclose(fp);
	}
}

<|endoftext|>


<commit_before>#include "ride/project.h"
#include <wx/utils.h>
#include <wx/process.h>
#include <wx/txtstrm.h>

#include "ride/mainwindow.h"
#include "ride/compilermessage.h"

Project::Project(MainWindow* output, const wxString& root_folder) : output_(output), root_folder_(root_folder) {
}

const wxString& Project::root_folder() const {
  return root_folder_;
}

void Project::Settings() {
  // todo: implement me
}

void Project::Build(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo build");
}

void Project::Clean(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo clean");
}

void Project::Rebuild(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  Clean(false);
  Build(false);
}

void Project::Doc(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo doc");
}

void Project::Run(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  Build(false);
}

void Project::Test(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo test");
}

void Project::Bench(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo bench");
}

void Project::Update(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo update");
}

//////////////////////////////////////////////////////////////////////////

class MyProcess : public wxProcess
{
public:
  MyProcess(Project* parent, const wxString& cmd)
    : wxProcess(), m_cmd(cmd)
  {
    m_parent = parent;
  }

  // instead of overriding this virtual function we might as well process the
  // event from it in the frame class - this might be more convenient in some
  // cases
  virtual void OnTerminate(int pid, int status) {
    m_parent->Append(wxString::Format(wxT("Process %u ('%s') terminated with exit code %d."),
      pid, m_cmd.c_str(), status));
    m_parent->Append("");
    m_parent->OnAsyncTermination(this);
  }

protected:
  Project *m_parent;
  wxString m_cmd;
};

// A specialization of MyProcess for redirecting the output
class MyPipedProcess : public MyProcess
{
public:
  MyPipedProcess(Project *parent, const wxString& cmd)
    : MyProcess(parent, cmd)
  {
    Redirect();
  }

  virtual void OnTerminate(int pid, int status) {
    // show the rest of the output
    while (HasInput())
      ;

    m_parent->OnProcessTerminated(this);

    MyProcess::OnTerminate(pid, status);
  }

  virtual bool HasInput() {
    bool hasInput = false;

    if (IsInputAvailable())
    {
      wxTextInputStream tis(*GetInputStream());

      // this assumes that the output is always line buffered
      wxString msg = tis.ReadLine();

      m_parent->Append(msg);

      hasInput = true;
    }

    if (IsErrorAvailable())
    {
      wxTextInputStream tis(*GetErrorStream());

      // this assumes that the output is always line buffered
      wxString msg = tis.ReadLine();

      m_parent->Append(msg);

      hasInput = true;
    }

    return hasInput;
  }
};

void Project::CleanOutput() {
  output_->Clear();
}

void Project::Append(const wxString str) {
  output_->Append(str);

#ifdef WIN32
  CompilerMessage mess;
  if (CompilerMessage::Parse(str, &mess)) {
    OutputDebugStringA(mess.message());
    OutputDebugStringA("\n");
  }
#endif
}

void Project::RunCmd(const wxString& cmd) {
  if (root_folder_.IsEmpty()) {
    wxMessageBox("No project open, you need to open a cargo project first!", "No project open!", wxICON_INFORMATION);
    return;
  }

  MyPipedProcess* process = new MyPipedProcess(this, cmd);
  Append("> " + cmd);

  wxExecuteEnv env;
  env.cwd = root_folder_;

  if (!wxExecute(cmd, wxEXEC_ASYNC | wxEXEC_HIDE_CONSOLE, process, &env)) {
    Append(wxString::Format(wxT("Execution of '%s' failed."), cmd.c_str()));
    delete process;
  }
  else {
    AddPipedProcess(process);
  }
}

void Project::AddPipedProcess(MyPipedProcess *process)
{
  m_running.Add(process);
  m_allAsync.Add(process);
}

void Project::OnProcessTerminated(MyPipedProcess *process)
{
  m_running.Remove(process);
}

void Project::OnAsyncTermination(MyProcess *process)
{
  m_allAsync.Remove(process);
  delete process;
}

<commit_msg>removed debug code<commit_after>#include "ride/project.h"
#include <wx/utils.h>
#include <wx/process.h>
#include <wx/txtstrm.h>

#include "ride/mainwindow.h"

Project::Project(MainWindow* output, const wxString& root_folder) : output_(output), root_folder_(root_folder) {
}

const wxString& Project::root_folder() const {
  return root_folder_;
}

void Project::Settings() {
  // todo: implement me
}

void Project::Build(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo build");
}

void Project::Clean(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo clean");
}

void Project::Rebuild(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  Clean(false);
  Build(false);
}

void Project::Doc(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo doc");
}

void Project::Run(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  Build(false);
}

void Project::Test(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo test");
}

void Project::Bench(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo bench");
}

void Project::Update(bool clean_output) {
  if (clean_output) {
    CleanOutput();
  }
  RunCmd("cargo update");
}

//////////////////////////////////////////////////////////////////////////

class MyProcess : public wxProcess
{
public:
  MyProcess(Project* parent, const wxString& cmd)
    : wxProcess(), m_cmd(cmd)
  {
    m_parent = parent;
  }

  // instead of overriding this virtual function we might as well process the
  // event from it in the frame class - this might be more convenient in some
  // cases
  virtual void OnTerminate(int pid, int status) {
    m_parent->Append(wxString::Format(wxT("Process %u ('%s') terminated with exit code %d."),
      pid, m_cmd.c_str(), status));
    m_parent->Append("");
    m_parent->OnAsyncTermination(this);
  }

protected:
  Project *m_parent;
  wxString m_cmd;
};

// A specialization of MyProcess for redirecting the output
class MyPipedProcess : public MyProcess
{
public:
  MyPipedProcess(Project *parent, const wxString& cmd)
    : MyProcess(parent, cmd)
  {
    Redirect();
  }

  virtual void OnTerminate(int pid, int status) {
    // show the rest of the output
    while (HasInput())
      ;

    m_parent->OnProcessTerminated(this);

    MyProcess::OnTerminate(pid, status);
  }

  virtual bool HasInput() {
    bool hasInput = false;

    if (IsInputAvailable())
    {
      wxTextInputStream tis(*GetInputStream());

      // this assumes that the output is always line buffered
      wxString msg = tis.ReadLine();

      m_parent->Append(msg);

      hasInput = true;
    }

    if (IsErrorAvailable())
    {
      wxTextInputStream tis(*GetErrorStream());

      // this assumes that the output is always line buffered
      wxString msg = tis.ReadLine();

      m_parent->Append(msg);

      hasInput = true;
    }

    return hasInput;
  }
};

void Project::CleanOutput() {
  output_->Clear();
}

void Project::Append(const wxString str) {
  output_->Append(str);
}

void Project::RunCmd(const wxString& cmd) {
  if (root_folder_.IsEmpty()) {
    wxMessageBox("No project open, you need to open a cargo project first!", "No project open!", wxICON_INFORMATION);
    return;
  }

  MyPipedProcess* process = new MyPipedProcess(this, cmd);
  Append("> " + cmd);

  wxExecuteEnv env;
  env.cwd = root_folder_;

  if (!wxExecute(cmd, wxEXEC_ASYNC | wxEXEC_HIDE_CONSOLE, process, &env)) {
    Append(wxString::Format(wxT("Execution of '%s' failed."), cmd.c_str()));
    delete process;
  }
  else {
    AddPipedProcess(process);
  }
}

void Project::AddPipedProcess(MyPipedProcess *process)
{
  m_running.Add(process);
  m_allAsync.Add(process);
}

void Project::OnProcessTerminated(MyPipedProcess *process)
{
  m_running.Remove(process);
}

void Project::OnAsyncTermination(MyProcess *process)
{
  m_allAsync.Remove(process);
  delete process;
}

<|endoftext|>


<commit_before>#include "layer_t.hpp"
#include "input_handler.hpp"

namespace rltk {

void layer_t::make_owner_draw_backing() {
	if (!backing) {
		backing = std::make_unique<sf::RenderTexture>();
	}
	backing->create(w, h);
}

void layer_t::on_resize(const int width, const int height) {
	resize_func(this, width, height);
	if (console && console->visible) {
		console->set_offset(x,y);
		console->resize_pixels(w, h);
	} else {
		make_owner_draw_backing();
	}
}

void layer_t::render(sf::RenderWindow &window) {
	if (console) {
		if (!controls.empty()) {

			// Render start events
			for (auto it=controls.begin(); it != controls.end(); ++it) {
				if (it->second->on_render_start) {
					auto callfunc = it->second->on_render_start.get();
					callfunc(it->second.get());
				}
			}

			int mouse_x, mouse_y;
			std::tie(mouse_x, mouse_y) = get_mouse_position();

			if (mouse_x >= x && mouse_x <= (x+w) && mouse_y >= y && mouse_y <= (y+h)) {
				// Mouse over in here is possible.
				auto font_dimensions = console->get_font_size();
				const int terminal_x = (mouse_x - x) / font_dimensions.first;
				const int terminal_y = (mouse_y - y) / font_dimensions.second;

				for (auto it=controls.begin(); it != controls.end(); ++it) {
					// Mouse over
					if (it->second->mouse_in_control(terminal_x, terminal_y)) {
						if (it->second->on_mouse_over) {
							auto callfunc = it->second->on_mouse_over.get();
							callfunc(it->second.get(), terminal_x, terminal_y);
						}

						// Mouse down and up
						if (get_mouse_button_state(button::LEFT) && it->second->on_mouse_down) {
							auto callfunc = it->second->on_mouse_down.get();
							callfunc(it->second.get(), terminal_x, terminal_y);
						}
						if (!get_mouse_button_state(button::LEFT) && it->second->on_mouse_up) {
							auto callfunc = it->second->on_mouse_up.get();
							callfunc(it->second.get(), terminal_x, terminal_y);
						}
					}
				}
			}

			for (auto it=controls.begin(); it != controls.end(); ++it) {
				it->second->render(console.get());
			}
		}
		console->render(window);
	} else if (sconsole) {
		sconsole->render(window);
	} else {
		if (!backing) make_owner_draw_backing();
		backing->clear(sf::Color(0,0,0,0));
		owner_draw_func(this, *backing);
		backing->display();
		sf::Sprite compositor(backing->getTexture());
		compositor.move(x, y);
		window.draw(sf::Sprite(compositor));
	}
}

void resize_fullscreen(rltk::layer_t * l, int w, int h) {
        // Use the whole window
        l->w = w;
        l->h = h;
}

}
<commit_msg>Fix formatting<commit_after>#include "layer_t.hpp"
#include "input_handler.hpp"

namespace rltk {

void layer_t::make_owner_draw_backing() {
	if (!backing) {
		backing = std::make_unique<sf::RenderTexture>();
	}
	backing->create(w, h);
}

void layer_t::on_resize(const int width, const int height) {
	resize_func(this, width, height);
	if (console && console->visible) {
		console->set_offset(x,y);
		console->resize_pixels(w, h);
		console->dirty = true;
	} else {
		make_owner_draw_backing();
	}
}

void layer_t::render(sf::RenderWindow &window) {
	if (console) {
		if (!controls.empty()) {

			// Render start events
			for (auto it=controls.begin(); it != controls.end(); ++it) {
				if (it->second->on_render_start) {
					auto callfunc = it->second->on_render_start.get();
					callfunc(it->second.get());
				}
			}

			int mouse_x, mouse_y;
			std::tie(mouse_x, mouse_y) = get_mouse_position();

			if (mouse_x >= x && mouse_x <= (x+w) && mouse_y >= y && mouse_y <= (y+h)) {
				// Mouse over in here is possible.
				auto font_dimensions = console->get_font_size();
				const int terminal_x = (mouse_x - x) / font_dimensions.first;
				const int terminal_y = (mouse_y - y) / font_dimensions.second;

				for (auto it=controls.begin(); it != controls.end(); ++it) {
					// Mouse over
					if (it->second->mouse_in_control(terminal_x, terminal_y)) {
						if (it->second->on_mouse_over) {
							auto callfunc = it->second->on_mouse_over.get();
							callfunc(it->second.get(), terminal_x, terminal_y);
						}

						// Mouse down and up
						if (get_mouse_button_state(button::LEFT) && it->second->on_mouse_down) {
							auto callfunc = it->second->on_mouse_down.get();
							callfunc(it->second.get(), terminal_x, terminal_y);
						}
						if (!get_mouse_button_state(button::LEFT) && it->second->on_mouse_up) {
							auto callfunc = it->second->on_mouse_up.get();
							callfunc(it->second.get(), terminal_x, terminal_y);
						}
					}
				}
			}

			for (auto it=controls.begin(); it != controls.end(); ++it) {
				it->second->render(console.get());
			}
		}
		console->render(window);
	} else if (sconsole) {
		sconsole->render(window);
	} else {
		if (!backing) make_owner_draw_backing();
		backing->clear(sf::Color(0,0,0,0));
		owner_draw_func(this, *backing);
		backing->display();
		sf::Sprite compositor(backing->getTexture());
		compositor.move(x, y);
		window.draw(sf::Sprite(compositor));
	}
}

void resize_fullscreen(rltk::layer_t * l, int w, int h) {
    // Use the whole window
    l->w = w;
    l->h = h;
}

}
<|endoftext|>