<commit_before>#ifndef buffer_hh_INCLUDED
#define buffer_hh_INCLUDED

#include <vector>
#include <list>
#include <memory>

#include "line_and_column.hh"
#include "option_manager.hh"
#include "hook_manager.hh"
#include "string.hh"
#include "units.hh"

namespace Kakoune
{

class Buffer;
class Window;

struct BufferCoord : LineAndColumn<BufferCoord, LineCount, ByteCount>
{
    constexpr BufferCoord(LineCount line = 0, ByteCount column = 0)
        : LineAndColumn(line, column) {}
};

// A BufferIterator permits to iterate over the characters of a buffer
class BufferIterator
{
public:
    typedef char value_type;
    typedef size_t difference_type;
    typedef const value_type* pointer;
    typedef const value_type& reference;
    typedef std::bidirectional_iterator_tag iterator_category;

    BufferIterator() : m_buffer(nullptr) {}
    BufferIterator(const Buffer& buffer, BufferCoord coord);

    bool operator== (const BufferIterator& iterator) const;
    bool operator!= (const BufferIterator& iterator) const;
    bool operator<  (const BufferIterator& iterator) const;
    bool operator<= (const BufferIterator& iterator) const;
    bool operator>  (const BufferIterator& iterator) const;
    bool operator>= (const BufferIterator& iterator) const;

    char   operator* () const;
    size_t operator- (const BufferIterator& iterator) const;

    BufferIterator operator+ (ByteCount size) const;
    BufferIterator operator- (ByteCount size) const;

    BufferIterator& operator+= (ByteCount size);
    BufferIterator& operator-= (ByteCount size);

    BufferIterator& operator++ ();
    BufferIterator& operator-- ();

    BufferIterator operator++ (int);
    BufferIterator operator-- (int);

    void clamp(bool avoid_eol);

    bool is_begin() const;
    bool is_end() const;
    bool is_valid() const;

    void on_insert(const BufferCoord& begin, const BufferCoord& end);
    void on_erase(const BufferCoord& begin, const BufferCoord& end);

    const Buffer& buffer() const;
    const BufferCoord& coord() const { return m_coord; }
    LineCount  line() const { return m_coord.line; }
    ByteCount column() const { return m_coord.column; }

private:
    ByteCount offset() const;

    const Buffer* m_buffer;
    BufferCoord   m_coord;
    friend class Buffer;
};

class BufferChangeListener
{
public:
    virtual void on_insert(const BufferIterator& begin, const BufferIterator& end) = 0;
    virtual void on_erase(const BufferIterator& begin, const BufferIterator& end) = 0;
};

// A Buffer is a in-memory representation of a file
//
// The Buffer class permits to read and mutate this file
// representation. It also manage modifications undo/redo and
// provides tools to deal with the line/column nature of text.
class Buffer : public SafeCountable
{
public:
    enum class Type
    {
        File,
        NewFile,
        Scratch
    };

    Buffer(String name, Type type, String initial_content = "\n");
    Buffer(const Buffer&) = delete;
    Buffer(Buffer&&) = delete;
    Buffer& operator= (const Buffer&) = delete;
    ~Buffer();

    Type type() const { return m_type; }

    void insert(BufferIterator pos, String content);
    void erase(BufferIterator begin, BufferIterator end);

    size_t         timestamp() const { return m_timestamp; }

    void           begin_undo_group();
    void           end_undo_group();
    bool           undo();
    bool           redo();
    void           reset_undo_data();

    String         string(const BufferIterator& begin,
                          const BufferIterator& end) const;

    BufferIterator begin() const;
    BufferIterator end() const;
    ByteCount      character_count() const;
    LineCount      line_count() const;
    ByteCount      line_length(LineCount line) const;

    // returns an iterator at given coordinates. line_and_column is
    // clamped according to avoid_eol.
    BufferIterator iterator_at(const BufferCoord& line_and_column,
                               bool avoid_eol = false) const;
    BufferCoord    line_and_column_at(const BufferIterator& iterator) const;

    // returns nearest valid coordinates from given ones
    // if avoid_eol, clamp to character before eol if line is not empty
    BufferCoord    clamp(const BufferCoord& line_and_column,
                         bool avoid_eol = false) const;

    const String& name() const { return m_name; }

    // Window handling
    using WindowList = std::vector<std::unique_ptr<Window>>;
    const WindowList& windows() const { return m_windows; }
    Window& new_window();
    void    delete_window(Window& window);

    // returns true if the buffer is in a different state than
    // the last time it was saved
    bool is_modified() const;

    // notify the buffer that it was saved in the current state
    void notify_saved();

    void add_change_listener(BufferChangeListener& listener);
    void remove_change_listener(BufferChangeListener& listener);

    // returns an iterator pointing to the first character of the line
    // iterator is on
    BufferIterator iterator_at_line_begin(const BufferIterator& iterator) const;
    // the same but taking a line number instead of an iterator
    BufferIterator iterator_at_line_begin(LineCount line) const;

    // returns an iterator pointing to the character after the last of the
    // line iterator is on (which is the first of the next line if iterator is
    // not on the last one)
    BufferIterator iterator_at_line_end(const BufferIterator& iterator) const;
    // the same but taking a line number instead of an iterator
    BufferIterator iterator_at_line_end(LineCount line) const;

    const String& line_content(LineCount line) const
    { return m_lines[line].content; }

    OptionManager&       option_manager()       { return m_option_manager; }
    const OptionManager& option_manager() const { return m_option_manager; }
    HookManager&         hook_manager()         { return m_hook_manager; }
    const HookManager&   hook_manager()   const { return m_hook_manager; }

private:
    friend class BufferIterator;

    void check_invariant() const;

    struct Line
    {
        ByteCount start;
        String    content;

        ByteCount length() const { return content.length(); }
    };
    struct LineList : std::vector<Line>
    {
    public:
        Line& operator[](LineCount line)
        { return std::vector<Line>::operator[]((int)line); }

        const Line& operator[](LineCount line) const
        { return std::vector<Line>::operator[]((int)line); }
    };
    LineList m_lines;

    void do_insert(const BufferIterator& pos, const String& content);
    void do_erase(const BufferIterator& begin, const BufferIterator& end);

    String  m_name;
    const Type   m_type;

    struct Modification;
    typedef std::vector<Modification> UndoGroup;

    std::vector<UndoGroup>           m_history;
    std::vector<UndoGroup>::iterator m_history_cursor;
    UndoGroup                        m_current_undo_group;

    void apply_modification(const Modification& modification);
    void revert_modification(const Modification& modification);

    WindowList m_windows;

    size_t m_last_save_undo_index;
    size_t m_timestamp;

    std::vector<BufferChangeListener*> m_change_listeners;

    OptionManager m_option_manager;
    HookManager   m_hook_manager;
};

}

#include "buffer_iterator.inl.hh"

#endif // buffer_hh_INCLUDED
<commit_msg>BufferIterator holds a safe_ptr to their buffer instead of a raw pointer<commit_after>#ifndef buffer_hh_INCLUDED
#define buffer_hh_INCLUDED

#include <vector>
#include <list>
#include <memory>

#include "line_and_column.hh"
#include "option_manager.hh"
#include "hook_manager.hh"
#include "string.hh"
#include "units.hh"

namespace Kakoune
{

class Buffer;
class Window;

struct BufferCoord : LineAndColumn<BufferCoord, LineCount, ByteCount>
{
    constexpr BufferCoord(LineCount line = 0, ByteCount column = 0)
        : LineAndColumn(line, column) {}
};

// A BufferIterator permits to iterate over the characters of a buffer
class BufferIterator
{
public:
    typedef char value_type;
    typedef size_t difference_type;
    typedef const value_type* pointer;
    typedef const value_type& reference;
    typedef std::bidirectional_iterator_tag iterator_category;

    BufferIterator() : m_buffer(nullptr) {}
    BufferIterator(const Buffer& buffer, BufferCoord coord);

    bool operator== (const BufferIterator& iterator) const;
    bool operator!= (const BufferIterator& iterator) const;
    bool operator<  (const BufferIterator& iterator) const;
    bool operator<= (const BufferIterator& iterator) const;
    bool operator>  (const BufferIterator& iterator) const;
    bool operator>= (const BufferIterator& iterator) const;

    char   operator* () const;
    size_t operator- (const BufferIterator& iterator) const;

    BufferIterator operator+ (ByteCount size) const;
    BufferIterator operator- (ByteCount size) const;

    BufferIterator& operator+= (ByteCount size);
    BufferIterator& operator-= (ByteCount size);

    BufferIterator& operator++ ();
    BufferIterator& operator-- ();

    BufferIterator operator++ (int);
    BufferIterator operator-- (int);

    void clamp(bool avoid_eol);

    bool is_begin() const;
    bool is_end() const;
    bool is_valid() const;

    void on_insert(const BufferCoord& begin, const BufferCoord& end);
    void on_erase(const BufferCoord& begin, const BufferCoord& end);

    const Buffer& buffer() const;
    const BufferCoord& coord() const { return m_coord; }
    LineCount  line() const { return m_coord.line; }
    ByteCount column() const { return m_coord.column; }

private:
    ByteCount offset() const;

    safe_ptr<const Buffer> m_buffer;
    BufferCoord   m_coord;
    friend class Buffer;
};

class BufferChangeListener
{
public:
    virtual void on_insert(const BufferIterator& begin, const BufferIterator& end) = 0;
    virtual void on_erase(const BufferIterator& begin, const BufferIterator& end) = 0;
};

// A Buffer is a in-memory representation of a file
//
// The Buffer class permits to read and mutate this file
// representation. It also manage modifications undo/redo and
// provides tools to deal with the line/column nature of text.
class Buffer : public SafeCountable
{
public:
    enum class Type
    {
        File,
        NewFile,
        Scratch
    };

    Buffer(String name, Type type, String initial_content = "\n");
    Buffer(const Buffer&) = delete;
    Buffer(Buffer&&) = delete;
    Buffer& operator= (const Buffer&) = delete;
    ~Buffer();

    Type type() const { return m_type; }

    void insert(BufferIterator pos, String content);
    void erase(BufferIterator begin, BufferIterator end);

    size_t         timestamp() const { return m_timestamp; }

    void           begin_undo_group();
    void           end_undo_group();
    bool           undo();
    bool           redo();
    void           reset_undo_data();

    String         string(const BufferIterator& begin,
                          const BufferIterator& end) const;

    BufferIterator begin() const;
    BufferIterator end() const;
    ByteCount      character_count() const;
    LineCount      line_count() const;
    ByteCount      line_length(LineCount line) const;

