text:
CBrowserObject::
CBrowserObject(CBrowserWindow *window, CHtmlTagId type, const CBrowserBaseData &data) :
 CBrowserBox(window), window_(window), iface_(this), type_(type), data_(data)
{
}

CBrowserObject::
~CBrowserObject()
{
  for (auto &c : children_)
    delete c;
}

void
CBrowserObject::
init()
{
  std::vector<std::string> strs = {{
    "id", "class", "name", "type", "display",
    "margin-left", "margin-bottom", "margin-right", "margin-top",
    "background-color", "color" }};

  addProperties(strs);
}

void
CBrowserObject::
setClass(const std::string &s)
{
  class_ = s;

  CStrUtil::toWords(class_, classes_);
}

CQJHtmlObj *
CBrowserObject::
createJObj(CJavaScript *js)
{
  return new CQJHtmlObj(js, iface());
}

CQJHtmlObj *
CBrowserObject::
getJObj() const
{
  return htmlObj_;
}

void
CBrowserObject::
setJObj(CQJHtmlObj *obj)
{
  htmlObj_ = obj;
}

CJValueP
CBrowserObject::
getJObjValue() const
{
  return htmlObj_->shared_from_this();
}

CJavaScript *
CBrowserObject::
js() const
{
  return getJObj()->js();
}

std::string
CBrowserObject::
typeName() const
{
  const CHtmlTagDef &tagDef = CHtmlTagDefLookupInst->lookup(type_);

  return tagDef.getName();
}

std::string
CBrowserObject::
hierTypeName() const
{
  const CBrowserObject *parent = this->parent();

  if (! parent)
    return typeName();

  if (parent->type() == CHtmlTagId::HTML || parent->type() == CHtmlTagId::BODY)
    return typeName();

  return parent->hierTypeName() + "/" + typeName();
}

void
CBrowserObject::
addChild(CBrowserObject *child)
{
  child->setParent(this);

  children_.push_back(child);
}

int
CBrowserObject::
childIndex(const CBrowserObject *child) const
{
  for (uint i = 0; i < children_.size(); ++i)
    if (children_[i] == child)
      return i;

  return -1;
}

void
CBrowserObject::
addProperties(const Properties &properties)
{
  for (const auto &p : properties)
    properties_.push_back(p);
}

std::string
CBrowserObject::
propertyValue(int i) const
{
  const std::string &name = propertyName(i);

  if      (name == "id"   ) return CBrowserProperty::toString(id());
  else if (name == "class") return CBrowserProperty::toString(getClass());
  else if (name == "name" ) return CBrowserProperty::toString(getName());
  else if (name == "type" ) return CBrowserProperty::toString(typeName());

  else if (name == "display") return CBrowserProperty::toString(display());

  else if (name == "margin-left"  ) return CBrowserProperty::toString(marginLeft  ());
  else if (name == "margin-bottom") return CBrowserProperty::toString(marginBottom());
  else if (name == "margin-right" ) return CBrowserProperty::toString(marginRight ());
  else if (name == "margin-top"   ) return CBrowserProperty::toString(marginTop   ());

  else if (name == "color") return CBrowserProperty::toString(foreground());

  else if (name == "background-color") return CBrowserProperty::toString(background());

  return "";
}

void
CBrowserObject::
setNameValue(const std::string &name, const std::string &value)
{
  std::string lname  = CStrUtil::toLower(name);
//std::string lvalue = CStrUtil::toLower(value);

  if      (lname == "accesskey") {
  }
  else if (lname == "bgcolor") {
    background_.setColor(CBrowserColor(value));
  }
  else if (lname == "class") {
    setClass(value);
  }
  else if (lname == "contenteditable") {
  }
  else if (lname == "contentmenu") {
  }
  else if (lname == "dir") {
  }
  else if (lname == "draggable") {
  }
  else if (lname == "dropzone") {
  }
  else if (lname == "hidden") {
    //visible_ = false;
  }
  else if (lname == "id") {
    setId(value);
  }
  else if (lname == "lang") {
  }
  else if (lname == "name") {
    setName(value);
  }
  else if (lname == "spellcheck") {
  }
  else if (lname == "style") {
    processStyleAttribute(value);
  }
  else if (lname == "tabindex") {
  }
  else if (lname == "title") {
    title_ = value;
  }
  else if (lname == "translate") {
  }
  else if (lname.substr(0, 5) == "data-") {
  }
  else {
    window_->displayError("Illegal '%s' name '%s' value '%s'\n", typeName().c_str(),
                          name.c_str(), value.c_str());
  }
}

