<commit_before>/* Copyright (C) 2003 MySQL AB

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

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#ifndef RESTORE_H
#define RESTORE_H

#include <ndb_global.h>
#include <NdbOut.hpp>
#include "../src/kernel/blocks/backup/BackupFormat.hpp"
#include "../src/ndbapi/NdbDictionaryImpl.hpp"
#include <NdbApi.hpp>

#include <ndb_version.h>
#include <version.h>

static const char * delimiter = ";"; // Delimiter in file dump

const int FileNameLenC = 256;
const int TableNameLenC = 256;
const int AttrNameLenC = 256;
const Uint32 timeToWaitForNdbC = 10000;
const Uint32 opsDefaultC = 1000;

// Forward declarations
//class AttributeDesc;
struct AttributeDesc;
struct AttributeData;
struct AttributeS;

struct AttributeData {
  bool null;
  Uint32 size;
  union {
    Int8 * int8_value;
    Uint8 * u_int8_value;

    Int16 * int16_value;
    Uint16 * u_int16_value;

    Int32 * int32_value;
    Uint32 * u_int32_value;

    Int64 * int64_value;
    Uint64 * u_int64_value;

    char * string_value;

    void* void_value;
  };
};

struct AttributeDesc {
  //private:
  friend class TupleS;
  friend class TableS;
  friend class RestoreDataIterator;
  friend class RestoreMetaData;
  friend struct AttributeS;
  Uint32 size; // bits
  Uint32 arraySize;
  Uint32 attrId;
  NdbDictionary::Column *m_column;

  Uint32 m_nullBitIndex;
public:

  AttributeDesc(NdbDictionary::Column *column);
  AttributeDesc();

  Uint32 getSizeInWords() const { return (size * arraySize + 31)/ 32;}
}; // AttributeDesc

struct AttributeS {
  const AttributeDesc * Desc;
  AttributeData Data;
};

class TupleS {
private:
  friend class RestoreDataIterator;

  class TableS *m_currentTable;
  AttributeData *allAttrData;
  bool prepareRecord(TableS &);

public:
  TupleS() {
    m_currentTable= 0;
    allAttrData= 0;
  };
  ~TupleS()
  {
    if (allAttrData)
      delete [] allAttrData;
  };
  TupleS(const TupleS& tuple); // disable copy constructor
  TupleS & operator=(const TupleS& tuple);
  int getNoOfAttributes() const;
  TableS * getTable() const;
  const AttributeDesc * getDesc(int i) const;
  AttributeData * getData(int i) const;
}; // class TupleS

class TableS {

  friend class TupleS;
  friend class RestoreMetaData;
  friend class RestoreDataIterator;

  Uint32 schemaVersion;
  Uint32 backupVersion;
  Vector<AttributeDesc *> allAttributesDesc;
  Vector<AttributeDesc *> m_fixedKeys;
  //Vector<AttributeDesc *> m_variableKey;
  Vector<AttributeDesc *> m_fixedAttribs;
  Vector<AttributeDesc *> m_variableAttribs;

  Uint32 m_noOfNullable;
  Uint32 m_nullBitmaskSize;

  Uint32 m_auto_val_id;
  Uint64 m_max_auto_val;

  int pos;

  void createAttr(NdbDictionary::Column *column);

public:
  class NdbDictionary::Table* m_dictTable;
  TableS (Uint32 version, class NdbTableImpl* dictTable);
  ~TableS();

  Uint32 getTableId() const {
    return m_dictTable->getTableId();
  }
  /*
  void setMysqlTableName(char * tableName) {
    strpcpy(mysqlTableName, tableName);
  }

  char *
  void setMysqlDatabaseName(char * databaseName) {
    strpcpy(mysqlDatabaseName, databaseName);
  }

  table.setMysqlDatabaseName(database);
  */
  void setBackupVersion(Uint32 version) {
    backupVersion = version;
  }

  Uint32 getBackupVersion() const {
    return backupVersion;
  }

  const char * getTableName() const {
    return m_dictTable->getName();
  }

  int getNoOfAttributes() const {
    return allAttributesDesc.size();
  };

  bool have_auto_inc() const {
    return m_auto_val_id != ~(Uint32)0;
  };

  bool have_auto_inc(Uint32 id) const {
    return m_auto_val_id == id;
  };

  Uint64 get_max_auto_val() const {
    return m_max_auto_val;
  };

  void update_max_auto_val(const char *data, int size) {
    Uint64 val= 0;
    switch(size){
    case 8:
      val= *(Uint8*)data;
      break;
    case 16:
      val= *(Uint16*)data;
      break;
    case 24:
      val= (0xffffff)&*(Uint32*)data;
      break;
    case 32:
      val= *(Uint32*)data;
      break;
    case 64:
      val= *(Uint64*)data;
      break;
    default:
      return;
    };
    if(val > m_max_auto_val)
      m_max_auto_val= val;
  };
  /**
   * Get attribute descriptor
   */
  const AttributeDesc * operator[](int attributeId) const {
    return allAttributesDesc[attributeId];
  }

  TableS& operator=(TableS& org) ;
}; // TableS;

class BackupFile {
protected:
  FILE * m_file;
  char m_path[PATH_MAX];
  char m_fileName[PATH_MAX];
  bool m_hostByteOrder;
  BackupFormat::FileHeader m_fileHeader;
  BackupFormat::FileHeader m_expectedFileHeader;

  Uint32 m_nodeId;

  void * m_buffer;
  void * m_buffer_ptr;
  Uint32 m_buffer_sz;
  Uint32 m_buffer_data_left;
  void (* free_data_callback)();

  bool openFile();
  void setCtlFile(Uint32 nodeId, Uint32 backupId, const char * path);
  void setDataFile(const BackupFile & bf, Uint32 no);
  void setLogFile(const BackupFile & bf, Uint32 no);

  Uint32 buffer_get_ptr(void **p_buf_ptr, Uint32 size, Uint32 nmemb);
  Uint32 buffer_read(void *ptr, Uint32 size, Uint32 nmemb);
  Uint32 buffer_get_ptr_ahead(void **p_buf_ptr, Uint32 size, Uint32 nmemb);
  Uint32 buffer_read_ahead(void *ptr, Uint32 size, Uint32 nmemb);

  void setName(const char * path, const char * name);

  BackupFile(void (* free_data_callback)() = 0);
  ~BackupFile();
public:
  bool readHeader();
  bool validateFooter();

  const char * getPath() const { return m_path;}
  const char * getFilename() const { return m_fileName;}
  Uint32 getNodeId() const { return m_nodeId;}
  const BackupFormat::FileHeader & getFileHeader() const { return m_fileHeader;}
  bool Twiddle(const AttributeDesc *  attr_desc, AttributeData * attr_data, Uint32 arraySize = 0);
};

class RestoreMetaData : public BackupFile {

  Vector<TableS *> allTables;
  bool readMetaFileHeader();
  bool readMetaTableDesc();

  bool readGCPEntry();
  Uint32 readMetaTableList();

  Uint32 m_startGCP;
  Uint32 m_stopGCP;

  bool parseTableDescriptor(const Uint32 * data, Uint32 len);

public:
  RestoreMetaData(const char * path, Uint32 nodeId, Uint32 bNo);
  virtual ~RestoreMetaData();

  int loadContent();

  Uint32 getNoOfTables() const { return allTables.size();}

  const TableS * operator[](int i) const { return allTables[i];}
  TableS * getTable(Uint32 tableId) const;

  Uint32 getStopGCP() const;
}; // RestoreMetaData

class RestoreDataIterator : public BackupFile {
  const RestoreMetaData & m_metaData;
  Uint32 m_count;
  TableS* m_currentTable;
  TupleS m_tuple;

public:

  // Constructor
  RestoreDataIterator(const RestoreMetaData &, void (* free_data_callback)());
  ~RestoreDataIterator() {};

  // Read data file fragment header
  bool readFragmentHeader(int & res);
  bool validateFragmentFooter();

  const TupleS *getNextTuple(int & res);
};

class LogEntry {
public:
  enum EntryType {
    LE_INSERT,
    LE_DELETE,
    LE_UPDATE
  };
  EntryType m_type;
  TableS * m_table;
  Vector<AttributeS*> m_values;
  Vector<AttributeS*> m_values_e;
  AttributeS *add_attr() {
    AttributeS * attr;
    if (m_values_e.size() > 0) {
      attr = m_values_e[m_values_e.size()-1];
      m_values_e.erase(m_values_e.size()-1);
    }
    else
    {
      attr = new AttributeS;
    }
    m_values.push_back(attr);
    return attr;
  }
  void clear() {
    for(Uint32 i= 0; i < m_values.size(); i++)
      m_values_e.push_back(m_values[i]);
    m_values.clear();
  }
  ~LogEntry()
  {
    Uint32 i;
    for(i= 0; i< m_values.size(); i++)
      delete m_values[i];
    for(i= 0; i< m_values_e.size(); i++)
      delete m_values_e[i];
  }
  Uint32 size() const { return m_values.size(); }
  const AttributeS * operator[](int i) const { return m_values[i];}
};