    // returns an iterator at given coordinates. line_and_column is
    // clamped according to avoid_eol.
    BufferIterator iterator_at(const BufferCoord& line_and_column,
                               bool avoid_eol = false) const;
    BufferCoord    line_and_column_at(const BufferIterator& iterator) const;

    // returns nearest valid coordinates from given ones
    // if avoid_eol, clamp to character before eol if line is not empty
    BufferCoord    clamp(const BufferCoord& line_and_column,
                         bool avoid_eol = false) const;

    const String& name() const { return m_name; }

    // Window handling
    using WindowList = std::vector<std::unique_ptr<Window>>;
    const WindowList& windows() const { return m_windows; }
    Window& new_window();
    void    delete_window(Window& window);

    // returns true if the buffer is in a different state than
    // the last time it was saved
    bool is_modified() const;

    // notify the buffer that it was saved in the current state
    void notify_saved();

    void add_change_listener(BufferChangeListener& listener);
    void remove_change_listener(BufferChangeListener& listener);

    // returns an iterator pointing to the first character of the line
    // iterator is on
    BufferIterator iterator_at_line_begin(const BufferIterator& iterator) const;
    // the same but taking a line number instead of an iterator
    BufferIterator iterator_at_line_begin(LineCount line) const;

    // returns an iterator pointing to the character after the last of the
    // line iterator is on (which is the first of the next line if iterator is
    // not on the last one)
    BufferIterator iterator_at_line_end(const BufferIterator& iterator) const;
    // the same but taking a line number instead of an iterator
    BufferIterator iterator_at_line_end(LineCount line) const;

    const String& line_content(LineCount line) const
    { return m_lines[line].content; }

    OptionManager&       option_manager()       { return m_option_manager; }
    const OptionManager& option_manager() const { return m_option_manager; }
    HookManager&         hook_manager()         { return m_hook_manager; }
    const HookManager&   hook_manager()   const { return m_hook_manager; }

private:
    friend class BufferIterator;

    void check_invariant() const;

    struct Line
    {
        ByteCount start;
        String    content;

        ByteCount length() const { return content.length(); }
    };
    struct LineList : std::vector<Line>
    {
    public:
        Line& operator[](LineCount line)
        { return std::vector<Line>::operator[]((int)line); }

        const Line& operator[](LineCount line) const
        { return std::vector<Line>::operator[]((int)line); }
    };
    LineList m_lines;

    void do_insert(const BufferIterator& pos, const String& content);
    void do_erase(const BufferIterator& begin, const BufferIterator& end);

    String  m_name;
    const Type   m_type;

    struct Modification;
    typedef std::vector<Modification> UndoGroup;

    std::vector<UndoGroup>           m_history;
    std::vector<UndoGroup>::iterator m_history_cursor;
    UndoGroup                        m_current_undo_group;

    void apply_modification(const Modification& modification);
    void revert_modification(const Modification& modification);

    WindowList m_windows;

    size_t m_last_save_undo_index;
    size_t m_timestamp;

    std::vector<BufferChangeListener*> m_change_listeners;

    OptionManager m_option_manager;
    HookManager   m_hook_manager;
};

}

#include "buffer_iterator.inl.hh"

#endif // buffer_hh_INCLUDED
<|endoftext|>


<commit_before>#include "personsmodel.h"

#include "personpluginmanager_p.h"
#include "metacontact_p.h"
#include "basepersonsdatasource.h"
#include "personmanager_p.h"

#include <KABC/Addressee>
#include <KStandardDirs>
#include <KDebug>

#include <QDebug>
#include <QPixmap>
#include <QTimer>

namespace KPeople {
class PersonsModelPrivate{
public:
    //NOTE This is the opposite way round to the return value from contactMapping() for easier lookups
    QHash<QString /*contactId*/, QString /*PersonId*/> contactToPersons;

    //hash of person objects indexed by ID
    QHash<QString /*Person ID*/, MetaContact> metacontacts;
    //a list so we have an order in the model
    QStringList personIds;

    QString genericAvatarImagePath;
    QList<AllContactsMonitorPtr> m_sourceMonitors;
};
}

using namespace KPeople;

PersonsModel::PersonsModel(QObject *parent):
    QAbstractItemModel(parent),
    d_ptr(new PersonsModelPrivate)
{
    Q_D(PersonsModel);

    d->genericAvatarImagePath = KStandardDirs::locate("data", "kpeople/dummy_avatar.png");
    Q_FOREACH (BasePersonsDataSource* dataSource, PersonPluginManager::dataSourcePlugins()) {
        d->m_sourceMonitors << dataSource->allContactsMonitor();
    }

    QTimer::singleShot(0, this, SLOT(onContactsFetched()));

    Q_FOREACH(const AllContactsMonitorPtr monitor, d->m_sourceMonitors) {
        connect(monitor.data(), SIGNAL(contactAdded(QString,KABC::Addressee)), SLOT(onContactAdded(QString,KABC::Addressee)));
        connect(monitor.data(), SIGNAL(contactChanged(QString,KABC::Addressee)), SLOT(onContactChanged(QString,KABC::Addressee)));
        connect(monitor.data(), SIGNAL(contactRemoved(QString)), SLOT(onContactRemoved(QString)));
    }

    connect(PersonManager::instance(), SIGNAL(contactAddedToPerson(QString,QString)), SLOT(onAddContactToPerson(QString,QString)));
    connect(PersonManager::instance(), SIGNAL(contactRemovedFromPerson(QString)), SLOT(onRemoveContactsFromPerson(QString)));
}

PersonsModel::~PersonsModel()
{
}

// QVariant dataForPerson(const KABC::Person &person)
// {
//
// }

QVariant PersonsModel::data(const QModelIndex &index, int role) const
{
    Q_D(const PersonsModel);

    //optimisation - if we don't cover this role, ignore it
    if (role < Qt::UserRole && role != Qt::DisplayRole && role != Qt::DecorationRole) {
        return QVariant();
    }

    if (index.row() < 0 || index.row() >= rowCount(index.parent())) {
        return QVariant();
    }

    if (index.parent().isValid()) {
        if (role == ContactsVCardRole) {
            return QVariant::fromValue<KABC::AddresseeList>(KABC::AddresseeList());
        }
        const QString &personId = d->personIds[index.parent().row()];
        const MetaContact &mc = d->metacontacts[personId];

        return dataForAddressee(personId, mc.contacts().at(index.row()), role);
    } else {
        const QString &personId = d->personIds[index.row()];
        return dataForAddressee(personId, d->metacontacts[personId].personAddressee(), role);
    }
}

QVariant PersonsModel::dataForAddressee(const QString &personId, const KABC::Addressee &person, int role) const
{
    Q_D(const PersonsModel);

    switch(role) {
    case FormattedNameRole:
        return person.formattedName();
    case PhotoRole:
        if (!person.photo().data().isNull()) {
            return person.photo().data();
        } else if (!person.photo().url().isEmpty()) {
            return QImage(person.photo().url());
        } else {
            return QImage(d->genericAvatarImagePath);
        }
    case PersonIdRole:
        return personId;
    case PersonVCardRole:
        return QVariant::fromValue<KABC::Addressee>(person);
    case ContactsVCardRole:
        return QVariant::fromValue<KABC::AddresseeList>(d->metacontacts[personId].contacts());
    case GroupsRole:
        return person.categories();
    }
    return QVariant();
}

int PersonsModel::columnCount(const QModelIndex &parent) const
{
    return 1;
}

int PersonsModel::rowCount(const QModelIndex &parent) const
{
    Q_D(const PersonsModel);

    if (!parent.isValid()) {
        return d->personIds.size();
    }

    if (parent.isValid() && !parent.parent().isValid()) {
        return d->metacontacts[d->personIds.at(parent.row())].contacts().count();
    }

    return 0;
}

QModelIndex PersonsModel::index(int row, int column, const QModelIndex &parent) const
{
    if (row < 0 || column < 0 || row >= rowCount(parent)) {
        return QModelIndex();
    }
    //top level items have internalId -1. Anything >=0 is the row of the top level item
    if (!parent.isValid()) {
        return createIndex(row, column, -1);
    }

    return createIndex(row, column, parent.row());
}

QModelIndex PersonsModel::parent(const QModelIndex &childIndex) const
{
    if (childIndex.internalId() == -1 || !childIndex.isValid()) {
        return QModelIndex();
    }

    return index(childIndex.internalId(), 0, QModelIndex());
}

void PersonsModel::onContactsFetched()
{
    Q_D(PersonsModel);
    KABC::Addressee::Map addresseeMap;

    //fetch all already loaded contacts from plugins
    KABC::AddresseeList contactList;
    Q_FOREACH (const AllContactsMonitorPtr &contactWatcher, d->m_sourceMonitors) {
        addresseeMap.unite(contactWatcher->contacts());
    }

    //add metacontacts
    QMultiHash<QString, QString> contactMapping = PersonManager::instance()->allPersons();

    Q_FOREACH (const QString &key, contactMapping.uniqueKeys()) {
        KABC::Addressee::Map contacts;
        Q_FOREACH (const QString &contact, contactMapping.values(key)) {
            d->contactToPersons[contact] = key;
            if (addresseeMap.contains(contact)) {
                contacts[contact] = addresseeMap.take(contact);
            }
        }
        if (!contacts.isEmpty()) {
            addPerson(MetaContact(key, contacts));
        }
    }

    //add remaining contacts
    KABC::Addressee::Map::const_iterator i;
    for (i = addresseeMap.constBegin(); i != addresseeMap.constEnd(); ++i) {
        addPerson(MetaContact(i.key(), i.value()));
    }

    emit modelInitialized();
}

void PersonsModel::onContactAdded(const QString &contactId, const KABC::Addressee &contact)
{
    Q_D(PersonsModel);

    const QString &personId = personIdForContact(contactId);

    if (d->personIds.contains(personId)) {
        MetaContact &mc = d->metacontacts[personId];

        //if the MC object already contains this object, we want to update the row, not do an insert
        if (mc.contactIds().contains(contactId)) {
            kWarning() << "Source emitted contactAdded for a contact we already know about " << contactId;
            onContactChanged(contactId, contact);
        } else {
            int newContactPos = mc.contacts().size();
            beginInsertRows(index(d->personIds.indexOf(personId)), newContactPos, newContactPos);
            mc.insertContact(contactId, contact);
            endInsertRows();
            personChanged(personId);
        }
    } else { //new contact -> new person
        KABC::Addressee::Map map;
        map[contactId] = contact;
        addPerson(MetaContact(personId, map));
    }
}

