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 #ifndef SEEK_SET /* Why doesn't Pacific define this? */
23 #define SEEK_SET 0
24 #define SEEK_CUR 1
25 #define SEEK_END 2
26 #endif
27
28 /* Convert a raw font to a .PSF font.
29 *
30 * If input is coming from a file, we can guess the height of glyphs by
31 * assuming 256 glyphs in the file. If input is coming from a pipe, the
32 * user has to specify glyph height.
33 */
34
35 static char helpbuf[2048];
36 static int width = 8;
37 static int height = 0;
38 static int skip = 0;
39 static int doflip = 0;
40 static int first = 0;
41 static int last = 255;
42 static int v1 = 0, v2 = 0;
43 static PSF_MAPPING *codepage = NULL;
44 static PSF_FILE psf;
45
46 /* Program name */
47 char *cnv_progname = "RAW2PSF";
48
49 /* ddash = 1 if option started with a double-dash; else 0 */
50 /* Return NULL if OK, else error string */
cnv_set_option(int ddash,char * variable,char * value)51 char *cnv_set_option(int ddash, char *variable, char *value)
52 {
53 if (!stricmp(variable, "width")) { width = atoi(value); return NULL; }
54 if (!stricmp(variable, "height")) { height = atoi(value); return NULL; }
55 if (!stricmp(variable, "skip")) { skip = atoi(value); return NULL; }
56 if (!stricmp(variable, "first")) { first = atoi(value); return NULL; }
57 if (!stricmp(variable, "last")) { last = atoi(value); return NULL; }
58 if (!stricmp(variable, "flip")) { doflip = 1; return NULL; }
59 if (!stricmp(variable, "psf1")) { v1 = 1; return NULL; }
60 if (!stricmp(variable, "psf2")) { v2 = 1; return NULL; }
61 if (!stricmp(variable, "512")) { first = 0; last = 511; return NULL; }
62 if (!stricmp(variable, "codepage"))
63 {
64 codepage = psf_find_mapping(value);
65 if (codepage == NULL) return "Code page name not recognised.";
66 return NULL;
67 }
68 if (strlen(variable) > 2000) variable[2000] = 0;
69 sprintf(helpbuf, "Unknown option: %s\n", variable);
70 return helpbuf;
71 }
72
73
74 /* Return help string */
cnv_help(void)75 char *cnv_help(void)
76 {
77 sprintf(helpbuf, "Syntax: %s rawfnt psffile { options }\n\n", cnv_progname);
78 strcat (helpbuf, "Options: \n"
79 " --height=x Height of glyphs\n"
80 " --width=x Width of glyphs (defaults to 8)\n"
81 " --skip=x Skip x characters at start of raw file (defaults to 0)\n"
82 " --first=x First character to use in the PSF\n"
83 " --last=x Last character to go into PSF (defaults to 255)\n"
84 " --codepage=x Create a Unicode directory from the specified code page\n"
85 " --flip Mirror all bytes in the file\n"
86 " --512 Equivalent to --first=0 --last=511\n"
87 " --psf1 Output in PSF1 format\n"
88 " --psf2 Output in PSF2 format (default) \n");
89
90 return helpbuf;
91 }
92
93
cnv_execute(FILE * infile,FILE * outfile)94 char *cnv_execute(FILE *infile, FILE *outfile)
95 {
96 int rv, n, max;
97 psf_dword count, pos;
98 long len = 0;
99
100 count = last + 1;
101 if (infile == stdin) pos = -1;
102 else pos = ftell(infile);
103
104 /* Guess height from file size, if possible */
105 if (pos != -1)
106 {
107 if (fseek(infile, 0, SEEK_END) >= 0 &&
108 (len = ftell(infile)) >= 0 &&
109 fseek(infile, pos, SEEK_SET) >= 0);
110 else pos = -1;
111 }
112 if (pos != -1 && height == 0)
113 {
114 len -= pos;
115 height = (len / count) / ((width + 7) /8);
116 fprintf(stderr, "From file size: height=%d\n",height);
117 }
118
119 if (height == 0)
120 {
121 return "Can't convert with no \"--height\" option";
122 }
123
124 psf_file_new(&psf);
125 rv = psf_file_create(&psf, width, height, last + 1, 0);
126 if (!rv)
127 {
128 skip *= psf.psf_charlen;
129 while (skip)
130 {
131 if (fgetc(infile) == EOF) return "Unexpected end of file";
132 --skip;
133 }
134 if (fread(psf.psf_data + first * psf.psf_charlen,
135 psf.psf_charlen, last + 1 - first, infile) < last + 1 - first)
136 {
137 psf_file_delete(&psf);
138 return "Could not read the input file.";
139 }
140 if (doflip)
141 {
142 max = last * psf.psf_charlen;
143 for (n = first * psf.psf_charlen;
144 n < max; n++)
145 {
146 psf.psf_data[n] = flip(psf.psf_data[n]);
147 }
148
149 }
150 if (codepage)
151 {
152 int n;
153 psf_file_create_unicode(&psf);
154 for (n = first; n < last; n++) if (n < 256)
155 psf_unicode_addmap(&psf, n, codepage, n);
156 }
157
158
159 if (v1) psf_force_v1(&psf);
160 if (v2) psf_force_v2(&psf);
161 rv = psf_file_write(&psf, outfile);
162 }
163 psf_file_delete(&psf);
164 if (rv) return psf_error_string(rv);
165 return NULL;
166 }
167
168