• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/gettext-0.17/gettext-tools/gnulib-lib/
1/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
2
3#line 1 "term-styled-ostream.oo.c"
4/* Output stream for CSS styled text, producing ANSI escape sequences.
5   Copyright (C) 2006-2007 Free Software Foundation, Inc.
6   Written by Bruno Haible <bruno@clisp.org>, 2006.
7
8   This program is free software: you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21#include <config.h>
22
23/* Specification.  */
24#include "term-styled-ostream.h"
25
26#include <stdlib.h>
27
28#include <cr-om-parser.h>
29#include <cr-sel-eng.h>
30#include <cr-style.h>
31#include <cr-rgb.h>
32/* <cr-fonts.h> has a broken double-inclusion guard in libcroco-0.6.1.  */
33#ifndef __CR_FONTS_H__
34# include <cr-fonts.h>
35#endif
36#include <cr-string.h>
37
38#include "term-ostream.h"
39#include "hash.h"
40#include "xalloc.h"
41
42
43/* CSS matching works as follows:
44   Suppose we have an element inside class "header" inside class "table".
45   We pretend to have an XML tree that looks like this:
46
47     (root)
48       +----table
49              +----header
50
51   For each of these XML nodes, the CSS matching engine can report the
52   matching CSS declarations.  We extract the CSS property values that
53   matter for terminal styling and cache them.  */
54
55/* Attributes that can be set on a character.  */
56typedef struct
57{
58  term_color_t     color;
59  term_color_t     bgcolor;
60  term_weight_t    weight;
61  term_posture_t   posture;
62  term_underline_t underline;
63} attributes_t;
64
65#line 66 "term-styled-ostream.c"
66#if !IS_CPLUSPLUS
67#define term_styled_ostream_representation any_ostream_representation
68#endif
69#include "term_styled_ostream.priv.h"
70
71const typeinfo_t term_styled_ostream_typeinfo = { "term_styled_ostream" };
72
73static 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
82static void
83term_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
95static void
96term_styled_ostream__flush (term_styled_ostream_t stream)
97{
98  term_ostream_flush (stream->destination);
99}
100
101static void
102term_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
128enum 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
138typedef 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.  */
146static CRXStyle *
147crx_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.  */
167static void
168crx_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.  */
175static enum CRStatus
176crx_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
278static term_color_t
279style_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
310static term_weight_t
311style_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
367static term_posture_t
368style_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
390static term_underline_t
391style_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.  */
416static attributes_t *
417match (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.  */
513static void
514match_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
524static void
525term_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
562static void
563term_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/* Constructor.  */
596
597term_styled_ostream_t
598term_styled_ostream_create (int fd, const char *filename,
599			    const char *css_filename)
600{
601  term_styled_ostream_t stream =
602    XMALLOC (struct term_styled_ostream_representation);
603  CRStyleSheet *css_file_contents;
604
605  stream->base.base.vtable = &term_styled_ostream_vtable;
606  stream->destination = term_ostream_create (fd, filename);
607
608  if (cr_om_parser_simply_parse_file ((const guchar *) css_filename,
609				      CR_UTF_8, /* CR_AUTO is not supported */
610				      &css_file_contents) != CR_OK)
611    {
612      term_ostream_free (stream->destination);
613      free (stream);
614      return NULL;
615    }
616  stream->css_document = cr_cascade_new (NULL, css_file_contents, NULL);
617  stream->css_engine = cr_sel_eng_new ();
618
619  stream->curr_classes_allocated = 60;
620  stream->curr_classes = XNMALLOC (stream->curr_classes_allocated, char);
621  stream->curr_classes_length = 0;
622
623  hash_init (&stream->cache, 10);
624
625  match_and_cache (stream);
626
627  return stream;
628}
629
630#line 631 "term-styled-ostream.c"
631
632const struct term_styled_ostream_implementation term_styled_ostream_vtable =
633{
634  term_styled_ostream_superclasses,
635  sizeof (term_styled_ostream_superclasses) / sizeof (term_styled_ostream_superclasses[0]),
636  sizeof (struct term_styled_ostream_representation),
637  term_styled_ostream__write_mem,
638  term_styled_ostream__flush,
639  term_styled_ostream__free,
640  term_styled_ostream__begin_use_class,
641  term_styled_ostream__end_use_class,
642};
643
644#if !HAVE_INLINE
645
646/* Define the functions that invoke the methods.  */
647
648void
649term_styled_ostream_write_mem (term_styled_ostream_t first_arg, const void *data, size_t len)
650{
651  const struct term_styled_ostream_implementation *vtable =
652    ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
653  vtable->write_mem (first_arg,data,len);
654}
655
656void
657term_styled_ostream_flush (term_styled_ostream_t first_arg)
658{
659  const struct term_styled_ostream_implementation *vtable =
660    ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
661  vtable->flush (first_arg);
662}
663
664void
665term_styled_ostream_free (term_styled_ostream_t first_arg)
666{
667  const struct term_styled_ostream_implementation *vtable =
668    ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
669  vtable->free (first_arg);
670}
671
672void
673term_styled_ostream_begin_use_class (term_styled_ostream_t first_arg, const char *classname)
674{
675  const struct term_styled_ostream_implementation *vtable =
676    ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
677  vtable->begin_use_class (first_arg,classname);
678}
679
680void
681term_styled_ostream_end_use_class (term_styled_ostream_t first_arg, const char *classname)
682{
683  const struct term_styled_ostream_implementation *vtable =
684    ((struct term_styled_ostream_representation_header *) (struct term_styled_ostream_representation *) first_arg)->vtable;
685  vtable->end_use_class (first_arg,classname);
686}
687
688#endif
689