<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- DAG
 *
 * Defines the base hierarchy for DAG nodes.
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __PREDICATE__DAG__
#define __PREDICATE__DAG__

#include <predicate/ironbee.hpp>
#include <predicate/value.hpp>

#include <ironbeepp/memory_pool_lite.hpp>

#include <boost/enable_shared_from_this.hpp>
#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>

#include <iostream>
#include <list>
#include <string>

namespace IronBee {
namespace Predicate {

// Defined below.
class Node;
class Call;
class Literal;

// Defined in reporter.hpp
class NodeReporter;
// Defined in merge_graph.hpp
class MergeGraph;
// Defined in call_factory.hpp
class CallFactory;
// Defined in eval.hpp.
class GraphEvalState;
class NodeEvalState;

/**
 * Shared pointer to Node.
 **/
typedef boost::shared_ptr<Node> node_p;

/**
 * Weak pointer to Node.
 **/
typedef boost::weak_ptr<Node> weak_node_p;

/**
 * Shared const pointer to Node.
 **/
typedef boost::shared_ptr<const Node> node_cp;

/**
 * Shared pointer to Call.
 **/
typedef boost::shared_ptr<Call> call_p;

/**
 * Shared const pointer to Call.
 **/
typedef boost::shared_ptr<const Call> call_cp;

/**
 * Shared pointer to Literal.
 **/
typedef boost::shared_ptr<Literal> literal_p;

/**
 * Shared const pointer to Literal.
 **/
typedef boost::shared_ptr<const Literal> literal_cp;

//! List of nodes.  See children().
typedef std::list<node_p> node_list_t;

//! Weak list of nodes.  See parents().
typedef std::list<weak_node_p> weak_node_list_t;

//! List of const nodes.
typedef std::list<node_cp> node_clist_t;

/**
 * A node in the predicate DAG.
 *
 * Nodes make up the predicate DAG.  They also appear in the expressions trees
 * that are merged together to construct the DAG. This class is the top of
 * the class hierarchy for nodes.  It can not be directly instantiated or
 * subclassed.  For literal values, Literal.  For call values, create and
 * instantiate a subclass of Call.
 *
 * This class hierarchy defines how to evaluate (through eval_calculate(),
 * eval_initialize()) but does not store the data.
 * Data is stored separately in GraphEvalState and NodeEvalState.  This
 * separation allows simultaneous evaluations of the DAG across different
 * EvalContext.
 *
 * @sa Call
 * @sa Literal
 */
class Node :
    public boost::enable_shared_from_this<Node>,
    boost::noncopyable
{
    friend class Call;
    friend class Literal;

private:
    //! Private Constructor.
    Node();

public:
    //! Destructor.
    virtual ~Node();

    /**
     * @name Graph Structure Manipulation
     * These routines are used to modify the structure of the graph.
     **/
    ///@{

    /**
     * Add a child.
     *
     * Adds to end of children() and adds @c this to end of parents() of
     * child.  Subclasses can add additional behavior.
     *
     * O(1)
     *
     * @param[in] child Child to add.
     * @throw IronBee::einval if ! @a child.
     **/
    virtual void add_child(const node_p& child);

    /**
     * Remove a child.
     *
     * Removes from children() and removes @c this from parents() of child.
     * Subclasses can add additional behavior.
     *
     * O(n) where n is size of children() of @c this or parents() of child.
     *
     * @param[in] child Child to remove.
     * @throw IronBee::enoent if no such child.
     * @throw IronBee::einval if not a parent of child.
     * @throw IronBee::einval if ! @a child.
     **/
    virtual void remove_child(const node_p& child);

    /**
     * Replace a child.
     *
     * Replaces a child with another node.  This can be used to change
     * a child without moving it to the end of the children as remove_child(),
     * add_child() would.
     *
     * O(n) where n is size of children() of @c this or parents() of child.
     *
     * @param[in] child Child to replace.
     * @param[in] with  Child to replace with.
     * @throw IronBee::enoent if no such child.
     * @throw IronBee::einval if not a parent of child.
     * @throw IronBee::einval if ! @a child or ! @a with.
     **/
    virtual void replace_child(const node_p& child, const node_p& with);

    ///@}

    /**
     * S-Expression.
     *
     * An S-expression representation of the expression tree rooted at this
     * node.  See parse.hpp for detailed grammar.
     *
     * This method returns a string reference, but this reference is not
     * stable if this node or any children are changed.  It should be copied
     * if needed beyond such operations.
     *
     * S-Expressions are calculated dynamically and cached, so calling this
     * method is cheap.
     *
     * @return S-Expression of expression tree rooted at node.
     **/
    virtual const std::string& to_s() const = 0;

    //! Children accessor -- const.
    const node_list_t& children() const
    {
        return m_children;
    }
    //! Parents accessor -- const.
    const weak_node_list_t& parents() const
    {
        return m_parents;
    }

    //! True iff node is a literal.
    bool is_literal() const;

    /**
     * @name Lifecycle
     * These routine implement the graph lifecycle.
     **/
    ///@{

    /**
     * Perform pre-transformation validations.
     *
     * This method may be overridden by a child.  Default behavior is to
     * call validate().
     *
     * @note Exceptions will not be immediately caught so should only be used
     *       if it is appropriate to abort the entire predicate system, e.g.,
     *       on an insanity error.
     *
     * @param[in] reporter Reporter to use for errors or warnings.
     **/
    virtual void pre_transform(NodeReporter reporter) const;

    /**
     * Perform transformations.
     *
     * This method may be overridden by a child.  Default behavior is to
     * do nothing and return false.
     *
     * This method is called for every Node during the transformation phase.
     * If any such call returns true, the whole process is repeated.
     *
     * Transformations should not be done directly, but rather through
     * @a merge_graph(), i.e., do not use add_child(), remove_child(), or
     * replace_child(); instead use MergeGraph::add(), MergeGraph::remove(),
     * or MergeGraph::replace().  Note that your method can fetch a
     * @ref node_p for itself via shared_from_this().
     *
     * Note: Reporting errors will allow the current transformation loop to
     * continue for other nodes, but will then end the transformation phase.
     *
     * @param[in] merge_graph  MergeGraph used to change the DAG.
     * @param[in] call_factory CallFactory to create new nodes with.
     * @param[in] reporter     Reporter to use for errors or warnings.
     * @return true iff any changes were made.
     **/
    virtual bool transform(
        MergeGraph&        merge_graph,
        const CallFactory& call_factory,
        NodeReporter       reporter
    );

    /**
     * Perform post-transformation validations.
     *
     * Default behavior is to call validate().  See pre_transform() for
     * additional discussion.
     *
     * @param[in] reporter Reporter to use for errors or warnings.
     **/
    virtual void post_transform(NodeReporter reporter) const;

    /**
     * Perform validation checks.
     *
     * By default, this is called by pre_transform() and post_transform(),
     * although that behavior can be overridden.
     *
     * Default behavior is to do nothing.
     *
     * @sa Standard::Validate
     *
     * @param[in] reporter Reporter to use for errors or warnings.
     * @return true iff no *errors* reported.
     **/
    virtual bool validate(NodeReporter reporter) const;

    /**
     * Preform any state preparations needed for evaluation.
     *
     * This method is called after all transformations are complete but before
     * any evaluation.  It provides the environment of the node and should be
     * used to do any setup needed to calculate values.
     *
     * @param[in]  environment Environment for evaluation.
     * @param[in]  reporter    Reporter to report errors with.
     **/
    virtual void pre_eval(Environment environment, NodeReporter reporter);

    ///@}

    /**
     * @name Evaluation Support
     * Methods to support evaluation.  These methods are usually not called
     * directly, but instead are called from GraphEvalState and NodeEvalState.
     * They are public to allow for certain low level interactions with nodes.
     **/
    ///@{

    //! Set index of node to @a index.
    void set_index(size_t index);

    //! Access index.
    // Intentionally inline.
    size_t index() const
    {
        return m_index;
    }

    /**
     * Initialize node eval state.
     *
     * This method is called before each evaluation run.  It should setup
     * any state or initial values of @a node_eval_state.  See
     * NodeEvalState::state().
     *
     * @param[in] graph_eval_state Graph evaluation state.
     * @param[in] context          Evaluation context.
     **/
    virtual void eval_initialize(
        GraphEvalState& node_eval_state,
        EvalContext     context
    ) const;

    /**
     * Calculate value and update state.
     *
     * Subclass classes should implement this to calculate and call methods
     * of @a node_eval_state appropriately to add values and finish.
     *
     * This method will be called any time eval() is called while the node is
     * unfinished.  It will not be called on a finished node.
     *
     * @param[in] graph_eval_state Graph evaluation state.
     * @param[in] context          Context of calculation.
     * @return Value of node.
     */
    virtual void eval_calculate(
        GraphEvalState& graph_eval_state,
        EvalContext     context
    ) const = 0;

    ///@}

private:
    /**
     * Remove this from parents of @a child.
     *
     * @param[in] child Child to unlink from.
     * @throw IronBee::einval if not in @a child's parent list.
     **/
    void unlink_from_child(const node_p& child) const;

    //! List of parents (note weak pointers).
    weak_node_list_t m_parents;
    //! List of children.
    node_list_t m_children;
    //! Index.
    size_t m_index;
};

//! Ostream output operator.
std::ostream& operator<<(std::ostream& out, const Node& node);

/**
 * Node representing a function Call.
 *
 * All Call nodes must have a name.  Calls with the same name are considered
 * to implement the same function.
 *
 * This class is unique in the class hierarchy as being subclassable.  Users
 * should create subclasses for specific functions.  Subclasses must implement
 * name() and eval_calculate().  Subclasses may also define add_child(),
 * remove_child(), and replace_child() but must call the parents methods
* within.
 **/
class Call :
    public Node
{
public:
    //! Constructor.
    Call();

    //! See Node::add_child().
    virtual void add_child(const node_p& child);

    //! See Node::remove_child().
    virtual void remove_child(const node_p& child);

    //! See Node::replace_child().
    virtual void replace_child(const node_p& child, const node_p& with);

    //! S-expression: (@c name children...)
    virtual const std::string& to_s() const;

    /**
     * Name accessor.
     */
    virtual std::string name() const = 0;

private:
    //! Mark m_s as in need of recalculation.
    void reset_s() const;

    //! Recalculate m_s.
    void recalculate_s() const;

    // Because name() is pure, Call::Call() can not calculate m_s.  I.e., we
    // need to fully construct the class before setting m_s.  So we have
    // to_s() calculate it on the fly the first time.  The following two
    // members maintain that cache.

    //! Have we calculate m_s at all?
    mutable bool m_calculated_s;

    //! String form.
    mutable std::string m_s;
};

/**
 * Literal node: no children and value independent of EvalContext.
 *
 * This class may not be subclassed.
 **/
class Literal :
    public Node
{
public:
    //! Construct null literal.
    Literal();

    //! Construct literal from memory pool and value.
    Literal(
        const boost::shared_ptr<ScopedMemoryPoolLite>& memory_pool,
        Value                                          value
    );

    //! Construct literal from value, duping value with Value::dup().
    explicit Literal(Value value);

    //! Construct literal from int.
    explicit Literal(int value);

    //! Construct literal from float.
    explicit Literal(long double value);

    //! Construct literal from string.
    explicit Literal(const std::string& value);

    //! Value of literal.
    // Intentionally inline.
    Value literal_value() const
    {
        return m_value;
    }

    //! @throw IronBee::einval always.
    virtual void add_child(const node_p&);
    //! @throw IronBee::einval always.
    virtual void remove_child(const node_p&);
    //! @throw IronBee::einval always.
    virtual void replace_child(const node_p& child, const node_p& with);

    //! @throw IronBee::einval always.
    virtual void eval_calculate(
        GraphEvalState& graph_eval_state,
        EvalContext    context
    ) const;

    //! Set value based on literal_values() and finish.
    virtual void eval_initialize(
        GraphEvalState& graph_eval_state,
        EvalContext     context
    ) const;

    //! S-Expression.
    // Intentionally inline.
    virtual const std::string& to_s() const
    {
        return m_sexpr;
    }

private:
    //! Keep track of where our memory comes from.
    boost::shared_ptr<ScopedMemoryPoolLite> m_memory_pool;

    //! Value returned by literal_values().
    Value m_value;

    //! Cache sexpr for easy access.
    std::string m_sexpr;
};

} // Predicate
} // IronBee

