7
#include <X11/Intrinsic.h>
12
#define FONTPATH "/usr/local/share/groff/font:/usr/local/lib/font:/usr/lib/font"
16
#define isascii(c) (1)
21
extern char *strtok();
24
extern char *strchr();
27
extern char *getenv();
30
/* Name of environment variable containing path to be used for
31
searching for device and font description files. */
32
#define FONTPATH_ENV_VAR "GROFF_FONT_PATH"
37
/* Minimum and maximum values a `signed int' can hold. */
38
#define INT_MIN (-INT_MAX-1)
39
#define INT_MAX 2147483647
42
#define CHAR_TABLE_SIZE 307
49
struct charinfo *char_table[CHAR_TABLE_SIZE];
50
struct charinfo *code_table[256];
56
struct charinfo *next;
57
struct charinfo *code_next;
61
static char *current_filename = 0;
62
static int current_lineno = -1;
65
static FILE *open_device_file();
66
static DeviceFont *load_font();
67
static Device *new_device();
68
static DeviceFont *new_font();
69
static void delete_font();
70
static unsigned hash_name();
71
static struct charinfo *add_char();
72
static int read_charset_section();
73
static char *canonicalize_name();
76
Device *new_device(name)
89
dev->name = XtNewString(name);
93
void device_destroy(dev)
111
Device *device_load(name)
119
fp = open_device_file(name, "DESC", ¤t_filename);
122
dev = new_device(name);
124
while (fgets(buf, sizeof(buf), fp)) {
132
if (strcmp(p, "charset") == 0)
134
if (strcmp(p, "X11") == 0)
136
else if (strcmp(p, "sizescale") == 0)
137
np = &dev->sizescale;
138
else if (strcmp(p, "res") == 0)
140
else if (strcmp(p, "unitwidth") == 0)
141
np = &dev->unitwidth;
142
else if (strcmp(p, "paperwidth") == 0)
143
np = &dev->paperwidth;
144
else if (strcmp(p, "paperlength") == 0)
145
np = &dev->paperlength;
148
q = strtok((char *)0, WS);
149
if (!q || sscanf(q, "%d", np) != 1 || *np <= 0) {
150
error("bad argument");
161
error("missing res line");
164
else if (dev->unitwidth == 0) {
165
error("missing unitwidth line");
169
if (dev->paperlength == 0)
170
dev->paperlength = dev->res*11;
171
if (dev->paperwidth == 0)
172
dev->paperwidth = dev->res*8 + dev->res/2;
177
XtFree(current_filename);
178
current_filename = 0;
183
DeviceFont *device_find_font(dev, name)
191
for (f = dev->fonts; f; f = f->next)
192
if (strcmp(f->name, name) == 0)
194
return load_font(dev, name);
198
DeviceFont *load_font(dev, name)
207
fp = open_device_file(dev->name, name, ¤t_filename);
214
if (!fgets(buf, sizeof(buf), fp)) {
215
error("no charset line");
220
/* charset must be on a line by itself */
221
if (p && strcmp(p, "charset") == 0 && strtok((char *)0, WS) == 0)
223
if (p && strcmp(p, "special") == 0)
226
f = new_font(name, dev);
227
f->special = special;
228
if (!read_charset_section(f, fp)) {
233
f->next = dev->fonts;
237
XtFree(current_filename);
238
current_filename = 0;
243
DeviceFont *new_font(name, dev)
250
f = XtNew(DeviceFont);
251
f->name = XtNewString(name);
255
for (i = 0; i < CHAR_TABLE_SIZE; i++)
256
f->char_table[i] = 0;
257
for (i = 0; i < 256; i++)
258
f->code_table[i] = 0;
271
for (i = 0; i < CHAR_TABLE_SIZE; i++) {
272
struct charinfo *ptr = f->char_table[i];
274
struct charinfo *tem = ptr;
284
unsigned hash_name(name)
288
/* XXX do better than this */
290
n = (n << 1) ^ *name++;
296
int scale_round(n, x, y)
305
if (n <= (INT_MAX - y2)/x)
308
else if (-(unsigned)n <= (-(unsigned)INT_MIN - y2)/x)
310
return (int)(n*(double)x/(double)y + .5);
314
char *canonicalize_name(s)
318
if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') {
322
for (p = s + 4; *p; p++)
323
if (!isascii(*p) || !isdigit((unsigned char)*p))
326
if (n >= 0 && n <= 0xff) {
334
/* Return 1 if the character is present in the font; widthp gets the
335
width if non-null. */
337
int device_char_width(f, ps, name, widthp)
345
name = canonicalize_name(name);
346
for (p = f->char_table[hash_name(name) % CHAR_TABLE_SIZE];; p = p->next) {
349
if (strcmp(p->name, name) == 0)
352
*widthp = scale_round(p->width, ps, f->dev->unitwidth);
356
int device_code_width(f, ps, code, widthp)
364
for (p = f->code_table[code & 0xff];; p = p->code_next) {
370
*widthp = scale_round(p->width, ps, f->dev->unitwidth);
374
char *device_name_for_code(f, code)
378
static struct charinfo *state = 0;
380
state = f->code_table[code & 0xff];
381
for (; state; state = state->code_next)
382
if (state->code == code && state->name[0] != '\0') {
383
char *name = state->name;
384
state = state->code_next;
390
int device_font_special(f)
397
struct charinfo *add_char(f, name, width, code)
402
struct charinfo **pp;
405
name = canonicalize_name(name);
406
if (strcmp(name, "---") == 0)
409
ci = (struct charinfo *)XtMalloc(XtOffsetOf(struct charinfo, name[0])
412
strcpy(ci->name, name);
417
pp = &f->char_table[hash_name(name) % CHAR_TABLE_SIZE];
421
pp = &f->code_table[code & 0xff];
427
/* Return non-zero for success. */
430
int read_charset_section(f, fp)
434
struct charinfo *last_charinfo = 0;
437
while (fgets(buf, sizeof(buf), fp)) {
444
name = strtok(buf, WS);
446
continue; /* ignore blank lines */
447
p = strtok((char *)0, WS);
448
if (!p) /* end of charset section */
450
if (strcmp(p, "\"") == 0) {
451
if (!last_charinfo) {
452
error("first line of charset section cannot use `\"'");
456
(void)add_char(f, name,
457
last_charinfo->width, last_charinfo->code);
461
if (sscanf(p, "%d", &width) != 1) {
462
error("bad width field");
465
p = strtok((char *)0, WS);
467
error("missing type field");
470
p = strtok((char *)0, WS);
472
error("missing code field");
475
code = (int)strtol(p, &q, 0);
477
error("bad code field");
480
last_charinfo = add_char(f, name, width, code);
487
FILE *find_file(file, result)
488
char *file, **result;
497
env = getenv(FONTPATH_ENV_VAR);
498
path = XtMalloc(((env && *env) ? strlen(env) + 1 : 0)
499
+ strlen(FONTPATH) + 1);
505
strcat(path, FONTPATH);
515
fp = fopen(file, "r");
517
*result = XtNewString(file);
528
end = strchr(path, ':');
532
path = end = strchr(path, '\0');
537
len = (end - start) + 1 + flen + 1;
540
buf = XtRealloc(buf, len);
545
memcpy(buf, start, end - start);
546
buf[end - start] = '/';
547
strcpy(buf + (end - start) + 1, file);
548
fp = fopen(buf, "r");
559
FILE *open_device_file(device_name, file_name, result)
560
char *device_name, *file_name, **result;
565
buf = XtMalloc(3 + strlen(device_name) + 1 + strlen(file_name) + 1);
566
sprintf(buf, "dev%s/%s", device_name, file_name);
567
fp = find_file(buf, result);
569
fprintf(stderr, "can't find device file `%s'\n", file_name);
580
if (current_filename) {
581
fprintf(stderr, "%s:", current_filename);
582
if (current_lineno > 0)
583
fprintf(stderr, "%d:", current_lineno);
594
c-continued-statement-offset: 4
598
c-tab-always-indent: nil