/// <summary> /// Read next token /// </summary> /// <returns>token</returns> public Token NextToken() { var token = new Token(); var c = _reader.Read(); var peekChar = _reader.Peek(); if (c == '\"' && peekChar != '\\') // || peekChar != '{' || peekChar != 13)) { var stringBuilder = new StringBuilder(); while (true) { c = _reader.Read(); if (c < 0 || c == '\"' || c == '\r' || c == '\n') break; stringBuilder.Append((char) c); } token.Type = RtfTokenType.Text; token.Key = stringBuilder.ToString(); return token; } while (c == '\r' || c == '\n' || c == '\t' || c == '\0') c = _reader.Read(); if (c != Eof) { switch (c) { case '{': token.Type = RtfTokenType.GroupStart; break; case '}': token.Type = RtfTokenType.GroupEnd; break; case '\\': ParseKeyword(token); break; default: token.Type = RtfTokenType.Text; ParseText(c, token); break; } } else token.Type = RtfTokenType.Eof; return token; }
/// <summary> /// Accept rtf token /// </summary> /// <param name="token">RTF token</param> /// <param name="reader"></param> /// <returns>Is accept it?</returns> public bool Accept(Token token, Reader reader) { if (token == null) return false; if (token.Type == RtfTokenType.Text) { if (reader != null) { if (token.Key[0] == '?') { if (reader.LastToken != null) { if (reader.LastToken.Type == RtfTokenType.Keyword && reader.LastToken.Key == "u" && reader.LastToken.HasParam) { if (token.Key.Length > 0) CheckBuffer(); return true; } } } } CheckBuffer(); _stringBuilder.Append(token.Key); return true; } if (token.Type == RtfTokenType.Control && token.Key == "'" && token.HasParam) { if (reader.CurrentLayerInfo.CheckUcValueCount()) _byteBuffer.Add((byte) token.Param); return true; } if (token.Key == Consts.U && token.HasParam) { // Unicode char CheckBuffer(); _stringBuilder.Append((char) token.Param); reader.CurrentLayerInfo.UCValueCount = reader.CurrentLayerInfo.UcValue; return true; } if (token.Key == Consts.Tab) { CheckBuffer(); _stringBuilder.Append("\t"); return true; } if (token.Key == Consts.Emdash) { CheckBuffer(); _stringBuilder.Append('-'); return true; } if (token.Key == "") { CheckBuffer(); _stringBuilder.Append('-'); return true; } return false; }
/// <summary> /// Read the following plain text in the current level /// </summary> /// <param name="reader">RTF reader</param> /// <param name="firstToken"></param> /// <param name="deeply">whether read the text in the sub level</param> /// <param name="breakMeetControlWord"></param> /// <param name="htmlMode"></param> /// <returns>text</returns> private string ReadInnerText( Reader reader, Token firstToken, bool deeply, bool breakMeetControlWord, bool htmlMode) { var level = 0; var container = new TextContainer(this); container.Accept(firstToken, reader); while (true) { var type = reader.PeekTokenType(); if (type == RtfTokenType.Eof) break; if (type == RtfTokenType.GroupStart) level++; else if (type == RtfTokenType.GroupEnd) { level--; if (level < 0) break; } reader.ReadToken(); if (!deeply && level != 0) continue; if (htmlMode && reader.Keyword == Consts.Par) { container.Append(Environment.NewLine); continue; } container.Accept(reader.CurrentToken, reader); if (breakMeetControlWord) break; } return container.Text; }
/// <summary> /// Parse text after char /// </summary> /// <param name="c"></param> /// <param name="token"></param> private void ParseText(int c, Token token) { var stringBuilder = new StringBuilder(((char) c).ToString(CultureInfo.InvariantCulture)); c = ClearWhiteSpace(); while (c != '\\' && c != '}' && c != '{' && c != Eof) { _reader.Read(); stringBuilder.Append((char) c); c = ClearWhiteSpace(); } token.Key = stringBuilder.ToString(); }
/// <summary> /// Parse keyword from token /// </summary> /// <param name="token"></param> private void ParseKeyword(Token token) { var ext = false; var c = _reader.Peek(); if (!char.IsLetter((char) c)) { _reader.Read(); if (c == '*') { // Expand keyword token.Type = RtfTokenType.Keyword; _reader.Read(); ext = true; } else { if (c == '\\' || c == '{' || c == '}') { // Special character token.Type = RtfTokenType.Text; token.Key = ((char) c).ToString(CultureInfo.InvariantCulture); } else { token.Type = RtfTokenType.Control; token.Key = ((char) c).ToString(CultureInfo.InvariantCulture); if (token.Key == "\'") { // Read 2 hex characters var text = new StringBuilder(); text.Append((char) _reader.Read()); text.Append((char) _reader.Read()); token.HasParam = true; token.Hex = text.ToString().ToLower(); token.Param = Convert.ToInt32(text.ToString().ToLower(), 16); } } return; } } // Read keyword var keyword = new StringBuilder(); c = _reader.Peek(); while (char.IsLetter((char) c)) { _reader.Read(); keyword.Append((char) c); c = _reader.Peek(); } token.Type = ext ? RtfTokenType.ExtKeyword : RtfTokenType.Keyword; token.Key = keyword.ToString(); // Read an integer if (char.IsDigit((char) c) || c == '-') { token.HasParam = true; var negative = false; if (c == '-') { negative = true; _reader.Read(); } c = _reader.Peek(); var text = new StringBuilder(); while (char.IsDigit((char) c)) { _reader.Read(); text.Append((char) c); c = _reader.Peek(); } var param = Convert.ToInt32(text.ToString()); if (negative) param = - param; token.Param = param; } if (c == ' ') _reader.Read(); }