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