discomfitor pushed a commit to branch enlightenment-0.19.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=6530a73db8379a16fd890bd483ec133ddb60167a

commit 6530a73db8379a16fd890bd483ec133ddb60167a
Author: Mike Blumenkrantz <zm...@osg.samsung.com>
Date:   Thu Apr 30 14:11:06 2015 -0400

    fix notification text to conform to spec and libnotify implementation
    
    fix T2053
    fix T2187
---
 src/modules/notification/e_mod_popup.c | 126 +++++++++++++++++++++++++++++++--
 1 file changed, 121 insertions(+), 5 deletions(-)

diff --git a/src/modules/notification/e_mod_popup.c 
b/src/modules/notification/e_mod_popup.c
index 907faf6..1647af4 100644
--- a/src/modules/notification/e_mod_popup.c
+++ b/src/modules/notification/e_mod_popup.c
@@ -17,6 +17,47 @@ static void        _notification_popdown(Popup_Data          
        *popup,
  * happily, it was decided that the function would not be external so that it 
could
  * be duplicated into the module in full.
  */
+
+static int
+_text_escape(Eina_Strbuf *txt, const char *text)
+{
+   const char *escaped;
+   int advance;
+
+   escaped = evas_textblock_string_escape_get(text, &advance);
+   if (!escaped)
+     {
+        eina_strbuf_append_char(txt, text[0]);
+        advance = 1;
+     }
+   else
+     eina_strbuf_append(txt, escaped);
+   return advance;
+}
+
+/* hardcoded list of allowed tags based on
+ * 
https://people.gnome.org/~mccann/docs/notification-spec/notification-spec-latest.html#markup
+ */
+static const char *tags[] =
+{
+   "<b",
+   "<i",
+   "<u",
+   //"<a", FIXME: we can't actually display these right now
+   //"<img",
+};
+
+static const char *
+_get_tag(const char *c)
+{
+   unsigned int i;
+
+   if (c[1] != '>') return NULL;
+   for (i = 0; i < EINA_C_ARRAY_LENGTH(tags); i++)
+     if (tags[i][1] == c[0]) return tags[i];
+   return NULL;
+}
+
 char *
 _nedje_text_escape(const char *text)
 {
@@ -24,28 +65,103 @@ _nedje_text_escape(const char *text)
    char *ret;
    const char *text_end;
    size_t text_len;
+   Eina_Array *arr;
+   const char *cur_tag = NULL;
 
    if (!text) return NULL;
 
    txt = eina_strbuf_new();
    text_len = strlen(text);
+   arr = eina_array_new(3);
 
    text_end = text + text_len;
    while (text < text_end)
      {
         int advance;
-        const char *escaped = evas_textblock_string_escape_get(text, &advance);
-        if (!escaped)
+
+        if ((text[0] == '<') && text[1])
+          {
+             const char *tag, *popped;
+             Eina_Bool closing = EINA_FALSE;
+
+             if (text[1] == '/') //closing tag
+               {
+                  closing = EINA_TRUE;
+                  tag = _get_tag(text + 2);
+               }
+             else
+               tag = _get_tag(text + 1);
+             if (closing)
+               {
+                  if (cur_tag && (tag != cur_tag))
+                    {
+                       /* tag mismatch: autoclose all failure tags
+                        * not technically required by the spec,
+                        * but it makes me feel better about myself
+                        */
+                       do
+                         {
+                            popped = eina_array_pop(arr);
+                            if (eina_array_count(arr))
+                              cur_tag = eina_array_data_get(arr, 
eina_array_count(arr) - 1);
+                            else
+                              cur_tag = NULL;
+                            eina_strbuf_append_printf(txt, "</%c>", popped[1]);
+                         } while (cur_tag && (popped != tag));
+                       advance = 4;
+                    }
+                  else if (cur_tag)
+                    {
+                       /* tag match: just pop */
+                       popped = eina_array_pop(arr);
+                       if (eina_array_count(arr))
+                         cur_tag = eina_array_data_get(arr, 
eina_array_count(arr) - 1);
+                       else
+                         cur_tag = NULL;
+                       eina_strbuf_append_printf(txt, "</%c>", popped[1]);
+                       advance = 4;
+                    }
+                  else
+                    {
+                       /* no current tag: escape */
+                       advance = _text_escape(txt, text);
+                    }
+               }
+             else
+               {
+                  if (tag)
+                    {
+                       cur_tag = tag;
+                       eina_array_push(arr, tag);
+                       eina_strbuf_append_printf(txt, "<%c>", tag[1]);
+                       advance = 3;
+                    }
+                  else
+                    advance = _text_escape(txt, text);
+               }
+          }
+        else if (text[0] == '&')
           {
-             eina_strbuf_append_char(txt, text[0]);
-             advance = 1;
+             const char *s;
+
+             s = strchr(text, ';');
+             if (s)
+               s = evas_textblock_escape_string_range_get(text, s + 1);
+             if (s)
+               {
+                  eina_strbuf_append_char(txt, text[0]);
+                  advance = 1;
+               }
+             else
+               advance = _text_escape(txt, text);
           }
         else
-          eina_strbuf_append(txt, escaped);
+          advance = _text_escape(txt, text);
 
         text += advance;
      }
 
+   eina_array_free(arr);
    ret = eina_strbuf_string_steal(txt);
    eina_strbuf_free(txt);
    return ret;

-- 


Reply via email to