<commit_before>/*
* Copyright (c) 2003-2011 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/**
 * \file Linux-specific implementation of env.h
 */

#include <sstream>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
#include <pwd.h>

#include "../env.h"
#include "../utf8conv.h" // for pws_os::towc

stringT pws_os::getenv(const char *env, bool is_path)
{
  assert(env != NULL);
  stringT retval;
  char *value = std::getenv(env);
  if (value != NULL) {
#ifdef UNICODE
    retval = pws_os::towc(value);
#else
    retval = value;
#endif
    if (is_path) {
      // make sure path has trailing '\'
      if (retval[retval.length()-1] != charT('/'))
        retval += _S("/");
    } // is_path
  } // value != NULL
  return retval;
}

void pws_os::setenv(const char *name, const char *value)
{
  ASSERT(name != NULL && value != NULL);
  std::string envstring(name);
  envstring += "=";
  envstring += value;
  setenv(envstring.c_str());
}

stringT pws_os::getusername()
{
  stringT retval;
  struct passwd *pw_s = ::getpwuid(::getuid());
  const char *user = (pw_s != NULL) ? pw_s->pw_name : "?";
#ifdef UNICODE
  retval = pws_os::towc(user);
#else
  retval = user;
#endif
  return retval;
}

stringT pws_os::gethostname()
{
  stringT retval;
  char name[HOST_NAME_MAX];
  if (::gethostname(name, HOST_NAME_MAX) != 0) {
    assert(0);
    name[0] = '?'; name[1] = '\0';
  }
#ifdef UNICODE
  retval = pws_os::towc(name);
#else
  retval = name;
#endif
  return retval;
}

stringT pws_os::getprocessid()
{
#ifdef UNICODE
  std::wostringstream os;
#else
  std::ostringstream os;
#endif
  os.width(8);
  os.fill(charT('0'));
  os << getpid();

  return os.str();
}

void pws_os::getosversion(DWORD &major, DWORD &minor)
{
  // TBD - get info via uname()
  major = minor = 0; // XXX placeholder
}
<commit_msg>Fixed broken Linux build<commit_after>/*
* Copyright (c) 2003-2011 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/**
 * \file Linux-specific implementation of env.h
 */

#include <sstream>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
#include <pwd.h>

#include "../env.h"
#include "../utf8conv.h" // for pws_os::towc

stringT pws_os::getenv(const char *env, bool is_path)
{
  assert(env != NULL);
  stringT retval;
  char *value = std::getenv(env);
  if (value != NULL) {
#ifdef UNICODE
    retval = pws_os::towc(value);
#else
    retval = value;
#endif
    if (is_path) {
      // make sure path has trailing '\'
      if (retval[retval.length()-1] != charT('/'))
        retval += _S("/");
    } // is_path
  } // value != NULL
  return retval;
}

void pws_os::setenv(const char *name, const char *value)
{
  ASSERT(name != NULL && value != NULL);
  ::setenv(name, value, 1); // Shouldn't this be under std:: ?
}

stringT pws_os::getusername()
{
  stringT retval;
  struct passwd *pw_s = ::getpwuid(::getuid());
  const char *user = (pw_s != NULL) ? pw_s->pw_name : "?";
#ifdef UNICODE
  retval = pws_os::towc(user);
#else
  retval = user;
#endif
  return retval;
}

stringT pws_os::gethostname()
{
  stringT retval;
  char name[HOST_NAME_MAX];
  if (::gethostname(name, HOST_NAME_MAX) != 0) {
    assert(0);
    name[0] = '?'; name[1] = '\0';
  }
#ifdef UNICODE
  retval = pws_os::towc(name);
#else
  retval = name;
#endif
  return retval;
}

stringT pws_os::getprocessid()
{
#ifdef UNICODE
  std::wostringstream os;
#else
  std::ostringstream os;
#endif
  os.width(8);
  os.fill(charT('0'));
  os << getpid();

  return os.str();
}

