<commit_before>// brpc - A framework to host and access services throughout Baidu.
// Copyright (c) 2014 Baidu, Inc.

// Date: 2018/09/19 14:51:06

#include <pthread.h>
#include <gtest/gtest.h>
#include <gflags/gflags.h>
#include "butil/macros.h"
#include "bthread/bthread.h"
#include "brpc/circuit_breaker.h"
#include "brpc/socket.h"
#include "brpc/server.h"
#include "echo.pb.h"

namespace {
void initialize_random() {
    srand(time(0));
}

const int kShortWindowSize = 500;
const int kLongWindowSize = 1000;
const int kShortWindowErrorPercent = 10;
const int kLongWindowErrorPercent = 5;
const int kMinIsolationDurationMs = 100;
const int kMaxIsolationDurationMs = 1000;
const int kErrorCodeForFailed = 131;
const int kErrorCodeForSucc = 0;
const int kErrorCost = 1000;
const int kLatency = 1000;
const int kThreadNum = 3;
} // namespace

namespace brpc {
DECLARE_int32(circuit_breaker_short_window_size);
DECLARE_int32(circuit_breaker_long_window_size);
DECLARE_int32(circuit_breaker_short_window_error_percent);
DECLARE_int32(circuit_breaker_long_window_error_percent);
DECLARE_int32(circuit_breaker_min_isolation_duration_ms);
DECLARE_int32(circuit_breaker_max_isolation_duration_ms);
} // namespace brpc

int main(int argc, char* argv[]) {
    brpc::FLAGS_circuit_breaker_short_window_size = kShortWindowSize;
    brpc::FLAGS_circuit_breaker_long_window_size = kLongWindowSize;
    brpc::FLAGS_circuit_breaker_short_window_error_percent = kShortWindowErrorPercent;
    brpc::FLAGS_circuit_breaker_long_window_error_percent = kLongWindowErrorPercent;
    brpc::FLAGS_circuit_breaker_min_isolation_duration_ms = kMinIsolationDurationMs;
    brpc::FLAGS_circuit_breaker_max_isolation_duration_ms = kMaxIsolationDurationMs;
    testing::InitGoogleTest(&argc, argv);
    GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true);
    return RUN_ALL_TESTS();
}

pthread_once_t initialize_random_control = PTHREAD_ONCE_INIT;

struct FeedbackControl {
    FeedbackControl(int req_num, int error_percent,
                 brpc::CircuitBreaker* circuit_breaker)
        : _req_num(req_num)
        , _error_percent(error_percent)
        , _circuit_breaker(circuit_breaker)
        , _healthy_cnt(0)
        , _unhealthy_cnt(0)
        , _healthy(true) {}
    int _req_num;
    int _error_percent;
    brpc::CircuitBreaker* _circuit_breaker;
    int _healthy_cnt;
    int _unhealthy_cnt;
    bool _healthy;
};

class CircuitBreakerTest : public ::testing::Test {
protected:
    CircuitBreakerTest() {
        pthread_once(&initialize_random_control, initialize_random);
    };

    virtual ~CircuitBreakerTest() {};
    virtual void SetUp() {};
    virtual void TearDown() {};

    static void* feed_back_thread(void* data) {
        FeedbackControl* fc = static_cast<FeedbackControl*>(data);
        for (int i = 0; i < fc->_req_num; ++i) {
            bool healthy = false;
            if (rand() % 100 < fc->_error_percent) {
                healthy = fc->_circuit_breaker->OnCallEnd(kErrorCodeForFailed, kErrorCost);
            } else {
                healthy = fc->_circuit_breaker->OnCallEnd(kErrorCodeForSucc, kLatency);
            }
            fc->_healthy = healthy;
            if (healthy) {
                ++fc->_healthy_cnt;
            } else {
                ++fc->_unhealthy_cnt;
            }
        }
        return fc;
    }

    void StartFeedbackThread(std::vector<pthread_t>* thread_list,
                             std::vector<std::unique_ptr<FeedbackControl>>* fc_list,
                             int error_percent) {
        thread_list->clear();
        fc_list->clear();
        for (int i = 0; i < kThreadNum; ++i) {
            pthread_t tid = 0;
            FeedbackControl* fc =
                new FeedbackControl(2 * kLongWindowSize, error_percent, &_circuit_breaker);
            fc_list->emplace_back(fc);
            pthread_create(&tid, NULL, feed_back_thread, fc);
            thread_list->push_back(tid);
        }
    }

    brpc::CircuitBreaker _circuit_breaker;
};

TEST_F(CircuitBreakerTest, should_not_isolate) {
    std::vector<pthread_t> thread_list;
    std::vector<std::unique_ptr<FeedbackControl>> fc_list;
    StartFeedbackThread(&thread_list, &fc_list, 3);
    for (int  i = 0; i < kThreadNum; ++i) {
        void* ret_data = NULL;
        EXPECT_EQ(pthread_join(thread_list[i], &ret_data), 0);
        FeedbackControl* fc = static_cast<FeedbackControl*>(ret_data);
        EXPECT_EQ(fc->_unhealthy_cnt, 0);
        EXPECT_TRUE(fc->_healthy);
    }
}

TEST_F(CircuitBreakerTest, should_isolate) {
    std::vector<pthread_t> thread_list;
    std::vector<std::unique_ptr<FeedbackControl>> fc_list;
    StartFeedbackThread(&thread_list, &fc_list, 50);
    for (int  i = 0; i < kThreadNum; ++i) {
        void* ret_data = NULL;
        EXPECT_EQ(pthread_join(thread_list[i], &ret_data), 0);
        FeedbackControl* fc = static_cast<FeedbackControl*>(ret_data);
        EXPECT_GT(fc->_unhealthy_cnt, 0);
        EXPECT_FALSE(fc->_healthy);
    }
}

TEST_F(CircuitBreakerTest, isolation_duration_grow) {
    _circuit_breaker.Reset();
    std::vector<pthread_t> thread_list;
    std::vector<std::unique_ptr<FeedbackControl>> fc_list;
    StartFeedbackThread(&thread_list, &fc_list, 100);
    for (int  i = 0; i < kThreadNum; ++i) {
        void* ret_data = NULL;
        EXPECT_EQ(pthread_join(thread_list[i], &ret_data), 0);
        FeedbackControl* fc = static_cast<FeedbackControl*>(ret_data);
        EXPECT_FALSE(fc->_healthy);
        EXPECT_LE(fc->_healthy_cnt, kShortWindowSize);
        EXPECT_GT(fc->_unhealthy_cnt, 0);
    }
    EXPECT_EQ(_circuit_breaker.isolation_duration_ms(), kMinIsolationDurationMs * 2);

    _circuit_breaker.Reset();
    bthread_usleep(kMinIsolationDurationMs * 1000);
    StartFeedbackThread(&thread_list, &fc_list, 100);
    for (int  i = 0; i < kThreadNum; ++i) {
        void* ret_data = NULL;
        EXPECT_EQ(pthread_join(thread_list[i], &ret_data), 0);
        FeedbackControl* fc = static_cast<FeedbackControl*>(ret_data);
        EXPECT_FALSE(fc->_healthy);
        EXPECT_LE(fc->_healthy_cnt, kShortWindowSize);
        EXPECT_GT(fc->_unhealthy_cnt, 0);
    }
    EXPECT_EQ(_circuit_breaker.isolation_duration_ms(), kMinIsolationDurationMs * 4);

    _circuit_breaker.Reset();
    bthread_usleep((kMaxIsolationDurationMs + kMinIsolationDurationMs) * 1000);
    StartFeedbackThread(&thread_list, &fc_list, 100);
    for (int  i = 0; i < kThreadNum; ++i) {
        void* ret_data = NULL;
        EXPECT_EQ(pthread_join(thread_list[i], &ret_data), 0);
        FeedbackControl* fc = static_cast<FeedbackControl*>(ret_data);
        EXPECT_FALSE(fc->_healthy);
        EXPECT_LE(fc->_healthy_cnt, kShortWindowSize);
        EXPECT_GT(fc->_unhealthy_cnt, 0);
    }
    EXPECT_EQ(_circuit_breaker.isolation_duration_ms(), kMinIsolationDurationMs);
}
<commit_msg>update unit-test<commit_after>// brpc - A framework to host and access services throughout Baidu.
// Copyright (c) 2014 Baidu, Inc.

// Date: 2018/09/19 14:51:06

#include <pthread.h>
#include <gtest/gtest.h>
#include <gflags/gflags.h>
#include "butil/macros.h"
#include "bthread/bthread.h"
#include "brpc/circuit_breaker.h"
#include "brpc/socket.h"
#include "brpc/server.h"
#include "echo.pb.h"

namespace {
void initialize_random() {
    srand(time(0));
}

const int kShortWindowSize = 500;
const int kLongWindowSize = 1000;
const int kShortWindowErrorPercent = 10;
const int kLongWindowErrorPercent = 5;
const int kMinIsolationDurationMs = 100;
const int kMaxIsolationDurationMs = 1000;
const int kErrorCodeForFailed = 131;
const int kErrorCodeForSucc = 0;
const int kErrorCost = 1000;
const int kLatency = 1000;
const int kThreadNum = 3;
} // namespace

namespace brpc {
DECLARE_int32(circuit_breaker_short_window_size);
DECLARE_int32(circuit_breaker_long_window_size);
DECLARE_int32(circuit_breaker_short_window_error_percent);
DECLARE_int32(circuit_breaker_long_window_error_percent);
DECLARE_int32(circuit_breaker_min_isolation_duration_ms);
DECLARE_int32(circuit_breaker_max_isolation_duration_ms);
} // namespace brpc

int main(int argc, char* argv[]) {
    brpc::FLAGS_circuit_breaker_short_window_size = kShortWindowSize;
    brpc::FLAGS_circuit_breaker_long_window_size = kLongWindowSize;
    brpc::FLAGS_circuit_breaker_short_window_error_percent = kShortWindowErrorPercent;
    brpc::FLAGS_circuit_breaker_long_window_error_percent = kLongWindowErrorPercent;
    brpc::FLAGS_circuit_breaker_min_isolation_duration_ms = kMinIsolationDurationMs;
    brpc::FLAGS_circuit_breaker_max_isolation_duration_ms = kMaxIsolationDurationMs;
    testing::InitGoogleTest(&argc, argv);
    GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true);
    return RUN_ALL_TESTS();
}

pthread_once_t initialize_random_control = PTHREAD_ONCE_INIT;

struct FeedbackControl {
    FeedbackControl(int req_num, int error_percent,
                 brpc::CircuitBreaker* circuit_breaker)
        : _req_num(req_num)
        , _error_percent(error_percent)
        , _circuit_breaker(circuit_breaker)
        , _healthy(true) {}
    int _req_num;
    int _error_percent;
    brpc::CircuitBreaker* _circuit_breaker;
    bool _healthy;
};

class CircuitBreakerTest : public ::testing::Test {
protected:
    CircuitBreakerTest() {
        pthread_once(&initialize_random_control, initialize_random);
    };

    virtual ~CircuitBreakerTest() {};
    virtual void SetUp() {};
    virtual void TearDown() {};

    static void* feed_back_thread(void* data) {
        FeedbackControl* fc = static_cast<FeedbackControl*>(data);
        for (int i = 0; i < fc->_req_num; ++i) {
            bool healthy = false;
            if (rand() % 100 < fc->_error_percent) {
                healthy = fc->_circuit_breaker->OnCallEnd(kErrorCodeForFailed, kErrorCost);
            } else {
                healthy = fc->_circuit_breaker->OnCallEnd(kErrorCodeForSucc, kLatency);
            }
            fc->_healthy = healthy;
            if (!healthy) {
                break;
            }
        }
        return fc;
    }

    void StartFeedbackThread(std::vector<pthread_t>* thread_list,
                             std::vector<std::unique_ptr<FeedbackControl>>* fc_list,
                             int error_percent) {
        thread_list->clear();
        fc_list->clear();
        for (int i = 0; i < kThreadNum; ++i) {
            pthread_t tid = 0;
            FeedbackControl* fc =
                new FeedbackControl(2 * kLongWindowSize, error_percent, &_circuit_breaker);
            fc_list->emplace_back(fc);
            pthread_create(&tid, NULL, feed_back_thread, fc);
            thread_list->push_back(tid);
        }
    }

