<commit_before>#include <chrono>
#include <random>
#include <array>

#include <opencv2/core/core.hpp>
#include <opencv2/ocl/ocl.hpp>

#include "opencl.hpp"
#include "utility.hpp"
#include "hog.pencil.h"
#include "HogDescriptor.h"
#include "hog.clh"

void time_hog( const std::vector<carp::record_t>& pool, const std::vector<float>& sizes, int num_positions, int repeat )
{
    carp::Timing timing("HOG");

    for (;repeat>0; --repeat) {
        for ( auto & size : sizes ) {
            for ( auto & item : pool ) {
                std::mt19937 rng(0);   //uses same seed, reseed for all iteration

                cv::Mat cpu_gray;
                cv::cvtColor( item.cpuimg(), cpu_gray, CV_RGB2GRAY );

                static_assert(sizeof(float[2]) == sizeof(std::array<float,2>), "This code needs std::array to behave exactly like C arrays.");
                std::vector<std::array<float,2>> locations;
                std::uniform_real_distribution<float> genx(size/2+1, cpu_gray.rows-1-size/2-1);
                std::uniform_real_distribution<float> geny(size/2+1, cpu_gray.cols-1-size/2-1);
                std::generate_n(std::back_inserter(locations), num_positions, [&](){ return std::array<float,2>{{ genx(rng), geny(rng) }}; });

                std::vector<float> cpu_result(num_positions * HISTOGRAM_BINS), gpu_result(num_positions * HISTOGRAM_BINS), pen_result(num_positions * HISTOGRAM_BINS);
                std::chrono::duration<double> elapsed_time_cpu, elapsed_time_gpu_p_copy, elapsed_time_gpu_nocopy, elapsed_time_pencil;

                {
                    //CPU implement
                    const auto cpu_start = std::chrono::high_resolution_clock::now();

                    auto result = nel::HOGDescriptor< NUMBER_OF_CELLS
                                                    , NUMBER_OF_BINS
                                                    , GAUSSIAN_WEIGHTS
                                                    , SPARTIAL_WEIGHTS
                                                    , SIGNED_HOG
                                                    >::compute(cpu_gray, locations, size);

                    const auto cpu_end = std::chrono::high_resolution_clock::now();

                    std::copy(result.begin(), result.end(), cpu_result.begin());
                    elapsed_time_cpu = cpu_end - cpu_start;
                    //Free up resources
                }
                {
                    carp::opencl::device device;

                    size_t max_work_group_size;
                    cl_int err;
                    err = clGetDeviceInfo( device.get_device_id()
                                         , CL_DEVICE_MAX_WORK_GROUP_SIZE
                                         , sizeof(size_t)
                                         , &max_work_group_size
                                         , nullptr
                                         );
                    const int work_size_locations = 64;
                    const int work_size_x = pow(2, std::ceil(std::log2(max_work_group_size / work_size_locations)/2));  //The square root of the max size/locations, rounded up to power-of-two
                    const int work_size_y = max_work_group_size / work_size_locations / work_size_x;
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot query max work group size.");

                    const auto gpu_compile_start = std::chrono::high_resolution_clock::now();
                    device.source_compile( hog_opencl_cl, hog_opencl_cl_len, {"calc_histogram", "fill_zeros"} );

                    const auto gpu_copy_start = std::chrono::high_resolution_clock::now();
                    cl_mem gpu_gray = clCreateBuffer( device.get_context()
                                                    , CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR
                                                    , cpu_gray.elemSize()*cpu_gray.rows*cpu_gray.step1()
                                                    , cpu_gray.data
                                                    , &err
                                                    );
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot copy source image to GPU.");
                    cl_mem gpu_locations = clCreateBuffer( device.get_context()
                                                         , CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR
                                                         , sizeof(float[2])*num_positions
                                                         , locations.data()
                                                         , &err
                                                         );
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot copy locations array to GPU.");
                    cl_mem gpu_hist = clCreateBuffer(device.get_context(), CL_MEM_WRITE_ONLY, sizeof(cl_float)*HISTOGRAM_BINS*num_positions, nullptr, &err);
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot allocate histogram array.");
                    device["fill_zeros"](gpu_hist, HISTOGRAM_BINS*num_positions).groupsize({255}, {HISTOGRAM_BINS*num_positions});

                    const auto gpu_start = std::chrono::high_resolution_clock::now();
                    device["calc_histogram"]( cpu_gray.rows
                                            , cpu_gray.cols
                                            , (int)cpu_gray.step1()
                                            , gpu_gray
                                            , num_positions
                                            , gpu_locations
                                            , size
                                            , gpu_hist
                                            , carp::opencl::buffer(sizeof(cl_float)*HISTOGRAM_BINS*num_positions)
                                            ).groupsize({work_size_locations,work_size_x,work_size_y}, {num_positions, (int)ceil(size), (int)ceil(size)});
                    const auto gpu_end = std::chrono::high_resolution_clock::now();

                    err = clEnqueueReadBuffer(device.get_queue(), gpu_hist, CL_TRUE, 0, sizeof(cl_float)*HISTOGRAM_BINS*num_positions, gpu_result.data(), 0, nullptr, nullptr);
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot copy histogram array to host.");

                    err = clReleaseMemObject(gpu_hist);
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot free histogram array.");
                    err = clReleaseMemObject(gpu_locations);
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot free gpu_locations array.");
                    err = clReleaseMemObject(gpu_gray);
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot free gpu_image array.");

                    const auto gpu_copy_end = std::chrono::high_resolution_clock::now();
                    const auto gpu_compile_end = std::chrono::high_resolution_clock::now();

                    elapsed_time_gpu_p_copy = gpu_copy_end - gpu_copy_start;
                    elapsed_time_gpu_nocopy = gpu_end      - gpu_start;
                    auto elapsed_time_gpu_compile = gpu_compile_end - gpu_compile_start;
                    //Free up resources
                }
                {
                    pen_result.resize(num_positions * HISTOGRAM_BINS, 0.0f);
                    const auto pencil_start = std::chrono::high_resolution_clock::now();
                    pencil_hog( cpu_gray.rows, cpu_gray.cols, cpu_gray.step1(), cpu_gray.ptr<uint8_t>()
                              , num_positions, reinterpret_cast<const float (*)[2]>(locations.data())
                              , size
                              , pen_result.data()
                              );

                    const auto pencil_end = std::chrono::high_resolution_clock::now();
                    elapsed_time_pencil = pencil_end - pencil_start;
                    //Free up resources
                }
                // Verifying the results
                if ( cv::norm( cpu_result, gpu_result, cv::NORM_INF) > cv::norm( gpu_result, cv::NORM_INF)*1e-5
                  || cv::norm( cpu_result, pen_result, cv::NORM_INF) > cv::norm( cpu_result, cv::NORM_INF)*1e-5
                   )
                {
                    std::vector<float> diff;
                    std::transform(cpu_result.begin(), cpu_result.end(), gpu_result.begin(), std::back_inserter(diff), std::minus<float>());

                    std::cerr << "ERROR: Results don't match." << std::endl;
                    std::cerr << "CPU norm:" << cv::norm(cpu_result, cv::NORM_INF) << std::endl;
                    std::cerr << "GPU norm:" << cv::norm(gpu_result, cv::NORM_INF) << std::endl;
                    std::cerr << "PEN norm:" << cv::norm(pen_result, cv::NORM_INF) << std::endl;
                    std::cerr << "GPU-CPU norm:" << cv::norm(gpu_result, cpu_result, cv::NORM_INF) << std::endl;
                    std::cerr << "PEN-CPU norm:" << cv::norm(pen_result, cpu_result, cv::NORM_INF) << std::endl;

                    throw std::runtime_error("The OpenCL or PENCIL results are not equivalent with the C++ results.");
                }
                timing.print( elapsed_time_cpu, elapsed_time_gpu_p_copy, elapsed_time_gpu_nocopy, elapsed_time_pencil );
            }
        }
    }
}

int main(int argc, char* argv[])
{
    try {
        std::cout << "This executable is iterating over all the files which are present in the directory `./pool'. " << std::endl;

        auto pool = carp::get_pool("pool");
#ifdef RUN_ONLY_ONE_EXPERIMENT
        time_hog( pool, {64}, 50, 1 );
#else
        time_hog( pool, {16, 32, 64, 128, 192}, 50, 10 );
#endif

        return EXIT_SUCCESS;
    }catch(const std::exception& e) {
        std::cout << e.what() << std::endl;
        return EXIT_FAILURE;
    }
} // main
<commit_msg>Better groupsize for calling fill_zeros OpenCL kernel<commit_after>#include <chrono>
#include <random>
#include <array>

#include <opencv2/core/core.hpp>
#include <opencv2/ocl/ocl.hpp>

#include "opencl.hpp"
#include "utility.hpp"
#include "hog.pencil.h"
#include "HogDescriptor.h"
#include "hog.clh"