void pws_os::getosversion(DWORD &major, DWORD &minor)
{
  // TBD - get info via uname()
  major = minor = 0; // XXX placeholder
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief threads in win32 & win64
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "threads.h"

#include "Basics/logging.h"
#include "Basics/tri-strings.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                            THREAD
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                                     private types
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief data block for thread starter
////////////////////////////////////////////////////////////////////////////////

typedef struct thread_data_s {
  void (*starter) (void*);
  void* _data;
  char* _name;
}
thread_data_t;

// -----------------------------------------------------------------------------
// --SECTION--                                                 private functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief starter function for thread
////////////////////////////////////////////////////////////////////////////////

static DWORD __stdcall ThreadStarter (void* data) {
  thread_data_t* d;

  d = (thread_data_t*) data;
  d->starter(d->_data);

  TRI_Free(TRI_CORE_MEM_ZONE, d);

  return 0;
}

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief initialises a thread
////////////////////////////////////////////////////////////////////////////////

void TRI_InitThread (TRI_thread_t* thread) {
  *thread = 0;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the current process identifier
////////////////////////////////////////////////////////////////////////////////

TRI_pid_t TRI_CurrentProcessId () {
  return _getpid();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the current thread process identifier
////////////////////////////////////////////////////////////////////////////////

TRI_tpid_t TRI_CurrentThreadProcessId () {
  return _getpid();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the current thread identifier
////////////////////////////////////////////////////////////////////////////////

TRI_tid_t TRI_CurrentThreadId () {
  return GetCurrentThreadId();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief starts a thread
////////////////////////////////////////////////////////////////////////////////

bool TRI_StartThread (TRI_thread_t* thread, TRI_tid_t* threadId, const char* name, void (*starter)(void*), void* data) {
  thread_data_t* d = static_cast<thread_data_t*>(TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(thread_data_t), false));

  if (d == nullptr) {
    return false;
  }

  d->starter = starter;
  d->_data = data;
  d->_name = TRI_DuplicateString(name);

  *thread = CreateThread(0, // default security attributes
                         0, // use default stack size
                         ThreadStarter, // thread function name
                         d, // argument to thread function
                         0, // use default creation flags
                         threadId); // returns the thread identifier

  if (*thread == 0) {
    TRI_Free(TRI_CORE_MEM_ZONE, d);
    LOG_ERROR("could not start thread: %s ", strerror(errno));
    return false;
  }

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief attempts to stop/terminate a thread
////////////////////////////////////////////////////////////////////////////////

int TRI_StopThread (TRI_thread_t* thread) {
  if (TerminateThread(*thread, 0) == 0) {
    DWORD result = GetLastError();

    LOG_ERROR("threads-win32.c:TRI_StopThread:could not stop thread -->%d", result);

    return TRI_ERROR_INTERNAL;
  }

  return TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief waits for a thread to finish
////////////////////////////////////////////////////////////////////////////////

int TRI_DetachThread (TRI_thread_t* thread) {
  // TODO: no native implementation
  return TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief waits for a thread to finish
////////////////////////////////////////////////////////////////////////////////

int TRI_JoinThread (TRI_thread_t* thread) {
  DWORD result = WaitForSingleObject(*thread, INFINITE);

  switch (result) {
    case WAIT_ABANDONED: {
      LOG_FATAL_AND_EXIT("threads-win32.c:TRI_JoinThread:could not join thread --> WAIT_ABANDONED");
    }

    case WAIT_OBJECT_0: {
      // everything ok
      break;
    }

    case WAIT_TIMEOUT: {
      LOG_FATAL_AND_EXIT("threads-win32.c:TRI_JoinThread:could not joint thread --> WAIT_TIMEOUT");
    }

    case WAIT_FAILED: {
      result = GetLastError();
      LOG_FATAL_AND_EXIT("threads-win32.c:TRI_JoinThread:could not join thread --> WAIT_FAILED - reason -->%d",result);
    }
  }

  return TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief sends a signal to a thread
////////////////////////////////////////////////////////////////////////////////

bool TRI_SignalThread (TRI_thread_t* thread, int signum) {
  // TODO:  NO NATIVE implementation of signals
  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief checks if this thread is the thread passed as a parameter
////////////////////////////////////////////////////////////////////////////////

bool TRI_IsSelfThread (TRI_thread_t* thread) {
  return false;
  // ...........................................................................
  // The GetThreadID(...) function is only available in Windows Vista or Higher
  // TODO: Change the TRI_thread_t into a structure which stores the thread id
  // as well as the thread handle. This can then be passed around
  // ...........................................................................
  //return ( GetCurrentThreadId() == GetThreadId(thread) );
}

////////////////////////////////////////////////////////////////////////////////
/// @brief allow cancellation
////////////////////////////////////////////////////////////////////////////////

void TRI_AllowCancelation(void) {
  // TODO: No native implementation of this
}

////////////////////////////////////////////////////////////////////////////////
/// @brief sets the process affinity
////////////////////////////////////////////////////////////////////////////////

void TRI_SetProcessorAffinity (size_t core) {
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>Fix signature of windows function dummy.<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief threads in win32 & win64
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "threads.h"

#include "Basics/logging.h"
#include "Basics/tri-strings.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                            THREAD
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                                     private types
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief data block for thread starter
////////////////////////////////////////////////////////////////////////////////

typedef struct thread_data_s {
  void (*starter) (void*);
  void* _data;
  char* _name;
}
thread_data_t;

// -----------------------------------------------------------------------------
// --SECTION--                                                 private functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief starter function for thread
////////////////////////////////////////////////////////////////////////////////

static DWORD __stdcall ThreadStarter (void* data) {
  thread_data_t* d;

  d = (thread_data_t*) data;
  d->starter(d->_data);

  TRI_Free(TRI_CORE_MEM_ZONE, d);

  return 0;
}

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief initialises a thread
////////////////////////////////////////////////////////////////////////////////

void TRI_InitThread (TRI_thread_t* thread) {
  *thread = 0;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the current process identifier
////////////////////////////////////////////////////////////////////////////////

TRI_pid_t TRI_CurrentProcessId () {
  return _getpid();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the current thread process identifier
////////////////////////////////////////////////////////////////////////////////

TRI_tpid_t TRI_CurrentThreadProcessId () {
  return _getpid();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the current thread identifier
////////////////////////////////////////////////////////////////////////////////

TRI_tid_t TRI_CurrentThreadId () {
  return GetCurrentThreadId();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief starts a thread
////////////////////////////////////////////////////////////////////////////////

bool TRI_StartThread (TRI_thread_t* thread, TRI_tid_t* threadId, const char* name, void (*starter)(void*), void* data) {
  thread_data_t* d = static_cast<thread_data_t*>(TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(thread_data_t), false));

  if (d == nullptr) {
    return false;
  }

  d->starter = starter;
  d->_data = data;
  d->_name = TRI_DuplicateString(name);

  *thread = CreateThread(0, // default security attributes
                         0, // use default stack size
                         ThreadStarter, // thread function name
                         d, // argument to thread function
                         0, // use default creation flags
                         threadId); // returns the thread identifier

  if (*thread == 0) {
    TRI_Free(TRI_CORE_MEM_ZONE, d);
    LOG_ERROR("could not start thread: %s ", strerror(errno));
    return false;
  }

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief attempts to stop/terminate a thread
////////////////////////////////////////////////////////////////////////////////

int TRI_StopThread (TRI_thread_t* thread) {
  if (TerminateThread(*thread, 0) == 0) {
    DWORD result = GetLastError();

    LOG_ERROR("threads-win32.c:TRI_StopThread:could not stop thread -->%d", result);

    return TRI_ERROR_INTERNAL;
  }

  return TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief waits for a thread to finish
////////////////////////////////////////////////////////////////////////////////

int TRI_DetachThread (TRI_thread_t* thread) {
  // TODO: no native implementation
  return TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief waits for a thread to finish
////////////////////////////////////////////////////////////////////////////////

int TRI_JoinThread (TRI_thread_t* thread) {
  DWORD result = WaitForSingleObject(*thread, INFINITE);

  switch (result) {
    case WAIT_ABANDONED: {
      LOG_FATAL_AND_EXIT("threads-win32.c:TRI_JoinThread:could not join thread --> WAIT_ABANDONED");
    }

    case WAIT_OBJECT_0: {
      // everything ok
      break;
    }

    case WAIT_TIMEOUT: {
      LOG_FATAL_AND_EXIT("threads-win32.c:TRI_JoinThread:could not joint thread --> WAIT_TIMEOUT");
    }

    case WAIT_FAILED: {
      result = GetLastError();
      LOG_FATAL_AND_EXIT("threads-win32.c:TRI_JoinThread:could not join thread --> WAIT_FAILED - reason -->%d",result);
    }
  }

  return TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief sends a signal to a thread
////////////////////////////////////////////////////////////////////////////////

bool TRI_SignalThread (TRI_thread_t* thread, int signum) {
  // TODO:  NO NATIVE implementation of signals
  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief checks if this thread is the thread passed as a parameter
////////////////////////////////////////////////////////////////////////////////

bool TRI_IsSelfThread (TRI_thread_t* thread) {
  return false;
  // ...........................................................................
  // The GetThreadID(...) function is only available in Windows Vista or Higher
  // TODO: Change the TRI_thread_t into a structure which stores the thread id
  // as well as the thread handle. This can then be passed around
  // ...........................................................................
  //return ( GetCurrentThreadId() == GetThreadId(thread) );
}

////////////////////////////////////////////////////////////////////////////////
/// @brief allow cancellation
////////////////////////////////////////////////////////////////////////////////

void TRI_AllowCancelation(void) {
  // TODO: No native implementation of this
}

////////////////////////////////////////////////////////////////////////////////
/// @brief sets the process affinity
////////////////////////////////////////////////////////////////////////////////

void TRI_SetProcessorAffinity (TRI_thread_t* thread, size_t core) {
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/
#include <stdio.h>
#include <math.h>
#include <float.h>

#include <osg/Drawable>
#include <osg/State>
#include <osg/Notify>
#include <osg/Node>

#include <algorithm>
#include <map>
#include <set>

using namespace osg;

// static cache of deleted display lists which can only
// by completely deleted once the appropriate OpenGL context
// is set.  Used osg::Drawable::deleteDisplayList(..) and flushDeletedDisplayLists(..) below.
typedef std::vector<GLuint> DisplayListVector;
typedef std::map<GLuint,DisplayListVector> DeletedDisplayListCache;
static DeletedDisplayListCache s_deletedDisplayListCache;

void Drawable::deleteDisplayList(uint contextID,uint globj)
{
    if (globj!=0)
    {
        // insert the globj into the cache for the appropriate context.
        s_deletedDisplayListCache[contextID].push_back(globj);
    }
}

/** flush all the cached display list which need to be deleted
  * in the OpenGL context related to contextID.*/
void Drawable::flushDeletedDisplayLists(uint contextID)
{
    DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID);
    if (citr!=s_deletedDisplayListCache.end())
    {
        DisplayListVector displayListSet;

        // this swap will transfer the content of and empty citr->second
        // in one quick pointer change.
        displayListSet.swap(citr->second);

        for(std::DisplayListVector::iterator gitr=displayListSet.begin();
                                     gitr!=displayListSet.end();
                                     ++gitr)
        {
            glDeleteLists(*gitr,1);
        }
    }
}

Drawable::Drawable()
{
    _bbox_computed = false;

    // Note, if your are defining a subclass from drawable which is
    // dynamically updated then you should set both the following to
    // to false in your constructor.  This will prevent any display
    // lists from being automatically created and safeguard the
    // dynamic updating of data.
    _supportsDisplayList = true;
    _useDisplayList = true;
}

Drawable::Drawable(const Drawable& drawable,const CopyOp& copyop):
    Object(drawable,copyop),
    _parents(), // leave empty as parentList is managed by Geode
    _stateset(copyop(drawable._stateset.get())),
    _bbox(drawable._bbox),
    _bbox_computed(drawable._bbox_computed),
    _shape(copyop(drawable._shape.get())),
    _supportsDisplayList(drawable._supportsDisplayList),
    _useDisplayList(drawable._useDisplayList),
    _drawCallback(drawable._drawCallback),
    _cullCallback(drawable._cullCallback)
{
}

Drawable::~Drawable()
{
    dirtyDisplayList();
}

void Drawable::addParent(osg::Node* node)
{
    _parents.push_back(node);
}

void Drawable::removeParent(osg::Node* node)
{
    ParentList::iterator pitr = std::find(_parents.begin(),_parents.end(),node);
    if (pitr!=_parents.end()) _parents.erase(pitr);
}

osg::StateSet* Drawable::getOrCreateStateSet()
{
    if (!_stateset) _stateset = new StateSet;
    return _stateset.get();
}

void Drawable::dirtyBound()
{
    if (_bbox_computed)
    {
        _bbox_computed = false;

        // dirty parent bounding sphere's to ensure that all are valid.
        for(ParentList::iterator itr=_parents.begin();
            itr!=_parents.end();
            ++itr)
        {
            (*itr)->dirtyBound();
        }

    }
}

void Drawable::compile(State& state) const
{
    if (!_useDisplayList) return;

    // get the contextID (user defined ID of 0 upwards) for the
    // current OpenGL context.
    uint contextID = state.getContextID();

    // get the globj for the current contextID.
    uint& globj = _globjList[contextID];

    // call the globj if already set otherwise comple and execute.
    if( globj != 0 )
    {
        glDeleteLists( globj, 1 );
    }

    if (_stateset.valid())
    {
        _stateset->compile(state);
    }

    globj = glGenLists( 1 );
    glNewList( globj, GL_COMPILE );

    if (_drawCallback.valid())
        _drawCallback->drawImplementation(state,this);
    else
        drawImplementation(state);

    glEndList();

}

void Drawable::setSupportsDisplayList(bool flag)
{
    // if value unchanged simply return.
    if (_supportsDisplayList==flag) return;

    // if previously set to true then need to check about display lists.
    if (_supportsDisplayList)
    {
        if (_useDisplayList)
        {
            // used to support display lists and display lists switched
            // on so now delete them and turn useDisplayList off.
            dirtyDisplayList();
            _useDisplayList = false;
        }
    }

    // set with new value.
    _supportsDisplayList=flag;
}

void Drawable::setUseDisplayList(bool flag)
{
    // if value unchanged simply return.
    if (_useDisplayList==flag) return;

    // if was previously set to true, remove display list.
    if (_useDisplayList)
    {
        dirtyDisplayList();
    }

    if (_supportsDisplayList)
    {

        // set with new value.
        _useDisplayList = flag;

    }
    else // does not support display lists.
    {
        if (flag)
        {
            notify(WARN)<<"Warning: attempt to setUseDisplayList(true) on a drawable with does not support display lists."<<std::endl;
        }
        else
        {
            // set with new value.
            _useDisplayList = false;
        }
    }
}

void Drawable::dirtyDisplayList()
{
    for(uint i=0;i<_globjList.size();++i)
    {
        if (_globjList[i] != 0)
        {
            Drawable::deleteDisplayList(i,_globjList[i]);
            _globjList[i] = 0;
        }
    }
}

void Drawable::setUpdateCallback(UpdateCallback* ac)
{
    if (_updateCallback==ac) return;

    int delta = 0;
    if (_updateCallback.valid()) --delta;
    if (ac) ++delta;

    _updateCallback = ac;

    if (delta!=0)
    {
        for(ParentList::iterator itr=_parents.begin();
            itr!=_parents.end();
            ++itr)
        {
            (*itr)->setNumChildrenRequiringUpdateTraversal((*itr)->getNumChildrenRequiringUpdateTraversal()+delta);
        }
    }
}

struct ComputeBound : public Drawable::PrimitiveFunctor
{
        ComputeBound():_vertices(0) {}

        virtual void setVertexArray(unsigned int,const Vec3* vertices) { _vertices = vertices; }

        virtual void drawArrays(GLenum,GLint first,GLsizei count)
        {
            if (_vertices)
            {
                const osg::Vec3* vert = _vertices+first;
                for(;count>0;--count,++vert)
                {
                    _bb.expandBy(*vert);
                }
            }
        }

        virtual void drawElements(GLenum,GLsizei count,const GLubyte* indices)
        {
            if (_vertices)
            {
                for(;count>0;--count,++indices)
                {
                    _bb.expandBy(_vertices[*indices]);
                }
            }
        }

        virtual void drawElements(GLenum,GLsizei count,const GLushort* indices)
        {
            if (_vertices)
            {
                for(;count>0;--count,++indices)
                {
                    _bb.expandBy(_vertices[*indices]);
                }
            }
        }

        virtual void drawElements(GLenum,GLsizei count,const GLuint* indices)
        {
            if (_vertices)
            {
                for(;count>0;--count,++indices)
                {
                    _bb.expandBy(_vertices[*indices]);
                }
            }
        }

        virtual void begin(GLenum) {}
        virtual void vertex(const Vec3& vert) { _bb.expandBy(vert); }
        virtual void vertex(float x,float y,float z) { _bb.expandBy(x,y,z); }
        virtual void end() {}

        const Vec3*     _vertices;
        BoundingBox     _bb;
};

bool Drawable::computeBound() const
{
    ComputeBound cb;

    Drawable* non_const_this = const_cast<Drawable*>(this);
    non_const_this->accept(cb);

    _bbox = cb._bb;
    _bbox_computed = true;

    return true;
}

<commit_msg>Removed eroneous std:: from the from of DisplayListVector.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/
#include <stdio.h>
#include <math.h>
#include <float.h>

#include <osg/Drawable>
#include <osg/State>
#include <osg/Notify>
#include <osg/Node>

#include <algorithm>
#include <map>
#include <set>

using namespace osg;

// static cache of deleted display lists which can only
// by completely deleted once the appropriate OpenGL context
// is set.  Used osg::Drawable::deleteDisplayList(..) and flushDeletedDisplayLists(..) below.
typedef std::vector<GLuint> DisplayListVector;
typedef std::map<GLuint,DisplayListVector> DeletedDisplayListCache;
static DeletedDisplayListCache s_deletedDisplayListCache;

void Drawable::deleteDisplayList(uint contextID,uint globj)
{
    if (globj!=0)
    {
        // insert the globj into the cache for the appropriate context.
        s_deletedDisplayListCache[contextID].push_back(globj);
    }
}

/** flush all the cached display list which need to be deleted
  * in the OpenGL context related to contextID.*/
void Drawable::flushDeletedDisplayLists(uint contextID)
{
    DeletedDisplayListCache::iterator citr = s_deletedDisplayListCache.find(contextID);
    if (citr!=s_deletedDisplayListCache.end())
    {
        DisplayListVector displayListSet;

        // this swap will transfer the content of and empty citr->second
        // in one quick pointer change.
        displayListSet.swap(citr->second);

        for(DisplayListVector::iterator gitr=displayListSet.begin();
                                     gitr!=displayListSet.end();
                                     ++gitr)
        {
            glDeleteLists(*gitr,1);
        }
    }
}

Drawable::Drawable()
{
    _bbox_computed = false;

    // Note, if your are defining a subclass from drawable which is
    // dynamically updated then you should set both the following to
    // to false in your constructor.  This will prevent any display
    // lists from being automatically created and safeguard the
    // dynamic updating of data.
    _supportsDisplayList = true;
    _useDisplayList = true;
}

Drawable::Drawable(const Drawable& drawable,const CopyOp& copyop):
    Object(drawable,copyop),
    _parents(), // leave empty as parentList is managed by Geode
    _stateset(copyop(drawable._stateset.get())),
    _bbox(drawable._bbox),
    _bbox_computed(drawable._bbox_computed),
    _shape(copyop(drawable._shape.get())),
    _supportsDisplayList(drawable._supportsDisplayList),
    _useDisplayList(drawable._useDisplayList),
    _drawCallback(drawable._drawCallback),
    _cullCallback(drawable._cullCallback)
{
}

Drawable::~Drawable()
{
    dirtyDisplayList();
}

void Drawable::addParent(osg::Node* node)
{
    _parents.push_back(node);
}

void Drawable::removeParent(osg::Node* node)
{
    ParentList::iterator pitr = std::find(_parents.begin(),_parents.end(),node);
    if (pitr!=_parents.end()) _parents.erase(pitr);
}

osg::StateSet* Drawable::getOrCreateStateSet()
{
    if (!_stateset) _stateset = new StateSet;
    return _stateset.get();
}

void Drawable::dirtyBound()
{
    if (_bbox_computed)
    {
        _bbox_computed = false;

        // dirty parent bounding sphere's to ensure that all are valid.
        for(ParentList::iterator itr=_parents.begin();
            itr!=_parents.end();
            ++itr)
        {
            (*itr)->dirtyBound();
        }

    }
}

void Drawable::compile(State& state) const
{
    if (!_useDisplayList) return;

    // get the contextID (user defined ID of 0 upwards) for the
    // current OpenGL context.
    uint contextID = state.getContextID();

    // get the globj for the current contextID.
    uint& globj = _globjList[contextID];

    // call the globj if already set otherwise comple and execute.
    if( globj != 0 )
    {
        glDeleteLists( globj, 1 );
    }

    if (_stateset.valid())
    {
        _stateset->compile(state);
    }

    globj = glGenLists( 1 );
    glNewList( globj, GL_COMPILE );

    if (_drawCallback.valid())
        _drawCallback->drawImplementation(state,this);
    else
        drawImplementation(state);

    glEndList();

}

void Drawable::setSupportsDisplayList(bool flag)
{
    // if value unchanged simply return.
    if (_supportsDisplayList==flag) return;

    // if previously set to true then need to check about display lists.
    if (_supportsDisplayList)
    {
        if (_useDisplayList)
        {
            // used to support display lists and display lists switched
            // on so now delete them and turn useDisplayList off.
            dirtyDisplayList();
            _useDisplayList = false;
        }
    }

    // set with new value.
    _supportsDisplayList=flag;
}

void Drawable::setUseDisplayList(bool flag)
{
    // if value unchanged simply return.
    if (_useDisplayList==flag) return;

    // if was previously set to true, remove display list.
    if (_useDisplayList)
    {
        dirtyDisplayList();
    }

    if (_supportsDisplayList)
    {

        // set with new value.
        _useDisplayList = flag;

    }
    else // does not support display lists.
    {
        if (flag)
        {
            notify(WARN)<<"Warning: attempt to setUseDisplayList(true) on a drawable with does not support display lists."<<std::endl;
        }
        else
        {
            // set with new value.
            _useDisplayList = false;
        }
    }
}

void Drawable::dirtyDisplayList()
{
    for(uint i=0;i<_globjList.size();++i)
    {
        if (_globjList[i] != 0)
        {
            Drawable::deleteDisplayList(i,_globjList[i]);
            _globjList[i] = 0;
        }
    }
}

void Drawable::setUpdateCallback(UpdateCallback* ac)
{
    if (_updateCallback==ac) return;

    int delta = 0;
    if (_updateCallback.valid()) --delta;
    if (ac) ++delta;

    _updateCallback = ac;

    if (delta!=0)
    {
        for(ParentList::iterator itr=_parents.begin();
            itr!=_parents.end();
            ++itr)
        {
            (*itr)->setNumChildrenRequiringUpdateTraversal((*itr)->getNumChildrenRequiringUpdateTraversal()+delta);
        }
    }
}

struct ComputeBound : public Drawable::PrimitiveFunctor
{
        ComputeBound():_vertices(0) {}

        virtual void setVertexArray(unsigned int,const Vec3* vertices) { _vertices = vertices; }

        virtual void drawArrays(GLenum,GLint first,GLsizei count)
        {
            if (_vertices)
            {
                const osg::Vec3* vert = _vertices+first;
                for(;count>0;--count,++vert)
                {
                    _bb.expandBy(*vert);
                }
            }
        }

        virtual void drawElements(GLenum,GLsizei count,const GLubyte* indices)
        {
            if (_vertices)
            {
                for(;count>0;--count,++indices)
                {
                    _bb.expandBy(_vertices[*indices]);
                }
            }
        }

        virtual void drawElements(GLenum,GLsizei count,const GLushort* indices)
        {
            if (_vertices)
            {
                for(;count>0;--count,++indices)
                {
                    _bb.expandBy(_vertices[*indices]);
                }
            }
        }

        virtual void drawElements(GLenum,GLsizei count,const GLuint* indices)
        {
            if (_vertices)
            {
                for(;count>0;--count,++indices)
                {
                    _bb.expandBy(_vertices[*indices]);
                }
            }
        }

        virtual void begin(GLenum) {}
        virtual void vertex(const Vec3& vert) { _bb.expandBy(vert); }
        virtual void vertex(float x,float y,float z) { _bb.expandBy(x,y,z); }
        virtual void end() {}

        const Vec3*     _vertices;
        BoundingBox     _bb;
};

bool Drawable::computeBound() const
{
    ComputeBound cb;

    Drawable* non_const_this = const_cast<Drawable*>(this);
    non_const_this->accept(cb);

    _bbox = cb._bb;
    _bbox_computed = true;

    return true;
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <stdexcept>

#include <sal/types.h>

#include <rtl/ustring.hxx>

#include <ToxWhitespaceStripper.hxx>

#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/plugin/TestPlugIn.h>

using namespace sw;

class ToxWhitespaceStripperTest : public CppUnit::TestFixture
{
    void
    MappingCharactersToVariousStrippedStringsWorks();

    void
    StrippingWhitespacesFromVariousStringsWorks();

    void
    PositionAfterStringCanBeRequested();

    CPPUNIT_TEST_SUITE(ToxWhitespaceStripperTest);
    CPPUNIT_TEST(MappingCharactersToVariousStrippedStringsWorks);
    CPPUNIT_TEST(StrippingWhitespacesFromVariousStringsWorks);
    CPPUNIT_TEST(PositionAfterStringCanBeRequested);

    CPPUNIT_TEST_SUITE_END();

};

void
ToxWhitespaceStripperTest::MappingCharactersToVariousStrippedStringsWorks()
{
    {
        OUString test("abc\n");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(0, sut.GetPositionInStrippedString(0));
        CPPUNIT_ASSERT_EQUAL(1, sut.GetPositionInStrippedString(1));
        CPPUNIT_ASSERT_EQUAL(2, sut.GetPositionInStrippedString(2));
        CPPUNIT_ASSERT_EQUAL(3, sut.GetPositionInStrippedString(3));
    }
    {
        OUString test("abc\n\n");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(0, sut.GetPositionInStrippedString(0));
        CPPUNIT_ASSERT_EQUAL(1, sut.GetPositionInStrippedString(1));
        CPPUNIT_ASSERT_EQUAL(2, sut.GetPositionInStrippedString(2));
        CPPUNIT_ASSERT_EQUAL(3, sut.GetPositionInStrippedString(3));
        CPPUNIT_ASSERT_EQUAL(3, sut.GetPositionInStrippedString(4));
    }
    {
        OUString test("abc\ndef");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(0, sut.GetPositionInStrippedString(0));
        CPPUNIT_ASSERT_EQUAL(1, sut.GetPositionInStrippedString(1));
        CPPUNIT_ASSERT_EQUAL(2, sut.GetPositionInStrippedString(2));
        CPPUNIT_ASSERT_EQUAL(3, sut.GetPositionInStrippedString(3));
        CPPUNIT_ASSERT_EQUAL(4, sut.GetPositionInStrippedString(4));
        CPPUNIT_ASSERT_EQUAL(5, sut.GetPositionInStrippedString(5));
        CPPUNIT_ASSERT_EQUAL(6, sut.GetPositionInStrippedString(6));
    }
    {
        //             012345 6789
        OUString test("  abc \ndef");
        //             01234567
        //            " abc def"
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(0, sut.GetPositionInStrippedString(0));
        CPPUNIT_ASSERT_EQUAL(0, sut.GetPositionInStrippedString(1));
        CPPUNIT_ASSERT_EQUAL(1, sut.GetPositionInStrippedString(2));
        CPPUNIT_ASSERT_EQUAL(2, sut.GetPositionInStrippedString(3));
        CPPUNIT_ASSERT_EQUAL(3, sut.GetPositionInStrippedString(4));
        CPPUNIT_ASSERT_EQUAL(4, sut.GetPositionInStrippedString(5));
        CPPUNIT_ASSERT_EQUAL(4, sut.GetPositionInStrippedString(6));
        CPPUNIT_ASSERT_EQUAL(5, sut.GetPositionInStrippedString(7));
        CPPUNIT_ASSERT_EQUAL(6, sut.GetPositionInStrippedString(8));
        CPPUNIT_ASSERT_EQUAL(7, sut.GetPositionInStrippedString(9));
    }
}

void
ToxWhitespaceStripperTest::StrippingWhitespacesFromVariousStringsWorks()
{
    {
        OUString test("abc\n");
        OUString expected("abc");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
    {
        OUString test("abc\n\n");
        OUString expected("abc");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
    {
        OUString test("abc\ndef");
        OUString expected("abc def");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
    {
        OUString test("  abc \ndef");
        OUString expected(" abc def");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
    {
        OUString test("  ");
        OUString expected("");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
    {
        OUString test("d  ");
        OUString expected("d");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
}

void
ToxWhitespaceStripperTest::PositionAfterStringCanBeRequested()
{
    OUString test("abc");
    ToxWhitespaceStripper sut(test);
    sal_Int32 expected = test.getLength();
    CPPUNIT_ASSERT_EQUAL(expected, sut.GetPositionInStrippedString(test.getLength()));
}

// Put the test suite in the registry
CPPUNIT_TEST_SUITE_REGISTRATION(ToxWhitespaceStripperTest);

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>C2782: we hate you sal_Int32 as long on 32bit<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <stdexcept>

#include <sal/types.h>

#include <rtl/ustring.hxx>

#include <ToxWhitespaceStripper.hxx>

#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/plugin/TestPlugIn.h>

using namespace sw;

class ToxWhitespaceStripperTest : public CppUnit::TestFixture
{
    void
    MappingCharactersToVariousStrippedStringsWorks();

    void
    StrippingWhitespacesFromVariousStringsWorks();

    void
    PositionAfterStringCanBeRequested();

    CPPUNIT_TEST_SUITE(ToxWhitespaceStripperTest);
    CPPUNIT_TEST(MappingCharactersToVariousStrippedStringsWorks);
    CPPUNIT_TEST(StrippingWhitespacesFromVariousStringsWorks);
    CPPUNIT_TEST(PositionAfterStringCanBeRequested);

    CPPUNIT_TEST_SUITE_END();

};

void
ToxWhitespaceStripperTest::MappingCharactersToVariousStrippedStringsWorks()
{
    {
        OUString test("abc\n");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), sut.GetPositionInStrippedString(0));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), sut.GetPositionInStrippedString(1));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), sut.GetPositionInStrippedString(2));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), sut.GetPositionInStrippedString(3));
    }
    {
        OUString test("abc\n\n");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), sut.GetPositionInStrippedString(0));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), sut.GetPositionInStrippedString(1));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), sut.GetPositionInStrippedString(2));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), sut.GetPositionInStrippedString(3));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), sut.GetPositionInStrippedString(4));
    }
    {
        OUString test("abc\ndef");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), sut.GetPositionInStrippedString(0));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), sut.GetPositionInStrippedString(1));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), sut.GetPositionInStrippedString(2));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), sut.GetPositionInStrippedString(3));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), sut.GetPositionInStrippedString(4));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(5), sut.GetPositionInStrippedString(5));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(6), sut.GetPositionInStrippedString(6));
    }
    {
        //             012345 6789
        OUString test("  abc \ndef");
        //             01234567
        //            " abc def"
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), sut.GetPositionInStrippedString(0));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), sut.GetPositionInStrippedString(1));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), sut.GetPositionInStrippedString(2));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), sut.GetPositionInStrippedString(3));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), sut.GetPositionInStrippedString(4));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), sut.GetPositionInStrippedString(5));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), sut.GetPositionInStrippedString(6));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(5), sut.GetPositionInStrippedString(7));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(6), sut.GetPositionInStrippedString(8));
        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(7), sut.GetPositionInStrippedString(9));
    }
}