void PersonsModel::onContactChanged(const QString &contactId, const KABC::Addressee &contact)
{
    Q_D(PersonsModel);

    const QString &personId = personIdForContact(contactId);
    int row = d->metacontacts[personId].updateContact(contactId, contact);

    const QModelIndex contactIndex = index(row,
                                           0,
                                           index(d->personIds.indexOf(personId)));

    Q_EMIT dataChanged(contactIndex, contactIndex);

    personChanged(personId);
}

void PersonsModel::onContactRemoved(const QString &contactId)
{
    Q_D(PersonsModel);

    const QString &personId = personIdForContact(contactId);

    MetaContact &mc = d->metacontacts[personId];
    int contactPosition = d->metacontacts[personId].contactIds().indexOf(contactId);
    beginRemoveRows(index(d->personIds.indexOf(personId), 0), contactPosition, contactPosition);
    d->metacontacts[personId].removeContact(contactId);
    endRemoveRows();

    //if MC object is now invalid remove the person from the list
    if (!mc.isValid()) {
        removePerson(personId);
    }
    personChanged(personId);
}

void PersonsModel::onAddContactToPerson(const QString &contactId, const QString &newPersonId)
{
    Q_D(PersonsModel);

    const QString oldPersonId = personIdForContact(contactId);
    d->contactToPersons.insert(contactId, newPersonId);

    //get contact already in the model, remove it from the previous contact
    const KABC::Addressee &contact = d->metacontacts[oldPersonId].contact(contactId);
    int contactPosition = d->metacontacts[oldPersonId].contacts().indexOf(contact);
    beginRemoveRows(index(d->personIds.indexOf(oldPersonId), 0), contactPosition, contactPosition);
    d->metacontacts[oldPersonId].removeContact(contactId);
    endRemoveRows();

    if (!d->metacontacts[oldPersonId].isValid()) {
        removePerson(oldPersonId);
    } else {
        personChanged(oldPersonId);
    }

    //if the new person is already in the model, add the contact to it
    if (d->personIds.contains(newPersonId)) {
        int newContactPos = d->metacontacts[newPersonId].contacts().size();
        beginInsertRows(index(d->personIds.indexOf(newPersonId), 0), newContactPos, newContactPos);
        d->metacontacts[newPersonId].insertContact(contactId, contact);
        endInsertRows();
        personChanged(newPersonId);
    } else { //if the person is not in the model, create a new person and insert it
        KABC::Addressee::Map contacts;
        contacts[contactId] = contact;
        addPerson(MetaContact(newPersonId, contacts));
    }
}

void PersonsModel::onRemoveContactsFromPerson(const QString &contactId)
{
    Q_D(PersonsModel);

    const QString personId = personIdForContact(contactId);
    const KABC::Addressee &contact = d->metacontacts[personId].contact(contactId);
    d->metacontacts[personId].removeContact(contactId);
    d->contactToPersons.remove(contactId);

    //if we don't want the person object anymore
    if (!d->metacontacts[personId].isValid()) {
        removePerson(personId);
    } else {
        personChanged(personId);
    }

    //now re-insert as a new contact
    //we know it's not part of a metacontact anymore so reinsert as a contact
    addPerson(MetaContact(contactId, contact));
}

void PersonsModel::addPerson(const KPeople::MetaContact &mc)
{
    Q_D(PersonsModel);

    const QString &id = mc.id();

    beginInsertRows(QModelIndex(), d->personIds.size(), d->personIds.size());
    d->metacontacts[id] = mc;
    d->personIds << id;
    endInsertRows();
}

void PersonsModel::removePerson(const QString& id)
{
    Q_D(PersonsModel);

    int row = d->personIds.indexOf(id);
    if (row < 0) { //item not found
        return;
    }

    beginRemoveRows(QModelIndex(), row, row);
    d->metacontacts.remove(id);
    d->personIds.removeOne(id);
    endRemoveRows();
}

void PersonsModel::personChanged(const QString &personId)
{
    Q_D(const PersonsModel);
    int row = d->personIds.indexOf(personId);
    if (row >= 0) {
        const QModelIndex personIndex = index(row);
        dataChanged(personIndex, personIndex);
    }
}

QString PersonsModel::personIdForContact(const QString &contactId) const
{
    Q_D(const PersonsModel);
    //TODO optimise with constFind()
    if (d->contactToPersons.contains(contactId)) {
        return d->contactToPersons[contactId];
    } else {
        return contactId;
    }
}

<commit_msg>Only start monitoring for DataSource changes after loading<commit_after>#include "personsmodel.h"

#include "personpluginmanager_p.h"
#include "metacontact_p.h"
#include "basepersonsdatasource.h"
#include "personmanager_p.h"

#include <KABC/Addressee>
#include <KStandardDirs>
#include <KDebug>

#include <QDebug>
#include <QPixmap>
#include <QTimer>

namespace KPeople {
class PersonsModelPrivate{
public:
    //NOTE This is the opposite way round to the return value from contactMapping() for easier lookups
    QHash<QString /*contactId*/, QString /*PersonId*/> contactToPersons;

    //hash of person objects indexed by ID
    QHash<QString /*Person ID*/, MetaContact> metacontacts;
    //a list so we have an order in the model
    QStringList personIds;

    QString genericAvatarImagePath;
    QList<AllContactsMonitorPtr> m_sourceMonitors;
};
}

using namespace KPeople;

PersonsModel::PersonsModel(QObject *parent):
    QAbstractItemModel(parent),
    d_ptr(new PersonsModelPrivate)
{
    Q_D(PersonsModel);

    d->genericAvatarImagePath = KStandardDirs::locate("data", "kpeople/dummy_avatar.png");
    Q_FOREACH (BasePersonsDataSource* dataSource, PersonPluginManager::dataSourcePlugins()) {
        d->m_sourceMonitors << dataSource->allContactsMonitor();
    }

    QTimer::singleShot(0, this, SLOT(onContactsFetched()));

    connect(PersonManager::instance(), SIGNAL(contactAddedToPerson(QString,QString)), SLOT(onAddContactToPerson(QString,QString)));
    connect(PersonManager::instance(), SIGNAL(contactRemovedFromPerson(QString)), SLOT(onRemoveContactsFromPerson(QString)));
}

PersonsModel::~PersonsModel()
{
}

// QVariant dataForPerson(const KABC::Person &person)
// {
//
// }

QVariant PersonsModel::data(const QModelIndex &index, int role) const
{
    Q_D(const PersonsModel);

    //optimisation - if we don't cover this role, ignore it
    if (role < Qt::UserRole && role != Qt::DisplayRole && role != Qt::DecorationRole) {
        return QVariant();
    }

    if (index.row() < 0 || index.row() >= rowCount(index.parent())) {
        return QVariant();
    }

    if (index.parent().isValid()) {
        if (role == ContactsVCardRole) {
            return QVariant::fromValue<KABC::AddresseeList>(KABC::AddresseeList());
        }
        const QString &personId = d->personIds[index.parent().row()];
        const MetaContact &mc = d->metacontacts[personId];

        return dataForAddressee(personId, mc.contacts().at(index.row()), role);
    } else {
        const QString &personId = d->personIds[index.row()];
        return dataForAddressee(personId, d->metacontacts[personId].personAddressee(), role);
    }
}

QVariant PersonsModel::dataForAddressee(const QString &personId, const KABC::Addressee &person, int role) const
{
    Q_D(const PersonsModel);

    switch(role) {
    case FormattedNameRole:
        return person.formattedName();
    case PhotoRole:
        if (!person.photo().data().isNull()) {
            return person.photo().data();
        } else if (!person.photo().url().isEmpty()) {
            return QImage(person.photo().url());
        } else {
            return QImage(d->genericAvatarImagePath);
        }
    case PersonIdRole:
        return personId;
    case PersonVCardRole:
        return QVariant::fromValue<KABC::Addressee>(person);
    case ContactsVCardRole:
        return QVariant::fromValue<KABC::AddresseeList>(d->metacontacts[personId].contacts());
    case GroupsRole:
        return person.categories();
    }
    return QVariant();
}

int PersonsModel::columnCount(const QModelIndex &parent) const
{
    return 1;
}

int PersonsModel::rowCount(const QModelIndex &parent) const
{
    Q_D(const PersonsModel);

    if (!parent.isValid()) {
        return d->personIds.size();
    }

    if (parent.isValid() && !parent.parent().isValid()) {
        return d->metacontacts[d->personIds.at(parent.row())].contacts().count();
    }

    return 0;
}

QModelIndex PersonsModel::index(int row, int column, const QModelIndex &parent) const
{
    if (row < 0 || column < 0 || row >= rowCount(parent)) {
        return QModelIndex();
    }
    //top level items have internalId -1. Anything >=0 is the row of the top level item
    if (!parent.isValid()) {
        return createIndex(row, column, -1);
    }

    return createIndex(row, column, parent.row());
}

QModelIndex PersonsModel::parent(const QModelIndex &childIndex) const
{
    if (childIndex.internalId() == -1 || !childIndex.isValid()) {
        return QModelIndex();
    }

    return index(childIndex.internalId(), 0, QModelIndex());
}

void PersonsModel::onContactsFetched()
{
    Q_D(PersonsModel);
    KABC::Addressee::Map addresseeMap;

    //fetch all already loaded contacts from plugins
    KABC::AddresseeList contactList;
    Q_FOREACH (const AllContactsMonitorPtr &contactWatcher, d->m_sourceMonitors) {
        addresseeMap.unite(contactWatcher->contacts());
    }

    //add metacontacts
    QMultiHash<QString, QString> contactMapping = PersonManager::instance()->allPersons();

    Q_FOREACH (const QString &key, contactMapping.uniqueKeys()) {
        KABC::Addressee::Map contacts;
        Q_FOREACH (const QString &contact, contactMapping.values(key)) {
            d->contactToPersons[contact] = key;
            if (addresseeMap.contains(contact)) {
                contacts[contact] = addresseeMap.take(contact);
            }
        }
        if (!contacts.isEmpty()) {
            addPerson(MetaContact(key, contacts));
        }
    }

    //add remaining contacts
    KABC::Addressee::Map::const_iterator i;
    for (i = addresseeMap.constBegin(); i != addresseeMap.constEnd(); ++i) {
        addPerson(MetaContact(i.key(), i.value()));
    }

    Q_FOREACH(const AllContactsMonitorPtr monitor, d->m_sourceMonitors) {
        connect(monitor.data(), SIGNAL(contactAdded(QString,KABC::Addressee)), SLOT(onContactAdded(QString,KABC::Addressee)));
        connect(monitor.data(), SIGNAL(contactChanged(QString,KABC::Addressee)), SLOT(onContactChanged(QString,KABC::Addressee)));
        connect(monitor.data(), SIGNAL(contactRemoved(QString)), SLOT(onContactRemoved(QString)));
    }

    emit modelInitialized();
}