class RestoreLogIterator : public BackupFile {
private:
  const RestoreMetaData & m_metaData;

  Uint32 m_count;
  LogEntry m_logEntry;
public:
  RestoreLogIterator(const RestoreMetaData &);
  virtual ~RestoreLogIterator() {};

  const LogEntry * getNextLogEntry(int & res);
};

NdbOut& operator<<(NdbOut& ndbout, const TableS&);
NdbOut& operator<<(NdbOut& ndbout, const TupleS&);
NdbOut& operator<<(NdbOut& ndbout, const LogEntry&);
NdbOut& operator<<(NdbOut& ndbout, const RestoreMetaData&);

#endif

<commit_msg>Bug#7937<commit_after>/* Copyright (C) 2003 MySQL AB

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

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#ifndef RESTORE_H
#define RESTORE_H

#include <ndb_global.h>
#include <NdbOut.hpp>
#include "../src/kernel/blocks/backup/BackupFormat.hpp"
#include "../src/ndbapi/NdbDictionaryImpl.hpp"
#include <NdbApi.hpp>

#include <ndb_version.h>
#include <version.h>

static const char * delimiter = ";"; // Delimiter in file dump

const int FileNameLenC = 256;
const int TableNameLenC = 256;
const int AttrNameLenC = 256;
const Uint32 timeToWaitForNdbC = 10000;
const Uint32 opsDefaultC = 1000;

// Forward declarations
//class AttributeDesc;
struct AttributeDesc;
struct AttributeData;
struct AttributeS;

struct AttributeData {
  bool null;
  Uint32 size;
  union {
    Int8 * int8_value;
    Uint8 * u_int8_value;

    Int16 * int16_value;
    Uint16 * u_int16_value;

    Int32 * int32_value;
    Uint32 * u_int32_value;

    Int64 * int64_value;
    Uint64 * u_int64_value;

    char * string_value;

    void* void_value;
  };
};

struct AttributeDesc {
  //private:
  friend class TupleS;
  friend class TableS;
  friend class RestoreDataIterator;
  friend class RestoreMetaData;
  friend struct AttributeS;
  Uint32 size; // bits
  Uint32 arraySize;
  Uint32 attrId;
  NdbDictionary::Column *m_column;

  Uint32 m_nullBitIndex;
public:

  AttributeDesc(NdbDictionary::Column *column);
  AttributeDesc();

  Uint32 getSizeInWords() const { return (size * arraySize + 31)/ 32;}
}; // AttributeDesc

struct AttributeS {
  const AttributeDesc * Desc;
  AttributeData Data;
};

class TupleS {
private:
  friend class RestoreDataIterator;

  class TableS *m_currentTable;
  AttributeData *allAttrData;
  bool prepareRecord(TableS &);

public:
  TupleS() {
    m_currentTable= 0;
    allAttrData= 0;
  };
  ~TupleS()
  {
    if (allAttrData)
      delete [] allAttrData;
  };
  TupleS(const TupleS& tuple); // disable copy constructor
  TupleS & operator=(const TupleS& tuple);
  int getNoOfAttributes() const;
  TableS * getTable() const;
  const AttributeDesc * getDesc(int i) const;
  AttributeData * getData(int i) const;
}; // class TupleS

class TableS {

  friend class TupleS;
  friend class RestoreMetaData;
  friend class RestoreDataIterator;

  Uint32 schemaVersion;
  Uint32 backupVersion;
  Vector<AttributeDesc *> allAttributesDesc;
  Vector<AttributeDesc *> m_fixedKeys;
  //Vector<AttributeDesc *> m_variableKey;
  Vector<AttributeDesc *> m_fixedAttribs;
  Vector<AttributeDesc *> m_variableAttribs;

  Uint32 m_noOfNullable;
  Uint32 m_nullBitmaskSize;

  Uint32 m_auto_val_id;
  Uint64 m_max_auto_val;

  int pos;

  void createAttr(NdbDictionary::Column *column);

public:
  class NdbDictionary::Table* m_dictTable;
  TableS (Uint32 version, class NdbTableImpl* dictTable);
  ~TableS();

  Uint32 getTableId() const {
    return m_dictTable->getTableId();
  }
  /*
  void setMysqlTableName(char * tableName) {
    strpcpy(mysqlTableName, tableName);
  }

  char *
  void setMysqlDatabaseName(char * databaseName) {
    strpcpy(mysqlDatabaseName, databaseName);
  }

  table.setMysqlDatabaseName(database);
  */
  void setBackupVersion(Uint32 version) {
    backupVersion = version;
  }

  Uint32 getBackupVersion() const {
    return backupVersion;
  }

  const char * getTableName() const {
    return m_dictTable->getName();
  }

  int getNoOfAttributes() const {
    return allAttributesDesc.size();
  };

  bool have_auto_inc() const {
    return m_auto_val_id != ~(Uint32)0;
  };

  bool have_auto_inc(Uint32 id) const {
    return m_auto_val_id == id;
  };

  Uint64 get_max_auto_val() const {
    return m_max_auto_val;
  };

  void update_max_auto_val(const char *data, int size) {
    union {
      Uint8  u8;
      Uint16 u16;
      Uint32 u32;
    } val;
    Uint64 v;
    switch(size){
    case 64:
      memcpy(&v,data,8);
      break;
    case 32:
      memcpy(&val.u32,data,4);
      v= val.u32;
      break;
    case 16:
      memcpy(&val.u16,data,2);
      v= val.u16;
      break;
    case 8:
      memcpy(&val.u8,data,1);
      v= val.u8;
      break;
    default:
      return;
    };
    if(v > m_max_auto_val)
      m_max_auto_val= v;
  };
  /**
   * Get attribute descriptor
   */
  const AttributeDesc * operator[](int attributeId) const {
    return allAttributesDesc[attributeId];
  }

  TableS& operator=(TableS& org) ;
}; // TableS;

class BackupFile {
protected:
  FILE * m_file;
  char m_path[PATH_MAX];
  char m_fileName[PATH_MAX];
  bool m_hostByteOrder;
  BackupFormat::FileHeader m_fileHeader;
  BackupFormat::FileHeader m_expectedFileHeader;

  Uint32 m_nodeId;

  void * m_buffer;
  void * m_buffer_ptr;
  Uint32 m_buffer_sz;
  Uint32 m_buffer_data_left;
  void (* free_data_callback)();

  bool openFile();
  void setCtlFile(Uint32 nodeId, Uint32 backupId, const char * path);
  void setDataFile(const BackupFile & bf, Uint32 no);
  void setLogFile(const BackupFile & bf, Uint32 no);

  Uint32 buffer_get_ptr(void **p_buf_ptr, Uint32 size, Uint32 nmemb);
  Uint32 buffer_read(void *ptr, Uint32 size, Uint32 nmemb);
  Uint32 buffer_get_ptr_ahead(void **p_buf_ptr, Uint32 size, Uint32 nmemb);
  Uint32 buffer_read_ahead(void *ptr, Uint32 size, Uint32 nmemb);

  void setName(const char * path, const char * name);

  BackupFile(void (* free_data_callback)() = 0);
  ~BackupFile();
public:
  bool readHeader();
  bool validateFooter();

  const char * getPath() const { return m_path;}
  const char * getFilename() const { return m_fileName;}
  Uint32 getNodeId() const { return m_nodeId;}
  const BackupFormat::FileHeader & getFileHeader() const { return m_fileHeader;}
  bool Twiddle(const AttributeDesc *  attr_desc, AttributeData * attr_data, Uint32 arraySize = 0);
};

class RestoreMetaData : public BackupFile {

  Vector<TableS *> allTables;
  bool readMetaFileHeader();
  bool readMetaTableDesc();

  bool readGCPEntry();
  Uint32 readMetaTableList();

  Uint32 m_startGCP;
  Uint32 m_stopGCP;

  bool parseTableDescriptor(const Uint32 * data, Uint32 len);

public:
  RestoreMetaData(const char * path, Uint32 nodeId, Uint32 bNo);
  virtual ~RestoreMetaData();

  int loadContent();

  Uint32 getNoOfTables() const { return allTables.size();}

  const TableS * operator[](int i) const { return allTables[i];}
  TableS * getTable(Uint32 tableId) const;

  Uint32 getStopGCP() const;
}; // RestoreMetaData

class RestoreDataIterator : public BackupFile {
  const RestoreMetaData & m_metaData;
  Uint32 m_count;
  TableS* m_currentTable;
  TupleS m_tuple;

public:

