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