<commit_before>#include "Entity.hpp"

#include <glm/gtc/matrix_transform.hpp>
#include "../Component/Animation.hpp"
#include "../Component/Lens.hpp"
#include "../Component/Mesh.hpp"
#include "../Component/Material.hpp"
#include "../Component/DirectionalLight.hpp"
#include "../Component/PointLight.hpp"
#include "../Component/SpotLight.hpp"
#include "../Component/Physics.hpp"
#include "../Component/Listener.hpp"
#include "../Component/Script.hpp"
#include "../Component/SoundSource.hpp"
#include "../Component/ParticleEmitter.hpp"
#include "../Util/Json.hpp"
#include "../Util/FileSystem.hpp"
#include <Utility/Log.hpp>
#include "../Hymn.hpp"
#include <fstream>
#include "../Manager/Managers.hpp"
#include "../Manager/ParticleManager.hpp"
#include "../Manager/PhysicsManager.hpp"
#include "../Manager/RenderManager.hpp"
#include "../Manager/ScriptManager.hpp"
#include "../Manager/SoundManager.hpp"

Entity::Entity(World* world, const std::string& name) : name ( name ) {
    this->world = world;
}

Entity::~Entity() {

}

Entity* Entity::GetParent() const {
    return parent;
}

Entity* Entity::AddChild(const std::string& name) {
    Entity* child = world->CreateEntity(name);
    child->parent = this;
    children.push_back(child);
    return child;
}

bool Entity::SetParent(Entity* newParent) {
    //We make sure we're not trying to put the root as a child.
    if (parent != nullptr) {
        //We make sure we're not trying to set a parent as a child to one of it's own children.
        if (!HasChild(newParent)) {
            parent->RemoveChild(this);
            parent = newParent;
            newParent->children.push_back(this);

            return true;
        }
    }

    return false;
}

bool Entity::HasChild(const Entity* check_child, bool deep) const {
    for (Entity* child : children) {
        if (child->name == check_child->name)
            return true;
        else if (deep)
            child->HasChild(check_child);
    }

    return false;
}

Entity* Entity::InstantiateScene(const std::string& name) {
    Entity* child = AddChild();

    // Load scene.
    std::string filename = Hymn().GetPath() + FileSystem::DELIMITER + "Scenes" + FileSystem::DELIMITER + name + ".json";
    if (FileSystem::FileExists(filename.c_str())) {
        Json::Value root;
        std::ifstream file(filename);
        file >> root;
        file.close();
        child->Load(root);

        child->scene = true;
        child->sceneName = name;
    } else {
        child->name = "Error loading scene";
        Log() << "Couldn't find scene to load.";
    }

    return child;
}

const std::vector<Entity*>& Entity::GetChildren() const {
    return children;
}

Entity* Entity::GetChild(const std::string& name) const {
    for (Entity* child : children) {
        if (child->name == name)
            return child;
    }

    return nullptr;
}

bool Entity::RemoveChild(Entity* child) {
    for (auto it = children.begin(); it != children.end(); ++it) {
        if (*it == child) {
            children.erase(it);
            return true;
        }
    }

    return false;
}

bool Entity::IsScene() const {
    return scene;
}

void Entity::Kill() {
    KillHelper();

    // Remove this entity from the parent's list of children.
    if (parent != nullptr)
        parent->RemoveChild(this);
}

bool Entity::IsKilled() const {
    return killed;
}

Json::Value Entity::Save() const {
    Json::Value entity;
    entity["name"] = name;
    entity["position"] = Json::SaveVec3(position);
    entity["scale"] = Json::SaveVec3(scale);
    entity["rotation"] = Json::SaveVec3(rotation);
    entity["scene"] = scene;
    entity["uid"] = uniqueIdentifier;

    if (scene) {
        entity["sceneName"] = sceneName;
    } else {
        // Save components.
        Save<Component::Animation>(entity, "Animation");
        Save<Component::Lens>(entity, "Lens");
        Save<Component::Mesh>(entity, "Mesh");
        Save<Component::Material>(entity, "Material");
        Save<Component::DirectionalLight>(entity, "DirectionalLight");
        Save<Component::PointLight>(entity, "PointLight");
        Save<Component::SpotLight>(entity, "SpotLight");
        Save<Component::Physics>(entity, "Physics");
        Save<Component::Listener>(entity, "Listener");
        Save<Component::Script>(entity, "Script");
        Save<Component::SoundSource>(entity, "SoundSource");
        Save<Component::ParticleEmitter>(entity, "ParticleEmitter");

        // Save children.
        Json::Value childNodes;
        for (Entity* child : children)
            childNodes.append(child->Save());
        entity["children"] = childNodes;
    }

    return entity;
}

void Entity::Load(const Json::Value& node) {
    scene = node["scene"].asBool();

    if (scene) {
        sceneName = node["sceneName"].asString();

        // Load scene.
        std::string filename = Hymn().GetPath() + FileSystem::DELIMITER + "Scenes" + FileSystem::DELIMITER + sceneName + ".json";
        Json::Value root;
        std::ifstream file(filename);
        file >> root;
        file.close();
        Load(root);

        scene = true;
    } else {
        // Load components.
        Load<Component::Animation>(node, "Animation");
        Load<Component::Lens>(node, "Lens");
        Load<Component::Mesh>(node, "Mesh");
        Load<Component::Material>(node, "Material");
        Load<Component::DirectionalLight>(node, "DirectionalLight");
        Load<Component::PointLight>(node, "PointLight");
        Load<Component::SpotLight>(node, "SpotLight");
        Load<Component::Physics>(node, "Physics");
        Load<Component::Listener>(node, "Listener");
        Load<Component::Script>(node, "Script");
        Load<Component::SoundSource>(node, "SoundSource");
        Load<Component::ParticleEmitter>(node, "ParticleEmitter");

        // Load children.
        for (unsigned int i=0; i < node["children"].size(); ++i) {
            Entity* entity = AddChild("");
            entity->Load(node["children"][i]);
        }
    }

    name = node.get("name", "").asString();
    position = Json::LoadVec3(node["position"]);
    scale = Json::LoadVec3(node["scale"]);
    rotation = Json::LoadVec3(node["rotation"]);
    uniqueIdentifier = node.get("uid", 0).asUInt();

}

glm::mat4 Entity::GetModelMatrix() const {
    glm::mat4 matrix = glm::translate(glm::mat4(), position) * GetOrientation() * glm::scale(glm::mat4(), scale);

    if (parent != nullptr)
        matrix = parent->GetModelMatrix() * matrix;

    return matrix;
}

glm::mat4 Entity::GetOrientation() const {
    glm::mat4 orientation;
    orientation = glm::rotate(orientation, glm::radians(rotation.x), glm::vec3(0.f, 1.f, 0.f));
    orientation = glm::rotate(orientation, glm::radians(rotation.y), glm::vec3(1.f, 0.f, 0.f));
    return glm::rotate(orientation, glm::radians(rotation.z), glm::vec3(0.f, 0.f, 1.f));
}

glm::mat4 Entity::GetCameraOrientation() const {
    glm::mat4 orientation;
    orientation = glm::rotate(orientation, glm::radians(rotation.z), glm::vec3(0.f, 0.f, 1.f));
    orientation = glm::rotate(orientation, glm::radians(rotation.y), glm::vec3(1.f, 0.f, 0.f));
    return glm::rotate(orientation, glm::radians(rotation.x), glm::vec3(0.f, 1.f, 0.f));
}

glm::vec3 Entity::GetDirection() const {
    return glm::normalize(glm::vec3(GetOrientation() * glm::vec4(0.f, 0.f, -1.f, 0.f)));
}

glm::vec3 Entity::GetWorldPosition() const {
    if (parent != nullptr)
        return glm::vec3(parent->GetModelMatrix() * glm::vec4(position, 1.f));

    return position;
}

unsigned int Entity::GetUniqueIdentifier() const {
    return uniqueIdentifier;
}

void Entity::SetUniqueIdentifier(unsigned int UID) {
    uniqueIdentifier = UID;
}

Component::SuperComponent* Entity::AddComponent(const std::type_info* componentType) {
    Component::SuperComponent* component;

    // Create a component in the correct manager.
    if (*componentType == typeid(Component::Animation*))
        component = Managers().renderManager->CreateAnimation();
    else if (*componentType == typeid(Component::DirectionalLight*))
        component = Managers().renderManager->CreateDirectionalLight();
    else if (*componentType == typeid(Component::Lens*))
        component = Managers().renderManager->CreateLens();
    else if (*componentType == typeid(Component::Listener*))
        component = Managers().soundManager->CreateListener();
    else if (*componentType == typeid(Component::Material*))
        component = Managers().renderManager->CreateMaterial();
    else if (*componentType == typeid(Component::Mesh*))
        component = Managers().renderManager->CreateMesh();
    else if (*componentType == typeid(Component::ParticleEmitter*))
        component = Managers().particleManager->CreateParticleEmitter();
    else if (*componentType == typeid(Component::Physics*))
        component = Managers().physicsManager->CreatePhysics();
    else if (*componentType == typeid(Component::PointLight*))
        component = Managers().renderManager->CreatePointLight();
    else if (*componentType == typeid(Component::Script*))
        component = Managers().scriptManager->CreateScript();
    else if (*componentType == typeid(Component::SoundSource*))
        component = Managers().soundManager->CreateSoundSource();
    else if (*componentType == typeid(Component::SpotLight*))
        component = Managers().renderManager->CreateSpotLight();
    else
        Log() << componentType->name() << " not assigned to a manager!" << "\n";

    // Add component to our map.
    components[componentType] = component;

    // Set ourselves as the owner.
    component->entity = this;

    return component;
}

