private void HandleOptDest(RTF rtf) { int group_levels = 1; while (true) { GetToken(); // Here is where we should handle recognised optional // destinations. // // Handle a picture group // if (rtf.CheckCMM(TokenClass.Control, Major.Destination, Minor.Pict)) { ReadPictGroup(rtf); return; } if (rtf.CheckCM(TokenClass.Group, Major.EndGroup)) { if ((--group_levels) == 0) { break; } } if (rtf.CheckCM(TokenClass.Group, Major.BeginGroup)) { group_levels++; } } }
public Stream SetToSameSize(Stream stream, int size) { stream.Position = 0; Parser.RTF rtf = new Parser.RTF(stream); var replaceList = new List <Record <int, int, byte[]> >(); rtf.ClassCallback[TokenClass.Control] = (r) => { if (r.Major == Major.CharAttr && r.Minor == Minor.FontSize) { var len = r.Param.ToString().Length; replaceList.Add(new Record <int, int, byte[]>( r.CharPos - len, len, Encoding.ASCII.GetBytes(size.ToString()))); } }; rtf.Read(); if (replaceList.Count > 0) { replaceList.Sort((a, b) => { return(a.One - b.One); }); return(Replace(stream, replaceList)); } else { stream.Position = 0; return(stream); } }
//static IDictionary<string, Parser.KeyStruct> _keyTable = null; //public static IDictionary<string,Parser.KeyStruct> KeyTable { // get { // if(_keyTable ==null) { // KeyStruct[] keys = KeysInit.Init (); // _keyTable = new Dictionary<string, Parser.KeyStruct> (keys.Length); // foreach(var s in keys){ // } // } // return _keyTable; // } //} public string GetDoccom(Stream stream) { stream.Position = 0; Parser.RTF rtf = new Parser.RTF(stream); bool infoStarted = false; bool doccomStarted = false; int headerGroupCount = 0; rtf.ClassCallback[TokenClass.Group] = (r) => { if (r.Major == Major.BeginGroup) { headerGroupCount++; } else if (r.Major == Major.EndGroup) { headerGroupCount--; if (infoStarted) { infoStarted = headerGroupCount > 1; } doccomStarted = false; } }; rtf.DestinationCallback = new DestinationCallback(); rtf.DestinationCallback[Minor.Info] = (r) => { infoStarted = true; }; rtf.DestinationCallback[Minor.IDoccomm] = (r) => { doccomStarted = true; }; StringBuilder info = new StringBuilder(); rtf.ClassCallback[TokenClass.Text] = (r) => { if (doccomStarted) { info.Append(r.EncodedText); } }; while (rtf.GetToken() != TokenClass.EOF && headerGroupCount >= 0) { rtf.RouteToken(); } stream.Position = 0; return(info.ToString()); }
private void ReadColorTbl(RTF rtf) { Color color; int num; num = 0; while (true) { rtf.GetToken(); if (rtf.CheckCM(TokenClass.Group, Major.EndGroup)) { break; } color = new Color(rtf); color.Num = num++; while (rtf.CheckCM(TokenClass.Control, Major.ColorName)) { switch (rtf.minor) { case Minor.Red: { color.Red = rtf.param; break; } case Minor.Green: { color.Green = rtf.param; break; } case Minor.Blue: { color.Blue = rtf.param; break; } } rtf.GetToken(); } if (!rtf.CheckCM(TokenClass.Text, (Major)';')) { throw new RTFException(rtf, "Malformed color entry"); } } rtf.RouteToken(); }
public Stream SetToSameFont(Stream stream, string fontName) { stream.Position = 0; Parser.RTF rtf = new Parser.RTF(stream); var replaceList = new List <Record <int, int, byte[]> >(); bool isInFontTbl = false; bool isInFontDef = false; bool firstFont = false; int fontNamePos = 0; int otherFontsStartPos = 0; int otherFontsEndPos = 0; StringBuilder fontNameB = null; int fontGroups = 0; rtf.DestinationCallback[Minor.FontTbl] = (r) => { isInFontTbl = true; isInFontDef = true; fontGroups = 1; }; rtf.ClassCallback[TokenClass.Control] = (r) => { if (isInFontDef) { if (r.Major == Major.CharAttr && r.Minor == Minor.FontNum && r.Param == 0) { firstFont = true; otherFontsStartPos = 0; } } else if (otherFontsStartPos != 0) { if (r.Major == Major.CharAttr && r.Minor == Minor.FontNum) { var len = r.Param.ToString().Length; replaceList.Add(new Record <int, int, byte[]>( r.CharPos - len, len, // the ";" Encoding.ASCII.GetBytes("0") )); } } }; rtf.ClassCallback[TokenClass.Group] = (r) => { if (isInFontTbl) { if (r.Major == Major.BeginGroup) { fontGroups++; isInFontDef = fontGroups == 2; if (isInFontDef && otherFontsStartPos == 0) { otherFontsStartPos = r.CharPos; } } if (r.Major == Major.EndGroup) { fontGroups--; isInFontDef = fontGroups == 2; isInFontTbl = fontGroups > 0; if (firstFont && fontGroups == 1) { fontNameB.Remove(fontNameB.Length - 1, 1); if (fontNameB.ToString() != fontName) { replaceList.Add(new Record <int, int, byte[]>( fontNamePos, fontNameB.Length, // the ";" Encoding.ASCII.GetBytes(fontName) )); firstFont = false; } } else if (fontGroups == 1) { otherFontsEndPos = r.CharPos; } else { if (fontGroups == 0 && otherFontsStartPos != 0) { replaceList.Add(new Record <int, int, byte[]>( otherFontsStartPos, otherFontsEndPos - otherFontsStartPos + 1, null )); } } } } }; rtf.ClassCallback[TokenClass.Text] = (r) => { if (isInFontDef && firstFont) { if (fontNameB == null) { fontNamePos = r.CharPos; fontNameB = new StringBuilder(); } fontNameB.Append(r.EncodedText); } }; rtf.Read(); if (replaceList.Count > 0) { replaceList.Sort((a, b) => { return(a.One - b.One); }); return(Replace(stream, replaceList)); } else { stream.Position = 0; return(stream); } return(stream); }
public Stream SetAttributes(Stream stream, FontStyle style) { stream.Position = 0; Parser.RTF rtf = new Parser.RTF(stream); var replaceList = new List <Record <int, int, byte[]> >(); // the parser is in the text (not in a paragraph definition) bool textRun = false; // the style gathered by CharAttrs FontStyle runningStyle = default(FontStyle); // the style gathered in the first paragaph FontStyle givenStyle = default(FontStyle); // the style to add to the paragraph definition // and to delete in the text run FontStyle paraStyle = default(FontStyle); FontStyle styleToApply = default(FontStyle); int parDefPos = 0; int stylePos = 0; bool firstPara = true; Action <FontStyle, Parser.RTF> remove = (fstyle, r) => { if (textRun && (paraStyle & fstyle) != 0) { var len = r.Text.Length; replaceList.Add(new Record <int, int, byte[]>( r.CharPos - len, len, null)); } if (fstyle == style) { stylePos = r.CharPos; } }; rtf.ClassCallback[TokenClass.Control] = (r) => { if (r.Major == Major.ParAttr) { if (r.Minor == Minor.ParDef) { parDefPos = r.CharPos; } textRun = false; } if (r.Major == Major.CharAttr) { bool replaceIt = false; bool removeIt = false; string replace = null; if (r.Minor == Minor.Bold) { if (r.Param == 0) // bold end { runningStyle &= FontStyle.AllStyles ^ FontStyle.Bold; } else { runningStyle |= FontStyle.Bold; } remove(FontStyle.Bold, r); } if (r.Minor == Minor.Italic) { if (r.Param == 0) // Italic end { runningStyle &= FontStyle.AllStyles ^ FontStyle.Italic; } else { runningStyle |= FontStyle.Italic; } remove(FontStyle.Italic, r); } if (r.Minor == Minor.Underline) { runningStyle |= FontStyle.Underline; remove(FontStyle.Underline, r); } if (r.Minor == Minor.NoUnderline) { runningStyle &= FontStyle.AllStyles ^ FontStyle.Underline; remove(FontStyle.Underline, r); } if (r.Minor == Minor.Plain) // what to do with this?? { } if (replaceIt || removeIt) { var len = r.Param.ToString().Length; byte[] bReplace = null; if (replace != null) { bReplace = Encoding.ASCII.GetBytes(replace); } replaceList.Add(new Record <int, int, byte[]>( r.CharPos - len, len, bReplace)); } } }; int groupLevel = 0; rtf.ClassCallback[TokenClass.Group] = (r) => { if (r.Major == Major.BeginGroup) { groupLevel++; } if (r.Major == Major.EndGroup) { if (r.Minor == Minor.Par) // paragraph end?? { ; } groupLevel--; } }; rtf.ClassCallback[TokenClass.Text] = (r) => { if (!textRun) { if (firstPara) { givenStyle = runningStyle; firstPara = false; } styleToApply = runningStyle ^ style; paraStyle = styleToApply ^ runningStyle; string rtfStyle = ""; if (style == FontStyle.Italic) { rtfStyle = @"\i"; } if (style == FontStyle.Bold) { rtfStyle = @"\b"; } if (style == FontStyle.Underline) { rtfStyle = @"\ul"; } if ((runningStyle & style) == 0) { // the style has to be added: replaceList.Add(new Record <int, int, byte[]>( parDefPos, 0, Encoding.ASCII.GetBytes(rtfStyle) )); } else { // toogle; the style has to be removed from paragraph var len = rtfStyle.Length; replaceList.Add(new Record <int, int, byte[]>( stylePos - len, len, null )); } runningStyle = default(FontStyle); } textRun = true; }; rtf.Read(); if (replaceList.Count > 0) { replaceList.Sort((a, b) => { return(a.One - b.One); }); return(Replace(stream, replaceList)); } else { stream.Position = 0; return(stream); } }
public Stream SetDoccom(Stream stream, string infoText) { stream.Position = 0; Parser.RTF rtf = new Parser.RTF(stream); int infoPos = -1; int infoEndPos = -1; int firstHeaderGroupPos = -1; int headerGroupCount = 0; int doccomPos = -1; int doccomEndPos = -1; rtf.ClassCallback[TokenClass.Group] = (r) => { if (r.Major == Major.BeginGroup) { headerGroupCount++; if (headerGroupCount == 2) { firstHeaderGroupPos = r.CharPos; } } else if (r.Major == Major.EndGroup) { headerGroupCount--; if (infoPos > 0 && headerGroupCount == 1) { infoEndPos = r.CharPos; } if (doccomPos > 0) { doccomEndPos = r.CharPos; } } }; rtf.DestinationCallback = new DestinationCallback(); rtf.DestinationCallback[Minor.Info] = (r) => { infoPos = r.CharPos; }; rtf.DestinationCallback[Minor.IDoccomm] = (r) => { doccomPos = r.CharPos; }; StringBuilder info = new StringBuilder(); rtf.ClassCallback[TokenClass.Text] = (r) => { if (doccomPos > 0 && doccomEndPos == -1) { info.Append(r.EncodedText); } }; while (rtf.GetToken() != TokenClass.EOF && headerGroupCount >= 0) { rtf.RouteToken(); } stream.Position = 0; var replaceList = new List <Record <int, int, byte[]> >(); if (infoPos > 0) { if (doccomPos > 0) { replaceList.Add(new Record <int, int, byte[]>( doccomPos + 1, info.Length, Encoding.ASCII.GetBytes(infoText))); } else { replaceList.Add(new Record <int, int, byte[]> ( infoPos, 0, Encoding.ASCII.GetBytes("{\\doccomm " + infoText + "}"))); } } else { replaceList.Add(new Record <int, int, byte[]>( firstHeaderGroupPos, 0, Encoding.ASCII.GetBytes("{\\info{\\doccomm " + infoText + "}}"))); } return(Replace(stream, replaceList)); }
private void ReadStyleSheet(RTF rtf) { Style style; StringBuilder sb; sb = new StringBuilder(); while (true) { rtf.GetToken(); if (rtf.CheckCM(TokenClass.Group, Major.EndGroup)) { break; } style = new Style(rtf); if (!rtf.CheckCM(TokenClass.Group, Major.BeginGroup)) { throw new RTFException(rtf, "Missing \"{\""); } while (true) { rtf.GetToken(); if ((rtf.rtf_class == TokenClass.EOF) || rtf.CheckCM(TokenClass.Text, (Major)';')) { break; } if (rtf.rtf_class == TokenClass.Control) { if (rtf.CheckMM(Major.ParAttr, Minor.StyleNum)) { style.Num = rtf.param; style.Type = StyleType.Paragraph; continue; } if (rtf.CheckMM(Major.CharAttr, Minor.CharStyleNum)) { style.Num = rtf.param; style.Type = StyleType.Character; continue; } if (rtf.CheckMM(Major.StyleAttr, Minor.SectStyleNum)) { style.Num = rtf.param; style.Type = StyleType.Section; continue; } if (rtf.CheckMM(Major.StyleAttr, Minor.BasedOn)) { style.BasedOn = rtf.param; continue; } if (rtf.CheckMM(Major.StyleAttr, Minor.Additive)) { style.Additive = true; continue; } if (rtf.CheckMM(Major.StyleAttr, Minor.Next)) { style.NextPar = rtf.param; continue; } new StyleElement(style, rtf.rtf_class, rtf.major, rtf.minor, rtf.param, rtf.text_buffer.ToString()); } else if (rtf.CheckCM(TokenClass.Group, Major.BeginGroup)) { // This passes over "{\*\keycode ... }, among other things rtf.SkipGroup(); } else if (rtf.rtf_class == TokenClass.Text) { var name = new StringBuilder(); while (rtf.rtf_class == TokenClass.Text) { if (rtf.major == (Major)';') { rtf.UngetToken(); break; } sb.Append((char)rtf.major); name.Append((char)rtf.major); rtf.GetToken(); } style.InternalName = sb.ToString(); style.Name = name.ToString(); #if RTF_DEBUG } else { Console.WriteLine("ReadStyleSheet: Ignored token " + rtf.text_buffer); #endif } } rtf.GetToken(); if (!rtf.CheckCM(TokenClass.Group, Major.EndGroup)) { throw new RTFException(rtf, "Missing EndGroup (\"}\""); } // Sanity checks if (style.InternalName == null) { throw new RTFException(rtf, "Style must have name"); } if (style.Num < 0) { if (!sb.ToString().StartsWith("Normal") && !sb.ToString().StartsWith("Standard")) { throw new RTFException(rtf, "Missing style number"); } style.Num = Style.NormalStyleNum; } if (style.NextPar == -1) { style.NextPar = style.Num; } } rtf.RouteToken(); }
public void ReadFontTbl(RTF rtf) { int old; Font font; old = -1; font = null; while (true) { rtf.GetToken(); if (rtf.CheckCM(TokenClass.Group, Major.EndGroup)) { break; } if (old < 0) { if (rtf.CheckCMM(TokenClass.Control, Major.CharAttr, Minor.FontNum)) { old = 1; } else if (rtf.CheckCM(TokenClass.Group, Major.BeginGroup)) { old = 0; } else { throw new RTFException(rtf, "Cannot determine format"); } } if (old == 0) { if (!rtf.CheckCM(TokenClass.Group, Major.BeginGroup)) { throw new RTFException(rtf, "missing \"{\""); } rtf.GetToken(); } font = new Font(rtf); while ((rtf.rtf_class != TokenClass.EOF) && (!rtf.CheckCM(TokenClass.Text, (Major)';')) && (!rtf.CheckCM(TokenClass.Group, Major.EndGroup))) { if (rtf.rtf_class == TokenClass.Control) { switch (rtf.major) { case Major.FontFamily: { font.Family = (int)rtf.minor; break; } case Major.CharAttr: { switch (rtf.minor) { case Minor.FontNum: { font.Num = rtf.param; break; } default: { #if RTF_DEBUG Console.WriteLine("Got unhandled Control.CharAttr.Minor: " + rtf.minor); #endif break; } } break; } case Major.FontAttr: { switch (rtf.minor) { case Minor.FontCharSet: { font.Charset = (CharsetType)rtf.param; break; } case Minor.FontPitch: { font.Pitch = rtf.param; break; } case Minor.FontCodePage: { font.Codepage = rtf.param; break; } case Minor.FTypeNil: case Minor.FTypeTrueType: { font.Type = rtf.param; break; } default: { #if RTF_DEBUG Console.WriteLine("Got unhandled Control.FontAttr.Minor: " + rtf.minor); #endif break; } } break; } default: { #if RTF_DEBUG Console.WriteLine("ReadFontTbl: Unknown Control token " + rtf.major); #endif break; } } } else if (rtf.CheckCM(TokenClass.Group, Major.BeginGroup)) { rtf.SkipGroup(); } else if (rtf.rtf_class == TokenClass.Text) { StringBuilder sb; sb = new StringBuilder(); while ((rtf.rtf_class != TokenClass.EOF) && (!rtf.CheckCM(TokenClass.Text, (Major)';')) && (!rtf.CheckCM(TokenClass.Group, Major.EndGroup)) && (!rtf.CheckCM(TokenClass.Group, Major.BeginGroup))) { sb.Append((char)rtf.major); rtf.GetToken(); } if (rtf.CheckCM(TokenClass.Group, Major.EndGroup)) { rtf.UngetToken(); } font.Name = sb.ToString(); continue; #if RTF_DEBUG } else { Console.WriteLine("ReadFontTbl: Unknown token " + rtf.text_buffer); #endif } rtf.GetToken(); } if (old == 0) { rtf.GetToken(); if (!rtf.CheckCM(TokenClass.Group, Major.EndGroup)) { throw new RTFException(rtf, "Missing \"}\""); } } } if (font == null) { throw new RTFException(rtf, "No font created"); } if (font.Num == -1) { throw new RTFException(rtf, "Missing font number"); } rtf.RouteToken(); }
private void ReadObjGroup(RTF rtf) { rtf.SkipGroup(); rtf.RouteToken(); }
private void ReadPictGroup(RTF rtf) { bool read_image_data = false; Picture picture = new Picture(); while (true) { rtf.GetToken(); if (rtf.CheckCM(TokenClass.Group, Major.EndGroup)) { break; } switch (minor) { case Minor.PngBlip: picture.ImageType = minor; read_image_data = true; break; case Minor.WinMetafile: picture.ImageType = minor; read_image_data = true; continue; case Minor.PicWid: continue; case Minor.PicHt: continue; case Minor.PicGoalWid: picture.SetWidthFromTwips(param); continue; case Minor.PicGoalHt: picture.SetHeightFromTwips(param); continue; } if (read_image_data && rtf.rtf_class == TokenClass.Text) { picture.Data.Seek(0, SeekOrigin.Begin); //char c = (char) rtf.major; uint digitValue1; uint digitValue2; char hexDigit1 = (char)rtf.major; char hexDigit2; while (true) { while (hexDigit1 == '\n' || hexDigit1 == '\r') { hexDigit1 = (char)source.Peek(); if (hexDigit1 == '}') { break; } hexDigit1 = (char)source.Read(); } hexDigit2 = (char)source.Peek(); if (hexDigit2 == '}') { break; } hexDigit2 = (char)source.Read(); while (hexDigit2 == '\n' || hexDigit2 == '\r') { hexDigit2 = (char)source.Peek(); if (hexDigit2 == '}') { break; } hexDigit2 = (char)source.Read(); } if (Char.IsDigit(hexDigit1)) { digitValue1 = (uint)(hexDigit1 - '0'); } else if (Char.IsLower(hexDigit1)) { digitValue1 = (uint)(hexDigit1 - 'a' + 10); } else if (Char.IsUpper(hexDigit1)) { digitValue1 = (uint)(hexDigit1 - 'A' + 10); } else if (hexDigit1 == '\n' || hexDigit1 == '\r') { continue; } else { break; } if (Char.IsDigit(hexDigit2)) { digitValue2 = (uint)(hexDigit2 - '0'); } else if (Char.IsLower(hexDigit2)) { digitValue2 = (uint)(hexDigit2 - 'a' + 10); } else if (Char.IsUpper(hexDigit2)) { digitValue2 = (uint)(hexDigit2 - 'A' + 10); } else if (hexDigit2 == '\n' || hexDigit2 == '\r') { continue; } else { break; } picture.Data.WriteByte((byte)checked (digitValue1 * 16 + digitValue2)); // We get the first hex digit at the end, since in the very first // iteration we use rtf.major as the first hex digit hexDigit1 = (char)source.Peek(); if (hexDigit1 == '}') { break; } hexDigit1 = (char)source.Read(); } read_image_data = false; break; } } if (picture.ImageType != Minor.Undefined && !read_image_data) { this.picture = picture; SetToken(TokenClass.Control, Major.PictAttr, picture.ImageType, 0, String.Empty); } }
public Stream RemoveAdobeParagraphTags(Stream stream) { stream.Position = 0; Parser.RTF rtf = new Parser.RTF(stream); bool newPara = false; int adobeTagPos = -1; int tcTagPos = -1; int groupStartPos = -1; var removeList = new List <Pair <int, int> >(); rtf.ClassCallback[TokenClass.Control] = (r) => { if (rtf.Minor == Minor.ParDef) { newPara = true; } if (rtf.Text == @"\tc") { tcTagPos = r.CharPos; } adobeTagPos = -1; }; rtf.ClassCallback[TokenClass.Group] = (r) => { adobeTagPos = -1; char s = r.Text[0]; if (r.Major == Major.BeginGroup) { groupStartPos = r.CharPos; } else if (r.Major == Major.EndGroup) { if (tcTagPos > 0) { removeList.Add(new Pair <int, int>(groupStartPos, tcTagPos - 1)); removeList.Add(new Pair <int, int>(r.CharPos, r.CharPos)); tcTagPos = -1; } } }; rtf.ClassCallback[TokenClass.Text] = (r) => { char s = r.Text[0]; if (newPara && s == '<') { adobeTagPos = rtf.CharPos; } else if (adobeTagPos > 0 && s == '>') { removeList.Add(new Pair <int, int>(adobeTagPos, rtf.CharPos)); adobeTagPos = -1; } newPara = false; }; rtf.Read(); if (removeList.Count > 0) { removeList.Sort((a, b) => { return(a.One - b.One); }); return(Remove(stream, removeList)); } else { stream.Position = 0; return(stream); } }