#endif
<commit_msg>predicate/dag.hpp: Fix documentation error.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- DAG
 *
 * Defines the base hierarchy for DAG nodes.
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __PREDICATE__DAG__
#define __PREDICATE__DAG__

#include <predicate/ironbee.hpp>
#include <predicate/value.hpp>

#include <ironbeepp/memory_pool_lite.hpp>

#include <boost/enable_shared_from_this.hpp>
#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>

#include <iostream>
#include <list>
#include <string>

namespace IronBee {
namespace Predicate {

// Defined below.
class Node;
class Call;
class Literal;

// Defined in reporter.hpp
class NodeReporter;
// Defined in merge_graph.hpp
class MergeGraph;
// Defined in call_factory.hpp
class CallFactory;
// Defined in eval.hpp.
class GraphEvalState;
class NodeEvalState;

/**
 * Shared pointer to Node.
 **/
typedef boost::shared_ptr<Node> node_p;

/**
 * Weak pointer to Node.
 **/
typedef boost::weak_ptr<Node> weak_node_p;

/**
 * Shared const pointer to Node.
 **/
typedef boost::shared_ptr<const Node> node_cp;

/**
 * Shared pointer to Call.
 **/
typedef boost::shared_ptr<Call> call_p;

/**
 * Shared const pointer to Call.
 **/
typedef boost::shared_ptr<const Call> call_cp;

/**
 * Shared pointer to Literal.
 **/
typedef boost::shared_ptr<Literal> literal_p;

/**
 * Shared const pointer to Literal.
 **/
typedef boost::shared_ptr<const Literal> literal_cp;

//! List of nodes.  See children().
typedef std::list<node_p> node_list_t;

//! Weak list of nodes.  See parents().
typedef std::list<weak_node_p> weak_node_list_t;

//! List of const nodes.
typedef std::list<node_cp> node_clist_t;

/**
 * A node in the predicate DAG.
 *
 * Nodes make up the predicate DAG.  They also appear in the expressions trees
 * that are merged together to construct the DAG. This class is the top of
 * the class hierarchy for nodes.  It can not be directly instantiated or
 * subclassed.  For literal values, Literal.  For call values, create and
 * instantiate a subclass of Call.
 *
 * This class hierarchy defines how to evaluate (through eval_calculate(),
 * eval_initialize()) but does not store the data.
 * Data is stored separately in GraphEvalState and NodeEvalState.  This
 * separation allows simultaneous evaluations of the DAG across different
 * EvalContext.
 *
 * @sa Call
 * @sa Literal
 */
class Node :
    public boost::enable_shared_from_this<Node>,
    boost::noncopyable
{
    friend class Call;
    friend class Literal;

private:
    //! Private Constructor.
    Node();

public:
    //! Destructor.
    virtual ~Node();

    /**
     * @name Graph Structure Manipulation
     * These routines are used to modify the structure of the graph.
     **/
    ///@{

    /**
     * Add a child.
     *
     * Adds to end of children() and adds @c this to end of parents() of
     * child.  Subclasses can add additional behavior.
     *
     * O(1)
     *
     * @param[in] child Child to add.
     * @throw IronBee::einval if ! @a child.
     **/
    virtual void add_child(const node_p& child);

    /**
     * Remove a child.
     *
     * Removes from children() and removes @c this from parents() of child.
     * Subclasses can add additional behavior.
     *
     * O(n) where n is size of children() of @c this or parents() of child.
     *
     * @param[in] child Child to remove.
     * @throw IronBee::enoent if no such child.
     * @throw IronBee::einval if not a parent of child.
     * @throw IronBee::einval if ! @a child.
     **/
    virtual void remove_child(const node_p& child);

    /**
     * Replace a child.
     *
     * Replaces a child with another node.  This can be used to change
     * a child without moving it to the end of the children as remove_child(),
     * add_child() would.
     *
     * O(n) where n is size of children() of @c this or parents() of child.
     *
     * @param[in] child Child to replace.
     * @param[in] with  Child to replace with.
     * @throw IronBee::enoent if no such child.
     * @throw IronBee::einval if not a parent of child.
     * @throw IronBee::einval if ! @a child or ! @a with.
     **/
    virtual void replace_child(const node_p& child, const node_p& with);

    ///@}

    /**
     * S-Expression.
     *
     * An S-expression representation of the expression tree rooted at this
     * node.  See parse.hpp for detailed grammar.
     *
     * This method returns a string reference, but this reference is not
     * stable if this node or any children are changed.  It should be copied
     * if needed beyond such operations.
     *
     * S-Expressions are calculated dynamically and cached, so calling this
     * method is cheap.
     *
     * @return S-Expression of expression tree rooted at node.
     **/
    virtual const std::string& to_s() const = 0;

    //! Children accessor -- const.
    const node_list_t& children() const
    {
        return m_children;
    }
    //! Parents accessor -- const.
    const weak_node_list_t& parents() const
    {
        return m_parents;
    }

    //! True iff node is a literal.
    bool is_literal() const;

    /**
     * @name Lifecycle
     * These routine implement the graph lifecycle.
     **/
    ///@{

    /**
     * Perform pre-transformation validations.
     *
     * This method may be overridden by a child.  Default behavior is to
     * call validate().
     *
     * @note Exceptions will not be immediately caught so should only be used
     *       if it is appropriate to abort the entire predicate system, e.g.,
     *       on an insanity error.
     *
     * @param[in] reporter Reporter to use for errors or warnings.
     **/
    virtual void pre_transform(NodeReporter reporter) const;

    /**
     * Perform transformations.
     *
     * This method may be overridden by a child.  Default behavior is to
     * do nothing and return false.
     *
     * This method is called for every Node during the transformation phase.
     * If any such call returns true, the whole process is repeated.
     *
     * Transformations should not be done directly, but rather through
     * @a merge_graph(), i.e., do not use add_child(), remove_child(), or
     * replace_child(); instead use MergeGraph::add(), MergeGraph::remove(),
     * or MergeGraph::replace().  Note that your method can fetch a
     * @ref node_p for itself via shared_from_this().
     *
     * Note: Reporting errors will allow the current transformation loop to
     * continue for other nodes, but will then end the transformation phase.
     *
     * @param[in] merge_graph  MergeGraph used to change the DAG.
     * @param[in] call_factory CallFactory to create new nodes with.
     * @param[in] reporter     Reporter to use for errors or warnings.
     * @return true iff any changes were made.
     **/
    virtual bool transform(
        MergeGraph&        merge_graph,
        const CallFactory& call_factory,
        NodeReporter       reporter
    );

    /**
     * Perform post-transformation validations.
     *
     * Default behavior is to call validate().  See pre_transform() for
     * additional discussion.
     *
     * @param[in] reporter Reporter to use for errors or warnings.
     **/
    virtual void post_transform(NodeReporter reporter) const;

    /**
     * Perform validation checks.
     *
     * By default, this is called by pre_transform() and post_transform(),
     * although that behavior can be overridden.
     *
     * Default behavior is to do nothing.
     *
     * @sa Standard::Validate
     *
     * @param[in] reporter Reporter to use for errors or warnings.
     * @return true iff no *errors* reported.
     **/
    virtual bool validate(NodeReporter reporter) const;

    /**
     * Preform any state preparations needed for evaluation.
     *
     * This method is called after all transformations are complete but before
     * any evaluation.  It provides the environment of the node and should be
     * used to do any setup needed to calculate values.
     *
     * @param[in]  environment Environment for evaluation.
     * @param[in]  reporter    Reporter to report errors with.
     **/
    virtual void pre_eval(Environment environment, NodeReporter reporter);

    ///@}

    /**
     * @name Evaluation Support
     * Methods to support evaluation.  These methods are usually not called
     * directly, but instead are called from GraphEvalState and NodeEvalState.
     * They are public to allow for certain low level interactions with nodes.
     **/
    ///@{

    //! Set index of node to @a index.
    void set_index(size_t index);

    //! Access index.
    // Intentionally inline.
    size_t index() const
    {
        return m_index;
    }

    /**
     * Initialize node eval state.
     *
     * This method is called before each evaluation run.  It should setup
     * any state or initial values of @a node_eval_state.  See
     * NodeEvalState::state().
     *
     * @param[in] graph_eval_state Graph evaluation state.
     * @param[in] context          Evaluation context.
     **/
    virtual void eval_initialize(
        GraphEvalState& graph_eval_state,
        EvalContext     context
    ) const;

    /**
     * Calculate value and update state.
     *
     * Subclass classes should implement this to calculate and call methods
     * of @a node_eval_state appropriately to add values and finish.
     *
     * This method will be called any time eval() is called while the node is
     * unfinished.  It will not be called on a finished node.
     *
     * @param[in] graph_eval_state Graph evaluation state.
     * @param[in] context          Context of calculation.
     * @return Value of node.
     */
    virtual void eval_calculate(
        GraphEvalState& graph_eval_state,
        EvalContext     context
    ) const = 0;

    ///@}

private:
    /**
     * Remove this from parents of @a child.
     *
     * @param[in] child Child to unlink from.
     * @throw IronBee::einval if not in @a child's parent list.
     **/
    void unlink_from_child(const node_p& child) const;

    //! List of parents (note weak pointers).
    weak_node_list_t m_parents;
    //! List of children.
    node_list_t m_children;
    //! Index.
    size_t m_index;
};

//! Ostream output operator.
std::ostream& operator<<(std::ostream& out, const Node& node);

/**
 * Node representing a function Call.
 *
 * All Call nodes must have a name.  Calls with the same name are considered
 * to implement the same function.
 *
 * This class is unique in the class hierarchy as being subclassable.  Users
 * should create subclasses for specific functions.  Subclasses must implement
 * name() and eval_calculate().  Subclasses may also define add_child(),
 * remove_child(), and replace_child() but must call the parents methods
* within.
 **/
class Call :
    public Node
{
public:
    //! Constructor.
    Call();

    //! See Node::add_child().
    virtual void add_child(const node_p& child);

    //! See Node::remove_child().
    virtual void remove_child(const node_p& child);

    //! See Node::replace_child().
    virtual void replace_child(const node_p& child, const node_p& with);

    //! S-expression: (@c name children...)
    virtual const std::string& to_s() const;

    /**
     * Name accessor.
     */
    virtual std::string name() const = 0;

private:
    //! Mark m_s as in need of recalculation.
    void reset_s() const;

    //! Recalculate m_s.
    void recalculate_s() const;

    // Because name() is pure, Call::Call() can not calculate m_s.  I.e., we
    // need to fully construct the class before setting m_s.  So we have
    // to_s() calculate it on the fly the first time.  The following two
    // members maintain that cache.

    //! Have we calculate m_s at all?
    mutable bool m_calculated_s;

    //! String form.
    mutable std::string m_s;
};

/**
 * Literal node: no children and value independent of EvalContext.
 *
 * This class may not be subclassed.
 **/
class Literal :
    public Node
{
public:
    //! Construct null literal.
    Literal();

    //! Construct literal from memory pool and value.
    Literal(
        const boost::shared_ptr<ScopedMemoryPoolLite>& memory_pool,
        Value                                          value
    );

    //! Construct literal from value, duping value with Value::dup().
    explicit Literal(Value value);

    //! Construct literal from int.
    explicit Literal(int value);

    //! Construct literal from float.
    explicit Literal(long double value);

    //! Construct literal from string.
    explicit Literal(const std::string& value);

    //! Value of literal.
    // Intentionally inline.
    Value literal_value() const
    {
        return m_value;
    }

    //! @throw IronBee::einval always.
    virtual void add_child(const node_p&);
    //! @throw IronBee::einval always.
    virtual void remove_child(const node_p&);
    //! @throw IronBee::einval always.
    virtual void replace_child(const node_p& child, const node_p& with);

    //! @throw IronBee::einval always.
    virtual void eval_calculate(
        GraphEvalState& graph_eval_state,
        EvalContext    context
    ) const;

    //! Set value based on literal_values() and finish.
    virtual void eval_initialize(
        GraphEvalState& graph_eval_state,
        EvalContext     context
    ) const;

    //! S-Expression.
    // Intentionally inline.
    virtual const std::string& to_s() const
    {
        return m_sexpr;
    }

private:
    //! Keep track of where our memory comes from.
    boost::shared_ptr<ScopedMemoryPoolLite> m_memory_pool;

    //! Value returned by literal_values().
    Value m_value;

    //! Cache sexpr for easy access.
    std::string m_sexpr;
};

} // Predicate
} // IronBee

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/login_utils.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/lock.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/singleton.h"
#include "base/string_util.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_init.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/external_cookie_handler.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/login/cookie_fetcher.h"
#include "chrome/browser/chromeos/login/google_authenticator.h"
#include "chrome/browser/chromeos/login/ownership_service.h"
#include "chrome/browser/chromeos/login/parallel_authenticator.h"
#include "chrome/browser/chromeos/login/user_image_downloader.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/net/gaia/token_service.h"
#include "chrome/browser/prefs/pref_member.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "chrome/common/pref_names.h"
#include "googleurl/src/gurl.h"
#include "net/base/cookie_store.h"
#include "net/url_request/url_request_context.h"
#include "views/widget/widget_gtk.h"

namespace chromeos {

namespace {

// Prefix for Auth token received from ClientLogin request.
const char kAuthPrefix[] = "Auth=";
// Suffix for Auth token received from ClientLogin request.
const char kAuthSuffix[] = "\n";

}  // namespace

class LoginUtilsImpl : public LoginUtils {
 public:
  LoginUtilsImpl()
      : browser_launch_enabled_(true) {
  }

  // Invoked after the user has successfully logged in. This launches a browser
  // and does other bookkeeping after logging in.
  virtual void CompleteLogin(const std::string& username,
      const GaiaAuthConsumer::ClientLoginResult& credentials);

  // Invoked after the tmpfs is successfully mounted.
  // Launches a browser in the off the record (incognito) mode.
  virtual void CompleteOffTheRecordLogin(const GURL& start_url);

  // Creates and returns the authenticator to use. The caller owns the returned
  // Authenticator and must delete it when done.
  virtual Authenticator* CreateAuthenticator(LoginStatusConsumer* consumer);

  // Used to postpone browser launch via DoBrowserLaunch() if some post
  // login screen is to be shown.
  virtual void EnableBrowserLaunch(bool enable);

  // Returns if browser launch enabled now or not.
  virtual bool IsBrowserLaunchEnabled() const;

  // Returns auth token for 'cp' Contacts service.
  virtual const std::string& GetAuthToken() const { return auth_token_; }

 private:
  // Indicates if DoBrowserLaunch will actually launch the browser or not.
  bool browser_launch_enabled_;

  // Auth token for Contacts service. Received by GoogleAuthenticator as
  // part of ClientLogin response.
  std::string auth_token_;

  DISALLOW_COPY_AND_ASSIGN(LoginUtilsImpl);
};

class LoginUtilsWrapper {
 public:
  LoginUtilsWrapper() {}

  LoginUtils* get() {
    AutoLock create(create_lock_);
    if (!ptr_.get())
      reset(new LoginUtilsImpl);
    return ptr_.get();
  }

  void reset(LoginUtils* ptr) {
    ptr_.reset(ptr);
  }

 private:
  Lock create_lock_;
  scoped_ptr<LoginUtils> ptr_;

  DISALLOW_COPY_AND_ASSIGN(LoginUtilsWrapper);
};

void LoginUtilsImpl::CompleteLogin(const std::string& username,
    const GaiaAuthConsumer::ClientLoginResult& credentials) {

  LOG(INFO) << "Completing login for " << username;

  if (CrosLibrary::Get()->EnsureLoaded())
    CrosLibrary::Get()->GetLoginLibrary()->StartSession(username, "");

  bool first_login = !UserManager::Get()->IsKnownUser(username);
  UserManager::Get()->UserLoggedIn(username);

  // Now launch the initial browser window.
  FilePath user_data_dir;
  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  // The default profile will have been changed because the ProfileManager
  // will process the notification that the UserManager sends out.
  Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);

  // Init extension event routers; this normally happens in browser_main
  // but on Chrome OS it has to be deferred until the user finishes
  // logging in and the profile is not OTR.
  if (profile->GetExtensionsService() &&
      profile->GetExtensionsService()->extensions_enabled()) {
    profile->GetExtensionsService()->InitEventRouters();
  }

  logging::RedirectChromeLogging(
      user_data_dir.Append(profile_manager->GetCurrentProfileDir()),
      *(CommandLine::ForCurrentProcess()),
      logging::DELETE_OLD_LOG_FILE);

  // Supply credentials for sync and others to use. Load tokens from disk.
  TokenService* token_service = profile->GetTokenService();
  token_service->Initialize(GaiaConstants::kChromeOSSource,
                            profile);
  token_service->LoadTokensFromDB();
  token_service->UpdateCredentials(credentials);
  if (token_service->AreCredentialsValid()) {
    token_service->StartFetchingTokens();
  }

  // Set the CrOS user by getting this constructor run with the
  // user's email on first retrieval.
  profile->GetProfileSyncService(username);

  // Attempt to take ownership; this will fail if device is already owned.
  OwnershipService::GetSharedInstance()->StartTakeOwnershipAttempt(
      UserManager::Get()->logged_in_user().email());

  // Own TPM device if, for any reason, it has not been done in EULA
  // wizard screen.
  if (chromeos::CryptohomeTpmIsEnabled() &&
      !chromeos::CryptohomeTpmIsBeingOwned()) {
    if (chromeos::CryptohomeTpmIsOwned()) {
      chromeos::CryptohomeTpmClearStoredPassword();
    } else {
      chromeos::CryptohomeTpmCanAttemptOwnership();
    }
  }

  // Take the credentials passed in and try to exchange them for
  // full-fledged Google authentication cookies.  This is
  // best-effort; it's possible that we'll fail due to network
  // troubles or some such.  Either way, |cf| will call
  // DoBrowserLaunch on the UI thread when it's done, and then
  // delete itself.
  CookieFetcher* cf = new CookieFetcher(profile);
  cf->AttemptFetch(credentials.data);
  auth_token_ = credentials.token;

  static const char kFallbackInputMethodLocale[] = "en-US";
  if (first_login) {
    std::string locale(g_browser_process->GetApplicationLocale());
    // Add input methods based on the application locale when the user first
    // logs in. For instance, if the user chooses Japanese as the UI
    // language at the first login, we'll add input methods associated with
    // Japanese, such as mozc.
    if (locale != kFallbackInputMethodLocale) {
      StringPrefMember language_preload_engines;
      language_preload_engines.Init(prefs::kLanguagePreloadEngines,
                                    profile->GetPrefs(), NULL);
      StringPrefMember language_preferred_languages;
      language_preferred_languages.Init(prefs::kLanguagePreferredLanguages,
                                        profile->GetPrefs(), NULL);

      std::string preload_engines(language_preload_engines.GetValue());
      std::vector<std::string> input_method_ids;
      input_method::GetInputMethodIdsFromLanguageCode(
          locale, input_method::kAllInputMethods, &input_method_ids);
      if (!input_method_ids.empty()) {
        if (!preload_engines.empty())
          preload_engines += ',';
        preload_engines += input_method_ids[0];
      }
      language_preload_engines.SetValue(preload_engines);

      // Add the UI language to the preferred languages the user first logs in.
      std::string preferred_languages(locale);
      preferred_languages += ",";
      preferred_languages += kFallbackInputMethodLocale;
      language_preferred_languages.SetValue(preferred_languages);
    }
  }
}

void LoginUtilsImpl::CompleteOffTheRecordLogin(const GURL& start_url) {
  LOG(INFO) << "Completing off the record login";

  UserManager::Get()->OffTheRecordUserLoggedIn();

  if (CrosLibrary::Get()->EnsureLoaded()) {
    // For BWSI we ask session manager to restart Chrome with --bwsi flag.
    // We keep only some of the arguments of this process.
    static const char* kForwardSwitches[] = {
        switches::kLoggingLevel,
        switches::kEnableLogging,
        switches::kUserDataDir,
        switches::kScrollPixels,
        switches::kEnableGView,
        switches::kNoFirstRun,
        switches::kLoginProfile
    };
    const CommandLine& browser_command_line =
        *CommandLine::ForCurrentProcess();
    CommandLine command_line(browser_command_line.GetProgram());
    command_line.CopySwitchesFrom(browser_command_line,
                                  kForwardSwitches,
                                  arraysize(kForwardSwitches));
    command_line.AppendSwitch(switches::kBWSI);
    command_line.AppendSwitch(switches::kIncognito);
    command_line.AppendSwitch(switches::kEnableTabbedOptions);
    command_line.AppendSwitchASCII(
        switches::kLoginUser,
        UserManager::Get()->logged_in_user().email());
    if (start_url.is_valid())
      command_line.AppendArg(start_url.spec());
    CrosLibrary::Get()->GetLoginLibrary()->RestartJob(
        getpid(),
        command_line.command_line_string());
  }
}

Authenticator* LoginUtilsImpl::CreateAuthenticator(
    LoginStatusConsumer* consumer) {
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kParallelAuth))
    return new ParallelAuthenticator(consumer);
  else
    return new GoogleAuthenticator(consumer);
}

void LoginUtilsImpl::EnableBrowserLaunch(bool enable) {
  browser_launch_enabled_ = enable;
}

bool LoginUtilsImpl::IsBrowserLaunchEnabled() const {
  return browser_launch_enabled_;
}

