1
/* Copyright (c) 1992, 1999, 2001, 2002, 2003 John E. Davis
2
* This file is part of the S-Lang library.
4
* You may distribute under the terms of either the GNU General Public
5
* License or the Perl Artistic License.
2
Copyright (C) 2004, 2005, 2006 John E. Davis
4
This file is part of the S-Lang Library.
6
The S-Lang Library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU General Public License as
8
published by the Free Software Foundation; either version 2 of the
9
License, or (at your option) any later version.
11
The S-Lang Library is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this library; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
8
22
#include "slinclud.h"
77
91
* not include this attribute.
80
#define GET_FG(color) ((color & FG_MASK) >> 8)
81
#define GET_BG(color) ((color & BG_MASK) >> 16)
94
#define GET_FG(fgbg) (((fgbg) & FG_MASK) >> 8)
95
#define GET_BG(fgbg) (((fgbg) & BG_MASK) >> 16)
82
96
#define MAKE_COLOR(fg, bg) (((fg) | ((bg) << 8)) << 8)
98
int SLtt_Screen_Cols = 80;
99
int SLtt_Screen_Rows = 24;
86
100
int SLtt_Term_Cannot_Insert;
87
101
int SLtt_Term_Cannot_Scroll;
88
102
int SLtt_Use_Ansi_Colors;
89
int SLtt_Blink_Mode = 1;
103
int SLtt_Blink_Mode = 0;
90
104
int SLtt_Use_Blink_For_ACS = 0;
91
105
int SLtt_Newline_Ok = 0;
92
106
int SLtt_Has_Alt_Charset = 0;
93
107
int SLtt_Force_Keypad_Init = 0;
95
void (*_SLtt_color_changed_hook)(void);
109
/* static int UTF8_Mode = -1; */
111
void (*_pSLtt_color_changed_hook)(void);
97
113
#if SLTT_HAS_NON_BCE_SUPPORT
98
114
static int Bce_Color_Offset = 0;
120
136
static int Linux_Console;
121
137
static int QANSI_Console;
138
static int Mouse_Mode = -1;
123
/* It is crucial that JMAX_COLORS must be less than 128 since the high bit
140
/* The following comment is nolonger valid, but is here in case there are
141
* some apps that use SLtt_Use_Blink_For_ACS and still need porting to v2.
143
* It is crucial that JMAX_COLORS must be less than 128 since the high bit
124
144
* is used to indicate a character from the ACS (alt char set). The exception
125
145
* to this rule is if SLtt_Use_Blink_For_ACS is true. This means that of
126
146
* the highbit is set, we interpret that as a blink character. This is
127
147
* exploited by DOSemu.
129
#define JMAX_COLORS 256
149
#define JMAX_COLORS 512
130
150
#define JNORMAL_COLOR 0
134
154
SLtt_Char_Type fgbg;
135
155
SLtt_Char_Type mono;
140
#define RGB1(r, g, b) ((r) | ((g) << 1) | ((b) << 2))
141
#define RGB(r, g, b, br, bg, bb) ((RGB1(r, g, b) << 8) | (RGB1(br, bg, bb) << 16))
143
static Ansi_Color_Type Ansi_Color_Map[JMAX_COLORS] =
145
{RGB(1, 1, 1, 0, 0, 0), 0x00000000, NULL}, /* white/black */
146
{RGB(0, 1, 0, 0, 0, 0), SLTT_REV_MASK, NULL}, /* green/black */
147
{RGB(1, 0, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* magenta/black */
148
{RGB(0, 1, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* cyan/black */
149
{RGB(1, 0, 0, 0, 0, 0), SLTT_REV_MASK, NULL},
150
{RGB(0, 1, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
151
{RGB(1, 0, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
152
{RGB(1, 0, 0, 0, 1, 0), SLTT_REV_MASK, NULL},
153
{RGB(0, 0, 1, 1, 0, 0), SLTT_REV_MASK, NULL},
154
{RGB(0, 1, 0, 1, 0, 0), SLTT_REV_MASK, NULL},
155
{RGB(0, 1, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
156
{RGB(1, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
157
{RGB(1, 0, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
158
{RGB(0, 0, 0, 0, 1, 1), SLTT_REV_MASK, NULL},
159
{RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
160
{RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
161
{RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
162
{RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL}
159
static Brush_Info_Type Brush_Table[JMAX_COLORS];
165
161
/* 0 if least significant bit is blue, not red */
166
static int Is_Fg_BGR = 0;
162
/* static int Is_Fg_BGR = 0; */
167
163
static int Is_Bg_BGR = 0;
168
164
#define COLOR_ARG(color, is_bgr) ((is_bgr) ? RGB_to_BGR[(color)&0x7] : (color))
169
static const int RGB_to_BGR[] =
165
static SLCONST int RGB_to_BGR[] =
171
167
0, 4, 2, 6, 1, 5, 3, 7
999
1007
{"default", SLSMG_COLOR_DEFAULT}
1002
void SLtt_set_mono (int obj, char *what, SLtt_Char_Type mask)
1010
static int Brushes_Initialized = 0;
1012
static int initialize_brushes (void)
1005
if ((obj < 0) || (obj >= JMAX_COLORS))
1015
Brush_Info_Type *b, *bmax;
1018
bmax = b + JMAX_COLORS;
1028
b->fgbg = MAKE_COLOR(fg,bg);
1029
b->mono = SLTT_REV_MASK;
1009
Ansi_Color_Map[obj].mono = mask & ATTR_MASK;
1041
Brush_Table[0].mono = 0;
1042
Brushes_Initialized = 1;
1047
static Brush_Info_Type *get_brush_info (unsigned int color)
1049
if (Brushes_Initialized == 0)
1050
initialize_brushes ();
1052
color &= SLSMG_COLOR_MASK;
1054
if (color >= JMAX_COLORS)
1057
return Brush_Table + color;
1060
static SLtt_Char_Type get_brush_attr (unsigned int color)
1064
if (NULL == (b = get_brush_info (color)))
1065
return (SLtt_Char_Type)-1;
1067
if (SLtt_Use_Ansi_Colors)
1073
static SLtt_Char_Type get_brush_fgbg (unsigned int color)
1075
return get_brush_info(color)->fgbg;
1078
int SLtt_set_mono (int obj, char *what, SLtt_Char_Type mask)
1083
if (NULL == (b = get_brush_info (obj)))
1086
b->mono = mask & ATTR_MASK;
1012
1090
static char *check_color_for_digit_form (char *color)
1098
static unsigned char FgBg_Stats[JMAX_COLORS];
1100
1176
static int Color_0_Modified = 0;
1102
void SLtt_set_color_object (int obj, SLtt_Char_Type attr)
1178
int SLtt_set_color_object (int obj, SLtt_Char_Type attr)
1106
if ((obj < 0) || (obj >= JMAX_COLORS)) return;
1108
cust_esc = Ansi_Color_Map[obj].custom_esc;
1109
if (cust_esc != NULL)
1112
FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
1113
Ansi_Color_Map[obj].custom_esc = NULL;
1116
Ansi_Color_Map[obj].fgbg = attr;
1182
if (NULL == (b = get_brush_info (obj)))
1117
1186
if (obj == 0) Color_0_Modified = 1;
1119
if (_SLtt_color_changed_hook != NULL)
1120
(*_SLtt_color_changed_hook)();
1188
if (_pSLtt_color_changed_hook != NULL)
1189
(*_pSLtt_color_changed_hook)();
1123
1194
SLtt_Char_Type SLtt_get_color_object (int obj)
1125
if ((obj < 0) || (obj >= JMAX_COLORS)) return 0;
1126
return Ansi_Color_Map[obj].fgbg;
1196
return get_brush_fgbg (obj);
1129
void SLtt_add_color_attribute (int obj, SLtt_Char_Type attr)
1199
int SLtt_add_color_attribute (int obj, SLtt_Char_Type attr)
1131
if ((obj < 0) || (obj >= JMAX_COLORS)) return;
1133
Ansi_Color_Map[obj].fgbg |= (attr & ATTR_MASK);
1203
if (NULL == (b = get_brush_info (obj)))
1206
b->fgbg |= (attr & ATTR_MASK);
1134
1208
if (obj == 0) Color_0_Modified = 1;
1135
if (_SLtt_color_changed_hook != NULL)
1136
(*_SLtt_color_changed_hook)();
1209
if (_pSLtt_color_changed_hook != NULL)
1210
(*_pSLtt_color_changed_hook)();
1139
1215
static SLtt_Char_Type fb_to_fgbg (SLtt_Char_Type f, SLtt_Char_Type b)
1255
void SLtt_set_color (int obj, char *what, char *fg, char *bg)
1331
int SLtt_set_color (int obj, char *what, char *fg, char *bg)
1257
1333
SLtt_Char_Type fgbg;
1260
if ((obj < 0) || (obj >= JMAX_COLORS))
1263
if (-1 != make_color_fgbg (fg, bg, &fgbg))
1264
SLtt_set_color_object (obj, fgbg);
1267
void SLtt_set_color_fgbg (int obj, SLtt_Char_Type f, SLtt_Char_Type b)
1269
SLtt_set_color_object (obj, fb_to_fgbg (f, b));
1272
void SLtt_set_color_esc (int obj, char *esc)
1275
SLtt_Char_Type fgbg = 0;
1278
if ((obj < 0) || (obj >= JMAX_COLORS))
1283
cust_esc = Ansi_Color_Map[obj].custom_esc;
1284
if (cust_esc != NULL)
1287
FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
1290
cust_esc = (char *) SLmalloc (strlen(esc) + 1);
1291
if (cust_esc != NULL) strcpy (cust_esc, esc);
1293
Ansi_Color_Map[obj].custom_esc = cust_esc;
1294
if (cust_esc == NULL) fgbg = 0;
1297
/* The whole point of this is to generate a unique fgbg */
1298
for (i = 0; i < JMAX_COLORS; i++)
1300
if (FgBg_Stats[i] == 0) fgbg = i;
1302
if (obj == i) continue;
1303
if ((Ansi_Color_Map[i].custom_esc) == NULL) continue;
1304
if (!strcmp (Ansi_Color_Map[i].custom_esc, cust_esc))
1306
fgbg = (Ansi_Color_Map[i].fgbg >> 8) & 0x7F;
1310
FgBg_Stats[fgbg] += 1;
1314
Ansi_Color_Map[obj].fgbg = (fgbg | (fgbg << 8)) << 8;
1315
if (obj == 0) Color_0_Modified = 1;
1316
if (_SLtt_color_changed_hook != NULL)
1317
(*_SLtt_color_changed_hook)();
1337
if (-1 == make_color_fgbg (fg, bg, &fgbg))
1340
return SLtt_set_color_object (obj, fgbg);
1343
int SLtt_set_color_fgbg (int obj, SLtt_Char_Type f, SLtt_Char_Type b)
1345
return SLtt_set_color_object (obj, fb_to_fgbg (f, b));
1320
1348
void SLtt_set_alt_char_set (int i)
1455
1468
/* Highest bit represents the character set. */
1456
#define COLOR_MASK 0x7F00
1457
#define COLOR_OF(x) (((x)&COLOR_MASK)>>8)
1458
#define CHAR_OF(x) ((x)&0x80FF)
1469
#define COLOR_OF(a) ((a)->color & SLSMG_COLOR_MASK)
1460
#if SLTT_HAS_NON_BCE_SUPPORT
1461
static int bce_color_eqs (unsigned int a, unsigned int b)
1471
static int bce_color_eqs (SLsmg_Char_Type *a, SLsmg_Char_Type *b)
1473
SLsmg_Color_Type ca, cb;
1474
Brush_Info_Type *ba, *bb;
1482
ba = get_brush_info (ca);
1483
bb = get_brush_info (cb);
1469
1485
if (SLtt_Use_Ansi_Colors == 0)
1470
return Ansi_Color_Map[a].mono == Ansi_Color_Map[b].mono;
1486
return ba->mono == bb->mono;
1472
1488
if (Bce_Color_Offset == 0)
1473
return Ansi_Color_Map[a].fgbg == Ansi_Color_Map[b].fgbg;
1489
return ba->fgbg == bb->fgbg;
1475
1491
/* If either are color 0, then we do not know what that means since the
1476
1492
* terminal does not support BCE */
1477
if ((a == 0) || (b == 0))
1493
if ((ca == 0) || (cb == 0))
1480
return Ansi_Color_Map[a-1].fgbg == Ansi_Color_Map[b-1].fgbg;
1496
return get_brush_fgbg (ca-1) == get_brush_fgbg(cb-1);
1482
#define COLOR_EQS(a,b) bce_color_eqs (a,b)
1484
# define COLOR_EQS(a, b) \
1485
(SLtt_Use_Ansi_Colors \
1486
? (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)\
1487
: (Ansi_Color_Map[COLOR_OF(a)].mono == Ansi_Color_Map[COLOR_OF(b)].mono))
1490
#define CHAR_EQS(a, b) (((a) == (b))\
1491
|| ((CHAR_OF(a)==CHAR_OF(b)) && COLOR_EQS(a,b)))
1493
1499
/* The whole point of this routine is to prevent writing to the last column
1494
1500
* and last row on terminals with automatic margins.
1502
1508
len = strlen (str);
1503
1509
if (Automatic_Margins && (Cursor_r + 1 == SLtt_Screen_Rows))
1505
if (len + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
1507
/* For now, just do not write there. Later, something more
1508
* sophisticated will be implemented.
1510
if (SLtt_Screen_Cols > Cursor_c)
1511
len = SLtt_Screen_Cols - Cursor_c - 1;
1511
if (_pSLtt_UTF8_Mode == 0)
1513
if (len + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
1515
/* For now, just do not write there. Later, something more
1516
* sophisticated will be implemented.
1518
if (SLtt_Screen_Cols > Cursor_c)
1519
len = SLtt_Screen_Cols - Cursor_c - 1;
1526
unsigned int nchars = SLutf8_strlen((SLuchar_Type *)str, 1);
1527
if (nchars + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
1529
if (SLtt_Screen_Cols > Cursor_c)
1532
nchars = SLtt_Screen_Cols - Cursor_c - 1;
1533
p = (char *)SLutf8_skip_chars((SLuchar_Type *) str, (SLuchar_Type *)(str + len), nchars, NULL, 1);
1516
1541
tt_write (str, len);
1519
static void send_attr_str (SLsmg_Char_Type *s)
1544
static void send_attr_str (SLsmg_Char_Type *s, SLsmg_Char_Type *smax)
1521
unsigned char out[SLTT_MAX_SCREEN_COLS], ch, *p;
1546
unsigned char out[1+SLUTF8_MAX_MBLEN*SLSMG_MAX_CHARS_PER_CELL*SLTT_MAX_SCREEN_COLS];
1547
unsigned char *p, *pmax;
1522
1548
register SLtt_Char_Type attr;
1523
register SLsmg_Char_Type sh;
1524
int color, last_color = -1;
1549
SLsmg_Color_Type color, last_color = (SLsmg_Color_Type)-1;
1527
while (0 != (sh = *s++))
1553
pmax = p + (sizeof (out)-1);
1530
color = ((int) sh & 0xFF00) >> 8;
1559
unsigned int nchars;
1561
if (0 == (nchars = s->nchars))
1563
/* 2nd element of a char that occupies two columns */
1565
if (_pSLtt_UTF8_Mode == 0)
1532
1573
#if SLTT_HAS_NON_BCE_SUPPORT
1533
1574
if (Bce_Color_Offset
1552
1594
if (attr != Current_Fgbg)
1555
1598
/* it is a space so only consider it different if it
1556
1599
* has different attributes.
1558
(attr != Current_Fgbg))
1559
/* The previous line was: */
1560
/* (attr & BGALL_MASK) != (Current_Fgbg & BGALL_MASK)) */
1561
/* However, it does not account for ACS */
1601
|| (attr != Current_Fgbg)
1566
1607
write_string_with_care ((char *) out);
1567
Cursor_c += (int) (p - out);
1571
if (SLtt_Use_Ansi_Colors && (NULL != Ansi_Color_Map[color & 0x7F].custom_esc))
1573
tt_write_string (Ansi_Color_Map[color & 0x7F].custom_esc);
1574
/* Just in case the custom escape sequence screwed up
1575
* the alt character set state...
1577
if ((attr & SLTT_ALTC_MASK) != (Current_Fgbg & SLTT_ALTC_MASK))
1578
SLtt_set_alt_char_set ((int) (attr & SLTT_ALTC_MASK));
1579
Current_Fgbg = attr;
1581
else write_attributes (attr);
1609
Cursor_c += dcursor_c;
1612
write_attributes (attr);
1583
1613
last_color = color;
1618
if ((wch < 0x80) && (nchars == 1))
1619
*p++ = (unsigned char) wch;
1620
else if (_pSLtt_UTF8_Mode == 0)
1624
else if (wch < (SLwchar_Type)SLsmg_Display_Eight_Bit)
1626
*p++ = (unsigned char) wch;
1631
for (i = 0; i < nchars; i++)
1633
if (NULL == (p = SLutf8_encode (s->wchars[i], p, pmax-p)))
1635
fprintf (stderr, "*** send_attr_str: buffer too small\n");
1590
1644
if (p != out) write_string_with_care ((char *) out);
1591
Cursor_c += (int) (p - out);
1645
Cursor_c += dcursor_c;
1594
1648
static void forward_cursor (unsigned int n, int row)