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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
#include "atascii.h"
const char *atascii_inverse_on = "\x1b[7m";
const char *atascii_inverse_off = "\x1b[27m";
/* only called in magazine mode. cursor control characters
like a bell in the middle of a non-inverse string
should not cause it to print {inv}{bell}{norm}. The {bell}
is "inherently" inverse (since its high bit is set) but doesn't
need to be printed that way. */
static int affects_inv(int c) {
switch(c) {
case 0x1b: /* esc */
case 0x1c: /* up */
case 0x1d: /* down */
case 0x1e: /* left */
case 0x1f: /* right */
case 0x9b: /* EOL */
case 0x9c: /* del line */
case 0x9d: /* ins line */
case 0x9e: /* clear tab */
case 0x9f: /* set tab */
case 0x7d: /* cls */
case 0x7e: /* BS */
case 0x7f: /* tab */
case 0xfd: /* bell */
case 0xfe: /* del chr */
case 0xff: /* ins chr */
return 0;
default:
return 1;
}
}
int atascii_context_init(atascii_ctx *ctx, int mode, int flags) {
memset(ctx, 0, sizeof(atascii_ctx));
switch(mode) {
case ATA_MODE_UTF8:
if(flags & ATA_FLAG_ICS)
ctx->table = ics2utf;
else
ctx->table = ata2utf;
break;
case ATA_MODE_MAGAZINE:
ctx->flags &= ~ATA_FLAG_UNDERLINE;
ctx->table = ata2mag;
break;
default:
return 0;
}
ctx->mode = mode;
ctx->flags = flags;
return 1;
}
char *atascii_a2utf(atascii_ctx *ctx, int src, char *dest) {
dest[0] = 0;
if(src == ATA_CHR_FINISH) {
if(ctx->inv)
strcpy(dest, atascii_inverse_off);
return dest;
}
if(src == 0x9b) {
strcpy(dest, "\n");
ctx->lines++;
return dest;
}
if(ctx->flags & ATA_FLAG_TEXTMODE) {
switch(src) {
case 0x7f: /* tab */
strcpy(dest, "\t");
return dest;
case 0xfd: /* bell */
strcpy(dest, "\a");
return dest;
case 0x7e: /* backspace */
strcpy(dest, "\b");
return dest;
default: break;
}
}
if(ctx->flags & ATA_FLAG_STRIP_INVERSE) src &= 0x7f;
if(!(ctx->flags & ATA_FLAG_UNDERLINE)) {
/* strings of inverse chars only get one "inverse on" ANSI
sequence, and one "inverse off" afterwards. */
if(src & 0x80) {
if(!ctx->inv) {
if(ctx->mode == ATA_MODE_MAGAZINE) {
if(affects_inv(src)) {
strcpy(dest, "{inv}");
ctx->inv = 1;
}
} else {
strcpy(dest, atascii_inverse_on);
ctx->inv = 1;
}
}
} else {
if(ctx->inv) {
if(ctx->mode == ATA_MODE_MAGAZINE) {
if(affects_inv(src)) {
strcpy(dest, "{norm}");
ctx->inv = 0;
}
} else {
strcpy(dest, atascii_inverse_off);
ctx->inv = 0;
}
}
}
}
if(ctx->mode == ATA_MODE_MAGAZINE) {
/* special cases: control codes with bit 7 set can't go
in the table since it's only got 128 entries. */
switch(src) {
case 0x9c:
strcat(dest, "{del-line}"); return dest;
case 0x9d:
strcat(dest, "{ins-line}"); return dest;
case 0x9e:
strcat(dest, "{clr-tab}"); return dest;
case 0x9f:
strcat(dest, "{set-tab}"); return dest;
case 0xfd:
strcat(dest, "{bell}"); return dest;
case 0xfe:
strcat(dest, "{del-char}"); return dest;
case 0xff:
strcat(dest, "{ins-char}"); return dest;
default: break;
}
}
strcat(dest, ctx->table[src & 0x7f]);
if((ctx->flags & ATA_FLAG_UNDERLINE) && (src & 0x80)) {
strcat(dest, "\b_");
}
return dest;
}
|