    brpc::CircuitBreaker _circuit_breaker;
};

TEST_F(CircuitBreakerTest, should_not_isolate) {
    std::vector<pthread_t> thread_list;
    std::vector<std::unique_ptr<FeedbackControl>> fc_list;
    StartFeedbackThread(&thread_list, &fc_list, 3);
    for (int  i = 0; i < kThreadNum; ++i) {
        void* ret_data = NULL;
        EXPECT_EQ(pthread_join(thread_list[i], &ret_data), 0);
        FeedbackControl* fc = static_cast<FeedbackControl*>(ret_data);
        EXPECT_TRUE(fc->_healthy);
    }
    // MarkAsBroken shoul be called only once.
    _circuit_breaker.MarkAsBroken();
    _circuit_breaker.Reset();
}

TEST_F(CircuitBreakerTest, should_isolate) {
    std::vector<pthread_t> thread_list;
    std::vector<std::unique_ptr<FeedbackControl>> fc_list;
    StartFeedbackThread(&thread_list, &fc_list, 50);
    for (int  i = 0; i < kThreadNum; ++i) {
        void* ret_data = NULL;
        EXPECT_EQ(pthread_join(thread_list[i], &ret_data), 0);
        FeedbackControl* fc = static_cast<FeedbackControl*>(ret_data);
        EXPECT_FALSE(fc->_healthy);
    }
    // MarkAsBroken shoul be called only once.
    _circuit_breaker.MarkAsBroken();
    _circuit_breaker.Reset();
}

TEST_F(CircuitBreakerTest, isolation_duration_grow) {
    EXPECT_EQ(_circuit_breaker.isolation_duration_ms(), kMinIsolationDurationMs);
    _circuit_breaker.Reset();
    std::vector<pthread_t> thread_list;
    std::vector<std::unique_ptr<FeedbackControl>> fc_list;
    StartFeedbackThread(&thread_list, &fc_list, 100);
    for (int  i = 0; i < kThreadNum; ++i) {
        void* ret_data = NULL;
        EXPECT_EQ(pthread_join(thread_list[i], &ret_data), 0);
        FeedbackControl* fc = static_cast<FeedbackControl*>(ret_data);
        EXPECT_FALSE(fc->_healthy);
    }
    // MarkAsBroken shoul be called only once.
    _circuit_breaker.MarkAsBroken();
    EXPECT_EQ(_circuit_breaker.isolation_duration_ms(), kMinIsolationDurationMs * 2);

    _circuit_breaker.Reset();
    bthread_usleep(kMinIsolationDurationMs * 1000);
    StartFeedbackThread(&thread_list, &fc_list, 100);
    for (int  i = 0; i < kThreadNum; ++i) {
        void* ret_data = NULL;
        EXPECT_EQ(pthread_join(thread_list[i], &ret_data), 0);
        FeedbackControl* fc = static_cast<FeedbackControl*>(ret_data);
        EXPECT_FALSE(fc->_healthy);
    }
    // MarkAsBroken shoul be called only once.
    _circuit_breaker.MarkAsBroken();
    EXPECT_EQ(_circuit_breaker.isolation_duration_ms(), kMinIsolationDurationMs * 4);

    _circuit_breaker.Reset();
    bthread_usleep((kMaxIsolationDurationMs + kMinIsolationDurationMs) * 1000);
    StartFeedbackThread(&thread_list, &fc_list, 100);
    for (int  i = 0; i < kThreadNum; ++i) {
        void* ret_data = NULL;
        EXPECT_EQ(pthread_join(thread_list[i], &ret_data), 0);
        FeedbackControl* fc = static_cast<FeedbackControl*>(ret_data);
        EXPECT_FALSE(fc->_healthy);
    }
    // MarkAsBroken shoul be called only once.
    _circuit_breaker.MarkAsBroken();
    EXPECT_EQ(_circuit_breaker.isolation_duration_ms(), kMinIsolationDurationMs);
}
<|endoftext|>


<commit_before>/*
 * =====================================================================================
 *
 *       Filename:  warp.cpp
 *
 *    Description:  Demonstrate various projection of an image onto a flat screen
 *
 *        Version:  0.0.1
 *        Created:  06/03/2014 13:38:27
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Eugene Scherba
 *   Organization:  Livefyre
 *
 * =====================================================================================
 */

#include <cmath>
#include <opencv2/opencv.hpp>

using namespace cv;

cv::Vec4b getSubpix(const cv::Mat& src, cv::Point2f pt)
{
    // Simple bilinear interpolation
    //
    const int x = (int)pt.x;
    const int y = (int)pt.y;

    const int x0 = cv::borderInterpolate(x,     src.cols, cv::BORDER_REFLECT_101);
    const int x1 = cv::borderInterpolate(x + 1, src.cols, cv::BORDER_REFLECT_101);
    const int y0 = cv::borderInterpolate(y,     src.rows, cv::BORDER_REFLECT_101);
    const int y1 = cv::borderInterpolate(y + 1, src.rows, cv::BORDER_REFLECT_101);

    const float a = pt.x - (float)x;
    const float c = pt.y - (float)y;

    const uchar b = (uchar)cvRound(
        (src.at<cv::Vec4b>(y0, x0)[0] * (1.f - a) + src.at<cv::Vec4b>(y0, x1)[0] * a) * (1.f - c) +
        (src.at<cv::Vec4b>(y1, x0)[0] * (1.f - a) + src.at<cv::Vec4b>(y1, x1)[0] * a) * c
    );
    const uchar g = (uchar)cvRound(
        (src.at<cv::Vec4b>(y0, x0)[1] * (1.f - a) + src.at<cv::Vec4b>(y0, x1)[1] * a) * (1.f - c) +
        (src.at<cv::Vec4b>(y1, x0)[1] * (1.f - a) + src.at<cv::Vec4b>(y1, x1)[1] * a) * c
    );
    const uchar r = (uchar)cvRound(
        (src.at<cv::Vec4b>(y0, x0)[2] * (1.f - a) + src.at<cv::Vec4b>(y0, x1)[2] * a) * (1.f - c) +
        (src.at<cv::Vec4b>(y1, x0)[2] * (1.f - a) + src.at<cv::Vec4b>(y1, x1)[2] * a) * c
    );
    const uchar t = (uchar)cvRound(
        (src.at<cv::Vec4b>(y0, x0)[2] * (1.f - a) + src.at<cv::Vec4b>(y0, x1)[2] * a) * (1.f - c) +
        (src.at<cv::Vec4b>(y1, x0)[2] * (1.f - a) + src.at<cv::Vec4b>(y1, x1)[2] * a) * c
    );
    return cv::Vec4b(b, g, r, t);
}

void project_identity(cv::Mat& dst, cv::Mat& src)
{
    // Identity projection (no change)
    //
    const int height = dst.rows;
    const int width  = dst.cols;

    for (int j = 0; j < height; j++) {
        const int j_src = j;
        for (int i = 0; i < width; i++) {
            const int i_src = i;
            dst.at<cv::Vec4b>(j, i) = src.at<cv::Vec4b>(j_src, i_src);
        }
    }
}

void project_flat(cv::Mat& dst, cv::Mat& src)
{
    // Project from a flat background onto a flat screen
    //
    const int height = dst.rows;
    const int width  = dst.cols;

    const float jf = (float)height * 0.75f; // distance from camera to ceiling
    const float zf = (float)height * 2.0f;  // distance from camera to screen
    const float zb = (float)height * 0.5f;  // distance from screen to image

    for (int j = 0; j < height; j++) {
        const float z_ratio = (zb + zf) / zf;
        const float j_src = jf + z_ratio * ((float)j - jf);
        for (int i = 0; i < width; i++){
            const int i_src = i;
            if (i_src >= 0.0f && i_src <= (float)width &&
                j_src >= 0.0f && j_src <= (float)height) {
                dst.at<cv::Vec4b>(j, i) = getSubpix(src, cv::Point2f(i_src, j_src));
            }
        }
    }
}

void project_cylinder(cv::Mat& dst, cv::Mat& src)
{
    // Project from a cylindrical background onto a flat screen
    //
    const int height = dst.rows;
    const int width  = dst.cols;

    const float r  = (float)width * 0.5f;    // cylinder radius ((width / 2) <= r < inf)
    const float yf = (float)height * 0.75f;  // distance from camera to ceiling
    const float zf = hypot((float)height, (float)width);
                                             // distance from camera to screen (default: hypothenuse)
    const float xf = (float)width * 0.50f;   // distance from camera to left edge

    // precompute some constants
    const float half_width = (float)width * 0.50f;
    const float zfr = cos(half_width / r); // distance from cylinder center to projection plane

    for (int i = 0; i < width; i++)
    {
        // X-axis (columns)
        const float zb = r * (cos((half_width - (float)i) / r) - zfr);
        const float z_ratio = (zb + zf) / zf;

        const float i_src = r * asin(((float)i - xf) * z_ratio / r) + half_width;
        //const float i_src = xf + z_ratio * r * sin(((float)i - half_width) / r);
        for (int j = 0; j < height; j++)
        {
            // Y-axis (rows)
            const float j_src = yf + z_ratio * ((float)j - yf);
            if (i_src >= 0.0f && i_src <= (float)width &&
                j_src >= 0.0f && j_src <= (float)height)
            {
                dst.at<cv::Vec4b>(j, i) = getSubpix(src, cv::Point2f(i_src, j_src));
            }
        }
    }
}

int main(int argc, char *argv[]) {
    cv::Mat src = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
    src.convertTo(src, CV_8UC4); // convert to BGR

    // fix jaggies on the bottom by adding a 2-px black border
    cv::copyMakeBorder(src, src, 2, 2, 0, 0, cv::BORDER_CONSTANT, cv::Scalar::all(0));

    // prepare black destination canvas
    cv::Mat dst = cv::Mat::zeros(src.rows, src.cols, src.type());

    project_cylinder(dst, src);
    cv::imwrite(argv[2], dst);

}

<commit_msg>switch back to tricolor<commit_after>/*
 * =====================================================================================
 *
 *       Filename:  warp.cpp
 *
 *    Description:  Demonstrate various projection of an image onto a flat screen
 *
 *        Version:  0.0.1
 *        Created:  06/03/2014 13:38:27
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Eugene Scherba
 *   Organization:  Livefyre
 *
 * =====================================================================================
 */

#include <cmath>
#include <opencv2/opencv.hpp>

using namespace cv;

cv::Vec3b getSubpix(const cv::Mat& src, cv::Point2f pt)
{
    // Simple bilinear interpolation
    //
    const int x = (int)pt.x;
    const int y = (int)pt.y;

    const int x0 = cv::borderInterpolate(x,     src.cols, cv::BORDER_REFLECT_101);
    const int x1 = cv::borderInterpolate(x + 1, src.cols, cv::BORDER_REFLECT_101);
    const int y0 = cv::borderInterpolate(y,     src.rows, cv::BORDER_REFLECT_101);
    const int y1 = cv::borderInterpolate(y + 1, src.rows, cv::BORDER_REFLECT_101);

    const float a = pt.x - (float)x;
    const float c = pt.y - (float)y;

    const uchar b = (uchar)cvRound(
        (src.at<cv::Vec3b>(y0, x0)[0] * (1.f - a) + src.at<cv::Vec3b>(y0, x1)[0] * a) * (1.f - c) +
        (src.at<cv::Vec3b>(y1, x0)[0] * (1.f - a) + src.at<cv::Vec3b>(y1, x1)[0] * a) * c
    );
    const uchar g = (uchar)cvRound(
        (src.at<cv::Vec3b>(y0, x0)[1] * (1.f - a) + src.at<cv::Vec3b>(y0, x1)[1] * a) * (1.f - c) +
        (src.at<cv::Vec3b>(y1, x0)[1] * (1.f - a) + src.at<cv::Vec3b>(y1, x1)[1] * a) * c
    );
    const uchar r = (uchar)cvRound(
        (src.at<cv::Vec3b>(y0, x0)[2] * (1.f - a) + src.at<cv::Vec3b>(y0, x1)[2] * a) * (1.f - c) +
        (src.at<cv::Vec3b>(y1, x0)[2] * (1.f - a) + src.at<cv::Vec3b>(y1, x1)[2] * a) * c
    );

    /*
    const uchar t = (uchar)cvRound(
        (src.at<cv::Vec3b>(y0, x0)[2] * (1.f - a) + src.at<cv::Vec3b>(y0, x1)[2] * a) * (1.f - c) +
        (src.at<cv::Vec3b>(y1, x0)[2] * (1.f - a) + src.at<cv::Vec3b>(y1, x1)[2] * a) * c
    );
    return cv::Vec3b(b, g, r, t);
    */
    return cv::Vec3b(b, g, r);
}

void project_identity(cv::Mat& dst, cv::Mat& src)
{
    // Identity projection (no change)
    //
    const int height = dst.rows;
    const int width  = dst.cols;

    for (int j = 0; j < height; j++) {
        const int j_src = j;
        for (int i = 0; i < width; i++) {
            const int i_src = i;
            dst.at<cv::Vec3b>(j, i) = src.at<cv::Vec3b>(j_src, i_src);
        }
    }
}

void project_flat(cv::Mat& dst, cv::Mat& src)
{
    // Project from a flat background onto a flat screen
    //
    const int height = dst.rows;
    const int width  = dst.cols;

    const float jf = (float)height * 0.75f; // distance from camera to ceiling
    const float zf = (float)height * 2.0f;  // distance from camera to screen
    const float zb = (float)height * 0.5f;  // distance from screen to image

    for (int j = 0; j < height; j++) {
        const float z_ratio = (zb + zf) / zf;
        const float j_src = jf + z_ratio * ((float)j - jf);
        for (int i = 0; i < width; i++){
            const int i_src = i;
            if (i_src >= 0.0f && i_src <= (float)width &&
                j_src >= 0.0f && j_src <= (float)height) {
                dst.at<cv::Vec3b>(j, i) = getSubpix(src, cv::Point2f(i_src, j_src));
            }
        }
    }
}

void project_cylinder(cv::Mat& dst, cv::Mat& src)
{
    // Project from a cylindrical background onto a flat screen
    //
    const int height = dst.rows;
    const int width  = dst.cols;

    const float r  = (float)width * 0.5f;    // cylinder radius ((width / 2) <= r < inf)
    const float yf = (float)height * 0.75f;  // distance from camera to ceiling
    const float zf = hypot((float)height, (float)width);
                                             // distance from camera to screen (default: hypothenuse)
    const float xf = (float)width * 0.50f;   // distance from camera to left edge

    // precompute some constants
    const float half_width = (float)width * 0.50f;
    const float zfr = cos(half_width / r); // distance from cylinder center to projection plane

    for (int i = 0; i < width; i++)
    {
        // X-axis (columns)
        const float zb = r * (cos((half_width - (float)i) / r) - zfr);
        const float z_ratio = (zb + zf) / zf;

        const float i_src = r * asin(((float)i - xf) * z_ratio / r) + half_width;
        //const float i_src = xf + z_ratio * r * sin(((float)i - half_width) / r);
        for (int j = 0; j < height; j++)
        {
            // Y-axis (rows)
            const float j_src = yf + z_ratio * ((float)j - yf);
            if (i_src >= 0.0f && i_src <= (float)width &&
                j_src >= 0.0f && j_src <= (float)height)
            {
                dst.at<cv::Vec3b>(j, i) = getSubpix(src, cv::Point2f(i_src, j_src));
            }
        }
    }
}

int main(int argc, char *argv[]) {
    cv::Mat src = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
    src.convertTo(src, CV_8UC3); // convert to BGR

    // fix jaggies on the bottom by adding a 2-px black border
    cv::copyMakeBorder(src, src, 2, 2, 0, 0, cv::BORDER_CONSTANT, cv::Scalar::all(0));

    // prepare black destination canvas
    cv::Mat dst = cv::Mat::zeros(src.rows, src.cols, src.type());

    project_cylinder(dst, src);
    cv::imwrite(argv[2], dst);
}

<|endoftext|>


<commit_before>#include "Halide.h"
#include <stdio.h>

#ifndef _MSC_VER
#include <unistd.h>
#endif

using namespace Halide;

int main(int argc, char **argv) {
    // Make sure it's possible to generate object files for lots of
    // targets. This provides early warning that you may have broken
    // Halide on some other platform.

    Func f;
    Var x;
    f(x) = x;

    std::string targets[] = {
        "x86-64-linux",
        "x86-32-linux",
        "x86-64-osx",
        "x86-32-osx",
        "x86-64-windows",
        "x86-32-windows",
        "arm-64-ios",
        "arm-32-ios",
        "arm-64-android",
        "arm-32-android",
        "mips-32-android"
    };

    for (const std::string &t : targets) {
        Target target = parse_target_string(t);
        f.compile_to_file("test_object_" + t, std::vector<Argument>(), target);

        #ifndef _MSC_VER
        std::string object_name = "test_object_" + t + ".o";
        if (target.os == Target::Windows) object_name += "bj";
        assert(access(object_name.c_str(), F_OK) == 0 && "Output file not created.");
        #endif
    }

    printf("Success!\n");
    return 0;
}
<commit_msg>Be less tricky<commit_after>#include "Halide.h"
#include <stdio.h>

#ifndef _MSC_VER
#include <unistd.h>
#endif

using namespace Halide;

int main(int argc, char **argv) {
    // Make sure it's possible to generate object files for lots of
    // targets. This provides early warning that you may have broken
    // Halide on some other platform.

    Func f;
    Var x;
    f(x) = x;

    std::string targets[] = {
        "x86-64-linux",
        "x86-32-linux",
        "x86-64-osx",
        "x86-32-osx",
        "x86-64-windows",
        "x86-32-windows",
        "arm-64-ios",
        "arm-32-ios",
        "arm-64-android",
        "arm-32-android",
        "mips-32-android"
    };

    for (const std::string &t : targets) {
        Target target = parse_target_string(t);
        f.compile_to_file("test_object_" + t, std::vector<Argument>(), target);

        #ifndef _MSC_VER
        std::string object_name = "test_object_" + t;
        if (target.os == Target::Windows) {
            object_name += ".obj";
        } else {
            object_name += ".o";
        }
        assert(access(object_name.c_str(), F_OK) == 0 && "Output file not created.");
        #endif
    }

    printf("Success!\n");
    return 0;
}
<|endoftext|>


<commit_before>/**
* Copyright (C) Mellanox Technologies Ltd. 2001-2016.  ALL RIGHTS RESERVED.
* Copyright (C) UT-Battelle, LLC. 2016. ALL RIGHTS RESERVED.
* Copyright (C) ARM Ltd. 2016.All rights reserved.
* See file LICENSE for terms.
*/

extern "C" {
#include <uct/api/uct.h>
#include <uct/ib/rc/base/rc_ep.h>
#include <uct/ib/rc/base/rc_iface.h>
}
#include <common/test.h>
#include "uct_test.h"

class test_rc_flow_control : public uct_test {
public:
    virtual void init() {
        uct_test::init();

        m_e1 = uct_test::create_entity(0);
        m_entities.push_back(m_e1);

        m_e2 = uct_test::create_entity(0);
        m_entities.push_back(m_e2);

        connect();
    }

    typedef struct pending_send_request {
        uct_ep_h          ep;
        uct_pending_req_t uct;
    } pending_send_request_t;

    void connect() {
        m_e1->connect(0, *m_e2, 0);
        m_e2->connect(0, *m_e1, 0);

        uct_iface_set_am_handler(m_e1->iface(), 0, am_dummy_handler,
                                 NULL, UCT_AM_CB_FLAG_SYNC);
        uct_iface_set_am_handler(m_e2->iface(), 0, am_dummy_handler,
                                 NULL, UCT_AM_CB_FLAG_SYNC);
    }

    uct_rc_iface_t* rc_iface(entity *e) {
        return ucs_derived_of(e->iface(), uct_rc_iface_t);
    }

    uct_rc_ep_t* rc_ep(entity *e) {
        return ucs_derived_of(e->ep(0), uct_rc_ep_t);
    }

    void set_fc_attributes(entity *e, int wnd, int s_thresh, int h_thresh) {
        rc_iface(e)->config.fc_wnd_size    = rc_ep(e)->fc_wnd = wnd;
        rc_iface(e)->config.fc_soft_thresh = s_thresh;
        rc_iface(e)->config.fc_hard_thresh = h_thresh;

    }

    void send_am_messages(entity *e, int wnd, ucs_status_t expected) {
        for (int i = 0; i < wnd; i++) {
            EXPECT_EQ(uct_ep_am_short(e->ep(0), 0, 0, NULL, 0), expected);
        }
    }

    static ucs_status_t am_dummy_handler(void *arg, void *data, size_t length, void *desc) {
        return UCS_OK;
    }

    static ucs_status_t am_send(uct_pending_req_t *self) {

        pending_send_request_t *req = ucs_container_of(self, pending_send_request_t, uct);
        ucs_status_t status;

        status = uct_ep_am_short(req->ep, 0, 0, NULL,0);
        ucs_debug("sending short with grant %d ",status);
        return status;
    }

    static ucs_status_t pending_cb(uct_pending_req_t *self)
    {
        req_count++;
        return UCS_OK;
    }

    virtual void cleanup() {
        uct_test::cleanup();
    }

protected:
    static int req_count;
    entity *m_e1, *m_e2;
};

int test_rc_flow_control::req_count = 0;

/* Check that FC window works as expected */
UCS_TEST_P(test_rc_flow_control, general)
{
    int test_wnd = 8;

    set_fc_attributes(m_e1, test_wnd,
                      ucs_max((int)(test_wnd*0.5), 1),
                      ucs_max((int)(test_wnd*0.25), 1));

    send_am_messages(m_e1, test_wnd, UCS_OK);
    send_am_messages(m_e1, 1, UCS_ERR_NO_RESOURCE);

    short_progress_loop();
    send_am_messages(m_e1, 1, UCS_OK);
}

/* Test the scenario when ep is being destroyed while there is
 * FC grant message in the pending queue */
UCS_TEST_P(test_rc_flow_control, pending_only_fc)
{
    int test_wnd = 2;

    /* Set tx resources of m2 to 0 for FC grant message
     * to be added to the pending group */
    rc_ep(m_e2)->available = 0;

    set_fc_attributes(m_e1, test_wnd, test_wnd, 1);

    send_am_messages(m_e1, test_wnd, UCS_OK);
    short_progress_loop();

    m_e2->destroy_ep(0);
    ASSERT_TRUE(rc_iface(m_e2)->tx.arbiter.current == NULL);
}

/* Check that user callback passed to uct_ep_pending_purge is not
 * invoked for FC grant message */
UCS_TEST_P(test_rc_flow_control, pending_purge)
{
    int test_wnd = 2;
    int num_pend_sends = 5;
    uct_pending_req_t reqs[num_pend_sends];

    /* Set tx resources of m2 to 0 for FC grant message
     * to be added to the pending group*/
    rc_ep(m_e2)->available = 0;

    set_fc_attributes(m_e1, test_wnd, test_wnd, 1);

    req_count = 0;

    send_am_messages(m_e1, test_wnd, UCS_OK);
    short_progress_loop();

    /* Now m2 ep should have FC grant message in the pending queue.
     * Add some user pending requests as well */
    for (int i = 0; i < num_pend_sends; i ++) {
        EXPECT_EQ(uct_ep_pending_add(m_e2->ep(0), &reqs[i]), UCS_OK);
    }

    uct_ep_pending_purge(m_e2->ep(0), pending_cb);
    EXPECT_EQ(num_pend_sends, req_count);
}

/* Check that FC grant message is not added to the pending queue
 * if it is already present there. Potentially it may happen if
 * endpoint answered on soft request with some AM message, but
 * grant message was added to pending due to lack of resources. */
