Logo Search packages:      
Sourcecode: galaxium version File versions  Download package

MessageUtility.cs

/*
 * Galaxium Messenger
 * Copyright (C) 2003-2007 Philippe Durand <draekz@gmail.com>
 * Copyright (C) 2007 Paul Burton <paulburton89@gmail.com>
 * Copyright (C) 2007 Ben Motmans <ben.motmans@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Globalization;

using Anculus.Core;

using Galaxium.Core;
using Galaxium.Protocol;

namespace Galaxium.Gui
{
      public static class MessageUtility
      {
            private static Regex _regexHyperlinks;
            private static Regex _regexEmails = new Regex (@"([\w\d\._-]+@[\w\d\._-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            
            static Dictionary<IEntity, List<string>> _cachedSearchLists = new Dictionary<IEntity, List<string>> ();
            static List<string> _uriSearchStrings = new List<string> ();
            
            static Dictionary<IProtocol, IMessageSplitter> _splitters = new Dictionary<IProtocol, IMessageSplitter> ();
            
            public static string[] UriStarts = { "http://", "https://", "file://", "ftp://", "mms://", "www.", "ftp." };
            
            public static char[] WhitespaceChars = { ' ', '\t', '\r', '\n' };
            
            static MessageUtility ()
            {
                  _uriSearchStrings.AddRange (UriStarts);
                  
                  _regexHyperlinks = new Regex (@"((" + string.Join ("|", UriStarts) + @")[\w\d\.\/\+&;=_:?-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            }
            
            //TODO: the ParseHyperlinks function should be re-used inside this function if possible
            public static List<ITextChunk> SplitMessage (string message, TextStyle style, IProtocol protocol, IEntity entity, List<IEmoticon> customEmoticons)
            {
                  List<ITextChunk> messageChunks;
                  
                  lock (_splitters)
                  {
                        CreateSplitter (protocol);
                        
                        if (_splitters.ContainsKey (protocol))
                              messageChunks = _splitters[protocol].SplitMessage (message, style, entity, customEmoticons);
                        else
                        {
                              messageChunks = new List<ITextChunk> ();
                              messageChunks.Add (new TextChunk (style, TextChunkType.Text, message));
                        }
                  }
                  
                  IContact dest = entity as IContact;
                  IAccount account = (dest != null) ? dest.Session.Account : entity as IAccount;
                  bool outgoing = (entity != null) ? entity.Local : false;
                  
                  OrderedDictionary<string, IEmoticon> emots = EmoticonUtility.GetEmoticonDict (account, dest, customEmoticons, outgoing);
                  
                  List<string> searchList = new List<string> ();
                  searchList.Add ("\n");
                  searchList.AddRange (_uriSearchStrings);
                  searchList.AddRange (emots.Keys);
                  
                  List<ITextChunk> chunks = new List<ITextChunk>();
                  
                  foreach (ITextChunk msgChunk in messageChunks)
                  {
                        string chunkTxt = msgChunk.Text.Replace ("\r\n", "\n").Replace ("\r", "\n");
                        SearchResult[] results = SetSearch.SearchAll (chunkTxt, searchList.ToArray ());
                        
                        int pos = 0;
                        
                        foreach (SearchResult result in results)
                        {
                              if (pos < result.Index)
                              {
                                    // Add any text which came before this match
                                    
                                    chunks.Add (new TextChunk (msgChunk.Style, TextChunkType.Text, chunkTxt.Substring (pos, result.Index - pos)));
                                    pos = result.Index;
                              }
                              else if (pos > result.Index)
                              {
                                    // This could happen if we have a URL containing an emoticon equivalent
                                    continue;
                              }
                              
                              if (result.Match == "\n")
                              {
                                    // PangoUtility expects new lines to be in separate chunks
                                    
                                    chunks.Add (new TextChunk (msgChunk.Style, TextChunkType.Text, "\n"));
                                    pos++;
                              }
                              else if (_uriSearchStrings.Contains (result.Match))
                              {
                                    // This is a hyperlink
                                    
                                    int end = chunkTxt.IndexOfAny (WhitespaceChars, result.Index);
                                    string url = (end < 0) ? chunkTxt.Substring (result.Index) : chunkTxt.Substring (result.Index, end - result.Index);
                                    
                                    chunks.Add (new TextChunk (msgChunk.Style, TextChunkType.URL, url));
                                    
                                    pos += url.Length;
                              }
                              else
                              {
                                    // This is an emoticon
                                    
                                    chunks.Add (new EmoticonTextChunk (msgChunk.Style, result.Match, emots[result.Match]));
                                    pos += result.Length;
                              }
                        }
                        
                        // Any remaining text after the last match
                        if (pos < chunkTxt.Length)
                              chunks.Add (new TextChunk (msgChunk.Style, TextChunkType.Text, chunkTxt.Substring (pos)));
                  }
                  
                  return chunks;
            }
            
            public static IEnumerable<ITextChunk> ParseHyperlinks (string text, ITextStyle style, TextChunkType type)
            {
                  MatchCollection matches = _regexHyperlinks.Matches (text);
                  if (matches.Count == 0) {
                        yield return new TextChunk (style, type, text);
                  } else {
                        int prev = 0;
                        ITextChunk subChunk = null;
                        foreach (Match match in matches) {
                              if (prev < match.Index) {
                                    string chunkText = text.Substring (prev, match.Index - prev);
                                    subChunk = new TextChunk (style, type, chunkText);
                                    yield return subChunk;
                              }
                              
                              subChunk = new TextChunk (style, TextChunkType.URL, match.Value.ToString ());
                              yield return subChunk;
                              
                              prev = match.Index + match.Length;
                        }
                        
                        if (prev < (text.Length - 1)) {
                              string chunkText = text.Substring (prev);
                              subChunk = new TextChunk (style, type, chunkText);
                              yield return subChunk;
                        }
                  }
            }
            
            // Always call from within lock (_splitters)
            static void CreateSplitter (IProtocol protocol)
            {
                  if (!_splitters.ContainsKey (protocol))
                  {
                        IMessageSplitter splitter = null;
                        IProtocolFactory factory = ProtocolUtility.GetProtocolFactory (protocol);
                        
                        // Example protocol for the message display prefs doesn't have a factory
                        if (factory != null)
                              splitter = factory.CreateSplitter ();
                        
                        if (splitter != null)
                              _splitters.Add (protocol, splitter);
                  }
            }
            
            public static string StripMarkup (string message, IProtocol protocol)
            {
                  List<ITextChunk> chunks;
                  
                  lock (_splitters)
                  {
                        CreateSplitter (protocol);
                        
                        if (!_splitters.ContainsKey (protocol))
                              return message;
                        
                        chunks = _splitters[protocol].SplitMessage (message, new TextStyle (), null, null);
                  }
                  
                  string output = string.Empty;
                  
                  foreach (ITextChunk chunk in chunks)
                        output += chunk.Text;
                  
                  return output;
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index