From 21982ac9d0ad08b6d6b9968a140908c6f242f790 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Tue, 24 May 2011 12:41:17 +0900 Subject: [PATCH] [elm_cnp_helper.c] add convert from efl tag to html tag --- src/lib/elm_cnp_helper.c | 602 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 600 insertions(+), 2 deletions(-) diff --git a/src/lib/elm_cnp_helper.c b/src/lib/elm_cnp_helper.c index 980308c..5081977 100644 --- a/src/lib/elm_cnp_helper.c +++ b/src/lib/elm_cnp_helper.c @@ -406,6 +406,560 @@ static Ecore_Event_Handler *handler_status = NULL; /* 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 boldfontbold + * HTML boldfont boldfont */ + +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, "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) { @@ -995,8 +1549,52 @@ html_converter(char *target __UNUSED__, void *data, int size __UNUSED__, void ** 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; } -- 2.7.4