UCS_TEST_P(test_rc_flow_control, pending_fc_req)
{
    int test_wnd = 4;
    int h_thresh = 1;
    int num_pend = 2;
    int available = rc_ep(m_e2)->available;
    pending_send_request_t req[num_pend];

    req_count = 0;

    /* Disable send capabilities of m_e2 */
    rc_iface(m_e2)->tx.cq_available = 0;

    set_fc_attributes(m_e1, test_wnd, test_wnd, h_thresh);

    for (int i = 0; i < num_pend; i++) {
        req[i].uct.func = am_send;
        req[i].ep = m_e2->ep(0);
        EXPECT_EQ(uct_ep_pending_add(m_e2->ep(0), &req[i].uct), UCS_OK);
        rc_ep(m_e1)->fc_wnd = h_thresh;
        send_am_messages(m_e1, 1, UCS_OK); /* send AM with FC hard request */
        short_progress_loop();
    }

    /* Now pending group of m_e2 endpoint should look like:
     * AM-0->FC_grant->AM-1
     * The second FC grant should not be added to the group! */

    /* Now force dispatching of m_e2 pending group */
    rc_iface(m_e2)->tx.cq_available = 2;

    /* Make sure this AM message is signalled to force pendings dispatch */
    rc_iface(m_e2)->config.tx_moderation = 0;
    send_am_messages(m_e2, 1, UCS_OK);

    /* Avoid modifying of ep->available by send completions */
    rc_iface(m_e2)->config.tx_moderation = 10;
    short_progress_loop();

    /* Check that only num_pend + 1 (for FC grant) messages were sent */
    EXPECT_EQ(rc_ep(m_e2)->available, available - (num_pend + 1));
}

_UCT_INSTANTIATE_TEST_CASE(test_rc_flow_control, rc)
_UCT_INSTANTIATE_TEST_CASE(test_rc_flow_control, rc_mlx5)
<commit_msg>UCT: FC test fix<commit_after>/**
* Copyright (C) Mellanox Technologies Ltd. 2001-2016.  ALL RIGHTS RESERVED.
* Copyright (C) UT-Battelle, LLC. 2016. ALL RIGHTS RESERVED.
* Copyright (C) ARM Ltd. 2016.All rights reserved.
* See file LICENSE for terms.
*/

extern "C" {
#include <uct/api/uct.h>
#include <uct/ib/rc/base/rc_ep.h>
#include <uct/ib/rc/base/rc_iface.h>
}
#include <common/test.h>
#include "uct_test.h"

class test_rc_flow_control : public uct_test {
public:
    virtual void init() {
        uct_test::init();

        m_e1 = uct_test::create_entity(0);
        m_entities.push_back(m_e1);

        m_e2 = uct_test::create_entity(0);
        m_entities.push_back(m_e2);

        connect();
    }

    typedef struct pending_send_request {
        uct_ep_h          ep;
        uct_pending_req_t uct;
    } pending_send_request_t;

    void connect() {
        m_e1->connect(0, *m_e2, 0);
        m_e2->connect(0, *m_e1, 0);

        uct_iface_set_am_handler(m_e1->iface(), 0, am_dummy_handler,
                                 NULL, UCT_AM_CB_FLAG_SYNC);
        uct_iface_set_am_handler(m_e2->iface(), 0, am_dummy_handler,
                                 NULL, UCT_AM_CB_FLAG_SYNC);
    }

    uct_rc_iface_t* rc_iface(entity *e) {
        return ucs_derived_of(e->iface(), uct_rc_iface_t);
    }

    uct_rc_ep_t* rc_ep(entity *e) {
        return ucs_derived_of(e->ep(0), uct_rc_ep_t);
    }

    void set_fc_attributes(entity *e, int wnd, int s_thresh, int h_thresh) {
        rc_iface(e)->config.fc_wnd_size    = rc_ep(e)->fc_wnd = wnd;
        rc_iface(e)->config.fc_soft_thresh = s_thresh;
        rc_iface(e)->config.fc_hard_thresh = h_thresh;

    }

    void send_am_messages(entity *e, int wnd, ucs_status_t expected) {
        for (int i = 0; i < wnd; i++) {
            EXPECT_EQ(uct_ep_am_short(e->ep(0), 0, 0, NULL, 0), expected);
        }
    }

    virtual void short_progress_loop(double delta_ms=10.0) const {
        uct_test::short_progress_loop(delta_ms);
    }

    static ucs_status_t am_dummy_handler(void *arg, void *data, size_t length, void *desc) {
        return UCS_OK;
    }

    static ucs_status_t am_send(uct_pending_req_t *self) {

        pending_send_request_t *req = ucs_container_of(self, pending_send_request_t, uct);
        ucs_status_t status;

        status = uct_ep_am_short(req->ep, 0, 0, NULL,0);
        ucs_debug("sending short with grant %d ",status);
        return status;
    }

    static ucs_status_t pending_cb(uct_pending_req_t *self)
    {
        req_count++;
        return UCS_OK;
    }

    virtual void cleanup() {
        uct_test::cleanup();
    }

protected:
    static int req_count;
    entity *m_e1, *m_e2;
};

int test_rc_flow_control::req_count = 0;

/* Check that FC window works as expected */
UCS_TEST_P(test_rc_flow_control, general)
{
    int test_wnd = 8;

    set_fc_attributes(m_e1, test_wnd,
                      ucs_max((int)(test_wnd*0.5), 1),
                      ucs_max((int)(test_wnd*0.25), 1));

    send_am_messages(m_e1, test_wnd, UCS_OK);
    send_am_messages(m_e1, 1, UCS_ERR_NO_RESOURCE);

    short_progress_loop();
    send_am_messages(m_e1, 1, UCS_OK);
}

/* Test the scenario when ep is being destroyed while there is
 * FC grant message in the pending queue */
UCS_TEST_P(test_rc_flow_control, pending_only_fc)
{
    int test_wnd = 2;

    /* Set tx resources of m2 to 0 for FC grant message
     * to be added to the pending group */
    rc_ep(m_e2)->available = 0;

    set_fc_attributes(m_e1, test_wnd, test_wnd, 1);

    send_am_messages(m_e1, test_wnd, UCS_OK);
    short_progress_loop();

    m_e2->destroy_ep(0);
    ASSERT_TRUE(rc_iface(m_e2)->tx.arbiter.current == NULL);
}

/* Check that user callback passed to uct_ep_pending_purge is not
 * invoked for FC grant message */
UCS_TEST_P(test_rc_flow_control, pending_purge)
{
    int test_wnd = 2;
    int num_pend_sends = 5;
    uct_pending_req_t reqs[num_pend_sends];

    /* Set tx resources of m2 to 0 for FC grant message
     * to be added to the pending group*/
    rc_ep(m_e2)->available = 0;

    set_fc_attributes(m_e1, test_wnd, test_wnd, 1);

    req_count = 0;

    send_am_messages(m_e1, test_wnd, UCS_OK);
    short_progress_loop();

    /* Now m2 ep should have FC grant message in the pending queue.
     * Add some user pending requests as well */
    for (int i = 0; i < num_pend_sends; i ++) {
        EXPECT_EQ(uct_ep_pending_add(m_e2->ep(0), &reqs[i]), UCS_OK);
    }

    uct_ep_pending_purge(m_e2->ep(0), pending_cb);
    EXPECT_EQ(num_pend_sends, req_count);
}

/* Check that FC grant message is not added to the pending queue
 * if it is already present there. Potentially it may happen if
 * endpoint answered on soft request with some AM message, but
 * grant message was added to pending due to lack of resources. */
UCS_TEST_P(test_rc_flow_control, pending_fc_req)
{
    int test_wnd = 4;
    int h_thresh = 1;
    int num_pend = 2;
    int available = rc_ep(m_e2)->available;
    pending_send_request_t req[num_pend];

    req_count = 0;

    /* Disable send capabilities of m_e2 */
    rc_iface(m_e2)->tx.cq_available = 0;

    set_fc_attributes(m_e1, test_wnd, test_wnd, h_thresh);

    for (int i = 0; i < num_pend; i++) {
        req[i].uct.func = am_send;
        req[i].ep = m_e2->ep(0);
        EXPECT_EQ(uct_ep_pending_add(m_e2->ep(0), &req[i].uct), UCS_OK);
        rc_ep(m_e1)->fc_wnd = h_thresh;
        send_am_messages(m_e1, 1, UCS_OK); /* send AM with FC hard request */
        short_progress_loop();
    }

    /* Now pending group of m_e2 endpoint should look like:
     * AM-0->FC_grant->AM-1
     * The second FC grant should not be added to the group! */

    /* Now force dispatching of m_e2 pending group */
    rc_iface(m_e2)->tx.cq_available = 2;

    /* Make sure this AM message is signalled to force pendings dispatch */
    rc_iface(m_e2)->config.tx_moderation = 0;
    send_am_messages(m_e2, 1, UCS_OK);

    /* Avoid modifying of ep->available by send completions */
    rc_iface(m_e2)->config.tx_moderation = 10;
    short_progress_loop();

    /* Check that only num_pend + 1 (for FC grant) messages were sent */
    EXPECT_EQ(rc_ep(m_e2)->available, available - (num_pend + 1));
}

_UCT_INSTANTIATE_TEST_CASE(test_rc_flow_control, rc)
_UCT_INSTANTIATE_TEST_CASE(test_rc_flow_control, rc_mlx5)
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: markarr.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: er $ $Date: 2002-01-18 12:01:08 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "core_pch.hxx"
#endif

#pragma hdrstop

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

#include <tools/debug.hxx>

#include "markarr.hxx"
#include "global.hxx"

// STATIC DATA -----------------------------------------------------------

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

ScMarkArray::ScMarkArray()
{
    nCount = nLimit = 1;
    pData = new ScMarkEntry[1];
    if (pData)
    {
        pData[0].nRow = MAXROW;
        pData[0].bMarked = FALSE;
    }
}

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

ScMarkArray::~ScMarkArray()
{
    if (pData)
        delete[] pData;
}

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

void ScMarkArray::Reset( BOOL bMarked )
{
    if (pData)
    {
        delete[] pData;

        nCount = nLimit = 1;
        pData = new ScMarkEntry[1];
        if (pData)
        {
            pData[0].nRow = MAXROW;
            pData[0].bMarked = bMarked;
        }
    }
}

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

BOOL ScMarkArray::Search( USHORT nRow, short& nIndex ) const
{
    short   nLo         = 0;
    short   nHi         = ((short) nCount) - 1;
    short   nStartRow   = 0;
    short   nEndRow     = 0;
    short   i           = 0;
    BOOL    bFound      = (nCount == 1);
    if (pData)
    {
        while ( !bFound && nLo <= nHi )
        {
            i = (nLo + nHi) / 2;
            if (i > 0)
                nStartRow = (short) pData[i - 1].nRow;
            else
                nStartRow = -1;
            nEndRow = (short) pData[i].nRow;
            if (nEndRow < (short) nRow)
                nLo = ++i;
            else
                if (nStartRow >= (short) nRow)
                    nHi = --i;
                else
                    bFound = TRUE;
        }
    }
    else
        bFound = FALSE;

    if (bFound)
        nIndex=i;
    else
        nIndex=0;
    return bFound;
}

BOOL ScMarkArray::GetMark( USHORT nRow ) const
{
    short i;
    if (Search( nRow, i ))
        return pData[i].bMarked;
    else
        return FALSE;

}

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

void ScMarkArray::SetMark( USHORT nRow, BOOL bMarked )
{
    SetMarkArea( nRow, nRow, bMarked );
}