void time_hog( const std::vector<carp::record_t>& pool, const std::vector<float>& sizes, int num_positions, int repeat )
{
    carp::Timing timing("HOG");

    for (;repeat>0; --repeat) {
        for ( auto & size : sizes ) {
            for ( auto & item : pool ) {
                std::mt19937 rng(0);   //uses same seed, reseed for all iteration

                cv::Mat cpu_gray;
                cv::cvtColor( item.cpuimg(), cpu_gray, CV_RGB2GRAY );

                static_assert(sizeof(float[2]) == sizeof(std::array<float,2>), "This code needs std::array to behave exactly like C arrays.");
                std::vector<std::array<float,2>> locations;
                std::uniform_real_distribution<float> genx(size/2+1, cpu_gray.rows-1-size/2-1);
                std::uniform_real_distribution<float> geny(size/2+1, cpu_gray.cols-1-size/2-1);
                std::generate_n(std::back_inserter(locations), num_positions, [&](){ return std::array<float,2>{{ genx(rng), geny(rng) }}; });

                std::vector<float> cpu_result(num_positions * HISTOGRAM_BINS), gpu_result(num_positions * HISTOGRAM_BINS), pen_result(num_positions * HISTOGRAM_BINS);
                std::chrono::duration<double> elapsed_time_cpu, elapsed_time_gpu_p_copy, elapsed_time_gpu_nocopy, elapsed_time_pencil;

                {
                    //CPU implement
                    const auto cpu_start = std::chrono::high_resolution_clock::now();

                    auto result = nel::HOGDescriptor< NUMBER_OF_CELLS
                                                    , NUMBER_OF_BINS
                                                    , GAUSSIAN_WEIGHTS
                                                    , SPARTIAL_WEIGHTS
                                                    , SIGNED_HOG
                                                    >::compute(cpu_gray, locations, size);

                    const auto cpu_end = std::chrono::high_resolution_clock::now();

                    std::copy(result.begin(), result.end(), cpu_result.begin());
                    elapsed_time_cpu = cpu_end - cpu_start;
                    //Free up resources
                }
                {
                    carp::opencl::device device;

                    size_t max_work_group_size;
                    cl_int err;
                    err = clGetDeviceInfo( device.get_device_id()
                                         , CL_DEVICE_MAX_WORK_GROUP_SIZE
                                         , sizeof(size_t)
                                         , &max_work_group_size
                                         , nullptr
                                         );
                    const int work_size_locations = 64;
                    const int work_size_x = pow(2, std::ceil(std::log2(max_work_group_size / work_size_locations)/2));  //The square root of the max size/locations, rounded up to power-of-two
                    const int work_size_y = max_work_group_size / work_size_locations / work_size_x;
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot query max work group size.");

                    const auto gpu_compile_start = std::chrono::high_resolution_clock::now();
                    device.source_compile( hog_opencl_cl, hog_opencl_cl_len, {"calc_histogram", "fill_zeros"} );

                    const auto gpu_copy_start = std::chrono::high_resolution_clock::now();
                    cl_mem gpu_gray = clCreateBuffer( device.get_context()
                                                    , CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR
                                                    , cpu_gray.elemSize()*cpu_gray.rows*cpu_gray.step1()
                                                    , cpu_gray.data
                                                    , &err
                                                    );
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot copy source image to GPU.");
                    cl_mem gpu_locations = clCreateBuffer( device.get_context()
                                                         , CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR
                                                         , sizeof(float[2])*num_positions
                                                         , locations.data()
                                                         , &err
                                                         );
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot copy locations array to GPU.");
                    cl_mem gpu_hist = clCreateBuffer(device.get_context(), CL_MEM_WRITE_ONLY, sizeof(cl_float)*HISTOGRAM_BINS*num_positions, nullptr, &err);
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot allocate histogram array.");
                    device["fill_zeros"](gpu_hist, HISTOGRAM_BINS*num_positions).groupsize({std::min<size_t>(max_work_group_size, HISTOGRAM_BINS*num_positions)}, {HISTOGRAM_BINS*num_positions});

                    const auto gpu_start = std::chrono::high_resolution_clock::now();
                    device["calc_histogram"]( cpu_gray.rows
                                            , cpu_gray.cols
                                            , (int)cpu_gray.step1()
                                            , gpu_gray
                                            , num_positions
                                            , gpu_locations
                                            , size
                                            , gpu_hist
                                            , carp::opencl::buffer(sizeof(cl_float)*HISTOGRAM_BINS*num_positions)
                                            ).groupsize({work_size_locations,work_size_x,work_size_y}, {num_positions, (int)ceil(size), (int)ceil(size)});
                    const auto gpu_end = std::chrono::high_resolution_clock::now();

                    err = clEnqueueReadBuffer(device.get_queue(), gpu_hist, CL_TRUE, 0, sizeof(cl_float)*HISTOGRAM_BINS*num_positions, gpu_result.data(), 0, nullptr, nullptr);
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot copy histogram array to host.");

                    err = clReleaseMemObject(gpu_hist);
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot free histogram array.");
                    err = clReleaseMemObject(gpu_locations);
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot free gpu_locations array.");
                    err = clReleaseMemObject(gpu_gray);
                    if (err != CL_SUCCESS) throw std::runtime_error("Cannot free gpu_image array.");

                    const auto gpu_copy_end = std::chrono::high_resolution_clock::now();
                    const auto gpu_compile_end = std::chrono::high_resolution_clock::now();

                    elapsed_time_gpu_p_copy = gpu_copy_end - gpu_copy_start;
                    elapsed_time_gpu_nocopy = gpu_end      - gpu_start;
                    auto elapsed_time_gpu_compile = gpu_compile_end - gpu_compile_start;
                    //Free up resources
                }
                {
                    pen_result.resize(num_positions * HISTOGRAM_BINS, 0.0f);
                    const auto pencil_start = std::chrono::high_resolution_clock::now();
                    pencil_hog( cpu_gray.rows, cpu_gray.cols, cpu_gray.step1(), cpu_gray.ptr<uint8_t>()
                              , num_positions, reinterpret_cast<const float (*)[2]>(locations.data())
                              , size
                              , pen_result.data()
                              );

                    const auto pencil_end = std::chrono::high_resolution_clock::now();
                    elapsed_time_pencil = pencil_end - pencil_start;
                    //Free up resources
                }
                // Verifying the results
                if ( cv::norm( cpu_result, gpu_result, cv::NORM_INF) > cv::norm( gpu_result, cv::NORM_INF)*1e-5
                  || cv::norm( cpu_result, pen_result, cv::NORM_INF) > cv::norm( cpu_result, cv::NORM_INF)*1e-5
                   )
                {
                    std::vector<float> diff;
                    std::transform(cpu_result.begin(), cpu_result.end(), gpu_result.begin(), std::back_inserter(diff), std::minus<float>());

                    std::cerr << "ERROR: Results don't match." << std::endl;
                    std::cerr << "CPU norm:" << cv::norm(cpu_result, cv::NORM_INF) << std::endl;
                    std::cerr << "GPU norm:" << cv::norm(gpu_result, cv::NORM_INF) << std::endl;
                    std::cerr << "PEN norm:" << cv::norm(pen_result, cv::NORM_INF) << std::endl;
                    std::cerr << "GPU-CPU norm:" << cv::norm(gpu_result, cpu_result, cv::NORM_INF) << std::endl;
                    std::cerr << "PEN-CPU norm:" << cv::norm(pen_result, cpu_result, cv::NORM_INF) << std::endl;

                    throw std::runtime_error("The OpenCL or PENCIL results are not equivalent with the C++ results.");
                }
                timing.print( elapsed_time_cpu, elapsed_time_gpu_p_copy, elapsed_time_gpu_nocopy, elapsed_time_pencil );
            }
        }
    }
}

int main(int argc, char* argv[])
{
    try {
        std::cout << "This executable is iterating over all the files which are present in the directory `./pool'. " << std::endl;

        auto pool = carp::get_pool("pool");
#ifdef RUN_ONLY_ONE_EXPERIMENT
        time_hog( pool, {64}, 50, 1 );
#else
        time_hog( pool, {16, 32, 64, 128, 192}, 50, 10 );
#endif

        return EXIT_SUCCESS;
    }catch(const std::exception& e) {
        std::cout << e.what() << std::endl;
        return EXIT_FAILURE;
    }
} // main
<|endoftext|>


<commit_before>#include "RenderTarget.h"

#include <unirender/UR_RenderContext.h>
#include <shaderlab/ShaderMgr.h>
#include <shaderlab/Sprite2Shader.h>
#include <shaderlab/FilterShader.h>
#include <shaderlab/ShaderMgr.h>
#include <sprite2/RenderScissor.h>
#include <sprite2/RenderCtxStack.h>

namespace gum
{

RenderTarget::RenderTarget(int width, int height)
	: s2::RenderTarget(width, height)
{
}

void RenderTarget::Bind()
{
	s2::RenderScissor::Instance()->Disable();

	int w = Width(),
		h = Height();
	s2::RenderContext ctx(w, h, w, h);
	// use last model view
	const s2::RenderContext* last = s2::RenderCtxStack::Instance()->Top();
	if (last) {
		ctx.SetModelView(last->GetMVOffset(), last->GetMVScale());
	}
	s2::RenderCtxStack::Instance()->Push(ctx);

	s2::RenderTarget::Bind();
}

void RenderTarget::Unbind()
{
	s2::RenderCtxStack::Instance()->Pop();
	s2::RenderScissor::Instance()->Enable();

	s2::RenderTarget::Unbind();
}

void RenderTarget::Draw(const sm::rect& src, const sm::rect& dst, int dst_w, int dst_h) const
{
	sl::ShaderMgr::Instance()->FlushShader();

	float vertices[8], texcoords[8];

	float w, h;
	if (dst_w != 0 && dst_h != 0) {
		w = dst_w;
		h = dst_h;
	} else {
		w = Width();
		h = Height();
	}

	s2::RenderScissor::Instance()->Disable();
	s2::RenderCtxStack::Instance()->Push(s2::RenderContext(w, h, w, h));

	float hw = w * 0.5f,
		  hh = h * 0.5f;
	vertices[0] = w * dst.xmin - hw; vertices[1] = h * dst.ymin - hh;
	vertices[2] = w * dst.xmax - hw; vertices[3] = h * dst.ymin - hh;
	vertices[4] = w * dst.xmax - hw; vertices[5] = h * dst.ymax - hh;
	vertices[6] = w * dst.xmin - hw; vertices[7] = h * dst.ymax - hh;

	texcoords[0] = src.xmin; texcoords[1] = src.ymin;
	texcoords[2] = src.xmax; texcoords[3] = src.ymin;
	texcoords[4] = src.xmax; texcoords[5] = src.ymax;
	texcoords[6] = src.xmin; texcoords[7] = src.ymax;

	sl::ShaderMgr* sl_mgr = sl::ShaderMgr::Instance();
	switch (sl_mgr->GetShaderType())
	{
	case sl::SPRITE2:
		{
			sl::Sprite2Shader* shader = static_cast<sl::Sprite2Shader*>(sl_mgr->GetShader());
			shader->SetColor(0xffffffff, 0);
			shader->SetColorMap(0x000000ff, 0x0000ff00, 0x00ff0000);
			shader->DrawQuad(vertices, texcoords, GetTexID());
		}
		break;
	case sl::FILTER:
		{
			sl::FilterShader* shader = static_cast<sl::FilterShader*>(sl_mgr->GetShader());
			shader->SetColor(0xffffffff, 0);
			shader->Draw(vertices, texcoords, GetTexID());
		}
		break;
	default:
		break;
	}

	s2::RenderCtxStack::Instance()->Pop();
	s2::RenderScissor::Instance()->Enable();
}

void RenderTarget::Clear()
{
	Bind();

	sl::ShaderMgr* mgr = sl::ShaderMgr::Instance();
	mgr->GetContext()->Clear(0);

	Unbind();
}

}<commit_msg>[FIXED] rt draw, use last viewport<commit_after>#include "RenderTarget.h"

#include <unirender/UR_RenderContext.h>
#include <shaderlab/ShaderMgr.h>
#include <shaderlab/Sprite2Shader.h>
#include <shaderlab/FilterShader.h>
#include <shaderlab/ShaderMgr.h>
#include <sprite2/RenderScissor.h>
#include <sprite2/RenderCtxStack.h>

