1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2
3 #include "vt_line_iscii.h"
4
5 #include <stdio.h> /* NULL */
6 #include <pobl/bl_debug.h>
7
8 #include "vt_iscii.h"
9
10 /* --- global functions --- */
11
vt_line_set_use_iscii(vt_line_t * line,int flag)12 int vt_line_set_use_iscii(vt_line_t *line, int flag) {
13 if (flag) {
14 if (vt_line_is_using_iscii(line)) {
15 return 1;
16 } else if (line->ctl_info_type != 0) {
17 return 0;
18 }
19
20 if ((line->ctl_info.iscii = vt_iscii_new()) == NULL) {
21 return 0;
22 }
23
24 line->ctl_info_type = VINFO_ISCII;
25 } else {
26 if (vt_line_is_using_iscii(line)) {
27 vt_iscii_destroy(line->ctl_info.iscii);
28 line->ctl_info_type = 0;
29 }
30 }
31
32 return 1;
33 }
34
35 /* The caller should check vt_line_is_using_iscii() in advance. */
vt_line_iscii_render(vt_line_t * line)36 int vt_line_iscii_render(vt_line_t *line /* is always visual */
37 ) {
38 int ret;
39 int visual_mod_beg;
40
41 /*
42 * Lower case: ASCII
43 * Upper case: ISCII
44 * (Logical) AAA == (Visual) BBBBB
45 * => (Logical) aaa == (Visual) aaa
46 * In this case vt_line_is_cleared_to_end() returns 0, so "BB" remains on
47 * the screen unless following vt_line_set_modified().
48 */
49 visual_mod_beg = vt_line_get_beg_of_modified(line);
50 if (line->ctl_info.iscii->has_iscii) {
51 visual_mod_beg = vt_line_iscii_convert_logical_char_index_to_visual(line, visual_mod_beg);
52 }
53
54 if (vt_line_is_real_modified(line)) {
55 if ((ret = vt_iscii(line->ctl_info.iscii, line->chars, line->num_filled_chars)) <= 0) {
56 return ret;
57 }
58
59 if (line->ctl_info.iscii->has_iscii) {
60 int beg;
61
62 if ((beg = vt_line_iscii_convert_logical_char_index_to_visual(
63 line, vt_line_get_beg_of_modified(line))) < visual_mod_beg) {
64 visual_mod_beg = beg;
65 }
66 }
67
68 /*
69 * Conforming line->change_{beg|end}_col to visual mode.
70 * If this line contains ISCII chars, it should be redrawn to the end of
71 * line.
72 */
73 vt_line_set_modified(line, visual_mod_beg, line->num_chars);
74 } else {
75 vt_line_set_modified(line, visual_mod_beg, vt_line_iscii_convert_logical_char_index_to_visual(
76 line, vt_line_get_end_of_modified(line)));
77 }
78
79 return 1;
80 }
81
82 /* The caller should check vt_line_is_using_iscii() in advance. */
vt_line_iscii_visual(vt_line_t * line)83 int vt_line_iscii_visual(vt_line_t *line) {
84 vt_char_t *src;
85 u_int src_len;
86 vt_char_t *dst;
87 u_int dst_len;
88 int dst_pos;
89 int src_pos;
90
91 if (line->ctl_info.iscii->size == 0 || !line->ctl_info.iscii->has_iscii) {
92 #ifdef __DEBUG
93 bl_warn_printf(BL_DEBUG_TAG " Not need to visualize.\n");
94 #endif
95
96 return 1;
97 }
98
99 src_len = line->num_filled_chars;
100 if ((src = vt_str_alloca(src_len)) == NULL) {
101 return 0;
102 }
103 vt_str_init(src, src_len);
104 vt_str_copy(src, line->chars, src_len);
105
106 dst_len = line->ctl_info.iscii->size;
107 if (line->num_chars < dst_len) {
108 vt_char_t *chars;
109
110 if ((chars = vt_str_new(dst_len))) {
111 /* XXX => shrunk at vt_screen.c and vt_logical_visual_ctl.c */
112 vt_str_destroy(line->chars, line->num_chars);
113 line->chars = chars;
114 line->num_chars = dst_len;
115 } else {
116 line->ctl_info.iscii->size = dst_len = line->num_chars;
117 }
118 }
119
120 dst = line->chars;
121
122 src_pos = 0;
123 for (dst_pos = 0; dst_pos < dst_len; dst_pos++) {
124 if (line->ctl_info.iscii->num_chars_array[dst_pos] == 0) {
125 vt_char_copy(dst + dst_pos, vt_get_base_char(src + src_pos - 1));
126 /* NULL */
127 vt_char_set_code(dst + dst_pos, 0);
128 } else {
129 u_int count;
130
131 vt_char_copy(dst + dst_pos, src + (src_pos++));
132
133 for (count = 1; count < line->ctl_info.iscii->num_chars_array[dst_pos]; count++) {
134 vt_char_t *comb;
135 u_int num;
136
137 #ifdef DEBUG
138 if (vt_char_is_comb(vt_get_base_char(src + src_pos))) {
139 bl_debug_printf(BL_DEBUG_TAG " illegal iscii\n");
140 }
141 #endif
142 vt_char_combine_simple(dst + dst_pos, vt_get_base_char(src + src_pos));
143
144 comb = vt_get_combining_chars(src + (src_pos++), &num);
145 for (; num > 0; num--) {
146 #ifdef DEBUG
147 if (!vt_char_is_comb(comb)) {
148 bl_debug_printf(BL_DEBUG_TAG " illegal iscii\n");
149 }
150 #endif
151 vt_char_combine_simple(dst + dst_pos, comb++);
152 }
153 }
154 }
155 }
156
157 #ifdef DEBUG
158 if (src_pos != src_len) {
159 bl_debug_printf(BL_DEBUG_TAG "vt_line_iscii_visual() failed: %d -> %d\n", src_len, src_pos);
160 }
161 #endif
162
163 vt_str_final(src, src_len);
164
165 line->num_filled_chars = dst_pos;
166
167 return 1;
168 }
169
170 /* The caller should check vt_line_is_using_iscii() in advance. */
vt_line_iscii_logical(vt_line_t * line)171 int vt_line_iscii_logical(vt_line_t *line) {
172 vt_char_t *src;
173 u_int src_len;
174 vt_char_t *dst;
175 int src_pos;
176
177 if (line->ctl_info.iscii->size == 0 || !line->ctl_info.iscii->has_iscii) {
178 #ifdef __DEBUG
179 bl_warn_printf(BL_DEBUG_TAG " Not need to logicalize.\n");
180 #endif
181
182 return 1;
183 }
184
185 src_len = line->num_filled_chars;
186 if ((src = vt_str_alloca(src_len)) == NULL) {
187 return 0;
188 }
189 vt_str_init(src, src_len);
190 vt_str_copy(src, line->chars, src_len);
191 dst = line->chars;
192
193 for (src_pos = 0; src_pos < line->ctl_info.iscii->size; src_pos++) {
194 vt_char_t *comb;
195 u_int num;
196
197 if (line->ctl_info.iscii->num_chars_array[src_pos] == 0) {
198 continue;
199 } else if (line->ctl_info.iscii->num_chars_array[src_pos] == 1) {
200 vt_char_copy(dst, src + src_pos);
201 } else {
202 vt_char_copy(dst, vt_get_base_char(src + src_pos));
203
204 comb = vt_get_combining_chars(src + src_pos, &num);
205 for (; num > 0; num--, comb++) {
206 if (vt_char_is_comb(comb)) {
207 vt_char_combine_simple(dst, comb);
208 } else {
209 vt_char_copy(++dst, comb);
210 }
211 }
212 }
213
214 dst++;
215 }
216
217 vt_str_final(src, src_len);
218
219 line->num_filled_chars = dst - line->chars;
220
221 return 1;
222 }
223
224 /* The caller should check vt_line_is_using_iscii() in advance. */
vt_line_iscii_convert_logical_char_index_to_visual(vt_line_t * line,int logical_char_index)225 int vt_line_iscii_convert_logical_char_index_to_visual(vt_line_t *line, int logical_char_index) {
226 int visual_char_index;
227
228 if (vt_line_is_empty(line)) {
229 return 0;
230 }
231
232 if (line->ctl_info.iscii->size == 0 || !line->ctl_info.iscii->has_iscii) {
233 #ifdef __DEBUG
234 bl_debug_printf(BL_DEBUG_TAG " logical char_index is same as visual one.\n");
235 #endif
236 return logical_char_index;
237 }
238
239 for (visual_char_index = 0; visual_char_index < line->ctl_info.iscii->size; visual_char_index++) {
240 if (logical_char_index == 0 ||
241 (logical_char_index -= line->ctl_info.iscii->num_chars_array[visual_char_index]) < 0) {
242 break;
243 }
244 }
245
246 return visual_char_index;
247 }
248
249 /* The caller should check vt_line_is_using_iscii() in advance. */
vt_line_iscii_convert_visual_char_index_to_logical(vt_line_t * line,int visual_char_index)250 int vt_line_iscii_convert_visual_char_index_to_logical(vt_line_t *line,
251 int visual_char_index) {
252 int logical_char_index;
253 int count;
254
255 if (vt_line_is_empty(line)) {
256 return 0;
257 }
258
259 if (line->ctl_info.iscii->size == 0 || !line->ctl_info.iscii->has_iscii) {
260 #ifdef __DEBUG
261 bl_debug_printf(BL_DEBUG_TAG " visual char_index is same as logical one.\n");
262 #endif
263 return visual_char_index;
264 }
265
266 if (line->ctl_info.iscii->size - 1 < visual_char_index) {
267 visual_char_index = line->ctl_info.iscii->size - 1;
268 }
269
270 logical_char_index = 0;
271 for (count = 0; count < visual_char_index; count++) {
272 logical_char_index += line->ctl_info.iscii->num_chars_array[count];
273 }
274
275 return logical_char_index;
276 }
277
vt_line_iscii_need_shape(vt_line_t * line)278 int vt_line_iscii_need_shape(vt_line_t *line) {
279 return line->ctl_info.iscii->size > 0 && line->ctl_info.iscii->has_iscii;
280 }
281