void PersonsModel::onContactAdded(const QString &contactId, const KABC::Addressee &contact)
{
    Q_D(PersonsModel);

    const QString &personId = personIdForContact(contactId);

    if (d->personIds.contains(personId)) {
        MetaContact &mc = d->metacontacts[personId];

        //if the MC object already contains this object, we want to update the row, not do an insert
        if (mc.contactIds().contains(contactId)) {
            kWarning() << "Source emitted contactAdded for a contact we already know about " << contactId;
            onContactChanged(contactId, contact);
        } else {
            int newContactPos = mc.contacts().size();
            beginInsertRows(index(d->personIds.indexOf(personId)), newContactPos, newContactPos);
            mc.insertContact(contactId, contact);
            endInsertRows();
            personChanged(personId);
        }
    } else { //new contact -> new person
        KABC::Addressee::Map map;
        map[contactId] = contact;
        addPerson(MetaContact(personId, map));
    }
}

void PersonsModel::onContactChanged(const QString &contactId, const KABC::Addressee &contact)
{
    Q_D(PersonsModel);

    const QString &personId = personIdForContact(contactId);
    int row = d->metacontacts[personId].updateContact(contactId, contact);

    const QModelIndex contactIndex = index(row,
                                           0,
                                           index(d->personIds.indexOf(personId)));

    Q_EMIT dataChanged(contactIndex, contactIndex);

    personChanged(personId);
}

void PersonsModel::onContactRemoved(const QString &contactId)
{
    Q_D(PersonsModel);

    const QString &personId = personIdForContact(contactId);

    MetaContact &mc = d->metacontacts[personId];
    int contactPosition = d->metacontacts[personId].contactIds().indexOf(contactId);
    beginRemoveRows(index(d->personIds.indexOf(personId), 0), contactPosition, contactPosition);
    d->metacontacts[personId].removeContact(contactId);
    endRemoveRows();

    //if MC object is now invalid remove the person from the list
    if (!mc.isValid()) {
        removePerson(personId);
    }
    personChanged(personId);
}

void PersonsModel::onAddContactToPerson(const QString &contactId, const QString &newPersonId)
{
    Q_D(PersonsModel);

    const QString oldPersonId = personIdForContact(contactId);
    d->contactToPersons.insert(contactId, newPersonId);

    //get contact already in the model, remove it from the previous contact
    const KABC::Addressee &contact = d->metacontacts[oldPersonId].contact(contactId);
    int contactPosition = d->metacontacts[oldPersonId].contacts().indexOf(contact);
    beginRemoveRows(index(d->personIds.indexOf(oldPersonId), 0), contactPosition, contactPosition);
    d->metacontacts[oldPersonId].removeContact(contactId);
    endRemoveRows();

    if (!d->metacontacts[oldPersonId].isValid()) {
        removePerson(oldPersonId);
    } else {
        personChanged(oldPersonId);
    }

    //if the new person is already in the model, add the contact to it
    if (d->personIds.contains(newPersonId)) {
        int newContactPos = d->metacontacts[newPersonId].contacts().size();
        beginInsertRows(index(d->personIds.indexOf(newPersonId), 0), newContactPos, newContactPos);
        d->metacontacts[newPersonId].insertContact(contactId, contact);
        endInsertRows();
        personChanged(newPersonId);
    } else { //if the person is not in the model, create a new person and insert it
        KABC::Addressee::Map contacts;
        contacts[contactId] = contact;
        addPerson(MetaContact(newPersonId, contacts));
    }
}

void PersonsModel::onRemoveContactsFromPerson(const QString &contactId)
{
    Q_D(PersonsModel);

    const QString personId = personIdForContact(contactId);
    const KABC::Addressee &contact = d->metacontacts[personId].contact(contactId);
    d->metacontacts[personId].removeContact(contactId);
    d->contactToPersons.remove(contactId);

    //if we don't want the person object anymore
    if (!d->metacontacts[personId].isValid()) {
        removePerson(personId);
    } else {
        personChanged(personId);
    }

    //now re-insert as a new contact
    //we know it's not part of a metacontact anymore so reinsert as a contact
    addPerson(MetaContact(contactId, contact));
}

void PersonsModel::addPerson(const KPeople::MetaContact &mc)
{
    Q_D(PersonsModel);

    const QString &id = mc.id();

    beginInsertRows(QModelIndex(), d->personIds.size(), d->personIds.size());
    d->metacontacts[id] = mc;
    d->personIds << id;
    endInsertRows();
}

void PersonsModel::removePerson(const QString& id)
{
    Q_D(PersonsModel);

    int row = d->personIds.indexOf(id);
    if (row < 0) { //item not found
        return;
    }

    beginRemoveRows(QModelIndex(), row, row);
    d->metacontacts.remove(id);
    d->personIds.removeOne(id);
    endRemoveRows();
}

void PersonsModel::personChanged(const QString &personId)
{
    Q_D(const PersonsModel);
    int row = d->personIds.indexOf(personId);
    if (row >= 0) {
        const QModelIndex personIndex = index(row);
        dataChanged(personIndex, personIndex);
    }
}

QString PersonsModel::personIdForContact(const QString &contactId) const
{
    Q_D(const PersonsModel);
    //TODO optimise with constFind()
    if (d->contactToPersons.contains(contactId)) {
        return d->contactToPersons[contactId];
    } else {
        return contactId;
    }
}

<|endoftext|>


<commit_before>#ifndef buffer_hh_INCLUDED
#define buffer_hh_INCLUDED

#include <string>
#include <vector>
#include <list>
#include <memory>

#include "line_and_column.hh"

namespace Kakoune
{

class Buffer;
class Window;

typedef int      BufferPos;
typedef int      BufferSize;
typedef char     BufferChar;
typedef std::basic_string<BufferChar> BufferString;

struct BufferCoord : LineAndColumn<BufferCoord>
{
    BufferCoord(int line = 0, int column = 0)
        : LineAndColumn(line, column) {}
};

class BufferIterator
{
public:
    typedef BufferChar value_type;
    typedef BufferSize difference_type;
    typedef const value_type* pointer;
    typedef const value_type& reference;
    typedef std::bidirectional_iterator_tag iterator_category;

    BufferIterator() : m_buffer(NULL), m_position(0) {}
    BufferIterator(const Buffer& buffer, BufferPos position);
    BufferIterator& operator=(const BufferIterator& iterator);

    bool operator== (const BufferIterator& iterator) const;
    bool operator!= (const BufferIterator& iterator) const;
    bool operator<  (const BufferIterator& iterator) const;
    bool operator<= (const BufferIterator& iterator) const;
    bool operator>  (const BufferIterator& iterator) const;
    bool operator>= (const BufferIterator& iterator) const;

    BufferChar operator* () const;
    BufferSize operator- (const BufferIterator& iterator) const;

    BufferIterator operator+ (BufferSize size) const;
    BufferIterator operator- (BufferSize size) const;

    BufferIterator& operator+= (BufferSize size);
    BufferIterator& operator-= (BufferSize size);

    BufferIterator& operator++ ();
    BufferIterator& operator-- ();

    bool is_begin() const;
    bool is_end() const;

    const Buffer& buffer() const;

private:
    const Buffer* m_buffer;
    BufferPos     m_position;
    friend class Buffer;
};

class Buffer
{
public:
    enum class Type
    {
        File,
        Scratch
    };

    Buffer(const std::string& name, Type type,
           const BufferString& initial_content = "");

    void           begin_undo_group();
    void           end_undo_group();

    bool           undo();
    bool           redo();

    void           erase(const BufferIterator& begin,
                         const BufferIterator& end);

    void           insert(const BufferIterator& position,
                          const BufferString& string);

    BufferString   string(const BufferIterator& begin,
                          const BufferIterator& end) const;

    BufferIterator begin() const;
    BufferIterator end() const;
    BufferSize     length() const;
    BufferSize     line_count() const;

    BufferIterator iterator_at(const BufferCoord& line_and_column) const;
    BufferCoord    line_and_column_at(const BufferIterator& iterator) const;

    BufferCoord     clamp(const BufferCoord& line_and_column) const;

    const std::string& name() const { return m_name; }

    const BufferString& content() const { return m_content; }

    Window* get_or_create_window();
    void delete_window(Window* window);

    bool is_modified() const;
    Type type() const { return m_type; }
    void notify_saved();

private:
    BufferChar at(BufferPos position) const;

    void       do_erase(const BufferIterator& begin,
                        const BufferIterator& end);

    void       do_insert(const BufferIterator& position,
                         const BufferString& string);

    friend class BufferIterator;

    std::vector<BufferPos> m_lines;

    void compute_lines();
    BufferPos line_at(const BufferIterator& iterator) const;
    BufferSize line_length(BufferPos line) const;

    BufferString m_content;

    std::string  m_name;
    const Type   m_type;

    struct Modification
    {
        enum Type { Insert, Erase };

        Type           type;
        BufferIterator position;
        BufferString   content;

        Modification(Type type, BufferIterator position, BufferString content)
            : type(type), position(position), content(content) {}

        Modification inverse() const;
    };
    typedef std::vector<Modification> UndoGroup;

    std::vector<UndoGroup>           m_history;
    std::vector<UndoGroup>::iterator m_history_cursor;
    UndoGroup                        m_current_undo_group;

    void replay_modification(const Modification& modification);
    void revert_modification(const Modification& modification);

    void append_modification(Modification&& modification);

    std::list<std::unique_ptr<Window>> m_windows;

    std::vector<UndoGroup>::iterator m_last_save_undo_group;
};

}

#endif // buffer_hh_INCLUDED
<commit_msg>BufferCoord: allow explicit construction from all LineAndColumns<commit_after>#ifndef buffer_hh_INCLUDED
#define buffer_hh_INCLUDED

#include <string>
#include <vector>
#include <list>
#include <memory>

#include "line_and_column.hh"

namespace Kakoune
{

class Buffer;
class Window;

typedef int      BufferPos;
typedef int      BufferSize;
typedef char     BufferChar;
typedef std::basic_string<BufferChar> BufferString;

struct BufferCoord : LineAndColumn<BufferCoord>
{
    BufferCoord(int line = 0, int column = 0)
        : LineAndColumn(line, column) {}

    template<typename T>
    explicit BufferCoord(const LineAndColumn<T>& other)
        : LineAndColumn(other.line, other.column)
    {
    }
};

class BufferIterator
{
public:
    typedef BufferChar value_type;
    typedef BufferSize difference_type;
    typedef const value_type* pointer;
    typedef const value_type& reference;
    typedef std::bidirectional_iterator_tag iterator_category;

