} // DoGroupBegin // ---------------------------------------------------------------------- public void TagFound(IRtfTag tag) { if (tag != null) { DoTagFound(tag); } } // TagFound
} // IsSupportedDocument // ---------------------------------------------------------------------- public static IRtfGroup GetSupportedDocument(IRtfGroup rtfDocument) { if (rtfDocument == null) { throw new ArgumentNullException("rtfDocument"); } if (rtfDocument.Contents.Count == 0) { throw new RtfEmptyDocumentException(Strings.EmptyDocument); } IRtfElement firstElement = rtfDocument.Contents[0]; if (firstElement.Kind != RtfElementKind.Tag) { throw new RtfStructureException(Strings.MissingDocumentStartTag); } IRtfTag firstTag = (IRtfTag)firstElement; if (!RtfSpec.TagRtf.Equals(firstTag.Name)) { throw new RtfStructureException(Strings.InvalidDocumentStartTag(RtfSpec.TagRtf)); } if (!firstTag.HasValue) { throw new RtfUnsupportedStructureException(Strings.MissingRtfVersion); } if (firstTag.ValueAsNumber != RtfSpec.RtfVersion1) { throw new RtfUnsupportedStructureException(Strings.UnsupportedRtfVersion(firstTag.ValueAsNumber)); } return(rtfDocument); } // GetSupportedDocument
// ---------------------------------------------------------------------- public void VisitTag( IRtfTag tag ) { if ( tag != null ) { DoVisitTag( tag ); } }
} // RtfElementVisitorBase public void VisitTag(IRtfTag tag) { if (tag != null) { DoVisitTag(tag); } } // VisitTag
// ---------------------------------------------------------------------- public void TagFound( IRtfTag tag ) { if ( tag != null ) { DoTagFound( tag ); } }
} // HandleTag // ---------------------------------------------------------------------- private void UpdateEncoding(IRtfTag tag) { switch (tag.Name) { case RtfSpec.TagEncodingAnsi: UpdateEncoding(RtfSpec.AnsiCodePage); break; case RtfSpec.TagEncodingMac: UpdateEncoding(10000); break; case RtfSpec.TagEncodingPc: UpdateEncoding(437); break; case RtfSpec.TagEncodingPca: UpdateEncoding(850); break; case RtfSpec.TagEncodingAnsiCodePage: UpdateEncoding(tag.ValueAsNumber); break; } } // UpdateEncoding
} // DoVisitGroup protected override void DoVisitTag(IRtfTag tag) { switch (tag.Name) { case RtfSpec.TagPictureFormatWinDib: case RtfSpec.TagPictureFormatWinBmp: Format = RtfVisualImageFormat.Bmp; break; case RtfSpec.TagPictureFormatEmf: Format = RtfVisualImageFormat.Emf; break; case RtfSpec.TagPictureFormatJpg: Format = RtfVisualImageFormat.Jpg; break; case RtfSpec.TagPictureFormatPng: Format = RtfVisualImageFormat.Png; break; case RtfSpec.TagPictureFormatWmf: Format = RtfVisualImageFormat.Wmf; break; case RtfSpec.TagPictureWidth: Width = Math.Abs(tag.ValueAsNumber); DesiredWidth = Width; break; case RtfSpec.TagPictureHeight: Height = Math.Abs(tag.ValueAsNumber); DesiredHeight = Height; break; case RtfSpec.TagPictureWidthGoal: DesiredWidth = Math.Abs(tag.ValueAsNumber); if (Width == 0) { Width = DesiredWidth; } break; case RtfSpec.TagPictureHeightGoal: DesiredHeight = Math.Abs(tag.ValueAsNumber); if (Height == 0) { Height = DesiredHeight; } break; case RtfSpec.TagPictureWidthScale: ScaleWidthPercent = Math.Abs(tag.ValueAsNumber); break; case RtfSpec.TagPictureHeightScale: ScaleHeightPercent = Math.Abs(tag.ValueAsNumber); break; } } // DoVisitTag
} // DoVisitGroup // ---------------------------------------------------------------------- protected override void DoVisitTag(IRtfTag tag) { switch (tag.Name) { case RtfSpec.TagInfoVersion: info.Version = tag.ValueAsNumber; break; case RtfSpec.TagInfoRevision: info.Revision = tag.ValueAsNumber; break; case RtfSpec.TagInfoNumberOfPages: info.NumberOfPages = tag.ValueAsNumber; break; case RtfSpec.TagInfoNumberOfWords: info.NumberOfWords = tag.ValueAsNumber; break; case RtfSpec.TagInfoNumberOfChars: info.NumberOfCharacters = tag.ValueAsNumber; break; case RtfSpec.TagInfoId: info.Id = tag.ValueAsNumber; break; case RtfSpec.TagInfoEditingTimeMinutes: info.EditingTimeInMinutes = tag.ValueAsNumber; break; } } // DoVisitTag
} // CreateTimestamp protected override void DoVisitTag(IRtfTag tag) { switch (tag.Name) { case RtfSpec.TagInfoYear: _year = tag.ValueAsNumber; break; case RtfSpec.TagInfoMonth: _month = tag.ValueAsNumber; break; case RtfSpec.TagInfoDay: _day = tag.ValueAsNumber; break; case RtfSpec.TagInfoHour: _hour = tag.ValueAsNumber; break; case RtfSpec.TagInfoMinute: _minutes = tag.ValueAsNumber; break; case RtfSpec.TagInfoSecond: _seconds = tag.ValueAsNumber; break; } } // DoVisitTag
} // DoGroupBegin // ---------------------------------------------------------------------- protected override void DoTagFound(IRtfTag tag) { if (this.curGroup == null) { throw new RtfStructureException(Strings.MissingGroupForNewTag); } this.curGroup.WritableContents.Add(tag); } // DoTagFound
} // DoGroupBegin // ---------------------------------------------------------------------- protected override void DoTagFound( IRtfTag tag ) { if ( this.curGroup == null ) { throw new RtfStructureException( Strings.MissingGroupForNewTag ); } this.curGroup.WritableContents.Add( tag ); } // DoTagFound
} // DoVisitGroup // ---------------------------------------------------------------------- protected override void DoVisitTag( IRtfTag tag ) { switch ( tag.Name ) { case RtfSpec.TagUserPropertyType: this.propertyTypeCode = tag.ValueAsNumber; break; } } // DoVisitTag
} // DoVisitGroup // ---------------------------------------------------------------------- protected override void DoVisitTag(IRtfTag tag) { switch (tag.Name) { case RtfSpec.TagUserPropertyType: this.propertyTypeCode = tag.ValueAsNumber; break; } } // DoVisitTag
} // NotifyGroupBegin protected void NotifyTagFound(IRtfTag tag) { if (_listeners != null) { foreach (IRtfParserListener listener in _listeners) { listener.TagFound(tag); } } } // NotifyTagFound
} // DoGroupBegin // ---------------------------------------------------------------------- protected override void DoTagFound(IRtfTag tag) { if (settings.Enabled && logger.IsInfoEnabled && !string.IsNullOrEmpty(settings.ParseTagText)) { Log(string.Format( CultureInfo.InvariantCulture, settings.ParseTagText, tag)); } } // DoTagFound
} // DoGroupBegin // ---------------------------------------------------------------------- protected override void DoTagFound(IRtfTag tag) { if (this.settings.Enabled && !string.IsNullOrEmpty(this.settings.ParseTagText)) { WriteLine(string.Format( CultureInfo.InvariantCulture, this.settings.ParseTagText, tag)); } } // DoTagFound
} // DoGroupBegin // ---------------------------------------------------------------------- protected override void DoTagFound( IRtfTag tag ) { if ( this.settings.Enabled && !string.IsNullOrEmpty( this.settings.ParseTagText ) ) { WriteLine( string.Format( CultureInfo.InvariantCulture, this.settings.ParseTagText, tag ) ); } } // DoTagFound
} // DoVisitGroup // ---------------------------------------------------------------------- protected override void DoVisitTag( IRtfTag tag ) { switch ( tag.Name ) { case RtfSpec.TagColorRed: this.curRed = tag.ValueAsNumber; break; case RtfSpec.TagColorGreen: this.curGreen = tag.ValueAsNumber; break; case RtfSpec.TagColorBlue: this.curBlue = tag.ValueAsNumber; break; } } // DoVisitTag
} // DoVisitGroup // ---------------------------------------------------------------------- protected override void DoVisitTag(IRtfTag tag) { switch (tag.Name) { case RtfSpec.TagColorRed: curRed = tag.ValueAsNumber; break; case RtfSpec.TagColorGreen: curGreen = tag.ValueAsNumber; break; case RtfSpec.TagColorBlue: curBlue = tag.ValueAsNumber; break; } } // DoVisitTag
// ---------------------------------------------------------------------- protected override void DoVisitTag( IRtfTag tag ) { switch ( tag.Name ) { case RtfSpec.TagInfoYear: year = tag.ValueAsNumber; break; case RtfSpec.TagInfoMonth: month = tag.ValueAsNumber; break; case RtfSpec.TagInfoDay: day = tag.ValueAsNumber; break; case RtfSpec.TagInfoHour: hour = tag.ValueAsNumber; break; case RtfSpec.TagInfoMinute: minutes = tag.ValueAsNumber; break; case RtfSpec.TagInfoSecond: seconds = tag.ValueAsNumber; break; } }
} // DoVisitGroup // ---------------------------------------------------------------------- protected override void DoVisitTag(IRtfTag tag) { switch (tag.Name) { case RtfSpec.TagThemeFontLoMajor: case RtfSpec.TagThemeFontHiMajor: case RtfSpec.TagThemeFontDbMajor: case RtfSpec.TagThemeFontBiMajor: case RtfSpec.TagThemeFontLoMinor: case RtfSpec.TagThemeFontHiMinor: case RtfSpec.TagThemeFontDbMinor: case RtfSpec.TagThemeFontBiMinor: // skip and ignore for the moment break; case RtfSpec.TagFont: // Only Set the font id and index if there is a valid number. We have bad rtf text with just \f with no index -Joe if (tag.FullName.Length > 1) { fontId = tag.FullName; fontIndex = tag.ValueAsNumber; } break; case RtfSpec.TagFontKindNil: fontKind = RtfFontKind.Nil; break; case RtfSpec.TagFontKindRoman: fontKind = RtfFontKind.Roman; break; case RtfSpec.TagFontKindSwiss: fontKind = RtfFontKind.Swiss; break; case RtfSpec.TagFontKindModern: fontKind = RtfFontKind.Modern; break; case RtfSpec.TagFontKindScript: fontKind = RtfFontKind.Script; break; case RtfSpec.TagFontKindDecor: fontKind = RtfFontKind.Decor; break; case RtfSpec.TagFontKindTech: fontKind = RtfFontKind.Tech; break; case RtfSpec.TagFontKindBidi: fontKind = RtfFontKind.Bidi; break; case RtfSpec.TagFontCharset: fontCharset = tag.ValueAsNumber; break; case RtfSpec.TagCodePage: fontCodePage = tag.ValueAsNumber; break; case RtfSpec.TagFontPitch: switch (tag.ValueAsNumber) { case 0: fontPitch = RtfFontPitch.Default; break; case 1: fontPitch = RtfFontPitch.Fixed; break; case 2: fontPitch = RtfFontPitch.Variable; break; } break; } } // DoVisitTag
// ---------------------------------------------------------------------- protected override void DoVisitTag( IRtfTag tag ) { switch ( tag.Name ) { case RtfSpec.TagPictureFormatWinDib: case RtfSpec.TagPictureFormatWinBmp: format = RtfVisualImageFormat.Bmp; break; case RtfSpec.TagPictureFormatEmf: format = RtfVisualImageFormat.Emf; break; case RtfSpec.TagPictureFormatJpg: format = RtfVisualImageFormat.Jpg; break; case RtfSpec.TagPictureFormatPng: format = RtfVisualImageFormat.Png; break; case RtfSpec.TagPictureFormatWmf: format = RtfVisualImageFormat.Wmf; break; case RtfSpec.TagPictureWidth: width = tag.ValueAsNumber; desiredWidth = width; break; case RtfSpec.TagPictureHeight: height = tag.ValueAsNumber; desiredHeight = height; break; case RtfSpec.TagPictureWidthGoal: desiredWidth = tag.ValueAsNumber; if ( width == 0 ) { // hack to prevent WordPad documents which lack the \picw and \pich tags // from resulting in an exception due to undefined width/height width = desiredWidth; } break; case RtfSpec.TagPictureHeightGoal: desiredHeight = tag.ValueAsNumber; if ( height == 0 ) { // hack to prevent WordPad documents which lack the \picw and \pich tags // from resulting in an exception due to undefined width/height height = desiredHeight; } break; case RtfSpec.TagPictureWidthScale: scaleWidthPercent = tag.ValueAsNumber; break; case RtfSpec.TagPictureHeightScale: scaleHeightPercent = tag.ValueAsNumber; break; } }
} // DoVisitGroup // ---------------------------------------------------------------------- protected override void DoVisitTag(IRtfTag tag) { switch (tag.Name) { case RtfSpec.TagPictureFormatWinDib: case RtfSpec.TagPictureFormatWinBmp: format = RtfVisualImageFormat.Bmp; break; case RtfSpec.TagPictureFormatEmf: format = RtfVisualImageFormat.Emf; break; case RtfSpec.TagPictureFormatJpg: format = RtfVisualImageFormat.Jpg; break; case RtfSpec.TagPictureFormatPng: format = RtfVisualImageFormat.Png; break; case RtfSpec.TagPictureFormatWmf: format = RtfVisualImageFormat.Wmf; break; case RtfSpec.TagPictureWidth: width = Math.Abs(tag.ValueAsNumber); desiredWidth = width; break; case RtfSpec.TagPictureHeight: height = Math.Abs(tag.ValueAsNumber); desiredHeight = height; break; case RtfSpec.TagPictureWidthGoal: desiredWidth = Math.Abs(tag.ValueAsNumber); if (width == 0) { // hack to prevent WordPad documents which lack the \picw and \pich tags // from resulting in an exception due to undefined width/height width = desiredWidth; } break; case RtfSpec.TagPictureHeightGoal: desiredHeight = Math.Abs(tag.ValueAsNumber); if (height == 0) { // hack to prevent WordPad documents which lack the \picw and \pich tags // from resulting in an exception due to undefined width/height height = desiredHeight; } break; case RtfSpec.TagPictureWidthScale: scaleWidthPercent = Math.Abs(tag.ValueAsNumber); break; case RtfSpec.TagPictureHeightScale: scaleHeightPercent = Math.Abs(tag.ValueAsNumber); break; } } // DoVisitTag
// ---------------------------------------------------------------------- protected override void DoVisitTag( IRtfTag tag ) { switch ( tag.Name ) { case RtfSpec.TagInfoVersion: info.Version = tag.ValueAsNumber; break; case RtfSpec.TagInfoRevision: info.Revision = tag.ValueAsNumber; break; case RtfSpec.TagInfoNumberOfPages: info.NumberOfPages = tag.ValueAsNumber; break; case RtfSpec.TagInfoNumberOfWords: info.NumberOfWords = tag.ValueAsNumber; break; case RtfSpec.TagInfoNumberOfChars: info.NumberOfCharacters = tag.ValueAsNumber; break; case RtfSpec.TagInfoId: info.Id = tag.ValueAsNumber; break; case RtfSpec.TagInfoEditingTimeMinutes: info.EditingTimeInMinutes = tag.ValueAsNumber; break; } }
// ---------------------------------------------------------------------- void IRtfElementVisitor.VisitTag( IRtfTag tag ) { if ( Context.State != RtfInterpreterState.InDocument ) { if ( Context.FontTable.Count > 0 ) { // somewhat of a hack to detect state change from header to in-document for // rtf-docs which do neither have a generator group nor encapsulate the // actual document content in a group. if ( Context.ColorTable.Count > 0 || RtfSpec.TagViewKind.Equals( tag.Name ) ) { Context.State = RtfInterpreterState.InDocument; } } } switch ( Context.State ) { case RtfInterpreterState.Init: if ( RtfSpec.TagRtf.Equals( tag.Name ) ) { Context.State = RtfInterpreterState.InHeader; Context.RtfVersion = tag.ValueAsNumber; } else { throw new RtfStructureException( Strings.InvalidInitTagState( tag.ToString() ) ); } break; case RtfInterpreterState.InHeader: switch ( tag.Name ) { case RtfSpec.TagDefaultFont: Context.DefaultFontId = RtfSpec.TagFont + tag.ValueAsNumber; break; } break; case RtfInterpreterState.InDocument: switch ( tag.Name ) { case RtfSpec.TagPlain: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveNormal(); break; case RtfSpec.TagParagraphDefaults: case RtfSpec.TagSectionDefaults: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithAlignment( RtfTextAlignment.Left ); break; case RtfSpec.TagBold: bool bold = !tag.HasValue || tag.ValueAsNumber != 0; Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithBold( bold ); break; case RtfSpec.TagItalic: bool italic = !tag.HasValue || tag.ValueAsNumber != 0; Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithItalic( italic ); break; case RtfSpec.TagUnderLine: bool underline = !tag.HasValue || tag.ValueAsNumber != 0; Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithUnderline( underline ); break; case RtfSpec.TagUnderLineNone: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithUnderline( false ); break; case RtfSpec.TagStrikeThrough: bool strikeThrough = !tag.HasValue || tag.ValueAsNumber != 0; Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithStrikeThrough( strikeThrough ); break; case RtfSpec.TagHidden: bool hidden = !tag.HasValue || tag.ValueAsNumber != 0; Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithHidden( hidden ); break; case RtfSpec.TagFont: string fontId = tag.FullName; if ( Context.FontTable.ContainsFontWithId( fontId ) ) { Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithFont( Context.FontTable[ fontId ] ); } else { throw new RtfUndefinedFontException( Strings.UndefinedFont( fontId ) ); } break; case RtfSpec.TagFontSize: int fontSize = tag.ValueAsNumber; if ( fontSize > 0 ) { Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithFontSize( fontSize ); } else { throw new RtfInvalidDataException( Strings.InvalidFontSize( fontSize ) ); } break; case RtfSpec.TagFontSubscript: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithSuperScript( false ); break; case RtfSpec.TagFontSuperscript: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithSuperScript( true ); break; case RtfSpec.TagFontNoSuperSub: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithSuperScript( 0 ); break; case RtfSpec.TagFontDown: int moveDown = tag.ValueAsNumber; if ( moveDown == 0 ) { moveDown = 6; // the default value according to rtf spec } Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithSuperScript( -moveDown ); break; case RtfSpec.TagFontUp: int moveUp = tag.ValueAsNumber; if ( moveUp == 0 ) { moveUp = 6; // the default value according to rtf spec } Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithSuperScript( moveUp ); break; case RtfSpec.TagAlignLeft: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithAlignment( RtfTextAlignment.Left ); break; case RtfSpec.TagAlignCenter: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithAlignment( RtfTextAlignment.Center ); break; case RtfSpec.TagAlignRight: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithAlignment( RtfTextAlignment.Right ); break; case RtfSpec.TagAlignJustify: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithAlignment( RtfTextAlignment.Justify ); break; case RtfSpec.TagColorBackground: case RtfSpec.TagColorBackgroundWord: case RtfSpec.TagColorHighlight: case RtfSpec.TagColorForeground: int colorIndex = tag.ValueAsNumber; if ( colorIndex >= 0 && colorIndex < Context.ColorTable.Count ) { IRtfColor newColor = Context.ColorTable[ colorIndex ]; bool isForeground = RtfSpec.TagColorForeground.Equals( tag.Name ); Context.WritableCurrentTextFormat = isForeground ? Context.WritableCurrentTextFormat.DeriveWithForegroundColor( newColor ) : Context.WritableCurrentTextFormat.DeriveWithBackgroundColor( newColor ); } else { throw new RtfUndefinedColorException( Strings.UndefinedColor( colorIndex ) ); } break; case RtfSpec.TagSection: NotifyInsertBreak( RtfVisualBreakKind.Section ); break; case RtfSpec.TagParagraph: NotifyInsertBreak( RtfVisualBreakKind.Paragraph ); break; case RtfSpec.TagLine: NotifyInsertBreak( RtfVisualBreakKind.Line ); break; case RtfSpec.TagPage: NotifyInsertBreak( RtfVisualBreakKind.Page ); break; case RtfSpec.TagTabulator: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.Tabulator ); break; case RtfSpec.TagTilde: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.NonBreakingSpace ); break; case RtfSpec.TagEmDash: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.EmDash ); break; case RtfSpec.TagEnDash: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.EnDash ); break; case RtfSpec.TagEmSpace: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.EmSpace ); break; case RtfSpec.TagEnSpace: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.EnSpace ); break; case RtfSpec.TagQmSpace: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.QmSpace ); break; case RtfSpec.TagBulltet: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.Bullet ); break; case RtfSpec.TagLeftSingleQuote: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.LeftSingleQuote ); break; case RtfSpec.TagRightSingleQuote: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.RightSingleQuote ); break; case RtfSpec.TagLeftDoubleQuote: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.LeftDoubleQuote ); break; case RtfSpec.TagRightDoubleQuote: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.RightDoubleQuote ); break; case RtfSpec.TagHyphen: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.OptionalHyphen ); break; case RtfSpec.TagUnderscore: NotifyInsertSpecialChar( RtfVisualSpecialCharKind.NonBreakingHyphen ); break; } break; } }
// ---------------------------------------------------------------------- protected void NotifyTagFound( IRtfTag tag ) { if ( listeners != null ) { foreach ( IRtfParserListener listener in listeners ) { listener.TagFound( tag ); } } }
// ---------------------------------------------------------------------- protected virtual void DoTagFound( IRtfTag tag ) { }
// ---------------------------------------------------------------------- private bool HandleTag( TextReader reader, IRtfTag tag ) { if ( level == 0 ) { throw new RtfStructureException( Strings.TagOnRootLevel( tag.ToString() ) ); } if ( tagCount < 4 ) { // this only handles the initial encoding tag in the header section UpdateEncoding( tag ); } string tagName = tag.Name; // enable the font name detection in case the last tag was introducing // a theme font bool detectFontName = expectingThemeFont; if ( tagCountAtLastGroupStart == tagCount ) { // first tag in a group switch ( tagName ) { case RtfSpec.TagThemeFontLoMajor: case RtfSpec.TagThemeFontHiMajor: case RtfSpec.TagThemeFontDbMajor: case RtfSpec.TagThemeFontBiMajor: case RtfSpec.TagThemeFontLoMinor: case RtfSpec.TagThemeFontHiMinor: case RtfSpec.TagThemeFontDbMinor: case RtfSpec.TagThemeFontBiMinor: // these introduce a new font, but the actual font tag will be // the second tag in the group, so we must remember this condition ... expectingThemeFont = true; break; } // always enable the font name detection also for the first tag in a group detectFontName = true; } if ( detectFontName ) { // first tag in a group: switch ( tagName ) { case RtfSpec.TagFont: if ( fontTableStartLevel > 0 ) { // in the font-table definition: // -> remember the target font for charset mapping targetFont = tag.FullName; expectingThemeFont = false; // reset that state now } break; case RtfSpec.TagFontTable: // -> remember we're in the font-table definition fontTableStartLevel = level; break; } } if ( targetFont != null ) { // within a font-tables font definition: perform charset mapping if ( RtfSpec.TagFontCharset.Equals( tagName ) ) { int charSet = tag.ValueAsNumber; int codePage = RtfSpec.GetCodePage( charSet ); fontToCodePageMapping[ targetFont ] = codePage; UpdateEncoding( codePage ); } } if ( fontToCodePageMapping.Count > 0 && RtfSpec.TagFont.Equals( tagName ) ) { int? codePage = (int?)fontToCodePageMapping[ tag.FullName ]; if ( codePage != null ) { UpdateEncoding( codePage.Value ); } } bool skippedContent = false; switch ( tagName ) { case RtfSpec.TagUnicodeCode: int unicodeValue = tag.ValueAsNumber; char unicodeChar = (char)unicodeValue; curText.Append( unicodeChar ); // skip over the indicated number of 'alternative representation' text for ( int i = 0; i < unicodeSkipCount; i++ ) { int nextChar = PeekNextChar( reader, true ); switch ( nextChar ) { case ' ': case '\r': case '\n': reader.Read(); // consume peeked char skippedContent = true; if ( i == 0 ) { // the first whitespace after the tag // -> only a delimiter, doesn't count for skipping ... i--; } break; case '\\': reader.Read(); // consume peeked char skippedContent = true; int secondChar = ReadOneByte( reader ); // mandatory switch ( secondChar ) { case '\'': // ok, this is a hex-encoded 'byte' -> need to consume both // hex digits too ReadOneByte( reader ); // high nibble ReadOneByte( reader ); // low nibble break; } break; case '{': case '}': // don't consume peeked char and abort skipping i = unicodeSkipCount; break; default: reader.Read(); // consume peeked char skippedContent = true; break; } } break; case RtfSpec.TagUnicodeSkipCount: int newSkipCount = tag.ValueAsNumber; if ( newSkipCount < 0 || newSkipCount > 10 ) { throw new RtfUnicodeEncodingException( Strings.InvalidUnicodeSkipCount( tag.ToString() ) ); } unicodeSkipCount = newSkipCount; break; default: FlushText(); NotifyTagFound( tag ); break; } tagCount++; return skippedContent; }
} // VisitChildrenOf // ---------------------------------------------------------------------- void IRtfElementVisitor.VisitTag(IRtfTag tag) { if (Context.State != RtfInterpreterState.InDocument) { if (Context.FontTable.Count > 0) { // somewhat of a hack to detect state change from header to in-document for // rtf-docs which do neither have a generator group nor encapsulate the // actual document content in a group. if (Context.ColorTable.Count > 0 || RtfSpec.TagViewKind.Equals(tag.Name)) { Context.State = RtfInterpreterState.InDocument; } } } switch (Context.State) { case RtfInterpreterState.Init: if (RtfSpec.TagRtf.Equals(tag.Name)) { Context.State = RtfInterpreterState.InHeader; Context.RtfVersion = tag.ValueAsNumber; } else { throw new RtfStructureException(Strings.InvalidInitTagState(tag.ToString())); } break; case RtfInterpreterState.InHeader: switch (tag.Name) { case RtfSpec.TagDefaultFont: Context.DefaultFontId = RtfSpec.TagFont + tag.ValueAsNumber; break; } break; case RtfInterpreterState.InDocument: switch (tag.Name) { case RtfSpec.TagPlain: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveNormal(); break; case RtfSpec.TagParagraphDefaults: case RtfSpec.TagSectionDefaults: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithAlignment(RtfTextAlignment.Left); break; case RtfSpec.TagBold: bool bold = !tag.HasValue || tag.ValueAsNumber != 0; Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithBold(bold); break; case RtfSpec.TagItalic: bool italic = !tag.HasValue || tag.ValueAsNumber != 0; Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithItalic(italic); break; case RtfSpec.TagUnderLine: bool underline = !tag.HasValue || tag.ValueAsNumber != 0; Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithUnderline(underline); break; case RtfSpec.TagUnderLineNone: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithUnderline(false); break; case RtfSpec.TagStrikeThrough: bool strikeThrough = !tag.HasValue || tag.ValueAsNumber != 0; Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithStrikeThrough(strikeThrough); break; case RtfSpec.TagHidden: bool hidden = !tag.HasValue || tag.ValueAsNumber != 0; Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithHidden(hidden); break; case RtfSpec.TagFont: string fontId = tag.FullName; if (Context.FontTable.ContainsFontWithId(fontId)) { Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithFont( Context.FontTable[fontId]); } else { if (Settings.IgnoreUnknownFonts && Context.FontTable.Count > 0) { Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithFont(Context.FontTable[0]); } else { throw new RtfUndefinedFontException(Strings.UndefinedFont(fontId)); } } break; case RtfSpec.TagFontSize: int fontSize = tag.ValueAsNumber; if (fontSize >= 0) { Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithFontSize(fontSize); } else { throw new RtfInvalidDataException(Strings.InvalidFontSize(fontSize)); } break; case RtfSpec.TagFontSubscript: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithSuperScript(false); break; case RtfSpec.TagFontSuperscript: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithSuperScript(true); break; case RtfSpec.TagFontNoSuperSub: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithSuperScript(0); break; case RtfSpec.TagFontDown: int moveDown = tag.ValueAsNumber; if (moveDown == 0) { moveDown = 6; // the default value according to rtf spec } Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithSuperScript(-moveDown); break; case RtfSpec.TagFontUp: int moveUp = tag.ValueAsNumber; if (moveUp == 0) { moveUp = 6; // the default value according to rtf spec } Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithSuperScript(moveUp); break; case RtfSpec.TagAlignLeft: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithAlignment(RtfTextAlignment.Left); break; case RtfSpec.TagAlignCenter: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithAlignment(RtfTextAlignment.Center); break; case RtfSpec.TagAlignRight: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithAlignment(RtfTextAlignment.Right); break; case RtfSpec.TagAlignJustify: Context.WritableCurrentTextFormat = Context.WritableCurrentTextFormat.DeriveWithAlignment(RtfTextAlignment.Justify); break; case RtfSpec.TagColorBackground: case RtfSpec.TagColorBackgroundWord: case RtfSpec.TagColorHighlight: case RtfSpec.TagColorForeground: int colorIndex = tag.ValueAsNumber; if (colorIndex >= 0 && colorIndex < Context.ColorTable.Count) { IRtfColor newColor = Context.ColorTable[colorIndex]; bool isForeground = RtfSpec.TagColorForeground.Equals(tag.Name); Context.WritableCurrentTextFormat = isForeground ? Context.WritableCurrentTextFormat.DeriveWithForegroundColor(newColor) : Context.WritableCurrentTextFormat.DeriveWithBackgroundColor(newColor); } else { throw new RtfUndefinedColorException(Strings.UndefinedColor(colorIndex)); } break; case RtfSpec.TagSection: NotifyInsertBreak(RtfVisualBreakKind.Section); break; case RtfSpec.TagParagraph: NotifyInsertBreak(RtfVisualBreakKind.Paragraph); break; case RtfSpec.TagLine: NotifyInsertBreak(RtfVisualBreakKind.Line); break; case RtfSpec.TagPage: NotifyInsertBreak(RtfVisualBreakKind.Page); break; case RtfSpec.TagTabulator: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.Tabulator); break; case RtfSpec.TagTilde: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.NonBreakingSpace); break; case RtfSpec.TagEmDash: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.EmDash); break; case RtfSpec.TagEnDash: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.EnDash); break; case RtfSpec.TagEmSpace: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.EmSpace); break; case RtfSpec.TagEnSpace: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.EnSpace); break; case RtfSpec.TagQmSpace: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.QmSpace); break; case RtfSpec.TagBulltet: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.Bullet); break; case RtfSpec.TagLeftSingleQuote: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.LeftSingleQuote); break; case RtfSpec.TagRightSingleQuote: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.RightSingleQuote); break; case RtfSpec.TagLeftDoubleQuote: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.LeftDoubleQuote); break; case RtfSpec.TagRightDoubleQuote: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.RightDoubleQuote); break; case RtfSpec.TagHyphen: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.OptionalHyphen); break; case RtfSpec.TagUnderscore: NotifyInsertSpecialChar(RtfVisualSpecialCharKind.NonBreakingHyphen); break; } break; } } // IRtfElementVisitor.VisitTag
} // ParseTag // ---------------------------------------------------------------------- private bool HandleTag(TextReader reader, IRtfTag tag) { if (level == 0) { throw new RtfStructureException(Strings.TagOnRootLevel(tag.ToString())); } if (tagCount < 4) { // this only handles the initial encoding tag in the header section UpdateEncoding(tag); } string tagName = tag.Name; // enable the font name detection in case the last tag was introducing // a theme font bool detectFontName = expectingThemeFont; if (tagCountAtLastGroupStart == tagCount) { // first tag in a group switch (tagName) { case RtfSpec.TagThemeFontLoMajor: case RtfSpec.TagThemeFontHiMajor: case RtfSpec.TagThemeFontDbMajor: case RtfSpec.TagThemeFontBiMajor: case RtfSpec.TagThemeFontLoMinor: case RtfSpec.TagThemeFontHiMinor: case RtfSpec.TagThemeFontDbMinor: case RtfSpec.TagThemeFontBiMinor: // these introduce a new font, but the actual font tag will be // the second tag in the group, so we must remember this condition ... expectingThemeFont = true; break; } // always enable the font name detection also for the first tag in a group detectFontName = true; } if (detectFontName) { // first tag in a group: switch (tagName) { case RtfSpec.TagFont: if (fontTableStartLevel > 0) { // in the font-table definition: // -> remember the target font for charset mapping targetFont = tag.FullName; expectingThemeFont = false; // reset that state now } break; case RtfSpec.TagFontTable: // -> remember we're in the font-table definition fontTableStartLevel = level; break; } } if (targetFont != null) { // within a font-tables font definition: perform charset mapping if (RtfSpec.TagFontCharset.Equals(tagName)) { int charSet = tag.ValueAsNumber; int codePage = RtfSpec.GetCodePage(charSet); fontToCodePageMapping[targetFont] = codePage; UpdateEncoding(codePage); } } if (fontToCodePageMapping.Count > 0 && RtfSpec.TagFont.Equals(tagName)) { int codePage; if (fontToCodePageMapping.TryGetValue(tag.FullName, out codePage)) { UpdateEncoding(codePage); } } bool skippedContent = false; switch (tagName) { case RtfSpec.TagUnicodeCode: int unicodeValue = tag.ValueAsNumber; char unicodeChar = (char)unicodeValue; curText.Append(unicodeChar); // skip over the indicated number of 'alternative representation' text for (int i = 0; i < unicodeSkipCount; i++) { int nextChar = PeekNextChar(reader, true); switch (nextChar) { case ' ': case '\r': case '\n': reader.Read(); // consume peeked char skippedContent = true; if (i == 0) { // the first whitespace after the tag // -> only a delimiter, doesn't count for skipping ... i--; } break; case '\\': reader.Read(); // consume peeked char skippedContent = true; int secondChar = ReadOneByte(reader); // mandatory switch (secondChar) { case '\'': // ok, this is a hex-encoded 'byte' -> need to consume both // hex digits too ReadOneByte(reader); // high nibble ReadOneByte(reader); // low nibble break; } break; case '{': case '}': // don't consume peeked char and abort skipping i = unicodeSkipCount; break; default: reader.Read(); // consume peeked char skippedContent = true; break; } } break; case RtfSpec.TagUnicodeSkipCount: int newSkipCount = tag.ValueAsNumber; if (newSkipCount < 0 || newSkipCount > 10) { throw new RtfUnicodeEncodingException(Strings.InvalidUnicodeSkipCount(tag.ToString())); } unicodeSkipCount = newSkipCount; break; default: FlushText(); NotifyTagFound(tag); break; } tagCount++; return(skippedContent); } // HandleTag
// ---------------------------------------------------------------------- protected override void DoVisitTag( IRtfTag tag ) { switch ( tag.Name ) { case RtfSpec.TagThemeFontLoMajor: case RtfSpec.TagThemeFontHiMajor: case RtfSpec.TagThemeFontDbMajor: case RtfSpec.TagThemeFontBiMajor: case RtfSpec.TagThemeFontLoMinor: case RtfSpec.TagThemeFontHiMinor: case RtfSpec.TagThemeFontDbMinor: case RtfSpec.TagThemeFontBiMinor: // skip and ignore for the moment break; case RtfSpec.TagFont: fontId = tag.FullName; fontIndex = tag.ValueAsNumber; break; case RtfSpec.TagFontKindNil: fontKind = RtfFontKind.Nil; break; case RtfSpec.TagFontKindRoman: fontKind = RtfFontKind.Roman; break; case RtfSpec.TagFontKindSwiss: fontKind = RtfFontKind.Swiss; break; case RtfSpec.TagFontKindModern: fontKind = RtfFontKind.Modern; break; case RtfSpec.TagFontKindScript: fontKind = RtfFontKind.Script; break; case RtfSpec.TagFontKindDecor: fontKind = RtfFontKind.Decor; break; case RtfSpec.TagFontKindTech: fontKind = RtfFontKind.Tech; break; case RtfSpec.TagFontKindBidi: fontKind = RtfFontKind.Bidi; break; case RtfSpec.TagFontCharset: fontCharset = tag.ValueAsNumber; break; case RtfSpec.TagCodePage: fontCodePage = tag.ValueAsNumber; break; case RtfSpec.TagFontPitch: switch ( tag.ValueAsNumber ) { case 0: fontPitch = RtfFontPitch.Default; break; case 1: fontPitch = RtfFontPitch.Fixed; break; case 2: fontPitch = RtfFontPitch.Variable; break; } break; } }
} // DoVisitGroup // ---------------------------------------------------------------------- protected override void DoVisitTag(IRtfTag tag) { switch (tag.Name) { case RtfSpec.TagThemeFontLoMajor: case RtfSpec.TagThemeFontHiMajor: case RtfSpec.TagThemeFontDbMajor: case RtfSpec.TagThemeFontBiMajor: case RtfSpec.TagThemeFontLoMinor: case RtfSpec.TagThemeFontHiMinor: case RtfSpec.TagThemeFontDbMinor: case RtfSpec.TagThemeFontBiMinor: // skip and ignore for the moment break; case RtfSpec.TagFont: fontId = tag.FullName; fontIndex = tag.ValueAsNumber; break; case RtfSpec.TagFontKindNil: fontKind = RtfFontKind.Nil; break; case RtfSpec.TagFontKindRoman: fontKind = RtfFontKind.Roman; break; case RtfSpec.TagFontKindSwiss: fontKind = RtfFontKind.Swiss; break; case RtfSpec.TagFontKindModern: fontKind = RtfFontKind.Modern; break; case RtfSpec.TagFontKindScript: fontKind = RtfFontKind.Script; break; case RtfSpec.TagFontKindDecor: fontKind = RtfFontKind.Decor; break; case RtfSpec.TagFontKindTech: fontKind = RtfFontKind.Tech; break; case RtfSpec.TagFontKindBidi: fontKind = RtfFontKind.Bidi; break; case RtfSpec.TagFontCharset: fontCharset = tag.ValueAsNumber; break; case RtfSpec.TagCodePage: fontCodePage = tag.ValueAsNumber; break; case RtfSpec.TagFontPitch: switch (tag.ValueAsNumber) { case 0: fontPitch = RtfFontPitch.Default; break; case 1: fontPitch = RtfFontPitch.Fixed; break; case 2: fontPitch = RtfFontPitch.Variable; break; } break; } } // DoVisitTag
// ---------------------------------------------------------------------- protected virtual void DoVisitTag( IRtfTag tag ) { }
// ---------------------------------------------------------------------- protected override void DoTagFound( IRtfTag tag ) { if ( settings.Enabled && logger.IsInfoEnabled && !string.IsNullOrEmpty( settings.ParseTagText ) ) { Log( string.Format( CultureInfo.InvariantCulture, settings.ParseTagText, tag ) ); } }
} // VisitText protected virtual void DoVisitTag(IRtfTag tag) { } // DoVisitTag
// ---------------------------------------------------------------------- private void UpdateEncoding( IRtfTag tag ) { switch ( tag.Name ) { case RtfSpec.TagEncodingAnsi: UpdateEncoding( RtfSpec.AnsiCodePage ); break; case RtfSpec.TagEncodingMac: UpdateEncoding( 10000 ); break; case RtfSpec.TagEncodingPc: UpdateEncoding( 437 ); break; case RtfSpec.TagEncodingPca: UpdateEncoding( 850 ); break; case RtfSpec.TagEncodingAnsiCodePage: UpdateEncoding( tag.ValueAsNumber ); break; } }
} // TagFound // ---------------------------------------------------------------------- protected virtual void DoTagFound(IRtfTag tag) { } // DoTagFound
} // ParseTag private bool HandleTag(TextReader reader, IRtfTag tag) { if (_level == 0) { throw new RtfStructureException(Strings.TagOnRootLevel(tag.ToString())); } if (_tagCount < 4) { UpdateEncoding(tag); } var tagName = tag.Name; // enable the font name detection in case the last tag was introducing // a theme font var detectFontName = _expectingThemeFont; if (_tagCountAtLastGroupStart == _tagCount) { // first tag in a group switch (tagName) { case RtfSpec.TagThemeFontLoMajor: case RtfSpec.TagThemeFontHiMajor: case RtfSpec.TagThemeFontDbMajor: case RtfSpec.TagThemeFontBiMajor: case RtfSpec.TagThemeFontLoMinor: case RtfSpec.TagThemeFontHiMinor: case RtfSpec.TagThemeFontDbMinor: case RtfSpec.TagThemeFontBiMinor: // these introduce a new font, but the actual font tag will be // the second tag in the group, so we must remember this condition ... _expectingThemeFont = true; break; } // always enable the font name detection also for the first tag in a group detectFontName = true; } if (detectFontName) { switch (tagName) { case RtfSpec.TagFont: if (_fontTableStartLevel > 0) { // in the font-table definition: _targetFont = tag.FullName; _expectingThemeFont = false; // reset that state now } break; case RtfSpec.TagFontTable: _fontTableStartLevel = _level; break; } } if (_targetFont != null) { if (RtfSpec.TagFontCharset.Equals(tagName)) { var charSet = tag.ValueAsNumber; var codePage = RtfSpec.GetCodePage(charSet); _fontToCodePageMapping[_targetFont] = codePage; UpdateEncoding(codePage); } } if (_fontToCodePageMapping.Count > 0 && RtfSpec.TagFont.Equals(tagName)) { var codePage = (int?)_fontToCodePageMapping[tag.FullName]; if (codePage != null) { UpdateEncoding(codePage.Value); } } var skippedContent = false; switch (tagName) { case RtfSpec.TagUnicodeCode: var unicodeValue = tag.ValueAsNumber; var unicodeChar = (char)unicodeValue; _curText.Append(unicodeChar); // skip over the indicated number of 'alternative representation' text for (var i = 0; i < _unicodeSkipCount; i++) { var nextChar = PeekNextChar(reader, true); switch (nextChar) { case ' ': case '\r': case '\n': reader.Read(); // consume peeked char skippedContent = true; if (i == 0) { i--; } break; case '\\': reader.Read(); // consume peeked char skippedContent = true; var secondChar = ReadOneByte(reader); // mandatory switch (secondChar) { case '\'': // ok, this is a hex-encoded 'byte' -> need to consume both // hex digits too ReadOneByte(reader); // high nibble ReadOneByte(reader); // low nibble break; } break; case '{': case '}': // don't consume peeked char and abort skipping i = _unicodeSkipCount; break; default: reader.Read(); // consume peeked char skippedContent = true; break; } } break; case RtfSpec.TagUnicodeSkipCount: var newSkipCount = tag.ValueAsNumber; if (newSkipCount < 0 || newSkipCount > 10) { throw new RtfUnicodeEncodingException(Strings.InvalidUnicodeSkipCount(tag.ToString())); } _unicodeSkipCount = newSkipCount; break; default: FlushText(); NotifyTagFound(tag); break; } _tagCount++; return(skippedContent); } // HandleTag