void ScMarkArray::SetMarkArea( USHORT nStartRow, USHORT nEndRow, BOOL bMarked )
{
    if ((nStartRow >= 0 && nStartRow <= MAXROW) && (nEndRow >= 0 && nEndRow <= MAXROW))
    {
        if ((nStartRow == 0) && (nEndRow == MAXROW))
        {
            Reset(bMarked);
        }
        else
        {
            USHORT nNeeded = nCount + 2;
            if ( nLimit < nNeeded )
            {
                nLimit += SC_MARKARRAY_DELTA;
                if ( nLimit < nNeeded )
                    nLimit = nNeeded;
                ScMarkEntry* pNewData = new ScMarkEntry[nLimit];
                memcpy( pNewData, pData, nCount*sizeof(ScMarkEntry) );
                delete[] pData;
                pData = pNewData;
            }

            USHORT ni;          // number of entries in beginning
            USHORT nInsert;     // insert position (MAXROW+1 := no insert)
            BOOL bCombined = FALSE;
            BOOL bSplit = FALSE;
            if ( nStartRow > 0 )
            {
                // skip beginning
                short nIndex;
                Search( nStartRow, nIndex );
                ni = nIndex;

                nInsert = MAXROW+1;
                if ( pData[ni].bMarked != bMarked )
                {
                    if ( ni == 0 || (pData[ni-1].nRow < nStartRow - 1) )
                    {   // may be a split or a simple insert or just a shrink,
                        // row adjustment is done further down
                        if ( pData[ni].nRow > nEndRow )
                            bSplit = TRUE;
                        ni++;
                        nInsert = ni;
                    }
                    else if ( ni > 0 && pData[ni-1].nRow == nStartRow - 1 )
                        nInsert = ni;
                }
                if ( ni > 0 && pData[ni-1].bMarked == bMarked )
                {   // combine
                    pData[ni-1].nRow = nEndRow;
                    nInsert = MAXROW+1;
                    bCombined = TRUE;
                }
            }
            else
                nInsert = ni = 0;

            USHORT nj = ni;     // stop position of range to replace
            while ( nj < nCount && pData[nj].nRow <= nEndRow )
                nj++;
            if ( !bSplit )
            {
                if ( nj < nCount && pData[nj].bMarked == bMarked )
                {   // combine
                    if ( ni > 0 )
                    {
                        if ( pData[ni-1].bMarked == bMarked )
                        {   // adjacent entries
                            pData[ni-1].nRow = pData[nj].nRow;
                            nj++;
                        }
                        else if ( nj == nInsert && nj == ni )
                            pData[ni-1].nRow = nStartRow - 1;   // shrink
                    }
                    nInsert = MAXROW+1;
                    bCombined = TRUE;
                }
                else if ( ni > 0 && ni == nInsert )
                    pData[ni-1].nRow = nStartRow - 1;   // shrink
            }
            if ( ni < nj )
            {   // remove middle entries
                if ( !bCombined )
                {   // replace one entry
                    pData[ni].nRow = nEndRow;
                    pData[ni].bMarked = bMarked;
                    ni++;
                    nInsert = MAXROW+1;
                }
                if ( ni < nj )
                {   // remove entries
                    memmove( pData + ni, pData + nj, (nCount - nj) * sizeof(ScMarkEntry) );
                    nCount -= nj - ni;
                }
            }

            if ( nInsert <= MAXROW )
            {   // insert or append new entry
                if ( nInsert <= nCount )
                {
                    if ( !bSplit )
                        memmove( pData + nInsert + 1, pData + nInsert,
                            (nCount - nInsert) * sizeof(ScMarkEntry) );
                    else
                    {
                        memmove( pData + nInsert + 2, pData + nInsert,
                            (nCount - nInsert) * sizeof(ScMarkEntry) );
                        pData[nInsert+1] = pData[nInsert-1];
                        nCount++;
                    }
                }
                if ( nInsert )
                    pData[nInsert-1].nRow = nStartRow - 1;
                pData[nInsert].nRow = nEndRow;
                pData[nInsert].bMarked = bMarked;
                nCount++;
            }
        }
    }
//  InfoBox(0, String(nCount) + String(" Eintraege") ).Execute();
}

void ScMarkArray::DeleteArea(USHORT nStartRow, USHORT nEndRow)
{
    SetMarkArea(nStartRow, nEndRow, FALSE);
}

BOOL ScMarkArray::IsAllMarked( USHORT nStartRow, USHORT nEndRow ) const
{
    short nStartIndex;
    short nEndIndex;

    if (Search( nStartRow, nStartIndex ))
        if (pData[nStartIndex].bMarked)
            if (Search( nEndRow, nEndIndex ))
                if (nEndIndex==nStartIndex)
                    return TRUE;

    return FALSE;
}

BOOL ScMarkArray::HasOneMark( USHORT& rStartRow, USHORT& rEndRow ) const
{
    BOOL bRet = FALSE;
    if ( nCount == 1 )
    {
        if ( pData[0].bMarked )
        {
            rStartRow = 0;
            rEndRow = MAXROW;
            bRet = TRUE;
        }
    }
    else if ( nCount == 2 )
    {
        if ( pData[0].bMarked )
        {
            rStartRow = 0;
            rEndRow = pData[0].nRow;
        }
        else
        {
            rStartRow = pData[0].nRow + 1;
            rEndRow = MAXROW;
        }
        bRet = TRUE;
    }
    else if ( nCount == 3 )
    {
        if ( pData[1].bMarked )
        {
            rStartRow = pData[0].nRow + 1;
            rEndRow = pData[1].nRow;
            bRet = TRUE;
        }
    }
    return bRet;
}

BOOL ScMarkArray::HasMarks() const
{
    return ( nCount > 1 || pData[0].bMarked );
}

void ScMarkArray::SwapCol(ScMarkArray& rMarkArray)
{
    USHORT nTemp = rMarkArray.nCount;
    rMarkArray.nCount = nCount;
    nCount = nTemp;

    nTemp = rMarkArray.nLimit;
    rMarkArray.nLimit = nLimit;
    nLimit = nTemp;

    ScMarkEntry* pTemp = rMarkArray.pData;
    rMarkArray.pData = pData;
    pData = pTemp;
}

void ScMarkArray::MoveTo(USHORT nStartRow, USHORT nEndRow, ScMarkArray& rMarkArray)
{
    USHORT nStart = nStartRow;
    for (USHORT i = 0; i < nCount; i++)
    {
        if ((pData[i].nRow >= nStartRow) && ((i==0) ? TRUE : pData[i-1].nRow < nEndRow))
        {
            rMarkArray.SetMarkArea(nStart, Min(pData[i].nRow,nEndRow), pData[i].bMarked);
        }
        nStart = Max((USHORT)nStart, (USHORT)(pData[i].nRow + 1) );
    }
    DeleteArea(nStartRow, nEndRow);
}

void ScMarkArray::CopyMarksTo( ScMarkArray& rDestMarkArray ) const
{
    if (rDestMarkArray.pData)
        delete rDestMarkArray.pData;

    if (pData)
    {
        rDestMarkArray.pData = new ScMarkEntry[nCount];
        memmove( rDestMarkArray.pData, pData, nCount * sizeof(ScMarkEntry) );
    }
    else
        rDestMarkArray.pData = NULL;

    rDestMarkArray.nCount = rDestMarkArray.nLimit = nCount;
}

short ScMarkArray::GetNextMarked( short nRow, BOOL bUp ) const
{
    short nRet = nRow;
    if (VALIDROW(nRow))
    {
        short nIndex;
        Search(nRow, nIndex);
        if (!pData[nIndex].bMarked)
        {
            if (bUp)
            {
                if (nIndex>0)
                    nRet = pData[nIndex-1].nRow;
                else
                    nRet = -1;
            }
            else
                nRet = pData[nIndex].nRow + 1;
        }
    }
    return nRet;
}

USHORT ScMarkArray::GetMarkEnd( USHORT nRow, BOOL bUp ) const
{
    USHORT nRet;
    short nIndex;
    Search(nRow, nIndex);
    DBG_ASSERT( pData[nIndex].bMarked, "GetMarkEnd ohne bMarked" );
    if (bUp)
    {
        if (nIndex>0)
            nRet = pData[nIndex-1].nRow + 1;
        else
            nRet = 0;
    }
    else
        nRet = pData[nIndex].nRow;

    return nRet;
}

//
//  -------------- Iterator ----------------------------------------------
//

ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
    pArray( pNewArray ),
    nPos( 0 )
{
}

ScMarkArrayIter::~ScMarkArrayIter()
{
}

BOOL ScMarkArrayIter::Next( USHORT& rTop, USHORT& rBottom )
{
    if ( nPos >= pArray->nCount )
        return FALSE;
    while (!pArray->pData[nPos].bMarked)
    {
        ++nPos;
        if ( nPos >= pArray->nCount )
            return FALSE;
    }
    rBottom = pArray->pData[nPos].nRow;
    if (nPos==0)
        rTop = 0;
    else
        rTop = pArray->pData[nPos-1].nRow + 1;
    ++nPos;
    return TRUE;
}

<commit_msg>#96630# SetMarkArea: shrink predecessor also if multiple areas are thrown away and combined<commit_after>/*************************************************************************
 *
 *  $RCSfile: markarr.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: er $ $Date: 2002-01-18 16:58:05 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "core_pch.hxx"
#endif

#pragma hdrstop

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

#include <tools/debug.hxx>

#include "markarr.hxx"
#include "global.hxx"

// STATIC DATA -----------------------------------------------------------

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

ScMarkArray::ScMarkArray()
{
    nCount = nLimit = 1;
    pData = new ScMarkEntry[1];
    if (pData)
    {
        pData[0].nRow = MAXROW;
        pData[0].bMarked = FALSE;
    }
}

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

ScMarkArray::~ScMarkArray()
{
    if (pData)
        delete[] pData;
}

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

void ScMarkArray::Reset( BOOL bMarked )
{
    if (pData)
    {
        delete[] pData;

        nCount = nLimit = 1;
        pData = new ScMarkEntry[1];
        if (pData)
        {
            pData[0].nRow = MAXROW;
            pData[0].bMarked = bMarked;
        }
    }
}

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

BOOL ScMarkArray::Search( USHORT nRow, short& nIndex ) const
{
    short   nLo         = 0;
    short   nHi         = ((short) nCount) - 1;
    short   nStartRow   = 0;
    short   nEndRow     = 0;
    short   i           = 0;
    BOOL    bFound      = (nCount == 1);
    if (pData)
    {
        while ( !bFound && nLo <= nHi )
        {
            i = (nLo + nHi) / 2;
            if (i > 0)
                nStartRow = (short) pData[i - 1].nRow;
            else
                nStartRow = -1;
            nEndRow = (short) pData[i].nRow;
            if (nEndRow < (short) nRow)
                nLo = ++i;
            else
                if (nStartRow >= (short) nRow)
                    nHi = --i;
                else
                    bFound = TRUE;
        }
    }
    else
        bFound = FALSE;

    if (bFound)
        nIndex=i;
    else
        nIndex=0;
    return bFound;
}

BOOL ScMarkArray::GetMark( USHORT nRow ) const
{
    short i;
    if (Search( nRow, i ))
        return pData[i].bMarked;
    else
        return FALSE;

}

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

void ScMarkArray::SetMark( USHORT nRow, BOOL bMarked )
{
    SetMarkArea( nRow, nRow, bMarked );
}

