1 /*
2     psftools: Manipulate console fonts in the .PSF format
3     Copyright (C) 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 
20 /* This fine deals with the management of the in-memory structures associated
21  * with a codepage (CPI) file */
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include "cpi.h"
26 
cpi_new(CPI_FILE * f,cpi_format format)27 int cpi_new   (CPI_FILE *f, cpi_format format)
28 {
29 	switch(format)
30 	{
31 		case CPI_NAKED:
32 		case CPI_FONT:
33 			f->magic0 = 0xFF;
34 			strcpy(f->format, "FONT   ");
35 			break;
36 		case CPI_FONTNT:
37 			f->magic0 = 0xFF;
38 			strcpy(f->format, "FONT.NT");
39 			break;
40 		case CPI_DRFONT:
41 			f->magic0 = 0x7F;
42 			strcpy(f->format, "DRFONT ");
43 			break;
44 	}
45 	f->firstpage = NULL;
46 	f->drfonts   = NULL;
47 	f->drcount   = 0;
48 	f->comment   = NULL;
49 	f->comment_len=0;
50 	return 0;
51 }
52 
cpi_delete(CPI_FILE * f)53 int cpi_delete(CPI_FILE *f)
54 {
55 	CP_HEAD *h,  *h1;
56 	CP_FONT *fn, *fn1;
57 
58 	for (h = f->firstpage; h != NULL; )
59 	{
60 		for (fn = h->fonts; fn != NULL; )
61 		{
62 			if (fn->data) free(fn->data);
63 			fn1 = fn;
64 			fn = fn->next;
65 			free(fn1);
66 		}
67 		if (h->dr_lookup) free(h->dr_lookup);
68 		h1 = h;
69 		h = h->next;
70 		free(h1);
71 	}
72 	if (f->drfonts)
73 	{
74 		int n;
75 		for (n = 0; n < f->drcount; n++)
76 		{
77 			if (f->drfonts[n].bitmap) free(f->drfonts[n].bitmap);
78 		}
79 		free(f->drfonts);
80 	}
81 	if (f->comment) free(f->comment);
82 	f->comment = NULL;
83 	f->comment_len = 0;
84 	f->drcount = 0;
85 	f->drfonts = NULL;
86 	f->firstpage = NULL;
87 	return 0;
88 }
89 
90 
cpi_lookup(CPI_FILE * f,unsigned number)91 CP_HEAD *cpi_lookup(CPI_FILE *f, unsigned number)
92 {
93 	CP_HEAD *h;
94 
95 	for (h = f->firstpage; h != NULL; h = h->next)
96 	{
97 		if (h->codepage == number) return h;
98 	}
99 	return NULL;
100 }
101 
102 
cpi_add_page(CPI_FILE * f,unsigned number)103 CP_HEAD *cpi_add_page(CPI_FILE *f, unsigned number)
104 {
105 	CP_HEAD *cph;
106 	CP_HEAD *h;
107 
108 	cph = cpi_lookup(f, number);
109 	if (cph) return cph;
110 
111  	cph = malloc(sizeof(*cph));
112 	if (!cph) return NULL;
113 	memset(cph, 0, sizeof(*cph));
114 	cph->codepage = number;
115 	if (!f->firstpage)
116 	{
117 		f->firstpage = cph;
118 		return cph;
119 	}
120 	for (h = f->firstpage; h->next != NULL; h = h->next);
121 	h->next = cph;
122 	return cph;
123 }
124 
125 
126 
cph_add_font(CP_HEAD * h)127 CP_FONT *cph_add_font(CP_HEAD *h)
128 {
129 	CP_FONT *cpf = malloc(sizeof(CP_FONT));
130 	CP_FONT *f;
131 
132 	if (!cpf) return NULL;
133 	memset(cpf, 0, sizeof(*cpf));
134 	if (!h->fonts)
135 	{
136 		h->fonts = cpf;
137 		return cpf;
138 	}
139 	for (f = h->fonts; f->next != NULL; f = f->next);
140 	f->next = cpf;
141 	return cpf;
142 }
143 
144 
cpi_count_chars(CP_HEAD * cph)145 int cpi_count_chars(CP_HEAD *cph)
146 {
147 	int count = -1;
148 	CP_FONT *cpf;
149 
150 /* Let count = the number of characters in the shortest font in this
151    codepage (all fonts in a codepage ought to have the same number
152    of characters anyway!) */
153 	for (cpf = cph->fonts; cpf != NULL; cpf = cpf->next)
154 	{
155 		if (count < 0 || cpf->nchars > count) count = cpf->nchars;
156 	}
157 	return count;
158 }
159 
160 
cpi_find_glyph(CPI_FILE * f,int codepage,int height,int width,int glyph)161 cpi_byte *cpi_find_glyph(CPI_FILE *f, int codepage, int height, int width,
162 		int glyph)
163 {
164 	CP_FONT *cpf;
165 	CP_HEAD *cph;
166 	CP_DRFONT *cpd;
167 	int n, char_len;
168 	cpi_byte *result = NULL;
169 
170 	char_len = ((width + 7) / 8) * height;
171 	/* If this is a DRFONT, see if we cover this size */
172 	cpd = NULL;
173 	if (!strcmp(f->format, "DRFONT "))
174 	{
175 		for (n = 0; n < f->drcount; n++)
176 		{
177 			if (f->drfonts[n].char_len == char_len)
178 			{
179 				cpd = &f->drfonts[n];
180 				break;
181 			}
182 		}
183 		if (!cpd) return NULL;
184 	}
185 
186 	for (cph = f->firstpage; cph != NULL; cph = cph->next)
187 	{
188 		if (cph->codepage != codepage) continue;
189 		for (cpf = cph->fonts; cpf != NULL; cpf = cpf->next)
190 		{
191 			if (cpf->height != height) continue;
192 			if (cpf->width  != width ) continue;
193 			if (glyph < 0 || glyph >= cpf->nchars) continue;
194 
195 			if (cpd) /* DRFONT file */
196 			{
197 				result = cpd->bitmap + cph->dr_lookup[glyph] * char_len;
198 			}
199 			else
200 			{
201 				result = cpf->data + glyph * char_len;
202 			}
203 			return result;
204 		}
205 	}
206 	return result;
207 }
208