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 *Convstr(char *s
, int *len
) {
49 * length of result len
51 int c
; /* character assembly */
52 unsigned char *cp
; /* temporary character pointer */
53 char *em
; /* error message */
54 int i
; /* temporary index */
56 unsigned char *r
; /* result string */
58 * Make space for the result.
60 if ((r
= (unsigned char *)malloc(strlen((char *)s
) + 1)) == NULL
) {
61 (void) fprintf(stderr
, "%s: out of string space at %s\n",
66 * Copy the input string to the result, processing '\\' escapes.
68 for (cp
= r
, l
= 0; *s
;) {
73 if (*s
>= '0' && *s
<= '7') {
75 * '\xxx' -- octal form
77 for (c
= i
= 0; i
< 3; i
++, s
++) {
78 if (*s
< '0' || *s
> '7') {
79 em
= "non-octal char";
81 (void) fprintf(stderr
,
83 Pname
, em
, (char *)r
);
86 c
= (c
<< 3) + *s
- '0';
89 em
= "octal char > 0377";
94 } else if (*s
== 'x') {
96 * '\xyy' -- hexadecimal form
99 for (c
= i
= 0; i
< 2; i
++, s
++) {
100 #if defined(__STDC__)
101 if ( ! isalpha(*s
) && ! isdigit(*s
))
103 if ( ! isascii(*s
) && ! isalpha(*s
)
112 if (*s
>= '0' && *s
<= '9')
114 else if ((*s
>= 'a' && *s
<= 'f')
115 || (*s
>= 'A' && *s
<= 'F'))
117 (isupper(*s
) ? 'A' : 'a');
121 *cp
++ = (unsigned char)c
;
123 } else if (*s
== 'E' || *s
== 'e') {
125 * '\E' or '\e' -- ESCape
130 } else if (*s
== '\0') {
131 em
= "no char after \\";
135 * escaped character (for some reason)
142 * Copy a "normal" character.
156 * Convfont(nm, s, fn, fi) - convert a font for a device
159 static int Convfont(char* nm
, char *s
, char **fn
, unsigned char **fi
) {
160 /* output device name nm
161 * font definition string s
162 * font name address fn
163 * initialization string address fi
165 char *cp
; /* temporary character pointer */
166 int len
; /* length */
168 * Get the font name, allocate space for it and allocate space for
171 if ((cp
= strchr(s
, '=')) == NULL
) {
172 (void) fprintf(stderr
, "%s: bad %s font line format: %s\n",
176 if ((*fn
= (char *)malloc(cp
- s
+ 1)) == NULL
) {
177 (void) fprintf(stderr
, "%s: no space for %s font name %s\n",
181 (void) strncpy(*fn
, s
, cp
- s
);
182 (*fn
)[cp
- s
] = '\0';
184 * Assmble the font initialization string.
186 if ((*fi
= Convstr(cp
+ 1, &len
)) == NULL
)
193 * Defdev() - define the output device
197 unsigned char *fi
= NULL
; /* last font initialization string */
198 char *fn
= NULL
; /* font name */
199 int fd
= 0; /* found-device flag */
200 FILE *fs
; /* file stream */
201 int err
= 0; /* errror count */
202 int i
; /* temporary index */
203 int len
; /* length */
204 char line
[MAXLINE
]; /* line buffer */
205 char *p
; /* output device configuration file */
206 char *s
; /* temporary string pointer */
208 * Check for the built-in devices, ANSI, NONE or NORMAL (default).
210 Fstr
.b
= Fstr
.i
= Fstr
.it
= Fstr
.r
= NULL
;
211 Fstr
.bl
= Fstr
.il
= Fstr
.itl
= Fstr
.rl
= 0;
212 if (Device
== NULL
|| strcasecmp(Device
, "normal") == 0) {
216 (void) fprintf(stderr
,
217 "%s: font %s for device %s illegal\n",
218 Pname
, Devfont
, Device
? Device
: "NORMAL");
224 if (strcasecmp(Device
, "ansi") == 0) {
225 Fstr
.b
= Newstr((unsigned char *)"x[1m");
226 Fstr
.it
= Newstr((unsigned char *)"x[4m");
227 Fstr
.r
= Newstr((unsigned char *)"x[0m");
228 Fstr
.b
[0] = Fstr
.it
[0] = Fstr
.r
[0] = ESC
;
229 Fstr
.bl
= Fstr
.itl
= Fstr
.rl
= 4;
232 if (strcasecmp(Device
, "none") == 0)
235 * If a device configuration file path is supplied, use it.
242 * Use the CAWFLIB environment if it is defined.
244 if ((p
= getenv("CAWFLIB")) == NULL
)
246 len
= strlen(p
) + 1 + strlen(DEVCONFIG
) + 1;
247 if ((s
= (char *)malloc(len
)) == NULL
) {
248 (void) fprintf(stderr
, "%s: no space for %s name\n",
252 (void) sprintf(s
, "%s/%s", p
, DEVCONFIG
);
256 * Open the configuration file.
259 if ((fs
= fopen(p
, "r")) == NULL
)
261 if ((fs
= fopen(p
, "rt")) == NULL
)
264 (void) fprintf(stderr
, "%s: can't open config file: %s\n",
270 * Look for a device definition line -- a line that begins with a name.
272 while ( ! feof(fs
)) {
273 if (*line
== '\t' || *line
== '#' || *line
== ' ') {
274 (void) fgets(line
, MAXLINE
, fs
);
277 if ((s
= strrchr(line
, '\n')) != NULL
)
280 line
[MAXLINE
-1] = '\0';
284 if (strcmp(Device
, line
) != 0) {
285 (void) fgets(line
, MAXLINE
, fs
);
290 * Read the parameter lines for the device.
292 while (fgets(line
, MAXLINE
, fs
) != NULL
) {
294 for (i
= 1; line
[i
] == ' '; i
++)
296 } else if (*line
== '\t')
300 #if defined(__STDC__)
301 if ( ! isalpha(line
[i
])
303 if ( ! isascii(line
[i
]) || ! isalpha(line
[i
])
307 if ((s
= strrchr(line
, '\n')) != NULL
)
310 line
[MAXLINE
-1] = '\0';
313 * \tb=<bolding_string>
316 if (Fstr
.b
!= NULL
) {
317 (void) fprintf(stderr
,
318 "%s: dup bold for %s in %s: %s\n",
319 Pname
, Device
, p
, line
);
323 if ((Fstr
.b
= Convstr(&line
[i
+2], &Fstr
.bl
))
328 * \ti=<italicization_string>
331 if (Fstr
.it
!= NULL
) {
332 (void) fprintf(stderr
,
333 "%s: dup italic for %s in %s: %s\n",
334 Pname
, Device
, p
, line
);
335 (void) free(Fstr
.it
);
338 if ((Fstr
.it
= Convstr(&line
[i
+2], &Fstr
.itl
))
343 * \tr=<return_to_Roman_string>
346 if (Fstr
.r
!= NULL
) {
347 (void) fprintf(stderr
,
348 "%s: dup roman for %s in %s: %s\n",
349 Pname
, Device
, p
, line
);
353 if ((Fstr
.r
= Convstr(&line
[i
+2], &Fstr
.rl
))
358 * \tf=<font_name>=<font_initialization_string>
361 if ( ! Devfont
|| Fstr
.i
)
363 if ((i
= Convfont(Device
, &line
[i
+2], &fn
, &fi
))
366 else if (fn
&& strcmp(Devfont
, fn
) == 0) {
376 (void) free((char *)fi
);
384 (void) fprintf(stderr
,
385 "%s: unknown device %s line: %s\n",
386 Pname
, Device
, line
);
396 * See if the device stanza was located and the font exists.
399 (void) fprintf(stderr
, "%s: can't find device %s in %s\n",
403 if (Devfont
&& ! Fstr
.i
) {
404 (void) fprintf(stderr
,
405 "%s: font %s for device %s not found in %s\n",
406 Pname
, Devfont
, Device
, p
);