LoginUtils* LoginUtils::Get() {
  return Singleton<LoginUtilsWrapper>::get()->get();
}

void LoginUtils::Set(LoginUtils* mock) {
  Singleton<LoginUtilsWrapper>::get()->reset(mock);
}

void LoginUtils::DoBrowserLaunch(Profile* profile) {
  // Browser launch was disabled due to some post login screen.
  if (!LoginUtils::Get()->IsBrowserLaunchEnabled())
    return;

  // Update command line in case loose values were added.
  CommandLine::ForCurrentProcess()->InitFromArgv(
      CommandLine::ForCurrentProcess()->argv());

  LOG(INFO) << "Launching browser...";
  BrowserInit browser_init;
  int return_code;
  browser_init.LaunchBrowser(*CommandLine::ForCurrentProcess(),
                             profile,
                             FilePath(),
                             true,
                             &return_code);
}

}  // namespace chromeos
<commit_msg>Switch system logs on user log earlier to show extension initialization in user log<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/login_utils.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/lock.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/singleton.h"
#include "base/string_util.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_init.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/external_cookie_handler.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/login/cookie_fetcher.h"
#include "chrome/browser/chromeos/login/google_authenticator.h"
#include "chrome/browser/chromeos/login/ownership_service.h"
#include "chrome/browser/chromeos/login/parallel_authenticator.h"
#include "chrome/browser/chromeos/login/user_image_downloader.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/net/gaia/token_service.h"
#include "chrome/browser/prefs/pref_member.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "chrome/common/pref_names.h"
#include "googleurl/src/gurl.h"
#include "net/base/cookie_store.h"
#include "net/url_request/url_request_context.h"
#include "views/widget/widget_gtk.h"

namespace chromeos {

namespace {

// Prefix for Auth token received from ClientLogin request.
const char kAuthPrefix[] = "Auth=";
// Suffix for Auth token received from ClientLogin request.
const char kAuthSuffix[] = "\n";

}  // namespace

class LoginUtilsImpl : public LoginUtils {
 public:
  LoginUtilsImpl()
      : browser_launch_enabled_(true) {
  }

  // Invoked after the user has successfully logged in. This launches a browser
  // and does other bookkeeping after logging in.
  virtual void CompleteLogin(const std::string& username,
      const GaiaAuthConsumer::ClientLoginResult& credentials);

  // Invoked after the tmpfs is successfully mounted.
  // Launches a browser in the off the record (incognito) mode.
  virtual void CompleteOffTheRecordLogin(const GURL& start_url);

  // Creates and returns the authenticator to use. The caller owns the returned
  // Authenticator and must delete it when done.
  virtual Authenticator* CreateAuthenticator(LoginStatusConsumer* consumer);

  // Used to postpone browser launch via DoBrowserLaunch() if some post
  // login screen is to be shown.
  virtual void EnableBrowserLaunch(bool enable);

  // Returns if browser launch enabled now or not.
  virtual bool IsBrowserLaunchEnabled() const;

  // Returns auth token for 'cp' Contacts service.
  virtual const std::string& GetAuthToken() const { return auth_token_; }

 private:
  // Indicates if DoBrowserLaunch will actually launch the browser or not.
  bool browser_launch_enabled_;

  // Auth token for Contacts service. Received by GoogleAuthenticator as
  // part of ClientLogin response.
  std::string auth_token_;

  DISALLOW_COPY_AND_ASSIGN(LoginUtilsImpl);
};

class LoginUtilsWrapper {
 public:
  LoginUtilsWrapper() {}

  LoginUtils* get() {
    AutoLock create(create_lock_);
    if (!ptr_.get())
      reset(new LoginUtilsImpl);
    return ptr_.get();
  }

  void reset(LoginUtils* ptr) {
    ptr_.reset(ptr);
  }

 private:
  Lock create_lock_;
  scoped_ptr<LoginUtils> ptr_;

  DISALLOW_COPY_AND_ASSIGN(LoginUtilsWrapper);
};

void LoginUtilsImpl::CompleteLogin(const std::string& username,
    const GaiaAuthConsumer::ClientLoginResult& credentials) {

  LOG(INFO) << "Completing login for " << username;

  if (CrosLibrary::Get()->EnsureLoaded())
    CrosLibrary::Get()->GetLoginLibrary()->StartSession(username, "");

  bool first_login = !UserManager::Get()->IsKnownUser(username);
  UserManager::Get()->UserLoggedIn(username);

  // Now launch the initial browser window.
  FilePath user_data_dir;
  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
  ProfileManager* profile_manager = g_browser_process->profile_manager();

  // Switch log file as soon as possible.
  logging::RedirectChromeLogging(
      user_data_dir.Append(profile_manager->GetCurrentProfileDir()),
      *(CommandLine::ForCurrentProcess()),
      logging::DELETE_OLD_LOG_FILE);

  // The default profile will have been changed because the ProfileManager
  // will process the notification that the UserManager sends out.
  Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);

  // Init extension event routers; this normally happens in browser_main
  // but on Chrome OS it has to be deferred until the user finishes
  // logging in and the profile is not OTR.
  if (profile->GetExtensionsService() &&
      profile->GetExtensionsService()->extensions_enabled()) {
    profile->GetExtensionsService()->InitEventRouters();
  }

  // Supply credentials for sync and others to use. Load tokens from disk.
  TokenService* token_service = profile->GetTokenService();
  token_service->Initialize(GaiaConstants::kChromeOSSource,
                            profile);
  token_service->LoadTokensFromDB();
  token_service->UpdateCredentials(credentials);
  if (token_service->AreCredentialsValid()) {
    token_service->StartFetchingTokens();
  }

  // Set the CrOS user by getting this constructor run with the
  // user's email on first retrieval.
  profile->GetProfileSyncService(username);

  // Attempt to take ownership; this will fail if device is already owned.
  OwnershipService::GetSharedInstance()->StartTakeOwnershipAttempt(
      UserManager::Get()->logged_in_user().email());

  // Own TPM device if, for any reason, it has not been done in EULA
  // wizard screen.
  if (chromeos::CryptohomeTpmIsEnabled() &&
      !chromeos::CryptohomeTpmIsBeingOwned()) {
    if (chromeos::CryptohomeTpmIsOwned()) {
      chromeos::CryptohomeTpmClearStoredPassword();
    } else {
      chromeos::CryptohomeTpmCanAttemptOwnership();
    }
  }

  // Take the credentials passed in and try to exchange them for
  // full-fledged Google authentication cookies.  This is
  // best-effort; it's possible that we'll fail due to network
  // troubles or some such.  Either way, |cf| will call
  // DoBrowserLaunch on the UI thread when it's done, and then
  // delete itself.
  CookieFetcher* cf = new CookieFetcher(profile);
  cf->AttemptFetch(credentials.data);
  auth_token_ = credentials.token;

  static const char kFallbackInputMethodLocale[] = "en-US";
  if (first_login) {
    std::string locale(g_browser_process->GetApplicationLocale());
    // Add input methods based on the application locale when the user first
    // logs in. For instance, if the user chooses Japanese as the UI
    // language at the first login, we'll add input methods associated with
    // Japanese, such as mozc.
    if (locale != kFallbackInputMethodLocale) {
      StringPrefMember language_preload_engines;
      language_preload_engines.Init(prefs::kLanguagePreloadEngines,
                                    profile->GetPrefs(), NULL);
      StringPrefMember language_preferred_languages;
      language_preferred_languages.Init(prefs::kLanguagePreferredLanguages,
                                        profile->GetPrefs(), NULL);

      std::string preload_engines(language_preload_engines.GetValue());
      std::vector<std::string> input_method_ids;
      input_method::GetInputMethodIdsFromLanguageCode(
          locale, input_method::kAllInputMethods, &input_method_ids);
      if (!input_method_ids.empty()) {
        if (!preload_engines.empty())
          preload_engines += ',';
        preload_engines += input_method_ids[0];
      }
      language_preload_engines.SetValue(preload_engines);

      // Add the UI language to the preferred languages the user first logs in.
      std::string preferred_languages(locale);
      preferred_languages += ",";
      preferred_languages += kFallbackInputMethodLocale;
      language_preferred_languages.SetValue(preferred_languages);
    }
  }
}

void LoginUtilsImpl::CompleteOffTheRecordLogin(const GURL& start_url) {
  LOG(INFO) << "Completing off the record login";

  UserManager::Get()->OffTheRecordUserLoggedIn();

  if (CrosLibrary::Get()->EnsureLoaded()) {
    // For BWSI we ask session manager to restart Chrome with --bwsi flag.
    // We keep only some of the arguments of this process.
    static const char* kForwardSwitches[] = {
        switches::kLoggingLevel,
        switches::kEnableLogging,
        switches::kUserDataDir,
        switches::kScrollPixels,
        switches::kEnableGView,
        switches::kNoFirstRun,
        switches::kLoginProfile
    };
    const CommandLine& browser_command_line =
        *CommandLine::ForCurrentProcess();
    CommandLine command_line(browser_command_line.GetProgram());
    command_line.CopySwitchesFrom(browser_command_line,
                                  kForwardSwitches,
                                  arraysize(kForwardSwitches));
    command_line.AppendSwitch(switches::kBWSI);
    command_line.AppendSwitch(switches::kIncognito);
    command_line.AppendSwitch(switches::kEnableTabbedOptions);
    command_line.AppendSwitchASCII(
        switches::kLoginUser,
        UserManager::Get()->logged_in_user().email());
    if (start_url.is_valid())
      command_line.AppendArg(start_url.spec());
    CrosLibrary::Get()->GetLoginLibrary()->RestartJob(
        getpid(),
        command_line.command_line_string());
  }
}

Authenticator* LoginUtilsImpl::CreateAuthenticator(
    LoginStatusConsumer* consumer) {
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kParallelAuth))
    return new ParallelAuthenticator(consumer);
  else
    return new GoogleAuthenticator(consumer);
}

void LoginUtilsImpl::EnableBrowserLaunch(bool enable) {
  browser_launch_enabled_ = enable;
}

bool LoginUtilsImpl::IsBrowserLaunchEnabled() const {
  return browser_launch_enabled_;
}

LoginUtils* LoginUtils::Get() {
  return Singleton<LoginUtilsWrapper>::get()->get();
}

void LoginUtils::Set(LoginUtils* mock) {
  Singleton<LoginUtilsWrapper>::get()->reset(mock);
}

void LoginUtils::DoBrowserLaunch(Profile* profile) {
  // Browser launch was disabled due to some post login screen.
  if (!LoginUtils::Get()->IsBrowserLaunchEnabled())
    return;

  // Update command line in case loose values were added.
  CommandLine::ForCurrentProcess()->InitFromArgv(
      CommandLine::ForCurrentProcess()->argv());

  LOG(INFO) << "Launching browser...";
  BrowserInit browser_init;
  int return_code;
  browser_init.LaunchBrowser(*CommandLine::ForCurrentProcess(),
                             profile,
                             FilePath(),
                             true,
                             &return_code);
}

}  // namespace chromeos
<|endoftext|>


<commit_before>#include "Display.h"

#include <CommCtrl.h>

#include "../3RVX/DisplayManager.h"
#include "../3RVX/Logger.h"
#include "../3RVX/Settings.h"

#include "UIContext.h"
#include "resource.h"