void Entity::LoadComponent(const std::type_info* componentType, const Json::Value& node) {
    Component::SuperComponent* component;

    // Create a component in the correct manager.
    if (*componentType == typeid(Component::Animation*))
        component = Managers().renderManager->CreateAnimation(node);
    else if (*componentType == typeid(Component::DirectionalLight*))
        component = Managers().renderManager->CreateDirectionalLight(node);
    else if (*componentType == typeid(Component::Lens*))
        component = Managers().renderManager->CreateLens(node);
    else if (*componentType == typeid(Component::Listener*))
        component = Managers().soundManager->CreateListener(node);
    else if (*componentType == typeid(Component::Material*))
        component = Managers().renderManager->CreateMaterial(node);
    else if (*componentType == typeid(Component::Mesh*))
        component = Managers().renderManager->CreateMesh(node);
    else if (*componentType == typeid(Component::ParticleEmitter*))
        component = Managers().particleManager->CreateParticleEmitter(node);
    else if (*componentType == typeid(Component::Physics*))
        component = Managers().physicsManager->CreatePhysics(node);
    else if (*componentType == typeid(Component::PointLight*))
        component = Managers().renderManager->CreatePointLight(node);
    else if (*componentType == typeid(Component::Script*))
        component = Managers().scriptManager->CreateScript(node);
    else if (*componentType == typeid(Component::SoundSource*))
        component = Managers().soundManager->CreateSoundSource(node);
    else if (*componentType == typeid(Component::SpotLight*))
        component = Managers().renderManager->CreateSpotLight(node);
    else
        Log() << componentType->name() << " not assigned to a manager!" << "\n";

    // Add component to our map.
    components[componentType] = component;

    // Set ourselves as the owner.
    component->entity = this;
}

void Entity::KillHelper() {
    killed = true;

    for (auto& it : components)
        it.second->Kill();

    for (Entity* child : children) {
        child->KillHelper();
    }
}
<commit_msg>Fix potential use of unintialized variable<commit_after>#include "Entity.hpp"

#include <glm/gtc/matrix_transform.hpp>
#include "../Component/Animation.hpp"
#include "../Component/Lens.hpp"
#include "../Component/Mesh.hpp"
#include "../Component/Material.hpp"
#include "../Component/DirectionalLight.hpp"
#include "../Component/PointLight.hpp"
#include "../Component/SpotLight.hpp"
#include "../Component/Physics.hpp"
#include "../Component/Listener.hpp"
#include "../Component/Script.hpp"
#include "../Component/SoundSource.hpp"
#include "../Component/ParticleEmitter.hpp"
#include "../Util/Json.hpp"
#include "../Util/FileSystem.hpp"
#include <Utility/Log.hpp>
#include "../Hymn.hpp"
#include <fstream>
#include "../Manager/Managers.hpp"
#include "../Manager/ParticleManager.hpp"
#include "../Manager/PhysicsManager.hpp"
#include "../Manager/RenderManager.hpp"
#include "../Manager/ScriptManager.hpp"
#include "../Manager/SoundManager.hpp"

Entity::Entity(World* world, const std::string& name) : name ( name ) {
    this->world = world;
}

Entity::~Entity() {

}

Entity* Entity::GetParent() const {
    return parent;
}

Entity* Entity::AddChild(const std::string& name) {
    Entity* child = world->CreateEntity(name);
    child->parent = this;
    children.push_back(child);
    return child;
}

bool Entity::SetParent(Entity* newParent) {
    //We make sure we're not trying to put the root as a child.
    if (parent != nullptr) {
        //We make sure we're not trying to set a parent as a child to one of it's own children.
        if (!HasChild(newParent)) {
            parent->RemoveChild(this);
            parent = newParent;
            newParent->children.push_back(this);

            return true;
        }
    }

    return false;
}

bool Entity::HasChild(const Entity* check_child, bool deep) const {
    for (Entity* child : children) {
        if (child->name == check_child->name)
            return true;
        else if (deep)
            child->HasChild(check_child);
    }

    return false;
}

Entity* Entity::InstantiateScene(const std::string& name) {
    Entity* child = AddChild();

    // Load scene.
    std::string filename = Hymn().GetPath() + FileSystem::DELIMITER + "Scenes" + FileSystem::DELIMITER + name + ".json";
    if (FileSystem::FileExists(filename.c_str())) {
        Json::Value root;
        std::ifstream file(filename);
        file >> root;
        file.close();
        child->Load(root);

        child->scene = true;
        child->sceneName = name;
    } else {
        child->name = "Error loading scene";
        Log() << "Couldn't find scene to load.";
    }

    return child;
}

const std::vector<Entity*>& Entity::GetChildren() const {
    return children;
}

Entity* Entity::GetChild(const std::string& name) const {
    for (Entity* child : children) {
        if (child->name == name)
            return child;
    }

    return nullptr;
}

bool Entity::RemoveChild(Entity* child) {
    for (auto it = children.begin(); it != children.end(); ++it) {
        if (*it == child) {
            children.erase(it);
            return true;
        }
    }

    return false;
}

bool Entity::IsScene() const {
    return scene;
}

void Entity::Kill() {
    KillHelper();

    // Remove this entity from the parent's list of children.
    if (parent != nullptr)
        parent->RemoveChild(this);
}

bool Entity::IsKilled() const {
    return killed;
}

Json::Value Entity::Save() const {
    Json::Value entity;
    entity["name"] = name;
    entity["position"] = Json::SaveVec3(position);
    entity["scale"] = Json::SaveVec3(scale);
    entity["rotation"] = Json::SaveVec3(rotation);
    entity["scene"] = scene;
    entity["uid"] = uniqueIdentifier;

    if (scene) {
        entity["sceneName"] = sceneName;
    } else {
        // Save components.
        Save<Component::Animation>(entity, "Animation");
        Save<Component::Lens>(entity, "Lens");
        Save<Component::Mesh>(entity, "Mesh");
        Save<Component::Material>(entity, "Material");
        Save<Component::DirectionalLight>(entity, "DirectionalLight");
        Save<Component::PointLight>(entity, "PointLight");
        Save<Component::SpotLight>(entity, "SpotLight");
        Save<Component::Physics>(entity, "Physics");
        Save<Component::Listener>(entity, "Listener");
        Save<Component::Script>(entity, "Script");
        Save<Component::SoundSource>(entity, "SoundSource");
        Save<Component::ParticleEmitter>(entity, "ParticleEmitter");

        // Save children.
        Json::Value childNodes;
        for (Entity* child : children)
            childNodes.append(child->Save());
        entity["children"] = childNodes;
    }

    return entity;
}

void Entity::Load(const Json::Value& node) {
    scene = node["scene"].asBool();

    if (scene) {
        sceneName = node["sceneName"].asString();

        // Load scene.
        std::string filename = Hymn().GetPath() + FileSystem::DELIMITER + "Scenes" + FileSystem::DELIMITER + sceneName + ".json";
        Json::Value root;
        std::ifstream file(filename);
        file >> root;
        file.close();
        Load(root);

        scene = true;
    } else {
        // Load components.
        Load<Component::Animation>(node, "Animation");
        Load<Component::Lens>(node, "Lens");
        Load<Component::Mesh>(node, "Mesh");
        Load<Component::Material>(node, "Material");
        Load<Component::DirectionalLight>(node, "DirectionalLight");
        Load<Component::PointLight>(node, "PointLight");
        Load<Component::SpotLight>(node, "SpotLight");
        Load<Component::Physics>(node, "Physics");
        Load<Component::Listener>(node, "Listener");
        Load<Component::Script>(node, "Script");
        Load<Component::SoundSource>(node, "SoundSource");
        Load<Component::ParticleEmitter>(node, "ParticleEmitter");

        // Load children.
        for (unsigned int i=0; i < node["children"].size(); ++i) {
            Entity* entity = AddChild("");
            entity->Load(node["children"][i]);
        }
    }

    name = node.get("name", "").asString();
    position = Json::LoadVec3(node["position"]);
    scale = Json::LoadVec3(node["scale"]);
    rotation = Json::LoadVec3(node["rotation"]);
    uniqueIdentifier = node.get("uid", 0).asUInt();

}

glm::mat4 Entity::GetModelMatrix() const {
    glm::mat4 matrix = glm::translate(glm::mat4(), position) * GetOrientation() * glm::scale(glm::mat4(), scale);

    if (parent != nullptr)
        matrix = parent->GetModelMatrix() * matrix;

    return matrix;
}

glm::mat4 Entity::GetOrientation() const {
    glm::mat4 orientation;
    orientation = glm::rotate(orientation, glm::radians(rotation.x), glm::vec3(0.f, 1.f, 0.f));
    orientation = glm::rotate(orientation, glm::radians(rotation.y), glm::vec3(1.f, 0.f, 0.f));
    return glm::rotate(orientation, glm::radians(rotation.z), glm::vec3(0.f, 0.f, 1.f));
}

glm::mat4 Entity::GetCameraOrientation() const {
    glm::mat4 orientation;
    orientation = glm::rotate(orientation, glm::radians(rotation.z), glm::vec3(0.f, 0.f, 1.f));
    orientation = glm::rotate(orientation, glm::radians(rotation.y), glm::vec3(1.f, 0.f, 0.f));
    return glm::rotate(orientation, glm::radians(rotation.x), glm::vec3(0.f, 1.f, 0.f));
}

glm::vec3 Entity::GetDirection() const {
    return glm::normalize(glm::vec3(GetOrientation() * glm::vec4(0.f, 0.f, -1.f, 0.f)));
}

glm::vec3 Entity::GetWorldPosition() const {
    if (parent != nullptr)
        return glm::vec3(parent->GetModelMatrix() * glm::vec4(position, 1.f));

    return position;
}

unsigned int Entity::GetUniqueIdentifier() const {
    return uniqueIdentifier;
}

void Entity::SetUniqueIdentifier(unsigned int UID) {
    uniqueIdentifier = UID;
}

Component::SuperComponent* Entity::AddComponent(const std::type_info* componentType) {
    Component::SuperComponent* component;

    // Create a component in the correct manager.
    if (*componentType == typeid(Component::Animation*))
        component = Managers().renderManager->CreateAnimation();
    else if (*componentType == typeid(Component::DirectionalLight*))
        component = Managers().renderManager->CreateDirectionalLight();
    else if (*componentType == typeid(Component::Lens*))
        component = Managers().renderManager->CreateLens();
    else if (*componentType == typeid(Component::Listener*))
        component = Managers().soundManager->CreateListener();
    else if (*componentType == typeid(Component::Material*))
        component = Managers().renderManager->CreateMaterial();
    else if (*componentType == typeid(Component::Mesh*))
        component = Managers().renderManager->CreateMesh();
    else if (*componentType == typeid(Component::ParticleEmitter*))
        component = Managers().particleManager->CreateParticleEmitter();
    else if (*componentType == typeid(Component::Physics*))
        component = Managers().physicsManager->CreatePhysics();
    else if (*componentType == typeid(Component::PointLight*))
        component = Managers().renderManager->CreatePointLight();
    else if (*componentType == typeid(Component::Script*))
        component = Managers().scriptManager->CreateScript();
    else if (*componentType == typeid(Component::SoundSource*))
        component = Managers().soundManager->CreateSoundSource();
    else if (*componentType == typeid(Component::SpotLight*))
        component = Managers().renderManager->CreateSpotLight();
    else {
        Log() << componentType->name() << " not assigned to a manager!" << "\n";
        return nullptr;
    }

    // Add component to our map.
    components[componentType] = component;

    // Set ourselves as the owner.
    component->entity = this;

    return component;
}

