Exemple #1
0
        public static void ParseSmileys(MessageModel msg)
        {
            string simleyRegex;
            simleyRegex = @":-?(\(|\))";
            Regex reg = new Regex(simleyRegex);
            // clone MessageParts
            IList<MessagePartModel> parts = new List<MessagePartModel>(msg.MessageParts);
            foreach (MessagePartModel part in parts) {
                if (!(part is TextMessagePartModel)) {
                    continue;
                }

                TextMessagePartModel textPart = (TextMessagePartModel) part;
                Match simleyMatch = reg.Match(textPart.Text);
                // OPT: fast regex scan
                if (!simleyMatch.Success) {
                    // no smileys in this MessagePart, nothing to do
                    continue;
                }

                // found smiley(s)
                // remove current MessagePartModel as we need to split it
                int idx = msg.MessageParts.IndexOf(part);
                msg.MessageParts.RemoveAt(idx);

                string[] textPartParts = textPart.Text.Split(new char[] {' '});
                for (int i = 0; i < textPartParts.Length; i++) {
                    string textPartPart = textPartParts[i];
                    simleyMatch = reg.Match(textPartPart);
                    if (simleyMatch.Success) {
                        string filename = null;
                        if (textPartPart == ":-)") {
                            filename = "smile.png";
                        }
                        ImageMessagePartModel imagePart = new ImageMessagePartModel(
                            filename,
                            textPartPart
                        );
                        msg.MessageParts.Insert(idx++, imagePart);
                        msg.MessageParts.Insert(idx++, new TextMessagePartModel(" "));
                    } else {
                        // FIXME: we put each text part into it's own object, instead of combining them (the smart way)
                        TextMessagePartModel notUrlPart = new TextMessagePartModel(textPartPart + " ");
                        // restore formatting / colors from the original text part
                        notUrlPart.IsHighlight     = textPart.IsHighlight;
                        notUrlPart.ForegroundColor = textPart.ForegroundColor;
                        notUrlPart.BackgroundColor = textPart.BackgroundColor;
                        notUrlPart.Bold            = textPart.Bold;
                        notUrlPart.Italic          = textPart.Italic;
                        notUrlPart.Underline       = textPart.Underline;
                        msg.MessageParts.Insert(idx++, notUrlPart);
                    }
                }
            }
        }
Exemple #2
0
        public static IList <MessagePartModel> ParsePatterns(TextMessagePartModel textPart,
                                                             List <MessagePatternModel> patterns)
        {
            if (textPart == null)
            {
                throw new ArgumentNullException("textPart");
            }
            if (patterns == null)
            {
                throw new ArgumentNullException("patterns");
            }

            var msgParts = new List <MessagePartModel>();

            if (patterns.Count == 0)
            {
                // all patterns have been tried -> this text is PURE text
                msgParts.Add(textPart);
                return(msgParts);
            }

            var remainingPatterns = new List <MessagePatternModel>(patterns);
            var pattern           = remainingPatterns.First();

            remainingPatterns.Remove(pattern);

            var match = pattern.MessagePartPattern.Match(textPart.Text);

            if (!match.Success)
            {
                // no matches in this MessagePart, try other smartlinks
                return(ParsePatterns(textPart, remainingPatterns));
            }

            int lastindex = 0;

            do
            {
                var groupValues = new string[match.Groups.Count];
                int i           = 0;
                foreach (Group @group in match.Groups)
                {
                    groupValues[i++] = @group.Value;
                }

                string url;
                if (String.IsNullOrEmpty(pattern.LinkFormat))
                {
                    url = match.Value;
                }
                else
                {
                    url = String.Format(pattern.LinkFormat, groupValues);
                }
                string text;
                if (String.IsNullOrEmpty(pattern.TextFormat))
                {
                    text = match.Value;
                }
                else
                {
                    text = String.Format(pattern.TextFormat, groupValues);
                }

                if (lastindex != match.Index)
                {
                    // there were some non-matching-chars before the match
                    // copy that to a TextMessagePartModel
                    var notMatchPart = new TextMessagePartModel(textPart);
                    // only take the proper chunk of text
                    notMatchPart.Text = textPart.Text.Substring(lastindex, match.Index - lastindex);
                    // and try other patterns on this part
                    var parts = ParsePatterns(notMatchPart, remainingPatterns);
                    foreach (var part in parts)
                    {
                        msgParts.Add(part);
                    }
                }

                MessagePartModel msgPart;
                if (pattern.MessagePartType == typeof(UrlMessagePartModel))
                {
                    // no need to set URL and text if they are the same
                    text    = text == url ? null : text;
                    msgPart = new UrlMessagePartModel(url, text);
                }
                else if (pattern.MessagePartType == typeof(ImageMessagePartModel))
                {
                    msgPart = new ImageMessagePartModel(url, text);
                }
                else
                {
                    msgPart = new TextMessagePartModel(text);
                }
                msgParts.Add(msgPart);
                lastindex = match.Index + match.Length;
                match     = match.NextMatch();
            } while (match.Success);

            if (lastindex != textPart.Text.Length)
            {
                // there were some non-url-chars before this url
                // copy TextMessagePartModel
                var notMatchPart = new TextMessagePartModel(textPart);
                // only take the proper chunk of text
                notMatchPart.Text = textPart.Text.Substring(lastindex);
                // and try other smartlinks on this part
                var parts = ParsePatterns(notMatchPart, remainingPatterns);
                foreach (var part in parts)
                {
                    msgParts.Add(part);
                }
            }
            return(msgParts);
        }