    BufferIterator() : m_buffer(NULL), m_position(0) {}
    BufferIterator(const Buffer& buffer, BufferPos position);
    BufferIterator& operator=(const BufferIterator& iterator);

    bool operator== (const BufferIterator& iterator) const;
    bool operator!= (const BufferIterator& iterator) const;
    bool operator<  (const BufferIterator& iterator) const;
    bool operator<= (const BufferIterator& iterator) const;
    bool operator>  (const BufferIterator& iterator) const;
    bool operator>= (const BufferIterator& iterator) const;

    BufferChar operator* () const;
    BufferSize operator- (const BufferIterator& iterator) const;

    BufferIterator operator+ (BufferSize size) const;
    BufferIterator operator- (BufferSize size) const;

    BufferIterator& operator+= (BufferSize size);
    BufferIterator& operator-= (BufferSize size);

    BufferIterator& operator++ ();
    BufferIterator& operator-- ();

    bool is_begin() const;
    bool is_end() const;

    const Buffer& buffer() const;

private:
    const Buffer* m_buffer;
    BufferPos     m_position;
    friend class Buffer;
};

class Buffer
{
public:
    enum class Type
    {
        File,
        Scratch
    };

    Buffer(const std::string& name, Type type,
           const BufferString& initial_content = "");

    void           begin_undo_group();
    void           end_undo_group();

    bool           undo();
    bool           redo();

    void           erase(const BufferIterator& begin,
                         const BufferIterator& end);

    void           insert(const BufferIterator& position,
                          const BufferString& string);

    BufferString   string(const BufferIterator& begin,
                          const BufferIterator& end) const;

    BufferIterator begin() const;
    BufferIterator end() const;
    BufferSize     length() const;
    BufferSize     line_count() const;

    BufferIterator iterator_at(const BufferCoord& line_and_column) const;
    BufferCoord    line_and_column_at(const BufferIterator& iterator) const;

    BufferCoord     clamp(const BufferCoord& line_and_column) const;

    const std::string& name() const { return m_name; }

    const BufferString& content() const { return m_content; }

    Window* get_or_create_window();
    void delete_window(Window* window);

    bool is_modified() const;
    Type type() const { return m_type; }
    void notify_saved();

private:
    BufferChar at(BufferPos position) const;

    void       do_erase(const BufferIterator& begin,
                        const BufferIterator& end);

    void       do_insert(const BufferIterator& position,
                         const BufferString& string);

    friend class BufferIterator;

    std::vector<BufferPos> m_lines;

    void compute_lines();
    BufferPos line_at(const BufferIterator& iterator) const;
    BufferSize line_length(BufferPos line) const;

    BufferString m_content;

    std::string  m_name;
    const Type   m_type;

    struct Modification
    {
        enum Type { Insert, Erase };

        Type           type;
        BufferIterator position;
        BufferString   content;

        Modification(Type type, BufferIterator position, BufferString content)
            : type(type), position(position), content(content) {}

        Modification inverse() const;
    };
    typedef std::vector<Modification> UndoGroup;

    std::vector<UndoGroup>           m_history;
    std::vector<UndoGroup>::iterator m_history_cursor;
    UndoGroup                        m_current_undo_group;

    void replay_modification(const Modification& modification);
    void revert_modification(const Modification& modification);

    void append_modification(Modification&& modification);

    std::list<std::unique_ptr<Window>> m_windows;

    std::vector<UndoGroup>::iterator m_last_save_undo_group;
};

}

#endif // buffer_hh_INCLUDED
<|endoftext|>


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

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

#include <ctype.h> // don't ask. msdev breaks otherwise...
#include <canvas/debug.hxx>
#include <canvas/verbosetrace.hxx>
#include <canvas/canvastools.hxx>
#include <tools/diagnose_ex.h>

#include <osl/mutex.hxx>

#include <com/sun/star/awt/XWindow.hpp>
#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
#include <com/sun/star/registry/XRegistryKey.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/lang/NoSupportException.hpp>

#include <toolkit/helper/vclunohelper.hxx>
#include <cppuhelper/factory.hxx>
#include <cppuhelper/implementationentry.hxx>
#include <comphelper/servicedecl.hxx>

#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/tools/canvastools.hxx>
#include <basegfx/numeric/ftools.hxx>

#include "dx_graphicsprovider.hxx"
#include "dx_winstuff.hxx"
#include "dx_canvas.hxx"

#include <vcl/sysdata.hxx>

#define CANVAS_TECH "GDI+"
#define CANVAS_SERVICE_NAME              "com.sun.star.rendering.Canvas."            CANVAS_TECH
#define CANVAS_IMPLEMENTATION_NAME       "com.sun.star.comp.rendering.Canvas."       CANVAS_TECH
#define BITMAPCANVAS_SERVICE_NAME        "com.sun.star.rendering.BitmapCanvas."      CANVAS_TECH
#define BITMAPCANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.BitmapCanvas." CANVAS_TECH

using namespace ::com::sun::star;

namespace dxcanvas
{
    /// Actual canonical implementation of the GraphicsProvider interface
    class GraphicsProviderImpl : public GraphicsProvider
    {
        GraphicsSharedPtr mpGraphics;
    public:
        explicit GraphicsProviderImpl( Gdiplus::Graphics* pGraphics ) : mpGraphics( pGraphics ) {}
        virtual GraphicsSharedPtr getGraphics() { return mpGraphics; }
    };

    Canvas::Canvas( const uno::Sequence< uno::Any >&                aArguments,
                    const uno::Reference< uno::XComponentContext >& rxContext ) :
        maArguments(aArguments),
        mxComponentContext( rxContext )
    {
    }

    void Canvas::initialize()
    {
        // #i64742# Only perform initialization when not in probe mode
        if( maArguments.getLength() == 0 )
            return;

        VERBOSE_TRACE( "Canvas::initialize called" );

        // At index 1, we expect a HWND handle here, containing a
        // pointer to a valid window, on which to output
        // At index 2, we expect the current window bound rect
        ENSURE_ARG_OR_THROW( maArguments.getLength() >= 6 &&
                             maArguments[5].getValueTypeClass() == uno::TypeClass_SEQUENCE,
                             "SpriteCanvas::initialize: wrong number of arguments, or wrong types" );

        uno::Sequence<sal_Int8> aSeq;
        maArguments[5] >>= aSeq;

        const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
        if( !pSysData || !pSysData->hDC )
            throw lang::NoSupportException(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                     "Passed SystemGraphicsData or HDC invalid!")),
                NULL);

        // setup helper
        maDeviceHelper.init( pSysData->hDC,
                             *this );
        maCanvasHelper.setDevice( *this );
        maCanvasHelper.setTarget(
            GraphicsProviderSharedPtr(
                new GraphicsProviderImpl(
                    Gdiplus::Graphics::FromHDC(pSysData->hDC))));

        maArguments.realloc(0);
    }

    void SAL_CALL Canvas::disposing()
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        mxComponentContext.clear();

        // forward to parent
        CanvasBaseT::disposing();
    }

    ::rtl::OUString SAL_CALL Canvas::getServiceName(  ) throw (uno::RuntimeException)
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CANVAS_SERVICE_NAME ) );
    }

    BitmapCanvas::BitmapCanvas( const uno::Sequence< uno::Any >&                aArguments,
                                const uno::Reference< uno::XComponentContext >& rxContext ) :
        maArguments(aArguments),
        mxComponentContext( rxContext ),
        mpTarget()
    {
    }

    void BitmapCanvas::initialize()
    {
        // #i64742# Only perform initialization when not in probe mode
        if( maArguments.getLength() == 0 )
            return;

        VERBOSE_TRACE( "BitmapCanvas::initialize called" );

        // At index 1, we expect a HWND handle here, containing a
        // pointer to a valid window, on which to output
        // At index 2, we expect the current window bound rect
        ENSURE_ARG_OR_THROW( maArguments.getLength() >= 6 &&
                             maArguments[5].getValueTypeClass() == uno::TypeClass_SEQUENCE,
                             "SpriteCanvas::initialize: wrong number of arguments, or wrong types" );

        uno::Sequence<sal_Int8> aSeq;
        maArguments[5] >>= aSeq;

        const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
        if( !pSysData || !pSysData->hDC )
            throw lang::NoSupportException(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                     "Passed SystemGraphicsData or HDC invalid!")),
                NULL);

        // setup helper
        maDeviceHelper.init( pSysData->hDC,
                             *this );
        maCanvasHelper.setDevice( *this );

        // check whether we can actually provide a BitmapCanvas
        // here. for this, check whether the HDC has a bitmap
        // selected.
        HBITMAP hBmp;
        if( !(hBmp=(HBITMAP)GetCurrentObject(pSysData->hDC,
                                             OBJ_BITMAP)) ||
            GetObjectType(pSysData->hDC) != OBJ_MEMDC )
        {
            throw lang::NoSupportException(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                     "Passed HDC is no mem DC/has no bitmap selected!")),
                NULL);
        }

        mpTarget.reset( new DXBitmap(
                            BitmapSharedPtr(
                                Gdiplus::Bitmap::FromHBITMAP(
                                    hBmp, 0) ),
                            false ));

        maCanvasHelper.setTarget( mpTarget );

        maArguments.realloc(0);
    }

    void SAL_CALL BitmapCanvas::disposing()
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        mpTarget.reset();
        mxComponentContext.clear();

        // forward to parent
        BitmapCanvasBaseT::disposing();
    }

    ::rtl::OUString SAL_CALL BitmapCanvas::getServiceName(  ) throw (uno::RuntimeException)
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( BITMAPCANVAS_SERVICE_NAME ) );
    }

    IBitmapSharedPtr BitmapCanvas::getBitmap() const
    {
        return mpTarget;
    }

    static uno::Reference<uno::XInterface> initCanvas( Canvas* pCanvas )
    {
        uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
        pCanvas->initialize();
        return xRet;
    }

    namespace sdecl = comphelper::service_decl;
    sdecl::class_<Canvas, sdecl::with_args<true> > serviceImpl1(&initCanvas);
    const sdecl::ServiceDecl dxCanvasDecl(
        serviceImpl1,
        CANVAS_IMPLEMENTATION_NAME,
        CANVAS_SERVICE_NAME );

    static uno::Reference<uno::XInterface> initBitmapCanvas( BitmapCanvas* pCanvas )
    {
        uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
        pCanvas->initialize();
        return xRet;
    }

    namespace sdecl = comphelper::service_decl;
    sdecl::class_<BitmapCanvas, sdecl::with_args<true> > serviceImpl2(&initBitmapCanvas);
    const sdecl::ServiceDecl dxBitmapCanvasDecl(
        serviceImpl2,
        BITMAPCANVAS_IMPLEMENTATION_NAME,
        BITMAPCANVAS_SERVICE_NAME );
}

