/// ------------------------------------------------------------------------------------ /// <summary> /// Check whether this object is equal to another. /// </summary> /// <param name="obj"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ public override bool Equals(object obj) { OxesInfo that = obj as OxesInfo; if (that == null) { return(false); } else { return(this.StyleName == that.StyleName && this.m_fIsCharStyle == that.m_fIsCharStyle && this.Context == that.Context && this.XmlTag == that.XmlTag && this.AttrName == that.AttrName && this.AttrValue == that.AttrValue && this.AttrName2 == that.AttrName2 && this.AttrValue2 == that.AttrValue2 && this.CanEmbed == that.CanEmbed && this.IsHeading == that.IsHeading); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Check whether the OxesInfo object is compatible with the given context information. /// </summary> /// <param name="xinfo"></param> /// <param name="fInIntroSection"></param> /// <param name="sSectionType"></param> /// <param name="sXmlParentTag"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private static bool IsProperContextForStyle(OxesInfo xinfo, bool fInIntroSection, string sSectionType, string sXmlParentTag) { // If there's no context needed or provided, return true. if (xinfo.Context == OxesContext.Default && sXmlParentTag == null && !fInIntroSection) return true; switch (xinfo.Context) { case OxesContext.Introduction: case OxesContext.IntroSection: return fInIntroSection; case OxesContext.Embedded: return sXmlParentTag == "embedded"; case OxesContext.Speech: return sXmlParentTag == "speech"; case OxesContext.Table: return sXmlParentTag == "table"; case OxesContext.Row: return sXmlParentTag == "row"; case OxesContext.MajorSection: return sSectionType == "major"; case OxesContext.NormalSection: return sSectionType == ""; case OxesContext.MinorSection: return sSectionType == "minor"; case OxesContext.SeriesSection: return sSectionType == "series"; case OxesContext.VariantSection: return sSectionType == "variant"; case OxesContext.ListItem1: return sXmlParentTag == ScrStyleNames.ListItem1; case OxesContext.ListItem2: return sXmlParentTag == ScrStyleNames.ListItem2; case OxesContext.Book: case OxesContext.Footnote: case OxesContext.Title: break; // these don't really distinguish as far as I can tell } switch (sXmlParentTag) { case "embedded": return xinfo.Context == OxesContext.Embedded; case "speech": return xinfo.Context == OxesContext.Speech; case "table": return xinfo.Context == OxesContext.Table; case "row": return xinfo.Context == OxesContext.Row; case ScrStyleNames.ListItem1: return xinfo.Context == OxesContext.ListItem1; case ScrStyleNames.ListItem2: return xinfo.Context == OxesContext.ListItem2; case "title": case "note": break; // I don't know if these even occur. } return true; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Test whether attributes listed in the OxesInfo are compatible with those in the /// XmlNode. /// </summary> /// <param name="xinfo"></param> /// <param name="node"></param> /// <returns>true if the two objects have matching attributes, otherwise false</returns> /// ------------------------------------------------------------------------------------ private static bool AttributesMatch(OxesInfo xinfo, XmlNode node) { // First, check that everything in the OxesInfo is in the XmlNode. if (xinfo.AttrName != null) { string sValue = XmlUtils.GetOptionalAttributeValue(node, xinfo.AttrName); // If the node is "abbreviation", we need a special case here because another // abbreviation node has an expansion attribute which is not required for // the character style. if (node.Name == "abbreviation") return true; if (xinfo.AttrValue == null && sValue == null) return false; // we need a value, we don't care what it is. if (xinfo.AttrValue != null && sValue != xinfo.AttrValue) return false; // we need a specific value. } if (xinfo.AttrName2 != null) { string sValue = XmlUtils.GetOptionalAttributeValue(node, xinfo.AttrName2); if (xinfo.AttrValue2 == null && sValue == null) return false; // we need a value, we don't care what it is. else if (xinfo.AttrValue2 != null && sValue != xinfo.AttrValue2) return false; // we need a specific value. } // Now, check that attributes in the XmlNode are in the OxesInfo. foreach (XmlAttribute attr in node.Attributes) { if (attr.Name == xinfo.AttrName) { if (xinfo.AttrValue == null) continue; // any value is okay. else if (attr.Value != xinfo.AttrValue) return false; } else if (attr.Name == xinfo.AttrName2) { if (xinfo.AttrValue2 == null) continue; // any value is okay else if (attr.Value != xinfo.AttrValue2) return false; } // oxesRef is always the third attribute (not listed), // and xmlns is auto-inserted by the .Net framework code. else if (attr.Name != "oxesRef" && attr.Name != "xmlns") { return false; } } return true; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the OXES information that best matches the given XML node in the given context. /// </summary> /// <param name="node"></param> /// <param name="fInIntroSection"></param> /// <param name="sSectionType"></param> /// <param name="sXmlParentTag"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ static public OxesInfo GetOxesInfoForParaNode(XmlNode node, bool fInIntroSection, string sSectionType, string sXmlParentTag) { List <OxesInfo> rgoxes; if (TagMap.TryGetValue(node.Name, out rgoxes)) { OxesInfo xinfoMatch = null; OxesInfo xinfoSemiMatch = null; foreach (OxesInfo xinfo in rgoxes) { if (xinfo.m_fIsCharStyle) { continue; } if (!IsProperContextForStyle(xinfo, fInIntroSection, sSectionType, sXmlParentTag)) { continue; } if (!AttributesMatch(xinfo, node)) { continue; } if (fInIntroSection != (xinfo.Context == OxesContext.Introduction || xinfo.Context == OxesContext.IntroSection)) { xinfoSemiMatch = xinfo; continue; } Debug.Assert(xinfoMatch == null || xinfoMatch.Context == OxesContext.Default, "We should only get another match if its more specific"); xinfoMatch = xinfo; } if (xinfoMatch == null && xinfoSemiMatch != null) { // TODO: Log error message about misplaced style? xinfoMatch = xinfoSemiMatch; } if (xinfoMatch != null) { return(xinfoMatch); } bool isSectionHead = (node.Name == "sectionHead"); if ((node.Name == "p" && XmlUtils.GetOptionalAttributeValue(node, "type") == "userPS") || (isSectionHead && XmlUtils.GetOptionalAttributeValue(node, "type") == "userDefined")) { string sStyle = XmlUtils.GetOptionalAttributeValue(node, "subType"); if (!String.IsNullOrEmpty(sStyle)) { OxesContext context; if (isSectionHead) { context = (fInIntroSection) ? OxesContext.IntroSection : OxesContext.NormalSection; } else { context = (fInIntroSection) ? OxesContext.Introduction : OxesContext.Default; } return(new OxesInfo(false, sStyle, context, node.Name, "type", "userPS", "subType", sStyle, false, isSectionHead)); } } } // Handle oddball entries. if (node.Name == "title") { string sType = XmlUtils.GetOptionalAttributeValue(node, "type"); if (sType == "parallelPassage") { foreach (XmlNode xn in node.ChildNodes) { if (xn.Name == "reference") { return(GetOxesInfoForParaNode(xn, fInIntroSection, sSectionType, sXmlParentTag)); } } } } return(m_emptyPara); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Test whether attributes listed in the OxesInfo are compatible with those in the /// XmlNode. /// </summary> /// <param name="xinfo"></param> /// <param name="node"></param> /// <returns>true if the two objects have matching attributes, otherwise false</returns> /// ------------------------------------------------------------------------------------ private static bool AttributesMatch(OxesInfo xinfo, XmlNode node) { // First, check that everything in the OxesInfo is in the XmlNode. if (xinfo.AttrName != null) { string sValue = XmlUtils.GetOptionalAttributeValue(node, xinfo.AttrName); // If the node is "abbreviation", we need a special case here because another // abbreviation node has an expansion attribute which is not required for // the character style. if (node.Name == "abbreviation") { return(true); } if (xinfo.AttrValue == null && sValue == null) { return(false); // we need a value, we don't care what it is. } if (xinfo.AttrValue != null && sValue != xinfo.AttrValue) { return(false); // we need a specific value. } } if (xinfo.AttrName2 != null) { string sValue = XmlUtils.GetOptionalAttributeValue(node, xinfo.AttrName2); if (xinfo.AttrValue2 == null && sValue == null) { return(false); // we need a value, we don't care what it is. } else if (xinfo.AttrValue2 != null && sValue != xinfo.AttrValue2) { return(false); // we need a specific value. } } // Now, check that attributes in the XmlNode are in the OxesInfo. foreach (XmlAttribute attr in node.Attributes) { if (attr.Name == xinfo.AttrName) { if (xinfo.AttrValue == null) { continue; // any value is okay. } else if (attr.Value != xinfo.AttrValue) { return(false); } } else if (attr.Name == xinfo.AttrName2) { if (xinfo.AttrValue2 == null) { continue; // any value is okay } else if (attr.Value != xinfo.AttrValue2) { return(false); } } else if (attr.Name == "type" && attr.Value == "citation" && xinfo.AttrName2 == null) { // Let Citation Line X stuff just go to ordinary Line X styles (the Citation Line X styles were removed as part of TE-5100) continue; } // oxesRef is always the third attribute (not listed), // and xmlns is auto-inserted by the .Net framework code. else if (attr.Name != "oxesRef" && attr.Name != "xmlns") { return(false); } } return(true); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Check whether the OxesInfo object is compatible with the given context information. /// </summary> /// <param name="xinfo"></param> /// <param name="fInIntroSection"></param> /// <param name="sSectionType"></param> /// <param name="sXmlParentTag"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private static bool IsProperContextForStyle(OxesInfo xinfo, bool fInIntroSection, string sSectionType, string sXmlParentTag) { // If there's no context needed or provided, return true. if (xinfo.Context == OxesContext.Default && sXmlParentTag == null && !fInIntroSection) { return(true); } switch (xinfo.Context) { case OxesContext.Introduction: case OxesContext.IntroSection: return(fInIntroSection); case OxesContext.Embedded: return(sXmlParentTag == "embedded"); case OxesContext.Speech: return(sXmlParentTag == "speech"); case OxesContext.Table: return(sXmlParentTag == "table"); case OxesContext.Row: return(sXmlParentTag == "row"); case OxesContext.MajorSection: return(sSectionType == "major"); case OxesContext.NormalSection: return(sSectionType == ""); case OxesContext.MinorSection: return(sSectionType == "minor"); case OxesContext.SeriesSection: return(sSectionType == "series"); case OxesContext.VariantSection: return(sSectionType == "variant"); case OxesContext.ListItem1: return(sXmlParentTag == ScrStyleNames.ListItem1); case OxesContext.ListItem2: return(sXmlParentTag == ScrStyleNames.ListItem2); case OxesContext.Book: case OxesContext.Footnote: case OxesContext.Title: break; // these don't really distinguish as far as I can tell } switch (sXmlParentTag) { case "embedded": return(xinfo.Context == OxesContext.Embedded); case "speech": return(xinfo.Context == OxesContext.Speech); case "table": return(xinfo.Context == OxesContext.Table); case "row": return(xinfo.Context == OxesContext.Row); case ScrStyleNames.ListItem1: return(xinfo.Context == OxesContext.ListItem1); case ScrStyleNames.ListItem2: return(xinfo.Context == OxesContext.ListItem2); case "title": case "note": break; // I don't know if these even occur. } return(true); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Write out either a secondary or tertiary title segment as a separate <title> /// element, taking footnotes into account. /// </summary> /// <param name="dictBackTrans"></param> /// <param name="mapWsBackTransRunIndex"></param> /// <param name="mapWsStatus"></param> /// <param name="ttState"></param> /// <param name="data"></param> /// <param name="xinfo"></param> /// <param name="ws"></param> /// <param name="ttWant"></param> /// <param name="fExportAnnotation"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private TitleType WriteSubtitle(Dictionary<int, ITsString> dictBackTrans, Dictionary<int, int> mapWsBackTransRunIndex, Dictionary<int, string> mapWsStatus, TitleType ttState, string data, OxesInfo xinfo, int ws, TitleType ttWant, ref bool fExportAnnotation) { if (ttState != ttWant) { if (ttState != TitleType.kttNone) m_writer.WriteEndElement(); // </title> m_writer.WriteStartElement(xinfo.XmlTag); m_writer.WriteAttributeString(xinfo.AttrName, xinfo.AttrValue); if (fExportAnnotation) { ExportAnyRelatedAnnotation(); fExportAnnotation = false; } } OpenTrGroupIfNeeded(); OpenTranslationElementIfNeeded(); bool fForeign = MarkForeignIfNeeded(m_cache.DefaultVernWs, ws); m_writer.WriteString(data); if (fForeign) m_writer.WriteEndElement(); // </foreign> CloseTranslationElementIfNeeded(); WriteTitleBackTrans(mapWsStatus, dictBackTrans, mapWsBackTransRunIndex, ttWant); CloseTrGroupIfNeeded(); return ttWant; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Many header paragraphs need special handling. Some are handled completely by this /// method. /// </summary> /// <param name="para"></param> /// <param name="styleName"></param> /// <param name="xinfo"></param> /// <param name="backtran"></param> /// <param name="rgBTSeg">list of segments for a segmented back translation</param> /// <returns>true iff the paragraph is completely exported by this method</returns> /// ------------------------------------------------------------------------------------ private bool HandleHeaderParagraph(IStTxtPara para, string styleName, OxesInfo xinfo, BackTranslationInfo backtran, List<BTSegment> rgBTSeg) { if (xinfo.IsHeading) { if (styleName == ScrStyleNames.MainBookTitle) { bool fExportAnnotation = false; ExportTitleParagraph(para, backtran, ref fExportAnnotation); return true; } else if (styleName == ScrStyleNames.ParallelPassageReference) { // necessary markup is table driven return false; } else if (m_fInSectionHeader && styleName != ScrStyleNames.SpeechSpeaker) { // The XML markup for these styles are handled by the caller. ExportParagraphData(para.Contents, rgBTSeg); return true; } } return false; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Open any nesting elements (such as <embedded> or <speech>) that are /// required by the context. /// </summary> /// <param name="para"></param> /// <param name="styleName"></param> /// <param name="xinfo"></param> /// <returns>true if opening an element is all that should be done</returns> /// ------------------------------------------------------------------------------------ private bool OpenNestingElementsAsNeeded(IStTxtPara para, string styleName, OxesInfo xinfo) { switch (xinfo.Context) { case OxesContext.Embedded: StartEmbeddingIfNeeded(); return false; case OxesContext.Table: Debug.Assert(styleName == ScrStyleNames.TableRow); StartTableRow(); if (para.Contents.Length > 0) { // REVIEW: warn user?? } return true; // this style is not supposed to have any content! case OxesContext.Row: StartTableAndRowIfNeeded(); return false; case OxesContext.Speech: StartSpeechIfNeeded(); return false; default: return false; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Close any open nesting elements (such as <embedded> or <speech>) that /// are no longer required by the context. /// </summary> /// <param name="styleName"></param> /// <param name="xinfo"></param> /// ------------------------------------------------------------------------------------ private void CloseNestingElementsAsNeeded(string styleName, OxesInfo xinfo) { if (m_stackTableElements.Count > 0 && !InFootnote && xinfo.Context != OxesContext.Table && xinfo.Context != OxesContext.Row) { FinishTable(); } if (m_fListItem1Open && !InFootnote && styleName != ScrStyleNames.ListItem1Additional) { m_writer.WriteEndElement(); // </item> m_fListItem1Open = false; } if (m_fListItem2Open && !InFootnote && styleName != ScrStyleNames.ListItem2Additional) { m_writer.WriteEndElement(); // </item> m_fListItem2Open = false; } if (m_fEmbedded && !InFootnote && xinfo.Context != OxesContext.Embedded) { m_writer.WriteEndElement(); // </embedded> m_fEmbedded = false; } if (m_fInSpeech && !InFootnote && xinfo.Context != OxesContext.Speech) { m_writer.WriteEndElement(); // </speech> m_fInSpeech = false; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Create the given style if it doesn't already exist in the style sheet. /// </summary> /// <param name="xinfo">The OXES info.</param> /// <param name="fParaStyle">if set to <c>true</c> [f para style].</param> /// ------------------------------------------------------------------------------------ private void CreateCustomStyleIfNeeded(OxesInfo xinfo, bool fParaStyle) { string sCustom = xinfo.StyleName; if (String.IsNullOrEmpty(sCustom)) return; IStStyle sty = m_styleSheet.FindStyle(sCustom); if (sty == null) { Debug.WriteLine(String.Format("Creating {0} style \"{1}\"", fParaStyle ? "paragraph" : "character", sCustom)); IStStyle newStyle = new StStyle(m_cache, m_styleSheet.MakeNewStyle()); newStyle.Name = sCustom; if (fParaStyle) { newStyle.Type = StyleType.kstParagraph; switch (xinfo.Context) { case OxesContext.IntroSection: newStyle.BasedOnRA = m_styleSheet.FindStyle(ScrStyleNames.IntroSectionHead); break; case OxesContext.Introduction: newStyle.BasedOnRA = m_styleSheet.FindStyle(ScrStyleNames.IntroParagraph); break; case OxesContext.NormalSection: newStyle.BasedOnRA = m_styleSheet.FindStyle(ScrStyleNames.SectionHead); break; default: newStyle.BasedOnRA = m_styleSheet.FindStyle(ScrStyleNames.NormalParagraph); break; } } else { newStyle.Type = StyleType.kstCharacter; } string sUsage = String.Format(TeResourceHelper.GetResourceString("kstidStyleFromImport"), m_sOXESFile); m_styleSheet.PutStyle(sCustom, sUsage, newStyle.Hvo, newStyle.BasedOnRAHvo, newStyle.Hvo, (int)newStyle.Type, false, false, null); sty = m_styleSheet.FindStyle(sCustom); Debug.Assert(sty != null); } }