diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-05-20 17:08:31 +0200 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-05-30 15:56:16 +0200 |
commit | a766006297e8fa8b8168b7a887098d5176a87b20 (patch) | |
tree | 6aee522990538c60aaff56cbfc66fedb89d163ae /lib/gtk-experiment-widgets/gtk-experiment-transcript-formats.c | |
parent | b2229a97882e31e0c89061184731082cfd13ec03 (diff) | |
download | gtk-vlc-player-a766006297e8fa8b8168b7a887098d5176a87b20.tar.gz |
implemented "format" file and expression parsing as well as application to the transcript
* "formats" are regular expressions encapsulated in Pango markup that allow the description of powerful highlighting rules
* highlight as you type via entry boxes
* loading from files implemented and tested but cannot yet be done via the UI
* transcript widget is built as libtool convenience library
* some renamings were necessary
* install transcript widget header
Diffstat (limited to 'lib/gtk-experiment-widgets/gtk-experiment-transcript-formats.c')
-rw-r--r-- | lib/gtk-experiment-widgets/gtk-experiment-transcript-formats.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/lib/gtk-experiment-widgets/gtk-experiment-transcript-formats.c b/lib/gtk-experiment-widgets/gtk-experiment-transcript-formats.c new file mode 100644 index 0000000..2c6c22d --- /dev/null +++ b/lib/gtk-experiment-widgets/gtk-experiment-transcript-formats.c @@ -0,0 +1,201 @@ +/** + * @file + * "Format" expression-related functions of the \e GtkExperimentTranscript + * widget + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <glib.h> +#include <glib/gprintf.h> +#include <glib/gstdio.h> + +#include <gtk/gtk.h> + +#include "gtk-experiment-transcript-private.h" + +static gboolean +gtk_experiment_transcript_parse_format(GtkExperimentTranscriptFormat *fmt, + const gchar *str) +{ + PangoAttrIterator *iter; + + gchar *pattern, pattern_captures[255], *p; + + if (!pango_parse_markup(str, -1, 0, &fmt->attribs, &pattern, + NULL, NULL)) + return TRUE; + + p = pattern_captures; + iter = pango_attr_list_get_iterator(fmt->attribs); + do { + gint start, end; + + pango_attr_iterator_range(iter, &start, &end); + + if (end < G_MAXINT) { + *p++ = '('; + strncpy(p, pattern + start, end - start); + p += end - start; + *p++ = ')'; + } + } while (pango_attr_iterator_next(iter)); + pango_attr_iterator_destroy(iter); + *p = '\0'; + g_free(pattern); + + fmt->regexp = g_regex_new(pattern_captures, G_REGEX_CASELESS, 0, NULL); + if (fmt->regexp == NULL) { + pango_attr_list_unref(fmt->attribs); + fmt->attribs = NULL; + return TRUE; + } + + return FALSE; +} + +/** @private */ +void +gtk_experiment_transcript_apply_format(GtkExperimentTranscriptFormat *fmt, + const gchar *text, + PangoAttrList *attrib_list) +{ + GMatchInfo *match_info; + + if (fmt->regexp == NULL || fmt->attribs == NULL) + return; + + g_regex_match(fmt->regexp, text, 0, &match_info); + + while (g_match_info_matches(match_info)) { + PangoAttrIterator *iter; + gint match_num = 1; + + iter = pango_attr_list_get_iterator(fmt->attribs); + do { + gint start, end; + + pango_attr_iterator_range(iter, &start, &end); + if (end == G_MAXINT) + continue; + + start = end = -1; + g_match_info_fetch_pos(match_info, match_num, + &start, &end); + if (start >= 0 && end >= 0) { + GSList *attribs; + + attribs = pango_attr_iterator_get_attrs(iter); + for (GSList *cur = attribs; cur != NULL; cur = cur->next) { + PangoAttribute *attrib; + + attrib = pango_attribute_copy((PangoAttribute *)cur->data); + attrib->start_index = (guint)start; + attrib->end_index = (guint)end; + pango_attr_list_change(attrib_list, attrib); + } + g_slist_free(attribs); + } + + match_num++; + } while (pango_attr_iterator_next(iter)); + pango_attr_iterator_destroy(iter); + + g_match_info_next(match_info, NULL); + } + + g_match_info_free(match_info); +} + +/** @private */ +void +gtk_experiment_transcript_free_formats(GSList *formats) +{ + for (GSList *cur = formats; cur != NULL; cur = cur->next) { + GtkExperimentTranscriptFormat *fmt = + (GtkExperimentTranscriptFormat *)cur->data; + + gtk_experiment_transcript_free_format(fmt); + g_free(fmt); + } + + g_slist_free(formats); +} + +/* + * API + */ + +gboolean +gtk_experiment_transcript_load_formats(GtkExperimentTranscript *trans, + const gchar *filename) +{ + FILE *file; + gchar buf[255]; + + if ((file = g_fopen(filename, "r")) == NULL) + return TRUE; + + gtk_experiment_transcript_free_formats(trans->priv->formats); + trans->priv->formats = NULL; + + while (fgets((char *)buf, sizeof(buf)-1, file) != NULL) { + GtkExperimentTranscriptFormat *fmt; + + g_strchug(buf); + + switch (*buf) { + case '#': + case '\n': + case '\0': + continue; + } + + fmt = g_new(GtkExperimentTranscriptFormat, 1); + + if (gtk_experiment_transcript_parse_format(fmt, buf)) { + g_free(fmt); + fclose(file); + return TRUE; + } + + trans->priv->formats = g_slist_prepend(trans->priv->formats, fmt); + } + trans->priv->formats = g_slist_reverse(trans->priv->formats); + + fclose(file); + + gtk_experiment_transcript_text_layer_redraw(trans); + return FALSE; +} + +gboolean +gtk_experiment_transcript_set_interactive_format(GtkExperimentTranscript *trans, + const gchar *format, + gboolean with_markup) +{ + gboolean res = TRUE; + + gtk_experiment_transcript_free_format(&trans->priv->interactive_format); + trans->priv->interactive_format.regexp = NULL; + trans->priv->interactive_format.attribs = NULL; + + if (format == NULL || *format == '\0') { + res = FALSE; + } else if (with_markup) { + res = gtk_experiment_transcript_parse_format(&trans->priv->interactive_format, + format); + } else { + /** @todo !with_markup, default attributes */ + res = TRUE; + } + + gtk_experiment_transcript_text_layer_redraw(trans); + return res; +} |