Skip to content

Commit 469d22d

Browse files
author
PavelTorgashov
committed
RTF export added
1 parent 909afb6 commit 469d22d

14 files changed

Lines changed: 370 additions & 45 deletions

Binary/FastColoredTextBox.dll

4 KB
Binary file not shown.

Binary/FastColoredTextBox.xml

Lines changed: 64 additions & 36 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Binary/Tester.exe

512 Bytes
Binary file not shown.
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class ExportToHTML
2929
/// </summary>
3030
public bool UseStyleTag { get; set; }
3131
/// <summary>
32-
/// Use br tag instead \n
32+
/// Use 'br' tag instead of '\n'
3333
/// </summary>
3434
public bool UseBr { get; set; }
3535
/// <summary>
@@ -67,8 +67,6 @@ public string GetHtml(Range r)
6767
styles[currentStyleId] = null;
6868
//
6969
if (UseOriginalFont)
70-
/*sb.AppendFormat("<font style=\"font-family: {0}, monospace; font-size: {1}px; line-height: {2}px;\">",
71-
r.tb.Font.Name, r.tb.CharHeight - r.tb.LineInterval, r.tb.CharHeight);*/
7270
sb.AppendFormat("<font style=\"font-family: {0}, monospace; font-size: {1}pt; line-height: {2}px;\">",
7371
r.tb.Font.Name, r.tb.Font.SizeInPoints, r.tb.CharHeight);
7472

