Hi, On 21 June 2010 15:06, Kristen Carlson Accardi <kris...@linux.intel.com> wrote: > --- > src/stkutil.c | 165 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > src/stkutil.h | 22 ++++++++ > 2 files changed, 187 insertions(+), 0 deletions(-) > > diff --git a/src/stkutil.c b/src/stkutil.c > index 642081e..1c8bac9 100644 > --- a/src/stkutil.c > +++ b/src/stkutil.c > @@ -26,6 +26,7 @@ > #include <string.h> > #include <stdlib.h> > #include <stdint.h> > +#include <stdio.h> > > #include <glib.h> > > @@ -5978,3 +5979,167 @@ const unsigned char *stk_pdu_from_envelope(const > struct stk_envelope *envelope, > > return pdu; > } > + > +static const char *html_colors[] = { > + "#000000", /* Black */ > + "#808080", /* Dark Grey */ > + "#C11B17", /* Dark Red */ > + "#FBB117", /* Dark Yellow */ > + "#347235", /* Dark Green */ > + "#307D7E", /* Dark Cyan */ > + "#0000A0", /* Dark Blue */ > + "#C031C7", /* Dark Magenta */ > + "#C0C0C0", /* Grey */ > + "#FFFFFF", /* White */ > + "#FF0000", /* Bright Red */ > + "#FFFF00", /* Bright Yellow */ > + "#00FF00", /* Bright Green */ > + "#00FFFF", /* Bright Cyan */ > + "#0000FF", /* Bright Blue */ > + "#FF00FF", /* Bright Magenta */ > +}; > + > +static void end_format(GString *string, guint8 code) > +{ > + g_string_append(string, "</span>"); > + > + if ((code & STK_TEXT_FORMAT_ALIGN_MASK) != STK_TEXT_FORMAT_NO_ALIGN) > + g_string_append(string, "</div>"); > +} > + > +static void start_format(GString *string, guint8 code, guint8 color) > +{ > + guint8 align = code & STK_TEXT_FORMAT_ALIGN_MASK; > + guint8 font = code & STK_TEXT_FORMAT_FONT_MASK; > + guint8 style = code & STK_TEXT_FORMAT_STYLE_MASK; > + int fg = color & 0x0f; > + int bg = (color >> 4) & 0x0f; > + > + /* align formatting applies to a block of test */ > + if (align != STK_TEXT_FORMAT_NO_ALIGN) > + g_string_append(string, "<div style=\""); > + > + if (align == STK_TEXT_FORMAT_RIGHT_ALIGN) > + g_string_append(string, "text-align: right;\">"); > + else if (align == STK_TEXT_FORMAT_CENTER_ALIGN) > + g_string_append(string, "text-align: center;\">"); > + else if (align == STK_TEXT_FORMAT_LEFT_ALIGN) > + g_string_append(string, "text-align: left;\">"); > + > + /* font, style, and color are inline */ > + g_string_append(string, "<span style=\""); > + > + if (font == STK_TEXT_FORMAT_FONT_SIZE_LARGE) > + g_string_append(string, "font-size: big;"); > + else if (font == STK_TEXT_FORMAT_FONT_SIZE_SMALL) > + g_string_append(string, "font-size: small;"); > + > + if (style == STK_TEXT_FORMAT_STYLE_BOLD) > + g_string_append(string, "font-weight: bold;"); > + else if (style == STK_TEXT_FORMAT_STYLE_ITALIC) > + g_string_append(string, "font-style: italic;"); > + else if (style == STK_TEXT_FORMAT_STYLE_UNDERLINED) > + g_string_append(string, "text-decoration: underline;"); > + else if (style == STK_TEXT_FORMAT_STYLE_STRIKETHROUGH) > + g_string_append(string, "text-decoration: line-through;"); > + > + /* add any color */ > + if (fg) > + g_string_append_printf(string, "color: %s;", html_colors[fg]); > + if (bg) > + g_string_append_printf(string, "background-color: %s;", > + html_colors[bg]); > + g_string_append(string, "\">"); > +} > + > +char *stk_text_to_html(char *text, int text_len, > + const unsigned char *attrs, int attrs_len) > +{ > + GString *string = g_string_sized_new(text_len + 1); > + GQueue formats[241]; /* maximum number of chars in text + 1 */ > + int pos = 0, attr, i; > + guint8 start, end, code, color, len; > + guint8 align = STK_DEFAULT_TEXT_ALIGNMENT; /* hardcoded to left */ > + > + /* we may need formatting at the position beyond the last char */ > + for (i = 0; i <= text_len; i++) > + g_queue_init(&formats[i]); > + > + i = 0; > + > + /* > + * each position in the text may have multiple attributes. > + * store each attribute in a queue for that position in the > + * order in which it was sent. This will cause the last > + * attribute sent for that position to take priority. > + */ > + while (i < attrs_len) { > + /* TBD - check for bad values */ > + start = attrs[i++]; > + len = attrs[i++]; > + code = attrs[i++]; > + > + /* > + * if the alignment is the same as either the default > + * or the last alignment used, don't set any alignment > + * value. > + */ > + if ((code & STK_TEXT_FORMAT_ALIGN_MASK) == align) > + code |= 0x3; > + else > + align = code & STK_TEXT_FORMAT_ALIGN_MASK; > + > + if (i < attrs_len) > + color = attrs[i++]; > + else > + color = 0; > + > + if (len == 0) > + end = text_len; > + else > + end = start + len; > + > + attr = start | (code << 16) | (color << 24); > + > + g_queue_push_tail(&formats[start], GINT_TO_POINTER(attr)); > + g_queue_push_tail(&formats[end], GINT_TO_POINTER(attr)); > + } > + > + while (pos <= text_len) { > + GQueue *q = &formats[pos]; > + > + /* there may be multiple formats per position */ > + while ((attr = GPOINTER_TO_INT(g_queue_pop_head(q)))) { > + start = attr & 0xff; > + code = attr >> 16 & 0xff; > + color = attr >> 24 & 0xff; > + > + if (pos == start) > + start_format(string, code, color); > + else > + end_format(string, code); > + }
Can we always end_format() and start_format() when the formatting changes, and just once instead of in a loop? Here's a test case that I'm worried about: text is "abc" attribute 1 (red text) starts at 0, len 2 attribute 2 (blue text) starts at 1, len 2 the generated html, by my reading will look like this: <span style="color: red;">a<span style="color: blue;">b</span>c</span> The end result is that c is red, while it should be blue. But the real problem is if one of them was a div, then you would have badly balanced xml and it wouldn't parse. (I mentioned this on IRC) > + > + if (pos == text_len) > + break; > + > + if (text[pos] == '\n') > + g_string_append(string, "<br/>"); > + else if (text[pos] == '\r') { > + g_string_append(string, "<br/>"); > + if ((pos + 1 < text_len) && (text[pos + 1] == '\n')) > + pos++; > + } else if (text[pos] == '<') > + g_string_append(string, "<"); > + else if (text[pos] == '>') > + g_string_append(string, ">"); > + else if (text[pos] == '&') > + g_string_append(string, "&"); > + else > + g_string_append_c(string, text[pos]); > + pos++; > + } > + > + /* return characters from string. Caller must free char data */ > + return g_string_free(string, FALSE); > +} This approach with having so many queues seems a little heavy. On irc I proposed that probably we don't need to implement this behaviour fully and maybe could make some assumptions to simplify it. But if you want a full implementation here's what I'd do: Make a list of all starts and ends of attributes, and sort it by position in the text, for example for the abc case above, that list would contain: position 0, pointer to attribute 1 position 1, pointer to attribute 2 position 2, pointer to attribute 1 position 3, pointer to attribute 2 Each attribute has a .start, a .end (.start + .len) and a rank which is just its position in the original array. Then I'd loop through the text like this: while (pos <= text_len) { if anything to do on current position { close previous <span>; foreach (attributes that start here) { if attribute->start >= attribute.end continue if attribute->rank > current_attribute->rank { current_attribute->start = attribute->end; current_attribute = attribute; } else attribute->start = current_attribute->end; } open new span(current_attribute); } append chunk of text up to next interesting position; } I'm not sure if this is enough (would have to try it) but it seems to work, provided the list is maintained sorted. That way whenever one attibute ends, another is going to start at the same position, so maybe it's unnecessary to keep the end positions in that list. Regards _______________________________________________ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono