|
|
1.1 root 1: /*
2: * Copyright (c) 1984, 1985 Xerox Corp.
3: * Handle troff here
4: *
5: * note that Troff uses "fat points" of which there are exactly 72 per inch.
6: *
7: * HISTORY
8: * Nov, 1985 Lee Moore, Xerox Webster Research Center
9: * Created.
10: */
11:
12: #include <stdio.h>
13: #include <math.h>
14: #include "stack.h"
15: #include "token.h"
16: #include "config.h"
17: #include "ipmetrics.h"
18: #include "troff.h"
19:
20: #define TRUE 1
21: #define FALSE 0
22:
23:
24: /* the following value should be choosen so that none of the widths
25: * is greater than 256
26: */
27: #define UNITWIDTH 5 /* was 10 */
28:
29:
30: #define MAXSPECIALNAMES 221 /* maximum number of special characters.
31: * this constant is fixed in Troff
32: */
33:
34: #define public
35: #define private static
36:
37: public char *malloc();
38:
39: public char *DeviceName,
40: *LibraryDirectory;
41:
42: struct CharElement {
43: struct CharElement *Next;
44: char CharName[3]; };
45:
46: private struct CharElement *CharSet = NULL;
47:
48: private int SetOfPointSizes[MAXPOINTSIZE],
49: FontCount = 0;
50:
51: public
52: InitTroff() {
53: }
54:
55: public
56: CleanUpTroff(configChain)
57: struct FontConfig *configChain; {
58: struct FontConfig *p;
59:
60: WriteDescFile(configChain);
61: WriteFontMapFile(configChain);
62: WriteInstallFile(configChain);
63: WriteCleanUpFile(configChain);
64:
65: for( p = configChain; p != NULL; p = p->Next )
66: if( !p->SeenFlag )
67: printf("couldn't find: %s/%s/%s\n",
68: p->FontPt1, p->FontPt2, p->FontPt3);
69: }
70:
71: private
72: WriteDescFile(configChain)
73: struct FontConfig *configChain; {
74: int i;
75: FILE *deviceFile;
76: struct FontConfig *p;
77:
78: if( (deviceFile = fopen("DESC", "w")) == NULL ) {
79: printf("can't open 'DESC' for writing\n");
80: exit(1); }
81:
82: /* output boiler plate */
83: fprintf(deviceFile, "# describe the '%s' interpress device\n", DeviceName);
84: fprintf(deviceFile, "res %d\n", MICAS_PER_INCH);
85: fprintf(deviceFile, "hor 1\n");
86: fprintf(deviceFile, "vert 1\n");
87: fprintf(deviceFile, "unitwidth %d\n", UNITWIDTH);
88: fprintf(deviceFile, "paperwidth %d\n", PAGE_WIDTH_IN_MICAS);
89: fprintf(deviceFile, "paperlength %d\n", PAGE_HEIGHT_IN_MICAS);
90:
91: /* output sizes */
92: fprintf(deviceFile, "sizes ");
93:
94: for( i = 1; i < MAXPOINTSIZE; i++ )
95: if( SetOfPointSizes[i] )
96: fprintf(deviceFile," %d", i);
97:
98: fprintf(deviceFile, " 0\n");
99:
100: /* output fonts */
101: fprintf(deviceFile, "fonts %d ", FontCount);
102:
103: for( p = configChain; p != NULL; p = p->Next )
104: if( p->SeenFlag )
105: fprintf(deviceFile, "%s ", p->TroffName);
106:
107: fprintf(deviceFile, "\n");
108: PrintCharSet(deviceFile);
109: fclose(deviceFile); }
110:
111:
112:
113: private
114: WriteFontMapFile(configChain)
115: struct FontConfig *configChain; {
116: int i;
117: FILE *fontMapFile;
118: struct FontConfig *p;
119:
120: if( (fontMapFile = fopen(FONTMAPFILENAME, "w")) == NULL ) {
121: fprintf(stderr, "can't open the file '%s' for writing\n", FONTMAPFILENAME);
122: return; }
123:
124: for( p = configChain; p != NULL; p = p->Next )
125: if( p->SeenFlag )
126: fprintf(fontMapFile, "%s %s/%s/%s\n", p->TroffName,
127: p->FontPt1, p->FontPt2, p->FontPt3);
128:
129: fclose(fontMapFile);
130: chmod(FONTMAPFILENAME, 0755); }
131:
132:
133: private
134: WriteInstallFile(configChain)
135: struct FontConfig *configChain; {
136: int i;
137: FILE *installFile;
138: struct FontConfig *p;
139:
140: if( (installFile = fopen(INSTALLNAME, "w")) == NULL ) {
141: fprintf(stderr, "can't open the file 'install' for writing\n");
142: return; }
143:
144: fprintf(installFile, "#! /bin/sh\n");
145: fprintf(installFile, "if test ! -d %s/fonts/%s\n", LibraryDirectory, DeviceName);
146: fprintf(installFile, " then\n");
147: fprintf(installFile, " mkdir %s/fonts/%s\n", LibraryDirectory, DeviceName);
148: fprintf(installFile, " fi\n");
149: fprintf(installFile, "if test ! -d %s/fonts/%s/devipress\n", LibraryDirectory, DeviceName);
150: fprintf(installFile, " then\n");
151: fprintf(installFile, " mkdir %s/fonts/%s/devipress\n", LibraryDirectory, DeviceName);
152: fprintf(installFile, " fi\n");
153:
154:
155: for( p = configChain; p != NULL; p = p->Next )
156: if( p->SeenFlag )
157: fprintf(installFile, "cp %s %s/fonts/%s/devipress\n",
158: p->TroffName, LibraryDirectory, DeviceName);
159:
160: fprintf(installFile, "cp DESC %s/fonts/%s/devipress\n", LibraryDirectory,
161: DeviceName);
162: fprintf(installFile, "cp %s %s/fonts/%s/devipress\n", FONTMAPFILENAME,
163: LibraryDirectory, DeviceName);
164: fprintf(installFile, "cd %s/fonts/%s/devipress\n", LibraryDirectory,
165: DeviceName);
166: fprintf(installFile, "makedev DESC\n");
167: fprintf(installFile, "makextdev DESC\n");
168: fclose(installFile);
169: chmod(INSTALLNAME, 0755); }
170:
171:
172: /*
173: * write a file that rm's all the files created by this program
174: */
175:
176: private
177: WriteCleanUpFile(configChain)
178: struct FontConfig *configChain; {
179: int i;
180: FILE *cleanupFile;
181: struct FontConfig *p;
182:
183: if( (cleanupFile = fopen(CLEANUPNAME, "w")) == NULL ) {
184: fprintf(stderr, "can't open the file 'cleanup' for writing\n");
185: return; }
186:
187: fprintf(cleanupFile, "#! /bin/sh\n");
188:
189: for( p = configChain; p != NULL; p = p->Next )
190: if( p->SeenFlag )
191: fprintf(cleanupFile, "rm %s\n", p->TroffName);
192:
193: fprintf(cleanupFile, "rm DESC\n");
194: fprintf(cleanupFile, "rm %s\n", INSTALLNAME);
195: fprintf(cleanupFile, "rm %s\n", FONTMAPFILENAME);
196: fprintf(cleanupFile, "rm %s\n", CLEANUPNAME);
197: fclose(cleanupFile);
198: chmod(CLEANUPNAME, 0755); }
199:
200: /*
201: * called once per font on the stack
202: */
203:
204: public
205: PerTroffFont(configChain, fontDescVec)
206: struct FontConfig *configChain;
207: unsigned char *fontDescVec; {
208: unsigned char *charMetricsProperty,
209: *metricsProperty,
210: *width,
211: *charMetric;
212: char iSender[MAXTOKENSIZE],
213: iCharName[MAXTOKENSIZE],
214: fileType[MAXTOKENSIZE],
215: *fontName[3],
216: iCharSet[MAXTOKENSIZE],
217: iCharCode[MAXTOKENSIZE];
218: FILE *descFile,
219: *modelFile;
220: struct FontConfig *p;
221: struct TokenState *ts;
222: int charSet,
223: charNumber,
224: charIndex,
225: xWidth;
226:
227: if( !GetFontNameProperty(fontDescVec, fontName) ) {
228: fprintf(stderr, "ipmetrics: can't get font name\n");
229: return;
230: }
231:
232: if( (charMetricsProperty = GetStringProp("characterMetrics", fontDescVec))
233: == NULL ) {
234: printf("ipmetrics: can't find 'characterMetrics' property\n");
235: return; }
236:
237: for( p = configChain; p != NULL; p = p->Next ) {
238: if( !(strcmp(p->FontPt1, fontName[0]) == 0 &&
239: strcmp(p->FontPt2, fontName[1]) == 0 &&
240: strcmp(p->FontPt3, fontName[2]) == 0) )
241: continue;
242:
243: if( (descFile = fopen(p->TroffName , "w")) == NULL ) {
244: printf("ipmetrics: can't open %s for writing\n", p->TroffName);
245: return;}
246:
247: if( (modelFile = fopen(p->MapFile, "r")) == NULL ) {
248: printf("ipmetrics: can't open %s for reading\n", p->MapFile);
249: return;}
250:
251: p->SeenFlag = TRUE;
252: /* (void) strcpy(malloc((unsigned) 3), p->TroffName); */
253: FontCount++;
254:
255: ts = InitTokenStream(modelFile);
256:
257: fprintf(descFile, "#\n");
258: fprintf(descFile, "# %s/%s/%s for Interpress device %s\n", p->FontPt1, p->FontPt2, p->FontPt3, DeviceName);
259: fprintf(descFile, "name %s\n", p->TroffName);
260: fprintf(descFile, "internalname %d\n", FontCount);
261:
262: GetToken(ts, fileType, MAXTOKENSIZE);
263:
264: if( strcmp(fileType, "special") == 0 )
265: fprintf(descFile, "special\n");
266: else
267: ProcessTroffLigatures(charMetricsProperty, descFile);
268:
269: fprintf(descFile, "charset\n");
270:
271: while( !EndOfFile(ts) ) {
272: GetToken(ts, iCharSet, MAXTOKENSIZE);
273: sscanf(iCharSet, "%o", &charSet);
274: GetToken(ts, iCharCode, MAXTOKENSIZE);
275: sscanf(iCharCode, "%o", &charNumber);
276: GetToken(ts, iSender, MAXTOKENSIZE);
277: GetToken(ts, iCharName, MAXTOKENSIZE);
278: charIndex = Make16BitChar(charSet, charNumber);
279:
280: /* skip the rest of this loop if it's not in this font */
281: if( (charMetric =
282: GetIntegerProp(charIndex, charMetricsProperty)) == NULL )
283: continue;
284:
285: if( (width = GetStringProp("widthX", charMetric)) == NULL ){
286: printf("ipmetrics: can't find widthX property of %d\n",
287: charIndex);
288: continue;}
289:
290: if( gettype(width) != type_number ) {
291: printf("ipmetrics: width not of type number for %d\n",
292: charIndex);
293: continue;}
294:
295: if( getsubtype(width) != subtype_rational ) {
296: printf("ipmetrics: width not of subtype number for %d\n",
297: charIndex);
298: continue;}
299:
300: xWidth = (getnumerator(width)*UNITWIDTH*MICAS_PER_INCH +
301: (getdenominator(width) * POINTS_PER_INCH)/2)/
302: (getdenominator(width) * POINTS_PER_INCH);
303:
304: if( xWidth >= 256 )
305: printf("ipmetrics: warning width >= 256\n");
306:
307: fprintf(descFile, "%s\t%d\t%s\t", iCharName, xWidth,
308: iSender);
309:
310: if( charIndex < 0377 )
311: fprintf(descFile, "%d\n", charIndex);
312: else
313: fprintf(descFile, "0377\t0%o\n", charIndex);
314:
315: CheckForSpecialness(iCharName);
316:
317: while( !EndOfLine(ts) ) {
318: GetToken(ts, iCharName, MAXTOKENSIZE);
319: fprintf(descFile, "%s\t\"\n", iCharName);
320: CheckForSpecialness(iCharName);}}
321:
322: CloseTokenStream(ts);
323: fclose(descFile);
324: fclose(modelFile);
325: }
326:
327: if( (metricsProperty = GetStringProp("metrics", fontDescVec))
328: != NULL ) {
329: unsigned char *easyProperty;
330:
331: if( (easyProperty = GetStringProp("easy", metricsProperty))
332: != NULL )
333: ProcessEasy(easyProperty);
334: }
335: }
336:
337: /*
338: * assume that the font is in XC1-1-1 standard and find the ligatures
339: * that troff wants
340: */
341:
342: private
343: ProcessTroffLigatures(charMetricsVec, descFile)
344: unsigned char *charMetricsVec;
345: FILE *descFile; {
346: char ligatureNames[21];
347:
348: (void) strcpy(ligatureNames, "");
349:
350: if( GetIntegerProp(Make16BitChar(0360, 044), charMetricsVec) != NULL )
351: (void) strcat(ligatureNames, " fi");
352:
353: if( GetIntegerProp(Make16BitChar(0360, 045), charMetricsVec) != NULL )
354: (void) strcat(ligatureNames, " fl");
355:
356: if( GetIntegerProp(Make16BitChar(0360, 041), charMetricsVec) != NULL )
357: (void) strcat(ligatureNames, " ff");
358:
359: if( GetIntegerProp(Make16BitChar(0360, 042), charMetricsVec) != NULL )
360: (void) strcat(ligatureNames, " ffi");
361:
362: if( GetIntegerProp(Make16BitChar(0360, 043), charMetricsVec) != NULL )
363: (void) strcat(ligatureNames, " ffl");
364:
365: if( strcmp(ligatureNames, "") != 0 )
366: fprintf(descFile, "ligatures %s 0\n", ligatureNames);}
367:
368: /*
369: * Check to see if a character is special and add it to the "charset"
370: * in the DESC file if it is.
371: */
372:
373: private
374: CheckForSpecialness(s)
375: char *s; {
376: /* right now, if it two characters long, then it must be special */
377: if( strlen(s) == 2 )
378: AddToCharSet(s); }
379:
380: /*
381: * add a special character to the set of special characters. The set
382: * is implemented as a linked list.
383: */
384:
385: private
386: AddToCharSet(s)
387: char *s; {
388: struct CharElement **p,
389: *q;
390:
391: p = &CharSet;
392:
393: while( *p != NULL ) {
394: if( strcmp(s, (*p)->CharName) == 0 )
395: return;
396:
397: p = &(*p)->Next; }
398:
399: q = (struct CharElement *) malloc((unsigned) sizeof(struct CharElement));
400: (void) strcpy(q->CharName, s);
401: q->Next = NULL;
402: *p = q; }
403:
404: /*
405: * print out the list of special characters to the DESC file
406: */
407:
408: private
409: PrintCharSet(file)
410: FILE *file; {
411: int itemsPerLine;
412: struct CharElement *p;
413:
414: /* test to see if there is a char. set. ditroff requires this!
415: * you just can't have a null charset! */
416: if( CharSet == NULL )
417: return;
418:
419: fprintf(file, "charset\n");
420: itemsPerLine = 0;
421:
422: for( p = CharSet; p != NULL; p = p->Next ) {
423: fprintf(file, " %s", p->CharName);
424:
425: if( itemsPerLine++ > 20 ) {
426: fputc('\n', file);
427: itemsPerLine = 0; } }
428:
429: if( itemsPerLine != 0 )
430: fputc('\n', file); }
431:
432: /*
433: * Process the "easy" property of the "metrics" property. This
434: * will tell us what (viewing) sizes the font is available in.
435: */
436:
437: private
438: ProcessEasy(easyProperty)
439: unsigned char *easyProperty; {
440: int depth,
441: i;
442: unsigned char **array;
443:
444: if( gettype(easyProperty) != type_vector ||
445: getsubtype(easyProperty) != subtype_general ) {
446: printf("ipmetrics: wrong vector type in 'easy'\n");
447: return; }
448:
449: depth = getdepth(easyProperty);
450: array = getvector(easyProperty);
451:
452: for( i = 0; i < depth; i++ ) {
453: double *transform,
454: fPointSize;
455: int iPointSize;
456:
457: if( gettype(array[i]) != type_transformation ) {
458: printf("ipmetrics: transforms not found in 'easy'\n");
459: return; }
460:
461: transform = gettransformation(array[i]);
462:
463: if( transform[0] != transform[4] ) {
464: printf("ipmetrics: only square transforms in 'easy'\n");
465: return; }
466:
467: if( transform[1] != 0 || transform[2] != 0 ||
468: transform[3] != 0 || transform[5] != 0 ) {
469: printf("ipmetrics: troff doesn't support rotations\n");
470: return; }
471:
472: fPointSize = transform[0]*72*100000/2540;
473: iPointSize = fPointSize + 0.5;
474:
475: if( fabs(fPointSize - iPointSize) > .25 ) {
476: printf("ipmetrics: troff doesn't support fractional points: %f6.2\n", fPointSize);
477: return; }
478:
479: SetOfPointSizes[iPointSize] = 1;
480: free((char *) transform);
481: }
482:
483: free((char *) array);
484: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.