Exemple #3
0
 static void AddAlternativeText(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, ImageMessagePartModel imgPart)
 {
     if (!String.IsNullOrEmpty(imgPart.AlternativeText)) {
         buffer.Insert(ref iter, imgPart.AlternativeText);
     }
 }
Exemple #4
0
        void AddEmoji(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, ImageMessagePartModel imgPart, string shortName)
        {
            var unicode = Emojione.ShortnameToUnicode(shortName);
            if (unicode == null) {
                AddAlternativeText(buffer, ref iter, imgPart);
                return;
            }

            int width, height;
            int widthPango, heightPango;
            int descent;
            using (var layout = CreatePangoLayout(null)) {
                layout.GetPixelSize(out width, out height);
                layout.GetSize(out widthPango, out heightPango);
                descent = layout.Context.GetMetrics(layout.FontDescription, null).Descent;
            }

            // A mark here serves two pusposes. One is to allow us to apply the
            // tag across the pixbuf. It also lets us know later where to put
            // the pixbuf if we need to load it from the network
            var mark = new Gtk.TextMark(null, true);
            buffer.AddMark(mark, iter);

            var emojiName = unicode + ".png";
            string emojiPath;
            if (EmojiCache.TryGetIcon("emojione", emojiName, out emojiPath)) {
                var emojiFile = new FileInfo(emojiPath);
                if (emojiFile.Exists && emojiFile.Length > 0) {
                    var pix = new Gdk.Pixbuf(emojiPath, -1, height);
                    buffer.InsertPixbuf(ref iter, pix);
                    var beforeIter = buffer.GetIterAtMark(mark);
                    var imgTag = new EmojiTag(mark, emojiFile.FullName);
                    imgTag.Rise = - descent;
                    _MessageTextTagTable.Add(imgTag);
                    buffer.ApplyTag(imgTag, beforeIter, iter);
                } else {
                    AddAlternativeText(buffer, ref iter, imgPart);
                }

                return;
            }

            var emojiUrl = Emojione.UnicodeToUrl(unicode);
            EmojiCache.BeginDownloadFile("emojione", emojiName, emojiUrl,
                (path) => {
                    GLib.Idle.Add(delegate {
                        var afterIter = buffer.GetIterAtMark(mark);
                        buffer.InsertPixbuf(ref afterIter, new Gdk.Pixbuf(path, -1, height));
                        var beforeIter = buffer.GetIterAtMark(mark);
                        var emojiTag = new EmojiTag(mark, path);
                        _MessageTextTagTable.Add(emojiTag);
                        emojiTag.Rise = - descent;
                        buffer.ApplyTag(emojiTag, beforeIter, afterIter);
                        return false;
                    });
                },
                (ex) => {
                    GLib.Idle.Add(delegate {
                        var markIter = buffer.GetIterAtMark(mark);
                        buffer.DeleteMark(mark);
                        AddAlternativeText(buffer, ref markIter, imgPart);
                        return false;
                    });
                }
            );
        }
Exemple #5
0
 private void InsertToBuffer(Gtk.TextBuffer buffer, ref Gtk.TextIter iter, ImageMessagePartModel imgpart)
 {
     Uri uri = null;
     string scheme = null;
     try {
         uri = new Uri(imgpart.ImageFileName);
         scheme = uri.Scheme;
     } catch (UriFormatException) {
         AddAlternativeText(buffer, ref iter, imgpart);
     }
     switch (scheme) {
         case "smuxi-emoji":
             var shortName = uri.Host;
             AddEmoji(buffer, ref iter, imgpart, shortName);
             break;
         default:
             AddAlternativeText(buffer, ref iter, imgpart);
             break;
     }
 }