  // Constructor
  RestoreDataIterator(const RestoreMetaData &, void (* free_data_callback)());
  ~RestoreDataIterator() {};

  // Read data file fragment header
  bool readFragmentHeader(int & res);
  bool validateFragmentFooter();

  const TupleS *getNextTuple(int & res);
};

class LogEntry {
public:
  enum EntryType {
    LE_INSERT,
    LE_DELETE,
    LE_UPDATE
  };
  EntryType m_type;
  TableS * m_table;
  Vector<AttributeS*> m_values;
  Vector<AttributeS*> m_values_e;
  AttributeS *add_attr() {
    AttributeS * attr;
    if (m_values_e.size() > 0) {
      attr = m_values_e[m_values_e.size()-1];
      m_values_e.erase(m_values_e.size()-1);
    }
    else
    {
      attr = new AttributeS;
    }
    m_values.push_back(attr);
    return attr;
  }
  void clear() {
    for(Uint32 i= 0; i < m_values.size(); i++)
      m_values_e.push_back(m_values[i]);
    m_values.clear();
  }
  ~LogEntry()
  {
    Uint32 i;
    for(i= 0; i< m_values.size(); i++)
      delete m_values[i];
    for(i= 0; i< m_values_e.size(); i++)
      delete m_values_e[i];
  }
  Uint32 size() const { return m_values.size(); }
  const AttributeS * operator[](int i) const { return m_values[i];}
};

class RestoreLogIterator : public BackupFile {
private:
  const RestoreMetaData & m_metaData;

  Uint32 m_count;
  LogEntry m_logEntry;
public:
  RestoreLogIterator(const RestoreMetaData &);
  virtual ~RestoreLogIterator() {};

  const LogEntry * getNextLogEntry(int & res);
};

NdbOut& operator<<(NdbOut& ndbout, const TableS&);
NdbOut& operator<<(NdbOut& ndbout, const TupleS&);
NdbOut& operator<<(NdbOut& ndbout, const LogEntry&);
NdbOut& operator<<(NdbOut& ndbout, const RestoreMetaData&);

#endif

<|endoftext|>


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

#include "chrome/browser/chromeos/input_method/virtual_keyboard_selector.h"

#include "base/logging.h"
#include "base/stl_util-inl.h"

namespace {
const char kDefaultURLPath[] = "index.html";
const size_t kDefaultURLPathLen = arraysize(kDefaultURLPath) - 1;
}  // namespace

namespace chromeos {
namespace input_method {

VirtualKeyboard::VirtualKeyboard(const GURL& url,
                                 const std::set<std::string>& supported_layouts,
                                 bool is_system)
    : url_(url),
      supported_layouts_(supported_layouts),
      is_system_(is_system) {
}

VirtualKeyboard::~VirtualKeyboard() {
}

GURL VirtualKeyboard::GetURLForLayout(const std::string& layout) const {
  if (layout.empty()) {
    return url_;
  }
  url_canon::Replacements<char> replacements;
  replacements.SetPath(
      kDefaultURLPath, url_parse::Component(0, kDefaultURLPathLen));
  // TODO(yusukes): would be better to URL-encode the |layout|?
  replacements.SetRef(layout.c_str(), url_parse::Component(0, layout.length()));
  return url_.ReplaceComponents(replacements);
}

VirtualKeyboardSelector::VirtualKeyboardSelector()
    : current_(NULL) {
}

VirtualKeyboardSelector::~VirtualKeyboardSelector() {
  STLDeleteElements(&keyboards_);
}

void VirtualKeyboardSelector::AddVirtualKeyboard(
    const GURL& url,
    const std::set<std::string>& supported_layouts,
    bool is_system) {
  const VirtualKeyboard* new_keyboard = new VirtualKeyboard(url,
                                                            supported_layouts,
                                                            is_system);
  if (is_system) {
    system_keyboards_.push_front(new_keyboard);
  } else {
    keyboards_.push_front(new_keyboard);
  }
}

const VirtualKeyboard* VirtualKeyboardSelector::SelectVirtualKeyboard(
    const std::string& layout) {
  if (layout.empty()) {
    LOG(ERROR) << "No layout is specified";
    return NULL;
  }

  // First, check whether the current keyboard supports the layout.
  if (current_ && current_->supported_layouts().count(layout) > 0) {
    return current_;
  }

  const VirtualKeyboard* keyboard = SelectVirtualKeyboardInternal(layout);
  if (!keyboard) {
    VLOG(1) << "No virtual keyboard for " << layout << " is found";
    return NULL;
  }

  current_ = keyboard;
  return keyboard;
}

const VirtualKeyboard* VirtualKeyboardSelector::SelectVirtualKeyboardInternal(
    const std::string& layout) {
  std::list<const VirtualKeyboard*>::const_iterator iter;
  for (iter = keyboards_.begin(); iter != keyboards_.end(); ++iter) {
    if ((*iter)->supported_layouts().count(layout) > 0) {
      return *iter;
    }
  }
  for (iter = system_keyboards_.begin();
       iter != system_keyboards_.end(); ++iter) {
    if ((*iter)->supported_layouts().count(layout) > 0) {
      return *iter;
    }
  }
  return NULL;
}

}  // namespace input_method
}  // namespace chromeos
<commit_msg>Fix memory leak in VirtualKeyboardSelector.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/input_method/virtual_keyboard_selector.h"

#include "base/logging.h"
#include "base/stl_util-inl.h"

namespace {
const char kDefaultURLPath[] = "index.html";
const size_t kDefaultURLPathLen = arraysize(kDefaultURLPath) - 1;
}  // namespace

namespace chromeos {
namespace input_method {

VirtualKeyboard::VirtualKeyboard(const GURL& url,
                                 const std::set<std::string>& supported_layouts,
                                 bool is_system)
    : url_(url),
      supported_layouts_(supported_layouts),
      is_system_(is_system) {
}

VirtualKeyboard::~VirtualKeyboard() {
}

GURL VirtualKeyboard::GetURLForLayout(const std::string& layout) const {
  if (layout.empty()) {
    return url_;
  }
  url_canon::Replacements<char> replacements;
  replacements.SetPath(
      kDefaultURLPath, url_parse::Component(0, kDefaultURLPathLen));
  // TODO(yusukes): would be better to URL-encode the |layout|?
  replacements.SetRef(layout.c_str(), url_parse::Component(0, layout.length()));
  return url_.ReplaceComponents(replacements);
}

VirtualKeyboardSelector::VirtualKeyboardSelector()
    : current_(NULL) {
}

VirtualKeyboardSelector::~VirtualKeyboardSelector() {
  STLDeleteElements(&keyboards_);
  STLDeleteElements(&system_keyboards_);
}

void VirtualKeyboardSelector::AddVirtualKeyboard(
    const GURL& url,
    const std::set<std::string>& supported_layouts,
    bool is_system) {
  const VirtualKeyboard* new_keyboard = new VirtualKeyboard(url,
                                                            supported_layouts,
                                                            is_system);
  if (is_system) {
    system_keyboards_.push_front(new_keyboard);
  } else {
    keyboards_.push_front(new_keyboard);
  }
}

const VirtualKeyboard* VirtualKeyboardSelector::SelectVirtualKeyboard(
    const std::string& layout) {
  if (layout.empty()) {
    LOG(ERROR) << "No layout is specified";
    return NULL;
  }

  // First, check whether the current keyboard supports the layout.
  if (current_ && current_->supported_layouts().count(layout) > 0) {
    return current_;
  }

  const VirtualKeyboard* keyboard = SelectVirtualKeyboardInternal(layout);
  if (!keyboard) {
    VLOG(1) << "No virtual keyboard for " << layout << " is found";
    return NULL;
  }

  current_ = keyboard;
  return keyboard;
}

const VirtualKeyboard* VirtualKeyboardSelector::SelectVirtualKeyboardInternal(
    const std::string& layout) {
  std::list<const VirtualKeyboard*>::const_iterator iter;
  for (iter = keyboards_.begin(); iter != keyboards_.end(); ++iter) {
    if ((*iter)->supported_layouts().count(layout) > 0) {
      return *iter;
    }
  }
  for (iter = system_keyboards_.begin();
       iter != system_keyboards_.end(); ++iter) {
    if ((*iter)->supported_layouts().count(layout) > 0) {
      return *iter;
    }
  }
  return NULL;
}

}  // namespace input_method
}  // namespace chromeos
<|endoftext|>


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

#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/password_manager/password_form_data.h"
#include "chrome/test/live_sync/live_passwords_sync_test.h"

using webkit_glue::PasswordForm;

