All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] stkutil: convert text attributes to html
@ 2010-06-14 15:19 Kristen Carlson Accardi
  2010-06-14 23:10 ` andrzej zaborowski
  0 siblings, 1 reply; 4+ messages in thread
From: Kristen Carlson Accardi @ 2010-06-14 15:19 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 7265 bytes --]

---
 src/stkutil.c |  203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/stkutil.h |   21 ++++++
 2 files changed, 224 insertions(+), 0 deletions(-)

diff --git a/src/stkutil.c b/src/stkutil.c
index 8ac1dba..dbcb6ac 100644
--- a/src/stkutil.c
+++ b/src/stkutil.c
@@ -4307,3 +4307,206 @@ const unsigned char *stk_pdu_from_envelope(const struct stk_envelope *envelope,
 
 	return pdu;
 }
+
+static GString *mapColourToHtml(GString *string, guint8 colour)
+{
+	GString *result = string;
+	int fg = colour & 0x0f;
+	int bg = (colour >> 4) & 0x0f;
+	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 */
+	};
+
+	if (colour == 0)
+		return string;
+
+	if (fg) {
+		result = g_string_append(result, "color: ");
+		result = g_string_append(result, html_colors[fg]);
+		result = g_string_append_c(result, ';');
+	}
+	if (bg) {
+		result = g_string_append(result, "background-color: ");
+		result = g_string_append(result, html_colors[bg]);
+		result = g_string_append_c(result, ';');
+	}
+
+
+	return result;
+}
+
+static GString *endFormat(GString *string)
+{
+	return g_string_append(string, "</p>");
+}
+
+static GString *mapFormatToHtml(GString *string, guint8 code, guint8 colour)
+{
+	GString *result = string;
+	guint8 align = code & STK_TEXT_FORMAT_ALIGN_MASK;
+	guint8 font = code & STK_TEXT_FORMAT_FONT_MASK;
+	guint8 style = code & STK_TEXT_FORMAT_STYLE_MASK;
+
+	/* formatting applies to a block of test */
+	result = g_string_append(result, "<p style=\"");
+
+	if (align == STK_TEXT_FORMAT_RIGHT_ALIGN)
+		result = g_string_append(result, "text-align: right;");
+	else if (align == STK_TEXT_FORMAT_CENTER_ALIGN)
+		result = g_string_append(result, "text-align: center;");
+	else if (align == STK_TEXT_FORMAT_LEFT_ALIGN)
+		result = g_string_append(result, "text-align: left;");
+
+	if (font == STK_TEXT_FORMAT_FONT_SIZE_LARGE)
+		result = g_string_append(result, "font-size: big;");
+	else if (font == STK_TEXT_FORMAT_FONT_SIZE_SMALL)
+		result = g_string_append(result, "font-size: small;");
+
+	if (style == STK_TEXT_FORMAT_STYLE_BOLD)
+		result = g_string_append(result, "font-weight: bold;");
+	else if (style == STK_TEXT_FORMAT_STYLE_ITALIC)
+		result = g_string_append(result, "font-style: italic;");
+	else if (style == STK_TEXT_FORMAT_STYLE_UNDERLINED)
+		result = g_string_append(result, "text-decoration: underline;");
+	else if (style == STK_TEXT_FORMAT_STYLE_STRIKETHROUGH)
+		result = g_string_append(result,
+					"text-decoration: line-through;");
+
+	/* add any color */
+	result = mapColourToHtml(result, colour);
+
+	result = g_string_append(result, "\">");
+
+	return result;
+}
+
+static gboolean isSpecialChar(char c)
+{
+	return (c == '\n' || c == '\r' || c == '<' || c == '>' || c == '&');
+}
+
+static gboolean mapCharToHtml(char *s, int pos, int len,
+			GString **string)
+{
+	gboolean rval = FALSE;
+	GString *result = *string;
+	unsigned char c = s[pos];
+
+	switch (c) {
+		case '\n':
+			result = g_string_append(result, "<br>");
+			break;
+		case '\r':
+			result = g_string_append(result, "<br>");
+			if ((pos + 1 < len) && (s[pos + 1] == '\n'))
+				rval = TRUE;
+			break;
+		case '<':
+			result = g_string_append(result, "&lt;");
+			break;
+		case '>':
+			result = g_string_append(result, "&gt;");
+			break;
+		case '&':
+			result = g_string_append(result, "&amp;");
+			break;
+	}
+	*string = result;
+	return rval;
+}
+
+static GString *copyText(GString *string, char *text,
+				int *start_pos, int start, int end)
+{
+	GString *result = string;
+	int pos = *start_pos;
+
+	while (pos < start && pos < end) {
+		if (isSpecialChar(text[pos])) {
+			if (mapCharToHtml(text, pos, end, &result) == TRUE)
+				pos++;
+		}
+		else
+			result = g_string_append_c(result, text[pos]);
+		pos++;
+	}
+	*start_pos = pos;
+	return result;
+}
+
+static int extractFormat(const unsigned char *attrs, int index, int attrs_len,
+				int text_len, guint8 *start,
+				guint8 *end, guint8 *code, guint8 *colour)
+{
+	int i = index;
+
+	/* If there are no more attributes, initialize to default values */
+	if (i >= attrs_len) {
+		*start = text_len;
+		*end = text_len;
+		*code = 0;
+		*colour = 0;
+		return i;
+	}
+
+	*start = attrs[i++];
+	*end = attrs[i++];
+	*code = attrs[i++];
+
+	if (i < attrs_len)
+		*colour = attrs[i++];
+	else
+		*colour = 0;
+
+	if (*end == 0)
+		*end = text_len;
+
+	return i;
+}
+
+char *textToHtml(char *text, int text_len,
+				const unsigned char *attrs, int attrs_len)
+{
+	GString *result = g_string_new(NULL);
+	guint8 start, end, code, colour;
+	int pos = 0;
+	int i = 0;
+
+	while (pos < text_len) {
+		/* check for an attribute */
+		i = extractFormat(attrs, i, attrs_len, text_len, &start,
+					&end, &code, &colour);
+
+		/* insert any non-formatted text */
+		result = copyText(result, text, &pos, start, text_len);
+		if (pos >= text_len)
+			break;
+
+		/* start formatting */
+		result = mapFormatToHtml(result, code, colour);
+
+		/* insert formatted text */
+		result = copyText(result, text, &pos, end, text_len);
+
+		/* end formatting */
+		result = endFormat(result);
+	}
+
+	/* return characters from result. Caller must free char data */
+	return g_string_free(result, FALSE);
+}
diff --git a/src/stkutil.h b/src/stkutil.h
index 2da787d..2c78382 100644
--- a/src/stkutil.h
+++ b/src/stkutil.h
@@ -447,6 +447,25 @@ enum stk_broadcast_network_technology {
 	STK_BROADCAST_NETWORK_T_DMB = 0x03
 };
 
+#define STK_TEXT_FORMAT_ALIGN_MASK 0x03
+#define STK_TEXT_FORMAT_FONT_MASK 0x0C
+#define STK_TEXT_FORMAT_STYLE_MASK 0xF0
+
+/* Defined in ETSI 123 40 9.2.3.24.10.1.1 */
+enum stk_text_format_code {
+	STK_TEXT_FORMAT_LEFT_ALIGN = 0x00,
+	STK_TEXT_FORMAT_CENTER_ALIGN = 0x01,
+	STK_TEXT_FORMAT_RIGHT_ALIGN = 0x02,
+	STK_TEXT_FORMAT_NO_ALIGN = 0x03,
+	STK_TEXT_FORMAT_FONT_SIZE_LARGE = 0x04,
+	STK_TEXT_FORMAT_FONT_SIZE_SMALL = 0x08,
+	STK_TEXT_FORMAT_FONT_SIZE_RESERVED = 0x0c,
+	STK_TEXT_FORMAT_STYLE_BOLD = 0x10,
+	STK_TEXT_FORMAT_STYLE_ITALIC = 0x20,
+	STK_TEXT_FORMAT_STYLE_UNDERLINED = 0x40,
+	STK_TEXT_FORMAT_STYLE_STRIKETHROUGH = 0x80,
+};
+
 /* For data object that only has a byte array with undetermined length */
 struct stk_common_byte_array {
 	unsigned char *array;
@@ -1213,3 +1232,5 @@ const unsigned char *stk_pdu_from_response(const struct stk_response *response,
 						unsigned int *out_length);
 const unsigned char *stk_pdu_from_envelope(const struct stk_envelope *envelope,
 						unsigned int *out_length);
+char *textToHtml(char *text, int text_len,
+				const unsigned char *attrs, int attrs_len);
-- 
1.6.6.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] stkutil: convert text attributes to html
  2010-06-14 15:19 [PATCH] stkutil: convert text attributes to html Kristen Carlson Accardi
@ 2010-06-14 23:10 ` andrzej zaborowski
  2010-06-15 23:32   ` Kristen Carlson Accardi
  0 siblings, 1 reply; 4+ messages in thread
From: andrzej zaborowski @ 2010-06-14 23:10 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 6051 bytes --]

Hi,

On 14 June 2010 17:19, Kristen Carlson Accardi <kristen@linux.intel.com> wrote:
> ---
>  src/stkutil.c |  203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/stkutil.h |   21 ++++++
>  2 files changed, 224 insertions(+), 0 deletions(-)
>
> diff --git a/src/stkutil.c b/src/stkutil.c
> index 8ac1dba..dbcb6ac 100644
> --- a/src/stkutil.c
> +++ b/src/stkutil.c
> @@ -4307,3 +4307,206 @@ const unsigned char *stk_pdu_from_envelope(const struct stk_envelope *envelope,
>
>        return pdu;
>  }
> +
> +static GString *mapColourToHtml(GString *string, guint8 colour)
> +{
> +       GString *result = string;
> +       int fg = colour & 0x0f;
> +       int bg = (colour >> 4) & 0x0f;
> +       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 */
> +       };
> +
> +       if (colour == 0)
> +               return string;
> +
> +       if (fg) {
> +               result = g_string_append(result, "color: ");
> +               result = g_string_append(result, html_colors[fg]);
> +               result = g_string_append_c(result, ';');
> +       }
> +       if (bg) {
> +               result = g_string_append(result, "background-color: ");
> +               result = g_string_append(result, html_colors[bg]);
> +               result = g_string_append_c(result, ';');
> +       }
> +
> +
> +       return result;
> +}
> +
> +static GString *endFormat(GString *string)
> +{
> +       return g_string_append(string, "</p>");
> +}
> +
> +static GString *mapFormatToHtml(GString *string, guint8 code, guint8 colour)
> +{
> +       GString *result = string;
> +       guint8 align = code & STK_TEXT_FORMAT_ALIGN_MASK;
> +       guint8 font = code & STK_TEXT_FORMAT_FONT_MASK;
> +       guint8 style = code & STK_TEXT_FORMAT_STYLE_MASK;
> +
> +       /* formatting applies to a block of test */
> +       result = g_string_append(result, "<p style=\"");
> +
> +       if (align == STK_TEXT_FORMAT_RIGHT_ALIGN)
> +               result = g_string_append(result, "text-align: right;");
> +       else if (align == STK_TEXT_FORMAT_CENTER_ALIGN)
> +               result = g_string_append(result, "text-align: center;");
> +       else if (align == STK_TEXT_FORMAT_LEFT_ALIGN)
> +               result = g_string_append(result, "text-align: left;");
> +
> +       if (font == STK_TEXT_FORMAT_FONT_SIZE_LARGE)
> +               result = g_string_append(result, "font-size: big;");
> +       else if (font == STK_TEXT_FORMAT_FONT_SIZE_SMALL)
> +               result = g_string_append(result, "font-size: small;");
> +
> +       if (style == STK_TEXT_FORMAT_STYLE_BOLD)
> +               result = g_string_append(result, "font-weight: bold;");
> +       else if (style == STK_TEXT_FORMAT_STYLE_ITALIC)
> +               result = g_string_append(result, "font-style: italic;");
> +       else if (style == STK_TEXT_FORMAT_STYLE_UNDERLINED)
> +               result = g_string_append(result, "text-decoration: underline;");
> +       else if (style == STK_TEXT_FORMAT_STYLE_STRIKETHROUGH)
> +               result = g_string_append(result,
> +                                       "text-decoration: line-through;");
> +
> +       /* add any color */
> +       result = mapColourToHtml(result, colour);
> +
> +       result = g_string_append(result, "\">");
> +
> +       return result;
> +}
> +
> +static gboolean isSpecialChar(char c)
> +{
> +       return (c == '\n' || c == '\r' || c == '<' || c == '>' || c == '&');
> +}
> +
> +static gboolean mapCharToHtml(char *s, int pos, int len,
> +                       GString **string)
> +{
> +       gboolean rval = FALSE;
> +       GString *result = *string;
> +       unsigned char c = s[pos];
> +
> +       switch (c) {
> +               case '\n':
> +                       result = g_string_append(result, "<br>");

It would be nice to not annoy xml parsers, <br /> instead of <br>
should be both a valid html and xml.  But there's a possible conflict,
using <p> means a new paragraph is started for every formatted piece
of text, while \n will not start a new paragraph.  Perhaps it would be
better to use <span> for formatting.  It seems that only when the
alignment mode changes, a new paragraph should start [1].

Also it seems the code won't handle nested formatting, I don't see a
place where that is allowed or disallowed in 23.040, but it's needed
if you want to handle default formatting.  For example let's say
default is set to green and in the middle of the text you have a word
in blue, then blue needs to override green for just that span.

Note the rest of stkutil.c doesn't use camelcase.

Regards,
Andrew

1. "*in case formatting text is inserted on the same line as previous
non formatting text or with a different
mode value, the alignment value shall be set to the same value as the
previous formatted predefined
object."

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] stkutil: convert text attributes to html
  2010-06-14 23:10 ` andrzej zaborowski
@ 2010-06-15 23:32   ` Kristen Carlson Accardi
  2010-06-16  6:27     ` Marcel Holtmann
  0 siblings, 1 reply; 4+ messages in thread
From: Kristen Carlson Accardi @ 2010-06-15 23:32 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 7353 bytes --]

From c9f4c7a0a605ef304e40ee6589f300469e7fc9f1 Mon Sep 17 00:00:00 2001
From: Kristen Carlson Accardi <kristen@linux.intel.com>
Date: Mon, 14 Jun 2010 14:27:25 -0700
Subject: [PATCH] stkutil: convert text attribute to HTML

---
 src/stkutil.c |  195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/stkutil.h |   21 ++++++
 2 files changed, 216 insertions(+), 0 deletions(-)

diff --git a/src/stkutil.c b/src/stkutil.c
index 8ac1dba..6244d03 100644
--- a/src/stkutil.c
+++ b/src/stkutil.c
@@ -4307,3 +4307,198 @@ const unsigned char *stk_pdu_from_envelope(const struct stk_envelope *envelope,
 
 	return pdu;
 }
+
+static void map_color_to_html(GString *string, guint8 color)
+{
+	int fg = color & 0x0f;
+	int bg = (color >> 4) & 0x0f;
+	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 */
+	};
+
+	if (color == 0)
+		return;
+
+	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]);
+
+	return;
+}
+
+static void end_format(GString *string, guint8 code)
+{
+	g_string_append_printf(string, "</span>");
+
+	if ((code & STK_TEXT_FORMAT_ALIGN_MASK) != STK_TEXT_FORMAT_NO_ALIGN)
+		g_string_append_printf(string, "</div>");
+}
+
+static void map_format_to_html(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;
+
+	/* align formatting applies to a block of test */
+	if (align != STK_TEXT_FORMAT_NO_ALIGN)
+		g_string_append_printf(string, "<div style=\"");
+
+	if (align == STK_TEXT_FORMAT_RIGHT_ALIGN)
+		g_string_append_printf(string, "text-align: right;>\"");
+	else if (align == STK_TEXT_FORMAT_CENTER_ALIGN)
+		g_string_append_printf(string, "text-align: center;>\"");
+	else if (align == STK_TEXT_FORMAT_LEFT_ALIGN)
+		g_string_append_printf(string, "text-align: left;>\"");
+
+	/* font, style, and color are inline */
+	g_string_append_printf(string, "<span style=\"");
+
+	if (font == STK_TEXT_FORMAT_FONT_SIZE_LARGE)
+		g_string_append_printf(string, "font-size: big;");
+	else if (font == STK_TEXT_FORMAT_FONT_SIZE_SMALL)
+		g_string_append_printf(string, "font-size: small;");
+
+	if (style == STK_TEXT_FORMAT_STYLE_BOLD)
+		g_string_append_printf(string, "font-weight: bold;");
+	else if (style == STK_TEXT_FORMAT_STYLE_ITALIC)
+		g_string_append_printf(string, "font-style: italic;");
+	else if (style == STK_TEXT_FORMAT_STYLE_UNDERLINED)
+		g_string_append_printf(string, "text-decoration: underline;");
+	else if (style == STK_TEXT_FORMAT_STYLE_STRIKETHROUGH)
+		g_string_append_printf(string,
+					"text-decoration: line-through;");
+
+	/* add any color */
+	map_color_to_html(string, color);
+
+	g_string_append_printf(string, "\">");
+}
+
+static gboolean is_special_char(char c)
+{
+	return (c == '\n' || c == '\r' || c == '<' || c == '>' || c == '&');
+}
+
+static gboolean map_char_to_html(char *s, int pos, int len, GString *string)
+{
+	gboolean rval = FALSE;
+	unsigned char c = s[pos];
+
+	switch (c) {
+		case '\n':
+			g_string_append_printf(string, "<br/>");
+			break;
+		case '\r':
+			g_string_append_printf(string, "<br/>");
+			if ((pos + 1 < len) && (s[pos + 1] == '\n'))
+				rval = TRUE;
+			break;
+		case '<':
+			g_string_append_printf(string, "&lt;");
+			break;
+		case '>':
+			g_string_append_printf(string, "&gt;");
+			break;
+		case '&':
+			g_string_append_printf(string, "&amp;");
+			break;
+	}
+	return rval;
+}
+
+static void copy_text(GString *string, char *text,
+				int *start_pos, int start, int end)
+{
+	int pos = *start_pos;
+
+	while (pos < start && pos < end) {
+		if (is_special_char(text[pos])) {
+			if (map_char_to_html(text, pos, end, string) == TRUE)
+				pos++;
+		}
+		else
+			g_string_append_printf(string, "%c", text[pos]);
+		pos++;
+	}
+	*start_pos = pos;
+}
+
+static int extract_format(const unsigned char *attrs, int index, int attrs_len,
+				int text_len, guint8 *start,
+				guint8 *end, guint8 *code, guint8 *color)
+{
+	int i = index;
+
+	/* If there are no more attributes, initialize to default values */
+	if (i >= attrs_len) {
+		*start = text_len;
+		*end = text_len;
+		*code = 0;
+		*color = 0;
+		return i;
+	}
+
+	*start = attrs[i++];
+	*end = attrs[i++];
+	*code = attrs[i++];
+
+	if (i < attrs_len)
+		*color = attrs[i++];
+	else
+		*color = 0;
+
+	if (*end == 0)
+		*end = text_len;
+
+	return i;
+}
+
+char *text_to_html(char *text, int text_len,
+				const unsigned char *attrs, int attrs_len)
+{
+	GString *string = g_string_new(NULL);
+	guint8 start, end, code, color;
+	int pos = 0;
+	int i = 0;
+
+	while (pos < text_len) {
+		/* check for an attribute */
+		i = extract_format(attrs, i, attrs_len, text_len, &start,
+					&end, &code, &color);
+
+		/* insert any non-formatted text */
+		copy_text(string, text, &pos, start, text_len);
+		if (pos >= text_len)
+			break;
+
+		/* start formatting */
+		map_format_to_html(string, code, color);
+
+		/* insert formatted text */
+		copy_text(string, text, &pos, end, text_len);
+
+		/* end formatting */
+		end_format(string, code);
+	}
+
+	/* return characters from string. Caller must free char data */
+	return g_string_free(string, FALSE);
+}
diff --git a/src/stkutil.h b/src/stkutil.h
index 2da787d..2b714dd 100644
--- a/src/stkutil.h
+++ b/src/stkutil.h
@@ -447,6 +447,25 @@ enum stk_broadcast_network_technology {
 	STK_BROADCAST_NETWORK_T_DMB = 0x03
 };
 