void
CBrowserObject::
setStyleValue(const std::string &name, const std::string &value)
{
  std::string lname  = CStrUtil::toLower(name);
  std::string lvalue = CStrUtil::toLower(value);

  //--- A ---
  if      (lname == "align-items") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "align-self") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "all") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "animation") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "animation-delay") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "animation-direction") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "animation-duration") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "animation-fill-mode") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "animation-iteration-count") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "animation-name") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "animation-play-state") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "animation-timing-function") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- B ---
  else if (lname == "backface-visibility") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "background") {
    // bg-color bg-image position/bg-size bg-repeat bg-origin bg-clip bg-attachment initial|inherit

    CBrowserBackground bg;

    std::vector<std::string> words;

    styleValueToWords(value, words);

    if (words.size() > 0)
      bg.setColor(CBrowserColor(words[0]));

    if (words.size() > 1)
      bg.setImage(CBrowserBackgroundImage(words[1]));

    if (words.size() > 2)
      bg.setPosition(CBrowserBackgroundPosition(words[2]));

    setBackground(bg);
  }
  else if (lname == "background-attachment") {
    background_.setAttachment(CBrowserBackgroundAttachment(value));
  }
  else if (lname == "background-blend-mode") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "background-clip") {
    background_.setClip(CBrowserBackgroundClip(value));
  }
  else if (lname == "background-color") {
    background_.setColor(CBrowserColor(value));
  }
  else if (lname == "background-image") {
    background_.setImage(CBrowserBackgroundImage(value));
  }
  else if (lname == "background-origin") {
    background_.setOrigin(CBrowserBackgroundOrigin(value));
  }
  else if (lname == "background-position") {
    background_.setPosition(CBrowserBackgroundPosition(value));
  }
  else if (lname == "background-repeat") {
    background_.setRepeat(CBrowserBackgroundRepeat(value));
  }
  else if (lname == "background-size") {
    background_.setSize(CBrowserBackgroundSize(value));
  }
  else if (lname == "border") {
    std::vector<std::string> words;

    styleValueToWords(value, words);

    CBrowserBorder border = this->border();

    if (words.size() >= 1) {
      CBrowserBorderWidth width(words[0]);

      border.setWidth(width);
    }

    if (words.size() >= 2) {
      CBrowserBorderStyle style = CBrowserBorder::stringToStyle(words[1]);

      border.setStyle(style);
    }

    if (words.size() >= 3) {
      CBrowserColor color(words[2]);

      border.setColor(color);
    }

    setBorder(border);
  }
  else if (lname == "border-bottom") {
    std::vector<std::string> words;

    styleValueToWords(value, words);

    if (words.size() >= 1) {
      CBrowserBorderWidth width(words[0]);

      borderRef().setBottomWidth(width);
    }

    if (words.size() >= 2) {
      CBrowserBorderStyle style = CBrowserBorder::stringToStyle(words[1]);

      borderRef().setBottomStyle(style);
    }

    if (words.size() >= 3) {
      CBrowserColor color(words[2]);

      borderRef().setBottomColor(color);
    }
  }
  else if (lname == "border-bottom-color") {
    CBrowserColor color(value);

    borderRef().setBottomColor(color);
  }
  else if (lname == "border-bottom-left-radius") {
    CBrowserUnitValue r(value);

    borderRef().setBottomLeftRadius(r);
  }
  else if (lname == "border-bottom-right-radius") {
    CBrowserUnitValue r(value);

    borderRef().setBottomRightRadius(r);
  }
  else if (lname == "border-bottom-style") {
    CBrowserBorderStyle style = CBrowserBorder::stringToStyle(value);

    borderRef().setBottomStyle(style);
  }
  else if (lname == "border-bottom-width") {
    CBrowserBorderWidth width(value);

    borderRef().setBottomWidth(width);
  }
  else if (lname == "border-collapse") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "border-color") {
    CBrowserColor color(value);

    borderRef().setColor(color);
  }
  else if (lname == "border-image") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "border-image-outset") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "border-image-repeat") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "border-image-slice") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "border-image-source") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "border-image-width") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "border-left") {
    std::vector<std::string> words;

    styleValueToWords(value, words);

    if (words.size() >= 1) {
      CBrowserBorderWidth width(words[0]);

      borderRef().setLeftWidth(width);
    }

    if (words.size() >= 2) {
      CBrowserBorderStyle style = CBrowserBorder::stringToStyle(words[1]);

      borderRef().setLeftStyle(style);
    }

    if (words.size() >= 3) {
      CBrowserColor color(words[2]);

      borderRef().setLeftColor(color);
    }
  }
  else if (lname == "border-left-color") {
    CBrowserColor color(value);

    borderRef().setLeftColor(color);
  }
  else if (lname == "border-left-style") {
    CBrowserBorderStyle style = CBrowserBorder::stringToStyle(value);

    borderRef().setLeftStyle(style);
  }
  else if (lname == "border-left-width") {
    CBrowserBorderWidth width(value);

    borderRef().setLeftWidth(width);
  }
  else if (lname == "border-radius") {
    CBrowserUnitValue r(value);

    borderRef().setTopLeftRadius    (r);
    borderRef().setTopRightRadius   (r);
    borderRef().setBottomLeftRadius (r);
    borderRef().setBottomRightRadius(r);
  }
  else if (lname == "border-right") {
    std::vector<std::string> words;

    styleValueToWords(value, words);

    if (words.size() >= 1) {
      CBrowserBorderWidth width(words[0]);

      borderRef().setRightWidth(width);
    }

    if (words.size() >= 2) {
      CBrowserBorderStyle style = CBrowserBorder::stringToStyle(words[1]);

      borderRef().setRightStyle(style);
    }

    if (words.size() >= 3) {
      CBrowserColor color(words[2]);

      borderRef().setRightColor(color);
    }
  }
  else if (lname == "border-right-color") {
    CBrowserColor color(value);

    borderRef().setRightColor(color);
  }
  else if (lname == "border-right-style") {
    CBrowserBorderStyle style = CBrowserBorder::stringToStyle(value);

    borderRef().setRightStyle(style);
  }
  else if (lname == "border-right-width") {
    CBrowserBorderWidth width(value);

    borderRef().setRightWidth(width);
  }
  else if (lname == "border-spacing") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "border-style") {
     std::vector<std::string> words;

    styleValueToWords(value, words);

    if      (words.size() == 1) {
      borderRef().setStyle(CBrowserBorder::stringToStyle(words[0]));
    }
    else if (words.size() == 2) {
      CBrowserBorderStyle hstyle = CBrowserBorder::stringToStyle(words[0]);
      CBrowserBorderStyle vstyle = CBrowserBorder::stringToStyle(words[1]);

      borderRef().setTopStyle   (hstyle);
      borderRef().setBottomStyle(hstyle);
      borderRef().setLeftStyle  (vstyle);
      borderRef().setRightStyle (vstyle);
    }
    else if (words.size() == 3) {
      CBrowserBorderStyle vstyle = CBrowserBorder::stringToStyle(words[1]);

      borderRef().setTopStyle   (CBrowserBorder::stringToStyle(words[0]));
      borderRef().setBottomStyle(CBrowserBorder::stringToStyle(words[2]));
      borderRef().setLeftStyle  (vstyle);
      borderRef().setRightStyle (vstyle);
    }
    else if (words.size() >= 4) {
      borderRef().setTopStyle   (CBrowserBorder::stringToStyle(words[0]));
      borderRef().setRightStyle (CBrowserBorder::stringToStyle(words[1]));
      borderRef().setBottomStyle(CBrowserBorder::stringToStyle(words[2]));
      borderRef().setLeftStyle  (CBrowserBorder::stringToStyle(words[3]));
    }
  }
  else if (lname == "border-top") {
    std::vector<std::string> words;

    styleValueToWords(value, words);

    if (words.size() >= 1) {
      CBrowserBorderWidth width(words[0]);

      borderRef().setTopWidth(width);
    }

    if (words.size() >= 2) {
      CBrowserBorderStyle style = CBrowserBorder::stringToStyle(words[1]);

      borderRef().setTopStyle(style);
    }

    if (words.size() >= 3) {
      CBrowserColor color(words[2]);

      borderRef().setTopColor(color);
    }
  }
  else if (lname == "border-top-color") {
    CBrowserColor color(value);

    borderRef().setTopColor(color);
  }
  else if (lname == "border-top-left-radius") {
    CBrowserUnitValue r(value);

    borderRef().setTopLeftRadius(r);
  }
  else if (lname == "border-top-right-radius") {
    CBrowserUnitValue r(value);

    borderRef().setTopRightRadius(r);
  }
  else if (lname == "border-top-style") {
    CBrowserBorderStyle style = CBrowserBorder::stringToStyle(value);

    borderRef().setTopStyle(style);
  }
  else if (lname == "border-top-width") {
    CBrowserBorderWidth width(value);

    borderRef().setTopWidth(width);
  }
  else if (lname == "border-width") {
    CBrowserBorderWidth width(value);

    borderRef().setWidth(width);
  }
  else if (lname == "bottom") {
    position_.setBottom(CBrowserUnitValue(value));

    if (! position_.bottom().isValid())
      window_->displayError("Illegal '%s' name '%s' value '%s'\n", typeName().c_str(),
                            name.c_str(), value.c_str());
  }
  else if (lname == "box-shadow") {
    shadow_ = CBrowserShadow(value);
  }
  else if (lname == "box-sizing") {
    boxSizing_ = CBrowserBoxSizing(value);
  }

  //--- C ---
  else if (lname == "caption-side") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "clear") {
    clear_ = CBrowserClear(value);
  }
  else if (lname == "clip") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "color") {
    foreground_ = CBrowserColor(value);
  }
  else if (lname == "column-count") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "column-fill") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "column-gap") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "column-rule") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "column-rule-color") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "column-rule-style") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "column-rule-width") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "column-span") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "column-width") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "columns") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "content") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "counter-increment") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "counter-reset") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "cursor") {
    cursor_ = CBrowserCursor(value);
  }

  //--- D ---
  else if (lname == "direction") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "display") {
    CBrowserObject::Display d;

    if (CBrowserProperty::fromString<CBrowserObject::Display>(lvalue, d))
      setDisplay(d);
  }

  //--- E ---
  else if (lname == "empty-cells") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- F ---
  else if (lname == "filter") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "flex") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "flex-basis") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "flex-direction") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "flex-flow") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "flex-grow") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "flex-shrink") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "flex-wrap") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "float") {
    float_ = CBrowserFloat(value);
  }
  else if (lname == "font") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "font-family") {
    font_.setFamily(CBrowserFontFamily(value));
  }
  else if (lname == "font-size") {
    font_.setSize(CBrowserFontSize(value));
  }
  else if (lname == "font-size-adjust") {
    font_.setSizeAdjust(CBrowserFontSizeAdjust(value));
  }
  else if (lname == "font-stretch") {
    font_.setStretch(CBrowserFontStretch(value));
  }
  else if (lname == "font-style") {
    font_.setStyle(CBrowserFontStyle(value));
  }
  else if (lname == "font-variant") {
  }
  else if (lname == "font-weight") {
    font_.setWeight(CBrowserFontWeight(value));
  }
  else if (lname == "@font-face") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- H ---
  else if (lname == "hanging-punctuation") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "height") {
    setHeight(CBrowserUnitValue(value));

    if (! height().isValid())
      window_->displayError("Illegal '%s' name '%s' value '%s'\n", typeName().c_str(),
                            name.c_str(), value.c_str());
  }

  //--- J ---
  else if (lname == "justify-content") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- K ---
  else if (lname == "@keyframes") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- L ---
  else if (lname == "left") {
    position_.setLeft(CBrowserUnitValue(value));
  }
  else if (lname == "letter-spacing") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "line-height") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "list-style") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "list-style-image") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "list-style-position") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "list-style-type") {
    CBrowserListStyleType styleType(value);

    CBrowserList     *ol = dynamic_cast<CBrowserList *>(this);
    CBrowserListItem *li = dynamic_cast<CBrowserListItem *>(this);

    if      (ol)
      ol->setStyleType(styleType);
    else if (li)
      li->setStyleType(styleType);
    else
      window_->displayError("Invalid object for '%s' : value '%s'\n",
                            name.c_str(), value.c_str());
  }

  //--- M ---
  else if (lname == "margin") {
    std::vector<std::string> words;

    styleValueToWords(value, words);

    std::vector<CBrowserUnitValue> uvalues;

    for (const auto &w : words)
      uvalues.push_back(CBrowserUnitValue(w));

    CBrowserMargin margin = this->margin();

    if      (words.size() == 1) {
      margin.setTop   (uvalues[0]);
      margin.setRight (uvalues[0]);
      margin.setBottom(uvalues[0]);
      margin.setLeft  (uvalues[0]);
    }
    else if (words.size() == 2) {
      margin.setTop   (uvalues[0]);
      margin.setBottom(uvalues[0]);
      margin.setRight (uvalues[1]);
      margin.setLeft  (uvalues[1]);
    }
    else if (words.size() == 3) {
      margin.setTop   (uvalues[0]);
      margin.setRight (uvalues[1]);
      margin.setLeft  (uvalues[1]);
      margin.setBottom(uvalues[2]);
    }
    else if (words.size() == 4) {
      margin.setTop   (uvalues[0]);
      margin.setRight (uvalues[1]);
      margin.setBottom(uvalues[2]);
      margin.setLeft  (uvalues[3]);
    }

    setMargin(margin);
  }
  else if (lname == "margin-bottom") {
    marginRef().setBottom(CBrowserUnitValue(value));
  }
  else if (lname == "margin-left") {
    marginRef().setLeft(CBrowserUnitValue(value));
  }
  else if (lname == "margin-right") {
    marginRef().setRight(CBrowserUnitValue(value));
  }
  else if (lname == "margin-top") {
    marginRef().setTop(CBrowserUnitValue(value));
  }
  else if (lname == "max-height") {
    maxHeight_ = CBrowserUnitValue(value);

    if (! maxHeight_.isValid())
      window_->displayError("Illegal '%s' name '%s' value '%s'\n", typeName().c_str(),
                            name.c_str(), value.c_str());
  }
  else if (lname == "max-width") {
    maxWidth_ = CBrowserUnitValue(value);

    if (! maxWidth_.isValid())
      window_->displayError("Illegal '%s' name '%s' value '%s'\n", typeName().c_str(),
                            name.c_str(), value.c_str());
  }
  else if (lname == "@media") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "min-height") {
    minHeight_ = CBrowserUnitValue(value);

    if (! minHeight_.isValid())
      window_->displayError("Illegal '%s' name '%s' value '%s'\n", typeName().c_str(),
                            name.c_str(), value.c_str());
  }
  else if (lname == "min-width") {
    minWidth_ = CBrowserUnitValue(value);

    if (! minWidth_.isValid())
      window_->displayError("Illegal '%s' name '%s' value '%s'\n", typeName().c_str(),
                            name.c_str(), value.c_str());
  }

  //--- N ---
  else if (lname == "nav-down") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "nav-index") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "nav-left") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "nav-right") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "nav-up") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- O ---
  else if (lname == "opacity") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "order") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "outline") {
    std::vector<std::string> words;

    styleValueToWords(value, words);

    if      (words.size() == 3) {
      CBrowserColor        color(words[0]);
      CBrowserOutlineStyle style(words[1]);
      CBrowserOutlineWidth width(words[2]);

      outline_.setColor(color);
      outline_.setStyle(style);
      outline_.setWidth(width);
    }
    else if (words.size() == 1) {
      CBrowserColor color(value);

      if (color.isValid())
        outline_.setColor(color);
      else {
        CBrowserOutlineStyle style(value);

        if (style.isValid())
          outline_.setStyle(style);
        else {
          CBrowserOutlineWidth width(value);

          if (width.isValid())
            outline_.setWidth(width);
        }
      }
    }
    else {
      window_->displayError("Unsupported style name '%s' value '%s'\n",
                            name.c_str(), value.c_str());
    }
  }
  else if (lname == "outline-color") {
    CBrowserColor color(value);

    outline_.setColor(color);
  }
  else if (lname == "outline-offset") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "outline-style") {
    CBrowserOutlineStyle style(value);

    outline_.setStyle(style);
  }
  else if (lname == "outline-width") {
    CBrowserOutlineWidth width(value);

    outline_.setWidth(width);
  }
  else if (lname == "overflow") {
    overflow_ = CBrowserOverflow(value);
  }
  else if (lname == "overflow-x") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "overflow-y") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- P ---
  else if (lname == "padding") {
    std::vector<std::string> words;

    styleValueToWords(value, words);

    std::vector<CBrowserUnitValue> uvalues;

    for (const auto &w : words)
      uvalues.push_back(CBrowserUnitValue(w));

    CBrowserPadding padding = this->padding();

    if      (words.size() == 1) {
      padding.setTop   (uvalues[0]);
      padding.setRight (uvalues[0]);
      padding.setBottom(uvalues[0]);
      padding.setLeft  (uvalues[0]);
    }
    else if (words.size() == 2) {
      padding.setTop   (uvalues[0]);
      padding.setBottom(uvalues[0]);
      padding.setRight (uvalues[1]);
      padding.setLeft  (uvalues[1]);
    }
    else if (words.size() == 3) {
      padding.setTop   (uvalues[0]);
      padding.setRight (uvalues[1]);
      padding.setLeft  (uvalues[1]);
      padding.setBottom(uvalues[2]);
    }
    else if (words.size() == 4) {
      padding.setTop   (uvalues[0]);
      padding.setRight (uvalues[1]);
      padding.setBottom(uvalues[2]);
      padding.setLeft  (uvalues[3]);
    }

    setPadding(padding);
  }
  else if (lname == "padding-bottom") {
    paddingRef().setBottom(CBrowserUnitValue(value));
  }
  else if (lname == "padding-left") {
    paddingRef().setLeft(CBrowserUnitValue(value));
  }
  else if (lname == "padding-right") {
    paddingRef().setRight(CBrowserUnitValue(value));
  }
  else if (lname == "padding-top") {
    paddingRef().setTop(CBrowserUnitValue(value));
  }
  else if (lname == "page-break-after") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "page-break-before") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "page-break-inside") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "perspective") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "perspective-origin") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "position") {
    position_.setType(value);
  }

  //--- Q ---
  else if (lname == "quotes") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- R ---
  else if (lname == "resize") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "right") {
    position_.setRight(CBrowserUnitValue(value));

    if (! position_.right().isValid())
      window_->displayError("Illegal '%s' name '%s' value '%s'\n", typeName().c_str(),
                            name.c_str(), value.c_str());
  }

  //--- T ---
  else if (lname == "tab-size") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "table-layout") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "text-align") {
    textProp_.setAlign(CBrowserTextAlign(value));
  }
  else if (lname == "text-align-last") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "text-decoration") {
    textProp_.setDecoration(CBrowserTextDecoration(value));
  }
  else if (lname == "text-decoration-color") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "text-decoration-line") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "text-decoration-style") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "text-indent") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "text-justify") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "text-overflow") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "text-shadow") {
    textProp_.setShadow(CBrowserTextShadow(value));
  }
  else if (lname == "text-transform") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "top") {
    position_.setTop(CBrowserUnitValue(value));
  }
  else if (lname == "transform") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "transform-origin") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "transform-style") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "transition") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "transition-delay") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "transition-duration") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "transition-property") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "transition-timing-function") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- U ---
  else if (lname == "unicode-bidi") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "user-select") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- V ---
  else if (lname == "vertical-align") {
    textProp_.setVerticalAlign(CBrowserTextVAlign(value));
  }
  else if (lname == "visibility") {
    //visible_ = true;
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- W ---
  else if (lname == "white-space") {
    CBrowserObject::WhiteSpace w;

    if (CBrowserProperty::fromString<CBrowserObject::WhiteSpace>(lvalue, w))
      setWhiteSpace(w);
  }
  else if (lname == "width") {
    setWidth(CBrowserUnitValue(value));

    if (! width().isValid())
      window_->displayError("Illegal '%s' name '%s' value '%s'\n", typeName().c_str(),
                            name.c_str(), value.c_str());
  }
  else if (lname == "word-break") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }
  else if (lname == "word-spacing") {
    wordSpacing_ = CBrowserWordSpacing(value);
  }
  else if (lname == "word-wrap") {
    window_->displayError("Unsupported style name '%s' value '%s'\n",
                          name.c_str(), value.c_str());
  }

  //--- Z ---
  else if (lname == "z-index") {
    if (CStrUtil::isInteger(value))
      zIndex_ = CStrUtil::toInteger(value);
    else
      window_->displayError("Illegal '%s' name '%s' value '%s'\n", typeName().c_str(),
                            name.c_str(), value.c_str());
  }

  //--- Misc ---
  else if (lname.substr(0, 8) == "-webkit-") {
  }
  else if (lname.substr(0, 5) == "-moz-") {
  }

  //---
  else {
    window_->displayError("Illegal '%s' style name '%s' value '%s'\n", typeName().c_str(),
                          name.c_str(), value.c_str());
  }
}