void
ToxWhitespaceStripperTest::StrippingWhitespacesFromVariousStringsWorks()
{
    {
        OUString test("abc\n");
        OUString expected("abc");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
    {
        OUString test("abc\n\n");
        OUString expected("abc");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
    {
        OUString test("abc\ndef");
        OUString expected("abc def");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
    {
        OUString test("  abc \ndef");
        OUString expected(" abc def");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
    {
        OUString test("  ");
        OUString expected("");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
    {
        OUString test("d  ");
        OUString expected("d");
        ToxWhitespaceStripper sut(test);
        CPPUNIT_ASSERT_EQUAL(expected, sut.GetStrippedString());
    }
}

void
ToxWhitespaceStripperTest::PositionAfterStringCanBeRequested()
{
    OUString test("abc");
    ToxWhitespaceStripper sut(test);
    sal_Int32 expected = test.getLength();
    CPPUNIT_ASSERT_EQUAL(expected, sut.GetPositionInStrippedString(test.getLength()));
}

// Put the test suite in the registry
CPPUNIT_TEST_SUITE_REGISTRATION(ToxWhitespaceStripperTest);

CPPUNIT_PLUGIN_IMPLEMENT();

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


<commit_before>/***************************************************************************
**
** Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QList>
#include <QVector>
#include <QPropertyAnimation>
#include <QStyleOptionGraphicsItem>

#include <QGestureEvent>
#include <QTapAndHoldGesture>

#include <MList>
#include <MWidgetView>
#include <MSeparator>
#include <MPannableViewport>

#include "mlistview.h"
#include "mlistview_p.h"

//// MListView /////
MListView::MListView(MWidgetController *widgetController)
    : MWidgetView(widgetController),
    d_ptr(NULL)
{
    controller = dynamic_cast<MList *>(widgetController);
}

MListView::~MListView()
{
    if (d_ptr) {
        if (!model()->headerCreator())
            delete d_ptr->headersCreator;

        delete d_ptr;
    }
}

void MListView::init()
{
    Q_ASSERT(controller);

    MCellCreator *headersCreator = NULL;

    if(d_ptr) {
        d_ptr->disconnectSignalsFromModelToListView();
        headersCreator = d_ptr->headersCreator;

        // Schedule deletion as we might have some events pending for delivery.
        d_ptr->destroy();
    }

    if (model()->columns() > 1) {
        if (model()->showGroups())
            d_ptr = new MMultiColumnListViewPrivate;
        else
            d_ptr = new MPlainMultiColumnListViewPrivate;
    } else {
        if (model()->showGroups())
            d_ptr = new MGroupHeaderListViewPrivate;
        else
            d_ptr = new MPlainListViewPrivate;
    }

    if (model()->headerCreator()) {
        d_ptr->setHeadersCreator(model()->headerCreator());
        if (model()->headerCreator() != headersCreator)
            delete headersCreator;
    } else
        d_ptr->setHeadersCreator(headersCreator);

    d_ptr->q_ptr = this;
    d_ptr->controller = dynamic_cast<MList *>(controller);
    d_ptr->createSeparators();
    d_ptr->updateSeparators();
    d_ptr->updateSeparatorSize();
    d_ptr->updateAnimations();

    connectSelectionModel();
    d_ptr->connectPannableViewport();

    d_ptr->resetModel(model());
}

void MListView::updateData(const QList<const char *>& modifications)
{
    MWidgetView::updateData(modifications);

    const char *member;
    for (int i = 0; i < modifications.count(); i++) {
        member = modifications[i];

        if (member == MListModel::ItemModel || member == MListModel::ShowGroups || member == MListModel::Columns || member == MListModel::CellCreator ||
            member == MListModel::HeaderCreator) {
            if (model()->itemModel()) {
                init();
                if (d_ptr->pannableViewport) {
                    d_ptr->updateListGeometry();
                } else {
                    // Postpone the update of the list geometry to the next
                    // event loop, otherwise too many cells get created without
                    // having a pannable viewport.
                    QTimer::singleShot(0, d_ptr, SLOT(updateListGeometry()));
                }
            }
        } else if (member == MListModel::SelectionModel) {
            connectSelectionModel();
        } else if (member == MListModel::ScrollToIndex) {
            scrollTo(model()->scrollToIndex(),
                     static_cast<MList::ScrollHint>(model()->scrollHint()),
                     static_cast<MList::AnimationMode>(model()->animationMode()));
        } else if (member == MListModel::LongTap) {
            longTap(model()->longTap());
        } else if (member == MListModel::ListIndexDisplayMode) {
            d_ptr->updateListIndexVisibility();
        } else if (member == MListModel::LongTapEnabled) {
            d_ptr->updateItemConnections();
        }
    }
}

void MListView::connectSelectionModel()
{
    if (d_ptr->selectionModel)
        d_ptr->selectionModel->disconnect(this);

    if (model()->selectionModel()) {
        connect(model()->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
                this, SLOT(selectionChanged(QItemSelection, QItemSelection)));
    }

    d_ptr->selectionModel = model()->selectionModel();
}

void MListView::setupModel()
{
    MWidgetView::setupModel();

    init();
    updateGeometry();
}

void MListView::applyStyle()
{
    MWidgetView::applyStyle();

    if (d_ptr) {
        d_ptr->clearVisibleItemsArray();
        d_ptr->updateAnimations();
        d_ptr->updateItemHeight();
        d_ptr->updateSeparators();
        d_ptr->updateSeparatorSize();
        d_ptr->updateHeaders();
        d_ptr->updateHeaderHeight();
        d_ptr->updateListIndexStyle();

        relayoutItemsInViewportRect();
    }
}

void MListView::notifyItemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
    MWidgetView::notifyItemChange(change, value);

    if(change == QGraphicsItem::ItemSceneHasChanged)
        emit controller->parentChanged();
}

QSizeF MListView::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
    if (!d_ptr)
        return MWidgetView::sizeHint(which, constraint);

    return QSizeF(-1, d_ptr->totalHeight());
}

void MListView::setGeometry(const QRectF &rect)
{
    if (d_ptr) {
        if (!d_ptr->pannableViewport)
            d_ptr->viewportVisibleHeight = d_ptr->totalHeight();

        d_ptr->updatePannableViewportPosition();

        if (d_ptr->lastGeometrySize != rect.size() || d_ptr->clearVisibleOnRelayout) {
            d_ptr->viewWidth = rect.width();
            d_ptr->updateItemSize();
            d_ptr->updateSeparatorSize();

            if (d_ptr->lockPosition) {
                d_ptr->lockPosition = false;
                if (d_ptr->pannableViewport) {
                    qreal heightDelta = rect.size().height() - d_ptr->lastGeometrySize.height();
                    QPointF lockedViewportPosition = d_ptr->pannableViewport->position() + QPointF(0, heightDelta);
                    if (heightDelta != 0 && d_ptr->pannableViewport->range().contains(lockedViewportPosition))
                        d_ptr->pannableViewport->physics()->setPosition(lockedViewportPosition, false);
                }
            }

            relayoutItemsInViewportRect();

            d_ptr->scrollToLastIndex();
            d_ptr->lastGeometrySize = rect.size();
        }
    }

    MWidgetView::setGeometry(rect);
}

void MListView::relayoutItemsInViewportRect()
{
    if (d_ptr->clearVisibleOnRelayout) {
        d_ptr->clearVisibleItemsArray();
        d_ptr->clearFirstAndLastVisibleRows();
        d_ptr->clearVisibleOnRelayout = false;
    }

    if (d_ptr->model && model()->cellCreator()) {
        int rowCount = d_ptr->rowCount;

        if (rowCount) {
            QModelIndex firstVisibleIndex = d_ptr->locateVisibleIndexAt(d_ptr->viewportTopLeft.y());
            d_ptr->updateFirstVisibleRow(firstVisibleIndex);
            QModelIndex lastVisibleIndex = d_ptr->locateLastVisibleIndexInRowAt(d_ptr->viewportTopLeft.y() + d_ptr->viewportVisibleHeight);
            d_ptr->updateLastVisibleRow(lastVisibleIndex);

            QPoint firstVisibleItemPos(0, d_ptr->locatePosOfItem(firstVisibleIndex));
            QPoint lastVisibleItemPos(0, d_ptr->locatePosOfItem(lastVisibleIndex));
            d_ptr->removeInvisibleItems(firstVisibleItemPos, lastVisibleItemPos);

            d_ptr->createVisibleItems(firstVisibleIndex, lastVisibleIndex);
        } else {
            d_ptr->clearVisibleItemsArray();
            d_ptr->clearFirstAndLastVisibleRows();
        }
    }
}

void MListView::drawForeground(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    Q_UNUSED(painter);
    Q_UNUSED(option);
}

void MListView::drawBackground(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    if (!d_ptr->clearVisibleOnRelayout)
        d_ptr->drawSeparators(painter, option);
}

void MListView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    if (d_ptr->clearVisibleOnRelayout || (!model()->firstVisibleItem().isValid() && !model()->lastVisibleItem().isValid()))
        return;

    if (d_ptr->controller->isVisible()) {
        const MCellCreator *cellCreator = model()->cellCreator();

        int firstVisibleRow = d_ptr->indexToFlatRow(model()->firstVisibleItem());
        int lastVisibleRow = d_ptr->indexToFlatRow(model()->lastVisibleItem());
        int topLeftRow = d_ptr->indexToFlatRow(topLeft);
        int bottomRightRow = d_ptr->indexToFlatRow(bottomRight);

        int top = qMax(topLeftRow, firstVisibleRow);
        int lastCellInLastVisibleRow = lastVisibleRow + model()->columns() - lastVisibleRow % model()->columns() - 1;
        int bottom = qMin(bottomRightRow, lastCellInLastVisibleRow);

        for (int i = top; i <= bottom; i++) {
            QModelIndex cellIndex = d_ptr->flatRowToIndex(i);
            if (!d_ptr->isGroupHeader(cellIndex)) {
                MWidget *cell = d_ptr->findCellAtRow(i);
                if (cell) {
                    if( (controller->optimizationFlags() & MList::DontCallCreateCellDuringUpdate) == MList::DontCallCreateCellDuringUpdate) {
                        cellCreator->updateCell(cellIndex, cell);
                    } else {
                        MWidget* newCell = d_ptr->createCell(i);
                        d_ptr->replaceItem(cell, newCell);
                    }
                }
            }
        }
    } else {
        d_ptr->clearVisibleOnRelayout = true;
    }
}

/*!
 * This slot is called when items are inserted under the given \a parent.
 * The changed items are those from \a start to \a end inclusive.
 *
 * \sa QAbstractItemView::rowsInserted(), exposedRectUpdated()
 */
void MListView::rowsInserted(const QModelIndex &parent, int start, int end, bool animated)
{
    if (!d_ptr->animateRowsInsertion(parent, start, end, animated)) {
        int first = d_ptr->indexToFlatRow(model()->firstVisibleItem());
        start = d_ptr->indexToFlatRow(model()->itemModel()->index(start, 0, parent));
        end = d_ptr->indexToFlatRow(model()->itemModel()->index(end, 0, parent));
        d_ptr->lockPosition = (start < first && end < first);
        layoutChanged();
    }
}

/*!
 * This slot is called when items under the given \a parent are removed.
 * The removed items are those from \a start to \a end inclusive.
 *
 * \sa rowsInserted(), exposedRectUpdated()
 */
void MListView::rowsRemoved(const QModelIndex &parent, int start, int end, bool animated)
{
    if (!d_ptr->animateRowsRemoval(parent, start, end, animated)) {
        int first = d_ptr->indexToFlatRow(model()->firstVisibleItem());
        start = d_ptr->indexToFlatRow(model()->itemModel()->index(start, 0, parent));
        end = d_ptr->indexToFlatRow(model()->itemModel()->index(end, 0, parent));
        d_ptr->lockPosition = (start < first && end < first);
        layoutChanged();
    }
}

void MListView::layoutChanged()
{
    if (!d_ptr->isAnimating()) {
        d_ptr->layoutChanged();

        d_ptr->clearVisibleOnRelayout = true;
        d_ptr->clearFirstAndLastVisibleRows();
        updateGeometry();

        d_ptr->lastScrolledToFlatRow = -1;
    }
}

void MListView::modelReset()
{
    layoutChanged();
}

void MListView::rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
                                const QModelIndex &destinationParent, int destinationRow)
{
    Q_UNUSED(sourceParent);
    Q_UNUSED(sourceStart);
    Q_UNUSED(sourceEnd);
    Q_UNUSED(destinationParent);
    Q_UNUSED(destinationRow);

    layoutChanged();
}

void MListView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
    d_ptr->selectionChange(selected, deselected);
}

void MListView::itemClick()
{
    QObject *s = sender();
    MWidget *senderWidget = qobject_cast<MWidget *>(s);
    if (senderWidget)
        d_ptr->cellClicked(senderWidget);
}

void MListView::scrollTo(const QModelIndex &index, MList::ScrollHint hint, MList::AnimationMode mode)
{
    if (index.isValid()) {
        int row = d_ptr->indexToFlatRow(index);
        scrollTo(row, hint, mode);
    }
}

void MListView::scrollTo(int row, MList::ScrollHint hint, MList::AnimationMode mode)
{
    if (row >= 0) {
        d_ptr->lastScrolledToFlatRow = row;
        if (d_ptr->pannableViewport) {
            QPointF targetPosition = d_ptr->locateScrollToPosition(row, hint);

            if (targetPosition != d_ptr->pannableViewport->position())
                d_ptr->scrollToPos(targetPosition, mode);
        }
    }
}

void MListView::longTap(const QPointF &pos)
{
    QPointF relativePos = d_ptr->controller->mapFromScene(pos);
    QModelIndex index = d_ptr->flatRowToIndex(d_ptr->locateVisibleRowAt(relativePos.y(), relativePos.x()));
    d_ptr->cellLongTapped(index, pos);
}

#include "moc_mlistview.cpp"

M_REGISTER_VIEW_NEW(MListView, MList)
<commit_msg>Changes: MListView - properly detect if the locked viewport position is within the range.<commit_after>/***************************************************************************
**
** Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QList>
#include <QVector>
#include <QPropertyAnimation>
#include <QStyleOptionGraphicsItem>

#include <QGestureEvent>
#include <QTapAndHoldGesture>

#include <MList>
#include <MWidgetView>
#include <MSeparator>
#include <MPannableViewport>

#include "mlistview.h"
#include "mlistview_p.h"

//// MListView /////
MListView::MListView(MWidgetController *widgetController)
    : MWidgetView(widgetController),
    d_ptr(NULL)
{
    controller = dynamic_cast<MList *>(widgetController);
}

MListView::~MListView()
{
    if (d_ptr) {
        if (!model()->headerCreator())
            delete d_ptr->headersCreator;

        delete d_ptr;
    }
}

void MListView::init()
{
    Q_ASSERT(controller);

    MCellCreator *headersCreator = NULL;

    if(d_ptr) {
        d_ptr->disconnectSignalsFromModelToListView();
        headersCreator = d_ptr->headersCreator;

        // Schedule deletion as we might have some events pending for delivery.
        d_ptr->destroy();
    }

    if (model()->columns() > 1) {
        if (model()->showGroups())
            d_ptr = new MMultiColumnListViewPrivate;
        else
            d_ptr = new MPlainMultiColumnListViewPrivate;
    } else {
        if (model()->showGroups())
            d_ptr = new MGroupHeaderListViewPrivate;
        else
            d_ptr = new MPlainListViewPrivate;
    }

    if (model()->headerCreator()) {
        d_ptr->setHeadersCreator(model()->headerCreator());
        if (model()->headerCreator() != headersCreator)
            delete headersCreator;
    } else
        d_ptr->setHeadersCreator(headersCreator);

    d_ptr->q_ptr = this;
    d_ptr->controller = dynamic_cast<MList *>(controller);
    d_ptr->createSeparators();
    d_ptr->updateSeparators();
    d_ptr->updateSeparatorSize();
    d_ptr->updateAnimations();

    connectSelectionModel();
    d_ptr->connectPannableViewport();

    d_ptr->resetModel(model());
}

void MListView::updateData(const QList<const char *>& modifications)
{
    MWidgetView::updateData(modifications);

    const char *member;
    for (int i = 0; i < modifications.count(); i++) {
        member = modifications[i];

        if (member == MListModel::ItemModel || member == MListModel::ShowGroups || member == MListModel::Columns || member == MListModel::CellCreator ||
            member == MListModel::HeaderCreator) {
            if (model()->itemModel()) {
                init();
                if (d_ptr->pannableViewport) {
                    d_ptr->updateListGeometry();
                } else {
                    // Postpone the update of the list geometry to the next
                    // event loop, otherwise too many cells get created without
                    // having a pannable viewport.
                    QTimer::singleShot(0, d_ptr, SLOT(updateListGeometry()));
                }
            }
        } else if (member == MListModel::SelectionModel) {
            connectSelectionModel();
        } else if (member == MListModel::ScrollToIndex) {
            scrollTo(model()->scrollToIndex(),
                     static_cast<MList::ScrollHint>(model()->scrollHint()),
                     static_cast<MList::AnimationMode>(model()->animationMode()));
        } else if (member == MListModel::LongTap) {
            longTap(model()->longTap());
        } else if (member == MListModel::ListIndexDisplayMode) {
            d_ptr->updateListIndexVisibility();
        } else if (member == MListModel::LongTapEnabled) {
            d_ptr->updateItemConnections();
        }
    }
}

void MListView::connectSelectionModel()
{
    if (d_ptr->selectionModel)
        d_ptr->selectionModel->disconnect(this);

    if (model()->selectionModel()) {
        connect(model()->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
                this, SLOT(selectionChanged(QItemSelection, QItemSelection)));
    }

    d_ptr->selectionModel = model()->selectionModel();
}

void MListView::setupModel()
{
    MWidgetView::setupModel();

    init();
    updateGeometry();
}

void MListView::applyStyle()
{
    MWidgetView::applyStyle();

    if (d_ptr) {
        d_ptr->clearVisibleItemsArray();
        d_ptr->updateAnimations();
        d_ptr->updateItemHeight();
        d_ptr->updateSeparators();
        d_ptr->updateSeparatorSize();
        d_ptr->updateHeaders();
        d_ptr->updateHeaderHeight();
        d_ptr->updateListIndexStyle();

        relayoutItemsInViewportRect();
    }
}

void MListView::notifyItemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
    MWidgetView::notifyItemChange(change, value);

    if(change == QGraphicsItem::ItemSceneHasChanged)
        emit controller->parentChanged();
}

QSizeF MListView::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
    if (!d_ptr)
        return MWidgetView::sizeHint(which, constraint);

    return QSizeF(-1, d_ptr->totalHeight());
}

void MListView::setGeometry(const QRectF &rect)
{
    if (d_ptr) {
        if (!d_ptr->pannableViewport)
            d_ptr->viewportVisibleHeight = d_ptr->totalHeight();

        d_ptr->updatePannableViewportPosition();

        if (d_ptr->lastGeometrySize != rect.size() || d_ptr->clearVisibleOnRelayout) {
            d_ptr->viewWidth = rect.width();
            d_ptr->updateItemSize();
            d_ptr->updateSeparatorSize();

            if (d_ptr->lockPosition) {
                d_ptr->lockPosition = false;
                if (d_ptr->pannableViewport &&
                        d_ptr->lastGeometrySize.height() != 0 && rect.size().height() != 0) {
                    qreal heightDelta = rect.size().height() - d_ptr->lastGeometrySize.height();
                    QRectF viewportRange = d_ptr->pannableViewport->range();
                    if ((int)heightDelta != 0 && viewportRange.height() > 0) {
                        QPointF lockedViewportPosition = d_ptr->pannableViewport->position();
                        lockedViewportPosition.setY(qBound(viewportRange.top(),
                                                           lockedViewportPosition.y() + heightDelta,
                                                           viewportRange.bottom()));
                        d_ptr->pannableViewport->physics()->setPosition(lockedViewportPosition, false);
                    }
                }
            }

            relayoutItemsInViewportRect();

            d_ptr->scrollToLastIndex();
            d_ptr->lastGeometrySize = rect.size();
        }
    }

    MWidgetView::setGeometry(rect);
}

void MListView::relayoutItemsInViewportRect()
{
    if (d_ptr->clearVisibleOnRelayout) {
        d_ptr->clearVisibleItemsArray();
        d_ptr->clearFirstAndLastVisibleRows();
        d_ptr->clearVisibleOnRelayout = false;
    }

    if (d_ptr->model && model()->cellCreator()) {
        int rowCount = d_ptr->rowCount;

        if (rowCount) {
            QModelIndex firstVisibleIndex = d_ptr->locateVisibleIndexAt(d_ptr->viewportTopLeft.y());
            d_ptr->updateFirstVisibleRow(firstVisibleIndex);
            QModelIndex lastVisibleIndex = d_ptr->locateLastVisibleIndexInRowAt(d_ptr->viewportTopLeft.y() + d_ptr->viewportVisibleHeight);
            d_ptr->updateLastVisibleRow(lastVisibleIndex);

            QPoint firstVisibleItemPos(0, d_ptr->locatePosOfItem(firstVisibleIndex));
            QPoint lastVisibleItemPos(0, d_ptr->locatePosOfItem(lastVisibleIndex));
            d_ptr->removeInvisibleItems(firstVisibleItemPos, lastVisibleItemPos);

            d_ptr->createVisibleItems(firstVisibleIndex, lastVisibleIndex);
        } else {
            d_ptr->clearVisibleItemsArray();
            d_ptr->clearFirstAndLastVisibleRows();
        }
    }
}

void MListView::drawForeground(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    Q_UNUSED(painter);
    Q_UNUSED(option);
}

void MListView::drawBackground(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    if (!d_ptr->clearVisibleOnRelayout)
        d_ptr->drawSeparators(painter, option);
}

void MListView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    if (d_ptr->clearVisibleOnRelayout || (!model()->firstVisibleItem().isValid() && !model()->lastVisibleItem().isValid()))
        return;

    if (d_ptr->controller->isVisible()) {
        const MCellCreator *cellCreator = model()->cellCreator();

        int firstVisibleRow = d_ptr->indexToFlatRow(model()->firstVisibleItem());
        int lastVisibleRow = d_ptr->indexToFlatRow(model()->lastVisibleItem());
        int topLeftRow = d_ptr->indexToFlatRow(topLeft);
        int bottomRightRow = d_ptr->indexToFlatRow(bottomRight);

        int top = qMax(topLeftRow, firstVisibleRow);
        int lastCellInLastVisibleRow = lastVisibleRow + model()->columns() - lastVisibleRow % model()->columns() - 1;
        int bottom = qMin(bottomRightRow, lastCellInLastVisibleRow);

        for (int i = top; i <= bottom; i++) {
            QModelIndex cellIndex = d_ptr->flatRowToIndex(i);
            if (!d_ptr->isGroupHeader(cellIndex)) {
                MWidget *cell = d_ptr->findCellAtRow(i);
                if (cell) {
                    if( (controller->optimizationFlags() & MList::DontCallCreateCellDuringUpdate) == MList::DontCallCreateCellDuringUpdate) {
                        cellCreator->updateCell(cellIndex, cell);
                    } else {
                        MWidget* newCell = d_ptr->createCell(i);
                        d_ptr->replaceItem(cell, newCell);
                    }
                }
            }
        }
    } else {
        d_ptr->clearVisibleOnRelayout = true;
    }
}

/*!
 * This slot is called when items are inserted under the given \a parent.
 * The changed items are those from \a start to \a end inclusive.
 *
 * \sa QAbstractItemView::rowsInserted(), exposedRectUpdated()
 */
void MListView::rowsInserted(const QModelIndex &parent, int start, int end, bool animated)
{
    if (!d_ptr->animateRowsInsertion(parent, start, end, animated)) {
        int first = d_ptr->indexToFlatRow(model()->firstVisibleItem());
        start = d_ptr->indexToFlatRow(model()->itemModel()->index(start, 0, parent));
        end = d_ptr->indexToFlatRow(model()->itemModel()->index(end, 0, parent));
        d_ptr->lockPosition = (start < first && end < first);
        layoutChanged();
    }
}

/*!
 * This slot is called when items under the given \a parent are removed.
 * The removed items are those from \a start to \a end inclusive.
 *
 * \sa rowsInserted(), exposedRectUpdated()
 */
void MListView::rowsRemoved(const QModelIndex &parent, int start, int end, bool animated)
{
    if (!d_ptr->animateRowsRemoval(parent, start, end, animated)) {
        int first = d_ptr->indexToFlatRow(model()->firstVisibleItem());
        start = d_ptr->indexToFlatRow(model()->itemModel()->index(start, 0, parent));
        end = d_ptr->indexToFlatRow(model()->itemModel()->index(end, 0, parent));
        d_ptr->lockPosition = (start < first && end < first);
        layoutChanged();
    }
}

void MListView::layoutChanged()
{
    if (!d_ptr->isAnimating()) {
        d_ptr->layoutChanged();

        d_ptr->clearVisibleOnRelayout = true;
        d_ptr->clearFirstAndLastVisibleRows();
        updateGeometry();

        d_ptr->lastScrolledToFlatRow = -1;
    }
}

void MListView::modelReset()
{
    layoutChanged();
}

void MListView::rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
                                const QModelIndex &destinationParent, int destinationRow)
{
    Q_UNUSED(sourceParent);
    Q_UNUSED(sourceStart);
    Q_UNUSED(sourceEnd);
    Q_UNUSED(destinationParent);
    Q_UNUSED(destinationRow);

    layoutChanged();
}

void MListView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
    d_ptr->selectionChange(selected, deselected);
}

void MListView::itemClick()
{
    QObject *s = sender();
    MWidget *senderWidget = qobject_cast<MWidget *>(s);
    if (senderWidget)
        d_ptr->cellClicked(senderWidget);
}

void MListView::scrollTo(const QModelIndex &index, MList::ScrollHint hint, MList::AnimationMode mode)
{
    if (index.isValid()) {
        int row = d_ptr->indexToFlatRow(index);
        scrollTo(row, hint, mode);
    }
}

void MListView::scrollTo(int row, MList::ScrollHint hint, MList::AnimationMode mode)
{
    if (row >= 0) {
        d_ptr->lastScrolledToFlatRow = row;
        if (d_ptr->pannableViewport) {
            QPointF targetPosition = d_ptr->locateScrollToPosition(row, hint);

            if (targetPosition != d_ptr->pannableViewport->position())
                d_ptr->scrollToPos(targetPosition, mode);
        }
    }
}

void MListView::longTap(const QPointF &pos)
{
    QPointF relativePos = d_ptr->controller->mapFromScene(pos);
    QModelIndex index = d_ptr->flatRowToIndex(d_ptr->locateVisibleRowAt(relativePos.y(), relativePos.x()));
    d_ptr->cellLongTapped(index, pos);
}

#include "moc_mlistview.cpp"

M_REGISTER_VIEW_NEW(MListView, MList)
<|endoftext|>


<commit_before>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

/*============================================================
**
** Header:  AssemblyName.cpp
**
** Purpose: Implements AssemblyName (loader domain) architecture
**
**

**
===========================================================*/

#include "common.h"

#include <stdlib.h>
#include <shlwapi.h>

#include "assemblyname.hpp"
#include "security.h"
#include "field.h"
#ifdef FEATURE_FUSION
#include "fusion.h"
#endif
#include "strongname.h"
#include "eeconfig.h"

#ifndef URL_ESCAPE_AS_UTF8
#define URL_ESCAPE_AS_UTF8              0x00040000  // Percent-encode all non-ASCII characters as their UTF-8 equivalents.
#endif

FCIMPL1(Object*, AssemblyNameNative::GetFileInformation, StringObject* filenameUNSAFE)
{
    FCALL_CONTRACT;

    struct _gc
    {
        ASSEMBLYNAMEREF result;
        STRINGREF       filename;
    } gc;

    gc.result   = NULL;
    gc.filename = (STRINGREF) filenameUNSAFE;

    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);

    if (gc.filename == NULL)
        COMPlusThrow(kArgumentNullException, W("ArgumentNull_FileName"));

    if (gc.filename->GetStringLength() == 0)
        COMPlusThrow(kArgumentException, W("Argument_EmptyFileName"));

    gc.result = (ASSEMBLYNAMEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__ASSEMBLY_NAME));

    ///////////////////////////////////////////////
    SString sFileName(gc.filename->GetBuffer());
    PEImageHolder pImage = PEImage::OpenImage(sFileName, MDInternalImport_NoCache);

    EX_TRY
    {
#ifdef FEATURE_CORECLR
        // Allow AssemblyLoadContext.GetAssemblyName for native images on CoreCLR
        if (pImage->HasNTHeaders() && pImage->HasCorHeader() && pImage->HasNativeHeader())
            pImage->VerifyIsNIAssembly();
        else
            pImage->VerifyIsAssembly();
#else
        pImage->VerifyIsAssembly();
#endif
    }
    EX_CATCH
    {
        Exception *ex = GET_EXCEPTION();
        EEFileLoadException::Throw(sFileName,ex->GetHR(),ex);
    }
    EX_END_CATCH_UNREACHABLE;

    SString sUrl = sFileName;
    PEAssembly::PathToUrl(sUrl);

    AssemblySpec spec;
    spec.InitializeSpec(TokenFromRid(mdtAssembly,1),pImage->GetMDImport(),NULL,TRUE);