+#define STK_TEXT_FORMAT_ALIGN_MASK 0x03
+#define STK_TEXT_FORMAT_FONT_MASK 0x0C
+#define STK_TEXT_FORMAT_STYLE_MASK 0xF0
+
+/* Defined in ETSI 123 40 9.2.3.24.10.1.1 */
+enum stk_text_format_code {
+	STK_TEXT_FORMAT_LEFT_ALIGN = 0x00,
+	STK_TEXT_FORMAT_CENTER_ALIGN = 0x01,
+	STK_TEXT_FORMAT_RIGHT_ALIGN = 0x02,
+	STK_TEXT_FORMAT_NO_ALIGN = 0x03,
+	STK_TEXT_FORMAT_FONT_SIZE_LARGE = 0x04,
+	STK_TEXT_FORMAT_FONT_SIZE_SMALL = 0x08,
+	STK_TEXT_FORMAT_FONT_SIZE_RESERVED = 0x0c,
+	STK_TEXT_FORMAT_STYLE_BOLD = 0x10,
+	STK_TEXT_FORMAT_STYLE_ITALIC = 0x20,
+	STK_TEXT_FORMAT_STYLE_UNDERLINED = 0x40,
+	STK_TEXT_FORMAT_STYLE_STRIKETHROUGH = 0x80,
+};
+
 /* For data object that only has a byte array with undetermined length */
 struct stk_common_byte_array {
 	unsigned char *array;
@@ -1213,3 +1232,5 @@ const unsigned char *stk_pdu_from_response(const struct stk_response *response,
 						unsigned int *out_length);
 const unsigned char *stk_pdu_from_envelope(const struct stk_envelope *envelope,
 						unsigned int *out_length);
+char *text_to_html(char *text, int text_len,
+				const unsigned char *attrs, int attrs_len);
-- 
1.6.6.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] stkutil: convert text attributes to html
  2010-06-15 23:32   ` Kristen Carlson Accardi
@ 2010-06-16  6:27     ` Marcel Holtmann
  0 siblings, 0 replies; 4+ messages in thread