void ScMarkArray::SetMarkArea( USHORT nStartRow, USHORT nEndRow, BOOL bMarked )
{
    if ((nStartRow >= 0 && nStartRow <= MAXROW) && (nEndRow >= 0 && nEndRow <= MAXROW))
    {
        if ((nStartRow == 0) && (nEndRow == MAXROW))
        {
            Reset(bMarked);
        }
        else
        {
            USHORT nNeeded = nCount + 2;
            if ( nLimit < nNeeded )
            {
                nLimit += SC_MARKARRAY_DELTA;
                if ( nLimit < nNeeded )
                    nLimit = nNeeded;
                ScMarkEntry* pNewData = new ScMarkEntry[nLimit];
                memcpy( pNewData, pData, nCount*sizeof(ScMarkEntry) );
                delete[] pData;
                pData = pNewData;
            }

            USHORT ni;          // number of entries in beginning
            USHORT nInsert;     // insert position (MAXROW+1 := no insert)
            BOOL bCombined = FALSE;
            BOOL bSplit = FALSE;
            if ( nStartRow > 0 )
            {
                // skip beginning
                short nIndex;
                Search( nStartRow, nIndex );
                ni = nIndex;

                nInsert = MAXROW+1;
                if ( pData[ni].bMarked != bMarked )
                {
                    if ( ni == 0 || (pData[ni-1].nRow < nStartRow - 1) )
                    {   // may be a split or a simple insert or just a shrink,
                        // row adjustment is done further down
                        if ( pData[ni].nRow > nEndRow )
                            bSplit = TRUE;
                        ni++;
                        nInsert = ni;
                    }
                    else if ( ni > 0 && pData[ni-1].nRow == nStartRow - 1 )
                        nInsert = ni;
                }
                if ( ni > 0 && pData[ni-1].bMarked == bMarked )
                {   // combine
                    pData[ni-1].nRow = nEndRow;
                    nInsert = MAXROW+1;
                    bCombined = TRUE;
                }
            }
            else
                nInsert = ni = 0;

            USHORT nj = ni;     // stop position of range to replace
            while ( nj < nCount && pData[nj].nRow <= nEndRow )
                nj++;
            if ( !bSplit )
            {
                if ( nj < nCount && pData[nj].bMarked == bMarked )
                {   // combine
                    if ( ni > 0 )
                    {
                        if ( pData[ni-1].bMarked == bMarked )
                        {   // adjacent entries
                            pData[ni-1].nRow = pData[nj].nRow;
                            nj++;
                        }
                        else if ( ni == nInsert )
                            pData[ni-1].nRow = nStartRow - 1;   // shrink
                    }
                    nInsert = MAXROW+1;
                    bCombined = TRUE;
                }
                else if ( ni > 0 && ni == nInsert )
                    pData[ni-1].nRow = nStartRow - 1;   // shrink
            }
            if ( ni < nj )
            {   // remove middle entries
                if ( !bCombined )
                {   // replace one entry
                    pData[ni].nRow = nEndRow;
                    pData[ni].bMarked = bMarked;
                    ni++;
                    nInsert = MAXROW+1;
                }
                if ( ni < nj )
                {   // remove entries
                    memmove( pData + ni, pData + nj, (nCount - nj) * sizeof(ScMarkEntry) );
                    nCount -= nj - ni;
                }
            }

            if ( nInsert <= MAXROW )
            {   // insert or append new entry
                if ( nInsert <= nCount )
                {
                    if ( !bSplit )
                        memmove( pData + nInsert + 1, pData + nInsert,
                            (nCount - nInsert) * sizeof(ScMarkEntry) );
                    else
                    {
                        memmove( pData + nInsert + 2, pData + nInsert,
                            (nCount - nInsert) * sizeof(ScMarkEntry) );
                        pData[nInsert+1] = pData[nInsert-1];
                        nCount++;
                    }
                }
                if ( nInsert )
                    pData[nInsert-1].nRow = nStartRow - 1;
                pData[nInsert].nRow = nEndRow;
                pData[nInsert].bMarked = bMarked;
                nCount++;
            }
        }
    }
//  InfoBox(0, String(nCount) + String(" Eintraege") ).Execute();
}

void ScMarkArray::DeleteArea(USHORT nStartRow, USHORT nEndRow)
{
    SetMarkArea(nStartRow, nEndRow, FALSE);
}

BOOL ScMarkArray::IsAllMarked( USHORT nStartRow, USHORT nEndRow ) const
{
    short nStartIndex;
    short nEndIndex;

    if (Search( nStartRow, nStartIndex ))
        if (pData[nStartIndex].bMarked)
            if (Search( nEndRow, nEndIndex ))
                if (nEndIndex==nStartIndex)
                    return TRUE;

    return FALSE;
}

BOOL ScMarkArray::HasOneMark( USHORT& rStartRow, USHORT& rEndRow ) const
{
    BOOL bRet = FALSE;
    if ( nCount == 1 )
    {
        if ( pData[0].bMarked )
        {
            rStartRow = 0;
            rEndRow = MAXROW;
            bRet = TRUE;
        }
    }
    else if ( nCount == 2 )
    {
        if ( pData[0].bMarked )
        {
            rStartRow = 0;
            rEndRow = pData[0].nRow;
        }
        else
        {
            rStartRow = pData[0].nRow + 1;
            rEndRow = MAXROW;
        }
        bRet = TRUE;
    }
    else if ( nCount == 3 )
    {
        if ( pData[1].bMarked )
        {
            rStartRow = pData[0].nRow + 1;
            rEndRow = pData[1].nRow;
            bRet = TRUE;
        }
    }
    return bRet;
}

BOOL ScMarkArray::HasMarks() const
{
    return ( nCount > 1 || pData[0].bMarked );
}

void ScMarkArray::SwapCol(ScMarkArray& rMarkArray)
{
    USHORT nTemp = rMarkArray.nCount;
    rMarkArray.nCount = nCount;
    nCount = nTemp;

    nTemp = rMarkArray.nLimit;
    rMarkArray.nLimit = nLimit;
    nLimit = nTemp;

    ScMarkEntry* pTemp = rMarkArray.pData;
    rMarkArray.pData = pData;
    pData = pTemp;
}

void ScMarkArray::MoveTo(USHORT nStartRow, USHORT nEndRow, ScMarkArray& rMarkArray)
{
    USHORT nStart = nStartRow;
    for (USHORT i = 0; i < nCount; i++)
    {
        if ((pData[i].nRow >= nStartRow) && ((i==0) ? TRUE : pData[i-1].nRow < nEndRow))
        {
            rMarkArray.SetMarkArea(nStart, Min(pData[i].nRow,nEndRow), pData[i].bMarked);
        }
        nStart = Max((USHORT)nStart, (USHORT)(pData[i].nRow + 1) );
    }
    DeleteArea(nStartRow, nEndRow);
}

void ScMarkArray::CopyMarksTo( ScMarkArray& rDestMarkArray ) const
{
    if (rDestMarkArray.pData)
        delete rDestMarkArray.pData;

    if (pData)
    {
        rDestMarkArray.pData = new ScMarkEntry[nCount];
        memmove( rDestMarkArray.pData, pData, nCount * sizeof(ScMarkEntry) );
    }
    else
        rDestMarkArray.pData = NULL;

    rDestMarkArray.nCount = rDestMarkArray.nLimit = nCount;
}

short ScMarkArray::GetNextMarked( short nRow, BOOL bUp ) const
{
    short nRet = nRow;
    if (VALIDROW(nRow))
    {
        short nIndex;
        Search(nRow, nIndex);
        if (!pData[nIndex].bMarked)
        {
            if (bUp)
            {
                if (nIndex>0)
                    nRet = pData[nIndex-1].nRow;
                else
                    nRet = -1;
            }
            else
                nRet = pData[nIndex].nRow + 1;
        }
    }
    return nRet;
}

USHORT ScMarkArray::GetMarkEnd( USHORT nRow, BOOL bUp ) const
{
    USHORT nRet;
    short nIndex;
    Search(nRow, nIndex);
    DBG_ASSERT( pData[nIndex].bMarked, "GetMarkEnd ohne bMarked" );
    if (bUp)
    {
        if (nIndex>0)
            nRet = pData[nIndex-1].nRow + 1;
        else
            nRet = 0;
    }
    else
        nRet = pData[nIndex].nRow;

    return nRet;
}

//
//  -------------- Iterator ----------------------------------------------
//

ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
    pArray( pNewArray ),
    nPos( 0 )
{
}

ScMarkArrayIter::~ScMarkArrayIter()
{
}

BOOL ScMarkArrayIter::Next( USHORT& rTop, USHORT& rBottom )
{
    if ( nPos >= pArray->nCount )
        return FALSE;
    while (!pArray->pData[nPos].bMarked)
    {
        ++nPos;
        if ( nPos >= pArray->nCount )
            return FALSE;
    }
    rBottom = pArray->pData[nPos].nRow;
    if (nPos==0)
        rTop = 0;
    else
        rTop = pArray->pData[nPos-1].nRow + 1;
    ++nPos;
    return TRUE;
}

<|endoftext|>


<commit_before><commit_msg>properly inherit relative and 3D flags when extending, tdf#83365 related<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: formel.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: vg $ $Date: 2007-02-27 12:33:39 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _FORMEL_HXX
#define _FORMEL_HXX

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif
#ifndef _LIST_HXX
#include <tools/list.hxx>
#endif
#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif

#ifndef _TOKSTACK_HXX
#include "tokstack.hxx"
#endif
#ifndef _ROOT_HXX
#include "root.hxx"
#endif
#ifndef SC_SCGLOB_HXX
#include <global.hxx>
#endif
#ifndef SC_COMPILER_HXX
#include <compiler.hxx>
#endif

// ----- forwards --------------------------------------------------------

class XclImpStream;
class ScTokenArray;
class ScFormulaCell;
struct SingleRefData;
struct ComplRefData;

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

enum ConvErr
{
    ConvOK = 0,
    ConvErrNi,      // nicht implemntierter/unbekannter Opcode aufgetreten
    ConvErrNoMem,   // Fehler beim Speicheranfordern
    ConvErrExternal,// Add-Ins aus Excel werden nicht umgesetzt
    ConvErrCount    // Nicht alle Bytes der Formel 'erwischt'
};

enum FORMULA_TYPE
{
    FT_CellFormula,
    FT_RangeName,
    FT_SharedFormula
};

//--------------------------------------------------------- class ScRangeList -

class _ScRangeList : protected List
{
private:
protected:
public:
    virtual                 ~_ScRangeList();
    inline void             Append( const ScRange& rRange );
    inline void             Append( ScRange* pRange );
    inline void             Append( const SingleRefData& rSRD );
    inline void             Append( const ComplRefData& rCRD );

    using                   List::Count;
    inline BOOL             HasRanges( void ) const;

    inline const ScRange*   First( void );
    inline const ScRange*   Next( void );
};

inline void _ScRangeList::Append( const ScRange& r )
{
    List::Insert( new ScRange( r ), LIST_APPEND );
}

inline void _ScRangeList::Append( ScRange* p )
{
    List::Insert( p, LIST_APPEND );
}

inline BOOL _ScRangeList::HasRanges( void ) const
{
    return Count() > 0;
}

inline const ScRange* _ScRangeList::First( void )
{
    return ( const ScRange* ) List::First();
}

inline const ScRange* _ScRangeList::Next( void )
{
    return ( const ScRange* ) List::Next();
}

inline void _ScRangeList::Append( const SingleRefData& r )
{
    List::Insert( new ScRange( r.nCol, r.nRow, r.nTab ), LIST_APPEND );
}

inline void _ScRangeList::Append( const ComplRefData& r )
{
    List::Insert(   new ScRange(    r.Ref1.nCol, r.Ref1.nRow, r.Ref1.nTab,
                                    r.Ref2.nCol, r.Ref2.nRow, r.Ref2.nTab ),
                    LIST_APPEND );
}

//----------------------------------------------------- class ScRangeListTabs -

class _ScRangeListTabs
{
private:
protected:
    BOOL                        bHasRanges;
    _ScRangeList**              ppTabLists;
    _ScRangeList*               pAct;
    UINT16                      nAct;
public:
                                _ScRangeListTabs( void );
    virtual                     ~_ScRangeListTabs();

    void                        Append( SingleRefData aSRD, const BOOL bLimit = TRUE );
    void                        Append( ComplRefData aCRD, const BOOL bLimit = TRUE );

    inline BOOL                 HasRanges( void ) const;

    const ScRange*              First( const UINT16 nTab = 0 );
    const ScRange*              Next( void );
//      const ScRange*              NextContinue( void );
    inline const _ScRangeList*  GetActList( void ) const;
};

inline BOOL _ScRangeListTabs::HasRanges( void ) const
{
    return bHasRanges;
}

inline const _ScRangeList* _ScRangeListTabs::GetActList( void ) const
{
    return pAct;
}

class ConverterBase
{
protected:
    TokenPool           aPool;          // User Token + Predefined Token
    TokenStack          aStack;
    ScAddress           aEingPos;
    ConvErr             eStatus;
    sal_Char*           pBuffer;        // Universal-Puffer
    UINT16              nBufferSize;    // ...und seine Groesse