DLGPROC Display::Command(unsigned short nCode, unsigned short ctrlId) {
    switch (nCode) {
    case BN_CLICKED:
        switch (ctrlId) {
        case CHK_EDGE:
            OnCustomCheckChanged();
            return (DLGPROC) TRUE;
        }

        break;

    case CBN_SELCHANGE:
        switch (ctrlId) {
        case CMB_POSITION:
            OnPositionChanged();
            return (DLGPROC) TRUE;

        case CMB_ANIMATION:
            OnAnimationChanged();
            return (DLGPROC) TRUE;
        }

        break;
    }

    return FALSE;
}

DLGPROC Display::Notification(NMHDR *nHdr) {
    unsigned int ctrlId = nHdr->idFrom;
    switch (nHdr->code) {
    case UDN_DELTAPOS:
        if (ctrlId == SP_DELAY || ctrlId == SP_SPEED) {
            NMUPDOWN *ud = (NMUPDOWN *) nHdr;
            ud->iDelta *= 100;
            return FALSE; /* Allows the change */
        }
    }

    return FALSE;
}

void Display::Initialize() {
    INIT_CONTROL(CHK_ONTOP, Checkbox, _onTop);
    INIT_CONTROL(CHK_FULLSCREEN, Checkbox, _hideFullscreen);

    INIT_CONTROL(CMB_POSITION, ComboBox, _position);
    INIT_CONTROL(ED_CUSTOMX, EditBox, _positionX);
    INIT_CONTROL(ED_CUSTOMY, EditBox, _positionY);
    INIT_CONTROL(CHK_EDGE, Checkbox, _customDistance);
    INIT_CONTROL(SP_EDGE, Spinner, _edgeSpinner);
    _edgeSpinner.Buddy(ED_EDGE);

    INIT_CONTROL(LBL_DISPLAYDEV, Label, _displayDevLabel);
    INIT_CONTROL(CMB_MONITOR, ComboBox, _displayDevice);

    INIT_CONTROL(CMB_ANIMATION, ComboBox, _animation);
    INIT_CONTROL(LBL_HIDEDELAY, Label, _hideDelayLabel);
    INIT_CONTROL(SP_HIDEDELAY, Spinner, _hideDelay);
    _hideDelay.Buddy(ED_HIDEDELAY);
    INIT_CONTROL(LBL_HIDESPEED, Label, _hideSpeedLabel);
    INIT_CONTROL(SP_HIDESPEED, Spinner, _hideSpeed);
    _hideSpeed.Buddy(ED_HIDESPEED);
}

void Display::LoadSettings() {
    Settings *settings = Settings::Instance();

    /* Visibility Settings */
    _ctxt->SetCheck(CHK_ONTOP, settings->AlwaysOnTop());
    _ctxt->SetCheck(CHK_FULLSCREEN, settings->HideFullscreen());

    /* Position on Screen*/
    for (std::wstring pos : settings->OSDPosNames) {
        _ctxt->AddComboItem(CMB_POSITION, pos);
    }
    _ctxt->SelectComboItem(CMB_POSITION, (int) settings->OSDPosition());

    /* Custom positions/offsets */
    _ctxt->SetText(ED_CUSTOMX, settings->OSDX());
    _ctxt->SetText(ED_CUSTOMY, settings->OSDY());
    _ctxt->SetCheck(CHK_EDGE, settings->OSDEdgeOffset() != DEFAULT_OSD_OFFSET);
    _ctxt->SetText(ED_EDGE, settings->OSDEdgeOffset());
    _ctxt->SetSpinRange(SP_EDGE, MIN_EDGE, MAX_EDGE);

    /* Display Devices */
    _ctxt->AddComboItem(CMB_MONITOR, L"Primary Monitor");
    _ctxt->AddComboItem(CMB_MONITOR, L"All Monitors");
    std::list<DISPLAY_DEVICE> devices = DisplayManager::ListAllDevices();
    for (DISPLAY_DEVICE dev : devices) {
        std::wstring devString(dev.DeviceName);
        _ctxt->AddComboItem(CMB_MONITOR, devString.c_str());
    }
    std::wstring monitorName = settings->Monitor();
    if (monitorName == L"") {
        monitorName = L"Primary Monitor";
    } else if (monitorName == L"*") {
        monitorName = L"All Monitors";
    }
    _ctxt->SelectComboItem(CMB_MONITOR, monitorName);

    /* Animation Settings */
    for (std::wstring anim : AnimationTypes::HideAnimationNames) {
        _ctxt->AddComboItem(CMB_ANIMATION, anim);
    }
    _ctxt->SelectComboItem(CMB_ANIMATION, (int) settings->HideAnim());
    _ctxt->SetSpinRange(SP_DELAY, MIN_MS, MAX_MS);
    _ctxt->SetText(ED_DELAY, settings->HideDelay());
    _ctxt->SetSpinRange(SP_SPEED, MIN_MS, MAX_MS);
    _ctxt->SetText(ED_SPEED, settings->HideSpeed());

    /* Refresh control states */
    OnPositionChanged();
    OnCustomCheckChanged();
    OnAnimationChanged();
}

void Display::SaveSettings() {
    if (_hWnd == NULL) {
        return;
    }

    CLOG(L"Saving: Display");
    Settings *settings = Settings::Instance();

    settings->AlwaysOnTop(_ctxt->GetCheck(CHK_ONTOP));
    settings->HideFullscreen(_ctxt->GetCheck(CHK_FULLSCREEN));

    Settings::OSDPos pos = (Settings::OSDPos)
        _ctxt->GetComboSelectionIndex(CMB_POSITION);
    settings->OSDPosition(pos);
    if (pos == Settings::OSDPos::Custom) {
        int x = _ctxt->GetTextAsInt(ED_CUSTOMX);
        int y = _ctxt->GetTextAsInt(ED_CUSTOMY);
        settings->OSDX(x);
        settings->OSDY(y);
    }

    if (_ctxt->GetCheck(CHK_EDGE) == true) {
        int edge = _ctxt->GetTextAsInt(ED_EDGE);
        settings->OSDEdgeOffset(edge);
    } else {
        /* We have to write the default here, just in case somebody unchecked
         * the checkbox. */
        settings->OSDEdgeOffset(DEFAULT_OSD_OFFSET);
    }

    std::wstring monitor = _ctxt->GetComboSelection(CMB_MONITOR);
    int monitorIdx = _ctxt->GetComboSelectionIndex(CMB_MONITOR);
    if (monitorIdx == 0) {
        monitor = L"";
    } else if (monitorIdx == 1) {
        monitor = L"*";
    }
    settings->Monitor(monitor);

    int hideAnimIdx = _ctxt->GetComboSelectionIndex(CMB_ANIMATION);
    settings->HideAnim((AnimationTypes::HideAnimation) hideAnimIdx);

    settings->HideDelay(_ctxt->GetTextAsInt(ED_DELAY));
    settings->HideSpeed(_ctxt->GetTextAsInt(ED_SPEED));
}

void Display::OnPositionChanged() {
    std::wstring sel = _ctxt->GetComboSelection(CMB_POSITION);
    bool isCustom = (sel == L"Custom");
    _ctxt->SetEnabled(LBL_CUSTOMX, isCustom);
    _ctxt->SetEnabled(LBL_CUSTOMY, isCustom);
    _ctxt->SetEnabled(ED_CUSTOMX, isCustom);
    _ctxt->SetEnabled(ED_CUSTOMY, isCustom);
}

void Display::OnCustomCheckChanged() {
    bool checked = _ctxt->GetCheck(CHK_EDGE);
    _ctxt->SetEnabled(ED_EDGE, checked);
    _ctxt->SetEnabled(SP_EDGE, checked);
}

void Display::OnAnimationChanged() {
    std::wstring sel = _ctxt->GetComboSelection(CMB_ANIMATION);
    bool animEnabled = (sel != L"None");
    _ctxt->SetEnabled(ED_SPEED, animEnabled);
}<commit_msg>Use control methods instead of UIContext<commit_after>#include "Display.h"

#include <CommCtrl.h>

#include "../3RVX/DisplayManager.h"
#include "../3RVX/Logger.h"
#include "../3RVX/Settings.h"

#include "UIContext.h"
#include "resource.h"

DLGPROC Display::Command(unsigned short nCode, unsigned short ctrlId) {
    switch (nCode) {
    case BN_CLICKED:
        switch (ctrlId) {
        case CHK_EDGE:
            OnCustomCheckChanged();
            return (DLGPROC) TRUE;
        }

        break;

    case CBN_SELCHANGE:
        switch (ctrlId) {
        case CMB_POSITION:
            OnPositionChanged();
            return (DLGPROC) TRUE;

        case CMB_ANIMATION:
            OnAnimationChanged();
            return (DLGPROC) TRUE;
        }

        break;
    }

    return FALSE;
}

DLGPROC Display::Notification(NMHDR *nHdr) {
    unsigned int ctrlId = nHdr->idFrom;
    switch (nHdr->code) {
    case UDN_DELTAPOS:
        if (ctrlId == SP_DELAY || ctrlId == SP_SPEED) {
            NMUPDOWN *ud = (NMUPDOWN *) nHdr;
            ud->iDelta *= 100;
            return FALSE; /* Allows the change */
        }
    }

    return FALSE;
}

void Display::Initialize() {
    INIT_CONTROL(CHK_ONTOP, Checkbox, _onTop);
    INIT_CONTROL(CHK_FULLSCREEN, Checkbox, _hideFullscreen);

    INIT_CONTROL(CMB_POSITION, ComboBox, _position);
    INIT_CONTROL(ED_CUSTOMX, EditBox, _positionX);
    INIT_CONTROL(ED_CUSTOMY, EditBox, _positionY);
    INIT_CONTROL(CHK_EDGE, Checkbox, _customDistance);
    INIT_CONTROL(SP_EDGE, Spinner, _edgeSpinner);
    _edgeSpinner.Buddy(ED_EDGE);

    INIT_CONTROL(LBL_DISPLAYDEV, Label, _displayDevLabel);
    INIT_CONTROL(CMB_MONITOR, ComboBox, _displayDevice);

    INIT_CONTROL(CMB_ANIMATION, ComboBox, _animation);
    INIT_CONTROL(LBL_HIDEDELAY, Label, _hideDelayLabel);
    INIT_CONTROL(SP_HIDEDELAY, Spinner, _hideDelay);
    _hideDelay.Buddy(ED_HIDEDELAY);
    INIT_CONTROL(LBL_HIDESPEED, Label, _hideSpeedLabel);
    INIT_CONTROL(SP_HIDESPEED, Spinner, _hideSpeed);
    _hideSpeed.Buddy(ED_HIDESPEED);
}