void Entity::LoadComponent(const std::type_info* componentType, const Json::Value& node) {
    Component::SuperComponent* component;

    // Create a component in the correct manager.
    if (*componentType == typeid(Component::Animation*))
        component = Managers().renderManager->CreateAnimation(node);
    else if (*componentType == typeid(Component::DirectionalLight*))
        component = Managers().renderManager->CreateDirectionalLight(node);
    else if (*componentType == typeid(Component::Lens*))
        component = Managers().renderManager->CreateLens(node);
    else if (*componentType == typeid(Component::Listener*))
        component = Managers().soundManager->CreateListener(node);
    else if (*componentType == typeid(Component::Material*))
        component = Managers().renderManager->CreateMaterial(node);
    else if (*componentType == typeid(Component::Mesh*))
        component = Managers().renderManager->CreateMesh(node);
    else if (*componentType == typeid(Component::ParticleEmitter*))
        component = Managers().particleManager->CreateParticleEmitter(node);
    else if (*componentType == typeid(Component::Physics*))
        component = Managers().physicsManager->CreatePhysics(node);
    else if (*componentType == typeid(Component::PointLight*))
        component = Managers().renderManager->CreatePointLight(node);
    else if (*componentType == typeid(Component::Script*))
        component = Managers().scriptManager->CreateScript(node);
    else if (*componentType == typeid(Component::SoundSource*))
        component = Managers().soundManager->CreateSoundSource(node);
    else if (*componentType == typeid(Component::SpotLight*))
        component = Managers().renderManager->CreateSpotLight(node);
    else {
        Log() << componentType->name() << " not assigned to a manager!" << "\n";
        return;
    }

    // Add component to our map.
    components[componentType] = component;

    // Set ourselves as the owner.
    component->entity = this;
}

void Entity::KillHelper() {
    killed = true;

    for (auto& it : components)
        it.second->Kill();

    for (Entity* child : children) {
        child->KillHelper();
    }
}
<|endoftext|>


<commit_before>//===- FunctionResolution.cpp - Resolve declarations to implementations ---===//
//
// Loop over the functions that are in the module and look for functions that
// have the same name.  More often than not, there will be things like:
//
//    declare void %foo(...)
//    void %foo(int, int) { ... }
//
// because of the way things are declared in C.  If this is the case, patch
// things up.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/iOther.h"
#include "llvm/Constants.h"
#include "llvm/Assembly/Writer.h"  // FIXME: remove when varargs implemented
#include "Support/Statistic.h"
#include <algorithm>

namespace {
  Statistic<>NumResolved("funcresolve", "Number of varargs functions resolved");
  Statistic<> NumGlobals("funcresolve", "Number of global variables resolved");

  struct FunctionResolvingPass : public Pass {
    bool run(Module &M);
  };
  RegisterOpt<FunctionResolvingPass> X("funcresolve", "Resolve Functions");
}

Pass *createFunctionResolvingPass() {
  return new FunctionResolvingPass();
}

// ConvertCallTo - Convert a call to a varargs function with no arg types
// specified to a concrete nonvarargs function.
//
static void ConvertCallTo(CallInst *CI, Function *Dest) {
  const FunctionType::ParamTypes &ParamTys =
    Dest->getFunctionType()->getParamTypes();
  BasicBlock *BB = CI->getParent();

  // Keep an iterator to where we want to insert cast instructions if the
  // argument types don't agree.
  //
  BasicBlock::iterator BBI = CI;
  unsigned NumArgsToCopy = CI->getNumOperands()-1;
  if (NumArgsToCopy != ParamTys.size() &&
      !(NumArgsToCopy > ParamTys.size() &&
        Dest->getFunctionType()->isVarArg())) {
    std::cerr << "WARNING: Call arguments do not match expected number of"
              << " parameters.\n";
    std::cerr << "WARNING: In function '"
              << CI->getParent()->getParent()->getName() << "': call: " << *CI;
    std::cerr << "Function resolved to: ";
    WriteAsOperand(std::cerr, Dest);
    std::cerr << "\n";
    if (NumArgsToCopy > ParamTys.size())
      NumArgsToCopy = ParamTys.size();
  }

  std::vector<Value*> Params;

  // Convert all of the call arguments over... inserting cast instructions if
  // the types are not compatible.
  for (unsigned i = 1; i <= NumArgsToCopy; ++i) {
    Value *V = CI->getOperand(i);

    if (i-1 < ParamTys.size() && V->getType() != ParamTys[i-1]) {
      // Must insert a cast...
      V = new CastInst(V, ParamTys[i-1], "argcast", BBI);
    }

    Params.push_back(V);
  }

  // Replace the old call instruction with a new call instruction that calls
  // the real function.
  //
  Instruction *NewCall = new CallInst(Dest, Params, "", BBI);

  // Remove the old call instruction from the program...
  BB->getInstList().remove(BBI);

  // Transfer the name over...
  if (NewCall->getType() != Type::VoidTy)
    NewCall->setName(CI->getName());

  // Replace uses of the old instruction with the appropriate values...
  //
  if (NewCall->getType() == CI->getType()) {
    CI->replaceAllUsesWith(NewCall);
    NewCall->setName(CI->getName());

  } else if (NewCall->getType() == Type::VoidTy) {
    // Resolved function does not return a value but the prototype does.  This
    // often occurs because undefined functions default to returning integers.
    // Just replace uses of the call (which are broken anyway) with dummy
    // values.
    CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
  } else if (CI->getType() == Type::VoidTy) {
    // If we are gaining a new return value, we don't have to do anything
    // special here, because it will automatically be ignored.
  } else {
    // Insert a cast instruction to convert the return value of the function
    // into it's new type.  Of course we only need to do this if the return
    // value of the function is actually USED.
    //
    if (!CI->use_empty()) {
      // Insert the new cast instruction...
      CastInst *NewCast = new CastInst(NewCall, CI->getType(),
                                       NewCall->getName(), BBI);
      CI->replaceAllUsesWith(NewCast);
    }
  }

  // The old instruction is no longer needed, destroy it!
  delete CI;
}

static bool ResolveFunctions(Module &M, std::vector<GlobalValue*> &Globals,
                             Function *Concrete) {
  bool Changed = false;
  for (unsigned i = 0; i != Globals.size(); ++i)
    if (Globals[i] != Concrete) {
      Function *Old = cast<Function>(Globals[i]);
      const FunctionType *OldMT = Old->getFunctionType();
      const FunctionType *ConcreteMT = Concrete->getFunctionType();

      assert(OldMT->getParamTypes().size() <=
             ConcreteMT->getParamTypes().size() &&
             "Concrete type must have more specified parameters!");

      // Check to make sure that if there are specified types, that they
      // match...
      //
      for (unsigned i = 0; i < OldMT->getParamTypes().size(); ++i)
        if (OldMT->getParamTypes()[i] != ConcreteMT->getParamTypes()[i]) {
          std::cerr << "funcresolve: Function [" << Old->getName()
                    << "]: Parameter types conflict for: '" << OldMT
                    << "' and '" << ConcreteMT << "'\n";
          return Changed;
        }

      // Attempt to convert all of the uses of the old function to the
      // concrete form of the function.  If there is a use of the fn that
      // we don't understand here we punt to avoid making a bad
      // transformation.
      //
      // At this point, we know that the return values are the same for
      // our two functions and that the Old function has no varargs fns
      // specified.  In otherwords it's just <retty> (...)
      //
      for (unsigned i = 0; i < Old->use_size(); ) {
        User *U = *(Old->use_begin()+i);
        if (CastInst *CI = dyn_cast<CastInst>(U)) {
          // Convert casts directly
          assert(CI->getOperand(0) == Old);
          CI->setOperand(0, Concrete);
          Changed = true;
          ++NumResolved;
        } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
          // Can only fix up calls TO the argument, not args passed in.
          if (CI->getCalledValue() == Old) {
            ConvertCallTo(CI, Concrete);
            Changed = true;
            ++NumResolved;
          } else {
            std::cerr << "Couldn't cleanup this function call, must be an"
                      << " argument or something!" << CI;
            ++i;
          }
        } else {
          std::cerr << "Cannot convert use of function: " << U << "\n";
          ++i;
        }
      }
    }
  return Changed;
}

static bool ResolveGlobalVariables(Module &M,
                                   std::vector<GlobalValue*> &Globals,
                                   GlobalVariable *Concrete) {
  bool Changed = false;
  assert(isa<ArrayType>(Concrete->getType()->getElementType()) &&
         "Concrete version should be an array type!");

  // Get the type of the things that may be resolved to us...
  const Type *AETy =
    cast<ArrayType>(Concrete->getType()->getElementType())->getElementType();

  std::vector<Constant*> Args;
  Args.push_back(Constant::getNullValue(Type::LongTy));
  Args.push_back(Constant::getNullValue(Type::LongTy));
  ConstantExpr *Replacement =
    ConstantExpr::getGetElementPtr(ConstantPointerRef::get(Concrete), Args);

  for (unsigned i = 0; i != Globals.size(); ++i)
    if (Globals[i] != Concrete) {
      GlobalVariable *Old = cast<GlobalVariable>(Globals[i]);
      if (Old->getType()->getElementType() != AETy) {
        std::cerr << "WARNING: Two global variables exist with the same name "
                  << "that cannot be resolved!\n";
        return false;
      }

      // In this case, Old is a pointer to T, Concrete is a pointer to array of
      // T.  Because of this, replace all uses of Old with a constantexpr
      // getelementptr that returns the address of the first element of the
      // array.
      //
      Old->replaceAllUsesWith(Replacement);
      // Since there are no uses of Old anymore, remove it from the module.
      M.getGlobalList().erase(Old);

      ++NumGlobals;
      Changed = true;
    }
  return Changed;
}