namespace gum
{

RenderTarget::RenderTarget(int width, int height)
	: s2::RenderTarget(width, height)
{
}

void RenderTarget::Bind()
{
	s2::RenderScissor::Instance()->Disable();

	int w = Width(),
		h = Height();
	s2::RenderContext ctx(w, h, w, h);
	// use last model view
	const s2::RenderContext* last = s2::RenderCtxStack::Instance()->Top();
	if (last) {
		ctx.SetModelView(last->GetMVOffset(), last->GetMVScale());
	}
	s2::RenderCtxStack::Instance()->Push(ctx);

	s2::RenderTarget::Bind();
}

void RenderTarget::Unbind()
{
	s2::RenderCtxStack::Instance()->Pop();
	s2::RenderScissor::Instance()->Enable();

	s2::RenderTarget::Unbind();
}

void RenderTarget::Draw(const sm::rect& src, const sm::rect& dst, int dst_w, int dst_h) const
{
	sl::ShaderMgr::Instance()->FlushShader();

	float vertices[8], texcoords[8];

	float w, h;
	if (dst_w != 0 && dst_h != 0) {
		w = dst_w;
		h = dst_h;
	} else {
		w = Width();
		h = Height();
	}

	const s2::RenderContext* last = s2::RenderCtxStack::Instance()->Top();
	int vp_x, vp_y, vp_w, vp_h;
	if (last) {
		last->GetViewport(vp_x, vp_y, vp_w, vp_h);
	}

	s2::RenderScissor::Instance()->Disable();
	s2::RenderCtxStack::Instance()->Push(s2::RenderContext(w, h, w, h));
	if (last) {
		const s2::RenderContext* curr = s2::RenderCtxStack::Instance()->Top();
		const_cast<s2::RenderContext*>(curr)->SetViewport(vp_x, vp_y, vp_w, vp_h);
	}

	float hw = w * 0.5f,
		  hh = h * 0.5f;
	vertices[0] = w * dst.xmin - hw; vertices[1] = h * dst.ymin - hh;
	vertices[2] = w * dst.xmax - hw; vertices[3] = h * dst.ymin - hh;
	vertices[4] = w * dst.xmax - hw; vertices[5] = h * dst.ymax - hh;
	vertices[6] = w * dst.xmin - hw; vertices[7] = h * dst.ymax - hh;

	texcoords[0] = src.xmin; texcoords[1] = src.ymin;
	texcoords[2] = src.xmax; texcoords[3] = src.ymin;
	texcoords[4] = src.xmax; texcoords[5] = src.ymax;
	texcoords[6] = src.xmin; texcoords[7] = src.ymax;

	sl::ShaderMgr* sl_mgr = sl::ShaderMgr::Instance();
	switch (sl_mgr->GetShaderType())
	{
	case sl::SPRITE2:
		{
			sl::Sprite2Shader* shader = static_cast<sl::Sprite2Shader*>(sl_mgr->GetShader());
			shader->SetColor(0xffffffff, 0);
			shader->SetColorMap(0x000000ff, 0x0000ff00, 0x00ff0000);
			shader->DrawQuad(vertices, texcoords, GetTexID());
		}
		break;
	case sl::FILTER:
		{
			sl::FilterShader* shader = static_cast<sl::FilterShader*>(sl_mgr->GetShader());
			shader->SetColor(0xffffffff, 0);
			shader->Draw(vertices, texcoords, GetTexID());
		}
		break;
	default:
		break;
	}

	s2::RenderCtxStack::Instance()->Pop();
	s2::RenderScissor::Instance()->Enable();
}

void RenderTarget::Clear()
{
	Bind();

	sl::ShaderMgr* mgr = sl::ShaderMgr::Instance();
	mgr->GetContext()->Clear(0);

	Unbind();
}

}<|endoftext|>


<commit_before>#include <memory>

#include <svgren/render.hpp>

// Some bad stuff defines OVERFLOW macro and there is an enum value with same name in svgdom/dom.h.
#ifdef OVERFLOW
#	undef OVERFLOW
#endif

#include <svgdom/dom.hpp>

#include "image.hpp"

#include "../context.hpp"

#include "../util/util.hpp"

using namespace morda;
using namespace morda::res;

image::image(std::shared_ptr<morda::context> c) :
		resource(std::move(c))
{}

atlas_image::atlas_image(std::shared_ptr<morda::context> c, std::shared_ptr<res::texture> tex, const rectangle& rect) :
		image(std::move(c)),
		image::texture(this->context->renderer, rect.d.abs()),
		tex(std::move(tex))
{
//	this->texCoords[3] = vector2(rect.left(), this->tex->tex().dim().y - rect.bottom()).compDivBy(this->tex->tex().dim());
//	this->texCoords[2] = vector2(rect.right(), this->tex->tex().dim().y - rect.bottom()).compDivBy(this->tex->tex().dim());
//	this->texCoords[1] = vector2(rect.right(), this->tex->tex().dim().y - rect.top()).compDivBy(this->tex->tex().dim());
//	this->texCoords[0] = vector2(rect.left(), this->tex->tex().dim().y - rect.top()).compDivBy(this->tex->tex().dim());
	//TODO:
	ASSERT(false)
}

atlas_image::atlas_image(std::shared_ptr<morda::context> c, std::shared_ptr<res::texture> tex) :
		image(std::move(c)),
		image::texture(this->context->renderer, tex->tex().dims()),
		tex(std::move(tex)),
		vao(this->context->renderer->pos_tex_quad_01_vao)
{}

std::shared_ptr<atlas_image> atlas_image::load(morda::context& ctx, const puu::forest& desc, const papki::file& fi){
	std::shared_ptr<res::texture> tex;
	rectangle rect(-1, -1);

	for(auto& p : desc){
		if(p.value == "tex"){
			tex = ctx.loader.load<res::texture>(get_property_value(p).to_string());
		}else if(p.value == "rect"){
			rect = parse_rect(p.children);
		}
	}

	if(!tex){
		throw std::runtime_error("atlas_image::load(): could not load texture");
	}

	if(rect.p.x() >= 0){
		return std::make_shared<atlas_image>(utki::make_shared_from(ctx), tex, rect);
	}else{
		return std::make_shared<atlas_image>(utki::make_shared_from(ctx), tex);
	}
}

void atlas_image::render(const matrix4& matrix, const vertex_array& vao)const{
	this->context->renderer->shader->pos_tex->render(matrix, *this->vao, this->tex->tex());
}

std::shared_ptr<const image::texture> atlas_image::get(vector2 forDim)const{
	return utki::make_shared_from(*this);
}

namespace{
class fixed_texture : public image::texture{
protected:
	std::shared_ptr<texture_2d> tex_v;

	fixed_texture(std::shared_ptr<morda::renderer> r, std::shared_ptr<texture_2d> tex) :
			image::texture(std::move(r), tex->dims()),
			tex_v(std::move(tex))
	{}

public:
	void render(const matrix4& matrix, const vertex_array& vao)const override{
		this->renderer->shader->pos_tex->render(matrix, vao, *this->tex_v);
	}
};

class res_raster_image :
		public image,
		public fixed_texture
{
public:
	res_raster_image(std::shared_ptr<morda::context> c, std::shared_ptr<texture_2d> tex) :
			image(std::move(c)),
			fixed_texture(this->context->renderer, std::move(tex))
	{}

	std::shared_ptr<const image::texture> get(vector2 forDim)const override{
		return utki::make_shared_from(*this);
	}

	vector2 dims(real dpi)const noexcept override{
		return this->tex_v->dims();
	}

	static std::shared_ptr<res_raster_image> load(morda::context& ctx, const papki::file& fi){
		return std::make_shared<res_raster_image>(utki::make_shared_from(ctx), load_texture(*ctx.renderer, fi));
	}
};

class res_svg_image : public image{
	std::unique_ptr<svgdom::svg_element> dom;
public:
	res_svg_image(std::shared_ptr<morda::context> c, decltype(dom) dom) :
			image(std::move(c)),
			dom(std::move(dom))
	{}

	vector2 dims(real dpi)const noexcept override{
		auto wh = this->dom->get_dimensions(dpi);
		using std::ceil;
		return vector2(ceil(wh[0]), ceil(wh[1]));
	}

	class svg_texture : public fixed_texture{
		std::weak_ptr<const res_svg_image> parent;
	public:
		svg_texture(std::shared_ptr<morda::renderer> r, std::shared_ptr<const res_svg_image> parent, std::shared_ptr<texture_2d> tex) :
				fixed_texture(std::move(r), std::move(tex)),
				parent(parent)
		{}

		~svg_texture()noexcept{
			if(auto p = this->parent.lock()){
				r4::vector2<unsigned> d = this->tex_v->dims().to<unsigned>();
				p->cache.erase(std::make_tuple(d.x(), d.y()));
			}
		}
	};

	std::shared_ptr<const texture> get(vector2 forDim)const override{
//		TRACE(<< "forDim = " << forDim << std::endl)
		unsigned width = unsigned(forDim.x());
//		TRACE(<< "imWidth = " << imWidth << std::endl)
		unsigned height = unsigned(forDim.y());
//		TRACE(<< "imHeight = " << imHeight << std::endl)

		{ // check if in cache
			auto i = this->cache.find(std::make_tuple(width, height));
			if(i != this->cache.end()){
				if(auto p = i->second.lock()){
					return p;
				}
			}
		}
//		TRACE(<< "not in cache" << std::endl)

		ASSERT(this->dom)
//		TRACE(<< "width = " << this->dom->width << std::endl)
//		TRACE(<< "height = " << this->dom->height << std::endl)
//		TRACE(<< "dpi = " << morda::gui::inst().units.dpi() << std::endl)
//		TRACE(<< "id = " << this->dom->id << std::endl)
		svgren::parameters svgParams;
		svgParams.dpi = this->context->units.dots_per_inch;
		svgParams.width_request = width;
		svgParams.height_request = height;
		auto svg = svgren::render(*this->dom, svgParams);
		ASSERT(svg.width != 0)
		ASSERT(svg.height != 0)
		ASSERT_INFO(svg.width * svg.height == svg.pixels.size(), "imWidth = " << svg.width << " imHeight = " << svg.height << " pixels.size() = " << svg.pixels.size())

		auto img = std::make_shared<svg_texture>(
				this->context->renderer,
				utki::make_shared_from(*this),
				this->context->renderer->factory->create_texture_2d(r4::vector2<unsigned>(svg.width, svg.height), utki::make_span(svg.pixels))
			);

		this->cache[std::make_tuple(svg.width, svg.height)] = img;

		return img;
	}

	mutable std::map<std::tuple<unsigned, unsigned>, std::weak_ptr<texture>> cache;

	static std::shared_ptr<res_svg_image> load(morda::context& ctx, const papki::file& fi){
		return std::make_shared<res_svg_image>(utki::make_shared_from(ctx), svgdom::load(fi));
	}
};
}