#ifndef FEATURE_CORECLR
    spec.SetCodeBase(sUrl);
#endif
    spec.AssemblyNameInit(&gc.result, pImage);

    HELPER_METHOD_FRAME_END();
    return OBJECTREFToObject(gc.result);
}
FCIMPLEND

FCIMPL1(Object*, AssemblyNameNative::ToString, Object* refThisUNSAFE)
{
    FCALL_CONTRACT;

    OBJECTREF pObj          = NULL;
    ASSEMBLYNAMEREF pThis   = (ASSEMBLYNAMEREF) (OBJECTREF) refThisUNSAFE;
    HELPER_METHOD_FRAME_BEGIN_RET_1(pThis);

    if (pThis == NULL)
        COMPlusThrow(kNullReferenceException, W("NullReference_This"));

    Thread *pThread = GetThread();

    CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease

    AssemblySpec spec;
    spec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF*) &pThis, FALSE, FALSE);

    StackSString name;
#ifndef FEATURE_FUSION
    spec.GetFileOrDisplayName(ASM_DISPLAYF_VERSION |
                              ASM_DISPLAYF_CULTURE |
                              ASM_DISPLAYF_PUBLIC_KEY_TOKEN,
                              name);
#else
    spec.GetFileOrDisplayName(0, name);