static bool ProcessGlobalsWithSameName(Module &M,
                                       std::vector<GlobalValue*> &Globals) {
  assert(!Globals.empty() && "Globals list shouldn't be empty here!");

  bool isFunction = isa<Function>(Globals[0]);   // Is this group all functions?
  bool Changed = false;
  GlobalValue *Concrete = 0;  // The most concrete implementation to resolve to

  assert((isFunction ^ isa<GlobalVariable>(Globals[0])) &&
         "Should either be function or gvar!");

  for (unsigned i = 0; i != Globals.size(); ) {
    if (isa<Function>(Globals[i]) != isFunction) {
      std::cerr << "WARNING: Found function and global variable with the "
                << "same name: '" << Globals[i]->getName() << "'.\n";
      return false;                 // Don't know how to handle this, bail out!
    }

    if (isFunction) {
      // For functions, we look to merge functions definitions of "int (...)"
      // to 'int (int)' or 'int ()' or whatever else is not completely generic.
      //
      Function *F = cast<Function>(Globals[i]);
      if (!F->isExternal()) {
        if (Concrete && !Concrete->isExternal())
          return false;   // Found two different functions types.  Can't choose!

        Concrete = Globals[i];
      } else if (Concrete) {
        if (Concrete->isExternal()) // If we have multiple external symbols...x
          if (F->getFunctionType()->getNumParams() >
              cast<Function>(Concrete)->getFunctionType()->getNumParams())
            Concrete = F;  // We are more concrete than "Concrete"!

      } else {
        Concrete = F;
      }
      ++i;
    } else {
      // For global variables, we have to merge C definitions int A[][4] with
      // int[6][4]
      GlobalVariable *GV = cast<GlobalVariable>(Globals[i]);
      if (Concrete == 0) {
        if (isa<ArrayType>(GV->getType()->getElementType()))
          Concrete = GV;
      } else {    // Must have different types... one is an array of the other?
        const ArrayType *AT =
          dyn_cast<ArrayType>(GV->getType()->getElementType());

        // If GV is an array of Concrete, then GV is the array.
        if (AT && AT->getElementType() == Concrete->getType()->getElementType())
          Concrete = GV;
        else {
          // Concrete must be an array type, check to see if the element type of
          // concrete is already GV.
          AT = cast<ArrayType>(Concrete->getType()->getElementType());
          if (AT->getElementType() != GV->getType()->getElementType())
            Concrete = 0;           // Don't know how to handle it!
        }
      }

      ++i;
    }
  }

  if (Globals.size() > 1) {         // Found a multiply defined global...
    // We should find exactly one concrete function definition, which is
    // probably the implementation.  Change all of the function definitions and
    // uses to use it instead.
    //
    if (!Concrete) {
      std::cerr << "WARNING: Found function types that are not compatible:\n";
      for (unsigned i = 0; i < Globals.size(); ++i) {
        std::cerr << "\t" << Globals[i]->getType()->getDescription() << " %"
                  << Globals[i]->getName() << "\n";
      }
      std::cerr << "  No linkage of globals named '" << Globals[0]->getName()
                << "' performed!\n";
      return Changed;
    }

    if (isFunction)
      return Changed | ResolveFunctions(M, Globals, cast<Function>(Concrete));
    else
      return Changed | ResolveGlobalVariables(M, Globals,
                                              cast<GlobalVariable>(Concrete));
  }
  return Changed;
}

bool FunctionResolvingPass::run(Module &M) {
  SymbolTable &ST = M.getSymbolTable();

  std::map<std::string, std::vector<GlobalValue*> > Globals;

  // Loop over the entries in the symbol table. If an entry is a func pointer,
  // then add it to the Functions map.  We do a two pass algorithm here to avoid
  // problems with iterators getting invalidated if we did a one pass scheme.
  //
  for (SymbolTable::iterator I = ST.begin(), E = ST.end(); I != E; ++I)
    if (const PointerType *PT = dyn_cast<PointerType>(I->first)) {
      SymbolTable::VarMap &Plane = I->second;
      for (SymbolTable::type_iterator PI = Plane.begin(), PE = Plane.end();
           PI != PE; ++PI) {
        GlobalValue *GV = cast<GlobalValue>(PI->second);
        assert(PI->first == GV->getName() &&
               "Global name and symbol table do not agree!");
        if (GV->hasExternalLinkage())  // Only resolve decls to external fns
          Globals[PI->first].push_back(GV);
      }
    }

  bool Changed = false;

  // Now we have a list of all functions with a particular name.  If there is
  // more than one entry in a list, merge the functions together.
  //
  for (std::map<std::string, std::vector<GlobalValue*> >::iterator
         I = Globals.begin(), E = Globals.end(); I != E; ++I)
    Changed |= ProcessGlobalsWithSameName(M, I->second);

  // Now loop over all of the globals, checking to see if any are trivially
  // dead.  If so, remove them now.

  for (Module::iterator I = M.begin(), E = M.end(); I != E; )
    if (I->isExternal() && I->use_empty()) {
      Function *F = I;
      ++I;
      M.getFunctionList().erase(F);
      ++NumResolved;
      Changed = true;
    } else {
      ++I;
    }

  for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; )
    if (I->isExternal() && I->use_empty()) {
      GlobalVariable *GV = I;
      ++I;
      M.getGlobalList().erase(GV);
      ++NumGlobals;
      Changed = true;
    } else {
      ++I;
    }

  return Changed;
}
<commit_msg>Replace assertion with a handler.<commit_after>//===- FunctionResolution.cpp - Resolve declarations to implementations ---===//
//
// Loop over the functions that are in the module and look for functions that
// have the same name.  More often than not, there will be things like:
//
//    declare void %foo(...)
//    void %foo(int, int) { ... }
//
// because of the way things are declared in C.  If this is the case, patch
// things up.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/iOther.h"
#include "llvm/Constants.h"
#include "llvm/Assembly/Writer.h"  // FIXME: remove when varargs implemented
#include "Support/Statistic.h"
#include <algorithm>

namespace {
  Statistic<>NumResolved("funcresolve", "Number of varargs functions resolved");
  Statistic<> NumGlobals("funcresolve", "Number of global variables resolved");

  struct FunctionResolvingPass : public Pass {
    bool run(Module &M);
  };
  RegisterOpt<FunctionResolvingPass> X("funcresolve", "Resolve Functions");
}

Pass *createFunctionResolvingPass() {
  return new FunctionResolvingPass();
}

// ConvertCallTo - Convert a call to a varargs function with no arg types
// specified to a concrete nonvarargs function.
//
static void ConvertCallTo(CallInst *CI, Function *Dest) {
  const FunctionType::ParamTypes &ParamTys =
    Dest->getFunctionType()->getParamTypes();
  BasicBlock *BB = CI->getParent();

  // Keep an iterator to where we want to insert cast instructions if the
  // argument types don't agree.
  //
  unsigned NumArgsToCopy = CI->getNumOperands()-1;
  if (NumArgsToCopy != ParamTys.size() &&
      !(NumArgsToCopy > ParamTys.size() &&
        Dest->getFunctionType()->isVarArg())) {
    std::cerr << "WARNING: Call arguments do not match expected number of"
              << " parameters.\n";
    std::cerr << "WARNING: In function '"
              << CI->getParent()->getParent()->getName() << "': call: " << *CI;
    std::cerr << "Function resolved to: ";
    WriteAsOperand(std::cerr, Dest);
    std::cerr << "\n";
    if (NumArgsToCopy > ParamTys.size())
      NumArgsToCopy = ParamTys.size();
  }

  std::vector<Value*> Params;

  // Convert all of the call arguments over... inserting cast instructions if
  // the types are not compatible.
  for (unsigned i = 1; i <= NumArgsToCopy; ++i) {
    Value *V = CI->getOperand(i);

    if (i-1 < ParamTys.size() && V->getType() != ParamTys[i-1]) {
      // Must insert a cast...
      V = new CastInst(V, ParamTys[i-1], "argcast", CI);
    }

    Params.push_back(V);
  }

  // Replace the old call instruction with a new call instruction that calls
  // the real function.
  //
  Instruction *NewCall = new CallInst(Dest, Params, "", CI);
  std::string Name = CI->getName(); CI->setName("");

  // Transfer the name over...
  if (NewCall->getType() != Type::VoidTy)
    NewCall->setName(Name);

  // Replace uses of the old instruction with the appropriate values...
  //
  if (NewCall->getType() == CI->getType()) {
    CI->replaceAllUsesWith(NewCall);
    NewCall->setName(Name);

  } else if (NewCall->getType() == Type::VoidTy) {
    // Resolved function does not return a value but the prototype does.  This
    // often occurs because undefined functions default to returning integers.
    // Just replace uses of the call (which are broken anyway) with dummy
    // values.
    CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
  } else if (CI->getType() == Type::VoidTy) {
    // If we are gaining a new return value, we don't have to do anything
    // special here, because it will automatically be ignored.
  } else {
    // Insert a cast instruction to convert the return value of the function
    // into it's new type.  Of course we only need to do this if the return
    // value of the function is actually USED.
    //
    if (!CI->use_empty()) {
      // Insert the new cast instruction...
      CastInst *NewCast = new CastInst(NewCall, CI->getType(), Name, CI);
      CI->replaceAllUsesWith(NewCast);
    }
  }

  // The old instruction is no longer needed, destroy it!
  BB->getInstList().erase(CI);
}

static bool ResolveFunctions(Module &M, std::vector<GlobalValue*> &Globals,
                             Function *Concrete) {
  bool Changed = false;
  for (unsigned i = 0; i != Globals.size(); ++i)
    if (Globals[i] != Concrete) {
      Function *Old = cast<Function>(Globals[i]);
      const FunctionType *OldMT = Old->getFunctionType();
      const FunctionType *ConcreteMT = Concrete->getFunctionType();

      if (OldMT->getParamTypes().size() <= ConcreteMT->getParamTypes().size())
        if (!Old->use_empty()) {
          std::cerr << "WARNING: Linking function '" << Old->getName()
                    << "' is causing arguments to be dropped.\n";
          std::cerr << "WARNING: Prototype: ";
          WriteAsOperand(std::cerr, Old);
          std::cerr << " resolved to ";
          WriteAsOperand(std::cerr, Concrete);
          std::cerr << "\n";
        }

      // Check to make sure that if there are specified types, that they
      // match...
      //
      unsigned NumArguments = std::min(OldMT->getParamTypes().size(),
                                       ConcreteMT->getParamTypes().size());

      for (unsigned i = 0; i < NumArguments; ++i)
        if (OldMT->getParamTypes()[i] != ConcreteMT->getParamTypes()[i]) {
          std::cerr << "funcresolve: Function [" << Old->getName()
                    << "]: Parameter types conflict for: '" << OldMT
                    << "' and '" << ConcreteMT << "'\n";
          return Changed;
        }

      // Attempt to convert all of the uses of the old function to the
      // concrete form of the function.  If there is a use of the fn that
      // we don't understand here we punt to avoid making a bad
      // transformation.
      //
      // At this point, we know that the return values are the same for
      // our two functions and that the Old function has no varargs fns
      // specified.  In otherwords it's just <retty> (...)
      //
      for (unsigned i = 0; i < Old->use_size(); ) {
        User *U = *(Old->use_begin()+i);
        if (CastInst *CI = dyn_cast<CastInst>(U)) {
          // Convert casts directly
          assert(CI->getOperand(0) == Old);
          CI->setOperand(0, Concrete);
          Changed = true;
          ++NumResolved;
        } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
          // Can only fix up calls TO the argument, not args passed in.
          if (CI->getCalledValue() == Old) {
            ConvertCallTo(CI, Concrete);
            Changed = true;
            ++NumResolved;
          } else {
            std::cerr << "Couldn't cleanup this function call, must be an"
                      << " argument or something!" << CI;
            ++i;
          }
        } else {
          std::cerr << "Cannot convert use of function: " << U << "\n";
          ++i;
        }
      }
    }
  return Changed;
}

