aboutsummaryrefslogtreecommitdiff
path: root/atascii.c
blob: d1d1243021580a3838751eac3f94df14ba1e767e (plain)
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
#include "atascii.h"

const char *atascii_inverse_on  = "\x1b[7m";
const char *atascii_inverse_off = "\x1b[27m";

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) {
				ctx->inv = 1;
				if(ctx->mode == ATA_MODE_MAGAZINE) {
					strcpy(dest, "{inv}");
				} else {
					strcpy(dest, atascii_inverse_on);
				}
			}
		} else {
			if(ctx->inv) {
				ctx->inv = 0;
				if(ctx->mode == ATA_MODE_MAGAZINE) {
					strcpy(dest, "{norm}");
				} else {
					strcpy(dest, atascii_inverse_off);
				}
			}
		}
	}

	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;
}