Exemple #6
0
        public static IList<MessagePartModel> ParsePatterns(TextMessagePartModel textPart,
                                                            List<MessagePatternModel> patterns)
        {
            if (textPart == null) {
                throw new ArgumentNullException("textPart");
            }
            if (patterns == null) {
                throw new ArgumentNullException("patterns");
            }

            var msgParts = new List<MessagePartModel>();
            if (patterns.Count == 0) {
                // all patterns have been tried -> this text is PURE text
                msgParts.Add(textPart);
                return msgParts;
            }

            var remainingPatterns = new List<MessagePatternModel>(patterns);
            var pattern = remainingPatterns.First();
            remainingPatterns.Remove(pattern);

            var match = pattern.MessagePartPattern.Match(textPart.Text);
            if (!match.Success) {
                // no matches in this MessagePart, try other smartlinks
                return ParsePatterns(textPart, remainingPatterns);
            }

            int lastindex = 0;
            do {
                var groupValues = new string[match.Groups.Count];
                int i = 0;
                foreach (Group @group in match.Groups) {
                    groupValues[i++] = @group.Value;
                }

                string url;
                if (String.IsNullOrEmpty(pattern.LinkFormat)) {
                    url = match.Value;
                } else {
                    url = String.Format(pattern.LinkFormat, groupValues);
                }
                string text;
                if (String.IsNullOrEmpty(pattern.TextFormat)) {
                    text = match.Value;
                } else {
                    text = String.Format(pattern.TextFormat, groupValues);
                }

                if (lastindex != match.Index) {
                    // there were some non-matching-chars before the match
                    // copy that to a TextMessagePartModel
                    var notMatchPart = new TextMessagePartModel(textPart);
                    // only take the proper chunk of text
                    notMatchPart.Text = textPart.Text.Substring(lastindex, match.Index - lastindex);
                    // and try other patterns on this part
                    var parts = ParsePatterns(notMatchPart, remainingPatterns);
                    foreach (var part in parts) {
                        msgParts.Add(part);
                    }
                }

                MessagePartModel msgPart;
                if (pattern.MessagePartType == typeof(UrlMessagePartModel)) {
                    // no need to set URL and text if they are the same
                    text = text == url ? null : text;
                    msgPart = new UrlMessagePartModel(url, text);
                } else if (pattern.MessagePartType == typeof(ImageMessagePartModel)) {
                    msgPart = new ImageMessagePartModel(url, text);
                } else {
                    msgPart = new TextMessagePartModel(text);
                }
                msgParts.Add(msgPart);
                lastindex = match.Index + match.Length;
                match = match.NextMatch();
            } while (match.Success);

            if (lastindex != textPart.Text.Length) {
                // there were some non-url-chars before this url
                // copy TextMessagePartModel
                var notMatchPart = new TextMessagePartModel(textPart);
                // only take the proper chunk of text
                notMatchPart.Text = textPart.Text.Substring(lastindex);
                // and try other smartlinks on this part
                var parts = ParsePatterns(notMatchPart, remainingPatterns);
                foreach (var part in parts) {
                    msgParts.Add(part);
                }
            }
            return msgParts;
        }
