2 * device.c -- cawf(1) output device support functions
6 * Copyright (c) 1991 Purdue University Research Foundation,
7 * West Lafayette, Indiana 47907. All rights reserved.
9 * Written by Victor A. Abell <abe@mace.cc.purdue.edu>, Purdue
10 * University Computing Center. Not derived from licensed software;
11 * derived from awf(1) by Henry Spencer of the University of Toronto.
13 * Permission is granted to anyone to use this software for any
14 * purpose on any computer system, and to alter it and redistribute
15 * it freely, subject to the following restrictions:
17 * 1. The author is not responsible for any consequences of use of
18 * this software, even if they arise from flaws in it.
20 * 2. The origin of this software must not be misrepresented, either
21 * by explicit claim or by omission. Credits must appear in the
24 * 3. Altered versions must be plainly marked as such, and must not
25 * be misrepresented as being the original software. Credits must
26 * appear in the documentation.
28 * 4. This notice may not be removed or altered.
34 static unsigned char *Convstr(char *s
, int *len
);
35 static int Convfont(char *nm
, char *s
, char **fn
, unsigned char **fi
);
38 #define strcasecmp strcmpi
44 * Convstr(s, len) - convert a string
47 static unsigned char *
49 char *s
; /* input string */
50 int *len
; /* length of result */
52 int c
; /* character assembly */
53 unsigned char *cp
; /* temporary character pointer */
54 char *em
; /* error message */
55 int i
; /* temporary index */
57 unsigned char *r
; /* result string */
59 * Make space for the result.
61 if ((r
= (unsigned char *)malloc(strlen((char *)s
) + 1)) == NULL
) {
62 (void) fprintf(stderr
, "%s: out of string space at %s\n",
67 * Copy the input string to the result, processing '\\' escapes.
69 for (cp
= r
, l
= 0; *s
;) {
74 if (*s
>= '0' && *s
<= '7') {
76 * '\xxx' -- octal form
78 for (c
= i
= 0; i
< 3; i
++, s
++) {
79 if (*s
< '0' || *s
> '7') {
80 em
= "non-octal char";
82 (void) fprintf(stderr
,
84 Pname
, em
, (char *)r
);
87 c
= (c
<< 3) + *s
- '0';
90 em
= "octal char > 0377";
95 } else if (*s
== 'x') {
97 * '\xyy' -- hexadecimal form
100 for (c
= i
= 0; i
< 2; i
++, s
++) {
101 #if defined(__STDC__)
102 if ( ! isalpha(*s
) && ! isdigit(*s
))
104 if ( ! isascii(*s
) && ! isalpha(*s
)
113 if (*s
>= '0' && *s
<= '9')
115 else if ((*s
>= 'a' && *s
<= 'f')
116 || (*s
>= 'A' && *s
<= 'F'))
118 (isupper(*s
) ? 'A' : 'a');
122 *cp
++ = (unsigned char)c
;
124 } else if (*s
== 'E' || *s
== 'e') {
126 * '\E' or '\e' -- ESCape
131 } else if (*s
== '\0') {
132 em
= "no char after \\";
136 * escaped character (for some reason)
143 * Copy a "normal" character.
157 * Convfont(nm, s, fn, fi) - convert a font for a device
161 Convfont(nm
, s
, fn
, fi
)
162 char *nm
; /* output device name */
163 char *s
; /* font definition string */
164 char **fn
; /* font name address */
165 unsigned char **fi
; /* initialization string address */
167 char *cp
; /* temporary character pointer */
168 int len
; /* length */
170 * Get the font name, allocate space for it and allocate space for
173 if ((cp
= strchr(s
, '=')) == NULL
) {
174 (void) fprintf(stderr
, "%s: bad %s font line format: %s\n",
178 if ((*fn
= (char *)malloc(cp
- s
+ 1)) == NULL
) {
179 (void) fprintf(stderr
, "%s: no space for %s font name %s\n",
183 (void) strncpy(*fn
, s
, cp
- s
);
184 (*fn
)[cp
- s
] = '\0';
186 * Assmble the font initialization string.
188 if ((*fi
= Convstr(cp
+ 1, &len
)) == NULL
)
195 * Defdev() - define the output device
201 unsigned char *fi
= NULL
; /* last font initialization string */
202 char *fn
= NULL
; /* font name */
203 int fd
= 0; /* found-device flag */
204 FILE *fs
; /* file stream */
205 int err
= 0; /* errror count */
206 int i
; /* temporary index */
207 int len
; /* length */
208 char line
[MAXLINE
]; /* line buffer */
209 char *p
; /* output device configuration file */
210 char *s
; /* temporary string pointer */
212 * Check for the built-in devices, ANSI, NONE or NORMAL (default).
214 Fstr
.b
= Fstr
.i
= Fstr
.it
= Fstr
.r
= NULL
;
215 Fstr
.bl
= Fstr
.il
= Fstr
.itl
= Fstr
.rl
= 0;
216 if (Device
== NULL
|| strcasecmp(Device
, "normal") == 0) {
220 (void) fprintf(stderr
,
221 "%s: font %s for device %s illegal\n",
222 Pname
, Devfont
, Device
? Device
: "NORMAL");
228 if (strcasecmp(Device
, "ansi") == 0) {
229 Fstr
.b
= Newstr((unsigned char *)"x[1m");
230 Fstr
.it
= Newstr((unsigned char *)"x[4m");
231 Fstr
.r
= Newstr((unsigned char *)"x[0m");
232 Fstr
.b
[0] = Fstr
.it
[0] = Fstr
.r
[0] = ESC
;
233 Fstr
.bl
= Fstr
.itl
= Fstr
.rl
= 4;
236 if (strcasecmp(Device
, "none") == 0)
239 * If a device configuration file path is supplied, use it.
246 * Use the CAWFLIB environment if it is defined.
248 if ((p
= getenv("CAWFLIB")) == NULL
)
250 len
= strlen(p
) + 1 + strlen(DEVCONFIG
) + 1;
251 if ((s
= (char *)malloc(len
)) == NULL
) {
252 (void) fprintf(stderr
, "%s: no space for %s name\n",
256 (void) sprintf(s
, "%s/%s", p
, DEVCONFIG
);
260 * Open the configuration file.
263 if ((fs
= fopen(p
, "r")) == NULL
)
265 if ((fs
= fopen(p
, "rt")) == NULL
)
268 (void) fprintf(stderr
, "%s: can't open config file: %s\n",
274 * Look for a device definition line -- a line that begins with a name.
276 while ( ! feof(fs
)) {
277 if (*line
== '\t' || *line
== '#' || *line
== ' ') {
278 (void) fgets(line
, MAXLINE
, fs
);
281 if ((s
= strrchr(line
, '\n')) != NULL
)
284 line
[MAXLINE
-1] = '\0';
288 if (strcmp(Device
, line
) != 0) {
289 (void) fgets(line
, MAXLINE
, fs
);
294 * Read the parameter lines for the device.
296 while (fgets(line
, MAXLINE
, fs
) != NULL
) {
298 for (i
= 1; line
[i
] == ' '; i
++)
300 } else if (*line
== '\t')
304 #if defined(__STDC__)
305 if ( ! isalpha(line
[i
])
307 if ( ! isascii(line
[i
]) || ! isalpha(line
[i
])
311 if ((s
= strrchr(line
, '\n')) != NULL
)
314 line
[MAXLINE
-1] = '\0';
317 * \tb=<bolding_string>
320 if (Fstr
.b
!= NULL
) {
321 (void) fprintf(stderr
,
322 "%s: dup bold for %s in %s: %s\n",
323 Pname
, Device
, p
, line
);
327 if ((Fstr
.b
= Convstr(&line
[i
+2], &Fstr
.bl
))
332 * \ti=<italicization_string>
335 if (Fstr
.it
!= NULL
) {
336 (void) fprintf(stderr
,
337 "%s: dup italic for %s in %s: %s\n",
338 Pname
, Device
, p
, line
);
339 (void) free(Fstr
.it
);
342 if ((Fstr
.it
= Convstr(&line
[i
+2], &Fstr
.itl
))
347 * \tr=<return_to_Roman_string>
350 if (Fstr
.r
!= NULL
) {
351 (void) fprintf(stderr
,
352 "%s: dup roman for %s in %s: %s\n",
353 Pname
, Device
, p
, line
);
357 if ((Fstr
.r
= Convstr(&line
[i
+2], &Fstr
.rl
))
362 * \tf=<font_name>=<font_initialization_string>
365 if ( ! Devfont
|| Fstr
.i
)
367 if ((i
= Convfont(Device
, &line
[i
+2], &fn
, &fi
))
370 else if (fn
&& strcmp(Devfont
, fn
) == 0) {
380 (void) free((char *)fi
);
388 (void) fprintf(stderr
,
389 "%s: unknown device %s line: %s\n",
390 Pname
, Device
, line
);
400 * See if the device stanza was located and the font exists.
403 (void) fprintf(stderr
, "%s: can't find device %s in %s\n",
407 if (Devfont
&& ! Fstr
.i
) {
408 (void) fprintf(stderr
,
409 "%s: font %s for device %s not found in %s\n",
410 Pname
, Devfont
, Device
, p
);