forked from alexfru/dflat20
-
Notifications
You must be signed in to change notification settings - Fork 2
/
tty-cp437.c
129 lines (117 loc) · 3.17 KB
/
tty-cp437.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* IBM PC cp437 display routines */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/select.h>
#include <time.h>
#include "unikey.h"
#include "runes.h"
/* 16-color palette positions (not ANSI colors) */
#define BLACK 0
#define BLUE 1
#define GREEN 2
#define CYAN 3
#define RED 4
#define MAGENTA 5
#define BROWN 6
#define LIGHTGRAY 7
#define DARKGRAY 8
#define LIGHTBLUE 9
#define LIGHTGREEN 10
#define LIGHTCYAN 11
#define LIGHTRED 12
#define LIGHTMAGENTA 13
#define YELLOW 14
#define WHITE 15
/* Default 16-color fg, 8 color bg palette */
/* 0 1 2 3 4 5 6 7
blk blu grn cyn red mag yel wht */
static const int ansi_colors[16] = {30, 34, 32, 36, 31, 35, 33, 37,
90, 94, 92, 96, 91, 95, 93, 97 };
/* two 16-color palettes, fg_pal256 used on 256-color capable terminals */
static const int *fg_pal16 = ansi_colors;
static const int *fg_pal256;
/* Set non-standard 16-color fg palettes, for use on 16-color or 256-color terminals */
void tty_setfgpalette(const int *pal16, const int *pal256)
{
fg_pal16 = pal16;
fg_pal256 = pal256;
}
static char *attr_to_ansi(char *buf, unsigned int attr)
{
int fg = attr & 0x0F; /* 16 fg colors */
int bg = (attr & 0x70) >> 4; /* 8 bg colors */
if (fg_pal256 && !iselksconsole) {
sprintf(buf, "\e[38;5;%dm\e[%dm", fg_pal256[fg], ansi_colors[bg] + 10);
} else {
sprintf(buf, "\e[%d;%dm", fg_pal16[fg], ansi_colors[bg] + 10);
}
return buf;
}
#if ELKS
static int elks_displayable(int c)
{
switch (c) {
case '\0':
case '\007':
case '\b':
case '\t':
case '\r':
case '\n':
case '\033':
return 0;
}
return 1;
}
#endif
/* convert CP 437 byte to string + NUL, depending on platform */
int cp437tostr(char *s, int c)
{
#if ELKS
if (iselksconsole) {
if (!elks_displayable(c & 255))
c = '?';
s[0] = (char)c;
s[1] = '\0';
return 1;
}
#endif
return runetostr(s, kCp437[c & 255]);
}
static int COLS = 80;
static int LINES = 25;
static char *video_ram;
char *tty_allocate_screen(int cols, int lines)
{
if (cols) COLS = cols;
if (lines) LINES = lines;
video_ram = calloc(COLS * LINES * 2, 1);
return video_ram;
}
void tty_output_screen(int flush)
{
int r, c, a, b;
unsigned short *chattr = (unsigned short *)video_ram;
char buf[16];
printf("\e[?25l\e[H"); /* cursor off, home */
for (r=0; r<LINES; r++) {
a = -1;
for (c=0; c<COLS; c++) {
b = *chattr++;
if (a != (b & 0xFF00)) {
fputs(attr_to_ansi(buf, b >> 8), stdout);
a = b & 0xFF00;
}
if (cp437tostr(buf, b & 255))
fputs(buf, stdout);
}
if (r == LINES - 1)
printf("\r");
else printf("\n");
}
printf("\e[1;0;0m"); /* reset attrs, cursor left off */
if (flush)
fflush(stdout);
}