<commit_before>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <sstream>
#include <map>
#include <stdlib.h>
#include <Variant.h>
#include <Duration.h>
#include <Context.h>
#include <Nibbler.h>
#include <Date.h>
#include <text.h>
#include <i18n.h>
#include <DOM.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
DOM::DOM ()
{
}

////////////////////////////////////////////////////////////////////////////////
DOM::~DOM ()
{
}

////////////////////////////////////////////////////////////////////////////////
const std::vector <std::string> DOM::get_references () const
{
  std::vector <std::string> refs;

  refs.push_back ("context.program");
  refs.push_back ("context.args");
  refs.push_back ("context.width");
  refs.push_back ("context.height");
  refs.push_back ("system.version");
  refs.push_back ("system.os");

  return refs;
}

////////////////////////////////////////////////////////////////////////////////
// DOM Supported References:
//   rc.<name>
//
//   context.program
//   context.args
//   context.width
//   context.height
//
//   TODO stats.<name>           <-- context.stats
//
//   system.version
//   system.os
//
bool DOM::get (const std::string& name, Variant& value)
{
  int len = name.length ();
  Nibbler n (name);

  // rc. --> context.config
  if (len > 3 &&
      name.substr (0, 3) == "rc.")
  {
    std::string key = name.substr (3);
    std::map <std::string, std::string>::iterator c = context.config.find (key);
    if (c != context.config.end ())
    {
      value = Variant (c->second);
      return true;
    }

    return false;
  }

  // context.*
  if (len > 8 &&
           name.substr (0, 8) == "context.")
  {
    if (name == "context.program")
    {
      value = Variant (context.program);
      return true;
    }
    else if (name == "context.args")
    {
      std::string commandLine = "";
      std::vector <Tree*>::iterator i;
      for (i = context.parser.tree ()->_branches.begin (); i != context.parser.tree ()->_branches.end (); ++i)
      {
        if (commandLine != "")
          commandLine += " ";

        commandLine += (*i)->attribute ("raw");
      }

      value = Variant (commandLine);
      return true;
    }
    else if (name == "context.width")
    {
      value = Variant (context.terminal_width
                         ? context.terminal_width
                         : context.getWidth ());
      return true;
    }
    else if (name == "context.height")
    {
      value = Variant (context.terminal_height
                         ? context.terminal_height
                         : context.getHeight ());
      return true;
    }
    else
      throw format (STRING_DOM_UNREC, name);
  }

  // TODO stats.<name>

  // system. --> Implement locally.
  if (len > 7 &&
           name.substr (0, 7) == "system.")
  {
    // Taskwarrior version number.
    if (name == "system.version")
    {
      value = Variant (VERSION);
      return true;
    }

    // OS type.
    else if (name == "system.os")
    {
#if defined (DARWIN)
      value = Variant ("Darwin");
#elif defined (SOLARIS)
      value = Variant ("Solaris");
#elif defined (CYGWIN)
      value = Variant ("Cygwin");
#elif defined (HAIKU)
      value = Variant ("Haiku");
#elif defined (OPENBSD)
      value = Variant ("OpenBSD");
#elif defined (FREEBSD)
      value = Variant ("FreeBSD");
#elif defined (NETBSD)
      value = Variant ("NetBSD");
#elif defined (LINUX)
      value = Variant ("Linux");
#elif defined (KFREEBSD)
      value = Variant ("GNU/kFreeBSD");
#elif defined (GNUHURD)
      value = Variant ("GNU/Hurd");
#else
      value = Variant (STRING_DOM_UNKNOWN);
#endif
      return true;
    }
    else
      throw format (STRING_DOM_UNREC, name);
  }

  // Empty string if nothing is found.
  return false;
}

////////////////////////////////////////////////////////////////////////////////
// DOM Supported References:
//
//   <attribute>
//   <id>.<attribute>
//   <uuid>.<attribute>
//
// For certain attributes:
//   <date>.year
//   <date>.month
//   <date>.day
//   <date>.week
//   <date>.weekday
//   <date>.julian
//   <date>.hour
//   <date>.minute
//   <date>.second
//
//   tags.<literal>                  Includes virtual tags
//
//   annotations.<N>.entry
//   annotations.<N>.entry.year
//   annotations.<N>.entry.month
//   annotations.<N>.entry.day
//   annotations.<N>.entry.week
//   annotations.<N>.entry.weekday
//   annotations.<N>.entry.julian
//   annotations.<N>.entry.hour
//   annotations.<N>.entry.minute
//   annotations.<N>.entry.second
//   annotations.<N>.description
//
bool DOM::get (const std::string& name, const Task& task, Variant& value)
{
  // <attr>
  if (task.size () && name == "id")
  {
    value = Variant (task.id);
    return true;
  }

  if (task.size () && name == "urgency")
  {
    value = Variant (task.urgency_c ());
    return true;
  }

  // split name on '.'
  std::vector <std::string> elements;
  split (elements, name, '.');

  if (elements.size () == 1)
  {
    std::string canonical;
    if (task.size () && context.parser.canonicalize (canonical, "attribute", name))
    {
      value = Variant (task.get (canonical));
      return true;
    }
  }
  else if (elements.size () > 1)
  {
    Task ref;

    Nibbler n (elements[0]);
    n.save ();
    int id;
    std::string uuid;
    bool proceed = false;

    if (n.getInt (id) && n.depleted ())
    {
      if (id == task.id)
        ref = task;
      else
        context.tdb2.get (id, ref);

      proceed = true;
    }
    else
    {
      n.restore ();
      if (n.getUUID (uuid) && n.depleted ())
      {
        if (uuid == task.get ("uuid"))
          ref = task;
        else
          context.tdb2.get (uuid, ref);

        proceed = true;
      }
    }

    if (proceed)
    {
      if (elements[1] == "id")
      {
        value = Variant (ref.id);
        return true;
      }
      else if (elements[1] == "urgency")
      {
        value = Variant (ref.urgency_c ());
        return true;
      }

      std::string canonical;
      if (context.parser.canonicalize (canonical, "attribute", elements[1]))
      {
        if (elements.size () == 2)
        {
          Column* column = context.columns[canonical];
          if (column && column->type () == "date")
            value = Variant (ref.get_date (canonical), Variant::type_date);
          else if (column && column->type () == "duration")
            value = Variant ((time_t) Duration (ref.get (canonical)), Variant::type_duration);
          else
            value = Variant (ref.get (canonical));

          return true;
        }
        else if (elements.size () == 3)
        {
          // tags.<tag>
          if (canonical == "tags")
          {
            value = Variant (ref.hasTag (elements[2]) ? elements[2] : "");
            return true;
          }

          Column* column = context.columns[canonical];
          if (column && column->type () == "date")
          {
            // <date>.year
            // <date>.month
            // <date>.day
            // <date>.week
            // <date>.weekday
            // <date>.julian
            // <date>.hour
            // <date>.minute
            // <date>.second
            Date date (ref.get_date (canonical));
                 if (elements[2] == "year")    { value = Variant (date.year ());      return true; }
            else if (elements[2] == "month")   { value = Variant (date.month ());     return true; }
            else if (elements[2] == "day")     { value = Variant (date.day ());       return true; }
            else if (elements[2] == "week")    { value = Variant (date.week ());      return true; }
            else if (elements[2] == "weekday") { value = Variant (date.dayOfWeek ()); return true; }
            else if (elements[2] == "julian")  { value = Variant (date.dayOfYear ()); return true; }
            else if (elements[2] == "hour")    { value = Variant (date.hour ());      return true; }
            else if (elements[2] == "minute")  { value = Variant (date.minute ());    return true; }
            else if (elements[2] == "second")  { value = Variant (date.second ());    return true; }
          }
        }
      }
      else if (elements[1] == "annotations")
      {
        if (elements.size () == 4)
        {
          std::map <std::string, std::string> annos;
          ref.getAnnotations (annos);

          int a = strtol (elements[2].c_str (), NULL, 10);
          int count = 0;

          // Count off the 'a'th annotation.
          std::map <std::string, std::string>::iterator i;
          for (i = annos.begin (); i != annos.end (); ++i)
          {
            if (++count == a)
            {
              if (elements[3] == "entry")
              {
                // annotation_1234567890
                // 0          ^11
                value = Variant ((time_t) strtol (i->first.substr (11).c_str (), NULL, 10), Variant::type_date);
                return true;
              }
              else if (elements[3] == "description")
              {
                value = Variant (i->second);
                return true;
              }
            }
          }
        }
        else if (elements.size () == 5)
        {
          std::map <std::string, std::string> annos;
          ref.getAnnotations (annos);

          int a = strtol (elements[2].c_str (), NULL, 10);
          int count = 0;

          // Count off the 'a'th annotation.
          std::map <std::string, std::string>::iterator i;
          for (i = annos.begin (); i != annos.end (); ++i)
          {
            if (++count == a)
            {
              // <annotations>.<N>.entry.year
              // <annotations>.<N>.entry.month
              // <annotations>.<N>.entry.day
              // <annotations>.<N>.entry.week
              // <annotations>.<N>.entry.weekday
              // <annotations>.<N>.entry.julian
              // <annotations>.<N>.entry.hour
              // <annotations>.<N>.entry.minute
              // <annotations>.<N>.entry.second
              Date date (i->first.substr (11));
                   if (elements[4] == "year")    { value = Variant (date.year ());      return true; }
              else if (elements[4] == "month")   { value = Variant (date.month ());     return true; }
              else if (elements[4] == "day")     { value = Variant (date.day ());       return true; }
              else if (elements[4] == "week")    { value = Variant (date.week ());      return true; }
              else if (elements[4] == "weekday") { value = Variant (date.dayOfWeek ()); return true; }
              else if (elements[4] == "julian")  { value = Variant (date.dayOfYear ()); return true; }
              else if (elements[4] == "hour")    { value = Variant (date.hour ());      return true; }
              else if (elements[4] == "minute")  { value = Variant (date.minute ());    return true; }
              else if (elements[4] == "second")  { value = Variant (date.second ());    return true; }
            }
          }
        }
      }
    }
  }

  // Delegate to the context-free version of DOM::get.
  return this->get (name, value);
}

