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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
131
/* r = g = b. A grey color. */
132
result->hue = 0; /* arbitrary */
133
result->saturation = 0;
134
result->brightness = (float) r / 255.0f;
131
/* r = g = b. A grey color. */
132
result->hue = 0; /* arbitrary */
133
result->saturation = 0;
134
result->brightness = (float) r / 255.0f;
242
242
/* The color model used by the terminal. */
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. */
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. */
253
253
/* ----------------------- cm_monochrome color model ----------------------- */
842
842
/* Greyscale approximation. */
843
843
float luminance = color_luminance (r, g, b);
844
844
if (luminance < 0.015f)
846
846
else if (luminance < 0.051f)
848
848
else if (luminance < 0.090f)
850
850
else if (luminance < 0.129f)
852
852
else if (luminance < 0.157f)
854
854
else if (luminance < 0.177f)
856
856
else if (luminance < 0.207f)
858
858
else if (luminance < 0.247f)
860
860
else if (luminance < 0.284f)
862
862
else if (luminance < 0.304f)
864
864
else if (luminance < 0.319f)
866
866
else if (luminance < 0.339f)
868
868
else if (luminance < 0.364f)
870
870
else if (luminance < 0.404f)
872
872
else if (luminance < 0.443f)
874
874
else if (luminance < 0.480f)
876
876
else if (luminance < 0.500f)
878
878
else if (luminance < 0.521f)
880
880
else if (luminance < 0.560f)
882
882
else if (luminance < 0.600f)
884
884
else if (luminance < 0.639f)
886
886
else if (luminance < 0.663f)
888
888
else if (luminance < 0.682f)
890
890
else if (luminance < 0.717f)
892
892
else if (luminance < 0.756f)
894
894
else if (luminance < 0.796f)
896
896
else if (luminance < 0.823f)
898
898
else if (luminance < 0.843f)
900
900
else if (luminance < 0.874f)
902
902
else if (luminance < 0.896f)
904
904
else if (luminance < 0.915f)
906
906
else if (luminance < 0.966f)
912
912
/* Color approximation. */
1017
1017
if (out_fd >= 0)
1019
1019
if (restore_colors != NULL)
1020
tputs (restore_colors, 1, out_char_unchecked);
1020
tputs (restore_colors, 1, out_char_unchecked);
1021
1021
if (restore_weight != NULL)
1022
tputs (restore_weight, 1, out_char_unchecked);
1022
tputs (restore_weight, 1, out_char_unchecked);
1023
1023
if (restore_posture != NULL)
1024
tputs (restore_posture, 1, out_char_unchecked);
1024
tputs (restore_posture, 1, out_char_unchecked);
1025
1025
if (restore_underline != NULL)
1026
tputs (restore_underline, 1, out_char_unchecked);
1026
tputs (restore_underline, 1, out_char_unchecked);
1170
1170
if ((old_attr.weight != WEIGHT_NORMAL
1171
1171
&& new_attr.weight == WEIGHT_NORMAL)
1172
1172
|| (old_attr.posture != POSTURE_NORMAL
1173
&& new_attr.posture == POSTURE_NORMAL
1174
/* implies stream->exit_italics_mode == NULL */)
1173
&& new_attr.posture == POSTURE_NORMAL
1174
/* implies stream->exit_italics_mode == NULL */)
1175
1175
|| (old_attr.underline != UNDERLINE_OFF
1176
&& new_attr.underline == UNDERLINE_OFF
1177
/* implies stream->exit_underline_mode == NULL */))
1176
&& new_attr.underline == UNDERLINE_OFF
1177
/* implies stream->exit_underline_mode == NULL */))
1179
1179
tputs (stream->exit_attribute_mode, 1, out_char);
1180
1180
/* We don't know exactly what effects exit_attribute_mode has, but
1181
this is the minimum effect: */
1181
this is the minimum effect: */
1182
1182
old_attr.weight = WEIGHT_NORMAL;
1183
1183
if (stream->exit_italics_mode == NULL)
1184
old_attr.posture = POSTURE_NORMAL;
1184
old_attr.posture = POSTURE_NORMAL;
1185
1185
if (stream->exit_underline_mode == NULL)
1186
old_attr.underline = UNDERLINE_OFF;
1186
old_attr.underline = UNDERLINE_OFF;
1187
1187
cleared_attributes = true;
1194
1194
assert (stream->supports_foreground);
1195
1195
assert (new_attr.color != COLOR_DEFAULT);
1196
1196
switch (stream->colormodel)
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)),
1205
tputs (tparm (stream->set_foreground, new_attr.color),
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. */
1211
assert (new_attr.color >= 0 && new_attr.color < 8);
1214
bytes[0] = 0x1B; bytes[1] = '[';
1215
bytes[2] = '3'; bytes[3] = '0' + new_attr.color;
1217
if (full_write (out_fd, bytes, 5) < 5)
1222
assert (new_attr.color >= 0 && new_attr.color < 16);
1225
bytes[0] = 0x1B; bytes[1] = '[';
1226
if (new_attr.color < 8)
1228
bytes[2] = '3'; bytes[3] = '0' + new_attr.color;
1232
bytes[2] = '9'; bytes[3] = '0' + (new_attr.color - 8);
1235
if (full_write (out_fd, bytes, 5) < 5)
1240
assert (new_attr.color >= 0 && new_attr.color < 88);
1244
bytes[0] = 0x1B; bytes[1] = '[';
1245
bytes[2] = '3'; bytes[3] = '8'; bytes[4] = ';';
1246
bytes[5] = '5'; bytes[6] = ';';
1248
if (new_attr.color >= 10)
1249
*p++ = '0' + (new_attr.color / 10);
1250
*p++ = '0' + (new_attr.color % 10);
1252
if (full_write (out_fd, bytes, p - bytes) < p - bytes)
1257
assert (new_attr.color >= 0 && new_attr.color < 256);
1261
bytes[0] = 0x1B; bytes[1] = '[';
1262
bytes[2] = '3'; bytes[3] = '8'; bytes[4] = ';';
1263
bytes[5] = '5'; bytes[6] = ';';
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);
1271
if (full_write (out_fd, bytes, p - bytes) < p - bytes)
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)),
1205
tputs (tparm (stream->set_foreground, new_attr.color),
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. */
1211
assert (new_attr.color >= 0 && new_attr.color < 8);
1214
bytes[0] = 0x1B; bytes[1] = '[';
1215
bytes[2] = '3'; bytes[3] = '0' + new_attr.color;
1217
if (full_write (out_fd, bytes, 5) < 5)
1222
assert (new_attr.color >= 0 && new_attr.color < 16);
1225
bytes[0] = 0x1B; bytes[1] = '[';
1226
if (new_attr.color < 8)
1228
bytes[2] = '3'; bytes[3] = '0' + new_attr.color;
1232
bytes[2] = '9'; bytes[3] = '0' + (new_attr.color - 8);
1235
if (full_write (out_fd, bytes, 5) < 5)
1240
assert (new_attr.color >= 0 && new_attr.color < 88);
1244
bytes[0] = 0x1B; bytes[1] = '[';
1245
bytes[2] = '3'; bytes[3] = '8'; bytes[4] = ';';
1246
bytes[5] = '5'; bytes[6] = ';';
1248
if (new_attr.color >= 10)
1249
*p++ = '0' + (new_attr.color / 10);
1250
*p++ = '0' + (new_attr.color % 10);
1252
if (full_write (out_fd, bytes, p - bytes) < p - bytes)
1257
assert (new_attr.color >= 0 && new_attr.color < 256);
1261
bytes[0] = 0x1B; bytes[1] = '[';
1262
bytes[2] = '3'; bytes[3] = '8'; bytes[4] = ';';
1263
bytes[5] = '5'; bytes[6] = ';';
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);
1271
if (full_write (out_fd, bytes, p - bytes) < p - bytes)
1279
1279
if (new_attr.bgcolor != old_attr.bgcolor
1280
1280
|| (cleared_attributes && new_attr.bgcolor != COLOR_DEFAULT))
1282
1282
assert (stream->supports_background);
1283
1283
assert (new_attr.bgcolor != COLOR_DEFAULT);
1284
1284
switch (stream->colormodel)
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)),
1293
tputs (tparm (stream->set_background, new_attr.bgcolor),
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. */
1299
assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 8);
1302
bytes[0] = 0x1B; bytes[1] = '[';
1303
bytes[2] = '4'; bytes[3] = '0' + new_attr.bgcolor;
1305
if (full_write (out_fd, bytes, 5) < 5)
1310
assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 16);
1313
bytes[0] = 0x1B; bytes[1] = '[';
1314
if (new_attr.bgcolor < 8)
1316
bytes[2] = '4'; bytes[3] = '0' + new_attr.bgcolor;
1318
if (full_write (out_fd, bytes, 5) < 5)
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)
1331
assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 88);
1335
bytes[0] = 0x1B; bytes[1] = '[';
1336
bytes[2] = '4'; bytes[3] = '8'; bytes[4] = ';';
1337
bytes[5] = '5'; bytes[6] = ';';
1339
if (new_attr.bgcolor >= 10)
1340
*p++ = '0' + (new_attr.bgcolor / 10);
1341
*p++ = '0' + (new_attr.bgcolor % 10);
1343
if (full_write (out_fd, bytes, p - bytes) < p - bytes)
1348
assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 256);
1352
bytes[0] = 0x1B; bytes[1] = '[';
1353
bytes[2] = '4'; bytes[3] = '8'; bytes[4] = ';';
1354
bytes[5] = '5'; bytes[6] = ';';
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);
1362
if (full_write (out_fd, bytes, p - bytes) < p - bytes)
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)),
1293
tputs (tparm (stream->set_background, new_attr.bgcolor),
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. */
1299
assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 8);
1302
bytes[0] = 0x1B; bytes[1] = '[';
1303
bytes[2] = '4'; bytes[3] = '0' + new_attr.bgcolor;
1305
if (full_write (out_fd, bytes, 5) < 5)
1310
assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 16);
1313
bytes[0] = 0x1B; bytes[1] = '[';
1314
if (new_attr.bgcolor < 8)
1316
bytes[2] = '4'; bytes[3] = '0' + new_attr.bgcolor;
1318
if (full_write (out_fd, bytes, 5) < 5)
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)
1331
assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 88);
1335
bytes[0] = 0x1B; bytes[1] = '[';
1336
bytes[2] = '4'; bytes[3] = '8'; bytes[4] = ';';
1337
bytes[5] = '5'; bytes[6] = ';';
1339
if (new_attr.bgcolor >= 10)
1340
*p++ = '0' + (new_attr.bgcolor / 10);
1341
*p++ = '0' + (new_attr.bgcolor % 10);
1343
if (full_write (out_fd, bytes, p - bytes) < p - bytes)
1348
assert (new_attr.bgcolor >= 0 && new_attr.bgcolor < 256);
1352
bytes[0] = 0x1B; bytes[1] = '[';
1353
bytes[2] = '4'; bytes[3] = '8'; bytes[4] = ';';
1354
bytes[5] = '5'; bytes[6] = ';';
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);
1362
if (full_write (out_fd, bytes, p - bytes) < p - bytes)
1371
1371
if (new_attr.weight != old_attr.weight
1439
1439
/* Block fatal signals, so that a SIGINT or similar doesn't interrupt
1440
us without the possibility of restoring the terminal's state. */
1440
us without the possibility of restoring the terminal's state. */
1441
1441
block_fatal_signals ();
1442
1442
/* Likewise for SIGTSTP etc. */
1443
1443
block_stopping_signals ();
1445
1445
/* Enable the exit handler for restoring the terminal's state. */
1446
1446
restore_colors =
1447
(stream->supports_foreground || stream->supports_background
1447
(stream->supports_foreground || stream->supports_background
1450
1450
restore_weight =
1451
(stream->supports_weight ? stream->exit_attribute_mode : NULL);
1451
(stream->supports_weight ? stream->exit_attribute_mode : NULL);
1452
1452
restore_posture =
1453
(stream->supports_posture
1454
? (stream->exit_italics_mode != NULL
1455
? stream->exit_italics_mode
1456
: stream->exit_attribute_mode)
1453
(stream->supports_posture
1454
? (stream->exit_italics_mode != NULL
1455
? stream->exit_italics_mode
1456
: stream->exit_attribute_mode)
1458
1458
restore_underline =
1459
(stream->supports_underline
1460
? (stream->exit_underline_mode != NULL
1461
? stream->exit_underline_mode
1462
: stream->exit_attribute_mode)
1459
(stream->supports_underline
1460
? (stream->exit_underline_mode != NULL
1461
? stream->exit_underline_mode
1462
: stream->exit_attribute_mode)
1464
1464
out_fd = stream->fd;
1465
1465
out_filename = stream->filename;
1467
1467
while (len > 0)
1469
/* Activate the attributes in *ap. */
1470
out_attr_change (stream, attr, *ap);
1472
/* See how many characters we can output without further attribute
1474
for (n = 1; n < len && equal_attributes (ap[n], attr); n++)
1476
if (full_write (stream->fd, cp, n) < n)
1477
error (EXIT_FAILURE, errno, _("error writing to %s"),
1469
/* Activate the attributes in *ap. */
1470
out_attr_change (stream, attr, *ap);
1472
/* See how many characters we can output without further attribute
1474
for (n = 1; n < len && equal_attributes (ap[n], attr); n++)
1476
if (full_write (stream->fd, cp, n) < n)
1477
error (EXIT_FAILURE, errno, _("error writing to %s"),
1484
1484
/* Switch back to the default attributes. */
1485
1485
out_attr_change (stream, attr, default_attr);
1532
1532
/* Copy n bytes into the buffer. */
1533
1533
if (n > stream->allocated - stream->buflen)
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"),
1542
stream->buffer = (char *) xrealloc (stream->buffer, new_allocated);
1543
stream->attrbuffer =
1545
xrealloc (stream->attrbuffer,
1546
new_allocated * sizeof (attributes_t));
1547
stream->allocated = new_allocated;
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"),
1542
stream->buffer = (char *) xrealloc (stream->buffer, new_allocated);
1543
stream->attrbuffer =
1545
xrealloc (stream->attrbuffer,
1546
new_allocated * sizeof (attributes_t));
1547
stream->allocated = new_allocated;
1549
1549
memcpy (stream->buffer + stream->buflen, cp, n);
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++)
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++)
1557
1557
stream->buflen += n;
1559
1559
if (newline != NULL)
1561
output_buffer (stream);
1562
if (full_write (stream->fd, "\n", 1) < 1)
1563
error (EXIT_FAILURE, errno, _("error writing to %s"),
1565
cp += n + 1; /* cp = newline + 1; */
1561
output_buffer (stream);
1562
if (full_write (stream->fd, "\n", 1) < 1)
1563
error (EXIT_FAILURE, errno, _("error writing to %s"),
1565
cp += n + 1; /* cp = newline + 1; */
1610
1610
/* Implementation of term_ostream_t methods. */
1613
1613
term_ostream__get_color (term_ostream_t stream)
1615
1615
return stream->curr_attr.color;
1619
1619
term_ostream__set_color (term_ostream_t stream, term_color_t color)
1621
1621
stream->curr_attr.color = color;
1622
1622
stream->simp_attr = simplify_attributes (stream, stream->curr_attr);
1626
1626
term_ostream__get_bgcolor (term_ostream_t stream)
1628
1628
return stream->curr_attr.bgcolor;
1632
1632
term_ostream__set_bgcolor (term_ostream_t stream, term_color_t color)
1634
1634
stream->curr_attr.bgcolor = color;
1635
1635
stream->simp_attr = simplify_attributes (stream, stream->curr_attr);
1638
static term_weight_t
1639
1639
term_ostream__get_weight (term_ostream_t stream)
1641
1641
return stream->curr_attr.weight;
1645
1645
term_ostream__set_weight (term_ostream_t stream, term_weight_t weight)
1647
1647
stream->curr_attr.weight = weight;
1648
1648
stream->simp_attr = simplify_attributes (stream, stream->curr_attr);
1651
static term_posture_t
1652
1652
term_ostream__get_posture (term_ostream_t stream)
1654
1654
return stream->curr_attr.posture;
1658
1658
term_ostream__set_posture (term_ostream_t stream, term_posture_t posture)
1660
1660
stream->curr_attr.posture = posture;
1661
1661
stream->simp_attr = simplify_attributes (stream, stream->curr_attr);
1664
static term_underline_t
1665
1665
term_ostream__get_underline (term_ostream_t stream)
1667
1667
return stream->curr_attr.underline;
1671
1671
term_ostream__set_underline (term_ostream_t stream, term_underline_t underline)
1673
1673
stream->curr_attr.underline = underline;
1718
1718
if (term != NULL && term[0] != '\0')
1720
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. */
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
1726
#if HAVE_TERMINFO
1729
1729
if (setupterm (term, fd, &err) || err == 1)
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"));
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"));
1746
1746
#elif HAVE_TERMCAP
1747
1747
struct { char buf[1024]; char canary[4]; } termcapbuf;
1751
1751
memcpy (termcapbuf.canary, "CnRy", 4);
1752
1752
retval = tgetent (termcapbuf.buf, term);
1753
1753
if (memcmp (termcapbuf.canary, "CnRy", 4) != 0)
1754
/* Buffer overflow! */
1754
/* Buffer overflow! */
1757
1757
if (retval > 0)
1759
struct { char buf[1024]; char canary[4]; } termentrybuf;
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)
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));
1759
struct { char buf[1024]; char canary[4]; } termentrybuf;
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)
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));
1783
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)
1790
free (stream->set_a_foreground);
1791
stream->set_a_foreground = xstrdup ("\033[3%dm");
1793
if (stream->set_a_background != NULL
1794
&& strcmp (stream->set_a_background, "\033[4%p1%dm") == 0)
1796
free (stream->set_a_background);
1797
stream->set_a_background = xstrdup ("\033[4%dm");
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)
1790
free (stream->set_a_foreground);
1791
stream->set_a_foreground = xstrdup ("\033[3%dm");
1793
if (stream->set_a_background != NULL
1794
&& strcmp (stream->set_a_background, "\033[4%p1%dm") == 0)
1796
free (stream->set_a_background);
1797
stream->set_a_background = xstrdup ("\033[4%dm");
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;
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;
1806
/* Done with tgetstr. Detect possible buffer overflow. */
1808
if (memcmp (termentrybuf.canary, "CnRz", 4) != 0)
1809
/* Buffer overflow! */
1806
/* Done with tgetstr. Detect possible buffer overflow. */
1808
if (memcmp (termentrybuf.canary, "CnRz", 4) != 0)
1809
/* Buffer overflow! */
1813
1813
/* Fallback code for platforms with neither the terminfo nor the termcap
1814
1814
functions, such as mingw.
1828
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. */
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
1832
if (stream->max_colors <= 1
1833
&& (strcmp (term, "xterm") == 0 || strcmp (term, "xterms") == 0))
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");
1833
&& (strcmp (term, "xterm") == 0 || strcmp (term, "xterms") == 0))
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");
1842
1842
/* Infer the capabilities. */
1851
1851
stream->colormodel =
1852
1852
(stream->supports_foreground || stream->supports_background
1853
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 :
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 :
1865
1865
: cm_monochrome);
1866
1866
stream->supports_weight =
1867
1867
(stream->enter_bold_mode != NULL && stream->exit_attribute_mode != NULL);
1868
1868
stream->supports_posture =
1869
1869
(stream->enter_italics_mode != NULL
1870
1870
&& (stream->exit_italics_mode != NULL
1871
|| stream->exit_attribute_mode != NULL));
1871
|| stream->exit_attribute_mode != NULL));
1872
1872
stream->supports_underline =
1873
1873
(stream->enter_underline_mode != NULL
1874
1874
&& (stream->exit_underline_mode != NULL
1875
|| stream->exit_attribute_mode != NULL));
1875
|| stream->exit_attribute_mode != NULL));
1877
1877
/* Initialize the buffer. */
1878
1878
stream->allocated = 120;