void Display::LoadSettings() {
    Settings *settings = Settings::Instance();

    /* Visibility Settings */
    _onTop.Checked(settings->AlwaysOnTop());
    _hideFullscreen.Checked(settings->HideFullscreen());

    /* Position on Screen*/
    for (std::wstring position : settings->OSDPosNames) {
        _position.AddItem(position);
    }
    _position.Select((int) settings->OSDPosition());

    /* Custom positions/offsets */
    _positionX.Text(settings->OSDX());
    _positionY.Text(settings->OSDY());
    _customDistance.Checked(settings->OSDEdgeOffset() != DEFAULT_OSD_OFFSET);
    _edgeSpinner.Text(settings->OSDEdgeOffset());
    _edgeSpinner.Range(MIN_EDGE, MAX_EDGE);

    /* Display Devices */
    _ctxt->AddComboItem(CMB_MONITOR, L"Primary Monitor");
    _ctxt->AddComboItem(CMB_MONITOR, L"All Monitors");
    std::list<DISPLAY_DEVICE> devices = DisplayManager::ListAllDevices();
    for (DISPLAY_DEVICE dev : devices) {
        std::wstring devString(dev.DeviceName);
        _ctxt->AddComboItem(CMB_MONITOR, devString.c_str());
    }
    std::wstring monitorName = settings->Monitor();
    if (monitorName == L"") {
        monitorName = L"Primary Monitor";
    } else if (monitorName == L"*") {
        monitorName = L"All Monitors";
    }
    _ctxt->SelectComboItem(CMB_MONITOR, monitorName);

    /* Animation Settings */
    for (std::wstring anim : AnimationTypes::HideAnimationNames) {
        _ctxt->AddComboItem(CMB_ANIMATION, anim);
    }
    _ctxt->SelectComboItem(CMB_ANIMATION, (int) settings->HideAnim());
    _ctxt->SetSpinRange(SP_DELAY, MIN_MS, MAX_MS);
    _ctxt->SetText(ED_DELAY, settings->HideDelay());
    _ctxt->SetSpinRange(SP_SPEED, MIN_MS, MAX_MS);
    _ctxt->SetText(ED_SPEED, settings->HideSpeed());

    /* Refresh control states */
    OnPositionChanged();
    OnCustomCheckChanged();
    OnAnimationChanged();
}

void Display::SaveSettings() {
    if (_hWnd == NULL) {
        return;
    }

    CLOG(L"Saving: Display");
    Settings *settings = Settings::Instance();

    settings->AlwaysOnTop(_ctxt->GetCheck(CHK_ONTOP));
    settings->HideFullscreen(_ctxt->GetCheck(CHK_FULLSCREEN));

    Settings::OSDPos pos = (Settings::OSDPos)
        _ctxt->GetComboSelectionIndex(CMB_POSITION);
    settings->OSDPosition(pos);
    if (pos == Settings::OSDPos::Custom) {
        int x = _ctxt->GetTextAsInt(ED_CUSTOMX);
        int y = _ctxt->GetTextAsInt(ED_CUSTOMY);
        settings->OSDX(x);
        settings->OSDY(y);
    }

    if (_ctxt->GetCheck(CHK_EDGE) == true) {
        int edge = _ctxt->GetTextAsInt(ED_EDGE);
        settings->OSDEdgeOffset(edge);
    } else {
        /* We have to write the default here, just in case somebody unchecked
         * the checkbox. */
        settings->OSDEdgeOffset(DEFAULT_OSD_OFFSET);
    }

    std::wstring monitor = _ctxt->GetComboSelection(CMB_MONITOR);
    int monitorIdx = _ctxt->GetComboSelectionIndex(CMB_MONITOR);
    if (monitorIdx == 0) {
        monitor = L"";
    } else if (monitorIdx == 1) {
        monitor = L"*";
    }
    settings->Monitor(monitor);

    int hideAnimIdx = _ctxt->GetComboSelectionIndex(CMB_ANIMATION);
    settings->HideAnim((AnimationTypes::HideAnimation) hideAnimIdx);

    settings->HideDelay(_ctxt->GetTextAsInt(ED_DELAY));
    settings->HideSpeed(_ctxt->GetTextAsInt(ED_SPEED));
}

void Display::OnPositionChanged() {
    std::wstring sel = _ctxt->GetComboSelection(CMB_POSITION);
    bool isCustom = (sel == L"Custom");
    _ctxt->SetEnabled(LBL_CUSTOMX, isCustom);
    _ctxt->SetEnabled(LBL_CUSTOMY, isCustom);
    _ctxt->SetEnabled(ED_CUSTOMX, isCustom);
    _ctxt->SetEnabled(ED_CUSTOMY, isCustom);
}

void Display::OnCustomCheckChanged() {
    bool checked = _ctxt->GetCheck(CHK_EDGE);
    _ctxt->SetEnabled(ED_EDGE, checked);
    _ctxt->SetEnabled(SP_EDGE, checked);
}

void Display::OnAnimationChanged() {
    std::wstring sel = _ctxt->GetComboSelection(CMB_ANIMATION);
    bool animEnabled = (sel != L"None");
    _ctxt->SetEnabled(ED_SPEED, animEnabled);
}<|endoftext|>


<commit_before><commit_msg>fixed typo<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2016 Chase Fugett
 */

/*
 * File:   SimpleHTTPServer.cpp
 * Author: Chase Fugett
 *
 * Created on October 16, 2016, 9:39 PM
 *
 * Implements Server.h as a simple HTTP server
 */

#include <boost/asio.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include "Server.h"

/*
 * Constructor
 */
Server::Server(unsigned short port) {
    this->port = port;
}

/**
 * Destructor
 */
Server::~Server() {
}

/**
 * Takes in a file and gives the size back
 * @param inFile
 * @return size as an int
 */
std::string getFileSize(std::ifstream& inFile) {
    inFile.seekg(0, std::ios_base::end);
    const int fileSize = inFile.tellg();
    std::string num = std::to_string(fileSize);
    return num;
}

/**
 * Takes in the extension as a string and returns the MIME type
 * @param line
 * @return MIME type
 */
std::string detType(std::string& line) {
    if (line == "html") {
        return "text/html";
    } else if (line == "png") {
        return "image/png";
    } else if (line == "jpg") {
        return "image/jpg";
    } else if (line == "txt") {
        return "text/plain";
    } else {
        return "text/plain";
    }
}

/**
 * Prints the header if the file was not found
 * @param inFile
 * @param ext
 * @return header as a string
 */
std::string printBadHeader(std::ifstream& inFile, std::string& ext) {
    std::string line = "HTTP/1.1 404 Not Found\r\n";
    line += "Server: SimpleServer\r\n";
    line += "Content-Length: ";
    line += getFileSize(inFile);
    line += "\r\n";
    line += "Connection: Close\r\n";
    line += "Content-Type: ";
    line += detType(ext);
    line += "\r\n\r\n";
    return line;
}

/**
 * Prints the header if the file was good
 * @param inFile
 * @param ext
 * @return the header as a string
 */
std::string printGoodHeader(std::ifstream& inFile, std::string& ext) {
    std::string line = "HTTP/1.1 200 OK\r\n";
    line += "Server: SimpleServer\r\n";
    line += "Content-Length: ";
    line += getFileSize(inFile);
    line += "\r\n";
    line += "Connection: Close\r\n";
    line += "Content-Type: ";
    line += detType(ext);
    line += "\r\n\r\n";
    return line;
}

/**
 * Serves one connection from 1 client by processing HTTP request
 * (ignoring headers) and responding to the request with contents
 * of a file (specified in the GET request).
 *
 * @param is The input stream from where the client request is to be read.
 * @param os The output stream where the response is to be written.
 */
void Server::serveClient(std::istream& is, std::ostream& os) {
    std::string item;
    getline(is, item);
    std::string path = item.substr(item.find_first_of(' ') + 1);
    path = path.substr(0, path.find_first_of(' '));
    // Clarification for '/' file name
    if (path == "/") {
        path = "index.html";
    } else {
        // path finally becomes the full path to the file
        path = path.substr(path.find_last_of('/') + 1);
    }
    // Isolates the extension to be used later
    std::string extension = path.substr(path.find_last_of('.') + 1);
    // Creates the file from the path and checks if good
    std::ifstream inFile(path);
    if (!inFile.good()) {
        // Send bad header message back to client with error message
        os << printBadHeader(inFile, extension);
        os << "The following file was not found: " << path << std::endl;
    } else {
        // Send a good header message back to the client
        os << printGoodHeader(inFile, extension);
        // Print the contents of the file to the os
        std::string line;
        inFile.seekg(0);
        while (std::getline(inFile, line)) {
            os << line << std::endl;
        }
    }
}

/**
 * Runs the program as a server processing incoming connections/requests
 * forever.
 *
 * @param port
 */
void Server::runServer() {
    using namespace boost::asio;
    using namespace boost::asio::ip;
    io_service service;
    // Create end point
    tcp::endpoint myEndpoint(tcp::v4(), port);
    // Create a socket that accepts connections
    tcp::acceptor server(service, myEndpoint);
    // Process client connections one-by-one forever
    while (true) {
        tcp::iostream client;
        // Wait for a client to connect
        server.accept(*client.rdbuf());
        // Process information from client.
        serveClient(client, client);
    }
}
<commit_msg>Delete SimpleHTTPServer.cpp<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/gtk/gtk_chrome_link_button.h"

#include "base/logging.h"

static const char* kLinkMarkup = "%s";

namespace {

// Set the GTK style on our custom link button. We don't want any border around
// the link text.
void SetLinkButtonStyle() {
  static bool style_was_set = false;

  if (style_was_set)
    return;
  style_was_set = true;

  gtk_rc_parse_string(
      "style \"chrome-link-button\" {"
      "  GtkButton::inner-border = {0, 0, 0, 0}"
      "  xthickness = 0"
      "  ythickness = 0"
      "}"
      "widget \"*chrome-link-button\" style \"chrome-link-button\"");
}

}  // namespace

G_BEGIN_DECLS
G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON)

static gboolean gtk_chrome_link_button_expose(GtkWidget* widget,
                                              GdkEventExpose* event) {
  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget);
  GtkWidget* label = button->label;

  if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE && button->is_blue) {
    gtk_label_set_markup(GTK_LABEL(label), button->red_markup);
    button->is_blue = FALSE;
  } else if (GTK_WIDGET_STATE(widget) != GTK_STATE_ACTIVE && !button->is_blue) {
    gtk_label_set_markup(GTK_LABEL(label), button->blue_markup);
    button->is_blue = TRUE;
  }

  // Draw the link inside the button.
  gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event);

  // Draw the focus rectangle.
  if (GTK_WIDGET_HAS_FOCUS(widget)) {
    gtk_paint_focus(widget->style, widget->window,
                    static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)),
                    &event->area, widget, NULL,
                    widget->allocation.x, widget->allocation.y,
                    widget->allocation.width, widget->allocation.height);
  }

  return TRUE;
}

static gboolean gtk_chrome_link_button_button_press(GtkWidget* widget,
                                                    GdkEventButton* event) {
  GtkButton* button;

  if (event->type == GDK_BUTTON_PRESS) {
    button = GTK_BUTTON(widget);

    if (button->focus_on_click && !GTK_WIDGET_HAS_FOCUS (widget))
      gtk_widget_grab_focus(widget);

    if (event->button == 1 || event->button == 2)
      gtk_button_pressed(button);
  }

  return TRUE;
}

static gboolean gtk_chrome_link_button_button_release(GtkWidget* widget,
                                                      GdkEventButton* event) {
  GtkButton* button = GTK_BUTTON(widget);
  GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(widget);

  free(link_button->click_button_event);
  link_button->click_button_event = static_cast<GdkEventButton*>(
      malloc(sizeof(GdkEventButton)));
  *link_button->click_button_event = *event;

  if (event->button == 1 || event->button == 2)
    gtk_button_released(button);

  return TRUE;
}

