summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--text.c70
1 files changed, 63 insertions, 7 deletions
diff --git a/text.c b/text.c
index 24cfb3e..256e804 100644
--- a/text.c
+++ b/text.c
@@ -28,8 +28,9 @@ union Command
} block;
struct {
int type;
- int position;
- int length;
+ int start;
+ int end;
+ const char * uri;
} span;
};
@@ -65,20 +66,29 @@ struct Layout
int setup(struct State *);
void finalize(struct State *, struct Layout *);
int handle(struct State *, xcb_generic_event_t *);
+xcb_visualtype_t * find_visual(xcb_screen_t *);
+PangoAttribute * find_link_under(PangoLayout *, PangoAttrList *, int, int);
void arrange(struct State *, struct Layout *, union Command[]);
void draw(struct State *, struct Layout *);
-xcb_visualtype_t * find_visual(xcb_screen_t *);
+PangoAttribute * attr_hyperlink_new(const char *);
+PangoAttribute * attr_string_copy(const PangoAttribute *);
+void attr_string_destroy(PangoAttribute *);
+gboolean attr_string_equal(const PangoAttribute *, const PangoAttribute *);
+PangoAttribute * attr_string_new(const PangoAttrClass *, const char *);
static const int MARGIN = 20;
static const char * const FONT = "Serif 16";
+static PangoAttrType PANGO_CUSTOM_ATTR_HYPERLINK;
+static PangoAttrClass hyperlink_klass; // TODO: Separate almost-pango-internals somewhere to minimize clutter.
#define _BLOCK(_txt) {.block = {.type = COMMAND_BLOCK, .length = sizeof(_txt) - 1, .data = _txt}}
union Command body[] = {
- {.span = {.type = COMMAND_SPAN, .position = 28, .length = 11}},
+ {.span = {.type = COMMAND_SPAN, .start = 28, .end = 39, .uri = "https://ignore.pl/consectetur"}},
_BLOCK(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam auctor porta eros at tempus. Aliquam "
"elementum lectus id mi fermentum, non consectetur urna lobortis."
),
+ {.span = {.type = COMMAND_SPAN, .start = 10, .end = 19, .uri = "https://ignore.pl/dignissim"}},
_BLOCK("Phasellus dignissim rhoncus magna at imperdiet."),
{.type = COMMAND_DONE},
};
@@ -89,6 +99,13 @@ int main(int argc, const char ** argv)
{
(void) argc;
(void) argv;
+ PANGO_CUSTOM_ATTR_HYPERLINK = pango_attr_type_register("hyperlink");
+ hyperlink_klass = (PangoAttrClass){
+ PANGO_CUSTOM_ATTR_HYPERLINK,
+ attr_string_copy,
+ attr_string_destroy,
+ attr_string_equal,
+ };
struct State state;
if (-1 == setup(&state))
{
@@ -264,8 +281,12 @@ void arrange(struct State * state, struct Layout * layout, union Command body[])
case COMMAND_SPAN:
;
PangoAttribute * attr = pango_attr_foreground_new(0x0000, 0x0000, 0xffff);
- attr->start_index = c->span.position;
- attr->end_index = c->span.position + c->span.length;
+ attr->start_index = c->span.start;
+ attr->end_index = c->span.end;
+ pango_attr_list_change(attrs, attr);
+ attr = attr_hyperlink_new(c->span.uri);
+ attr->start_index = c->span.start;
+ attr->end_index = c->span.end;
pango_attr_list_change(attrs, attr);
break;
case COMMAND_BLOCK:
@@ -273,7 +294,7 @@ void arrange(struct State * state, struct Layout * layout, union Command body[])
attr = find_link_under(layout->v[i], attrs, state->pointer_x - MARGIN, state->pointer_y - MARGIN);
if (NULL != attr)
pango_attr_list_change(attrs, attr);
- pango_layout_set_attributes(layout->v[i], attrs); // TODO-maybe: Don't reset everything?
+ pango_layout_set_attributes(layout->v[i], attrs);
pango_attr_list_unref(attrs);
attrs = pango_attr_list_new();
pango_layout_set_font_description(layout->v[i], layout->desc);
@@ -309,3 +330,38 @@ void draw(struct State * state, struct Layout * layout)
cairo_surface_flush(state->surface);
xcb_flush(state->c);
}
+
+
+PangoAttribute * attr_hyperlink_new(const char * uri)
+{
+ return attr_string_new(&hyperlink_klass, uri);
+}
+
+
+PangoAttribute * attr_string_copy(const PangoAttribute * src)
+{
+ return attr_string_new(src->klass, ((PangoAttrString *) src)->value);
+}
+
+
+void attr_string_destroy(PangoAttribute * attr)
+{
+ PangoAttrString * str = (PangoAttrString *) attr;
+ g_free(str->value);
+ g_slice_free(PangoAttrString, str);
+}
+
+
+gboolean attr_string_equal(const PangoAttribute * lhs, const PangoAttribute * rhs)
+{
+ return 0 == strcmp(((PangoAttrString *) lhs)->value, ((PangoAttrString *) rhs)->value);
+}
+
+
+PangoAttribute * attr_string_new(const PangoAttrClass * klass, const char * uri)
+{
+ PangoAttrString * str = g_slice_new(PangoAttrString);
+ pango_attribute_init(&str->attr, klass);
+ str->value = g_strdup(uri);
+ return (PangoAttribute *) str;
+}