void
CBrowserObject::
styleValueToWords(const std::string &value, std::vector<std::string> &words)
{
  //CStrUtil::toWords(value, words);
  CStrParse parse(value);

  while (! parse.eof()) {
    int i1 = parse.getPos();

    while (! parse.eof()) {
      if      (parse.isChar('(')) {
        parse.skipChar();

        int brackets = 1;

        while (! parse.eof()) {
          if      (parse.isChar('('))
            ++brackets;
          else if (parse.isChar(')')) {
            --brackets;

            if (brackets == 0) {
              parse.skipChar();
              break;
            }
          }

          parse.skipChar();
        }
      }
      else if (parse.isSpace())
        break;

      parse.skipChar();
    }

    std::string word = parse.getBefore(i1);

    words.push_back(word);

    parse.skipSpace();
  }
}

void
CBrowserObject::
processStyleAttribute(const std::string &style)
{
  std::vector<std::string> words;

  CStrUtil::addFields(style, words, ";");

  for (const auto &word : words) {
    std::string sword = CStrUtil::stripSpaces(word);

    if (sword == "")
      continue;

    std::vector<std::string> words1;

    CStrUtil::addFields(sword, words1, ":");

    if (words1.size() != 2) {
      window_->displayError("Style name:value '%s'", word.c_str());
      continue;
    }

    std::string name  = CStrUtil::stripSpaces(words1[0]);
    std::string value = CStrUtil::stripSpaces(words1[1]);

    setStyleValue(name, value);
  }
}

bool
CBrowserObject::
isHierSelected() const
{
  if (isSelected())
    return true;

  const CBrowserObject *parent = this->parent();

  while (parent) {
    if (parent->isSelected())
      return true;

    parent = parent->parent();
  }

  return false;
}

CIBBox2D
CBrowserObject::
calcBBox() const
{
  CBrowserRegion region = this->calcRegion();

  return CIBBox2D(region.x(), region.y(),
                  region.x() + region.width(), region.y() + region.height());
}

bool
CBrowserObject::
isVisible() const
{
  return display() != Display::NONE;
}

bool
CBrowserObject::
isInline() const
{
  return display() == Display::INLINE;
}

bool
CBrowserObject::
hasInlineChildren() const
{
  for (auto &c : children_) {
    if (c->isInline())
      return true;
  }

  return false;
}

void
CBrowserObject::
heightForWidth(CTextBox &box) const
{
  CBrowserRegion region = this->calcRegion();

  box.setAscent (region.ascent ());
  box.setDescent(region.descent());
}

void
CBrowserObject::
getInlineWords(Words &) const
{
}

void
CBrowserObject::
fillBackground(const CTextBox &region)
{
  int x = region.x();
  int y = region.y();
  int w = region.width();
  int h = region.height();

  if      (background_.color().isValid()) {
    CBrush brush;

    if (background().color().type() == CBrowserColor::Type::COLOR) {
      const CRGBA &c = background().color().color();

      brush = CBrush(c);
    }
    else {
      const CBrowserColorGradient &g = background().color().gradient();

      CLinearGradient *gradient = new CLinearGradient;

      gradient->setX1(0);
      gradient->setY1(0);

      // top left -> right
      if (g.direction() & uint(CBrowserColorGradient::Direction::RIGHT))
        gradient->setX2(1);
      else
        gradient->setX2(0);

      if (g.direction() & uint(CBrowserColorGradient::Direction::BOTTOM))
        gradient->setY2(1);
      else
        gradient->setY2(0);

      double d = 1.0/std::max(int(g.colors().size()) - 1, 1);

      double offset = 0.0;

      for (const auto &c : g.colors()) {
        gradient->addStop(offset, c);

        offset += d;
      }

      brush.setGradient(CBrush::GradientPtr(gradient));
    }

    window_->fillRectangle(x, y, w, h, brush);
  }
  else if (background().image().isValid()) {
    CBrush brush = CBrush(background().image().image());

    window_->fillRectangle(x, y, w, h, brush);
  }
}

void
CBrowserObject::
draw(const CTextBox &)
{
}

void
CBrowserObject::
drawBorder(const CTextBox &region)
{
  int x1 = region.xmin();
  int y1 = region.ymin();
  int x2 = region.xmax();
  int y2 = region.ymax();

  if (border().isTopVisible()) {
    drawBorderLine(x1, y1, x2, y1, border().topStyle(), border().topPen(),
                   CBrowserBorderSide::TOP);
  }

  if (border().isLeftVisible()) {
    drawBorderLine(x1, y1, x1, y2, border().leftStyle(), border().leftPen(),
                   CBrowserBorderSide::LEFT);
  }

  if (border().isRightVisible()) {
    drawBorderLine(x2, y1, x2, y2, border().rightStyle(), border().rightPen(),
                   CBrowserBorderSide::RIGHT);
  }

  if (border().isBottomVisible()) {
    drawBorderLine(x1, y2, x2, y2, border().bottomStyle(), border().bottomPen(),
                   CBrowserBorderSide::BOTTOM);
  }
}