Exemple #7
0
        public static IList <MessagePartModel> ParsePatterns(TextMessagePartModel textPart,
                                                             List <MessagePatternModel> patterns)
        {
            if (textPart == null)
            {
                throw new ArgumentNullException("textPart");
            }
            if (patterns == null)
            {
                throw new ArgumentNullException("patterns");
            }

            var msgParts = new List <MessagePartModel>();

            if (patterns.Count == 0)
            {
                // all patterns have been tried -> this text is PURE text
                msgParts.Add(textPart);
                return(msgParts);
            }

            var remainingPatterns = new List <MessagePatternModel>(patterns);
            var pattern           = remainingPatterns.First();

            remainingPatterns.Remove(pattern);

            var match = pattern.MessagePartPattern.Match(textPart.Text);

            if (!match.Success)
            {
                // no matches in this MessagePart, try other smartlinks
                return(ParsePatterns(textPart, remainingPatterns));
            }

            int lastindex = 0;

            do
            {
                var startDelimiterLength = 0;
                var regexDelimiterForStartOfPatternValue = match.Groups[MessageBuilderSettings.StartDelimiterGroupName];
                if (regexDelimiterForStartOfPatternValue != null)
                {
                    startDelimiterLength = regexDelimiterForStartOfPatternValue.Value.Length;
                }
                var endDelimiterLength = 0;
                var regexDelimiterForEndOfPatternValue = match.Groups[MessageBuilderSettings.EndDelimiterGroupName];
                if (regexDelimiterForEndOfPatternValue != null)
                {
                    endDelimiterLength = regexDelimiterForEndOfPatternValue.Value.Length;
                }

                var groupValues = match.Groups.Cast <Group>()

                                  // don't get the delimiter because it only determines
                                  // the start or end of pattern, which is not part of the pattern
                                  .Where(g => g != regexDelimiterForStartOfPatternValue &&
                                         g != regexDelimiterForEndOfPatternValue)

                                  .Select(g => g.Value).ToArray();

                string url;
                if (String.IsNullOrEmpty(pattern.LinkFormat))
                {
                    url = match.Value;
                    url = url.Substring(0 + startDelimiterLength, url.Length - (startDelimiterLength - endDelimiterLength));
                }
                else
                {
                    url = String.Format(pattern.LinkFormat, groupValues);
                }
                string text;
                if (String.IsNullOrEmpty(pattern.TextFormat))
                {
                    text = match.Value;
                }
                else
                {
                    text = String.Format(pattern.TextFormat, groupValues);
                }
                text = text.Substring(0 + startDelimiterLength, text.Length - (startDelimiterLength + endDelimiterLength));

                if (lastindex != match.Index)
                {
                    // there were some non-matching-chars before the match
                    // copy that to a TextMessagePartModel
                    var notMatchPart = new TextMessagePartModel(textPart);
                    // only take the proper chunk of text
                    notMatchPart.Text = textPart.Text.Substring(lastindex, match.Index + startDelimiterLength - lastindex);
                    // and try other patterns on this part
                    var parts = ParsePatterns(notMatchPart, remainingPatterns);
                    foreach (var part in parts)
                    {
                        msgParts.Add(part);
                    }
                }

                MessagePartModel msgPart;
                if (pattern.MessagePartType == typeof(UrlMessagePartModel))
                {
                    // no need to set URL and text if they are the same
                    text    = text == url ? null : text;
                    msgPart = new UrlMessagePartModel(url, text);
                }
                else if (pattern.MessagePartType == typeof(ImageMessagePartModel))
                {
                    msgPart = new ImageMessagePartModel(url, text);
                }
                else
                {
                    msgPart = new TextMessagePartModel(text);
                }
                msgParts.Add(msgPart);
                lastindex = match.Index + match.Length - endDelimiterLength;
                match     = match.NextMatch();
            } while (match.Success);

            if (lastindex != textPart.Text.Length)
            {
                // there were some non-matching-chars after the last match
                // copy TextMessagePartModel
                var notMatchPart = new TextMessagePartModel(textPart);
                // only take the proper chunk of text
                notMatchPart.Text = textPart.Text.Substring(lastindex);
                // and try other smartlinks on this part
                var parts = ParsePatterns(notMatchPart, remainingPatterns);
                foreach (var part in parts)
                {
                    msgParts.Add(part);
                }
            }
            return(msgParts);
        }
Exemple #8
0
        public static void ParseSmileys(MessageModel msg)
        {
            // clone MessageParts
            IList <MessagePartModel> parts = new List <MessagePartModel>(msg.MessageParts);

            foreach (MessagePartModel part in parts)
            {
                if (!(part is TextMessagePartModel))
                {
                    continue;
                }

                TextMessagePartModel textPart = (TextMessagePartModel)part;
                Match simleyMatch             = SimleyRegex.Match(textPart.Text);
                // OPT: fast regex scan
                if (!simleyMatch.Success)
                {
                    // no smileys in this MessagePart, nothing to do
                    continue;
                }

                // found smiley(s)
                // remove current MessagePartModel as we need to split it
                int idx = msg.MessageParts.IndexOf(part);
                msg.MessageParts.RemoveAt(idx);

                string[] textPartParts = textPart.Text.Split(new char[] { ' ' });
                for (int i = 0; i < textPartParts.Length; i++)
                {
                    string textPartPart = textPartParts[i];
                    simleyMatch = SimleyRegex.Match(textPartPart);
                    if (simleyMatch.Success)
                    {
                        string filename = null;
                        if (textPartPart == ":-)")
                        {
                            filename = "smile.png";
                        }
                        ImageMessagePartModel imagePart = new ImageMessagePartModel(
                            filename,
                            textPartPart
                            );
                        msg.MessageParts.Insert(idx++, imagePart);
                        msg.MessageParts.Insert(idx++, new TextMessagePartModel(" "));
                    }
                    else
                    {
                        // FIXME: we put each text part into it's own object, instead of combining them (the smart way)
                        TextMessagePartModel notUrlPart = new TextMessagePartModel(textPartPart + " ");
                        // restore formatting / colors from the original text part
                        notUrlPart.IsHighlight     = textPart.IsHighlight;
                        notUrlPart.ForegroundColor = textPart.ForegroundColor;
                        notUrlPart.BackgroundColor = textPart.BackgroundColor;
                        notUrlPart.Bold            = textPart.Bold;
                        notUrlPart.Italic          = textPart.Italic;
                        notUrlPart.Underline       = textPart.Underline;
                        msg.MessageParts.Insert(idx++, notUrlPart);
                    }
                }
            }
        }