                        ConverterBase( UINT16 nNewBuffer );
    virtual             ~ConverterBase();

    void                Reset();

public:
    inline SCCOL        GetEingabeCol( void ) const { return aEingPos.Col(); }
    inline SCROW        GetEingabeRow( void ) const { return aEingPos.Row(); }
    inline SCTAB        GetEingabeTab( void ) const { return aEingPos.Tab(); }
    inline ScAddress    GetEingPos( void ) const    { return aEingPos; }
};

class ExcelConverterBase : public ConverterBase
{
protected:
                        ExcelConverterBase( UINT16 nNewBuffer );
    virtual             ~ExcelConverterBase();

public:
    void                Reset();
    void                Reset( const ScAddress& rEingPos );

    virtual ConvErr     Convert( const ScTokenArray*& rpErg, XclImpStream& rStrm, sal_Size nFormulaLen,
                                    const FORMULA_TYPE eFT = FT_CellFormula ) = 0;
    virtual ConvErr     Convert( _ScRangeListTabs&, XclImpStream& rStrm, sal_Size nFormulaLen,
                                    const FORMULA_TYPE eFT = FT_CellFormula ) = 0;
};

class LotusConverterBase : public ConverterBase
{
protected:
    SvStream&           aIn;
    INT32               nBytesLeft;

    inline void         Ignore( const long nSeekRel );
    inline void         Read( sal_Char& nByte );
    inline void         Read( BYTE& nByte );
    inline void         Read( UINT16& nUINT16 );
    inline void         Read( INT16& nINT16 );
    inline void         Read( double& fDouble );
        inline void                     Read( UINT32& nUINT32 );

                        LotusConverterBase( SvStream& rStr, UINT16 nNewBuffer );
    virtual             ~LotusConverterBase();

public:
    void                Reset( INT32 nLen );
    void                Reset( INT32 nLen, const ScAddress& rEingPos );
    void                Reset( const ScAddress& rEingPos );

    virtual ConvErr     Convert( const ScTokenArray*& rpErg, INT32& nRest,
                                    const FORMULA_TYPE eFT = FT_CellFormula ) = 0;

protected:
    using               ConverterBase::Reset;
};

inline void LotusConverterBase::Ignore( const long nSeekRel )
{
    aIn.SeekRel( nSeekRel );
    nBytesLeft -= nSeekRel;
}

inline void LotusConverterBase::Read( sal_Char& nByte )
{
    aIn >> nByte;
    nBytesLeft--;
}

inline void LotusConverterBase::Read( BYTE& nByte )
{
    aIn >> nByte;
    nBytesLeft--;
}

inline void LotusConverterBase::Read( UINT16& nUINT16 )
{
    aIn >> nUINT16;
    nBytesLeft -= 2;
}

inline void LotusConverterBase::Read( INT16& nINT16 )
{
    aIn >> nINT16;
    nBytesLeft -= 2;
}

inline void LotusConverterBase::Read( double& fDouble )
{
    aIn >> fDouble;
    nBytesLeft -= 8;
}

inline void LotusConverterBase::Read( UINT32& nUINT32 )
{
    aIn >> nUINT32;
    nBytesLeft -= 4;
}

#endif

<commit_msg>INTEGRATION: CWS jgarrays (1.9.52); FILE MERGED 2007/04/26 12:26:06 jodygoldberg 1.9.52.1: Issue number:  32342 Submitted by:  jodygoldberg Reviewed by:   er,dr<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: formel.hxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: obo $ $Date: 2007-06-13 09:11:54 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _FORMEL_HXX
#define _FORMEL_HXX

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif
#ifndef _LIST_HXX
#include <tools/list.hxx>
#endif
#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif

#ifndef _TOKSTACK_HXX
#include "tokstack.hxx"
#endif
#ifndef _ROOT_HXX
#include "root.hxx"
#endif
#ifndef SC_SCGLOB_HXX
#include <global.hxx>
#endif
#ifndef SC_COMPILER_HXX
#include <compiler.hxx>
#endif

// ----- forwards --------------------------------------------------------

class XclImpStream;
class ScTokenArray;
class ScFormulaCell;
struct SingleRefData;
struct ComplRefData;

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

enum ConvErr
{
    ConvOK = 0,
    ConvErrNi,      // nicht implemntierter/unbekannter Opcode aufgetreten
    ConvErrNoMem,   // Fehler beim Speicheranfordern
    ConvErrExternal,// Add-Ins aus Excel werden nicht umgesetzt
    ConvErrCount    // Nicht alle Bytes der Formel 'erwischt'
};

enum FORMULA_TYPE
{
    FT_CellFormula,
    FT_RangeName,
    FT_SharedFormula
};

//--------------------------------------------------------- class ScRangeList -

class _ScRangeList : protected List
{
private:
protected:
public:
    virtual                 ~_ScRangeList();
    inline void             Append( const ScRange& rRange );
    inline void             Append( ScRange* pRange );
    inline void             Append( const SingleRefData& rSRD );
    inline void             Append( const ComplRefData& rCRD );

    using                   List::Count;
    inline BOOL             HasRanges( void ) const;

    inline const ScRange*   First( void );
    inline const ScRange*   Next( void );
};

inline void _ScRangeList::Append( const ScRange& r )
{
    List::Insert( new ScRange( r ), LIST_APPEND );
}

inline void _ScRangeList::Append( ScRange* p )
{
    List::Insert( p, LIST_APPEND );
}

inline BOOL _ScRangeList::HasRanges( void ) const
{
    return Count() > 0;
}

inline const ScRange* _ScRangeList::First( void )
{
    return ( const ScRange* ) List::First();
}

inline const ScRange* _ScRangeList::Next( void )
{
    return ( const ScRange* ) List::Next();
}

inline void _ScRangeList::Append( const SingleRefData& r )
{
    List::Insert( new ScRange( r.nCol, r.nRow, r.nTab ), LIST_APPEND );
}

inline void _ScRangeList::Append( const ComplRefData& r )
{
    List::Insert(   new ScRange(    r.Ref1.nCol, r.Ref1.nRow, r.Ref1.nTab,
                                    r.Ref2.nCol, r.Ref2.nRow, r.Ref2.nTab ),
                    LIST_APPEND );
}

//----------------------------------------------------- class ScRangeListTabs -

class _ScRangeListTabs
{
private:
protected:
    BOOL                        bHasRanges;
    _ScRangeList**              ppTabLists;
    _ScRangeList*               pAct;
    UINT16                      nAct;
public:
                                _ScRangeListTabs( void );
    virtual                     ~_ScRangeListTabs();

    void                        Append( SingleRefData aSRD, const BOOL bLimit = TRUE );
    void                        Append( ComplRefData aCRD, const BOOL bLimit = TRUE );

    inline BOOL                 HasRanges( void ) const;

    const ScRange*              First( const UINT16 nTab = 0 );
    const ScRange*              Next( void );
//      const ScRange*              NextContinue( void );
    inline const _ScRangeList*  GetActList( void ) const;
};

inline BOOL _ScRangeListTabs::HasRanges( void ) const
{
    return bHasRanges;
}

inline const _ScRangeList* _ScRangeListTabs::GetActList( void ) const
{
    return pAct;
}

class ConverterBase
{
protected:
    TokenPool           aPool;          // User Token + Predefined Token
    TokenStack          aStack;
    ScAddress           aEingPos;
    ConvErr             eStatus;
    sal_Char*           pBuffer;        // Universal-Puffer
    UINT16              nBufferSize;    // ...und seine Groesse

                        ConverterBase( UINT16 nNewBuffer );
    virtual             ~ConverterBase();

    void                Reset();

public:
    inline SCCOL        GetEingabeCol( void ) const { return aEingPos.Col(); }
    inline SCROW        GetEingabeRow( void ) const { return aEingPos.Row(); }
    inline SCTAB        GetEingabeTab( void ) const { return aEingPos.Tab(); }
    inline ScAddress    GetEingPos( void ) const    { return aEingPos; }
};

class ExcelConverterBase : public ConverterBase
{
protected:
                        ExcelConverterBase( UINT16 nNewBuffer );
    virtual             ~ExcelConverterBase();

public:
    void                Reset();
    void                Reset( const ScAddress& rEingPos );

    virtual ConvErr     Convert( const ScTokenArray*& rpErg, XclImpStream& rStrm, sal_Size nFormulaLen,
                                 bool bAllowArrays, const FORMULA_TYPE eFT = FT_CellFormula ) = 0;
    virtual ConvErr     Convert( _ScRangeListTabs&, XclImpStream& rStrm, sal_Size nFormulaLen,
                                    const FORMULA_TYPE eFT = FT_CellFormula ) = 0;
};

class LotusConverterBase : public ConverterBase
{
protected:
    SvStream&           aIn;
    INT32               nBytesLeft;

    inline void         Ignore( const long nSeekRel );
    inline void         Read( sal_Char& nByte );
    inline void         Read( BYTE& nByte );
    inline void         Read( UINT16& nUINT16 );
    inline void         Read( INT16& nINT16 );
    inline void         Read( double& fDouble );
        inline void                     Read( UINT32& nUINT32 );

                        LotusConverterBase( SvStream& rStr, UINT16 nNewBuffer );
    virtual             ~LotusConverterBase();

public:
    void                Reset( INT32 nLen );
    void                Reset( INT32 nLen, const ScAddress& rEingPos );
    void                Reset( const ScAddress& rEingPos );

    virtual ConvErr     Convert( const ScTokenArray*& rpErg, INT32& nRest,
                                    const FORMULA_TYPE eFT = FT_CellFormula ) = 0;

protected:
    using               ConverterBase::Reset;
};

inline void LotusConverterBase::Ignore( const long nSeekRel )
{
    aIn.SeekRel( nSeekRel );
    nBytesLeft -= nSeekRel;
}

inline void LotusConverterBase::Read( sal_Char& nByte )
{
    aIn >> nByte;
    nBytesLeft--;
}

inline void LotusConverterBase::Read( BYTE& nByte )
{
    aIn >> nByte;
    nBytesLeft--;
}

inline void LotusConverterBase::Read( UINT16& nUINT16 )
{
    aIn >> nUINT16;
    nBytesLeft -= 2;
}

inline void LotusConverterBase::Read( INT16& nINT16 )
{
    aIn >> nINT16;
    nBytesLeft -= 2;
}

inline void LotusConverterBase::Read( double& fDouble )
{
    aIn >> fDouble;
    nBytesLeft -= 8;
}

inline void LotusConverterBase::Read( UINT32& nUINT32 )
{
    aIn >> nUINT32;
    nBytesLeft -= 4;
}

#endif

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xeroot.hxx,v $
 *
 *  $Revision: 1.18 $
 *
 *  last change: $Author: obo $ $Date: 2006-03-22 12:07:50 $
 *
 *  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
 *
 ************************************************************************/

#ifndef SC_XEROOT_HXX
#define SC_XEROOT_HXX

#ifndef SC_XLROOT_HXX
#include "xlroot.hxx"
#endif

// Forward declarations of objects in public use ==============================

class XclExpStream;
class XclExpRecordBase;
class XclExpString;
class XclExpTokenArray;

typedef ScfRef< XclExpRecordBase >  XclExpRecordRef;
typedef ScfRef< XclExpString >      XclExpStringRef;
typedef ScfRef< XclExpTokenArray >  XclExpTokenArrayRef;

// Global data ================================================================

class XclExpTabInfo;
class XclExpAddressConverter;
class XclExpFormulaCompiler;
class XclExpProgressBar;
class XclExpSst;
class XclExpPalette;
class XclExpFontBuffer;
class XclExpNumFmtBuffer;
class XclExpXFBuffer;
class XclExpLinkManager;
class XclExpNameManager;
class XclExpFilterManager;
class XclExpPivotTableManager;

