/* psftools: Manipulate console fonts in the .PSF format Copyright (C) 2005 John Elliott This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Merge one or more PSF files into a new PSF file */ #include "cnvmulti.h" #include "psflib.h" #include static char helpbuf[2048]; static char msgbuf[1000]; static int v1 = 0; static PSF_FILE *psf_in, psf_out; /* Program name */ char *cnv_progname = "PSFJOIN"; /* ddash = 1 if option started with a double-dash; else 0 */ /* Return NULL if OK, else error string */ char *cnv_set_option(int ddash, char *variable, char *value) { if (!stricmp(variable, "psf1")) { v1 = 1; return NULL; } if (!stricmp(variable, "psf2")) { v1 = 0; return NULL; } if (strlen(variable) > 2000) variable[2000] = 0; sprintf(helpbuf, "Unknown option: %s\n", variable); return helpbuf; } /* Return help string */ char *cnv_help(void) { sprintf(helpbuf, "Concatenates .PSF fonts\n\n" "Syntax: %s source.psf source.psf " " ... target.psf \n\n", cnv_progname); strcat(helpbuf, "Options are:\n"); strcat(helpbuf, " --psf1: Output in PSF1 format\n"); strcat(helpbuf, " --psf2: Output in PSF2 format (default)\n"); return helpbuf; } /* Do the conversion */ char *cnv_multi(int nfiles, char **infiles, FILE *outfile) { int rv, nf, nc; psf_dword mc, nchars, charlen = 0; FILE *fp; int w = -1, h = -1; psf_unicode_dirent *ude; /* Load all the source files */ nchars = 0; psf_in = malloc(nfiles * sizeof(PSF_FILE)); if (!psf_in) return "Out of memory"; for (nf = 0; nf < nfiles; nf++) { psf_file_new(&psf_in[nf]); if (!strcmp(infiles[nf], "-")) fp = stdin; else fp = fopen(infiles[nf], "rb"); if (!fp) { perror(infiles[nf]); return "Cannot open font file."; } rv = psf_file_read(&psf_in[nf], fp); if (fp != stdin) fclose(fp); if (rv != PSF_E_OK) { sprintf(msgbuf, "%s: %s", infiles[nf], psf_error_string(rv)); return msgbuf; } if (w == -1 && h == -1) { w = psf_in[nf].psf_width; h = psf_in[nf].psf_height; charlen = psf_in[nf].psf_charlen; } /* Allow a little slackness in the width; we can concatenate say 6x8 and 8x8 * fonts */ else if (h != psf_in[nf].psf_height || charlen != psf_in[nf].psf_charlen) { return "All fonts must have the same dimensions."; } nchars += psf_in[nf].psf_length; } rv = psf_file_create(&psf_out, w, h, nchars, 0); if (rv) return psf_error_string(rv); mc = 0; for (nf = 0; nf < nfiles; nf++) { for (nc = 0; nc < psf_in[nf].psf_length; nc++) { memcpy(psf_out.psf_data + mc * psf_out.psf_charlen, psf_in[nf].psf_data + nc * psf_in[nf].psf_charlen, psf_out.psf_charlen); mc++; } } /* Copy the Unicode directory from the first font only */ rv = 0; if (psf_is_unicode(&psf_in[0])) { rv = psf_file_create_unicode(&psf_out); } if (!rv) for (nc = 0; nc < psf_in[0].psf_length; nc++) { for (ude = psf_in[0].psf_dir.psf_dirents_used[nc]; ude != NULL; ude = ude->psfu_next) { rv = psf_unicode_add(&psf_out, nf, ude->psfu_token); if (rv) break; } if (rv) break; } if (!rv) rv = psf_file_write(&psf_out, outfile); psf_file_delete(&psf_out); for (nf = 0; nf < nfiles; nf++) { psf_file_delete(&psf_in[nf]); } free(psf_in); if (rv) return psf_error_string(rv); return NULL; }