void
CBrowserObject::
drawBorderLine(double x1, double y1, double x2, double y2,
               CBrowserBorderStyle style, const CPen &pen, CBrowserBorderSide side)
{
  double w = pen.getWidth();

  if      (style == CBrowserBorderStyle::DOUBLE) {
    CPen pen1 = pen;

    pen1.setWidth(1);

    double dw = w - 1;

    if      (side == CBrowserBorderSide::TOP || side == CBrowserBorderSide::BOTTOM) {
      if (side == CBrowserBorderSide::TOP) {
        double y2 = y1 + dw;

        window_->drawLine(x1     , y1, x2     , y1, pen1);
        window_->drawLine(x1 + dw, y2, x2 - dw, y2, pen1);
      }
      else {
        double y2 = y1 - dw;

        window_->drawLine(x1     , y1, x2     , y1, pen1);
        window_->drawLine(x1 + dw, y2, x2 - dw, y2, pen1);
      }
    }
    else {
      if (side == CBrowserBorderSide::LEFT) {
        double x2 = x1 + dw;

        window_->drawLine(x1, y1     , x1, y2     , pen1);
        window_->drawLine(x2, y1 + dw, x2, y2 - dw, pen1);
      }
      else {
        double x2 = x1 - dw;

        window_->drawLine(x1, y1     , x1, y2     , pen1);
        window_->drawLine(x2, y1 + dw, x2, y2 - dw, pen1);
      }
    }
  }
  else if (style == CBrowserBorderStyle::SOLID ||
           style == CBrowserBorderStyle::INSET || style == CBrowserBorderStyle::OUTSET) {
    CRGBA bg = window_->getBgColor();

    CRGBA c     = pen.getColor();
    CRGBA light = c.blended(bg, 0.5);
    CRGBA dark  = c.blended(bg, 0.8);

    if      (side == CBrowserBorderSide::TOP) {
      double x11 = x1 + w;
      double x21 = x2 - w;
      double y11 = y1 + w;

      std::vector<CIPoint2D> points = {{
        CIPoint2D(x1, y1), CIPoint2D(x2, y1), CIPoint2D(x21, y11), CIPoint2D(x11, y11)
      }};

      if      (style == CBrowserBorderStyle::SOLID)
        window_->fillPolygon(points, CBrush(c));
      else if (style == CBrowserBorderStyle::INSET)
        window_->fillPolygon(points, CBrush(dark));
      else
        window_->fillPolygon(points, CBrush(light));
    }
    else if (side == CBrowserBorderSide::LEFT) {
      double x11 = x1 + w;
      double y11 = y1 + w;
      double y21 = y2 - w;

      std::vector<CIPoint2D> points = {{
        CIPoint2D(x1, y1), CIPoint2D(x11, y11), CIPoint2D(x11, y21), CIPoint2D(x1, y2)
      }};

      if      (style == CBrowserBorderStyle::SOLID)
        window_->fillPolygon(points, CBrush(c));
      else if (style == CBrowserBorderStyle::INSET)
        window_->fillPolygon(points, CBrush(dark));
      else
        window_->fillPolygon(points, CBrush(light));
    }
    else if (side == CBrowserBorderSide::RIGHT) {
      double x11 = x1 - w;
      double y11 = y1 + w;
      double y21 = y2 - w;

      if (y21 < y11) {
        y11 = (y1 + y2)/2;
        y21 = y11;
      }

      std::vector<CIPoint2D> points = {{
        CIPoint2D(x11, y11), CIPoint2D(x1, y1), CIPoint2D(x1, y2), CIPoint2D(x11, y21)
      }};

      if      (style == CBrowserBorderStyle::SOLID)
        window_->fillPolygon(points, CBrush(c));
      else if (style == CBrowserBorderStyle::INSET)
        window_->fillPolygon(points, CBrush(light));
      else
        window_->fillPolygon(points, CBrush(dark));
    }
    else if (side == CBrowserBorderSide::BOTTOM) {
      double x11 = x1 + w;
      double x21 = x2 - w;
      double y11 = y1 - w;

      std::vector<CIPoint2D> points = {{
        CIPoint2D(x11, y11), CIPoint2D(x21, y11), CIPoint2D(x2, y1), CIPoint2D(x1, y1)
      }};

      if      (style == CBrowserBorderStyle::SOLID)
        window_->fillPolygon(points, CBrush(c));
      else if (style == CBrowserBorderStyle::INSET)
        window_->fillPolygon(points, CBrush(light));
      else
        window_->fillPolygon(points, CBrush(dark));
    }
  }
  else if (style == CBrowserBorderStyle::OUTSET) {
    CRGBA bg = window_->getBgColor();

    CRGBA c;

    if (side == CBrowserBorderSide::TOP || side == CBrowserBorderSide::LEFT)
      c = pen.getColor().blended(bg, 0.5);
    else
      c = pen.getColor().blended(bg, 0.8);

    CPen pen1 = pen;

    pen1.setColor(c);

    window_->drawLine(x1, y1, x2, y2, pen1);
  }
  else if (style == CBrowserBorderStyle::GROOVE || style == CBrowserBorderStyle::RIDGE) {
    double w1 = w/2;

    CRGBA bg = window_->getBgColor();

    CRGBA light = pen.getColor().blended(bg, 0.5);
    CRGBA dark  = pen.getColor().blended(bg, 0.8);

    if      (side == CBrowserBorderSide::TOP) {
      double x11 = x1 + w1;
      double x21 = x2 - w1;
      double y11 = y1 + w1;

      std::vector<CIPoint2D> points1 = {{
        CIPoint2D(x1, y1), CIPoint2D(x2, y1), CIPoint2D(x21, y11), CIPoint2D(x11, y11)
      }};

      if (style == CBrowserBorderStyle::GROOVE)
        window_->fillPolygon(points1, CBrush(dark));
      else
        window_->fillPolygon(points1, CBrush(light));

      double x12 = x11 + w1;
      double x22 = x21 - w1;
      double y22 = y11 + w1;

      std::vector<CIPoint2D> points2 = {{
        CIPoint2D(x11, y11), CIPoint2D(x21, y11), CIPoint2D(x22, y22), CIPoint2D(x12, y22)
      }};

      if (style == CBrowserBorderStyle::GROOVE)
        window_->fillPolygon(points2, CBrush(light));
      else
        window_->fillPolygon(points2, CBrush(dark));
    }
    else if (side == CBrowserBorderSide::LEFT) {
      double x11 = x1 + w1;
      double y11 = y1 + w1;
      double y21 = y2 - w1;

      std::vector<CIPoint2D> points1 = {{
        CIPoint2D(x1, y1), CIPoint2D(x11, y11), CIPoint2D(x11, y21), CIPoint2D(x1, y2)
      }};

      if (style == CBrowserBorderStyle::GROOVE)
        window_->fillPolygon(points1, CBrush(dark));
      else
        window_->fillPolygon(points1, CBrush(light));

      double x12 = x11 + w1;
      double y12 = y11 + w1;
      double y22 = y21 - w1;

      std::vector<CIPoint2D> points2 = {{
        CIPoint2D(x11, y11), CIPoint2D(x12, y12), CIPoint2D(x12, y22), CIPoint2D(x11, y21)
      }};

      if (style == CBrowserBorderStyle::GROOVE)
        window_->fillPolygon(points2, CBrush(light));
      else
        window_->fillPolygon(points2, CBrush(dark));
    }
    else if (side == CBrowserBorderSide::RIGHT) {
      double x11 = x1 - w1;
      double y11 = y1 + w1;
      double y21 = y2 - w1;

      std::vector<CIPoint2D> points1 = {{
        CIPoint2D(x11, y11), CIPoint2D(x1, y1), CIPoint2D(x1, y2), CIPoint2D(x11, y21)
      }};

      if (style == CBrowserBorderStyle::GROOVE)
        window_->fillPolygon(points1, CBrush(light));
      else
        window_->fillPolygon(points1, CBrush(dark));

      double x12 = x11 - w1;
      double y12 = y11 + w1;
      double y22 = y21 - w1;

      std::vector<CIPoint2D> points2 = {{
        CIPoint2D(x12, y12), CIPoint2D(x11, y11), CIPoint2D(x11, y21), CIPoint2D(x12, y22)
      }};

      if (style == CBrowserBorderStyle::GROOVE)
        window_->fillPolygon(points2, CBrush(dark));
      else
        window_->fillPolygon(points2, CBrush(light));
    }
    else if (side == CBrowserBorderSide::BOTTOM) {
      double x11 = x1 + w1;
      double x21 = x2 - w1;
      double y11 = y1 - w1;

      std::vector<CIPoint2D> points1 = {{
        CIPoint2D(x11, y11), CIPoint2D(x21, y11), CIPoint2D(x2, y1), CIPoint2D(x1, y1)
      }};

      if (style == CBrowserBorderStyle::GROOVE)
        window_->fillPolygon(points1, CBrush(light));
      else
        window_->fillPolygon(points1, CBrush(dark));

      double x12 = x11 + w1;
      double x22 = x21 - w1;
      double y22 = y11 - w1;

      std::vector<CIPoint2D> points2 = {{
        CIPoint2D(x12, y22), CIPoint2D(x22, y22), CIPoint2D(x21, y11), CIPoint2D(x11, y11)
      }};

      if (style == CBrowserBorderStyle::GROOVE)
        window_->fillPolygon(points2, CBrush(dark));
      else
        window_->fillPolygon(points2, CBrush(light));
    }
  }
  else {
    window_->drawLine(x1, y1, x2, y2, pen);
  }
}

void
CBrowserObject::
drawSelected(const CTextBox &region)
{
  if (isSelected())
    window_->drawSelected(region.x(), region.y(), region.width(), region.height());
}

CBrowserObject::Display
CBrowserObject::
display() const
{
  if (display_ == Display::INVALID) {
    const CHtmlTagDef &tagDef = CHtmlTagDefLookupInst->lookup(type_);

    if (tagDef.isInline())
      return Display::INLINE;

    return Display::BLOCK;
  }
  else
    return display_;
}

CBrowserObject::WhiteSpace
CBrowserObject::
hierWhiteSpace() const
{
  if (whiteSpace() == WhiteSpace::INHERIT) {
    if (parent())
      return parent()->hierWhiteSpace();

    return WhiteSpace::NORMAL;
  }

  return whiteSpace();
}