////////////////////////////////////////////////////////////////////////////////
void DOM::set (const std::string& name, const Variant& value)
{
  int len = name.length ();

  // rc. --> context.config
  if (len > 3 &&
      name.substr (0, 3) == "rc.")
  {
    context.config.set (name.substr (3), (std::string) value);
  }

  // Unrecognized --> error.
  else
    throw format (STRING_DOM_CANNOT_SET, name);
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>DOM<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <sstream>
#include <map>
#include <stdlib.h>
#include <Variant.h>
#include <Duration.h>
#include <Context.h>
#include <Nibbler.h>
#include <Date.h>
#include <text.h>
#include <i18n.h>
#include <DOM.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
DOM::DOM ()
{
}

////////////////////////////////////////////////////////////////////////////////
DOM::~DOM ()
{
}

////////////////////////////////////////////////////////////////////////////////
const std::vector <std::string> DOM::get_references () const
{
  std::vector <std::string> refs;

  refs.push_back ("context.program");
  refs.push_back ("context.args");
  refs.push_back ("context.width");
  refs.push_back ("context.height");
  refs.push_back ("system.version");
  refs.push_back ("system.os");

  return refs;
}

////////////////////////////////////////////////////////////////////////////////
// DOM Supported References:
//   rc.<name>
//
//   context.program
//   context.args
//   context.width
//   context.height
//
//   TODO stats.<name>           <-- context.stats
//
//   system.version
//   system.os
//
bool DOM::get (const std::string& name, Variant& value)
{
  int len = name.length ();
  Nibbler n (name);

  // rc. --> context.config
  if (len > 3 &&
      name.substr (0, 3) == "rc.")
  {
    std::string key = name.substr (3);
    std::map <std::string, std::string>::iterator c = context.config.find (key);
    if (c != context.config.end ())
    {
      value = Variant (c->second);
      return true;
    }

    return false;
  }

  // context.*
  if (len > 8 &&
           name.substr (0, 8) == "context.")
  {
    if (name == "context.program")
    {
      value = Variant (context.program);
      return true;
    }
    else if (name == "context.args")
    {
      std::string commandLine = "";
      std::vector <Tree*>::iterator i;
      for (i = context.parser.tree ()->_branches.begin (); i != context.parser.tree ()->_branches.end (); ++i)
      {
        if (commandLine != "")
          commandLine += " ";

        commandLine += (*i)->attribute ("raw");
      }

      value = Variant (commandLine);
      return true;
    }
    else if (name == "context.width")
    {
      value = Variant (context.terminal_width
                         ? context.terminal_width
                         : context.getWidth ());
      return true;
    }
    else if (name == "context.height")
    {
      value = Variant (context.terminal_height
                         ? context.terminal_height
                         : context.getHeight ());
      return true;
    }
    else
      throw format (STRING_DOM_UNREC, name);
  }

  // TODO stats.<name>

  // system. --> Implement locally.
  if (len > 7 &&
           name.substr (0, 7) == "system.")
  {
    // Taskwarrior version number.
    if (name == "system.version")
    {
      value = Variant (VERSION);
      return true;
    }

    // OS type.
    else if (name == "system.os")
    {
#if defined (DARWIN)
      value = Variant ("Darwin");
#elif defined (SOLARIS)
      value = Variant ("Solaris");
#elif defined (CYGWIN)
      value = Variant ("Cygwin");
#elif defined (HAIKU)
      value = Variant ("Haiku");
#elif defined (OPENBSD)
      value = Variant ("OpenBSD");
#elif defined (FREEBSD)
      value = Variant ("FreeBSD");
#elif defined (NETBSD)
      value = Variant ("NetBSD");
#elif defined (LINUX)
      value = Variant ("Linux");
#elif defined (KFREEBSD)
      value = Variant ("GNU/kFreeBSD");
#elif defined (GNUHURD)
      value = Variant ("GNU/Hurd");
#else
      value = Variant (STRING_DOM_UNKNOWN);
#endif
      return true;
    }
    else
      throw format (STRING_DOM_UNREC, name);
  }

  // Empty string if nothing is found.
  return false;
}

////////////////////////////////////////////////////////////////////////////////
// DOM Supported References:
//
//   <attribute>
//   <id>.<attribute>
//   <uuid>.<attribute>
//
// For certain attributes:
//   <date>.year
//   <date>.month
//   <date>.day
//   <date>.week
//   <date>.weekday
//   <date>.julian
//   <date>.hour
//   <date>.minute
//   <date>.second
//
//   tags.<literal>                  Includes virtual tags
//
//   annotations.<N>.entry
//   annotations.<N>.entry.year
//   annotations.<N>.entry.month
//   annotations.<N>.entry.day
//   annotations.<N>.entry.week
//   annotations.<N>.entry.weekday
//   annotations.<N>.entry.julian
//   annotations.<N>.entry.hour
//   annotations.<N>.entry.minute
//   annotations.<N>.entry.second
//   annotations.<N>.description
//
bool DOM::get (const std::string& name, const Task& task, Variant& value)
{
  // <attr>
  if (task.size () && name == "id")
  {
    value = Variant (task.id);
    return true;
  }

  if (task.size () && name == "urgency")
  {
    value = Variant (task.urgency_c ());
    return true;
  }

  // split name on '.'
  std::vector <std::string> elements;
  split (elements, name, '.');

  if (elements.size () == 1)
  {
    std::string canonical;
    if (task.size () && context.parser.canonicalize (canonical, "attribute", name))
    {
      Column* column = context.columns[canonical];
      if (column)
      {
        if (column->type () == "date")
          value = Variant (task.get_date (canonical), Variant::type_date);
        else if (column->type () == "duration")
          value = Variant ((time_t) Duration (task.get (canonical)), Variant::type_duration);
        else if (column->type () == "numeric")
          value = Variant (task.get_float (canonical));
        else
          value = Variant (task.get (canonical));

        return true;
      }
    }
  }
  else if (elements.size () > 1)
  {
    Task ref;

    Nibbler n (elements[0]);
    n.save ();
    int id;
    std::string uuid;
    bool proceed = false;

    if (n.getInt (id) && n.depleted ())
    {
      if (id == task.id)
        ref = task;
      else
        context.tdb2.get (id, ref);

      proceed = true;
    }
    else
    {
      n.restore ();
      if (n.getUUID (uuid) && n.depleted ())
      {
        if (uuid == task.get ("uuid"))
          ref = task;
        else
          context.tdb2.get (uuid, ref);

        proceed = true;
      }
    }

    if (proceed)
    {
      if (elements[1] == "id")
      {
        value = Variant (ref.id);
        return true;
      }
      else if (elements[1] == "urgency")
      {
        value = Variant (ref.urgency_c ());
        return true;
      }

      std::string canonical;
      if (context.parser.canonicalize (canonical, "attribute", elements[1]))
      {
        if (elements.size () == 2)
        {
          Column* column = context.columns[canonical];
          if (column)
          {
            if (column->type () == "date")
              value = Variant (ref.get_date (canonical), Variant::type_date);
            else if (column->type () == "duration")
              value = Variant ((time_t) Duration (ref.get (canonical)), Variant::type_duration);
            else if (column->type () == "numeric")
              value = Variant (ref.get_float (canonical));
            else
              value = Variant (ref.get (canonical));

            return true;
          }
        }
        else if (elements.size () == 3)
        {
          // tags.<tag>
          if (canonical == "tags")
          {
            value = Variant (ref.hasTag (elements[2]) ? elements[2] : "");
            return true;
          }

          Column* column = context.columns[canonical];
          if (column && column->type () == "date")
          {
            // <date>.year
            // <date>.month
            // <date>.day
            // <date>.week
            // <date>.weekday
            // <date>.julian
            // <date>.hour
            // <date>.minute
            // <date>.second
            Date date (ref.get_date (canonical));
                 if (elements[2] == "year")    { value = Variant (date.year ());      return true; }
            else if (elements[2] == "month")   { value = Variant (date.month ());     return true; }
            else if (elements[2] == "day")     { value = Variant (date.day ());       return true; }
            else if (elements[2] == "week")    { value = Variant (date.week ());      return true; }
            else if (elements[2] == "weekday") { value = Variant (date.dayOfWeek ()); return true; }
            else if (elements[2] == "julian")  { value = Variant (date.dayOfYear ()); return true; }
            else if (elements[2] == "hour")    { value = Variant (date.hour ());      return true; }
            else if (elements[2] == "minute")  { value = Variant (date.minute ());    return true; }
            else if (elements[2] == "second")  { value = Variant (date.second ());    return true; }
          }
        }
      }
      else if (elements[1] == "annotations")
      {
        if (elements.size () == 4)
        {
          std::map <std::string, std::string> annos;
          ref.getAnnotations (annos);

          int a = strtol (elements[2].c_str (), NULL, 10);
          int count = 0;

          // Count off the 'a'th annotation.
          std::map <std::string, std::string>::iterator i;
          for (i = annos.begin (); i != annos.end (); ++i)
          {
            if (++count == a)
            {
              if (elements[3] == "entry")
              {
                // annotation_1234567890
                // 0          ^11
                value = Variant ((time_t) strtol (i->first.substr (11).c_str (), NULL, 10), Variant::type_date);
                return true;
              }
              else if (elements[3] == "description")
              {
                value = Variant (i->second);
                return true;
              }
            }
          }
        }
        else if (elements.size () == 5)
        {
          std::map <std::string, std::string> annos;
          ref.getAnnotations (annos);

          int a = strtol (elements[2].c_str (), NULL, 10);
          int count = 0;

          // Count off the 'a'th annotation.
          std::map <std::string, std::string>::iterator i;
          for (i = annos.begin (); i != annos.end (); ++i)
          {
            if (++count == a)
            {
              // <annotations>.<N>.entry.year
              // <annotations>.<N>.entry.month
              // <annotations>.<N>.entry.day
              // <annotations>.<N>.entry.week
              // <annotations>.<N>.entry.weekday
              // <annotations>.<N>.entry.julian
              // <annotations>.<N>.entry.hour
              // <annotations>.<N>.entry.minute
              // <annotations>.<N>.entry.second
              Date date (i->first.substr (11));
                   if (elements[4] == "year")    { value = Variant (date.year ());      return true; }
              else if (elements[4] == "month")   { value = Variant (date.month ());     return true; }
              else if (elements[4] == "day")     { value = Variant (date.day ());       return true; }
              else if (elements[4] == "week")    { value = Variant (date.week ());      return true; }
              else if (elements[4] == "weekday") { value = Variant (date.dayOfWeek ()); return true; }
              else if (elements[4] == "julian")  { value = Variant (date.dayOfYear ()); return true; }
              else if (elements[4] == "hour")    { value = Variant (date.hour ());      return true; }
              else if (elements[4] == "minute")  { value = Variant (date.minute ());    return true; }
              else if (elements[4] == "second")  { value = Variant (date.second ());    return true; }
            }
          }
        }
      }
    }
  }

  // Delegate to the context-free version of DOM::get.
  return this->get (name, value);
}

////////////////////////////////////////////////////////////////////////////////
void DOM::set (const std::string& name, const Variant& value)
{
  int len = name.length ();

  // rc. --> context.config
  if (len > 3 &&
      name.substr (0, 3) == "rc.")
  {
    context.config.set (name.substr (3), (std::string) value);
  }

  // Unrecognized --> error.
  else
    throw format (STRING_DOM_CANNOT_SET, name);
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>#include "menuDemo.h"
#include "sinScrollDemo.h"
#include "peepHoleWindowDemo.h"
#include "spotlightDemo.h"
#include "demoRunner.h"
#include "scanInDemo.h"
#include "rasterbarDemo.h"
#include "flutterDemo.h"

#include <nds/arm9/console.h>
#include <cassert>
#include <nds/arm9/input.h>

MenuDemo::MenuDemo() : selection(0) {}
MenuDemo::~MenuDemo() {}
void MenuDemo::Load() {
	setupDefaultBG();
	consoleClear();
}
void MenuDemo::Unload() {}
void MenuDemo::PrepareFrame(VramBatcher &) {}

void MenuDemo::AcceptInput() {
	auto keys = keysDown();

	if(keys & KEY_UP && selection > 0) {
		selection--;
	} else if(keys & KEY_DOWN && selection+1 < demoCount) {
		selection++;
	}

	if(keys & KEY_START) {
		runner.RunDemo(makeDemo());
	}
}

std::shared_ptr<Demo> MenuDemo::makeDemo() {
	switch(selection) {
	case 0:
		return std::make_shared<SinXScrollDemo>();
	case 1:
		return std::make_shared<SpotLightDemo>();
	case 2:
		return std::make_shared<PeepHoleWindowDemo>();
	case 3:
		return std::make_shared<ScanInDemo>();
	case 4:
		return std::make_shared<RasterBarDemo>();
	case 5:
		return std::make_shared<FlutterDemo>();
	case 6:
		return std::make_shared<SinYScrollDemo>();
	}
	sassert(0,"Bad menu selection instatiated");

	assert(0);
}
<commit_msg>Sort the demos to make logical sense<commit_after>#include "menuDemo.h"
#include "sinScrollDemo.h"
#include "peepHoleWindowDemo.h"
#include "spotlightDemo.h"
#include "demoRunner.h"
#include "scanInDemo.h"
#include "rasterbarDemo.h"
#include "flutterDemo.h"

#include <nds/arm9/console.h>
#include <cassert>
#include <nds/arm9/input.h>

MenuDemo::MenuDemo() : selection(0) {}
MenuDemo::~MenuDemo() {}
void MenuDemo::Load() {
	setupDefaultBG();
	consoleClear();
}
void MenuDemo::Unload() {}
void MenuDemo::PrepareFrame(VramBatcher &) {}

void MenuDemo::AcceptInput() {
	auto keys = keysDown();

	if(keys & KEY_UP && selection > 0) {
		selection--;
	} else if(keys & KEY_DOWN && selection+1 < demoCount) {
		selection++;
	}

	if(keys & KEY_START) {
		runner.RunDemo(makeDemo());
	}
}

std::shared_ptr<Demo> MenuDemo::makeDemo() {
	switch(selection) {
	case 0:
		return std::make_shared<SinXScrollDemo>();
	case 1:
		return std::make_shared<SinYScrollDemo>();
	case 2:
		return std::make_shared<ScanInDemo>();
	case 3:
		return std::make_shared<PeepHoleWindowDemo>();
	case 4:
		return std::make_shared<SpotLightDemo>();
	case 5:
		return std::make_shared<RasterBarDemo>();
	case 6:
		return std::make_shared<FlutterDemo>();

	}
	sassert(0,"Bad menu selection instatiated");

	assert(0);
}
<|endoftext|>


<commit_before>#include "dataload_ros.h"
#include <QTextStream>
#include <QFile>
#include <QMessageBox>
#include <QDebug>
#include <QApplication>
#include <QProgressDialog>
#include <QElapsedTimer>
#include <QFileInfo>
#include <QProcess>
#include <rosbag/view.h>
#include <sys/sysinfo.h>
#include <QSettings>

#include "../dialog_select_ros_topics.h"
#include "../shape_shifter_factory.hpp"
#include "../rule_editing.h"

DataLoadROS::DataLoadROS()
{
    _extensions.push_back( "bag");
}

const std::vector<const char*> &DataLoadROS::compatibleFileExtensions() const
{
    return _extensions;
}

size_t getAvailableRAM()
{
    struct sysinfo info;
    sysinfo(&info);
    return info.freeram;
}

PlotDataMap DataLoadROS::readDataFromFile(const QString &file_name, bool use_previous_configuration)
{
    if( _bag ) _bag->close();

    _bag = std::make_shared<rosbag::Bag>();

    using namespace RosIntrospection;

    std::vector<std::pair<QString,QString>> all_topics;
    PlotDataMap plot_map;

    try{
        _bag->open( file_name.toStdString(), rosbag::bagmode::Read );
    }
    catch( rosbag::BagException&  ex)
    {
        QMessageBox::warning(0, tr("Error"),
                             QString("rosbag::open thrown an exception:\n")+
                             QString(ex.what()) );
        return PlotDataMap{};
    }

    rosbag::View bag_view ( *_bag, ros::TIME_MIN, ros::TIME_MAX, true );
    std::vector<const rosbag::ConnectionInfo*> connections = bag_view.getConnections();

    for(unsigned i=0; i<connections.size(); i++)
    {
        const auto&  topic      =  connections[i]->topic;
        const auto&  md5sum     =  connections[i]->md5sum;
        const auto&  datatype   =  connections[i]->datatype;
        const auto&  definition =  connections[i]->msg_def;

        all_topics.push_back( std::make_pair(QString( topic.c_str()), QString( datatype.c_str()) ) );
        RosIntrospectionFactory::registerMessage(topic, md5sum, datatype, definition);
    }

    int count = 0;

    //----------------------------------
    QSettings settings( "IcarusTechnology", "PlotJuggler");

    if( _default_topic_names.empty())
    {
        // if _default_topic_names is empty (xmlLoad didn't work) use QSettings.
        QVariant def = settings.value("DataLoadROS/default_topics");
        if( !def.isNull() && def.isValid())
        {
            _default_topic_names = def.toStringList();
        }
    }

    DialogSelectRosTopics* dialog = new DialogSelectRosTopics( all_topics, _default_topic_names );

    if( !use_previous_configuration )
    {
        if( dialog->exec() == static_cast<int>(QDialog::Accepted) )
        {
            _default_topic_names = dialog->getSelectedItems();

            // load the rules
            if( dialog->checkBoxUseRenamingRules()->isChecked())
            {
                _rules = RuleEditing::getRenamingRules();
            }
            else{
                _rules.clear();
            }
            for(const auto& it: _rules) {
                RosIntrospectionFactory::parser().registerRenamingRules( ROSType(it.first) , it.second );
            }
        }
        settings.setValue("DataLoadROS/default_topics", _default_topic_names);
    }
    //-----------------------------------
    std::set<std::string> topic_selected;
    for(const auto& topic: _default_topic_names)
    {
        topic_selected.insert( topic.toStdString() );
    }

    QProgressDialog progress_dialog;
    progress_dialog.setLabelText("Loading... please wait");
    progress_dialog.setWindowModality( Qt::ApplicationModal );

    rosbag::View bag_view_selected ( true );
    bag_view_selected.addQuery( *_bag, [topic_selected](rosbag::ConnectionInfo const* connection)
    {
        return topic_selected.find( connection->topic ) != topic_selected.end();
    } );
    progress_dialog.setRange(0, bag_view_selected.size()-1);
    progress_dialog.show();

    QElapsedTimer timer;
    timer.start();

    static FlatMessage flat_container;
    static std::vector<uint8_t> buffer;
    static RenamedValues renamed_value;

    for(rosbag::MessageInstance msg_instance: bag_view_selected )
    {
        const std::string& topic_name  = msg_instance.getTopic();
        const std::string& datatype = msg_instance.getDataType();
        const size_t msg_size  = msg_instance.size();

        buffer.resize(msg_size);

        if( count++ %100 == 0)
        {
            progress_dialog.setValue( count );
            QApplication::processEvents();

            if( progress_dialog.wasCanceled() ) {
                return PlotDataMap();
            }
        }

        ros::serialization::OStream stream(buffer.data(), buffer.size());
        msg_instance.write(stream);

        RosIntrospectionFactory::parser().deserializeIntoFlatContainer( topic_name, absl::Span<uint8_t>(buffer), &flat_container, 250 );
        RosIntrospectionFactory::parser().applyNameTransform( topic_name, flat_container, &renamed_value );

        // apply time offsets
        double msg_time = 0;

        if(dialog->checkBoxUseHeaderStamp()->isChecked() == false)
        {
            msg_time = msg_instance.getTime().toSec();
        }
        else{
            auto offset = FlatContainedContainHeaderStamp(renamed_value);
            if(offset){
                msg_time = offset.value();
            }
            else{
                msg_time = msg_instance.getTime().toSec();
            }
        }

        for(const auto& it: renamed_value )
        {
            const std::string& field_name = it.first;

            auto plot_pair = plot_map.numeric.find( field_name );
            if( !(plot_pair != plot_map.numeric.end()) )
            {
                PlotDataPtr temp(new PlotData(field_name.data()));
                auto res = plot_map.numeric.insert( std::make_pair(field_name, temp ) );
                plot_pair = res.first;
            }

            PlotDataPtr& plot_data = plot_pair->second;
            plot_data->pushBack( PlotData::Point(msg_time, it.second.convert<double>() ));
        } //end of for renamed_value

        //-----------------------------------------
        // adding raw serialized topic for future uses.
        {
            auto plot_pair = plot_map.user_defined.find( topic_name );

            if( plot_pair == plot_map.user_defined.end() )
            {
                PlotDataAnyPtr temp(new PlotDataAny(topic_name.c_str()));
                auto res = plot_map.user_defined.insert( std::make_pair( topic_name, temp ) );
                plot_pair = res.first;
            }
            PlotDataAnyPtr& plot_raw = plot_pair->second;
            plot_raw->pushBack( PlotDataAny::Point(msg_time, nonstd::any(std::move(msg_instance)) ));
        }
    }

    qDebug() << "The loading operation took" << timer.elapsed() << "milliseconds";
    return plot_map;
}

DataLoadROS::~DataLoadROS()
{

}

QDomElement DataLoadROS::xmlSaveState(QDomDocument &doc) const
{
    QString topics_list = _default_topic_names.join(";");
    QDomElement list_elem = doc.createElement("selected_topics");
    list_elem.setAttribute("list", topics_list );
    return list_elem;
}

bool DataLoadROS::xmlLoadState(QDomElement &parent_element)
{
    QDomElement list_elem = parent_element.firstChildElement( "selected_topics" );
    if( !list_elem.isNull()    )
    {
        if( list_elem.hasAttribute("list") )
        {
            QString topics_list = list_elem.attribute("list");
            _default_topic_names = topics_list.split(";", QString::SkipEmptyParts);
            return true;
        }
    }
    return false;
}

<commit_msg>warnings added<commit_after>#include "dataload_ros.h"
#include <QTextStream>
#include <QFile>
#include <QMessageBox>
#include <QDebug>
#include <QApplication>
#include <QProgressDialog>
#include <QElapsedTimer>
#include <QFileInfo>
#include <QProcess>
#include <rosbag/view.h>
#include <sys/sysinfo.h>
#include <QSettings>

#include "../dialog_select_ros_topics.h"
#include "../shape_shifter_factory.hpp"
#include "../rule_editing.h"

DataLoadROS::DataLoadROS()
{
    _extensions.push_back( "bag");
}

const std::vector<const char*> &DataLoadROS::compatibleFileExtensions() const
{
    return _extensions;
}

size_t getAvailableRAM()
{
    struct sysinfo info;
    sysinfo(&info);
    return info.freeram;
}

PlotDataMap DataLoadROS::readDataFromFile(const QString &file_name, bool use_previous_configuration)
{
    if( _bag ) _bag->close();

    _bag = std::make_shared<rosbag::Bag>();

    using namespace RosIntrospection;

    std::vector<std::pair<QString,QString>> all_topics;
    PlotDataMap plot_map;

    try{
        _bag->open( file_name.toStdString(), rosbag::bagmode::Read );
    }
    catch( rosbag::BagException&  ex)
    {
        QMessageBox::warning(0, tr("Error"),
                             QString("rosbag::open thrown an exception:\n")+
                             QString(ex.what()) );
        return PlotDataMap{};
    }

    rosbag::View bag_view ( *_bag, ros::TIME_MIN, ros::TIME_MAX, true );
    std::vector<const rosbag::ConnectionInfo*> connections = bag_view.getConnections();

    for(unsigned i=0; i<connections.size(); i++)
    {
        const auto&  topic      =  connections[i]->topic;
        const auto&  md5sum     =  connections[i]->md5sum;
        const auto&  datatype   =  connections[i]->datatype;
        const auto&  definition =  connections[i]->msg_def;

        all_topics.push_back( std::make_pair(QString( topic.c_str()), QString( datatype.c_str()) ) );
        RosIntrospectionFactory::registerMessage(topic, md5sum, datatype, definition);
    }

    int count = 0;

    //----------------------------------
    QSettings settings( "IcarusTechnology", "PlotJuggler");

    if( _default_topic_names.empty())
    {
        // if _default_topic_names is empty (xmlLoad didn't work) use QSettings.
        QVariant def = settings.value("DataLoadROS/default_topics");
        if( !def.isNull() && def.isValid())
        {
            _default_topic_names = def.toStringList();
        }
    }

    DialogSelectRosTopics* dialog = new DialogSelectRosTopics( all_topics, _default_topic_names );

    if( !use_previous_configuration )
    {
        if( dialog->exec() == static_cast<int>(QDialog::Accepted) )
        {
            _default_topic_names = dialog->getSelectedItems();

            // load the rules
            if( dialog->checkBoxUseRenamingRules()->isChecked())
            {
                _rules = RuleEditing::getRenamingRules();
            }
            else{
                _rules.clear();
            }
            for(const auto& it: _rules) {
                RosIntrospectionFactory::parser().registerRenamingRules( ROSType(it.first) , it.second );
            }
        }
        settings.setValue("DataLoadROS/default_topics", _default_topic_names);
    }
    //-----------------------------------
    std::set<std::string> topic_selected;
    for(const auto& topic: _default_topic_names)
    {
        topic_selected.insert( topic.toStdString() );
    }

    QProgressDialog progress_dialog;
    progress_dialog.setLabelText("Loading... please wait");
    progress_dialog.setWindowModality( Qt::ApplicationModal );

    rosbag::View bag_view_selected ( true );
    bag_view_selected.addQuery( *_bag, [topic_selected](rosbag::ConnectionInfo const* connection)
    {
        return topic_selected.find( connection->topic ) != topic_selected.end();
    } );
    progress_dialog.setRange(0, bag_view_selected.size()-1);
    progress_dialog.show();

    QElapsedTimer timer;
    timer.start();

    static FlatMessage flat_container;
    static std::vector<uint8_t> buffer;
    static RenamedValues renamed_value;

    bool parsed = true;

    for(rosbag::MessageInstance msg_instance: bag_view_selected )
    {
        const std::string& topic_name  = msg_instance.getTopic();
        const std::string& datatype = msg_instance.getDataType();
        const size_t msg_size  = msg_instance.size();

        buffer.resize(msg_size);

        if( count++ %100 == 0)
        {
            progress_dialog.setValue( count );
            QApplication::processEvents();

            if( progress_dialog.wasCanceled() ) {
                return PlotDataMap();
            }
        }

        ros::serialization::OStream stream(buffer.data(), buffer.size());
        msg_instance.write(stream);

        parsed &= RosIntrospectionFactory::parser().deserializeIntoFlatContainer( topic_name,
                                                                                absl::Span<uint8_t>(buffer),
                                                                                &flat_container, 250 );
        RosIntrospectionFactory::parser().applyNameTransform( topic_name, flat_container, &renamed_value );

        // apply time offsets
        double msg_time = 0;

        if(dialog->checkBoxUseHeaderStamp()->isChecked() == false)
        {
            msg_time = msg_instance.getTime().toSec();
        }
        else{
            auto offset = FlatContainedContainHeaderStamp(renamed_value);
            if(offset){
                msg_time = offset.value();
            }
            else{
                msg_time = msg_instance.getTime().toSec();
            }
        }

        for(const auto& it: renamed_value )
        {
            const std::string& field_name = it.first;

            auto plot_pair = plot_map.numeric.find( field_name );
            if( !(plot_pair != plot_map.numeric.end()) )
            {
                PlotDataPtr temp(new PlotData(field_name.data()));
                auto res = plot_map.numeric.insert( std::make_pair(field_name, temp ) );
                plot_pair = res.first;
            }

            PlotDataPtr& plot_data = plot_pair->second;
            plot_data->pushBack( PlotData::Point(msg_time, it.second.convert<double>() ));
        } //end of for renamed_value

        //-----------------------------------------
        // adding raw serialized topic for future uses.
        {
            auto plot_pair = plot_map.user_defined.find( topic_name );

            if( plot_pair == plot_map.user_defined.end() )
            {
                PlotDataAnyPtr temp(new PlotDataAny(topic_name.c_str()));
                auto res = plot_map.user_defined.insert( std::make_pair( topic_name, temp ) );
                plot_pair = res.first;
            }
            PlotDataAnyPtr& plot_raw = plot_pair->second;
            plot_raw->pushBack( PlotDataAny::Point(msg_time, nonstd::any(std::move(msg_instance)) ));
        }
    }
    if( !parsed )
    {
      QMessageBox::warning(0, tr("Warning"),
                           tr("Some fields were not parsed, because they contain arrays\n"
                              "larger than 250 elements.") );
    }

    qDebug() << "The loading operation took" << timer.elapsed() << "milliseconds";
    return plot_map;
}

DataLoadROS::~DataLoadROS()
{

}

QDomElement DataLoadROS::xmlSaveState(QDomDocument &doc) const
{
    QString topics_list = _default_topic_names.join(";");
    QDomElement list_elem = doc.createElement("selected_topics");
    list_elem.setAttribute("list", topics_list );
    return list_elem;
}

bool DataLoadROS::xmlLoadState(QDomElement &parent_element)
{
    QDomElement list_elem = parent_element.firstChildElement( "selected_topics" );
    if( !list_elem.isNull()    )
    {
        if( list_elem.hasAttribute("list") )
        {
            QString topics_list = list_elem.attribute("list");
            _default_topic_names = topics_list.split(";", QString::SkipEmptyParts);
            return true;
        }
    }
    return false;
}

<|endoftext|>


<commit_before>/***********************************************************************
    filename:   CEGUIOpenGL3RenderTarget.cpp
    created:    Wed, 8th Feb 2012
    author:     Lukas E Meindl (based on code by Paul D Turner)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2012 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/RendererModules/OpenGL/RenderTarget.h"
#include "CEGUI/RenderQueue.h"
#include "CEGUI/RendererModules/OpenGL/GeometryBufferBase.h"
#include "CEGUI/RendererModules/OpenGL/GlmPimpl.h"

#include <cmath>

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
template <typename T>
const double OpenGLRenderTarget<T>::d_yfov_tan = 0.267949192431123;

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::OpenGLRenderTarget(OpenGLRendererBase& owner) :
    d_owner(owner),
    d_area(0, 0, 0, 0),
    d_matrix(0),
    d_matrixValid(false),
    d_viewDistance(0)
{
    d_matrix = new mat4Pimpl();
}

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::~OpenGLRenderTarget()
{
    delete d_matrix;
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const GeometryBuffer& buffer)
{
    buffer.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const RenderQueue& queue)
{
    queue.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::setArea(const Rectf& area)
{
    d_area = area;
    d_matrixValid = false;

    RenderTargetEventArgs args(this);
    T::fireEvent(RenderTarget::EventAreaChanged, args);
}

//----------------------------------------------------------------------------//
template <typename T>
const Rectf& OpenGLRenderTarget<T>::getArea() const
{
    return d_area;
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::activate()
{
    glViewport(static_cast<GLsizei>(d_area.left()),
               static_cast<GLsizei>(d_area.top()),
               static_cast<GLsizei>(d_area.getWidth()),
               static_cast<GLsizei>(d_area.getHeight()));

    if (!d_matrixValid)
        updateMatrix();

    d_owner.setViewProjectionMatrix(d_matrix);

    d_owner.setActiveRenderTarget(this);
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::deactivate()
{
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::unprojectPoint(const GeometryBuffer& buff,
    const Vector2f& p_in, Vector2f& p_out) const
{
    if (!d_matrixValid)
        updateMatrix();

    const OpenGLGeometryBufferBase& gb =
        static_cast<const OpenGLGeometryBufferBase&>(buff);

    const GLint vp[4] = {
        static_cast<GLint>(d_area.left()),
        static_cast<GLint>(d_area.top()),
        static_cast<GLint>(d_area.getWidth()),
        static_cast<GLint>(d_area.getHeight())
    };

    GLdouble in_x, in_y, in_z = 0.0;

    glm::ivec4 viewPort = glm::ivec4(vp[0], vp[1], vp[2], vp[3]);
    const glm::mat4& projMatrix = d_matrix->d_matrix;
    const glm::mat4& modelMatrix = gb.getMatrix()->d_matrix;

    // unproject the ends of the ray
    glm::vec3 unprojected1;
    glm::vec3 unprojected2;
    in_x = vp[2] * 0.5;
    in_y = vp[3] * 0.5;
    in_z = -d_viewDistance;
    unprojected1 =  glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = p_in.d_x;
    in_y = vp[3] - p_in.d_y;
    in_z = 0.0;
    unprojected2 = glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // project points to orientate them with GeometryBuffer plane
    glm::vec3 projected1;
    glm::vec3 projected2;
    glm::vec3 projected3;
    in_x = 0.0;
    in_y = 0.0;
    projected1 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 1.0;
    in_y = 0.0;
    projected2 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 0.0;
    in_y = 1.0;
    projected3 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // calculate vectors for generating the plane
    const glm::vec3 pv1 = projected2 - projected1;
    const glm::vec3 pv2 = projected3 - projected1;
    // given the vectors, calculate the plane normal
    const glm::vec3 planeNormal = glm::cross(pv1, pv2);
    // calculate plane
    const glm::vec3 planeNormalNormalized = glm::normalize(planeNormal);
    const double pl_d = - glm::dot(projected1, planeNormalNormalized);
    // calculate vector of picking ray
    const glm::vec3 rv = unprojected1 - unprojected2;
    // calculate intersection of ray and plane
    const double pn_dot_r1 = glm::dot(unprojected1, planeNormal);
    const double pn_dot_rv = glm::dot(rv, planeNormal);
    const double tmp1 = pn_dot_rv != 0.0 ? (pn_dot_r1 + pl_d) / pn_dot_rv : 0.0;
    const double is_x = unprojected1.x - rv.x * tmp1;
    const double is_y = unprojected1.y - rv.y * tmp1;

    p_out.d_x = static_cast<float>(is_x);
    p_out.d_y = static_cast<float>(is_y);

    p_out = p_in; // CrazyEddie wanted this
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::updateMatrix() const
{
    const float w = d_area.getWidth();
    const float h = d_area.getHeight();
    const float aspect = w / h;
    const float midx = w * 0.5f;
    const float midy = h * 0.5f;
    d_viewDistance = midx / (aspect * d_yfov_tan);

    glm::vec3 eye = glm::vec3(midx, midy, float(-d_viewDistance));
    glm::vec3 center = glm::vec3(midx, midy, 1);
    glm::vec3 up = glm::vec3(0, -1, 0);

    glm::mat4 projectionMatrix = glm::perspective(30.f, aspect, float(d_viewDistance * 0.5), float(d_viewDistance * 2.0));
    // Projection matrix abuse!
    glm::mat4 viewMatrix = glm::lookAt(eye, center, up);

    d_matrix->d_matrix = projectionMatrix * viewMatrix;

    d_matrixValid = true;
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<commit_msg>MOD: Fixing assert issues on MSVC in glm when a 0-sized window is used happens only for autorendering surfaces, because of the calculations done in the rendertarget class<commit_after>/***********************************************************************
    filename:   CEGUIOpenGL3RenderTarget.cpp
    created:    Wed, 8th Feb 2012
    author:     Lukas E Meindl (based on code by Paul D Turner)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2012 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/RendererModules/OpenGL/RenderTarget.h"
#include "CEGUI/RenderQueue.h"
#include "CEGUI/RendererModules/OpenGL/GeometryBufferBase.h"
#include "CEGUI/RendererModules/OpenGL/GlmPimpl.h"

#include <cmath>

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
template <typename T>
const double OpenGLRenderTarget<T>::d_yfov_tan = 0.267949192431123;

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::OpenGLRenderTarget(OpenGLRendererBase& owner) :
    d_owner(owner),
    d_area(0, 0, 0, 0),
    d_matrix(0),
    d_matrixValid(false),
    d_viewDistance(0)
{
    d_matrix = new mat4Pimpl();
}

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::~OpenGLRenderTarget()
{
    delete d_matrix;
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const GeometryBuffer& buffer)
{
    buffer.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const RenderQueue& queue)
{
    queue.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::setArea(const Rectf& area)
{
    d_area = area;
    d_matrixValid = false;

    RenderTargetEventArgs args(this);
    T::fireEvent(RenderTarget::EventAreaChanged, args);
}

//----------------------------------------------------------------------------//
template <typename T>
const Rectf& OpenGLRenderTarget<T>::getArea() const
{
    return d_area;
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::activate()
{
    glViewport(static_cast<GLsizei>(d_area.left()),
               static_cast<GLsizei>(d_area.top()),
               static_cast<GLsizei>(d_area.getWidth()),
               static_cast<GLsizei>(d_area.getHeight()));

    if (!d_matrixValid)
        updateMatrix();

    d_owner.setViewProjectionMatrix(d_matrix);

    d_owner.setActiveRenderTarget(this);
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::deactivate()
{
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::unprojectPoint(const GeometryBuffer& buff,
    const Vector2f& p_in, Vector2f& p_out) const
{
    if (!d_matrixValid)
        updateMatrix();

    const OpenGLGeometryBufferBase& gb =
        static_cast<const OpenGLGeometryBufferBase&>(buff);

    const GLint vp[4] = {
        static_cast<GLint>(d_area.left()),
        static_cast<GLint>(d_area.top()),
        static_cast<GLint>(d_area.getWidth()),
        static_cast<GLint>(d_area.getHeight())
    };

    GLdouble in_x, in_y, in_z = 0.0;

    glm::ivec4 viewPort = glm::ivec4(vp[0], vp[1], vp[2], vp[3]);
    const glm::mat4& projMatrix = d_matrix->d_matrix;
    const glm::mat4& modelMatrix = gb.getMatrix()->d_matrix;

    // unproject the ends of the ray
    glm::vec3 unprojected1;
    glm::vec3 unprojected2;
    in_x = vp[2] * 0.5;
    in_y = vp[3] * 0.5;
    in_z = -d_viewDistance;
    unprojected1 =  glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = p_in.d_x;
    in_y = vp[3] - p_in.d_y;
    in_z = 0.0;
    unprojected2 = glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // project points to orientate them with GeometryBuffer plane
    glm::vec3 projected1;
    glm::vec3 projected2;
    glm::vec3 projected3;
    in_x = 0.0;
    in_y = 0.0;
    projected1 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 1.0;
    in_y = 0.0;
    projected2 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 0.0;
    in_y = 1.0;
    projected3 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // calculate vectors for generating the plane
    const glm::vec3 pv1 = projected2 - projected1;
    const glm::vec3 pv2 = projected3 - projected1;
    // given the vectors, calculate the plane normal
    const glm::vec3 planeNormal = glm::cross(pv1, pv2);
    // calculate plane
    const glm::vec3 planeNormalNormalized = glm::normalize(planeNormal);
    const double pl_d = - glm::dot(projected1, planeNormalNormalized);
    // calculate vector of picking ray
    const glm::vec3 rv = unprojected1 - unprojected2;
    // calculate intersection of ray and plane
    const double pn_dot_r1 = glm::dot(unprojected1, planeNormal);
    const double pn_dot_rv = glm::dot(rv, planeNormal);
    const double tmp1 = pn_dot_rv != 0.0 ? (pn_dot_r1 + pl_d) / pn_dot_rv : 0.0;
    const double is_x = unprojected1.x - rv.x * tmp1;
    const double is_y = unprojected1.y - rv.y * tmp1;

    p_out.d_x = static_cast<float>(is_x);
    p_out.d_y = static_cast<float>(is_y);

    p_out = p_in; // CrazyEddie wanted this
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::updateMatrix() const
{
    const float w = d_area.getWidth();
    const float h = d_area.getHeight();

    // We need to check if width or height are zero and act accordingly to prevent running into issues
    // with divisions by zero which would lead to undefined values, as well as faulty clipping planes
    // This is mostly important for avoiding asserts
    bool widthAndHeightNotZero = ( w != 0.0f ) && ( h != 0.0f);

    const float aspect = widthAndHeightNotZero ? w / h : 1.0f;
    const float midx = widthAndHeightNotZero ? w * 0.5f : 0.5f;
    const float midy = widthAndHeightNotZero ? h * 0.5f : 0.5f;
    d_viewDistance = midx / (aspect * d_yfov_tan);

    glm::vec3 eye = glm::vec3(midx, midy, float(-d_viewDistance));
    glm::vec3 center = glm::vec3(midx, midy, 1);
    glm::vec3 up = glm::vec3(0, -1, 0);

    glm::mat4 projectionMatrix = glm::perspective(30.f, aspect, float(d_viewDistance * 0.5), float(d_viewDistance * 2.0));
    // Projection matrix abuse!
    glm::mat4 viewMatrix = glm::lookAt(eye, center, up);

    d_matrix->d_matrix = projectionMatrix * viewMatrix;

    d_matrixValid = true;
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>/***********************************************************************
    created:    Tue Jul 5 2005
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/WindowRendererSets/Core/StaticImage.h"
#include "CEGUI/falagard/WidgetLookManager.h"
#include "CEGUI/falagard/WidgetLookFeel.h"
#include "CEGUI/TplWindowRendererProperty.h"

// Start of CEGUI namespace section
namespace CEGUI
{
    const String FalagardStaticImage::TypeName("Core/StaticImage");

    FalagardStaticImage::FalagardStaticImage(const String& type) :
        FalagardStatic(type),
        d_image(0)
    {
        CEGUI_DEFINE_WINDOW_RENDERER_PROPERTY(FalagardStaticImage, Image*,
            "Image", "Property to get/set the image for the FalagardStaticImage widget."
            "  Value is a pointer to an Image.",
            &FalagardStaticImage::setImage, &FalagardStaticImage::getImage,
            0);
    }

    void FalagardStaticImage::render()
    {
        // base class rendering
        FalagardStatic::render();

        // render image if there is one
        if (d_image!=0)
        {
            // get WidgetLookFeel for the assigned look.
            const WidgetLookFeel& wlf = getLookNFeel();
            String imagery_name = (!d_frameEnabled && wlf.isStateImageryPresent("NoFrameImage")) ? "NoFrameImage" : "WithFrameImage";
            wlf.getStateImagery(imagery_name).render(*d_window);
        }
    }

    void FalagardStaticImage::setImage(const Image* img)
    {
        d_image = img;
        d_window->invalidate();
    }

} // End of  CEGUI namespace section
<commit_msg>MOD: Correcting StaticImage Image prop description<commit_after>/***********************************************************************
    created:    Tue Jul 5 2005
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/WindowRendererSets/Core/StaticImage.h"
#include "CEGUI/falagard/WidgetLookManager.h"
#include "CEGUI/falagard/WidgetLookFeel.h"
#include "CEGUI/TplWindowRendererProperty.h"

// Start of CEGUI namespace section
namespace CEGUI
{
    const String FalagardStaticImage::TypeName("Core/StaticImage");

    FalagardStaticImage::FalagardStaticImage(const String& type) :
        FalagardStatic(type),
        d_image(0)
    {
        CEGUI_DEFINE_WINDOW_RENDERER_PROPERTY(FalagardStaticImage, Image*,
            "Image", "Property to get/set the image for the FalagardStaticImage widget."
            " Value is \"ImagesetName/ImageName\".",
            &FalagardStaticImage::setImage, &FalagardStaticImage::getImage,
            0);
    }

    void FalagardStaticImage::render()
    {
        // base class rendering
        FalagardStatic::render();

        // render image if there is one
        if (d_image!=0)
        {
            // get WidgetLookFeel for the assigned look.
            const WidgetLookFeel& wlf = getLookNFeel();
            String imagery_name = (!d_frameEnabled && wlf.isStateImageryPresent("NoFrameImage")) ? "NoFrameImage" : "WithFrameImage";
            wlf.getStateImagery(imagery_name).render(*d_window);
        }
    }

    void FalagardStaticImage::setImage(const Image* img)
    {
        d_image = img;
        d_window->invalidate();
    }

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "meegotapsensor.h"

char const * const meegotapsensor::id("meego.tapsensor");
bool meegotapsensor::m_initDone = false;

meegotapsensor::meegotapsensor(QSensor *sensor)
    : meegosensorbase(sensor), m_isOnceStarted(false)
{
    initSensor<TapSensorChannelInterface>(m_initDone);
    setReading<QTapReading>(&m_reading);
}

void meegotapsensor::start(){
    QVariant v = sensor()->property("returnDoubleTapEvents");
    bool isDoubleTapSensor = m_isDoubleTapSensor;
    if (!(v.isValid())){
        sensor()->setProperty("returnDoubleTapEvents", true); //by default doubles
        m_isDoubleTapSensor = true;
    }
    else m_isDoubleTapSensor = v.toBool();

    if (!m_isOnceStarted || (m_isOnceStarted && isDoubleTapSensor != m_isDoubleTapSensor))
        ((TapSensorChannelInterface*)m_sensorInterface)->
                setTapType(m_isDoubleTapSensor?TapSensorChannelInterface::Double:TapSensorChannelInterface::Single);

    meegosensorbase::start();
    // Set tap type (single/double)
    m_reading.setDoubleTap(m_isDoubleTapSensor);
    m_isOnceStarted = true;
}

void meegotapsensor::slotDataAvailable(const Tap& data)
{
    // Set tap direction
    QTapReading::TapDirection o;
    switch (data.direction()) {
    case TapData::X:         o = QTapReading::X_Both;    break;
    case TapData::Y:         o = QTapReading::Y_Both;    break;
    case TapData::Z:         o = QTapReading::Z_Both;    break;
    case TapData::LeftRight: o = QTapReading::X_Pos;     break;
    case TapData::RightLeft: o = QTapReading::X_Neg;     break;
    case TapData::TopBottom: o = QTapReading::Z_Neg;     break;
    case TapData::BottomTop: o = QTapReading::Z_Pos;     break;
    case TapData::FaceBack:  o = QTapReading::Y_Pos;     break;
    case TapData::BackFace:  o = QTapReading::Y_Neg;     break;
    default:                 o = QTapReading::Undefined;
    }
    m_reading.setTapDirection(o);
    m_reading.setTimestamp(data.tapData().timestamp_);
    newReadingAvailable();
}

bool meegotapsensor::doConnect(){
    if (!(QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const Tap&)),
                           this, SLOT(slotDataAvailable(const Tap&))))){
        return false;
    }
    return true;
}

const QString meegotapsensor::sensorName(){
    return "tapsensor";
}
<commit_msg>range added<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "meegotapsensor.h"

char const * const meegotapsensor::id("meego.tapsensor");
bool meegotapsensor::m_initDone = false;

meegotapsensor::meegotapsensor(QSensor *sensor)
    : meegosensorbase(sensor), m_isOnceStarted(false)
{
    initSensor<TapSensorChannelInterface>(m_initDone);
    setReading<QTapReading>(&m_reading);
    addOutputRange(QTapReading::Undefined, QTapReading::Z_Both, 1);
}

void meegotapsensor::start(){
    QVariant v = sensor()->property("returnDoubleTapEvents");
    bool isDoubleTapSensor = m_isDoubleTapSensor;
    if (!(v.isValid())){
        sensor()->setProperty("returnDoubleTapEvents", true); //by default doubles
        m_isDoubleTapSensor = true;
    }
    else m_isDoubleTapSensor = v.toBool();

    if (!m_isOnceStarted || (m_isOnceStarted && isDoubleTapSensor != m_isDoubleTapSensor))
        ((TapSensorChannelInterface*)m_sensorInterface)->
                setTapType(m_isDoubleTapSensor?TapSensorChannelInterface::Double:TapSensorChannelInterface::Single);

    meegosensorbase::start();
    // Set tap type (single/double)
    m_reading.setDoubleTap(m_isDoubleTapSensor);
    m_isOnceStarted = true;
}

void meegotapsensor::slotDataAvailable(const Tap& data)
{
    // Set tap direction
    QTapReading::TapDirection o;
    switch (data.direction()) {
    case TapData::X:         o = QTapReading::X_Both;    break;
    case TapData::Y:         o = QTapReading::Y_Both;    break;
    case TapData::Z:         o = QTapReading::Z_Both;    break;
    case TapData::LeftRight: o = QTapReading::X_Pos;     break;
    case TapData::RightLeft: o = QTapReading::X_Neg;     break;
    case TapData::TopBottom: o = QTapReading::Z_Neg;     break;
    case TapData::BottomTop: o = QTapReading::Z_Pos;     break;
    case TapData::FaceBack:  o = QTapReading::Y_Pos;     break;
    case TapData::BackFace:  o = QTapReading::Y_Neg;     break;
    default:                 o = QTapReading::Undefined;
    }
    m_reading.setTapDirection(o);
    m_reading.setTimestamp(data.tapData().timestamp_);
    newReadingAvailable();
}

bool meegotapsensor::doConnect(){
    if (!(QObject::connect(m_sensorInterface, SIGNAL(dataAvailable(const Tap&)),
                           this, SLOT(slotDataAvailable(const Tap&))))){
        return false;
    }
    return true;
}

const QString meegotapsensor::sensorName(){
    return "tapsensor";
}
<|endoftext|>


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

#include "chrome/browser/autocomplete/shortcuts_provider.h"

#include <algorithm>
#include <cmath>
#include <map>
#include <vector>

#include "base/i18n/break_iterator.h"
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/guid.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "googleurl/src/url_parse.h"
#include "googleurl/src/url_util.h"
#include "net/base/escape.h"
#include "net/base/net_util.h"

using shortcuts_provider::Shortcut;
using shortcuts_provider::ShortcutMap;

namespace {

class RemoveMatchPredicate {
 public:
  explicit RemoveMatchPredicate(const std::set<GURL>& urls)
      : urls_(urls) {
  }
  bool operator()(AutocompleteMatch match) {
    return urls_.find(match.destination_url) != urls_.end();
  }
 private:
  // Lifetime of the object is less than the lifetime of passed |urls|, so
  // it is safe to store reference.
  const std::set<GURL>& urls_;
};

}  // namespace

ShortcutsProvider::ShortcutsProvider(ACProviderListener* listener,
                                     Profile* profile)
    : AutocompleteProvider(listener, profile, "ShortcutsProvider"),
      languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
      initialized_(false),
      shortcuts_backend_(profile->GetShortcutsBackend()) {
  if (shortcuts_backend_.get()) {
    shortcuts_backend_->AddObserver(this);
    if (shortcuts_backend_->initialized())
      initialized_ = true;
  }
}

ShortcutsProvider::~ShortcutsProvider() {
  if (shortcuts_backend_.get())
    shortcuts_backend_->RemoveObserver(this);
}

void ShortcutsProvider::Start(const AutocompleteInput& input,
                              bool minimal_changes) {
  matches_.clear();

  if (input.type() == AutocompleteInput::INVALID)
    return;

  if (input.text().empty())
    return;

  if (!initialized_)
    return;

  base::TimeTicks start_time = base::TimeTicks::Now();
  GetMatches(input);
  if (input.text().length() < 6) {
    base::TimeTicks end_time = base::TimeTicks::Now();
    std::string name = "ShortcutsProvider.QueryIndexTime." +
        base::IntToString(input.text().size());
    base::Histogram* counter = base::Histogram::FactoryGet(
        name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag);
    counter->Add(static_cast<int>((end_time - start_time).InMilliseconds()));
  }
  UpdateStarredStateOfMatches();
}

void ShortcutsProvider::DeleteMatch(const AutocompleteMatch& match) {
  // When a user deletes a match, he probably means for the URL to disappear out
  // of history entirely. So nuke all shortcuts that map to this URL.
  std::set<GURL> url;
  url.insert(match.destination_url);
  // Immediately delete matches and shortcuts with the URL, so we can update the
  // controller synchronously.
  DeleteShortcutsWithURLs(url);
  DeleteMatchesWithURLs(url);

  // Delete the match from the history DB. This will eventually result in a
  // second call to DeleteShortcutsWithURLs(), which is harmless.
  HistoryService* const history_service =
      profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);

  DCHECK(history_service && match.destination_url.is_valid());
  history_service->DeleteURL(match.destination_url);
}

void ShortcutsProvider::OnShortcutsLoaded() {
  initialized_ = true;
}

int ShortcutsProvider::GetMaxScore() {
  // For ease of unit testing, make the clamp value divisible by 4 (since some
  // tests check for half or quarter of the max score).
  const int kMaxScore = (AutocompleteResult::kLowestDefaultScore - 1) & ~3;
  return kMaxScore;
}

void ShortcutsProvider::DeleteMatchesWithURLs(const std::set<GURL>& urls) {
  std::remove_if(matches_.begin(), matches_.end(), RemoveMatchPredicate(urls));
  listener_->OnProviderUpdate(true);
}

void ShortcutsProvider::DeleteShortcutsWithURLs(const std::set<GURL>& urls) {
  if (!shortcuts_backend_.get())
    return;  // We are off the record.
  for (std::set<GURL>::const_iterator url = urls.begin(); url != urls.end();
       ++url)
    shortcuts_backend_->DeleteShortcutsWithUrl(*url);
}

void ShortcutsProvider::GetMatches(const AutocompleteInput& input) {
  // Get the URLs from the shortcuts database with keys that partially or
  // completely match the search term.
  string16 term_string(base::i18n::ToLower(input.text()));
  DCHECK(!term_string.empty());

  for (ShortcutMap::const_iterator it = FindFirstMatch(term_string);
       it != shortcuts_backend_->shortcuts_map().end() &&
            StartsWith(it->first, term_string, true); ++it)
    matches_.push_back(ShortcutToACMatch(input, term_string, it));
  std::partial_sort(matches_.begin(),
      matches_.begin() +
          std::min(AutocompleteProvider::kMaxMatches, matches_.size()),
      matches_.end(), &AutocompleteMatch::MoreRelevant);
  if (matches_.size() > AutocompleteProvider::kMaxMatches) {
    matches_.erase(matches_.begin() + AutocompleteProvider::kMaxMatches,
                   matches_.end());
  }
}

AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
    const AutocompleteInput& input,
    const string16& term_string,
    ShortcutMap::const_iterator it) {
  AutocompleteMatch match(this, CalculateScore(term_string, it->second),
                          true, AutocompleteMatch::HISTORY_TITLE);
  match.destination_url = it->second.url;
  DCHECK(match.destination_url.is_valid());
  match.fill_into_edit = UTF8ToUTF16(it->second.url.spec());

  match.contents = it->second.contents;
  match.contents_class = ClassifyAllMatchesInString(term_string,
                                                    match.contents,
                                                    it->second.contents_class);

  match.description = it->second.description;
  match.description_class = ClassifyAllMatchesInString(
      term_string, match.description, it->second.description_class);

  return match;
}

// static
ACMatchClassifications ShortcutsProvider::ClassifyAllMatchesInString(
    const string16& find_text,
    const string16& text,
    const ACMatchClassifications& original_matches) {
  DCHECK(!find_text.empty());

  base::i18n::BreakIterator term_iter(find_text,
                                      base::i18n::BreakIterator::BREAK_WORD);
  if (!term_iter.Init())
    return original_matches;

  std::vector<string16> terms;
  while (term_iter.Advance()) {
    if (term_iter.IsWord())
      terms.push_back(term_iter.GetString());
  }
  // Sort the strings so that longer strings appear after their prefixes, if
  // any.
  std::sort(terms.begin(), terms.end());

  // Find the earliest match of any word in |find_text| in the |text|. Add to
  // |matches|. Move pointer after match. Repeat until all matches are found.
  string16 text_lowercase(base::i18n::ToLower(text));
  ACMatchClassifications matches;
  // |matches| should start at the position 0, if the matched text start from
  // the position 0, this will be poped from the vector further down.
  matches.push_back(ACMatchClassification(0, ACMatchClassification::NONE));
  for (size_t last_position = 0; last_position < text_lowercase.length();) {
    size_t match_start = text_lowercase.length();
    size_t match_end = last_position;

    for (size_t i = 0; i < terms.size(); ++i) {
      size_t match = text_lowercase.find(terms[i], last_position);
      // Use <= in conjunction with the sort() call above so that longer strings
      // are matched in preference to their prefixes.
      if (match != string16::npos && match <= match_start) {
        match_start = match;
        match_end = match + terms[i].length();
      }
    }

    if (match_start >= match_end)
      break;

    // Collapse adjacent ranges into one.
    if (!matches.empty() && matches.back().offset == match_start)
      matches.pop_back();

    shortcuts_provider::AddLastMatchIfNeeded(&matches, match_start,
                                             ACMatchClassification::MATCH);
    if (match_end < text_lowercase.length()) {
      shortcuts_provider::AddLastMatchIfNeeded(&matches, match_end,
                                               ACMatchClassification::NONE);
    }

    last_position = match_end;
  }

  // Merge matches with highlight data.
  if (matches.empty())
    return original_matches;

  ACMatchClassifications output;
  for (ACMatchClassifications::const_iterator i = original_matches.begin(),
       j = matches.begin(); i != original_matches.end();) {
    shortcuts_provider::AddLastMatchIfNeeded(&output,
                                             std::max(i->offset, j->offset),
                                             i->style | j->style);
    if ((j + 1) == matches.end() || (((i + 1) != original_matches.end()) &&
        ((j + 1)->offset > (i + 1)->offset)))
      ++i;
    else
      ++j;
  }

  return output;
}

ShortcutMap::const_iterator ShortcutsProvider::FindFirstMatch(
    const string16& keyword) {
  ShortcutMap::const_iterator it =
      shortcuts_backend_->shortcuts_map().lower_bound(keyword);
  // Lower bound not necessarily matches the keyword, check for item pointed by
  // the lower bound iterator to at least start with keyword.
  return ((it == shortcuts_backend_->shortcuts_map().end()) ||
    StartsWith(it->first, keyword, true)) ? it :
    shortcuts_backend_->shortcuts_map().end();
}

// static
int ShortcutsProvider::CalculateScore(const string16& terms,
                                      const Shortcut& shortcut) {
  DCHECK(!terms.empty());
  DCHECK_LE(terms.length(), shortcut.text.length());

  // The initial score is based on how much of the shortcut the user has typed.
  double base_score = GetMaxScore() * static_cast<double>(terms.length()) /
      shortcut.text.length();

  // Then we decay this by half each week.
  const double kLn2 = 0.6931471805599453;
  base::TimeDelta time_passed = base::Time::Now() - shortcut.last_access_time;
  // Clamp to 0 in case time jumps backwards (e.g. due to DST).
  double decay_exponent = std::max(0.0, kLn2 * static_cast<double>(
      time_passed.InMicroseconds()) / base::Time::kMicrosecondsPerWeek);

  // We modulate the decay factor based on how many times the shortcut has been
  // used. Newly created shortcuts decay at full speed; otherwise, decaying by
  // half takes |n| times as much time, where n increases by
  // (1.0 / each 5 additional hits), up to a maximum of 5x as long.
  const double kMaxDecaySpeedDivisor = 5.0;
  const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0;
  double decay_divisor = std::min(kMaxDecaySpeedDivisor,
      (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) /
      kNumUsesPerDecaySpeedDivisorIncrement);

  return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) +
      0.5);
}

void ShortcutsProvider::set_shortcuts_backend(
    history::ShortcutsBackend* shortcuts_backend) {
  DCHECK(shortcuts_backend);
  shortcuts_backend_ = shortcuts_backend;
  shortcuts_backend_->AddObserver(this);
  if (shortcuts_backend_->initialized())
    initialized_ = true;
}

<commit_msg>[Coverity] Pass AutocompleteMatch to predicate as const-ref<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/autocomplete/shortcuts_provider.h"

#include <algorithm>
#include <cmath>
#include <map>
#include <vector>

#include "base/i18n/break_iterator.h"
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/guid.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "googleurl/src/url_parse.h"
#include "googleurl/src/url_util.h"
#include "net/base/escape.h"
#include "net/base/net_util.h"

using shortcuts_provider::Shortcut;
using shortcuts_provider::ShortcutMap;

namespace {

class RemoveMatchPredicate {
 public:
  explicit RemoveMatchPredicate(const std::set<GURL>& urls)
      : urls_(urls) {
  }
  bool operator()(const AutocompleteMatch& match) {
    return urls_.find(match.destination_url) != urls_.end();
  }
 private:
  // Lifetime of the object is less than the lifetime of passed |urls|, so
  // it is safe to store reference.
  const std::set<GURL>& urls_;
};

}  // namespace

ShortcutsProvider::ShortcutsProvider(ACProviderListener* listener,
                                     Profile* profile)
    : AutocompleteProvider(listener, profile, "ShortcutsProvider"),
      languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
      initialized_(false),
      shortcuts_backend_(profile->GetShortcutsBackend()) {
  if (shortcuts_backend_.get()) {
    shortcuts_backend_->AddObserver(this);
    if (shortcuts_backend_->initialized())
      initialized_ = true;
  }
}

ShortcutsProvider::~ShortcutsProvider() {
  if (shortcuts_backend_.get())
    shortcuts_backend_->RemoveObserver(this);
}

void ShortcutsProvider::Start(const AutocompleteInput& input,
                              bool minimal_changes) {
  matches_.clear();

  if (input.type() == AutocompleteInput::INVALID)
    return;

  if (input.text().empty())
    return;

  if (!initialized_)
    return;

  base::TimeTicks start_time = base::TimeTicks::Now();
  GetMatches(input);
  if (input.text().length() < 6) {
    base::TimeTicks end_time = base::TimeTicks::Now();
    std::string name = "ShortcutsProvider.QueryIndexTime." +
        base::IntToString(input.text().size());
    base::Histogram* counter = base::Histogram::FactoryGet(
        name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag);
    counter->Add(static_cast<int>((end_time - start_time).InMilliseconds()));
  }
  UpdateStarredStateOfMatches();
}

void ShortcutsProvider::DeleteMatch(const AutocompleteMatch& match) {
  // When a user deletes a match, he probably means for the URL to disappear out
  // of history entirely. So nuke all shortcuts that map to this URL.
  std::set<GURL> url;
  url.insert(match.destination_url);
  // Immediately delete matches and shortcuts with the URL, so we can update the
  // controller synchronously.
  DeleteShortcutsWithURLs(url);
  DeleteMatchesWithURLs(url);

  // Delete the match from the history DB. This will eventually result in a
  // second call to DeleteShortcutsWithURLs(), which is harmless.
  HistoryService* const history_service =
      profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);

  DCHECK(history_service && match.destination_url.is_valid());
  history_service->DeleteURL(match.destination_url);
}

void ShortcutsProvider::OnShortcutsLoaded() {
  initialized_ = true;
}

int ShortcutsProvider::GetMaxScore() {
  // For ease of unit testing, make the clamp value divisible by 4 (since some
  // tests check for half or quarter of the max score).
  const int kMaxScore = (AutocompleteResult::kLowestDefaultScore - 1) & ~3;
  return kMaxScore;
}

void ShortcutsProvider::DeleteMatchesWithURLs(const std::set<GURL>& urls) {
  std::remove_if(matches_.begin(), matches_.end(), RemoveMatchPredicate(urls));
  listener_->OnProviderUpdate(true);
}

void ShortcutsProvider::DeleteShortcutsWithURLs(const std::set<GURL>& urls) {
  if (!shortcuts_backend_.get())
    return;  // We are off the record.
  for (std::set<GURL>::const_iterator url = urls.begin(); url != urls.end();
       ++url)
    shortcuts_backend_->DeleteShortcutsWithUrl(*url);
}

void ShortcutsProvider::GetMatches(const AutocompleteInput& input) {
  // Get the URLs from the shortcuts database with keys that partially or
  // completely match the search term.
  string16 term_string(base::i18n::ToLower(input.text()));
  DCHECK(!term_string.empty());

  for (ShortcutMap::const_iterator it = FindFirstMatch(term_string);
       it != shortcuts_backend_->shortcuts_map().end() &&
            StartsWith(it->first, term_string, true); ++it)
    matches_.push_back(ShortcutToACMatch(input, term_string, it));
  std::partial_sort(matches_.begin(),
      matches_.begin() +
          std::min(AutocompleteProvider::kMaxMatches, matches_.size()),
      matches_.end(), &AutocompleteMatch::MoreRelevant);
  if (matches_.size() > AutocompleteProvider::kMaxMatches) {
    matches_.erase(matches_.begin() + AutocompleteProvider::kMaxMatches,
                   matches_.end());
  }
}

AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
    const AutocompleteInput& input,
    const string16& term_string,
    ShortcutMap::const_iterator it) {
  AutocompleteMatch match(this, CalculateScore(term_string, it->second),
                          true, AutocompleteMatch::HISTORY_TITLE);
  match.destination_url = it->second.url;
  DCHECK(match.destination_url.is_valid());
  match.fill_into_edit = UTF8ToUTF16(it->second.url.spec());

  match.contents = it->second.contents;
  match.contents_class = ClassifyAllMatchesInString(term_string,
                                                    match.contents,
                                                    it->second.contents_class);

  match.description = it->second.description;
  match.description_class = ClassifyAllMatchesInString(
      term_string, match.description, it->second.description_class);

  return match;
}

// static
ACMatchClassifications ShortcutsProvider::ClassifyAllMatchesInString(
    const string16& find_text,
    const string16& text,
    const ACMatchClassifications& original_matches) {
  DCHECK(!find_text.empty());

  base::i18n::BreakIterator term_iter(find_text,
                                      base::i18n::BreakIterator::BREAK_WORD);
  if (!term_iter.Init())
    return original_matches;

  std::vector<string16> terms;
  while (term_iter.Advance()) {
    if (term_iter.IsWord())
      terms.push_back(term_iter.GetString());
  }
  // Sort the strings so that longer strings appear after their prefixes, if
  // any.
  std::sort(terms.begin(), terms.end());

  // Find the earliest match of any word in |find_text| in the |text|. Add to
  // |matches|. Move pointer after match. Repeat until all matches are found.
  string16 text_lowercase(base::i18n::ToLower(text));
  ACMatchClassifications matches;
  // |matches| should start at the position 0, if the matched text start from
  // the position 0, this will be poped from the vector further down.
  matches.push_back(ACMatchClassification(0, ACMatchClassification::NONE));
  for (size_t last_position = 0; last_position < text_lowercase.length();) {
    size_t match_start = text_lowercase.length();
    size_t match_end = last_position;

    for (size_t i = 0; i < terms.size(); ++i) {
      size_t match = text_lowercase.find(terms[i], last_position);
      // Use <= in conjunction with the sort() call above so that longer strings
      // are matched in preference to their prefixes.
      if (match != string16::npos && match <= match_start) {
        match_start = match;
        match_end = match + terms[i].length();
      }
    }

    if (match_start >= match_end)
      break;

    // Collapse adjacent ranges into one.
    if (!matches.empty() && matches.back().offset == match_start)
      matches.pop_back();

    shortcuts_provider::AddLastMatchIfNeeded(&matches, match_start,
                                             ACMatchClassification::MATCH);
    if (match_end < text_lowercase.length()) {
      shortcuts_provider::AddLastMatchIfNeeded(&matches, match_end,
                                               ACMatchClassification::NONE);
    }

    last_position = match_end;
  }

  // Merge matches with highlight data.
  if (matches.empty())
    return original_matches;

  ACMatchClassifications output;
  for (ACMatchClassifications::const_iterator i = original_matches.begin(),
       j = matches.begin(); i != original_matches.end();) {
    shortcuts_provider::AddLastMatchIfNeeded(&output,
                                             std::max(i->offset, j->offset),
                                             i->style | j->style);
    if ((j + 1) == matches.end() || (((i + 1) != original_matches.end()) &&
        ((j + 1)->offset > (i + 1)->offset)))
      ++i;
    else
      ++j;
  }

  return output;
}

ShortcutMap::const_iterator ShortcutsProvider::FindFirstMatch(
    const string16& keyword) {
  ShortcutMap::const_iterator it =
      shortcuts_backend_->shortcuts_map().lower_bound(keyword);
  // Lower bound not necessarily matches the keyword, check for item pointed by
  // the lower bound iterator to at least start with keyword.
  return ((it == shortcuts_backend_->shortcuts_map().end()) ||
    StartsWith(it->first, keyword, true)) ? it :
    shortcuts_backend_->shortcuts_map().end();
}

// static
int ShortcutsProvider::CalculateScore(const string16& terms,
                                      const Shortcut& shortcut) {
  DCHECK(!terms.empty());
  DCHECK_LE(terms.length(), shortcut.text.length());

  // The initial score is based on how much of the shortcut the user has typed.
  double base_score = GetMaxScore() * static_cast<double>(terms.length()) /
      shortcut.text.length();

  // Then we decay this by half each week.
  const double kLn2 = 0.6931471805599453;
  base::TimeDelta time_passed = base::Time::Now() - shortcut.last_access_time;
  // Clamp to 0 in case time jumps backwards (e.g. due to DST).
  double decay_exponent = std::max(0.0, kLn2 * static_cast<double>(
      time_passed.InMicroseconds()) / base::Time::kMicrosecondsPerWeek);

  // We modulate the decay factor based on how many times the shortcut has been
  // used. Newly created shortcuts decay at full speed; otherwise, decaying by
  // half takes |n| times as much time, where n increases by
  // (1.0 / each 5 additional hits), up to a maximum of 5x as long.
  const double kMaxDecaySpeedDivisor = 5.0;
  const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0;
  double decay_divisor = std::min(kMaxDecaySpeedDivisor,
      (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) /
      kNumUsesPerDecaySpeedDivisorIncrement);

  return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) +
      0.5);
}

void ShortcutsProvider::set_shortcuts_backend(
    history::ShortcutsBackend* shortcuts_backend) {
  DCHECK(shortcuts_backend);
  shortcuts_backend_ = shortcuts_backend;
  shortcuts_backend_->AddObserver(this);
  if (shortcuts_backend_->initialized())
    initialized_ = true;
}

<|endoftext|>