├── LICENSE.md ├── CHANGELOG.md ├── RTFExporter ├── Color.cs ├── RTFExporter.csproj ├── RTFParagraph.cs ├── RTFTextStyle.cs ├── RTFParagraphStyle.cs ├── RTFText.cs ├── RTFDocument.cs └── RTFParser.cs ├── RTFExporter.sln ├── README.md ├── RTFSyntaxReference.md └── .gitignore /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2017-2021 Bruno Araujo 2 | This work is free. You can redistribute it and/or modify it under the 3 | terms of the Do What The Fuck You Want To Public License, Version 2, 4 | as published by Sam Hocevar. See the [COPYING](http://www.wtfpl.net/txt/copying) file for more details. 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | ## [1.1.4] - 2020-10-09 5 | ### Added 6 | - This CHANGELOG file. 7 | 8 | ### Changed 9 | - Folders structure (src folder renamed to RTFExporter). Preparing to multi project solution. 10 | 11 | ### Fixes 12 | - RTFExporter.csproj informations. 13 | -------------------------------------------------------------------------------- /RTFExporter/Color.cs: -------------------------------------------------------------------------------- 1 | namespace RTFExporter 2 | { 3 | /// 4 | /// A class to manage RTF colors as rgb values from 0 to 255 5 | /// 6 | public class Color 7 | { 8 | public byte r; 9 | public byte g; 10 | public byte b; 11 | public int index; 12 | public static Color black = new Color(0, 0, 0); 13 | public static Color white = new Color(255, 255, 255); 14 | public static Color red = new Color(255, 0, 0); 15 | public static Color green = new Color(0, 255, 0); 16 | public static Color blue = new Color(0, 0, 255); 17 | public static Color yellow = new Color(255, 255, 0); 18 | public static Color purple = new Color(255, 0, 255); 19 | public static Color cyan = new Color(0, 255, 255); 20 | 21 | /// 22 | /// Color constructor 23 | /// 24 | /// Red 25 | /// Green 26 | /// Blue 27 | public Color(byte r, byte g, byte b) 28 | { 29 | this.r = r; 30 | this.g = g; 31 | this.b = b; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /RTFExporter.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RTFExporter", "RTFExporter\RTFExporter.csproj", "{3A8F9811-8741-4276-8818-4DD2641B76DD}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3A8F9811-8741-4276-8818-4DD2641B76DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {3A8F9811-8741-4276-8818-4DD2641B76DD}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {3A8F9811-8741-4276-8818-4DD2641B76DD}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {3A8F9811-8741-4276-8818-4DD2641B76DD}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {3F7769F3-EED8-4A07-A2F5-251E0E318DF6} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /RTFExporter/RTFExporter.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | true 5 | RTFExporter 6 | RTFExporter 7 | RTFExporter 8 | RTFExporter 9 | 1.1.4 10 | Bruno Araujo 11 | Lava Leak 12 | Copyright (c) 2017-2020 Bruno Araujo 13 | LICENSE.md 14 | false 15 | https://github.com/brunurd/RTFExporter 16 | https://github.com/brunurd/RTFExporter 17 | git 18 | A C# library to generate .RTF text files from any string object data, stylized and ready for any text processor. No fancy dependencies or restrictive licenses. 19 | chore: Copyright update. 20 | rtf;rich;text;doc;docx;word;string 21 | 4 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /RTFExporter/RTFParagraph.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RTFExporter 4 | { 5 | /// 6 | /// The RTF paragraph class, every class need a document to append 7 | /// 8 | public class RTFParagraph 9 | { 10 | public List text = new List(); 11 | public RTFParagraphStyle style; 12 | 13 | /// 14 | /// The RTF paragraph constructor 15 | /// 16 | /// 17 | /// The RTF document to append the paragraph 18 | public RTFParagraph(RTFDocument document) 19 | { 20 | style = new RTFParagraphStyle(document); 21 | document.paragraphs.Add(this); 22 | } 23 | 24 | /// 25 | /// The method to add a text to a paragraph 26 | /// 27 | /// 28 | /// The text content 29 | /// Return the text instantiated with the content 30 | public RTFText AppendText(string content) 31 | { 32 | RTFText text = new RTFText(this, content); 33 | return text; 34 | } 35 | 36 | /// 37 | /// The method to add a text to a paragraph 38 | /// 39 | /// 40 | /// 41 | /// The text content 42 | /// The text styler 43 | /// Return the text instantiated with the content and the style 44 | public RTFText AppendText(string content, RTFTextStyle style) 45 | { 46 | RTFText text = new RTFText(this, content, style); 47 | return text; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /RTFExporter/RTFTextStyle.cs: -------------------------------------------------------------------------------- 1 | namespace RTFExporter 2 | { 3 | /// 4 | /// Underline types 5 | /// 6 | public enum Underline 7 | { 8 | None, 9 | Basic, 10 | Double, 11 | Thick, 12 | WordsOnly, 13 | Wave, 14 | Dotted, 15 | Dash, 16 | DotDash 17 | } 18 | 19 | /// 20 | /// A group of text styling configuration 21 | /// 22 | public class RTFTextStyle 23 | { 24 | public bool italic; 25 | public bool bold; 26 | public bool smallCaps; 27 | public bool strikeThrough; 28 | public bool allCaps; 29 | public bool outline; 30 | public int fontSize; 31 | public string fontFamily; 32 | public Color color; 33 | public Underline underline; 34 | 35 | /// 36 | /// The simple style constructor 37 | /// 38 | /// 39 | /// Is italic? 40 | /// Is bold? 41 | /// Font size in pt 42 | /// A valid font family, will use Calibri if doesn't exist 43 | /// A rgb color to the text 44 | public RTFTextStyle(bool italic, bool bold, int fontSize, string fontFamily, Color color) 45 | { 46 | this.italic = italic; 47 | this.bold = bold; 48 | this.fontSize = fontSize; 49 | this.fontFamily = fontFamily; 50 | this.color = color; 51 | } 52 | 53 | /// 54 | /// The style constructor 55 | /// 56 | /// 57 | /// 58 | /// Is italic? 59 | /// Is bold? 60 | /// Use all small caps? 61 | /// Use strike through? 62 | /// Use all caps? 63 | /// Has outline? 64 | /// Font size in pt 65 | /// A valid font family, will use Calibri if doesn't exist 66 | /// A rgb color to the text 67 | /// The underline type 68 | public RTFTextStyle(bool italic, bool bold, bool smallCaps, bool strikeThrough, bool allCaps, 69 | bool outline, int fontSize, string fontFamily, Color color, Underline underline) 70 | { 71 | this.italic = italic; 72 | this.bold = bold; 73 | this.smallCaps = smallCaps; 74 | this.strikeThrough = strikeThrough; 75 | this.allCaps = allCaps; 76 | this.outline = outline; 77 | this.fontSize = fontSize; 78 | this.fontFamily = fontFamily; 79 | this.color = color; 80 | this.underline = underline; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RTFExporter 2 | 3 | 4 | [![NuGet Version](https://img.shields.io/nuget/v/RTFExporter)][nuget] 5 | ![C# Version](https://img.shields.io/badge/C%23-4.0-621ee5) 6 | ![Framework Version](https://img.shields.io/badge/framework-netstandard2.0-621ee5) 7 | ![.NETFramework Version](https://img.shields.io/badge/.NET_Framework-4.6.1-621ee5) 8 | 9 | 10 | A C# library to generate .RTF text files from any string object data, stylized and ready for any text processor. No fancy dependencies or restrictive licenses. 11 | 12 | 13 | --- 14 | 15 | 16 | ## Simple usage 17 | 18 | 19 | IDisposable style: 20 | 21 | 22 | ```C# 23 | using RTFExporter; 24 | 25 | public class Example { 26 | 27 | public void IDisposableExample() { 28 | 29 | using (RTFDocument doc = new RTFDocument("example.rtf")) { 30 | var p = doc.AppendParagraph(); 31 | 32 | p.style.alignment = Alignment.Center; 33 | p.style.indent = new Indent(1, 0, 0); 34 | p.style.spaceAfter = 400; 35 | 36 | var t = p.AppendText("One: Don't pick up the phone\n"); 37 | t.content += "You know he's only callin' 'cause he's drunk and alone"; 38 | 39 | t.style.bold = true; 40 | t.style.color = new Color(255, 0, 0); 41 | t.style.fontFamily = "Courier"; 42 | } 43 | 44 | } 45 | 46 | } 47 | ``` 48 | 49 | 50 | String style: 51 | 52 | 53 | ```C# 54 | using RTFExporter; 55 | 56 | public class Example { 57 | 58 | public void StringExample() { 59 | 60 | RTFDocument doc = new RTFDocument(); 61 | RTFParagraph p = new RTFParagraph(doc); 62 | 63 | RTFText t1 = new RTFText(p, "Two: Don't let him in\n"); 64 | t1.SetStyle(new Color(255, 0, 0), 18, "Helv"); 65 | 66 | RTFText t2 = new RTFText(p, "You'll have to kick him out again"); 67 | t2.style = t1.style; 68 | 69 | string output = RTFParser.ToString(doc); 70 | 71 | } 72 | 73 | } 74 | ``` 75 | 76 | 77 | --- 78 | 79 | 80 | ## Features 81 | 82 | 83 | - Document 84 | - Set page size 85 | - Set orientation 86 | - Set margin 87 | - Set units (inch, mm, cm) 88 | 89 | 90 | - Paragraph style 91 | - Set indent 92 | - Set text alignment 93 | - Set spacing 94 | 95 | 96 | - Text style 97 | - Set color 98 | - Set font family 99 | - Set font size 100 | - Set style: bold, italic, small caps, all caps, strike through and outline 101 | - Set 8 different types of underline 102 | 103 | 104 | --- 105 | 106 | 107 | ## Missing 108 | 109 | - Parse a rtf file to RTFDocument object 110 | - Support to non-latin characters 111 | - Use stylesheets 112 | - Lists 113 | - And a lot more of RTF stuff 114 | 115 | 116 | --- 117 | 118 | 119 | ## License (WTFPL-2.0) 120 | 121 | 122 | [![WTFPL Badge](http://www.wtfpl.net/wp-content/uploads/2012/12/wtfpl-badge-4.png)](http://www.wtfpl.net/) 123 | 124 | [nuget]: https://www.nuget.org/packages/RTFExporter 125 | -------------------------------------------------------------------------------- /RTFExporter/RTFParagraphStyle.cs: -------------------------------------------------------------------------------- 1 | namespace RTFExporter 2 | { 3 | /// 4 | /// A paragraph indent configuration 5 | /// 6 | public struct Indent 7 | { 8 | public float firstLine; 9 | public float left; 10 | public float right; 11 | 12 | /// 13 | /// The paragraph indent constructor 14 | /// 15 | /// A space in the first line 16 | /// A space in the left of the block 17 | /// A space in the right of the block 18 | public Indent(float firstLine, float left, float right) 19 | { 20 | this.firstLine = firstLine; 21 | this.left = left; 22 | this.right = right; 23 | } 24 | } 25 | 26 | /// 27 | /// The text alignment type 28 | /// 29 | public enum Alignment 30 | { 31 | Left, 32 | Right, 33 | Center, 34 | Justified 35 | } 36 | 37 | /// 38 | /// A group of paragraph styling configuration 39 | /// 40 | public class RTFParagraphStyle 41 | { 42 | 43 | public Indent indent; 44 | public Alignment alignment; 45 | public int spaceBefore; 46 | public int spaceAfter = 100; 47 | 48 | /// 49 | /// RTF paragraph style constructor with just alignment 50 | /// 51 | /// 52 | /// Alignment object 53 | public RTFParagraphStyle(Alignment alignment) 54 | { 55 | this.alignment = alignment; 56 | } 57 | 58 | /// 59 | /// RTF paragraph style constructor with just alignment and indent 60 | /// 61 | /// 62 | /// 63 | /// Alignment object 64 | /// Indent object 65 | public RTFParagraphStyle(Alignment alignment, Indent indent) 66 | { 67 | this.alignment = alignment; 68 | this.indent = indent; 69 | } 70 | 71 | /// 72 | /// RTF paragraph style constructor complete 73 | /// 74 | /// 75 | /// 76 | /// Alignment object 77 | /// Indent object 78 | /// Space vertical before paragraph 79 | /// Space vertical after paragraph 80 | public RTFParagraphStyle(Alignment alignment, Indent indent, int spaceBefore, int spaceAfter) 81 | { 82 | this.alignment = alignment; 83 | this.indent = indent; 84 | this.spaceBefore = spaceBefore; 85 | this.spaceAfter = spaceAfter; 86 | } 87 | 88 | /// 89 | /// RTF paragraph style constructor with parent document 90 | /// 91 | /// 92 | /// The RTF document to append the paragraph 93 | public RTFParagraphStyle(RTFDocument document) 94 | { 95 | switch (document.units) 96 | { 97 | case Units.Inch: 98 | indent = new Indent(1, 0, 0); 99 | break; 100 | case Units.Millimeters: 101 | indent = new Indent(25.4f, 0, 0); 102 | break; 103 | case Units.Centimeters: 104 | indent = new Indent(2.54f, 0, 0); 105 | break; 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /RTFExporter/RTFText.cs: -------------------------------------------------------------------------------- 1 | namespace RTFExporter 2 | { 3 | /// 4 | /// The RTF text class, any snippet of text of a paragraph, every text is appended to a paragraph 5 | /// 6 | public class RTFText 7 | { 8 | public RTFTextStyle style; 9 | public string content; 10 | 11 | /// 12 | /// The text constructor 13 | /// 14 | /// 15 | /// The parent paragraph 16 | /// The text content itself 17 | public RTFText(RTFParagraph paragraph, string content) 18 | { 19 | style = new RTFTextStyle(false, false, 12, "Calibri", new Color(0, 0, 0)); 20 | this.content = content; 21 | paragraph.text.Add(this); 22 | } 23 | 24 | /// 25 | /// The text constructor 26 | /// 27 | /// 28 | /// 29 | /// The parent paragraph 30 | /// The text content itself 31 | /// A pre-configured style object 32 | public RTFText(RTFParagraph paragraph, string content, RTFTextStyle style) 33 | { 34 | this.style = style; 35 | this.content = content; 36 | paragraph.text.Add(this); 37 | } 38 | 39 | /// 40 | /// Set a default style to the text (Calibri black 12pt) 41 | /// 42 | /// 43 | /// The RTF text object after style setted 44 | public RTFText SetStyle() 45 | { 46 | style = new RTFTextStyle(false, false, false, false, false, false, 12, "Calibri", Color.black, Underline.None); 47 | return this; 48 | } 49 | 50 | /// 51 | /// Set the basic style of the text 52 | /// 53 | /// 54 | /// 55 | /// The text color 56 | /// The font size in pt, 12pt as default 57 | /// A valid font family, will use Calibri if doesn't exist and as default 58 | /// The RTF text object after style setted 59 | public RTFText SetStyle(Color color, int fontSize = 12, string fontFamily = "Calibri") 60 | { 61 | style = new RTFTextStyle(false, false, fontSize, fontFamily, color); 62 | return this; 63 | } 64 | 65 | /// 66 | /// Set the style of the text 67 | /// 68 | /// 69 | /// 70 | /// The text color 71 | /// If the text is italic, false as default 72 | /// If the text is italic, false as default 73 | /// The font size in pt, 12pt as default 74 | /// A valid font family, will use Calibri if doesn't exist and as default 75 | /// The RTF text object after style setted 76 | public RTFText SetStyle(Color color, bool italic = false, bool bold = false, int fontSize = 12, string fontFamily = "Calibri") 77 | { 78 | style = new RTFTextStyle(italic, bold, fontSize, fontFamily, color); 79 | return this; 80 | } 81 | 82 | /// 83 | /// Set the style of the text without color, font size and font family 84 | /// 85 | /// 86 | /// 87 | /// If the text is italic, false as default 88 | /// If the text is italic, false as default 89 | /// The underline type 90 | /// Use all small caps? 91 | /// Use strike through? 92 | /// Use all caps? 93 | /// Has outline? 94 | /// 95 | public RTFText SetStyle(bool italic, bool bold, Underline underline = Underline.None, 96 | bool smallCaps = false, bool strikeThrough = false, bool allCaps = false, bool outline = false) 97 | { 98 | style = new RTFTextStyle(italic, bold, smallCaps, strikeThrough, allCaps, outline, 12, "Calibri", Color.black, underline); 99 | return this; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /RTFSyntaxReference.md: -------------------------------------------------------------------------------- 1 | #### IF YOU WANNA GOING DEEP I RECOMMEND THOSE LINKS: 2 | 3 | 4 | [https://github.com/jokecamp/RtfWebVisualizer](https://github.com/jokecamp/RtfWebVisualizer) 5 | [http://www.pindari.com/rtf1.html](http://www.pindari.com/rtf1.html) 6 | [http://www.biblioscape.com/rtf15_spec.htm](http://www.biblioscape.com/rtf15_spec.htm) 7 | [https://msdn.microsoft.com/en-us/library/office/aa140302](https://msdn.microsoft.com/en-us/library/office/aa140302) 8 | 9 | 10 | --- 11 | 12 | 13 | #### INITIALIZING THE FILE 14 | 15 | 16 | {\rtf\ansi\deff0 17 | 18 | 19 | means: 20 | 21 | 22 | rtf -> rich text format 23 | ansi -> using ANSI 24 | deff0 -> define font: 0 25 | 26 | 27 | --- 28 | 29 | 30 | #### SET DOCUMENT SIZE AND ORIENTATION 31 | 32 | 33 | \landscape 34 | \paperw15840\paperh12240 35 | 36 | 37 | \portrait 38 | \paperw12240\paperh15840 39 | 40 | 41 | means: 42 | 43 | 44 | paperw -> paper width 45 | paperh -> paper height 46 | 47 | 48 | notes: 49 | - the size 15840 is equal to 11 inchs and 12240 to 8,5 inchs (letter size) 50 | - use only integer values 51 | 52 | 53 | --- 54 | 55 | 56 | #### SET MARGINS 57 | 58 | 59 | \margl720\margr720\margt720\margb720 60 | 61 | 62 | means: 63 | 64 | 65 | margl -> margin left 66 | margr -> margin right 67 | margt -> margin top 68 | margb -> margin bottom 69 | 70 | 71 | notes: 72 | - the size 720 is equal to 0,5 inch 73 | - use only integer values 74 | 75 | 76 | --- 77 | 78 | 79 | #### SET DOCUMENT COLORS 80 | 81 | 82 | {\colortbl; 83 | \red255\green0\blue0; 84 | \red0\green255\blue0; 85 | } 86 | 87 | 88 | means: 89 | 90 | 91 | colortbl -> color table 92 | red255\green0\blue0 -> rgb color byte value 93 | 94 | 95 | how to use colors: 96 | 97 | 98 | \cf1 99 | Text 100 | \cf2Text 101 | 102 | 103 | cf1 -> all text after this will use the color 1 of the table as foreground 104 | cf2 -> all text after this will use the color 2 of the table as foreground 105 | 106 | 107 | notes: 108 | - the default is black 109 | - could be declared just one time, only the first works 110 | - always start in 1, cf0 doesn't exists 111 | - use only integer values 112 | 113 | 114 | --- 115 | 116 | 117 | #### SET DOCUMENT FONTS 118 | 119 | 120 | {\fonttbl 121 | {\f0 Courier;} 122 | {\f1 Arial;} 123 | {\f2 Helv;} 124 | {\f3 Tms Rmn;} 125 | {\f4 Verdana;} 126 | {\f5 Symbol;} 127 | } 128 | 129 | 130 | means: 131 | 132 | 133 | fonttbl -> font table 134 | f0 -> font 0 135 | 136 | 137 | notes: 138 | - the default is Calibri 139 | - you can use \fN to set the text font 140 | - this table could be declared several times in the file, the text uses the last declaration values 141 | - if font doesn't exist and is not setted, will use Calibri with a fake name 142 | - the default font always will be \f0, if start the table with other number it will use Calibri, if no one is setted 143 | - if you use a declaration like: "\f0 \f1" the text will use the last one ever if this font doesn't exists 144 | 145 | 146 | --- 147 | 148 | 149 | #### BREAKLINE 150 | 151 | 152 | \line 153 | 154 | 155 | note: 156 | - same as the escape sequence \n in C 157 | - if don't have a space between \line and the text the command is ignored 158 | 159 | 160 | --- 161 | 162 | 163 | #### BREAKPAGE 164 | 165 | 166 | \page 167 | 168 | 169 | note: 170 | - if don't have a space between \page and the text the command is ignored 171 | 172 | 173 | --- 174 | 175 | 176 | #### TAB 177 | 178 | 179 | \tab 180 | \tx1440 \tab 181 | 182 | 183 | means: 184 | 185 | 186 | tx -> tab x size 187 | 188 | 189 | note: 190 | - same as the escape sequence \t in C 191 | - if don't have a space between \tab and the text the command is ignored 192 | - \tx1440 is equal to 1 inch and 24,5 mm or 2,45 cm 193 | - \tx can be used in a row to define differents sizes of tab. Ex.: \tx720 \tx1440 \tx720 \tab \tab \tab 194 | - \tx row can declared just one time, the others will be ignored 195 | - use only integer values 196 | 197 | 198 | --- 199 | 200 | 201 | #### FONTSIZE 202 | 203 | 204 | \fs20 205 | 206 | 207 | means: 208 | 209 | 210 | fs20 -> font size 20 211 | 212 | 213 | note: 214 | - \fs20 in points is 10pt 215 | - use only integer values 216 | 217 | 218 | --- 219 | 220 | 221 | #### PARAGRAPH 222 | 223 | 224 | \par 225 | 226 | 227 | means: 228 | 229 | 230 | par -> end of a paragraph 231 | 232 | 233 | note: 234 | - if don't have a space between \par and the text the command is ignored 235 | 236 | 237 | --- 238 | 239 | 240 | #### TEXT STYLE 241 | 242 | 243 | \i -> italic on 244 | \i0 -> italic off 245 | \b -> bold on 246 | \b0 -> bold off 247 | \scaps -> small caps on 248 | \scaps0 -> small caps off 249 | \strike -> strike through on 250 | \strike0 -> strike through off 251 | \caps -> capitals on 252 | \caps0 -> all capitals off 253 | \outl -> outline on 254 | \outl0 -> outline off 255 | \ul -> Underline on 256 | \uldb -> Double Underline on 257 | \ulth -> Thick Underline on 258 | \ulw -> Underline words only on 259 | \ulwave -> Wave Underline on 260 | \uld -> Dotted Underline on 261 | \uldash -> Dash Underline on 262 | \uldashd -> Dot Dash Underline on 263 | \ul0 -> Any underline off 264 | 265 | 266 | --- 267 | 268 | 269 | #### ALIGNMENT 270 | 271 | 272 | \ql -> left 273 | \qr -> right 274 | \qc -> centered 275 | \qj -> justified 276 | 277 | 278 | --- 279 | 280 | 281 | #### RESET VALUES 282 | 283 | 284 | \pard -> reset tables configuration (\tx) 285 | \plain -> reset text size, style and font family to default 286 | 287 | 288 | --- 289 | 290 | 291 | #### FILE INFO 292 | 293 | 294 | {\info 295 | {\author John Doe} <- author name 296 | {\creatim\yr1990\mo7\dy30\hr10\min48} <- time stamp 297 | } 298 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.pch 68 | *.pdb 69 | *.pgc 70 | *.pgd 71 | *.rsp 72 | *.sbr 73 | *.tlb 74 | *.tli 75 | *.tlh 76 | *.tmp 77 | *.tmp_proj 78 | *.log 79 | *.vspscc 80 | *.vssscc 81 | .builds 82 | *.pidb 83 | *.svclog 84 | *.scc 85 | 86 | # Chutzpah Test files 87 | _Chutzpah* 88 | 89 | # Visual C++ cache files 90 | ipch/ 91 | *.aps 92 | *.ncb 93 | *.opendb 94 | *.opensdf 95 | *.sdf 96 | *.cachefile 97 | *.VC.db 98 | *.VC.VC.opendb 99 | 100 | # Visual Studio profiler 101 | *.psess 102 | *.vsp 103 | *.vspx 104 | *.sap 105 | 106 | # Visual Studio Trace Files 107 | *.e2e 108 | 109 | # TFS 2012 Local Workspace 110 | $tf/ 111 | 112 | # Guidance Automation Toolkit 113 | *.gpState 114 | 115 | # ReSharper is a .NET coding add-in 116 | _ReSharper*/ 117 | *.[Rr]e[Ss]harper 118 | *.DotSettings.user 119 | 120 | # JustCode is a .NET coding add-in 121 | .JustCode 122 | 123 | # TeamCity is a build add-in 124 | _TeamCity* 125 | 126 | # DotCover is a Code Coverage Tool 127 | *.dotCover 128 | 129 | # AxoCover is a Code Coverage Tool 130 | .axoCover/* 131 | !.axoCover/settings.json 132 | 133 | # Visual Studio code coverage results 134 | *.coverage 135 | *.coveragexml 136 | 137 | # NCrunch 138 | _NCrunch_* 139 | .*crunch*.local.xml 140 | nCrunchTemp_* 141 | 142 | # MightyMoose 143 | *.mm.* 144 | AutoTest.Net/ 145 | 146 | # Web workbench (sass) 147 | .sass-cache/ 148 | 149 | # Installshield output folder 150 | [Ee]xpress/ 151 | 152 | # DocProject is a documentation generator add-in 153 | DocProject/buildhelp/ 154 | DocProject/Help/*.HxT 155 | DocProject/Help/*.HxC 156 | DocProject/Help/*.hhc 157 | DocProject/Help/*.hhk 158 | DocProject/Help/*.hhp 159 | DocProject/Help/Html2 160 | DocProject/Help/html 161 | 162 | # Click-Once directory 163 | publish/ 164 | 165 | # Publish Web Output 166 | *.[Pp]ublish.xml 167 | *.azurePubxml 168 | # Note: Comment the next line if you want to checkin your web deploy settings, 169 | # but database connection strings (with potential passwords) will be unencrypted 170 | *.pubxml 171 | *.publishproj 172 | 173 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 174 | # checkin your Azure Web App publish settings, but sensitive information contained 175 | # in these scripts will be unencrypted 176 | PublishScripts/ 177 | 178 | # NuGet Packages 179 | *.nupkg 180 | # The packages folder can be ignored because of Package Restore 181 | **/[Pp]ackages/* 182 | # except build/, which is used as an MSBuild target. 183 | !**/[Pp]ackages/build/ 184 | # Uncomment if necessary however generally it will be regenerated when needed 185 | #!**/[Pp]ackages/repositories.config 186 | # NuGet v3's project.json files produces more ignorable files 187 | *.nuget.props 188 | *.nuget.targets 189 | 190 | # Microsoft Azure Build Output 191 | csx/ 192 | *.build.csdef 193 | 194 | # Microsoft Azure Emulator 195 | ecf/ 196 | rcf/ 197 | 198 | # Windows Store app package directories and files 199 | AppPackages/ 200 | BundleArtifacts/ 201 | Package.StoreAssociation.xml 202 | _pkginfo.txt 203 | *.appx 204 | 205 | # Visual Studio cache files 206 | # files ending in .cache can be ignored 207 | *.[Cc]ache 208 | # but keep track of directories ending in .cache 209 | !*.[Cc]ache/ 210 | 211 | # Others 212 | ClientBin/ 213 | ~$* 214 | *~ 215 | *.dbmdl 216 | *.dbproj.schemaview 217 | *.jfm 218 | *.pfx 219 | *.publishsettings 220 | orleans.codegen.cs 221 | 222 | # Including strong name files can present a security risk 223 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 224 | #*.snk 225 | 226 | # Since there are multiple workflows, uncomment next line to ignore bower_components 227 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 228 | #bower_components/ 229 | 230 | # RIA/Silverlight projects 231 | Generated_Code/ 232 | 233 | # Backup & report files from converting an old project file 234 | # to a newer Visual Studio version. Backup files are not needed, 235 | # because we have git ;-) 236 | _UpgradeReport_Files/ 237 | Backup*/ 238 | UpgradeLog*.XML 239 | UpgradeLog*.htm 240 | 241 | # SQL Server files 242 | *.mdf 243 | *.ldf 244 | *.ndf 245 | 246 | # Business Intelligence projects 247 | *.rdl.data 248 | *.bim.layout 249 | *.bim_*.settings 250 | 251 | # Microsoft Fakes 252 | FakesAssemblies/ 253 | 254 | # GhostDoc plugin setting file 255 | *.GhostDoc.xml 256 | 257 | # Node.js Tools for Visual Studio 258 | .ntvs_analysis.dat 259 | node_modules/ 260 | 261 | # TypeScript v1 declaration files 262 | typings/ 263 | 264 | # Visual Studio 6 build log 265 | *.plg 266 | 267 | # Visual Studio 6 workspace options file 268 | *.opt 269 | 270 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 271 | *.vbw 272 | 273 | # Visual Studio LightSwitch build output 274 | **/*.HTMLClient/GeneratedArtifacts 275 | **/*.DesktopClient/GeneratedArtifacts 276 | **/*.DesktopClient/ModelManifest.xml 277 | **/*.Server/GeneratedArtifacts 278 | **/*.Server/ModelManifest.xml 279 | _Pvt_Extensions 280 | 281 | # Paket dependency manager 282 | .paket/paket.exe 283 | paket-files/ 284 | 285 | # FAKE - F# Make 286 | .fake/ 287 | 288 | # JetBrains Rider 289 | .idea/ 290 | *.sln.iml 291 | 292 | # CodeRush 293 | .cr/ 294 | 295 | # Python Tools for Visual Studio (PTVS) 296 | __pycache__/ 297 | *.pyc 298 | 299 | # Cake - Uncomment if you are using it 300 | # tools/** 301 | # !tools/packages.config 302 | 303 | # Tabs Studio 304 | *.tss 305 | 306 | # Telerik's JustMock configuration file 307 | *.jmconfig 308 | 309 | # BizTalk build output 310 | *.btp.cs 311 | *.btm.cs 312 | *.odx.cs 313 | *.xsd.cs 314 | 315 | # OpenCover UI analysis results 316 | OpenCover/ 317 | 318 | # Azure Stream Analytics local run output 319 | ASALocalRun/ 320 | 321 | # MSBuild Binary and Structured Log 322 | *.binlog 323 | 324 | # misc 325 | .DS_Store 326 | -------------------------------------------------------------------------------- /RTFExporter/RTFDocument.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | 5 | namespace RTFExporter 6 | { 7 | /// 8 | /// The document margin 9 | /// 10 | public class Margin 11 | { 12 | public float left; 13 | public float right; 14 | public float top; 15 | public float bottom; 16 | 17 | /// 18 | /// Margin constructor. All values need to be declared 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | public Margin(float left, float right, float top, float bottom) 25 | { 26 | this.left = left; 27 | this.right = right; 28 | this.top = top; 29 | this.bottom = bottom; 30 | } 31 | } 32 | 33 | /// 34 | /// Page orientation setup 35 | /// 36 | public enum Orientation 37 | { 38 | Landscape, 39 | Portrait 40 | } 41 | 42 | /// 43 | /// Page measure units 44 | /// 45 | public enum Units 46 | { 47 | Inch, 48 | Millimeters, 49 | Centimeters 50 | } 51 | 52 | /// 53 | /// The RTF document, it is the main class and use a IDisposable interface 54 | /// 55 | public class RTFDocument : IDisposable 56 | { 57 | public List paragraphs = new List(); 58 | public List colors = new List(); 59 | public List fonts = new List(); 60 | public string author; 61 | public float width; 62 | public float height; 63 | public Orientation orientation; 64 | public Margin margin; 65 | public Units units; 66 | private FileStream fileStream; 67 | private StreamWriter streamWriter; 68 | public int version = 1; 69 | public List keywords = new List(); 70 | 71 | /// 72 | /// The simple RTF Document constructor without use streams 73 | /// 74 | public RTFDocument() 75 | { 76 | Init(8, 11, Orientation.Portrait, Units.Inch); 77 | } 78 | 79 | /// 80 | /// The RTF Document constructor with a file path 81 | /// 82 | /// A path to a folder with file name 83 | public RTFDocument(string path) 84 | { 85 | SetFile(path); 86 | Init(8, 11, Orientation.Portrait, Units.Inch); 87 | } 88 | 89 | /// 90 | /// The RTF Document constructor with a file stream 91 | /// 92 | /// A file stream 93 | public RTFDocument(FileStream fileStream) 94 | { 95 | SetStream(fileStream); 96 | Init(8, 11, Orientation.Portrait, Units.Inch); 97 | } 98 | 99 | /// 100 | /// RTF document constructor with setup parameters 101 | /// 102 | /// 103 | /// 104 | /// A path to a folder with file name 105 | /// the width of the page 106 | /// the height of the page 107 | /// the page orientation 108 | /// the measure units of the page 109 | public RTFDocument(string path, float width = 8, float height = 11, Orientation orientation = Orientation.Portrait, Units units = Units.Inch) 110 | { 111 | SetFile(path); 112 | Init(width, height, orientation, units); 113 | } 114 | 115 | /// 116 | /// RTF document constructor with setup parameters without use streams 117 | /// 118 | /// 119 | /// 120 | /// A file stream 121 | /// the width of the page 122 | /// the height of the page 123 | /// the page orientation 124 | /// the measure units of the page 125 | public RTFDocument(FileStream fileStream, float width = 8, float height = 11, Orientation orientation = Orientation.Portrait, Units units = Units.Inch) 126 | { 127 | SetStream(fileStream); 128 | Init(width, height, orientation, units); 129 | } 130 | 131 | /// 132 | /// RTF document constructor with setup parameters 133 | /// 134 | /// 135 | /// 136 | /// the width of the page 137 | /// the height of the page 138 | /// the page orientation 139 | /// the measure units of the page 140 | public RTFDocument(float width = 8, float height = 11, Orientation orientation = Orientation.Portrait, Units units = Units.Inch) 141 | { 142 | Init(width, height, orientation, units); 143 | } 144 | 145 | /// 146 | /// Set a file by path and allocate it stream 147 | /// 148 | /// A path to a folder with file name 149 | public void SetFile(string path) 150 | { 151 | fileStream = new FileStream(path, FileMode.Create); 152 | streamWriter = new StreamWriter(fileStream); 153 | } 154 | 155 | /// 156 | /// Use a file stream directly 157 | /// 158 | /// A file stream 159 | public void SetStream(FileStream fileStream) 160 | { 161 | this.fileStream = fileStream; 162 | streamWriter = new StreamWriter(fileStream); 163 | } 164 | 165 | /// 166 | /// RTF document init method to use after a simple constructor 167 | /// 168 | /// 169 | /// 170 | /// the width of the page 171 | /// the height of the page 172 | /// the page orientation 173 | /// the measure units of the page 174 | public void Init(float width, float height, Orientation orientation, Units units) 175 | { 176 | this.width = width; 177 | this.height = height; 178 | this.orientation = orientation; 179 | this.units = units; 180 | 181 | switch (units) 182 | { 183 | case Units.Inch: 184 | margin = new Margin(1, 1, 1, 1); 185 | break; 186 | case Units.Millimeters: 187 | margin = new Margin(25.4f, 25.4f, 25.4f, 25.4f); 188 | break; 189 | case Units.Centimeters: 190 | margin = new Margin(2.54f, 2.54f, 2.54f, 2.54f); 191 | break; 192 | } 193 | } 194 | 195 | /// 196 | /// A method to set the margin of the document 197 | /// 198 | /// 199 | /// 200 | /// 201 | /// 202 | public void SetMargin(float left, float right, float top, float bottom) 203 | { 204 | margin.left = left; 205 | margin.right = right; 206 | margin.top = top; 207 | margin.bottom = bottom; 208 | } 209 | 210 | /// 211 | /// Append a new paragraph to the document 212 | /// 213 | /// 214 | /// The appended paragraph 215 | public RTFParagraph AppendParagraph() 216 | { 217 | RTFParagraph paragraph = new RTFParagraph(this); 218 | return paragraph; 219 | } 220 | 221 | /// 222 | /// Append a new paragraph to the document 223 | /// 224 | /// 225 | /// 226 | /// A paragraph style object 227 | /// The appended paragraph 228 | public RTFParagraph AppendParagraph(RTFParagraphStyle style) 229 | { 230 | RTFParagraph paragraph = new RTFParagraph(this); 231 | paragraph.style = style; 232 | return paragraph; 233 | } 234 | 235 | /// 236 | /// Append a new paragraph to the document 237 | /// 238 | /// 239 | /// 240 | /// A paragraph alignment object 241 | /// The appended paragraph 242 | public RTFParagraph AppendParagraph(Alignment alignment) 243 | { 244 | RTFParagraph paragraph = new RTFParagraph(this); 245 | paragraph.style = new RTFParagraphStyle(alignment); 246 | return paragraph; 247 | } 248 | 249 | /// 250 | /// Append a new paragraph to the document 251 | /// 252 | /// 253 | /// 254 | /// A paragraph indent object 255 | /// The appended paragraph 256 | public RTFParagraph AppendParagraph(Indent indent) 257 | { 258 | return AppendParagraph(Alignment.Left, indent); 259 | } 260 | 261 | /// 262 | /// 263 | /// 264 | /// 265 | /// 266 | /// 267 | /// A paragraph alignment object 268 | /// A paragraph indent object 269 | /// The appended paragraph 270 | public RTFParagraph AppendParagraph(Alignment alignment, Indent indent) 271 | { 272 | RTFParagraph paragraph = new RTFParagraph(this); 273 | paragraph.style = new RTFParagraphStyle(alignment, indent); 274 | return paragraph; 275 | } 276 | 277 | /// 278 | /// Append a new paragraph to the document 279 | /// 280 | /// 281 | /// 282 | /// 283 | /// A paragraph alignment object 284 | /// A paragraph indent object 285 | /// The value of the vertical space before the paragraph 286 | /// The value of the vertical space after the paragraph 287 | /// The appended paragraph 288 | public RTFParagraph AppendParagraph(Alignment alignment, Indent indent, int spaceBefore, int spaceAfter) 289 | { 290 | RTFParagraph paragraph = new RTFParagraph(this); 291 | paragraph.style = new RTFParagraphStyle(alignment, indent, spaceBefore, spaceAfter); 292 | return paragraph; 293 | } 294 | 295 | /// 296 | /// Close the streams (StreamWriter, FileStream) 297 | /// 298 | public void Close() 299 | { 300 | streamWriter.Close(); 301 | fileStream.Close(); 302 | } 303 | 304 | /// 305 | /// Save the values to the file 306 | /// 307 | public void Save() 308 | { 309 | streamWriter.Write(RTFParser.ToString(this)); 310 | } 311 | 312 | /// 313 | /// The dispose routine. It save and close the streams (StreamWriter, FileStream) 314 | /// 315 | public void Dispose() 316 | { 317 | if (fileStream != null && streamWriter != null) 318 | { 319 | Save(); 320 | Close(); 321 | } 322 | } 323 | } 324 | } 325 | -------------------------------------------------------------------------------- /RTFExporter/RTFParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | 5 | namespace RTFExporter 6 | { 7 | /// 8 | /// The RTF parser class, it transform the RTFdocument into a file or string 9 | /// 10 | public class RTFParser 11 | { 12 | public static RTFDocument document; 13 | private static Dictionary fontsIndex = new Dictionary(); 14 | 15 | /// 16 | /// Create or rewrite a file with RTF content 17 | /// 18 | /// 19 | /// The folder path with filename 20 | /// The RTF document to save 21 | public static void ToFile(string path, RTFDocument document) 22 | { 23 | document.SetFile(path); 24 | document.Save(); 25 | document.Close(); 26 | } 27 | 28 | /// 29 | /// Write a content straight to a file 30 | /// 31 | /// The folder path with filename 32 | /// The file content 33 | public static void ToFile(string path, string content) 34 | { 35 | using(FileStream fs = new FileStream(path, FileMode.Create)) 36 | { 37 | using(StreamWriter writer = new StreamWriter(fs)) 38 | { 39 | writer.Write(content); 40 | } 41 | } 42 | } 43 | 44 | /// 45 | /// Return a rich text formatted string from a RTF document object 46 | /// 47 | /// 48 | /// The RTF document to be formatted 49 | /// A rich text formatted string 50 | public static string ToString(RTFDocument document) 51 | { 52 | RTFParser.document = document; 53 | 54 | string str = "{\\rtf1\\ansi\\deff0"; 55 | 56 | foreach (RTFParagraph paragraph in document.paragraphs) 57 | { 58 | foreach (RTFText text in paragraph.text) 59 | { 60 | document.colors.Add(text.style.color); 61 | 62 | if (text.style.fontFamily != string.Empty) 63 | { 64 | document.fonts.Add(text.style.fontFamily); 65 | } 66 | } 67 | } 68 | 69 | str += FontsParsing(); 70 | str += ColorParsing(); 71 | 72 | str += "{\\info {\\author " + document.author + "}"; 73 | DateTime date = DateTime.Now; 74 | str += "{\\creatim\\yr" + date.Year + "\\mo" + date.Month + "\\dy" + date.Day + "\\hr" + date.Hour + "\\min" + date.Minute + "}"; 75 | str += "{\\version" + document.version + "}"; 76 | str += "{\\edmins0}"; 77 | str += "{\\nofpages1}"; 78 | str += "{\\nofwords0}"; 79 | str += "{\\nofchars0}"; 80 | str += "}"; 81 | 82 | str += "{\\keywords "; 83 | 84 | foreach (string keyword in document.keywords) 85 | { 86 | str += keyword + " "; 87 | } 88 | 89 | str += "}"; 90 | 91 | switch (document.orientation) 92 | { 93 | case Orientation.Landscape: 94 | str += "\\landscape"; 95 | break; 96 | case Orientation.Portrait: 97 | str += "\\portrait"; 98 | break; 99 | } 100 | 101 | str += "\\paperw" + value(document.width) + "\\paperh" + value(document.height) + 102 | "\\margl" + value(document.margin.left) + "\\margr" + value(document.margin.right) + 103 | "\\margt" + value(document.margin.top) + "\\margb" + value(document.margin.bottom) + " "; 104 | 105 | str += ParagraphParsing(); 106 | 107 | str += "}"; 108 | return str; 109 | } 110 | 111 | private static string FontsParsing() 112 | { 113 | List fonts = new List(); 114 | 115 | foreach (string docFonts in document.fonts) 116 | { 117 | var add = true; 118 | 119 | foreach (string font in fonts) 120 | { 121 | if (font == docFonts) 122 | { 123 | add = false; 124 | break; 125 | } 126 | } 127 | 128 | if (add) 129 | { 130 | fonts.Add(docFonts); 131 | } 132 | } 133 | 134 | string str = "{\\fonttbl"; 135 | 136 | for (int i = 0; i < fonts.Count; i++) 137 | { 138 | str += "{\\f" + i + " " + fonts[i] + ";}"; 139 | try 140 | { 141 | fontsIndex.Add(fonts[i], i); 142 | } 143 | catch 144 | { 145 | // Font repeated 146 | } 147 | } 148 | 149 | str += "}"; 150 | 151 | return str; 152 | } 153 | 154 | private static string ColorParsing() 155 | { 156 | List colors = new List(); 157 | int j = 1; 158 | 159 | for (int i = 0; i < document.colors.Count; i++) 160 | { 161 | var add = true; 162 | 163 | foreach (Color color in colors) 164 | { 165 | if (color.r == document.colors[i].r && color.g == document.colors[i].g && color.b == document.colors[i].b) 166 | { 167 | add = false; 168 | break; 169 | } 170 | } 171 | 172 | if (add) 173 | { 174 | document.colors[i].index = j; 175 | j++; 176 | 177 | colors.Add(document.colors[i]); 178 | } 179 | } 180 | 181 | string str = "{\\colortbl;"; 182 | 183 | for (int i = 0; i < colors.Count; i++) 184 | { 185 | str += "\\red" + colors[i].r + "\\green" + colors[i].g + "\\blue" + colors[i].b + ";"; 186 | } 187 | 188 | str += "}"; 189 | 190 | return str; 191 | } 192 | 193 | private static string ParagraphParsing() 194 | { 195 | string str = ""; 196 | 197 | foreach (RTFParagraph paragraph in document.paragraphs) 198 | { 199 | str += "\\pard"; 200 | str += "\\sb" + paragraph.style.spaceBefore; 201 | str += "\\sa" + paragraph.style.spaceAfter; 202 | 203 | switch (paragraph.style.alignment) 204 | { 205 | case Alignment.Left: 206 | str += "\\ql"; 207 | break; 208 | case Alignment.Right: 209 | str += "\\qr"; 210 | break; 211 | case Alignment.Center: 212 | str += "\\qc"; 213 | break; 214 | case Alignment.Justified: 215 | str += "\\qj"; 216 | break; 217 | } 218 | 219 | str += "\\fi" + value(paragraph.style.indent.firstLine); 220 | str += "\\li" + value(paragraph.style.indent.left); 221 | str += "\\ri" + value(paragraph.style.indent.right); 222 | 223 | foreach (RTFText text in paragraph.text) 224 | { 225 | str += "\\plain "; 226 | 227 | if (text.style.italic) 228 | { 229 | str += "\\i "; 230 | } 231 | if (text.style.bold) 232 | { 233 | str += "\\b "; 234 | } 235 | if (text.style.smallCaps) 236 | { 237 | str += "\\scaps "; 238 | } 239 | if (text.style.allCaps) 240 | { 241 | str += "\\caps "; 242 | } 243 | if (text.style.strikeThrough) 244 | { 245 | str += "\\strike "; 246 | } 247 | if (text.style.outline) 248 | { 249 | str += "\\outl "; 250 | } 251 | 252 | switch (text.style.underline) 253 | { 254 | case Underline.Dash: 255 | str += "\\uldash "; 256 | break; 257 | case Underline.DotDash: 258 | str += "\\uldashd "; 259 | break; 260 | case Underline.Dotted: 261 | str += "\\uld "; 262 | break; 263 | case Underline.Double: 264 | str += "\\uldb "; 265 | break; 266 | case Underline.Thick: 267 | str += "\\ulth "; 268 | break; 269 | case Underline.Basic: 270 | str += "\\ul "; 271 | break; 272 | case Underline.Wave: 273 | str += "\\ulwave "; 274 | break; 275 | case Underline.WordsOnly: 276 | str += "\\ulw "; 277 | break; 278 | } 279 | 280 | str += "\\fs" + (2 * text.style.fontSize) + " "; 281 | str += "\\f" + fontsIndex[text.style.fontFamily] + " "; 282 | str += "\\cf" + text.style.color.index + " "; 283 | 284 | text.content = text.content.Replace("\n", "\\line "); 285 | text.content = text.content.Replace("\t", "\\tab "); 286 | text.content = text.content.Replace("", "\\i "); 287 | text.content = text.content.Replace("", "\\i0 "); 288 | text.content = text.content.Replace("", "\\b "); 289 | text.content = text.content.Replace("", "\\b0 "); 290 | text.content = text.content.Replace("€", "\\'80"); 291 | text.content = text.content.Replace("‚", "\\'82"); 292 | text.content = text.content.Replace("ƒ", "\\'83"); 293 | text.content = text.content.Replace("„", "\\'84"); 294 | text.content = text.content.Replace("…", "\\'85"); 295 | text.content = text.content.Replace("†", "\\'86"); 296 | text.content = text.content.Replace("‡", "\\'87"); 297 | text.content = text.content.Replace("ˆ", "\\'88"); 298 | text.content = text.content.Replace("‰", "\\'89"); 299 | text.content = text.content.Replace("Š", "\\'8A"); 300 | text.content = text.content.Replace("‹", "\\'8B"); 301 | text.content = text.content.Replace("Œ", "\\'8C"); 302 | text.content = text.content.Replace("Ž", "\\'8E"); 303 | text.content = text.content.Replace("‘", "\\'91"); 304 | text.content = text.content.Replace("’", "\\'92"); 305 | text.content = text.content.Replace("“", "\\'93"); 306 | text.content = text.content.Replace("”", "\\'94"); 307 | text.content = text.content.Replace("•", "\\'95"); 308 | text.content = text.content.Replace("–", "\\'96"); 309 | text.content = text.content.Replace("—", "\\'97"); 310 | text.content = text.content.Replace("˜", "\\'98"); 311 | text.content = text.content.Replace("™", "\\'99"); 312 | text.content = text.content.Replace("š", "\\'9A"); 313 | text.content = text.content.Replace("›", "\\'9B"); 314 | text.content = text.content.Replace("œ", "\\'9C"); 315 | text.content = text.content.Replace("ž", "\\'9E"); 316 | text.content = text.content.Replace("Ÿ", "\\'9F"); 317 | text.content = text.content.Replace("¡", "\\'A1"); 318 | text.content = text.content.Replace("¢", "\\'A2"); 319 | text.content = text.content.Replace("£", "\\'A3"); 320 | text.content = text.content.Replace("¤", "\\'A4"); 321 | text.content = text.content.Replace("¥", "\\'A5"); 322 | text.content = text.content.Replace("¦", "\\'A6"); 323 | text.content = text.content.Replace("§", "\\'A7"); 324 | text.content = text.content.Replace("¨", "\\'A8"); 325 | text.content = text.content.Replace("©", "\\'A9"); 326 | text.content = text.content.Replace("ª", "\\'AA"); 327 | text.content = text.content.Replace("«", "\\'AB"); 328 | text.content = text.content.Replace("¬", "\\'AC"); 329 | text.content = text.content.Replace("®", "\\'AE"); 330 | text.content = text.content.Replace("¯", "\\'AF"); 331 | text.content = text.content.Replace("°", "\\'B0"); 332 | text.content = text.content.Replace("±", "\\'B1"); 333 | text.content = text.content.Replace("²", "\\'B2"); 334 | text.content = text.content.Replace("³", "\\'B3"); 335 | text.content = text.content.Replace("´", "\\'B4"); 336 | text.content = text.content.Replace("µ", "\\'B5"); 337 | text.content = text.content.Replace("¶", "\\'B6"); 338 | text.content = text.content.Replace("·", "\\'B7"); 339 | text.content = text.content.Replace("¸", "\\'B8"); 340 | text.content = text.content.Replace("¹", "\\'B9"); 341 | text.content = text.content.Replace("º", "\\'BA"); 342 | text.content = text.content.Replace("»", "\\'BB"); 343 | text.content = text.content.Replace("¼", "\\'BC"); 344 | text.content = text.content.Replace("½", "\\'BD"); 345 | text.content = text.content.Replace("¾", "\\'BE"); 346 | text.content = text.content.Replace("¿", "\\'BF"); 347 | text.content = text.content.Replace("À", "\\'C0"); 348 | text.content = text.content.Replace("Á", "\\'C1"); 349 | text.content = text.content.Replace("Â", "\\'C2"); 350 | text.content = text.content.Replace("Ã", "\\'C3"); 351 | text.content = text.content.Replace("Ä", "\\'C4"); 352 | text.content = text.content.Replace("Å", "\\'C5"); 353 | text.content = text.content.Replace("Æ", "\\'C6"); 354 | text.content = text.content.Replace("Ç", "\\'C7"); 355 | text.content = text.content.Replace("È", "\\'C8"); 356 | text.content = text.content.Replace("É", "\\'C9"); 357 | text.content = text.content.Replace("Ê", "\\'CA"); 358 | text.content = text.content.Replace("Ë", "\\'CB"); 359 | text.content = text.content.Replace("Ì", "\\'CC"); 360 | text.content = text.content.Replace("Í", "\\'CD"); 361 | text.content = text.content.Replace("Î", "\\'CE"); 362 | text.content = text.content.Replace("Ï", "\\'CF"); 363 | text.content = text.content.Replace("Ð", "\\'D0"); 364 | text.content = text.content.Replace("Ñ", "\\'D1"); 365 | text.content = text.content.Replace("Ò", "\\'D2"); 366 | text.content = text.content.Replace("Ó", "\\'D3"); 367 | text.content = text.content.Replace("Ô", "\\'D4"); 368 | text.content = text.content.Replace("Õ", "\\'D5"); 369 | text.content = text.content.Replace("Ö", "\\'D6"); 370 | text.content = text.content.Replace("×", "\\'D7"); 371 | text.content = text.content.Replace("Ø", "\\'D8"); 372 | text.content = text.content.Replace("Ù", "\\'D9"); 373 | text.content = text.content.Replace("Ú", "\\'DA"); 374 | text.content = text.content.Replace("Û", "\\'DB"); 375 | text.content = text.content.Replace("Ü", "\\'DC"); 376 | text.content = text.content.Replace("Ý", "\\'DD"); 377 | text.content = text.content.Replace("Þ", "\\'DE"); 378 | text.content = text.content.Replace("ß", "\\'DF"); 379 | text.content = text.content.Replace("à", "\\'E0"); 380 | text.content = text.content.Replace("á", "\\'E1"); 381 | text.content = text.content.Replace("â", "\\'E2"); 382 | text.content = text.content.Replace("ã", "\\'E3"); 383 | text.content = text.content.Replace("ä", "\\'E4"); 384 | text.content = text.content.Replace("å", "\\'E5"); 385 | text.content = text.content.Replace("æ", "\\'E6"); 386 | text.content = text.content.Replace("ç", "\\'E7"); 387 | text.content = text.content.Replace("è", "\\'E8"); 388 | text.content = text.content.Replace("é", "\\'E9"); 389 | text.content = text.content.Replace("ê", "\\'EA"); 390 | text.content = text.content.Replace("ë", "\\'EB"); 391 | text.content = text.content.Replace("ì", "\\'EC"); 392 | text.content = text.content.Replace("í", "\\'ED"); 393 | text.content = text.content.Replace("î", "\\'EE"); 394 | text.content = text.content.Replace("ï", "\\'EF"); 395 | text.content = text.content.Replace("ð", "\\'F0"); 396 | text.content = text.content.Replace("ñ", "\\'F1"); 397 | text.content = text.content.Replace("ò", "\\'F2"); 398 | text.content = text.content.Replace("ó", "\\'F3"); 399 | text.content = text.content.Replace("ô", "\\'F4"); 400 | text.content = text.content.Replace("õ", "\\'F5"); 401 | text.content = text.content.Replace("ö", "\\'F6"); 402 | text.content = text.content.Replace("÷", "\\'F7"); 403 | text.content = text.content.Replace("ø", "\\'F8"); 404 | text.content = text.content.Replace("ù", "\\'F9"); 405 | text.content = text.content.Replace("ú", "\\'FA"); 406 | text.content = text.content.Replace("û", "\\'FB"); 407 | text.content = text.content.Replace("ü", "\\'FC"); 408 | text.content = text.content.Replace("ý", "\\'FD"); 409 | text.content = text.content.Replace("þ", "\\'FE"); 410 | text.content = text.content.Replace("ÿ", "\\'FF"); 411 | 412 | str += text.content; 413 | } 414 | 415 | str += "\\par "; 416 | } 417 | 418 | return str; 419 | } 420 | 421 | private static int value(float i) 422 | { 423 | float result = 0; 424 | 425 | switch (document.units) 426 | { 427 | case Units.Inch: 428 | result = i * 1440; 429 | break; 430 | case Units.Millimeters: 431 | result = (i / 25.4f) * 1440; 432 | break; 433 | case Units.Centimeters: 434 | result = (i / 2.54f) * 1440; 435 | break; 436 | } 437 | 438 | return (int) Math.Ceiling(result); 439 | } 440 | } 441 | } 442 | --------------------------------------------------------------------------------