/* Stringshared, so I can just compare pointers later */
static const char *text_uri;
+
+/* For convert EFL to HTML */
+
+#define TAGPOS_START 0x00000001
+#define TAGPOS_END 0x00000002
+#define TAGPOS_ALONE 0x00000003
+
+/* TEXTBLOCK tag using stack but close tag word has no mean maybe bug...
+ * TEXTBLOCK <b>bold<font>font</b>bold</font>
+ * HTML <b>bold<font>font bold</b>font</font> */
+
+typedef struct _TagTable {
+ char *src;
+ char *dst;
+ char tagType;
+}TagTable;
+
+TagTable _EFLtoHTMLConvertTable[] = {
+ {"font", "font", 0},
+ {"underline", "del", 0},
+ {"strikethrough", "ins", 0},
+ {"br", "br", 1},
+ {"b", "b", 1},
+ {"item", "img", 1}
+};
+
+typedef struct _TagNode TagNode, *PTagNode;
+struct _TagNode {
+ char *tag; //EINA_STRINGSHARE if NULL just str
+ char *tag_str;
+ char *str;
+ char *pos_in_ori_str;
+ PTagNode matchTag;
+ void *tagData;
+ unsigned char tagPosType;
+};
+
+typedef struct _FontTagData FontTagData, *PFontTagData;
+struct _FontTagData {
+ char *name;
+ char *color;
+ char *size;
+ char *bg_color;
+};
+
+
+typedef struct _ItemTagData ItemTagData, *PItemTagData;
+struct _ItemTagData {
+ char *href;
+ char *width;
+ char *height;
+};
+
+#define SAFEFREE(ptr) \
+ do\
+{\
+ if (ptr)\
+ free(ptr);\
+ ptr = NULL;\
+} while(0);\
+
+#define freeAndAssign(dst, value) \
+ do\
+{\
+ if (value)\
+ {\
+ SAFEFREE(dst);\
+ dst = value;\
+ }\
+} while(0);
+
+
+static PTagNode _new_tag_node(char *tag, char *tag_str, char* str, char *pos_in_ori_str);
+static PTagNode _get_start_node(char *str);
+static PTagNode _get_next_node(PTagNode prev);
+static void _delete_node(PTagNode node);
+static void _link_match_tags(Eina_List *nodes);
+static char *_get_tag_value(const char *tag_str, const char *tag_name);
+static char *_convert_to_html(Eina_List* nodes);
+static void _set_EFL_tag_data(Eina_List* nodes);
+static PFontTagData _set_EFL_font_data(PFontTagData data, const char *tag_str);
+static PItemTagData _set_EFL_item_data(PItemTagData data, const char *tag_str);
+
+#ifdef DEBUGON
+static void _dumpNode(Eina_List* nodes);
+#endif
+
+static PTagNode
+_new_tag_node(char *tag, char *tag_str, char* str, char *pos_in_ori_str)
+{
+ PTagNode newNode = calloc(1, sizeof(TagNode));
+ newNode->tag = tag;
+ newNode->tag_str = tag_str;
+ newNode->str = str;
+ newNode->pos_in_ori_str = pos_in_ori_str;
+ return newNode;
+}
+
+static PTagNode
+_get_start_node(char *str)
+{
+ char *startStr = NULL;
+ if (!str || str[0] == '\0')
+ return NULL;
+
+ if (str[0] != '<')
+ {
+ char *tagStart = strchr(str, '<');
+ if (!tagStart)
+ startStr = strdup(str);
+ else
+ {
+ int strLength = tagStart - str;
+ startStr = malloc(sizeof(char) * (strLength + 1));
+ strncpy(startStr, str, strLength);
+ startStr[strLength] = '\0';
+ }
+ }
+
+ return _new_tag_node(NULL, NULL, startStr, str);
+}
+
+static PTagNode
+_get_next_node(PTagNode prev)
+{
+ PTagNode retTag = NULL;
+ char *tagStart;
+ char *tagEnd;
+ char *tagNameEnd = NULL;
+ char *nextTagStart;
+
+ if (prev->tag == NULL)
+ tagStart = strchr(prev->pos_in_ori_str, '<');
+ else
+ tagStart = strchr(prev->pos_in_ori_str + 1, '<');
+
+ if (!tagStart)
+ return retTag;
+
+ tagEnd = strchr(tagStart, '>');
+ nextTagStart = strchr(tagStart + 1, '<');
+
+ if (!tagEnd || (nextTagStart && (nextTagStart < tagEnd)))
+ return _get_start_node(tagStart + 1);
+
+ int spCnt = 5;
+ char *spArray[spCnt];
+ spArray[0] = strchr(tagStart, '=');
+ spArray[1] = strchr(tagStart, '_');
+ spArray[2] = strchr(tagStart, ' ');
+ spArray[3] = strchr(tagStart, '\t');
+ spArray[4] = strchr(tagStart, '\n');
+ tagNameEnd = tagEnd;
+
+ int i;
+ for (i = 0; i < spCnt; i++)
+ {
+ if (spArray[i] && spArray[i] < tagNameEnd)
+ tagNameEnd = spArray[i];
+ }
+
+ int tagLength = tagNameEnd - tagStart - 1;
+ char *tagName = NULL;
+ if (!strncmp(&tagStart[1], "color", tagLength))
+ tagName = strndup("font", 4);
+ else if (!strncmp(&tagStart[1], "/color", tagLength))
+ tagName = strndup("/font", 5);
+ else if (!strncmp(&tagStart[1], "/item", tagLength))
+ tagName = strdup("");
+ else
+ tagName = strndup(&tagStart[1], tagLength);
+
+ int tagStrLength = 0;
+ char *tagStr = NULL;
+ if (tagName)
+ {
+ tagStrLength = tagEnd - tagStart + 1;
+ tagStr = strndup(tagStart, tagStrLength);
+ }
+
+ unsigned int strLength = nextTagStart ? (unsigned int)(nextTagStart - tagEnd - 1) : strlen(&tagEnd[1]);
+ char *str = strndup(&tagEnd[1], strLength);
+
+ retTag = _new_tag_node(tagName, tagStr, str, tagStart);
+ return retTag;
+}
+
+
+static void
+_delete_node(PTagNode node)
+{
+ if (node)
+ {
+ SAFEFREE(node->tag_str);
+ SAFEFREE(node->str);
+
+ if (node->tagData)
+ {
+ if (node->tag)
+ {
+ if (!strcmp("font", node->tag))
+ {
+ PFontTagData data = node->tagData;
+ SAFEFREE(data->name);
+ SAFEFREE(data->color);
+ SAFEFREE(data->size);
+ SAFEFREE(data->bg_color);
+ }
+ if (!strcmp("item", node->tag))
+ {
+ PItemTagData data = node->tagData;
+ SAFEFREE(data->href);
+ SAFEFREE(data->width);
+ SAFEFREE(data->height);
+ }
+
+ }
+ SAFEFREE(node->tagData);
+ }
+ SAFEFREE(node->tag);
+ SAFEFREE(node);
+ }
+}
+
+static void
+_link_match_tags(Eina_List *nodes)
+{
+ Eina_List *stack = NULL;
+
+ PTagNode trail, popData;
+ Eina_List *l, *r;
+
+ EINA_LIST_FOREACH(nodes, l, trail)
+ {
+ if (!trail->tag || trail->tag[0] == '\0')
+ continue;
+ if (!strcmp("br", trail->tag))
+ {
+ trail->tagPosType = TAGPOS_ALONE;
+ continue;
+ }
+ else if (!strcmp("item", trail->tag))
+ {
+ trail->tagPosType = TAGPOS_ALONE;
+ continue;
+ }
+
+ if (trail->tag[0] != '/') // PUSH
+ {
+ stack = eina_list_append(stack, trail);
+/* eina_array_push(stack, trail);
+ cnp_debug("stack: %d, tag %s\n", eina_array_count_get(stack), trail->tag);*/
+ cnp_debug("stack: %d, tag %s\n", eina_list_count(stack), trail->tag);
+ }
+ else // POP
+ {
+ if (!eina_list_count(stack))
+ {
+ cnp_debug("tag not matched %s\n", trail->tag);
+ continue;
+ }
+
+ EINA_LIST_REVERSE_FOREACH(stack, r, popData)
+ {
+ if (popData->tag && !strcmp(popData->tag, &trail->tag[1]))
+ {
+ popData->tagPosType = TAGPOS_START;
+ trail->tagPosType = TAGPOS_END;
+ popData->matchTag = trail;
+ trail->matchTag = popData;
+ stack = eina_list_remove_list(stack, r);
+ break;
+ }
+ }
+/* popData = eina_array_pop(stack);
+
+ popData->tagPosType = TAGPOS_START;
+ trail->tagPosType = TAGPOS_END;
+ popData->matchTag = trail;
+ trail->matchTag = popData;
+ cnp_debug("pop stack: %d, tag %s\n", eina_array_count_get(stack), trail->tag);
+ */
+ }
+ }
+
+/* if (eina_array_count_get(stack))
+ cnp_debug("stack state: %d, tag %s\n", eina_array_count_get(stack), trail->tag);*/
+
+ /* Make Dummy close tag */
+/* while ((popData = eina_array_pop(stack))) */
+
+ EINA_LIST_REVERSE_FOREACH(stack, r, popData)
+ {
+ PTagNode newData;
+ int tagLength = strlen(popData->tag);
+ char *tagName = malloc(sizeof(char) * (tagLength + 2));
+
+ tagName[0] = '/';
+ tagName[1] = '\0';
+ strcat(tagName, popData->tag);
+
+ newData = _new_tag_node(tagName, NULL, NULL, NULL);
+ popData->tagPosType = TAGPOS_START;
+ newData->tagPosType = TAGPOS_END;
+ popData->matchTag = newData;
+ newData->matchTag = popData;
+ nodes = eina_list_append(nodes, newData);
+/* cnp_debug("stack: %d, tag %s\n", eina_array_count_get(stack), popData->tag);*/
+ }
+/* cnp_debug("stack_top: %d\n", eina_array_count_get(stack));
+ eina_array_free(stack);*/
+ eina_list_free(stack);
+}
+
+static char *
+_get_tag_value(const char *tag_str, const char *tag_name)
+{
+ if (!tag_name || !tag_str)
+ return NULL;
+
+ char *tag;
+ if ((tag = strstr(tag_str, tag_name)))
+ {
+ if (tag[strlen(tag_name)] == '_')
+ return NULL;
+ char *value = strchr(tag, '=');
+ if (value)
+ {
+ do
+ {
+ value++;
+ } while (!isalnum(*value) && *value != '#');
+
+ int spCnt = 6;
+ char *spArray[spCnt];
+ spArray[0] = strchr(value, ' ');
+ spArray[1] = strchr(value, '>');
+ spArray[2] = strchr(value, '\"');
+ spArray[3] = strchr(value, '\'');
+ spArray[4] = strchr(value, '\t');
+ spArray[5] = strchr(value, '\n');
+ char *valueEnd = strchr(value, '\0');
+
+ int i;
+ for (i = 0; i < spCnt; i++)
+ {
+ if (spArray[i] && spArray[i] < valueEnd)
+ valueEnd = spArray[i];
+ }
+
+ int valueLength = valueEnd - value;
+ return strndup(value, valueLength);
+ }
+ }
+ return NULL;
+}
+
+static PFontTagData
+_set_EFL_font_data(PFontTagData data, const char *tag_str)
+{
+ char *value;
+
+ if (!data)
+ data = calloc(1, sizeof(FontTagData));
+ value = _get_tag_value(tag_str, "font_size");
+ freeAndAssign(data->size, value);
+ value = _get_tag_value(tag_str, "color");
+ freeAndAssign(data->color, value);
+ value = _get_tag_value(tag_str, "bgcolor");
+ freeAndAssign(data->bg_color, value);
+ value = _get_tag_value(tag_str, "font");
+ freeAndAssign(data->name, value);
+
+ return data;
+}
+
+static PItemTagData
+_set_EFL_item_data(PItemTagData data, const char *tag_str)
+{
+ char *value;
+
+ if (!data)
+ data = calloc(1, sizeof(ItemTagData));
+ value = _get_tag_value(tag_str, "href");
+ if (value)
+ {
+ char *path = strstr(value, "file://");
+ if (path)
+ {
+ char *modify = malloc(sizeof(char) * (strlen(value) + 1));
+ strncpy(modify, "file://", 7);
+ modify[7] = '\0';
+ path += 7;
+ while (path[1] && path[0] && path[1] == '/' && path[0] == '/')
+ {
+ path++;
+ }
+ strcat(modify, path);
+ data->href = modify;
+ cnp_debug("image href ---%s---\n", data->href);
+ }
+ free(value);
+ }
+
+ value = _get_tag_value(tag_str, "absize");
+ if (value)
+ {
+ char *xpos = strchr(value, 'x');
+ if (xpos)
+ {
+ int absizeLen = strlen(value);
+ freeAndAssign(data->width, strndup(value, xpos - value));
+ freeAndAssign(data->height, strndup(xpos + 1, absizeLen - (xpos - value) - 1));
+ cnp_debug("image width: -%s-, height: -%s-\n", data->width, data->height);
+ }
+ free(value);
+ }
+ return data;
+}
+
+static void
+_set_EFL_tag_data(Eina_List* nodes)
+{
+ PTagNode trail;
+ Eina_List *l;
+
+ EINA_LIST_FOREACH(nodes, l, trail)
+ {
+ if (!trail->tag)
+ continue;
+ if (!strcmp("font", trail->tag))
+ trail->tagData = _set_EFL_font_data(trail->tagData, trail->tag_str);
+ else if (!strcmp("item", trail->tag))
+ trail->tagData = _set_EFL_item_data(trail->tagData, trail->tag_str);
+ }
+}
+
+#ifdef DEBUGON
+static void
+_dumpNode(Eina_List* nodes)
+{
+ PTagNode trail;
+ Eina_List *l;
+
+ EINA_LIST_FOREACH(nodes, l, trail)
+ {
+ cnp_debug("tag: %s, tag_str: %s, str: %s, tagPosType: %d\n",
+ trail->tag, trail->tag_str, trail->str, trail->tagPosType);
+ cnp_debug("matchTag: %x ", (unsigned int)trail->matchTag);
+ if (trail->matchTag)
+ cnp_debug("matchTag->tag_str: %s", trail->matchTag->tag_str);
+ if (trail->tagData)
+ {
+ if (!strcmp(trail->tag, "font"))
+ {
+ PFontTagData data = trail->tagData;
+ cnp_debug(" tagData->name: %s, tagData->color: %s, tagData->size: %s, tagData->bg_color: %s",
+ data->name, data->color, data->size, data->bg_color);
+ }
+ else if (!strcmp(trail->tag, "item"))
+ {
+ PItemTagData data = trail->tagData;
+ cnp_debug(" tagData->href: %s, tagData->width: %s, tagData->height: %s",
+ data->href, data->width, data->height);
+ }
+ else
+ cnp_debug("\nERROR!!!! not need tagData");
+ }
+ cnp_debug("\n");
+ }
+}
+#endif
+
+static char *
+_convert_to_html(Eina_List* nodes)
+{
+ PTagNode trail;
+ Eina_List *l;
+
+ Eina_Strbuf *html = eina_strbuf_new();
+
+ int tableCnt = sizeof(_EFLtoHTMLConvertTable) / sizeof(TagTable);
+
+ EINA_LIST_FOREACH(nodes, l, trail)
+ {
+ if (trail->tag)
+ {
+ char *tagName = trail->tagPosType == TAGPOS_END ?
+ trail->matchTag->tag : trail->tag;
+ int j;
+ for(j = 0; j < tableCnt; j++)
+ {
+ if (!strcmp(_EFLtoHTMLConvertTable[j].src, tagName))
+ {
+ switch(trail->tagPosType)
+ {
+ case TAGPOS_END:
+ eina_strbuf_append(html, "</");
+ break;
+ default:
+ eina_strbuf_append(html, "<");
+ break;
+ }
+
+ eina_strbuf_append(html, _EFLtoHTMLConvertTable[j].dst);
+ if (trail->tagPosType != TAGPOS_END)
+ {
+ if (!strcmp(_EFLtoHTMLConvertTable[j].src, "font"))
+ {
+ PFontTagData data = trail->tagData;
+ if (data->name)
+ {
+ }
+ if (data->color)
+ eina_strbuf_append_printf(html, " color=\"%s\"", data->color);
+ if (data->size)
+ eina_strbuf_append_printf(html, " size=\"%s\"", data->size);
+ if (data->bg_color)
+ {
+ }
+ }
+ else if (!strcmp(_EFLtoHTMLConvertTable[j].src, "item"))
+ {
+ PItemTagData data = trail->tagData;
+ if (data->href)
+ eina_strbuf_append_printf(html, " src=\"%s\"", data->href);
+ if (data->width)
+ eina_strbuf_append_printf(html, " width=\"%s\"", data->width);
+ if (data->height)
+ eina_strbuf_append_printf(html, " height=\"%s\"", data->height);
+ }
+ }
+ switch(trail->tagPosType)
+ {
+ case TAGPOS_ALONE:
+ eina_strbuf_append(html, "/>");
+ break;
+ default:
+ eina_strbuf_append(html, ">");
+ break;
+ }
+ break;
+ }
+ }
+ }
+ if (trail->str)
+ eina_strbuf_append(html, trail->str);
+ }
+
+ char *ret = eina_strbuf_string_steal(html);
+ eina_strbuf_free(html);
+ return ret;
+}
+
Eina_Bool
elm_selection_set(Elm_Sel_Type selection, Evas_Object *widget, Elm_Sel_Format format, const char *selbuf)
{
Cnp_Selection *sel;
sel = selections + *(int *)data;
- if (data_ret) *data_ret = strdup(sel->selbuf);
- if (size_ret) *size_ret = strlen(sel->selbuf);
+
+ char *html = NULL;
+ if (data_ret && (sel->format & ELM_SEL_FORMAT_MARKUP))
+ {
+ Eina_List *nodeList = NULL;
+ Eina_List *trail;
+ PTagNode nodeData;
+
+ nodeData = _get_start_node(sel->selbuf);
+
+ while (nodeData)
+ {
+ nodeList = eina_list_append(nodeList, nodeData);
+ nodeData = _get_next_node(nodeData);
+ }
+
+ _link_match_tags(nodeList);
+
+ _set_EFL_tag_data(nodeList);
+
+#ifdef DEBUGON
+ _dumpNode(nodeList);
+#endif
+ html = _convert_to_html(nodeList);
+
+ cnp_debug("convert html: %s\n", html);
+
+ EINA_LIST_FOREACH(nodeList, trail, nodeData)
+ _delete_node(nodeData);
+ eina_list_free(nodeList);
+ }
+ if (data_ret)
+ {
+ if (html)
+ *data_ret = html;
+ else
+ *data_ret = strdup(sel->selbuf);
+ }
+
+ if (size_ret)
+ {
+ if (html)
+ *size_ret = strlen(html);
+ else
+ *size_ret = strlen(sel->selbuf);
+ }
return EINA_TRUE;
}