From: Marcel Holtmann @ 2010-06-16  6:27 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 10192 bytes --]

Hi Kristen,

> ---
>  src/stkutil.c |  195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/stkutil.h |   21 ++++++
>  2 files changed, 216 insertions(+), 0 deletions(-)
> 
> diff --git a/src/stkutil.c b/src/stkutil.c
> index 8ac1dba..6244d03 100644
> --- a/src/stkutil.c
> +++ b/src/stkutil.c
> @@ -4307,3 +4307,198 @@ const unsigned char *stk_pdu_from_envelope(const struct stk_envelope *envelope,
>  
>  	return pdu;
>  }
> +
> +static void map_color_to_html(GString *string, guint8 color)
> +{
> +	int fg = color & 0x0f;
> +	int bg = (color >> 4) & 0x0f;
> +	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 */
> +	};
> +
> +	if (color == 0)
> +		return;
> +
> +	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]);

so here is where g_string_append_printf() makes is a lot more readable.
You clearly see what is the key and what the value you are setting. It
is not split over multiple lines.

> +
> +	return;
> +}

We don't add return; statements that are not needed. So please remove
this.

> +
> +static void end_format(GString *string, guint8 code)
> +{
> +	g_string_append_printf(string, "</span>");
> +
> +	if ((code & STK_TEXT_FORMAT_ALIGN_MASK) != STK_TEXT_FORMAT_NO_ALIGN)
> +		g_string_append_printf(string, "</div>");

Here the g_string_append_printf() is not useful. Just using
g_string_append() is enough.

It is actually pretty simple. If you have variable parameters in your
string, then use ...append_printf() if just pure string, do
just ..._append().

> +}
> +
> +static void map_format_to_html(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;
> +
> +	/* align formatting applies to a block of test */
> +	if (align != STK_TEXT_FORMAT_NO_ALIGN)
> +		g_string_append_printf(string, "<div style=\"");
> +
> +	if (align == STK_TEXT_FORMAT_RIGHT_ALIGN)
> +		g_string_append_printf(string, "text-align: right;>\"");
> +	else if (align == STK_TEXT_FORMAT_CENTER_ALIGN)
> +		g_string_append_printf(string, "text-align: center;>\"");
> +	else if (align == STK_TEXT_FORMAT_LEFT_ALIGN)
> +		g_string_append_printf(string, "text-align: left;>\"");
> +
> +	/* font, style, and color are inline */
> +	g_string_append_printf(string, "<span style=\"");
> +
> +	if (font == STK_TEXT_FORMAT_FONT_SIZE_LARGE)
> +		g_string_append_printf(string, "font-size: big;");
> +	else if (font == STK_TEXT_FORMAT_FONT_SIZE_SMALL)
> +		g_string_append_printf(string, "font-size: small;");
> +
> +	if (style == STK_TEXT_FORMAT_STYLE_BOLD)
> +		g_string_append_printf(string, "font-weight: bold;");
> +	else if (style == STK_TEXT_FORMAT_STYLE_ITALIC)
> +		g_string_append_printf(string, "font-style: italic;");
> +	else if (style == STK_TEXT_FORMAT_STYLE_UNDERLINED)
> +		g_string_append_printf(string, "text-decoration: underline;");
> +	else if (style == STK_TEXT_FORMAT_STYLE_STRIKETHROUGH)
> +		g_string_append_printf(string,
> +					"text-decoration: line-through;");
> +
> +	/* add any color */
> +	map_color_to_html(string, color);

Can we just make the color array a global static variable and then just
add the colors here directly instead of calling map_to_color. The
compiler will optimize it anyway, but that way also the reader doesn't
have to jump while reading this function.

> +
> +	g_string_append_printf(string, "\">");
> +}
> +
> +static gboolean is_special_char(char c)
> +{
> +	return (c == '\n' || c == '\r' || c == '<' || c == '>' || c == '&');
> +}

