• 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-ostream.oo.c"
4/* Output stream for attributed 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-ostream.h"
25
26#include <assert.h>
27#include <errno.h>
28#include <signal.h>
29#include <stdbool.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include "error.h"
34#include "fatal-signal.h"
35#include "full-write.h"
36#include "terminfo.h"
37#include "xalloc.h"
38#include "xsize.h"
39#include "gettext.h"
40
41#define _(str) gettext (str)
42
43#if HAVE_TPARAM
44/* GNU termcap's tparam() function requires a buffer argument.  Make it so
45   large that there is no risk that tparam() needs to call malloc().  */
46static char tparambuf[100];
47/* Define tparm in terms of tparam.  In the scope of this file, it is called
48   with at most one argument after the string.  */
49# define tparm(str, arg1) \
50  tparam (str, tparambuf, sizeof (tparambuf), arg1)
51#endif
52
53#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
54
55
56/* =========================== Color primitives =========================== */
57
58/* A color in RGB format.  */
59typedef struct
60{
61  unsigned int red   : 8; /* range 0..255 */
62  unsigned int green : 8; /* range 0..255 */
63  unsigned int blue  : 8; /* range 0..255 */
64} rgb_t;
65
66/* A color in HSV (a.k.a. HSB) format.  */
67typedef struct
68{
69  float hue;        /* normalized to interval [0,6) */
70  float saturation; /* normalized to interval [0,1] */
71  float brightness; /* a.k.a. value, normalized to interval [0,1] */
72} hsv_t;
73
74/* Conversion of a color in RGB to HSV format.  */
75static void
76rgb_to_hsv (rgb_t c, hsv_t *result)
77{
78  unsigned int r = c.red;
79  unsigned int g = c.green;
80  unsigned int b = c.blue;
81
82  if (r > g)
83    {
84      if (b > r)
85	{
86	  /* b > r > g, so max = b, min = g */
87	  result->hue = 4.0f + (float) (r - g) / (float) (b - g);
88	  result->saturation = 1.0f - (float) g / (float) b;
89	  result->brightness = (float) b / 255.0f;
90	}
91      else if (b <= g)
92	{
93	  /* r > g >= b, so max = r, min = b */
94	  result->hue = 0.0f + (float) (g - b) / (float) (r - b);
95	  result->saturation = 1.0f - (float) b / (float) r;
96	  result->brightness = (float) r / 255.0f;
97	}
98      else
99	{
100	  /* r >= b > g, so max = r, min = g */
101	  result->hue = 6.0f - (float) (b - g) / (float) (r - g);
102	  result->saturation = 1.0f - (float) g / (float) r;
103	  result->brightness = (float) r / 255.0f;
104	}
105    }
106  else
107    {
108      if (b > g)
109	{
110	  /* b > g >= r, so max = b, min = r */
111	  result->hue = 4.0f - (float) (g - r) / (float) (b - r);
112	  result->saturation = 1.0f - (float) r / (float) b;
113	  result->brightness = (float) b / 255.0f;
114	}
115      else if (b < r)
116	{
117	  /* g >= r > b, so max = g, min = b */
118	  result->hue = 2.0f - (float) (r - b) / (float) (g - b);
119	  result->saturation = 1.0f - (float) b / (float) g;
120	  result->brightness = (float) g / 255.0f;
121	}
122      else if (g > r)
123	{
124	  /* g >= b >= r, g > r, so max = g, min = r */
125	  result->hue = 2.0f + (float) (b - r) / (float) (g - r);
126	  result->saturation = 1.0f - (float) r / (float) g;
127	  result->brightness = (float) g / 255.0f;
128	}
129      else
130	{
131	  /* r = g = b.  A grey color.  */
132	  result->hue = 0; /* arbitrary */
133	  result->saturation = 0;
134	  result->brightness = (float) r / 255.0f;
135	}
136    }
137}
138
139/* Square of distance of two colors.  */
140static float
141color_distance (const hsv_t *color1, const hsv_t *color2)
142{
143#if 0
144  /* Formula taken from "John Smith: Color Similarity",
145       http://www.ctr.columbia.edu/~jrsmith/html/pubs/acmmm96/node8.html.  */
146  float angle1 = color1->hue * 1.04719755f; /* normalize to [0,2��] */
147  float angle2 = color2->hue * 1.04719755f; /* normalize to [0,2��] */
148  float delta_x = color1->saturation * cosf (angle1)
149		  - color2->saturation * cosf (angle2);
150  float delta_y = color1->saturation * sinf (angle1)
151		  - color2->saturation * sinf (angle2);
152  float delta_v = color1->brightness
153		  - color2->brightness;
154
155  return delta_x * delta_x + delta_y * delta_y + delta_v * delta_v;
156#else
157  /* Formula that considers hue differences with more weight than saturation
158     or brightness differences, like the human eye does.  */
159  float delta_hue =
160    (color1->hue >= color2->hue
161     ? (color1->hue - color2->hue >= 3.0f
162	? 6.0f + color2->hue - color1->hue
163	: color1->hue - color2->hue)
164     : (color2->hue - color1->hue >= 3.0f
165	? 6.0f + color1->hue - color2->hue
166	: color2->hue - color1->hue));
167  float min_saturation =
168    (color1->saturation < color2->saturation
169     ? color1->saturation
170     : color2->saturation);
171  float delta_saturation = color1->saturation - color2->saturation;
172  float delta_brightness = color1->brightness - color2->brightness;
173
174  return delta_hue * delta_hue * min_saturation
175	 + delta_saturation * delta_saturation * 0.2f
176	 + delta_brightness * delta_brightness * 0.8f;
177#endif
178}
179
180/* Return the index of the color in a color table that is nearest to a given
181   color.  */
182static unsigned int
183nearest_color (rgb_t given, const rgb_t *table, unsigned int table_size)
184{
185  hsv_t given_hsv;
186  unsigned int best_index;
187  float best_distance;
188  unsigned int i;
189
190  assert (table_size > 0);
191
192  rgb_to_hsv (given, &given_hsv);
193
194  best_index = 0;
195  best_distance = 1000000.0f;
196  for (i = 0; i < table_size; i++)
197    {
198      hsv_t i_hsv;
199
200      rgb_to_hsv (table[i], &i_hsv);
201
202      /* Avoid converting a color to grey, or fading out a color too much.  */
203      if (i_hsv.saturation > given_hsv.saturation * 0.5f)
204	{
205	  float distance = color_distance (&given_hsv, &i_hsv);
206	  if (distance < best_distance)
207	    {
208	      best_index = i;
209	      best_distance = distance;
210	    }
211	}
212    }
213
214#if 0 /* Debugging code */
215  hsv_t best_hsv;
216  rgb_to_hsv (table[best_index], &best_hsv);
217  fprintf (stderr, "nearest: (%d,%d,%d) = (%f,%f,%f)\n    -> (%f,%f,%f) = (%d,%d,%d)\n",
218                   given.red, given.green, given.blue,
219                   (double)given_hsv.hue, (double)given_hsv.saturation, (double)given_hsv.brightness,
220                   (double)best_hsv.hue, (double)best_hsv.saturation, (double)best_hsv.brightness,
221                   table[best_index].red, table[best_index].green, table[best_index].blue);
222#endif
223
224  return best_index;
225}
226
227/* The luminance of a color.  This is the brightness of the color, as it
228   appears to the human eye.  This must be used in color to grey conversion.  */
229static float
230color_luminance (int r, int g, int b)
231{
232  /* Use the luminance model used by NTSC and JPEG.
233     Taken from http://www.fho-emden.de/~hoffmann/gray10012001.pdf .
234     No need to care about rounding errors leading to luminance > 1;
235     this cannot happen.  */
236  return (0.299f * r + 0.587f * g + 0.114f * b) / 255.0f;
237}
238
239
240/* ============================= Color models ============================= */
241
242/* The color model used by the terminal.  */
243typedef enum
244{
245  cm_monochrome,	/* No colors.  */
246  cm_common8,		/* Usual terminal with at least 8 colors.  */
247  cm_xterm8,		/* TERM=xterm, with 8 colors.  */
248  cm_xterm16,		/* TERM=xterm-16color, with 16 colors.  */
249  cm_xterm88,		/* TERM=xterm-88color, with 88 colors.  */
250  cm_xterm256		/* TERM=xterm-256color, with 256 colors.  */
251} colormodel_t;
252
253/* ----------------------- cm_monochrome color model ----------------------- */
254
255/* A non-default color index doesn't exist in this color model.  */
256static inline term_color_t
257rgb_to_color_monochrome ()
258{
259  return COLOR_DEFAULT;
260}
261
262/* ------------------------ cm_common8 color model ------------------------ */
263
264/* A non-default color index is in the range 0..7.
265                       RGB components
266   COLOR_BLACK         000
267   COLOR_BLUE          001
268   COLOR_GREEN         010
269   COLOR_CYAN          011
270   COLOR_RED           100
271   COLOR_MAGENTA       101
272   COLOR_YELLOW        110
273   COLOR_WHITE         111 */
274static const rgb_t colors_of_common8[8] =
275{
276  /* R    G    B        grey  index */
277  {   0,   0,   0 }, /* 0.000   0 */
278  {   0,   0, 255 },
279  {   0, 255,   0 },
280  {   0, 255, 255 },
281  { 255,   0,   0 },
282  { 255,   0, 255 },
283  { 255, 255,   0 },
284  { 255, 255, 255 }  /* 1.000   7 */
285};
286
287static inline term_color_t
288rgb_to_color_common8 (int r, int g, int b)
289{
290  rgb_t color;
291  hsv_t hsv;
292
293  color.red = r; color.green = g; color.blue = b;
294  rgb_to_hsv (color, &hsv);
295
296  if (hsv.saturation < 0.065f)
297    {
298      /* Greyscale approximation.  */
299      float luminance = color_luminance (r, g, b);
300      if (luminance < 0.500f)
301	return 0;
302      else
303	return 7;
304    }
305  else
306    /* Color approximation.  */
307    return nearest_color (color, colors_of_common8, 8);
308}
309
310/* Convert a cm_common8 color in RGB encoding to BGR encoding.
311   See the ncurses terminfo(5) manual page, section "Color Handling", for an
312   explanation why this is needed.  */
313static inline int
314color_bgr (term_color_t color)
315{
316  return ((color & 4) >> 2) | (color & 2) | ((color & 1) << 2);
317}
318
319/* ------------------------- cm_xterm8 color model ------------------------- */
320
321/* A non-default color index is in the range 0..7.
322                       BGR components
323   COLOR_BLACK         000
324   COLOR_RED           001
325   COLOR_GREEN         010
326   COLOR_YELLOW        011
327   COLOR_BLUE          100
328   COLOR_MAGENTA       101
329   COLOR_CYAN          110
330   COLOR_WHITE         111 */
331static const rgb_t colors_of_xterm8[8] =
332{
333  /* The real xterm's colors are dimmed; assume full-brightness instead.  */
334  /* R    G    B        grey  index */
335  {   0,   0,   0 }, /* 0.000   0 */
336  { 255,   0,   0 },
337  {   0, 255,   0 },
338  { 255, 255,   0 },
339  {   0,   0, 255 },
340  { 255,   0, 255 },
341  {   0, 255, 255 },
342  { 255, 255, 255 }  /* 1.000   7 */
343};
344
345static inline term_color_t
346rgb_to_color_xterm8 (int r, int g, int b)
347{
348  rgb_t color;
349  hsv_t hsv;
350
351  color.red = r; color.green = g; color.blue = b;
352  rgb_to_hsv (color, &hsv);
353
354  if (hsv.saturation < 0.065f)
355    {
356      /* Greyscale approximation.  */
357      float luminance = color_luminance (r, g, b);
358      if (luminance < 0.500f)
359	return 0;
360      else
361	return 7;
362    }
363  else
364    /* Color approximation.  */
365    return nearest_color (color, colors_of_xterm8, 8);
366}
367
368/* ------------------------ cm_xterm16 color model ------------------------ */
369
370/* A non-default color index is in the range 0..15.
371   The RGB values come from xterm's XTerm-col.ad.  */
372static const rgb_t colors_of_xterm16[16] =
373{
374  /* R    G    B        grey  index */
375  {   0,   0,   0 }, /* 0.000   0 */
376  { 205,   0,   0 },
377  {   0, 205,   0 },
378  { 205, 205,   0 },
379  {   0,   0, 205 },
380  { 205,   0, 205 },
381  {   0, 205, 205 },
382  { 229, 229, 229 }, /* 0.898   7 */
383  {  77,  77,  77 }, /* 0.302   8 */
384  { 255,   0,   0 },
385  {   0, 255,   0 },
386  { 255, 255,   0 },
387  {   0,   0, 255 },
388  { 255,   0, 255 },
389  {   0, 255, 255 },
390  { 255, 255, 255 }  /* 1.000  15 */
391};
392
393static inline term_color_t
394rgb_to_color_xterm16 (int r, int g, int b)
395{
396  rgb_t color;
397  hsv_t hsv;
398
399  color.red = r; color.green = g; color.blue = b;
400  rgb_to_hsv (color, &hsv);
401
402  if (hsv.saturation < 0.065f)
403    {
404      /* Greyscale approximation.  */
405      float luminance = color_luminance (r, g, b);
406      if (luminance < 0.151f)
407	return 0;
408      else if (luminance < 0.600f)
409	return 8;
410      else if (luminance < 0.949f)
411	return 7;
412      else
413	return 15;
414    }
415  else
416    /* Color approximation.  */
417    return nearest_color (color, colors_of_xterm16, 16);
418}
419
420/* ------------------------ cm_xterm88 color model ------------------------ */
421
422/* A non-default color index is in the range 0..87.
423   Colors 0..15 are the same as in the cm_xterm16 color model.
424   Colors 16..87 are defined in xterm's 88colres.h.  */
425
426static const rgb_t colors_of_xterm88[88] =
427{
428  /* R    G    B        grey  index */
429  {   0,   0,   0 }, /* 0.000   0 */
430  { 205,   0,   0 },
431  {   0, 205,   0 },
432  { 205, 205,   0 },
433  {   0,   0, 205 },
434  { 205,   0, 205 },
435  {   0, 205, 205 },
436  { 229, 229, 229 }, /* 0.898   7 */
437  {  77,  77,  77 }, /* 0.302   8 */
438  { 255,   0,   0 },
439  {   0, 255,   0 },
440  { 255, 255,   0 },
441  {   0,   0, 255 },
442  { 255,   0, 255 },
443  {   0, 255, 255 },
444  { 255, 255, 255 }, /* 1.000  15 */
445  {   0,   0,   0 }, /* 0.000  16 */
446  {   0,   0, 139 },
447  {   0,   0, 205 },
448  {   0,   0, 255 },
449  {   0, 139,   0 },
450  {   0, 139, 139 },
451  {   0, 139, 205 },
452  {   0, 139, 255 },
453  {   0, 205,   0 },
454  {   0, 205, 139 },
455  {   0, 205, 205 },
456  {   0, 205, 255 },
457  {   0, 255,   0 },
458  {   0, 255, 139 },
459  {   0, 255, 205 },
460  {   0, 255, 255 },
461  { 139,   0,   0 },
462  { 139,   0, 139 },
463  { 139,   0, 205 },
464  { 139,   0, 255 },
465  { 139, 139,   0 },
466  { 139, 139, 139 }, /* 0.545  37 */
467  { 139, 139, 205 },
468  { 139, 139, 255 },
469  { 139, 205,   0 },
470  { 139, 205, 139 },
471  { 139, 205, 205 },
472  { 139, 205, 255 },
473  { 139, 255,   0 },
474  { 139, 255, 139 },
475  { 139, 255, 205 },
476  { 139, 255, 255 },
477  { 205,   0,   0 },
478  { 205,   0, 139 },
479  { 205,   0, 205 },
480  { 205,   0, 255 },
481  { 205, 139,   0 },
482  { 205, 139, 139 },
483  { 205, 139, 205 },
484  { 205, 139, 255 },
485  { 205, 205,   0 },
486  { 205, 205, 139 },
487  { 205, 205, 205 }, /* 0.804  58 */
488  { 205, 205, 255 },
489  { 205, 255,   0 },
490  { 205, 255, 139 },
491  { 205, 255, 205 },
492  { 205, 255, 255 },
493  { 255,   0,   0 },
494  { 255,   0, 139 },
495  { 255,   0, 205 },
496  { 255,   0, 255 },
497  { 255, 139,   0 },
498  { 255, 139, 139 },
499  { 255, 139, 205 },
500  { 255, 139, 255 },
501  { 255, 205,   0 },
502  { 255, 205, 139 },
503  { 255, 205, 205 },
504  { 255, 205, 255 },
505  { 255, 255,   0 },
506  { 255, 255, 139 },
507  { 255, 255, 205 },
508  { 255, 255, 255 }, /* 1.000  79 */
509  {  46,  46,  46 }, /* 0.180  80 */
510  {  92,  92,  92 }, /* 0.361  81 */
511  { 115, 115, 115 }, /* 0.451  82 */
512  { 139, 139, 139 }, /* 0.545  83 */
513  { 162, 162, 162 }, /* 0.635  84 */
514  { 185, 185, 185 }, /* 0.725  85 */
515  { 208, 208, 208 }, /* 0.816  86 */
516  { 231, 231, 231 }  /* 0.906  87 */
517};
518
519static inline term_color_t
520rgb_to_color_xterm88 (int r, int g, int b)
521{
522  rgb_t color;
523  hsv_t hsv;
524
525  color.red = r; color.green = g; color.blue = b;
526  rgb_to_hsv (color, &hsv);
527
528  if (hsv.saturation < 0.065f)
529    {
530      /* Greyscale approximation.  */
531      float luminance = color_luminance (r, g, b);
532      if (luminance < 0.090f)
533	return 0;
534      else if (luminance < 0.241f)
535	return 80;
536      else if (luminance < 0.331f)
537	return 8;
538      else if (luminance < 0.406f)
539	return 81;
540      else if (luminance < 0.498f)
541	return 82;
542      else if (luminance < 0.585f)
543	return 37;
544      else if (luminance < 0.680f)
545	return 84;
546      else if (luminance < 0.764f)
547	return 85;
548      else if (luminance < 0.810f)
549	return 58;
550      else if (luminance < 0.857f)
551	return 86;
552      else if (luminance < 0.902f)
553	return 7;
554      else if (luminance < 0.953f)
555	return 87;
556      else
557	return 15;
558    }
559  else
560    /* Color approximation.  */
561    return nearest_color (color, colors_of_xterm88, 88);
562}
563
564/* ------------------------ cm_xterm256 color model ------------------------ */
565
566/* A non-default color index is in the range 0..255.
567   Colors 0..15 are the same as in the cm_xterm16 color model.
568   Colors 16..255 are defined in xterm's 256colres.h.  */
569
570static const rgb_t colors_of_xterm256[256] =
571{
572  /* R    G    B        grey  index */
573  {   0,   0,   0 }, /* 0.000   0 */
574  { 205,   0,   0 },
575  {   0, 205,   0 },
576  { 205, 205,   0 },
577  {   0,   0, 205 },
578  { 205,   0, 205 },
579  {   0, 205, 205 },
580  { 229, 229, 229 }, /* 0.898   7 */
581  {  77,  77,  77 }, /* 0.302   8 */
582  { 255,   0,   0 },
583  {   0, 255,   0 },
584  { 255, 255,   0 },
585  {   0,   0, 255 },
586  { 255,   0, 255 },
587  {   0, 255, 255 },
588  { 255, 255, 255 }, /* 1.000  15 */
589  {   0,   0,   0 }, /* 0.000  16 */
590  {   0,   0,  42 },
591  {   0,   0,  85 },
592  {   0,   0, 127 },
593  {   0,   0, 170 },
594  {   0,   0, 212 },
595  {   0,  42,   0 },
596  {   0,  42,  42 },
597  {   0,  42,  85 },
598  {   0,  42, 127 },
599  {   0,  42, 170 },
600  {   0,  42, 212 },
601  {   0,  85,   0 },
602  {   0,  85,  42 },
603  {   0,  85,  85 },
604  {   0,  85, 127 },
605  {   0,  85, 170 },
606  {   0,  85, 212 },
607  {   0, 127,   0 },
608  {   0, 127,  42 },
609  {   0, 127,  85 },
610  {   0, 127, 127 },
611  {   0, 127, 170 },
612  {   0, 127, 212 },
613  {   0, 170,   0 },
614  {   0, 170,  42 },
615  {   0, 170,  85 },
616  {   0, 170, 127 },
617  {   0, 170, 170 },
618  {   0, 170, 212 },
619  {   0, 212,   0 },
620  {   0, 212,  42 },
621  {   0, 212,  85 },
622  {   0, 212, 127 },
623  {   0, 212, 170 },
624  {   0, 212, 212 },
625  {  42,   0,   0 },
626  {  42,   0,  42 },
627  {  42,   0,  85 },
628  {  42,   0, 127 },
629  {  42,   0, 170 },
630  {  42,   0, 212 },
631  {  42,  42,   0 },
632  {  42,  42,  42 }, /* 0.165  59 */
633  {  42,  42,  85 },
634  {  42,  42, 127 },
635  {  42,  42, 170 },
636  {  42,  42, 212 },
637  {  42,  85,   0 },
638  {  42,  85,  42 },
639  {  42,  85,  85 },
640  {  42,  85, 127 },
641  {  42,  85, 170 },
642  {  42,  85, 212 },
643  {  42, 127,   0 },
644  {  42, 127,  42 },
645  {  42, 127,  85 },
646  {  42, 127, 127 },
647  {  42, 127, 170 },
648  {  42, 127, 212 },
649  {  42, 170,   0 },
650  {  42, 170,  42 },
651  {  42, 170,  85 },
652  {  42, 170, 127 },
653  {  42, 170, 170 },
654  {  42, 170, 212 },
655  {  42, 212,   0 },
656  {  42, 212,  42 },
657  {  42, 212,  85 },
658  {  42, 212, 127 },
659  {  42, 212, 170 },
660  {  42, 212, 212 },
661  {  85,   0,   0 },
662  {  85,   0,  42 },
663  {  85,   0,  85 },
664  {  85,   0, 127 },
665  {  85,   0, 170 },
666  {  85,   0, 212 },
667  {  85,  42,   0 },
668  {  85,  42,  42 },
669  {  85,  42,  85 },
670  {  85,  42, 127 },
671  {  85,  42, 170 },
672  {  85,  42, 212 },
673  {  85,  85,   0 },
674  {  85,  85,  42 },
675  {  85,  85,  85 }, /* 0.333 102 */
676  {  85,  85, 127 },
677  {  85,  85, 170 },
678  {  85,  85, 212 },
679  {  85, 127,   0 },
680  {  85, 127,  42 },
681  {  85, 127,  85 },
682  {  85, 127, 127 },
683  {  85, 127, 170 },
684  {  85, 127, 212 },
685  {  85, 170,   0 },
686  {  85, 170,  42 },
687  {  85, 170,  85 },
688  {  85, 170, 127 },
689  {  85, 170, 170 },
690  {  85, 170, 212 },
691  {  85, 212,   0 },
692  {  85, 212,  42 },
693  {  85, 212,  85 },
694  {  85, 212, 127 },
695  {  85, 212, 170 },
696  {  85, 212, 212 },
697  { 127,   0,   0 },
698  { 127,   0,  42 },
699  { 127,   0,  85 },
700  { 127,   0, 127 },
701  { 127,   0, 170 },
702  { 127,   0, 212 },
703  { 127,  42,   0 },
704  { 127,  42,  42 },
705  { 127,  42,  85 },
706  { 127,  42, 127 },
707  { 127,  42, 170 },
708  { 127,  42, 212 },
709  { 127,  85,   0 },
710  { 127,  85,  42 },
711  { 127,  85,  85 },
712  { 127,  85, 127 },
713  { 127,  85, 170 },
714  { 127,  85, 212 },
715  { 127, 127,   0 },
716  { 127, 127,  42 },
717  { 127, 127,  85 },
718  { 127, 127, 127 }, /* 0.498 145 */
719  { 127, 127, 170 },
720  { 127, 127, 212 },
721  { 127, 170,   0 },
722  { 127, 170,  42 },
723  { 127, 170,  85 },
724  { 127, 170, 127 },
725  { 127, 170, 170 },
726  { 127, 170, 212 },
727  { 127, 212,   0 },
728  { 127, 212,  42 },
729  { 127, 212,  85 },
730  { 127, 212, 127 },
731  { 127, 212, 170 },
732  { 127, 212, 212 },
733  { 170,   0,   0 },
734  { 170,   0,  42 },
735  { 170,   0,  85 },
736  { 170,   0, 127 },
737  { 170,   0, 170 },
738  { 170,   0, 212 },
739  { 170,  42,   0 },
740  { 170,  42,  42 },
741  { 170,  42,  85 },
742  { 170,  42, 127 },
743  { 170,  42, 170 },
744  { 170,  42, 212 },
745  { 170,  85,   0 },
746  { 170,  85,  42 },
747  { 170,  85,  85 },
748  { 170,  85, 127 },
749  { 170,  85, 170 },
750  { 170,  85, 212 },
751  { 170, 127,   0 },
752  { 170, 127,  42 },
753  { 170, 127,  85 },
754  { 170, 127, 127 },
755  { 170, 127, 170 },
756  { 170, 127, 212 },
757  { 170, 170,   0 },
758  { 170, 170,  42 },
759  { 170, 170,  85 },
760  { 170, 170, 127 },
761  { 170, 170, 170 }, /* 0.667 188 */
762  { 170, 170, 212 },
763  { 170, 212,   0 },
764  { 170, 212,  42 },
765  { 170, 212,  85 },
766  { 170, 212, 127 },
767  { 170, 212, 170 },
768  { 170, 212, 212 },
769  { 212,   0,   0 },
770  { 212,   0,  42 },
771  { 212,   0,  85 },
772  { 212,   0, 127 },
773  { 212,   0, 170 },
774  { 212,   0, 212 },
775  { 212,  42,   0 },
776  { 212,  42,  42 },
777  { 212,  42,  85 },
778  { 212,  42, 127 },
779  { 212,  42, 170 },
780  { 212,  42, 212 },
781  { 212,  85,   0 },
782  { 212,  85,  42 },
783  { 212,  85,  85 },
784  { 212,  85, 127 },
785  { 212,  85, 170 },
786  { 212,  85, 212 },
787  { 212, 127,   0 },
788  { 212, 127,  42 },
789  { 212, 127,  85 },
790  { 212, 127, 127 },
791  { 212, 127, 170 },
792  { 212, 127, 212 },
793  { 212, 170,   0 },
794  { 212, 170,  42 },
795  { 212, 170,  85 },
796  { 212, 170, 127 },
797  { 212, 170, 170 },
798  { 212, 170, 212 },
799  { 212, 212,   0 },
800  { 212, 212,  42 },
801  { 212, 212,  85 },
802  { 212, 212, 127 },
803  { 212, 212, 170 },
804  { 212, 212, 212 }, /* 0.831 231 */
805  {   8,   8,   8 }, /* 0.031 232 */
806  {  18,  18,  18 }, /* 0.071 233 */
807  {  28,  28,  28 }, /* 0.110 234 */
808  {  38,  38,  38 }, /* 0.149 235 */
809  {  48,  48,  48 }, /* 0.188 236 */
810  {  58,  58,  58 }, /* 0.227 237 */
811  {  68,  68,  68 }, /* 0.267 238 */
812  {  78,  78,  78 }, /* 0.306 239 */
813  {  88,  88,  88 }, /* 0.345 240 */
814  {  98,  98,  98 }, /* 0.384 241 */
815  { 108, 108, 108 }, /* 0.424 242 */
816  { 118, 118, 118 }, /* 0.463 243 */
817  { 128, 128, 128 }, /* 0.502 244 */
818  { 138, 138, 138 }, /* 0.541 245 */
819  { 148, 148, 148 }, /* 0.580 246 */
820  { 158, 158, 158 }, /* 0.620 247 */
821  { 168, 168, 168 }, /* 0.659 248 */
822  { 178, 178, 178 }, /* 0.698 249 */
823  { 188, 188, 188 }, /* 0.737 250 */
824  { 198, 198, 198 }, /* 0.776 251 */
825  { 208, 208, 208 }, /* 0.816 252 */
826  { 218, 218, 218 }, /* 0.855 253 */
827  { 228, 228, 228 }, /* 0.894 254 */
828  { 238, 238, 238 }  /* 0.933 255 */
829};
830
831static inline term_color_t
832rgb_to_color_xterm256 (int r, int g, int b)
833{
834  rgb_t color;
835  hsv_t hsv;
836
837  color.red = r; color.green = g; color.blue = b;
838  rgb_to_hsv (color, &hsv);
839
840  if (hsv.saturation < 0.065f)
841    {
842      /* Greyscale approximation.  */
843      float luminance = color_luminance (r, g, b);
844      if (luminance < 0.015f)
845	return 0;
846      else if (luminance < 0.051f)
847	return 232;
848      else if (luminance < 0.090f)
849	return 233;
850      else if (luminance < 0.129f)
851	return 234;
852      else if (luminance < 0.157f)
853	return 235;
854      else if (luminance < 0.177f)
855	return 59;
856      else if (luminance < 0.207f)
857	return 236;
858      else if (luminance < 0.247f)
859	return 237;
860      else if (luminance < 0.284f)
861	return 238;
862      else if (luminance < 0.304f)
863	return 8;
864      else if (luminance < 0.319f)
865	return 239;
866      else if (luminance < 0.339f)
867	return 102;
868      else if (luminance < 0.364f)
869	return 240;
870      else if (luminance < 0.404f)
871	return 241;
872      else if (luminance < 0.443f)
873	return 242;
874      else if (luminance < 0.480f)
875	return 243;
876      else if (luminance < 0.500f)
877	return 145;
878      else if (luminance < 0.521f)
879	return 244;
880      else if (luminance < 0.560f)
881	return 245;
882      else if (luminance < 0.600f)
883	return 246;
884      else if (luminance < 0.639f)
885	return 247;
886      else if (luminance < 0.663f)
887	return 248;
888      else if (luminance < 0.682f)
889	return 188;
890      else if (luminance < 0.717f)
891	return 249;
892      else if (luminance < 0.756f)
893	return 250;
894      else if (luminance < 0.796f)
895	return 251;
896      else if (luminance < 0.823f)
897	return 252;
898      else if (luminance < 0.843f)
899	return 231;
900      else if (luminance < 0.874f)
901	return 253;
902      else if (luminance < 0.896f)
903	return 254;
904      else if (luminance < 0.915f)
905	return 7;
906      else if (luminance < 0.966f)
907	return 255;
908      else
909	return 15;
910    }
911  else
912    /* Color approximation.  */
913    return nearest_color (color, colors_of_xterm256, 256);
914}
915
916
917/* ============================= attributes_t ============================= */
918
919/* ANSI C and ISO C99 6.7.2.1.(4) forbid use of bit fields for types other
920   than 'int' or 'unsigned int'.
921   On the other hand, C++ forbids conversion between enum types and integer
922   types without an explicit cast.  */
923#ifdef __cplusplus
924# define BITFIELD_TYPE(orig_type,integer_type) orig_type
925#else
926# define BITFIELD_TYPE(orig_type,integer_type) integer_type
927#endif
928
929/* Attributes that can be set on a character.  */
930typedef struct
931{
932  BITFIELD_TYPE(term_color_t,     signed int)   color     : 9;
933  BITFIELD_TYPE(term_color_t,     signed int)   bgcolor   : 9;
934  BITFIELD_TYPE(term_weight_t,    unsigned int) weight    : 1;
935  BITFIELD_TYPE(term_posture_t,   unsigned int) posture   : 1;
936  BITFIELD_TYPE(term_underline_t, unsigned int) underline : 1;
937} attributes_t;
938
939
940/* ============================ term_ostream_t ============================ */
941
942#line 943 "term-ostream.c"
943#if !IS_CPLUSPLUS
944#define term_ostream_representation any_ostream_representation
945#endif
946#include "term_ostream.priv.h"
947
948const typeinfo_t term_ostream_typeinfo = { "term_ostream" };
949
950static const typeinfo_t * const term_ostream_superclasses[] =
951  { term_ostream_SUPERCLASSES };
952
953#define super ostream_vtable
954
955#line 979 "term-ostream.oo.c"
956
957/* Simplify attributes, according to the terminal's capabilities.  */
958static attributes_t
959simplify_attributes (term_ostream_t stream, attributes_t attr)
960{
961  if ((attr.color != COLOR_DEFAULT || attr.bgcolor != COLOR_DEFAULT)
962      && stream->no_color_video > 0)
963    {
964      /* When colors and attributes can not be represented simultaneously,
965	 we give preference to the color.  */
966      if (stream->no_color_video & 2)
967	/* Colors conflict with underlining.  */
968	attr.underline = UNDERLINE_OFF;
969      if (stream->no_color_video & 32)
970	/* Colors conflict with bold weight.  */
971	attr.weight = WEIGHT_NORMAL;
972    }
973  if (!stream->supports_foreground)
974    attr.color = COLOR_DEFAULT;
975  if (!stream->supports_background)
976    attr.bgcolor = COLOR_DEFAULT;
977  if (!stream->supports_weight)
978    attr.weight = WEIGHT_DEFAULT;
979  if (!stream->supports_posture)
980    attr.posture = POSTURE_DEFAULT;
981  if (!stream->supports_underline)
982    attr.underline = UNDERLINE_DEFAULT;
983  return attr;
984}
985
986/* While a line is being output, we need to be careful to restore the
987   terminal's settings in case of a fatal signal or an exit() call.  */
988
989/* File descriptor to which out_char shall output escape sequences.  */
990static int out_fd = -1;
991
992/* Filename of out_fd.  */
993static const char *out_filename;
994
995/* Output a single char to out_fd.  Ignore errors.  */
996static int
997out_char_unchecked (int c)
998{
999  char bytes[1];
1000
1001  bytes[0] = (char)c;
1002  full_write (out_fd, bytes, 1);
1003  return 0;
1004}
1005
1006/* State that informs the exit handler what to do.  */
1007static const char *restore_colors;
1008static const char *restore_weight;
1009static const char *restore_posture;
1010static const char *restore_underline;
1011
1012/* The exit handler.  */
1013static void
1014restore (void)
1015{
1016  /* Only do something while some output was interrupted.  */
1017  if (out_fd >= 0)
1018    {
1019      if (restore_colors != NULL)
1020	tputs (restore_colors, 1, out_char_unchecked);
1021      if (restore_weight != NULL)
1022	tputs (restore_weight, 1, out_char_unchecked);
1023      if (restore_posture != NULL)
1024	tputs (restore_posture, 1, out_char_unchecked);
1025      if (restore_underline != NULL)
1026	tputs (restore_underline, 1, out_char_unchecked);
1027    }
1028}
1029
1030/* The list of signals whose default behaviour is to stop the program.  */
1031static int stopping_signals[] =
1032  {
1033#ifdef SIGTSTP
1034    SIGTSTP,
1035#endif
1036#ifdef SIGTTIN
1037    SIGTTIN,
1038#endif
1039#ifdef SIGTTOU
1040    SIGTTOU,
1041#endif
1042    0
1043  };
1044
1045#define num_stopping_signals (SIZEOF (stopping_signals) - 1)
1046
1047static sigset_t stopping_signal_set;
1048
1049static void
1050init_stopping_signal_set ()
1051{
1052  static bool stopping_signal_set_initialized = false;
1053  if (!stopping_signal_set_initialized)
1054    {
1055      size_t i;
1056
1057      sigemptyset (&stopping_signal_set);
1058      for (i = 0; i < num_stopping_signals; i++)
1059	sigaddset (&stopping_signal_set, stopping_signals[i]);
1060
1061      stopping_signal_set_initialized = true;
1062    }
1063}
1064
1065/* Temporarily delay the stopping signals.  */
1066static inline void
1067block_stopping_signals ()
1068{
1069  init_stopping_signal_set ();
1070  sigprocmask (SIG_BLOCK, &stopping_signal_set, NULL);
1071}
1072
1073/* Stop delaying the stopping signals.  */
1074static inline void
1075unblock_stopping_signals ()
1076{
1077  init_stopping_signal_set ();
1078  sigprocmask (SIG_UNBLOCK, &stopping_signal_set, NULL);
1079}
1080
1081/* Compare two sets of attributes for equality.  */
1082static inline bool
1083equal_attributes (attributes_t attr1, attributes_t attr2)
1084{
1085  return (attr1.color == attr2.color
1086	  && attr1.bgcolor == attr2.bgcolor
1087	  && attr1.weight == attr2.weight
1088	  && attr1.posture == attr2.posture
1089	  && attr1.underline == attr2.underline);
1090}
1091
1092/* Signal error after full_write failed.  */
1093static void
1094out_error ()
1095{
1096  error (EXIT_FAILURE, errno, _("error writing to %s"), out_filename);
1097}
1098
1099/* Output a single char to out_fd.  */
1100static int
1101out_char (int c)
1102{
1103  char bytes[1];
1104
1105  bytes[0] = (char)c;
1106  /* We have to write directly to the file descriptor, not to a buffer with
1107     the same destination, because of the padding and sleeping that tputs()
1108     does.  */
1109  if (full_write (out_fd, bytes, 1) < 1)
1110    out_error ();
1111  return 0;
1112}
1113
1114/* Output escape sequences to switch from OLD_ATTR to NEW_ATTR.  */
1115static void
1116out_attr_change (term_ostream_t stream,
1117		 attributes_t old_attr, attributes_t new_attr)
1118{
1119  bool cleared_attributes;
1120
1121  /* We don't know the default colors of the terminal.  The only way to switch
1122     back to a default color is to use stream->orig_pair.  */
1123  if ((new_attr.color == COLOR_DEFAULT && old_attr.color != COLOR_DEFAULT)
1124      || (new_attr.bgcolor == COLOR_DEFAULT && old_attr.bgcolor != COLOR_DEFAULT))
1125    {
1126      assert (stream->supports_foreground || stream->supports_background);
1127      tputs (stream->orig_pair, 1, out_char);
1128      old_attr.color = COLOR_DEFAULT;
1129      old_attr.bgcolor = COLOR_DEFAULT;
1130    }
1131
1132  /* To turn off WEIGHT_BOLD, the only way is to output the exit_attribute_mode
1133     sequence.  (With xterm, you can also do it with "Esc [ 0 m", but this
1134     escape sequence is not contained in the terminfo description.)  It may
1135     also clear the colors; this is the case e.g. when TERM="xterm" or
1136     TERM="ansi".
1137     To turn off UNDERLINE_ON, we can use the exit_underline_mode or the
1138     exit_attribute_mode sequence.  In the latter case, it will not only
1139     turn off UNDERLINE_ON, but also the other attributes, and possibly also
1140     the colors.
1141     To turn off POSTURE_ITALIC, we can use the exit_italics_mode or the
1142     exit_attribute_mode sequence.  Again, in the latter case, it will not
1143     only turn off POSTURE_ITALIC, but also the other attributes, and possibly
1144     also the colors.
1145     There is no point in setting an attribute just before emitting an
1146     escape sequence that may again turn off the attribute.  Therefore we
1147     proceed in two steps: First, clear the attributes that need to be
1148     cleared; then - taking into account that this may have cleared all
1149     attributes and all colors - set the colors and the attributes.
1150     The variable 'cleared_attributes' tells whether an escape sequence
1151     has been output that may have cleared all attributes and all color
1152     settings.  */
1153  cleared_attributes = false;
1154  if (old_attr.posture != POSTURE_NORMAL
1155      && new_attr.posture == POSTURE_NORMAL
1156      && stream->exit_italics_mode != NULL)
1157    {
1158      tputs (stream->exit_italics_mode, 1, out_char);
1159      old_attr.posture = POSTURE_NORMAL;
1160      cleared_attributes = true;
1161    }
1162  if (old_attr.underline != UNDERLINE_OFF
1163      && new_attr.underline == UNDERLINE_OFF
1164      && stream->exit_underline_mode != NULL)
1165    {
1166      tputs (stream->exit_underline_mode, 1, out_char);
1167      old_attr.underline = UNDERLINE_OFF;
1168      cleared_attributes = true;
1169    }
1170  if ((old_attr.weight != WEIGHT_NORMAL
1171       && new_attr.weight == WEIGHT_NORMAL)
1172      || (old_attr.posture != POSTURE_NORMAL
1173	  && new_attr.posture == POSTURE_NORMAL
1174	  /* implies stream->exit_italics_mode == NULL */)
1175      || (old_attr.underline != UNDERLINE_OFF
1176	  && new_attr.underline == UNDERLINE_OFF
1177	  /* implies stream->exit_underline_mode == NULL */))
1178    {
1179      tputs (stream->exit_attribute_mode, 1, out_char);
1180      /* We don't know exactly what effects exit_attribute_mode has, but
1181	 this is the minimum effect:  */
1182      old_attr.weight = WEIGHT_NORMAL;
1183      if (stream->exit_italics_mode == NULL)
1184	old_attr.posture = POSTURE_NORMAL;
1185      if (stream->exit_underline_mode == NULL)
1186	old_attr.underline = UNDERLINE_OFF;
1187      cleared_attributes = true;
1188    }
1189
1190  /* Turn on the colors.  */
1191  if (new_attr.color != old_attr.color
1192      || (cleared_attributes && new_attr.color != COLOR_DEFAULT))
1193    {
1194      assert (stream->supports_foreground);
1195      assert (new_attr.color != COLOR_DEFAULT);
1196      switch (stream->colormodel)
1197	{
1198	case cm_common8:
1199	  assert (new_attr.color >= 0 && new_attr.color < 8);
1200	  if (stream->set_a_foreground != NULL)
1201	    tputs (tparm (stream->set_a_foreground,
1202			  color_bgr (new_attr.color)),
1203		   1, out_char);
1204	  else
1205	    tputs (tparm (stream->set_foreground, new_attr.color),
1206		   1, out_char);
1207	  break;
1208	/* When we are dealing with an xterm, there is no need to go through
1209	   tputs() because we know there is no padding and sleeping.  */
1210	case cm_xterm8:
1211	  assert (new_attr.color >= 0 && new_attr.color < 8);
1212	  {
1213	    char bytes[5];
1214	    bytes[0] = 0x1B; bytes[1] = '[';
1215	    bytes[2] = '3'; bytes[3] = '0' + new_attr.color;
1216	    bytes[4] = 'm';
1217	    if (full_write (out_fd, bytes, 5) < 5)
1218	      out_error ();
1219	  }
1220	  break;
1221	case cm_xterm16:
1222	  assert (new_attr.color >= 0 && new_attr.color < 16);
1223	  {
1224	    char bytes[5];
1225	    bytes[0] = 0x1B; bytes[1] = '[';
1226	    if (new_attr.color < 8)
1227	      {
1228		bytes[2] = '3'; bytes[3] = '0' + new_attr.color;
1229	      }
1230	    else
1231	      {
1232		bytes[2] = '9'; bytes[3] = '0' + (new_attr.color - 8);
1233	      }
1234	    bytes[4] = 'm';
1235	    if (full_write (out_fd, bytes, 5) < 5)
1236	      out_error ();
1237	  }
1238	  break;
1239	case cm_xterm88:
1240	  assert (new_attr.color >= 0 && new_attr.color < 88);
1241	  {
1242	    char bytes[10];
1243	    char *p;
1244	    bytes[0] = 0x1B; bytes[1] = '[';
1245	    bytes[2] = '3'; bytes[3] = '8'; bytes[4] = ';';
1246	    bytes[5] = '5'; bytes[6] = ';';
1247	    p = bytes + 7;
1248	    if (new_attr.color >= 10)
1249	      *p++ = '0' + (new_attr.color / 10);
1250	    *p++ = '0' + (new_attr.color % 10);
1251	    *p++ = 'm';
1252	    if (full_write (out_fd, bytes, p - bytes) < p - bytes)
1253	      out_error ();
1254	  }
1255	  break;
1256	case cm_xterm256:
1257	  assert (new_attr.color >= 0 && new_attr.color < 256);
1258	  {
1259	    char bytes[11];
1260	    char *p;
1261	    bytes[0] = 0x1B; bytes[1] = '[';
1262	    bytes[2] = '3'; bytes[3] = '8'; bytes[4] = ';';
1263	    bytes[5] = '5'; bytes[6] = ';';
1264	    p = bytes + 7;
1265	    if (new_attr.color >= 100)
1266	      *p++ = '0' + (new_attr.color / 100);
1267	    if (new_attr.color >= 10)
1268	      *p++ = '0' + ((new_attr.color % 100) / 10);
1269	    *p++ = '0' + (new_attr.color % 10);
1270	    *p++ = 'm';
1271	    if (full_write (out_fd, bytes, p - bytes) < p - bytes)
1272	      out_error ();
1273	  }
1274	  break;
1275	default:
1276	  abort ();
1277	}
1278    }
1279  if (new_attr.bgcolor != old_attr.bgcolor
1280      || (cleared_attributes && new_attr.bgcolor != COLOR_DEFAULT))
1281    {
1282      assert (stream->supports_background);
1283      assert (new_attr.bgcolor != COLOR_DEFAULT);
1284      switch (stream->colormodel)
1285	{
1286	case cm_common8:
1287	  assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 8);
1288	  if (stream->set_a_background != NULL)
1289	    tputs (tparm (stream->set_a_background,
1290			  color_bgr (new_attr.bgcolor)),
1291		   1, out_char);
1292	  else
1293	    tputs (tparm (stream->set_background, new_attr.bgcolor),
1294		   1, out_char);
1295	  break;
1296	/* When we are dealing with an xterm, there is no need to go through
1297	   tputs() because we know there is no padding and sleeping.  */
1298	case cm_xterm8:
1299	  assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 8);
1300	  {
1301	    char bytes[5];
1302	    bytes[0] = 0x1B; bytes[1] = '[';
1303	    bytes[2] = '4'; bytes[3] = '0' + new_attr.bgcolor;
1304	    bytes[4] = 'm';
1305	    if (full_write (out_fd, bytes, 5) < 5)
1306	      out_error ();
1307	  }
1308	  break;
1309	case cm_xterm16:
1310	  assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 16);
1311	  {
1312	    char bytes[6];
1313	    bytes[0] = 0x1B; bytes[1] = '[';
1314	    if (new_attr.bgcolor < 8)
1315	      {
1316		bytes[2] = '4'; bytes[3] = '0' + new_attr.bgcolor;
1317		bytes[4] = 'm';
1318		if (full_write (out_fd, bytes, 5) < 5)
1319		  out_error ();
1320	      }
1321	    else
1322	      {
1323		bytes[2] = '1'; bytes[3] = '0';
1324		bytes[4] = '0' + (new_attr.bgcolor - 8); bytes[5] = 'm';
1325		if (full_write (out_fd, bytes, 6) < 6)
1326		  out_error ();
1327	      }
1328	  }
1329	  break;
1330	case cm_xterm88:
1331	  assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 88);
1332	  {
1333	    char bytes[10];
1334	    char *p;
1335	    bytes[0] = 0x1B; bytes[1] = '[';
1336	    bytes[2] = '4'; bytes[3] = '8'; bytes[4] = ';';
1337	    bytes[5] = '5'; bytes[6] = ';';
1338	    p = bytes + 7;
1339	    if (new_attr.bgcolor >= 10)
1340	      *p++ = '0' + (new_attr.bgcolor / 10);
1341	    *p++ = '0' + (new_attr.bgcolor % 10);
1342	    *p++ = 'm';
1343	    if (full_write (out_fd, bytes, p - bytes) < p - bytes)
1344	      out_error ();
1345	  }
1346	  break;
1347	case cm_xterm256:
1348	  assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 256);
1349	  {
1350	    char bytes[11];
1351	    char *p;
1352	    bytes[0] = 0x1B; bytes[1] = '[';
1353	    bytes[2] = '4'; bytes[3] = '8'; bytes[4] = ';';
1354	    bytes[5] = '5'; bytes[6] = ';';
1355	    p = bytes + 7;
1356	    if (new_attr.bgcolor >= 100)
1357	      *p++ = '0' + (new_attr.bgcolor / 100);
1358	    if (new_attr.bgcolor >= 10)
1359	      *p++ = '0' + ((new_attr.bgcolor % 100) / 10);
1360	    *p++ = '0' + (new_attr.bgcolor % 10);
1361	    *p++ = 'm';
1362	    if (full_write (out_fd, bytes, p - bytes) < p - bytes)
1363	      out_error ();
1364	  }
1365	  break;
1366	default:
1367	  abort ();
1368	}
1369    }
1370
1371  if (new_attr.weight != old_attr.weight
1372      || (cleared_attributes && new_attr.weight != WEIGHT_DEFAULT))
1373    {
1374      assert (stream->supports_weight);
1375      assert (new_attr.weight != WEIGHT_DEFAULT);
1376      /* This implies:  */
1377      assert (new_attr.weight == WEIGHT_BOLD);
1378      tputs (stream->enter_bold_mode, 1, out_char);
1379    }
1380  if (new_attr.posture != old_attr.posture
1381      || (cleared_attributes && new_attr.posture != POSTURE_DEFAULT))
1382    {
1383      assert (stream->supports_posture);
1384      assert (new_attr.posture != POSTURE_DEFAULT);
1385      /* This implies:  */
1386      assert (new_attr.posture == POSTURE_ITALIC);
1387      tputs (stream->enter_italics_mode, 1, out_char);
1388    }
1389  if (new_attr.underline != old_attr.underline
1390      || (cleared_attributes && new_attr.underline != UNDERLINE_DEFAULT))
1391    {
1392      assert (stream->supports_underline);
1393      assert (new_attr.underline != UNDERLINE_DEFAULT);
1394      /* This implies:  */
1395      assert (new_attr.underline == UNDERLINE_ON);
1396      tputs (stream->enter_underline_mode, 1, out_char);
1397    }
1398}
1399
1400/* Output the buffered line atomically.
1401   The terminal is assumed to have the default state (regarding colors and
1402   attributes) before this call.  It is left in default state after this
1403   call (regardless of stream->curr_attr).  */
1404static void
1405output_buffer (term_ostream_t stream)
1406{
1407  attributes_t default_attr;
1408  attributes_t attr;
1409  const char *cp;
1410  const attributes_t *ap;
1411  size_t len;
1412  size_t n;
1413
1414  default_attr.color = COLOR_DEFAULT;
1415  default_attr.bgcolor = COLOR_DEFAULT;
1416  default_attr.weight = WEIGHT_DEFAULT;
1417  default_attr.posture = POSTURE_DEFAULT;
1418  default_attr.underline = UNDERLINE_DEFAULT;
1419
1420  attr = default_attr;
1421
1422  cp = stream->buffer;
1423  ap = stream->attrbuffer;
1424  len = stream->buflen;
1425
1426  /* See how much we can output without blocking signals.  */
1427  for (n = 0; n < len && equal_attributes (ap[n], attr); n++)
1428    ;
1429  if (n > 0)
1430    {
1431      if (full_write (stream->fd, cp, n) < n)
1432	error (EXIT_FAILURE, errno, _("error writing to %s"), stream->filename);
1433      cp += n;
1434      ap += n;
1435      len -= n;
1436    }
1437  if (len > 0)
1438    {
1439      /* Block fatal signals, so that a SIGINT or similar doesn't interrupt
1440	 us without the possibility of restoring the terminal's state.  */
1441      block_fatal_signals ();
1442      /* Likewise for SIGTSTP etc.  */
1443      block_stopping_signals ();
1444
1445      /* Enable the exit handler for restoring the terminal's state.  */
1446      restore_colors =
1447	(stream->supports_foreground || stream->supports_background
1448	 ? stream->orig_pair
1449	 : NULL);
1450      restore_weight =
1451	(stream->supports_weight ? stream->exit_attribute_mode : NULL);
1452      restore_posture =
1453	(stream->supports_posture
1454	 ? (stream->exit_italics_mode != NULL
1455	    ? stream->exit_italics_mode
1456	    : stream->exit_attribute_mode)
1457	 : NULL);
1458      restore_underline =
1459	(stream->supports_underline
1460	 ? (stream->exit_underline_mode != NULL
1461	    ? stream->exit_underline_mode
1462	    : stream->exit_attribute_mode)
1463	 : NULL);
1464      out_fd = stream->fd;
1465      out_filename = stream->filename;
1466
1467      while (len > 0)
1468	{
1469	  /* Activate the attributes in *ap.  */
1470	  out_attr_change (stream, attr, *ap);
1471	  attr = *ap;
1472	  /* See how many characters we can output without further attribute
1473	     changes.  */
1474	  for (n = 1; n < len && equal_attributes (ap[n], attr); n++)
1475	    ;
1476	  if (full_write (stream->fd, cp, n) < n)
1477	    error (EXIT_FAILURE, errno, _("error writing to %s"),
1478		   stream->filename);
1479	  cp += n;
1480	  ap += n;
1481	  len -= n;
1482	}
1483
1484      /* Switch back to the default attributes.  */
1485      out_attr_change (stream, attr, default_attr);
1486
1487      /* Disable the exit handler.  */
1488      out_fd = -1;
1489      out_filename = NULL;
1490
1491      /* Unblock fatal and stopping signals.  */
1492      unblock_stopping_signals ();
1493      unblock_fatal_signals ();
1494    }
1495  stream->buflen = 0;
1496}
1497
1498/* Implementation of ostream_t methods.  */
1499
1500static term_color_t
1501term_ostream__rgb_to_color (term_ostream_t stream, int red, int green, int blue)
1502{
1503  switch (stream->colormodel)
1504    {
1505    case cm_monochrome:
1506      return rgb_to_color_monochrome ();
1507    case cm_common8:
1508      return rgb_to_color_common8 (red, green, blue);
1509    case cm_xterm8:
1510      return rgb_to_color_xterm8 (red, green, blue);
1511    case cm_xterm16:
1512      return rgb_to_color_xterm16 (red, green, blue);
1513    case cm_xterm88:
1514      return rgb_to_color_xterm88 (red, green, blue);
1515    case cm_xterm256:
1516      return rgb_to_color_xterm256 (red, green, blue);
1517    default:
1518      abort ();
1519    }
1520}
1521
1522static void
1523term_ostream__write_mem (term_ostream_t stream, const void *data, size_t len)
1524{
1525  const char *cp = (const char *) data;
1526  while (len > 0)
1527    {
1528      /* Look for the next newline.  */
1529      const char *newline = (const char *) memchr (cp, '\n', len);
1530      size_t n = (newline != NULL ? newline - cp : len);
1531
1532      /* Copy n bytes into the buffer.  */
1533      if (n > stream->allocated - stream->buflen)
1534	{
1535	  size_t new_allocated =
1536	    xmax (xsum (stream->buflen, n),
1537		  xsum (stream->allocated, stream->allocated));
1538	  if (size_overflow_p (new_allocated))
1539	    error (EXIT_FAILURE, 0,
1540		   _("%s: too much output, buffer size overflow"),
1541		   "term_ostream");
1542	  stream->buffer = (char *) xrealloc (stream->buffer, new_allocated);
1543	  stream->attrbuffer =
1544	    (attributes_t *)
1545	    xrealloc (stream->attrbuffer,
1546		      new_allocated * sizeof (attributes_t));
1547	  stream->allocated = new_allocated;
1548	}
1549      memcpy (stream->buffer + stream->buflen, cp, n);
1550      {
1551	attributes_t attr = stream->simp_attr;
1552	attributes_t *ap = stream->attrbuffer + stream->buflen;
1553	attributes_t *ap_end = ap + n;
1554	for (; ap < ap_end; ap++)
1555	  *ap = attr;
1556      }
1557      stream->buflen += n;
1558
1559      if (newline != NULL)
1560	{
1561	  output_buffer (stream);
1562	  if (full_write (stream->fd, "\n", 1) < 1)
1563	    error (EXIT_FAILURE, errno, _("error writing to %s"),
1564		   stream->filename);
1565	  cp += n + 1; /* cp = newline + 1; */
1566	  len -= n + 1;
1567	}
1568      else
1569	break;
1570    }
1571}
1572
1573static void
1574term_ostream__flush (term_ostream_t stream)
1575{
1576  output_buffer (stream);
1577}
1578
1579static void
1580term_ostream__free (term_ostream_t stream)
1581{
1582  term_ostream_flush (stream);
1583  free (stream->filename);
1584  if (stream->set_a_foreground != NULL)
1585    free (stream->set_a_foreground);
1586  if (stream->set_foreground != NULL)
1587    free (stream->set_foreground);
1588  if (stream->set_a_background != NULL)
1589    free (stream->set_a_background);
1590  if (stream->set_background != NULL)
1591    free (stream->set_background);
1592  if (stream->orig_pair != NULL)
1593    free (stream->orig_pair);
1594  if (stream->enter_bold_mode != NULL)
1595    free (stream->enter_bold_mode);
1596  if (stream->enter_italics_mode != NULL)
1597    free (stream->enter_italics_mode);
1598  if (stream->exit_italics_mode != NULL)
1599    free (stream->exit_italics_mode);
1600  if (stream->enter_underline_mode != NULL)
1601    free (stream->enter_underline_mode);
1602  if (stream->exit_underline_mode != NULL)
1603    free (stream->exit_underline_mode);
1604  if (stream->exit_attribute_mode != NULL)
1605    free (stream->exit_attribute_mode);
1606  free (stream->buffer);
1607  free (stream);
1608}
1609
1610/* Implementation of term_ostream_t methods.  */
1611
1612term_color_t
1613term_ostream__get_color (term_ostream_t stream)
1614{
1615  return stream->curr_attr.color;
1616}
1617
1618void
1619term_ostream__set_color (term_ostream_t stream, term_color_t color)
1620{
1621  stream->curr_attr.color = color;
1622  stream->simp_attr = simplify_attributes (stream, stream->curr_attr);
1623}
1624
1625term_color_t
1626term_ostream__get_bgcolor (term_ostream_t stream)
1627{
1628  return stream->curr_attr.bgcolor;
1629}
1630
1631void
1632term_ostream__set_bgcolor (term_ostream_t stream, term_color_t color)
1633{
1634  stream->curr_attr.bgcolor = color;
1635  stream->simp_attr = simplify_attributes (stream, stream->curr_attr);
1636}
1637
1638term_weight_t
1639term_ostream__get_weight (term_ostream_t stream)
1640{
1641  return stream->curr_attr.weight;
1642}
1643
1644void
1645term_ostream__set_weight (term_ostream_t stream, term_weight_t weight)
1646{
1647  stream->curr_attr.weight = weight;
1648  stream->simp_attr = simplify_attributes (stream, stream->curr_attr);
1649}
1650
1651term_posture_t
1652term_ostream__get_posture (term_ostream_t stream)
1653{
1654  return stream->curr_attr.posture;
1655}
1656
1657void
1658term_ostream__set_posture (term_ostream_t stream, term_posture_t posture)
1659{
1660  stream->curr_attr.posture = posture;
1661  stream->simp_attr = simplify_attributes (stream, stream->curr_attr);
1662}
1663
1664term_underline_t
1665term_ostream__get_underline (term_ostream_t stream)
1666{
1667  return stream->curr_attr.underline;
1668}
1669
1670void
1671term_ostream__set_underline (term_ostream_t stream, term_underline_t underline)
1672{
1673  stream->curr_attr.underline = underline;
1674  stream->simp_attr = simplify_attributes (stream, stream->curr_attr);
1675}
1676
1677/* Constructor.  */
1678
1679static inline char *
1680xstrdup0 (const char *str)
1681{
1682  if (str == NULL)
1683    return NULL;
1684#if HAVE_TERMINFO
1685  if (str == (const char *)(-1))
1686    return NULL;
1687#endif
1688  return xstrdup (str);
1689}
1690
1691term_ostream_t
1692term_ostream_create (int fd, const char *filename)
1693{
1694  term_ostream_t stream = XMALLOC (struct term_ostream_representation);
1695  const char *term;
1696
1697  stream->base.vtable = &term_ostream_vtable;
1698  stream->fd = fd;
1699  stream->filename = xstrdup (filename);
1700
1701  /* Defaults.  */
1702  stream->max_colors = -1;
1703  stream->no_color_video = -1;
1704  stream->set_a_foreground = NULL;
1705  stream->set_foreground = NULL;
1706  stream->set_a_background = NULL;
1707  stream->set_background = NULL;
1708  stream->orig_pair = NULL;
1709  stream->enter_bold_mode = NULL;
1710  stream->enter_italics_mode = NULL;
1711  stream->exit_italics_mode = NULL;
1712  stream->enter_underline_mode = NULL;
1713  stream->exit_underline_mode = NULL;
1714  stream->exit_attribute_mode = NULL;
1715
1716  /* Retrieve the terminal type.  */
1717  term = getenv ("TERM");
1718  if (term != NULL && term[0] != '\0')
1719    {
1720      /* When the terminfo function are available, we prefer them over the
1721	 termcap functions because
1722	   1. they don't risk a buffer overflow,
1723	   2. on OSF/1, for TERM=xterm, the tiget* functions provide access
1724	      to the number of colors and the color escape sequences, whereas
1725	      the tget* functions don't provide them.  */
1726#if HAVE_TERMINFO
1727      int err = 1;
1728
1729      if (setupterm (term, fd, &err) || err == 1)
1730	{
1731	  /* Retrieve particular values depending on the terminal type.  */
1732	  stream->max_colors = tigetnum ("colors");
1733	  stream->no_color_video = tigetnum ("ncv");
1734	  stream->set_a_foreground = xstrdup0 (tigetstr ("setaf"));
1735	  stream->set_foreground = xstrdup0 (tigetstr ("setf"));
1736	  stream->set_a_background = xstrdup0 (tigetstr ("setab"));
1737	  stream->set_background = xstrdup0 (tigetstr ("setb"));
1738	  stream->orig_pair = xstrdup0 (tigetstr ("op"));
1739	  stream->enter_bold_mode = xstrdup0 (tigetstr ("bold"));
1740	  stream->enter_italics_mode = xstrdup0 (tigetstr ("sitm"));
1741	  stream->exit_italics_mode = xstrdup0 (tigetstr ("ritm"));
1742	  stream->enter_underline_mode = xstrdup0 (tigetstr ("smul"));
1743	  stream->exit_underline_mode = xstrdup0 (tigetstr ("rmul"));
1744	  stream->exit_attribute_mode = xstrdup0 (tigetstr ("sgr0"));
1745	}
1746#elif HAVE_TERMCAP
1747      struct { char buf[1024]; char canary[4]; } termcapbuf;
1748      int retval;
1749
1750      /* Call tgetent, being defensive against buffer overflow.  */
1751      memcpy (termcapbuf.canary, "CnRy", 4);
1752      retval = tgetent (termcapbuf.buf, term);
1753      if (memcmp (termcapbuf.canary, "CnRy", 4) != 0)
1754	/* Buffer overflow!  */
1755	abort ();
1756
1757      if (retval > 0)
1758	{
1759	  struct { char buf[1024]; char canary[4]; } termentrybuf;
1760	  char *termentryptr;
1761
1762	  /* Prepare for calling tgetstr, being defensive against buffer
1763	     overflow.  ncurses' tgetstr() supports a second argument NULL,
1764	     but NetBSD's tgetstr() doesn't.  */
1765	  memcpy (termentrybuf.canary, "CnRz", 4);
1766	  #define TEBP ((termentryptr = termentrybuf.buf), &termentryptr)
1767
1768	  /* Retrieve particular values depending on the terminal type.  */
1769	  stream->max_colors = tgetnum ("Co");
1770	  stream->no_color_video = tgetnum ("NC");
1771	  stream->set_a_foreground = xstrdup0 (tgetstr ("AF", TEBP));
1772	  stream->set_foreground = xstrdup0 (tgetstr ("Sf", TEBP));
1773	  stream->set_a_background = xstrdup0 (tgetstr ("AB", TEBP));
1774	  stream->set_background = xstrdup0 (tgetstr ("Sb", TEBP));
1775	  stream->orig_pair = xstrdup0 (tgetstr ("op", TEBP));
1776	  stream->enter_bold_mode = xstrdup0 (tgetstr ("md", TEBP));
1777	  stream->enter_italics_mode = xstrdup0 (tgetstr ("ZH", TEBP));
1778	  stream->exit_italics_mode = xstrdup0 (tgetstr ("ZR", TEBP));
1779	  stream->enter_underline_mode = xstrdup0 (tgetstr ("us", TEBP));
1780	  stream->exit_underline_mode = xstrdup0 (tgetstr ("ue", TEBP));
1781	  stream->exit_attribute_mode = xstrdup0 (tgetstr ("me", TEBP));
1782
1783# ifdef __BEOS__
1784	  /* The BeOS termcap entry for "beterm" is broken: For "AF" and "AB"
1785	     it contains balues in terminfo syntax but the system's tparam()
1786	     function understands only the termcap syntax.  */
1787	  if (stream->set_a_foreground != NULL
1788	      && strcmp (stream->set_a_foreground, "\033[3%p1%dm") == 0)
1789	    {
1790	      free (stream->set_a_foreground);
1791	      stream->set_a_foreground = xstrdup ("\033[3%dm");
1792	    }
1793	  if (stream->set_a_background != NULL
1794	      && strcmp (stream->set_a_background, "\033[4%p1%dm") == 0)
1795	    {
1796	      free (stream->set_a_background);
1797	      stream->set_a_background = xstrdup ("\033[4%dm");
1798	    }
1799# endif
1800
1801	  /* The termcap entry for cygwin is broken: It has no "ncv" value,
1802	     but bold and underline are actually rendered through colors.  */
1803	  if (strcmp (term, "cygwin") == 0)
1804	    stream->no_color_video |= 2 | 32;
1805
1806	  /* Done with tgetstr.  Detect possible buffer overflow.  */
1807	  #undef TEBP
1808	  if (memcmp (termentrybuf.canary, "CnRz", 4) != 0)
1809	    /* Buffer overflow!  */
1810	    abort ();
1811	}
1812#else
1813    /* Fallback code for platforms with neither the terminfo nor the termcap
1814       functions, such as mingw.
1815       Assume the ANSI escape sequences.  Extracted through
1816       "TERM=ansi infocmp", replacing \E with \033.  */
1817      stream->max_colors = 8;
1818      stream->no_color_video = 3;
1819      stream->set_a_foreground = xstrdup ("\033[3%p1%dm");
1820      stream->set_a_background = xstrdup ("\033[4%p1%dm");
1821      stream->orig_pair = xstrdup ("\033[39;49m");
1822      stream->enter_bold_mode = xstrdup ("\033[1m");
1823      stream->enter_underline_mode = xstrdup ("\033[4m");
1824      stream->exit_underline_mode = xstrdup ("\033[m");
1825      stream->exit_attribute_mode = xstrdup ("\033[0;10m");
1826#endif
1827
1828      /* AIX 4.3.2, IRIX 6.5, HP-UX 11, Solaris 7..10 all lack the
1829	 description of color capabilities of "xterm" and "xterms"
1830	 in their terminfo database.  But it is important to have
1831	 color in xterm.  So we provide the color capabilities here.  */
1832      if (stream->max_colors <= 1
1833	  && (strcmp (term, "xterm") == 0 || strcmp (term, "xterms") == 0))
1834	{
1835	  stream->max_colors = 8;
1836	  stream->set_a_foreground = xstrdup ("\033[3%p1%dm");
1837	  stream->set_a_background = xstrdup ("\033[4%p1%dm");
1838	  stream->orig_pair = xstrdup ("\033[39;49m");
1839	}
1840    }
1841
1842  /* Infer the capabilities.  */
1843  stream->supports_foreground =
1844    (stream->max_colors >= 8
1845     && (stream->set_a_foreground != NULL || stream->set_foreground != NULL)
1846     && stream->orig_pair != NULL);
1847  stream->supports_background =
1848    (stream->max_colors >= 8
1849     && (stream->set_a_background != NULL || stream->set_background != NULL)
1850     && stream->orig_pair != NULL);
1851  stream->colormodel =
1852    (stream->supports_foreground || stream->supports_background
1853     ? (term != NULL
1854	&& (/* Recognize xterm-16color, xterm-88color, xterm-256color.  */
1855	    (strlen (term) >= 5 && memcmp (term, "xterm", 5) == 0)
1856	    || /* Recognize rxvt-16color.  */
1857	       (strlen (term) >= 4 && memcmp (term, "rxvt", 7) == 0)
1858	    || /* Recognize konsole-16color.  */
1859	       (strlen (term) >= 7 && memcmp (term, "konsole", 7) == 0))
1860	? (stream->max_colors == 256 ? cm_xterm256 :
1861	   stream->max_colors == 88 ? cm_xterm88 :
1862	   stream->max_colors == 16 ? cm_xterm16 :
1863	   cm_xterm8)
1864	: cm_common8)
1865     : cm_monochrome);
1866  stream->supports_weight =
1867    (stream->enter_bold_mode != NULL && stream->exit_attribute_mode != NULL);
1868  stream->supports_posture =
1869    (stream->enter_italics_mode != NULL
1870     && (stream->exit_italics_mode != NULL
1871	 || stream->exit_attribute_mode != NULL));
1872  stream->supports_underline =
1873    (stream->enter_underline_mode != NULL
1874     && (stream->exit_underline_mode != NULL
1875	 || stream->exit_attribute_mode != NULL));
1876
1877  /* Initialize the buffer.  */
1878  stream->allocated = 120;
1879  stream->buffer = XNMALLOC (stream->allocated, char);
1880  stream->attrbuffer = XNMALLOC (stream->allocated, attributes_t);
1881  stream->buflen = 0;
1882
1883  /* Initialize the current attributes.  */
1884  stream->curr_attr.color = COLOR_DEFAULT;
1885  stream->curr_attr.bgcolor = COLOR_DEFAULT;
1886  stream->curr_attr.weight = WEIGHT_DEFAULT;
1887  stream->curr_attr.posture = POSTURE_DEFAULT;
1888  stream->curr_attr.underline = UNDERLINE_DEFAULT;
1889  stream->simp_attr = simplify_attributes (stream, stream->curr_attr);
1890
1891  /* Register an exit handler.  */
1892  {
1893    static bool registered = false;
1894    if (!registered)
1895      {
1896	atexit (restore);
1897	registered = true;
1898      }
1899  }
1900
1901  return stream;
1902}
1903
1904#line 1905 "term-ostream.c"
1905
1906const struct term_ostream_implementation term_ostream_vtable =
1907{
1908  term_ostream_superclasses,
1909  sizeof (term_ostream_superclasses) / sizeof (term_ostream_superclasses[0]),
1910  sizeof (struct term_ostream_representation),
1911  term_ostream__write_mem,
1912  term_ostream__flush,
1913  term_ostream__free,
1914  term_ostream__rgb_to_color,
1915  term_ostream__get_color,
1916  term_ostream__set_color,
1917  term_ostream__get_bgcolor,
1918  term_ostream__set_bgcolor,
1919  term_ostream__get_weight,
1920  term_ostream__set_weight,
1921  term_ostream__get_posture,
1922  term_ostream__set_posture,
1923  term_ostream__get_underline,
1924  term_ostream__set_underline,
1925};
1926
1927#if !HAVE_INLINE
1928
1929/* Define the functions that invoke the methods.  */
1930
1931void
1932term_ostream_write_mem (term_ostream_t first_arg, const void *data, size_t len)
1933{
1934  const struct term_ostream_implementation *vtable =
1935    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
1936  vtable->write_mem (first_arg,data,len);
1937}
1938
1939void
1940term_ostream_flush (term_ostream_t first_arg)
1941{
1942  const struct term_ostream_implementation *vtable =
1943    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
1944  vtable->flush (first_arg);
1945}
1946
1947void
1948term_ostream_free (term_ostream_t first_arg)
1949{
1950  const struct term_ostream_implementation *vtable =
1951    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
1952  vtable->free (first_arg);
1953}
1954
1955term_color_t
1956term_ostream_rgb_to_color (term_ostream_t first_arg, 			     int red, int green, int blue)
1957{
1958  const struct term_ostream_implementation *vtable =
1959    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
1960  return vtable->rgb_to_color (first_arg,red,green,blue);
1961}
1962
1963term_color_t
1964term_ostream_get_color (term_ostream_t first_arg)
1965{
1966  const struct term_ostream_implementation *vtable =
1967    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
1968  return vtable->get_color (first_arg);
1969}
1970
1971void
1972term_ostream_set_color (term_ostream_t first_arg, term_color_t color)
1973{
1974  const struct term_ostream_implementation *vtable =
1975    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
1976  vtable->set_color (first_arg,color);
1977}
1978
1979term_color_t
1980term_ostream_get_bgcolor (term_ostream_t first_arg)
1981{
1982  const struct term_ostream_implementation *vtable =
1983    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
1984  return vtable->get_bgcolor (first_arg);
1985}
1986
1987void
1988term_ostream_set_bgcolor (term_ostream_t first_arg, term_color_t color)
1989{
1990  const struct term_ostream_implementation *vtable =
1991    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
1992  vtable->set_bgcolor (first_arg,color);
1993}
1994
1995term_weight_t
1996term_ostream_get_weight (term_ostream_t first_arg)
1997{
1998  const struct term_ostream_implementation *vtable =
1999    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
2000  return vtable->get_weight (first_arg);
2001}
2002
2003void
2004term_ostream_set_weight (term_ostream_t first_arg, term_weight_t weight)
2005{
2006  const struct term_ostream_implementation *vtable =
2007    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
2008  vtable->set_weight (first_arg,weight);
2009}
2010
2011term_posture_t
2012term_ostream_get_posture (term_ostream_t first_arg)
2013{
2014  const struct term_ostream_implementation *vtable =
2015    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
2016  return vtable->get_posture (first_arg);
2017}
2018
2019void
2020term_ostream_set_posture (term_ostream_t first_arg, term_posture_t posture)
2021{
2022  const struct term_ostream_implementation *vtable =
2023    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
2024  vtable->set_posture (first_arg,posture);
2025}
2026
2027term_underline_t
2028term_ostream_get_underline (term_ostream_t first_arg)
2029{
2030  const struct term_ostream_implementation *vtable =
2031    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
2032  return vtable->get_underline (first_arg);
2033}
2034
2035void
2036term_ostream_set_underline (term_ostream_t first_arg, 				  term_underline_t underline)
2037{
2038  const struct term_ostream_implementation *vtable =
2039    ((struct term_ostream_representation_header *) (struct term_ostream_representation *) first_arg)->vtable;
2040  vtable->set_underline (first_arg,underline);
2041}
2042
2043#endif
2044