#endif // FEATURE_FUSION

    pObj = (OBJECTREF) StringObject::NewString(name);

    HELPER_METHOD_FRAME_END();
    return OBJECTREFToObject(pObj);
}
FCIMPLEND

FCIMPL1(Object*, AssemblyNameNative::GetPublicKeyToken, Object* refThisUNSAFE)
{
    FCALL_CONTRACT;

    OBJECTREF orOutputArray = NULL;
    OBJECTREF refThis       = (OBJECTREF) refThisUNSAFE;
    HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);

    if (refThis == NULL)
        COMPlusThrow(kNullReferenceException, W("NullReference_This"));

    ASSEMBLYNAMEREF orThis = (ASSEMBLYNAMEREF)refThis;
    U1ARRAYREF orPublicKey = orThis->GetPublicKey();

    if (orPublicKey != NULL) {
        DWORD cb = orPublicKey->GetNumComponents();
        StrongNameBufferHolder<BYTE> pbToken;

        if (cb) {
            CQuickBytes qb;
            BYTE *pbKey = (BYTE*) qb.AllocThrows(cb);
            memcpy(pbKey, orPublicKey->GetDataPtr(), cb);

            {
                GCX_PREEMP();
                if (!StrongNameTokenFromPublicKey(pbKey, cb, &pbToken, &cb))
                    COMPlusThrowHR(StrongNameErrorInfo());
            }
        }

        Security::CopyEncodingToByteArray(pbToken, cb, &orOutputArray);
    }

    HELPER_METHOD_FRAME_END();
    return OBJECTREFToObject(orOutputArray);
}
FCIMPLEND

