home *** CD-ROM | disk | FTP | other *** search
- /* ------------------------------------------------------ */
- /* PSTEXT */
- /* PostScript-Universaltreiber für ASCII-Text */
- /* (c) 1990 David Geffen & TOOLBOX */
- /* ------------------------------------------------------ */
-
- #include <stdio.h>
- #include <string.h>
-
- #define FALSE 0
- #define TRUE !FALSE
-
- #define TOP_MARGIN 72 /* Default-Wert oberer Rand: 1" */
- #define LEFT_MARGIN 72 /* Default-Wert linker Rand: 1" */
- #define END_Y 72 /* Default-Wert unterer Rand: 1" */
-
- #define A4_Y 841 /* 29.7cm = 841Punkte */
- #define A4_X 595 /* 21.0cm = 595Punkte */
- #define A4_QUER (float)(0.7070707)
-
- #define MAX_X (A4_X-startX)
- #define MAX_Y (A4_Y-startY)
- #define MAX_LINES ((startY-endY+points)/(points+spacing))
- /* Zeilen pro Spalte */
- #define MAX_COLUMNS 200 /* Spalten pro Seite */
- #define MAX_SPACING 800 /* Durchschuß */
- #define MAX_CHARS 8192 /* maximale Absatzlänge
- in Zeichen */
- #define MAX_FILENAME 63 /* Dateinamenlänge */
- #define MAX_FILES 10 /* Eingabe-Dateien */
- #define MAX_FONTNAME 80 /* Fontnamenlänge */
-
- #define COLS_ON_LINE (((MAX_X/LandScape) \
- / default_cols) / points)
- /* Zeichen pro Spalte */
-
- void i2a (int, char *, int, int);
- void usage (char *);
- void error (char *);
-
- char breaks[] = { " +-\t)*/^%]}|" };
- /* Mögliche 'Break'-Zeichen
- für Wordwrap */
- char specials[150]; /* ASCII-Codes, die in Oktal
- ausgegeben werden müssen */
- char files[MAX_FILES][MAX_FILENAME];
- /* Eingabe-Dateien */
- int next_file; /* Eingabe-Datei-Zähler */
- unsigned int default_lines; /* Zeilen pro Spalte */
- unsigned int default_cols; /* Spalten pro Seite */
- unsigned int ln_count; /* Aktuelle Zeilennummer */
- unsigned int wrap; /* Index für Wordwrap-Test */
- unsigned int blanks; /* Anzahl Leerzeichen */
- unsigned int colwidth; /* Spaltenbreite */
-
- /* Variablen, die verschiedene Optionen beschreiben.
- Diese Variablen werden in der Funktion set_defaults()
- bzw. getopts() gesetzt.
- */
- char prolog_filename[MAX_FILENAME]; /* PS-Präambel-Datei */
- char font[MAX_FONTNAME]; /* Fontname */
- FILE *fp; /* Input-File Pointer */
- unsigned points; /* Schriftgröße */
- signed lines; /* Zeilen pro Spalte */
- unsigned cols; /* Spalten pro Seite */
- signed startX, startY, endY; /* Anfangs-Positionen */
- unsigned spacing; /* Durchschuß */
- float LandScape; /* Hoch- oder Querformat */
- int numbering; /* Zeilennumerierung */
- char text_on_page; /* Flag für nextpage */
- unsigned ln_interval; /* Zeilennumerierungs-
- Intervall */
- signed cols_on_line; /* Wordwrap-Spalte */
-
- /* ---- Unterprogramme -------------------------------- */
-
- /* get_blanks() zählt die Leerzeichen
- am Anfang der Zeile
- */
- get_blanks( char *s )
- {
- int blanks;
-
- blanks = 0;
- while( *s++ == ' ' )
- blanks++;
- return( blanks );
- }
-
- /* put_blanks() gibt 'blanks' Leerzeichen aus
- */
- void put_blanks( blanks )
- {
- while( blanks-- )
- fputc( ' ', stdout );
- }
-
- /* ispage() prüft, ob die Spalte voll ist
- und fügt in diesem Fall ein 'nextcol' bzw. 'nextpage'
- ein.
- */
- void ispage()
- {
- /* Sind wir am Seitenende? "Ja" bedeutet 'nextpage'
- oder 'nextcol'
- */
- if (!(--lines))
- {
- lines = default_lines;
- if (!(--cols))
- {
- if (text_on_page)
- fputs( "nextpage\n", stdout );
- text_on_page = FALSE;
- cols = default_cols;
- }
- else
- fputs( "nextcol\n", stdout );
- }
- }
-
- void process_char( unsigned char c )
- {
- char s[5]; /* Platz für ein Oktal-Zeichen (\xxx) */
-
- if ( strchr( specials, c ) )
- {
- fputc( '\\', stdout );
- i2a( c, s, 3, 8 );
- fputs( s, stdout );
- }
- else
- fputc( c, stdout );
- }
-
- /* Diese Funktion setzt die globalen Defaultwerte
- */
- void set_defaults()
- {
- LandScape = 1.0; /* Default ist Portrait */
- fp = stdin; /* ermöglicht 'Piping' */
- strcpy( font, "Courier" ); /* unproportionale Schrift */
- points = 12; /* Standardgröße */
- default_cols = 1; /* einspaltige Ausgabe als Default*/
- cols = default_cols; /* setze Default */
- startX = LEFT_MARGIN; /* links */
- endY = END_Y; /* unten */
- spacing = 1; /* 1 Punkt Durchschuß */
- default_lines = MAX_LINES;
- strcpy( prolog_filename, "pstext.ini" );
- /* PS-Präambeldatei */
- colwidth = A4_X;
- ln_count = 1;
- ln_interval = 1;
- numbering = FALSE; /* Zeilennumerierung */
-
- /* Die folgenden Variablen sind abhängig
- von anderen Variablen und werden nur
- als 'noch ohne Wert' gekennzeichnet
- */
- cols_on_line = -1;
- lines = -1;
- startY = -1;
- }
-
- /* Eingabe-Parameter analysieren
- */
- void getopts( int argc, char *argv[] )
- {
- int i; /* Index-Integer, zählt die Optionen */
- char s[40]; /* String für Fehlermeldungen */
-
- for (i = 1; i < argc; i++)
- {
- /* Erlaubte 'Schalter'-Symbole sind '-' und '/'.
- Falls keines davon zu finden, wird der Parameter
- als Dateiname interpretiert
- */
- if (*argv[i] != '/' && *argv[i] != '-')
- {
- if (next_file < MAX_FILES)
- strncpy( files[next_file++], argv[i],\
- MAX_FILENAME );
- }
- else
- if (strlen( argv[i] ) < 3 )
- {
- usage( argv[0] );
- error( "" );
- }
- else
- if (strlen( argv[i] ) > 2 )
- {
- switch ( tolower( *(argv[i]+1) ) )
- {
- case 'c':
- cols = atoi( argv[i]+2 );
- if ( (cols < 1) || (cols > MAX_COLUMNS) )
- {
- sprintf( s, "Kann nicht %d "\
- "Spalten drucken!", cols );
- error( s );
- }
- default_cols = cols;
- break;
- case 'd':
- spacing = atoi( argv[i]+2 );
- if ( (spacing < 0)
- || (spacing > MAX_SPACING) )
- {
- sprintf( s, "Kann keinen Durchschuß "\
- "von %d setzen!", spacing );
- error( s );
- }
- break;
- case 'f':
- /*
- Schriftart auswählen:
- Der Anwender will einen eigenen Font-
- namen benutzen, wenn er mehr als ein
- Zeichen hinter '-f' eingegeben hat
- */
- if (strlen( argv[i] + 2 ) > 1)
- strncpy( font, argv[i]+2, \
- MAX_FONTNAME );
- else
- switch( tolower( *(argv[i]+2) ) )
- {
- case 'a':
- strcpy( font, "AvantGarde" );
- break;
- case 'b':
- strcpy( font, "Bookman" );
- break;
- case 'c':
- strcpy( font, "Courier" );
- break;
- case 'h':
- strcpy( font, "Helvetica" );
- break;
- case 'p':
- strcpy( font, "Palatino" );
- break;
- case 's':
- strcpy( font, "Symbol" );
- break;
- case 't':
- strcpy( font, "Times-Roman" );
- break;
- default:
- strncpy( font, argv[i]+2, \
- MAX_FONTNAME );
- break;
- }
- break;
- case 'l':
- lines = atoi( argv[i]+2 );
- if (lines < 1)
- {
- sprintf( s, "Kann nicht %d Zeilen per"\
- " Seite drucken!", lines );
- error( s );
- }
- default_lines = lines;
- break;
- case 'n':
- ln_interval = atoi( argv[i]+2 );
- if (ln_interval < 0)
- {
- sprintf( s, "Kann nicht mit Intervall"\
- " %d numerieren!", ln_interval );
- error( s );
- }
- else
- if (ln_interval == 0) ln_interval = 1;
- numbering = TRUE;
- break;
- case 'o':
- switch ( tolower( *(argv[i]+2) ) )
- {
- case 'l':
- LandScape = A4_QUER;
- colwidth = A4_Y; break;
- case 'p':
- LandScape = 1.0;
- colwidth = A4_X; break;
- default:
- sprintf( s, "Orientierung ist "\
- "entweder 'l' oder 'p'!" );
- error( s );
- }
- break;
- case 'p':
- points = atoi( argv[i]+2 );
- if (points < 4)
- {
- sprintf( s, "Kann nicht %d "\
- "Punkt drucken!", points );
- error( s );
- }
- break;
- case 'w':
- cols_on_line = atoi( argv[i]+2 );
- if (cols_on_line < 1)
- {
- sprintf( s, "Kann Zeile nicht in der "\
- "%d. Spalte umbrechen!", cols_on_line );
- error( s );
- }
- break;
- case 'x':
- startX = atoi( argv[i]+2 );
- if ( (startX < 0) || (startX > A4_X) )
- {
- sprintf( s, "X-Anfangsposition (%d) "\
- "ist illegal!", startX );
- error( s );
- }
- break;
- case 'y':
- startY = atoi( argv[i]+2 );
- if ( (startY < 0) || (startY > A4_Y) )
- {
- sprintf( s, "Y-Anfangsposition (%d) "\
- "ist illegal!", startY );
- error( s );
- }
- break;
- default:
- sprintf( s, "Option '%c' ist nicht "\
- "vorhanden!", \
- tolower( *(argv[i]+1) ) );
- error( s );
- break;
- }
- }
- }
- /* 'colwidth', 'cols_on_line', 'startY'
- und 'lines', die von anderen Variablen
- abhängig sind, müssen neu berechnet werden.
- */
- colwidth = (colwidth - startX) / cols;
-
- if (cols_on_line == -1)
- cols_on_line = COLS_ON_LINE;
-
- if (startY == -1)
- startY = ((A4_Y-TOP_MARGIN)*LandScape) - points;
-
- if (lines == -1)
- {
- default_lines = MAX_LINES;
- lines = default_lines;
- }
- }
-
- /* Funktion header() beschreibt die PostScript-
- Funktionen, die später aufgerufen werden
- */
- void header()
- {
- char s[MAX_CHARS];
- char buf[MAX_CHARS];
- FILE *fp;
- int i;
- /*
- Hier wird die PostScript-Präambeldatei gelesen.
- Wenn die Datei nicht vorhanden ist, werden nur
- die Default-Daten ausgegeben.
- */
-
- fp = fopen( prolog_filename, "rt" );
- if ( fp != NULL )
- {
- while( fgets( s, MAX_CHARS, fp ) != NULL )
- {
- /* Aufpassen! 'i' wird innerhalb der Schleife
- inkrementiert. Obwohl in jedem 'case'-Befehl
- enthalten, wird das nur einmal vom Compiler
- expandiert, wenn der Optimierer
- eingeschaltet ist.
- */
- for (i = 0; i < strlen( s ); i++)
- {
- if ( (s[i] == '.') && (s[i+2] == '.') \
- && ((i+2) < strlen(s) ))
- {
- switch (tolower(s[i+1]))
- {
- case 'd':
- sprintf( buf, "%d", spacing );
- fputs( buf, stdout );
- i += 2;
- break;
- case 'f':
- fputs( font, stdout );
- i += 2;
- break;
- case 'p':
- sprintf( buf, "%d", points );
- fputs( buf, stdout );
- i += 2;
- break;
- case 't':
- if (LandScape == A4_QUER)
- {
- sprintf( buf, "%d 0 " \
- "translate 90 rotate", A4_X);
- fputs( buf, stdout );
- }
- i += 2;
- break;
- case 'w':
- sprintf( buf, "%d", colwidth );
- fputs( buf, stdout );
- i += 2;
- break;
- case 'x':
- sprintf( buf, "%d", startX );
- fputs( buf, stdout );
- i += 2;
- break;
- case 'y':
- sprintf( buf, "%d", startY );
- fputs( buf, stdout );
- i += 2;
- break;
- default:
- fputc( s[i], stdout );
- break;
- }
- }
- else
- {
- fputc( s[i], stdout );
- }
- }
- }
- fclose( fp );
- }
- else
- {
- fputs( "%!PS-Adobe-2.0\n", stdout );
- fputs( "%%Creator: PSTEXT-Treiber\n", stdout );
- fputs( "% (C) 1990, " \
- "David Geffen & TOOLBOX\n", stdout );
- fputs( "%%Title: PSTEXT Header File\n", stdout );
- fputs( "%%EndComments\n", stdout );
-
- fputs( "% Umlaut Functions\n", stdout );
- fputs( "/reencsmalldict 12 dict def\n", stdout );
- fputs( "/ReEncodeSmall\n", stdout );
- fputs( "{\n", stdout );
- fputs( " reencsmalldict begin\n", stdout );
- fputs( " /newcodesandnames exch def\n", stdout );
- fputs( " /newfontname exch def\n", stdout );
- fputs( " /basefontname exch def\n", stdout );
- fputs( " /basefontdict basefontname "\
- "findfont def\n", stdout );
- fputs( " /newfont basefontdict maxlength "\
- "dict def\n", stdout );
- fputs( " basefontdict\n", stdout );
- fputs( " {\n", stdout );
- fputs( " exch dup /FID ne\n", stdout );
- fputs( " {\n", stdout );
- fputs( " dup /Encoding eq\n", stdout );
- fputs( " {\n", stdout );
- fputs( " exch dup length array "\
- "copy\n", stdout );
- fputs( " newfont 3 1 roll put\n",\
- stdout );
- fputs( " }\n", stdout );
- fputs( " {\n", stdout );
- fputs( " exch newfont 3 1 roll "\
- "put\n", stdout );
- fputs( " }\n", stdout );
- fputs( " ifelse\n", stdout );
- fputs( " }\n", stdout );
- fputs( " {\n", stdout );
- fputs( " pop pop\n", stdout );
- fputs( " }\n", stdout );
- fputs( " ifelse\n", stdout );
- fputs( " }\n", stdout );
- fputs( " forall\n", stdout );
-
- fputs( " newfont /FontName newfontname "\
- "put\n", stdout );
- fputs( " newcodesandnames aload pop\n", \
- stdout );
-
- fputs( " newcodesandnames length 2 idiv\n", \
- stdout );
- fputs( " {\n", stdout );
- fputs( " newfont /Encoding get 3 1 roll"\
- " put\n", stdout );
- fputs( " }\n", stdout );
- fputs( " repeat\n", stdout );
-
- fputs( " newfontname newfont definefont pop\n",\
- stdout );
- fputs( " end\n", stdout );
- fputs( "} \n", stdout );
- fputs( "def\n", stdout );
-
- fputs( "/umlauts [\n", stdout );
- fputs( "8#204 /adieresis\n", stdout );
- fputs( "8#224 /odieresis\n", stdout );
- fputs( "8#201 /udieresis\n", stdout );
- fputs( "8#216 /Adieresis\n", stdout );
- fputs( "8#231 /Odieresis\n", stdout );
- fputs( "8#232 /Udieresis\n", stdout );
- fputs( "8#341 /germandbls\n", stdout );
- fputs( "] def\n", stdout );
-
- sprintf( s, "/%s /%s-Umlaut umlauts\n", font, font);
- fputs( s, stdout );
- fputs( "ReEncodeSmall\n", stdout );
- fputs( "% End of Preparation for Umlaut "\
- "Functions\n", stdout );
-
- fputs( "% Global Variables\n", stdout );
- fputs( "/", stdout );
- fputs( font, stdout );
- fputs( "-Umlaut findfont\n", stdout );
- sprintf( s, "%d", points );
- fputs( s, stdout );
- fputs( " scalefont setfont\n", stdout );
-
- sprintf( s, "/X %d def\n", startX );
- fputs( s, stdout );
- sprintf( s, "/Y %d def\n", startY );
- fputs( s, stdout );
-
- fputs( "/lineheight {", stdout );
- sprintf( s, "%d %d", points, spacing );
- fputs( s, stdout );
- fputs( " add} def\n", stdout );
-
- fputs( "/colwidth {", stdout );
- sprintf( s, "%d} def \n", colwidth );
- fputs( s, stdout );
-
- fputs( "% shline shows a line and updates Y\n", \
- stdout );
- fputs( "/shline\n", stdout );
- fputs( "{\n", stdout );
- fputs( " show\n", stdout );
- fputs( " Y lineheight sub\n", stdout );
- fputs( " /Y exch def\n", stdout );
- fputs( " X Y moveto\n", stdout );
- fputs( "} def\n", stdout );
-
- fputs( "% show page and update X and Y\n", stdout );
- fputs( "/nextpage \n", stdout );
- fputs( "{ \n", stdout );
- fputs( " showpage \n", stdout );
- sprintf( s, " /X %d def\n", startX );
- fputs( s, stdout );
- sprintf( s, " /Y %d def\n", startY );
- fputs( s, stdout );
- if (LandScape == A4_QUER)
- {
- sprintf( s, " %u 0 translate\n"\
- " 90 rotate\n", A4_X );
- fputs( s, stdout );
- }
- fputs( " X Y moveto \n", stdout );
- fputs( "} def\n", stdout );
-
- fputs( "% nextcol prepares the next column\n",\
- stdout );
- fputs( "/nextcol\n", stdout );
- fputs( "{\n", stdout );
- fputs( " X colwidth add\n", stdout );
- fputs( " /X exch def\n", stdout );
- sprintf( s, " /Y %d def\n", startY );
- fputs( s, stdout );
- fputs( " X Y moveto\n", stdout );
- fputs( "} def\n", stdout );
-
- if (LandScape == A4_QUER)
- {
- sprintf( s, "\n%d 0 translate\n", A4_X );
- fputs( s, stdout );
- fputs( "90 rotate\n", stdout );
- }
- fputs( "X Y moveto\n", stdout );
- }
- }
-
- /* i2a() übersetzt 'val' in einen 'places'-stelligen
- 'radix'-Wert und schreibt ihn in 's'.
- Es wird also immer mit 'places' Zeichen geschrieben,
- mit entsprechend vielen führenden Nullen.
- */
-
- void i2a ( int val, char *s, int places, int radix )
- {
- s[places--] = 0;
- do
- {
- s[places] = val % radix + '0';
- val /= radix;
- }
- while ( places-- );
- }
-
- /* 'usage'-Funktion zeigt die möglichen Optionen
- */
- void usage( char *s )
- {
- fprintf( stdout, "Aufruf: \t%s [Optionen]\n", s );
- fprintf( stdout, "\tDie Optionen sind:\n" );
- fprintf( stdout, "\t[Filename...]\n" );
- fprintf( stdout, "\t[-cColumns]\n" );
- fprintf( stdout, "\t[-dDurchschuß]\n" );
- fprintf( stdout, "\t[-fFont]\n" );
- fprintf( stdout, "\t[-lZeilen]\n" );
- fprintf( stdout, "\t[-nZeilennumerierung]\n" );
- fprintf( stdout, "\t[-oOrientierung]\n" );
- fprintf( stdout, "\t[-pSchriftgröße]\n" );
- fprintf( stdout, "\t[-wWordwrap-Spalte]\n" );
- fprintf( stdout, "\t[-xAnfangspunkt]\n" );
- fprintf( stdout, "\t[-yAnfangspunkt]\n" );
- }
-
- /* error() gibt eine Fehlermeldung aus und
- beendet das Programm.
- */
- void error( char *s )
- {
- fprintf( stderr, s );
- exit( 1 );
- }
-
- /* --- HAUPTPROGRAMM ------------------------------------ */
- int main( argc, argv )
- int argc;
- char *argv[];
- {
- char filename[MAX_FILENAME];
- char s[MAX_CHARS + 10];
- char *sp;
- unsigned int end_flag, back;
- int i, splen;
-
- /* Defaultoptionen setzen und
- Anwender-Optionen analysieren
- */
- if ( argc == 1 ) {
- usage( argv[0] );
- error( "" );
- exit(1);
- }
-
- set_defaults();
- getopts( argc, argv );
-
- /* array 'specials' enthält die Sonderzeichen, die nur
- in Oktal ausgegeben werden dürfen
- */
- for (i = 0; i < 128; i++) specials[i] = i + 128;
- strcat( specials, "\\/()<>[]{}%" );
-
- /* Vorbereitung des PostScript-Headers
- */
- header();
-
- /* Jede Zeile wird in Klammern geschrieben,
- mit einem 'shline'-Funktionsaufruf am Ende:
- z.B. "(Text) shline"
- */
-
- if (!next_file)
- next_file++;
-
- while( next_file-- )
- {
- ln_count = 1;
- lines = default_lines;
- cols = default_cols;
-
- if (!(*files[next_file]))
- fp = stdin;
- else
- if ((fp = fopen(files[next_file], "rt")) == NULL)
- {
- error("Datei konnte nicht geöffnet werden!");
- }
-
- while( fgets( s, MAX_CHARS, fp ) != NULL )
- {
- sp = s;
- fputs( "(", stdout );
- /*
- Flag für nextpage setzen
- */
- text_on_page = TRUE;
-
- if (numbering)
- {
- if (!((ln_count) % ln_interval))
- {
- fprintf( stdout, "%-5d ", ln_count );
- }
- else
- /* 6 Leerzeichen */
- fprintf( stdout, " " );
- }
-
- /* Weg mit dem '\n', sofern vorhanden.
- Beim Dateiende gibt es keins.
- */
- splen = strlen( sp );
- if (strchr( sp, '\n' ))
- back = 1;
- else
- back = 0;
- strcpy( &sp[strlen(sp) - back], ") shline\n" );
-
- blanks = get_blanks( sp );
- blanks %= cols_on_line;
- if (numbering) blanks += 6;
-
- /* String ausgeben und gleichzeitig prüfen, ob
- Wordwrap nötig ist.
- Alles zwischen '(' und ')' ausdrucken.
- Nach der Schleife wird ') shline'
- ausgegeben.
- */
-
- wrap = 0;
- i = 0;
- while (i < (int)(splen - back ) )
- {
- process_char( *sp );
- wrap++; i++;
- if ((wrap > cols_on_line)
- && strchr( breaks, *sp ))
- {
- fputs( ") shline\n", stdout );
- text_on_page = TRUE;
- ispage();
- wrap = 0;
- if (strlen(sp) > strlen(") shline\n"))
- {
- fputs( "(", stdout );
- /*
- Gleiche Anzahl von Blanks am
- Zeilenanfang nicht vergessen
- */
- put_blanks( blanks );
- }
- }
- sp++;
- }
-
- /* den Rest ausgeben
- */
- fputs( sp, stdout );
- ispage();
- /*
- Egal, ob es Wordwrap gab oder nicht -
- dies zählt nur als eine Zeile
- */
- ln_count++;
- }
-
- if (text_on_page)
- fputs( "nextpage\n", stdout );
- fclose( fp );
- }
- return(0);
- }
- /* --------------- Ende von PSTEXT.C ---------------- */
-