std::shared_ptr<image> image::load(morda::context& ctx, const puu::forest& desc, const papki::file& fi) {
	for(auto& p : desc){
		if(p.value == "file"){
			fi.set_path(get_property_value(p).to_string());
			return image::load(ctx, fi);
		}
	}

	return atlas_image::load(ctx, desc, fi);
}

std::shared_ptr<image> image::load(morda::context& ctx, const papki::file& fi) {
	if(fi.suffix().compare("svg") == 0){
		return res_svg_image::load(ctx, fi);
	}else{
		return res_raster_image::load(ctx, fi);
	}
}
<commit_msg>stuff<commit_after>#include <memory>

#include <svgren/render.hpp>

// Some bad stuff defines OVERFLOW macro and there is an enum value with same name in svgdom/dom.h.
#ifdef OVERFLOW
#	undef OVERFLOW
#endif

#include <svgdom/dom.hpp>

#include "image.hpp"

#include "../context.hpp"

#include "../util/util.hpp"

using namespace morda;
using namespace morda::res;

image::image(std::shared_ptr<morda::context> c) :
		resource(std::move(c))
{}

atlas_image::atlas_image(std::shared_ptr<morda::context> c, std::shared_ptr<res::texture> tex, const rectangle& rect) :
		image(std::move(c)),
		image::texture(this->context->renderer, rect.d.abs()),
		tex(std::move(tex))
{
//	this->texCoords[3] = vector2(rect.left(), this->tex->tex().dim().y - rect.bottom()).compDivBy(this->tex->tex().dim());
//	this->texCoords[2] = vector2(rect.right(), this->tex->tex().dim().y - rect.bottom()).compDivBy(this->tex->tex().dim());
//	this->texCoords[1] = vector2(rect.right(), this->tex->tex().dim().y - rect.top()).compDivBy(this->tex->tex().dim());
//	this->texCoords[0] = vector2(rect.left(), this->tex->tex().dim().y - rect.top()).compDivBy(this->tex->tex().dim());
	//TODO:
	ASSERT(false)
}

atlas_image::atlas_image(std::shared_ptr<morda::context> c, std::shared_ptr<res::texture> tex) :
		image(std::move(c)),
		image::texture(this->context->renderer, tex->tex().dims()),
		tex(std::move(tex)),
		vao(this->context->renderer->pos_tex_quad_01_vao)
{}

std::shared_ptr<atlas_image> atlas_image::load(morda::context& ctx, const puu::forest& desc, const papki::file& fi){
	std::shared_ptr<res::texture> tex;
	rectangle rect(-1, -1);

	for(auto& p : desc){
		if(p.value == "tex"){
			tex = ctx.loader.load<res::texture>(get_property_value(p).to_string());
		}else if(p.value == "rect"){
			rect = parse_rect(p.children);
		}
	}

	if(!tex){
		throw std::runtime_error("atlas_image::load(): could not load texture");
	}

	if(rect.p.x() >= 0){
		return std::make_shared<atlas_image>(utki::make_shared_from(ctx), tex, rect);
	}else{
		return std::make_shared<atlas_image>(utki::make_shared_from(ctx), tex);
	}
}

void atlas_image::render(const matrix4& matrix, const vertex_array& vao)const{
	this->context->renderer->shader->pos_tex->render(matrix, *this->vao, this->tex->tex());
}

std::shared_ptr<const image::texture> atlas_image::get(vector2 forDim)const{
	return utki::make_shared_from(*this);
}

namespace{
class fixed_texture : public image::texture{
protected:
	std::shared_ptr<texture_2d> tex_v;

	fixed_texture(std::shared_ptr<morda::renderer> r, std::shared_ptr<texture_2d> tex) :
			image::texture(std::move(r), tex->dims()),
			tex_v(std::move(tex))
	{}

public:
	void render(const matrix4& matrix, const vertex_array& vao)const override{
		this->renderer->shader->pos_tex->render(matrix, vao, *this->tex_v);
	}
};

class res_raster_image :
		public image,
		public fixed_texture
{
public:
	res_raster_image(std::shared_ptr<morda::context> c, std::shared_ptr<texture_2d> tex) :
			image(std::move(c)),
			fixed_texture(this->context->renderer, std::move(tex))
	{}

	std::shared_ptr<const image::texture> get(vector2 forDim)const override{
		return utki::make_shared_from(*this);
	}

	vector2 dims(real dpi)const noexcept override{
		return this->tex_v->dims();
	}

	static std::shared_ptr<res_raster_image> load(morda::context& ctx, const papki::file& fi){
		return std::make_shared<res_raster_image>(utki::make_shared_from(ctx), load_texture(*ctx.renderer, fi));
	}
};

class res_svg_image : public image{
	std::unique_ptr<svgdom::svg_element> dom;
public:
	res_svg_image(std::shared_ptr<morda::context> c, decltype(dom) dom) :
			image(std::move(c)),
			dom(std::move(dom))
	{}

	vector2 dims(real dpi)const noexcept override{
		auto wh = this->dom->get_dimensions(dpi);
		using std::ceil;
		return vector2(ceil(wh[0]), ceil(wh[1]));
	}

	class svg_texture : public fixed_texture{
		std::weak_ptr<const res_svg_image> parent;
	public:
		svg_texture(std::shared_ptr<morda::renderer> r, std::shared_ptr<const res_svg_image> parent, std::shared_ptr<texture_2d> tex) :
				fixed_texture(std::move(r), std::move(tex)),
				parent(parent)
		{}

		~svg_texture()noexcept{
			if(auto p = this->parent.lock()){
				r4::vector2<unsigned> d = this->tex_v->dims().to<unsigned>();
				p->cache.erase(std::make_tuple(d.x(), d.y()));
			}
		}
	};

	std::shared_ptr<const texture> get(vector2 forDim)const override{
//		TRACE(<< "forDim = " << forDim << std::endl)
		unsigned width = unsigned(forDim.x());
//		TRACE(<< "imWidth = " << imWidth << std::endl)
		unsigned height = unsigned(forDim.y());
//		TRACE(<< "imHeight = " << imHeight << std::endl)

		{ // check if in cache
			auto i = this->cache.find(std::make_tuple(width, height));
			if(i != this->cache.end()){
				if(auto p = i->second.lock()){
					return p;
				}
			}
		}
//		TRACE(<< "not in cache" << std::endl)

		ASSERT(this->dom)
//		TRACE(<< "width = " << this->dom->width << std::endl)
//		TRACE(<< "height = " << this->dom->height << std::endl)
//		TRACE(<< "dpi = " << morda::gui::inst().units.dpi() << std::endl)
//		TRACE(<< "id = " << this->dom->id << std::endl)
		svgren::parameters svg_params;
		svg_params.dpi = unsigned(this->context->units.dots_per_inch);
		svg_params.width_request = width;
		svg_params.height_request = height;
		auto svg = svgren::render(*this->dom, svg_params);
		ASSERT(svg.width != 0)
		ASSERT(svg.height != 0)
		ASSERT_INFO(svg.width * svg.height == svg.pixels.size(), "imWidth = " << svg.width << " imHeight = " << svg.height << " pixels.size() = " << svg.pixels.size())

		auto img = std::make_shared<svg_texture>(
				this->context->renderer,
				utki::make_shared_from(*this),
				this->context->renderer->factory->create_texture_2d(r4::vector2<unsigned>(svg.width, svg.height), utki::make_span(svg.pixels))
			);

		this->cache[std::make_tuple(svg.width, svg.height)] = img;

		return img;
	}

	mutable std::map<std::tuple<unsigned, unsigned>, std::weak_ptr<texture>> cache;

	static std::shared_ptr<res_svg_image> load(morda::context& ctx, const papki::file& fi){
		return std::make_shared<res_svg_image>(utki::make_shared_from(ctx), svgdom::load(fi));
	}
};
}

std::shared_ptr<image> image::load(morda::context& ctx, const puu::forest& desc, const papki::file& fi) {
	for(auto& p : desc){
		if(p.value == "file"){
			fi.set_path(get_property_value(p).to_string());
			return image::load(ctx, fi);
		}
	}

	return atlas_image::load(ctx, desc, fi);
}

std::shared_ptr<image> image::load(morda::context& ctx, const papki::file& fi) {
	if(fi.suffix().compare("svg") == 0){
		return res_svg_image::load(ctx, fi);
	}else{
		return res_raster_image::load(ctx, fi);
	}
}
<|endoftext|>


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

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

// INCLUDE ---------------------------------------------------------------

#include <svx/svdmark.hxx>
#include <svx/svdview.hxx>
#include <svx/galbrws.hxx>
#include <svx/gallery.hxx>
#include <svx/hlnkitem.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/request.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/dispatch.hxx>
#include <svtools/whiter.hxx>
#include <avmedia/mediaplayer.hxx>

#include "tabvwsh.hxx"
#include "viewdata.hxx"
#include "tabview.hxx"
#include "drwlayer.hxx"
#include "userdat.hxx"
#include "docsh.hxx"

// forwards -> galwrap.cxx (wg. CLOOKs)

USHORT  GallerySGA_FORMAT_GRAPHIC();
Graphic GalleryGetGraphic       ();
BOOL    GalleryIsLinkage        ();
String  GalleryGetFullPath      ();
String  GalleryGetFilterName    ();

// forwards -> imapwrap.cxx (wg. CLOOKs)

class SvxIMapDlg;

USHORT          ScIMapChildWindowId();
SvxIMapDlg*     ScGetIMapDlg();
const void*     ScIMapDlgGetObj( SvxIMapDlg* pDlg );
const ImageMap& ScIMapDlgGetMap( SvxIMapDlg* pDlg );

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

void ScTabViewShell::ExecChildWin(SfxRequest& rReq)
{
    USHORT nSlot = rReq.GetSlot();
    switch(nSlot)
    {
        case SID_GALLERY:
        {
            SfxViewFrame* pThisFrame = GetViewFrame();
            pThisFrame->ToggleChildWindow( GalleryChildWindow::GetChildWindowId() );
            pThisFrame->GetBindings().Invalidate( SID_GALLERY );
            rReq.Ignore();
        }
        break;

        case SID_AVMEDIA_PLAYER:
        {
            SfxViewFrame* pThisFrame = GetViewFrame();
            pThisFrame->ToggleChildWindow( ::avmedia::MediaPlayer::GetChildWindowId() );
            pThisFrame->GetBindings().Invalidate( SID_AVMEDIA_PLAYER );
            rReq.Ignore();
        }
        break;
    }
}

