/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy 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 General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.Net; using System.Text; namespace dnSpy.Contracts.Text.Formatting { sealed class HtmlClipboardFormatWriter { readonly StringBuilder sb; public int TabSize { get; set; } public HtmlClipboardFormatWriter() { sb = new StringBuilder(); TabSize = 4; } public void WriteRaw(string s) => sb.Append(s); public void WriteBr() => sb.Append("
"); public void WriteSpan(string cssText, string spanText) => WriteSpan(cssText, spanText, 0, spanText.Length); public void WriteSpan(string cssText, string spanText, int index, int length) { sb.Append(" 0) sb.Append($" style=\"{WebUtility.HtmlEncode(cssText)}\""); sb.Append('>'); WriteString(spanText, index, length); sb.Append(""); } static readonly char[] whitespace = new char[] { '\r', '\n', '\u0085', '\u2028', '\u2029', '\t', ' ' }; void WriteString(string text, int index, int length) { for (int i = 0; i < length;) { int wsi = text.IndexOfAny(whitespace, index + i, length - i); if (wsi < 0) { sb.Append(WebUtility.HtmlEncode(text.Substring(index + i, length - i))); break; } if (wsi != index + i) sb.Append(WebUtility.HtmlEncode(text.Substring(index + i, wsi - (index + i)))); switch (text[wsi]) { case ' ': sb.Append(" "); break; case '\t': for (int j = 0; j < TabSize; j++) sb.Append(" "); break; case '\r': break; case '\n': case '\u0085': case '\u2028': case '\u2029': WriteBr(); break; default: throw new InvalidOperationException(); } i = wsi + 1 - index; } } static string GetHeader(int startHtml, int endHtml, int startFragment, int endFragment) => string.Format( "Version:0.9" + Environment.NewLine + "StartHTML:{0:D10}" + Environment.NewLine + "EndHTML:{1:D10}" + Environment.NewLine + "StartFragment:{2:D10}" + Environment.NewLine + "EndFragment:{3:D10}" + Environment.NewLine, startHtml, endHtml, startFragment, endFragment); public override string ToString() { var header = GetHeader(0, 0, 0, 0); var prefix = "" + Environment.NewLine + "" + Environment.NewLine + ""; var html = sb.ToString(); var suffix = "" + Environment.NewLine + "" + Environment.NewLine + ""; int startHtml = header.Length; int startFragment = startHtml + prefix.Length; int endFragment = startFragment + Encoding.UTF8.GetByteCount(html); int endHtml = endFragment + suffix.Length; return GetHeader(startHtml, endHtml, startFragment, endFragment) + prefix + html + suffix; } } }