static void gtk_chrome_link_button_enter(GtkButton* button) {
  GtkWidget* widget = GTK_WIDGET(button);
  GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button);
  gdk_window_set_cursor(widget->window, link_button->hand_cursor);
}

static void gtk_chrome_link_button_leave(GtkButton* button) {
  GtkWidget* widget = GTK_WIDGET(button);
  GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button);
  gdk_window_set_cursor(widget->window, NULL);
  free(link_button->click_button_event);
  link_button->click_button_event = NULL;
}

static void gtk_chrome_link_button_destroy(GtkObject* object) {
  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object);
  if (button->blue_markup) {
    g_free(button->blue_markup);
    button->blue_markup = NULL;
  }
  if (button->red_markup) {
    g_free(button->red_markup);
    button->red_markup = NULL;
  }
  if (button->hand_cursor) {
    gdk_cursor_unref(button->hand_cursor);
    button->hand_cursor = NULL;
  }
  free(button->click_button_event);
  button->click_button_event = NULL;

  GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object);
}

static void gtk_chrome_link_button_class_init(
    GtkChromeLinkButtonClass* link_button_class) {
  GtkWidgetClass* widget_class =
      reinterpret_cast<GtkWidgetClass*>(link_button_class);
  GtkButtonClass* button_class =
      reinterpret_cast<GtkButtonClass*>(link_button_class);
  GtkObjectClass* object_class =
      reinterpret_cast<GtkObjectClass*>(link_button_class);
  widget_class->expose_event = &gtk_chrome_link_button_expose;
  widget_class->button_press_event = &gtk_chrome_link_button_button_press;
  widget_class->button_release_event = &gtk_chrome_link_button_button_release;
  button_class->enter = &gtk_chrome_link_button_enter;
  button_class->leave = &gtk_chrome_link_button_leave;
  object_class->destroy = &gtk_chrome_link_button_destroy;
}

static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) {
  SetLinkButtonStyle();

  // We put a label in a button so we can connect to the click event. We don't
  // let the button draw itself; catch all expose events to the button and pass
  // them through to the label.
  button->label = gtk_label_new(NULL);
  button->blue_markup = NULL;
  button->red_markup = NULL;
  button->is_blue = TRUE;
  button->hand_cursor = gdk_cursor_new(GDK_HAND2);
  button->click_button_event = NULL;

  gtk_container_add(GTK_CONTAINER(button), button->label);
  gtk_widget_set_name(GTK_WIDGET(button), "chrome-link-button");
  gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE);
}

static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button,
                                            const char* text) {
  // We should have only been called once or we'd leak the markups.
  DCHECK(!button->blue_markup && !button->red_markup);

  button->blue_markup = g_markup_printf_escaped(kLinkMarkup, "blue", text);
  button->red_markup = g_markup_printf_escaped(kLinkMarkup, "red", text);
  gtk_label_set_markup(GTK_LABEL(button->label), button->blue_markup);
  button->is_blue = TRUE;
}

GtkWidget* gtk_chrome_link_button_new(const char* text) {
  GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
  gtk_chrome_link_button_set_text(GTK_CHROME_LINK_BUTTON(lb), text);
  return lb;
}

const GdkEventButton* gtk_chrome_link_button_get_event_for_click(
    GtkChromeLinkButton* button) {
  return button->click_button_event;
}

G_END_DECLS
<commit_msg>Fix gcc-4.3 build<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/gtk/gtk_chrome_link_button.h"

#include <stdlib.h>

#include "base/logging.h"

static const char* kLinkMarkup = "%s";

namespace {

// Set the GTK style on our custom link button. We don't want any border around
// the link text.
void SetLinkButtonStyle() {
  static bool style_was_set = false;

  if (style_was_set)
    return;
  style_was_set = true;

  gtk_rc_parse_string(
      "style \"chrome-link-button\" {"
      "  GtkButton::inner-border = {0, 0, 0, 0}"
      "  xthickness = 0"
      "  ythickness = 0"
      "}"
      "widget \"*chrome-link-button\" style \"chrome-link-button\"");
}

}  // namespace

G_BEGIN_DECLS
G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON)

static gboolean gtk_chrome_link_button_expose(GtkWidget* widget,
                                              GdkEventExpose* event) {
  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget);
  GtkWidget* label = button->label;

  if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE && button->is_blue) {
    gtk_label_set_markup(GTK_LABEL(label), button->red_markup);
    button->is_blue = FALSE;
  } else if (GTK_WIDGET_STATE(widget) != GTK_STATE_ACTIVE && !button->is_blue) {
    gtk_label_set_markup(GTK_LABEL(label), button->blue_markup);
    button->is_blue = TRUE;
  }

  // Draw the link inside the button.
  gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event);

  // Draw the focus rectangle.
  if (GTK_WIDGET_HAS_FOCUS(widget)) {
    gtk_paint_focus(widget->style, widget->window,
                    static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)),
                    &event->area, widget, NULL,
                    widget->allocation.x, widget->allocation.y,
                    widget->allocation.width, widget->allocation.height);
  }

  return TRUE;
}

static gboolean gtk_chrome_link_button_button_press(GtkWidget* widget,
                                                    GdkEventButton* event) {
  GtkButton* button;

  if (event->type == GDK_BUTTON_PRESS) {
    button = GTK_BUTTON(widget);

    if (button->focus_on_click && !GTK_WIDGET_HAS_FOCUS (widget))
      gtk_widget_grab_focus(widget);

    if (event->button == 1 || event->button == 2)
      gtk_button_pressed(button);
  }

  return TRUE;
}

static gboolean gtk_chrome_link_button_button_release(GtkWidget* widget,
                                                      GdkEventButton* event) {
  GtkButton* button = GTK_BUTTON(widget);
  GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(widget);

  free(link_button->click_button_event);
  link_button->click_button_event = static_cast<GdkEventButton*>(
      malloc(sizeof(GdkEventButton)));
  *link_button->click_button_event = *event;

  if (event->button == 1 || event->button == 2)
    gtk_button_released(button);

  return TRUE;
}

static void gtk_chrome_link_button_enter(GtkButton* button) {
  GtkWidget* widget = GTK_WIDGET(button);
  GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button);
  gdk_window_set_cursor(widget->window, link_button->hand_cursor);
}

static void gtk_chrome_link_button_leave(GtkButton* button) {
  GtkWidget* widget = GTK_WIDGET(button);
  GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button);
  gdk_window_set_cursor(widget->window, NULL);
  free(link_button->click_button_event);
  link_button->click_button_event = NULL;
}

static void gtk_chrome_link_button_destroy(GtkObject* object) {
  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object);
  if (button->blue_markup) {
    g_free(button->blue_markup);
    button->blue_markup = NULL;
  }
  if (button->red_markup) {
    g_free(button->red_markup);
    button->red_markup = NULL;
  }
  if (button->hand_cursor) {
    gdk_cursor_unref(button->hand_cursor);
    button->hand_cursor = NULL;
  }
  free(button->click_button_event);
  button->click_button_event = NULL;

  GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object);
}

static void gtk_chrome_link_button_class_init(
    GtkChromeLinkButtonClass* link_button_class) {
  GtkWidgetClass* widget_class =
      reinterpret_cast<GtkWidgetClass*>(link_button_class);
  GtkButtonClass* button_class =
      reinterpret_cast<GtkButtonClass*>(link_button_class);
  GtkObjectClass* object_class =
      reinterpret_cast<GtkObjectClass*>(link_button_class);
  widget_class->expose_event = &gtk_chrome_link_button_expose;
  widget_class->button_press_event = &gtk_chrome_link_button_button_press;
  widget_class->button_release_event = &gtk_chrome_link_button_button_release;
  button_class->enter = &gtk_chrome_link_button_enter;
  button_class->leave = &gtk_chrome_link_button_leave;
  object_class->destroy = &gtk_chrome_link_button_destroy;
}

static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) {
  SetLinkButtonStyle();

  // We put a label in a button so we can connect to the click event. We don't
  // let the button draw itself; catch all expose events to the button and pass
  // them through to the label.
  button->label = gtk_label_new(NULL);
  button->blue_markup = NULL;
  button->red_markup = NULL;
  button->is_blue = TRUE;
  button->hand_cursor = gdk_cursor_new(GDK_HAND2);
  button->click_button_event = NULL;

  gtk_container_add(GTK_CONTAINER(button), button->label);
  gtk_widget_set_name(GTK_WIDGET(button), "chrome-link-button");
  gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE);
}

static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button,
                                            const char* text) {
  // We should have only been called once or we'd leak the markups.
  DCHECK(!button->blue_markup && !button->red_markup);

  button->blue_markup = g_markup_printf_escaped(kLinkMarkup, "blue", text);
  button->red_markup = g_markup_printf_escaped(kLinkMarkup, "red", text);
  gtk_label_set_markup(GTK_LABEL(button->label), button->blue_markup);
  button->is_blue = TRUE;
}

GtkWidget* gtk_chrome_link_button_new(const char* text) {
  GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
  gtk_chrome_link_button_set_text(GTK_CHROME_LINK_BUTTON(lb), text);
  return lb;
}

const GdkEventButton* gtk_chrome_link_button_get_event_for_click(
    GtkChromeLinkButton* button) {
  return button->click_button_event;
}

G_END_DECLS
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: optcolor.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 21:40:11 $
 *
 *  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 _SVX_OPTCOLOR_HXX
#define _SVX_OPTCOLOR_HXX

// include ---------------------------------------------------------------

#ifndef _SFXTABDLG_HXX //autogen
#include <sfx2/tabdlg.hxx>
#endif
#ifndef _SV_GROUP_HXX //autogen
#include <vcl/group.hxx>
#endif
#ifndef _SV_FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif
#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif

/* -----------------------------25.03.2002 10:40------------------------------

 ---------------------------------------------------------------------------*/
namespace svtools {class EditableColorConfig;}
class ColorConfigCtrl_Impl;
class AbstractSvxNameDialog; //CHINA001 class SvxNameDialog;
class SvxColorOptionsTabPage : public SfxTabPage
{
    FixedLine               aColorSchemeFL;
    FixedText               aColorSchemeFT;
    ListBox                 aColorSchemeLB;
    PushButton              aSaveSchemePB;
    PushButton              aDeleteSchemePB;

    FixedLine               aCustomColorsFL;

    BOOL                    bFillItemSetCalled;

    svtools::EditableColorConfig* pColorConfig;
    ColorConfigCtrl_Impl*   pColorConfigCT;

    DECL_LINK(SchemeChangedHdl_Impl, ListBox*);
    DECL_LINK(SaveDeleteHdl_Impl, PushButton*);
    DECL_LINK(CheckNameHdl_Impl, AbstractSvxNameDialog*);
    void UpdateColorConfig();

public:
    SvxColorOptionsTabPage( Window* pParent, const SfxItemSet& rSet );
    ~SvxColorOptionsTabPage(  );

    static SfxTabPage*  Create( Window* pParent, const SfxItemSet& rAttrSet );

    virtual BOOL        FillItemSet( SfxItemSet& rSet );
    virtual void        Reset( const SfxItemSet& rSet );

    virtual void        ActivatePage( const SfxItemSet& rSet );
    virtual int         DeactivatePage( SfxItemSet* pSet );
    virtual void        FillUserData();

};

#endif

<commit_msg>INTEGRATION: CWS warnings01 (1.3.222); FILE MERGED 2006/05/04 14:46:59 os 1.3.222.1: warnings removed<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: optcolor.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 15:21:20 $
 *
 *  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 _SVX_OPTCOLOR_HXX