void ScTabViewShell::GetChildWinState( SfxItemSet& rSet )
{
    if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_GALLERY ) )
    {
        USHORT nId = GalleryChildWindow::GetChildWindowId();
        rSet.Put( SfxBoolItem( SID_GALLERY, GetViewFrame()->HasChildWindow( nId ) ) );
    }
    else if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_AVMEDIA_PLAYER ) )
    {
        USHORT nId = ::avmedia::MediaPlayer::GetChildWindowId();
        rSet.Put( SfxBoolItem( SID_AVMEDIA_PLAYER, GetViewFrame()->HasChildWindow( nId ) ) );
    }
}

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

void ScTabViewShell::ExecGallery( SfxRequest& rReq )
{
    const SfxItemSet* pArgs = rReq.GetArgs();

    if ( pArgs )
    {
        const SfxPoolItem* pItem = NULL;
        SfxItemState eState = pArgs->GetItemState(SID_GALLERY_FORMATS, TRUE, &pItem);
        if ( eState == SFX_ITEM_SET )
        {
            UINT32 nFormats = ((const SfxUInt32Item*)pItem)->GetValue();

            /******************************************************************
            * Graphik einfuegen
            ******************************************************************/
            if ( nFormats & GallerySGA_FORMAT_GRAPHIC() )
            {
                MakeDrawLayer();

                Graphic aGraphic = GalleryGetGraphic();
                Point   aPos     = GetInsertPos();

                String aPath, aFilter;
                if ( GalleryIsLinkage() )           // als Link einfuegen?
                {
                    aPath = GalleryGetFullPath();
                    aFilter = GalleryGetFilterName();
                }

                PasteGraphic( aPos, aGraphic, aPath, aFilter );
            }
            else if ( nFormats & SGA_FORMAT_SOUND )
            {
                //  #98115# for sounds (linked or not), insert a hyperlink button,
                //  like in Impress and Writer

                GalleryExplorer* pGal = SVX_GALLERY();
                if ( pGal )
                {
                    const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, pGal->GetURL().GetMainURL( INetURLObject::NO_DECODE ) );
                       GetViewFrame()->GetDispatcher()->Execute( SID_INSERT_AVMEDIA, SFX_CALLMODE_SYNCHRON, &aMediaURLItem, 0L );
                }
            }
        }
    }
}

void ScTabViewShell::GetGalleryState( SfxItemSet& /* rSet */ )
{
}

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

ScInputHandler* ScTabViewShell::GetInputHandler() const
{
    return pInputHandler;
}

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

String __EXPORT ScTabViewShell::GetDescription() const
{
    return String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(" ** Test ** "));
}

void ScTabViewShell::ExecImageMap( SfxRequest& rReq )
{
    USHORT nSlot = rReq.GetSlot();
    switch(nSlot)
    {
        case SID_IMAP:
        {
            SfxViewFrame* pThisFrame = GetViewFrame();
            USHORT nId = ScIMapChildWindowId();
            pThisFrame->ToggleChildWindow( nId );
            GetViewFrame()->GetBindings().Invalidate( SID_IMAP );

            if ( pThisFrame->HasChildWindow( nId ) )
            {
                SvxIMapDlg* pDlg = ScGetIMapDlg();
                if ( pDlg )
                {
                    SdrView* pDrView = GetSdrView();
                    if ( pDrView )
                    {
                        const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
                        if ( rMarkList.GetMarkCount() == 1 )
                            UpdateIMap( rMarkList.GetMark( 0 )->GetMarkedSdrObj() );
                    }
                }
            }

            rReq.Ignore();
        }
        break;

        case SID_IMAP_EXEC:
        {
            SdrView* pDrView = GetSdrView();
            SdrMark* pMark = pDrView ? pDrView->GetMarkedObjectList().GetMark(0) : 0;

            if ( pMark )
            {
                SdrObject*  pSdrObj = pMark->GetMarkedSdrObj();
                SvxIMapDlg* pDlg = ScGetIMapDlg();

                if ( ScIMapDlgGetObj(pDlg) == (void*) pSdrObj )
                {
                    const ImageMap& rImageMap = ScIMapDlgGetMap(pDlg);
                    ScIMapInfo*     pIMapInfo = ScDrawLayer::GetIMapInfo( pSdrObj );

                    if ( !pIMapInfo )
                        pSdrObj->InsertUserData( new ScIMapInfo( rImageMap ) );
                    else
                        pIMapInfo->SetImageMap( rImageMap );

                    GetViewData()->GetDocShell()->SetDrawModified();
                }
            }
        }
        break;
    }
}

void ScTabViewShell::GetImageMapState( SfxItemSet& rSet )
{
    SfxWhichIter aIter(rSet);
    USHORT nWhich = aIter.FirstWhich();
    while ( nWhich )
    {
        switch ( nWhich )
        {
            case SID_IMAP:
                {
                    //  Disabled wird nicht mehr...

                    BOOL bThere = FALSE;
                    SfxViewFrame* pThisFrame = GetViewFrame();
                    USHORT nId = ScIMapChildWindowId();
                    if ( pThisFrame->KnowsChildWindow(nId) )
                        if ( pThisFrame->HasChildWindow(nId) )
                            bThere = TRUE;

                    ObjectSelectionType eType=GetCurObjectSelectionType();
                    BOOL bEnable=(eType==OST_OleObject) ||(eType==OST_Graphic);
                    if(!bThere && !bEnable)
                    {
                       rSet.DisableItem( nWhich );
                    }
                    else
                    {
                        rSet.Put( SfxBoolItem( nWhich, bThere ) );
                    }
                }
                break;

            case SID_IMAP_EXEC:
                {
                    BOOL bDisable = TRUE;

                    SdrView* pDrView = GetSdrView();
                    if ( pDrView )
                    {
                        const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
                        if ( rMarkList.GetMarkCount() == 1 )
                            if ( ScIMapDlgGetObj(ScGetIMapDlg()) ==
                                        (void*) rMarkList.GetMark(0)->GetMarkedSdrObj() )
                                bDisable = FALSE;
                    }

                    rSet.Put( SfxBoolItem( SID_IMAP_EXEC, bDisable ) );
                }
                break;
        }

        nWhich = aIter.NextWhich();
    }
}

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

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

// INCLUDE ---------------------------------------------------------------

#include <svx/svdmark.hxx>
#include <svx/svdview.hxx>
#include <svx/galbrws.hxx>
#include <svx/gallery.hxx>
#include <svx/hlnkitem.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/request.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/dispatch.hxx>
#include <svtools/whiter.hxx>
#include <avmedia/mediaplayer.hxx>

#include "tabvwsh.hxx"
#include "viewdata.hxx"
#include "tabview.hxx"
#include "drwlayer.hxx"
#include "userdat.hxx"
#include "docsh.hxx"

// forwards -> galwrap.cxx (wg. CLOOKs)

USHORT  GallerySGA_FORMAT_GRAPHIC();
Graphic GalleryGetGraphic       ();
BOOL    GalleryIsLinkage        ();
String  GalleryGetFullPath      ();
String  GalleryGetFilterName    ();

// forwards -> imapwrap.cxx (wg. CLOOKs)

class SvxIMapDlg;

USHORT          ScIMapChildWindowId();
SvxIMapDlg*     ScGetIMapDlg();
const void*     ScIMapDlgGetObj( SvxIMapDlg* pDlg );
const ImageMap& ScIMapDlgGetMap( SvxIMapDlg* pDlg );

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

void ScTabViewShell::ExecChildWin(SfxRequest& rReq)
{
    USHORT nSlot = rReq.GetSlot();
    switch(nSlot)
    {
        case SID_GALLERY:
        {
            SfxViewFrame* pThisFrame = GetViewFrame();
            pThisFrame->ToggleChildWindow( GalleryChildWindow::GetChildWindowId() );
            pThisFrame->GetBindings().Invalidate( SID_GALLERY );
            rReq.Ignore();
        }
        break;

        case SID_AVMEDIA_PLAYER:
        {
            SfxViewFrame* pThisFrame = GetViewFrame();
            pThisFrame->ToggleChildWindow( ::avmedia::MediaPlayer::GetChildWindowId() );
            pThisFrame->GetBindings().Invalidate( SID_AVMEDIA_PLAYER );
            rReq.Ignore();
        }
        break;
    }
}

void ScTabViewShell::GetChildWinState( SfxItemSet& rSet )
{
    if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_GALLERY ) )
    {
        USHORT nId = GalleryChildWindow::GetChildWindowId();
        rSet.Put( SfxBoolItem( SID_GALLERY, GetViewFrame()->HasChildWindow( nId ) ) );
    }
    else if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_AVMEDIA_PLAYER ) )
    {
        USHORT nId = ::avmedia::MediaPlayer::GetChildWindowId();
        rSet.Put( SfxBoolItem( SID_AVMEDIA_PLAYER, GetViewFrame()->HasChildWindow( nId ) ) );
    }
}

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

void ScTabViewShell::ExecGallery( SfxRequest& rReq )
{
    const SfxItemSet* pArgs = rReq.GetArgs();

    if ( pArgs )
    {
        const SfxPoolItem* pItem = NULL;
        SfxItemState eState = pArgs->GetItemState(SID_GALLERY_FORMATS, TRUE, &pItem);
        if ( eState == SFX_ITEM_SET )
        {
            UINT32 nFormats = ((const SfxUInt32Item*)pItem)->GetValue();

            /******************************************************************
            * Graphik einfuegen
            ******************************************************************/
            if ( nFormats & GallerySGA_FORMAT_GRAPHIC() )
            {
                MakeDrawLayer();

                Graphic aGraphic = GalleryGetGraphic();
                Point   aPos     = GetInsertPos();

                String aPath, aFilter;
                if ( GalleryIsLinkage() )           // als Link einfuegen?
                {
                    aPath = GalleryGetFullPath();
                    aFilter = GalleryGetFilterName();
                }

                PasteGraphic( aPos, aGraphic, aPath, aFilter );
            }
            else if ( nFormats & SGA_FORMAT_SOUND )
            {
                //  #98115# for sounds (linked or not), insert a hyperlink button,
                //  like in Impress and Writer

                GalleryExplorer* pGal = SVX_GALLERY();
                if ( pGal )
                {
                    const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, pGal->GetURL().GetMainURL( INetURLObject::NO_DECODE ) );
                       GetViewFrame()->GetDispatcher()->Execute( SID_INSERT_AVMEDIA, SFX_CALLMODE_SYNCHRON, &aMediaURLItem, 0L );
                }
            }
        }
    }
}

void ScTabViewShell::GetGalleryState( SfxItemSet& /* rSet */ )
{
}

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

ScInputHandler* ScTabViewShell::GetInputHandler() const
{
    return pInputHandler;
}

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

String __EXPORT ScTabViewShell::GetDescription() const
{
    return String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(" ** Test ** "));
}

