]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/texttops.c
Initial revision
[thirdparty/cups.git] / filter / texttops.c
1 /*
2 * "$Id: texttops.c,v 1.1 1996/10/14 16:07:57 mike Exp $"
3 *
4 * PostScript text output filter for espPrint, a collection of printer
5 * drivers.
6 *
7 * Copyright 1993-1996 by Easy Software Products
8 *
9 * These coded instructions, statements, and computer programs contain
10 * unpublished proprietary information of Easy Software Products, and
11 * are protected by Federal copyright law. They may not be disclosed
12 * to third parties or copied or duplicated in any form, in whole or
13 * in part, without the prior written consent of Easy Software Products.
14 *
15 * Contents:
16 *
17 * Revision History:
18 *
19 * $Log: texttops.c,v $
20 * Revision 1.1 1996/10/14 16:07:57 mike
21 * Initial revision
22 *
23 */
24
25 /*
26 * Include necessary headers...
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33
34 #include <pod.h>
35 #include <errorcodes.h>
36 #include <license.h>
37
38
39 /*
40 * Constants...
41 */
42
43 #ifndef FALSE
44 # define FALSE 0
45 # define TRUE (!FALSE)
46 #endif /* !FALSE */
47
48 #define MAX_COLUMNS 256
49 #define MAX_LINES 256
50
51 #define ATTR_BOLD 0x01
52 #define ATTR_UNDERLINE 0x02
53
54
55 /*
56 * Character/attribute structure...
57 */
58
59 typedef struct
60 {
61 char ch, /* ASCII character */
62 attr; /* Any attributes */
63 } lchar_t;
64
65
66 /*
67 * Globals...
68 */
69
70 int Verbosity = 0;
71 int SizeLines = 60,
72 SizeColumns = 80,
73 PageColumns = 1;
74
75 float CharsPerInch = 10.0;
76 int LinesPerInch = 6;
77
78
79 /*
80 * 'Setup()' - Output a PostScript prolog for this page.
81 */
82
83 void
84 Setup(FILE *out,
85 PDSizeTableStruct *size,
86 char *fontname,
87 float fontsize,
88 int landscape)
89 {
90 int i;
91 float length, width, left;
92
93
94 LinesPerInch = 72.0 / fontsize;
95 CharsPerInch = 120.0 / fontsize;
96
97 if (landscape)
98 {
99 SizeColumns = (size->length - 2.0 * size->top_margin - (PageColumns - 1) * 0.25) * CharsPerInch;
100 SizeLines = (size->width - 2.0 * size->left_margin) * LinesPerInch;
101
102 left = 72.0 * size->top_margin;
103 width = 72.0 * (size->length - 2.0 * size->top_margin) / PageColumns;
104 length = 72.0 * (size->width - size->left_margin) - fontsize;
105 }
106 else
107 {
108 SizeColumns = (size->width - 2.0 * size->left_margin - (PageColumns - 1) * 0.25) * CharsPerInch;
109 SizeLines = (size->length - 2.0 * size->top_margin) * LinesPerInch;
110
111 left = 72.0 * size->left_margin;
112 width = 72.0 * (size->width - 2.0 * size->left_margin) / PageColumns;
113 length = 72.0 * (size->length - size->top_margin) - fontsize;
114 };
115
116 SizeColumns /= PageColumns;
117
118 fputs("%!PS-Adobe-3.0\n", out);
119 fprintf(out, "%%%%BoundingBox: %f %f %f %f\n",
120 72.0 * size->left_margin,
121 72.0 * size->top_margin,
122 72.0 * (size->width - size->left_margin),
123 72.0 * (size->length - size->left_margin));
124 fputs("%%LanguageLevel: 1\n", out);
125 fputs("%%Creator: ntext2ps 3.1 Copyright 1993-1996 Easy Software Products\n", out);
126 fprintf(out, "%%%%Pages: (atend)\n");
127 fputs("%%EndComments\n\n", out);
128
129 fputs("%%BeginProlog\n", out);
130 fprintf(out, "/R /%s findfont %f scalefont def\n", fontname, fontsize);
131 fprintf(out, "/B /%s-Bold findfont %f scalefont def\n", fontname, fontsize);
132 fprintf(out, "/S { setfont /y exch %f mul %f sub neg def %f mul %f add exch %f mul add /x exch def "
133 "x y moveto show } bind def\n",
134 fontsize, length, 72.0 / CharsPerInch, left, width);
135 fprintf(out, "/U { setfont /y exch %f mul %f sub neg def %f mul %f add exch %f mul add /x exch def "
136 "x y moveto dup show x y moveto stringwidth rlineto } bind def\n",
137 fontsize, length, 72.0 / CharsPerInch, left, width);
138 fputs("%%EndProlog\n", out);
139 }
140
141
142 void
143 Shutdown(FILE *out,
144 int pages)
145 {
146 fprintf(out, "%%%%Pages: %d\n", pages);
147 fputs("%%EOF\n", out);
148 }
149
150
151 void
152 StartPage(FILE *out,
153 int page)
154 {
155 fprintf(out, "%%%%Page: %d\n", page);
156 }
157
158
159 void
160 EndPage(FILE *out)
161 {
162 fputs("showpage\n", out);
163 fputs("%%EndPage\n", out);
164 }
165
166
167 void
168 output_line(FILE *out, int page_column, int column, int row, int attr, char *line)
169 {
170 fprintf(out, "(%s) %d %d %d %s %s\n", line, page_column, column,
171 row, (attr & ATTR_BOLD) ? "B" : "R", (attr & ATTR_UNDERLINE) ? "U" : "S");
172 }
173
174
175 void
176 OutputLine(FILE *out,
177 int page_column,
178 int row,
179 lchar_t *buffer)
180 {
181 int column,
182 linecol,
183 attr;
184 char line[MAX_COLUMNS * 2 + 1],
185 *lineptr;
186
187
188 for (column = 0, attr = 0, lineptr = line, linecol = 0;
189 column < SizeColumns;
190 column ++, buffer ++)
191 {
192 if (buffer->ch == '\0')
193 break;
194
195 if (attr ^ buffer->attr)
196 {
197 if (lineptr > line)
198 {
199 *lineptr = '\0';
200 output_line(out, page_column, linecol, row, attr, line);
201 lineptr = line;
202 };
203
204 attr = buffer->attr;
205 linecol = column;
206 };
207
208 if (strchr("()\\", buffer->ch) != NULL)
209 {
210 *lineptr = '\\';
211 lineptr ++;
212 };
213
214 *lineptr = buffer->ch;
215 lineptr ++;
216 };
217
218 if (lineptr > line)
219 {
220 *lineptr = '\0';
221 output_line(out, page_column, linecol, row, attr, line);
222 };
223 }
224
225
226 /*
227 * 'Usage()' - Print usage message and exit.
228 */
229
230 void
231 Usage(void)
232 {
233 fputs("Usage: ntext2ps -P <printer-name> [-D]\n", stderr);
234 fputs(" [-e] [-s] [-w] [-Z]\n", stderr);
235 fputs(" [-L <log-file>] [-O <output-file>]\n", stderr);
236 fputs(" [-M <printer-model]\n", stderr);
237
238 exit(ERR_BAD_ARG);
239 }
240
241
242 /*
243 * 'main()' - Main entry and processing of driver.
244 */
245
246 void
247 main(int argc, /* I - Number of command-line arguments */
248 char *argv[]) /* I - Command-line arguments */
249 {
250 int i, /* Looping var */
251 ch; /* Current char from file */
252 char *opt; /* Current option character */
253 int empty_infile, /* TRUE if the input file is empty */
254 need_status; /* TRUE if all we need to do is update the printer status */
255 char *filename, /* Input filename, if specified (NULL otherwise). */
256 *printer; /* Name of printer */
257 FILE *fp; /* Input file */
258 int line,
259 column,
260 page_column,
261 page,
262 landscape;
263 char *fontname;
264 float fontsize;
265 PDInfoStruct *info; /* POD info */
266 PDStatusStruct *status; /* POD status */
267 time_t mod_time; /* Modification time */
268 PDSizeTableStruct *size; /* Page size */
269 char *outfile;
270 FILE *out;
271 lchar_t buffer[MAX_COLUMNS];
272
273
274 /*
275 * Process any command-line args...
276 */
277
278 filename = NULL;
279 outfile = NULL;
280 fontname = "Courier";
281 fontsize = 12.0;
282 landscape = 0;
283
284 if (argc < 3)
285 Usage();
286
287 for (i = 1; i < argc; i ++)
288 if (argv[i][0] == '-')
289 for (opt = argv[i] + 1; *opt != '\0'; opt ++)
290 switch (*opt)
291 {
292 case 'P' : /* Specify the printer name */
293 i ++;
294 if (i >= argc)
295 Usage();
296
297 printer = argv[i];
298 break;
299
300 case 'L' : /* Log file */
301 i ++;
302 if (i >= argc)
303 Usage();
304
305 freopen(argv[i], "w", stderr);
306 break;
307
308 case 'O' : /* Output file */
309 i ++;
310 if (i >= argc || outfile != NULL)
311 Usage();
312
313 outfile = argv[i];
314 break;
315
316 case 'D' : /* Produce debugging messages */
317 Verbosity ++;
318 break;
319
320 case 'l' : /* Landscape output */
321 landscape = TRUE;
322 break;
323
324 case 'F' : /* Font name */
325 i ++;
326 if (i >= argc)
327 Usage();
328
329 fontname = argv[i];
330 break;
331
332 case 'p' : /* Font pointsize */
333 i ++;
334 if (i >= argc)
335 Usage();
336
337 fontsize = atof(argv[i]);
338 break;
339
340 case 'M' : /* Multiple column mode */
341 i ++;
342 if (i >= argc)
343 Usage();
344
345 PageColumns = atof(argv[i]);
346 break;
347
348 default :
349 Usage();
350 break;
351 }
352 else if (filename != NULL)
353 Usage();
354 else
355 filename = argv[i];
356
357 if (Verbosity)
358 {
359 fputs("ntext2ps: Command-line args are:", stderr);
360 for (i = 1; i < argc; i ++)
361 fprintf(stderr, " %s", argv[i]);
362 fputs("\n", stderr);
363 };
364
365 /*
366 * Check for necessary args...
367 */
368
369 if (printer == NULL)
370 Usage();
371
372 /*
373 * Open the POD database files and get the printer definition record.
374 */
375
376 if (PDLocalReadInfo(printer, &info, &mod_time) < 0)
377 {
378 fprintf(stderr, "ntext2ps: Could not open required POD database files for printer \'%s\'.\n",
379 printer);
380 fprintf(stderr, " Are you sure all required POD files are properly installed?\n");
381
382 PDPerror("ntext2ps");
383 exit(ERR_POD_ACCESS);
384 };
385
386 status = info->active_status;
387 size = PDFindPageSize(info, PD_SIZE_CURRENT);
388
389 /*
390 * Setup the output file...
391 */
392
393 if (outfile == NULL)
394 out = stdout;
395 else
396 out = fopen(outfile, "w");
397
398 if (out == NULL)
399 {
400 fprintf(stderr, "ntext2ps: Unable to create PostScript output to %s - %s\n",
401 outfile == NULL ? "(stdout)" : outfile, strerror(errno));
402 exit(ERR_TRANSMISSION);
403 };
404
405 Setup(out, size, fontname, fontsize, landscape);
406
407 /*
408 * Read text from the specified source and print them...
409 */
410
411 if (filename != NULL)
412 {
413 if ((fp = fopen(filename, "r")) == NULL)
414 {
415 Shutdown(out, 0);
416 exit(ERR_DATA_FILE);
417 };
418 }
419 else
420 fp = stdin;
421
422 if (fp == NULL)
423 {
424 Shutdown(out, 0);
425 exit(ERR_DATA_SHORT_FILE);
426 };
427
428 empty_infile = TRUE;
429 column = 0;
430 line = -1;
431 page = 0;
432 page_column = 0;
433
434 memset(buffer, 0, sizeof(buffer));
435
436 while ((ch = getc(fp)) >= 0)
437 {
438 empty_infile = FALSE;
439
440 if (line < 0)
441 {
442 page ++;
443 StartPage(out, page);
444 line = 0;
445 page_column = 0;
446 };
447
448 switch (ch)
449 {
450 case 0x08 : /* BS - backspace for boldface & underline */
451 if (column > 0)
452 column --;
453 break;
454 case 0x09 : /* HT - tab to next 8th column */
455 do
456 {
457 if (column >= SizeColumns)
458 { /* Wrap text to margins */
459 OutputLine(out, page_column, line, buffer);
460 line ++;
461 if (line >= SizeLines)
462 {
463 page_column ++;
464 line = 0;
465 if (page_column >= PageColumns)
466 {
467 EndPage(out);
468 line = -1;
469 };
470 };
471 memset(buffer, 0, sizeof(buffer));
472 column = 0;
473 };
474
475 buffer[column].ch = ' ';
476 column ++;
477 }
478 while (column & 7);
479 break;
480 case 0x0a : /* LF - output current line */
481 OutputLine(out, page_column, line, buffer);
482 line ++;
483 if (line >= SizeLines)
484 {
485 page_column ++;
486 line = 0;
487 if (page_column >= PageColumns)
488 {
489 EndPage(out);
490 line = -1;
491 };
492 };
493 memset(buffer, 0, sizeof(buffer));
494 column = 0;
495 break;
496 case 0x0c : /* FF - eject current page... */
497 OutputLine(out, page_column, line, buffer);
498 page_column ++;
499 line = 0;
500 if (page_column >= PageColumns)
501 {
502 EndPage(out);
503 line = -1;
504 };
505 memset(buffer, 0, sizeof(buffer));
506 column = 0;
507 break;
508 case 0x0d : /* CR - ignored */
509 break;
510 default : /* All others... */
511 if (ch < ' ')
512 break; /* Ignore other control chars */
513
514 if (column >= SizeColumns)
515 { /* Wrap text to margins */
516 OutputLine(out, page_column, line, buffer);
517 line ++;
518 if (line >= SizeLines)
519 {
520 page_column ++;
521 line = 0;
522 if (page_column >= PageColumns)
523 {
524 EndPage(out);
525 line = -1;
526 };
527 };
528 memset(buffer, 0, sizeof(buffer));
529 column = 0;
530 };
531
532 if (ch == buffer[column].ch)
533 buffer[column].attr |= ATTR_BOLD;
534 else if (buffer[column].ch == '_')
535 buffer[column].attr |= ATTR_UNDERLINE;
536
537 buffer[column].ch = ch;
538 column ++;
539 break;
540 };
541 };
542
543 if (line >= 0)
544 {
545 OutputLine(out, page_column, line, buffer);
546 EndPage(out);
547 page ++;
548 };
549
550 Shutdown(out, page);
551
552 if (empty_infile)
553 exit(ERR_DATA_SHORT_FILE);
554
555 /*
556 * Exit with no errors...
557 */
558
559 exit(NO_ERROR);
560 }
561
562
563 /*
564 * End of "$Id: texttops.c,v 1.1 1996/10/14 16:07:57 mike Exp $".
565 */