NS_IMETHODIMP nsStyledElement::SetInlineStyleRule(nsICSSStyleRule* aStyleRule, PRBool aNotify) { SetFlags(NODE_MAY_HAVE_STYLE); PRBool modification = PR_FALSE; nsAutoString oldValueStr; PRBool hasListeners = aNotify && nsContentUtils::HasMutationListeners(this, NS_EVENT_BITS_MUTATION_ATTRMODIFIED, this); // There's no point in comparing the stylerule pointers since we're always // getting a new stylerule here. And we can't compare the stringvalues of // the old and the new rules since both will point to the same declaration // and thus will be the same. if (hasListeners) { // save the old attribute so we can set up the mutation event properly // XXXbz if the old rule points to the same declaration as the new one, // this is getting the new attr value, not the old one.... modification = GetAttr(kNameSpaceID_None, nsGkAtoms::style, oldValueStr); } else if (aNotify && IsInDoc()) { modification = !!mAttrsAndChildren.GetAttr(nsGkAtoms::style); } nsAttrValue attrValue(aStyleRule); return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nsnull, oldValueStr, attrValue, modification, hasListeners, aNotify, nsnull); }
// Loads this context from the given properties map. The names of all the fields are assumed to be prefixed // with the given string. module::context::context(properties::iterator props, std::string prefix) { int numCfgKeys = properties::getInt(props, txt()<<prefix<<"numCfgKeys"); for(int i=0; i<numCfgKeys; i++) { configuration[properties::get(props, txt()<<prefix<<"key_"<<i)] = attrValue(properties::get(props, txt()<<prefix<<"val_"<<i), attrValue::unknownT); //(attrValue::valueType)properties::getInt(props, txt()<<prefix<<"type_"<<i)); } }
Stone SgfTree::move() { Point p = attrValue("B").toPoint(); if ( ! p.isNull()) { return Stone(cBlack, p); } else { p = attrValue("W").toPoint(); if ( ! p.isNull() ) { return Stone(cWhite, p); } else { return Stone::null(); } } }
NS_IMETHODIMP nsStyledElementNotElementCSSInlineStyle::SetInlineStyleRule(css::StyleRule* aStyleRule, const nsAString* aSerialized, bool aNotify) { SetMayHaveStyle(); bool modification = false; nsAttrValue oldValue; bool hasListeners = aNotify && nsContentUtils::HasMutationListeners(this, NS_EVENT_BITS_MUTATION_ATTRMODIFIED, this); // There's no point in comparing the stylerule pointers since we're always // getting a new stylerule here. And we can't compare the stringvalues of // the old and the new rules since both will point to the same declaration // and thus will be the same. if (hasListeners) { // save the old attribute so we can set up the mutation event properly // XXXbz if the old rule points to the same declaration as the new one, // this is getting the new attr value, not the old one.... nsAutoString oldValueStr; modification = GetAttr(kNameSpaceID_None, nsGkAtoms::style, oldValueStr); if (modification) { oldValue.SetTo(oldValueStr); } } else if (aNotify && IsInDoc()) { modification = !!mAttrsAndChildren.GetAttr(nsGkAtoms::style); } nsAttrValue attrValue(aStyleRule, aSerialized); // XXXbz do we ever end up with ADDITION here? I doubt it. PRUint8 modType = modification ? static_cast<PRUint8>(nsIDOMMutationEvent::MODIFICATION) : static_cast<PRUint8>(nsIDOMMutationEvent::ADDITION); return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nsnull, oldValue, attrValue, modType, hasListeners, aNotify, kDontCallAfterSetAttr); }
// Overloaded version of createAssetTag that provides the ability to specify // user defined values for child elements within asset tags void daeWriter::createAssetTag(const osg::Node &node) { domAsset *asset = daeSafeCast<domAsset>(dom->add(COLLADA_ELEMENT_ASSET)); domAsset::domCreated *c = daeSafeCast<domAsset::domCreated>(asset->add("created")); domAsset::domModified *m = daeSafeCast<domAsset::domModified>(asset->add("modified")); domAsset::domUnit *u = daeSafeCast<domAsset::domUnit>(asset->add("unit")); domAsset::domUp_axis *up_axis = daeSafeCast<domAsset::domUp_axis>(asset->add("up_axis")); domAsset::domContributor *contributor = daeSafeCast<domAsset::domContributor>(asset->add("contributor")); // set date and time // Generate the date like this // "YYYY-mm-ddTHH:MM:SSZ" ISO 8601 Date Time format const size_t bufSize = 1024; static char dateStamp[bufSize]; time_t rawTime = time(NULL); struct tm *timeInfo = localtime(&rawTime); strftime(dateStamp, sizeof(dateStamp), "%Y-%m-%dT%H:%M:%SZ", timeInfo); // set up fallback defaults c->setValue(dateStamp); m->setValue(dateStamp); u->setName("meter"); // NOTE: SketchUp incorrectly sets this to "meters" but it does not really matter. // Also note that since the default is: <unit meter="1.0" name="meter"/> this is equivalent to <unit/> u->setMeter(1.0); // this is the important units setting as it tells consuming apps how to convert to meters. up_axis->setValue(UPAXISTYPE_Z_UP); // get description info as name value pairs if (node.getDescriptions().size() % 2 == 0) { for (osg::Node::DescriptionList::const_iterator ditr = node.getDescriptions().begin(); ditr != node.getDescriptions().end(); ++ditr) { std::string attrName(*ditr); ++ditr; std::string attrValue(*ditr); if (attrName == "collada_created" && !attrValue.empty()) { c->setValue(attrValue.c_str()); } else if (attrName == "collada_modified" && !attrValue.empty()) { m->setValue(attrValue.c_str()); } else if (attrName == "collada_keywords" && !attrValue.empty()) { domAsset::domKeywords *keywords = daeSafeCast<domAsset::domKeywords>(asset->add("keywords")); keywords->setValue(attrValue.c_str()); } else if (attrName == "collada_revision" && !attrValue.empty()) { domAsset::domRevision *revision = daeSafeCast<domAsset::domRevision>(asset->add("revision")); revision->setValue(attrValue.c_str()); } else if (attrName == "collada_subject" && !attrValue.empty()) { domAsset::domSubject *subject = daeSafeCast<domAsset::domSubject>(asset->add("subject")); subject->setValue(attrValue.c_str()); } else if (attrName == "collada_title" && !attrValue.empty()) { domAsset::domTitle *title = daeSafeCast<domAsset::domTitle>(asset->add("title")); title->setValue(attrValue.c_str()); } else if (attrName == "collada_up_axis" && !attrValue.empty()) { if (attrValue == "X_UP") { up_axis->setValue(UPAXISTYPE_X_UP); } else if (attrValue == "Y_UP") { up_axis->setValue(UPAXISTYPE_Y_UP); } else { up_axis->setValue(UPAXISTYPE_Z_UP); // default } } else if (attrName == "collada_unit_name" && !attrValue.empty()) { u->setName(attrValue.c_str()); } else if (attrName == "collada_unit_meter_length" && !attrValue.empty()) { double fValFromStr(1.0); try { std::istringstream sConversion(attrValue); sConversion >> fValFromStr; u->setMeter((domFloat)fValFromStr); } catch (...) { // TODO: handle error u->setMeter((domFloat)fValFromStr); continue; } } else if (attrName == "collada_contributor{0}.author" && !attrValue.empty()) { domAsset::domContributor::domAuthor *author = daeSafeCast<domAsset::domContributor::domAuthor>(contributor->add("author")); author->setValue(attrValue.c_str()); } else if (attrName == "collada_contributor{0}.authoring_tool" && !attrValue.empty()) { domAsset::domContributor::domAuthoring_tool *authoring_tool = daeSafeCast<domAsset::domContributor::domAuthoring_tool>(contributor->add("authoring_tool")); authoring_tool->setValue(attrValue.c_str()); } else if (attrName == "collada_contributor{0}.comments" && !attrValue.empty()) { domAsset::domContributor::domComments *comments = daeSafeCast<domAsset::domContributor::domComments>(contributor->add("comments")); comments->setValue(attrValue.c_str()); } else if (attrName == "collada_contributor{0}.source_data" && !attrValue.empty()) { domAsset::domContributor::domSource_data *source_data = daeSafeCast<domAsset::domContributor::domSource_data>(contributor->add("source_data")); source_data->setValue(attrValue.c_str()); } else if (attrName == "collada_contributor{0}.copyright" && !attrValue.empty()) { domAsset::domContributor::domCopyright *copyright = daeSafeCast<domAsset::domContributor::domCopyright>(contributor->add("copyright")); copyright->setValue(attrValue.c_str()); } // TODO: handle array of contributor data rather that just the first. // also there is probably a better way to pass attribute data as DescriptionList is a bit fragile }
//-------------------------------------------------------------- // parse a char buffer. Characters are assumed UTF-8, but this // is passed through to content and attributes. All we care // about is xml characters (<, >, =", etc.) void mgXMLScanner::parse( int len, const char* buffer) { int posn = 0; while (true) { // read a char, possibly pushed back char c; if (m_lastChar != '\0') { c = m_lastChar; m_lastChar = '\0'; } else { // if buffer empty if (posn >= len) break; c = buffer[posn++]; // track line and col nums for error messages if (c == '\n') { m_lineNum++; m_colNum = 0; } else if (c != '\r') m_colNum++; } // process against state machine switch (m_state) { case START_STATE: if (c == '<') { if (m_token.length() > 0) { content(m_token, m_token.length()); m_token.empty(); } m_state = OPEN_STATE; } else if (c == '&') { if (m_token.length() > 0) { content(m_token, m_token.length()); m_token.empty(); } m_state = AMPER_STATE; } else { if (m_token.length() > CONTENT_CHUNK_MAX) { content(m_token, m_token.length()); m_token.empty(); } m_token += c; } break; case OPEN_STATE: // '<' seen if (c == '?') m_state = PROCESS_STATE; else if (c == '!') m_state = TAGEXP_STATE; else if (c == '/') m_state = TAGCLOSE_STATE; else { m_state = TAGOPEN_STATE; m_lastChar = c; } break; case PROCESS_STATE: // <? seen if (c == '?') m_state = PROCESS_END_STATE; else m_token += c; break; case PROCESS_END_STATE: // <? ... ? seen if (c == '>') { processingInstruction(m_token); m_token.empty(); m_state = START_STATE; } else { m_token += '?'; m_lastChar = c; m_state = PROCESS_STATE; } break; case TAGEXP_STATE: // <! seen if (c == '-') m_state = TAGEXP_DASH_STATE; else if (c == '[') m_state = CDATA_OPEN_STATE; else errorMsg("xmlBadString", "string", "<!%c", c); break; case TAGEXP_DASH_STATE: // <!- seen if (c == '-') m_state = COMMENT_STATE; else errorMsg("xmlBadString", "string", "<!-%c", c); break; case COMMENT_STATE: // <!-- seen if (c == '-') m_state = COMMENT_END_STATE; else m_token += c; break; case COMMENT_END_STATE: // <!-- ... - seen if (c == '-') m_state = COMMENT_END2_STATE; else { m_token += '-'; m_lastChar = c; m_state = COMMENT_STATE; } break; case COMMENT_END2_STATE: // <!-- ... -- seen if (c == '>') { comment(m_token); m_token.empty(); m_state = START_STATE; } else { m_token += "--"; m_lastChar = c; m_state = COMMENT_STATE; } break; case CDATA_OPEN_STATE: // <![ seen if (c == 'C') m_state = CDATA_OPEN2_STATE; else errorMsg("xmlBadString", "string", "<![%c", c); break; case CDATA_OPEN2_STATE: // <![C seen if (c == 'D') m_state = CDATA_OPEN3_STATE; else errorMsg("xmlBadString", "string", "<![C%c", c); break; case CDATA_OPEN3_STATE: // <![CD seen if (c == 'A') m_state = CDATA_OPEN4_STATE; else errorMsg("xmlBadString", "string", "<![CD%c", c); break; case CDATA_OPEN4_STATE: // <![CDA seen if (c == 'T') m_state = CDATA_OPEN5_STATE; else errorMsg("xmlBadString", "string", "<![CDA%c", c); break; case CDATA_OPEN5_STATE: // <![CDAT seen if (c == 'A') m_state = CDATA_OPEN6_STATE; else errorMsg("xmlBadString", "string", "<![CDAT%c", c); break; case CDATA_OPEN6_STATE: // <![CDATA seen if (c == '[') m_state = CDATA_STATE; else errorMsg("xmlBadString", "string", "<![CDATA%c", c); break; case CDATA_STATE: // <![CDATA[ ... seen if (c == ']') m_state = CDATA_END_STATE; else { // break this into chunks if (m_token.length() > CONTENT_CHUNK_MAX) { CDATAContent(m_token, m_token.length()); m_token.empty(); } m_token += c; } break; case CDATA_END_STATE: // <![CDATA[ ... ] seen if (c == ']') m_state = CDATA_END2_STATE; else { m_state = CDATA_STATE; m_token += ']'; m_lastChar = c; } break; case CDATA_END2_STATE: // <![CDATA[ ... ]] seen if (c == '>') { CDATAContent(m_token, m_token.length()); m_token.empty(); m_state = START_STATE; } else { m_state = CDATA_STATE; m_token += "]]"; m_lastChar = c; } break; case TAGOPEN_STATE: // <x... seen if (c == '>') { tagOpen(m_token); endAttrs(); m_token.empty(); m_state = START_STATE; } else if (c == '/') { tagOpen(m_token); m_token.empty(); endAttrs(); tagNoContent(); m_state = TAGCLOSE_BLANK_STATE; } else if (isspace(c)) { tagOpen(m_token); m_token.empty(); m_state = ATTR_START_STATE; } else m_token += c; break; case TAGCLOSE_STATE: // </ seen if (c == '>') { tagClose(m_token); m_token.empty(); m_state = START_STATE; } else if (isspace(c)) { tagClose(m_token); m_token.empty(); m_state = TAGCLOSE_BLANK_STATE; } else m_token += c; break; case TAGCLOSE_BLANK_STATE: // </tag ' ' seen if (c == '>') m_state = START_STATE; else if (!isspace(c)) errorMsg("xmlBadClose", "", ""); break; case ATTR_START_STATE: // <tag ' ' seen, or attr=value seen if (c == '>') { if (m_token.length() > 0) { tagOpen(m_token); m_token.empty(); } endAttrs(); m_state = START_STATE; } else if (c == '/') { if (m_token.length() > 0) { tagOpen(m_token); m_token.empty(); } endAttrs(); tagNoContent(); m_state = TAGCLOSE_BLANK_STATE; } else if (!isspace(c)) { m_state = ATTR_NAME_STATE; m_lastChar = c; } break; case ATTR_NAME_STATE: // <tag ... 'letter' a seen if (iswalnum(c) || c == '_' || c == '.' || c == '-') m_token += c; else if (c == '=') { attrName(m_token); m_token.empty(); m_state = VALUE_START_STATE; } else if (isspace(c)) { attrName(m_token); m_token.empty(); m_state = EQUAL_START_STATE; } else errorMsg("xmlMissingEquals", "", ""); break; case EQUAL_START_STATE: if (c == '=') m_state = VALUE_START_STATE; else if (!isspace(c)) errorMsg("xmlMissingEquals", "", ""); break; case VALUE_START_STATE: if (c == '"') { m_state = VALUE_STATE; m_valueDelim = '"'; } else if (c == '\'') { m_state = VALUE_STATE; m_valueDelim = '\''; } else if (!isspace(c)) errorMsg("xmlMissingQuote", "", ""); break; case VALUE_STATE: if (c == m_valueDelim) { attrValue(m_token); m_token.empty(); m_state = ATTR_START_STATE; } else if (c == '&') m_state = VALUE_AMPER_STATE; else m_token += c; break; case VALUE_AMPER_STATE: // & seen in attribute value if (c == ';') { mgString value; entityRef(m_entityRef, value); m_token += value; m_entityRef.empty(); m_state = VALUE_STATE; } else if (isspace(c)) errorMsg("xmlMissingSemi", "", ""); else m_entityRef += c; break; case AMPER_STATE: // & seen in content if (c == ';') { mgString value; entityRef(m_entityRef, value); m_token += value; m_entityRef.empty(); m_state = START_STATE; } else if (isspace(c)) errorMsg("xmlMissingSemi", "", ""); else m_entityRef += c; break; } } }
void OXMLi_ListenerState_Textbox::startElement (OXMLi_StartElementRequest * rqst) { if(nameMatches(rqst->pName, NS_V_KEY, "shape")) { const gchar* style = attrMatches(NS_V_KEY, "style", rqst->ppAtts); if(style) { m_style = style; } rqst->handled = true; } else if(nameMatches(rqst->pName, NS_V_KEY, "textbox")) { OXML_SharedElement textboxElem(new OXML_Element_TextBox("")); if(m_style.compare("")) { //parse and apply style here std::string attrName(""); std::string attrValue(""); size_t attrStart = 0; size_t attrEnd = 0; while(attrStart < m_style.length()) { attrEnd = m_style.find(';', attrStart); if(attrEnd == std::string::npos) { //this should be the last attribute attrEnd = m_style.length(); } std::string attrNameValPair = m_style.substr(attrStart, attrEnd-attrStart); size_t seperator = attrNameValPair.find(':'); if(seperator != std::string::npos) { attrName = attrNameValPair.substr(0, seperator); attrValue = attrNameValPair.substr(seperator+1); //convert and apply attributes here if(!attrName.compare("width")) { textboxElem->setProperty("frame-width", attrValue); } else if(!attrName.compare("height")) { textboxElem->setProperty("frame-height", attrValue); } //TODO: more attributes coming } //finally update the start point for the next attribute attrStart = attrEnd+1; } } rqst->stck->push(textboxElem); rqst->handled = true; } else if(nameMatches(rqst->pName, NS_W_KEY, "txbxContent")) { rqst->handled = true; } }
void OXMLi_ListenerState_Image::startElement (OXMLi_StartElementRequest * rqst) { if(nameMatches(rqst->pName, NS_W_KEY, "object")) { // Abiword doesn't support embedded objects, enable this boolean lock when needed m_isEmbeddedObject = true; rqst->handled = true; } if(m_isEmbeddedObject) { return; } if(nameMatches(rqst->pName, NS_W_KEY, "drawing")) { OXML_SharedElement imgElem(new OXML_Element_Image("")); rqst->stck->push(imgElem); rqst->handled = true; } else if(nameMatches(rqst->pName, NS_WP_KEY, "inline")) { if(rqst->stck->empty()) { rqst->handled = false; rqst->valid = false; return; } std::string contextTag = ""; if(!rqst->context->empty()) { contextTag = rqst->context->back(); } int drawing = contextMatches(contextTag, NS_W_KEY, "drawing"); if(drawing) { m_isInlineImage = true; rqst->handled = true; } } else if(nameMatches(rqst->pName, NS_WP_KEY, "anchor")) { if(rqst->stck->empty()) { rqst->handled = false; rqst->valid = false; return; } std::string contextTag = ""; if(!rqst->context->empty()) { contextTag = rqst->context->back(); } int drawing = contextMatches(contextTag, NS_W_KEY, "drawing"); if(drawing) { m_isInlineImage = false; rqst->handled = true; } } else if(nameMatches(rqst->pName, NS_WP_KEY, "positionH")) { if(rqst->stck->empty()) { rqst->handled = false; rqst->valid = false; return; } std::string contextTag = ""; if(!rqst->context->empty()) { contextTag = rqst->context->back(); } int anchor = contextMatches(contextTag, NS_WP_KEY, "anchor"); if(anchor) { rqst->handled = true; } } else if(nameMatches(rqst->pName, NS_WP_KEY, "positionV")) { if(rqst->stck->empty()) { rqst->handled = false; rqst->valid = false; return; } std::string contextTag = ""; if(!rqst->context->empty()) { contextTag = rqst->context->back(); } int anchor = contextMatches(contextTag, NS_WP_KEY, "anchor"); if(anchor) { rqst->handled = true; } } else if(nameMatches(rqst->pName, NS_WP_KEY, "posOffset")) { if(rqst->stck->empty()) { rqst->handled = false; rqst->valid = false; return; } std::string contextTag = ""; if(!rqst->context->empty()) { contextTag = rqst->context->back(); } int positionH = contextMatches(contextTag, NS_WP_KEY, "positionH"); int positionV = contextMatches(contextTag, NS_WP_KEY, "positionV"); if(positionH || positionV) { rqst->handled = true; } } else if(nameMatches(rqst->pName, NS_WP_KEY, "extent")) { if(rqst->stck->empty()) { rqst->handled = false; rqst->valid = false; return; } OXML_SharedElement imgElem = rqst->stck->top(); if(!imgElem) return; const gchar * cx = attrMatches(NS_WP_KEY, "cx", rqst->ppAtts); //width if(cx) { std::string width(_EmusToInches(cx)); width += "in"; if(m_isInlineImage) { if(imgElem->setProperty("width", width) != UT_OK) { UT_DEBUGMSG(("SERHAT:OpenXML importer inline image width property can't be set\n")); } } else { if(imgElem->setProperty("frame-width", width) != UT_OK) { UT_DEBUGMSG(("SERHAT:OpenXML importer positioned image width property can't be set\n")); } } } const gchar * cy = attrMatches(NS_WP_KEY, "cy", rqst->ppAtts); //height if(cy) { std::string height(_EmusToInches(cy)); height += "in"; if(m_isInlineImage) { if(imgElem->setProperty("height", height) != UT_OK) { UT_DEBUGMSG(("SERHAT:OpenXML importer inline image height property can't be set\n")); } } else { if(imgElem->setProperty("frame-height", height) != UT_OK) { UT_DEBUGMSG(("SERHAT:OpenXML importer positioned image height property can't be set\n")); } } } rqst->handled = true; } else if(nameMatches(rqst->pName, NS_WP_KEY, "wrapSquare")) { if(rqst->stck->empty()) { rqst->handled = false; rqst->valid = false; return; } OXML_SharedElement imgElem = rqst->stck->top(); if(!imgElem) return; const gchar * wrapText = attrMatches(NS_WP_KEY, "wrapText", rqst->ppAtts); if(wrapText) { if(!strcmp(wrapText, "bothSides")) { if(imgElem->setProperty("wrap-mode", "wrapped-both") != UT_OK) { UT_DEBUGMSG(("SERHAT:OpenXML importer image wrap-mode property can't be set\n")); } } else if(!strcmp(wrapText, "right")) { if(imgElem->setProperty("wrap-mode", "wrapped-to-right") != UT_OK) { UT_DEBUGMSG(("SERHAT:OpenXML importer image wrap-mode property can't be set\n")); } } else if(!strcmp(wrapText, "left")) { if(imgElem->setProperty("wrap-mode", "wrapped-to-left") != UT_OK) { UT_DEBUGMSG(("SERHAT:OpenXML importer image wrap-mode property can't be set\n")); } } } rqst->handled = true; } else if (nameMatches(rqst->pName, NS_A_KEY, "blip")) { if(rqst->stck->empty()) { rqst->handled = false; rqst->valid = false; return; } OXML_SharedElement imgElem = rqst->stck->top(); if(!imgElem) return; const gchar * id = attrMatches(NS_R_KEY, "embed", rqst->ppAtts); if(id) { std::string imageId(id); imgElem->setId(id); rqst->handled = addImage(imageId); } } else if(nameMatches(rqst->pName, NS_V_KEY, "shape")) { const gchar* style = attrMatches(NS_V_KEY, "style", rqst->ppAtts); if(style) { m_style = style; } //don't handle the request here in case shape contains some other structure, ex: textbox } else if(nameMatches(rqst->pName, NS_V_KEY, "imagedata")) { const gchar* id = attrMatches(NS_R_KEY, "id", rqst->ppAtts); if(id) { std::string imageId(id); OXML_SharedElement imgElem(new OXML_Element_Image(imageId)); rqst->stck->push(imgElem); if(!addImage(imageId)) return; if(m_style.compare("")) { //parse and apply style here std::string attrName(""); std::string attrValue(""); size_t attrStart = 0; size_t attrEnd = 0; while(attrStart < m_style.length()) { attrEnd = m_style.find(';', attrStart); if(attrEnd == std::string::npos) { //this should be the last attribute attrEnd = m_style.length(); } std::string attrNameValPair = m_style.substr(attrStart, attrEnd-attrStart); size_t seperator = attrNameValPair.find(':'); if(seperator != std::string::npos) { attrName = attrNameValPair.substr(0, seperator); attrValue = attrNameValPair.substr(seperator+1); //convert and apply attributes here if(!attrName.compare("width")) { imgElem->setProperty("width", attrValue); } else if(!attrName.compare("height")) { imgElem->setProperty("height", attrValue); } //TODO: more attributes coming } //finally update the start point for the next attribute attrStart = attrEnd+1; } } rqst->handled = true; } } //TODO: more coming here }