private static string ProcessTags(RichTextBox rtb, List<KeyValuePair<int, string>> colFormat, bool bParaFormat) { StringBuilder sbT = new StringBuilder(); ctformatStates bold = ctformatStates.nctNone; ctformatStates bitalic = ctformatStates.nctNone; ctformatStates bstrikeout = ctformatStates.nctNone; ctformatStates bunderline = ctformatStates.nctNone; ctformatStates super = ctformatStates.nctNone; ctformatStates sub = ctformatStates.nctNone; ctformatStates bacenter = ctformatStates.nctNone; ctformatStates baleft = ctformatStates.nctNone; ctformatStates baright = ctformatStates.nctNone; ctformatStates bnumbering = ctformatStates.nctNone; bool fontSet = false; string strFont = ""; Int32 crFont = 0; Color color = new Color(); int yHeight = 0; int i = 0; int pos = 0; int k = rtb.TextLength; char[] chtrim = { ' ', '\x0000' }; //-------------------------------- // this is an inefficient method to get text format // but RichTextBox doesn't provide another method to // get something like an array of charformat and paraformat //-------------------------------- for (i = 0; i < k; i++) { // select one character rtb.Select(i, 1); string strChar = rtb.SelectedText; // get format for this character CHARFORMAT cf = rtb.GetCharFormat(); PARAFORMAT pf = rtb.GetParaFormat(); string strfname = cf.szFaceName; strfname = strfname.Trim(chtrim); // new font format ? if ((strFont != strfname) || (crFont != cf.crTextColor) || (yHeight != cf.yHeight)) { KeyValuePair<int, string> mfr; if (strFont != "") { // close previous <font> tag mfr = new KeyValuePair<int, string>(pos, "</font>"); colFormat.Add(mfr); } // save this for cache strFont = strfname; crFont = cf.crTextColor; yHeight = cf.yHeight; fontSet = strFont != ""; // font size should be translate to // html size (Approximately) int fsize = yHeight / (20 * 5); // color object from COLORREF color = GetColor(crFont); // add <font> tag string strcolor = string.Concat("#", (color.ToArgb() & 0x00FFFFFF).ToString("X6")); mfr = new KeyValuePair<int, string>(pos, "<font face=\"" + strFont + "\" color=\"" + strcolor + "\" size=\"" + fsize + "\">"); colFormat.Add(mfr); } // are we in another line ? if ((strChar == "\r") || (strChar == "\n")) { // yes? // then, we need to reset paragraph format // and character format if (bParaFormat) { bnumbering = ctformatStates.nctNone; baleft = ctformatStates.nctNone; baright = ctformatStates.nctNone; bacenter = ctformatStates.nctNone; } // close previous tags // is italic? => close it if (bitalic != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</i>"); colFormat.Add(mfr); bitalic = ctformatStates.nctNone; } // is bold? => close it if (bold != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</b>"); colFormat.Add(mfr); bold = ctformatStates.nctNone; } // is underline? => close it if (bunderline != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</u>"); colFormat.Add(mfr); bunderline = ctformatStates.nctNone; } // is strikeout? => close it if (bstrikeout != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</s>"); colFormat.Add(mfr); bstrikeout = ctformatStates.nctNone; } // is super? => close it if (super != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</sup>"); colFormat.Add(mfr); super = ctformatStates.nctNone; } // is sub? => close it if (sub != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</sub>"); colFormat.Add(mfr); sub = ctformatStates.nctNone; } } // now, process the paragraph format, // managing states: none, new, continue {with previous}, reset if (bParaFormat) { // align to center? UpdateState(pf.wAlignment == PFA.CENTER, ref bacenter); if (bacenter == ctformatStates.nctNew) { var mfr = new KeyValuePair<int, string>(pos, "<p align=\"center\">"); colFormat.Add(mfr); } else if (bacenter == ctformatStates.nctReset) bacenter = ctformatStates.nctNone; // align to left UpdateState(pf.wAlignment == PFA.LEFT, ref baleft); if (baleft == ctformatStates.nctNew) { var mfr = new KeyValuePair<int, string>(pos, "<p align=\"left\">"); colFormat.Add(mfr); } else if (baleft == ctformatStates.nctReset) baleft = ctformatStates.nctNone; // align to right UpdateState(pf.wAlignment == PFA.RIGHT, ref baright); if (baright == ctformatStates.nctNew) { var mfr = new KeyValuePair<int, string>(pos, "<p align=\"right\">"); colFormat.Add(mfr); } else if (baright == ctformatStates.nctReset) baright = ctformatStates.nctNone; // bullet UpdateState(pf.wNumbering == PFN.BULLET, ref bnumbering); if (bnumbering == ctformatStates.nctNew) { var mfr = new KeyValuePair<int, string>(pos, "<li>"); colFormat.Add(mfr); } else if (bnumbering == ctformatStates.nctReset) bnumbering = ctformatStates.nctNone; } // bold UpdateState((cf.dwEffects & CFE.BOLD) == CFE.BOLD, ref bold); AddTag(pos, "b", colFormat, ref bold); // Italic UpdateState((cf.dwEffects & CFE.ITALIC) == CFE.ITALIC, ref bitalic); AddTag(pos, "i", colFormat, ref bitalic); // strikeout UpdateState((cf.dwEffects & CFE.STRIKEOUT) == CFE.STRIKEOUT, ref bstrikeout); AddTag(pos, "s", colFormat, ref bstrikeout); // underline UpdateState((cf.dwEffects & CFE.UNDERLINE) == CFE.UNDERLINE, ref bunderline); AddTag(pos, "u", colFormat, ref bunderline); // superscript UpdateState((cf.dwEffects & CFE.SUPERSCRIPT) == CFE.SUPERSCRIPT, ref super); AddTag(pos, "sup", colFormat, ref super); // subscript UpdateState((cf.dwEffects & CFE.SUBSCRIPT) == CFE.SUBSCRIPT, ref sub); AddTag(pos, "sub", colFormat, ref sub); sbT.Append(strChar); pos = sbT.Length; } // close pending tags if (bold != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</b>"); colFormat.Add(mfr); } if (bitalic != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</i>"); colFormat.Add(mfr); } if (bstrikeout != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</s>"); colFormat.Add(mfr); } if (bunderline != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</u>"); colFormat.Add(mfr); } if (super != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</sup>"); colFormat.Add(mfr); } if (sub != ctformatStates.nctNone) { var mfr = new KeyValuePair<int, string>(pos, "</sub>"); colFormat.Add(mfr); } if (fontSet) { // close pending font format var mfr = new KeyValuePair<int, string>(pos, "</font>"); colFormat.Add(mfr); } // now, reorder the formatting array k = colFormat.Count; for (i = 0; i < k - 1; i++) { for (int j = i + 1; j < k; j++) { var mfr = colFormat[i]; var mfr2 = colFormat[j]; if (mfr2.Key < mfr.Key) { colFormat.RemoveAt(j); colFormat.Insert(i, mfr2); j--; } } } return sbT.ToString(); }