static bool ResolveGlobalVariables(Module &M,
                                   std::vector<GlobalValue*> &Globals,
                                   GlobalVariable *Concrete) {
  bool Changed = false;
  assert(isa<ArrayType>(Concrete->getType()->getElementType()) &&
         "Concrete version should be an array type!");

  // Get the type of the things that may be resolved to us...
  const Type *AETy =
    cast<ArrayType>(Concrete->getType()->getElementType())->getElementType();

  std::vector<Constant*> Args;
  Args.push_back(Constant::getNullValue(Type::LongTy));
  Args.push_back(Constant::getNullValue(Type::LongTy));
  ConstantExpr *Replacement =
    ConstantExpr::getGetElementPtr(ConstantPointerRef::get(Concrete), Args);

  for (unsigned i = 0; i != Globals.size(); ++i)
    if (Globals[i] != Concrete) {
      GlobalVariable *Old = cast<GlobalVariable>(Globals[i]);
      if (Old->getType()->getElementType() != AETy) {
        std::cerr << "WARNING: Two global variables exist with the same name "
                  << "that cannot be resolved!\n";
        return false;
      }

      // In this case, Old is a pointer to T, Concrete is a pointer to array of
      // T.  Because of this, replace all uses of Old with a constantexpr
      // getelementptr that returns the address of the first element of the
      // array.
      //
      Old->replaceAllUsesWith(Replacement);
      // Since there are no uses of Old anymore, remove it from the module.
      M.getGlobalList().erase(Old);

      ++NumGlobals;
      Changed = true;
    }
  return Changed;
}

static bool ProcessGlobalsWithSameName(Module &M,
                                       std::vector<GlobalValue*> &Globals) {
  assert(!Globals.empty() && "Globals list shouldn't be empty here!");

  bool isFunction = isa<Function>(Globals[0]);   // Is this group all functions?
  bool Changed = false;
  GlobalValue *Concrete = 0;  // The most concrete implementation to resolve to

  assert((isFunction ^ isa<GlobalVariable>(Globals[0])) &&
         "Should either be function or gvar!");

  for (unsigned i = 0; i != Globals.size(); ) {
    if (isa<Function>(Globals[i]) != isFunction) {
      std::cerr << "WARNING: Found function and global variable with the "
                << "same name: '" << Globals[i]->getName() << "'.\n";
      return false;                 // Don't know how to handle this, bail out!
    }

    if (isFunction) {
      // For functions, we look to merge functions definitions of "int (...)"
      // to 'int (int)' or 'int ()' or whatever else is not completely generic.
      //
      Function *F = cast<Function>(Globals[i]);
      if (!F->isExternal()) {
        if (Concrete && !Concrete->isExternal())
          return false;   // Found two different functions types.  Can't choose!

        Concrete = Globals[i];
      } else if (Concrete) {
        if (Concrete->isExternal()) // If we have multiple external symbols...x
          if (F->getFunctionType()->getNumParams() >
              cast<Function>(Concrete)->getFunctionType()->getNumParams())
            Concrete = F;  // We are more concrete than "Concrete"!

      } else {
        Concrete = F;
      }
      ++i;
    } else {
      // For global variables, we have to merge C definitions int A[][4] with
      // int[6][4]
      GlobalVariable *GV = cast<GlobalVariable>(Globals[i]);
      if (Concrete == 0) {
        if (isa<ArrayType>(GV->getType()->getElementType()))
          Concrete = GV;
      } else {    // Must have different types... one is an array of the other?
        const ArrayType *AT =
          dyn_cast<ArrayType>(GV->getType()->getElementType());

        // If GV is an array of Concrete, then GV is the array.
        if (AT && AT->getElementType() == Concrete->getType()->getElementType())
          Concrete = GV;
        else {
          // Concrete must be an array type, check to see if the element type of
          // concrete is already GV.
          AT = cast<ArrayType>(Concrete->getType()->getElementType());
          if (AT->getElementType() != GV->getType()->getElementType())
            Concrete = 0;           // Don't know how to handle it!
        }
      }

      ++i;
    }
  }

  if (Globals.size() > 1) {         // Found a multiply defined global...
    // We should find exactly one concrete function definition, which is
    // probably the implementation.  Change all of the function definitions and
    // uses to use it instead.
    //
    if (!Concrete) {
      std::cerr << "WARNING: Found function types that are not compatible:\n";
      for (unsigned i = 0; i < Globals.size(); ++i) {
        std::cerr << "\t" << Globals[i]->getType()->getDescription() << " %"
                  << Globals[i]->getName() << "\n";
      }
      std::cerr << "  No linkage of globals named '" << Globals[0]->getName()
                << "' performed!\n";
      return Changed;
    }

    if (isFunction)
      return Changed | ResolveFunctions(M, Globals, cast<Function>(Concrete));
    else
      return Changed | ResolveGlobalVariables(M, Globals,
                                              cast<GlobalVariable>(Concrete));
  }
  return Changed;
}

bool FunctionResolvingPass::run(Module &M) {
  SymbolTable &ST = M.getSymbolTable();

  std::map<std::string, std::vector<GlobalValue*> > Globals;

  // Loop over the entries in the symbol table. If an entry is a func pointer,
  // then add it to the Functions map.  We do a two pass algorithm here to avoid
  // problems with iterators getting invalidated if we did a one pass scheme.
  //
  for (SymbolTable::iterator I = ST.begin(), E = ST.end(); I != E; ++I)
    if (const PointerType *PT = dyn_cast<PointerType>(I->first)) {
      SymbolTable::VarMap &Plane = I->second;
      for (SymbolTable::type_iterator PI = Plane.begin(), PE = Plane.end();
           PI != PE; ++PI) {
        GlobalValue *GV = cast<GlobalValue>(PI->second);
        assert(PI->first == GV->getName() &&
               "Global name and symbol table do not agree!");
        if (GV->hasExternalLinkage())  // Only resolve decls to external fns
          Globals[PI->first].push_back(GV);
      }
    }

  bool Changed = false;

  // Now we have a list of all functions with a particular name.  If there is
  // more than one entry in a list, merge the functions together.
  //
  for (std::map<std::string, std::vector<GlobalValue*> >::iterator
         I = Globals.begin(), E = Globals.end(); I != E; ++I)
    Changed |= ProcessGlobalsWithSameName(M, I->second);

  // Now loop over all of the globals, checking to see if any are trivially
  // dead.  If so, remove them now.

  for (Module::iterator I = M.begin(), E = M.end(); I != E; )
    if (I->isExternal() && I->use_empty()) {
      Function *F = I;
      ++I;
      M.getFunctionList().erase(F);
      ++NumResolved;
      Changed = true;
    } else {
      ++I;
    }

  for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; )
    if (I->isExternal() && I->use_empty()) {
      GlobalVariable *GV = I;
      ++I;
      M.getGlobalList().erase(GV);
      ++NumGlobals;
      Changed = true;
    } else {
      ++I;
    }

  return Changed;
}
<|endoftext|>


<commit_before>#include <cmath>
#include <istream>
#include <ostream>
#include <sstream>
#include <time.h>

#include "PosixTimespec.hpp"

const unsigned int PosixTimespec::nanoseconds_per_second = 1000000000;

//==============================================================================
// Initializes to 0s 0ns
//==============================================================================
PosixTimespec::PosixTimespec()
{
    tp.tv_sec  = 0;
    tp.tv_nsec = 0;
}

//==============================================================================
// Saves the provided timespec internally
//==============================================================================
PosixTimespec::PosixTimespec(const timespec& tp) :
    tp(tp)
{
}

//==============================================================================
// Converts to timespec before saving
//==============================================================================
PosixTimespec::PosixTimespec(double tp_sec)
{
    setDouble(tp_sec);
}

//==============================================================================
// Does nothing
//==============================================================================
PosixTimespec::~PosixTimespec()
{
}

//==============================================================================
// Returns double-precision floating point representation of timespec
//==============================================================================
double PosixTimespec::getDouble() const
{
    return static_cast<double>(this->tp.tv_sec) +
        (static_cast<double>(this->tp.tv_nsec) /
         static_cast<double>(nanoseconds_per_second));
}