@@ -204,8 +202,6 @@ string GetStyleName(StyleIndex styleIndex)
204202
private void Flush(StringBuilder sb, StringBuilder tempSB, StyleIndex currentStyle)
205203
{
206204
//find textRenderer
207-
//var textStyle = styles.Where(s => s is TextStyle).FirstOrDefault();
208-
//
209205
if (tempSB.Length == 0)
210206
return;
211207
if (UseStyleTag)

FastColoredTextBox/ExportToRTF.cs

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Drawing;
4+
using System.Text;
5+
6+
namespace FastColoredTextBoxNS
7+
{
8+
/// <summary>
9+
/// Exports colored text as RTF
10+
/// </summary>
11+
/// <remarks>At this time only TextStyle renderer is supported. Other styles is not exported.</remarks>
12+
public class ExportToRTF
13+
{
14+
/// <summary>
15+
/// Includes line numbers
16+
/// </summary>
17+
public bool IncludeLineNumbers { get; set; }
18+
/// <summary>
19+
/// Use original font
20+
/// </summary>
21+
public bool UseOriginalFont { get; set; }
22+
23+
FastColoredTextBox tb;
24+
Dictionary<Color, int> colorTable = new Dictionary<Color, int>();
25+
26+
public ExportToRTF()
27+
{
28+
UseOriginalFont = true;
29+
}
30+
31+
public string GetRtf(FastColoredTextBox tb)
32+
{
33+
this.tb = tb;
34+
Range sel = new Range(tb);
35+
sel.SelectAll();
36+
return GetRtf(sel);
37+
}
38+
39+
public string GetRtf(Range r)
40+
{
41+
this.tb = r.tb;
42+
var styles = new Dictionary<StyleIndex, object>();
43+
var sb = new StringBuilder();
44+
var tempSB = new StringBuilder();
45+
var currentStyleId = StyleIndex.None;
46+
r.Normalize();
47+
int currentLine = r.Start.iLine;
48+
styles[currentStyleId] = null;
49+
colorTable.Clear();
50+
//
51+
var lineNumberColor = GetColorTableNumber(r.tb.LineNumberColor);
52+
53+
if (IncludeLineNumbers)
54+
tempSB.AppendFormat(@"{{\cf{1} {0}}}\tab", currentLine + 1, lineNumberColor);
55+
//
56+
foreach (Place p in r)
57+
{
58+
Char c = r.tb[p.iLine][p.iChar];
59+
if (c.style != currentStyleId)
60+
{
61+
Flush(sb, tempSB, currentStyleId);
62+
currentStyleId = c.style;
63+
styles[currentStyleId] = null;
64+
}
65+
66+
if (p.iLine != currentLine)
67+
{
68+
for (int i = currentLine; i < p.iLine; i++)
69+
{
70+
tempSB.AppendLine(@"\line");
71+
if (IncludeLineNumbers)
72+
tempSB.AppendFormat(@"{{\cf{1} {0}}}\tab", i + 2, lineNumberColor);
73+
}
74+
currentLine = p.iLine;
75+
}
76+
switch (c.c)
77+
{
78+
case '\\':
79+
tempSB.Append(@"\\");
80+
break;
81+
case '{':
82+
tempSB.Append(@"\{");
83+
break;
84+
case '}':
85+
tempSB.Append(@"\}");
86+
break;
87+
default:
88+
var ch = c.c;
89+
var code = (int)ch;
90+
if(code < 128)
91+
tempSB.Append(c.c);
92+
else
93+
tempSB.AppendFormat(@"{{\u{0}}}", code);
94+
break;
95+
}
96+
}
97+
Flush(sb, tempSB, currentStyleId);
98+
99+
//build color table
100+
var list = new SortedList<int, Color>();
101+
foreach (var pair in colorTable)
102+
list.Add(pair.Value, pair.Key);
103+
104+
tempSB.Length = 0;
105+
tempSB.AppendFormat(@"{{\colortbl;");
106+
107+
foreach (var pair in list)
108+
tempSB.Append(GetColorAsString(pair.Value)+";");
109+
tempSB.AppendLine("}");
110+
111+
//
112+
if (UseOriginalFont)
113+
{
114+
sb.Insert(0, string.Format(@"{{\fonttbl{{\f0\fmodern {0};}}}}{{\fs{1} ",
115+
tb.Font.Name, (int)(2 * tb.Font.SizeInPoints), tb.CharHeight));
116+
sb.AppendLine(@"}");
117+
}
118+
119+
sb.Insert(0, tempSB.ToString());
120+
121+
sb.Insert(0, @"{\rtf1\ud\deff0");
122+
sb.AppendLine(@"}");
123+
124+
return sb.ToString();
125+
}
126+
127+
private RTFStyleDescriptor GetRtfDescriptor(StyleIndex styleIndex)
128+
{
129+
List<Style> styles = new List<Style>();
130+
//find text renderer
131+
TextStyle textStyle = null;
132+
int mask = 1;
133+
bool hasTextStyle = false;
134+
for (int i = 0; i < tb.Styles.Length; i++)
135+
{
136+
if (tb.Styles[i] != null && ((int)styleIndex & mask) != 0)
137+
if (tb.Styles[i].IsExportable)
138+
{
139+
var style = tb.Styles[i];
140+
styles.Add(style);
141+
142+
bool isTextStyle = style is TextStyle;
143+
if (isTextStyle)
144+
if (!hasTextStyle || tb.AllowSeveralTextStyleDrawing)
145+
{
146+
hasTextStyle = true;
147+
textStyle = style as TextStyle;
148+
}
149+
}
150+
mask = mask << 1;
151+
}
152+
//add TextStyle css
153+
RTFStyleDescriptor result = null;
154+
155+
if (!hasTextStyle)
156+
{
157+
//draw by default renderer
158+
result = tb.DefaultStyle.GetRTF();
159+
}
160+
else
161+
{
162+
result = textStyle.GetRTF();
163+
}
164+
165+
return result;
166+
}
167+
168+
public static string GetColorAsString(Color color)
169+
{
170+
if (color == Color.Transparent)
171+
return "";
172+
return string.Format(@"\red{0}\green{1}\blue{2}", color.R, color.G, color.B);
173+
}
174+
175+
private void Flush(StringBuilder sb, StringBuilder tempSB, StyleIndex currentStyle)
176+
{
177+
//find textRenderer
178+
if (tempSB.Length == 0)
179+
return;
180+
181+
var desc = GetRtfDescriptor(currentStyle);
182+
var cf = GetColorTableNumber(desc.ForeColor);
183+
var cb = GetColorTableNumber(desc.BackColor);
184+
var tags = new StringBuilder();
185+
if (cf >= 0)
186+
tags.AppendFormat(@"\cf{0}", cf);
187+
if (cb >= 0)
188+
tags.AppendFormat(@"\highlight{0}", cb);
189+
if(!string.IsNullOrEmpty(desc.AdditionalTags))
190+
tags.Append(desc.AdditionalTags.Trim());
191+
192+
if(tags.Length > 0)
193+
sb.AppendFormat(@"{{{0} {1}}}", tags, tempSB.ToString());
194+
else
195+
sb.Append(tempSB.ToString());
196+
tempSB.Length = 0;
197+
}
198+
199+
private int GetColorTableNumber(Color color)
200+
{
201+
if (color.A == 0)
202+
return -1;
203+
204+
if (!colorTable.ContainsKey(color))
205+
colorTable[color] = colorTable.Count + 1;
206+
207+
return colorTable[color];
208+
}
209+
}
210+
211+
public class RTFStyleDescriptor
212+
{
213+
public Color ForeColor { get; set; }
214+
public Color BackColor { get; set; }
215+
public string AdditionalTags { get; set; }
216+
}
217+
}

0 commit comments

Comments
 (0)