Deleted Added
full compact
vtfontcvt.c (259019) vtfontcvt.c (259680)
1/*-
2 * Copyright (c) 2009 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Ed Schouten under sponsorship from the
6 * FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 14 unchanged lines hidden (view full) ---

23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Ed Schouten under sponsorship from the
6 * FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 14 unchanged lines hidden (view full) ---

23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/tools/tools/vt/fontcvt/fontcvt.c 219888 2011-03-22 21:31:31Z ed $");
31__FBSDID("$FreeBSD: head/tools/tools/vt/fontcvt/fontcvt.c 259680 2013-12-21 13:58:55Z emaste $");
32
33#include <sys/endian.h>
34#include <sys/param.h>
35#include <sys/queue.h>
36
37#include <assert.h>
38#include <stdint.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42
32
33#include <sys/endian.h>
34#include <sys/param.h>
35#include <sys/queue.h>
36
37#include <assert.h>
38#include <stdint.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42
43#define VFNT_MAPS 4
44#define VFNT_MAP_NORMAL 0
45#define VFNT_MAP_BOLD 2
46
43static unsigned int width, wbytes, height;
44
45struct glyph {
46 TAILQ_ENTRY(glyph) g_list;
47 uint8_t *g_data;
48 unsigned int g_index;
49};
50
47static unsigned int width, wbytes, height;
48
49struct glyph {
50 TAILQ_ENTRY(glyph) g_list;
51 uint8_t *g_data;
52 unsigned int g_index;
53};
54
51static TAILQ_HEAD(, glyph) glyph_list = TAILQ_HEAD_INITIALIZER(glyph_list);
52static unsigned int glyph_total, glyph_normal, glyph_bold,
53 glyph_unique, glyph_dupe;
55TAILQ_HEAD(glyph_list, glyph);
56static struct glyph_list glyphs[VFNT_MAPS] = {
57 TAILQ_HEAD_INITIALIZER(glyphs[0]),
58 TAILQ_HEAD_INITIALIZER(glyphs[1]),
59 TAILQ_HEAD_INITIALIZER(glyphs[2]),
60 TAILQ_HEAD_INITIALIZER(glyphs[3]),
61};
62static unsigned int glyph_total, glyph_count[4], glyph_unique, glyph_dupe;
54
55struct mapping {
56 TAILQ_ENTRY(mapping) m_list;
57 unsigned int m_char;
58 unsigned int m_length;
59 struct glyph *m_glyph;
60};
61
62TAILQ_HEAD(mapping_list, mapping);
63
64struct mapping {
65 TAILQ_ENTRY(mapping) m_list;
66 unsigned int m_char;
67 unsigned int m_length;
68 struct glyph *m_glyph;
69};
70
71TAILQ_HEAD(mapping_list, mapping);
63static struct mapping_list mapping_list_normal =
64 TAILQ_HEAD_INITIALIZER(mapping_list_normal);
65static struct mapping_list mapping_list_bold =
66 TAILQ_HEAD_INITIALIZER(mapping_list_bold);
67static unsigned int mapping_total, mapping_normal, mapping_normal_folded,
68 mapping_bold, mapping_bold_folded, mapping_unique, mapping_dupe;
72static struct mapping_list maps[VFNT_MAPS] = {
73 TAILQ_HEAD_INITIALIZER(maps[0]),
74 TAILQ_HEAD_INITIALIZER(maps[1]),
75 TAILQ_HEAD_INITIALIZER(maps[2]),
76 TAILQ_HEAD_INITIALIZER(maps[3]),
77};
78static unsigned int mapping_total, map_count[4], map_folded_count[4],
79 mapping_unique, mapping_dupe;
69
70static void
71usage(void)
72{
73
74 fprintf(stderr,
75"usage: fontcvt width height normal.bdf bold.bdf out.fnt\n");
76 exit(1);
77}
78
79static int
80
81static void
82usage(void)
83{
84
85 fprintf(stderr,
86"usage: fontcvt width height normal.bdf bold.bdf out.fnt\n");
87 exit(1);
88}
89
90static int
80add_mapping(struct glyph *gl, unsigned int c, int bold)
91add_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx)
81{
82 struct mapping *mp;
83 struct mapping_list *ml;
84
85 mapping_total++;
86
92{
93 struct mapping *mp;
94 struct mapping_list *ml;
95
96 mapping_total++;
97
87 if (bold) {
98 if (map_idx >= VFNT_MAP_BOLD) {
88 int found = 0;
99 int found = 0;
100 unsigned normal_map_idx = map_idx - VFNT_MAP_BOLD;
89
101
90 TAILQ_FOREACH(mp, &mapping_list_normal, m_list) {
102 TAILQ_FOREACH(mp, &maps[normal_map_idx], m_list) {
91 if (mp->m_char < c)
92 continue;
93 else if (mp->m_char > c)
94 break;
95 found = 1;
96
97 /*
98 * No mapping is needed if it's equal to the

--- 12 unchanged lines hidden (view full) ---

111 }
112 }
113
114 mp = malloc(sizeof *mp);
115 mp->m_char = c;
116 mp->m_glyph = gl;
117 mp->m_length = 0;
118
103 if (mp->m_char < c)
104 continue;
105 else if (mp->m_char > c)
106 break;
107 found = 1;
108
109 /*
110 * No mapping is needed if it's equal to the

--- 12 unchanged lines hidden (view full) ---

123 }
124 }
125
126 mp = malloc(sizeof *mp);
127 mp->m_char = c;
128 mp->m_glyph = gl;
129 mp->m_length = 0;
130
119 ml = bold ? &mapping_list_bold : &mapping_list_normal;
131 ml = &maps[map_idx];
120 if (TAILQ_LAST(ml, mapping_list) != NULL &&
121 TAILQ_LAST(ml, mapping_list)->m_char >= c) {
122 fprintf(stderr, "Bad ordering at character %u\n", c);
123 return (1);
124 }
125 TAILQ_INSERT_TAIL(ml, mp, m_list);
126
132 if (TAILQ_LAST(ml, mapping_list) != NULL &&
133 TAILQ_LAST(ml, mapping_list)->m_char >= c) {
134 fprintf(stderr, "Bad ordering at character %u\n", c);
135 return (1);
136 }
137 TAILQ_INSERT_TAIL(ml, mp, m_list);
138
127 if (bold)
128 mapping_bold++;
129 else
130 mapping_normal++;
139 map_count[map_idx]++;
131 mapping_unique++;
132
133 return (0);
134}
135
136static struct glyph *
140 mapping_unique++;
141
142 return (0);
143}
144
145static struct glyph *
137add_glyph(const uint8_t *bytes, int bold, int fallback)
146add_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback)
138{
139 struct glyph *gl;
147{
148 struct glyph *gl;
149 unsigned int i;
140
141 glyph_total++;
150
151 glyph_total++;
142 if (bold)
143 glyph_bold++;
144 else
145 glyph_normal++;
152 glyph_count[map_idx]++;
146
153
147 TAILQ_FOREACH(gl, &glyph_list, g_list) {
148 if (memcmp(gl->g_data, bytes, wbytes * height) == 0) {
149 glyph_dupe++;
150 return (gl);
154 for (i = 0; i < VFNT_MAPS; i++) {
155 TAILQ_FOREACH(gl, &glyphs[i], g_list) {
156 if (memcmp(gl->g_data, bytes, wbytes * height) == 0) {
157 glyph_dupe++;
158 return (gl);
159 }
151 }
152 }
153
154 gl = malloc(sizeof *gl);
155 gl->g_data = malloc(wbytes * height);
156 memcpy(gl->g_data, bytes, wbytes * height);
157 if (fallback)
160 }
161 }
162
163 gl = malloc(sizeof *gl);
164 gl->g_data = malloc(wbytes * height);
165 memcpy(gl->g_data, bytes, wbytes * height);
166 if (fallback)
158 TAILQ_INSERT_HEAD(&glyph_list, gl, g_list);
167 TAILQ_INSERT_HEAD(&glyphs[map_idx], gl, g_list);
159 else
168 else
160 TAILQ_INSERT_TAIL(&glyph_list, gl, g_list);
169 TAILQ_INSERT_TAIL(&glyphs[map_idx], gl, g_list);
161
162 glyph_unique++;
163 return (gl);
164}
165
166static int
170
171 glyph_unique++;
172 return (gl);
173}
174
175static int
167parse_bdf(const char *filename, int bold __unused)
176parse_bitmap_line(uint8_t *left, uint8_t *right, unsigned int line,
177 unsigned int dwidth)
168{
178{
179 uint8_t *p;
180 unsigned int i, subline;
181
182 if (dwidth != width && dwidth != width * 2) {
183 fprintf(stderr,
184 "Unsupported width %u!\n", dwidth);
185 return (1);
186 }
187
188 /* Move pixel data right to simplify splitting double characters. */
189 line >>= (howmany(dwidth, 8) * 8) - dwidth;
190
191 for (i = dwidth / width; i > 0; i--) {
192 p = (i == 2) ? right : left;
193
194 subline = line & ((1 << width) - 1);
195 subline <<= (howmany(width, 8) * 8) - width;
196
197 if (wbytes == 1) {
198 *p = subline;
199 } else if (wbytes == 2) {
200 *p++ = subline >> 8;
201 *p = subline;
202 } else {
203 fprintf(stderr,
204 "Unsupported wbytes %u!\n", wbytes);
205 return (1);
206 }
207
208 line >>= width;
209 }
210
211 return (0);
212}
213
214static int
215parse_bdf(const char *filename, unsigned int map_idx)
216{
169 FILE *fp;
170 char *ln;
171 size_t length;
217 FILE *fp;
218 char *ln;
219 size_t length;
172 uint8_t bytes[wbytes * height];
173 unsigned int curchar = 0, i, line;
220 uint8_t bytes[wbytes * height], bytes_r[wbytes * height];
221 unsigned int curchar = 0, dwidth = 0, i, line;
174 struct glyph *gl;
175
176 fp = fopen(filename, "r");
177 if (fp == NULL) {
178 perror(filename);
179 return (1);
180 }
181
182 while ((ln = fgetln(fp, &length)) != NULL) {
183 ln[length - 1] = '\0';
184
185 if (strncmp(ln, "ENCODING ", 9) == 0) {
186 curchar = atoi(ln + 9);
187 }
188
222 struct glyph *gl;
223
224 fp = fopen(filename, "r");
225 if (fp == NULL) {
226 perror(filename);
227 return (1);
228 }
229
230 while ((ln = fgetln(fp, &length)) != NULL) {
231 ln[length - 1] = '\0';
232
233 if (strncmp(ln, "ENCODING ", 9) == 0) {
234 curchar = atoi(ln + 9);
235 }
236
237 if (strncmp(ln, "DWIDTH ", 7) == 0) {
238 dwidth = atoi(ln + 7);
239 }
240
189 if (strcmp(ln, "BITMAP") == 0) {
190 for (i = 0; i < height; i++) {
191 if ((ln = fgetln(fp, &length)) == NULL) {
192 fprintf(stderr, "Unexpected EOF!\n");
193 return (1);
194 }
195 ln[length - 1] = '\0';
196 sscanf(ln, "%x", &line);
241 if (strcmp(ln, "BITMAP") == 0) {
242 for (i = 0; i < height; i++) {
243 if ((ln = fgetln(fp, &length)) == NULL) {
244 fprintf(stderr, "Unexpected EOF!\n");
245 return (1);
246 }
247 ln[length - 1] = '\0';
248 sscanf(ln, "%x", &line);
197 if (wbytes == 1) {
198 bytes[i] = line;
199 } else if (wbytes == 2) {
200 bytes[i * 2 + 0] = line >> 8;
201 bytes[i * 2 + 1] = line;
202 } else {
203 fprintf(stderr,
204 "Unsupported wbytes!\n");
249 if (parse_bitmap_line(bytes + i * wbytes,
250 bytes_r + i * wbytes, line, dwidth) != 0)
205 return (1);
251 return (1);
206 }
207 }
208
209 /* Prevent adding two glyphs for 0xFFFD */
210 if (curchar == 0xFFFD) {
252 }
253
254 /* Prevent adding two glyphs for 0xFFFD */
255 if (curchar == 0xFFFD) {
211 if (!bold)
212 gl = add_glyph(bytes, bold, 1);
256 if (map_idx < VFNT_MAP_BOLD)
257 gl = add_glyph(bytes, 0, 1);
213 } else if (curchar >= 0x20) {
258 } else if (curchar >= 0x20) {
214 gl = add_glyph(bytes, bold, 0);
215 if (add_mapping(gl, curchar, bold) != 0)
259 gl = add_glyph(bytes, map_idx, 0);
260 if (add_mapping(gl, curchar, map_idx) != 0)
216 return (1);
261 return (1);
262 if (dwidth == width * 2) {
263 gl = add_glyph(bytes_r, map_idx + 1, 0);
264 if (add_mapping(gl, curchar,
265 map_idx + 1) != 0)
266 return (1);
267 }
217 }
218 }
219 }
220
221 return (0);
222}
223
224static void
225number_glyphs(void)
226{
227 struct glyph *gl;
268 }
269 }
270 }
271
272 return (0);
273}
274
275static void
276number_glyphs(void)
277{
278 struct glyph *gl;
228 unsigned int idx = 0;
279 unsigned int i, idx = 0;
229
280
230 TAILQ_FOREACH(gl, &glyph_list, g_list)
231 gl->g_index = idx++;
281 for (i = 0; i < VFNT_MAPS; i++)
282 TAILQ_FOREACH(gl, &glyphs[i], g_list)
283 gl->g_index = idx++;
232}
233
234static void
235write_glyphs(FILE *fp)
236{
237 struct glyph *gl;
284}
285
286static void
287write_glyphs(FILE *fp)
288{
289 struct glyph *gl;
290 unsigned int i;
238
291
239 TAILQ_FOREACH(gl, &glyph_list, g_list)
240 fwrite(gl->g_data, wbytes * height, 1, fp);
292 for (i = 0; i < VFNT_MAPS; i++) {
293 TAILQ_FOREACH(gl, &glyphs[i], g_list)
294 fwrite(gl->g_data, wbytes * height, 1, fp);
295 }
241}
242
243static void
296}
297
298static void
244fold_mappings(int bold)
299fold_mappings(unsigned int map_idx)
245{
300{
246 struct mapping_list *ml;
301 struct mapping_list *ml = &maps[map_idx];
247 struct mapping *mn, *mp, *mbase;
248
302 struct mapping *mn, *mp, *mbase;
303
249 if (bold)
250 ml = &mapping_list_bold;
251 else
252 ml = &mapping_list_normal;
253
254 mp = mbase = TAILQ_FIRST(ml);
255 for (mp = mbase = TAILQ_FIRST(ml); mp != NULL; mp = mn) {
256 mn = TAILQ_NEXT(mp, m_list);
257 if (mn != NULL && mn->m_char == mp->m_char + 1 &&
258 mn->m_glyph->g_index == mp->m_glyph->g_index + 1)
259 continue;
260 mbase->m_length = mp->m_char - mbase->m_char + 1;
261 mbase = mp = mn;
304 mp = mbase = TAILQ_FIRST(ml);
305 for (mp = mbase = TAILQ_FIRST(ml); mp != NULL; mp = mn) {
306 mn = TAILQ_NEXT(mp, m_list);
307 if (mn != NULL && mn->m_char == mp->m_char + 1 &&
308 mn->m_glyph->g_index == mp->m_glyph->g_index + 1)
309 continue;
310 mbase->m_length = mp->m_char - mbase->m_char + 1;
311 mbase = mp = mn;
262 if (bold)
263 mapping_bold_folded++;
264 else
265 mapping_normal_folded++;
312 map_folded_count[map_idx]++;
266 }
267}
268
269struct file_mapping {
270 uint32_t source;
271 uint16_t destination;
272 uint16_t length;
273} __packed;
274
275static void
313 }
314}
315
316struct file_mapping {
317 uint32_t source;
318 uint16_t destination;
319 uint16_t length;
320} __packed;
321
322static void
276write_mappings(FILE *fp, int bold)
323write_mappings(FILE *fp, unsigned int map_idx)
277{
324{
278 struct mapping_list *ml;
325 struct mapping_list *ml = &maps[map_idx];
279 struct mapping *mp;
280 struct file_mapping fm;
281 unsigned int i = 0, j = 0;
282
326 struct mapping *mp;
327 struct file_mapping fm;
328 unsigned int i = 0, j = 0;
329
283 if (bold)
284 ml = &mapping_list_bold;
285 else
286 ml = &mapping_list_normal;
287
288 TAILQ_FOREACH(mp, ml, m_list) {
289 j++;
290 if (mp->m_length > 0) {
291 i += mp->m_length;
292 fm.source = htobe32(mp->m_char);
293 fm.destination = htobe16(mp->m_glyph->g_index);
294 fm.length = htobe16(mp->m_length - 1);
295 fwrite(&fm, sizeof fm, 1, fp);
296 }
297 }
298 assert(i == j);
299}
300
301struct file_header {
302 uint8_t magic[8];
303 uint8_t width;
304 uint8_t height;
330 TAILQ_FOREACH(mp, ml, m_list) {
331 j++;
332 if (mp->m_length > 0) {
333 i += mp->m_length;
334 fm.source = htobe32(mp->m_char);
335 fm.destination = htobe16(mp->m_glyph->g_index);
336 fm.length = htobe16(mp->m_length - 1);
337 fwrite(&fm, sizeof fm, 1, fp);
338 }
339 }
340 assert(i == j);
341}
342
343struct file_header {
344 uint8_t magic[8];
345 uint8_t width;
346 uint8_t height;
305 uint16_t nglyphs;
306 uint16_t nmappings_normal;
307 uint16_t nmappings_bold;
347 uint16_t pad;
348 uint32_t glyph_count;
349 uint32_t map_count[4];
308} __packed;
309
310static int
311write_fnt(const char *filename)
312{
313 FILE *fp;
314 struct file_header fh = {
350} __packed;
351
352static int
353write_fnt(const char *filename)
354{
355 FILE *fp;
356 struct file_header fh = {
315 .magic = "VFNT 1.0",
357 .magic = "VFNT0002",
316 };
317
318 fp = fopen(filename, "wb");
319 if (fp == NULL) {
320 perror(filename);
321 return (1);
322 }
323
324 fh.width = width;
325 fh.height = height;
358 };
359
360 fp = fopen(filename, "wb");
361 if (fp == NULL) {
362 perror(filename);
363 return (1);
364 }
365
366 fh.width = width;
367 fh.height = height;
326 fh.nglyphs = htobe16(glyph_unique);
327 fh.nmappings_normal = htobe16(mapping_normal_folded);
328 fh.nmappings_bold = htobe16(mapping_bold_folded);
368 fh.glyph_count = htobe32(glyph_unique);
369 fh.map_count[0] = htobe32(map_folded_count[0]);
370 fh.map_count[1] = htobe32(map_folded_count[1]);
371 fh.map_count[2] = htobe32(map_folded_count[2]);
372 fh.map_count[3] = htobe32(map_folded_count[3]);
329 fwrite(&fh, sizeof fh, 1, fp);
330
331 write_glyphs(fp);
373 fwrite(&fh, sizeof fh, 1, fp);
374
375 write_glyphs(fp);
332 write_mappings(fp, 0);
376 write_mappings(fp, VFNT_MAP_NORMAL);
333 write_mappings(fp, 1);
377 write_mappings(fp, 1);
378 write_mappings(fp, VFNT_MAP_BOLD);
379 write_mappings(fp, 3);
334
335 return (0);
336}
337
338int
339main(int argc, char *argv[])
340{
341
380
381 return (0);
382}
383
384int
385main(int argc, char *argv[])
386{
387
342 assert(sizeof(struct file_header) == 16);
388 assert(sizeof(struct file_header) == 32);
343 assert(sizeof(struct file_mapping) == 8);
344
345 if (argc != 6)
346 usage();
347
348 width = atoi(argv[1]);
349 wbytes = howmany(width, 8);
350 height = atoi(argv[2]);
351
389 assert(sizeof(struct file_mapping) == 8);
390
391 if (argc != 6)
392 usage();
393
394 width = atoi(argv[1]);
395 wbytes = howmany(width, 8);
396 height = atoi(argv[2]);
397
352 if (parse_bdf(argv[3], 0) != 0)
398 if (parse_bdf(argv[3], VFNT_MAP_NORMAL) != 0)
353 return (1);
399 return (1);
354 if (parse_bdf(argv[4], 1) != 0)
400 if (parse_bdf(argv[4], VFNT_MAP_BOLD) != 0)
355 return (1);
356 number_glyphs();
357 fold_mappings(0);
358 fold_mappings(1);
401 return (1);
402 number_glyphs();
403 fold_mappings(0);
404 fold_mappings(1);
405 fold_mappings(2);
406 fold_mappings(3);
359 if (write_fnt(argv[5]) != 0)
360 return (1);
361
362 printf(
363"Statistics:\n"
407 if (write_fnt(argv[5]) != 0)
408 return (1);
409
410 printf(
411"Statistics:\n"
364"- glyph_total: %5u\n"
365"- glyph_normal: %5u\n"
366"- glyph_bold: %5u\n"
367"- glyph_unique: %5u\n"
368"- glyph_dupe: %5u\n"
369"- mapping_total: %5u\n"
370"- mapping_normal: %5u\n"
371"- mapping_normal_folded: %5u\n"
372"- mapping_bold: %5u\n"
373"- mapping_bold_folded: %5u\n"
374"- mapping_unique: %5u\n"
375"- mapping_dupe: %5u\n",
412"- glyph_total: %5u\n"
413"- glyph_normal: %5u\n"
414"- glyph_normal_right: %5u\n"
415"- glyph_bold: %5u\n"
416"- glyph_bold_right: %5u\n"
417"- glyph_unique: %5u\n"
418"- glyph_dupe: %5u\n"
419"- mapping_total: %5u\n"
420"- mapping_normal: %5u\n"
421"- mapping_normal_folded: %5u\n"
422"- mapping_normal_right: %5u\n"
423"- mapping_normal_right_folded: %5u\n"
424"- mapping_bold: %5u\n"
425"- mapping_bold_folded: %5u\n"
426"- mapping_bold_right: %5u\n"
427"- mapping_bold_right_folded: %5u\n"
428"- mapping_unique: %5u\n"
429"- mapping_dupe: %5u\n",
376 glyph_total,
430 glyph_total,
377 glyph_normal, glyph_bold,
431 glyph_count[0],
432 glyph_count[1],
433 glyph_count[2],
434 glyph_count[3],
378 glyph_unique, glyph_dupe,
379 mapping_total,
435 glyph_unique, glyph_dupe,
436 mapping_total,
380 mapping_normal, mapping_normal_folded,
381 mapping_bold, mapping_bold_folded,
437 map_count[0], map_folded_count[0],
438 map_count[1], map_folded_count[1],
439 map_count[2], map_folded_count[2],
440 map_count[3], map_folded_count[3],
382 mapping_unique, mapping_dupe);
383
384 return (0);
385}
441 mapping_unique, mapping_dupe);
442
443 return (0);
444}