void ScTabViewShell::ExecImageMap( SfxRequest& rReq )
{
    USHORT nSlot = rReq.GetSlot();
    switch(nSlot)
    {
        case SID_IMAP:
        {
            SfxViewFrame* pThisFrame = GetViewFrame();
            USHORT nId = ScIMapChildWindowId();
            pThisFrame->ToggleChildWindow( nId );
            GetViewFrame()->GetBindings().Invalidate( SID_IMAP );

            if ( pThisFrame->HasChildWindow( nId ) )
            {
                SvxIMapDlg* pDlg = ScGetIMapDlg();
                if ( pDlg )
                {
                    SdrView* pDrView = GetSdrView();
                    if ( pDrView )
                    {
                        const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
                        if ( rMarkList.GetMarkCount() == 1 )
                            UpdateIMap( rMarkList.GetMark( 0 )->GetMarkedSdrObj() );
                    }
                }
            }

            rReq.Ignore();
        }
        break;

        case SID_IMAP_EXEC:
        {
            SdrView* pDrView = GetSdrView();
            SdrMark* pMark = pDrView ? pDrView->GetMarkedObjectList().GetMark(0) : 0;

            if ( pMark )
            {
                SdrObject*  pSdrObj = pMark->GetMarkedSdrObj();
                SvxIMapDlg* pDlg = ScGetIMapDlg();

                if ( ScIMapDlgGetObj(pDlg) == (void*) pSdrObj )
                {
                    const ImageMap& rImageMap = ScIMapDlgGetMap(pDlg);
                    ScIMapInfo*     pIMapInfo = ScDrawLayer::GetIMapInfo( pSdrObj );

                    if ( !pIMapInfo )
                        pSdrObj->InsertUserData( new ScIMapInfo( rImageMap ) );
                    else
                        pIMapInfo->SetImageMap( rImageMap );

                    GetViewData()->GetDocShell()->SetDrawModified();
                }
            }
        }
        break;
    }
}