FCIMPL1(Object*, AssemblyNameNative::EscapeCodeBase, StringObject* filenameUNSAFE)
{
    FCALL_CONTRACT;

    STRINGREF rv        = NULL;
    STRINGREF filename  = (STRINGREF) filenameUNSAFE;
    HELPER_METHOD_FRAME_BEGIN_RET_1(filename);

    LPWSTR pCodeBase = NULL;
    DWORD  dwCodeBase = 0;
    CQuickBytes qb;

    if (filename != NULL) {
        WCHAR* pString;
        int    iString;
        filename->RefInterpretGetStringValuesDangerousForGC(&pString, &iString);
        dwCodeBase = (DWORD) iString;
        pCodeBase = (LPWSTR) qb.AllocThrows((++dwCodeBase) * sizeof(WCHAR));
        memcpy(pCodeBase, pString, dwCodeBase*sizeof(WCHAR));
    }

    if(pCodeBase) {
        CQuickBytes qb2;
        DWORD dwEscaped = 1;

        DWORD flags = 0;
        if (RunningOnWin7())
            flags |= URL_ESCAPE_AS_UTF8;

        UrlEscape(pCodeBase, (LPWSTR) qb2.Ptr(), &dwEscaped, flags);

        LPWSTR result = (LPWSTR)qb2.AllocThrows((++dwEscaped) * sizeof(WCHAR));
        HRESULT hr = UrlEscape(pCodeBase, result, &dwEscaped, flags);

        if (SUCCEEDED(hr))
            rv = StringObject::NewString(result);
        else
            COMPlusThrowHR(hr);
    }

    HELPER_METHOD_FRAME_END();
    return OBJECTREFToObject(rv);
}
FCIMPLEND