// The C shared lib entry points
COMPHELPER_SERVICEDECL_EXPORTS2(dxcanvas::dxCanvasDecl,
                                dxcanvas::dxBitmapCanvasDecl);
<commit_msg>#i10000# warning fixed<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dx_canvas.cxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

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

#include <ctype.h> // don't ask. msdev breaks otherwise...
#include <canvas/debug.hxx>
#include <canvas/verbosetrace.hxx>
#include <canvas/canvastools.hxx>
#include <tools/diagnose_ex.h>

#include <osl/mutex.hxx>

#include <com/sun/star/awt/XWindow.hpp>
#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
#include <com/sun/star/registry/XRegistryKey.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/lang/NoSupportException.hpp>

#include <toolkit/helper/vclunohelper.hxx>
#include <cppuhelper/factory.hxx>
#include <cppuhelper/implementationentry.hxx>
#include <comphelper/servicedecl.hxx>

#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/tools/canvastools.hxx>
#include <basegfx/numeric/ftools.hxx>

#include "dx_graphicsprovider.hxx"
#include "dx_winstuff.hxx"
#include "dx_canvas.hxx"

#include <vcl/sysdata.hxx>

#define CANVAS_TECH "GDI+"
#define CANVAS_SERVICE_NAME              "com.sun.star.rendering.Canvas."            CANVAS_TECH
#define CANVAS_IMPLEMENTATION_NAME       "com.sun.star.comp.rendering.Canvas."       CANVAS_TECH
#define BITMAPCANVAS_SERVICE_NAME        "com.sun.star.rendering.BitmapCanvas."      CANVAS_TECH
#define BITMAPCANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.BitmapCanvas." CANVAS_TECH

using namespace ::com::sun::star;

namespace dxcanvas
{
    /// Actual canonical implementation of the GraphicsProvider interface
    class GraphicsProviderImpl : public GraphicsProvider
    {
        GraphicsSharedPtr mpGraphics;
    public:
        explicit GraphicsProviderImpl( Gdiplus::Graphics* pGraphics ) : mpGraphics( pGraphics ) {}
        virtual GraphicsSharedPtr getGraphics() { return mpGraphics; }
    };

    Canvas::Canvas( const uno::Sequence< uno::Any >&                aArguments,
                    const uno::Reference< uno::XComponentContext >& rxContext ) :
        maArguments(aArguments),
        mxComponentContext( rxContext )
    {
    }

    void Canvas::initialize()
    {
        // #i64742# Only perform initialization when not in probe mode
        if( maArguments.getLength() == 0 )
            return;

        VERBOSE_TRACE( "Canvas::initialize called" );

        // At index 1, we expect a HWND handle here, containing a
        // pointer to a valid window, on which to output
        // At index 2, we expect the current window bound rect
        ENSURE_ARG_OR_THROW( maArguments.getLength() >= 6 &&
                             maArguments[5].getValueTypeClass() == uno::TypeClass_SEQUENCE,
                             "SpriteCanvas::initialize: wrong number of arguments, or wrong types" );

        uno::Sequence<sal_Int8> aSeq;
        maArguments[5] >>= aSeq;

        const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
        if( !pSysData || !pSysData->hDC )
            throw lang::NoSupportException(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                     "Passed SystemGraphicsData or HDC invalid!")),
                NULL);

        // setup helper
        maDeviceHelper.init( pSysData->hDC,
                             *this );
        maCanvasHelper.setDevice( *this );
        maCanvasHelper.setTarget(
            GraphicsProviderSharedPtr(
                new GraphicsProviderImpl(
                    Gdiplus::Graphics::FromHDC(pSysData->hDC))));

        maArguments.realloc(0);
    }

    void SAL_CALL Canvas::disposing()
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        mxComponentContext.clear();

        // forward to parent
        CanvasBaseT::disposing();
    }

    ::rtl::OUString SAL_CALL Canvas::getServiceName(  ) throw (uno::RuntimeException)
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CANVAS_SERVICE_NAME ) );
    }

    BitmapCanvas::BitmapCanvas( const uno::Sequence< uno::Any >&                aArguments,
                                const uno::Reference< uno::XComponentContext >& rxContext ) :
        maArguments(aArguments),
        mxComponentContext( rxContext ),
        mpTarget()
    {
    }

    void BitmapCanvas::initialize()
    {
        // #i64742# Only perform initialization when not in probe mode
        if( maArguments.getLength() == 0 )
            return;

        VERBOSE_TRACE( "BitmapCanvas::initialize called" );

        // At index 1, we expect a HWND handle here, containing a
        // pointer to a valid window, on which to output
        // At index 2, we expect the current window bound rect
        ENSURE_ARG_OR_THROW( maArguments.getLength() >= 6 &&
                             maArguments[5].getValueTypeClass() == uno::TypeClass_SEQUENCE,
                             "SpriteCanvas::initialize: wrong number of arguments, or wrong types" );

        uno::Sequence<sal_Int8> aSeq;
        maArguments[5] >>= aSeq;

        const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
        if( !pSysData || !pSysData->hDC )
            throw lang::NoSupportException(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                     "Passed SystemGraphicsData or HDC invalid!")),
                NULL);

        // setup helper
        maDeviceHelper.init( pSysData->hDC,
                             *this );
        maCanvasHelper.setDevice( *this );

        // check whether we can actually provide a BitmapCanvas
        // here. for this, check whether the HDC has a bitmap
        // selected.
        HBITMAP hBmp;
        hBmp=(HBITMAP)GetCurrentObject(pSysData->hDC, OBJ_BITMAP);
        if( !hBmp || GetObjectType(pSysData->hDC) != OBJ_MEMDC )
        {
            throw lang::NoSupportException(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                     "Passed HDC is no mem DC/has no bitmap selected!")),
                NULL);
        }

        mpTarget.reset( new DXBitmap(
                            BitmapSharedPtr(
                                Gdiplus::Bitmap::FromHBITMAP(
                                    hBmp, 0) ),
                            false ));

        maCanvasHelper.setTarget( mpTarget );

        maArguments.realloc(0);
    }

    void SAL_CALL BitmapCanvas::disposing()
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        mpTarget.reset();
        mxComponentContext.clear();

        // forward to parent
        BitmapCanvasBaseT::disposing();
    }

    ::rtl::OUString SAL_CALL BitmapCanvas::getServiceName(  ) throw (uno::RuntimeException)
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( BITMAPCANVAS_SERVICE_NAME ) );
    }

    IBitmapSharedPtr BitmapCanvas::getBitmap() const
    {
        return mpTarget;
    }

    static uno::Reference<uno::XInterface> initCanvas( Canvas* pCanvas )
    {
        uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
        pCanvas->initialize();
        return xRet;
    }

    namespace sdecl = comphelper::service_decl;
    sdecl::class_<Canvas, sdecl::with_args<true> > serviceImpl1(&initCanvas);
    const sdecl::ServiceDecl dxCanvasDecl(
        serviceImpl1,
        CANVAS_IMPLEMENTATION_NAME,
        CANVAS_SERVICE_NAME );

    static uno::Reference<uno::XInterface> initBitmapCanvas( BitmapCanvas* pCanvas )
    {
        uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
        pCanvas->initialize();
        return xRet;
    }

    namespace sdecl = comphelper::service_decl;
    sdecl::class_<BitmapCanvas, sdecl::with_args<true> > serviceImpl2(&initBitmapCanvas);
    const sdecl::ServiceDecl dxBitmapCanvasDecl(
        serviceImpl2,
        BITMAPCANVAS_IMPLEMENTATION_NAME,
        BITMAPCANVAS_SERVICE_NAME );
}

// The C shared lib entry points
COMPHELPER_SERVICEDECL_EXPORTS2(dxcanvas::dxCanvasDecl,
                                dxcanvas::dxBitmapCanvasDecl);
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: IBM Corporation
 *
 *  Copyright: 2008 by IBM Corporation
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
/*************************************************************************
 * @file
 * Table cell style. Number format, string value, and so on...
 ************************************************************************/
#include "xfcellstyle.hxx"
#include "xfborders.hxx"
#include "xffont.hxx"
#include "xfbgimage.hxx"

XFCellStyle::XFCellStyle()
{
    m_eHoriAlign = enumXFAlignNone;
    m_eVertAlign = enumXFAlignNone;
    m_fTextIndent = 0;
    m_pBorders = NULL;
    m_pBackImage = NULL;
    m_bWrapText = false;
}

XFCellStyle::~XFCellStyle()
{
    if( m_pBorders )
        delete m_pBorders;
}

void XFCellStyle::SetPadding(double left, double right,double top, double bottom)
{
    if( left != -1 )
        m_aPadding.SetLeft(left);
    if( right != -1 )
        m_aPadding.SetRight(right);
    if( top != -1 )
        m_aPadding.SetTop(top);
    if( bottom != -1 )
        m_aPadding.SetBottom( bottom );
}

void    XFCellStyle::SetBackColor(XFColor& color)
{
    m_aBackColor = color;
}

void    XFCellStyle::SetBackImage(XFBGImage *pImage)
{
    if( m_pBackImage )
        delete m_pBackImage;
    m_pBackImage = pImage;
}

void    XFCellStyle::SetBorders(XFBorders *pBorders)
{
    if( m_pBorders )
        delete m_pBorders;
    m_pBorders = pBorders;
}

enumXFStyle XFCellStyle::GetStyleFamily()
{
    return enumXFStyleTableCell;
}

/**
 *Affirm whether two XFCellStyle objects are equal.
 */
bool    XFCellStyle::Equal(IXFStyle *pStyle)
{
    if( this == pStyle )
        return true;
    if( !pStyle || pStyle->GetStyleFamily() != enumXFStyleTableCell )
        return false;

    XFCellStyle *pOther = static_cast<XFCellStyle*>(pStyle);
    if( !pOther )
        return false;

    if( m_strDataStyle != pOther->m_strDataStyle )
        return false;

    if( m_strParentStyleName != pOther->m_strParentStyleName )
        return false;
    if( m_fTextIndent != pOther->m_fTextIndent )
        return false;

    //align:
    if( m_eHoriAlign != pOther->m_eHoriAlign )
        return false;
    if( m_eVertAlign != pOther->m_eVertAlign )
        return false;

    if( m_aBackColor != pOther->m_aBackColor )
        return false;
    //shadow:
    if( m_aShadow != pOther->m_aShadow )
        return false;
    //margin:
    if( m_aMargin != pOther->m_aMargin )
        return false;
    //padding:
    if( m_aPadding != pOther->m_aPadding )
        return false;

    //wrap:
    if( m_bWrapText != pOther->m_bWrapText )
        return false;

    //font:
    if( m_pFont.is() )
    {
        if( !pOther->m_pFont.is() )
            return false;
        if(*m_pFont != *pOther->m_pFont )
            return false;
    }
    else if( pOther->m_pFont.is() )
        return false;

    //border:
    if( m_pBorders )
    {
        if( !pOther->m_pBorders )
            return false;
        if( *m_pBorders != *pOther->m_pBorders )
            return false;
    }
    else if( pOther->m_pBorders )
        return false;

    //if there is backimage
    if( m_pBackImage )
    {
        if( !pOther->m_pBackImage )
            return false;
        if( !m_pBackImage->Equal(pOther) )
            return false;
    }
    else
    {
        if( pOther->m_pBackImage )
            return false;
    }

    return true;
}

