FreeCalypso > hg > falcon-mail-tools
comparison f-demime/ptext_in.c @ 0:7e0d08176f32
f-demime starting code
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 06 May 2023 06:14:03 +0000 |
parents | |
children | 05651a1b8ba8 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7e0d08176f32 |
---|---|
1 /* | |
2 * This module implements transformations that are specific to text/plain. | |
3 */ | |
4 | |
5 #include <sys/types.h> | |
6 #include <stdio.h> | |
7 #include <stdlib.h> | |
8 #include <string.h> | |
9 #include <strings.h> | |
10 #include "defs.h" | |
11 | |
12 extern void (*dec_outf)(); | |
13 extern FILE *tempfile; | |
14 extern int text_is_utf8; | |
15 | |
16 int ptext_has_backslash, ptext_has_linesplit; | |
17 | |
18 static enum { | |
19 FPS_GROUND, | |
20 FPS_CR, | |
21 FPS_UTF8 | |
22 } first_pass_state; | |
23 static u_char utf8_buf[4]; | |
24 static unsigned utf8_nbytes, utf8_wptr, unicode; | |
25 static unsigned out_line_len, trailing_newline; | |
26 | |
27 static void | |
28 unit_output(str) | |
29 char *str; | |
30 { | |
31 unsigned newlen; | |
32 | |
33 newlen = strlen(str); | |
34 if (out_line_len + newlen >= OUTPUT_LINE_MAX) | |
35 putc('\\', tempfile); | |
36 putc('\n', tempfile); | |
37 out_line_len = 0; | |
38 ptext_has_linesplit = 1; | |
39 } | |
40 fputs(str, tempfile); | |
41 out_line_len += newlen; | |
42 trailing_newline = 0; | |
43 } | |
44 | |
45 static void | |
46 newline_out() | |
47 { | |
48 putc('\n', tempfile); | |
49 out_line_len = 0; | |
50 trailing_newline++; | |
51 if (trailing_newline > 2) | |
52 trailing_newline = 2; | |
53 } | |
54 | |
55 static void | |
56 direct_output(ch) | |
57 { | |
58 char buf[2]; | |
59 | |
60 buf[0] = ch; | |
61 buf[1] = '\0'; | |
62 unit_output(buf); | |
63 } | |
64 | |
65 static void | |
66 simple_escape(ch) | |
67 { | |
68 char buf[3]; | |
69 | |
70 buf[0] = '\\'; | |
71 buf[1] = ch; | |
72 buf[2] = '\0'; | |
73 unit_output(buf); | |
74 } | |
75 | |
76 static void | |
77 hex_escape(ch) | |
78 { | |
79 char buf[5]; | |
80 | |
81 sprintf(buf, "\\x%02X", ch); | |
82 unit_output(buf); | |
83 } | |
84 | |
85 static void | |
86 regular_byte(ch) | |
87 { | |
88 if (ch == '\\') { | |
89 ptext_has_backslash = 1; | |
90 simple_escape(ch); | |
91 return; | |
92 } | |
93 if (ch >= ' ' && ch <= '~') { | |
94 direct_output(ch); | |
95 return; | |
96 } | |
97 switch (ch) { | |
98 case 0x07: | |
99 simple_escape('a'); | |
100 return; | |
101 case 0x08': | |
102 simple_escape('b'); | |
103 return; | |
104 case 0x09: | |
105 direct_output(ch); | |
106 return; | |
107 case 0x0B: | |
108 simple_escape('v'); | |
109 return; | |
110 case 0x0C: | |
111 simple_escape('f'); | |
112 return; | |
113 case 0x0D: | |
114 simple_escape('r'); | |
115 return; | |
116 case 0x1B: | |
117 simple_escape('e'); | |
118 return; | |
119 } | |
120 hex_escape(ch); | |
121 } | |
122 | |
123 static int | |
124 utf8_collect() | |
125 { | |
126 switch (utf8_nbytes) { | |
127 case 2: | |
128 unicode = ((utf8_buf[0] & 0x1F) << 6) | (utf8_buf[1] & 0x3F); | |
129 return(1); | |
130 case 3: | |
131 unicode = ((utf8_buf[0] & 0x0F) << 12) | | |
132 ((utf8_buf[1] & 0x3F) << 6) | (utf8_buf[2] & 0x3F); | |
133 if (unicode & 0xF800) | |
134 return(1); | |
135 else | |
136 return(0); | |
137 case 4: | |
138 unicode = ((utf8_buf[0] & 0x07) << 18) | | |
139 ((utf8_buf[1] & 0x3F) << 12) | | |
140 ((utf8_buf[2] & 0x3F) << 6) | (utf8_buf[3] & 0x3F); | |
141 if (unicode & 0x1F0000) | |
142 return(1); | |
143 else | |
144 return(0); | |
145 default: | |
146 return(0); | |
147 } | |
148 } | |
149 | |
150 static void | |
151 unicode_out() | |
152 { | |
153 char buf[9]; | |
154 | |
155 if (unicode >= 0x10000) | |
156 sprintf(buf, "\\U%06u", unicode); | |
157 else | |
158 sprintf(buf, "\\u%04u", unicode); | |
159 unit_output(buf); | |
160 } | |
161 | |
162 static void | |
163 flush_first_pass_state() | |
164 { | |
165 unsigned n; | |
166 | |
167 switch (first_pass_state) { | |
168 case FPS_CR: | |
169 regular_byte('\r'); | |
170 break; | |
171 case FPS_UTF8: | |
172 for (n = 0; n < utf8_wptr; n++) | |
173 regular_byte(utf8_buf[n]); | |
174 break; | |
175 } | |
176 first_pass_state = FPS_GROUND; | |
177 } | |
178 | |
179 static void | |
180 first_pass(ch) | |
181 { | |
182 if (first_pass_state == FPS_CR && ch == '\n') { | |
183 first_pass_state = FPS_GROUND; | |
184 newline_out(); | |
185 return; | |
186 } | |
187 if (first_pass_state == FPS_UTF8 && ch >= 0x80 && ch <= 0xBF) { | |
188 utf8_buf[utf8_wptr++] = ch; | |
189 if (utf8_wptr < utf8_nbytes) | |
190 return; | |
191 if (utf8_collect()) { | |
192 first_pass_state = FPS_GROUND; | |
193 unicode_out(); | |
194 return; | |
195 } | |
196 } | |
197 flush_first_pass_state(); | |
198 switch (ch) { | |
199 case '\n': | |
200 newline_out(); | |
201 return; | |
202 case '\r': | |
203 first_pass_state = FPS_CR; | |
204 return; | |
205 } | |
206 if (!text_is_utf8 || ch < 0xC2 || ch > 0xF7) { | |
207 regular_byte(ch); | |
208 return; | |
209 } | |
210 first_pass_state = FPS_UTF8; | |
211 utf8_buf[0] = ch; | |
212 utf8_wptr = 1; | |
213 if (ch < 0xE0) | |
214 utf8_nbytes = 2; | |
215 else if (ch < 0xF0) | |
216 utf8_nbytes = 3; | |
217 else | |
218 utf8_nbytes = 4; | |
219 } | |
220 | |
221 void | |
222 ptext_conv_init() | |
223 { | |
224 dec_outf = first_pass; | |
225 ptext_has_backslash = 0; | |
226 ptext_has_linesplit = 0; | |
227 first_pass_state = FPS_GROUND; | |
228 out_line_len = 0; | |
229 trailing_newline = 1; | |
230 } | |
231 | |
232 void | |
233 ptext_conv_finish() | |
234 { | |
235 flush_first_pass_state(); | |
236 while (trailing_newline < 2) { | |
237 putc('\n', tempfile); | |
238 trailing_newline++; | |
239 } | |
240 } |