Implemented absolute links

This commit is contained in:
Pierre Pronchery 2010-08-27 00:28:14 +00:00
parent e067f3bb42
commit f52ec7e720

View File

@ -46,7 +46,7 @@ typedef struct _GHtmlTag
char const * name;
GHtmlDisplay display;
GHtmlProperty const * properties;
GtkTextTag const * tag;
GtkTextTag * tag;
} GHtmlTag;
#define GHTML_TAGS_COUNT 20
@ -77,74 +77,86 @@ typedef struct _GHtml
/* constants */
/* properties */
static const GHtmlProperty _ghtml_properties_a[] = {
static const GHtmlProperty _ghtml_properties_a[] =
{
{ "foreground", "blue" },
{ "underline", PANGO_UNDERLINE_SINGLE },
{ "underline-set", TRUE },
{ NULL, 0 }
};
static const GHtmlProperty _ghtml_properties_b[] = {
static const GHtmlProperty _ghtml_properties_b[] =
{
{ "weight", PANGO_WEIGHT_BOLD },
{ "weight-set", TRUE },
{ NULL, 0 }
};
/* XXX should use "scale" but gdouble values are not accepted this way */
static const GHtmlProperty _ghtml_properties_h1[] = {
static const GHtmlProperty _ghtml_properties_h1[] =
{
{ "font", "Sans 16" },
{ "weight", PANGO_WEIGHT_BOLD },
{ "weight-set", TRUE },
{ NULL, 0 }
};
static const GHtmlProperty _ghtml_properties_h2[] = {
static const GHtmlProperty _ghtml_properties_h2[] =
{
{ "font", "Sans 14" },
{ "weight", PANGO_WEIGHT_BOLD },
{ "weight-set", TRUE },
{ NULL, 0 }
};
static const GHtmlProperty _ghtml_properties_h3[] = {
static const GHtmlProperty _ghtml_properties_h3[] =
{
{ "font", "Sans 13" },
{ "weight", PANGO_WEIGHT_BOLD },
{ "weight-set", TRUE },
{ NULL, 0 }
};
static const GHtmlProperty _ghtml_properties_h4[] = {
static const GHtmlProperty _ghtml_properties_h4[] =
{
{ "font", "Sans 12" },
{ "weight", PANGO_WEIGHT_BOLD },
{ "weight-set", TRUE },
{ NULL, 0 }
};
static const GHtmlProperty _ghtml_properties_h5[] = {
static const GHtmlProperty _ghtml_properties_h5[] =
{
{ "font", "Sans 11" },
{ "weight", PANGO_WEIGHT_BOLD },
{ "weight-set", TRUE },
{ NULL, 0 }
};
static const GHtmlProperty _ghtml_properties_h6[] = {
static const GHtmlProperty _ghtml_properties_h6[] =
{
{ "font", "Sans 10" },
{ "weight", PANGO_WEIGHT_BOLD },
{ "weight-set", TRUE },
{ NULL, 0 }
};
static const GHtmlProperty _ghtml_properties_pre[] = {
static const GHtmlProperty _ghtml_properties_pre[] =
{
{ "family", "Monospace" },
{ "wrap-mode", GTK_WRAP_NONE },
{ "wrap-mode-set", TRUE },
{ NULL, 0 }
};
static const GHtmlProperty _ghtml_properties_tt[] = {
static const GHtmlProperty _ghtml_properties_tt[] =
{
{ "family", "Monospace" },
{ NULL, 0 }
};
static const GHtmlProperty _ghtml_properties_u[] = {
static const GHtmlProperty _ghtml_properties_u[] =
{
{ "underline", PANGO_UNDERLINE_SINGLE },
{ "underline-set", TRUE },
{ NULL, 0 }
@ -181,6 +193,10 @@ static int _ghtml_document_load(GHtml * ghtml, char const * url,
char const * post);
static int _ghtml_stop(GHtml * ghtml);
/* callbacks */
static gboolean _on_view_event_after(GtkWidget * widget, GdkEvent * event,
gpointer data);
/* public */
/* functions */
@ -204,6 +220,8 @@ GtkWidget * ghtml_new(Surfer * surfer)
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
ghtml->view = gtk_text_view_new();
g_signal_connect(G_OBJECT(ghtml->view), "event-after", G_CALLBACK(
_on_view_event_after), ghtml);
ghtml->tbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ghtml->view));
memcpy(ghtml->tags, _ghtml_tags, sizeof(_ghtml_tags));
ghtml->tag = NULL;
@ -505,6 +523,8 @@ static ssize_t _document_load_write(Conn * conn, char const * buf, size_t size,
static gboolean _document_load_idle(gpointer data);
static void _document_load_write_node(GHtml * ghtml, XMLNode * node);
static void _document_load_write_node_tag(GHtml * ghtml, XMLNodeTag * node);
static void _document_load_write_node_tag_link(GHtml * ghtml,
XMLNodeTag * node);
static int _ghtml_document_load(GHtml * ghtml, char const * url,
char const * post)
@ -584,7 +604,7 @@ static void _document_load_write_node_tag(GHtml * ghtml, XMLNodeTag * node)
size_t i;
GHtmlDisplay display = GHTML_DISPLAY_INLINE;
GtkTextIter iter;
GHtmlProperty * p;
GHtmlProperty const * p;
ghtml->tag = NULL;
for(i = 0; i < GHTML_TAGS_COUNT; i++)
@ -594,13 +614,15 @@ static void _document_load_write_node_tag(GHtml * ghtml, XMLNodeTag * node)
{
display = ghtml->tags[i].display;
ghtml->tag = ghtml->tags[i].tag;
if(ghtml->tags[i].tag == NULL
&& ghtml->tags[i].properties != NULL)
if(ghtml->tag == NULL && ghtml->tags[i].properties != NULL)
{
ghtml->tags[i].tag = gtk_text_buffer_create_tag(
ghtml->tbuffer, node->name, NULL);
ghtml->tag = ghtml->tags[i].tag;
ghtml->tag = gtk_text_buffer_create_tag(
ghtml->tbuffer, NULL, NULL);
p = ghtml->tags[i].properties;
if(strcmp(node->name, "a") != 0)
ghtml->tags[i].tag = ghtml->tag;
else
_document_load_write_node_tag_link(ghtml, node);
for(i = 0; p[i].name != NULL; i++)
g_object_set(G_OBJECT(ghtml->tag), p[i].name,
p[i].value, NULL);
@ -620,6 +642,18 @@ static void _document_load_write_node_tag(GHtml * ghtml, XMLNodeTag * node)
_document_load_write_node(ghtml, node->childs[i]);
}
static void _document_load_write_node_tag_link(GHtml * ghtml, XMLNodeTag * node)
{
size_t i;
for(i = 0; i < node->attributes_cnt; i++)
if(strcmp(node->attributes[i]->name, "href") == 0)
break;
if(i < node->attributes_cnt)
g_object_set_data(G_OBJECT(ghtml->tag), "link", strdup(
node->attributes[i]->value));
}
static gboolean _document_load_idle(gpointer data)
{
GHtml * ghtml = data;
@ -639,3 +673,41 @@ static int _ghtml_stop(GHtml * ghtml)
ghtml->conn = NULL;
return 0;
}
/* callbacks */
/* on_view_event_after */
static gboolean _on_view_event_after(GtkWidget * widget, GdkEvent * event,
gpointer data)
{
GHtml * ghtml = data;
GdkEventButton * eb;
GtkTextIter start;
GtkTextIter end;
gint x;
gint y;
GtkTextIter iter;
GSList * tags;
GSList * p;
char * link = NULL;
if(event->type != GDK_BUTTON_RELEASE || event->button.button != 1)
return FALSE;
eb = &event->button;
gtk_text_buffer_get_selection_bounds(ghtml->tbuffer, &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(widget),
GTK_TEXT_WINDOW_WIDGET, eb->x, eb->y, &x, &y);
gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(widget), &iter, x, y);
tags = gtk_text_iter_get_tags(&iter);
for(p = tags; p != NULL; p = p->next)
if((link = g_object_get_data(G_OBJECT(p->data), "link"))
!= NULL)
break;
if(tags != NULL)
g_slist_free(tags);
if(link != NULL)
surfer_open(ghtml->surfer, link); /* XXX support relative */
return FALSE;
}