//==============================================================================
// Sets timespec based on provided double-precision floating point number
//==============================================================================
bool PosixTimespec::setDouble(double tp_dbl)
{
    // This class can't represent values less than zero
    if (tp_dbl < 0.0)
    {
        return false;
    }

    double fractional_part = 0.0;
    this->tp.tv_sec  = std::modf(tp_dbl, &fractional_part);
    this->tp.tv_nsec = fractional_part *
        static_cast<double>(nanoseconds_per_second);

    return true;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec& PosixTimespec::operator=(const timespec& tp)
{
    this->tp.tv_sec  = tp.tv_sec;
    this->tp.tv_nsec = tp.tv_nsec;

    return *this;
}

//==============================================================================
// Performs integer addition so no data loss occurs; tv_nsec overflows and adds
// to tv_sec as one would expect
//==============================================================================
PosixTimespec& PosixTimespec::operator+=(const timespec& tp)
{
    this->tp.tv_sec += tp.tv_sec;
    this->tp.tv_nsec += tp.tv_nsec;

    if (this->tp.tv_nsec >= nanoseconds_per_second)
    {
        this->tp.tv_nsec -= nanoseconds_per_second;
        this->tp.tv_sec += 1;
    }

    return *this;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec& PosixTimespec::operator+=(const PosixTimespec& tp)
{
    timespec tp_temp;
    tp.getTimespec(tp_temp);

    return operator+=(tp_temp);
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec& PosixTimespec::operator-=(const timespec& tp)
{
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec& PosixTimespec::operator-=(const PosixTimespec& tp)
{
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator+(PosixTimespec lhs, const PosixTimespec& rhs)
{
    lhs += rhs;
    return lhs;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator+(PosixTimespec lhs, const timespec& rhs)
{
    lhs += rhs;
    return lhs;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator+(timespec lhs, const PosixTimespec& rhs)
{
    // Addition is symmetric
    return operator+(rhs, lhs);
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator-(PosixTimespec lhs, const PosixTimespec& rhs)
{
    lhs -= rhs;
    return lhs;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator-(PosixTimespec lhs, const timespec& rhs)
{
    lhs -= rhs;
    return lhs;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator-(timespec lhs, const PosixTimespec& rhs)
{
    lhs -= rhs;
    return lhs;
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator==(const PosixTimespec& lhs, const PosixTimespec& rhs)
{
    timespec lhs_tp;
    timespec rhs_tp;

    lhs.getTimespec(lhs_tp);
    rhs.getTimespec(rhs_tp);

    return lhs_tp.tv_sec == rhs_tp.tv_sec && lhs_tp.tv_nsec == rhs_tp.tv_nsec;
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator==(const PosixTimespec& lhs, const timespec& rhs)
{
    return lhs == PosixTimespec(rhs);
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator==(const timespec& lhs, const PosixTimespec& rhs)
{
    return PosixTimespec(lhs) == rhs;
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator!=(const PosixTimespec& lhs, const PosixTimespec& rhs)
{
    return !(lhs == rhs);
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator!=(const PosixTimespec& lhs, const timespec& rhs)
{
    return !(lhs == rhs);
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator!=(const timespec& lhs, const PosixTimespec& rhs)
{
    return !(lhs == rhs);
}

//==============================================================================
// Writes a string representation
//==============================================================================
std::ostream& operator<<(std::ostream& os, PosixTimespec& posix_timespec)
{
    return os << posix_timespec.getDouble();
}

//==============================================================================
// Reads a string representation
//==============================================================================
std::istream& operator>>(std::istream& is, PosixTimespec& posix_timespec)
{
    // Get the number as a string
    std::string posix_timespec_str;
    is >> posix_timespec_str;

    // Convert to double and internalize
    std::istringstream to_double(posix_timespec_str);
    double posix_timespec_dbl = 0.0;
    to_double >> posix_timespec_dbl;

    posix_timespec.setDouble(posix_timespec_dbl);

    return is;
}
<commit_msg>Subtraction implemented, not tested<commit_after>#include <cmath>
#include <istream>
#include <ostream>
#include <sstream>
#include <time.h>

#include "PosixTimespec.hpp"

const unsigned int PosixTimespec::nanoseconds_per_second = 1000000000;

//==============================================================================
// Initializes to 0s 0ns
//==============================================================================
PosixTimespec::PosixTimespec()
{
    tp.tv_sec  = 0;
    tp.tv_nsec = 0;
}

//==============================================================================
// Saves the provided timespec internally
//==============================================================================
PosixTimespec::PosixTimespec(const timespec& tp) :
    tp(tp)
{
}

//==============================================================================
// Converts to timespec before saving
//==============================================================================
PosixTimespec::PosixTimespec(double tp_sec)
{
    setDouble(tp_sec);
}

//==============================================================================
// Does nothing
//==============================================================================
PosixTimespec::~PosixTimespec()
{
}

//==============================================================================
// Returns double-precision floating point representation of timespec
//==============================================================================
double PosixTimespec::getDouble() const
{
    return static_cast<double>(this->tp.tv_sec) +
        (static_cast<double>(this->tp.tv_nsec) /
         static_cast<double>(nanoseconds_per_second));
}

//==============================================================================
// Sets timespec based on provided double-precision floating point number
//==============================================================================
bool PosixTimespec::setDouble(double tp_dbl)
{
    // This class can't represent values less than zero
    if (tp_dbl < 0.0)
    {
        return false;
    }

    double fractional_part = 0.0;
    this->tp.tv_sec  = std::modf(tp_dbl, &fractional_part);
    this->tp.tv_nsec = fractional_part *
        static_cast<double>(nanoseconds_per_second);

    return true;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec& PosixTimespec::operator=(const timespec& tp)
{
    this->tp.tv_sec  = tp.tv_sec;
    this->tp.tv_nsec = tp.tv_nsec;

    return *this;
}

//==============================================================================
// Performs integer addition so no data loss occurs; tv_nsec overflows and adds
// to tv_sec as one would expect
//==============================================================================
PosixTimespec& PosixTimespec::operator+=(const timespec& tp)
{
    this->tp.tv_sec += tp.tv_sec;
    this->tp.tv_nsec += tp.tv_nsec;

    if (this->tp.tv_nsec >= nanoseconds_per_second)
    {
        this->tp.tv_nsec -= nanoseconds_per_second;
        this->tp.tv_sec += 1;
    }

    return *this;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec& PosixTimespec::operator+=(const PosixTimespec& tp)
{
    timespec tp_temp;
    tp.getTimespec(tp_temp);

    return operator+=(tp_temp);
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec& PosixTimespec::operator-=(const timespec& tp)
{
    this->tp.tv_sec -= tp.tv_sec;

    if (tp.tv_nsec > this->tp.tv_nsec)
    {
        this->tp.tv_sec -= 1;
        this->tp.tv_nsec = nanoseconds_per_second -
            (tp.tv_nsec - this->tp.tv_nsec);
    }

    return *this;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec& PosixTimespec::operator-=(const PosixTimespec& tp)
{
    timespec tp_temp;
    tp.getTimespec(tp_temp);

    return operator-=(tp_temp);
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator+(PosixTimespec lhs, const PosixTimespec& rhs)
{
    lhs += rhs;
    return lhs;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator+(PosixTimespec lhs, const timespec& rhs)
{
    lhs += rhs;
    return lhs;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator+(timespec lhs, const PosixTimespec& rhs)
{
    // Addition is symmetric
    return operator+(rhs, lhs);
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator-(PosixTimespec lhs, const PosixTimespec& rhs)
{
    lhs -= rhs;
    return lhs;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator-(PosixTimespec lhs, const timespec& rhs)
{
    lhs -= rhs;
    return lhs;
}

//==============================================================================
// Does what you would expect
//==============================================================================
PosixTimespec operator-(timespec lhs, const PosixTimespec& rhs)
{
    PosixTimespec lhs_ts(lhs);
    return operator-(lhs_ts, rhs);
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator==(const PosixTimespec& lhs, const PosixTimespec& rhs)
{
    timespec lhs_tp;
    timespec rhs_tp;

    lhs.getTimespec(lhs_tp);
    rhs.getTimespec(rhs_tp);

    return lhs_tp.tv_sec == rhs_tp.tv_sec && lhs_tp.tv_nsec == rhs_tp.tv_nsec;
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator==(const PosixTimespec& lhs, const timespec& rhs)
{
    return lhs == PosixTimespec(rhs);
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator==(const timespec& lhs, const PosixTimespec& rhs)
{
    return PosixTimespec(lhs) == rhs;
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator!=(const PosixTimespec& lhs, const PosixTimespec& rhs)
{
    return !(lhs == rhs);
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator!=(const PosixTimespec& lhs, const timespec& rhs)
{
    return !(lhs == rhs);
}

//==============================================================================
// Does what you would expect
//==============================================================================
bool operator!=(const timespec& lhs, const PosixTimespec& rhs)
{
    return !(lhs == rhs);
}

//==============================================================================
// Writes a string representation
//==============================================================================
std::ostream& operator<<(std::ostream& os, PosixTimespec& posix_timespec)
{
    return os << posix_timespec.getDouble();
}

//==============================================================================
// Reads a string representation
//==============================================================================
std::istream& operator>>(std::istream& is, PosixTimespec& posix_timespec)
{
    // Get the number as a string
    std::string posix_timespec_str;
    is >> posix_timespec_str;

    // Convert to double and internalize
    std::istringstream to_double(posix_timespec_str);
    double posix_timespec_dbl = 0.0;
    to_double >> posix_timespec_dbl;

    posix_timespec.setDouble(posix_timespec_dbl);

    return is;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
 */

#include "fucopy.hxx"
#include <sfx2/progress.hxx>
#include <svx/svxids.hrc>

#include "sdresid.hxx"
#include "sdattr.hxx"
#include "strings.hrc"
#include "ViewShell.hxx"
#include "View.hxx"
#include "drawdoc.hxx"
#include "DrawDocShell.hxx"
#include <vcl/wrkwin.hxx>
#include <svx/svdobj.hxx>
#include <vcl/msgbox.hxx>
#include <sfx2/app.hxx>
#include <svx/xcolit.hxx>
#include <svx/xflclit.hxx>
#include <svx/xdef.hxx>
#include <svx/xfillit0.hxx>
#include <sfx2/request.hxx>
#include "sdabstdlg.hxx"
namespace sd {

TYPEINIT1( FuCopy, FuPoor );

FuCopy::FuCopy (
    ViewShell* pViewSh,
    ::sd::Window* pWin,
    ::sd::View* pView,
    SdDrawDocument* pDoc,
    SfxRequest& rReq)
    : FuPoor(pViewSh, pWin, pView, pDoc, rReq)
{
}

rtl::Reference<FuPoor> FuCopy::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq )
{
    rtl::Reference<FuPoor> xFunc( new FuCopy( pViewSh, pWin, pView, pDoc, rReq ) );
    xFunc->DoExecute(rReq);
    return xFunc;
}

void FuCopy::DoExecute( SfxRequest& rReq )
{
    if( mpView->AreObjectsMarked() )
    {
        // Undo
        OUString aString( mpView->GetDescriptionOfMarkedObjects() );
        aString += " " + SD_RESSTR( STR_UNDO_COPYOBJECTS );
        mpView->BegUndo( aString );

        const SfxItemSet* pArgs = rReq.GetArgs();

        if( !pArgs )
        {
            SfxItemSet aSet( mpViewShell->GetPool(),
                                ATTR_COPY_START, ATTR_COPY_END, 0 );

            // indicate color attribute
            SfxItemSet aAttr( mpDoc->GetPool() );
            mpView->GetAttributes( aAttr );
            const SfxPoolItem*  pPoolItem = NULL;

            if( SFX_ITEM_SET == aAttr.GetItemState( XATTR_FILLSTYLE, true, &pPoolItem ) )
            {
                XFillStyle eStyle = ( ( const XFillStyleItem* ) pPoolItem )->GetValue();

                if( eStyle == XFILL_SOLID &&
                    SFX_ITEM_SET == aAttr.GetItemState( XATTR_FILLCOLOR, true, &pPoolItem ) )
                {
                    const XFillColorItem* pItem = ( const XFillColorItem* ) pPoolItem;
                    XColorItem aXColorItem( ATTR_COPY_START_COLOR, pItem->GetName(),
                                                        pItem->GetColorValue() );
                    aSet.Put( aXColorItem );

                }
            }

            SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
            if( pFact )
            {
                AbstractCopyDlg* pDlg = pFact->CreateCopyDlg(NULL, aSet, mpDoc->GetColorList(), mpView );
                if( pDlg )
                {
                    sal_uInt16 nResult = pDlg->Execute();

                    switch( nResult )
                    {
                        case RET_OK:
                            pDlg->GetAttr( aSet );
                            rReq.Done( aSet );
                            pArgs = rReq.GetArgs();
                        break;

                        default:
                        {
                            delete pDlg;
                            mpView->EndUndo();
                        }
                        return; // Cancel
                    }
                    delete( pDlg );
                }
            }
        }

        Rectangle           aRect;
        sal_Int32               lWidth = 0, lHeight = 0, lSizeX = 0L, lSizeY = 0L, lAngle = 0L;
        sal_uInt16              nNumber = 0;
        Color               aStartColor, aEndColor;
        sal_Bool                bColor = sal_False;
        const SfxPoolItem*  pPoolItem = NULL;

        // Count
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_NUMBER, true, &pPoolItem ) )
            nNumber = ( ( const SfxUInt16Item* ) pPoolItem )->GetValue();

        // translation
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_MOVE_X, true, &pPoolItem ) )
            lSizeX = ( ( const SfxInt32Item* ) pPoolItem )->GetValue();
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_MOVE_Y, true, &pPoolItem ) )
            lSizeY = ( ( const SfxInt32Item* ) pPoolItem )->GetValue();
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_ANGLE, true, &pPoolItem ) )
            lAngle = ( ( const SfxInt32Item* )pPoolItem )->GetValue();

        // scale
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_WIDTH, true, &pPoolItem ) )
            lWidth = ( ( const SfxInt32Item* ) pPoolItem )->GetValue();
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_HEIGHT, true, &pPoolItem ) )
            lHeight = ( ( const SfxInt32Item* ) pPoolItem )->GetValue();

        // start/end color
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_START_COLOR, true, &pPoolItem ) )
        {
            aStartColor = ( ( const XColorItem* ) pPoolItem )->GetColorValue();
            bColor = sal_True;
        }
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_END_COLOR, true, &pPoolItem ) )
        {
            aEndColor = ( ( const XColorItem* ) pPoolItem )->GetColorValue();
            if( aStartColor == aEndColor )
                bColor = sal_False;
        }
        else
            bColor = sal_False;

        // remove handles
        //HMHmpView->HideMarkHdl();

        SfxProgress*    pProgress = NULL;
        sal_Bool            bWaiting = sal_False;

        if( nNumber > 1 )
        {
            OUString aStr( SD_RESSTR( STR_OBJECTS ) );
            aStr += " " + SD_RESSTR( STR_UNDO_COPYOBJECTS );

            pProgress = new SfxProgress( mpDocSh, aStr, nNumber );
            mpDocSh->SetWaitCursor( sal_True );
            bWaiting = sal_True;
        }

        const SdrMarkList   aMarkList( mpView->GetMarkedObjectList() );
        const sal_uLong         nMarkCount = aMarkList.GetMarkCount();
        SdrObject*          pObj = NULL;

        // calculate number of possible copies
        aRect = mpView->GetAllMarkedRect();

        if( lWidth < 0L )
        {
            long nTmp = ( aRect.Right() - aRect.Left() ) / -lWidth;
            nNumber = (sal_uInt16) std::min( nTmp, (long)nNumber );
        }

        if( lHeight < 0L )
        {
            long nTmp = ( aRect.Bottom() - aRect.Top() ) / -lHeight;
            nNumber = (sal_uInt16) std::min( nTmp, (long)nNumber );
        }

        for( sal_uInt16 i = 1; i <= nNumber; i++ )
        {
            if( pProgress )
                pProgress->SetState( i );

            aRect = mpView->GetAllMarkedRect();

            if( ( 1 == i ) && bColor )
            {
                SfxItemSet aNewSet( mpViewShell->GetPool(), XATTR_FILLSTYLE, XATTR_FILLCOLOR, 0L );
                aNewSet.Put( XFillStyleItem( XFILL_SOLID ) );
                aNewSet.Put( XFillColorItem( OUString(), aStartColor ) );
                mpView->SetAttributes( aNewSet );
            }

            // make a copy of selected objects
            mpView->CopyMarked();

            // get newly selected objects
            SdrMarkList aCopyMarkList( mpView->GetMarkedObjectList() );
            sal_uLong       j, nCopyMarkCount = aMarkList.GetMarkCount();

            // set protection flags at marked copies to null
            for( j = 0; j < nCopyMarkCount; j++ )
            {
                pObj = aCopyMarkList.GetMark( j )->GetMarkedSdrObj();

                if( pObj )
                {
                    pObj->SetMoveProtect( false );
                    pObj->SetResizeProtect( false );
                }
            }

            Fraction aWidth( aRect.Right() - aRect.Left() + lWidth, aRect.Right() - aRect.Left() );
            Fraction aHeight( aRect.Bottom() - aRect.Top() + lHeight, aRect.Bottom() - aRect.Top() );

            if( mpView->IsResizeAllowed() )
                mpView->ResizeAllMarked( aRect.TopLeft(), aWidth, aHeight );

            if( mpView->IsRotateAllowed() )
                mpView->RotateAllMarked( aRect.Center(), lAngle * 100 );

            if( mpView->IsMoveAllowed() )
                mpView->MoveAllMarked( Size( lSizeX, lSizeY ) );

            // set protection flags at marked copies to original values
            if( nMarkCount == nCopyMarkCount )
            {
                for( j = 0; j < nMarkCount; j++ )
                {
                    SdrObject* pSrcObj = aMarkList.GetMark( j )->GetMarkedSdrObj();
                    SdrObject* pDstObj = aCopyMarkList.GetMark( j )->GetMarkedSdrObj();

                    if( pSrcObj && pDstObj &&
                        ( pSrcObj->GetObjInventor() == pDstObj->GetObjInventor() ) &&
                        ( pSrcObj->GetObjIdentifier() == pDstObj->GetObjIdentifier() ) )
                    {
                        pDstObj->SetMoveProtect( pSrcObj->IsMoveProtect() );
                        pDstObj->SetResizeProtect( pSrcObj->IsResizeProtect() );
                    }
                }
            }

            if( bColor )
            {
                // probably room for optimizations, but may can lead to rounding errors
                sal_uInt8 nRed = aStartColor.GetRed() + (sal_uInt8) ( ( (long) aEndColor.GetRed() - (long) aStartColor.GetRed() ) * (long) i / (long) nNumber  );
                sal_uInt8 nGreen = aStartColor.GetGreen() + (sal_uInt8) ( ( (long) aEndColor.GetGreen() - (long) aStartColor.GetGreen() ) *  (long) i / (long) nNumber );
                sal_uInt8 nBlue = aStartColor.GetBlue() + (sal_uInt8) ( ( (long) aEndColor.GetBlue() - (long) aStartColor.GetBlue() ) * (long) i / (long) nNumber );
                Color aNewColor( nRed, nGreen, nBlue );
                SfxItemSet aNewSet( mpViewShell->GetPool(), XATTR_FILLSTYLE, XATTR_FILLCOLOR, 0L );
                aNewSet.Put( XFillStyleItem( XFILL_SOLID ) );
                aNewSet.Put( XFillColorItem( OUString(), aNewColor ) );
                mpView->SetAttributes( aNewSet );
            }
        }

        if ( pProgress )
            delete pProgress;

        if ( bWaiting )
            mpDocSh->SetWaitCursor( sal_False );

        // show handles
        mpView->AdjustMarkHdl(); //HMH sal_True );
        //HMHpView->ShowMarkHdl();

        mpView->EndUndo();
    }
}

} // end of namespace

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#704748 Dereference after null check<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
 */

#include "fucopy.hxx"
#include <sfx2/progress.hxx>
#include <svx/svxids.hrc>

#include "sdresid.hxx"
#include "sdattr.hxx"
#include "strings.hrc"
#include "ViewShell.hxx"
#include "View.hxx"
#include "drawdoc.hxx"
#include "DrawDocShell.hxx"
#include <vcl/wrkwin.hxx>
#include <svx/svdobj.hxx>
#include <vcl/msgbox.hxx>
#include <sfx2/app.hxx>
#include <svx/xcolit.hxx>
#include <svx/xflclit.hxx>
#include <svx/xdef.hxx>
#include <svx/xfillit0.hxx>
#include <sfx2/request.hxx>
#include "sdabstdlg.hxx"
namespace sd {

TYPEINIT1( FuCopy, FuPoor );

FuCopy::FuCopy (
    ViewShell* pViewSh,
    ::sd::Window* pWin,
    ::sd::View* pView,
    SdDrawDocument* pDoc,
    SfxRequest& rReq)
    : FuPoor(pViewSh, pWin, pView, pDoc, rReq)
{
}

rtl::Reference<FuPoor> FuCopy::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq )
{
    rtl::Reference<FuPoor> xFunc( new FuCopy( pViewSh, pWin, pView, pDoc, rReq ) );
    xFunc->DoExecute(rReq);
    return xFunc;
}

void FuCopy::DoExecute( SfxRequest& rReq )
{
    if( mpView->AreObjectsMarked() )
    {
        // Undo
        OUString aString( mpView->GetDescriptionOfMarkedObjects() );
        aString += " " + SD_RESSTR( STR_UNDO_COPYOBJECTS );
        mpView->BegUndo( aString );

        const SfxItemSet* pArgs = rReq.GetArgs();

        if( !pArgs )
        {
            SfxItemSet aSet( mpViewShell->GetPool(),
                                ATTR_COPY_START, ATTR_COPY_END, 0 );

            // indicate color attribute
            SfxItemSet aAttr( mpDoc->GetPool() );
            mpView->GetAttributes( aAttr );
            const SfxPoolItem*  pPoolItem = NULL;

            if( SFX_ITEM_SET == aAttr.GetItemState( XATTR_FILLSTYLE, true, &pPoolItem ) )
            {
                XFillStyle eStyle = ( ( const XFillStyleItem* ) pPoolItem )->GetValue();

                if( eStyle == XFILL_SOLID &&
                    SFX_ITEM_SET == aAttr.GetItemState( XATTR_FILLCOLOR, true, &pPoolItem ) )
                {
                    const XFillColorItem* pItem = ( const XFillColorItem* ) pPoolItem;
                    XColorItem aXColorItem( ATTR_COPY_START_COLOR, pItem->GetName(),
                                                        pItem->GetColorValue() );
                    aSet.Put( aXColorItem );

                }
            }

            SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
            if( pFact )
            {
                AbstractCopyDlg* pDlg = pFact->CreateCopyDlg(NULL, aSet, mpDoc->GetColorList(), mpView );
                if (!pDlg)
                    return;

                sal_uInt16 nResult = pDlg->Execute();

                switch( nResult )
                {
                    case RET_OK:
                        pDlg->GetAttr( aSet );
                        rReq.Done( aSet );
                        pArgs = rReq.GetArgs();
                    break;

                    default:
                    {
                        delete pDlg;
                        mpView->EndUndo();
                    }
                    return; // Cancel
                }
                delete pDlg;
            }
        }

        Rectangle           aRect;
        sal_Int32               lWidth = 0, lHeight = 0, lSizeX = 0L, lSizeY = 0L, lAngle = 0L;
        sal_uInt16              nNumber = 0;
        Color               aStartColor, aEndColor;
        sal_Bool                bColor = sal_False;
        const SfxPoolItem*  pPoolItem = NULL;

        // Count
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_NUMBER, true, &pPoolItem ) )
            nNumber = ( ( const SfxUInt16Item* ) pPoolItem )->GetValue();

        // translation
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_MOVE_X, true, &pPoolItem ) )
            lSizeX = ( ( const SfxInt32Item* ) pPoolItem )->GetValue();
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_MOVE_Y, true, &pPoolItem ) )
            lSizeY = ( ( const SfxInt32Item* ) pPoolItem )->GetValue();
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_ANGLE, true, &pPoolItem ) )
            lAngle = ( ( const SfxInt32Item* )pPoolItem )->GetValue();

        // scale
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_WIDTH, true, &pPoolItem ) )
            lWidth = ( ( const SfxInt32Item* ) pPoolItem )->GetValue();
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_HEIGHT, true, &pPoolItem ) )
            lHeight = ( ( const SfxInt32Item* ) pPoolItem )->GetValue();

        // start/end color
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_START_COLOR, true, &pPoolItem ) )
        {
            aStartColor = ( ( const XColorItem* ) pPoolItem )->GetColorValue();
            bColor = sal_True;
        }
        if( SFX_ITEM_SET == pArgs->GetItemState( ATTR_COPY_END_COLOR, true, &pPoolItem ) )
        {
            aEndColor = ( ( const XColorItem* ) pPoolItem )->GetColorValue();
            if( aStartColor == aEndColor )
                bColor = sal_False;
        }
        else
            bColor = sal_False;

        // remove handles
        //HMHmpView->HideMarkHdl();

        SfxProgress*    pProgress = NULL;
        sal_Bool            bWaiting = sal_False;

        if( nNumber > 1 )
        {
            OUString aStr( SD_RESSTR( STR_OBJECTS ) );
            aStr += " " + SD_RESSTR( STR_UNDO_COPYOBJECTS );

            pProgress = new SfxProgress( mpDocSh, aStr, nNumber );
            mpDocSh->SetWaitCursor( sal_True );
            bWaiting = sal_True;
        }

        const SdrMarkList   aMarkList( mpView->GetMarkedObjectList() );
        const sal_uLong         nMarkCount = aMarkList.GetMarkCount();
        SdrObject*          pObj = NULL;

        // calculate number of possible copies
        aRect = mpView->GetAllMarkedRect();

        if( lWidth < 0L )
        {
            long nTmp = ( aRect.Right() - aRect.Left() ) / -lWidth;
            nNumber = (sal_uInt16) std::min( nTmp, (long)nNumber );
        }

        if( lHeight < 0L )
        {
            long nTmp = ( aRect.Bottom() - aRect.Top() ) / -lHeight;
            nNumber = (sal_uInt16) std::min( nTmp, (long)nNumber );
        }

        for( sal_uInt16 i = 1; i <= nNumber; i++ )
        {
            if( pProgress )
                pProgress->SetState( i );

            aRect = mpView->GetAllMarkedRect();

            if( ( 1 == i ) && bColor )
            {
                SfxItemSet aNewSet( mpViewShell->GetPool(), XATTR_FILLSTYLE, XATTR_FILLCOLOR, 0L );
                aNewSet.Put( XFillStyleItem( XFILL_SOLID ) );
                aNewSet.Put( XFillColorItem( OUString(), aStartColor ) );
                mpView->SetAttributes( aNewSet );
            }

            // make a copy of selected objects
            mpView->CopyMarked();

            // get newly selected objects
            SdrMarkList aCopyMarkList( mpView->GetMarkedObjectList() );
            sal_uLong       j, nCopyMarkCount = aMarkList.GetMarkCount();

            // set protection flags at marked copies to null
            for( j = 0; j < nCopyMarkCount; j++ )
            {
                pObj = aCopyMarkList.GetMark( j )->GetMarkedSdrObj();

                if( pObj )
                {
                    pObj->SetMoveProtect( false );
                    pObj->SetResizeProtect( false );
                }
            }

            Fraction aWidth( aRect.Right() - aRect.Left() + lWidth, aRect.Right() - aRect.Left() );
            Fraction aHeight( aRect.Bottom() - aRect.Top() + lHeight, aRect.Bottom() - aRect.Top() );

            if( mpView->IsResizeAllowed() )
                mpView->ResizeAllMarked( aRect.TopLeft(), aWidth, aHeight );

            if( mpView->IsRotateAllowed() )
                mpView->RotateAllMarked( aRect.Center(), lAngle * 100 );

            if( mpView->IsMoveAllowed() )
                mpView->MoveAllMarked( Size( lSizeX, lSizeY ) );

            // set protection flags at marked copies to original values
            if( nMarkCount == nCopyMarkCount )
            {
                for( j = 0; j < nMarkCount; j++ )
                {
                    SdrObject* pSrcObj = aMarkList.GetMark( j )->GetMarkedSdrObj();
                    SdrObject* pDstObj = aCopyMarkList.GetMark( j )->GetMarkedSdrObj();

                    if( pSrcObj && pDstObj &&
                        ( pSrcObj->GetObjInventor() == pDstObj->GetObjInventor() ) &&
                        ( pSrcObj->GetObjIdentifier() == pDstObj->GetObjIdentifier() ) )
                    {
                        pDstObj->SetMoveProtect( pSrcObj->IsMoveProtect() );
                        pDstObj->SetResizeProtect( pSrcObj->IsResizeProtect() );
                    }
                }
            }

            if( bColor )
            {
                // probably room for optimizations, but may can lead to rounding errors
                sal_uInt8 nRed = aStartColor.GetRed() + (sal_uInt8) ( ( (long) aEndColor.GetRed() - (long) aStartColor.GetRed() ) * (long) i / (long) nNumber  );
                sal_uInt8 nGreen = aStartColor.GetGreen() + (sal_uInt8) ( ( (long) aEndColor.GetGreen() - (long) aStartColor.GetGreen() ) *  (long) i / (long) nNumber );
                sal_uInt8 nBlue = aStartColor.GetBlue() + (sal_uInt8) ( ( (long) aEndColor.GetBlue() - (long) aStartColor.GetBlue() ) * (long) i / (long) nNumber );
                Color aNewColor( nRed, nGreen, nBlue );
                SfxItemSet aNewSet( mpViewShell->GetPool(), XATTR_FILLSTYLE, XATTR_FILLCOLOR, 0L );
                aNewSet.Put( XFillStyleItem( XFILL_SOLID ) );
                aNewSet.Put( XFillColorItem( OUString(), aNewColor ) );
                mpView->SetAttributes( aNewSet );
            }
        }

        if ( pProgress )
            delete pProgress;

        if ( bWaiting )
            mpDocSh->SetWaitCursor( sal_False );

        // show handles
        mpView->AdjustMarkHdl(); //HMH sal_True );
        //HMHpView->ShowMarkHdl();

        mpView->EndUndo();
    }
}

} // end of namespace

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


