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