void ScTabViewShell::GetImageMapState( SfxItemSet& rSet )
{
    SfxWhichIter aIter(rSet);
    USHORT nWhich = aIter.FirstWhich();
    while ( nWhich )
    {
        switch ( nWhich )
        {
            case SID_IMAP:
                {
                    //  Disabled wird nicht mehr...

                    BOOL bThere = FALSE;
                    SfxViewFrame* pThisFrame = GetViewFrame();
                    USHORT nId = ScIMapChildWindowId();
                    if ( pThisFrame->KnowsChildWindow(nId) )
                        if ( pThisFrame->HasChildWindow(nId) )
                            bThere = TRUE;

                    ObjectSelectionType eType=GetCurObjectSelectionType();
                    BOOL bEnable=(eType==OST_OleObject) ||(eType==OST_Graphic);
                    if(!bThere && !bEnable)
                    {
                       rSet.DisableItem( nWhich );
                    }
                    else
                    {
                        rSet.Put( SfxBoolItem( nWhich, bThere ) );
                    }
                }
                break;

            case SID_IMAP_EXEC:
                {
                    BOOL bDisable = TRUE;

                    SdrView* pDrView = GetSdrView();
                    if ( pDrView )
                    {
                        const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
                        if ( rMarkList.GetMarkCount() == 1 )
                            if ( ScIMapDlgGetObj(ScGetIMapDlg()) ==
                                        (void*) rMarkList.GetMark(0)->GetMarkedSdrObj() )
                                bDisable = FALSE;
                    }

                    rSet.Put( SfxBoolItem( SID_IMAP_EXEC, bDisable ) );
                }
                break;
        }

        nWhich = aIter.NextWhich();
    }
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

#include <svx/svdundo.hxx>
#include <svx/svdocapt.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/sound.hxx>
#include "svl/zforlist.hxx"

#include "viewfunc.hxx"
#include "detfunc.hxx"
#include "detdata.hxx"
#include "viewdata.hxx"
#include "drwlayer.hxx"
#include "docsh.hxx"
#include "undocell.hxx"
#include "futext.hxx"
#include "docfunc.hxx"
#include "globstr.hrc"
#include "sc.hrc"
#include "fusel.hxx"
#include "reftokenhelper.hxx"
#include "externalrefmgr.hxx"
#include "cell.hxx"

#include <vector>

using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::std::vector;

#define D_TIMEFACTOR              86400.0

//==================================================================

void ScViewFunc::DetectiveAddPred()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveAddPred( GetViewData()->GetCurPos() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();    //! use broadcast in DocFunc instead?
}

void ScViewFunc::DetectiveDelPred()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveDelPred( GetViewData()->GetCurPos() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveAddSucc()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveAddSucc( GetViewData()->GetCurPos() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveDelSucc()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveDelSucc( GetViewData()->GetCurPos() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveAddError()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveAddError( GetViewData()->GetCurPos() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveDelAll()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveDelAll( GetViewData()->GetTabNo() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveMarkInvalid()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveMarkInvalid( GetViewData()->GetTabNo() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveRefresh()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().DetectiveRefresh();
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

static void lcl_jumpToRange(const ScRange& rRange, ScViewData* pView, ScDocument* pDoc)
{
    String aAddrText;
    rRange.Format(aAddrText, SCR_ABS_3D, pDoc);
    SfxStringItem aPosItem(SID_CURRENTCELL, aAddrText);
    SfxBoolItem aUnmarkItem(FN_PARAM_1, TRUE);        // remove existing selection
    pView->GetDispatcher().Execute(
        SID_CURRENTCELL, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD,
        &aPosItem, &aUnmarkItem, 0L);
}

void ScViewFunc::MarkAndJumpToRanges(const ScRangeList& rRanges)
{
    ScViewData* pView = GetViewData();
    ScDocShell* pDocSh = pView->GetDocShell();

    ScRangeList aRanges(rRanges);
    ScRange* p = aRanges.front();
    ScRangeList aRangesToMark;
    ScAddress aCurPos = pView->GetCurPos();
    size_t ListSize = aRanges.size();
    for ( size_t i = 0; i < ListSize; ++i )
    {
        p = aRanges[i];
        // Collect only those ranges that are on the same sheet as the current
        // cursor.
        if (p->aStart.Tab() == aCurPos.Tab())
            aRangesToMark.Append(*p);
    }

    if (aRangesToMark.empty())
        return;

    // Jump to the first range of all precedent ranges.
    p = aRangesToMark.front();
    lcl_jumpToRange(*p, pView, pDocSh->GetDocument());

    ListSize = aRangesToMark.size();
    for ( size_t i = 0; i < ListSize; ++i )
    {
        p = aRangesToMark[i];
        MarkRange(*p, false, true);
    }
}

void ScViewFunc::DetectiveMarkPred()
{
    ScViewData* pView = GetViewData();
    ScDocShell* pDocSh = pView->GetDocShell();
    ScDocument* pDoc = pDocSh->GetDocument();
    ScMarkData& rMarkData = pView->GetMarkData();
    ScAddress aCurPos = pView->GetCurPos();
    ScRangeList aRanges;
    if (rMarkData.IsMarked() || rMarkData.IsMultiMarked())
        rMarkData.FillRangeListWithMarks(&aRanges, false);
    else
        aRanges.Append(aCurPos);

    vector<ScSharedTokenRef> aRefTokens;
    pDocSh->GetDocFunc().DetectiveCollectAllPreds(aRanges, aRefTokens);

    if (aRefTokens.empty())
        // No precedents found.  Nothing to do.
        return;

    ScSharedTokenRef p = aRefTokens.front();
    if (ScRefTokenHelper::isExternalRef(p))
    {
        // This is external.  Open the external document if available, and
        // jump to the destination.

        sal_uInt16 nFileId = p->GetIndex();
        ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
        const String* pPath = pRefMgr->getExternalFileName(nFileId);

        ScRange aRange;
        if (pPath && ScRefTokenHelper::getRangeFromToken(aRange, p, true))
        {
            const String& rTabName = p->GetString();
            OUStringBuffer aBuf;
            aBuf.append(*pPath);
            aBuf.append(sal_Unicode('#'));
            aBuf.append(rTabName);
            aBuf.append(sal_Unicode('.'));

            String aRangeStr;
            aRange.Format(aRangeStr, SCA_VALID);
            aBuf.append(aRangeStr);

            ScGlobal::OpenURL(aBuf.makeStringAndClear(), String());
        }
        return;
    }
    else
    {
        ScRange aRange;
        ScRefTokenHelper::getRangeFromToken(aRange, p, false);
        if (aRange.aStart.Tab() != aCurPos.Tab())
        {
            // The first precedent range is on a different sheet.  Jump to it
            // immediately and forget the rest.
            lcl_jumpToRange(aRange, pView, pDoc);
            return;
        }
    }

    ScRangeList aDestRanges;
    ScRefTokenHelper::getRangeListFromTokens(aDestRanges, aRefTokens);
    MarkAndJumpToRanges(aDestRanges);
}

void ScViewFunc::DetectiveMarkSucc()
{
    ScViewData* pView = GetViewData();
    ScDocShell* pDocSh = pView->GetDocShell();
    ScMarkData& rMarkData = pView->GetMarkData();
    ScAddress aCurPos = pView->GetCurPos();
    ScRangeList aRanges;
    if (rMarkData.IsMarked() || rMarkData.IsMultiMarked())
        rMarkData.FillRangeListWithMarks(&aRanges, false);
    else
        aRanges.Append(aCurPos);

    vector<ScSharedTokenRef> aRefTokens;
    pDocSh->GetDocFunc().DetectiveCollectAllSuccs(aRanges, aRefTokens);

    if (aRefTokens.empty())
        // No dependants found.  Nothing to do.
        return;

    ScRangeList aDestRanges;
    ScRefTokenHelper::getRangeListFromTokens(aDestRanges, aRefTokens);
    MarkAndJumpToRanges(aDestRanges);
}

void ScViewFunc::InsertCurrentTime(short nCellFmt, const OUString& rUndoStr)
{
    ScViewData* pViewData = GetViewData();
    ScAddress aCurPos = pViewData->GetCurPos();
    ScDocShell* pDocSh = pViewData->GetDocShell();
    ScDocument* pDoc = pDocSh->GetDocument();
    SfxUndoManager* pUndoMgr = pDocSh->GetUndoManager();
    SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
    Date aActDate;
    double fDate = aActDate - *pFormatter->GetNullDate();
    Time aActTime;
    double fTime =
        aActTime.Get100Sec() / 100.0 + aActTime.GetSec() +
        (aActTime.GetMin() * 60.0) + (aActTime.GetHour() * 3600.0);
    fTime /= D_TIMEFACTOR;
    pUndoMgr->EnterListAction(rUndoStr, rUndoStr);
    pDocSh->GetDocFunc().PutCell(aCurPos, new ScValueCell(fDate+fTime), false);
    SetNumberFormat(nCellFmt);
    pUndoMgr->LeaveListAction();
}

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

void ScViewFunc::ShowNote( bool bShow )
{
    if( bShow )
        HideNoteMarker();
    const ScViewData& rViewData = *GetViewData();
    ScAddress aPos( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() );
    // show note moved to ScDocFunc, to be able to use it in notesuno.cxx
    rViewData.GetDocShell()->GetDocFunc().ShowNote( aPos, bShow );
}

void ScViewFunc::EditNote()
{
    //  zum Editieren einblenden und aktivieren

    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    ScDocument* pDoc = pDocSh->GetDocument();
    SCCOL nCol = GetViewData()->GetCurX();
    SCROW nRow = GetViewData()->GetCurY();
    SCTAB nTab = GetViewData()->GetTabNo();
    ScAddress aPos( nCol, nRow, nTab );

    // start drawing undo to catch undo action for insertion of the caption object
    pDocSh->MakeDrawLayer();
    ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
    pDrawLayer->BeginCalcUndo();
    // generated undo action is processed in FuText::StopEditMode

    // get existing note or create a new note (including caption drawing object)
    if( ScPostIt* pNote = pDoc->GetOrCreateNote( aPos ) )
    {
        // hide temporary note caption
        HideNoteMarker();
        // show caption object without changing internal visibility state
        pNote->ShowCaptionTemp( aPos );

        /*  Drawing object has been created in ScDocument::GetOrCreateNote() or
            in ScPostIt::ShowCaptionTemp(), so ScPostIt::GetCaption() should
            return a caption object. */
        if( SdrCaptionObj* pCaption = pNote->GetCaption() )
        {
            // #i33764# enable the resize handles before starting edit mode
            if( FuPoor* pDraw = GetDrawFuncPtr() )
                static_cast< FuSelection* >( pDraw )->ActivateNoteHandles( pCaption );

            // activate object (as in FuSelection::TestComment)
            GetViewData()->GetDispatcher().Execute( SID_DRAW_NOTEEDIT, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD );
            // jetzt den erzeugten FuText holen und in den EditModus setzen
            FuPoor* pPoor = GetDrawFuncPtr();
            if ( pPoor && (pPoor->GetSlotID() == SID_DRAW_NOTEEDIT) )    // hat keine RTTI
            {
                ScrollToObject( pCaption );         // Objekt komplett sichtbar machen
                static_cast< FuText* >( pPoor )->SetInEditMode( pCaption );
            }
        }
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>When inserting current date/time, set cell format only when necessary.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

#include <svx/svdundo.hxx>
#include <svx/svdocapt.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/sound.hxx>
#include "svl/zforlist.hxx"
#include "svl/zformat.hxx"

#include "viewfunc.hxx"
#include "detfunc.hxx"
#include "detdata.hxx"
#include "viewdata.hxx"
#include "drwlayer.hxx"
#include "docsh.hxx"
#include "undocell.hxx"
#include "futext.hxx"
#include "docfunc.hxx"
#include "globstr.hrc"
#include "sc.hrc"
#include "fusel.hxx"
#include "reftokenhelper.hxx"
#include "externalrefmgr.hxx"
#include "cell.hxx"

#include <vector>

using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::std::vector;

#define D_TIMEFACTOR              86400.0

//==================================================================

void ScViewFunc::DetectiveAddPred()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveAddPred( GetViewData()->GetCurPos() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();    //! use broadcast in DocFunc instead?
}

void ScViewFunc::DetectiveDelPred()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveDelPred( GetViewData()->GetCurPos() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveAddSucc()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveAddSucc( GetViewData()->GetCurPos() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveDelSucc()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveDelSucc( GetViewData()->GetCurPos() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveAddError()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveAddError( GetViewData()->GetCurPos() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveDelAll()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveDelAll( GetViewData()->GetTabNo() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveMarkInvalid()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().
                    DetectiveMarkInvalid( GetViewData()->GetTabNo() );
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

void ScViewFunc::DetectiveRefresh()
{
    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    BOOL bDone = pDocSh->GetDocFunc().DetectiveRefresh();
    if (!bDone)
        Sound::Beep();

    RecalcPPT();
}

static void lcl_jumpToRange(const ScRange& rRange, ScViewData* pView, ScDocument* pDoc)
{
    String aAddrText;
    rRange.Format(aAddrText, SCR_ABS_3D, pDoc);
    SfxStringItem aPosItem(SID_CURRENTCELL, aAddrText);
    SfxBoolItem aUnmarkItem(FN_PARAM_1, TRUE);        // remove existing selection
    pView->GetDispatcher().Execute(
        SID_CURRENTCELL, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD,
        &aPosItem, &aUnmarkItem, 0L);
}

void ScViewFunc::MarkAndJumpToRanges(const ScRangeList& rRanges)
{
    ScViewData* pView = GetViewData();
    ScDocShell* pDocSh = pView->GetDocShell();

    ScRangeList aRanges(rRanges);
    ScRange* p = aRanges.front();
    ScRangeList aRangesToMark;
    ScAddress aCurPos = pView->GetCurPos();
    size_t ListSize = aRanges.size();
    for ( size_t i = 0; i < ListSize; ++i )
    {
        p = aRanges[i];
        // Collect only those ranges that are on the same sheet as the current
        // cursor.
        if (p->aStart.Tab() == aCurPos.Tab())
            aRangesToMark.Append(*p);
    }

    if (aRangesToMark.empty())
        return;

    // Jump to the first range of all precedent ranges.
    p = aRangesToMark.front();
    lcl_jumpToRange(*p, pView, pDocSh->GetDocument());

    ListSize = aRangesToMark.size();
    for ( size_t i = 0; i < ListSize; ++i )
    {
        p = aRangesToMark[i];
        MarkRange(*p, false, true);
    }
}

void ScViewFunc::DetectiveMarkPred()
{
    ScViewData* pView = GetViewData();
    ScDocShell* pDocSh = pView->GetDocShell();
    ScDocument* pDoc = pDocSh->GetDocument();
    ScMarkData& rMarkData = pView->GetMarkData();
    ScAddress aCurPos = pView->GetCurPos();
    ScRangeList aRanges;
    if (rMarkData.IsMarked() || rMarkData.IsMultiMarked())
        rMarkData.FillRangeListWithMarks(&aRanges, false);
    else
        aRanges.Append(aCurPos);

    vector<ScSharedTokenRef> aRefTokens;
    pDocSh->GetDocFunc().DetectiveCollectAllPreds(aRanges, aRefTokens);

    if (aRefTokens.empty())
        // No precedents found.  Nothing to do.
        return;

    ScSharedTokenRef p = aRefTokens.front();
    if (ScRefTokenHelper::isExternalRef(p))
    {
        // This is external.  Open the external document if available, and
        // jump to the destination.

        sal_uInt16 nFileId = p->GetIndex();
        ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
        const String* pPath = pRefMgr->getExternalFileName(nFileId);

        ScRange aRange;
        if (pPath && ScRefTokenHelper::getRangeFromToken(aRange, p, true))
        {
            const String& rTabName = p->GetString();
            OUStringBuffer aBuf;
            aBuf.append(*pPath);
            aBuf.append(sal_Unicode('#'));
            aBuf.append(rTabName);
            aBuf.append(sal_Unicode('.'));

            String aRangeStr;
            aRange.Format(aRangeStr, SCA_VALID);
            aBuf.append(aRangeStr);

            ScGlobal::OpenURL(aBuf.makeStringAndClear(), String());
        }
        return;
    }
    else
    {
        ScRange aRange;
        ScRefTokenHelper::getRangeFromToken(aRange, p, false);
        if (aRange.aStart.Tab() != aCurPos.Tab())
        {
            // The first precedent range is on a different sheet.  Jump to it
            // immediately and forget the rest.
            lcl_jumpToRange(aRange, pView, pDoc);
            return;
        }
    }

    ScRangeList aDestRanges;
    ScRefTokenHelper::getRangeListFromTokens(aDestRanges, aRefTokens);
    MarkAndJumpToRanges(aDestRanges);
}

void ScViewFunc::DetectiveMarkSucc()
{
    ScViewData* pView = GetViewData();
    ScDocShell* pDocSh = pView->GetDocShell();
    ScMarkData& rMarkData = pView->GetMarkData();
    ScAddress aCurPos = pView->GetCurPos();
    ScRangeList aRanges;
    if (rMarkData.IsMarked() || rMarkData.IsMultiMarked())
        rMarkData.FillRangeListWithMarks(&aRanges, false);
    else
        aRanges.Append(aCurPos);

    vector<ScSharedTokenRef> aRefTokens;
    pDocSh->GetDocFunc().DetectiveCollectAllSuccs(aRanges, aRefTokens);

    if (aRefTokens.empty())
        // No dependants found.  Nothing to do.
        return;

    ScRangeList aDestRanges;
    ScRefTokenHelper::getRangeListFromTokens(aDestRanges, aRefTokens);
    MarkAndJumpToRanges(aDestRanges);
}

void ScViewFunc::InsertCurrentTime(short nCellFmt, const OUString& rUndoStr)
{
    ScViewData* pViewData = GetViewData();
    ScAddress aCurPos = pViewData->GetCurPos();
    ScDocShell* pDocSh = pViewData->GetDocShell();
    ScDocument* pDoc = pDocSh->GetDocument();
    SfxUndoManager* pUndoMgr = pDocSh->GetUndoManager();
    SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
    Date aActDate;
    double fDate = aActDate - *pFormatter->GetNullDate();
    Time aActTime;
    double fTime =
        aActTime.Get100Sec() / 100.0 + aActTime.GetSec() +
        (aActTime.GetMin() * 60.0) + (aActTime.GetHour() * 3600.0);
    fTime /= D_TIMEFACTOR;
    pUndoMgr->EnterListAction(rUndoStr, rUndoStr);
    pDocSh->GetDocFunc().PutCell(aCurPos, new ScValueCell(fDate+fTime), false);

    // Set the new cell format only when it differs from the current cell
    // format type.
    sal_uInt32 nCurNumFormat = pDoc->GetNumberFormat(aCurPos);
    const SvNumberformat* pEntry = pFormatter->GetEntry(nCurNumFormat);
    if (!pEntry || !(pEntry->GetType() & nCellFmt))
        SetNumberFormat(nCellFmt);
    pUndoMgr->LeaveListAction();
}

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

void ScViewFunc::ShowNote( bool bShow )
{
    if( bShow )
        HideNoteMarker();
    const ScViewData& rViewData = *GetViewData();
    ScAddress aPos( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() );
    // show note moved to ScDocFunc, to be able to use it in notesuno.cxx
    rViewData.GetDocShell()->GetDocFunc().ShowNote( aPos, bShow );
}

void ScViewFunc::EditNote()
{
    //  zum Editieren einblenden und aktivieren

    ScDocShell* pDocSh = GetViewData()->GetDocShell();
    ScDocument* pDoc = pDocSh->GetDocument();
    SCCOL nCol = GetViewData()->GetCurX();
    SCROW nRow = GetViewData()->GetCurY();
    SCTAB nTab = GetViewData()->GetTabNo();
    ScAddress aPos( nCol, nRow, nTab );

    // start drawing undo to catch undo action for insertion of the caption object
    pDocSh->MakeDrawLayer();
    ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
    pDrawLayer->BeginCalcUndo();
    // generated undo action is processed in FuText::StopEditMode

    // get existing note or create a new note (including caption drawing object)
    if( ScPostIt* pNote = pDoc->GetOrCreateNote( aPos ) )
    {
        // hide temporary note caption
        HideNoteMarker();
        // show caption object without changing internal visibility state
        pNote->ShowCaptionTemp( aPos );

        /*  Drawing object has been created in ScDocument::GetOrCreateNote() or
            in ScPostIt::ShowCaptionTemp(), so ScPostIt::GetCaption() should
            return a caption object. */
        if( SdrCaptionObj* pCaption = pNote->GetCaption() )
        {
            // #i33764# enable the resize handles before starting edit mode
            if( FuPoor* pDraw = GetDrawFuncPtr() )
                static_cast< FuSelection* >( pDraw )->ActivateNoteHandles( pCaption );

            // activate object (as in FuSelection::TestComment)
            GetViewData()->GetDispatcher().Execute( SID_DRAW_NOTEEDIT, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD );
            // jetzt den erzeugten FuText holen und in den EditModus setzen
            FuPoor* pPoor = GetDrawFuncPtr();
            if ( pPoor && (pPoor->GetSlotID() == SID_DRAW_NOTEEDIT) )    // hat keine RTTI
            {
                ScrollToObject( pCaption );         // Objekt komplett sichtbar machen
                static_cast< FuText* >( pPoor )->SetInEditMode( pCaption );
            }
        }
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * TcpConnection.cpp
 *
 *  Created on: 13.05.2017
 *      Author: felix
 */

#include <unistd.h>
#include <asn-one-objects/GenericAsnOneObject.h>
#include <common/Log.h>
#include <network/TcpConnection.h>

namespace Flix {

TcpConnection::TcpConnection(int connectionSocket, const std::string& peer, int port):
    connectionSocket(connectionSocket),
    peer(peer),
    port(port)
{
    opened = connectionSocket >= 0 ? true : false;
    LOG_INFO("Accepted connection from " << peer << ":" << port);
}

TcpConnection::~TcpConnection()
{
}

int TcpConnection::getConnectionSocket(void) const
{
    return connectionSocket;
}

const std::string& TcpConnection::getPeer(void) const
{
    return peer;
}

int TcpConnection::getPort(void) const
{
    return port;
}

bool TcpConnection::close(void)
{
    if (!isOpened()) {
        return false;
    }

    ::close(connectionSocket);
    opened = false;

    return true;
}

bool TcpConnection::isOpened(void) const
{
    return opened;
}

void TcpConnection::handleIncomingData(const StreamBuffer& stream)
{
    if (!isOpened()) {
        return;
    }

    inputStream.insert(inputStream.end(), stream.cbegin(), stream.cend());

    AsnOneDecodeStatus decodeStatus = AsnOneDecodeStatus::UNKNOWN;
    bool quitImmediately = false;
    while (inputStream.size() > 0 && decodeStatus != AsnOneDecodeStatus::INCOMPLETE && !quitImmediately) {
        ssize_t consumedBytes = 0;
        GenericAsnOneObject* asnOneObject = GenericAsnOneObject::decode(inputStream, consumedBytes, decodeStatus);

        if (!asnOneObject) {
            switch (decodeStatus) {
            case AsnOneDecodeStatus::INVALID_TAG:
            case AsnOneDecodeStatus::NOT_SUPPORTED:
            case AsnOneDecodeStatus::UNKNOWN:
                LOG_NOTICE("Protocol error detected (" << decodeStatus << ")! Closing connection.");
                close();
                quitImmediately = true;
                break;
            default:
                break;
            }
        } else {
            LOG_INFO("Cleaning up ASN.1 object...");
            delete asnOneObject;
        }
        inputStream.erase(inputStream.begin(), inputStream.begin() + consumedBytes);
    }
}

} /* namespace Flix */
<commit_msg>Fixed detection of invalid ASN.1 objects.<commit_after>/*
 * TcpConnection.cpp
 *
 *  Created on: 13.05.2017
 *      Author: felix
 */

#include <unistd.h>
#include <asn-one-objects/GenericAsnOneObject.h>
#include <common/Log.h>
#include <network/TcpConnection.h>

namespace Flix {

TcpConnection::TcpConnection(int connectionSocket, const std::string& peer, int port):
    connectionSocket(connectionSocket),
    peer(peer),
    port(port)
{
    opened = connectionSocket >= 0 ? true : false;
    LOG_INFO("Accepted connection from " << peer << ":" << port);
}

TcpConnection::~TcpConnection()
{
}

int TcpConnection::getConnectionSocket(void) const
{
    return connectionSocket;
}

const std::string& TcpConnection::getPeer(void) const
{
    return peer;
}

int TcpConnection::getPort(void) const
{
    return port;
}

bool TcpConnection::close(void)
{
    if (!isOpened()) {
        return false;
    }

    ::close(connectionSocket);
    opened = false;

    return true;
}

bool TcpConnection::isOpened(void) const
{
    return opened;
}

void TcpConnection::handleIncomingData(const StreamBuffer& stream)
{
    if (!isOpened()) {
        return;
    }

    inputStream.insert(inputStream.end(), stream.cbegin(), stream.cend());

    AsnOneDecodeStatus decodeStatus = AsnOneDecodeStatus::UNKNOWN;
    bool quitImmediately = false;
    while (inputStream.size() > 0 && decodeStatus != AsnOneDecodeStatus::INCOMPLETE && !quitImmediately) {
        ssize_t consumedBytes = 0;
        GenericAsnOneObject* asnOneObject = GenericAsnOneObject::decode(inputStream, consumedBytes, decodeStatus);

        if (!asnOneObject) {
            switch (decodeStatus) {
            case AsnOneDecodeStatus::OK:
            case AsnOneDecodeStatus::INCOMPLETE:
                break;
            default:
                LOG_NOTICE("Protocol error detected (" << decodeStatus << ")! Closing connection.");
                close();
                quitImmediately = true;
                break;
            }
        } else {
            LOG_INFO("Cleaning up ASN.1 object...");
            delete asnOneObject;
        }
        inputStream.erase(inputStream.begin(), inputStream.begin() + consumedBytes);
    }
}

} /* namespace Flix */
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017, Matias Fontanini
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following disclaimer
 *   in the documentation and/or other materials provided with the
 *   distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <string.h>
#include <tins/offline_packet_filter.h>
#include <tins/pdu.h>
#include <tins/exceptions.h>

using std::string;

namespace Tins {

OfflinePacketFilter::OfflinePacketFilter(const OfflinePacketFilter& other) {
    *this = other;
}

OfflinePacketFilter& OfflinePacketFilter::operator=(const OfflinePacketFilter& other) {
    string_filter_ = other.string_filter_;
    init(string_filter_, pcap_datalink(other.handle_), pcap_snapshot(other.handle_));
    return* this;
}

OfflinePacketFilter::~OfflinePacketFilter() {
    pcap_freecode(&filter_);
    pcap_close(handle_);
}

void OfflinePacketFilter::init(const string& pcap_filter,
                               int link_type,
                               unsigned int snap_len) {
    handle_ = pcap_open_dead(
        link_type,
        snap_len
    );
    if (!handle_) {
        throw pcap_open_failed();
    }
    if (pcap_compile(handle_, &filter_, pcap_filter.c_str(), 1, 0xffffffff) == -1) {
        string error(pcap_geterr(handle_));
        pcap_freecode(&filter_);
        pcap_close(handle_);
        throw invalid_pcap_filter(error.c_str());
    }
}

bool OfflinePacketFilter::matches_filter(const uint8_t* buffer, uint32_t total_sz) const {
    pcap_pkthdr header;
    memset(&header, 0, sizeof(header));
    header.len = total_sz;
    header.caplen = total_sz;
    return pcap_offline_filter(&filter_, &header, buffer) != 0;
}

bool OfflinePacketFilter::matches_filter(PDU& pdu) const {
    PDU::serialization_type buffer = pdu.serialize();
    return matches_filter(&buffer[0], static_cast<uint32_t>(buffer.size()));
}

} // Tins
<commit_msg>OfflinePacketFilter: avoid leak during copy-construction or assignment<commit_after>/*
 * Copyright (c) 2017, Matias Fontanini
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following disclaimer
 *   in the documentation and/or other materials provided with the
 *   distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <string.h>
#include <tins/offline_packet_filter.h>
#include <tins/pdu.h>
#include <tins/exceptions.h>

using std::string;

namespace Tins {

OfflinePacketFilter::OfflinePacketFilter(const OfflinePacketFilter& other) {
    string_filter_ = other.string_filter_;
    init(string_filter_, pcap_datalink(other.handle_), pcap_snapshot(other.handle_));
}

OfflinePacketFilter& OfflinePacketFilter::operator=(const OfflinePacketFilter& other) {
    string_filter_ = other.string_filter_;
    pcap_freecode(&filter_);
    pcap_close(handle_);
    init(string_filter_, pcap_datalink(other.handle_), pcap_snapshot(other.handle_));
    return* this;
}

OfflinePacketFilter::~OfflinePacketFilter() {
    pcap_freecode(&filter_);
    pcap_close(handle_);
}

void OfflinePacketFilter::init(const string& pcap_filter,
                               int link_type,
                               unsigned int snap_len) {
    handle_ = pcap_open_dead(
        link_type,
        snap_len
    );
    if (!handle_) {
        throw pcap_open_failed();
    }
    if (pcap_compile(handle_, &filter_, pcap_filter.c_str(), 1, 0xffffffff) == -1) {
        string error(pcap_geterr(handle_));
        pcap_freecode(&filter_);
        pcap_close(handle_);
        throw invalid_pcap_filter(error.c_str());
    }
}

bool OfflinePacketFilter::matches_filter(const uint8_t* buffer, uint32_t total_sz) const {
    pcap_pkthdr header;
    memset(&header, 0, sizeof(header));
    header.len = total_sz;
    header.caplen = total_sz;
    return pcap_offline_filter(&filter_, &header, buffer) != 0;
}

bool OfflinePacketFilter::matches_filter(PDU& pdu) const {
    PDU::serialization_type buffer = pdu.serialize();
    return matches_filter(&buffer[0], static_cast<uint32_t>(buffer.size()));
}

} // Tins
<|endoftext|>