<commit_before>/*************************************************************************
 *
 *  $RCSfile: bmcache.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: ka $ $Date: 2001-09-24 13:18:14 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SD_BMCACHE_HXX
#define _SD_BMCACHE_HXX

#ifndef _LIST_HXX //autogen
#include <tools/list.hxx>
#endif

class SdPage;
class GraphicObject;

class BitmapCache
{
    ULONG                   nMaxSize;
    ULONG                   nCurSize;
    List                    aEntries;

public:
                            BitmapCache(ULONG nMaxSizeKB)
                              : nMaxSize(nMaxSizeKB), nCurSize(0) {}
    virtual                 ~BitmapCache();

    void                    Add(const SdPage* pPage, const Bitmap& rBmp, long nZoomPercent);
    const GraphicObject*    Get(const SdPage* pPage, long& rZoomPercent, long nZoomTolerancePercent);
    void                    Remove(const SdPage* pPage);
};

#endif  // _SD_BMCACHE_HXX

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.908); FILE MERGED 2005/09/05 13:22:54 rt 1.2.908.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: bmcache.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 05:22:25 $
 *
 *  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 _SD_BMCACHE_HXX
#define _SD_BMCACHE_HXX

#ifndef _LIST_HXX //autogen
#include <tools/list.hxx>
#endif

class SdPage;
class GraphicObject;

class BitmapCache
{
    ULONG                   nMaxSize;
    ULONG                   nCurSize;
    List                    aEntries;

public:
                            BitmapCache(ULONG nMaxSizeKB)
                              : nMaxSize(nMaxSizeKB), nCurSize(0) {}
    virtual                 ~BitmapCache();

    void                    Add(const SdPage* pPage, const Bitmap& rBmp, long nZoomPercent);
    const GraphicObject*    Get(const SdPage* pPage, long& rZoomPercent, long nZoomTolerancePercent);
    void                    Remove(const SdPage* pPage);
};

#endif  // _SD_BMCACHE_HXX

<|endoftext|>