1 /*-------------------------------------------------------------------------*/
2 /* fontfile.c --- Load font character and encoding defitions */
3 /* Copyright (c) 2001 Tim Edwards, Johns Hopkins University */
4 /*-------------------------------------------------------------------------*/
12 #include <X11/Intrinsic.h>
13 #include <X11/StringDefs.h>
24 /*-------------------------------------------------------------------------*/
26 /*-------------------------------------------------------------------------*/
30 /*----------------------------------------------------------------------*/
31 /* Function prototype declarations */
32 /*----------------------------------------------------------------------*/
33 #include "prototypes.h"
35 /*-------------------------------------------------------------------------*/
36 /* Global Variable definitions */
37 /*-------------------------------------------------------------------------*/
39 extern char _STR2
[250], _STR
[150];
41 extern short fontcount
;
42 extern fontinfo
*fonts
;
44 extern Globaldata xobjs
;
47 extern XCWindowData
*areawin
;
48 extern const char *utf8encodings
[][256];
51 extern char version
[];
54 extern Tcl_Interp
*xcinterp
;
57 /*----------------------------------------------------------------------*/
58 /* Find the file containing the encoding for the given font */
59 /*----------------------------------------------------------------------*/
61 FILE *findfontfile(char *fontname
)
67 /* Add subdirectory "fonts". We will try both with and */
68 /* without the subdirectory. */
70 sprintf(_STR
, "fonts/%s", fontname
);
72 /* change string to all lowercase and remove dashes */
74 for (i
= 0; i
< strlen(_STR
); i
++) {
75 _STR
[i
] = tolower(_STR
[i
]);
76 if (_STR
[i
] == '-') _STR
[i
] = '_';
79 /* Fprintf(stdout, "Searching for font file \"%s\"\n", _STR); */
81 /* Use the mechanism of "libopen" to find the encoding file */
82 /* in the search path */
84 fd
= libopen(_STR
+ 6, FONTENCODING
, NULL
, 0);
86 if (fd
== NULL
) fd
= libopen(_STR
, FONTENCODING
, NULL
, 0);
88 /* Some other, probably futile, attempts (call findfontfile recursively) */
93 /* If this font has a suffix, remove it and look for its root */
94 /* font on the supposition that this font is derived from the */
97 strncpy(tempname
, fontname
, 99);
98 if ((dashptr
= strrchr(tempname
, '-')) != NULL
) {
100 if ((fd
= findfontfile(tempname
)) != NULL
) return fd
;
102 /* And finally, because it's a common case, try adding */
103 /* -Roman and trying again (but don't infinite loop!) */
105 if (strcmp(dashptr
+ 1, "Roman")) {
106 strcat(dashptr
, "-Roman");
107 if ((fd
= findfontfile(tempname
)) != NULL
) return fd
;
111 Wprintf("No font encoding file found.");
112 if (fontcount
> 0) { /* Make font substitution */
113 char *dchr
, *psname
= NULL
;
116 if ((dchr
= strrchr(_STR
, '.')) != NULL
) *dchr
= '\0';
117 if ((fval
= findhelvetica()) == fontcount
) {
118 /* This will cause some chaos. . . */
119 Fprintf(stderr
, "Error: No fonts available! Check library path?\n");
123 psname
= (char *)malloc((1 + strlen(fontname
)) * sizeof(char));
124 strcpy(psname
, fontname
);
125 Wprintf("No encoding file found for font %s: substituting %s",
126 psname
, fonts
[fval
].psname
);
127 fonts
= (fontinfo
*)realloc(fonts
, (fontcount
+ 1) * sizeof(fontinfo
));
128 fonts
[fontcount
].psname
= psname
;
129 fonts
[fontcount
].family
= psname
;
130 fonts
[fontcount
].encoding
= fonts
[fval
].encoding
;
131 fonts
[fontcount
].flags
= 0;
132 fonts
[fontcount
].scale
= 1.0;
137 Fprintf(stderr
, "Error: font encoding file missing for font \"%s\"\n",
139 Fprintf(stderr
, "No fonts exist for a subsitution. Make sure "
140 "fonts are installed or that\nenvironment variable "
141 "XCIRCUIT_LIB_DIR points to a directory of valid fonts.\n");
148 /*----------------------------------------------------------------------*/
149 /* Load a named font */
150 /* Return 1 if successful, 0 if font is already present, and -1 if any */
151 /* other error occurred. */
152 /*----------------------------------------------------------------------*/
154 int loadfontfile(char *fname
)
157 char temp
[250], commandstr
[30], tempname
[100];
158 char *psname
= NULL
, *family
= NULL
;
162 float fontscale
= 1.0;
164 objectptr
*encoding
= NULL
;
165 char saveversion
[20];
166 char *fontname
= strdup(fname
);
168 const char **utf8enc
= NULL
;
169 #endif /* HAVE_CAIRO */
171 strcpy(saveversion
, version
);
173 /* check to see if font name is in list of fonts */
175 for (i
= 0; i
< fontcount
; i
++) {
176 if (!strcmp(fonts
[i
].psname
, fontname
)) {
181 if ((fd
= findfontfile(fontname
)) == NULL
) return -1;
183 while (fgets(temp
, 249, fd
) != NULL
) {
184 if (*temp
== '\n') continue;
185 sscanf(temp
, "%29s", commandstr
);
186 for(cmdptr
= commandstr
; isspace(*cmdptr
); cmdptr
++);
188 /* very liberal about comment line characters */
190 if (*cmdptr
== '#' || *cmdptr
== '%' || *cmdptr
== ';');
192 else if (!strcmp(cmdptr
, "name:")) {
193 sscanf(temp
, "%*s %99s", tempname
);
195 /* If font is already in list, ignore it */
196 /* This condition should be caught at the top of the routine. . . */
198 for (i
= 0; i
< fontcount
; i
++) {
199 if (!strcmp(fonts
[i
].psname
, tempname
)) {
200 /* Fprintf(stdout, "Font already loaded.\n"); */
206 psname
= (char *)malloc((1 + strlen(tempname
)) * sizeof(char));
207 strcpy(psname
, tempname
);
210 else if (!strcmp(cmdptr
, "file:") || !strcmp(cmdptr
, "load:")) {
211 /* Fprintf(stdout, "found file identifier in xfe file\n"); */
212 sscanf(temp
, "%*s %149s", _STR
);
214 /* since we can be in the middle of a file load, protect the */
215 /* current version number for the file load. */
217 strcpy(version
, PROG_VERSION
);
218 if (loadlibrary(FONTLIB
) == FALSE
) {
220 strcpy(version
, saveversion
);
223 else if (!strcmp(cmdptr
, "family:")){
224 sscanf(temp
, "%*s %99s", tempname
);
225 family
= (char *)malloc((1 + strlen(tempname
)) * sizeof(char));
226 strcpy(family
, tempname
);
229 else if (!strcmp(cmdptr
, "weight:")){
230 sscanf(temp
, "%*s %99s", tempname
);
231 tempname
[0] = tolower(tempname
[0]);
232 if (!strcmp(tempname
, "bold"))
236 else if (!strcmp(cmdptr
, "shape:")){
237 sscanf(temp
, "%*s %99s", tempname
);
238 tempname
[0] = tolower(tempname
[0]);
239 if (!strcmp(tempname
, "italic") || !strcmp(tempname
, "oblique")
240 || !strcmp(tempname
, "slanted"))
244 else if (!strcmp(cmdptr
, "scale:")){
245 sscanf(temp
, "%*s %f", &fontscale
);
248 else if (!strcmp(cmdptr
, "type:")) {
249 sscanf(temp
, "%*s %99s", tempname
);
250 tempname
[0] = tolower(tempname
[0]);
251 if (!strcmp(tempname
, "drawn") || !strcmp(tempname
, "vectored"))
255 else if (!strcmp(cmdptr
, "derived:")) {
256 if (encoding
== NULL
) {
257 Fprintf(stdout
, "Font warning: \"derived\" statement must come "
262 sscanf(temp
, "%*s %99s", tempname
);
263 psname2
= (char *)malloc((1 + strlen(tempname
)) * sizeof(char));
264 strcpy(psname2
, tempname
);
265 flags
&= 0xffe0; /* shares these flags with original */
266 flags
|= 0x020; /* derived font flag */
268 /* determine rest of flags */
270 sscanf(temp
, "%*s %*s %99s", tempname
);
271 tempname
[0] = tolower(tempname
[0]);
272 if (!strcmp(tempname
, "bold")) {
276 sscanf(temp
, "%*s %*s %*s %99s", tempname
);
277 tempname
[0] = tolower(tempname
[0]);
278 if (!strcmp(tempname
, "italic") || !strcmp(tempname
, "oblique"))
281 sscanf(temp
, "%*s %*s %*s %*s %99s", tempname
);
282 tempname
[0] = tolower(tempname
[0]);
283 if (!strcmp(tempname
, "drawn") || !strcmp(tempname
, "vectored"))
285 else if (!strcmp(tempname
, "special"))
288 /* generate a new fontinfo entry for the derived font */
290 fonts
= (fontinfo
*) realloc (fonts
, (fontcount
+ 1) * sizeof(fontinfo
));
291 fonts
[fontcount
].psname
= psname2
;
293 fonts
[fontcount
].family
= psname
;
295 fonts
[fontcount
].family
= family
;
296 fonts
[fontcount
].encoding
= encoding
; /* use original encoding */
297 fonts
[fontcount
].flags
= flags
;
298 fonts
[fontcount
].scale
= fontscale
;
300 fonts
[fontcount
].utf8encoding
= utf8enc
;
301 xc_cairo_set_fontinfo(fontcount
);
302 #endif /* HAVE_CAIRO */
307 else if (!strcmp(cmdptr
, "encoding:")) {
309 const char *findencstr
;
310 #endif /* HAVE_CAIRO */
311 sscanf(temp
, "%*s %99s", tempname
);
313 if (!strcmp(tempname
, "special") || !strcmp(tempname
, "Special")) {
316 XcInternalTagCall(xcinterp
, 3, "label", "encoding", "Special");
318 makenewencodingbutton("Special", (char)1);
323 utf8enc
= utf8encodings
[0];
324 /* treat encoding of symbol font in a special way */
325 if (!strcmp(family
, "Symbol"))
326 findencstr
= "Symbol";
328 findencstr
= tempname
;
330 /* Now try to find the encoding, */
331 /* default to the first encoding (stdenc) if not found */
332 utf8enc
= utf8encodings
[0];
333 for (i
= 0; utf8encodings
[i
][0]; i
++)
334 if (!strcmp(utf8encodings
[i
][0], findencstr
)) {
335 utf8enc
= utf8encodings
[i
];
338 #endif /* HAVE_CAIRO */
340 /* ISO-LatinX encodings where X=1 to 6 */
342 if (strstr(tempname
, "Latin") != NULL
) {
344 for (i
= 0; i
< 6; i
++) {
345 if (strchr(tempname
, '1' + (char)i
) != NULL
) {
346 flags
|= ((i
+ 2) << 7);
348 snprintf(estr
, sizeof(estr
), "ISOLatin%d", i
+ 1);
349 XcInternalTagCall(xcinterp
, 3, "label", "encoding", estr
);
351 snprintf(estr
, sizeof(estr
), "ISO-Latin%d", i
+ 1);
352 makenewencodingbutton(estr
, (char)(i
+ 2));
358 /* i == 6 maps to ISO8859-5 */
359 if (strstr(tempname
, "8859-5") != NULL
) {
363 flags
|= ((6 + 2) << 7);
365 XcInternalTagCall(xcinterp
, 3, "label", "encoding", "ISO8859-5");
367 snprintf(estr
, sizeof(estr
), "ISO-8859-5");
368 makenewencodingbutton(estr
, (char)8);
372 /* Make space for the font encoding vector */
374 encoding
= (objectptr
*)malloc(256 * sizeof(objectptr
));
377 while (fgets(temp
, 249, fd
) != NULL
) {
379 while (*temp2
!= '\0') {
380 if ((int)(eptr
- encoding
) == 256) break;
381 sscanf(temp2
, "%99s", tempname
);
382 *eptr
= (objectptr
) NULL
;
383 for (j
= xobjs
.fontlib
.library
; j
< xobjs
.fontlib
.library
+
384 xobjs
.fontlib
.number
; j
++) {
385 if (!strcmp(tempname
, (*j
)->name
)) {
390 if (j
== xobjs
.fontlib
.library
+ xobjs
.fontlib
.number
) {
391 Fprintf(stdout
, "Font load warning: character \"%s\" at code ",
393 Fprintf(stdout
, "position %d not found.\n", (int)(eptr
- encoding
));
396 while (*temp2
!= ' ' && *temp2
!= '\n' && *temp2
!= '\0') temp2
++;
397 while (*temp2
== ' ' || *temp2
== '\n') temp2
++;
399 if ((int)(eptr
- encoding
) == 256) break;
401 if ((int)(eptr
- encoding
) != 256) {
402 Fprintf(stdout
, "Font load warning: Only %d characters encoded.\n",
403 (int)(eptr
- encoding
));
404 while (eptr
< encoding
+ 256)
405 *eptr
++ = (objectptr
) NULL
;
408 /* If successful, register the font */
410 fonts
= (fontinfo
*) realloc (fonts
, (fontcount
+ 1) * sizeof(fontinfo
));
411 fonts
[fontcount
].psname
= psname
;
413 fonts
[fontcount
].family
= psname
;
415 fonts
[fontcount
].family
= family
;
416 fonts
[fontcount
].encoding
= encoding
;
417 fonts
[fontcount
].flags
= flags
;
418 fonts
[fontcount
].scale
= fontscale
;
420 fonts
[fontcount
].utf8encoding
= utf8enc
;
421 xc_cairo_set_fontinfo(fontcount
);
422 #endif /* HAVE_CAIRO */
425 /* Create a new menu button for the font family, if this is the first */
426 /* (In Tcl, this just registers the family name for cycling through */
427 /* via Alt-F; the menu update is done via command tag callback). */
429 for (i
= 0; i
< fontcount
- 1; i
++)
430 if (!strcmp(fonts
[i
].family
, fonts
[fontcount
- 1].family
))
433 if (i
== fontcount
- 1)