/* ----------------------------------------------------------------------------- Original: txt2pdf; Copyright 1998 P. G. Womack, Diss, Norfolk, UK. "BugBear" Do what you like, but don't claim you wrote it. ----------------------------------------------------------------------------- * * Copyright (c) 2006 John S. Urban, USA. (urbanjost @ comcast. net) * All rights reserved. * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * JOHN S. URBAN ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. JOHN S. URBAN DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * John S. Urban requests users of this software to return to * * urbanjost @ comcast. net * * any improvements or extensions that they make and grant John S. Urban and the * previous authors (see above ) the rights to redistribute these changes. * ----------------------------------------------------------------------------- Modified: asa2pdf; John S. Urban, Apr 30, 2006 Needed to emulate an old ASA 60 line by 132 column lineprinter quicky with output as a PDF file. Thanks, P.G.W.! o Added bar shading. o placed Adobe-recommended "binary" flag at top of PDF file. o changed sizes to simulate a 60 line by 132 column lineprinter. o changed so obeys ASA carriage control (' 01+' in column 1). o user-settable gray scale value via environmental variable IMPACT_GRAY ----------------------------------------------------------------------------- Next time in: o user-specified lines and columns and page orientation (T 0.4) o expand tabs (can use expand(1)) (T 0.1) o command line options instead of environmental variables? (T 0.2) o optional lines instead of shade; dash lines; shade spacing (T 0.5) o 1/2 line feeds? (T 0.2) o bold Courier font on overprint? (T 0.3) o underline? font color? shade color? font size? (? 3.0) But, if someone wants to get that fancy they can use fpr(1)/asa(1)/nasa(1) to handle the ASA carriage control, and something like a2ps(1)/enscript(1) and ps2pdf(1) if they have them or build them for their system. (? 0.0 -- 10.0) ----------------------------------------------------------------------------- Tested with xpdf, gv/ghostview, and acroread (PC version) PDF interpreters. ----------------------------------------------------------------------------- */ #include #include #include float page_depth; float page_width; /* Default is 72 points per inch */ float margin; float lead_size; float font_size; int object_id = 1; int page_tree_id; float gray_scale; typedef struct _PageList { struct _PageList *next; int page_id; } PageList; int num_pages = 0; PageList *pages = NULL; PageList **insert_page = &pages; void store_page(int id){ PageList *n = (PageList *)malloc(sizeof(*n)); if(n == NULL) { fprintf(stderr, "Unable to allocate array for page %d.", num_pages + 1); exit(1); } n->next = NULL; n->page_id = id; *insert_page = n; insert_page = &n->next; num_pages++; } int num_xrefs = 0; long *xrefs = NULL; void start_object(int id){ if(id >= num_xrefs) { long *new_xrefs; int delta, new_num_xrefs; delta = num_xrefs / 5; if(delta < 1000) { delta += 1000; } new_num_xrefs = num_xrefs + delta; new_xrefs = (long *)malloc(new_num_xrefs * sizeof(*new_xrefs)); if(new_xrefs == NULL) { fprintf(stderr, "Unable to allocate array for object %d.", id); exit(1); } memcpy(new_xrefs, xrefs, num_xrefs * sizeof(*xrefs)); free(xrefs); xrefs = new_xrefs; num_xrefs = new_num_xrefs; } xrefs[id] = ftell(stdout); printf("%d 0 obj\n", id); } int stream_id, stream_len_id; long stream_start; float ypos; void print_bars(){ float x1; float y1; float height; float width; int ii; fprintf(stdout,"%f g\n",gray_scale); /* gray-scale value */ /* * If you want to add color, * R G B rg where R G B are red, green, blue components * in range 0.0 to 1.0 sets fill color, "RG" sets line * color instead of fill color. * * 0.60 0.82 0.60 rg * * */ fprintf(stdout,"%d i\n",1); /* */ x1=margin-0.1*font_size; height=2.0*lead_size; y1 = page_depth - margin - height- 0.22*font_size; width=page_width-margin-margin; for ( ii=0; ii < 15; ii++ ){ fprintf(stdout,"%f %f %f %f re f\n",x1,y1,width,height); /* * x1 y1 m x2 y2 l S * xxx w # line width fprintf(stdout,"0.6 0.8 0.6 RG\n %f %f m %f %f l S\n",x1,y1,x1+width,y1); */ y1=y1-2.0*height; } fprintf(stdout,"%d G\n",0); /* */ fprintf(stdout,"%d g\n",0); /* gray-scale value */ } void print_back(){ char *buffer; char c; int i; buffer=getenv("IMPACT_TOP"); if(buffer != NULL ){ fprintf(stdout,"1.0 0.0 0.0 rg\n"); /* gray-scale value */ fprintf(stdout,"BT /F2 20.0 Tf 30 582 Td"); i=0; putchar('('); while((c = *buffer++) != '\0') { switch(c) { case '(': case ')': case '\\': putchar('\\'); } putchar(c); } fprintf(stdout,") Tj ET\n"); fprintf(stdout,"0.0 0.0 0.0 rg\n"); /* gray-scale value */ } } void start_page() { stream_id = object_id++; stream_len_id = object_id++; start_object(stream_id); printf("<< /Length %d 0 R >>\n", stream_len_id); printf("stream\n"); stream_start = ftell(stdout); print_bars(); print_back(); printf("BT\n/F0 %g Tf\n", font_size); ypos = page_depth - margin; printf("%g %g Td\n", margin, ypos); printf("%g TL\n", lead_size); } void end_page(){ long stream_len; int page_id = object_id++; store_page(page_id); printf("ET\n"); stream_len = ftell(stdout) - stream_start; printf("endstream\nendobj\n"); start_object(stream_len_id); printf("%ld\nendobj\n", stream_len); start_object(page_id); printf("<>\nendobj\n", page_tree_id, stream_id); } void do_text() { char buffer[8192]; char ASA; char c; char *s; int black; int add; start_page(); while(gets(buffer) != NULL) { black=0; add=0; if(ypos < margin && strlen(buffer) != 0 && buffer[0] != '+' ) { end_page(); start_page(); } if(strlen(buffer) == 0){ /* blank line */ printf("T*\n"); }else{ ASA=buffer[0]; switch(ASA) { case '1': /* start a new page before processing data on line */ if (ypos < page_depth - margin ){ end_page(); start_page(); } break; case '0': /* put out a blank line before processing data on line */ printf("T*\n"); ypos -= lead_size; break; case '-': /* put out two blank lines before processing data on line */ printf("T*\n"); ypos -= lead_size; ypos -= lead_size; break; case '+': /* print at same y-position as previous line */ printf("0 %f Td\n",lead_size); if (ypos < page_depth - margin ){ /* if not at top of page */ ypos += lead_size; } break; case 'R': /* RED print at same y-position as previous line */ fprintf(stdout,"1.0 0.0 0.0 rg\n"); /* red text */ black=1; printf("0 %f Td\n",lead_size); if (ypos < page_depth - margin ){ /* if not at top of page */ ypos += lead_size; } break; case 'G': /* GREEN print at same y-position as previous line */ fprintf(stdout,"0.0 1.0 0.0 rg\n"); /* green text */ black=1; printf("0 %f Td\n",lead_size); if (ypos < page_depth - margin ){ /* if not at top of page */ ypos += lead_size; } break; case 'B': /* BLUE print at same y-position as previous line */ fprintf(stdout,"0.0 0.0 1.0 rg\n"); /* blue text */ black=1; printf("0 %f Td\n",lead_size); if (ypos < page_depth - margin ){ /* if not at top of page */ ypos += lead_size; } break; case '^': /* print at same y-position as previous line like + but add 127 to character */ printf("0 %f Td\n",lead_size); if (ypos < page_depth - margin ){ /* if not at top of page */ ypos += lead_size; } add=127; break; case '>': /* Unknown */ break; case '\f': /* ctrl-L is a common form-feed character on Unix, but NOT ASA */ end_page(); start_page(); break; case 'r': fprintf(stdout,"1.0 0.0 0.0 rg\n"); /* red text */ black=1; break; case 'g': fprintf(stdout,"0.0 1.0 0.0 rg\n"); /* green text */ black=1; break; case 'b': fprintf(stdout,"0.0 0.0 1.0 rg\n"); /* blue text */ black=1; break; case ' ': break; default: fprintf(stderr,"unknown ASA carriage control character %c\n",buffer[0]); break; } s = &buffer[1]; putchar('('); while((c = *s++) != '\0') { switch(c+add) { case '(': case ')': case '\\': putchar('\\'); } putchar(c+add); } printf(")'\n"); } ypos -= lead_size; if(black != 0){ fprintf(stdout,"0.0 0.0 0.0 rg\n"); /* black text */ } } end_page(); } int main(int argc, char **argv) { int i, catalog_id, font_id; long start_xref; char *varname; varname=getenv("IMPACT_GRAY"); if (varname == (char)NULL ){ gray_scale=0.800781; /* gray-scale value */ }else if (varname[0] == '\0'){ gray_scale=0.800781; /* gray-scale value */ }else{ sscanf(varname,"%f",&gray_scale); if(gray_scale < 0 ){ gray_scale=0.800781; /* gray-scale value */ } } printf("%%PDF-1.0\n"); /* Note: If a PDF file contains binary data, as most do , it is recommended that the header line be immediately followed by a comment line containing at least four binary characters--that is, characters whose codes are 128 or greater. This will ensure proper behavior of file transfer applications that inspect data near the beginning of a file to determine whether to treat the file's contents as text or as binary. */ fprintf(stdout,"%%%c%c%c%c\n",128,129,130,131); fprintf(stdout,"%% PDF: Adobe Portable Document Format\n"); page_depth = 612.0; page_width = 792.0; /* Default is 72 points per inch */ margin = 30.0; lead_size=(page_depth-margin-margin)/60.0; font_size=lead_size; object_id = 1; page_tree_id = object_id++; do_text(); font_id = object_id++; start_object(font_id); printf("<>\nendobj\n"); start_object(page_tree_id); printf("<page_id); ptr = ptr->next; } printf("]\n"); } printf("/Resources<> >>\n"); printf(">>/MediaBox [ 0 0 %g %g ]\n", page_width, page_depth); printf(">>\nendobj\n"); catalog_id = object_id++; start_object(catalog_id); printf("<>\nendobj\n", page_tree_id); start_xref = ftell(stdout); printf("xref\n"); printf("0 %d\n", object_id); printf("0000000000 65535 f \n"); for(i = 1; i < object_id; i++){ printf("%010ld 00000 n \n", xrefs[i]); } printf("trailer\n<<\n/Size %d\n/Root %d 0 R\n>>\n", object_id, catalog_id); printf("startxref\n%ld\n%%%%EOF\n", start_xref); exit(0); return 0; }