Exemple #9
0
        public static IList<MessagePartModel> ParsePatterns(TextMessagePartModel textPart,
                                                            List<MessagePatternModel> patterns)
        {
            if (textPart == null) {
                throw new ArgumentNullException("textPart");
            }
            if (patterns == null) {
                throw new ArgumentNullException("patterns");
            }

            var msgParts = new List<MessagePartModel>();
            if (patterns.Count == 0) {
                // all patterns have been tried -> this text is PURE text
                msgParts.Add(textPart);
                return msgParts;
            }

            var remainingPatterns = new List<MessagePatternModel>(patterns);
            var pattern = remainingPatterns.First();
            remainingPatterns.Remove(pattern);

            var match = pattern.MessagePartPattern.Match(textPart.Text);
            if (!match.Success) {
                // no matches in this MessagePart, try other smartlinks
                return ParsePatterns(textPart, remainingPatterns);
            }

            int lastindex = 0;
            do {
                var delimiterLength = 0;
                var regexDelimiterForEndOfPatternValue = match.Groups[MessageBuilderSettings.EndDelimiterGroupName];
                if (regexDelimiterForEndOfPatternValue != null) {
                    delimiterLength = regexDelimiterForEndOfPatternValue.Value.Length;
                }

                var groupValues = match.Groups.Cast<Group>()

                    // don't get the delimiter because it only determines
                    // the end of pattern, which is not part of the pattern
                    .Where(g => g != regexDelimiterForEndOfPatternValue)

                    .Select(g => g.Value).ToArray();

                string url;
                if (String.IsNullOrEmpty(pattern.LinkFormat)) {
                    url = match.Value;
                } else {
                    url = String.Format(pattern.LinkFormat, groupValues);
                }
                url = url.Substring(0, url.Length - delimiterLength);
                string text;
                if (String.IsNullOrEmpty(pattern.TextFormat)) {
                    text = match.Value;
                } else {
                    text = String.Format(pattern.TextFormat, groupValues);
                }
                text = text.Substring(0, text.Length - delimiterLength);

                if (lastindex != match.Index) {
                    // there were some non-matching-chars before the match
                    // copy that to a TextMessagePartModel
                    var notMatchPart = new TextMessagePartModel(textPart);
                    // only take the proper chunk of text
                    notMatchPart.Text = textPart.Text.Substring(lastindex, match.Index - lastindex);
                    // and try other patterns on this part
                    var parts = ParsePatterns(notMatchPart, remainingPatterns);
                    foreach (var part in parts) {
                        msgParts.Add(part);
                    }
                }

                MessagePartModel msgPart;
                if (pattern.MessagePartType == typeof(UrlMessagePartModel)) {
                    // no need to set URL and text if they are the same
                    text = text == url ? null : text;
                    msgPart = new UrlMessagePartModel(url, text);
                } else if (pattern.MessagePartType == typeof(ImageMessagePartModel)) {
                    msgPart = new ImageMessagePartModel(url, text);
                } else {
                    msgPart = new TextMessagePartModel(text);
                }
                msgParts.Add(msgPart);
                lastindex = match.Index + match.Length - delimiterLength;
                match = match.NextMatch();
            } while (match.Success);

            if (lastindex != textPart.Text.Length) {
                // there were some non-url-chars before this url
                // copy TextMessagePartModel
                var notMatchPart = new TextMessagePartModel(textPart);
                // only take the proper chunk of text
                notMatchPart.Text = textPart.Text.Substring(lastindex);
                // and try other smartlinks on this part
                var parts = ParsePatterns(notMatchPart, remainingPatterns);
                foreach (var part in parts) {
                    msgParts.Add(part);
                }
            }
            return msgParts;
        }