Options for paper output?

Q&A's, tips, howto's
Post Reply
HPW
Posts: 1377
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Options for paper output?

Post by HPW »

Thinking of professional output on paper let me search for this in newlisp.
But it seems not much native options.

So what are the options:

Using TCL-Extensions?
Generating HTML and lauch a browser?
Generating PDF and use Acro Reader?
Other?

Any thoughts or ideas?
Hans-Peter

Lutz
Posts: 5282
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

>>>>>>
Using TCL-Extensions?
Generating HTML and lauch a browser?
Generating PDF and use Acro Reader?
>>>>>>

all of the above: HTML and launching a browser would be the easiest. Don't know about the TCL-extensions. Best quality for printing of course PDF. Post Script the language behind PDF is fun to learn.

If you have a lot of tabular data you also might think eporting CVS format, which you could use in Excel/Access etc.

Or you could write an Excel sheet or Access database directly using the ODBC module shipped in the source distribution. Steve, alias adamss3 on this board, seems to have done some work with this and helped to develop / debug it.

Lutz

HPW
Posts: 1377
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Post by HPW »

>HTML and launching a browser would be the easiest.

That have I done with my alisp-code and it only has to be ported.

>Don't know about the TCL-extensions.

I am investigating on this, but it seems that multiplatform-support for it is tricky.

>Best quality for printing of course PDF. Post Script the language behind PDF is fun to learn.

Would it be possible to have support for this in newlisp? Something like CL-PDF and CL-Typesetting. Sample here:

http://www.fractalconcept.com/ex.pdf

The work of Mark Battyani is fantastic, but only for the heavy CommonLisp's.
Is something simpler possible?
Hans-Peter

HPW
Posts: 1377
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Post by HPW »

Hans-Peter

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

As newlisp has a light scripting feel why not use it as the start of
a tool chain that generates pdfs. Searching www.freshmeat.net projects
for pdf (as I'm sure you've done) reveals quite a list of tool chain candidates.
Plug for tool chains: Overall I feel that the tool chain approach is
underutilized - too often it seems to be felt that if you can't do it by static or dynamic linking from your own app that using a tool chain is an inferior last resort.

A set of recipes for using newlisp with various tool chains may be a useful resource.

Nigel

HPW
Posts: 1377
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Post by HPW »

>Searching www.freshmeat.net projects for pdf (as I'm sure you've done) reveals quite a list of tool chain candidates.

No, I get the hint from powerbasic-forum (another programming tool out of my toolbox, also fast and small code) where lots of user seems to use it successfully.

And I want a full integration into one process, so that the enduser cannot see any interuption of his current session.

Or do I miss your point?
Hans-Peter

eddier
Posts: 289
Joined: Mon Oct 07, 2002 2:48 pm
Location: Blue Mountain College, MS US

Post by eddier »

You might try generating LaTeX documentation from within newlisp and then calling latex from the (! ) shell command to compile it and dvips (dvi to postscript) from the shell command to print the resulting file. Or if you want the pdf file -- call dvipdf (dvi to pdf) instead of dvips.

I've generated nice output this way in the past.

Eddie

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

Hi
re Or do I miss your point?
I was suggesting that in the background you exec a tool chain to produce the output rather than interrupt the current process. Essentially after ypu click print on MS-Word for example you don't really care whether printing is directly integrated or runs a a separate process.

I'll try to come up with a specific example (next week)
Nigel

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

Looking at freasmeat.net I found the GPL'ed ipdf.exe that is a binary for converting plain text to simple pdf. See http://hoopajoo.net/ipdf_win32.html for the precompiled binary and look at http://hoopajoo.net/project_list.html IPDF section for source to compile on linux.
Trying
C:\newlisp>ipdf -m 'A4-p' -o readme2.pdf readme.txt
gives a reasonable, simple, pdf of the newlisp readme.

