1 /*
2 psftools: Manipulate console fonts in the .PSF format
3 Copyright (C) 2003, 2008 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 #define MAX_H 8 /* Maximum font height */
23
24 #ifndef SEEK_SET /* Why doesn't Pacific define this? */
25 #define SEEK_SET 0
26 #define SEEK_CUR 1
27 #define SEEK_END 2
28 #endif
29
30 /* Convert a BBC micro soft-font to a .PSF font.
31 *
32 * We assume a maximum of 256 characters with a maximum height of 8.
33 */
34 static char workbuf[256 * MAX_H];
35
36 static char helpbuf[2048];
37 static int width = 8;
38 static int height = 8;
39 static int v1 = 0, v2 = 0;
40 static PSF_MAPPING *codepage = NULL;
41 static PSF_FILE psf;
42 static int firstc = -1;
43 static int lastc = -1;
44
45 /* Program name */
46 char *cnv_progname = "BBC2PSF";
47
48 /* ddash = 1 if option started with a double-dash; else 0 */
49 /* Return NULL if OK, else error string */
cnv_set_option(int ddash,char * variable,char * value)50 char *cnv_set_option(int ddash, char *variable, char *value)
51 {
52 if (!stricmp(variable, "width")) { width = atoi(value); return NULL; }
53 if (!stricmp(variable, "height")) { height = atoi(value); return NULL; }
54 if (!stricmp(variable, "psf1")) { v1 = 1; return NULL; }
55 if (!stricmp(variable, "psf2")) { v2 = 1; return NULL; }
56 if (!stricmp(variable, "codepage"))
57 {
58 codepage = psf_find_mapping(value);
59 if (codepage == NULL) return "Code page name not recognised.";
60 return NULL;
61 }
62 if (strlen(variable) > 2000) variable[2000] = 0;
63 sprintf(helpbuf, "Unknown option: %s\n", variable);
64 return helpbuf;
65 }
66
67
68 /* Return help string */
cnv_help(void)69 char *cnv_help(void)
70 {
71 sprintf(helpbuf, "Syntax: %s softfont psffile { options }\n\n", cnv_progname);
72 strcat (helpbuf, "Options: \n"
73 " --height=x Height of glyphs (defaults to 8)\n"
74 " --width=x Width of glyphs (defaults to 8)\n"
75 " --codepage=x Create a Unicode directory from the specified code page\n"
76 " --psf1 Output in PSF1 format\n"
77 " --psf2 Output in PSF2 format (default) \n");
78
79 return helpbuf;
80 }
81
82
cnv_execute(FILE * infile,FILE * outfile)83 char *cnv_execute(FILE *infile, FILE *outfile)
84 {
85 int rv;
86 int ch, curchar, y, wb;
87
88 /* Work through the file until we find VDU23 (redefine character) */
89
90 memset(workbuf, 0, sizeof(workbuf));
91 while (1)
92 {
93 ch = fgetc(infile); if (ch == EOF) break;
94 if (ch != 0x17) continue; /* VDU23 */
95
96 /* Next character says what is being defined. */
97 ch = fgetc(infile); if (ch == EOF) break;
98 curchar = ch;
99 /* The next 8 give the bitmap */
100 for (y = 0; y < 8; y++)
101 {
102 ch = fgetc(infile); if (ch == EOF) break;
103 workbuf[curchar * 8 + y] = ch;
104 }
105 if (ch == EOF) break;
106 /* Character successfully defined. Move on to the next one */
107 if (curchar < firstc || firstc == -1) firstc = curchar;
108 if (curchar > lastc || lastc == -1) lastc = curchar;
109 }
110 if (firstc == -1 || lastc == -1)
111 {
112 return "No BBC micro character definitions found in input";
113 }
114
115 psf_file_new(&psf);
116 rv = psf_file_create(&psf, width, height, lastc - firstc + 1, 0);
117 if (!rv)
118 {
119 wb = psf.psf_charlen / psf.psf_height;
120 for (ch = firstc; ch <= lastc; ch++)
121 {
122 if (ch >= 256) break;
123
124 for (y = 0; y < height; y++)
125 {
126 if (y >= MAX_H) break;
127 psf.psf_data[psf.psf_charlen * (ch-firstc)
128 + y * wb] = workbuf[ch * MAX_H + y];
129 }
130 }
131
132 if (codepage)
133 {
134 int n;
135 psf_file_create_unicode(&psf);
136 for (n = 0; n < lastc - firstc; n++) if (n < 256)
137 psf_unicode_addmap(&psf, n, codepage, n);
138 }
139
140
141 if (v1) psf_force_v1(&psf);
142 if (v2) psf_force_v2(&psf);
143 rv = psf_file_write(&psf, outfile);
144 }
145 psf_file_delete(&psf);
146 if (rv) return psf_error_string(rv);
147 return NULL;
148 }
149
150