CFontPtr
CBrowserObject::
hierFont() const
{
  CBrowserObject *th = const_cast<CBrowserObject *>(this);

  th->font_.setUnderline(textProp_.decoration().type() ==
                          CBrowserTextDecoration::Type::UNDERLINE);

  th->font_.setStrike(textProp_.decoration().type() ==
                       CBrowserTextDecoration::Type::LINE_THROUGH);

  th->font_.setSuperscript(textProp_.verticalAlign().type() == CBrowserTextVAlign::Type::SUPER);
  th->font_.setSubscript(textProp_.verticalAlign().type() == CBrowserTextVAlign::Type::SUB);

  return font().font(this);
}

CRGBA
CBrowserObject::
hierFgColor() const
{
  if (foreground().isValid())
    return foreground().color();

  if (parent())
    return parent()->hierFgColor();

  return window_->getFgColor();
}


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">

This bundle provides support for accessing a
Subversion
repository.

redpajama_set_name: RedPajamaGithub


text:
[![Build Status](https://travis-ci.org/momitians/gestpay.png?branch=master)](https://travis-ci.org/momitians/gestpay)
[![Dependency Status](https://gemnasium.com/momitians/gestpay.png)](https://gemnasium.com/momitians/gestpay)
[![Code Climate](https://codeclimate.com/github/momitians/gestpay.png)](https://codeclimate.com/github/momitians/gestpay)

Service wrapper for BancaSella Gestpay interface.

## Installation

Add this line to your application's Gemfile:

    gem 'gestpay'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install gestpay

## Usage

You can setup the gem in a Rails project using an initializer like this:

```ruby
Gestpay.setup do |config|
  config.account = 'GESPAY12345'
  config.environment = :test # default, change it to :production when ready
  config.proxy = 'http://user:password@proxy-host:proxy-port' # OPTIONAL
end
```

or using an export:

```shell
export GESTPAY_ACCOUNT=GESPAY12345
export GESTPAY_ENVIRONMENT=test
export GESTPAY_PROXY=http://user:password@proxy-host:proxy-port
```

You then have two different classes: `Gestpay::Digest` will help with the Crypt/Decrypt web service, while `Gestpay::Gateway` with the server-to-server webservice operations.

## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request

## Licence

Released under the [MIT License](http://www.opensource.org/licenses/MIT). © 2013 [Momit S.r.l.](http://momit.it/)


text:
package de.timosl.ssp;

import de.timosl.ssp.models.PendingEvent;

/**
 * A listener that will be called when a new message
 * was received from the remote end of the connection
 * and is not to a response to a local message.
 *
 */
public interface ServerEventListener {

	/**
	 * Called when a new message was received from the remote end.
	 *
	 * @param connectionID A String object uniquely identifying the client, which sent the event
	 * @param receivedEvent The received event
	 * @return Return a {@link PendingEvent} to deliver to the remote end
	 * in response to the received event or return 'null' to respond with
	 * the default response
	 */
	public PendingEvent onMessageReceived(String connectionID, Object receivedEvent);
}


text:
import {
  UPDATE_CURRENT_DATA,
  UPDATE_SELECTED_LOCATION,
  UPDATE_HISTORY_DATA
} from '../actions/actionTypes';

export const initialState = {
  data: {
    "datetime":"2017-05-06T17:55:15",
    "country_name":"Macedonia",
    "breezometer_aqi":66,
    "breezometer_color":"#9CD828",
    "breezometer_description":"Fair air quality",
    "country_aqi":null,
    "country_aqi_prefix":"",
    "country_color":"#99CC00",
    "country_description":"Low air pollution",
    "data_valid":true,
    "key_valid":true,
    "random_recommendations":{
      "children":"No reason to panic, but pay attention to changes in air quality and any signals of breathing problems in your children",
      "sport":"Since we inhale more air during sports, you should keep track of changes in air quality for the next few hours",
      "health":"Exposure to air hazards is dangerous for people with health sensitivities, so it is important to monitor air quality at this time",
      "inside":"The amount of pollutants in the air is noticeable, but still there is no danger to your health - It is recommended to continue monitoring changes in the coming hours",
      "outside":"It's still OK to go out and enjoy a stroll, just pay attention for changes in air quality"
    },
    "dominant_pollutant_canonical_name":"o3",
    "dominant_pollutant_description":"Ozone",
    "dominant_pollutant_text":{
      "main":"The dominant pollutant is ozone (O₃).",
      "effects":"Ozone can irritate the airways causing coughing, a burning sensation, wheezing and shortness of breath. Children, people with respiratory or lung and heart diseases, elderly and those who exercise outdoors are particularly vulnerable to ozone exposure.",
      "causes":"Ozone is created in a chemical reaction between atmospheric oxygen, nitrogen oxides, organic compounds and sunlight."
    }
  },
  location: {
    address: 'Skopje, Macedonia (FYROM)',
    latitude: 41.9973462,
    longitude: 21.42799560000003
  },
  historyData: [
    {
      "datetime": "2017-04-20T01:54:36",
      "country_name": "United States",
      "breezometer_aqi": 59,
      "breezometer_color": "#C7E916",
      "breezometer_description": "Moderate air quality",
      "country_aqi": 54,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "Pay attention to signs of respiratory distress in small children",
        "sport": "You want to work out now??!\u2026 Only if you have no plan B",
        "health": "People with health sensitivities should be prepared for minor respiratory difficulties",
        "inside": "You don't have to stay inside, but it's recommended that you keep tracking the air quality",
        "outside": "If you wish to stay outside for a long time, you should try to find a cleaner place nearby"
      },
      "dominant_pollutant_canonical_name": "no2",
      "dominant_pollutant_description": "Nitrogen dioxide",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is nitrogen dioxide (NO\u2082).",
        "effects": "Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with COPD and increased risk of respiratory infections, especially in young children",
        "causes": "Main sources are fuel burning processes in industry and transportation."
      }
    },
    {
      "datetime": "2017-04-21T01:54:24",
      "country_name": "United States",
      "breezometer_aqi": 55,
      "breezometer_color": "#E0F30C",
      "breezometer_description": "Moderate air quality",
      "country_aqi": 64,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "You can go outside with the kids, but monitor their breathing & pay attention to notifications",
        "sport": "You want to work out now??!\u2026 Only if you have no plan B",
        "health": "Exposure to air hazards is dangerous for people with health sensitivities, so it is important to monitor air quality at this time",
        "inside": "There's no need to get worried, but keep tracking air quality in the next few hours",
        "outside": "The air quality outside isn't the best\u2026 try to find a cleaner area"
      },
      "dominant_pollutant_canonical_name": "no2",
      "dominant_pollutant_description": "Nitrogen dioxide",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is nitrogen dioxide (NO\u2082).",
        "effects": "Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with COPD and increased risk of respiratory infections, especially in young children",
        "causes": "Main sources are fuel burning processes in industry and transportation."
      }
    },
    {
      "datetime": "2017-04-22T01:57:20",
      "country_name": "United States",
      "breezometer_aqi": 53,
      "breezometer_color": "#ECF707",
      "breezometer_description": "Moderate air quality",
      "country_aqi": 67,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "You can go outside with the kids, but monitor their breathing & pay attention to notifications",
        "sport": "Our recommendation: search for a cleaner area for a physical outdoor activity",
        "health": "People with health sensitivities should be prepared for minor respiratory difficulties",
        "inside": "You don't have to stay inside, but it's recommended that you keep tracking the air quality",
        "outside": "If you wish to stay outside for a long time, you should try to find a cleaner place nearby"
      },
      "dominant_pollutant_canonical_name": "no2",
      "dominant_pollutant_description": "Nitrogen dioxide",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is nitrogen dioxide (NO\u2082).",
        "effects": "Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with COPD and increased risk of respiratory infections, especially in young children",
        "causes": "Main sources are fuel burning processes in industry and transportation."
      }
    },
    {
      "datetime": "2017-04-23T05:45:08",
      "country_name": "United States",
      "breezometer_aqi": 59,
      "breezometer_color": "#C7E916",
      "breezometer_description": "Moderate air quality",
      "country_aqi": 56,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "You can go outside with the kids, but monitor their breathing & pay attention to notifications",
        "sport": "You should look for an alternative area with better air quality to work out",
        "health": "Exposure to air hazards is dangerous for people with health sensitivities, so it is important to monitor air quality at this time",
        "inside": "There's no need to get worried, but keep tracking air quality in the next few hours",
        "outside": "Try to minimize long stays outdoors & Keep tracking the air quality around your area"
      },
      "dominant_pollutant_canonical_name": "no2",
      "dominant_pollutant_description": "Nitrogen dioxide",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is nitrogen dioxide (NO\u2082).",
        "effects": "Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with COPD and increased risk of respiratory infections, especially in young children",
        "causes": "Main sources are fuel burning processes in industry and transportation."
      }
    },
    {
      "datetime": "2017-04-24T05:52:34",
      "country_name": "United States",
      "breezometer_aqi": 57,
      "breezometer_color": "#D3EE11",
      "breezometer_description": "Moderate air quality",
      "country_aqi": 57,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "Pay attention to the respiratory status of your kid(s)",
        "sport": "Our recommendation: search for a cleaner area for a physical outdoor activity",
        "health": "Exposure to air hazards is dangerous for people with health sensitivities, so it is important to monitor air quality at this time",
        "inside": "We're not going to tell you not to go outside, but you should continue tracking the air quality around you",
        "outside": "Try to minimize long stays outdoors & Keep tracking the air quality around your area"
      },
      "dominant_pollutant_canonical_name": "no2",
      "dominant_pollutant_description": "Nitrogen dioxide",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is nitrogen dioxide (NO\u2082).",
        "effects": "Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with COPD and increased risk of respiratory infections, especially in young children",
        "causes": "Main sources are fuel burning processes in industry and transportation."
      }
    },
    {
      "datetime": "2017-04-25T05:54:10",
      "country_name": "United States",
      "breezometer_aqi": 54,
      "breezometer_color": "#E6F50A",
      "breezometer_description": "Moderate air quality",
      "country_aqi": 66,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "Pay attention to signs of respiratory distress in small children",
        "sport": "Our recommendation: search for a cleaner area for a physical outdoor activity",
        "health": "People with health sensitivities should be prepared for minor respiratory difficulties",
        "inside": "We're not going to tell you not to go outside, but you should continue tracking the air quality around you",
        "outside": "Try to minimize long stays outdoors & Keep tracking the air quality around your area"
      },
      "dominant_pollutant_canonical_name": "no2",
      "dominant_pollutant_description": "Nitrogen dioxide",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is nitrogen dioxide (NO\u2082).",
        "effects": "Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with COPD and increased risk of respiratory infections, especially in young children",
        "causes": "Main sources are fuel burning processes in industry and transportation."
      }
    },
    {
      "datetime": "2017-04-26T05:01:06",
      "country_name": "United States",
      "breezometer_aqi": 60,
      "breezometer_color": "#C1E719",
      "breezometer_description": "Fair air quality",
      "country_aqi": 53,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "You should supervise your children in the coming hours and monitor changes in air quality",
        "sport": "Since we inhale more air during sports, you should keep track of changes in air quality for the next few hours",
        "health": "People with health sensitivities should monitor the air quality in the next few hours",
        "inside": "The amount of pollutants in the air is noticeable, but still there is no danger to health - It is recommended to watch for changes",
        "outside": "It's still OK to go out and enjoy a stroll, just pay attention for changes in air quality"
      },
      "dominant_pollutant_canonical_name": "no2",
      "dominant_pollutant_description": "Nitrogen dioxide",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is nitrogen dioxide (NO\u2082).",
        "effects": "Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with COPD and increased risk of respiratory infections, especially in young children",
        "causes": "Main sources are fuel burning processes in industry and transportation."
      }
    },
    {
      "datetime": "2017-04-27T05:55:48",
      "country_name": "United States",
      "breezometer_aqi": 49,
      "breezometer_color": "#FFF900",
      "breezometer_description": "Moderate air quality",
      "country_aqi": 78,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "You can go outside with the kids, but monitor their breathing & pay attention to notifications",
        "sport": "Our recommendation: search for a cleaner area for a physical outdoor activity",
        "health": "People with health sensitivities should be prepared for minor respiratory difficulties",
        "inside": "There's no need to get worried, but keep tracking air quality in the next few hours",
        "outside": "The air quality outside isn't the best\u2026 try to find a cleaner area"
      },
      "dominant_pollutant_canonical_name": "no2",
      "dominant_pollutant_description": "Nitrogen dioxide",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is nitrogen dioxide (NO\u2082).",
        "effects": "Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with COPD and increased risk of respiratory infections, especially in young children",
        "causes": "Main sources are fuel burning processes in industry and transportation."
      }
    },
    {
      "datetime": "2017-04-28T06:55:16",
      "country_name": "United States",
      "breezometer_aqi": 58,
      "breezometer_color": "#CDEB14",
      "breezometer_description": "Moderate air quality",
      "country_aqi": 65,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "You can go outside with the kids, but monitor their breathing & pay attention to notifications",
        "sport": "Our recommendation: search for a cleaner area for a physical outdoor activity",
        "health": "Exposure to air hazards is dangerous for people with health sensitivities, so it is important to monitor air quality at this time",
        "inside": "You don't have to stay inside, but it's recommended that you keep tracking the air quality",
        "outside": "Try to minimize long stays outdoors & Keep tracking the air quality around your area"
      },
      "dominant_pollutant_canonical_name": "no2",
      "dominant_pollutant_description": "Nitrogen dioxide",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is nitrogen dioxide (NO\u2082).",
        "effects": "Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with COPD and increased risk of respiratory infections, especially in young children",
        "causes": "Main sources are fuel burning processes in industry and transportation."
      }
    },
    {
      "datetime": "2017-04-29T06:55:46",
      "country_name": "United States",
      "breezometer_aqi": 47,
      "breezometer_color": "#FFED00",
      "breezometer_description": "Moderate air quality",
      "country_aqi": 84,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "Pay attention to signs of respiratory distress in small children",
        "sport": "Our recommendation: search for a cleaner area for a physical outdoor activity",
        "health": "There is no real danger for people with health sensitivities. Just keep an eye out for changes in air quality for the next few hours",
        "inside": "There's no need to get worried, but keep tracking air quality in the next few hours",
        "outside": "If you wish to stay outside for a long time, you should try to find a cleaner place nearby"
      },
      "dominant_pollutant_canonical_name": "no2",
      "dominant_pollutant_description": "Nitrogen dioxide",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is nitrogen dioxide (NO\u2082).",
        "effects": "Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with COPD and increased risk of respiratory infections, especially in young children",
        "causes": "Main sources are fuel burning processes in industry and transportation."
      }
    },
    {
      "datetime": "2017-04-30T06:54:06",
      "country_name": "United States",
      "breezometer_aqi": 63,
      "breezometer_color": "#AFDF21",
      "breezometer_description": "Fair air quality",
      "country_aqi": 65,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "No reason to panic, but pay attention to changes in air quality and any signals of breathing problems in your children",
        "sport": "You can go on a run - just keep your nose open for any changes!",
        "health": "There is no real danger for people with health sensitivities. Just keep an eye out for changes in air quality for the next few hours",
        "inside": "The amount of pollutants in the air is noticeable, but still there is no danger to your health - It is recommended to continue monitoring changes in the coming hours",
        "outside": "It's still OK to go out and enjoy a stroll, just pay attention for changes in air quality"
      },
      "dominant_pollutant_canonical_name": "pm10",
      "dominant_pollutant_description": "Inhalable particulate matter (<10\u00b5m)",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is inhalable particulate matter (PM10).",
        "effects": "Particles enter the lungs and cause local and systemic inflammation in the respiratory system & heart, thus cause cardiovascular and respiratory diseases such as asthma and bronchitis.",
        "causes": "Main sources are natural dust, smoke and pollen."
      }
    },
    {
      "datetime": "2017-05-01T06:56:15",
      "country_name": "United States",
      "breezometer_aqi": 62,
      "breezometer_color": "#B5E21E",
      "breezometer_description": "Fair air quality",
      "country_aqi": 59,
      "country_aqi_prefix": "",
      "country_color": "#FFFF00",
      "country_description": "Moderate air quality",
      "data_valid": true,
      "key_valid": true,
      "random_recommendations": {
        "children": "You should supervise your children in the coming hours and monitor changes in air quality",
        "sport": "You can go on a run - just keep your nose open for any changes!",
        "health": "People with health sensitivities should monitor the air quality in the next few hours",
        "inside": "The air quality is still good - we'll keep you updated if things get worse",
        "outside": "You can go out, but please pay attention for changes in air quality"
      },
      "dominant_pollutant_canonical_name": "no2",
      "dominant_pollutant_description": "Nitrogen dioxide",
      "dominant_pollutant_text": {
        "main": "The dominant pollutant is nitrogen dioxide (NO\u2082).",
        "effects": "Exposure may cause increased bronchial reactivity in patients with asthma, lung function decline in patients with COPD and increased risk of respiratory infections, especially in young children",
        "causes": "Main sources are fuel burning processes in industry and transportation."
      }
    }
  ]
};

