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 _PROTOTYPE(static unsigned char *Convstr
,(char *s
, int *len
));
35 _PROTOTYPE(static int Convfont
,(char *nm
, char *s
, char **fn
,
39 #define strcasecmp strcmpi
45 * Convstr(s, len) - convert a string
48 static unsigned char *
50 char *s
; /* input string */
51 int *len
; /* length of result */
53 int c
; /* character assembly */
54 unsigned char *cp
; /* temporary character pointer */
55 char *em
; /* error message */
56 int i
; /* temporary index */
58 unsigned char *r
; /* result string */
60 * Make space for the result.
62 if ((r
= (unsigned char *)malloc(strlen((char *)s
) + 1)) == NULL
) {
63 (void) fprintf(stderr
, "%s: out of string space at %s\n",
68 * Copy the input string to the result, processing '\\' escapes.
70 for (cp
= r
, l
= 0; *s
;) {
75 if (*s
>= '0' && *s
<= '7') {
77 * '\xxx' -- octal form
79 for (c
= i
= 0; i
< 3; i
++, s
++) {
80 if (*s
< '0' || *s
> '7') {
81 em
= "non-octal char";
83 (void) fprintf(stderr
,
85 Pname
, em
, (char *)r
);
88 c
= (c
<< 3) + *s
- '0';
91 em
= "octal char > 0377";
96 } else if (*s
== 'x') {
98 * '\xyy' -- hexadecimal form
101 for (c
= i
= 0; i
< 2; i
++, s
++) {
102 #if defined(__STDC__)
103 if ( ! isalpha(*s
) && ! isdigit(*s
))
105 if ( ! isascii(*s
) && ! isalpha(*s
)
114 if (*s
>= '0' && *s
<= '9')
116 else if ((*s
>= 'a' && *s
<= 'f')
117 || (*s
>= 'A' && *s
<= 'F'))
119 (isupper(*s
) ? 'A' : 'a');
123 *cp
++ = (unsigned char)c
;
125 } else if (*s
== 'E' || *s
== 'e') {
127 * '\E' or '\e' -- ESCape
132 } else if (*s
== '\0') {
133 em
= "no char after \\";
137 * escaped character (for some reason)
144 * Copy a "normal" character.
158 * Convfont(nm, s, fn, fi) - convert a font for a device
162 Convfont(nm
, s
, fn
, fi
)
163 char *nm
; /* output device name */
164 char *s
; /* font definition string */
165 char **fn
; /* font name address */
166 unsigned char **fi
; /* initialization string address */
168 char *cp
; /* temporary character pointer */
169 int len
; /* length */
171 * Get the font name, allocate space for it and allocate space for
174 if ((cp
= strchr(s
, '=')) == NULL
) {
175 (void) fprintf(stderr
, "%s: bad %s font line format: %s\n",
179 if ((*fn
= (char *)malloc(cp
- s
+ 1)) == NULL
) {
180 (void) fprintf(stderr
, "%s: no space for %s font name %s\n",
184 (void) strncpy(*fn
, s
, cp
- s
);
185 (*fn
)[cp
- s
] = '\0';
187 * Assmble the font initialization string.
189 if ((*fi
= Convstr(cp
+ 1, &len
)) == NULL
)
196 * Defdev() - define the output device
202 unsigned char *fi
= NULL
; /* last font initialization string */
203 char *fn
= NULL
; /* font name */
204 int fd
= 0; /* found-device flag */
205 FILE *fs
; /* file stream */
206 int err
= 0; /* errror count */
207 int i
; /* temporary index */
208 int len
; /* length */
209 char line
[MAXLINE
]; /* line buffer */
210 char *p
; /* output device configuration file */
211 char *s
; /* temporary string pointer */
213 * Check for the built-in devices, ANSI, NONE or NORMAL (default).
215 Fstr
.b
= Fstr
.i
= Fstr
.it
= Fstr
.r
= NULL
;
216 Fstr
.bl
= Fstr
.il
= Fstr
.itl
= Fstr
.rl
= 0;
217 if (Device
== NULL
|| strcasecmp(Device
, "normal") == 0) {
221 (void) fprintf(stderr
,
222 "%s: font %s for device %s illegal\n",
223 Pname
, Devfont
, Device
? Device
: "NORMAL");
229 if (strcasecmp(Device
, "ansi") == 0) {
230 Fstr
.b
= Newstr((unsigned char *)"x[1m");
231 Fstr
.it
= Newstr((unsigned char *)"x[4m");
232 Fstr
.r
= Newstr((unsigned char *)"x[0m");
233 Fstr
.b
[0] = Fstr
.it
[0] = Fstr
.r
[0] = ESC
;
234 Fstr
.bl
= Fstr
.itl
= Fstr
.rl
= 4;
237 if (strcasecmp(Device
, "none") == 0)
240 * If a device configuration file path is supplied, use it.
247 * Use the CAWFLIB environment if it is defined.
249 if ((p
= getenv("CAWFLIB")) == NULL
)
251 len
= strlen(p
) + 1 + strlen(DEVCONFIG
) + 1;
252 if ((s
= (char *)malloc(len
)) == NULL
) {
253 (void) fprintf(stderr
, "%s: no space for %s name\n",
257 (void) sprintf(s
, "%s/%s", p
, DEVCONFIG
);
261 * Open the configuration file.
264 if ((fs
= fopen(p
, "r")) == NULL
)
266 if ((fs
= fopen(p
, "rt")) == NULL
)
269 (void) fprintf(stderr
, "%s: can't open config file: %s\n",
275 * Look for a device definition line -- a line that begins with a name.
277 while ( ! feof(fs
)) {
278 if (*line
== '\t' || *line
== '#' || *line
== ' ') {
279 (void) fgets(line
, MAXLINE
, fs
);
282 if ((s
= strrchr(line
, '\n')) != NULL
)
285 line
[MAXLINE
-1] = '\0';
289 if (strcmp(Device
, line
) != 0) {
290 (void) fgets(line
, MAXLINE
, fs
);
295 * Read the parameter lines for the device.
297 while (fgets(line
, MAXLINE
, fs
) != NULL
) {
299 for (i
= 1; line
[i
] == ' '; i
++)
301 } else if (*line
== '\t')
305 #if defined(__STDC__)
306 if ( ! isalpha(line
[i
])
308 if ( ! isascii(line
[i
]) || ! isalpha(line
[i
])
312 if ((s
= strrchr(line
, '\n')) != NULL
)
315 line
[MAXLINE
-1] = '\0';
318 * \tb=<bolding_string>
321 if (Fstr
.b
!= NULL
) {
322 (void) fprintf(stderr
,
323 "%s: dup bold for %s in %s: %s\n",
324 Pname
, Device
, p
, line
);
328 if ((Fstr
.b
= Convstr(&line
[i
+2], &Fstr
.bl
))
333 * \ti=<italicization_string>
336 if (Fstr
.it
!= NULL
) {
337 (void) fprintf(stderr
,
338 "%s: dup italic for %s in %s: %s\n",
339 Pname
, Device
, p
, line
);
340 (void) free(Fstr
.it
);
343 if ((Fstr
.it
= Convstr(&line
[i
+2], &Fstr
.itl
))
348 * \tr=<return_to_Roman_string>
351 if (Fstr
.r
!= NULL
) {
352 (void) fprintf(stderr
,
353 "%s: dup roman for %s in %s: %s\n",
354 Pname
, Device
, p
, line
);
358 if ((Fstr
.r
= Convstr(&line
[i
+2], &Fstr
.rl
))
363 * \tf=<font_name>=<font_initialization_string>
366 if ( ! Devfont
|| Fstr
.i
)
368 if ((i
= Convfont(Device
, &line
[i
+2], &fn
, &fi
))
371 else if (fn
&& strcmp(Devfont
, fn
) == 0) {
381 (void) free((char *)fi
);
389 (void) fprintf(stderr
,
390 "%s: unknown device %s line: %s\n",
391 Pname
, Device
, line
);
401 * See if the device stanza was located and the font exists.
404 (void) fprintf(stderr
, "%s: can't find device %s in %s\n",
408 if (Devfont
&& ! Fstr
.i
) {
409 (void) fprintf(stderr
,
410 "%s: font %s for device %s not found in %s\n",
411 Pname
, Devfont
, Device
, p
);