IN_PROC_BROWSER_TEST_F(MultipleClientLivePasswordsSyncTest, Sanity) {
  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";

  for (int i = 0; i < num_clients(); ++i) {
    PasswordForm form = CreateTestPasswordForm(i);
    AddLogin(GetPasswordStore(i), form);
  }
  ASSERT_TRUE(AwaitQuiescence());

  std::vector<PasswordForm> forms0;
  GetLogins(GetPasswordStore(0), forms0);
  ASSERT_EQ((size_t) num_clients(), forms0.size());

  for (int i = 1; i < num_clients(); ++i) {
    std::vector<PasswordForm> forms;
    GetLogins(GetPasswordStore(i), forms);
    ASSERT_TRUE(ContainsSamePasswordForms(forms0, forms));
  }
}
<commit_msg>Marking MultipleClientLivePasswordsSyncTest.Sanity as failing<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/password_manager/password_form_data.h"
#include "chrome/test/live_sync/live_passwords_sync_test.h"

using webkit_glue::PasswordForm;

// TODO(rsimha): This test fails intermittently -- see http://crbug.com/77993.
IN_PROC_BROWSER_TEST_F(MultipleClientLivePasswordsSyncTest, FAILS_Sanity) {
  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";

  for (int i = 0; i < num_clients(); ++i) {
    PasswordForm form = CreateTestPasswordForm(i);
    AddLogin(GetPasswordStore(i), form);
  }
  ASSERT_TRUE(AwaitQuiescence());

  std::vector<PasswordForm> forms0;
  GetLogins(GetPasswordStore(0), forms0);
  ASSERT_EQ((size_t) num_clients(), forms0.size());

  for (int i = 1; i < num_clients(); ++i) {
    std::vector<PasswordForm> forms;
    GetLogins(GetPasswordStore(i), forms);
    ASSERT_TRUE(ContainsSamePasswordForms(forms0, forms));
  }
}
<|endoftext|>


<commit_before>//===-- sanitizer_mac.cc --------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries and implements mac-specific functions from
// sanitizer_libc.h.
//===----------------------------------------------------------------------===//

#include "sanitizer_platform.h"
#if SANITIZER_MAC

// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
// the clients will most certainly use 64-bit ones as well.
#ifndef _DARWIN_USE_64_BIT_INODE
#define _DARWIN_USE_64_BIT_INODE 1
#endif
#include <stdio.h>

#include "sanitizer_common.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_libc.h"
#include "sanitizer_procmaps.h"

#include <crt_externs.h>  // for _NSGetEnviron
#include <fcntl.h>
#include <mach-o/dyld.h>
#include <mach-o/loader.h>
#include <pthread.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <libkern/OSAtomic.h>

namespace __sanitizer {

#include "sanitizer_syscall_generic.inc"

// ---------------------- sanitizer_libc.h
void *internal_mmap(void *addr, size_t length, int prot, int flags,
                    int fd, u64 offset) {
  return mmap(addr, length, prot, flags, fd, offset);
}

int internal_munmap(void *addr, uptr length) {
  return munmap(addr, length);
}

uptr internal_close(fd_t fd) {
  return close(fd);
}

uptr internal_open(const char *filename, int flags) {
  return open(filename, flags);
}

uptr internal_open(const char *filename, int flags, u32 mode) {
  return open(filename, flags, mode);
}

uptr OpenFile(const char *filename, bool write) {
  return internal_open(filename,
      write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
}

uptr internal_read(fd_t fd, void *buf, uptr count) {
  return read(fd, buf, count);
}

uptr internal_write(fd_t fd, const void *buf, uptr count) {
  return write(fd, buf, count);
}

uptr internal_stat(const char *path, void *buf) {
  return stat(path, (struct stat *)buf);
}

uptr internal_lstat(const char *path, void *buf) {
  return lstat(path, (struct stat *)buf);
}

uptr internal_fstat(fd_t fd, void *buf) {
  return fstat(fd, (struct stat *)buf);
}

uptr internal_filesize(fd_t fd) {
  struct stat st;
  if (internal_fstat(fd, &st))
    return -1;
  return (uptr)st.st_size;
}

uptr internal_dup2(int oldfd, int newfd) {
  return dup2(oldfd, newfd);
}

uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
  return readlink(path, buf, bufsize);
}

uptr internal_sched_yield() {
  return sched_yield();
}

void internal__exit(int exitcode) {
  _exit(exitcode);
}

// ----------------- sanitizer_common.h
bool FileExists(const char *filename) {
  struct stat st;
  if (stat(filename, &st))
    return false;
  // Sanity check: filename is a regular file.
  return S_ISREG(st.st_mode);
}

uptr GetTid() {
  return reinterpret_cast<uptr>(pthread_self());
}

void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
                                uptr *stack_bottom) {
  CHECK(stack_top);
  CHECK(stack_bottom);
  uptr stacksize = pthread_get_stacksize_np(pthread_self());
  void *stackaddr = pthread_get_stackaddr_np(pthread_self());
  *stack_top = (uptr)stackaddr;
  *stack_bottom = *stack_top - stacksize;
}

const char *GetEnv(const char *name) {
  char ***env_ptr = _NSGetEnviron();
  CHECK(env_ptr);
  char **environ = *env_ptr;
  CHECK(environ);
  uptr name_len = internal_strlen(name);
  while (*environ != 0) {
    uptr len = internal_strlen(*environ);
    if (len > name_len) {
      const char *p = *environ;
      if (!internal_memcmp(p, name, name_len) &&
          p[name_len] == '=') {  // Match.
        return *environ + name_len + 1;  // String starting after =.
      }
    }
    environ++;
  }
  return 0;
}

void ReExec() {
  UNIMPLEMENTED();
}

void PrepareForSandboxing() {
  // Nothing here for now.
}

// ----------------- sanitizer_procmaps.h

MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
  Reset();
}

MemoryMappingLayout::~MemoryMappingLayout() {
}

// More information about Mach-O headers can be found in mach-o/loader.h
// Each Mach-O image has a header (mach_header or mach_header_64) starting with
// a magic number, and a list of linker load commands directly following the
// header.
// A load command is at least two 32-bit words: the command type and the
// command size in bytes. We're interested only in segment load commands
// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped
// into the task's address space.
// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or
// segment_command_64 correspond to the memory address, memory size and the
// file offset of the current memory segment.
// Because these fields are taken from the images as is, one needs to add
// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime.

void MemoryMappingLayout::Reset() {
  // Count down from the top.
  // TODO(glider): as per man 3 dyld, iterating over the headers with
  // _dyld_image_count is thread-unsafe. We need to register callbacks for
  // adding and removing images which will invalidate the MemoryMappingLayout
  // state.
  current_image_ = _dyld_image_count();
  current_load_cmd_count_ = -1;
  current_load_cmd_addr_ = 0;
  current_magic_ = 0;
  current_filetype_ = 0;
}

// static
void MemoryMappingLayout::CacheMemoryMappings() {
  // No-op on Mac for now.
}

void MemoryMappingLayout::LoadFromCache() {
  // No-op on Mac for now.
}

// Next and NextSegmentLoad were inspired by base/sysinfo.cc in
// Google Perftools, http://code.google.com/p/google-perftools.

// NextSegmentLoad scans the current image for the next segment load command
// and returns the start and end addresses and file offset of the corresponding
// segment.
// Note that the segment addresses are not necessarily sorted.
template<u32 kLCSegment, typename SegmentCommand>
bool MemoryMappingLayout::NextSegmentLoad(
    uptr *start, uptr *end, uptr *offset,
    char filename[], uptr filename_size, uptr *protection) {
  if (protection)
    UNIMPLEMENTED();
  const char* lc = current_load_cmd_addr_;
  current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize;
  if (((const load_command *)lc)->cmd == kLCSegment) {
    const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_);
    const SegmentCommand* sc = (const SegmentCommand *)lc;
    if (start) *start = sc->vmaddr + dlloff;
    if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
    if (offset) {
      if (current_filetype_ == /*MH_EXECUTE*/ 0x2) {
        *offset = sc->vmaddr;
      } else {
        *offset = sc->fileoff;
      }
    }
    if (filename) {
      internal_strncpy(filename, _dyld_get_image_name(current_image_),
                       filename_size);
    }
    return true;
  }
  return false;
}

bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
                               char filename[], uptr filename_size,
                               uptr *protection) {
  for (; current_image_ >= 0; current_image_--) {
    const mach_header* hdr = _dyld_get_image_header(current_image_);
    if (!hdr) continue;
    if (current_load_cmd_count_ < 0) {
      // Set up for this image;
      current_load_cmd_count_ = hdr->ncmds;
      current_magic_ = hdr->magic;
      current_filetype_ = hdr->filetype;
      switch (current_magic_) {
#ifdef MH_MAGIC_64
        case MH_MAGIC_64: {
          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header_64);
          break;
        }
#endif
        case MH_MAGIC: {
          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header);
          break;
        }
        default: {
          continue;
        }
      }
    }

    for (; current_load_cmd_count_ >= 0; current_load_cmd_count_--) {
      switch (current_magic_) {
        // current_magic_ may be only one of MH_MAGIC, MH_MAGIC_64.
#ifdef MH_MAGIC_64
        case MH_MAGIC_64: {
          if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
                  start, end, offset, filename, filename_size, protection))
            return true;
          break;
        }
