1 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
2
3 #if !IS_CPLUSPLUS
4 #define term_styled_ostream_representation any_ostream_representation
5 #endif
6 #line 1 "term-styled-ostream.oo.c"
7 /* Output stream for CSS styled text, producing ANSI escape sequences.
8 Copyright (C) 2006-2007, 2019-2020 Free Software Foundation, Inc.
9 Written by Bruno Haible <bruno@clisp.org>, 2006.
10
11 This program is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <https://www.gnu.org/licenses/>. */
23
24 #include <config.h>
25
26 /* Specification. */
27 #include "term-styled-ostream.h"
28
29 #include <stdlib.h>
30
31 #include <cr-om-parser.h>
32 #include <cr-sel-eng.h>
33 #include <cr-style.h>
34 #include <cr-rgb.h>
35 /* <cr-fonts.h> has a broken double-inclusion guard in libcroco-0.6.1. */
36 #ifndef __CR_FONTS_H__
37 # include <cr-fonts.h>
38 #endif
39 #include <cr-string.h>
40
41 #include "term-ostream.h"
42 #include "mem-hash-map.h"
43 #include "xalloc.h"
44
45
46 /* CSS matching works as follows:
47 Suppose we have an element inside class "header" inside class "table".
48 We pretend to have an XML tree that looks like this:
49
50 (root)
51 +----table
52 +----header
53
54 For each of these XML nodes, the CSS matching engine can report the
55 matching CSS declarations. We extract the CSS property values that
56 matter for terminal styling and cache them. */
57
58 /* Attributes that can be set on a character. */
59 typedef struct
60 {
61 term_color_t color;
62 term_color_t bgcolor;
63 term_weight_t weight;
64 term_posture_t posture;
65 term_underline_t underline;
66 } attributes_t;
67
68 #line 69 "term-styled-ostream.c"
69 #include "term_styled_ostream.priv.h"
70
71 const typeinfo_t term_styled_ostream_typeinfo = { "term_styled_ostream" };
72
73 static const typeinfo_t * const term_styled_ostream_superclasses[] =
74 { term_styled_ostream_SUPERCLASSES };
75
76 #define super styled_ostream_vtable
77
78 #line 82 "term-styled-ostream.oo.c"
79
80 /* Implementation of ostream_t methods. */
81
82 static void
term_styled_ostream__write_mem(term_styled_ostream_t stream,const void * data,size_t len)83 term_styled_ostream__write_mem (term_styled_ostream_t stream,
84 const void *data, size_t len)
85 {
86 term_ostream_set_color (stream->destination, stream->curr_attr->color);
87 term_ostream_set_bgcolor (stream->destination, stream->curr_attr->bgcolor);
88 term_ostream_set_weight (stream->destination, stream->curr_attr->weight);
89 term_ostream_set_posture (stream->destination, stream->curr_attr->posture);
90 term_ostream_set_underline (stream->destination, stream->curr_attr->underline);
91
92 term_ostream_write_mem (stream->destination, data, len);
93 }
94
95 static void
term_styled_ostream__flush(term_styled_ostream_t stream,ostream_flush_scope_t scope)96 term_styled_ostream__flush (term_styled_ostream_t stream, ostream_flush_scope_t scope)
97 {
98 term_ostream_flush (stream->destination, scope);
99 }
100
101 static void
term_styled_ostream__free(term_styled_ostream_t stream)102 term_styled_ostream__free (term_styled_ostream_t stream)
103 {
104 term_ostream_free (stream->destination);
105 cr_cascade_destroy (stream->css_document);
106 cr_sel_eng_destroy (stream->css_engine);
107 free (stream->curr_classes);
108 {
109 void *ptr = NULL;
110 const void *key;
111 size_t keylen;
112 void *data;
113
114 while (hash_iterate (&stream->cache, &ptr, &key, &keylen, &data) == 0)
115 {
116 free (data);
117 }
118 }
119 hash_destroy (&stream->cache);
120 free (stream);
121 }
122
123 /* Implementation of styled_ostream_t methods. */
124
125 /* CRStyle doesn't contain a value for the 'text-decoration' property.
126 So we have to extend it. */
127
128 enum CRXTextDecorationType
129 {
130 TEXT_DECORATION_NONE,
131 TEXT_DECORATION_UNDERLINE,
132 TEXT_DECORATION_OVERLINE,
133 TEXT_DECORATION_LINE_THROUGH,
134 TEXT_DECORATION_BLINK,
135 TEXT_DECORATION_INHERIT
136 };
137
138 typedef struct _CRXStyle
139 {
140 struct _CRXStyle *parent_style;
141 CRStyle *base;
142 enum CRXTextDecorationType text_decoration;
143 } CRXStyle;
144
145 /* An extended version of cr_style_new. */
146 static CRXStyle *
crx_style_new(gboolean a_set_props_to_initial_values)147 crx_style_new (gboolean a_set_props_to_initial_values)
148 {
149 CRStyle *base;
150 CRXStyle *result;
151
152 base = cr_style_new (a_set_props_to_initial_values);
153 if (base == NULL)
154 return NULL;
155
156 result = XMALLOC (CRXStyle);
157 result->base = base;
158 if (a_set_props_to_initial_values)
159 result->text_decoration = TEXT_DECORATION_NONE;
160 else
161 result->text_decoration = TEXT_DECORATION_INHERIT;
162
163 return result;
164 }
165
166 /* An extended version of cr_style_destroy. */
167 static void
crx_style_destroy(CRXStyle * a_style)168 crx_style_destroy (CRXStyle *a_style)
169 {
170 cr_style_destroy (a_style->base);
171 free (a_style);
172 }
173
174 /* An extended version of cr_sel_eng_get_matched_style. */
175 static enum CRStatus
crx_sel_eng_get_matched_style(CRSelEng * a_this,CRCascade * a_cascade,xmlNode * a_node,CRXStyle * a_parent_style,CRXStyle ** a_style,gboolean a_set_props_to_initial_values)176 crx_sel_eng_get_matched_style (CRSelEng * a_this, CRCascade * a_cascade,
177 xmlNode * a_node,
178 CRXStyle * a_parent_style, CRXStyle ** a_style,
179 gboolean a_set_props_to_initial_values)
180 {
181 enum CRStatus status;
182 CRPropList *props = NULL;
183
184 if (!(a_this && a_cascade && a_node && a_style))
185 return CR_BAD_PARAM_ERROR;
186
187 status = cr_sel_eng_get_matched_properties_from_cascade (a_this, a_cascade,
188 a_node, &props);
189 if (!(status == CR_OK))
190 return status;
191
192 if (props)
193 {
194 CRXStyle *style;
195
196 if (!*a_style)
197 {
198 *a_style = crx_style_new (a_set_props_to_initial_values);
199 if (!*a_style)
200 return CR_ERROR;
201 }
202 else
203 {
204 if (a_set_props_to_initial_values)
205 {
206 cr_style_set_props_to_initial_values ((*a_style)->base);
207 (*a_style)->text_decoration = TEXT_DECORATION_NONE;
208 }
209 else
210 {
211 cr_style_set_props_to_default_values ((*a_style)->base);
212 (*a_style)->text_decoration = TEXT_DECORATION_INHERIT;
213 }
214 }
215 style = *a_style;
216 style->parent_style = a_parent_style;
217 style->base->parent_style =
218 (a_parent_style != NULL ? a_parent_style->base : NULL);
219
220 {
221 CRPropList *cur;
222
223 for (cur = props; cur != NULL; cur = cr_prop_list_get_next (cur))
224 {
225 CRDeclaration *decl = NULL;
226
227 cr_prop_list_get_decl (cur, &decl);
228 cr_style_set_style_from_decl (style->base, decl);
229 if (decl != NULL
230 && decl->property != NULL
231 && decl->property->stryng != NULL
232 && decl->property->stryng->str != NULL)
233 {
234 if (strcmp (decl->property->stryng->str, "text-decoration") == 0
235 && decl->value != NULL
236 && decl->value->type == TERM_IDENT
237 && decl->value->content.str != NULL)
238 {
239 const char *value =
240 cr_string_peek_raw_str (decl->value->content.str);
241
242 if (value != NULL)
243 {
244 if (strcmp (value, "none") == 0)
245 style->text_decoration = TEXT_DECORATION_NONE;
246 else if (strcmp (value, "underline") == 0)
247 style->text_decoration = TEXT_DECORATION_UNDERLINE;
248 else if (strcmp (value, "overline") == 0)
249 style->text_decoration = TEXT_DECORATION_OVERLINE;
250 else if (strcmp (value, "line-through") == 0)
251 style->text_decoration = TEXT_DECORATION_LINE_THROUGH;
252 else if (strcmp (value, "blink") == 0)
253 style->text_decoration = TEXT_DECORATION_BLINK;
254 else if (strcmp (value, "inherit") == 0)
255 style->text_decoration = TEXT_DECORATION_INHERIT;
256 }
257 }
258 }
259 }
260 }
261
262 cr_prop_list_destroy (props);
263 }
264
265 return CR_OK;
266 }
267
268 /* According to the CSS2 spec, sections 6.1 and 6.2, we need to do a
269 propagation: specified values -> computed values -> actual values.
270 The computed values are necessary. libcroco does not compute them for us.
271 The function cr_style_resolve_inherited_properties is also not sufficient:
272 it handles only the case of inheritance, not the case of non-inheritance.
273 So we write style accessors that fetch the computed value, doing the
274 inheritance on the fly.
275 We then compute the actual values from the computed values; for colors,
276 this is done through the rgb_to_color method. */
277
278 static term_color_t
style_compute_color_value(CRStyle * style,enum CRRgbProp which,term_ostream_t stream)279 style_compute_color_value (CRStyle *style, enum CRRgbProp which,
280 term_ostream_t stream)
281 {
282 for (;;)
283 {
284 if (style == NULL)
285 return COLOR_DEFAULT;
286 if (cr_rgb_is_set_to_inherit (&style->rgb_props[which].sv))
287 style = style->parent_style;
288 else if (cr_rgb_is_set_to_transparent (&style->rgb_props[which].sv))
289 /* A transparent color occurs as default background color, set by
290 cr_style_set_props_to_default_values. */
291 return COLOR_DEFAULT;
292 else
293 {
294 CRRgb rgb;
295 int r;
296 int g;
297 int b;
298
299 cr_rgb_copy (&rgb, &style->rgb_props[which].sv);
300 if (cr_rgb_compute_from_percentage (&rgb) != CR_OK)
301 abort ();
302 r = rgb.red & 0xff;
303 g = rgb.green & 0xff;
304 b = rgb.blue & 0xff;
305 return term_ostream_rgb_to_color (stream, r, g, b);
306 }
307 }
308 }
309
310 static term_weight_t
style_compute_font_weight_value(const CRStyle * style)311 style_compute_font_weight_value (const CRStyle *style)
312 {
313 int value = 0;
314 for (;;)
315 {
316 if (style == NULL)
317 value += 4;
318 else
319 switch (style->font_weight)
320 {
321 case FONT_WEIGHT_INHERIT:
322 style = style->parent_style;
323 continue;
324 case FONT_WEIGHT_BOLDER:
325 value += 1;
326 style = style->parent_style;
327 continue;
328 case FONT_WEIGHT_LIGHTER:
329 value -= 1;
330 style = style->parent_style;
331 continue;
332 case FONT_WEIGHT_100:
333 value += 1;
334 break;
335 case FONT_WEIGHT_200:
336 value += 2;
337 break;
338 case FONT_WEIGHT_300:
339 value += 3;
340 break;
341 case FONT_WEIGHT_400: case FONT_WEIGHT_NORMAL:
342 value += 4;
343 break;
344 case FONT_WEIGHT_500:
345 value += 5;
346 break;
347 case FONT_WEIGHT_600:
348 value += 6;
349 break;
350 case FONT_WEIGHT_700: case FONT_WEIGHT_BOLD:
351 value += 7;
352 break;
353 case FONT_WEIGHT_800:
354 value += 8;
355 break;
356 case FONT_WEIGHT_900:
357 value += 9;
358 break;
359 default:
360 abort ();
361 }
362 /* Value >= 600 -> WEIGHT_BOLD. Value <= 500 -> WEIGHT_NORMAL. */
363 return (value >= 6 ? WEIGHT_BOLD : WEIGHT_NORMAL);
364 }
365 }
366
367 static term_posture_t
style_compute_font_posture_value(const CRStyle * style)368 style_compute_font_posture_value (const CRStyle *style)
369 {
370 for (;;)
371 {
372 if (style == NULL)
373 return POSTURE_DEFAULT;
374 switch (style->font_style)
375 {
376 case FONT_STYLE_INHERIT:
377 style = style->parent_style;
378 break;
379 case FONT_STYLE_NORMAL:
380 return POSTURE_NORMAL;
381 case FONT_STYLE_ITALIC:
382 case FONT_STYLE_OBLIQUE:
383 return POSTURE_ITALIC;
384 default:
385 abort ();
386 }
387 }
388 }
389
390 static term_underline_t
style_compute_text_underline_value(const CRXStyle * style)391 style_compute_text_underline_value (const CRXStyle *style)
392 {
393 for (;;)
394 {
395 if (style == NULL)
396 return UNDERLINE_DEFAULT;
397 switch (style->text_decoration)
398 {
399 case TEXT_DECORATION_INHERIT:
400 style = style->parent_style;
401 break;
402 case TEXT_DECORATION_NONE:
403 case TEXT_DECORATION_OVERLINE:
404 case TEXT_DECORATION_LINE_THROUGH:
405 case TEXT_DECORATION_BLINK:
406 return UNDERLINE_OFF;
407 case TEXT_DECORATION_UNDERLINE:
408 return UNDERLINE_ON;
409 default:
410 abort ();
411 }
412 }
413 }
414
415 /* Match the current list of CSS classes to the CSS and return the result. */
416 static attributes_t *
match(term_styled_ostream_t stream)417 match (term_styled_ostream_t stream)
418 {
419 xmlNodePtr root;
420 xmlNodePtr curr;
421 char *p_end;
422 char *p_start;
423 CRXStyle *curr_style;
424 CRStyle *curr_style_base;
425 attributes_t *attr;
426
427 /* Create a hierarchy of XML nodes. */
428 root = xmlNewNode (NULL, (const xmlChar *) "__root__");
429 root->type = XML_ELEMENT_NODE;
430 curr = root;
431 p_end = &stream->curr_classes[stream->curr_classes_length];
432 p_start = stream->curr_classes;
433 while (p_start < p_end)
434 {
435 char *p;
436 xmlNodePtr child;
437
438 if (!(*p_start == ' '))
439 abort ();
440 p_start++;
441 for (p = p_start; p < p_end && *p != ' '; p++)
442 ;
443
444 /* Temporarily replace the ' ' by '\0'. */
445 *p = '\0';
446 child = xmlNewNode (NULL, (const xmlChar *) p_start);
447 child->type = XML_ELEMENT_NODE;
448 xmlSetProp (child, (const xmlChar *) "class", (const xmlChar *) p_start);
449 *p = ' ';
450
451 if (xmlAddChild (curr, child) == NULL)
452 /* Error! Shouldn't happen. */
453 abort ();
454
455 curr = child;
456 p_start = p;
457 }
458
459 /* Retrieve the matching CSS declarations. */
460 /* Not curr_style = crx_style_new (TRUE); because that assumes that the
461 default foreground color is black and that the default background color
462 is white, which is not necessarily true in a terminal context. */
463 curr_style = NULL;
464 for (curr = root; curr != NULL; curr = curr->children)
465 {
466 CRXStyle *parent_style = curr_style;
467 curr_style = NULL;
468
469 if (crx_sel_eng_get_matched_style (stream->css_engine,
470 stream->css_document,
471 curr,
472 parent_style, &curr_style,
473 FALSE) != CR_OK)
474 abort ();
475 if (curr_style == NULL)
476 /* No declarations matched this node. Inherit all values. */
477 curr_style = parent_style;
478 else
479 /* curr_style is a new style, inheriting from parent_style. */
480 ;
481 }
482 curr_style_base = (curr_style != NULL ? curr_style->base : NULL);
483
484 /* Extract the CSS declarations that we can use. */
485 attr = XMALLOC (attributes_t);
486 attr->color =
487 style_compute_color_value (curr_style_base, RGB_PROP_COLOR,
488 stream->destination);
489 attr->bgcolor =
490 style_compute_color_value (curr_style_base, RGB_PROP_BACKGROUND_COLOR,
491 stream->destination);
492 attr->weight = style_compute_font_weight_value (curr_style_base);
493 attr->posture = style_compute_font_posture_value (curr_style_base);
494 attr->underline = style_compute_text_underline_value (curr_style);
495
496 /* Free the style chain. */
497 while (curr_style != NULL)
498 {
499 CRXStyle *parent_style = curr_style->parent_style;
500
501 crx_style_destroy (curr_style);
502 curr_style = parent_style;
503 }
504
505 /* Free the XML nodes. */
506 xmlFreeNodeList (root);
507
508 return attr;
509 }
510
511 /* Match the current list of CSS classes to the CSS and store the result in
512 stream->curr_attr and in the cache. */
513 static void
match_and_cache(term_styled_ostream_t stream)514 match_and_cache (term_styled_ostream_t stream)
515 {
516 attributes_t *attr = match (stream);
517 if (hash_insert_entry (&stream->cache,
518 stream->curr_classes, stream->curr_classes_length,
519 attr) == NULL)
520 abort ();
521 stream->curr_attr = attr;
522 }
523
524 static void
term_styled_ostream__begin_use_class(term_styled_ostream_t stream,const char * classname)525 term_styled_ostream__begin_use_class (term_styled_ostream_t stream,
526 const char *classname)
527 {
528 size_t classname_len;
529 char *p;
530 void *found;
531
532 if (classname[0] == '\0' || strchr (classname, ' ') != NULL)
533 /* Invalid classname argument. */
534 abort ();
535
536 /* Push the classname onto the classname list. */
537 classname_len = strlen (classname);
538 if (stream->curr_classes_length + 1 + classname_len + 1
539 > stream->curr_classes_allocated)
540 {
541 size_t new_allocated = stream->curr_classes_length + 1 + classname_len + 1;
542 if (new_allocated < 2 * stream->curr_classes_allocated)
543 new_allocated = 2 * stream->curr_classes_allocated;
544
545 stream->curr_classes = xrealloc (stream->curr_classes, new_allocated);
546 stream->curr_classes_allocated = new_allocated;
547 }
548 p = &stream->curr_classes[stream->curr_classes_length];
549 *p++ = ' ';
550 memcpy (p, classname, classname_len);
551 stream->curr_classes_length += 1 + classname_len;
552
553 /* Uodate stream->curr_attr. */
554 if (hash_find_entry (&stream->cache,
555 stream->curr_classes, stream->curr_classes_length,
556 &found) < 0)
557 match_and_cache (stream);
558 else
559 stream->curr_attr = (attributes_t *) found;
560 }
561
562 static void
term_styled_ostream__end_use_class(term_styled_ostream_t stream,const char * classname)563 term_styled_ostream__end_use_class (term_styled_ostream_t stream,
564 const char *classname)
565 {
566 char *p_end;
567 char *p_start;
568 char *p;
569 void *found;
570
571 if (stream->curr_classes_length == 0)
572 /* No matching call to begin_use_class. */
573 abort ();
574
575 /* Remove the trailing classname. */
576 p_end = &stream->curr_classes[stream->curr_classes_length];
577 p = p_end;
578 while (*--p != ' ')
579 ;
580 p_start = p + 1;
581 if (!(p_end - p_start == strlen (classname)
582 && memcmp (p_start, classname, p_end - p_start) == 0))
583 /* The match ing call to begin_use_class used a different classname. */
584 abort ();
585 stream->curr_classes_length = p - stream->curr_classes;
586
587 /* Update stream->curr_attr. */
588 if (hash_find_entry (&stream->cache,
589 stream->curr_classes, stream->curr_classes_length,
590 &found) < 0)
591 abort ();
592 stream->curr_attr = (attributes_t *) found;
593 }
594
595 static const char *
term_styled_ostream__get_hyperlink_ref(term_styled_ostream_t stream)596 term_styled_ostream__get_hyperlink_ref (term_styled_ostream_t stream)
597 {
598 return term_ostream_get_hyperlink_ref (stream->destination);
599 }
600
601 static const char *
term_styled_ostream__get_hyperlink_id(term_styled_ostream_t stream)602 term_styled_ostream__get_hyperlink_id (term_styled_ostream_t stream)
603 {
604 return term_ostream_get_hyperlink_id (stream->destination);
605 }
606
607 static void
term_styled_ostream__set_hyperlink(term_styled_ostream_t stream,const char * ref,const char * id)608 term_styled_ostream__set_hyperlink (term_styled_ostream_t stream,
609 const char *ref, const char *id)
610 {
611 term_ostream_set_hyperlink (stream->destination, ref, id);
612 }
613
614 static void
term_styled_ostream__flush_to_current_style(term_styled_ostream_t stream)615 term_styled_ostream__flush_to_current_style (term_styled_ostream_t stream)
616 {
617 term_ostream_set_color (stream->destination, stream->curr_attr->color);
618 term_ostream_set_bgcolor (stream->destination, stream->curr_attr->bgcolor);
619 term_ostream_set_weight (stream->destination, stream->curr_attr->weight);
620 term_ostream_set_posture (stream->destination, stream->curr_attr->posture);
621 term_ostream_set_underline (stream->destination, stream->curr_attr->underline);
622
623 term_ostream_flush_to_current_style (stream->destination);
624 }
625
626 /* Constructor. */
627
628 term_styled_ostream_t
term_styled_ostream_create(int fd,const char * filename,ttyctl_t tty_control,const char * css_filename)629 term_styled_ostream_create (int fd, const char *filename, ttyctl_t tty_control,
630 const char *css_filename)
631 {
632 term_styled_ostream_t stream;
633 CRStyleSheet *css_file_contents;
634
635 /* If css_filename is NULL, no styling is desired. The code below would end
636 up returning NULL anyway. But it's better to not rely on such details of
637 libcroco behaviour. */
638 if (css_filename == NULL)
639 return NULL;
640
641 stream = XMALLOC (struct term_styled_ostream_representation);
642
643 stream->base.base.vtable = &term_styled_ostream_vtable;
644 stream->destination = term_ostream_create (fd, filename, tty_control);
645
646 if (cr_om_parser_simply_parse_file ((const guchar *) css_filename,
647 CR_UTF_8, /* CR_AUTO is not supported */
648 &css_file_contents) != CR_OK)
649 {
650 term_ostream_free (stream->destination);
651 free (stream);
652 return NULL;
653 }
654 stream->css_document = cr_cascade_new (NULL, css_file_contents, NULL);
655 stream->css_engine = cr_sel_eng_new ();
656
657 stream->curr_classes_allocated = 60;
658 stream->curr_classes = XNMALLOC (stream->curr_classes_allocated, char);
659 stream->curr_classes_length = 0;
660
661 hash_init (&stream->cache, 10);
662
663 match_and_cache (stream);
664
665 return stream;
666 }
667
668 #line 669 "term-styled-ostream.c"
669
670 const struct term_styled_ostream_implementation term_styled_ostream_vtable =
671 {
672 term_styled_ostream_superclasses,
673 sizeof (term_styled_ostream_superclasses) / sizeof (term_styled_ostream_superclasses[0]),
674 sizeof (struct term_styled_ostream_representation),
675 term_styled_ostream__write_mem,
676 term_styled_ostream__flush,
677 term_styled_ostream__free,
678 term_styled_ostream__begin_use_class,
679 term_styled_ostream__end_use_class,
680 term_styled_ostream__get_hyperlink_ref,
681 term_styled_ostream__get_hyperlink_id,
682 term_styled_ostream__set_hyperlink,
683 term_styled_ostream__flush_to_current_style,
684 };
685
686 #if !HAVE_INLINE
687
688 /* Define the functions that invoke the methods. */
689
690 void
term_styled_ostream_write_mem(term_styled_ostream_t first_arg,const void * data,size_t len)691 term_styled_ostream_write_mem (term_styled_ostream_t first_arg, const void *data, size_t len)
692 {
693 const struct term_styled_ostream_implementation *vtable =
694 ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
695 vtable->write_mem (first_arg,data,len);
696 }
697
698 void
term_styled_ostream_flush(term_styled_ostream_t first_arg,ostream_flush_scope_t scope)699 term_styled_ostream_flush (term_styled_ostream_t first_arg, ostream_flush_scope_t scope)
700 {
701 const struct term_styled_ostream_implementation *vtable =
702 ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
703 vtable->flush (first_arg,scope);
704 }
705
706 void
term_styled_ostream_free(term_styled_ostream_t first_arg)707 term_styled_ostream_free (term_styled_ostream_t first_arg)
708 {
709 const struct term_styled_ostream_implementation *vtable =
710 ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
711 vtable->free (first_arg);
712 }
713
714 void
term_styled_ostream_begin_use_class(term_styled_ostream_t first_arg,const char * classname)715 term_styled_ostream_begin_use_class (term_styled_ostream_t first_arg, const char *classname)
716 {
717 const struct term_styled_ostream_implementation *vtable =
718 ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
719 vtable->begin_use_class (first_arg,classname);
720 }
721
722 void
term_styled_ostream_end_use_class(term_styled_ostream_t first_arg,const char * classname)723 term_styled_ostream_end_use_class (term_styled_ostream_t first_arg, const char *classname)
724 {
725 const struct term_styled_ostream_implementation *vtable =
726 ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
727 vtable->end_use_class (first_arg,classname);
728 }
729
730 const char *
term_styled_ostream_get_hyperlink_ref(term_styled_ostream_t first_arg)731 term_styled_ostream_get_hyperlink_ref (term_styled_ostream_t first_arg)
732 {
733 const struct term_styled_ostream_implementation *vtable =
734 ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
735 return vtable->get_hyperlink_ref (first_arg);
736 }
737
738 const char *
term_styled_ostream_get_hyperlink_id(term_styled_ostream_t first_arg)739 term_styled_ostream_get_hyperlink_id (term_styled_ostream_t first_arg)
740 {
741 const struct term_styled_ostream_implementation *vtable =
742 ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
743 return vtable->get_hyperlink_id (first_arg);
744 }
745
746 void
term_styled_ostream_set_hyperlink(term_styled_ostream_t first_arg,const char * ref,const char * id)747 term_styled_ostream_set_hyperlink (term_styled_ostream_t first_arg, const char *ref, const char *id)
748 {
749 const struct term_styled_ostream_implementation *vtable =
750 ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
751 vtable->set_hyperlink (first_arg,ref,id);
752 }
753
754 void
term_styled_ostream_flush_to_current_style(term_styled_ostream_t first_arg)755 term_styled_ostream_flush_to_current_style (term_styled_ostream_t first_arg)
756 {
757 const struct term_styled_ostream_implementation *vtable =
758 ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
759 vtable->flush_to_current_style (first_arg);
760 }
761
762 #endif
763