home *** CD-ROM | disk | FTP | other *** search
- ############################################################################
- #
- # File: printcol.icn
- #
- # Subject: Procedure to format columnar data
- #
- # Author: Robert J. Alexander
- #
- # Date: June 10, 1988
- #
- ###########################################################################
- #
- # This procedure deals with with the problem of printing tabular
- # data where the total width of items to be printed is wider than
- # the page. Simply allowing the data to wrap to additional lines
- # often produces marginally readable output. This procedure facil-
- # itates printing such groups of data as vertical columns down the
- # page length, instead of as horizontal rows across the page. That
- # way many, many fields can be printed neatly. The programming of
- # such a transformation can be a nuisance. This procedure does
- # much of the work for you, like deciding how many items can fit
- # across the page width and ensuring that entire items will be
- # printed on the same page without page breaks (if that service is
- # requested).
- #
- # For example, suppose we have a list of records we would like
- # to print. The record is defined as:
- #
- # record rec(item1,item2,item3,...)
- #
- # Also suppose that lines such as
- #
- # Field 1 Field 2 Field 3 ...
- # ------- ------- ------- ---
- # Record 1 item1 item2 item3 ...
- # Record 2 item1 item2 item3 ...
- #
- # are too long to print across the page. This procedure will print
- # them as:
- #
- # TITLE
- # =====
- # Record 1 Record 2 ...
- # -------- -------- ---
- # Field 1 item1 item1 ...
- # Field 2 item2 item2 ...
- # Field 3 item3 item3 ...
- #
- # The arguments are:
- #
- # items: a co-expression that produces a sequence of
- # items (usually structured data objects, but not
- # necessarily) for which data is to be printed.
- #
- # fields: a list of procedures to produce the field's
- # data. Each procedure takes two arguments. The
- # procedure's action depends upon what is passed
- # in the first argument:
- #
- # header Produces the row heading string to be used
- # for that field (the field name).
- #
- # width Produces the maximum field width that can
- # be produced (including the column header).
- #
- # Other Produces the field value string for the
- # item passed as the argument.
- #
- # The second argument is arbitrary data from the procedures
- # with each invocation. The data returned by the first func-
- # tion on the list is used as a column heading string (the
- # item name).
- #
- # title: optional.
- #
- #
- # pagelength: if null (omitted) page breaks are ignored.
- #
- # linelength: default 80.
- #
- # auxdata: auxiliary arbitrary data to be passed to the field
- # procedures -- see `fields', above.
- #
- ############################################################################
-
- procedure printcol(items,fields,title,pagelength,linelength,auxdata)
- local maxwidth,maxhead,groups,columns,itemlist,cont,f,p,underline,
- hfield
- /linelength := 80
- /pagelength := 30000
- /title := ""
- #
- # Compute the maximum field width (so we know the column spacing) and
- # the maximum header width (so we know how much space to leave on the
- # left for headings.
- #
- maxwidth := maxhead := -1
- cont := ""
- every maxwidth <:= (!fields)("width",auxdata)
- hfield := get(fields)
- every maxhead <:= *(!fields)("header",auxdata)
- columns := (linelength - maxhead) / (maxwidth + 1)
- groups := pagelength / (6 + *fields)
- #
- # Loop to print groups of data.
- #
- repeat {
- if pagelength < 30000 then writes("\f")
- #
- # Loop to print data of a group (a page's worth).
- #
- every 1 to groups do {
- #
- # Collect the items to be output in this group. A group is the number
- # of columns that can fit across the page.
- #
- itemlist := []
- every 1 to columns do put(itemlist,@items) | break
- if *itemlist = 0 then break break
- #
- # Print a title and the column headings.
- #
- write(repl("=",*write("\n",title || cont)))
- cont := " (continued)"
- writes(underline := left("",maxhead))
- every f := hfield(!itemlist,auxdata) do {
- p := if *f < maxwidth then center else left
- writes(" ",p(f,maxwidth))
- underline ||:= " " || p(repl("-",*f),maxwidth)
- }
- write("\n",underline)
- #
- # Print the fields.
- #
- every f := !fields do {
- writes(right(f("header",auxdata),maxhead))
- every writes(" ",center(f(!itemlist,auxdata),maxwidth))
- write()
- }
- } # End of loop to print groups.
- } # End of loop to print all items.
- return
- end
-