text2pdf

Git mirror of http://www.eprg.org/pdfcorner/text2pdf/
git clone git://git.finwo.net/app/text2pdf
Log | Files | Refs | README

commit 7db02e8a97252d81fa0caa2746b453a6e5791659
Author: finwo <finwo@pm.me>
Date:   Tue, 28 Apr 2020 12:40:57 +0200

Initialize git repo

Diffstat:
A.gitignore | 1+
AMakefile | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atext2pdf.1 | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atext2pdf.c | 455+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 610 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +text2pdf diff --git a/Makefile b/Makefile @@ -0,0 +1,64 @@ +#======================================================================== +# Makefile for text2pdf by Nelson Beebe +# NB: This program requires an ANSI/ISO Standard C compiler, such as +# GNU gcc. +# +# The ".pok" file is a PDF file produced with +# "text2pdf text2pdf.c > text2pdf.pok" on some master system. Subsequent +# installations can be verified against this file using "make check". +# Nelson recommends using "make all check install". +# +# [16-Oct-1996] +#======================================================================== + +# Change this to suit local customs +BINDIR = /usr/local/bin + +# The rest of this Makefile should not require changes on any UNIX system +CHMOD = /bin/chmod + +DIFF = /bin/diff + +CP = /bin/cp + +RM = /bin/rm -f + +PROGRAM = text2pdf + +SHELL = /bin/sh + +#======================================================================== + +all: $(PROGRAM) + +check: $(PROGRAM) $(PROGRAM).pdf + @echo "The only differences should be in the /CreationDate lines" + -$(DIFF) $(PROGRAM).pdf $(PROGRAM).pok + +clean mostlyclean: + -$(RM) *.i + -$(RM) *.o + -$(RM) *~ + -$(RM) \#* + -$(RM) a.out + -$(RM) core + +clobber distclean: clean + -$(RM) $(PROGRAM) + -$(RM) $(PROGRAM).pdf + +install: all uninstall + $(CP) $(PROGRAM) $(BINDIR)/$(PROGRAM) + $(CHMOD) 775 $(BINDIR)/$(PROGRAM) + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + -$(RM) $(PROGRAM).pok + +$(PROGRAM).pdf: $(PROGRAM).c $(PROGRAM) + ./$(PROGRAM) $(PROGRAM).c >$(PROGRAM).pdf + +uninstall: + -$(RM) $(BINDIR)/$(PROGRAM) + diff --git a/text2pdf.1 b/text2pdf.1 @@ -0,0 +1,90 @@ +.TH TEXT2PDF 1 "V1.1, 02/97" "Local command" +.SH NAME +text2pdf \- traduction d'un fichier texte en un fichier Acrobat PDF + +.SH SYNOPSIS +.B text2pdf +[-options] [filename] + +.SH DESCRIPTION + +.B text2pdf +makes a 7-bit clean PDF file (version 1.1) from any input file. +It reads from standard input or a named file, and writes the PDF file +to standard output. + +.SH OPTIONS + +There are various options as follows: + +.TP 1i +.B -h +show this message +.TP +.B -f<font> +use PostScript <font> (must be in standard 14, default: Courier) +.TP +.B -I +use ISOLatin1Encoding (default) +.TP +.B -s<size> +use font at given pointsize (default 10) +.TP +.B -v<dist> +use given line spacing (default 12 points) +.TP +.B -l<lines> +lines per page (default 60, determined automatically if unspecified) +.TP +.B -c<chars> +maximum characters per line (default 80) +.TP +.B -t<spaces> +spaces per tab character (default 8) +.TP +.B -F +ignore formfeed characters (^L) +.TP +.B -A4 +use A4 paper (default) +.TP +.B -A3 +use A3 paper (default A4) +.TP +.B -x<width> +independent paper width in points +.TP +.B -y<height> +independent paper height in points +.TP +.B -2 +format in 2 columns +.TP +.B -L +landscape mode + +.P +Note that where one variable is implied by two options, the second option +takes precedence for that variable. (e.g. -A4 -y500). + +In +.B landscape +mode, page width and height are simply swapped over before +formatting, no matter how or when they were defined. + +.SH BUGS + +Backspace character is not processed, so the result of +.ce +.B "nroff -man man.1 | text2pdf > man.pdf" +has not a very nice touch. + +.SH AUTHOR +text2pdf v1.1 (c) Phil Smith, 1996., <pns@cs.nott.ac.uk> + +This software can be find at URL: +.ce +http://www.ep.cs.nott.ac.uk/~pns/pdfcorner/text2pdf/ + +.SH NOTE +Cette page de man est faite par Bertrand Decouty, fvrier 1997. diff --git a/text2pdf.c b/text2pdf.c @@ -0,0 +1,455 @@ +/************************************************************************** +This ugly, sparsely-commented program is the source for text2pdf version +1.1. It should be ANSI-conforming and compile on most platforms. You'll +need to change LF_EXTRA to 1 for machines which write 2 characters for \n. +These include PCs, of course. + +You may distribute the source or compiled versions free of charge. You may +not alter the source in any way other than those mentioned above without +the permission of the author, Phil Smith <phil@bagobytes.co.uk>. + +Please send any comments to the author. + +Copyright (c) Phil Smith, 1996 + +REVISION HISTORY + +Version 1.1 +11 Oct 96 Added handling of form-feed characters, removed need for tmp file, + put reference to resources in each page (avoid bug in Acrobat), + changed date format to PDF-1.1 standard. +12 Jun 96 Added check to avoid blank last page +12 Jun 96 Added LINE_END def to get round platform-specific \r, \n etc. +18 Mar 96 Added ISOLatin1Encoding option +**************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#define LF_EXTRA 0 /* how many extra characters are written for \n */ + /* change to 1 for PCs (where \n => <CR><LF>) */ + +#define LINE_END '\015' /* CR used in xref table */ +#define FF 12 /* formfeed character (^L) */ + +char *appname = "text2pdf v1.1"; +char *progname = "text2pdf"; + +FILE *infile; +int pageNo = 0; +int pageObs[500]; +int curObj = 5; /* object number being or last written */ +long locations[1000]; + +char font[256]; +char *defaultFont = "Courier"; +int ISOEnc = 0; +int doFFs = 1; +int tab = 8; +int pointSize = 10; +int vertSpace = 12; +int lines = 0; +int cols = 80; /* max chars per output line */ +int columns = 1; /* number of columns */ + +/* Default paper is Letter size, as in distiller */ +int pageHeight = 792; +int pageWidth = 612; + +unsigned char buf[1024]; +unsigned long fpos = 0; + +void writestr(char *str) { + /* Everything written to the PDF file goes through this function. */ + /* This means we can keep track of the file position without using */ + /* ftell on a real (tmp) file. However, PCs write out 2 characters */ + /* for \n, so we need this ugly loop to keep fpos correct */ + + fpos += strlen(str); + while (*str) { + if (*str == '\n') fpos += LF_EXTRA; + putchar(*str++); + } +} + + +void WriteHeader(char *title){ + + struct tm *ltime; + time_t clock; + char datestring[30]; + + time(&clock); + ltime = localtime(&clock); + + strftime(datestring, 30, "D:%Y%m%d%H%M%S", ltime); + + writestr("%PDF-1.1\n"); + locations[1] = fpos; + writestr("1 0 obj\n"); + writestr("<<\n"); + sprintf(buf, "/CreationDate (%s)\n", datestring); writestr(buf); + sprintf(buf, "/Producer (%s (\\251 Phil Smith, 1996))\n", appname); writestr(buf); + if (title) {sprintf(buf, "/Title (%s)\n", title); writestr(buf);} + writestr(">>\n"); + writestr("endobj\n"); + + locations[2] = fpos; + writestr("2 0 obj\n"); + writestr("<<\n"); + writestr("/Type /Catalog\n"); + writestr("/Pages 3 0 R\n"); + writestr(">>\n"); + writestr("endobj\n"); + + locations[4] = fpos; + writestr("4 0 obj\n"); + writestr("<<\n"); + writestr("/Type /Font\n"); + writestr("/Subtype /Type1\n"); + writestr("/Name /F1\n"); + sprintf(buf, "/BaseFont %s\n", font); writestr(buf); + if (ISOEnc) { + writestr("/Encoding <<\n"); + writestr("/Differences [ 0 /.notdef /.notdef /.notdef /.notdef\n"); + writestr("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"); + writestr("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"); + writestr("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"); + writestr("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"); + writestr("/.notdef /.notdef /.notdef /.notdef /space /exclam\n"); + writestr("/quotedbl /numbersign /dollar /percent /ampersand\n"); + writestr("/quoteright /parenleft /parenright /asterisk /plus /comma\n"); + writestr("/hyphen /period /slash /zero /one /two /three /four /five\n"); + writestr("/six /seven /eight /nine /colon /semicolon /less /equal\n"); + writestr("/greater /question /at /A /B /C /D /E /F /G /H /I /J /K /L\n"); + writestr("/M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft\n"); + writestr("/backslash /bracketright /asciicircum /underscore\n"); + writestr("/quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p\n"); + writestr("/q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright\n"); + writestr("/asciitilde /.notdef /.notdef /.notdef /.notdef /.notdef\n"); + writestr("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"); + writestr("/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"); + writestr("/dotlessi /grave /acute /circumflex /tilde /macron /breve\n"); + writestr("/dotaccent /dieresis /.notdef /ring /cedilla /.notdef\n"); + writestr("/hungarumlaut /ogonek /caron /space /exclamdown /cent\n"); + writestr("/sterling /currency /yen /brokenbar /section /dieresis\n"); + writestr("/copyright /ordfeminine /guillemotleft /logicalnot /hyphen\n"); + writestr("/registered /macron /degree /plusminus /twosuperior\n"); + writestr("/threesuperior /acute /mu /paragraph /periodcentered\n"); + writestr("/cedilla /onesuperior /ordmasculine /guillemotright\n"); + writestr("/onequarter /onehalf /threequarters /questiondown /Agrave\n"); + writestr("/Aacute /Acircumflex /Atilde /Adieresis /Aring /AE\n"); + writestr("/Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave\n"); + writestr("/Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve\n"); + writestr("/Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n"); + writestr("/Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn\n"); + writestr("/germandbls /agrave /aacute /acircumflex /atilde /adieresis\n"); + writestr("/aring /ae /ccedilla /egrave /eacute /ecircumflex\n"); + writestr("/edieresis /igrave /iacute /icircumflex /idieresis /eth\n"); + writestr("/ntilde /ograve /oacute /ocircumflex /otilde /odieresis\n"); + writestr("/divide /oslash /ugrave /uacute /ucircumflex /udieresis\n"); + writestr("/yacute /thorn /ydieresis ]\n"); + writestr(">>\n"); + } + + writestr(">>\n"); + writestr("endobj\n"); + + locations[5] = fpos; + writestr("5 0 obj\n"); + writestr("<<\n"); + writestr(" /Font << /F1 4 0 R >>\n"); + writestr(" /ProcSet [ /PDF /Text ]\n"); + writestr(">>\n"); + writestr("endobj\n"); +} + +long StartPage(){ + long strmPos; + + locations[++curObj] = fpos; + pageObs[++pageNo] = curObj; + sprintf(buf, "%d 0 obj\n", curObj); writestr(buf); + writestr("<<\n"); + writestr("/Type /Page\n"); + writestr("/Parent 3 0 R\n"); + writestr("/Resources 5 0 R\n"); + sprintf(buf, "/Contents %d 0 R\n", ++curObj); writestr(buf); + writestr(">>\n"); + writestr("endobj\n"); + + locations[curObj] = fpos; + sprintf(buf, "%d 0 obj\n", curObj); writestr(buf); + writestr("<<\n"); + sprintf(buf, "/Length %d 0 R\n", curObj + 1); writestr(buf); + writestr(">>\n"); + writestr("stream\n"); + strmPos = fpos; + + writestr("BT\n"); + sprintf(buf, "/F1 %d Tf\n", pointSize); writestr(buf); + sprintf(buf, "1 0 0 1 50 %d Tm\n", pageHeight - 40); writestr(buf); + sprintf(buf, "%d TL\n", vertSpace); writestr(buf); + + return strmPos; +} + +void EndPage(long streamStart){ + long streamEnd; + + writestr("ET\n"); + streamEnd = fpos; + writestr("endstream\n"); + writestr("endobj\n"); + + locations[++curObj] = fpos; + sprintf(buf, "%d 0 obj\n", curObj); writestr(buf); + sprintf(buf, "%lu\n", streamEnd - streamStart); writestr(buf); + writestr("endobj\n"); +} + +void WritePages(){ + int atEOF = 0; + int atFF; + int atBOP; + long beginstream; + int lineNo, charNo; + int ch, column; + int padding, i; + + while (!atEOF) { + beginstream = StartPage(); + column = 1; + while (column++ <= columns) { + atFF = 0; + atBOP = 0; + lineNo = 0; + while (lineNo++ < lines && !atEOF && !atFF) { + writestr("("); + charNo = 0; + while (charNo++<cols && + (ch = getc(infile))!=EOF && + !(ch==FF && doFFs) && + ch!='\n') { + if (ch >= 32 && ch <= 127) { + if (ch == '(' || ch == ')' || ch == '\\') writestr("\\"); + sprintf(buf, "%c", (char)ch); writestr(buf); + } else { + if (ch == 9) { + padding = tab - ((charNo - 1) % tab); + for (i = 1; i <= padding; i++) writestr(" "); + charNo += (padding - 1); + } else { + if (ch != FF) { + /* write \xxx form for dodgy character */ + sprintf(buf, "\\%.3o", ch); writestr(buf); + } else { + /* don't print anything for a FF */ + charNo--; + } + } + } + } + writestr(")'\n"); + + /* messy stuff to handle formfeeds. Yuk! */ + if (ch == EOF) atEOF = 1; + if (ch == FF) atFF = 1; + if (lineNo == lines) atBOP = 1; + if (atBOP) { + ch = getc(infile); + if (ch == FF) ch = getc(infile); + if (ch == EOF) atEOF = 1; + else ungetc(ch, infile); + } + else if (atFF) { + ch = getc(infile); + if (ch == EOF) atEOF = 1; + else ungetc(ch, infile); + } + } + + if (column <= columns) { + sprintf(buf, "1 0 0 1 %d %d Tm\n", + (pageWidth / 2) + 25, pageHeight - 40); + writestr(buf); + } + } + EndPage(beginstream); + } +} + +void WriteRest(){ + long xref; + int i; + + locations[3] = fpos; + writestr("3 0 obj\n"); + writestr("<<\n"); + writestr("/Type /Pages\n"); + sprintf(buf, "/Count %d\n", pageNo); writestr(buf); + sprintf(buf, "/MediaBox [ 0 0 %d %d ]\n", pageWidth, pageHeight); writestr(buf); + writestr("/Kids [ "); + for (i = 1; i <= pageNo; i++) {sprintf(buf, "%d 0 R ", pageObs[i]); writestr(buf);} + writestr("]\n"); + writestr(">>\n"); + writestr("endobj\n"); + + xref = fpos; + writestr("xref\n"); + sprintf(buf, "0 %d\n", curObj + 1); writestr(buf); + /* note that \n is translated by writestr */ + sprintf(buf, "0000000000 65535 f %c", LINE_END); writestr(buf); + for (i = 1; i <= curObj; i++) { + sprintf(buf, "%.10ld 00000 n %c", locations[i], LINE_END); + writestr(buf); + } + + writestr("trailer\n"); + writestr("<<\n"); + sprintf(buf, "/Size %d\n", curObj + 1); writestr(buf); + writestr("/Root 2 0 R\n"); + writestr("/Info 1 0 R\n"); + writestr(">>\n"); + + writestr("startxref\n"); + sprintf(buf, "%ld\n", xref); writestr(buf); + writestr("%%EOF\n"); +} + + +void ShowHelp(){ + + printf("\n%s [options] [filename]\n\n", progname); + printf(" %s makes a 7-bit clean PDF file (version 1.1) from any input file.\n", progname); + printf(" It reads from standard input or a named file, and writes the PDF file\n"); + printf(" to standard output.\n"); + printf("\n There are various options as follows:\n\n"); + printf(" -h\t\tshow this message\n"); + printf(" -f<font>\tuse PostScript <font> (must be in standard 14, default: Courier)\n"); + printf(" -I\t\tuse ISOLatin1Encoding\n"); + printf(" -s<size>\tuse font at given pointsize (default %d)\n", pointSize); + printf(" -v<dist>\tuse given line spacing (default %d points)\n", vertSpace); + printf(" -l<lines>\tlines per page (default 60, determined automatically\n\t\tif unspecified)\n"); + printf(" -c<chars>\tmaximum characters per line (default 80)\n"); + printf(" -t<spaces>\tspaces per tab character (default 8)\n"); + printf(" -F\t\tignore formfeed characters (^L)\n"); + printf(" -A4\t\tuse A4 paper (default Letter)\n"); + printf(" -A3\t\tuse A3 paper (default Letter)\n"); + printf(" -x<width>\tindependent paper width in points\n"); + printf(" -y<height>\tindependent paper height in points\n"); + printf(" -2\t\tformat in 2 columns\n"); + printf(" -L\t\tlandscape mode\n"); + printf("\n Note that where one variable is implied by two options, the second option\n takes precedence for that variable. (e.g. -A4 -y500)\n"); + printf(" In landscape mode, page width and height are simply swapped over before\n formatting, no matter how or when they were defined.\n"); + printf("\n%s (c) Phil Smith, 1996\n", appname); +} + +int main(int argc, char **argv){ + int i = 1; + int tmp, landscape = 0; + char *ifilename = NULL; + + strcpy(font, "/"); + strcat(font, defaultFont); + infile = stdin; /* default */ + + while (i < argc) { + if (*argv[i] != '-') { /* input filename */ + ifilename = argv[i]; + if (!(infile = fopen(ifilename, "r"))) { + fprintf(stderr, "%s: couldn't open input file `%s'\n", progname, ifilename); + exit(0); + } + } else { + switch (*++argv[i]) { + case 'h': + ShowHelp(); + exit(0); + case 'f': + strcpy(font, "/"); + strcat(font, ++argv[i]); + break; + case 'I': + ISOEnc = 1; + break; + case 'F': + doFFs = 0; + break; + case 's': + pointSize = atoi(++argv[i]); + if (pointSize < 1) pointSize = 1; + break; + case 'v': + vertSpace = atoi(++argv[i]); + if (vertSpace < 1) vertSpace = 1; + break; + case 'l': + lines = atoi(++argv[i]); + if (lines < 1) lines = 1; + break; + case 'c': + cols = atoi(++argv[i]); + if (cols < 4) cols = 4; + break; + case '2': + columns = 2; + break; + case 't': + tab = atoi(++argv[i]); + if (tab < 1) tab = 1; + break; + case 'A': + switch (*++argv[i]) { + case '3': + pageWidth = 842; + pageHeight = 1190; + break; + case '4': + pageWidth = 595; + pageHeight = 842; + break; + default: + fprintf(stderr, "%s: ignoring unknown paper size: A%s\n", progname, argv[i]); + } + break; + case 'x': + pageWidth = atoi(++argv[i]); + if (pageWidth < 72) pageWidth = 72; + break; + case 'y': + pageHeight = atoi(++argv[i]); + if (pageHeight < 72) pageHeight = 72; + break; + case 'L': + landscape = 1; + break; + default: + fprintf(stderr, "%s: ignoring invalid switch: -%s\n", progname, argv[i]); + } + } + i++; + } + + if (landscape) { + tmp = pageHeight; + pageHeight = pageWidth; + pageWidth = tmp; + } + + if (lines == 0) lines = (pageHeight - 72) / vertSpace; + if (lines < 1) lines = 1; + /* happens to give 60 as default */ + + WriteHeader(ifilename); + WritePages(); + WriteRest(); + + return 0; +}