1 /*
2 psftools: Manipulate console fonts in the .PSF format
3 Copyright (C) 2003 John Elliott
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 #include "cnvshell.h"
20 #include "psflib.h"
21
22 /* Convert a PSF font to a Hercules WriteOn font.
23 *
24 */
25
26 static char helpbuf[2048];
27 static int first = -1;
28 static int last = -1;
29
30 static PSF_FILE psf;
31 static PSF_MAPPING *codepage = NULL;
32
33 /* Program name */
34 char *cnv_progname = "PSF2WOF";
35
36 /* ddash = 1 if option started with a double-dash; else 0 */
37 /* Return NULL if OK, else error string */
cnv_set_option(int ddash,char * variable,char * value)38 char *cnv_set_option(int ddash, char *variable, char *value)
39 {
40 if (!stricmp(variable, "first")) { first = atoi(value); return NULL; }
41 if (!stricmp(variable, "last")) { last = atoi(value); return NULL; }
42 if (!stricmp(variable, "256")) { first = 0; last = 255; return NULL; }
43 if (!stricmp(variable, "codepage"))
44 {
45 codepage = psf_find_mapping(value);
46 if (codepage == NULL) return "Code page name not recognised.";
47 return NULL;
48 }
49 if (strlen(variable) > 2000) variable[2000] = 0;
50 sprintf(helpbuf, "Unknown option: %s\n", variable);
51 return helpbuf;
52 }
53
54
55 /* Return help string */
cnv_help(void)56 char *cnv_help(void)
57 {
58 sprintf(helpbuf, "Converts a PSF font to a Hercules WriteOn font.\n"
59 "Syntax: %s psffile woffile { options }\n\n",
60 cnv_progname);
61 strcat (helpbuf, "Options: \n"
62 " --first=n Start with character n\n"
63 " --last=n Finish with character n\n"
64 " --256 Equivalent to --first=0 --last=255\n");
65
66 return helpbuf;
67 }
68
69
70 unsigned char wof_head[] =
71 {
72 0x45, 0x53, 0x01, 0x00, /* magic */
73 0x16, 0x00, /* sizeof(wof_head) */
74 0x00, 0x00, /* width */
75 0x00, 0x00, /* height */
76 0x0E, 0x00, /* 14 in all WOF files */
77 0x00, 0x00, /* first char */
78 0x00, 0x00, /* last char */
79 0x00, 0x00, /* Always 0? */
80 0x00, 0x00, /* width again? */
81 0x00, 0x00, /* Always 0? */
82 };
83
cnv_execute(FILE * infile,FILE * outfile)84 char *cnv_execute(FILE *infile, FILE *outfile)
85 {
86 int rv;
87 psf_dword ch, f, l, glyph, z;
88
89 psf_file_new(&psf);
90 rv = psf_file_read(&psf, infile);
91
92 if (rv != PSF_E_OK) return psf_error_string(rv);
93 if (codepage && !psf_is_unicode(&psf))
94 {
95 psf_file_delete(&psf);
96 return "Cannot extract by codepage; source file has no Unicode table";
97 }
98
99 f = (first >= 0) ? first : 0;
100 l = (last >= 0) ? last : (psf.psf_length - 1);
101 if (codepage && l >= 256) l = 255;
102 if (l >= psf.psf_length) l = psf.psf_length;
103
104 /* Create .WOF header */
105 wof_head[6] = psf.psf_width & 0xFF;
106 wof_head[7] = psf.psf_width >> 8;
107 wof_head[8] = psf.psf_height & 0xFF;
108 wof_head[9] = psf.psf_height >> 8;
109 wof_head[12] = f & 0xFF;
110 wof_head[13] = f >> 8;
111 wof_head[14] = l & 0xFF;
112 wof_head[15] = l >> 8;
113 wof_head[18] = psf.psf_width & 0xFF;
114 wof_head[19] = psf.psf_width >> 8;
115
116 if (fwrite(wof_head, 1, sizeof(wof_head), outfile) < (int)sizeof(wof_head))
117 {
118 psf_file_delete(&psf);
119 return "Could not write to output.";
120 }
121 for (ch = f; ch <= l; ch++)
122 {
123 psf_byte *src;
124
125 if (codepage)
126 {
127 if (ch < 256 && !psf_unicode_lookupmap(&psf, codepage,
128 ch, &glyph, NULL))
129 {
130 src = psf.psf_data + glyph * psf.psf_charlen;
131 }
132 else
133 {
134 if (ch < 256 && !psf_unicode_banned(codepage->psfm_tokens[ch][0])) fprintf(stderr, "Warning: U+%04lx not found in font\n", codepage->psfm_tokens[ch][0]);
135 src = NULL;
136 }
137 }
138 else src = psf.psf_data + ch * psf.psf_charlen;
139
140 if (!src) for (z = 0; z < psf.psf_charlen; z++)
141 {
142 if (fputc(0, outfile) == EOF)
143 {
144 psf_file_delete(&psf);
145 return "Could not write to output.";
146 }
147 }
148 else if (fwrite(src, 1, psf.psf_charlen, outfile) <
149 psf.psf_charlen)
150 {
151 psf_file_delete(&psf);
152 return "Could not write to output.";
153 }
154 }
155 psf_file_delete(&psf);
156 return NULL;
157 }
158
159