private static void ProcessEndElement(XmlReader reader, RTFCurrentState cs, RichTextBox rtb) { switch (reader.Name) { case "b": cs.cf.dwEffects &= ~CFE.BOLD; cs.cf.wWeight = FW.NORMAL; cs.charFormatChanged = true; break; case "i": cs.cf.dwEffects &= ~CFE.ITALIC; cs.charFormatChanged = true; break; case "u": cs.cf.dwEffects &= ~CFE.UNDERLINE; cs.charFormatChanged = true; break; case "s": cs.cf.dwEffects &= ~CFE.STRIKEOUT; cs.charFormatChanged = true; break; case "sup": cs.cf.dwEffects &= ~CFE.SUPERSCRIPT; cs.charFormatChanged = true; break; case "sub": cs.cf.dwEffects &= ~CFE.SUBSCRIPT; cs.charFormatChanged = true; break; case "a": int length = rtb.TextLength - cs.hyperlinkStart; if (cs.hyperlink != null) { rtb.Select(cs.hyperlinkStart, length); if (cs.hyperlink != rtb.SelectedText) { string rtfText = rtb.SelectedRtf; int idx = rtfText.LastIndexOf('}'); if (idx != -1) { string head = rtfText.Substring(0, idx); string tail = rtfText.Substring(idx); rtb.SelectedRtf = head + @"\v #" + cs.hyperlink + @"\v0" + tail; length = rtb.TextLength - cs.hyperlinkStart; } } // reposition to final rtb.Select(rtb.TextLength + 1, 0); } cs.links.Add(new KeyValuePair<int, int>(cs.hyperlinkStart, length)); cs.hyperlinkStart = -1; break; case "p": cs.pf = cs.spf.Pop(); cs.paraFormatChanged = true; break; case "li": cs.pf = cs.spf.Pop(); cs.paraFormatChanged = true; break; case "font": cs.cf = cs.scf.Pop(); cs.charFormatChanged = true; break; } }
private static void ProcessNode(RichTextBox rtb, HandleRef handleRef, XmlReader reader, RTFCurrentState cs) { switch (reader.NodeType) { case XmlNodeType.Element: ProcessElement(reader, cs, rtb); break; case XmlNodeType.EndElement: ProcessEndElement(reader, cs, rtb); break; case XmlNodeType.Text: string strData = reader.Value; bool bNewParagraph = (strData.IndexOf("\r\n", 0) >= 0) || (strData.IndexOf("\n", 0) >= 0); if (strData.Length > 0) { // now, add text to control int nStartCache = rtb.SelectionStart; rtb.SelectedText = strData; rtb.Select(nStartCache, strData.Length); // apply format if (cs.paraFormatChanged) SetParaFormat(handleRef, cs.pf); if (cs.charFormatChanged) SetCharFormat(handleRef, cs.cf); cs.charFormatChanged = false; cs.paraFormatChanged = false; // reposition to final rtb.Select(rtb.TextLength + 1, 0); // new paragraph requires to reset alignment if (bNewParagraph) { cs.pf.dwMask = PFM.ALIGNMENT | PFM.NUMBERING; cs.pf.wAlignment = PFA.LEFT; cs.pf.wNumbering = 0; cs.paraFormatChanged = true; } } break; case XmlNodeType.Whitespace: case XmlNodeType.SignificantWhitespace: rtb.SelectedText = reader.Value; break; case XmlNodeType.XmlDeclaration: case XmlNodeType.ProcessingInstruction: break; case XmlNodeType.Comment: break; default: break; } }
private static void ProcessElement(XmlReader reader, RTFCurrentState cs, RichTextBox rtb) { switch (reader.Name.ToLower()) { case "b": cs.cf.dwMask |= CFM.WEIGHT | CFM.BOLD; cs.cf.dwEffects |= CFE.BOLD; cs.cf.wWeight = FW.BOLD; cs.charFormatChanged = true; break; case "i": cs.cf.dwMask |= CFM.ITALIC; cs.cf.dwEffects |= CFE.ITALIC; cs.charFormatChanged = true; break; case "u": cs.cf.dwMask |= CFM.UNDERLINE | CFM.UNDERLINETYPE; cs.cf.dwEffects |= CFE.UNDERLINE; cs.cf.bUnderlineType = CFU.UNDERLINE; cs.charFormatChanged = true; break; case "s": cs.cf.dwMask |= CFM.STRIKEOUT; cs.cf.dwEffects |= CFE.STRIKEOUT; cs.charFormatChanged = true; break; case "sup": cs.cf.dwMask |= CFM.SUPERSCRIPT; cs.cf.dwEffects |= CFE.SUPERSCRIPT; cs.charFormatChanged = true; break; case "sub": cs.cf.dwMask |= CFM.SUBSCRIPT; cs.cf.dwEffects |= CFE.SUBSCRIPT; cs.charFormatChanged = true; break; case "a": cs.hyperlinkStart = rtb.TextLength; cs.hyperlink = null; while (reader.MoveToNextAttribute()) { if (reader.Name.ToLower() == "href") { cs.hyperlink = reader.Value; } } reader.MoveToElement(); break; case "p": cs.spf.Push(cs.pf); while (reader.MoveToNextAttribute()) { if (reader.Name.ToLower() == "align") { if (reader.Value == "left") { cs.pf.dwMask |= PFM.ALIGNMENT; cs.pf.wAlignment = PFA.LEFT; cs.paraFormatChanged = true; } else if (reader.Value == "right") { cs.pf.dwMask |= PFM.ALIGNMENT; cs.pf.wAlignment = PFA.RIGHT; cs.paraFormatChanged = true; } else if (reader.Value == "center") { cs.pf.dwMask |= PFM.ALIGNMENT; cs.pf.wAlignment = PFA.CENTER; cs.paraFormatChanged = true; } } } reader.MoveToElement(); break; case "li": cs.spf.Push(cs.pf); if (cs.pf.wNumbering != PFN.BULLET) { cs.pf.dwMask |= PFM.NUMBERING; cs.pf.wNumbering = PFN.BULLET; cs.paraFormatChanged = true; } break; case "font": cs.scf.Push(cs.cf); string strFont = cs.cf.szFaceName; int crFont = cs.cf.crTextColor; int yHeight = cs.cf.yHeight; while (reader.MoveToNextAttribute()) { switch (reader.Name.ToLower()) { case "face": cs.cf.dwMask |= CFM.FACE; strFont = reader.Value; break; case "size": cs.cf.dwMask |= CFM.SIZE; yHeight = int.Parse(reader.Value); yHeight *= (20 * 5); break; case "color": cs.cf.dwMask |= CFM.COLOR; string text = reader.Value; if (text.StartsWith("#")) { string strCr = text.Substring(1); int nCr = Convert.ToInt32(strCr, 16); Color color = Color.FromArgb(nCr); crFont = GetCOLORREF(color); } else if (!int.TryParse(text, out crFont)) { Color color = Color.FromName(text); crFont = GetCOLORREF(color); } break; } } reader.MoveToElement(); cs.cf.szFaceName = strFont; cs.cf.crTextColor = crFont; cs.cf.yHeight = yHeight; cs.cf.dwEffects &= ~CFE.AUTOCOLOR; cs.charFormatChanged = true; break; } }
public static void SetXHTMLText(this RichTextBox rtb, string xhtmlText) { if (EnvUtils.IsMonoRuntime()) { SetXHTMLTextAsPlainText(rtb, xhtmlText); return; } rtb.Clear(); RTFCurrentState cs = new RTFCurrentState(); var handleRef = new HandleRef(rtb, rtb.Handle); cs.cf = GetDefaultCharFormat(handleRef); // to apply character formatting cs.pf = GetDefaultParaFormat(handleRef); // to apply paragraph formatting IntPtr oldMask = BeginUpdate(handleRef); SetHideSelectionInternal(handleRef, true); XmlReaderSettings settings = new XmlReaderSettings(); settings.ConformanceLevel = ConformanceLevel.Fragment; settings.CheckCharacters = false; try { using (StringReader stringreader = new StringReader(EscapeNonXMLChars(xhtmlText))) { XmlReader reader = XmlReader.Create(stringreader, settings); while (reader.Read()) ProcessNode(rtb, handleRef, reader, cs); } } catch (System.Xml.XmlException ex) { Debug.WriteLine(ex.Message); } // apply links style CHARFORMAT ncf = new CHARFORMAT(CFM.LINK, CFE.LINK); ncf.cbSize = Marshal.SizeOf(ncf); foreach (var pair in cs.links) { rtb.Select(pair.Key, pair.Value); SetCharFormat(handleRef, ncf); } SetHideSelectionInternal(handleRef, false); // reposition to first rtb.Select(0, 0); EndUpdate(handleRef, oldMask); rtb.Invalidate(); }