diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 057e7d0ca..cb9a4e4a3 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -91,6 +91,7 @@ set(llui_SOURCE_FILES llviewborder.cpp llviewmodel.cpp llviewquery.cpp + llxuiparser.cpp ) set(llui_HEADER_FILES @@ -172,6 +173,7 @@ set(llui_HEADER_FILES llviewborder.h llviewmodel.h llviewquery.h + llxuiparser.h ) set_source_files_properties(${llui_HEADER_FILES} diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 57cdb8462..66b8d64ec 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -867,10 +867,10 @@ void LLLineEditor::removeChar() // Remove a word (set of characters up to next space/punctuation) from the text void LLLineEditor::removeWord(bool prev) { - const U32 pos(getCursor()); - if (prev ? pos > 0 : static_cast(pos) < getLength()) + const S32& pos(mCursorPos); + if (prev ? pos > 0 : pos < getLength()) { - U32 new_pos(prev ? prevWordPos(pos) : nextWordPos(pos)); + S32 new_pos(prev ? prevWordPos(pos) : nextWordPos(pos)); if (new_pos == pos) // Other character we don't jump over new_pos = prev ? prevWordPos(new_pos-1) : nextWordPos(new_pos+1); diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 83912db9c..0412c302e 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1817,10 +1817,10 @@ void LLTextEditor::removeChar() // Remove a word (set of characters up to next space/punctuation) from the text void LLTextEditor::removeWord(bool prev) { - const U32 pos(mCursorPos); - if (prev ? pos > 0 : static_cast(pos) < getLength()) + const S32& pos(mCursorPos); + if (prev ? pos > 0 : pos < getLength()) { - U32 new_pos(prev ? prevWordPos(pos) : nextWordPos(pos)); + S32 new_pos(prev ? prevWordPos(pos) : nextWordPos(pos)); if (new_pos == pos) // Other character we don't jump over new_pos = prev ? prevWordPos(new_pos-1) : nextWordPos(new_pos+1); @@ -2368,6 +2368,13 @@ BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask) } break; + case KEY_DELETE: + if (getEnabled()) + removeWord(false); + else + handled = false; + break; + default: handled = FALSE; break; @@ -2485,17 +2492,6 @@ BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask, BOOL* return } break; - case KEY_DELETE: - if (getEnabled() && mask == MASK_CONTROL) - { - removeWord(false); - } - else - { - handled = false; - } - break; - case KEY_RETURN: if (mask == MASK_NONE) { diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp new file mode 100644 index 000000000..9cf5bb03e --- /dev/null +++ b/indra/llui/llxuiparser.cpp @@ -0,0 +1,1785 @@ +/** + * @file llxuiparser.cpp + * @brief Utility functions for handling XUI structures in XML + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llxuiparser.h" + +#include "llxmlnode.h" +#include "llfasttimer.h" +#ifdef LL_STANDALONE //LL_USESYSTEMLIBS +#include +#else +#include "expat/expat.h" +#endif + +#include +#include +#include +//#include +#include + +#include "lluicolor.h" +#include "v3math.h" +using namespace BOOST_SPIRIT_CLASSIC_NS; + +const S32 MAX_STRING_ATTRIBUTE_SIZE = 40; + +static LLInitParam::Parser::parser_read_func_map_t sXSDReadFuncs; +static LLInitParam::Parser::parser_write_func_map_t sXSDWriteFuncs; +static LLInitParam::Parser::parser_inspect_func_map_t sXSDInspectFuncs; + +static LLInitParam::Parser::parser_read_func_map_t sSimpleXUIReadFuncs; +static LLInitParam::Parser::parser_write_func_map_t sSimpleXUIWriteFuncs; +static LLInitParam::Parser::parser_inspect_func_map_t sSimpleXUIInspectFuncs; + +const char* NO_VALUE_MARKER = "no_value"; + +#ifdef LL_WINDOWS +const S32 LINE_NUMBER_HERE = 0; +#endif + +struct MaxOccursValues : public LLInitParam::TypeValuesHelper +{ + static void declareValues() + { + declare("unbounded", U32_MAX); + } +}; + +struct Occurs : public LLInitParam::Block +{ + Optional minOccurs; + Optional maxOccurs; + + Occurs() + : minOccurs("minOccurs", 0), + maxOccurs("maxOccurs", U32_MAX) + + {} +}; + +typedef enum +{ + USE_REQUIRED, + USE_OPTIONAL +} EUse; + +namespace LLInitParam +{ + template<> + struct TypeValues : public TypeValuesHelper + { + static void declareValues() + { + declare("required", USE_REQUIRED); + declare("optional", USE_OPTIONAL); + } + }; +} + +struct Element; +struct Group; +struct Sequence; + +struct All : public LLInitParam::Block +{ + Multiple< Lazy > elements; + + All() + : elements("element") + { + maxOccurs = 1; + } +}; + +struct Attribute : public LLInitParam::Block +{ + Mandatory name, + type; + Mandatory use; + + Attribute() + : name("name"), + type("type"), + use("use") + {} +}; + +struct Any : public LLInitParam::Block +{ + Optional _namespace; + + Any() + : _namespace("namespace") + {} +}; + +struct Choice : public LLInitParam::ChoiceBlock +{ + Alternative< Lazy > element; + Alternative< Lazy > group; + Alternative< Lazy > choice; + Alternative< Lazy > sequence; + Alternative< Lazy > any; + + Choice() + : element("element"), + group("group"), + choice("choice"), + sequence("sequence"), + any("any") + {} + +}; + +struct Sequence : public LLInitParam::ChoiceBlock +{ + Alternative< Lazy > element; + Alternative< Lazy > group; + Alternative< Lazy > choice; + Alternative< Lazy > sequence; + Alternative< Lazy > any; +}; + +struct GroupContents : public LLInitParam::ChoiceBlock +{ + Alternative all; + Alternative choice; + Alternative sequence; + + GroupContents() + : all("all"), + choice("choice"), + sequence("sequence") + {} +}; + +struct Group : public LLInitParam::Block +{ + Optional name, + ref; + + Group() + : name("name"), + ref("ref") + {} +}; + +struct Restriction : public LLInitParam::Block +{ +}; + +struct Extension : public LLInitParam::Block +{ +}; + +struct SimpleContent : public LLInitParam::ChoiceBlock +{ + Alternative restriction; + Alternative extension; + + SimpleContent() + : restriction("restriction"), + extension("extension") + {} +}; + +struct SimpleType : public LLInitParam::Block +{ + // TODO +}; + +struct ComplexContent : public LLInitParam::Block +{ + Optional mixed; + + ComplexContent() + : mixed("mixed", true) + {} +}; + +struct ComplexTypeContents : public LLInitParam::ChoiceBlock +{ + Alternative simple_content; + Alternative complex_content; + Alternative group; + Alternative all; + Alternative choice; + Alternative sequence; + + ComplexTypeContents() + : simple_content("simpleContent"), + complex_content("complexContent"), + group("group"), + all("all"), + choice("choice"), + sequence("sequence") + {} +}; + +struct ComplexType : public LLInitParam::Block +{ + Optional name; + Optional mixed; + + Multiple attribute; + Multiple< Lazy > elements; + + ComplexType() + : name("name"), + attribute("xs:attribute"), + elements("xs:element"), + mixed("mixed") + { + } +}; + +struct ElementContents : public LLInitParam::ChoiceBlock +{ + Alternative simpleType; + Alternative complexType; + + ElementContents() + : simpleType("simpleType"), + complexType("complexType") + {} +}; + +struct Element : public LLInitParam::Block +{ + Optional name, + ref, + type; + + Element() + : name("xs:name"), + ref("xs:ref"), + type("xs:type") + {} +}; + +struct Schema : public LLInitParam::Block +{ +private: + Mandatory targetNamespace, + xmlns, + xs; + +public: + Optional attributeFormDefault, + elementFormDefault; + + Mandatory root_element; + + void setNameSpace(const std::string& ns) {targetNamespace = ns; xmlns = ns;} + + Schema(const std::string& ns = LLStringUtil::null) + : attributeFormDefault("attributeFormDefault"), + elementFormDefault("elementFormDefault"), + xs("xmlns:xs"), + targetNamespace("targetNamespace"), + xmlns("xmlns"), + root_element("xs:element") + { + attributeFormDefault = "unqualified"; + elementFormDefault = "qualified"; + xs = "http://www.w3.org/2001/XMLSchema"; + if (!ns.empty()) + { + setNameSpace(ns); + }; + } +}; + +// +// LLXSDWriter +// +LLXSDWriter::LLXSDWriter() +: Parser(sXSDReadFuncs, sXSDWriteFuncs, sXSDInspectFuncs) +{ + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:boolean", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedByte", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedByte", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedShort", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedShort", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedInt", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:integer", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:float", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:double", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); + registerInspectFunc(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); +} + +LLXSDWriter::~LLXSDWriter() {} + +void LLXSDWriter::writeXSD(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace) +{ + Schema schema(xml_namespace); + + schema.root_element.name = type_name; + Choice& choice = schema.root_element.complexType.choice; + + choice.minOccurs = 0; + choice.maxOccurs = "unbounded"; + + mSchemaNode = node; + //node->setName("xs:schema"); + //node->createChild("attributeFormDefault", true)->setStringValue("unqualified"); + //node->createChild("elementFormDefault", true)->setStringValue("qualified"); + //node->createChild("targetNamespace", true)->setStringValue(xml_namespace); + //node->createChild("xmlns:xs", true)->setStringValue("http://www.w3.org/2001/XMLSchema"); + //node->createChild("xmlns", true)->setStringValue(xml_namespace); + + //node = node->createChild("xs:complexType", false); + //node->createChild("name", true)->setStringValue(type_name); + //node->createChild("mixed", true)->setStringValue("true"); + + //mAttributeNode = node; + //mElementNode = node->createChild("xs:choice", false); + //mElementNode->createChild("minOccurs", true)->setStringValue("0"); + //mElementNode->createChild("maxOccurs", true)->setStringValue("unbounded"); + block.inspectBlock(*this); + + // duplicate element choices + LLXMLNodeList children; + mElementNode->getChildren("xs:element", children, FALSE); + for (LLXMLNodeList::iterator child_it = children.begin(); child_it != children.end(); ++child_it) + { + LLXMLNodePtr child_copy = child_it->second->deepCopy(); + std::string child_name; + child_copy->getAttributeString("name", child_name); + child_copy->setAttributeString("name", type_name + "." + child_name); + mElementNode->addChild(child_copy); + } + + LLXMLNodePtr element_declaration_node = mSchemaNode->createChild("xs:element", false); + element_declaration_node->createChild("name", true)->setStringValue(type_name); + element_declaration_node->createChild("type", true)->setStringValue(type_name); +} + +void LLXSDWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector* possible_values) +{ + name_stack_t non_empty_names; + std::string attribute_name; + for (name_stack_t::const_iterator it = stack.begin(); + it != stack.end(); + ++it) + { + const std::string& name = it->first; + if (!name.empty()) + { + non_empty_names.push_back(*it); + } + } + + for (name_stack_t::const_iterator it = non_empty_names.begin(); + it != non_empty_names.end(); + ++it) + { + if (!attribute_name.empty()) + { + attribute_name += "."; + } + attribute_name += it->first; + } + + // only flag non-nested attributes as mandatory, nested attributes have variant syntax + // that can't be properly constrained in XSD + // e.g. vs + bool attribute_mandatory = min_count == 1 && max_count == 1 && non_empty_names.size() == 1; + + // don't bother supporting "Multiple" params as xml attributes + if (max_count <= 1) + { + // add compound attribute to root node + addAttributeToSchema(mAttributeNode, attribute_name, type, attribute_mandatory, possible_values); + } + + // now generated nested elements for compound attributes + if (non_empty_names.size() > 1 && !attribute_mandatory) + { + std::string element_name; + + // traverse all but last element, leaving that as an attribute name + name_stack_t::const_iterator end_it = non_empty_names.end(); + end_it--; + + for (name_stack_t::const_iterator it = non_empty_names.begin(); + it != end_it; + ++it) + { + if (it != non_empty_names.begin()) + { + element_name += "."; + } + element_name += it->first; + } + + std::string short_attribute_name = non_empty_names.back().first; + + LLXMLNodePtr complex_type_node; + + // find existing element node here, starting at tail of child list + if (mElementNode->mChildren.notNull()) + { + for(LLXMLNodePtr element = mElementNode->mChildren->tail; + element.notNull(); + element = element->mPrev) + { + std::string name; + if(element->getAttributeString("name", name) && name == element_name) + { + complex_type_node = element->mChildren->head; + break; + } + } + } + //create complex_type node + // + // + // + // + // + if(complex_type_node.isNull()) + { + complex_type_node = mElementNode->createChild("xs:element", false); + + complex_type_node->createChild("minOccurs", true)->setIntValue(min_count); + complex_type_node->createChild("maxOccurs", true)->setIntValue(max_count); + complex_type_node->createChild("name", true)->setStringValue(element_name); + complex_type_node = complex_type_node->createChild("xs:complexType", false); + } + + addAttributeToSchema(complex_type_node, short_attribute_name, type, false, possible_values); + } +} + +void LLXSDWriter::addAttributeToSchema(LLXMLNodePtr type_declaration_node, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector* possible_values) +{ + if (!attribute_name.empty()) + { + LLXMLNodePtr new_enum_type_node; + if (possible_values != NULL) + { + // custom attribute type, for example + // + // + // + // + // + // + new_enum_type_node = new LLXMLNode("xs:simpleType", false); + + LLXMLNodePtr restriction_node = new_enum_type_node->createChild("xs:restriction", false); + restriction_node->createChild("base", true)->setStringValue("xs:string"); + + for (std::vector::const_iterator it = possible_values->begin(); + it != possible_values->end(); + ++it) + { + LLXMLNodePtr enum_node = restriction_node->createChild("xs:enumeration", false); + enum_node->createChild("value", true)->setStringValue(*it); + } + } + + string_set_t& attributes_written = mAttributesWritten[type_declaration_node]; + + string_set_t::iterator found_it = attributes_written.lower_bound(attribute_name); + + // attribute not yet declared + if (found_it == attributes_written.end() || attributes_written.key_comp()(attribute_name, *found_it)) + { + attributes_written.insert(found_it, attribute_name); + + LLXMLNodePtr attribute_node = type_declaration_node->createChild("xs:attribute", false); + + // attribute name + attribute_node->createChild("name", true)->setStringValue(attribute_name); + + if (new_enum_type_node.notNull()) + { + attribute_node->addChild(new_enum_type_node); + } + else + { + // simple attribute type + attribute_node->createChild("type", true)->setStringValue(type); + } + + // required or optional + attribute_node->createChild("use", true)->setStringValue(mandatory ? "required" : "optional"); + } + // attribute exists...handle collision of same name attributes with potentially different types + else + { + LLXMLNodePtr attribute_declaration; + if (type_declaration_node.notNull()) + { + for(LLXMLNodePtr node = type_declaration_node->mChildren->tail; + node.notNull(); + node = node->mPrev) + { + std::string name; + if (node->getAttributeString("name", name) && name == attribute_name) + { + attribute_declaration = node; + break; + } + } + } + + bool new_type_is_enum = new_enum_type_node.notNull(); + bool existing_type_is_enum = !attribute_declaration->hasAttribute("type"); + + // either type is enum, revert to string in collision + // don't bother to check for enum equivalence + if (new_type_is_enum || existing_type_is_enum) + { + if (attribute_declaration->hasAttribute("type")) + { + attribute_declaration->setAttributeString("type", "xs:string"); + } + else + { + attribute_declaration->createChild("type", true)->setStringValue("xs:string"); + } + attribute_declaration->deleteChildren("xs:simpleType"); + } + else + { + // check for collision of different standard types + std::string existing_type; + attribute_declaration->getAttributeString("type", existing_type); + // if current type is not the same as the new type, revert to strnig + if (existing_type != type) + { + // ...than use most general type, string + attribute_declaration->setAttributeString("type", "string"); + } + } + } + } +} + +// +// LLXUIXSDWriter +// +void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& path, const LLInitParam::BaseBlock& block) +{ + std::string file_name(path); + file_name += type_name + ".xsd"; + LLXMLNodePtr root_nodep = new LLXMLNode(); + + LLXSDWriter::writeXSD(type_name, root_nodep, block, "http://www.lindenlab.com/xui"); + + // add includes for all possible children + const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name); + const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type); + + // add choices for valid children + if (widget_registryp) + { + // add include declarations for all valid children + for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems(); + it != widget_registryp->currentRegistrar().endItems(); + ++it) + { + std::string widget_name = it->first; + if (widget_name == type_name) + { + continue; + } + LLXMLNodePtr nodep = new LLXMLNode("xs:include", false); + nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd"); + + // add to front of schema + mSchemaNode->addChild(nodep); + } + + for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems(); + it != widget_registryp->currentRegistrar().endItems(); + ++it) + { + std::string widget_name = it->first; + // + LLXMLNodePtr widget_node = mElementNode->createChild("xs:element", false); + widget_node->createChild("name", true)->setStringValue(widget_name); + widget_node->createChild("type", true)->setStringValue(widget_name); + } + } + + LLFILE* xsd_file = LLFile::fopen(file_name.c_str(), "w"); + LLXMLNode::writeHeaderToFile(xsd_file); + root_nodep->writeToFile(xsd_file); + fclose(xsd_file); +} + +static LLInitParam::Parser::parser_read_func_map_t sXUIReadFuncs; +static LLInitParam::Parser::parser_write_func_map_t sXUIWriteFuncs; +static LLInitParam::Parser::parser_inspect_func_map_t sXUIInspectFuncs; + +// +// LLXUIParser +// +LLXUIParser::LLXUIParser() +: Parser(sXUIReadFuncs, sXUIWriteFuncs, sXUIInspectFuncs), + mCurReadDepth(0) +{ + if (sXUIReadFuncs.empty()) + { + registerParserFuncs(readFlag, writeFlag); + registerParserFuncs(readBoolValue, writeBoolValue); + registerParserFuncs(readStringValue, writeStringValue); + registerParserFuncs(readU8Value, writeU8Value); + registerParserFuncs(readS8Value, writeS8Value); + registerParserFuncs(readU16Value, writeU16Value); + registerParserFuncs(readS16Value, writeS16Value); + registerParserFuncs(readU32Value, writeU32Value); + registerParserFuncs(readS32Value, writeS32Value); + registerParserFuncs(readF32Value, writeF32Value); + registerParserFuncs(readF64Value, writeF64Value); + registerParserFuncs(readVector3Value, writeVector3Value); + registerParserFuncs(readColor4Value, writeColor4Value); + registerParserFuncs(readUIColorValue, writeUIColorValue); + registerParserFuncs(readUUIDValue, writeUUIDValue); + registerParserFuncs(readSDValue, writeSDValue); + } +} + +LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing"); +const LLXMLNodePtr DUMMY_NODE = new LLXMLNode(); + +void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename, bool silent) +{ + LLFastTimer ft(FTM_PARSE_XUI); + mNameStack.clear(); + mRootNodeName = node->getName()->mString; + mCurFileName = filename; + mCurReadDepth = 0; + setParseSilently(silent); + + if (node.isNull()) + { + parserWarning("Invalid node"); + } + else + { + readXUIImpl(node, block); + } +} + +bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block) +{ + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("."); + + bool values_parsed = false; + bool silent = mCurReadDepth > 0; + + if (nodep->getFirstChild().isNull() + && nodep->mAttributes.empty() + && nodep->getSanitizedValue().empty()) + { + // empty node, just parse as flag + mCurReadNode = DUMMY_NODE; + return block.submitValue(mNameStack, *this, silent); + } + + // submit attributes for current node + values_parsed |= readAttributes(nodep, block); + + // treat text contents of xml node as "value" parameter + std::string text_contents = nodep->getSanitizedValue(); + if (!text_contents.empty()) + { + mCurReadNode = nodep; + mNameStack.push_back(std::make_pair(std::string("value"), true)); + // child nodes are not necessarily valid parameters (could be a child widget) + // so don't complain once we've recursed + if (!block.submitValue(mNameStack, *this, true)) + { + mNameStack.pop_back(); + block.submitValue(mNameStack, *this, silent); + } + else + { + mNameStack.pop_back(); + } + } + + // then traverse children + // child node must start with last name of parent node (our "scope") + // for example: "" + // which equates to the following nesting: + // button + // param + // nested_param1 + // nested_param2 + // nested_param3 + mCurReadDepth++; + for(LLXMLNodePtr childp = nodep->getFirstChild(); childp.notNull();) + { + std::string child_name(childp->getName()->mString); + S32 num_tokens_pushed = 0; + + // for non "dotted" child nodes check to see if child node maps to another widget type + // and if not, treat as a child element of the current node + // e.g. will interpret as "button.rect" + // since there is no widget named "rect" + if (child_name.find(".") == std::string::npos) + { + mNameStack.push_back(std::make_pair(child_name, true)); + num_tokens_pushed++; + } + else + { + // parse out "dotted" name into individual tokens + tokenizer name_tokens(child_name, sep); + + tokenizer::iterator name_token_it = name_tokens.begin(); + if(name_token_it == name_tokens.end()) + { + childp = childp->getNextSibling(); + continue; + } + + // check for proper nesting + if (mNameStack.empty()) + { + if (*name_token_it != mRootNodeName) + { + childp = childp->getNextSibling(); + continue; + } + } + else if(mNameStack.back().first != *name_token_it) + { + childp = childp->getNextSibling(); + continue; + } + + // now ignore first token + ++name_token_it; + + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push) + { + mNameStack.push_back(std::make_pair(*token_to_push, true)); + num_tokens_pushed++; + } + } + + // recurse and visit children XML nodes + if(readXUIImpl(childp, block)) + { + // child node successfully parsed, remove from DOM + + values_parsed = true; + LLXMLNodePtr node_to_remove = childp; + childp = childp->getNextSibling(); + + nodep->deleteChild(node_to_remove); + } + else + { + childp = childp->getNextSibling(); + } + + while(num_tokens_pushed-- > 0) + { + mNameStack.pop_back(); + } + } + mCurReadDepth--; + return values_parsed; +} + +bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block) +{ + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("."); + + bool any_parsed = false; + bool silent = mCurReadDepth > 0; + + for(LLXMLAttribList::const_iterator attribute_it = nodep->mAttributes.begin(); + attribute_it != nodep->mAttributes.end(); + ++attribute_it) + { + S32 num_tokens_pushed = 0; + std::string attribute_name(attribute_it->first->mString); + mCurReadNode = attribute_it->second; + + tokenizer name_tokens(attribute_name, sep); + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push) + { + mNameStack.push_back(std::make_pair(*token_to_push, true)); + num_tokens_pushed++; + } + + // child nodes are not necessarily valid attributes, so don't complain once we've recursed + any_parsed |= block.submitValue(mNameStack, *this, silent); + + while(num_tokens_pushed-- > 0) + { + mNameStack.pop_back(); + } + } + + return any_parsed; +} + +void LLXUIParser::writeXUIImpl(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::predicate_rule_t rules, const LLInitParam::BaseBlock* diff_block) +{ + mWriteRootNode = node; + name_stack_t name_stack = Parser::name_stack_t(); + block.serializeBlock(*this, name_stack, rules, diff_block); + mOutNodes.clear(); +} + +// go from a stack of names to a specific XML node +LLXMLNodePtr LLXUIParser::getNode(name_stack_t& stack) +{ + LLXMLNodePtr out_node = mWriteRootNode; + + name_stack_t::iterator next_it = stack.begin(); + for (name_stack_t::iterator it = stack.begin(); + it != stack.end(); + it = next_it) + { + ++next_it; + bool force_new_node = false; + + if (it->first.empty()) + { + it->second = false; + continue; + } + + if (next_it != stack.end() && next_it->first.empty() && next_it->second) + { + force_new_node = true; + } + + + out_nodes_t::iterator found_it = mOutNodes.find(it->first); + + // node with this name not yet written + if (found_it == mOutNodes.end() || it->second || force_new_node) + { + // make an attribute if we are the last element on the name stack + bool is_attribute = next_it == stack.end(); + LLXMLNodePtr new_node = new LLXMLNode(it->first.c_str(), is_attribute); + out_node->addChild(new_node); + mOutNodes[it->first] = new_node; + out_node = new_node; + it->second = false; + } + else + { + out_node = found_it->second; + } + } + + return (out_node == mWriteRootNode ? LLXMLNodePtr(NULL) : out_node); +} + +bool LLXUIParser::readFlag(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode == DUMMY_NODE; +} + +bool LLXUIParser::writeFlag(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + // just create node + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + return node.notNull(); +} + +bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr) +{ + S32 value; + LLXUIParser& self = static_cast(parser); + bool success = self.mCurReadNode->getBoolValue(1, &value); + *((bool*)val_ptr) = (value != FALSE); + return success; +} + +bool LLXUIParser::writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setBoolValue(*((bool*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readStringValue(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + *((std::string*)val_ptr) = self.mCurReadNode->getSanitizedValue(); + return true; +} + +bool LLXUIParser::writeStringValue(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + const std::string* string_val = reinterpret_cast(val_ptr); + if (string_val->find('\n') != std::string::npos + || string_val->size() > MAX_STRING_ATTRIBUTE_SIZE) + { + // don't write strings with newlines into attributes + std::string attribute_name = node->getName()->mString; + LLXMLNodePtr parent_node = node->mParent; + parent_node->deleteChild(node); + // write results in text contents of node + if (attribute_name == "value") + { + // "value" is implicit, just write to parent + node = parent_node; + } + else + { + // create a child that is not an attribute, but with same name + node = parent_node->createChild(attribute_name.c_str(), false); + } + } + node->setStringValue(*string_val); + return true; + } + return false; +} + +bool LLXUIParser::readU8Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode->getByteValue(1, (U8*)val_ptr); +} + +bool LLXUIParser::writeU8Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setUnsignedValue(*((U8*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readS8Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + S32 value; + if(self.mCurReadNode->getIntValue(1, &value)) + { + *((S8*)val_ptr) = value; + return true; + } + return false; +} + +bool LLXUIParser::writeS8Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setIntValue(*((S8*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readU16Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + U32 value; + if(self.mCurReadNode->getUnsignedValue(1, &value)) + { + *((U16*)val_ptr) = value; + return true; + } + return false; +} + +bool LLXUIParser::writeU16Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setUnsignedValue(*((U16*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readS16Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + S32 value; + if(self.mCurReadNode->getIntValue(1, &value)) + { + *((S16*)val_ptr) = value; + return true; + } + return false; +} + +bool LLXUIParser::writeS16Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setIntValue(*((S16*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readU32Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode->getUnsignedValue(1, (U32*)val_ptr); +} + +bool LLXUIParser::writeU32Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setUnsignedValue(*((U32*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readS32Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode->getIntValue(1, (S32*)val_ptr); +} + +bool LLXUIParser::writeS32Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setIntValue(*((S32*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readF32Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode->getFloatValue(1, (F32*)val_ptr); +} + +bool LLXUIParser::writeF32Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setFloatValue(*((F32*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readF64Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + return self.mCurReadNode->getDoubleValue(1, (F64*)val_ptr); +} + +bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setDoubleValue(*((F64*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readVector3Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + LLVector3* vecp = (LLVector3*)val_ptr; + if(self.mCurReadNode->getFloatValue(3, vecp->mV) >= 3) + { + return true; + } + + return false; +} + +bool LLXUIParser::writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + LLVector3 vector = *((LLVector3*)val_ptr); + node->setFloatValue(3, vector.mV); + return true; + } + return false; +} + +bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + LLColor4* colorp = (LLColor4*)val_ptr; + if(self.mCurReadNode->getFloatValue(4, colorp->mV) >= 3) + { + return true; + } + + return false; +} + +bool LLXUIParser::writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + LLColor4 color = *((LLColor4*)val_ptr); + node->setFloatValue(4, color.mV); + return true; + } + return false; +} + +bool LLXUIParser::readUIColorValue(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + LLUIColor* param = (LLUIColor*)val_ptr; + LLColor4 color; + bool success = self.mCurReadNode->getFloatValue(4, color.mV) >= 3; + if (success) + { + param->set(color); + return true; + } + return false; +} + +bool LLXUIParser::writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + LLUIColor color = *((LLUIColor*)val_ptr); + //RN: don't write out the color that is represented by a function + // rely on param block exporting to get the reference to the color settings + if (color.isReference()) return false; + node->setFloatValue(4, color.get().mV); + return true; + } + return false; +} + +bool LLXUIParser::readUUIDValue(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + LLUUID temp_id; + // LLUUID::set is destructive, so use temporary value + if (temp_id.set(self.mCurReadNode->getSanitizedValue())) + { + *(LLUUID*)(val_ptr) = temp_id; + return true; + } + return false; +} + +bool LLXUIParser::writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + node->setStringValue(((LLUUID*)val_ptr)->asString()); + return true; + } + return false; +} + +bool LLXUIParser::readSDValue(Parser& parser, void* val_ptr) +{ + LLXUIParser& self = static_cast(parser); + *((LLSD*)val_ptr) = LLSD(self.mCurReadNode->getSanitizedValue()); + return true; +} + +bool LLXUIParser::writeSDValue(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ + LLXUIParser& self = static_cast(parser); + + LLXMLNodePtr node = self.getNode(stack); + if (node.notNull()) + { + std::string string_val = ((LLSD*)val_ptr)->asString(); + if (string_val.find('\n') != std::string::npos || string_val.size() > MAX_STRING_ATTRIBUTE_SIZE) + { + // don't write strings with newlines into attributes + std::string attribute_name = node->getName()->mString; + LLXMLNodePtr parent_node = node->mParent; + parent_node->deleteChild(node); + // write results in text contents of node + if (attribute_name == "value") + { + // "value" is implicit, just write to parent + node = parent_node; + } + else + { + node = parent_node->createChild(attribute_name.c_str(), false); + } + } + + node->setStringValue(string_val); + return true; + } + return false; +} + +/*virtual*/ std::string LLXUIParser::getCurrentElementName() +{ + std::string full_name; + for (name_stack_t::iterator it = mNameStack.begin(); + it != mNameStack.end(); + ++it) + { + full_name += it->first + "."; // build up dotted names: "button.param.nestedparam." + } + + return full_name; +} + +void LLXUIParser::parserWarning(const std::string& message) +{ +#ifdef LL_WINDOWS + // use Visual Studio friendly formatting of output message for easy access to originating xml + LL_INFOS() << llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()) << LL_ENDL; +#else + Parser::parserWarning(message); +#endif +} + +void LLXUIParser::parserError(const std::string& message) +{ +#ifdef LL_WINDOWS + // use Visual Studio friendly formatting of output message for easy access to originating xml + LL_INFOS() << llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()) << LL_ENDL; +#else + Parser::parserError(message); +#endif +} + + +// +// LLSimpleXUIParser +// + +struct ScopedFile +{ + ScopedFile( const std::string& filename, const char* accessmode ) + { + mFile = LLFile::fopen(filename, accessmode); + } + + ~ScopedFile() + { + fclose(mFile); + mFile = NULL; + } + + S32 getRemainingBytes() + { + if (!isOpen()) return 0; + + S32 cur_pos = ftell(mFile); + fseek(mFile, 0L, SEEK_END); + S32 file_size = ftell(mFile); + fseek(mFile, cur_pos, SEEK_SET); + return file_size - cur_pos; + } + + bool isOpen() { return mFile != NULL; } + + LLFILE* mFile; +}; +LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t element_cb) +: Parser(sSimpleXUIReadFuncs, sSimpleXUIWriteFuncs, sSimpleXUIInspectFuncs), + mCurReadDepth(0), + mElementCB(element_cb) +{ + if (sSimpleXUIReadFuncs.empty()) + { + registerParserFuncs(readFlag); + registerParserFuncs(readBoolValue); + registerParserFuncs(readStringValue); + registerParserFuncs(readU8Value); + registerParserFuncs(readS8Value); + registerParserFuncs(readU16Value); + registerParserFuncs(readS16Value); + registerParserFuncs(readU32Value); + registerParserFuncs(readS32Value); + registerParserFuncs(readF32Value); + registerParserFuncs(readF64Value); + registerParserFuncs(readColor4Value); + registerParserFuncs(readUIColorValue); + registerParserFuncs(readUUIDValue); + registerParserFuncs(readSDValue); + } +} + +LLSimpleXUIParser::~LLSimpleXUIParser() +{ +} + + +bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent) +{ + LLFastTimer ft(FTM_PARSE_XUI); + + mParser = XML_ParserCreate(NULL); + XML_SetUserData(mParser, this); + XML_SetElementHandler( mParser, startElementHandler, endElementHandler); + XML_SetCharacterDataHandler( mParser, characterDataHandler); + + mOutputStack.push_back(std::make_pair(&block, 0)); + mNameStack.clear(); + mCurFileName = filename; + mCurReadDepth = 0; + setParseSilently(silent); + + ScopedFile file(filename, "rb"); + if( !file.isOpen() ) + { + LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL; + XML_ParserFree( mParser ); + return false; + } + + S32 bytes_read = 0; + + S32 buffer_size = file.getRemainingBytes(); + void* buffer = XML_GetBuffer(mParser, buffer_size); + if( !buffer ) + { + LL_WARNS("ReadXUI") << "Unable to allocate XML buffer while reading file " << filename << LL_ENDL; + XML_ParserFree( mParser ); + return false; + } + + bytes_read = (S32)fread(buffer, 1, buffer_size, file.mFile); + if( bytes_read <= 0 ) + { + LL_WARNS("ReadXUI") << "Error while reading file " << filename << LL_ENDL; + XML_ParserFree( mParser ); + return false; + } + + mEmptyLeafNode.push_back(false); + + if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) ) + { + LL_WARNS("ReadXUI") << "Error while parsing file " << filename << LL_ENDL; + XML_ParserFree( mParser ); + return false; + } + + mEmptyLeafNode.pop_back(); + + XML_ParserFree( mParser ); + return true; +} + +void LLSimpleXUIParser::startElementHandler(void *userData, const char *name, const char **atts) +{ + LLSimpleXUIParser* self = reinterpret_cast(userData); + self->startElement(name, atts); +} + +void LLSimpleXUIParser::endElementHandler(void *userData, const char *name) +{ + LLSimpleXUIParser* self = reinterpret_cast(userData); + self->endElement(name); +} + +void LLSimpleXUIParser::characterDataHandler(void *userData, const char *s, int len) +{ + LLSimpleXUIParser* self = reinterpret_cast(userData); + self->characterData(s, len); +} + +void LLSimpleXUIParser::characterData(const char *s, int len) +{ + mTextContents += std::string(s, len); +} + +void LLSimpleXUIParser::startElement(const char *name, const char **atts) +{ + processText(); + + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("."); + + if (mElementCB) + { + LLInitParam::BaseBlock* blockp = mElementCB(*this, name); + if (blockp) + { + mOutputStack.push_back(std::make_pair(blockp, 0)); + } + } + + mOutputStack.back().second++; + S32 num_tokens_pushed = 0; + std::string child_name(name); + + if (mOutputStack.back().second == 1) + { // root node for this block + mScope.push_back(child_name); + } + else + { // compound attribute + if (child_name.find(".") == std::string::npos) + { + mNameStack.push_back(std::make_pair(child_name, true)); + num_tokens_pushed++; + mScope.push_back(child_name); + } + else + { + // parse out "dotted" name into individual tokens + tokenizer name_tokens(child_name, sep); + + tokenizer::iterator name_token_it = name_tokens.begin(); + if(name_token_it == name_tokens.end()) + { + return; + } + + // check for proper nesting + if(!mScope.empty() && *name_token_it != mScope.back()) + { + return; + } + + // now ignore first token + ++name_token_it; + + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push) + { + mNameStack.push_back(std::make_pair(*token_to_push, true)); + num_tokens_pushed++; + } + mScope.push_back(mNameStack.back().first); + } + } + + // parent node is not empty + mEmptyLeafNode.back() = false; + // we are empty if we have no attributes + mEmptyLeafNode.push_back(atts[0] == NULL); + + mTokenSizeStack.push_back(num_tokens_pushed); + readAttributes(atts); + +} + +void LLSimpleXUIParser::endElement(const char *name) +{ + bool has_text = processText(); + + // no text, attributes, or children + if (!has_text && mEmptyLeafNode.back()) + { + // submit this as a valueless name (even though there might be text contents we haven't seen yet) + mCurAttributeValueBegin = NO_VALUE_MARKER; + mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently); + } + + if (--mOutputStack.back().second == 0) + { + if (mOutputStack.empty()) + { + LL_ERRS("ReadXUI") << "Parameter block output stack popped while empty." << LL_ENDL; + } + mOutputStack.pop_back(); + } + + S32 num_tokens_to_pop = mTokenSizeStack.back(); + mTokenSizeStack.pop_back(); + while(num_tokens_to_pop-- > 0) + { + mNameStack.pop_back(); + } + mScope.pop_back(); + mEmptyLeafNode.pop_back(); +} + +bool LLSimpleXUIParser::readAttributes(const char **atts) +{ + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("."); + + bool any_parsed = false; + for(S32 i = 0; atts[i] && atts[i+1]; i += 2 ) + { + std::string attribute_name(atts[i]); + mCurAttributeValueBegin = atts[i+1]; + + S32 num_tokens_pushed = 0; + tokenizer name_tokens(attribute_name, sep); + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push) + { + mNameStack.push_back(std::make_pair(*token_to_push, true)); + num_tokens_pushed++; + } + + // child nodes are not necessarily valid attributes, so don't complain once we've recursed + any_parsed |= mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently); + + while(num_tokens_pushed-- > 0) + { + mNameStack.pop_back(); + } + } + return any_parsed; +} + +bool LLSimpleXUIParser::processText() +{ + if (!mTextContents.empty()) + { + LLStringUtil::trim(mTextContents); + if (!mTextContents.empty()) + { + mNameStack.push_back(std::make_pair(std::string("value"), true)); + mCurAttributeValueBegin = mTextContents.c_str(); + mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently); + mNameStack.pop_back(); + } + mTextContents.clear(); + return true; + } + return false; +} + +/*virtual*/ std::string LLSimpleXUIParser::getCurrentElementName() +{ + std::string full_name; + for (name_stack_t::iterator it = mNameStack.begin(); + it != mNameStack.end(); + ++it) + { + full_name += it->first + "."; // build up dotted names: "button.param.nestedparam." + } + + return full_name; +} + +void LLSimpleXUIParser::parserWarning(const std::string& message) +{ +#ifdef LL_WINDOWS + // use Visual Studio friendly formatting of output message for easy access to originating xml + LL_INFOS() << llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()) << LL_ENDL; +#else + Parser::parserWarning(message); +#endif +} + +void LLSimpleXUIParser::parserError(const std::string& message) +{ +#ifdef LL_WINDOWS + // use Visual Studio friendly formatting of output message for easy access to originating xml + LL_INFOS() << llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()) << LL_ENDL; +#else + Parser::parserError(message); +#endif +} + +bool LLSimpleXUIParser::readFlag(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return self.mCurAttributeValueBegin == NO_VALUE_MARKER; +} + +bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + if (!strcmp(self.mCurAttributeValueBegin, "true")) + { + *((bool*)val_ptr) = true; + return true; + } + else if (!strcmp(self.mCurAttributeValueBegin, "false")) + { + *((bool*)val_ptr) = false; + return true; + } + + return false; +} + +bool LLSimpleXUIParser::readStringValue(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + *((std::string*)val_ptr) = self.mCurAttributeValueBegin; + return true; +} + +bool LLSimpleXUIParser::readU8Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U8*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readS8Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S8*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readU16Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U16*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readS16Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S16*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readU32Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U32*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readS32Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S32*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readF32Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F32*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readF64Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F64*)val_ptr)]).full; +} + +bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + LLColor4 value; + + if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) + { + *(LLColor4*)(val_ptr) = value; + return true; + } + return false; +} + +bool LLSimpleXUIParser::readUIColorValue(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + LLColor4 value; + LLUIColor* colorp = (LLUIColor*)val_ptr; + + if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) + { + colorp->set(value); + return true; + } + return false; +} + +bool LLSimpleXUIParser::readUUIDValue(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + LLUUID temp_id; + // LLUUID::set is destructive, so use temporary value + if (temp_id.set(std::string(self.mCurAttributeValueBegin))) + { + *(LLUUID*)(val_ptr) = temp_id; + return true; + } + return false; +} + +bool LLSimpleXUIParser::readSDValue(Parser& parser, void* val_ptr) +{ + LLSimpleXUIParser& self = static_cast(parser); + *((LLSD*)val_ptr) = LLSD(self.mCurAttributeValueBegin); + return true; +} diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h new file mode 100644 index 000000000..ad2a39cab --- /dev/null +++ b/indra/llui/llxuiparser.h @@ -0,0 +1,254 @@ +/** + * @file llxuiparser.h + * @brief Utility functions for handling XUI structures in XML + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLXUIPARSER_H +#define LLXUIPARSER_H + +#include "llinitparam.h" +#include "llregistry.h" +#include "llxmlnode.h" + +#include +#include +#include +#include + +class LLView; + +// lookup widget type by name +class LLWidgetTypeRegistry +: public LLRegistrySingleton +{}; + + +// global static instance for registering all widget types +typedef boost::function LLWidgetCreatorFunc; + +typedef LLRegistry widget_registry_t; + +class LLChildRegistryRegistry +: public LLRegistrySingleton +{}; + +class LLXSDWriter : public LLInitParam::Parser +{ + LOG_CLASS(LLXSDWriter); +public: + void writeXSD(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); + + /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } + + LLXSDWriter(); + ~LLXSDWriter(); + +protected: + void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector* possible_values); + void addAttributeToSchema(LLXMLNodePtr nodep, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector* possible_values); + LLXMLNodePtr mAttributeNode; + LLXMLNodePtr mElementNode; + LLXMLNodePtr mSchemaNode; + + typedef std::set string_set_t; + typedef std::map attributes_map_t; + attributes_map_t mAttributesWritten; +}; + + + +// NOTE: DOES NOT WORK YET +// should support child widgets for XUI +class LLXUIXSDWriter : public LLXSDWriter +{ +public: + void writeXSD(const std::string& name, const std::string& path, const LLInitParam::BaseBlock& block); +}; + + +class LLXUIParserImpl; + +class LLXUIParser : public LLInitParam::Parser +{ +LOG_CLASS(LLXUIParser); + +public: + LLXUIParser(); + typedef LLInitParam::Parser::name_stack_t name_stack_t; + + /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ void parserWarning(const std::string& message); + /*virtual*/ void parserError(const std::string& message); + + void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename = LLStringUtil::null, bool silent=false); + template + void writeXUI(LLXMLNodePtr node, + const BLOCK& block, + const LLInitParam::predicate_rule_t rules = LLInitParam::default_parse_rules(), + const LLInitParam::BaseBlock* diff_block = NULL) + { + if (!diff_block + && !rules.isAmbivalent(LLInitParam::HAS_DEFAULT_VALUE)) + { + diff_block = &LLInitParam::defaultValue(); + } + writeXUIImpl(node, block, rules, diff_block); + } + +private: + LLXUIParser(const LLXUIParser& other); // no-copy + void writeXUIImpl(LLXMLNodePtr node, + const LLInitParam::BaseBlock& block, + const LLInitParam::predicate_rule_t rules, + const LLInitParam::BaseBlock* diff_block); + bool readXUIImpl(LLXMLNodePtr node, LLInitParam::BaseBlock& block); + bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block); + + //reader helper functions + static bool readFlag(Parser& parser, void* val_ptr); + static bool readBoolValue(Parser& parser, void* val_ptr); + static bool readStringValue(Parser& parser, void* val_ptr); + static bool readU8Value(Parser& parser, void* val_ptr); + static bool readS8Value(Parser& parser, void* val_ptr); + static bool readU16Value(Parser& parser, void* val_ptr); + static bool readS16Value(Parser& parser, void* val_ptr); + static bool readU32Value(Parser& parser, void* val_ptr); + static bool readS32Value(Parser& parser, void* val_ptr); + static bool readF32Value(Parser& parser, void* val_ptr); + static bool readF64Value(Parser& parser, void* val_ptr); + static bool readVector3Value(Parser& parser, void* val_ptr); + static bool readColor4Value(Parser& parser, void* val_ptr); + static bool readUIColorValue(Parser& parser, void* val_ptr); + static bool readUUIDValue(Parser& parser, void* val_ptr); + static bool readSDValue(Parser& parser, void* val_ptr); + + //writer helper functions + static bool writeFlag(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeStringValue(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeU8Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeS8Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeU16Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeS16Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeU32Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeS32Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeF32Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeF64Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t&); + static bool writeSDValue(Parser& parser, const void* val_ptr, name_stack_t&); + + LLXMLNodePtr getNode(name_stack_t& stack); + +private: + Parser::name_stack_t mNameStack; + LLXMLNodePtr mCurReadNode; + // Root of the widget XML sub-tree, for example, "line_editor" + LLXMLNodePtr mWriteRootNode; + + typedef std::map out_nodes_t; + out_nodes_t mOutNodes; + LLXMLNodePtr mLastWrittenChild; + S32 mCurReadDepth; + std::string mCurFileName; + std::string mRootNodeName; +}; + +// LLSimpleXUIParser is a streamlined SAX-based XUI parser that does not support localization +// or parsing of a tree of independent param blocks, such as child widgets. +// Use this for reading non-localized files that only need a single param block as a result. +// +// NOTE: In order to support nested block parsing, we need callbacks for start element that +// push new blocks contexts on the mScope stack. +// NOTE: To support localization without building a DOM, we need to enforce consistent +// ordering of child elements from base file to localized diff file. Then we can use a pair +// of coroutines to perform matching of xml nodes during parsing. Not sure if the overhead +// of coroutines would offset the gain from SAX parsing +class LLSimpleXUIParserImpl; + +class LLSimpleXUIParser : public LLInitParam::Parser +{ +LOG_CLASS(LLSimpleXUIParser); +public: + typedef LLInitParam::Parser::name_stack_t name_stack_t; + typedef LLInitParam::BaseBlock* (*element_start_callback_t)(LLSimpleXUIParser&, const char* block_name); + + LLSimpleXUIParser(element_start_callback_t element_cb = NULL); + virtual ~LLSimpleXUIParser(); + + /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ void parserWarning(const std::string& message); + /*virtual*/ void parserError(const std::string& message); + + bool readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent=false); + + +private: + //reader helper functions + static bool readFlag(Parser&, void* val_ptr); + static bool readBoolValue(Parser&, void* val_ptr); + static bool readStringValue(Parser&, void* val_ptr); + static bool readU8Value(Parser&, void* val_ptr); + static bool readS8Value(Parser&, void* val_ptr); + static bool readU16Value(Parser&, void* val_ptr); + static bool readS16Value(Parser&, void* val_ptr); + static bool readU32Value(Parser&, void* val_ptr); + static bool readS32Value(Parser&, void* val_ptr); + static bool readF32Value(Parser&, void* val_ptr); + static bool readF64Value(Parser&, void* val_ptr); + static bool readColor4Value(Parser&, void* val_ptr); + static bool readUIColorValue(Parser&, void* val_ptr); + static bool readUUIDValue(Parser&, void* val_ptr); + static bool readSDValue(Parser&, void* val_ptr); + +private: + static void startElementHandler(void *userData, const char *name, const char **atts); + static void endElementHandler(void *userData, const char *name); + static void characterDataHandler(void *userData, const char *s, int len); + + void startElement(const char *name, const char **atts); + void endElement(const char *name); + void characterData(const char *s, int len); + bool readAttributes(const char **atts); + bool processText(); + + Parser::name_stack_t mNameStack; + struct XML_ParserStruct* mParser; + LLXMLNodePtr mLastWrittenChild; + S32 mCurReadDepth; + std::string mCurFileName; + std::string mTextContents; + const char* mCurAttributeValueBegin; + std::vector mTokenSizeStack; + std::vector mScope; + std::vector mEmptyLeafNode; + element_start_callback_t mElementCB; + + std::vector > mOutputStack; +}; + + +#endif //LLXUIPARSER_H diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 6611e74e3..bdfd161cd 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -259,7 +259,7 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child) return FALSE; } -void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child) +void LLXMLNode::addChild(LLXMLNodePtr& new_child, LLXMLNodePtr after_child) { if (new_child->mParent != NULL) { @@ -343,8 +343,9 @@ LLXMLNodePtr LLXMLNode::createChild(const char* name, BOOL is_attribute) // virtual LLXMLNodePtr LLXMLNode::createChild(LLStringTableEntry* name, BOOL is_attribute) { - LLXMLNode* ret = new LLXMLNode(name, is_attribute); + LLXMLNodePtr ret(new LLXMLNode(name, is_attribute)); ret->mID.clear(); + addChild(ret); return ret; } @@ -358,11 +359,12 @@ BOOL LLXMLNode::deleteChild(LLXMLNode *child) return FALSE; } -void LLXMLNode::setParent(LLXMLNodePtr new_parent) +void LLXMLNode::setParent(LLXMLNodePtr& new_parent) { if (new_parent.notNull()) { - new_parent->addChild(this); + LLXMLNodePtr this_ptr(this); + new_parent->addChild(this_ptr); } else { @@ -968,6 +970,12 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root, return true; } +// static +void LLXMLNode::writeHeaderToFile(LLFILE *out_file) +{ + fprintf(out_file, "\n"); +} + void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent, bool use_type_decorations) { if (isFullyDefault()) @@ -1233,7 +1241,8 @@ void LLXMLNode::scrubToTree(LLXMLNode *tree) std::vector::iterator itor3; for (itor3=to_delete_list.begin(); itor3!=to_delete_list.end(); ++itor3) { - (*itor3)->setParent(NULL); + LLXMLNodePtr ptr; + (*itor3)->setParent(ptr); } } } @@ -1384,7 +1393,7 @@ BOOL LLXMLNode::getAttributeU8(const char* name, U8& value ) BOOL LLXMLNode::getAttributeS8(const char* name, S8& value ) { LLXMLNodePtr node; - S32 val; + S32 val = 0; if (!(getAttribute(name, node) && node->getIntValue(1, &val))) { return false; @@ -1396,7 +1405,7 @@ BOOL LLXMLNode::getAttributeS8(const char* name, S8& value ) BOOL LLXMLNode::getAttributeU16(const char* name, U16& value ) { LLXMLNodePtr node; - U32 val; + U32 val = 0; if (!(getAttribute(name, node) && node->getUnsignedValue(1, &val))) { return false; @@ -1408,7 +1417,7 @@ BOOL LLXMLNode::getAttributeU16(const char* name, U16& value ) BOOL LLXMLNode::getAttributeS16(const char* name, S16& value ) { LLXMLNodePtr node; - S32 val; + S32 val = 0; if (!(getAttribute(name, node) && node->getIntValue(1, &val))) { return false; @@ -2781,7 +2790,8 @@ void LLXMLNode::setName(LLStringTableEntry* name) mName = name; if (old_parent) { - old_parent->addChild(this); + LLXMLNodePtr this_ptr(this); + old_parent->addChild(this_ptr); } } diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h index 5898375e9..b9eb429ff 100644 --- a/indra/llxml/llxmlnode.h +++ b/indra/llxml/llxmlnode.h @@ -50,7 +50,6 @@ #include "llstringtable.h" #include "llfile.h" - class LLVector3; class LLVector3d; class LLQuaternion; @@ -133,8 +132,8 @@ public: BOOL isNull(); BOOL deleteChild(LLXMLNode* child); - void addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child = LLXMLNodePtr(NULL)); - void setParent(LLXMLNodePtr new_parent); // reparent if necessary + void addChild(LLXMLNodePtr& new_child, LLXMLNodePtr after_child = LLXMLNodePtr(NULL)); + void setParent(LLXMLNodePtr& new_parent); // reparent if necessary // Serialization static bool parseFile( @@ -157,6 +156,11 @@ public: static bool getLayeredXMLNode(LLXMLNodePtr& root, const std::vector& paths); + + // Write standard XML file header: + // + static void writeHeaderToFile(LLFILE *out_file); + // Write XML to file with one attribute per line. // XML escapes values as they are written. void writeToFile(LLFILE *out_file, const std::string& indent = std::string(), bool use_type_decorations=true); @@ -325,7 +329,11 @@ public: protected: LLStringTableEntry *mName; // The name of this node - std::string mValue; // The value of this node (use getters/setters only) + + // The value of this node (use getters/setters only) + // Values are not XML-escaped in memory + // They may contain " (quot) ' (apos) & (amp) < (lt) > (gt) + std::string mValue; LLXMLNodePtr mDefault; // Mirror node in the default tree diff --git a/indra/newview/app_settings/keys.ini b/indra/newview/app_settings/keys.ini deleted file mode 100644 index 50594923b..000000000 --- a/indra/newview/app_settings/keys.ini +++ /dev/null @@ -1,387 +0,0 @@ -# keys.ini -# -# keyboard binding initialization -# -# comments must have # in the first column -# blank lines OK -# -# Format: -# mode key mask function -# -# mode must be one of FIRST_PERSON, THIRD_PERSON, EDIT, EDIT_AVATAR, or CONVERSATION -# key must be upper case, or SPACE, HOME, END, PGUP, PGDN, LEFT, RIGHT, UP, DOWN, -# or one of ,.;'[] -# mask must be NONE, SHIFT, ALT, ALT_SHIFT. -# Control is reserved for user commands. -# function must be a function named in llkeyboard.cpp - -FIRST_PERSON A NONE slide_left -FIRST_PERSON D NONE slide_right -FIRST_PERSON W NONE push_forward -FIRST_PERSON S NONE push_backward -FIRST_PERSON E NONE jump -FIRST_PERSON C NONE push_down -FIRST_PERSON F NONE toggle_fly - -FIRST_PERSON LEFT NONE slide_left -FIRST_PERSON RIGHT NONE slide_right -FIRST_PERSON UP NONE push_forward -FIRST_PERSON DOWN NONE push_backward -FIRST_PERSON PGUP NONE jump -FIRST_PERSON PGDN NONE push_down -FIRST_PERSON HOME NONE toggle_fly - -FIRST_PERSON PAD_LEFT NONE slide_left -FIRST_PERSON PAD_RIGHT NONE slide_right -FIRST_PERSON PAD_UP NONE push_forward -FIRST_PERSON PAD_DOWN NONE push_backward -FIRST_PERSON PAD_PGUP NONE jump -FIRST_PERSON PAD_PGDN NONE push_down -FIRST_PERSON PAD_HOME NONE toggle_fly -FIRST_PERSON PAD_CENTER NONE stop_moving -FIRST_PERSON PAD_ENTER NONE start_chat -FIRST_PERSON PAD_DIVIDE NONE start_gesture - -FIRST_PERSON A SHIFT slide_left -FIRST_PERSON D SHIFT slide_right -FIRST_PERSON W SHIFT push_forward -FIRST_PERSON S SHIFT push_backward -FIRST_PERSON E SHIFT jump -FIRST_PERSON C SHIFT toggle_down -FIRST_PERSON F SHIFT toggle_fly - -FIRST_PERSON SPACE NONE stop_moving -FIRST_PERSON ENTER NONE start_chat -FIRST_PERSON DIVIDE NONE start_gesture -FIRST_PERSON / NONE start_gesture - -FIRST_PERSON LEFT SHIFT slide_left -FIRST_PERSON RIGHT SHIFT slide_right -FIRST_PERSON UP SHIFT push_forward -FIRST_PERSON DOWN SHIFT push_backward -FIRST_PERSON PGUP SHIFT jump -FIRST_PERSON PGDN SHIFT toggle_down - -FIRST_PERSON PAD_LEFT SHIFT slide_left -FIRST_PERSON PAD_RIGHT SHIFT slide_right -FIRST_PERSON PAD_UP SHIFT push_forward -FIRST_PERSON PAD_DOWN SHIFT push_backward -FIRST_PERSON PAD_PGUP SHIFT jump -FIRST_PERSON PAD_PGDN SHIFT toggle_down -FIRST_PERSON PAD_HOME SHIFT toggle_fly -FIRST_PERSON PAD_ENTER SHIFT start_chat -FIRST_PERSON PAD_DIVIDE SHIFT start_gesture - -THIRD_PERSON A NONE turn_left -THIRD_PERSON D NONE turn_right -THIRD_PERSON A SHIFT slide_left -THIRD_PERSON D SHIFT slide_right -THIRD_PERSON W NONE push_forward -THIRD_PERSON S NONE push_backward -THIRD_PERSON W SHIFT push_forward -THIRD_PERSON S SHIFT push_backward -THIRD_PERSON E NONE jump -THIRD_PERSON C NONE push_down -THIRD_PERSON E SHIFT jump -THIRD_PERSON C SHIFT toggle_down - -THIRD_PERSON F NONE toggle_fly -THIRD_PERSON F SHIFT toggle_fly - -THIRD_PERSON SPACE NONE stop_moving -THIRD_PERSON ENTER NONE start_chat -THIRD_PERSON DIVIDE NONE start_gesture -THIRD_PERSON / NONE start_gesture - -THIRD_PERSON LEFT NONE turn_left -THIRD_PERSON LEFT SHIFT slide_left -THIRD_PERSON RIGHT NONE turn_right -THIRD_PERSON RIGHT SHIFT slide_right -THIRD_PERSON UP NONE push_forward -THIRD_PERSON DOWN NONE push_backward -THIRD_PERSON UP SHIFT push_forward -THIRD_PERSON DOWN SHIFT push_backward -THIRD_PERSON PGUP NONE jump -THIRD_PERSON PGDN NONE push_down -THIRD_PERSON PGUP SHIFT jump -THIRD_PERSON PGDN SHIFT toggle_down -THIRD_PERSON HOME SHIFT toggle_fly -THIRD_PERSON HOME NONE toggle_fly - -THIRD_PERSON PAD_LEFT NONE turn_left -THIRD_PERSON PAD_LEFT SHIFT slide_left -THIRD_PERSON PAD_RIGHT NONE turn_right -THIRD_PERSON PAD_RIGHT SHIFT slide_right -THIRD_PERSON PAD_UP NONE push_forward -THIRD_PERSON PAD_DOWN NONE push_backward -THIRD_PERSON PAD_UP SHIFT push_forward -THIRD_PERSON PAD_DOWN SHIFT push_backward -THIRD_PERSON PAD_PGUP NONE jump -THIRD_PERSON PAD_PGDN NONE push_down -THIRD_PERSON PAD_PGUP SHIFT jump -THIRD_PERSON PAD_PGDN SHIFT toggle_down -THIRD_PERSON PAD_HOME NONE toggle_fly -THIRD_PERSON PAD_HOME SHIFT toggle_fly -THIRD_PERSON PAD_CENTER NONE stop_moving -THIRD_PERSON PAD_CENTER SHIFT stop_moving -THIRD_PERSON PAD_ENTER NONE start_chat -THIRD_PERSON PAD_ENTER SHIFT start_chat -THIRD_PERSON PAD_DIVIDE NONE start_gesture -THIRD_PERSON PAD_DIVIDE SHIFT start_gesture - -# Camera controls in third person on Alt -THIRD_PERSON LEFT ALT spin_around_cw -THIRD_PERSON RIGHT ALT spin_around_ccw -THIRD_PERSON UP ALT move_forward -THIRD_PERSON DOWN ALT move_backward -THIRD_PERSON PGUP ALT spin_over -THIRD_PERSON PGDN ALT spin_under - -THIRD_PERSON A ALT spin_around_cw -THIRD_PERSON D ALT spin_around_ccw -THIRD_PERSON W ALT move_forward -THIRD_PERSON S ALT move_backward -THIRD_PERSON E ALT spin_over -THIRD_PERSON C ALT spin_under - -THIRD_PERSON PAD_LEFT ALT spin_around_cw -THIRD_PERSON PAD_RIGHT ALT spin_around_ccw -THIRD_PERSON PAD_UP ALT move_forward -THIRD_PERSON PAD_DOWN ALT move_backward -THIRD_PERSON PAD_PGUP ALT spin_over -THIRD_PERSON PAD_PGDN ALT spin_under -THIRD_PERSON PAD_ENTER ALT start_chat -THIRD_PERSON PAD_DIVIDE ALT start_gesture - -# mimic alt zoom behavior with keyboard only -THIRD_PERSON A CTL_ALT spin_around_cw -THIRD_PERSON D CTL_ALT spin_around_ccw -THIRD_PERSON W CTL_ALT spin_over -THIRD_PERSON S CTL_ALT spin_under -THIRD_PERSON E CTL_ALT spin_over -THIRD_PERSON C CTL_ALT spin_under - -THIRD_PERSON LEFT CTL_ALT spin_around_cw -THIRD_PERSON RIGHT CTL_ALT spin_around_ccw -THIRD_PERSON UP CTL_ALT spin_over -THIRD_PERSON DOWN CTL_ALT spin_under -THIRD_PERSON PGUP CTL_ALT spin_over -THIRD_PERSON PGDN CTL_ALT spin_under - -THIRD_PERSON PAD_LEFT CTL_ALT spin_around_cw -THIRD_PERSON PAD_RIGHT CTL_ALT spin_around_ccw -THIRD_PERSON PAD_UP CTL_ALT spin_over -THIRD_PERSON PAD_DOWN CTL_ALT spin_under -THIRD_PERSON PAD_PGUP CTL_ALT spin_over -THIRD_PERSON PAD_PGDN CTL_ALT spin_under -THIRD_PERSON PAD_ENTER CTL_ALT start_chat -THIRD_PERSON PAD_DIVIDE CTL_ALT start_gesture - -# Therefore pan on Alt-Shift -THIRD_PERSON A CTL_ALT_SHIFT pan_left -THIRD_PERSON D CTL_ALT_SHIFT pan_right -THIRD_PERSON W CTL_ALT_SHIFT pan_up -THIRD_PERSON S CTL_ALT_SHIFT pan_down -THIRD_PERSON E CTL_ALT_SHIFT pan_in -THIRD_PERSON C CTL_ALT_SHIFT pan_out - -THIRD_PERSON LEFT CTL_ALT_SHIFT pan_left -THIRD_PERSON RIGHT CTL_ALT_SHIFT pan_right -THIRD_PERSON UP CTL_ALT_SHIFT pan_up -THIRD_PERSON DOWN CTL_ALT_SHIFT pan_down -THIRD_PERSON PGUP CTL_ALT_SHIFT pan_in -THIRD_PERSON PGDN CTL_ALT_SHIFT pan_out - -THIRD_PERSON PAD_LEFT CTL_ALT_SHIFT pan_left -THIRD_PERSON PAD_RIGHT CTL_ALT_SHIFT pan_right -THIRD_PERSON PAD_UP CTL_ALT_SHIFT pan_up -THIRD_PERSON PAD_DOWN CTL_ALT_SHIFT pan_down -THIRD_PERSON PAD_PGUP CTL_ALT_SHIFT pan_in -THIRD_PERSON PAD_PGDN CTL_ALT_SHIFT pan_out -THIRD_PERSON PAD_ENTER CTL_ALT_SHIFT start_chat -THIRD_PERSON PAD_DIVIDE CTL_ALT_SHIFT start_gesture - -# Basic editing camera control -EDIT A NONE spin_around_cw -EDIT D NONE spin_around_ccw -EDIT W NONE move_forward -EDIT S NONE move_backward -EDIT E NONE spin_over -EDIT C NONE spin_under -EDIT ENTER NONE start_chat -EDIT DIVIDE NONE start_gesture -EDIT / NONE start_gesture -EDIT PAD_ENTER NONE start_chat -EDIT PAD_DIVIDE NONE start_gesture - -EDIT LEFT NONE spin_around_cw -EDIT RIGHT NONE spin_around_ccw -EDIT UP NONE move_forward -EDIT DOWN NONE move_backward -EDIT PGUP NONE spin_over -EDIT PGDN NONE spin_under - -EDIT A SHIFT pan_left -EDIT D SHIFT pan_right -EDIT W SHIFT pan_up -EDIT S SHIFT pan_down - -EDIT LEFT SHIFT pan_left -EDIT RIGHT SHIFT pan_right -EDIT UP SHIFT pan_up -EDIT DOWN SHIFT pan_down - -# Walking works with ALT held down. -EDIT A ALT slide_left -EDIT D ALT slide_right -EDIT W ALT push_forward -EDIT S ALT push_backward -EDIT E ALT jump -EDIT C ALT push_down - -EDIT LEFT ALT slide_left -EDIT RIGHT ALT slide_right -EDIT UP ALT push_forward -EDIT DOWN ALT push_backward -EDIT PGUP ALT jump -EDIT PGDN ALT push_down -EDIT HOME ALT toggle_fly - -EDIT PAD_LEFT ALT slide_left -EDIT PAD_RIGHT ALT slide_right -EDIT PAD_UP ALT push_forward -EDIT PAD_DOWN ALT push_backward -EDIT PAD_PGUP ALT jump -EDIT PAD_PGDN ALT push_down -EDIT PAD_ENTER ALT start_chat -EDIT PAD_DIVIDE ALT start_gesture - -SITTING A ALT spin_around_cw -SITTING D ALT spin_around_ccw -SITTING W ALT move_forward -SITTING S ALT move_backward -SITTING E ALT spin_over_sitting -SITTING C ALT spin_under_sitting - -SITTING LEFT ALT spin_around_cw -SITTING RIGHT ALT spin_around_ccw -SITTING UP ALT move_forward -SITTING DOWN ALT move_backward -SITTING PGUP ALT spin_over -SITTING PGDN ALT spin_under - -SITTING A CTL_ALT spin_around_cw -SITTING D CTL_ALT spin_around_ccw -SITTING W CTL_ALT spin_over -SITTING S CTL_ALT spin_under -SITTING E CTL_ALT spin_over -SITTING C CTL_ALT spin_under - -SITTING LEFT CTL_ALT spin_around_cw -SITTING RIGHT CTL_ALT spin_around_ccw -SITTING UP CTL_ALT spin_over -SITTING DOWN CTL_ALT spin_under -SITTING PGUP CTL_ALT spin_over -SITTING PGDN CTL_ALT spin_under - - -SITTING A NONE spin_around_cw_sitting -SITTING D NONE spin_around_ccw_sitting -SITTING W NONE move_forward_sitting -SITTING S NONE move_backward_sitting -SITTING E NONE spin_over_sitting -SITTING C NONE spin_under_sitting - -SITTING LEFT NONE spin_around_cw_sitting -SITTING RIGHT NONE spin_around_ccw_sitting -SITTING UP NONE move_forward_sitting -SITTING DOWN NONE move_backward_sitting -SITTING PGUP NONE spin_over_sitting -SITTING PGDN NONE spin_under_sitting - -SITTING PAD_LEFT NONE spin_around_cw_sitting -SITTING PAD_RIGHT NONE spin_around_ccw_sitting -SITTING PAD_UP NONE move_forward_sitting -SITTING PAD_DOWN NONE move_backward_sitting -SITTING PAD_PGUP NONE spin_over_sitting -SITTING PAD_PGDN NONE spin_under_sitting -SITTING PAD_CENTER NONE stop_moving -SITTING PAD_ENTER NONE start_chat -SITTING PAD_DIVIDE NONE start_gesture - -# these are for passing controls when sitting on vehicles -SITTING A SHIFT slide_left -SITTING D SHIFT slide_right -SITTING W SHIFT move_forward_sitting -SITTING S SHIFT move_backward_sitting -SITTING E SHIFT spin_over_sitting -SITTING C SHIFT spin_under_sitting - -SITTING LEFT SHIFT slide_left -SITTING RIGHT SHIFT slide_right -SITTING UP SHIFT move_forward_sitting -SITTING DOWN SHIFT move_backward_sitting -SITTING PGUP SHIFT spin_over_sitting -SITTING PGDN SHIFT spin_under_sitting - -SITTING PAD_LEFT SHIFT slide_left -SITTING PAD_RIGHT SHIFT slide_right -SITTING PAD_UP SHIFT move_forward_sitting -SITTING PAD_DOWN SHIFT move_backward_sitting -SITTING PAD_PGUP SHIFT spin_over_sitting -SITTING PAD_PGDN SHIFT spin_under_sitting -SITTING PAD_ENTER SHIFT start_chat -SITTING PAD_DIVIDE SHIFT start_gesture - -# pan on Alt-Shift -SITTING A CTL_ALT_SHIFT pan_left -SITTING D CTL_ALT_SHIFT pan_right -SITTING W CTL_ALT_SHIFT pan_up -SITTING S CTL_ALT_SHIFT pan_down -SITTING E CTL_ALT_SHIFT pan_in -SITTING C CTL_ALT_SHIFT pan_out - -SITTING LEFT CTL_ALT_SHIFT pan_left -SITTING RIGHT CTL_ALT_SHIFT pan_right -SITTING UP CTL_ALT_SHIFT pan_up -SITTING DOWN CTL_ALT_SHIFT pan_down -SITTING PGUP CTL_ALT_SHIFT pan_in -SITTING PGDN CTL_ALT_SHIFT pan_out - -SITTING PAD_LEFT CTL_ALT_SHIFT pan_left -SITTING PAD_RIGHT CTL_ALT_SHIFT pan_right -SITTING PAD_UP CTL_ALT_SHIFT pan_up -SITTING PAD_DOWN CTL_ALT_SHIFT pan_down -SITTING PAD_PGUP CTL_ALT_SHIFT pan_in -SITTING PAD_PGDN CTL_ALT_SHIFT pan_out -SITTING PAD_ENTER CTL_ALT_SHIFT start_chat -SITTING PAD_DIVIDE CTL_ALT_SHIFT start_gesture - -SITTING ENTER NONE start_chat -SITTING DIVIDE NONE start_gesture -SITTING / NONE start_gesture - -# Avatar editing camera controls -EDIT_AVATAR A NONE edit_avatar_spin_cw -EDIT_AVATAR D NONE edit_avatar_spin_ccw -EDIT_AVATAR W NONE edit_avatar_move_forward -EDIT_AVATAR S NONE edit_avatar_move_backward -EDIT_AVATAR E NONE edit_avatar_spin_over -EDIT_AVATAR C NONE edit_avatar_spin_under -EDIT_AVATAR LEFT NONE edit_avatar_spin_cw -EDIT_AVATAR RIGHT NONE edit_avatar_spin_ccw -EDIT_AVATAR UP NONE edit_avatar_move_forward -EDIT_AVATAR DOWN NONE edit_avatar_move_backward -EDIT_AVATAR PGUP NONE edit_avatar_spin_over -EDIT_AVATAR PGDN NONE edit_avatar_spin_under -EDIT_AVATAR ENTER NONE start_chat -EDIT_AVATAR DIVIDE NONE start_gesture -EDIT_AVATAR / NONE start_gesture -EDIT_AVATAR PAD_LEFT NONE edit_avatar_spin_cw -EDIT_AVATAR PAD_RIGHT NONE edit_avatar_spin_ccw -EDIT_AVATAR PAD_UP NONE edit_avatar_move_forward -EDIT_AVATAR PAD_DOWN NONE edit_avatar_move_backward -EDIT_AVATAR PAD_PGUP NONE edit_avatar_spin_over -EDIT_AVATAR PAD_PGDN NONE edit_avatar_spin_under -EDIT_AVATAR PAD_ENTER NONE start_chat -EDIT_AVATAR PAD_DIVIDE NONE start_gesture diff --git a/indra/newview/app_settings/keys.xml b/indra/newview/app_settings/keys.xml new file mode 100644 index 000000000..cb7546aec --- /dev/null +++ b/indra/newview/app_settings/keys.xml @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/indra/newview/app_settings/keysZQSD.ini b/indra/newview/app_settings/keysZQSD.ini deleted file mode 100644 index fd3d4805b..000000000 --- a/indra/newview/app_settings/keysZQSD.ini +++ /dev/null @@ -1,387 +0,0 @@ -# keys.ini -# -# keyboard binding initialization -# -# comments must have # in the first column -# blank lines OK -# -# Format: -# mode key mask function -# -# mode must be one of FIRST_PERSON, THIRD_PERSON, EDIT, EDIT_AVATAR, or CONVERSATION -# key must be upper case, or SPACE, HOME, END, PGUP, PGDN, LEFT, RIGHT, UP, DOWN, -# or one of ,.;'[] -# mask must be NONE, SHIFT, ALT, ALT_SHIFT. -# Control is reserved for user commands. -# function must be a function named in llkeyboard.cpp - -FIRST_PERSON Q NONE slide_left -FIRST_PERSON D NONE slide_right -FIRST_PERSON Z NONE push_forward -FIRST_PERSON S NONE push_backward -FIRST_PERSON E NONE jump -FIRST_PERSON C NONE push_down -FIRST_PERSON F NONE toggle_fly - -FIRST_PERSON LEFT NONE slide_left -FIRST_PERSON RIGHT NONE slide_right -FIRST_PERSON UP NONE push_forward -FIRST_PERSON DOWN NONE push_backward -FIRST_PERSON PGUP NONE jump -FIRST_PERSON PGDN NONE push_down -FIRST_PERSON HOME NONE toggle_fly - -FIRST_PERSON PAD_LEFT NONE slide_left -FIRST_PERSON PAD_RIGHT NONE slide_right -FIRST_PERSON PAD_UP NONE push_forward -FIRST_PERSON PAD_DOWN NONE push_backward -FIRST_PERSON PAD_PGUP NONE jump -FIRST_PERSON PAD_PGDN NONE push_down -FIRST_PERSON PAD_HOME NONE toggle_fly -FIRST_PERSON PAD_CENTER NONE stop_moving -FIRST_PERSON PAD_ENTER NONE start_chat -FIRST_PERSON PAD_DIVIDE NONE start_gesture - -FIRST_PERSON Q SHIFT slide_left -FIRST_PERSON D SHIFT slide_right -FIRST_PERSON Z SHIFT push_forward -FIRST_PERSON S SHIFT push_backward -FIRST_PERSON E SHIFT jump -FIRST_PERSON C SHIFT toggle_down -FIRST_PERSON F SHIFT toggle_fly - -FIRST_PERSON SPACE NONE stop_moving -FIRST_PERSON ENTER NONE start_chat -FIRST_PERSON DIVIDE NONE start_gesture -FIRST_PERSON / NONE start_gesture - -FIRST_PERSON LEFT SHIFT slide_left -FIRST_PERSON RIGHT SHIFT slide_right -FIRST_PERSON UP SHIFT push_forward -FIRST_PERSON DOWN SHIFT push_backward -FIRST_PERSON PGUP SHIFT jump -FIRST_PERSON PGDN SHIFT toggle_down - -FIRST_PERSON PAD_LEFT SHIFT slide_left -FIRST_PERSON PAD_RIGHT SHIFT slide_right -FIRST_PERSON PAD_UP SHIFT push_forward -FIRST_PERSON PAD_DOWN SHIFT push_backward -FIRST_PERSON PAD_PGUP SHIFT jump -FIRST_PERSON PAD_PGDN SHIFT toggle_down -FIRST_PERSON PAD_HOME SHIFT toggle_fly -FIRST_PERSON PAD_ENTER SHIFT start_chat -FIRST_PERSON PAD_DIVIDE SHIFT start_gesture - -THIRD_PERSON Q NONE turn_left -THIRD_PERSON D NONE turn_right -THIRD_PERSON Q SHIFT slide_left -THIRD_PERSON D SHIFT slide_right -THIRD_PERSON Z NONE push_forward -THIRD_PERSON S NONE push_backward -THIRD_PERSON Z SHIFT push_forward -THIRD_PERSON S SHIFT push_backward -THIRD_PERSON E NONE jump -THIRD_PERSON C NONE push_down -THIRD_PERSON E SHIFT jump -THIRD_PERSON C SHIFT toggle_down - -THIRD_PERSON F NONE toggle_fly -THIRD_PERSON F SHIFT toggle_fly - -THIRD_PERSON SPACE NONE stop_moving -THIRD_PERSON ENTER NONE start_chat -THIRD_PERSON DIVIDE NONE start_gesture -THIRD_PERSON / NONE start_gesture - -THIRD_PERSON LEFT NONE turn_left -THIRD_PERSON LEFT SHIFT slide_left -THIRD_PERSON RIGHT NONE turn_right -THIRD_PERSON RIGHT SHIFT slide_right -THIRD_PERSON UP NONE push_forward -THIRD_PERSON DOWN NONE push_backward -THIRD_PERSON UP SHIFT push_forward -THIRD_PERSON DOWN SHIFT push_backward -THIRD_PERSON PGUP NONE jump -THIRD_PERSON PGDN NONE push_down -THIRD_PERSON PGUP SHIFT jump -THIRD_PERSON PGDN SHIFT toggle_down -THIRD_PERSON HOME SHIFT toggle_fly -THIRD_PERSON HOME NONE toggle_fly - -THIRD_PERSON PAD_LEFT NONE turn_left -THIRD_PERSON PAD_LEFT SHIFT slide_left -THIRD_PERSON PAD_RIGHT NONE turn_right -THIRD_PERSON PAD_RIGHT SHIFT slide_right -THIRD_PERSON PAD_UP NONE push_forward -THIRD_PERSON PAD_DOWN NONE push_backward -THIRD_PERSON PAD_UP SHIFT push_forward -THIRD_PERSON PAD_DOWN SHIFT push_backward -THIRD_PERSON PAD_PGUP NONE jump -THIRD_PERSON PAD_PGDN NONE push_down -THIRD_PERSON PAD_PGUP SHIFT jump -THIRD_PERSON PAD_PGDN SHIFT toggle_down -THIRD_PERSON PAD_HOME NONE toggle_fly -THIRD_PERSON PAD_HOME SHIFT toggle_fly -THIRD_PERSON PAD_CENTER NONE stop_moving -THIRD_PERSON PAD_CENTER SHIFT stop_moving -THIRD_PERSON PAD_ENTER NONE start_chat -THIRD_PERSON PAD_ENTER SHIFT start_chat -THIRD_PERSON PAD_DIVIDE NONE start_gesture -THIRD_PERSON PAD_DIVIDE SHIFT start_gesture - -# Camera controls in third person on Alt -THIRD_PERSON LEFT ALT spin_around_cw -THIRD_PERSON RIGHT ALT spin_around_ccw -THIRD_PERSON UP ALT move_forward -THIRD_PERSON DOWN ALT move_backward -THIRD_PERSON PGUP ALT spin_over -THIRD_PERSON PGDN ALT spin_under - -THIRD_PERSON Q ALT spin_around_cw -THIRD_PERSON D ALT spin_around_ccw -THIRD_PERSON Z ALT move_forward -THIRD_PERSON S ALT move_backward -THIRD_PERSON E ALT spin_over -THIRD_PERSON C ALT spin_under - -THIRD_PERSON PAD_LEFT ALT spin_around_cw -THIRD_PERSON PAD_RIGHT ALT spin_around_ccw -THIRD_PERSON PAD_UP ALT move_forward -THIRD_PERSON PAD_DOWN ALT move_backward -THIRD_PERSON PAD_PGUP ALT spin_over -THIRD_PERSON PAD_PGDN ALT spin_under -THIRD_PERSON PAD_ENTER ALT start_chat -THIRD_PERSON PAD_DIVIDE ALT start_gesture - -# mimic alt zoom behavior with keyboard only -THIRD_PERSON Q CTL_ALT spin_around_cw -THIRD_PERSON D CTL_ALT spin_around_ccw -THIRD_PERSON Z CTL_ALT spin_over -THIRD_PERSON S CTL_ALT spin_under -THIRD_PERSON E CTL_ALT spin_over -THIRD_PERSON C CTL_ALT spin_under - -THIRD_PERSON LEFT CTL_ALT spin_around_cw -THIRD_PERSON RIGHT CTL_ALT spin_around_ccw -THIRD_PERSON UP CTL_ALT spin_over -THIRD_PERSON DOWN CTL_ALT spin_under -THIRD_PERSON PGUP CTL_ALT spin_over -THIRD_PERSON PGDN CTL_ALT spin_under - -THIRD_PERSON PAD_LEFT CTL_ALT spin_around_cw -THIRD_PERSON PAD_RIGHT CTL_ALT spin_around_ccw -THIRD_PERSON PAD_UP CTL_ALT spin_over -THIRD_PERSON PAD_DOWN CTL_ALT spin_under -THIRD_PERSON PAD_PGUP CTL_ALT spin_over -THIRD_PERSON PAD_PGDN CTL_ALT spin_under -THIRD_PERSON PAD_ENTER CTL_ALT start_chat -THIRD_PERSON PAD_DIVIDE CTL_ALT start_gesture - -# Therefore pan on Alt-Shift -THIRD_PERSON Q CTL_ALT_SHIFT pan_left -THIRD_PERSON D CTL_ALT_SHIFT pan_right -THIRD_PERSON Z CTL_ALT_SHIFT pan_up -THIRD_PERSON S CTL_ALT_SHIFT pan_down -THIRD_PERSON E CTL_ALT_SHIFT pan_in -THIRD_PERSON C CTL_ALT_SHIFT pan_out - -THIRD_PERSON LEFT CTL_ALT_SHIFT pan_left -THIRD_PERSON RIGHT CTL_ALT_SHIFT pan_right -THIRD_PERSON UP CTL_ALT_SHIFT pan_up -THIRD_PERSON DOWN CTL_ALT_SHIFT pan_down -THIRD_PERSON PGUP CTL_ALT_SHIFT pan_in -THIRD_PERSON PGDN CTL_ALT_SHIFT pan_out - -THIRD_PERSON PAD_LEFT CTL_ALT_SHIFT pan_left -THIRD_PERSON PAD_RIGHT CTL_ALT_SHIFT pan_right -THIRD_PERSON PAD_UP CTL_ALT_SHIFT pan_up -THIRD_PERSON PAD_DOWN CTL_ALT_SHIFT pan_down -THIRD_PERSON PAD_PGUP CTL_ALT_SHIFT pan_in -THIRD_PERSON PAD_PGDN CTL_ALT_SHIFT pan_out -THIRD_PERSON PAD_ENTER CTL_ALT_SHIFT start_chat -THIRD_PERSON PAD_DIVIDE CTL_ALT_SHIFT start_gesture - -# Basic editing camera control -EDIT Q NONE spin_around_cw -EDIT D NONE spin_around_ccw -EDIT Z NONE move_forward -EDIT S NONE move_backward -EDIT E NONE spin_over -EDIT C NONE spin_under -EDIT ENTER NONE start_chat -EDIT DIVIDE NONE start_gesture -EDIT / NONE start_gesture -EDIT PAD_ENTER NONE start_chat -EDIT PAD_DIVIDE NONE start_gesture - -EDIT LEFT NONE spin_around_cw -EDIT RIGHT NONE spin_around_ccw -EDIT UP NONE move_forward -EDIT DOWN NONE move_backward -EDIT PGUP NONE spin_over -EDIT PGDN NONE spin_under - -EDIT Q SHIFT pan_left -EDIT D SHIFT pan_right -EDIT Z SHIFT pan_up -EDIT S SHIFT pan_down - -EDIT LEFT SHIFT pan_left -EDIT RIGHT SHIFT pan_right -EDIT UP SHIFT pan_up -EDIT DOWN SHIFT pan_down - -# Walking works with ALT held down. -EDIT Q ALT slide_left -EDIT D ALT slide_right -EDIT Z ALT push_forward -EDIT S ALT push_backward -EDIT E ALT jump -EDIT C ALT push_down - -EDIT LEFT ALT slide_left -EDIT RIGHT ALT slide_right -EDIT UP ALT push_forward -EDIT DOWN ALT push_backward -EDIT PGUP ALT jump -EDIT PGDN ALT push_down -EDIT HOME ALT toggle_fly - -EDIT PAD_LEFT ALT slide_left -EDIT PAD_RIGHT ALT slide_right -EDIT PAD_UP ALT push_forward -EDIT PAD_DOWN ALT push_backward -EDIT PAD_PGUP ALT jump -EDIT PAD_PGDN ALT push_down -EDIT PAD_ENTER ALT start_chat -EDIT PAD_DIVIDE ALT start_gesture - -SITTING Q ALT spin_around_cw -SITTING D ALT spin_around_ccw -SITTING Z ALT move_forward -SITTING S ALT move_backward -SITTING E ALT spin_over_sitting -SITTING C ALT spin_under_sitting - -SITTING LEFT ALT spin_around_cw -SITTING RIGHT ALT spin_around_ccw -SITTING UP ALT move_forward -SITTING DOWN ALT move_backward -SITTING PGUP ALT spin_over -SITTING PGDN ALT spin_under - -SITTING Q CTL_ALT spin_around_cw -SITTING D CTL_ALT spin_around_ccw -SITTING Z CTL_ALT spin_over -SITTING S CTL_ALT spin_under -SITTING E CTL_ALT spin_over -SITTING C CTL_ALT spin_under - -SITTING LEFT CTL_ALT spin_around_cw -SITTING RIGHT CTL_ALT spin_around_ccw -SITTING UP CTL_ALT spin_over -SITTING DOWN CTL_ALT spin_under -SITTING PGUP CTL_ALT spin_over -SITTING PGDN CTL_ALT spin_under - - -SITTING Q NONE spin_around_cw_sitting -SITTING D NONE spin_around_ccw_sitting -SITTING Z NONE move_forward_sitting -SITTING S NONE move_backward_sitting -SITTING E NONE spin_over_sitting -SITTING C NONE spin_under_sitting - -SITTING LEFT NONE spin_around_cw_sitting -SITTING RIGHT NONE spin_around_ccw_sitting -SITTING UP NONE move_forward_sitting -SITTING DOWN NONE move_backward_sitting -SITTING PGUP NONE spin_over_sitting -SITTING PGDN NONE spin_under_sitting - -SITTING PAD_LEFT NONE spin_around_cw_sitting -SITTING PAD_RIGHT NONE spin_around_ccw_sitting -SITTING PAD_UP NONE move_forward_sitting -SITTING PAD_DOWN NONE move_backward_sitting -SITTING PAD_PGUP NONE spin_over_sitting -SITTING PAD_PGDN NONE spin_under_sitting -SITTING PAD_CENTER NONE stop_moving -SITTING PAD_ENTER NONE start_chat -SITTING PAD_DIVIDE NONE start_gesture - -# these are for passing controls when sitting on vehicles -SITTING Q SHIFT slide_left -SITTING D SHIFT slide_right -SITTING Z SHIFT move_forward_sitting -SITTING S SHIFT move_backward_sitting -SITTING E SHIFT spin_over_sitting -SITTING C SHIFT spin_under_sitting - -SITTING LEFT SHIFT slide_left -SITTING RIGHT SHIFT slide_right -SITTING UP SHIFT move_forward_sitting -SITTING DOWN SHIFT move_backward_sitting -SITTING PGUP SHIFT spin_over_sitting -SITTING PGDN SHIFT spin_under_sitting - -SITTING PAD_LEFT SHIFT slide_left -SITTING PAD_RIGHT SHIFT slide_right -SITTING PAD_UP SHIFT move_forward_sitting -SITTING PAD_DOWN SHIFT move_backward_sitting -SITTING PAD_PGUP SHIFT spin_over_sitting -SITTING PAD_PGDN SHIFT spin_under_sitting -SITTING PAD_ENTER SHIFT start_chat -SITTING PAD_DIVIDE SHIFT start_gesture - -# pan on Alt-Shift -SITTING Q CTL_ALT_SHIFT pan_left -SITTING D CTL_ALT_SHIFT pan_right -SITTING Z CTL_ALT_SHIFT pan_up -SITTING S CTL_ALT_SHIFT pan_down -SITTING E CTL_ALT_SHIFT pan_in -SITTING C CTL_ALT_SHIFT pan_out - -SITTING LEFT CTL_ALT_SHIFT pan_left -SITTING RIGHT CTL_ALT_SHIFT pan_right -SITTING UP CTL_ALT_SHIFT pan_up -SITTING DOWN CTL_ALT_SHIFT pan_down -SITTING PGUP CTL_ALT_SHIFT pan_in -SITTING PGDN CTL_ALT_SHIFT pan_out - -SITTING PAD_LEFT CTL_ALT_SHIFT pan_left -SITTING PAD_RIGHT CTL_ALT_SHIFT pan_right -SITTING PAD_UP CTL_ALT_SHIFT pan_up -SITTING PAD_DOWN CTL_ALT_SHIFT pan_down -SITTING PAD_PGUP CTL_ALT_SHIFT pan_in -SITTING PAD_PGDN CTL_ALT_SHIFT pan_out -SITTING PAD_ENTER CTL_ALT_SHIFT start_chat -SITTING PAD_DIVIDE CTL_ALT_SHIFT start_gesture - -SITTING ENTER NONE start_chat -SITTING DIVIDE NONE start_gesture -SITTING / NONE start_gesture - -# Avatar editing camera controls -EDIT_AVATAR Q NONE edit_avatar_spin_cw -EDIT_AVATAR D NONE edit_avatar_spin_ccw -EDIT_AVATAR Z NONE edit_avatar_move_forward -EDIT_AVATAR S NONE edit_avatar_move_backward -EDIT_AVATAR E NONE edit_avatar_spin_over -EDIT_AVATAR C NONE edit_avatar_spin_under -EDIT_AVATAR LEFT NONE edit_avatar_spin_cw -EDIT_AVATAR RIGHT NONE edit_avatar_spin_ccw -EDIT_AVATAR UP NONE edit_avatar_move_forward -EDIT_AVATAR DOWN NONE edit_avatar_move_backward -EDIT_AVATAR PGUP NONE edit_avatar_spin_over -EDIT_AVATAR PGDN NONE edit_avatar_spin_under -EDIT_AVATAR ENTER NONE start_chat -EDIT_AVATAR DIVIDE NONE start_gesture -EDIT_AVATAR / NONE start_gesture -EDIT_AVATAR PAD_LEFT NONE edit_avatar_spin_cw -EDIT_AVATAR PAD_RIGHT NONE edit_avatar_spin_ccw -EDIT_AVATAR PAD_UP NONE edit_avatar_move_forward -EDIT_AVATAR PAD_DOWN NONE edit_avatar_move_backward -EDIT_AVATAR PAD_PGUP NONE edit_avatar_spin_over -EDIT_AVATAR PAD_PGDN NONE edit_avatar_spin_under -EDIT_AVATAR PAD_ENTER NONE start_chat -EDIT_AVATAR PAD_DIVIDE NONE start_gesture diff --git a/indra/newview/app_settings/keysZQSD.xml b/indra/newview/app_settings/keysZQSD.xml new file mode 100644 index 000000000..c75b935b2 --- /dev/null +++ b/indra/newview/app_settings/keysZQSD.xml @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 302ed7481..f3fd2e5d3 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -592,13 +592,32 @@ public: void load_default_bindings(bool zqsd) { gViewerKeyboard.unloadBindings(); - const std::string keys(zqsd ? "keysZQSD.ini" : "keys.ini"); - if (!gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, keys))) + const std::string key_bindings_file(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, zqsd ? "keysZQSD.xml" : "keys.xml")); + if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerKeyboard.loadBindingsXML(key_bindings_file)) { - LL_ERRS("InitInfo") << "Unable to open " << keys << LL_ENDL; + const std::string key_bindings_file(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, zqsd ? "keysZQSD.ini" : "keys.ini")); + if (!gViewerKeyboard.loadBindings(key_bindings_file)) + { + LL_ERRS("InitInfo") << "Unable to open " << key_bindings_file << LL_ENDL; + } } // Load Custom bindings (override defaults) - gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"custom_keys.ini")); + std::string custom_keys(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "custom_keys.xml")); + if (!gDirUtilp->fileExists(custom_keys) || !gViewerKeyboard.loadBindingsXML(custom_keys)) + { + custom_keys = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "custom_keys.ini"); + if (gDirUtilp->fileExists(custom_keys)) + gViewerKeyboard.loadBindings(custom_keys); + } +} + +namespace { +// With Xcode 6, _exit() is too magical to use with boost::bind(), so provide +// this little helper function. +void fast_exit(int rc) +{ + _exit(rc); +} } bool LLAppViewer::init() @@ -645,7 +664,6 @@ bool LLAppViewer::init() // // OK to write stuff to logs now, we've now crash reported if necessary // - init_default_trans_args(); if (!initConfiguration()) diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp index c7367934b..61828b493 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -88,22 +88,22 @@ namespace static LLCachedControl radar_alert_chat_range(gSavedSettings, "RadarAlertChatRange"); static LLCachedControl radar_alert_age(gSavedSettings, "RadarAlertAge"); - LLFloaterAvatarList* self = LLFloaterAvatarList::getInstance(); + LLFloaterAvatarList& inst(LLFloaterAvatarList::instance()); LLStringUtil::format_map_t args; LLChat chat; switch(type) { - case STAT_TYPE_SIM: if (radar_alert_sim) args["[RANGE]"] = self->getString("the_sim"); break; - case STAT_TYPE_DRAW: if (radar_alert_draw) args["[RANGE]"] = self->getString("draw_distance"); break; - case STAT_TYPE_SHOUTRANGE: if (radar_alert_shout_range) args["[RANGE]"] = self->getString("shout_range"); break; - case STAT_TYPE_CHATRANGE: if (radar_alert_chat_range) args["[RANGE]"] = self->getString("chat_range"); break; - case STAT_TYPE_AGE: if (radar_alert_age) chat.mText = name + " " + self->getString("has_triggered_your_avatar_age_alert") + "."; break; + case STAT_TYPE_SIM: if (radar_alert_sim) args["[RANGE]"] = inst.getString("the_sim"); break; + case STAT_TYPE_DRAW: if (radar_alert_draw) args["[RANGE]"] = inst.getString("draw_distance"); break; + case STAT_TYPE_SHOUTRANGE: if (radar_alert_shout_range) args["[RANGE]"] = inst.getString("shout_range"); break; + case STAT_TYPE_CHATRANGE: if (radar_alert_chat_range) args["[RANGE]"] = inst.getString("chat_range"); break; + case STAT_TYPE_AGE: if (radar_alert_age) chat.mText = name + " " + inst.getString("has_triggered_your_avatar_age_alert") + "."; break; default: llassert(type); break; } args["[NAME]"] = name; - args["[ACTION]"] = self->getString(entering ? "has_entered" : "has_left"); + args["[ACTION]"] = inst.getString(entering ? "has_entered" : "has_left"); if (args.find("[RANGE]") != args.end()) - chat.mText = self->getString("template", args); + chat.mText = inst.getString("template", args); else if (chat.mText.empty()) return; if (entering) // Note: If we decide to make this for leaving as well, change this check to dist != F32_MIN { @@ -138,13 +138,14 @@ LLAvatarListEntry::LLAvatarListEntry(const LLUUID& id, const std::string& name, mActivityType(ACTIVITY_NEW), mActivityTimer(), mIsInList(false), mAge(-1), mTime(time(NULL)) { - LLAvatarPropertiesProcessor::getInstance()->addObserver(mID, this); - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(mID); + LLAvatarPropertiesProcessor& inst(LLAvatarPropertiesProcessor::instance()); + inst.addObserver(mID, this); + inst.sendAvatarPropertiesRequest(mID); } LLAvatarListEntry::~LLAvatarListEntry() { - LLAvatarPropertiesProcessor::getInstance()->removeObserver(mID, this); + LLAvatarPropertiesProcessor::instance().removeObserver(mID, this); } // virtual @@ -152,7 +153,8 @@ void LLAvatarListEntry::processProperties(void* data, EAvatarProcessorType type) { if (type == APT_PROPERTIES) { - LLAvatarPropertiesProcessor::getInstance()->removeObserver(mID, this); + LLAvatarPropertiesProcessor& inst(LLAvatarPropertiesProcessor::instance()); + inst.removeObserver(mID, this); const LLAvatarData* pAvatarData = static_cast(data); if (pAvatarData && (pAvatarData->avatar_id != LLUUID::null)) { @@ -166,8 +168,8 @@ void LLAvatarListEntry::processProperties(void* data, EAvatarProcessorType type) catch(const std::exception&) { LL_WARNS() << "Failed to extract age from APT_PROPERTIES for " << mID << ", received \"" << pAvatarData->born_on << "\". Requesting properties again." << LL_ENDL; - LLAvatarPropertiesProcessor::getInstance()->addObserver(mID, this); - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(mID); + inst.addObserver(mID, this); + inst.sendAvatarPropertiesRequest(mID); return; } if (!mStats[STAT_TYPE_AGE] && mAge >= 0) //Only announce age once per entry. @@ -210,7 +212,7 @@ void LLAvatarListEntry::resetName(const bool& hide_tags, const bool& anon_names, const F32 ACTIVITY_TIMEOUT = 1.0f; void LLAvatarListEntry::setActivity(ACTIVITY_TYPE activity) { - if ( activity >= mActivityType || mActivityTimer.getElapsedTimeF32() > ACTIVITY_TIMEOUT ) + if (activity >= mActivityType || mActivityTimer.getElapsedTimeF32() > ACTIVITY_TIMEOUT) { mActivityType = activity; mActivityTimer.start(); @@ -266,20 +268,15 @@ void LLFloaterAvatarList::draw() void LLFloaterAvatarList::onOpen() { - gSavedSettings.setBOOL("ShowRadar", true); + if (mAvatars.size()) refreshAvatarList(); } void LLFloaterAvatarList::onClose(bool app_quitting) { - setVisible(false); - if (!app_quitting) - { - gSavedSettings.setBOOL("ShowRadar", false); - } - if (!gSavedSettings.getBOOL("RadarKeepOpen") || app_quitting) - { + if (app_quitting || !gSavedSettings.getBOOL("RadarKeepOpen")) destroy(); - } + else + setVisible(false); } BOOL LLFloaterAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask) @@ -414,7 +411,10 @@ BOOL LLFloaterAvatarList::postBuild() mAvatarList->setCommitCallback(boost::bind(&LLFloaterAvatarList::onSelectName,this)); mAvatarList->setDoubleClickCallback(boost::bind(&LLFloaterAvatarList::onClickFocus,this)); mAvatarList->setSortChangedCallback(boost::bind(&LLFloaterAvatarList::onAvatarSortingChanged,this)); - refreshAvatarList(); + BOOST_FOREACH(LLViewerRegion* region, LLWorld::instance().getRegionList()) + { + updateAvatarList(region); + } assessColumns(); @@ -906,8 +906,8 @@ void LLFloaterAvatarList::refreshAvatarList() agep.column = "age"; agep.type = "text"; color = sDefaultListText; - std::string age = boost::lexical_cast(entry->mAge); - if (entry->mAge > -1) + bool age_set(entry->mAge > -1); + if (age_set) { static const LLCachedControl sAvatarAgeAlertDays(gSavedSettings, "AvatarAgeAlertDays"); if ((U32)entry->mAge < sAvatarAgeAlertDays) @@ -916,11 +916,7 @@ void LLFloaterAvatarList::refreshAvatarList() color = sRadarTextYoung; } } - else - { - age = "?"; - } - agep.value = age; + agep.value = age_set ? boost::lexical_cast(entry->mAge) : "?"; agep.color = color; element.columns.add(agep); } @@ -981,7 +977,6 @@ void LLFloaterAvatarList::refreshAvatarList() mDirtyAvatarSorting = true; // LL_INFOS() << "radar refresh: done" << LL_ENDL; - } void LLFloaterAvatarList::resetAvatarNames() @@ -1042,7 +1037,7 @@ void LLFloaterAvatarList::onClickTrack() mTracking = true; mTrackedAvatar = agent_id; // trackAvatar only works for friends allowing you to see them on map... -// LLTracker::trackAvatar(agent_id, self->mAvatars[agent_id].getName()); +// LLTracker::trackAvatar(agent_id, mAvatars[agent_id].getName()); trackAvatar(getAvatarEntry(mTrackedAvatar)); } } diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 8b52de9c5..5087b89e8 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -112,7 +112,6 @@ const std::string PANEL_NAMES[LLFloaterTools::PANEL_COUNT] = // Local prototypes void commit_grid_mode(LLUICtrl *ctrl); -void commit_select_component(void *data); void click_show_more(void*); void click_popup_info(void*); void click_popup_done(void*); @@ -444,7 +443,7 @@ LLFloaterTools::LLFloaterTools() mCommitCallbackRegistrar.add("BuildTool.commitRadioEdit", boost::bind(&commit_radio_group_edit,_1)); mCommitCallbackRegistrar.add("BuildTool.gridMode", boost::bind(&commit_grid_mode,_1)); - mCommitCallbackRegistrar.add("BuildTool.selectComponent", boost::bind(&commit_select_component, this)); + mCommitCallbackRegistrar.add("BuildTool.selectComponent", boost::bind(&LLFloaterTools::commitSelectComponent, this, _2)); mCommitCallbackRegistrar.add("BuildTool.gridOptions", boost::bind(&LLFloaterTools::onClickGridOptions,this)); mCommitCallbackRegistrar.add("BuildTool.applyToSelection", boost::bind(&click_apply_to_selection, this)); mCommitCallbackRegistrar.add("BuildTool.commitRadioLand", boost::bind(&commit_radio_group_land,_1)); @@ -1155,19 +1154,14 @@ void commit_radio_group_land(LLUICtrl* ctrl) } } -void commit_select_component(void *data) +void LLFloaterTools::commitSelectComponent(bool select_individuals) { - LLFloaterTools* floaterp = (LLFloaterTools*)data; - //forfeit focus - if (gFocusMgr.childHasKeyboardFocus(floaterp)) + if (gFocusMgr.childHasKeyboardFocus(this)) { gFocusMgr.setKeyboardFocus(NULL); } - - BOOL select_individuals = floaterp->mCheckSelectIndividual->get(); - gSavedSettings.setBOOL("EditLinkedParts", select_individuals); - floaterp->dirty(); + dirty(); if (select_individuals) { diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index 73c13f558..9029ba17c 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -122,6 +122,7 @@ private: void updateMediaSettings(); static bool deleteMediaConfirm(const LLSD& notification, const LLSD& response); static bool multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response); + void commitSelectComponent(bool select_individuals); static void setObjectType( LLPCode pcode ); void onClickGridOptions(); diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 7bde0c67e..028060358 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -952,6 +952,8 @@ static void formatDateString(std::string &date_string) using namespace boost; cmatch result; const regex expression("([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})"); + try + { if (regex_match(date_string.c_str(), result, expression)) { // convert matches to integers so that we can pad them with zeroes on Linux @@ -962,6 +964,11 @@ static void formatDateString(std::string &date_string) // ISO 8601 date format date_string = llformat("%04d-%02d-%02dT00:00:00Z", year, month, day); } + } + catch(...) + { + LL_ERRS() << "Decode of non-compliant DateTime format from [GroupMembersReply.GroupData.MemberData.OnlineStatus]. Please notify grid operators of this defect." << LL_ENDL; + } } const std::string& localized_online() diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 2e12406de..48c6e7a3e 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -2257,47 +2257,6 @@ void LLPanelObject::draw() LLPanel::draw(); } -// virtual -void LLPanelObject::clearCtrls() -{ - LLPanel::clearCtrls(); - - mCheckLock ->set(FALSE); - mCheckLock ->setEnabled( FALSE ); - mCheckPhysics ->set(FALSE); - mCheckPhysics ->setEnabled( FALSE ); - mCheckTemporary ->set(FALSE); - mCheckTemporary ->setEnabled( FALSE ); - mCheckPhantom ->set(FALSE); - mCheckPhantom ->setEnabled( FALSE ); - mComboMaterial ->setEnabled( FALSE ); - mLabelMaterial ->setEnabled( FALSE ); - // Disable text labels - mLabelPosition ->setEnabled( FALSE ); - mLabelSize ->setEnabled( FALSE ); - mLabelRotation ->setEnabled( FALSE ); - mLabelBaseType ->setEnabled( FALSE ); - mLabelCut ->setEnabled( FALSE ); - mLabelHollow ->setEnabled( FALSE ); - mLabelHoleType ->setEnabled( FALSE ); - mLabelTwist ->setEnabled( FALSE ); - mLabelSkew ->setEnabled( FALSE ); - mLabelShear ->setEnabled( FALSE ); - mLabelTaper ->setEnabled( FALSE ); - mLabelRadiusOffset->setEnabled( FALSE ); - mLabelRevolutions->setEnabled( FALSE ); - - childSetVisible("select_single", FALSE); - childSetVisible("edit_object", TRUE); - childSetEnabled("edit_object", FALSE); - - childSetEnabled("scale_hole", FALSE); - childSetEnabled("scale_taper", FALSE); - childSetEnabled("advanced_cut", FALSE); - childSetEnabled("advanced_dimple", FALSE); - childSetVisible("advanced_slice", FALSE); -} - // // Static functions // diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index 675a93053..e98808747 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -63,7 +63,6 @@ public: virtual BOOL postBuild(); virtual void draw(); - virtual void clearCtrls(); void refresh(); diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index b5fade37a..ab3feb724 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -512,51 +512,6 @@ void LLPanelVolume::draw() LLPanel::draw(); } -// virtual -void LLPanelVolume::clearCtrls() -{ - LLPanel::clearCtrls(); - - getChildView("select_single")->setEnabled(false); - getChildView("select_single")->setVisible(true); - getChildView("edit_object")->setEnabled(false); - getChildView("edit_object")->setVisible(false); - getChildView("Light Checkbox Ctrl")->setEnabled(false); - getChildView("label color")->setEnabled(false); - LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); - if(LightColorSwatch) - { - LightColorSwatch->setEnabled( FALSE ); - LightColorSwatch->setValid( FALSE ); - } - childSetEnabled("label texture",false); - LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); - if(LightTextureCtrl) - { - LightTextureCtrl->setEnabled( FALSE ); - LightTextureCtrl->setValid( FALSE ); - } - - getChildView("Light Intensity")->setEnabled(false); - getChildView("Light Radius")->setEnabled(false); - getChildView("Light Falloff")->setEnabled(false); - - getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false); - getChildView("FlexNumSections")->setEnabled(false); - getChildView("FlexGravity")->setEnabled(false); - getChildView("FlexTension")->setEnabled(false); - getChildView("FlexFriction")->setEnabled(false); - getChildView("FlexWind")->setEnabled(false); - getChildView("FlexForceX")->setEnabled(false); - getChildView("FlexForceY")->setEnabled(false); - getChildView("FlexForceZ")->setEnabled(false); - - mSpinPhysicsGravity->setEnabled(FALSE); - mSpinPhysicsFriction->setEnabled(FALSE); - mSpinPhysicsDensity->setEnabled(FALSE); - mSpinPhysicsRestitution->setEnabled(FALSE); -} - // // Static functions // diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index b82fc3916..e81f43052 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -53,7 +53,6 @@ public: virtual ~LLPanelVolume(); virtual void draw(); - virtual void clearCtrls(); virtual BOOL postBuild(); diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 22ca3dd5d..9b0649070 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -45,6 +45,7 @@ #include "lltoolfocus.h" #include "llviewerwindow.h" #include "llvoavatarself.h" +#include "llxuiparser.h" void handle_reset_view(); @@ -58,7 +59,6 @@ const F32 FLY_FRAMES = 4; const F32 NUDGE_TIME = 0.25f; // in seconds const S32 NUDGE_FRAMES = 2; const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed -const F32 YAW_NUDGE_RATE = 0.05f; // fraction of normal speed struct LLKeyboardActionRegistry : public LLRegistrySingleton, LLKeyboardActionRegistry> @@ -86,6 +86,7 @@ void agent_jump( EKeystate s ) gAgent.moveUp(1); } } +// void agent_toggle_down( EKeystate s ) { if (KEYSTATE_UP == s) return; @@ -96,6 +97,7 @@ void agent_toggle_down( EKeystate s ) } gAgent.moveUp(-1); } +// void agent_push_down( EKeystate s ) { @@ -103,22 +105,29 @@ void agent_push_down( EKeystate s ) gAgent.moveUp(-1); } +static void agent_check_temporary_run(LLAgent::EDoubleTapRunMode mode) +{ +// if (gAgent.mDoubleTapRunMode == mode && +// gAgent.getRunning() && +// !gAgent.getAlwaysRun()) +// { +// // Turn off temporary running. +// gAgent.clearRunning(); +// gAgent.sendWalkRun(gAgent.getRunning()); +// } +// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i + if ( (gAgent.mDoubleTapRunMode == mode) && (gAgent.getTempRun()) ) + gAgent.clearTempRun(); +// [/RLVa:KB] +} + static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode mode) { if (KEYSTATE_UP == s) { -// if (gAgent.mDoubleTapRunMode == mode && -// gAgent.getRunning() && -// !gAgent.getAlwaysRun()) -// { -// // Turn off temporary running. -// gAgent.clearRunning(); -// gAgent.sendWalkRun(gAgent.getRunning()); -// } -// [RLVa:KB] - Checked: 2011-05-11 (RLVa-1.3.0i) | Added: RLVa-1.3.0i - if ( (gAgent.mDoubleTapRunMode == mode) && (gAgent.getTempRun()) ) - gAgent.clearTempRun(); -// [/RLVa:KB] + // Note: in case shift is already released, slide left/right run + // will be released in agent_turn_left()/agent_turn_right() + agent_check_temporary_run(mode); } else if (gSavedSettings.getBOOL("AllowTapTapHoldRun") && KEYSTATE_DOWN == s && @@ -208,7 +217,10 @@ void agent_turn_left( EKeystate s ) } else { - if (KEYSTATE_UP == s) return; + if (KEYSTATE_UP == s) + { + return; + } F32 time = gKeyboard->getCurKeyElapsedTime(); gAgent.moveYaw( LLFloaterMove::getYawRate( time ) ); } @@ -223,7 +235,10 @@ void agent_turn_right( EKeystate s ) } else { - if (KEYSTATE_UP == s) return; + if (KEYSTATE_UP == s) + { + return; + } F32 time = gKeyboard->getCurKeyElapsedTime(); gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) ); } @@ -758,6 +773,61 @@ BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, c return TRUE; } +LLViewerKeyboard::KeyBinding::KeyBinding() +: key("key"), + mask("mask"), + command("command") +{} + +LLViewerKeyboard::KeyMode::KeyMode(EKeyboardMode _mode) +: bindings("binding"), + mode(_mode) +{} + +LLViewerKeyboard::Keys::Keys() +: first_person("first_person", KeyMode(MODE_FIRST_PERSON)), + third_person("third_person", KeyMode(MODE_THIRD_PERSON)), + edit("edit", KeyMode(MODE_EDIT)), + sitting("sitting", KeyMode(MODE_SITTING)), + edit_avatar("edit_avatar", KeyMode(MODE_EDIT_AVATAR)) +{} + +S32 LLViewerKeyboard::loadBindingsXML(const std::string& filename) +{ + S32 binding_count = 0; + Keys keys; + LLSimpleXUIParser parser; + + if (parser.readXUI(filename, keys) + && keys.validateBlock()) + { + binding_count += loadBindingMode(keys.first_person); + binding_count += loadBindingMode(keys.third_person); + binding_count += loadBindingMode(keys.edit); + binding_count += loadBindingMode(keys.sitting); + binding_count += loadBindingMode(keys.edit_avatar); + } + return binding_count; +} + +S32 LLViewerKeyboard::loadBindingMode(const LLViewerKeyboard::KeyMode& keymode) +{ + S32 binding_count = 0; + for (LLInitParam::ParamIterator::const_iterator it = keymode.bindings.begin(), + end_it = keymode.bindings.end(); + it != end_it; + ++it) + { + KEY key; + MASK mask; + LLKeyboard::keyFromString(it->key, &key); + LLKeyboard::maskFromString(it->mask, &mask); + bindKey(keymode.mode, key, mask, it->command); + binding_count++; + } + + return binding_count; +} S32 LLViewerKeyboard::loadBindings(const std::string& filename) { diff --git a/indra/newview/llviewerkeyboard.h b/indra/newview/llviewerkeyboard.h index 1893b6aee..29fff6f98 100644 --- a/indra/newview/llviewerkeyboard.h +++ b/indra/newview/llviewerkeyboard.h @@ -2,31 +2,25 @@ * @file llviewerkeyboard.h * @brief LLViewerKeyboard class header file * - * $LicenseInfo:firstyear=2005&license=viewergpl$ - * - * Copyright (c) 2005-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,6 +28,7 @@ #define LL_LLVIEWERKEYBOARD_H #include "llkeyboard.h" // For EKeystate +#include "llinitparam.h" const S32 MAX_NAMED_FUNCTIONS = 100; const S32 MAX_KEY_BINDINGS = 128; // was 60 @@ -64,18 +59,48 @@ void bind_keyboard_functions(); class LLViewerKeyboard { public: + struct KeyBinding : public LLInitParam::Block + { + Mandatory key, + mask, + command; + + KeyBinding(); + }; + + struct KeyMode : public LLInitParam::Block + { + Multiple bindings; + EKeyboardMode mode; + KeyMode(EKeyboardMode mode); + }; + + struct Keys : public LLInitParam::Block + { + Optional first_person, + third_person, + edit, + sitting, + edit_avatar; + + Keys(); + }; + LLViewerKeyboard(); BOOL handleKey(KEY key, MASK mask, BOOL repeated); S32 loadBindings(const std::string& filename); // returns number bound, 0 on error + S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error void unloadBindings(); EKeyboardMode getMode(); BOOL modeFromString(const std::string& string, S32 *mode); // False on failure void scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level); -protected: + +private: + S32 loadBindingMode(const LLViewerKeyboard::KeyMode& keymode); BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name); // Hold all the ugly stuff torn out to make LLKeyboard non-viewer-specific here diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 1297f76f3..4a896285f 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -5082,14 +5082,14 @@ void LLViewerWindow::drawMouselookInstructions() LLFontGL::HCENTER, LLFontGL::TOP, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT); font->renderUTF8( - llformat("Y: %.2f", vec.mV[VX]), 0, + llformat("Y: %.2f", vec.mV[VY]), 0, text_pos_start + 100, INSTRUCTIONS_PAD, LLColor4(0.5f, 1.0f, 0.5f, 0.5), LLFontGL::HCENTER, LLFontGL::TOP, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT); font->renderUTF8( - llformat("Z: %.2f", vec.mV[VX]), 0, + llformat("Z: %.2f", vec.mV[VZ]), 0, text_pos_start + 200, INSTRUCTIONS_PAD, LLColor4(0.5f, 0.5f, 1.0f, 0.5), diff --git a/indra/newview/rlvcommon.cpp b/indra/newview/rlvcommon.cpp index f2d3ecfee..d6a6b9d3f 100644 --- a/indra/newview/rlvcommon.cpp +++ b/indra/newview/rlvcommon.cpp @@ -26,7 +26,6 @@ #include "llviewerparcelmgr.h" #include "llviewermenu.h" #include "llviewerregion.h" -#include "llviewerstats.h" #include "llworld.h" #include "rlvactions.h" diff --git a/indra/newview/rlvextensions.cpp b/indra/newview/rlvextensions.cpp index fccd0fb5e..44e581826 100644 --- a/indra/newview/rlvextensions.cpp +++ b/indra/newview/rlvextensions.cpp @@ -18,7 +18,6 @@ #include "llagent.h" #include "llagentcamera.h" #include "lldaycyclemanager.h" -#include "llviewercontrol.h" #include "llvoavatarself.h" #include "llwlparammanager.h" diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index b0320e2eb..119b4332c 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -28,6 +28,7 @@ #include "llviewerregion.h" #include "rlvhandler.h" +#include "rlvhelper.h" #include "rlvinventory.h" #include "rlvlocks.h" #include "rlvui.h" diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index e8411c989..a1a3eeb8b 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -15,15 +15,11 @@ */ #include "llviewerprecompiledheaders.h" -#include "llagent.h" -#include "llagentwearables.h" #include "llappearancemgr.h" #include "llattachmentsmgr.h" #include "llgesturemgr.h" #include "llnotificationsutil.h" -#include "llviewerobject.h" #include "llviewerobjectlist.h" -#include "llwlparammanager.h" #include "rlvhelper.h" #include "rlvhandler.h" diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h index baac7a4ae..3ca6a4f82 100644 --- a/indra/newview/rlvhelper.h +++ b/indra/newview/rlvhelper.h @@ -21,7 +21,6 @@ #include "llinventorymodel.h" #include "llviewerinventory.h" #include "llwearabletype.h" -#include "llwlparamset.h" #include "rlvdefines.h" #include "rlvcommon.h" diff --git a/indra/newview/rlvinventory.cpp b/indra/newview/rlvinventory.cpp index 6bb039360..edc0cc703 100644 --- a/indra/newview/rlvinventory.cpp +++ b/indra/newview/rlvinventory.cpp @@ -17,17 +17,10 @@ #include "llviewerprecompiledheaders.h" #include "llagent.h" #include "llappearancemgr.h" -#include "llinventoryobserver.h" #include "llstartup.h" #include "llviewerfoldertype.h" -#include "llviewerobject.h" -#include "llvoavatarself.h" -#include "rlvdefines.h" -#include "rlvcommon.h" -#include "rlvlocks.h" #include "rlvinventory.h" -#include "rlvhandler.h" #include "boost/algorithm/string.hpp" diff --git a/indra/newview/rlvinventory.h b/indra/newview/rlvinventory.h index 682461857..90de5c73d 100644 --- a/indra/newview/rlvinventory.h +++ b/indra/newview/rlvinventory.h @@ -18,10 +18,8 @@ #define RLV_INVENTORY_H #include "llinventoryfunctions.h" -#include "llinventorymodel.h" #include "llinventoryobserver.h" #include "llsingleton.h" -#include "llviewerinventory.h" #include "rlvhelper.h" #include "rlvlocks.h" diff --git a/indra/newview/rlvlocks.cpp b/indra/newview/rlvlocks.cpp index 92c869bc2..f6b2b8ab8 100644 --- a/indra/newview/rlvlocks.cpp +++ b/indra/newview/rlvlocks.cpp @@ -18,7 +18,6 @@ #include "llagent.h" #include "llappearancemgr.h" #include "llattachmentsmgr.h" -#include "llinventoryobserver.h" #include "lloutfitobserver.h" #include "llviewerobjectlist.h" #include "pipeline.h" diff --git a/indra/newview/skins/default/xui/en-us/floater_radar.xml b/indra/newview/skins/default/xui/en-us/floater_radar.xml index 0a930677b..79a4eb07f 100644 --- a/indra/newview/skins/default/xui/en-us/floater_radar.xml +++ b/indra/newview/skins/default/xui/en-us/floater_radar.xml @@ -1,5 +1,5 @@ - Radar diff --git a/indra/newview/skins/default/xui/en-us/wlfPanel_AdvSettings_expanded.xml b/indra/newview/skins/default/xui/en-us/wlfPanel_AdvSettings_expanded.xml index 8e4c2d3f9..4f63d8917 100644 --- a/indra/newview/skins/default/xui/en-us/wlfPanel_AdvSettings_expanded.xml +++ b/indra/newview/skins/default/xui/en-us/wlfPanel_AdvSettings_expanded.xml @@ -12,7 +12,7 @@ - + diff --git a/indra/newview/wlfPanel_AdvSettings.cpp b/indra/newview/wlfPanel_AdvSettings.cpp index fa0a1b693..b105d22a2 100644 --- a/indra/newview/wlfPanel_AdvSettings.cpp +++ b/indra/newview/wlfPanel_AdvSettings.cpp @@ -222,6 +222,10 @@ BOOL wlfPanel_AdvSettings::postBuild() // Set up based on initial region. onRegionChanged(); } + else + { + mHoverHeight = NULL; + } return TRUE; } @@ -513,7 +517,7 @@ void wlfPanel_AdvSettings::updateEditHoverEnabled() { const LLViewerRegion* region = gAgent.getRegion(); bool enabled = region && region->avatarHoverHeightEnabled(); - mHoverHeight->setEnabled(enabled); + if (mHoverHeight) mHoverHeight->setEnabled(enabled); if (enabled) { syncFromPreferenceSetting(mHoverHeight);