1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2
3 #include "vt_drcs.h"
4
5 #include <string.h> /* memset */
6 #include <limits.h> /* UINT_MAX */
7 #include <pobl/bl_mem.h>
8 #include <pobl/bl_str.h> /* strdup */
9 #include <pobl/bl_debug.h>
10
11 #ifndef UINT16_MAX
12 #define UINT16_MAX ((1 << 16) - 1)
13 #endif
14
15 /* --- static variables --- */
16
17 static vt_drcs_t *cur_drcs;
18
19 /* --- global functions --- */
20
vt_drcs_select(vt_drcs_t * drcs)21 void vt_drcs_select(vt_drcs_t *drcs) {
22 cur_drcs = drcs;
23 }
24
vt_drcs_get_glyph(ef_charset_t cs,u_char idx)25 char *vt_drcs_get_glyph(ef_charset_t cs, u_char idx) {
26 vt_drcs_font_t *font;
27
28 /* msb can be set in vt_parser.c (e.g. ESC(I (JISX0201 kana)) */
29 if ((font = vt_drcs_get_font(cur_drcs, cs, 0)) && 0x20 <= (idx & 0x7f)) {
30 #if 0
31 /*
32 * See https://vt100.net/docs/vt510-rm/DECDLD.html
33 *
34 * Pcss: Defines the character set as a 94- or 96- character graphic set.
35 * 0 = 94-character set. (default)
36 * 1 = 96-character set.
37 * The value of Pcss changes the meaning of the Pcn (starting character) parameter above.
38 * If Pcss = 0 (94-character set)
39 * The terminal ignores any attempt to load characters into the 2/0 or 7/15 table positions.
40 * Pcn Specifies
41 * 1 column 2/row 1
42 * ...
43 * 94 column 7/row 14
44 *
45 * If Pcss = 1 (96-character set)
46 * Pcn Specifies
47 * 0 column 2/row 0
48 * ...
49 * 95 column 7/row 15
50 */
51 if (IS_CS94SB(cs) && (idx == 0x20 | idx == 0x7f)) {
52 return NULL;
53 }
54 #endif
55
56 return font->glyphs[(idx & 0x7f) - 0x20];
57 } else {
58 return NULL;
59 }
60 }
61
vt_drcs_get_font(vt_drcs_t * drcs,ef_charset_t cs,int create)62 vt_drcs_font_t *vt_drcs_get_font(vt_drcs_t *drcs, ef_charset_t cs, int create) {
63 if (!drcs) {
64 return NULL;
65 }
66
67 /* CS94SB(0x30)-CS94SB(0x7e) (=0x00-0x4e), CS96SB(0x30)-CS96SB(0x7e) (0x50-0x9e) */
68 if (cs > CS96SB_ID(0x7e)) {
69 return NULL;
70 }
71
72 if (!drcs->fonts[cs]) {
73 if (!create || !(drcs->fonts[cs] = calloc(1, sizeof(vt_drcs_font_t)))) {
74 return NULL;
75 }
76 }
77
78 return drcs->fonts[cs];
79 }
80
vt_drcs_final(vt_drcs_t * drcs,ef_charset_t cs)81 void vt_drcs_final(vt_drcs_t *drcs, ef_charset_t cs) {
82 if (drcs) {
83 if (drcs->fonts[cs]) {
84 int idx;
85
86 for (idx = 0; idx <= 0x5f; idx++) {
87 free(drcs->fonts[cs]->glyphs[idx]);
88 }
89
90 free(drcs->fonts[cs]);
91 drcs->fonts[cs] = NULL;
92 }
93 }
94 }
95
vt_drcs_final_full(vt_drcs_t * drcs)96 void vt_drcs_final_full(vt_drcs_t *drcs) {
97 ef_charset_t cs;
98
99 for (cs = CS94SB_ID(0x30); cs <= CS96SB_ID(0x7e); cs++) {
100 vt_drcs_final(drcs, cs);
101 }
102 }
103
vt_drcs_add_glyph(vt_drcs_font_t * font,int idx,const char * seq,u_int width,u_int height)104 void vt_drcs_add_glyph(vt_drcs_font_t *font, int idx, const char *seq, u_int width, u_int height) {
105 if (font) {
106 free(font->glyphs[idx]);
107
108 if ((font->glyphs[idx] = malloc(2 + strlen(seq) + 1))) {
109 font->glyphs[idx][0] = width;
110 font->glyphs[idx][1] = height;
111 strcpy(font->glyphs[idx] + 2, seq);
112 }
113 }
114 }
115
vt_drcs_add_picture(vt_drcs_font_t * font,int id,u_int offset,int beg_idx,u_int num_cols,u_int num_rows,u_int num_cols_small,u_int num_rows_small)116 void vt_drcs_add_picture(vt_drcs_font_t *font, int id, u_int offset, int beg_idx,
117 u_int num_cols, u_int num_rows,
118 u_int num_cols_small, u_int num_rows_small) {
119 /* 'offset > UINT32_MAX' is not necessary to check. */
120 if (num_cols > UINT16_MAX || num_rows > UINT16_MAX) {
121 return;
122 }
123
124 if (font) {
125 font->pic_id = id;
126 font->pic_offset = offset;
127 font->pic_beg_idx = beg_idx;
128 font->pic_num_rows = num_rows;
129 font->pic_num_cols = num_cols;
130 font->pic_num_cols_small = num_cols_small;
131 font->pic_num_rows_small = num_rows_small;
132 }
133 }
134
vt_drcs_get_picture(vt_drcs_font_t * font,int * id,int * pos,u_int ch)135 int vt_drcs_get_picture(vt_drcs_font_t *font, int *id, int *pos, u_int ch) {
136 if (font->pic_num_rows > 0) {
137 ch &= 0x7f;
138 if (ch >= 0x20 && (ch -= 0x20) >= font->pic_beg_idx) {
139 ch += font->pic_offset;
140 /* See MAKE_INLINEPIC_POS() in ui_picture.h */
141 *pos = (ch % font->pic_num_cols_small) * font->pic_num_rows +
142 (ch / font->pic_num_cols_small);
143 *id = font->pic_id;
144
145 return 1;
146 }
147 }
148
149 return 0;
150 }
151
vt_convert_drcs_to_unicode_pua(ef_char_t * ch)152 int vt_convert_drcs_to_unicode_pua(ef_char_t *ch) {
153 if (vt_drcs_get_glyph(ch->cs, ch->ch[0])) {
154 if (IS_CS94SB(ch->cs)) {
155 ch->ch[2] = CS94SB_FT(ch->cs);
156 ch->ch[3] = ch->ch[0] & 0x7f;
157 } else {
158 ch->ch[2] = CS96SB_FT(ch->cs);
159 ch->ch[3] = ch->ch[0] | 0x80;
160 }
161 ch->ch[1] = 0x10;
162 ch->ch[0] = 0x00;
163 ch->cs = ISO10646_UCS4_1;
164 ch->size = 4;
165 ch->property = 0;
166
167 return 1;
168 } else {
169 return 0;
170 }
171 }
172
vt_convert_unicode_pua_to_drcs(ef_char_t * ch)173 int vt_convert_unicode_pua_to_drcs(ef_char_t *ch) {
174 u_char *c;
175
176 c = ch->ch;
177
178 if (c[1] == 0x10 && 0x30 <= c[2] && c[2] <= 0x7e && c[0] == 0x00) {
179 if (0x20 <= c[3] && c[3] <= 0x7f) {
180 ch->cs = CS94SB_ID(c[2]);
181 } else if (0xa0 <= c[3] && c[3] <= 0xff) {
182 ch->cs = CS96SB_ID(c[2]);
183 } else {
184 return 0;
185 }
186
187 c[0] = c[3];
188 ch->size = 1;
189 ch->property = 0; /* Ignore EF_AWIDTH */
190
191 return 1;
192 }
193
194 return 0;
195 }
196