#define _SVX_OPTCOLOR_HXX

// include ---------------------------------------------------------------

#ifndef _SFXTABDLG_HXX //autogen
#include <sfx2/tabdlg.hxx>
#endif
#ifndef _SV_GROUP_HXX //autogen
#include <vcl/group.hxx>
#endif
#ifndef _SV_FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif
#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif

/* -----------------------------25.03.2002 10:40------------------------------

 ---------------------------------------------------------------------------*/
namespace svtools {class EditableColorConfig;}
class ColorConfigCtrl_Impl;
class AbstractSvxNameDialog; //CHINA001 class SvxNameDialog;
class SvxColorOptionsTabPage : public SfxTabPage
{
    FixedLine               aColorSchemeFL;
    FixedText               aColorSchemeFT;
    ListBox                 aColorSchemeLB;
    PushButton              aSaveSchemePB;
    PushButton              aDeleteSchemePB;

    FixedLine               aCustomColorsFL;

    BOOL                    bFillItemSetCalled;

    svtools::EditableColorConfig* pColorConfig;
    ColorConfigCtrl_Impl*   pColorConfigCT;

    DECL_LINK(SchemeChangedHdl_Impl, ListBox*);
    DECL_LINK(SaveDeleteHdl_Impl, PushButton*);
    DECL_LINK(CheckNameHdl_Impl, AbstractSvxNameDialog*);
    void UpdateColorConfig();

public:
    SvxColorOptionsTabPage( Window* pParent, const SfxItemSet& rSet );
    ~SvxColorOptionsTabPage(  );

    static SfxTabPage*  Create( Window* pParent, const SfxItemSet& rAttrSet );

    virtual BOOL        FillItemSet( SfxItemSet& rSet );
    virtual void        Reset( const SfxItemSet& rSet );

    virtual int         DeactivatePage( SfxItemSet* pSet );
    virtual void        FillUserData();

};

#endif

<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "PointShotStrategy.h"

/* system implementation headers */
#include <assert.h>

/* common implementation headers */
#include "BZDBCache.h"
#include "WallObstacle.h"
#include "Intersect.h"
/* local implementation headers */
#include "LocalPlayer.h"
#include "playing.h"

PointShotStrategy::PointShotStrategy(ShotPath* _path)
: ShotStrategy(_path)
{
	doBoxTest = false;
}

PointShotStrategy::~PointShotStrategy()
{
}

float PointShotStrategy::checkShotHit(const ShotCollider& tank, fvec3& position, float radius) const
{
  float minTime = Infinity;
  // expired shot can't hit anything
  if (getPath().isExpired())
    return minTime;

  static BZDB_fvec3 shotProxy(BZDBNAMES.TANKSHOTPROXIMITY);
  const fvec3 &proxySize = shotProxy.getData();

  // tank is positioned from it's bottom so shift position up by
  // half a tank height.
  const float tankHeight = tank.size.z;
  fvec3 lastTankPositionRaw = tank.motion.getOrigin();
  lastTankPositionRaw.z += 0.5f * tankHeight;
  Ray tankLastMotion(lastTankPositionRaw, tank.motion.getDirection());

  const Extents& tankBBox = tank.bbox;

  // if bounding box of tank and entire shot doesn't overlap then no hit
  // we only do this for shots that keep the bbox updated
  if (doBoxTest)
  {
	  if (!bbox.touches(tankBBox))
		  return minTime;
  }

  float shotRadius = radius;

  // check each segment in interval (prevTime,currentTime]
  const float dt = float(currentTime - prevTime);
  const int numSegments = (const int)segments.size();
  for (int i = lastSegment; i <= segment && i < numSegments; i++)
  {
    // can never hit your own first laser segment
    if ((i == 0) && tank.testLastSegment && (getPath().getShotType() == LaserShot))
      continue;
/*
    // skip segments that don't overlap in time with current interval
    if (segments[i].end <= prevTime) continue;
    if (currentTime <= segments[i].start) break;
*/

    // if shot segment and tank bboxes don't overlap then no hit,
    // or if it's a shot that is out of the world boundary
    const ShotPathSegment& s = segments[i];
    if (!s.bbox.touches(tankBBox) || (s.reason == ShotPathSegment::Boundary))
      continue;

    // construct relative shot ray:  origin and velocity relative to
    // my tank as a function of time (t=0 is start of the interval).
    Ray relativeRay(Intersect::rayMinusRay(s.ray, float(prevTime - s.start), tankLastMotion, 0.0f));

    // get hit time
    float t;
	if (tank.test2D) // for now just test as a box, the box -> sphere test does not use the same volume and may cause more problems then it tries to solve by being fast
	{
      // find closest approach to narrow box around tank.  width of box
      // is shell radius so you can actually hit narrow tank head on.
      static fvec3 tankBase(0.0f, 0.0f, -0.5f * tankHeight);
      t = Intersect::timeRayHitsBlock(relativeRay, tankBase, tank.angle,
			(0.5f * tank.length) + proxySize.x, shotRadius, tankHeight + proxySize.z);
    }
	else// find time when shot hits sphere around tank
	{
		// old sphere code, has problems when the hit is inside the smaller "prehit" box
 //     t = Intersect::rayAtDistanceFromOrigin(relativeRay, 0.99f * tank.radius);

		// find closest approach to wide box around tank.  width of box
		// is tank radius so you get a little fudge factor on the side
		static fvec3 tankBase(0.0f, 0.0f, -0.5f * tankHeight);
		t = Intersect::timeRayHitsBlock(relativeRay, tankBase, tank.angle,
			tank.size.x + proxySize.x, tank.size.y + proxySize.y, tankHeight + proxySize.z);
	}

    // short circuit if time is greater then smallest time so far
    if (t > minTime)
		continue;

    // make sure time falls within segment
    if ((t < 0.0f) || (t > dt))
		continue;
    if (t > (s.end - prevTime))
		continue;

    // check if shot hits tank -- get position at time t, see if in radius
    fvec3 closestPos;
    relativeRay.getPoint(t, closestPos);
	// save best time so far
	minTime = t;

	// compute location of tank at time of hit
	fvec3 tankPos;
	tank.motion.getPoint(t, tankPos);

	// compute position of intersection
	position = tankPos + closestPos + fvec3(0,0,0.5f * tankHeight);
	//printf("%u:%u %u:%u\n", tank->getId().port, tank->getId().number, getPath().getPlayer().port, getPath().getPlayer().number);
  }

  return minTime;
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>verify that the shotProximity is good before we use it, since humans are stupid.<commit_after>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "PointShotStrategy.h"

/* system implementation headers */
#include <assert.h>

/* common implementation headers */
#include "BZDBCache.h"
#include "WallObstacle.h"
#include "Intersect.h"
/* local implementation headers */
#include "LocalPlayer.h"
#include "playing.h"

PointShotStrategy::PointShotStrategy(ShotPath* _path)
: ShotStrategy(_path)
{
	doBoxTest = false;
}

PointShotStrategy::~PointShotStrategy()
{
}

float PointShotStrategy::checkShotHit(const ShotCollider& tank, fvec3& position, float radius) const
{
  float minTime = Infinity;
  // expired shot can't hit anything
  if (getPath().isExpired())
    return minTime;

  static BZDB_fvec3 shotProxy(BZDBNAMES.TANKSHOTPROXIMITY);
  static fvec3 zeroMargin(0,0,0);
  fvec3 &proxySize = zeroMargin;
  if (!isnan(shotProxy.getData().x) && !isnan(shotProxy.getData().y) && !isnan(shotProxy.getData().z))
	  proxySize = shotProxy.getData();

  // tank is positioned from it's bottom so shift position up by
  // half a tank height.
  const float tankHeight = tank.size.z;
  fvec3 lastTankPositionRaw = tank.motion.getOrigin();
  lastTankPositionRaw.z += 0.5f * tankHeight;
  Ray tankLastMotion(lastTankPositionRaw, tank.motion.getDirection());

  const Extents& tankBBox = tank.bbox;

  // if bounding box of tank and entire shot doesn't overlap then no hit
  // we only do this for shots that keep the bbox updated
  if (doBoxTest)
  {
	  if (!bbox.touches(tankBBox))
		  return minTime;
  }

  float shotRadius = radius;

  // check each segment in interval (prevTime,currentTime]
  const float dt = float(currentTime - prevTime);
  const int numSegments = (const int)segments.size();
  for (int i = lastSegment; i <= segment && i < numSegments; i++)
  {
    // can never hit your own first laser segment
    if ((i == 0) && tank.testLastSegment && (getPath().getShotType() == LaserShot))
      continue;
/*
    // skip segments that don't overlap in time with current interval
    if (segments[i].end <= prevTime) continue;
    if (currentTime <= segments[i].start) break;
*/

    // if shot segment and tank bboxes don't overlap then no hit,
    // or if it's a shot that is out of the world boundary
    const ShotPathSegment& s = segments[i];
    if (!s.bbox.touches(tankBBox) || (s.reason == ShotPathSegment::Boundary))
      continue;

    // construct relative shot ray:  origin and velocity relative to
    // my tank as a function of time (t=0 is start of the interval).
    Ray relativeRay(Intersect::rayMinusRay(s.ray, float(prevTime - s.start), tankLastMotion, 0.0f));

    // get hit time
    float t;
	if (tank.test2D) // for now just test as a box, the box -> sphere test does not use the same volume and may cause more problems then it tries to solve by being fast
	{
      // find closest approach to narrow box around tank.  width of box
      // is shell radius so you can actually hit narrow tank head on.
      static fvec3 tankBase(0.0f, 0.0f, -0.5f * tankHeight);
      t = Intersect::timeRayHitsBlock(relativeRay, tankBase, tank.angle,
			(0.5f * tank.length) + proxySize.x, shotRadius, tankHeight + proxySize.z);
    }
	else// find time when shot hits sphere around tank
	{
		// old sphere code, has problems when the hit is inside the smaller "prehit" box
 //     t = Intersect::rayAtDistanceFromOrigin(relativeRay, 0.99f * tank.radius);

		// find closest approach to wide box around tank.  width of box
		// is tank radius so you get a little fudge factor on the side
		static fvec3 tankBase(0.0f, 0.0f, -0.5f * tankHeight);
		t = Intersect::timeRayHitsBlock(relativeRay, tankBase, tank.angle,
			tank.size.x + proxySize.x, tank.size.y + proxySize.y, tankHeight + proxySize.z);
	}

    // short circuit if time is greater then smallest time so far
    if (t > minTime)
		continue;

    // make sure time falls within segment
    if ((t < 0.0f) || (t > dt))
		continue;
    if (t > (s.end - prevTime))
		continue;

    // check if shot hits tank -- get position at time t, see if in radius
    fvec3 closestPos;
    relativeRay.getPoint(t, closestPos);
	// save best time so far
	minTime = t;

	// compute location of tank at time of hit
	fvec3 tankPos;
	tank.motion.getPoint(t, tankPos);

	// compute position of intersection
	position = tankPos + closestPos + fvec3(0,0,0.5f * tankHeight);
	//printf("%u:%u %u:%u\n", tank->getId().port, tank->getId().number, getPath().getPlayer().port, getPath().getPlayer().number);
  }

  return minTime;
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>