1 /*
2 psftools: Manipulate console fonts in the .PSF format
3 Copyright (C) 2003, 2005 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 raw font (as used by DOS font editors etc.)
23 */
24
25 static char helpbuf[2048];
26 static int first = -1;
27 static int last = -1;
28 static int doflip = 0;
29 static PSF_MAPPING *codepage = NULL;
30 static PSF_FILE psf;
31
32 /* Program name */
33 char *cnv_progname = "PSF2RAW";
34
35 /* ddash = 1 if option started with a double-dash; else 0 */
36 /* Return NULL if OK, else error string */
cnv_set_option(int ddash,char * variable,char * value)37 char *cnv_set_option(int ddash, char *variable, char *value)
38 {
39 if (!stricmp(variable, "first")) { first = atoi(value); return NULL; }
40 if (!stricmp(variable, "last")) { last = atoi(value); return NULL; }
41 if (!stricmp(variable, "256")) { first = 0; last = 255; return NULL; }
42 if (!stricmp(variable, "flip")) { doflip = 1; 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, "Syntax: %s psffile rawfnt { options }\n\n", cnv_progname);
59 strcat (helpbuf, "Options: \n"
60 " --first=n Start with character n\n"
61 " --last=n Finish with character n\n"
62 " --codepage=xxx Extract codepage xxx\n"
63 " --flip Mirror all bytes as they are written\n"
64 " --256 Equivalent to --first=0 --last=255\n");
65
66 return helpbuf;
67 }
68
69
cnv_execute(FILE * infile,FILE * outfile)70 char *cnv_execute(FILE *infile, FILE *outfile)
71 {
72 int rv, n, max;
73 psf_dword ch, f, l, z, glyph;
74
75 psf_file_new(&psf);
76 rv = psf_file_read(&psf, infile);
77
78 if (rv != PSF_E_OK) return psf_error_string(rv);
79 if (codepage && !psf_is_unicode(&psf))
80 {
81 psf_file_delete(&psf);
82 return "Cannot extract by codepage; source file has no Unicode table";
83 }
84
85 /* Most systems that use raw fonts depend on the font being 1 byte
86 * wide */
87 if (psf.psf_width > 8)
88 fprintf(stderr, "Warning: Font is wider than 8 bits.\n");
89
90 f = (first >= 0) ? first : 0;
91 l = (last >= 0) ? last : (psf.psf_length - 1);
92 if (codepage && l >= 256) l = 255;
93 if (l >= psf.psf_length) l = psf.psf_length;
94
95 if (doflip)
96 {
97 max = (last+1) * psf.psf_charlen;
98 for (n = first * psf.psf_charlen; n < max; n++)
99 {
100 psf.psf_data[n] = flip(psf.psf_data[n]);
101 }
102 }
103 for (ch = f; ch <= l; ch++)
104 {
105 psf_byte *src;
106
107 if (codepage)
108 {
109 if (ch < 256 && !psf_unicode_lookupmap(&psf, codepage,
110 ch, &glyph, NULL))
111 {
112 src = psf.psf_data + glyph * psf.psf_charlen;
113 }
114 else
115 {
116 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]);
117 src = NULL;
118 }
119 }
120 else src = psf.psf_data + ch * psf.psf_charlen;
121
122 if (!src) for (z = 0; z < psf.psf_charlen; z++)
123 {
124 if (fputc(0, outfile) == EOF)
125 {
126 psf_file_delete(&psf);
127 return "Could not write to output.";
128 }
129 }
130 else if (fwrite(src, 1, psf.psf_charlen, outfile) <
131 psf.psf_charlen)
132 {
133 psf_file_delete(&psf);
134 return "Could not write to output.";
135 }
136 }
137 psf_file_delete(&psf);
138 return NULL;
139 }
140
141