#endif
        case MH_MAGIC: {
          if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
                  start, end, offset, filename, filename_size, protection))
            return true;
          break;
        }
      }
    }
    // If we get here, no more load_cmd's in this image talk about
    // segments.  Go on to the next image.
  }
  return false;
}

bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
                                                 char filename[],
                                                 uptr filename_size,
                                                 uptr *protection) {
  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
                                       protection);
}

BlockingMutex::BlockingMutex(LinkerInitialized) {
  // We assume that OS_SPINLOCK_INIT is zero
}

BlockingMutex::BlockingMutex() {
  internal_memset(this, 0, sizeof(*this));
}

void BlockingMutex::Lock() {
  CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
  CHECK_EQ(OS_SPINLOCK_INIT, 0);
  CHECK_NE(owner_, (uptr)pthread_self());
  OSSpinLockLock((OSSpinLock*)&opaque_storage_);
  CHECK(!owner_);
  owner_ = (uptr)pthread_self();
}

void BlockingMutex::Unlock() {
  CHECK(owner_ == (uptr)pthread_self());
  owner_ = 0;
  OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
}

void BlockingMutex::CheckLocked() {
  CHECK_EQ((uptr)pthread_self(), owner_);
}

uptr GetTlsSize() {
  return 0;
}

void InitTlsSize() {
}

void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
                          uptr *tls_addr, uptr *tls_size) {
  uptr stack_top, stack_bottom;
  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
  *stk_addr = stack_bottom;
  *stk_size = stack_top - stack_bottom;
  *tls_addr = 0;
  *tls_size = 0;
}

}  // namespace __sanitizer

#endif  // SANITIZER_MAC
<commit_msg>Try to fix the mac buildbots<commit_after>//===-- sanitizer_mac.cc --------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries and implements mac-specific functions from
// sanitizer_libc.h.
//===----------------------------------------------------------------------===//

#include "sanitizer_platform.h"
#if SANITIZER_MAC

// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
// the clients will most certainly use 64-bit ones as well.
#ifndef _DARWIN_USE_64_BIT_INODE
#define _DARWIN_USE_64_BIT_INODE 1
#endif
#include <stdio.h>

#include "sanitizer_common.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_libc.h"
#include "sanitizer_procmaps.h"

#include <crt_externs.h>  // for _NSGetEnviron
#include <fcntl.h>
#include <mach-o/dyld.h>
#include <mach-o/loader.h>
#include <pthread.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <libkern/OSAtomic.h>
#include <errno.h>

namespace __sanitizer {

#include "sanitizer_syscall_generic.inc"

// ---------------------- sanitizer_libc.h
uptr internal_mmap(void *addr, size_t length, int prot, int flags,
                   int fd, u64 offset) {
  return (uptr)mmap(addr, length, prot, flags, fd, offset);
}

uptr internal_munmap(void *addr, uptr length) {
  return munmap(addr, length);
}

uptr internal_close(fd_t fd) {
  return close(fd);
}

uptr internal_open(const char *filename, int flags) {
  return open(filename, flags);
}

uptr internal_open(const char *filename, int flags, u32 mode) {
  return open(filename, flags, mode);
}

uptr OpenFile(const char *filename, bool write) {
  return internal_open(filename,
      write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
}

uptr internal_read(fd_t fd, void *buf, uptr count) {
  return read(fd, buf, count);
}

uptr internal_write(fd_t fd, const void *buf, uptr count) {
  return write(fd, buf, count);
}

uptr internal_stat(const char *path, void *buf) {
  return stat(path, (struct stat *)buf);
}

uptr internal_lstat(const char *path, void *buf) {
  return lstat(path, (struct stat *)buf);
}

uptr internal_fstat(fd_t fd, void *buf) {
  return fstat(fd, (struct stat *)buf);
}

uptr internal_filesize(fd_t fd) {
  struct stat st;
  if (internal_fstat(fd, &st))
    return -1;
  return (uptr)st.st_size;
}

uptr internal_dup2(int oldfd, int newfd) {
  return dup2(oldfd, newfd);
}

uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
  return readlink(path, buf, bufsize);
}

uptr internal_sched_yield() {
  return sched_yield();
}

void internal__exit(int exitcode) {
  _exit(exitcode);
}

// ----------------- sanitizer_common.h
bool FileExists(const char *filename) {
  struct stat st;
  if (stat(filename, &st))
    return false;
  // Sanity check: filename is a regular file.
  return S_ISREG(st.st_mode);
}

uptr GetTid() {
  return reinterpret_cast<uptr>(pthread_self());
}

void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
                                uptr *stack_bottom) {
  CHECK(stack_top);
  CHECK(stack_bottom);
  uptr stacksize = pthread_get_stacksize_np(pthread_self());
  void *stackaddr = pthread_get_stackaddr_np(pthread_self());
  *stack_top = (uptr)stackaddr;
  *stack_bottom = *stack_top - stacksize;
}

const char *GetEnv(const char *name) {
  char ***env_ptr = _NSGetEnviron();
  CHECK(env_ptr);
  char **environ = *env_ptr;
  CHECK(environ);
  uptr name_len = internal_strlen(name);
  while (*environ != 0) {
    uptr len = internal_strlen(*environ);
    if (len > name_len) {
      const char *p = *environ;
      if (!internal_memcmp(p, name, name_len) &&
          p[name_len] == '=') {  // Match.
        return *environ + name_len + 1;  // String starting after =.
      }
    }
    environ++;
  }
  return 0;
}

void ReExec() {
  UNIMPLEMENTED();
}

void PrepareForSandboxing() {
  // Nothing here for now.
}

// ----------------- sanitizer_procmaps.h

MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
  Reset();
}

MemoryMappingLayout::~MemoryMappingLayout() {
}

// More information about Mach-O headers can be found in mach-o/loader.h
// Each Mach-O image has a header (mach_header or mach_header_64) starting with
// a magic number, and a list of linker load commands directly following the
// header.
// A load command is at least two 32-bit words: the command type and the
// command size in bytes. We're interested only in segment load commands
// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped
// into the task's address space.
// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or
// segment_command_64 correspond to the memory address, memory size and the
// file offset of the current memory segment.
// Because these fields are taken from the images as is, one needs to add
// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime.

void MemoryMappingLayout::Reset() {
  // Count down from the top.
  // TODO(glider): as per man 3 dyld, iterating over the headers with
  // _dyld_image_count is thread-unsafe. We need to register callbacks for
  // adding and removing images which will invalidate the MemoryMappingLayout
  // state.
  current_image_ = _dyld_image_count();
  current_load_cmd_count_ = -1;
  current_load_cmd_addr_ = 0;
  current_magic_ = 0;
  current_filetype_ = 0;
}

// static
void MemoryMappingLayout::CacheMemoryMappings() {
  // No-op on Mac for now.
}

void MemoryMappingLayout::LoadFromCache() {
  // No-op on Mac for now.
}

// Next and NextSegmentLoad were inspired by base/sysinfo.cc in
// Google Perftools, http://code.google.com/p/google-perftools.

// NextSegmentLoad scans the current image for the next segment load command
// and returns the start and end addresses and file offset of the corresponding
// segment.
// Note that the segment addresses are not necessarily sorted.
template<u32 kLCSegment, typename SegmentCommand>
bool MemoryMappingLayout::NextSegmentLoad(
    uptr *start, uptr *end, uptr *offset,
    char filename[], uptr filename_size, uptr *protection) {
  if (protection)
    UNIMPLEMENTED();
  const char* lc = current_load_cmd_addr_;
  current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize;
  if (((const load_command *)lc)->cmd == kLCSegment) {
    const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_);
    const SegmentCommand* sc = (const SegmentCommand *)lc;
    if (start) *start = sc->vmaddr + dlloff;
    if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
    if (offset) {
      if (current_filetype_ == /*MH_EXECUTE*/ 0x2) {
        *offset = sc->vmaddr;
      } else {
        *offset = sc->fileoff;
      }
    }
    if (filename) {
      internal_strncpy(filename, _dyld_get_image_name(current_image_),
                       filename_size);
    }
    return true;
  }
  return false;
}

bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
                               char filename[], uptr filename_size,
                               uptr *protection) {
  for (; current_image_ >= 0; current_image_--) {
    const mach_header* hdr = _dyld_get_image_header(current_image_);
    if (!hdr) continue;
    if (current_load_cmd_count_ < 0) {
      // Set up for this image;
      current_load_cmd_count_ = hdr->ncmds;
      current_magic_ = hdr->magic;
      current_filetype_ = hdr->filetype;
      switch (current_magic_) {
#ifdef MH_MAGIC_64
        case MH_MAGIC_64: {
          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header_64);
          break;
        }
#endif
        case MH_MAGIC: {
          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header);
          break;
        }
        default: {
          continue;
        }
      }
    }

    for (; current_load_cmd_count_ >= 0; current_load_cmd_count_--) {
      switch (current_magic_) {
        // current_magic_ may be only one of MH_MAGIC, MH_MAGIC_64.
#ifdef MH_MAGIC_64
        case MH_MAGIC_64: {
          if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
                  start, end, offset, filename, filename_size, protection))
            return true;
          break;
        }
#endif
        case MH_MAGIC: {
          if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
                  start, end, offset, filename, filename_size, protection))
            return true;
          break;
        }
      }
    }
    // If we get here, no more load_cmd's in this image talk about
    // segments.  Go on to the next image.
  }
  return false;
}

bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
                                                 char filename[],
                                                 uptr filename_size,
                                                 uptr *protection) {
  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
                                       protection);
}

BlockingMutex::BlockingMutex(LinkerInitialized) {
  // We assume that OS_SPINLOCK_INIT is zero
}

BlockingMutex::BlockingMutex() {
  internal_memset(this, 0, sizeof(*this));
}

void BlockingMutex::Lock() {
  CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
  CHECK_EQ(OS_SPINLOCK_INIT, 0);
  CHECK_NE(owner_, (uptr)pthread_self());
  OSSpinLockLock((OSSpinLock*)&opaque_storage_);
  CHECK(!owner_);
  owner_ = (uptr)pthread_self();
}

void BlockingMutex::Unlock() {
  CHECK(owner_ == (uptr)pthread_self());
  owner_ = 0;
  OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
}

void BlockingMutex::CheckLocked() {
  CHECK_EQ((uptr)pthread_self(), owner_);
}

uptr GetTlsSize() {
  return 0;
}

void InitTlsSize() {
}

void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
                          uptr *tls_addr, uptr *tls_size) {
  uptr stack_top, stack_bottom;
  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
  *stk_addr = stack_bottom;
  *stk_size = stack_top - stack_bottom;
  *tls_addr = 0;
  *tls_size = 0;
}

}  // namespace __sanitizer

#endif  // SANITIZER_MAC
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "selectiontool.h"
#include "layeritem.h"

//#include "resizehandleitem.h"
#include "../qdeclarativeviewobserver_p.h"

#include <QDeclarativeEngine>

#include <QApplication>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QClipboard>
#include <QMenu>
#include <QAction>
#include <QDeclarativeItem>
#include <QGraphicsObject>

#include <QDebug>

namespace QmlJSDebugger {

SelectionTool::SelectionTool(QDeclarativeViewObserver *editorView)
    : AbstractFormEditorTool(editorView),
    m_rubberbandSelectionMode(false),
    m_rubberbandSelectionManipulator(QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer, editorView),
    m_singleSelectionManipulator(editorView),
    m_selectionIndicator(editorView, QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer),
    //m_resizeIndicator(editorView->manipulatorLayer()),
    m_selectOnlyContentItems(true)
{

}

SelectionTool::~SelectionTool()
{
}

void SelectionTool::setRubberbandSelectionMode(bool value)
{
    m_rubberbandSelectionMode = value;
}

SingleSelectionManipulator::SelectionType SelectionTool::getSelectionType(Qt::KeyboardModifiers modifiers)
{
    SingleSelectionManipulator::SelectionType selectionType = SingleSelectionManipulator::ReplaceSelection;
    if (modifiers.testFlag(Qt::ControlModifier)) {
        selectionType = SingleSelectionManipulator::RemoveFromSelection;
    } else if (modifiers.testFlag(Qt::ShiftModifier)) {
        selectionType = SingleSelectionManipulator::AddToSelection;
    }
    return selectionType;
}

bool SelectionTool::alreadySelected(const QList<QGraphicsItem*> &itemList) const
{
    const QList<QGraphicsItem*> selectedItems = QDeclarativeViewObserverPrivate::get(observer())->selectedItems();

    if (selectedItems.isEmpty())
        return false;

    foreach(QGraphicsItem *item, itemList) {
        if (selectedItems.contains(item)) {
            return true;
        }
    }

    return false;
}

void SelectionTool::mousePressEvent(QMouseEvent *event)
{
    QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());
    SingleSelectionManipulator::SelectionType selectionType = getSelectionType(event->modifiers());

    if (event->buttons() & Qt::LeftButton) {
        m_mousePressTimer.start();

        if (m_rubberbandSelectionMode) {
            m_rubberbandSelectionManipulator.begin(event->pos());
        } else {

            if (itemList.isEmpty()) {
                QDeclarativeViewObserverPrivate::get(observer())->setSelectedItems(itemList);
                return;
            }

            if ((selectionType == SingleSelectionManipulator::InvertSelection
                 || selectionType == SingleSelectionManipulator::ReplaceSelection)
                && alreadySelected(itemList))
            {
                //view()->changeToMoveTool(event->pos());
                return;
            }

            QGraphicsItem* item = itemList.first();

            if (item->children().isEmpty()) {
                m_singleSelectionManipulator.begin(event->pos());
                m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
            } else {
                m_mousePressTimer.start();

                if (itemList.isEmpty()) {
                    observer()->setSelectedItems(itemList);
                    return;
                }

                if (item->children().isEmpty()) {
                    m_singleSelectionManipulator.begin(event->pos());
                    m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
                } else {
                    m_singleSelectionManipulator.begin(event->pos());
                    m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
                    m_singleSelectionManipulator.end(event->pos());
                    //view()->changeToMoveTool(event->pos());
                }

                m_singleSelectionManipulator.begin(event->pos());
                m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
                m_singleSelectionManipulator.end(event->pos());
                //view()->changeToMoveTool(event->pos());

            }
        }

    } else if (event->buttons() & Qt::RightButton) {
        createContextMenu(itemList, event->globalPos());
    }
}

void SelectionTool::createContextMenu(QList<QGraphicsItem*> itemList, QPoint globalPos)
{
    if (!QDeclarativeViewObserverPrivate::get(observer())->mouseInsideContextItem())
        return;

    QMenu contextMenu;
    connect(&contextMenu, SIGNAL(hovered(QAction*)), this, SLOT(contextMenuElementHovered(QAction*)));

    m_contextMenuItemList = itemList;

    contextMenu.addAction("Items");
    contextMenu.addSeparator();
    int shortcutKey = Qt::Key_1;
    bool addKeySequence = true;
    int i = 0;

    foreach(QGraphicsItem * const item, itemList) {
        QString itemTitle = titleForItem(item);
        QAction *elementAction = contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected()));

        if (observer()->selectedItems().contains(item)) {
            QFont boldFont = elementAction->font();
            boldFont.setBold(true);
            elementAction->setFont(boldFont);
        }

        elementAction->setData(i);
        if (addKeySequence)
            elementAction->setShortcut(QKeySequence(shortcutKey));

        shortcutKey++;
        if (shortcutKey > Qt::Key_9)
            addKeySequence = false;

        ++i;
    }
    // add root item separately
//    QString itemTitle = QString(tr("%1")).arg(titleForItem(view()->currentRootItem()));
//    contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected()));
//    m_contextMenuItemList.append(view()->currentRootItem());

    contextMenu.exec(globalPos);
    m_contextMenuItemList.clear();
}

void SelectionTool::contextMenuElementSelected()
{
    QAction *senderAction = static_cast<QAction*>(sender());
    int itemListIndex = senderAction->data().toInt();
    if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {

        QPointF updatePt(0, 0);
        QGraphicsItem *item = m_contextMenuItemList.at(itemListIndex);
        m_singleSelectionManipulator.begin(updatePt);
        m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection,
                                            QList<QGraphicsItem*>() << item,
                                            false);
        m_singleSelectionManipulator.end(updatePt);
        enterContext(item);
    }
}

void SelectionTool::contextMenuElementHovered(QAction *action)
{
    int itemListIndex = action->data().toInt();
    if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {
        QGraphicsObject *item = m_contextMenuItemList.at(itemListIndex)->toGraphicsObject();
        QDeclarativeViewObserverPrivate::get(observer())->highlight(item);
    }
}

void SelectionTool::mouseMoveEvent(QMouseEvent *event)
{
    if (m_singleSelectionManipulator.isActive()) {
        QPointF mouseMovementVector = m_singleSelectionManipulator.beginPoint() - event->pos();

        if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
            && (m_mousePressTimer.elapsed() > Constants::DragStartTime))
        {
            m_singleSelectionManipulator.end(event->pos());
            //view()->changeToMoveTool(m_singleSelectionManipulator.beginPoint());
            return;
        }
    } else if (m_rubberbandSelectionManipulator.isActive()) {
        QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();

        if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
            && (m_mousePressTimer.elapsed() > Constants::DragStartTime)) {
            m_rubberbandSelectionManipulator.update(event->pos());

            if (event->modifiers().testFlag(Qt::ControlModifier))
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::RemoveFromSelection);
            else if (event->modifiers().testFlag(Qt::ShiftModifier))
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection);
            else
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection);
        }
    }
}

void SelectionTool::hoverMoveEvent(QMouseEvent * event)
{
// ### commented out until move tool is re-enabled
//    QList<QGraphicsItem*> itemList = view()->items(event->pos());
//    if (!itemList.isEmpty() && !m_rubberbandSelectionMode) {
//
//        foreach(QGraphicsItem *item, itemList) {
//            if (item->type() == Constants::ResizeHandleItemType) {
//                ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(item);
//                if (resizeHandle)
//                    view()->changeTool(Constants::ResizeToolMode);
//                return;
//            }
//        }
//        if (topSelectedItemIsMovable(itemList))
//            view()->changeTool(Constants::MoveToolMode);
//    }
    QList<QGraphicsItem*> selectableItemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());
    if (!selectableItemList.isEmpty()) {
        QGraphicsObject *item = selectableItemList.first()->toGraphicsObject();
        if (item)
            QDeclarativeViewObserverPrivate::get(observer())->highlight(item);

        return;
    }

    QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
}

void SelectionTool::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_singleSelectionManipulator.isActive()) {
        m_singleSelectionManipulator.end(event->pos());
    }
    else if (m_rubberbandSelectionManipulator.isActive()) {

        QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();
        if (mouseMovementVector.toPoint().manhattanLength() < Constants::DragStartDistance) {
            m_singleSelectionManipulator.begin(event->pos());

            if (event->modifiers().testFlag(Qt::ControlModifier))
                m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection, m_selectOnlyContentItems);
            else if (event->modifiers().testFlag(Qt::ShiftModifier))
                m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection, m_selectOnlyContentItems);
            else
                m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, m_selectOnlyContentItems);

            m_singleSelectionManipulator.end(event->pos());
        } else {
            m_rubberbandSelectionManipulator.update(event->pos());

            if (event->modifiers().testFlag(Qt::ControlModifier))
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::RemoveFromSelection);
            else if (event->modifiers().testFlag(Qt::ShiftModifier))
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection);
            else
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection);

            m_rubberbandSelectionManipulator.end();
        }
    }
}

void SelectionTool::mouseDoubleClickEvent(QMouseEvent * /*event*/)
{

}

void SelectionTool::keyPressEvent(QKeyEvent *event)
{
    switch(event->key()) {
        case Qt::Key_Left:
        case Qt::Key_Right:
        case Qt::Key_Up:
        case Qt::Key_Down:
            // disabled for now, cannot move stuff yet.
            //view()->changeTool(Constants::MoveToolMode);
            //view()->currentTool()->keyPressEvent(event);
            break;
    }
}

void SelectionTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
{

}

void SelectionTool::wheelEvent(QWheelEvent *event)
{
    if (event->orientation() == Qt::Horizontal || m_rubberbandSelectionMode)
        return;

    QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());

    if (itemList.isEmpty())
        return;

    int selectedIdx = 0;
    if (!observer()->selectedItems().isEmpty()) {
        selectedIdx = itemList.indexOf(observer()->selectedItems().first());
        if (selectedIdx >= 0) {
            if (event->delta() > 0) {
                selectedIdx++;
                if (selectedIdx == itemList.length())
                    selectedIdx = 0;
            } else if (event->delta() < 0) {
                selectedIdx--;
                if (selectedIdx == -1)
                    selectedIdx = itemList.length() - 1;
            }
        } else {
            selectedIdx = 0;
        }
    }

    QPointF updatePt(0, 0);
    m_singleSelectionManipulator.begin(updatePt);
    m_singleSelectionManipulator.select(SingleSelectionManipulator::ReplaceSelection,
                                        QList<QGraphicsItem*>() << itemList.at(selectedIdx),
                                        false);
    m_singleSelectionManipulator.end(updatePt);

}

void SelectionTool::setSelectOnlyContentItems(bool selectOnlyContentItems)
{
    m_selectOnlyContentItems = selectOnlyContentItems;
}

void SelectionTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
{

}

void SelectionTool::clear()
{
    view()->setCursor(Qt::ArrowCursor);
    m_rubberbandSelectionManipulator.clear(),
    m_singleSelectionManipulator.clear();
    m_selectionIndicator.clear();
    //m_resizeIndicator.clear();
}

void SelectionTool::selectedItemsChanged(const QList<QGraphicsItem*> &itemList)
{
    foreach(QWeakPointer<QGraphicsObject> obj, m_selectedItemList) {
        if (!obj.isNull()) {
            disconnect(obj.data(), SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
        }
    }

    QList<QGraphicsObject*> objects = toGraphicsObjectList(itemList);
    m_selectedItemList.clear();

    foreach(QGraphicsObject *obj, objects) {
        m_selectedItemList.append(obj);
        connect(obj, SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
    }

    m_selectionIndicator.setItems(m_selectedItemList);
    //m_resizeIndicator.setItems(toGraphicsObjectList(itemList));
}

void SelectionTool::repaintBoundingRects()
{
    m_selectionIndicator.setItems(m_selectedItemList);
}

void SelectionTool::selectUnderPoint(QMouseEvent *event)
{
    m_singleSelectionManipulator.begin(event->pos());

    if (event->modifiers().testFlag(Qt::ControlModifier))
        m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection, m_selectOnlyContentItems);
    else if (event->modifiers().testFlag(Qt::ShiftModifier))
        m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection, m_selectOnlyContentItems);
    else
        m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, m_selectOnlyContentItems);

    m_singleSelectionManipulator.end(event->pos());
}

}
<commit_msg>QmlJSDebugger: Simplify selection handling code<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "selectiontool.h"
#include "layeritem.h"

//#include "resizehandleitem.h"
#include "../qdeclarativeviewobserver_p.h"

#include <QDeclarativeEngine>

#include <QApplication>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QClipboard>
#include <QMenu>
#include <QAction>
#include <QDeclarativeItem>
#include <QGraphicsObject>

#include <QDebug>

namespace QmlJSDebugger {

SelectionTool::SelectionTool(QDeclarativeViewObserver *editorView)
    : AbstractFormEditorTool(editorView),
    m_rubberbandSelectionMode(false),
    m_rubberbandSelectionManipulator(QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer, editorView),
    m_singleSelectionManipulator(editorView),
    m_selectionIndicator(editorView, QDeclarativeViewObserverPrivate::get(editorView)->manipulatorLayer),
    //m_resizeIndicator(editorView->manipulatorLayer()),
    m_selectOnlyContentItems(true)
{

}

SelectionTool::~SelectionTool()
{
}

void SelectionTool::setRubberbandSelectionMode(bool value)
{
    m_rubberbandSelectionMode = value;
}

SingleSelectionManipulator::SelectionType SelectionTool::getSelectionType(Qt::KeyboardModifiers modifiers)
{
    SingleSelectionManipulator::SelectionType selectionType = SingleSelectionManipulator::ReplaceSelection;
    if (modifiers.testFlag(Qt::ControlModifier)) {
        selectionType = SingleSelectionManipulator::RemoveFromSelection;
    } else if (modifiers.testFlag(Qt::ShiftModifier)) {
        selectionType = SingleSelectionManipulator::AddToSelection;
    }
    return selectionType;
}

bool SelectionTool::alreadySelected(const QList<QGraphicsItem*> &itemList) const
{
    const QList<QGraphicsItem*> selectedItems = QDeclarativeViewObserverPrivate::get(observer())->selectedItems();

    if (selectedItems.isEmpty())
        return false;

    foreach(QGraphicsItem *item, itemList) {
        if (selectedItems.contains(item)) {
            return true;
        }
    }

    return false;
}

void SelectionTool::mousePressEvent(QMouseEvent *event)
{
    QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());
    SingleSelectionManipulator::SelectionType selectionType = getSelectionType(event->modifiers());

    if (event->buttons() & Qt::LeftButton) {
        m_mousePressTimer.start();

        if (m_rubberbandSelectionMode) {
            m_rubberbandSelectionManipulator.begin(event->pos());
        } else {
            m_singleSelectionManipulator.begin(event->pos());
            m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
        }
    } else if (event->buttons() & Qt::RightButton) {
        createContextMenu(itemList, event->globalPos());
    }
}