void XFCellStyle::ToXml(IXFStream *pStrm)
{
    IXFAttrList *pAttrList = pStrm->GetAttrList();
    OUString style = GetStyleName();

    pAttrList->Clear();
    if( !style.isEmpty() )
        pAttrList->AddAttribute("style:name",GetStyleName());
    if( !GetParentStyleName().isEmpty() )
        pAttrList->AddAttribute("style:parent-style-name",GetParentStyleName());

    pAttrList->AddAttribute("style:family", "table-cell");
    if( !m_strParentStyleName.isEmpty() )
        pAttrList->AddAttribute("style:parent-style-name",m_strParentStyleName);
    if( !m_strDataStyle.isEmpty() )
        pAttrList->AddAttribute( "style:data-style-name", m_strDataStyle );

    pStrm->StartElement("style:style");

    //Paragraph properties:
    pAttrList->Clear();

    //text indent:
    if( m_fTextIndent>FLOAT_MIN )
    {
        pAttrList->AddAttribute("fo:text-indent", OUString::number(m_fTextIndent) + "cm" );
    }
    //padding:
    m_aPadding.ToXml(pStrm);
    //margin:
    m_aMargin.ToXml(pStrm);

    //text horizontal align:
    if( m_eHoriAlign != enumXFAlignNone )
    {
        pAttrList->AddAttribute("fo:text-align", GetAlignName(m_eHoriAlign) );
    }
    //text vertical align
    if( m_eVertAlign != enumXFAlignNone )
        pAttrList->AddAttribute( "fo:vertical-align", GetAlignName(m_eVertAlign) );

    //wrap text:
    if( m_bWrapText )
        pAttrList->AddAttribute( "fo:wrap-option", "wrap" );

    //shadow:
    m_aShadow.ToXml(pStrm);
    //borders:
    if( m_pBorders )
        m_pBorders->ToXml(pStrm);

    //background color:
    if( m_aBackColor.IsValid() && !m_pBackImage )
    {
        pAttrList->AddAttribute("fo:background-color", m_aBackColor.ToString() );
    }
    //Font properties:
    if( m_pFont.is() )
        m_pFont->ToXml(pStrm);

    pStrm->StartElement("style:properties");

    if( m_pBackImage )
        m_pBackImage->ToXml(pStrm);

    pStrm->EndElement("style:properties");

    pStrm->EndElement("style:style");
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#735441 Logically dead code<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: IBM Corporation
 *
 *  Copyright: 2008 by IBM Corporation
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
/*************************************************************************
 * @file
 * Table cell style. Number format, string value, and so on...
 ************************************************************************/
#include "xfcellstyle.hxx"
#include "xfborders.hxx"
#include "xffont.hxx"
#include "xfbgimage.hxx"

XFCellStyle::XFCellStyle()
{
    m_eHoriAlign = enumXFAlignNone;
    m_eVertAlign = enumXFAlignNone;
    m_fTextIndent = 0;
    m_pBorders = NULL;
    m_pBackImage = NULL;
    m_bWrapText = false;
}

XFCellStyle::~XFCellStyle()
{
    if( m_pBorders )
        delete m_pBorders;
}

void XFCellStyle::SetPadding(double left, double right,double top, double bottom)
{
    if( left != -1 )
        m_aPadding.SetLeft(left);
    if( right != -1 )
        m_aPadding.SetRight(right);
    if( top != -1 )
        m_aPadding.SetTop(top);
    if( bottom != -1 )
        m_aPadding.SetBottom( bottom );
}

void    XFCellStyle::SetBackColor(XFColor& color)
{
    m_aBackColor = color;
}

void    XFCellStyle::SetBackImage(XFBGImage *pImage)
{
    if( m_pBackImage )
        delete m_pBackImage;
    m_pBackImage = pImage;
}

void    XFCellStyle::SetBorders(XFBorders *pBorders)
{
    if( m_pBorders )
        delete m_pBorders;
    m_pBorders = pBorders;
}

enumXFStyle XFCellStyle::GetStyleFamily()
{
    return enumXFStyleTableCell;
}

/**
 *Affirm whether two XFCellStyle objects are equal.
 */
bool    XFCellStyle::Equal(IXFStyle *pStyle)
{
    if( this == pStyle )
        return true;
    if( !pStyle || pStyle->GetStyleFamily() != enumXFStyleTableCell )
        return false;

    XFCellStyle *pOther = dynamic_cast<XFCellStyle*>(pStyle);
    if( !pOther )
        return false;

    if( m_strDataStyle != pOther->m_strDataStyle )
        return false;

    if( m_strParentStyleName != pOther->m_strParentStyleName )
        return false;
    if( m_fTextIndent != pOther->m_fTextIndent )
        return false;

    //align:
    if( m_eHoriAlign != pOther->m_eHoriAlign )
        return false;
    if( m_eVertAlign != pOther->m_eVertAlign )
        return false;

    if( m_aBackColor != pOther->m_aBackColor )
        return false;
    //shadow:
    if( m_aShadow != pOther->m_aShadow )
        return false;
    //margin:
    if( m_aMargin != pOther->m_aMargin )
        return false;
    //padding:
    if( m_aPadding != pOther->m_aPadding )
        return false;

    //wrap:
    if( m_bWrapText != pOther->m_bWrapText )
        return false;

    //font:
    if( m_pFont.is() )
    {
        if( !pOther->m_pFont.is() )
            return false;
        if(*m_pFont != *pOther->m_pFont )
            return false;
    }
    else if( pOther->m_pFont.is() )
        return false;

    //border:
    if( m_pBorders )
    {
        if( !pOther->m_pBorders )
            return false;
        if( *m_pBorders != *pOther->m_pBorders )
            return false;
    }
    else if( pOther->m_pBorders )
        return false;

    //if there is backimage
    if( m_pBackImage )
    {
        if( !pOther->m_pBackImage )
            return false;
        if( !m_pBackImage->Equal(pOther) )
            return false;
    }
    else
    {
        if( pOther->m_pBackImage )
            return false;
    }

    return true;
}

void XFCellStyle::ToXml(IXFStream *pStrm)
{
    IXFAttrList *pAttrList = pStrm->GetAttrList();
    OUString style = GetStyleName();

    pAttrList->Clear();
    if( !style.isEmpty() )
        pAttrList->AddAttribute("style:name",GetStyleName());
    if( !GetParentStyleName().isEmpty() )
        pAttrList->AddAttribute("style:parent-style-name",GetParentStyleName());

    pAttrList->AddAttribute("style:family", "table-cell");
    if( !m_strParentStyleName.isEmpty() )
        pAttrList->AddAttribute("style:parent-style-name",m_strParentStyleName);
    if( !m_strDataStyle.isEmpty() )
        pAttrList->AddAttribute( "style:data-style-name", m_strDataStyle );

    pStrm->StartElement("style:style");

    //Paragraph properties:
    pAttrList->Clear();

    //text indent:
    if( m_fTextIndent>FLOAT_MIN )
    {
        pAttrList->AddAttribute("fo:text-indent", OUString::number(m_fTextIndent) + "cm" );
    }
    //padding:
    m_aPadding.ToXml(pStrm);
    //margin:
    m_aMargin.ToXml(pStrm);

    //text horizontal align:
    if( m_eHoriAlign != enumXFAlignNone )
    {
        pAttrList->AddAttribute("fo:text-align", GetAlignName(m_eHoriAlign) );
    }
    //text vertical align
    if( m_eVertAlign != enumXFAlignNone )
        pAttrList->AddAttribute( "fo:vertical-align", GetAlignName(m_eVertAlign) );

    //wrap text:
    if( m_bWrapText )
        pAttrList->AddAttribute( "fo:wrap-option", "wrap" );

    //shadow:
    m_aShadow.ToXml(pStrm);
    //borders:
    if( m_pBorders )
        m_pBorders->ToXml(pStrm);

    //background color:
    if( m_aBackColor.IsValid() && !m_pBackImage )
    {
        pAttrList->AddAttribute("fo:background-color", m_aBackColor.ToString() );
    }
    //Font properties:
    if( m_pFont.is() )
        m_pFont->ToXml(pStrm);

    pStrm->StartElement("style:properties");

    if( m_pBackImage )
        m_pBackImage->ToXml(pStrm);

    pStrm->EndElement("style:properties");

    pStrm->EndElement("style:style");
}

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


<commit_before>/*
     This file is part of libhttpserver
     Copyright (C) 2011, 2012, 2013, 2014, 2015 Sebastiano Merlino

     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public
     License as published by the Free Software Foundation; either
     version 2.1 of the License, or (at your option) any later version.

     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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
     USA
*/

#if !defined (_HTTPSERVER_HPP_INSIDE_) && !defined (HTTPSERVER_COMPILATION)
#error "Only <httpserver.hpp> or <httpserverpp> can be included directly."
#endif

#ifndef _HTTP_RESPONSE_PTR_HPP_
#define _HTTP_RESPONSE_PTR_HPP_

#include "http_response.hpp"

#if defined(__CLANG_ATOMICS)

#define atomic_increment(object) \
    __c11_atomicadd_fetch(object, 1, __ATOMIC_RELAXED)

#define atomic_decrement(object) \
    __c11_atomic_sub_fetch(object, 1, __ATOMIC_ACQ_REL)

#elif defined(__GNUC_ATOMICS)

#define atomic_increment(object) \
    __atomic_add_fetch(object, 1, __ATOMIC_RELAXED)

#define atomic_decrement(object) \
    __atomic_sub_fetch(object, 1, __ATOMIC_ACQ_REL)

#else

#define atomic_increment(object) \
    __sync_add_and_fetch(object, 1)

#define atomic_decrement(object) \
    __sync_sub_and_fetch(object, 1)

#endif

namespace httpserver
{

class webserver;

namespace details
{

struct http_response_ptr
{
    public:
        http_response_ptr(http_response* res = 0x0):
            res(res)
        {
            num_references = new int(1);
        }

        http_response_ptr(const http_response_ptr& b):
            res(b.res),
            num_references(b.num_references)
        {
            atomic_increment(b.num_references);
        }

        ~http_response_ptr()
        {
            if (atomic_decrement(num_references) != 0 || res == 0x0) return;

            delete res;
            delete num_references;

            res = 0x0;
            num_references = 0x0;
        }

        http_response_ptr& operator=(http_response_ptr b)
        {
            using std::swap;

            swap(this->num_references, b.num_references);
            swap(this->res, b.res);

            return *this;
        }

        http_response& operator* ()
        {
            return *res;
        }

        http_response* operator-> ()
        {
            return res;
        }

        http_response* ptr()
        {
            return res;
        }

    private:
        http_response* res;
        int* num_references;
        friend class ::httpserver::webserver;
};

} //details
} //httpserver

#endif //_HTTP_RESPONSE_PTR_HPP_
<commit_msg>Fixed memory leak in http_response_ptr<commit_after>/*
     This file is part of libhttpserver
     Copyright (C) 2011, 2012, 2013, 2014, 2015 Sebastiano Merlino

     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public
     License as published by the Free Software Foundation; either
     version 2.1 of the License, or (at your option) any later version.

     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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
     USA
*/

#if !defined (_HTTPSERVER_HPP_INSIDE_) && !defined (HTTPSERVER_COMPILATION)
#error "Only <httpserver.hpp> or <httpserverpp> can be included directly."
#endif

#ifndef _HTTP_RESPONSE_PTR_HPP_
#define _HTTP_RESPONSE_PTR_HPP_

#include "http_response.hpp"

#if defined(__CLANG_ATOMICS)

#define atomic_increment(object) \
    __c11_atomicadd_fetch(object, 1, __ATOMIC_RELAXED)

#define atomic_decrement(object) \
    __c11_atomic_sub_fetch(object, 1, __ATOMIC_ACQ_REL)

#elif defined(__GNUC_ATOMICS)

#define atomic_increment(object) \
    __atomic_add_fetch(object, 1, __ATOMIC_RELAXED)

#define atomic_decrement(object) \
    __atomic_sub_fetch(object, 1, __ATOMIC_ACQ_REL)

#else

#define atomic_increment(object) \
    __sync_add_and_fetch(object, 1)

#define atomic_decrement(object) \
    __sync_sub_and_fetch(object, 1)

#endif

namespace httpserver
{

class webserver;

namespace details
{

struct http_response_ptr
{
    public:
        http_response_ptr(http_response* res = 0x0):
            res(res)
        {
            num_references = new int(1);
        }

        http_response_ptr(const http_response_ptr& b):
            res(b.res),
            num_references(b.num_references)
        {
            atomic_increment(b.num_references);
        }

        ~http_response_ptr()
        {
            if (atomic_decrement(num_references) != 0) return;

            if (res != 0x0) delete res;
            if (num_references != 0x0) delete num_references;

            res = 0x0;
            num_references = 0x0;
        }

        http_response_ptr& operator=(http_response_ptr b)
        {
            using std::swap;

            swap(this->num_references, b.num_references);
            swap(this->res, b.res);

            return *this;
        }

        http_response& operator* ()
        {
            return *res;
        }

        http_response* operator-> ()
        {
            return res;
        }

        http_response* ptr()
        {
            return res;
        }

    private:
        http_response* res;
        int* num_references;
        friend class ::httpserver::webserver;
};

} //details
} //httpserver

#endif //_HTTP_RESPONSE_PTR_HPP_
<|endoftext|>


<commit_before>// -*- Mode: c++ -*-

#pragma once

// Do not use <cstring> for kext
#include <stdint.h>
#include <string.h>

namespace pqrs {
class karabiner_virtual_hid_device final {
public:
  class hid_report final {
  public:
    class __attribute__((packed)) keyboard_input final {
    public:
      keyboard_input(void) : modifiers(0), reserved(0), keys{} {}
      bool operator==(const hid_report::keyboard_input& other) const { return (memcmp(this, &other, sizeof(*this)) == 0); }
      bool operator!=(const hid_report::keyboard_input& other) const { return !(*this == other); }

      uint8_t modifiers;
      uint8_t reserved;
      uint8_t keys[6];

      // modifiers:
      //   0x1 << 0 : left control
      //   0x1 << 1 : left shift
      //   0x1 << 2 : left option
      //   0x1 << 3 : left command
      //   0x1 << 4 : right control
      //   0x1 << 5 : right shift
      //   0x1 << 6 : right option
      //   0x1 << 7 : right command
    };

    class __attribute__((packed)) pointing_input final {
    public:
      pointing_input(void)
          : buttons{}, x(0), y(0), vertical_wheel(0), horizontal_wheel(0) {}

      uint8_t buttons[4]; // 32 bits for each button (32 buttons)
      uint8_t x;
      uint8_t y;
      uint8_t vertical_wheel;
      uint8_t horizontal_wheel;

      // buttons[0] = (0x1 << 0) -> button 1
      // buttons[0] = (0x1 << 1) -> button 2
      // buttons[0] = (0x1 << 2) -> button 3
      // ...
      // buttons[1] = (0x1 << 0) -> button 9
      // ...
      // buttons[2] = (0x1 << 0) -> button 17
      // ...
      // buttons[3] = (0x1 << 0) -> button 25
    };
  };

  enum class event_type : uint32_t {
    key_down = 10,
    key_up = 11,
    flags_changed = 12,
  };

  class __attribute__((packed)) keyboard_event final {
  public:
    keyboard_event(void) : event_type(event_type::key_down),
                           flags(0),
                           key(0),
                           char_code(0),
                           char_set(0),
                           orig_char_code(0),
                           orig_char_set(0),
                           keyboard_type(0),
                           repeat(false) {}

    event_type event_type;
    uint32_t flags;
    uint32_t key;
    uint32_t char_code;
    uint32_t char_set;
    uint32_t orig_char_code;
    uint32_t orig_char_set;
    uint32_t keyboard_type;
    bool repeat;
  };

  class __attribute__((packed)) keyboard_special_event final {
  public:
    keyboard_special_event(void) : event_type(event_type::key_down),
                                   flags(0),
                                   key(0),
                                   flavor(0),
                                   guid(0),
                                   repeat(false) {}

    event_type event_type;
    uint32_t flags;
    uint32_t key;
    uint32_t flavor;
    uint64_t guid;
    bool repeat;
  };

  enum class user_client_method {
    // VirtualHIDKeyboard
    initialize_virtual_hid_keyboard,
    terminate_virtual_hid_keyboard,
    post_keyboard_input_report,
    reset_virtual_hid_keyboard,

    // VirtualHIDPointing
    initialize_virtual_hid_pointing,
    terminate_virtual_hid_pointing,
    post_pointing_input_report,
    reset_virtual_hid_pointing,

    // IOHIDSystem (since macOS 10.12)
    post_keyboard_event,
    post_keyboard_special_event,
    update_event_flags,

    end_,
  };

  static const char* get_virtual_hid_root_name(void) {
    return "org_pqrs_driver_Karabiner_VirtualHIDDevice_VirtualHIDRoot_v020900";
  }
};
}
<commit_msg>remove ignored file<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2016 Hewlett Packard Enterprise Development LP
 *
 * Licensed 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.
 */
#include "interface/standard/MessageReassembler.h"

#include <cassert>
#include <cstdio>

namespace Standard {

MessageReassembler::MessageReassembler(const std::string& _name,
                                       const Component* _parent)
    : Component(_name, _parent) {}

MessageReassembler::~MessageReassembler() {}

Message* MessageReassembler::receivePacket(Packet* _packet) {
  // get the message and determine unqiue id
  Message* message = _packet->message();
  u32 sourceId = message->getSourceId();
  u32 messageId = message->id();
  u64 mid = ((u64)sourceId) << 32 | ((u64)messageId);

  // if non-existent, add a new table entry
  bool midExists = messages_.count(mid) == 1;
  if (!midExists) {
    messages_[mid] = MessageData();
    messages_[mid].message = message;
    messages_[mid].packetsReceived.resize(message->numPackets(), false);
    messages_[mid].receivedCount = 0;
  }

  // retrieve the message data
  MessageData& messageData = messages_.at(mid);
  assert(messageData.message == message);

  // mark the packet as received
  assert(messageData.packetsReceived.at(_packet->id()) == false);
  messageData.packetsReceived.at(_packet->id()) = true;
  messageData.receivedCount++;

  // check if the full message has been received
  if (messageData.receivedCount == message->numPackets()) {
    // remove the message from the map
    s32 erased = messages_.erase(mid);
    (void)erased;  // unused
    assert(erased == 1);
    return message;
  } else {
    // return nullptr to signify more packets are needed for the message
    return nullptr;
  }
}

}  // namespace Standard
<commit_msg>fixed unique message ID bug in MessageReassembler<commit_after>/*
 * Copyright 2016 Hewlett Packard Enterprise Development LP
 *
 * Licensed 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.
 */
#include "interface/standard/MessageReassembler.h"

#include <cassert>
#include <cstdio>

#include "workload/util.h"

namespace Standard {

MessageReassembler::MessageReassembler(const std::string& _name,
                                       const Component* _parent)
    : Component(_name, _parent) {}

MessageReassembler::~MessageReassembler() {}

Message* MessageReassembler::receivePacket(Packet* _packet) {
  // get the message and determine unqiue id
  Message* message = _packet->message();
  u32 sourceId = message->getSourceId();
  u32 messageId = message->id();
  u32 appId1 = appId(message->getTransaction());
  u64 umid = transactionId(appId1, sourceId, messageId);
  // u64 mid = ((u64)sourceId) << 32 | ((u64)messageId);

  // if non-existent, add a new table entry
  bool umidExists = messages_.count(umid) == 1;
  if (!umidExists) {
    messages_[umid] = MessageData();
    messages_[umid].message = message;
    messages_[umid].packetsReceived.resize(message->numPackets(), false);
    messages_[umid].receivedCount = 0;
  }

  // retrieve the message data
  MessageData& messageData = messages_.at(umid);
  assert(messageData.message == message);

  // mark the packet as received
  assert(messageData.packetsReceived.at(_packet->id()) == false);
  messageData.packetsReceived.at(_packet->id()) = true;
  messageData.receivedCount++;

  // check if the full message has been received
  if (messageData.receivedCount == message->numPackets()) {
    // remove the message from the map
    s32 erased = messages_.erase(umid);
    (void)erased;  // unused
    assert(erased == 1);
    return message;
  } else {
    // return nullptr to signify more packets are needed for the message
    return nullptr;
  }
}

}  // namespace Standard
<|endoftext|>