export default function airQuality(state = initialState, action) {
  console.log('Action = ', action);
  switch (action.type) {
    case UPDATE_CURRENT_DATA:
      return Object.assign({}, state, { data: action.data });
    case UPDATE_HISTORY_DATA:
      return Object.assign({}, state, { historyData: action.historyData });
    case UPDATE_SELECTED_LOCATION:
      return Object.assign({}, state, { location: action.location });
    default:
      return state;
  }
}


text: AlgoliaSearch = algoliasearch = Npm.require('algoliasearch');


text:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <android.support.v4.view.ViewPager
        android:id="@+id/awesomepager"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentTop="true" />

</RelativeLayout>


text:
class SendMail < ActionMailer::Base
  default :from => "ysharma@heliosedu.com"

  def sendmail(email, subject, body, contact)
    @contact = contact
    @body = body
    @subject = subject
    mail(:to => email, :subject => subject)
  end

  def reminder(email, subject, reminder)
    if email == "" || email == "default"
      email = :from
    end

    @rem = reminder
    mail(:to => email, :subject => subject)
  end
end


text:
use std::io::Cursor;
use std::time::Duration;
use std::sync::{Arc, Mutex};

use rotor::{Scope, Time};
use rotor_http::server::{Server, Response, Head, RecvMode};
use cbor::{Encoder, Decoder, Config};

use inner::{MANAGER, Context, SockId};
use inner::Socket::HttpRequest;

pub enum BufferedHandler {
    HeadersRead { parent: SockId, buffer: Encoder<Cursor<Vec<u8>>> },
    WaitingResponse { id: SockId, response: Arc<Mutex<Option<Box<[u8]>>>> },
}

fn decode_into_response(data: &[u8], res: &mut Response)
    -> Result<(), String>
{
    let mut dec = Decoder::new(Config::default(), Cursor::new(data));
    let num = try!(dec.array()
        .map_err(|e| format!("must be an array: {}", e)));
    if num != 3 {
        return Err(format!("array must contain 3 elements: \
            status, headers, body; contains {} instead", num));
    }
    let num2 = try!(dec.array()
        .map_err(|e| format!("status must be an array: {}", e)));
    if num2 != 2 {
        return Err(format!("status array must contain 2 elements: \
            status_code and status_text; contains {} instead", num));
    }
    let status = try!(dec.u16()
        .map_err(|e| format!("status code must be number 200..599: {}", e)));
    if status < 200 || status > 599 {
        return Err(format!("status code must be number 200..599"));
    }
    {
        let text = try!(dec.text_borrow()
            .map_err(|e| format!("status text must be string: {}", e)));
        res.status(status, text);
    }
    let num3 = try!(dec.object()
        .map_err(|e| format!("headers must be dict (object): {}", e)));
    for _ in 0..num3 {
        // unfortunately can't borrow both
        let name = try!(dec.text()
            .map_err(|e| format!(
                "header name must be string (unicode): {}", e)));
        let value = try!(dec.bytes_borrow()
            .map_err(|e| format!(
                "header value must be bytes (binary): {}", e)));
        try!(res.add_header(&name, value)
            .map_err(|e| format!("error adding header: {}", e)));
    }
    let body = try!(dec.bytes_borrow()
        .map_err(|e| format!("response body must be bytes (binary): {}", e)));
    try!(res.add_length(body.len() as u64)
        .map_err(|e| format!("error adding response length: {}", e)));
    try!(res.done_headers()
        .map_err(|e| format!("error finalizing headers: {}", e)));
    res.write_body(body);
    res.done();
    Ok(())
}