How many times are you using is_special_char? If it is only one, I
prefer you just code this directly in the place where you are using
this.

> +
> +static gboolean map_char_to_html(char *s, int pos, int len, GString *string)
> +{
> +	gboolean rval = FALSE;
> +	unsigned char c = s[pos];

Why are you bothering with these two variables?

Just use s[pos] in the switch statement directly. Makes is a lot clearer
than having to look up where c is coming. And since c never changes I
don't see a point here.

Also rval is not needed. Always return FALSE at the end of the function.
And the only time you need to return TRUE, just call return TRUE.

> +	switch (c) {
> +		case '\n':
> +			g_string_append_printf(string, "<br/>");
> +			break;

It is like this:

	switch (s[pos]) {
	case '\n':
		...

> +		case '\r':
> +			g_string_append_printf(string, "<br/>");
> +			if ((pos + 1 < len) && (s[pos + 1] == '\n'))
> +				rval = TRUE;
> +			break;
> +		case '<':
> +			g_string_append_printf(string, "&lt;");
> +			break;
> +		case '>':
> +			g_string_append_printf(string, "&gt;");
> +			break;
> +		case '&':
> +			g_string_append_printf(string, "&amp;");
> +			break;
> +	}
> +	return rval;
> +}
> +
> +static void copy_text(GString *string, char *text,
> +				int *start_pos, int start, int end)
> +{
> +	int pos = *start_pos;
> +
> +	while (pos < start && pos < end) {
> +		if (is_special_char(text[pos])) {
> +			if (map_char_to_html(text, pos, end, string) == TRUE)
> +				pos++;
> +		}
> +		else
> +			g_string_append_printf(string, "%c", text[pos]);

It is } else on the same line.

And in this case using g_string_append_c() is just fine.

I am also wondering why we are making this so complex. Can not the
map_char_to_html be called unconditionally. So check for the special
char once and then again via the switch statement.

Why not just have a switch statement only and use the default case for
the literal copy. And while thinking about it, we not do everything
directly in the while loop.

> +		pos++;
> +	}
> +	*start_pos = pos;
> +}
> +
> +static int extract_format(const unsigned char *attrs, int index, int attrs_len,
> +				int text_len, guint8 *start,
> +				guint8 *end, guint8 *code, guint8 *color)
> +{
> +	int i = index;
> +
> +	/* If there are no more attributes, initialize to default values */
> +	if (i >= attrs_len) {
> +		*start = text_len;
> +		*end = text_len;
> +		*code = 0;
> +		*color = 0;
> +		return i;
> +	}
> +
> +	*start = attrs[i++];
> +	*end = attrs[i++];
> +	*code = attrs[i++];

Please add some extra checks here for potential malformed attributes.

> +
> +	if (i < attrs_len)
> +		*color = attrs[i++];
> +	else
> +		*color = 0;
> +
> +	if (*end == 0)
> +		*end = text_len;
> +
> +	return i;
> +}
> +
> +char *text_to_html(char *text, int text_len,
> +				const unsigned char *attrs, int attrs_len)
> +{
> +	GString *string = g_string_new(NULL);
> +	guint8 start, end, code, color;
> +	int pos = 0;
> +	int i = 0;

You can just move start, end, code, color into the while loop. And
please don't init i to 0. The call to extract_format() will do that.

In addition please check that the memory allocation succeeded. I can't
figure out from the GLib developer manual if GString can return NULL or
not. Would need to double check inside the source code.

I do think that one good idea would be to use at least
g_string_new_sized(text_len + 1) since we know that at minimum we need
the formatted string length here.

> +
> +	while (pos < text_len) {
> +		/* check for an attribute */
> +		i = extract_format(attrs, i, attrs_len, text_len, &start,
> +					&end, &code, &color);
> +
> +		/* insert any non-formatted text */
> +		copy_text(string, text, &pos, start, text_len);
> +		if (pos >= text_len)
> +			break;
> +
> +		/* start formatting */
> +		map_format_to_html(string, code, color);
> +
> +		/* insert formatted text */
> +		copy_text(string, text, &pos, end, text_len);
> +
> +		/* end formatting */
> +		end_format(string, code);
> +	}

I would prefer if do a bit of symmetry here. So something like
start_format() and end_format(). Just an idea.

> +
> +	/* return characters from string. Caller must free char data */
> +	return g_string_free(string, FALSE);
> +}
> diff --git a/src/stkutil.h b/src/stkutil.h
> index 2da787d..2b714dd 100644
> --- a/src/stkutil.h
> +++ b/src/stkutil.h
> @@ -447,6 +447,25 @@ enum stk_broadcast_network_technology {
>  	STK_BROADCAST_NETWORK_T_DMB = 0x03
>  };
>  
> +#define STK_TEXT_FORMAT_ALIGN_MASK 0x03
> +#define STK_TEXT_FORMAT_FONT_MASK 0x0C
> +#define STK_TEXT_FORMAT_STYLE_MASK 0xF0
> +
> +/* Defined in ETSI 123 40 9.2.3.24.10.1.1 */
> +enum stk_text_format_code {
> +	STK_TEXT_FORMAT_LEFT_ALIGN = 0x00,
> +	STK_TEXT_FORMAT_CENTER_ALIGN = 0x01,
> +	STK_TEXT_FORMAT_RIGHT_ALIGN = 0x02,
> +	STK_TEXT_FORMAT_NO_ALIGN = 0x03,
> +	STK_TEXT_FORMAT_FONT_SIZE_LARGE = 0x04,
> +	STK_TEXT_FORMAT_FONT_SIZE_SMALL = 0x08,
> +	STK_TEXT_FORMAT_FONT_SIZE_RESERVED = 0x0c,
> +	STK_TEXT_FORMAT_STYLE_BOLD = 0x10,
> +	STK_TEXT_FORMAT_STYLE_ITALIC = 0x20,
> +	STK_TEXT_FORMAT_STYLE_UNDERLINED = 0x40,
> +	STK_TEXT_FORMAT_STYLE_STRIKETHROUGH = 0x80,
> +};
> +
>  /* For data object that only has a byte array with undetermined length */
>  struct stk_common_byte_array {
>  	unsigned char *array;
> @@ -1213,3 +1232,5 @@ const unsigned char *stk_pdu_from_response(const struct stk_response *response,
>  						unsigned int *out_length);
>  const unsigned char *stk_pdu_from_envelope(const struct stk_envelope *envelope,
>  						unsigned int *out_length);
> +char *text_to_html(char *text, int text_len,
> +				const unsigned char *attrs, int attrs_len);

We should do some stk_ namespacing here.

Regards

Marcel




^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-06-16  6:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-14 15:19 [PATCH] stkutil: convert text attributes to html Kristen Carlson Accardi
2010-06-14 23:10 ` andrzej zaborowski
2010-06-15 23:32   ` Kristen Carlson Accardi
2010-06-16  6:27     ` Marcel Holtmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.