FCIMPL4(void, AssemblyNameNative::Init, Object * refThisUNSAFE, OBJECTREF * pAssemblyRef, CLR_BOOL fForIntrospection, CLR_BOOL fRaiseResolveEvent)
{
    FCALL_CONTRACT;

    ASSEMBLYNAMEREF pThis = (ASSEMBLYNAMEREF) (OBJECTREF) refThisUNSAFE;
    HRESULT hr = S_OK;

    HELPER_METHOD_FRAME_BEGIN_1(pThis);

    *pAssemblyRef = NULL;

    if (pThis == NULL)
        COMPlusThrow(kNullReferenceException, W("NullReference_This"));

    Thread * pThread = GetThread();

    CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease

    AssemblySpec spec;
    hr = spec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF *) &pThis, TRUE, FALSE);

    if (SUCCEEDED(hr))
    {
        spec.AssemblyNameInit(&pThis,NULL);
    }
    else if ((hr == FUSION_E_INVALID_NAME) && fRaiseResolveEvent)
    {
        Assembly * pAssembly = GetAppDomain()->RaiseAssemblyResolveEvent(&spec, fForIntrospection, FALSE);

        if (pAssembly == NULL)
        {
            EEFileLoadException::Throw(&spec, hr);
        }
        else
        {
            *((OBJECTREF *) (&(*pAssemblyRef))) = pAssembly->GetExposedObject();
        }
    }
    else
    {
        ThrowHR(hr);
    }

    HELPER_METHOD_FRAME_END();
}
FCIMPLEND

/// "parse" tells us to parse the simple name of the assembly as if it was the full name
/// almost never the right thing to do, but needed for compat
/* static */
FCIMPL3(FC_BOOL_RET, AssemblyNameNative::ReferenceMatchesDefinition, AssemblyNameBaseObject* refUNSAFE, AssemblyNameBaseObject* defUNSAFE, CLR_BOOL fParse)
{
    FCALL_CONTRACT;

    struct _gc
    {
        ASSEMBLYNAMEREF pRef;
        ASSEMBLYNAMEREF pDef;
    } gc;
    gc.pRef = (ASSEMBLYNAMEREF)ObjectToOBJECTREF (refUNSAFE);
    gc.pDef = (ASSEMBLYNAMEREF)ObjectToOBJECTREF (defUNSAFE);

    BOOL result = FALSE;
    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);

    Thread *pThread = GetThread();

    CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease

    if (gc.pRef == NULL)
        COMPlusThrow(kArgumentNullException, W("ArgumentNull_AssemblyName"));
    if (gc.pDef == NULL)
        COMPlusThrow(kArgumentNullException, W("ArgumentNull_AssemblyName"));

    AssemblySpec refSpec;
    refSpec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF*) &gc.pRef, fParse, FALSE);

    AssemblySpec defSpec;
    defSpec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF*) &gc.pDef, fParse, FALSE);

#ifdef FEATURE_FUSION
    SafeComHolder<IAssemblyName> pRefName (NULL);
    IfFailThrow(refSpec.CreateFusionName(&pRefName, FALSE));

    SafeComHolder <IAssemblyName> pDefName (NULL);
    IfFailThrow(defSpec.CreateFusionName(&pDefName, FALSE));

    // Order matters: Ref->IsEqual(Def)
    result = (S_OK == pRefName->IsEqual(pDefName, ASM_CMPF_IL_ALL));
#else
    result=AssemblySpec::RefMatchesDef(&refSpec,&defSpec);
#endif
    HELPER_METHOD_FRAME_END();
    FC_RETURN_BOOL(result);
}
FCIMPLEND
<commit_msg>Workaround missing UrlEscape<commit_after>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

/*============================================================
**
** Header:  AssemblyName.cpp
**
** Purpose: Implements AssemblyName (loader domain) architecture
**
**

**
===========================================================*/

#include "common.h"