fn write_502(response: &mut Response) {
    if !response.is_started() {
        response.status(502, "Bad Gateway");
        let data = "
502 Bad Gateway
\n\

Served for you by stator(rotor-http)
\n";
        let bytes = data.as_bytes();
        response.add_length(bytes.len() as u64).unwrap();
        response.add_header("Content-Type", b"text/html").unwrap();
        response.done_headers().unwrap();
        response.write_body(bytes);
        response.done();
    }
}

impl Server for BufferedHandler {
    type Seed = SockId;
    type Context = Context;
    fn headers_received(parent_socket: SockId,
        head: Head, _response: &mut Response,
        scope: &mut Scope<Self::Context>)
        -> Option<(Self, RecvMode, Time)>
    {
        let mut enc = Encoder::new(Cursor::new(Vec::new()));
        enc.object(8).unwrap();
        enc.text("client").unwrap();
        match head.client {
            Some(ip) => enc.text(&format!("{}", ip)).unwrap(),
            None => enc.null().unwrap(),
        }
        enc.text("version").unwrap();
        enc.text(&format!("{}", head.version)).unwrap();
        enc.text("method").unwrap();
        enc.text(head.method).unwrap();
        enc.text("scheme").unwrap();
        enc.text(head.scheme).unwrap();
        enc.text("path").unwrap();
        enc.text(head.path).unwrap();
        enc.text("headers").unwrap();
        enc.object(head.headers.len()).unwrap();
        for header in head.headers {
            enc.text(header.name).unwrap();
            enc.bytes(header.value).unwrap();
        }
        // And body and socket_id will be appended
        // as 7th and 8th elements in the request_received method
        Some((BufferedHandler::HeadersRead { parent: parent_socket,
                                             buffer: enc },
             RecvMode::Buffered(1_048_576),
             scope.now() + Duration::new(120, 0)))
    }
    fn request_received(self, data: &[u8], _response: &mut Response,
        scope: &mut Scope<Self::Context>)
        -> Option<Self>
    {
        match self {
            BufferedHandler::HeadersRead { parent, buffer: mut enc } => {
                let arc = Arc::new(Mutex::new(None));
                let sock_id = MANAGER.insert(
                    HttpRequest(arc.clone(), scope.notifier()));

                enc.text("body").unwrap();
                enc.bytes(data).unwrap();
                enc.text("response_socket").unwrap();
                enc.u64(sock_id as u64).unwrap();

                let vec = enc.into_writer().into_inner();
                MANAGER.send(parent, vec.into_boxed_slice());
                Some(BufferedHandler::WaitingResponse { id: sock_id,
                                                        response: arc })
            }
            _ => unreachable!(),
        }
    }
    fn request_chunk(self, _chunk: &[u8], _response: &mut Response,
        _scope: &mut Scope<Self::Context>)
        -> Option<Self>
    {
        unreachable!();
    }
    fn request_end(self, _response: &mut Response,
        _scope: &mut Scope<Self::Context>)
        -> Option<Self>
    {
        unreachable!();
    }
    fn timeout(self, response: &mut Response, scope: &mut Scope<Self::Context>)
        -> Option<(Self, Time)>
    {
        unimplemented!();
    }
    fn wakeup(self, resp: &mut Response, _scope: &mut Scope<Self::Context>)
        -> Option<Self>
    {
        match self {
            BufferedHandler::WaitingResponse { id, response } => {
                let data = response.lock().expect("error").take();
                if let Some(data) = data {
                    match decode_into_response(&data[..], resp) {
                        Ok(()) => {}
                        Err(e) => {
                            error!("error in response for http request: {}",
                                e);
                            write_502(resp);
                        }
                    }
                    MANAGER.remove(id);
                    None
                } else {
                    Some(BufferedHandler::WaitingResponse {
                        id: id, response: response })
                }
            }
            me @ _ => Some(me)
        }
    }

}


text:
from questionnaire.models import Questionnaire, Country
from questionnaire.models.support_document import SupportDocument
from questionnaire.tests.base_test import BaseTest

class FileAnswerTest(BaseTest):

    def test_file_answer_fields(self):
        _file = SupportDocument()
        fields = [str(item.attname) for item in _file._meta.fields]
        self.assertEqual(6, len(fields))
        for field in ['id', 'created', 'modified', 'country_id', 'path', 'questionnaire_id']:
            self.assertIn(field, fields)

    def test_file_answer_field_store(self):
        questionnaire = Questionnaire.objects.create(name="JRF 2013 Core English")
        country = Country.objects.create(name="Uganda")
        pdf_file_name = "/docs/user_files/survey2013.pdf"
        _file = SupportDocument.objects.create(questionnaire=questionnaire, country=country, path=pdf_file_name)
        self.failUnless(_file.id)
        self.assertEqual(pdf_file_name, _file.path)


text:
Show bulk job details

```
force bulk job <jobId> [flags]
```

### Options

```
  -h, --help   help for job
```

### Options inherited from parent commands

```
  -a, --account username    account username to use
  -V, --apiversion string   API version to use
```

### SEE ALSO

* [force bulk](force_bulk.md)	 - Load csv file or query data using Bulk API


text:
package merkle

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"math/big"
	"sync"

	"github.com/google/trillian/storage"
)

// For more information about how Sparse Merkle Trees work see the Revocation Transparency
// paper in the docs directory. Note that applications are not limited to X.509 certificates
// and this implementation handles arbitrary data.

// SparseMerkleTreeReader knows how to read data from a TreeStorage transaction
// to provide proofs etc.
type SparseMerkleTreeReader struct {
	tx           storage.ReadOnlyTreeTX
	hasher       MapHasher
	treeRevision int64
}

type newTXFunc func() (storage.TreeTX, error)

// SparseMerkleTreeWriter knows how to store/update a stored sparse Merkle tree
// via a TreeStorage transaction.
type SparseMerkleTreeWriter struct {
	hasher       MapHasher
	treeRevision int64
	tree         Subtree
}

type indexAndHash struct {
	index []byte
	hash  []byte
}

// rootHashOrError represents a (sub-)tree root hash, or an error which
// prevented the calculation from completing.
type rootHashOrError struct {
	hash []byte
	err  error
}

// Subtree is an interface which must be implemented by subtree workers.
// Currently there's only a locally sharded go-routine based implementation,
// the the idea is that an RPC based sharding implementation could be created
// and dropped in.
type Subtree interface {
	// SetLeaf sets a single leaf hash for integration into a sparse Merkle tree.
	SetLeaf(ctx context.Context, index []byte, hash []byte) error

	// CalculateRoot instructs the subtree worker to start calculating the root
	// hash of its tree.  It is an error to call SetLeaf() after calling this
	// method.
	CalculateRoot()

	// RootHash returns the calculated root hash for this subtree, if the root
	// hash has not yet been calculated, this method will block until it is.
	RootHash() ([]byte, error)
}

// getSubtreeFunc is essentially a factory method for getting child subtrees.
type getSubtreeFunc func(ctx context.Context, prefix []byte) (Subtree, error)

// subtreeWriter knows how to calculate and store nodes for a subtree.
type subtreeWriter struct {
	// prefix is the path to the root of this subtree in the full tree.
	// i.e. all paths/indices under this tree share the same prefix.
	prefix []byte

	// subtreeDepth is the number of levels this subtree contains.
	subtreeDepth int

	// leafQueue is the work-queue containing leaves to be integrated into the
	// subtree.
	leafQueue chan func() (*indexAndHash, error)

	// root is channel of size 1 from which the subtree root can be read once it
	// has been calculated.
	root chan rootHashOrError

	// childMutex protexts access to children.
	childMutex sync.RWMutex

	// children is a map of child-subtrees by stringified prefix.
	children map[string]Subtree

	tx           storage.TreeTX
	treeRevision int64

	treeHasher TreeHasher

	getSubtree getSubtreeFunc
}

// getOrCreateChildSubtree returns, or creates and returns, a subtree for the
// specified childPrefix.
func (s *subtreeWriter) getOrCreateChildSubtree(ctx context.Context, childPrefix []byte) (Subtree, error) {
	// TODO(al): figure out we actually need these copies and remove them if not.
	//           If we do then tidy up with a copyBytes helper.
	cp := append(make([]byte, 0, len(childPrefix)), childPrefix...)
	childPrefixStr := string(cp)
	s.childMutex.Lock()
	defer s.childMutex.Unlock()

	subtree := s.children[childPrefixStr]
	var err error
	if subtree == nil {
		subtree, err = s.getSubtree(ctx, cp)
		if err != nil {
			return nil, err
		}
		s.children[childPrefixStr] = subtree

		// Since a new subtree worker is being created we'll add a future to
		// to the leafQueue such that calculation of *this* subtree's root will
		// incorporate the newly calculated child subtree root.
		s.leafQueue <- func() (*indexAndHash, error) {
			// RootHash blocks until the root is available (or it's errored out)
			h, err := subtree.RootHash()
			if err != nil {
				return nil, err
			}
			return &indexAndHash{
				index: cp,
				hash:  h,
			}, nil
		}
	}
	return subtree, nil
}

// SetLeaf sets a single leaf hash for incorporation into the sparse Merkle
// tree.
func (s *subtreeWriter) SetLeaf(ctx context.Context, index []byte, hash []byte) error {
	indexLen := len(index) * 8

	switch {
	case indexLen < s.subtreeDepth:
		return fmt.Errorf("index length %d is < our depth %d", indexLen, s.subtreeDepth)

	case indexLen > s.subtreeDepth:
		childPrefix := index[:s.subtreeDepth/8]
		subtree, err := s.getOrCreateChildSubtree(ctx, childPrefix)
		if err != nil {
			return err
		}

		return subtree.SetLeaf(ctx, index[s.subtreeDepth/8:], hash)

	case indexLen == s.subtreeDepth:
		s.leafQueue <- func() (*indexAndHash, error) { return &indexAndHash{index: index, hash: hash}, nil }
		return nil
	}

	return fmt.Errorf("internal logic error in SetLeaf. index length: %d, subtreeDepth: %d", indexLen, s.subtreeDepth)
}

// CalculateRoot initiates the process of calculating the subtree root.
// The leafQueue is closed.
func (s *subtreeWriter) CalculateRoot() {
	close(s.leafQueue)

	for _, v := range s.children {
		v.CalculateRoot()
	}
}

// RootHash returns the calculated subtree root hash, blocking if necessary.
func (s *subtreeWriter) RootHash() ([]byte, error) {
	r := <-s.root
	return r.hash, r.err
}