/** Stores global buffers and data needed for Excel export filter. */
struct XclExpRootData : public XclRootData
{
    typedef ScfRef< XclExpTabInfo >             XclExpTabInfoRef;
    typedef ScfRef< XclExpAddressConverter >    XclExpAddrConvRef;
    typedef ScfRef< XclExpFormulaCompiler >     XclExpFmlaCompRef;
    typedef ScfRef< XclExpProgressBar >         XclExpProgressRef;

    typedef ScfRef< XclExpSst >                 XclExpSstRef;
    typedef ScfRef< XclExpPalette >             XclExpPaletteRef;
    typedef ScfRef< XclExpFontBuffer >          XclExpFontBfrRef;
    typedef ScfRef< XclExpNumFmtBuffer >        XclExpNumFmtBfrRef;
    typedef ScfRef< XclExpXFBuffer >            XclExpXFBfrRef;
    typedef ScfRef< XclExpNameManager >         XclExpNameMgrRef;
    typedef ScfRef< XclExpLinkManager >         XclExpLinkMgrRef;
    typedef ScfRef< XclExpFilterManager >       XclExpFilterMgrRef;
    typedef ScfRef< XclExpPivotTableManager >   XclExpPTableMgrRef;

    XclExpTabInfoRef    mxTabInfo;          /// Calc->Excel sheet index conversion.
    XclExpAddrConvRef   mxAddrConv;         /// The address converter.
    XclExpFmlaCompRef   mxFmlaComp;         /// The formula compiler.
    XclExpProgressRef   mxProgress;         /// The export progress bar.

    XclExpSstRef        mxSst;              /// The shared string table.
    XclExpPaletteRef    mxPalette;          /// The color buffer.
    XclExpFontBfrRef    mxFontBfr;          /// All fonts in the file.
    XclExpNumFmtBfrRef  mxNumFmtBfr;        /// All number formats in the file.
    XclExpXFBfrRef      mxXFBfr;            /// All XF records in the file.
    XclExpNameMgrRef    mxNameMgr;          /// Internal defined names.
    XclExpLinkMgrRef    mxGlobLinkMgr;      /// Global link manager for defined names.
    XclExpLinkMgrRef    mxLocLinkMgr;       /// Local link manager for a sheet.
    XclExpFilterMgrRef  mxFilterMgr;        /// Manager for filtered areas in all sheets.
    XclExpPTableMgrRef  mxPTableMgr;        /// All pivot tables and pivot caches.

    bool                mbRelUrl;           /// true = Store URLs relative.

    explicit            XclExpRootData( XclBiff eBiff, SfxMedium& rMedium,
                            SotStorageRef xRootStrg, ScDocument& rDoc, CharSet eCharSet );
    virtual             ~XclExpRootData();
};

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

/** Access to global data from other classes. */
class XclExpRoot : public XclRoot
{
public:
    explicit            XclExpRoot( XclExpRootData& rExpRootData );

    /** Returns this root instance - for code readability in derived classes. */
    inline const XclExpRoot& GetRoot() const { return *this; }
    /** Returns true, if URLs should be stored relative to the document location. */
    inline bool         IsRelUrl() const { return mrExpData.mbRelUrl; }

    /** Returns the buffer for Calc->Excel sheet index conversion. */
    XclExpTabInfo&      GetTabInfo() const;
    /** Returns the address converter. */
    XclExpAddressConverter& GetAddressConverter() const;
    /** Returns the formula compiler to produce formula token arrays. */
    XclExpFormulaCompiler& GetFormulaCompiler() const;
    /** Returns the export progress bar. */
    XclExpProgressBar&  GetProgressBar() const;

    /** Returns the shared string table. */
    XclExpSst&          GetSst() const;
    /** Returns the color buffer. */
    XclExpPalette&      GetPalette() const;
    /** Returns the font buffer. */
    XclExpFontBuffer&   GetFontBuffer() const;
    /** Returns the number format buffer. */
    XclExpNumFmtBuffer& GetNumFmtBuffer() const;
    /** Returns the cell formatting attributes buffer. */
    XclExpXFBuffer&     GetXFBuffer() const;
    /** Returns the global link manager for defined names. */
    XclExpLinkManager&  GetGlobalLinkManager() const;
    /** Returns the local link manager for the current sheet. */
    XclExpLinkManager&  GetLocalLinkManager() const;
    /** Returns the buffer that contains internal defined names. */
    XclExpNameManager&  GetNameManager() const;
    /** Returns the filter manager. */
    XclExpFilterManager& GetFilterManager() const;
    /** Returns the pivot table manager. */
    XclExpPivotTableManager& GetPivotTableManager() const;

    /** Is called when export filter starts to create the Excel document (all BIFF versions). */
    void                InitializeConvert();
    /** Is called when export filter starts to create the workbook global data (>=BIFF5). */
    void                InitializeGlobals();
    /** Is called when export filter starts to create data for a single sheet (all BIFF versions). */
    void                InitializeTable( SCTAB nScTab );
    /** Is called before export filter starts to write the records to the stream. */
    void                InitializeSave();
    /** Returns the reference to a record (or record list) representing a root object.
        @param nRecId  Identifier that specifies which record is returned. */
    XclExpRecordRef     CreateRecord( sal_uInt16 nRecId ) const;

private:
    /** Returns the local or global link manager, depending on current context. */
    XclExpRootData::XclExpLinkMgrRef GetLocalLinkMgrRef() const;

private:
    mutable XclExpRootData& mrExpData;      /// Reference to the global export data struct.
};

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

#endif

<commit_msg>INTEGRATION: CWS dr48 (1.18.46); FILE MERGED 2006/05/10 17:01:22 dr 1.18.46.1: #i63105# backport changes from CWS chart2mst3<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xeroot.hxx,v $
 *
 *  $Revision: 1.19 $
 *
 *  last change: $Author: obo $ $Date: 2006-07-10 13:55:52 $
 *
 *  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
 *
 ************************************************************************/

#ifndef SC_XEROOT_HXX
#define SC_XEROOT_HXX

#ifndef SC_XLROOT_HXX
#include "xlroot.hxx"
#endif

// Forward declarations of objects in public use ==============================

class XclExpStream;
class XclExpRecordBase;
class XclExpString;

typedef ScfRef< XclExpRecordBase >  XclExpRecordRef;
typedef ScfRef< XclExpString >      XclExpStringRef;

// Global data ================================================================

class XclExpTabInfo;
class XclExpAddressConverter;
class XclExpFormulaCompiler;
class XclExpProgressBar;
class XclExpSst;
class XclExpPalette;
class XclExpFontBuffer;
class XclExpNumFmtBuffer;
class XclExpXFBuffer;
class XclExpLinkManager;
class XclExpNameManager;
class XclExpFilterManager;
class XclExpPivotTableManager;

/** Stores global buffers and data needed for Excel export filter. */
struct XclExpRootData : public XclRootData
{
    typedef ScfRef< XclExpTabInfo >             XclExpTabInfoRef;
    typedef ScfRef< XclExpAddressConverter >    XclExpAddrConvRef;
    typedef ScfRef< XclExpFormulaCompiler >     XclExpFmlaCompRef;
    typedef ScfRef< XclExpProgressBar >         XclExpProgressRef;

    typedef ScfRef< XclExpSst >                 XclExpSstRef;
    typedef ScfRef< XclExpPalette >             XclExpPaletteRef;
    typedef ScfRef< XclExpFontBuffer >          XclExpFontBfrRef;
    typedef ScfRef< XclExpNumFmtBuffer >        XclExpNumFmtBfrRef;
    typedef ScfRef< XclExpXFBuffer >            XclExpXFBfrRef;
    typedef ScfRef< XclExpNameManager >         XclExpNameMgrRef;
    typedef ScfRef< XclExpLinkManager >         XclExpLinkMgrRef;
    typedef ScfRef< XclExpFilterManager >       XclExpFilterMgrRef;
    typedef ScfRef< XclExpPivotTableManager >   XclExpPTableMgrRef;

    XclExpTabInfoRef    mxTabInfo;          /// Calc->Excel sheet index conversion.
    XclExpAddrConvRef   mxAddrConv;         /// The address converter.
    XclExpFmlaCompRef   mxFmlaComp;         /// The formula compiler.
    XclExpProgressRef   mxProgress;         /// The export progress bar.

    XclExpSstRef        mxSst;              /// The shared string table.
    XclExpPaletteRef    mxPalette;          /// The color buffer.
    XclExpFontBfrRef    mxFontBfr;          /// All fonts in the file.
    XclExpNumFmtBfrRef  mxNumFmtBfr;        /// All number formats in the file.
    XclExpXFBfrRef      mxXFBfr;            /// All XF records in the file.
    XclExpNameMgrRef    mxNameMgr;          /// Internal defined names.
    XclExpLinkMgrRef    mxGlobLinkMgr;      /// Global link manager for defined names.
    XclExpLinkMgrRef    mxLocLinkMgr;       /// Local link manager for a sheet.
    XclExpFilterMgrRef  mxFilterMgr;        /// Manager for filtered areas in all sheets.
    XclExpPTableMgrRef  mxPTableMgr;        /// All pivot tables and pivot caches.

    bool                mbRelUrl;           /// true = Store URLs relative.

    explicit            XclExpRootData( XclBiff eBiff, SfxMedium& rMedium,
                            SotStorageRef xRootStrg, ScDocument& rDoc, CharSet eCharSet );
    virtual             ~XclExpRootData();
};

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

/** Access to global data from other classes. */
class XclExpRoot : public XclRoot
{
public:
    explicit            XclExpRoot( XclExpRootData& rExpRootData );

    /** Returns this root instance - for code readability in derived classes. */
    inline const XclExpRoot& GetRoot() const { return *this; }
    /** Returns true, if URLs should be stored relative to the document location. */
    inline bool         IsRelUrl() const { return mrExpData.mbRelUrl; }

    /** Returns the buffer for Calc->Excel sheet index conversion. */
    XclExpTabInfo&      GetTabInfo() const;
    /** Returns the address converter. */
    XclExpAddressConverter& GetAddressConverter() const;
    /** Returns the formula compiler to produce formula token arrays. */
    XclExpFormulaCompiler& GetFormulaCompiler() const;
    /** Returns the export progress bar. */
    XclExpProgressBar&  GetProgressBar() const;

    /** Returns the shared string table. */
    XclExpSst&          GetSst() const;
    /** Returns the color buffer. */
    XclExpPalette&      GetPalette() const;
    /** Returns the font buffer. */
    XclExpFontBuffer&   GetFontBuffer() const;
    /** Returns the number format buffer. */
    XclExpNumFmtBuffer& GetNumFmtBuffer() const;
    /** Returns the cell formatting attributes buffer. */
    XclExpXFBuffer&     GetXFBuffer() const;
    /** Returns the global link manager for defined names. */
    XclExpLinkManager&  GetGlobalLinkManager() const;
    /** Returns the local link manager for the current sheet. */
    XclExpLinkManager&  GetLocalLinkManager() const;
    /** Returns the buffer that contains internal defined names. */
    XclExpNameManager&  GetNameManager() const;
    /** Returns the filter manager. */
    XclExpFilterManager& GetFilterManager() const;
    /** Returns the pivot table manager. */
    XclExpPivotTableManager& GetPivotTableManager() const;

    /** Is called when export filter starts to create the Excel document (all BIFF versions). */
    void                InitializeConvert();
    /** Is called when export filter starts to create the workbook global data (>=BIFF5). */
    void                InitializeGlobals();
    /** Is called when export filter starts to create data for a single sheet (all BIFF versions). */
    void                InitializeTable( SCTAB nScTab );
    /** Is called before export filter starts to write the records to the stream. */
    void                InitializeSave();
    /** Returns the reference to a record (or record list) representing a root object.
        @param nRecId  Identifier that specifies which record is returned. */
    XclExpRecordRef     CreateRecord( sal_uInt16 nRecId ) const;

private:
    /** Returns the local or global link manager, depending on current context. */
    XclExpRootData::XclExpLinkMgrRef GetLocalLinkMgrRef() const;

private:
    mutable XclExpRootData& mrExpData;      /// Reference to the global export data struct.
};

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

#endif

<|endoftext|>