In newlisp, after putting the required plain text into temp001.txt (say) running:
> (exec {ipdf -m "a4-p" -o temp001.pdf temp001.txt})
()
>
creates the temp001.pdf.
Nigel

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

below is a context that outputs a pdf directly - it could be used to add extra funionality - create pdf from text file, callable functions that output pdf etc.
I don't have anywhere to put it up on a site. It's just a straight translation from the c - more or less.

; from txt2pdf.c that had header below
; from http://www.planetpdf.com/mainpage.asp?WebPageID=156
; titled "How to convert text to PDF"
;/*
; Copyright 1998
; P. G. Womack, Diss, Norfolk, UK.
; "BugBear"
; Do what you like, but don't claim you wrote it.
;*/
; converted by Nigel
; usage:
; access using (TXT2PDF:txt2psf function_to_provide_text filenamestring)
; file will be opened named from filenamestring (put your own .pdf extension on)
; then function_to_provide_text will be repeatedly called - each call should produce
; either
; a string that will be treated as text with a newline implicitly at the end
; or character \012 that will be treated as formfeed - that is start a new page
; or nil that will signal end of data - pdf will then be finalised and closed, no more calls will be made
; returns true if successful (file created and closed) false if file open fails.
; eg (TXT2PDF:txt2pdf (lambda() (pop '("line1" "line2" "\012" "line1 on newpage" "2nd line"))) "demo.pdf")
;

(context 'TXT2PDF)

(setq page_width 594.0 )
(setq page_depth 828.0 )
(setq margin 30.0 )
(setq font_size 10.0 )
(setq lead_size 10.0 )
(setq object_id 1 )

(setq num_pages 0)
(setq pages '())

(define (store_page id) (begin (push id pages -1) (inc 'num_pages)))

(setq num_xrefs 0)
(setq xrefs '()) ; holdsposition of xrefs as assoc list

(define (start_object id) (begin (push (list id (seek pdfout)) xrefs)
(write-buffer pdfout (format "%d 0 obj\n" id))))
(setq stream_id 0)
(setq stream_len_id 0)
(setq ypos 0.0)

(define (start_page) (begin (setq stream_id object_id)
(inc 'object_id)
(setq stream_len_id object_id)
(inc 'object_id)
(start_object stream_id)
(write-buffer pdfout (format "<< /Length %d 0 R >>\n" stream_len_id))
(write-buffer pdfout "stream\n")
(setq stream_start (seek pdfout))
(write-buffer pdfout (format "BT\n/F0 %g Tf\n" font_size))
(setq ypos (sub page_depth margin))
(write-buffer pdfout (format "%g %g Td\n" margin ypos))
(write-buffer pdfout (format "%g TL\n" lead_size))))

(define (end_page) (begin (setq page_id object_id)
(inc 'object_id)
(store_page page_id)
(write-buffer pdfout "ET\n")
(setq stream_len (- (seek pdfout) stream_start))
(write-buffer pdfout "endstream\nendobj\n")
(start_object stream_len_id)
(write-buffer pdfout (format "%d\nendobj\n" stream_len)) ; "%ld\nendobj\n" newlisp int is 32 bit
(start_object page_id)
(write-buffer pdfout (format "<</Type/Page/Parent %d 0 R/Contents %d 0 R>>\nendobj\n" page_tree_id stream_id))))

(define (do_text pdfgets)
(begin
(start_page)
(while (setq buffer (pdfgets))
(begin
(if (< ypos margin)
(begin
(end_page)
(start_page)))
(if (= (length buffer) 0)
(write-buffer pdfout "T*\n")
(if (= (first buffer) "\012"); formfeed code
(begin
(end_page)
(start_page))
(begin
(write-buffer pdfout "(")
(setq s -1)
(if (!= (nth -1 buffer) "\000") (setq buffer (append buffer "\000"))) ; protect from endless last char
(while (!= (setq c (nth (inc 's) buffer)) "")
(begin
(case c
("(" (write-buffer pdfout "\\"))
(")" (write-buffer pdfout "\\"))
("\\" (write-buffer pdfout "\\")))
(write-buffer pdfout c)))
(write-buffer pdfout ")'\n"))))
(setq ypos (sub ypos lead_size))))
(end_page)))

(define (txt2pdf pdfgets pdffilename) (begin
(set 'pdfout (open pdffilename "write")) ; mod to have txt2pdf to return nil if open fails
(if (= pdfout nil) nil (begin ; do else if file opened ok
(write-buffer pdfout "%%PDF-1.0\n")
(setq page_tree_id object_id)
(inc 'object_id)
(do_text pdfgets)
(setq font_id object_id)
(inc 'object_id)
(start_object font_id)
(write-buffer pdfout "<</Type/Font/Subtype/Type1/BaseFont/Courier/Encoding/WinAnsiEncoding>>\nendobj\n")
(start_object page_tree_id)
(write-buffer pdfout (format "<</Type /Pages /Count %d\n" num_pages))
(write-buffer pdfout "/Kids[\n")
(dolist (ppid pages) (write-buffer pdfout (format "%d 0 R\n" ppid)))
(write-buffer pdfout "]\n")
(write-buffer pdfout (format "/Resources<</ProcSet[/PDF/Text]/Font<</F0 %d 0 R>> >>\n" font_id))
(write-buffer pdfout (format "/MediaBox [ 0 0 %g %g ]\n" page_width page_depth))
(write-buffer pdfout ">>\nendobj\n")
(setq catalog_id object_id)
(inc 'object_id)
(start_object catalog_id)
(write-buffer pdfout (format "<</Type/Catalog/Pages %d 0 R>>\nendobj\n" page_tree_id))
(setq start_xref (seek pdfout))
(write-buffer pdfout "xref\n")
(write-buffer pdfout (format "0 %d\n" object_id))
(write-buffer pdfout "0000000000 65535 f \n")
(dotimes (i (- object_id 1)) (write-buffer pdfout (format "%010d 00000 n \n" (lookup (+ i 1) xrefs)))) ;"%010ld 00000 n \n"
(write-buffer pdfout (format "trailer\n<<\n/Size %d\n/Root %d 0 R\n>>\n" object_id catalog_id))
(write-buffer pdfout (format "startxref\n%d\n%%%%EOF\n" start_xref));"startxref\n%ld\n%%%%EOF\n"
(close pdfout)))))

(context 'MAIN)

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

Sorry a typo in usage it should of course be
access using (TXT2PDF:txt2pdf function_to_provide_text filenamestring)
see the demo line lower
Nigel

Lutz
Posts: 5282
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Thanks, wonderful! I will put it on the news website next week in the Tips&Tricks section, if this is Ok with you.

Lutz

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

Yes that's fine.
A couple of observations from the C-to-newLISP conversion process:

The acceptable format specifier in C %ld (long integer) isn't in newLISP - as all newLISP ints are long and %d handles that - so extra editing of formats was needed. Could newLISP accept ld as a specifier? (that is just treat it as %d)

The editor GVim ftp://ftp.vim.org/pub/vim/pc/gvim62.exe at http://www.vim.org/index.php is a handy text editor that is able to flash matching brackets (menu item Edit|Global Settings|Toggle Showmatch).
I've replaced my previous editor with it for lisp.

Nigel

Lutz
Posts: 5282
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

thanks, i will look into it

Lutz

Sammo
Posts: 180
Joined: Sat Dec 06, 2003 6:11 pm
Location: Loveland, Colorado USA

Post by Sammo »

Code: Select all

;; copy-text-to-pdf
;; simple wrapper for Nigel's 'txt2pdf' code
;;
(define (copy-text-to-pdf text-filename pdf-filename)
    (let
        ( (infile (open text-filename "read")) )
        (TXT2PDF:txt2pdf (lambda () (read-line infile)) pdf-filename)
        (close infile) ))

HPW
Posts: 1377
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Post by HPW »

Thanks Nigel for this small and nice code!
Quite usefull when simple text-generation is needed.

Sam, thanks for the file-wrapper.
Hans-Peter

Lutz
Posts: 5282
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

I also have been busy putting somethig around Nigel's code, here are some rotuines, which also do page numbers and footer text:

http://newlisp.org/download/development/txt2pdf.lsp

scroll th the end to see the interface routines. Perhaps I should rewrite line aquisition to 'read-line' style like Sam is doing, for less memory consumption. The whole thing goes on the news site one of these days.

Also a note to Sam's/HPW's 'loops' benchmark exchange: that is typical for benchmarks: you change the hardware / SW environment and everything comes out different. I think in this case it was Pentium versus Celeron, because on my Celeron things go in the same direction as on Sam's laptop, on my machine even more dramatic: 1.24 for 'for' and 0.80 for 'dotimes'.

Anyway I was happy to see that newLISP generally comes out of this strong and will continue to add more translations from Doug Bagley's test suite as I find time.

Lutz

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

Thanks for expanding the pdf stuff.

A point on the newLISP version vs C version : note that newLISP uses (seek to keep track of the internal position within the pdf file so internal cross references can be made while the original code uses ftell e.g.

(setq stream_len (- (seek pdfout) stream_start))
vs.
stream_len = ftell(stdout) - stream_start;

Ftell will work on stdout and thus the original program could use commandline piping, however seek won't (from my tests on windows
> (seek (device))
0
> (print "hello")
hello"hello"
> (seek (device))
0
>
) so that is why I forced writing to a file. If someone could make the output method more flexible, or perhaps open stdout in a way that seek returns a position, or implements ftell (Lutz?), then txt2pdf could be more flexible
(you may remember from posts above that I like toolchains).

Nigel

HPW
Posts: 1377
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Post by HPW »

Lutz,

some observations with your code:

; (TXT2PDF:file "this is a test page 1\n\012\nThis on page 2\n" "demo.pdf")

should be

; (TXT2PDF:text "this is a test page 1\n\012\nThis on page 2\n" "demo.pdf")

But when I call it it goes in a endless loop and produces and endless, wrong PDF.
Have not found the glitsh yet.

Code: Select all

(define (file inFileName outFileName ff-lines footer-lines preNr postNr)
	(setq	object_id 1
		num_pages 0
		pages '()
		formFeedLines nil
		footerLines nil
		countLines 0
		countPages 0
		prePagNr nil
		postPageNr nil
		outOfLines nil)
	(get-params)
	(setq input-lines (parse (read-file inFileName) "\n|\r\n" 0))
	(txt2pdf get-lines outFileName))

(define (text inBuffer outFileName ff-lines footer-lines preNr postNr)
	(setq	object_id 1
		num_pages 0
		pages '()
		formFeedLines nil
		footerLines nil
		countLines 0
		countPages 0
		prePagNr nil
		postPageNr nil
		outOfLines nil)
	(get-params)
	(setq input-lines (parse inBuffer "\n|\r\n" 0))
	(txt2pdf get-lines outFileName))
Initialisation should be inside the functions or subseqeunt calls will fail.
Hans-Peter

Lutz
Posts: 5282
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Seems like my function doesn't work without specifying at least the form feed lines, but the page numbering still has problems on the short text buffer example. The file function seems to work fine but will probably also do wrong paging on very short files where it inserts empty lines to fill the page.

The problem is with the 'get-lines' function, it should just give a line and not do anything else if no form-feed lines are specified.

Lutz

Lutz
Posts: 5282
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

On 7.5.3 (seek 0) or (seek (device)) for device=stdio will return the 'ftell(stdout)' value, but it only works on LINUX/BSD, on Win32 it will always give a -1.

Lutz

Post Reply