#include <stdlib.h>
#include <shlwapi.h>

#include "assemblyname.hpp"
#include "security.h"
#include "field.h"
#ifdef FEATURE_FUSION
#include "fusion.h"
#endif
#include "strongname.h"
#include "eeconfig.h"

#ifndef URL_ESCAPE_AS_UTF8
#define URL_ESCAPE_AS_UTF8              0x00040000  // Percent-encode all non-ASCII characters as their UTF-8 equivalents.
#endif

FCIMPL1(Object*, AssemblyNameNative::GetFileInformation, StringObject* filenameUNSAFE)
{
    FCALL_CONTRACT;

    struct _gc
    {
        ASSEMBLYNAMEREF result;
        STRINGREF       filename;
    } gc;

    gc.result   = NULL;
    gc.filename = (STRINGREF) filenameUNSAFE;

    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);

    if (gc.filename == NULL)
        COMPlusThrow(kArgumentNullException, W("ArgumentNull_FileName"));

    if (gc.filename->GetStringLength() == 0)
        COMPlusThrow(kArgumentException, W("Argument_EmptyFileName"));

    gc.result = (ASSEMBLYNAMEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__ASSEMBLY_NAME));

    ///////////////////////////////////////////////
    SString sFileName(gc.filename->GetBuffer());
    PEImageHolder pImage = PEImage::OpenImage(sFileName, MDInternalImport_NoCache);

    EX_TRY
    {
#ifdef FEATURE_CORECLR
        // Allow AssemblyLoadContext.GetAssemblyName for native images on CoreCLR
        if (pImage->HasNTHeaders() && pImage->HasCorHeader() && pImage->HasNativeHeader())
            pImage->VerifyIsNIAssembly();
        else
            pImage->VerifyIsAssembly();
#else
        pImage->VerifyIsAssembly();
#endif
    }
    EX_CATCH
    {
        Exception *ex = GET_EXCEPTION();
        EEFileLoadException::Throw(sFileName,ex->GetHR(),ex);
    }
    EX_END_CATCH_UNREACHABLE;

    SString sUrl = sFileName;
    PEAssembly::PathToUrl(sUrl);

    AssemblySpec spec;
    spec.InitializeSpec(TokenFromRid(mdtAssembly,1),pImage->GetMDImport(),NULL,TRUE);
#ifndef FEATURE_CORECLR
    spec.SetCodeBase(sUrl);
#endif
    spec.AssemblyNameInit(&gc.result, pImage);

    HELPER_METHOD_FRAME_END();
    return OBJECTREFToObject(gc.result);
}
FCIMPLEND

FCIMPL1(Object*, AssemblyNameNative::ToString, Object* refThisUNSAFE)
{
    FCALL_CONTRACT;

    OBJECTREF pObj          = NULL;
    ASSEMBLYNAMEREF pThis   = (ASSEMBLYNAMEREF) (OBJECTREF) refThisUNSAFE;
    HELPER_METHOD_FRAME_BEGIN_RET_1(pThis);

    if (pThis == NULL)
        COMPlusThrow(kNullReferenceException, W("NullReference_This"));

    Thread *pThread = GetThread();

    CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease

    AssemblySpec spec;
    spec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF*) &pThis, FALSE, FALSE);

    StackSString name;
#ifndef FEATURE_FUSION
    spec.GetFileOrDisplayName(ASM_DISPLAYF_VERSION |
                              ASM_DISPLAYF_CULTURE |
                              ASM_DISPLAYF_PUBLIC_KEY_TOKEN,
                              name);
#else
    spec.GetFileOrDisplayName(0, name);
#endif // FEATURE_FUSION

    pObj = (OBJECTREF) StringObject::NewString(name);

    HELPER_METHOD_FRAME_END();
    return OBJECTREFToObject(pObj);
}
FCIMPLEND

FCIMPL1(Object*, AssemblyNameNative::GetPublicKeyToken, Object* refThisUNSAFE)
{
    FCALL_CONTRACT;

    OBJECTREF orOutputArray = NULL;
    OBJECTREF refThis       = (OBJECTREF) refThisUNSAFE;
    HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);

    if (refThis == NULL)
        COMPlusThrow(kNullReferenceException, W("NullReference_This"));

    ASSEMBLYNAMEREF orThis = (ASSEMBLYNAMEREF)refThis;
    U1ARRAYREF orPublicKey = orThis->GetPublicKey();

    if (orPublicKey != NULL) {
        DWORD cb = orPublicKey->GetNumComponents();
        StrongNameBufferHolder<BYTE> pbToken;

        if (cb) {
            CQuickBytes qb;
            BYTE *pbKey = (BYTE*) qb.AllocThrows(cb);
            memcpy(pbKey, orPublicKey->GetDataPtr(), cb);

            {
                GCX_PREEMP();
                if (!StrongNameTokenFromPublicKey(pbKey, cb, &pbToken, &cb))
                    COMPlusThrowHR(StrongNameErrorInfo());
            }
        }

        Security::CopyEncodingToByteArray(pbToken, cb, &orOutputArray);
    }

    HELPER_METHOD_FRAME_END();
    return OBJECTREFToObject(orOutputArray);
}
FCIMPLEND

FCIMPL1(Object*, AssemblyNameNative::EscapeCodeBase, StringObject* filenameUNSAFE)
{
    FCALL_CONTRACT;

    STRINGREF rv        = NULL;
    STRINGREF filename  = (STRINGREF) filenameUNSAFE;
    HELPER_METHOD_FRAME_BEGIN_RET_1(filename);

#ifdef FEATURE_PAL
    // UNIXTODO: UrlEscape not implemented
    COMPlusThrow(kPlatformNotSupportedException);
#else
    LPWSTR pCodeBase = NULL;
    DWORD  dwCodeBase = 0;
    CQuickBytes qb;

    if (filename != NULL) {
        WCHAR* pString;
        int    iString;
        filename->RefInterpretGetStringValuesDangerousForGC(&pString, &iString);
        dwCodeBase = (DWORD) iString;
        pCodeBase = (LPWSTR) qb.AllocThrows((++dwCodeBase) * sizeof(WCHAR));
        memcpy(pCodeBase, pString, dwCodeBase*sizeof(WCHAR));
    }

    if(pCodeBase) {
        CQuickBytes qb2;
        DWORD dwEscaped = 1;

        DWORD flags = 0;
        if (RunningOnWin7())
            flags |= URL_ESCAPE_AS_UTF8;

        UrlEscape(pCodeBase, (LPWSTR) qb2.Ptr(), &dwEscaped, flags);

        LPWSTR result = (LPWSTR)qb2.AllocThrows((++dwEscaped) * sizeof(WCHAR));
        HRESULT hr = UrlEscape(pCodeBase, result, &dwEscaped, flags);

        if (SUCCEEDED(hr))
            rv = StringObject::NewString(result);
        else
            COMPlusThrowHR(hr);
    }
#endif

    HELPER_METHOD_FRAME_END();
    return OBJECTREFToObject(rv);
}
FCIMPLEND

FCIMPL4(void, AssemblyNameNative::Init, Object * refThisUNSAFE, OBJECTREF * pAssemblyRef, CLR_BOOL fForIntrospection, CLR_BOOL fRaiseResolveEvent)
{
    FCALL_CONTRACT;

    ASSEMBLYNAMEREF pThis = (ASSEMBLYNAMEREF) (OBJECTREF) refThisUNSAFE;
    HRESULT hr = S_OK;

    HELPER_METHOD_FRAME_BEGIN_1(pThis);

    *pAssemblyRef = NULL;

    if (pThis == NULL)
        COMPlusThrow(kNullReferenceException, W("NullReference_This"));

    Thread * pThread = GetThread();

    CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease

    AssemblySpec spec;
    hr = spec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF *) &pThis, TRUE, FALSE);

    if (SUCCEEDED(hr))
    {
        spec.AssemblyNameInit(&pThis,NULL);
    }
    else if ((hr == FUSION_E_INVALID_NAME) && fRaiseResolveEvent)
    {
        Assembly * pAssembly = GetAppDomain()->RaiseAssemblyResolveEvent(&spec, fForIntrospection, FALSE);

        if (pAssembly == NULL)
        {
            EEFileLoadException::Throw(&spec, hr);
        }
        else
        {
            *((OBJECTREF *) (&(*pAssemblyRef))) = pAssembly->GetExposedObject();
        }
    }
    else
    {
        ThrowHR(hr);
    }

    HELPER_METHOD_FRAME_END();
}
FCIMPLEND

/// "parse" tells us to parse the simple name of the assembly as if it was the full name
/// almost never the right thing to do, but needed for compat
/* static */
FCIMPL3(FC_BOOL_RET, AssemblyNameNative::ReferenceMatchesDefinition, AssemblyNameBaseObject* refUNSAFE, AssemblyNameBaseObject* defUNSAFE, CLR_BOOL fParse)
{
    FCALL_CONTRACT;

    struct _gc
    {
        ASSEMBLYNAMEREF pRef;
        ASSEMBLYNAMEREF pDef;
    } gc;
    gc.pRef = (ASSEMBLYNAMEREF)ObjectToOBJECTREF (refUNSAFE);
    gc.pDef = (ASSEMBLYNAMEREF)ObjectToOBJECTREF (defUNSAFE);

    BOOL result = FALSE;
    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);

    Thread *pThread = GetThread();

    CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease

    if (gc.pRef == NULL)
        COMPlusThrow(kArgumentNullException, W("ArgumentNull_AssemblyName"));
    if (gc.pDef == NULL)
        COMPlusThrow(kArgumentNullException, W("ArgumentNull_AssemblyName"));

    AssemblySpec refSpec;
    refSpec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF*) &gc.pRef, fParse, FALSE);

    AssemblySpec defSpec;
    defSpec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF*) &gc.pDef, fParse, FALSE);

#ifdef FEATURE_FUSION
    SafeComHolder<IAssemblyName> pRefName (NULL);
    IfFailThrow(refSpec.CreateFusionName(&pRefName, FALSE));

    SafeComHolder <IAssemblyName> pDefName (NULL);
    IfFailThrow(defSpec.CreateFusionName(&pDefName, FALSE));

    // Order matters: Ref->IsEqual(Def)
    result = (S_OK == pRefName->IsEqual(pDefName, ASM_CMPF_IL_ALL));
#else
    result=AssemblySpec::RefMatchesDef(&refSpec,&defSpec);
#endif
    HELPER_METHOD_FRAME_END();
    FC_RETURN_BOOL(result);
}
FCIMPLEND
<|endoftext|>


<commit_before><commit_msg>GUI: get runtime path from environment var<commit_after><|endoftext|>