aboutsummaryrefslogtreecommitdiff
path: root/hardinfo2/help-viewer/markdown-text-view.c
diff options
context:
space:
mode:
authorLeandro A. F. Pereira <leandro@hardinfo.org>2010-05-03 09:27:26 -0300
committerLeandro A. F. Pereira <leandro@hardinfo.org>2010-05-03 21:08:06 -0300
commit9273c075a2f993c5154614b70233d8f74515c851 (patch)
treeeb72a8c58e6bc8f4ca3b739d28fbecc269c0052d /hardinfo2/help-viewer/markdown-text-view.c
parent9a50155ec3e27aa6cedf3f118196f1947c769a29 (diff)
Move files from hardinfo2 to root.
Diffstat (limited to 'hardinfo2/help-viewer/markdown-text-view.c')
-rw-r--r--hardinfo2/help-viewer/markdown-text-view.c637
1 files changed, 0 insertions, 637 deletions
diff --git a/hardinfo2/help-viewer/markdown-text-view.c b/hardinfo2/help-viewer/markdown-text-view.c
deleted file mode 100644
index 6bfcc131..00000000
--- a/hardinfo2/help-viewer/markdown-text-view.c
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * Markdown Text View
- * GtkTextView subclass that supports Markdown syntax
- *
- * Copyright (C) 2009 Leandro Pereira <leandro@hardinfo.org>
- * Portions Copyright (C) 2007-2008 Richard Hughes <richard@hughsie.com>
- * Portions Copyright (C) GTK+ Team (based on hypertext textview demo)
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#include <stdlib.h>
-#include <gdk/gdkkeysyms.h>
-
-#include "markdown-text-view.h"
-#include "config.h"
-
-static GdkCursor *hand_cursor = NULL;
-
-G_DEFINE_TYPE(MarkdownTextView, markdown_textview, GTK_TYPE_TEXT_VIEW);
-
-enum {
- LINK_CLICKED,
- HOVERING_OVER_LINK,
- HOVERING_OVER_TEXT,
- FILE_LOAD_COMPLETE,
- LAST_SIGNAL
-};
-
-static guint markdown_textview_signals[LAST_SIGNAL] = { 0 };
-
-GtkWidget *markdown_textview_new()
-{
- return g_object_new(TYPE_MARKDOWN_TEXTVIEW, NULL);
-}
-
-static void markdown_textview_class_init(MarkdownTextViewClass * klass)
-{
- GObjectClass *object_class;
-
- if (!hand_cursor) {
- hand_cursor = gdk_cursor_new(GDK_HAND2);
- }
-
- object_class = G_OBJECT_CLASS(klass);
-
- markdown_textview_signals[LINK_CLICKED] = g_signal_new(
- "link-clicked",
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET(MarkdownTextViewClass, link_clicked),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE,
- 1,
- G_TYPE_STRING);
-
- markdown_textview_signals[HOVERING_OVER_LINK] = g_signal_new(
- "hovering-over-link",
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET(MarkdownTextViewClass, hovering_over_link),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE,
- 1,
- G_TYPE_STRING);
-
- markdown_textview_signals[HOVERING_OVER_TEXT] = g_signal_new(
- "hovering-over-text",
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET(MarkdownTextViewClass, hovering_over_text),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
- markdown_textview_signals[FILE_LOAD_COMPLETE] = g_signal_new(
- "file-load-complete",
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET(MarkdownTextViewClass, file_load_complete),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE,
- 1,
- G_TYPE_STRING);
-}
-
-static void
-gtk_text_buffer_insert_markup(GtkTextBuffer * buffer, GtkTextIter * iter,
- const gchar * markup)
-{
- PangoAttrIterator *paiter;
- PangoAttrList *attrlist;
- GtkTextMark *mark;
- GError *error = NULL;
- gchar *text;
-
- g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer));
- g_return_if_fail(markup != NULL);
-
- if (*markup == '\000')
- return;
-
- /* invalid */
- if (!pango_parse_markup(markup, -1, 0, &attrlist, &text, NULL, &error)) {
- g_warning("Invalid markup string: %s", error->message);
- g_error_free(error);
- return;
- }
-
- /* trivial, no markup */
- if (attrlist == NULL) {
- gtk_text_buffer_insert(buffer, iter, text, -1);
- g_free(text);
- return;
- }
-
- /* create mark with right gravity */
- mark = gtk_text_buffer_create_mark(buffer, NULL, iter, FALSE);
- paiter = pango_attr_list_get_iterator(attrlist);
-
- do {
- PangoAttribute *attr;
- GtkTextTag *tag;
- GtkTextTag *tag_para;
- gint start, end;
-
- pango_attr_iterator_range(paiter, &start, &end);
-
- if (end == G_MAXINT) /* last chunk */
- end = start - 1; /* resulting in -1 to be passed to _insert */
-
- tag = gtk_text_tag_new(NULL);
-
- if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_LANGUAGE)))
- g_object_set(tag, "language",
- pango_language_to_string(((PangoAttrLanguage *)
- attr)->value), NULL);
-
- if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_FAMILY)))
- g_object_set(tag, "family", ((PangoAttrString *) attr)->value,
- NULL);
-
- if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_STYLE)))
- g_object_set(tag, "style", ((PangoAttrInt *) attr)->value,
- NULL);
-
- if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_WEIGHT)))
- g_object_set(tag, "weight", ((PangoAttrInt *) attr)->value,
- NULL);
-
- if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_VARIANT)))
- g_object_set(tag, "variant", ((PangoAttrInt *) attr)->value,
- NULL);
-
- if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_STRETCH)))
- g_object_set(tag, "stretch", ((PangoAttrInt *) attr)->value,
- NULL);
-
- if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_SIZE)))
- g_object_set(tag, "size", ((PangoAttrInt *) attr)->value,
- NULL);
-
- if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_FONT_DESC)))
- g_object_set(tag, "font-desc",
- ((PangoAttrFontDesc *) attr)->desc, NULL);
-
- if ((attr =
- pango_attr_iterator_get(paiter, PANGO_ATTR_FOREGROUND))) {
- GdkColor col = { 0,
- ((PangoAttrColor *) attr)->color.red,
- ((PangoAttrColor *) attr)->color.green,
- ((PangoAttrColor *) attr)->color.blue
- };
-
- g_object_set(tag, "foreground-gdk", &col, NULL);
- }
-
- if ((attr =
- pango_attr_iterator_get(paiter, PANGO_ATTR_BACKGROUND))) {
- GdkColor col = { 0,
- ((PangoAttrColor *) attr)->color.red,
- ((PangoAttrColor *) attr)->color.green,
- ((PangoAttrColor *) attr)->color.blue
- };
-
- g_object_set(tag, "background-gdk", &col, NULL);
- }
-
- if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_UNDERLINE)))
- g_object_set(tag, "underline", ((PangoAttrInt *) attr)->value,
- NULL);
-
- if ((attr =
- pango_attr_iterator_get(paiter, PANGO_ATTR_STRIKETHROUGH)))
- g_object_set(tag, "strikethrough",
- (gboolean) (((PangoAttrInt *) attr)->value != 0),
- NULL);
-
- if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_RISE)))
- g_object_set(tag, "rise", ((PangoAttrInt *) attr)->value,
- NULL);
-
- if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_SCALE)))
- g_object_set(tag, "scale", ((PangoAttrFloat *) attr)->value,
- NULL);
-
- gtk_text_tag_table_add(gtk_text_buffer_get_tag_table(buffer), tag);
-
- tag_para =
- gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table
- (buffer), "para");
- gtk_text_buffer_insert_with_tags(buffer, iter, text + start,
- end - start, tag, tag_para, NULL);
-
- /* mark had right gravity, so it should be
- * at the end of the inserted text now */
- gtk_text_buffer_get_iter_at_mark(buffer, iter, mark);
- } while (pango_attr_iterator_next(paiter));
-
- gtk_text_buffer_delete_mark(buffer, mark);
- pango_attr_iterator_destroy(paiter);
- pango_attr_list_unref(attrlist);
- g_free(text);
-}
-
-
-static void
-set_cursor_if_appropriate(MarkdownTextView * self, gint x, gint y)
-{
- GSList *tags = NULL, *tagp = NULL;
- GtkTextIter iter;
- gboolean hovering = FALSE;
- gchar *link_uri = NULL;
-
- gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(self), &iter, x,
- y);
-
- tags = gtk_text_iter_get_tags(&iter);
- for (tagp = tags; tagp != NULL; tagp = tagp->next) {
- GtkTextTag *tag = tagp->data;
- gint is_underline = 0;
- gchar *lang = NULL;
-
- g_object_get(G_OBJECT(tag),
- "underline", &is_underline,
- "language", &lang,
- NULL);
-
- if (is_underline == 1 && lang) {
- link_uri = egg_markdown_get_link_uri(self->markdown, atoi(lang));
- g_free(lang);
- hovering = TRUE;
- break;
- }
-
- g_free(lang);
- }
-
- if (hovering != self->hovering_over_link) {
- self->hovering_over_link = hovering;
-
- if (self->hovering_over_link) {
- g_signal_emit(self, markdown_textview_signals[HOVERING_OVER_LINK],
- 0, link_uri);
- gdk_window_set_cursor(gtk_text_view_get_window
- (GTK_TEXT_VIEW(self),
- GTK_TEXT_WINDOW_TEXT), hand_cursor);
- } else {
- g_signal_emit(self, markdown_textview_signals[HOVERING_OVER_TEXT], 0);
- gdk_window_set_cursor(gtk_text_view_get_window
- (GTK_TEXT_VIEW(self),
- GTK_TEXT_WINDOW_TEXT), NULL);
- }
- }
-
- if (link_uri)
- g_free(link_uri);
-
- if (tags)
- g_slist_free(tags);
-}
-
-/* Update the cursor image if the pointer moved.
- */
-static gboolean
-motion_notify_event(GtkWidget * self, GdkEventMotion * event)
-{
- gint x, y;
-
- gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(self),
- GTK_TEXT_WINDOW_WIDGET,
- event->x, event->y, &x, &y);
-
- set_cursor_if_appropriate(MARKDOWN_TEXTVIEW(self), x, y);
-
- gdk_window_get_pointer(self->window, NULL, NULL, NULL);
- return FALSE;
-}
-
-/* Also update the cursor image if the window becomes visible
- * (e.g. when a window covering it got iconified).
- */
-static gboolean
-visibility_notify_event(GtkWidget * self, GdkEventVisibility * event)
-{
- gint wx, wy, bx, by;
-
- gdk_window_get_pointer(self->window, &wx, &wy, NULL);
-
- gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(self),
- GTK_TEXT_WINDOW_WIDGET,
- wx, wy, &bx, &by);
-
- set_cursor_if_appropriate(MARKDOWN_TEXTVIEW(self), bx, by);
-
- return FALSE;
-}
-
-static void
-follow_if_link(GtkWidget * widget, GtkTextIter * iter)
-{
- GSList *tags = NULL, *tagp = NULL;
- MarkdownTextView *self = MARKDOWN_TEXTVIEW(widget);
-
- tags = gtk_text_iter_get_tags(iter);
- for (tagp = tags; tagp != NULL; tagp = tagp->next) {
- GtkTextTag *tag = tagp->data;
- gint is_underline = 0;
- gchar *lang = NULL;
-
- g_object_get(G_OBJECT(tag),
- "underline", &is_underline,
- "language", &lang,
- NULL);
-
- if (is_underline == 1 && lang) {
- gchar *link = egg_markdown_get_link_uri(self->markdown, atoi(lang));
- if (link) {
- g_signal_emit(self, markdown_textview_signals[LINK_CLICKED],
- 0, link);
- g_free(link);
- }
- g_free(lang);
- break;
- }
-
- g_free(lang);
- }
-
- if (tags)
- g_slist_free(tags);
-}
-
-static gboolean
-key_press_event(GtkWidget * self,
- GdkEventKey * event)
-{
- GtkTextIter iter;
- GtkTextBuffer *buffer;
-
- switch (event->keyval) {
- case GDK_Return:
- case GDK_KP_Enter:
- buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(self));
- gtk_text_buffer_get_iter_at_mark(buffer, &iter,
- gtk_text_buffer_get_insert
- (buffer));
- follow_if_link(self, &iter);
- break;
-
- default:
- break;
- }
-
- return FALSE;
-}
-
-static gboolean
-event_after(GtkWidget * self, GdkEvent * ev)
-{
- GtkTextIter start, end, iter;
- GtkTextBuffer *buffer;
- GdkEventButton *event;
- gint x, y;
-
- if (ev->type != GDK_BUTTON_RELEASE)
- return FALSE;
-
- event = (GdkEventButton *) ev;
-
- if (event->button != 1)
- return FALSE;
-
- buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(self));
-
- /* we shouldn't follow a link if the user has selected something */
- gtk_text_buffer_get_selection_bounds(buffer, &start, &end);
- if (gtk_text_iter_get_offset(&start) != gtk_text_iter_get_offset(&end))
- return FALSE;
-
- gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(self),
- GTK_TEXT_WINDOW_WIDGET,
- event->x, event->y, &x, &y);
-
- gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(self), &iter, x,
- y);
-
- follow_if_link(self, &iter);
-
- return FALSE;
-}
-
-void
-markdown_textview_clear(MarkdownTextView * self)
-{
- GtkTextBuffer *text_buffer;
-
- g_return_if_fail(IS_MARKDOWN_TEXTVIEW(self));
-
- egg_markdown_clear(self->markdown);
-
- text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(self));
- gtk_text_buffer_set_text(text_buffer, "\n", 1);
-}
-
-static void
-load_images(MarkdownTextView * self)
-{
- GtkTextBuffer *buffer;
- GtkTextIter iter;
- GSList *tags, *tagp;
- gchar *image_path;
-
- buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(self));
- gtk_text_buffer_get_start_iter(buffer, &iter);
-
- do {
- tags = gtk_text_iter_get_tags(&iter);
- for (tagp = tags; tagp != NULL; tagp = tagp->next) {
- GtkTextTag *tag = tagp->data;
- gint is_underline = 0;
- gchar *lang = NULL;
-
- g_object_get(G_OBJECT(tag),
- "underline", &is_underline,
- "language", &lang,
- NULL);
-
- if (is_underline == 2 && lang) {
- GdkPixbuf *pixbuf;
- gchar *path;
-
- image_path = egg_markdown_get_link_uri(self->markdown, atoi(lang));
- path = g_build_filename(self->image_directory, image_path, NULL);
- pixbuf = gdk_pixbuf_new_from_file(path, NULL);
- if (pixbuf) {
- GtkTextMark *mark;
- GtkTextIter start;
-
- mark = gtk_text_buffer_create_mark(buffer, NULL, &iter, FALSE);
-
- gtk_text_buffer_get_iter_at_mark(buffer, &start, mark);
- gtk_text_iter_forward_to_tag_toggle(&iter, tag);
- gtk_text_buffer_delete(buffer, &start, &iter);
-
- gtk_text_buffer_insert_pixbuf(buffer, &iter, pixbuf);
-
- g_object_unref(pixbuf);
- gtk_text_buffer_delete_mark(buffer, mark);
- }
-
- g_free(image_path);
- g_free(lang);
- g_free(path);
- break;
- }
-
- g_free(lang);
- }
-
- if (tags)
- g_slist_free(tags);
- } while (gtk_text_iter_forward_to_tag_toggle(&iter, NULL));
-}
-
-static gboolean
-append_text(MarkdownTextView * self,
- const gchar * text)
-{
- GtkTextIter iter;
- GtkTextBuffer *text_buffer;
- gchar *line;
-
- g_return_val_if_fail(IS_MARKDOWN_TEXTVIEW(self), FALSE);
-
- text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(self));
- gtk_text_buffer_get_end_iter(text_buffer, &iter);
-
- line = egg_markdown_parse(self->markdown, text);
- if (line && *line) {
- gtk_text_buffer_insert_markup(text_buffer, &iter, line);
- gtk_text_buffer_insert(text_buffer, &iter, "\n", 1);
- g_free(line);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-gboolean
-markdown_textview_set_text(MarkdownTextView * self,
- const gchar * text)
-{
- gboolean result = TRUE;
- gchar **lines;
- gint line;
-
- g_return_val_if_fail(IS_MARKDOWN_TEXTVIEW(self), FALSE);
-
- markdown_textview_clear(self);
-
- lines = g_strsplit(text, "\n", 0);
- for (line = 0; result && lines[line]; line++) {
- result = append_text(self, (const gchar *)lines[line]);
- }
- g_strfreev(lines);
-
- load_images(self);
-
- return result;
-}
-
-gboolean
-markdown_textview_load_file(MarkdownTextView * self,
- const gchar * file_name)
-{
- FILE *text_file;
- gchar *path;
-
- g_return_val_if_fail(IS_MARKDOWN_TEXTVIEW(self), FALSE);
-
- path = g_build_filename(self->image_directory, file_name, NULL);
-
- /* we do assume UTF-8 encoding */
- if ((text_file = fopen(path, "rb"))) {
- GtkTextBuffer *text_buffer;
- GtkTextIter iter;
- gchar *line;
- gchar buffer[EGG_MARKDOWN_MAX_LINE_LENGTH];
-
- text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(self));
-
- gtk_text_buffer_set_text(text_buffer, "\n", 1);
- gtk_text_buffer_get_start_iter(text_buffer, &iter);
-
- egg_markdown_clear(self->markdown);
-
- while (fgets(buffer, EGG_MARKDOWN_MAX_LINE_LENGTH, text_file)) {
- line = egg_markdown_parse(self->markdown, buffer);
-
- if (line && *line) {
- gtk_text_buffer_insert_markup(text_buffer, &iter, line);
- gtk_text_buffer_insert(text_buffer, &iter, "\n", 1);
- }
-
- g_free(line);
- }
- fclose(text_file);
-
- load_images(self);
-
- g_signal_emit(self, markdown_textview_signals[FILE_LOAD_COMPLETE], 0, file_name);
-
- g_free(path);
-
- return TRUE;
- }
-
- g_free(path);
-
- return FALSE;
-}
-
-void
-markdown_textview_set_image_directory(MarkdownTextView * self, const gchar *directory)
-{
- g_return_if_fail(IS_MARKDOWN_TEXTVIEW(self));
-
- g_free(self->image_directory);
- self->image_directory = g_strdup(directory);
-}
-
-static void markdown_textview_init(MarkdownTextView * self)
-{
- self->markdown = egg_markdown_new();
- self->image_directory = g_strdup(".");
-
- egg_markdown_set_output(self->markdown, EGG_MARKDOWN_OUTPUT_PANGO);
- egg_markdown_set_escape(self->markdown, TRUE);
- egg_markdown_set_autocode(self->markdown, TRUE);
- egg_markdown_set_smart_quoting(self->markdown, TRUE);
-
- gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(self), GTK_WRAP_WORD);
- gtk_text_view_set_editable(GTK_TEXT_VIEW(self), FALSE);
- gtk_text_view_set_left_margin(GTK_TEXT_VIEW(self), 10);
- gtk_text_view_set_right_margin(GTK_TEXT_VIEW(self), 10);
- gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(self), 3);
- gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(self), 3);
-
- g_signal_connect(self, "event-after",
- G_CALLBACK(event_after), NULL);
- g_signal_connect(self, "key-press-event",
- G_CALLBACK(key_press_event), NULL);
- g_signal_connect(self, "motion-notify-event",
- G_CALLBACK(motion_notify_event), NULL);
- g_signal_connect(self, "visibility-notify-event",
- G_CALLBACK(visibility_notify_event), NULL);
-}
-