From: Bruno Haible Date: Wed, 14 Aug 2019 18:52:25 +0000 (+0200) Subject: libtextstyle: html-ostream: Add hyperlink support. X-Git-Tag: v0.21~192 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4a553fd8d37fe045d3be1d1995245cd1e389f32f;p=thirdparty%2Fgettext.git libtextstyle: html-ostream: Add hyperlink support. * libtextstyle/gnulib-local/lib/html-ostream.oo.h (struct html_ostream): Add methods get_hyperlink_ref, set_hyperlink_ref. * libtextstyle/gnulib-local/lib/html-ostream.oo.c (struct html_ostream): Add field hyperlink_ref; (write_attribute_value): New function. (html_ostream::free): Emit an anchor end if needed. (html_ostream::get_hyperlink_ref, html_ostream::set_hyperlink_ref): New functions. (html_ostream_create): Initialize the hyperlink_ref field. * libtextstyle/lib/textstyle.h (html_ostream_get_hyperlink_ref, html_ostream_set_hyperlink_ref): New declarations. --- diff --git a/libtextstyle/gnulib-local/lib/html-ostream.oo.c b/libtextstyle/gnulib-local/lib/html-ostream.oo.c index 6c55847a8..07e436a13 100644 --- a/libtextstyle/gnulib-local/lib/html-ostream.oo.c +++ b/libtextstyle/gnulib-local/lib/html-ostream.oo.c @@ -35,6 +35,8 @@ struct html_ostream : struct ostream fields: /* The destination stream. */ ostream_t destination; + /* The current hyperlink ref. */ + char *hyperlink_ref; /* The stack of active CSS classes. */ gl_list_t /* */ class_stack; /* Current and last size of the active portion of this stack. Always @@ -47,6 +49,49 @@ fields: size_t buflen; }; +/* Emit an HTML attribute value. + quote is either '"' or '\''. */ +static void +write_attribute_value (html_ostream_t stream, const char *value, char quote) +{ + /* Need to escape the '<', '>', '&', quote characters. */ + ostream_t destination = stream->destination; + const char *p = value; + + for (;;) + { + const char *q = p; + + while (*q != '\0' && *q != '<' && *q != '>' && *q != '&' && *q != quote) + q++; + if (p < q) + ostream_write_mem (destination, p, q - p); + if (*q == '\0') + break; + switch (*q) + { + case '<': + ostream_write_str (destination, "<"); + break; + case '>': + ostream_write_str (destination, ">"); + break; + case '&': + ostream_write_str (destination, "&"); + break; + case '"': + ostream_write_str (destination, """); + break; + case '\'': + ostream_write_str (destination, "'"); + break; + default: + abort (); + } + p = q + 1; + } +} + /* Implementation of ostream_t methods. */ static void @@ -261,6 +306,12 @@ html_ostream::free (html_ostream_t stream) { stream->curr_class_stack_size = 0; emit_pending_spans (stream, true); + if (stream->hyperlink_ref != NULL) + { + /* Close the current element. */ + ostream_write_str (stream->destination, ""); + free (stream->hyperlink_ref); + } verify_invariants (stream); gl_list_free (stream->class_stack); free (stream); @@ -312,6 +363,50 @@ html_ostream::end_span (html_ostream_t stream, const char *classname) abort (); } +static const char * +html_ostream::get_hyperlink_ref (html_ostream_t stream) +{ + return stream->hyperlink_ref; +} + +static void +html_ostream::set_hyperlink_ref (html_ostream_t stream, const char *ref) +{ + char *ref_copy = (ref != NULL ? xstrdup (ref) : NULL); + + verify_invariants (stream); + if (stream->hyperlink_ref != NULL) + { + /* Close the open tags, and prepare for reopening the same + tags. */ + size_t prev_class_stack_size = stream->curr_class_stack_size; + stream->curr_class_stack_size = 0; + emit_pending_spans (stream, false); + stream->curr_class_stack_size = prev_class_stack_size; + /* Close the current element. */ + ostream_write_str (stream->destination, ""); + shrink_class_stack (stream); + + free (stream->hyperlink_ref); + } + stream->hyperlink_ref = ref_copy; + if (stream->hyperlink_ref != NULL) + { + /* Close the open tags, and prepare for reopening the same + tags. */ + size_t prev_class_stack_size = stream->curr_class_stack_size; + stream->curr_class_stack_size = 0; + emit_pending_spans (stream, false); + stream->curr_class_stack_size = prev_class_stack_size; + /* Open an element. */ + ostream_write_str (stream->destination, "hyperlink_ref, '"'); + ostream_write_str (stream->destination, "\">"); + shrink_class_stack (stream); + } + verify_invariants (stream); +} + static void html_ostream::flush_to_current_style (html_ostream_t stream) { @@ -332,6 +427,7 @@ html_ostream_create (ostream_t destination) stream->base.vtable = &html_ostream_vtable; stream->destination = destination; + stream->hyperlink_ref = NULL; stream->class_stack = gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, NULL, true); stream->curr_class_stack_size = 0; diff --git a/libtextstyle/gnulib-local/lib/html-ostream.oo.h b/libtextstyle/gnulib-local/lib/html-ostream.oo.h index dd25aabac..05649c128 100644 --- a/libtextstyle/gnulib-local/lib/html-ostream.oo.h +++ b/libtextstyle/gnulib-local/lib/html-ostream.oo.h @@ -34,6 +34,10 @@ methods: The begin_span / end_span calls must match properly. */ void end_span (html_ostream_t stream, const char *classname); + /* Get/set the hyperlink attribute. */ + const char * get_hyperlink_ref (html_ostream_t stream); + void set_hyperlink_ref (html_ostream_t stream, const char *ref); + /* Like html_ostream_flush (first_arg, FLUSH_THIS_STREAM), except that it leaves the destination with the current text style enabled, instead of with the default text style. diff --git a/libtextstyle/lib/textstyle.h b/libtextstyle/lib/textstyle.h index ecb669179..00471d481 100644 --- a/libtextstyle/lib/textstyle.h +++ b/libtextstyle/lib/textstyle.h @@ -358,6 +358,8 @@ extern void html_ostream_flush (html_ostream_t first_arg, ostream_flush_scope_t extern void html_ostream_free (html_ostream_t first_arg); extern void html_ostream_begin_span (html_ostream_t first_arg, const char *classname); extern void html_ostream_end_span (html_ostream_t first_arg, const char *classname); +extern const char *html_ostream_get_hyperlink_ref (html_ostream_t first_arg); +extern void html_ostream_set_hyperlink_ref (html_ostream_t first_arg, const char *ref); /* Like html_ostream_flush (first_arg, FLUSH_THIS_STREAM), except that it leaves the destination with the current text style enabled, instead of with the default text style.