void SelectionTool::createContextMenu(QList<QGraphicsItem*> itemList, QPoint globalPos)
{
    if (!QDeclarativeViewObserverPrivate::get(observer())->mouseInsideContextItem())
        return;

    QMenu contextMenu;
    connect(&contextMenu, SIGNAL(hovered(QAction*)), this, SLOT(contextMenuElementHovered(QAction*)));

    m_contextMenuItemList = itemList;

    contextMenu.addAction("Items");
    contextMenu.addSeparator();
    int shortcutKey = Qt::Key_1;
    bool addKeySequence = true;
    int i = 0;

    foreach(QGraphicsItem * const item, itemList) {
        QString itemTitle = titleForItem(item);
        QAction *elementAction = contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected()));

        if (observer()->selectedItems().contains(item)) {
            QFont boldFont = elementAction->font();
            boldFont.setBold(true);
            elementAction->setFont(boldFont);
        }

        elementAction->setData(i);
        if (addKeySequence)
            elementAction->setShortcut(QKeySequence(shortcutKey));

        shortcutKey++;
        if (shortcutKey > Qt::Key_9)
            addKeySequence = false;

        ++i;
    }
    // add root item separately
//    QString itemTitle = QString(tr("%1")).arg(titleForItem(view()->currentRootItem()));
//    contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected()));
//    m_contextMenuItemList.append(view()->currentRootItem());

    contextMenu.exec(globalPos);
    m_contextMenuItemList.clear();
}

void SelectionTool::contextMenuElementSelected()
{
    QAction *senderAction = static_cast<QAction*>(sender());
    int itemListIndex = senderAction->data().toInt();
    if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {

        QPointF updatePt(0, 0);
        QGraphicsItem *item = m_contextMenuItemList.at(itemListIndex);
        m_singleSelectionManipulator.begin(updatePt);
        m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection,
                                            QList<QGraphicsItem*>() << item,
                                            false);
        m_singleSelectionManipulator.end(updatePt);
        enterContext(item);
    }
}

void SelectionTool::contextMenuElementHovered(QAction *action)
{
    int itemListIndex = action->data().toInt();
    if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {
        QGraphicsObject *item = m_contextMenuItemList.at(itemListIndex)->toGraphicsObject();
        QDeclarativeViewObserverPrivate::get(observer())->highlight(item);
    }
}

void SelectionTool::mouseMoveEvent(QMouseEvent *event)
{
    if (m_singleSelectionManipulator.isActive()) {
        QPointF mouseMovementVector = m_singleSelectionManipulator.beginPoint() - event->pos();

        if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
            && (m_mousePressTimer.elapsed() > Constants::DragStartTime))
        {
            m_singleSelectionManipulator.end(event->pos());
            //view()->changeToMoveTool(m_singleSelectionManipulator.beginPoint());
            return;
        }
    } else if (m_rubberbandSelectionManipulator.isActive()) {
        QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();

        if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
            && (m_mousePressTimer.elapsed() > Constants::DragStartTime)) {
            m_rubberbandSelectionManipulator.update(event->pos());

            if (event->modifiers().testFlag(Qt::ControlModifier))
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::RemoveFromSelection);
            else if (event->modifiers().testFlag(Qt::ShiftModifier))
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection);
            else
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection);
        }
    }
}

void SelectionTool::hoverMoveEvent(QMouseEvent * event)
{
// ### commented out until move tool is re-enabled
//    QList<QGraphicsItem*> itemList = view()->items(event->pos());
//    if (!itemList.isEmpty() && !m_rubberbandSelectionMode) {
//
//        foreach(QGraphicsItem *item, itemList) {
//            if (item->type() == Constants::ResizeHandleItemType) {
//                ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(item);
//                if (resizeHandle)
//                    view()->changeTool(Constants::ResizeToolMode);
//                return;
//            }
//        }
//        if (topSelectedItemIsMovable(itemList))
//            view()->changeTool(Constants::MoveToolMode);
//    }
    QList<QGraphicsItem*> selectableItemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());
    if (!selectableItemList.isEmpty()) {
        QGraphicsObject *item = selectableItemList.first()->toGraphicsObject();
        if (item)
            QDeclarativeViewObserverPrivate::get(observer())->highlight(item);

        return;
    }

    QDeclarativeViewObserverPrivate::get(observer())->clearHighlight();
}

void SelectionTool::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_singleSelectionManipulator.isActive()) {
        m_singleSelectionManipulator.end(event->pos());
    }
    else if (m_rubberbandSelectionManipulator.isActive()) {

        QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();
        if (mouseMovementVector.toPoint().manhattanLength() < Constants::DragStartDistance) {
            m_singleSelectionManipulator.begin(event->pos());

            if (event->modifiers().testFlag(Qt::ControlModifier))
                m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection, m_selectOnlyContentItems);
            else if (event->modifiers().testFlag(Qt::ShiftModifier))
                m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection, m_selectOnlyContentItems);
            else
                m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, m_selectOnlyContentItems);

            m_singleSelectionManipulator.end(event->pos());
        } else {
            m_rubberbandSelectionManipulator.update(event->pos());

            if (event->modifiers().testFlag(Qt::ControlModifier))
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::RemoveFromSelection);
            else if (event->modifiers().testFlag(Qt::ShiftModifier))
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection);
            else
                m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection);

            m_rubberbandSelectionManipulator.end();
        }
    }
}

void SelectionTool::mouseDoubleClickEvent(QMouseEvent * /*event*/)
{

}

void SelectionTool::keyPressEvent(QKeyEvent *event)
{
    switch(event->key()) {
        case Qt::Key_Left:
        case Qt::Key_Right:
        case Qt::Key_Up:
        case Qt::Key_Down:
            // disabled for now, cannot move stuff yet.
            //view()->changeTool(Constants::MoveToolMode);
            //view()->currentTool()->keyPressEvent(event);
            break;
    }
}

void SelectionTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
{

}

void SelectionTool::wheelEvent(QWheelEvent *event)
{
    if (event->orientation() == Qt::Horizontal || m_rubberbandSelectionMode)
        return;

    QList<QGraphicsItem*> itemList = QDeclarativeViewObserverPrivate::get(observer())->selectableItems(event->pos());

    if (itemList.isEmpty())
        return;

    int selectedIdx = 0;
    if (!observer()->selectedItems().isEmpty()) {
        selectedIdx = itemList.indexOf(observer()->selectedItems().first());
        if (selectedIdx >= 0) {
            if (event->delta() > 0) {
                selectedIdx++;
                if (selectedIdx == itemList.length())
                    selectedIdx = 0;
            } else if (event->delta() < 0) {
                selectedIdx--;
                if (selectedIdx == -1)
                    selectedIdx = itemList.length() - 1;
            }
        } else {
            selectedIdx = 0;
        }
    }

    QPointF updatePt(0, 0);
    m_singleSelectionManipulator.begin(updatePt);
    m_singleSelectionManipulator.select(SingleSelectionManipulator::ReplaceSelection,
                                        QList<QGraphicsItem*>() << itemList.at(selectedIdx),
                                        false);
    m_singleSelectionManipulator.end(updatePt);

}

void SelectionTool::setSelectOnlyContentItems(bool selectOnlyContentItems)
{
    m_selectOnlyContentItems = selectOnlyContentItems;
}

void SelectionTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
{

}

void SelectionTool::clear()
{
    view()->setCursor(Qt::ArrowCursor);
    m_rubberbandSelectionManipulator.clear(),
    m_singleSelectionManipulator.clear();
    m_selectionIndicator.clear();
    //m_resizeIndicator.clear();
}

void SelectionTool::selectedItemsChanged(const QList<QGraphicsItem*> &itemList)
{
    foreach(QWeakPointer<QGraphicsObject> obj, m_selectedItemList) {
        if (!obj.isNull()) {
            disconnect(obj.data(), SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
        }
    }

    QList<QGraphicsObject*> objects = toGraphicsObjectList(itemList);
    m_selectedItemList.clear();

    foreach(QGraphicsObject *obj, objects) {
        m_selectedItemList.append(obj);
        connect(obj, SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
    }

    m_selectionIndicator.setItems(m_selectedItemList);
    //m_resizeIndicator.setItems(toGraphicsObjectList(itemList));
}

void SelectionTool::repaintBoundingRects()
{
    m_selectionIndicator.setItems(m_selectedItemList);
}

void SelectionTool::selectUnderPoint(QMouseEvent *event)
{
    m_singleSelectionManipulator.begin(event->pos());

    if (event->modifiers().testFlag(Qt::ControlModifier))
        m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection, m_selectOnlyContentItems);
    else if (event->modifiers().testFlag(Qt::ShiftModifier))
        m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection, m_selectOnlyContentItems);
    else
        m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, m_selectOnlyContentItems);

    m_singleSelectionManipulator.end(event->pos());
}

}
<|endoftext|>