func nodeIDFromAddress(size int, prefix []byte, index *big.Int, depth int) storage.NodeID {
	switch {
	case depth < 0:
		panic(fmt.Errorf("logic error: cannot have depth (%d) < 0", depth))
	case depth == 0:
		return storage.NewEmptyNodeID(size * 8)
	}
	ib := index.Bytes()
	t := make([]byte, size)

	copy(t, prefix)
	copy(t[size-len(ib):], ib)
	n := storage.NewNodeIDFromHash(t)
	n.PrefixLenBits = len(prefix)*8 + depth
	return n
}

// buildSubtree is the worker function which calculates the root hash.
// The root chan will have had exactly one entry placed in it, and have been
// subsequently closed when this method exits.
func (s *subtreeWriter) buildSubtree(ctx context.Context) {
	defer close(s.root)
	defer s.tx.Close()

	leaves := make([]HStar2LeafHash, 0, len(s.leafQueue))
	nodesToStore := make([]storage.Node, 0, len(s.leafQueue)*2)

	for leaf := range s.leafQueue {
		ih, err := leaf()
		if err != nil {
			s.root <- rootHashOrError{hash: nil, err: err}
			return
		}
		leaves = append(leaves, HStar2LeafHash{Index: new(big.Int).SetBytes(ih.index), LeafHash: ih.hash})
		nodesToStore = append(nodesToStore,
			storage.Node{
				NodeID:       storage.NewNodeIDFromHash(bytes.Join([][]byte{s.prefix, ih.index}, []byte{})),
				Hash:         ih.hash,
				NodeRevision: s.treeRevision,
			})

	}

	// calculate new root, and intermediate nodes:
	hs2 := NewHStar2(s.treeHasher)
	treeDepthOffset := (s.treeHasher.Size()-len(s.prefix))*8 - s.subtreeDepth
	addressSize := len(s.prefix) + s.subtreeDepth/8
	root, err := hs2.HStar2Nodes(s.subtreeDepth, treeDepthOffset, leaves,
		func(depth int, index *big.Int) ([]byte, error) {
			nodeID := nodeIDFromAddress(addressSize, s.prefix, index, depth)
			nodes, err := s.tx.GetMerkleNodes(ctx, s.treeRevision, []storage.NodeID{nodeID})
			if err != nil {
				return nil, err
			}
			if len(nodes) == 0 {
				return nil, nil
			}
			if expected, got := nodeID, nodes[0].NodeID; !expected.Equivalent(got) {
				return nil, fmt.Errorf("expected node ID %s from storage, but got %s", expected.String(), got.String())
			}
			if expected, got := s.treeRevision, nodes[0].NodeRevision; got > expected {
				return nil, fmt.Errorf("expected node revision <= %d, but got %d", expected, got)
			}
			return nodes[0].Hash, nil
		},
		func(depth int, index *big.Int, h []byte) error {
			// Don't store the root node of the subtree - that's part of the parent
			// tree.
			if depth == 0 && len(s.prefix) > 0 {
				return nil
			}
			nID := nodeIDFromAddress(addressSize, s.prefix, index, depth)
			nodesToStore = append(nodesToStore,
				storage.Node{
					NodeID:       nID,
					Hash:         h,
					NodeRevision: s.treeRevision,
				})
			return nil
		})
	if err != nil {
		s.root <- rootHashOrError{nil, err}
		return
	}

	// write nodes back to storage
	if err := s.tx.SetMerkleNodes(ctx, nodesToStore); err != nil {
		s.root <- rootHashOrError{nil, err}
		return
	}
	if err := s.tx.Commit(); err != nil {
		s.root <- rootHashOrError{nil, err}
		return
	}

	// send calculated root hash
	s.root <- rootHashOrError{root, nil}
}

var (
	// ErrNoSuchRevision is returned when a request is made for information about
	// a tree revision which does not exist.
	ErrNoSuchRevision = errors.New("no such revision")
)

// NewSparseMerkleTreeReader returns a new SparseMerkleTreeReader, reading at
// the specified tree revision, using the passed in MapHasher for calculating
// and verifying tree hashes read via tx.
func NewSparseMerkleTreeReader(rev int64, h MapHasher, tx storage.ReadOnlyTreeTX) *SparseMerkleTreeReader {
	return &SparseMerkleTreeReader{
		tx:           tx,
		hasher:       h,
		treeRevision: rev,
	}
}

func leafQueueSize(depths []int) int {
	if len(depths) == 1 {
		return 1024
	}
	// for higher levels make sure we've got enough space if all leaves turn out
	// to be sub-tree futures...
	return 1 << uint(depths[0])
}

// newLocalSubtreeWriter creates a new local go-routine based subtree worker.
func newLocalSubtreeWriter(ctx context.Context, rev int64, prefix []byte, depths []int, newTX newTXFunc, h TreeHasher) (Subtree, error) {
	tx, err := newTX()
	if err != nil {
		return nil, err
	}
	tree := subtreeWriter{
		treeRevision: rev,
		// TODO(al): figure out if we actually need these copies and remove it not.
		prefix:       append(make([]byte, 0, len(prefix)), prefix...),
		subtreeDepth: depths[0],
		leafQueue:    make(chan func() (*indexAndHash, error), leafQueueSize(depths)),
		root:         make(chan rootHashOrError, 1),
		children:     make(map[string]Subtree),
		tx:           tx,
		treeHasher:   h,
		getSubtree: func(ctx context.Context, p []byte) (Subtree, error) {
			myPrefix := bytes.Join([][]byte{prefix, p}, []byte{})
			return newLocalSubtreeWriter(ctx, rev, myPrefix, depths[1:], newTX, h)
		},
	}

	// TODO(al): probably shouldn't be spawning go routines willy-nilly like
	// this, but it'll do for now.
	go tree.buildSubtree(ctx)
	return &tree, nil
}

// NewSparseMerkleTreeWriter returns a new SparseMerkleTreeWriter, which will
// write data back into the tree at the specified revision, using the passed
// in MapHasher to calculate/verify tree hashes, storing via tx.
func NewSparseMerkleTreeWriter(ctx context.Context, rev int64, h MapHasher, newTX newTXFunc) (*SparseMerkleTreeWriter, error) {
	// TODO(al): allow the tree layering sizes to be customisable somehow.
	const topSubtreeSize = 8 // must be a multiple of 8 for now.
	tree, err := newLocalSubtreeWriter(ctx, rev, []byte{}, []int{topSubtreeSize, h.Size()*8 - topSubtreeSize}, newTX, h.TreeHasher)
	if err != nil {
		return nil, err
	}
	return &SparseMerkleTreeWriter{
		hasher:       h,
		tree:         tree,
		treeRevision: rev,
	}, nil
}

// RootAtRevision returns the sparse Merkle tree root hash at the specified
// revision, or ErrNoSuchRevision if the requested revision doesn't exist.
func (s SparseMerkleTreeReader) RootAtRevision(ctx context.Context, rev int64) ([]byte, error) {
	rootNodeID := storage.NewEmptyNodeID(256)
	nodes, err := s.tx.GetMerkleNodes(ctx, rev, []storage.NodeID{rootNodeID})
	if err != nil {
		return nil, err
	}
	switch {
	case len(nodes) == 0:
		return nil, ErrNoSuchRevision
	case len(nodes) > 1:
		return nil, fmt.Errorf("expected 1 node, but got %d", len(nodes))
	}
	// Sanity check the nodeID
	if !nodes[0].NodeID.Equivalent(rootNodeID) {
		return nil, fmt.Errorf("unexpected node returned with ID: %v", nodes[0].NodeID)
	}
	// Sanity check the revision
	if nodes[0].NodeRevision > rev {
		return nil, fmt.Errorf("unexpected node revision returned: %d > %d", nodes[0].NodeRevision, rev)
	}
	return nodes[0].Hash, nil
}

// InclusionProof returns an inclusion (or non-inclusion) proof for the
// specified key at the specified revision.
// If the revision does not exist it will return ErrNoSuchRevision error.
func (s SparseMerkleTreeReader) InclusionProof(ctx context.Context, rev int64, index []byte) ([][]byte, error) {
	nid := storage.NewNodeIDFromHash(index)
	sibs := nid.Siblings()
	nodes, err := s.tx.GetMerkleNodes(ctx, rev, sibs)
	if err != nil {
		return nil, err
	}

	nodeMap := make(map[string]*storage.Node)
	for _, n := range nodes {
		n := n // need this or we'll end up with the same node hash repeated in the map
		nodeMap[n.NodeID.String()] = &n
	}

	// We're building a full proof from a combination of whichever nodes we got
	// back from the storage layer, and the set of "null" hashes.
	r := make([][]byte, len(sibs), len(sibs))
	// For each proof element:
	for i := 0; i < len(r); i++ {
		proofID := sibs[i]
		pNode := nodeMap[proofID.String()]
		if pNode == nil {
			// we have no node for this level from storage, so the client will use
			// the null hash.
			continue
		}
		r[i] = pNode.Hash
		delete(nodeMap, proofID.String())
	}

	// Make sure we used up all the returned nodes, otherwise something's gone wrong.
	if remaining := len(nodeMap); remaining != 0 {
		return nil, fmt.Errorf("failed to consume all returned nodes; got %d nodes, but %d remain(s) unused", len(nodes), remaining)
	}
	return r, nil
}

// SetLeaves adds a batch of leaves to the in-flight tree update.
func (s *SparseMerkleTreeWriter) SetLeaves(ctx context.Context, leaves []HashKeyValue) error {
	for _, l := range leaves {
		if err := s.tree.SetLeaf(ctx, l.HashedKey, l.HashedValue); err != nil {
			return err
		}
	}
	return nil
}

// CalculateRoot calculates the new root hash including the newly added leaves.
func (s *SparseMerkleTreeWriter) CalculateRoot() ([]byte, error) {
	s.tree.CalculateRoot()
	return s.tree.RootHash()
}

// HashKeyValue represents a Hash(key)-Hash(value) pair.
type HashKeyValue struct {
	// HashedKey is the hash of the key data
	HashedKey []byte

	// HashedValue is the hash of the value data.
	HashedValue []byte
}


text:
<?php
declare(strict_types=1);

namespace PhpMultiCurl\Task;

final class Ftp
{
    public function __construct()
    {
        throw new \Exception('Not implemented');
    }
}