WHAT IT IS: This is PRTCOL v1.0, inspired by Robert S. Stein's PRT2COL.BAS, based in turn on Ralph Landry's WSTWOCOL.BAS. PRTCOL is written in Zilog-dialect assembly. It uses the Z80 extensions and thus requires a Z80, an NSC800 or an HD64180 to run. Source is included in this library, for those with the urge either to tinker with it or to adapt it to 8080-bound microprocessors (or to hack out any bug that may have escaped my testing). PRTCOL reformats full-width text files into two or more parallel columns. The program's output can be sent to CON:, to LST: and to disk. Unlike its MBASIC predecessors, PRTCOL does its own column formatting. The program's formatting is ragged-right unless certain procedures are followed (see below, "WS-formatted columns"), but it does pack words from any format into its columns, even from Apple-style "stream of words" files. PRTCOL actively throws away WordStar soft-formatting, so all those extra spaces, soft hyphens and "soft carriage returns" don't show up in the columnized text. FORMAT: As released, PRTCOL formats its output as two-column pages. Each 55-line column contains up to 35 characters. The two columns are separated by a five-space "gutter". Two lines above the text columns is a header; four lines below the text is a footing. All text is offset from the printer's left margin by eight spaces. After each page comes a FormFeed code. This format is ideal for a printer set to 12-pitch (12 characters per inch), 6 lines per inch. The page parameters are stored variables, so they can be dynamically altered. "Dynamically" means just that: you can change the page parameters for one file, or make your changes a permanent part of the COMfile, all within the program's operation, prior to running a text file through the process, without resorting to the use of a debugger or disk editor. WHAT IT ISN'T: I wrote PRTCOL to be a quick tool, rather than an extensive one, so there's a lot that it doesn't have. (In the hacker spirit, I should add, in some cases, "yet".) 1. PRTCOL v1.0 has a somewhat cryptic, somewhat unfriendly parameter-change interface. It briefly explains the terms, but the user-entry mechanism leaves me profoundly dissatisfied. V2.0's change-interface will be much more cooperative, I promise. I'm releasing v1.0 now because some of you might need the program like I do... here's a wheel you might not have to invent. 2. PRTCOL does no right-justification. I wrote it to print out source files for a proprietary ALU we use where I work, where the source lines seldom exceed ten characters. While I was at it I put the WordStar-compatibility stuff in, since I was using a WS- doc text file as a tethered goat while I debugged the program. Perhaps a later version will perform WordStar-style line-padding. 3. I'm not happy with the "over-long word" mechanism. I'll probably end up putting in several ways to handle the problem, and a switch-variable for selecting one of them. Suggestions? 4. More of the formatting should be controlled by dynamic variables. Within limits, I'll get to it. 5. I've got working wildcard-expander and SUBfile-follower routines (in MORSETXT); eventually I want to put those in too, particularly the wildcard expander. Since all the virtual-page and output-buffer structures are built with calculated variables, they can be built just above a list-expansion buffer of uncertain length. I've maximized speed by restraining the use of relative jumps and word fetches and by maximizing the use of register variables. Even with that, the time it takes the program to format a virtual page is quite noticeable. Any additional options can only add to that time overhead. With ROFF out there in the public domain, I see no reason to put more than the comfortable minimum of process flexibility into PRTCOL. If you disagree, let me know what you consider essential here... I might not have considered it. HOW TO USE IT: PRTCOL's default operation is to send the output stream to both LST: and CON:. The string SETUP$ is sent to LST: before processing begins; the string PDONE$ is sent to LST: after it's done. In my application, SETUP$ sets the printer to 17cpi, PDONE$ sets it back to 12cpi. In the release image, each of these strings contains only a carriage-return. When you change these to suit your application, don't type the bytecount, do type the strings exactly as they will be sent, hitting the ESCAPE key to insert (1Bh) in the string. If your string has to contain a null (00h, ^@), a backspace (08h, ^H), a CAN (18h, ^X), a NAK (15h, ^U), a carriage return (0Dh, ^M) or a linefeed (0Ah, ^J), you'll have to tweak the string with a debugger or a disk editor (SUPERZAP is superb for this), because these are commands to the BDOS-like line-edit routine that accepts the new string from the console...sorry. Don't forget to change the bytecount, the first byte in the string, to show the number of bytes that follow. If you set a string's bytecount to zero, no bytes will be sent. Again, you'll have to work on the program from outside; the parameter-change routine leaves the string unchanged if it gets an empty line. Command-Line Syntax: A0>prtcol [du:]infile[ du:][outfile][ v][ q][ ?] The " V" switch suppresses LST: output. The " Q" switch suppresses CON: output. The " ?" switch gets you into the parameter-change routines after the program signs on and before it starts to read in its file. OUTFILE must be specified. That's the only way PRTCOL can tell that you want file output. You can wildcard the output filespec, though. For example,-- In Out Result tethered.got mauled.* output->MAULED.GOT tethered.got b3:*.* output->B3:TETHERED.GOT tethered.got *.* input is renamed TETHERED.BAK, output->TETHERED.GOT [TETHERED.$$$ until done] With only one of these universal "kerchunks" for a command-line argument-- A0>prtcol A0>prtcol ? A0>prtcol // PRTCOL shows a help screen and then goes home. Parameter-Change Interface: The v1.0 parameter-change interface, as mentioned above, is a few good ideas tacked onto a slightly unpleasant driver. When you it asks you for a label, type exactly that, the label of the variable whose value you wish to change. Either case will do and no colon is desired or needed. If it asks for a hexadecimal value, it wants two ASCII digits. For example, to specify (^J, 0Ah), type "0a". If it asks for a string, type the string exactly as you want it stored. Example: to set up a Gemini 15X for 17cpi, you send the string: ESCape B 3. Here, that's typed in as ,'B',^C. Don't type in a bytecount; the program does that part by itself. These are the variables. Only those with any meaning in v1.0 are displayed for check and change... ; -----MAGIC BYTES------ ; TABSPC: db 8 ;column count for tab expansion LOFSET: db 8 ;left margin from print-head start COLPRT: db 2 ;copy is split into this many columns GUTBYT: db 5 ;inter-copy midpage margin (gutter) COLBYT: db 35 ;width of each text column in characters ; ;The following variable is meaningless in v1.0: ; PAGLEN: db 65 ;lines that will fit on a page ; LINES: db 55 ;lines of copy per page HEDRUM: db 2 ;header-to-copy margin in lines FUTRUM: db 4 ;copy-to-footing margin in lines ; LFEED: db 0FFh ;0 = no perfskip. ;0FFh = use ^L for TOF. ;Else, = PERFSKIP in linefeeds BSCHAR: db 8 FFDMAP: db LF ;^L is mapped to this char for CON:. ; SETUP$: db 1,CR ;byct, then chars ; org SETUP$+16 ; PDONE$: db 1,CR ; org PDONE$+16 ; FLOPPY: db 0FFh ;true if floppy-based HOMDSK: db 'B'-'A' HOMUSR: db 0 HOMNAM: db 'PRTCOL COM' ; ;These two aren't operative in v1.0: ; BUFENA: db 0FFh ;true if dot-buffers are enabled DOTENA: db 0FFh ;true if dot-commands are enabled ; ;Down here where they're patchable (if there's room)... ;ECHOSW may be patched to 'call' opcode for print-echo. ; CONOUT: ld e,a ld c,2 ECHOSW: jp BDOS ; pop af push af LSTOUT: ld e,a ld c,5 jp BDOS ;HOW IT WORKS: The input stream is read into the default record buffer at 80h and fetched by a GETBYTE routine. PRTCOL does its formatting in a virtual page buffer in memory, just above its own code and operating variables and the header and footing buffers. It uses a pushback stack (located just under CCP) to hold the fetched beginning of any word that won't entirely fit into the current column line. All memory in between those two are used as an output buffer when the output is to be sent to disk. If you've invoked the parameter-change routine, that gets run first. If you change any of the variables, PRTCOL will ask whether you want those changes made permanent. If you say yes, PRTCOL looks for the file named at HOMNAM in HOMUSR user area of HOMDSK drive. Once it finds such a file, it reads in the second record of that file and compares it with its own memory area 180h-1FFh. If the two records are identical, it writes out bytes 100h-17Fh to the first file record and puts the changed file away. Then it calculates addresses for the virtual page buffer, based on the parameter variables. The columnated text goes into that virtual page; the header and footing are read straight out of their own buffers. There's a header-siding buffer too, used to hold a header found mid-page until the current page is sent out. PRTCOL's header handling currently differs slightly from that of WordStar. In WordStar, if a .HE line occurs just after a page break, it will be printed at the top of that page. If PRTCOL v1.0 finds such a line, though, it puts it into the header siding, where it sits until the current page is completed and sent out. Only then is the new header copied into the header buffer. This will probably be changed in a subsequent version, to follow the WordStar style, even though it's unlikely that PRTCOL's page break will occur at the same place as WordStar's. Starting with the first location in the leftmost column, PRTCOL writes the input stream characters into each line in the first column, after writing the Left-OFfSET bytes into place. If a partially-fetched word won't fit into the column, the program moves backwards, shoving the characters onto the pushback stack and replacing them with spaces, until it finds a space. When the pushback stack is checked at the beginning of the next line, that partial word will be pulled back off and plugged in, then the program will complete the word by fetching the rest of the characters on the input stream. When the leftmost column is filled in, the program starts filling in the next one. Each line of all succeeding columns is preceded by a GUTter BYTecount of spaces. Any characters (^I, 09h) encountered will be expanded into spaces. The release-version image has the controlling variable set to columns-of-eight (same as BDOS does when it sends text to CON:). Tab-expansion does not extend beyond the end of the column line. The last column of each line is filled in with nulls rather than spaces. This matters because nulls aren't sent out, so the last printable character of each multicolumn line of each page is followed by a , not a stream of spaces, unless the spaces or a are there in the input stream. Once the end of the input file is reached (either by fetching an EOF, a ^Z, or by a sequential-read error), the remainder of the last virtual page is filled in with nulls, with the same result at send-time. The last page of a PRTCOL output image will have a single column close to the left margin, rather than (as in some other similar programs) two or more short columns at the top of the page. Choose and use the tool that fits your needs and your tastes; this method meets mine. In the interest of universality, any one of these in the input stream is considered a valid End-Of-Line: (found in Commodore listings) (found in UNIX/C listings) (CP/M standard) ...the pushback stack makes this flexibility possible. WordStar Documents and PRTCOL: 1. Soft spaces, inserted by WordStar for right-justification, are discarded. (Soft space = A0h = ' '+80h.) 2. Soft EOLs, inserted by WordStar in word-wrapping, are discarded. (Soft End-Of-Line = 8Dh,0Ah; +80h, plus a normal . Together, a "soft carriage-return".) 3. Soft hyphens are discarded. (1Eh or 1Fh; WordStar displays both as half-intensity hyphens.) This happens in the input stream, so the words they hyphenated are slammed back together and considered whole words. 4. All print control codes (^B, etc) are discarded. 5. PRTCOL recognizes the .HE and .FO dot-commands, responding to them almost as does WordStar by putting their lines into header and footing buffers. The default header looks like that of DISK7; the default footing is WordStar's line number. Any encountered header and footing will displace them. PRTCOL recognizes WordStar's '#' symbol in a header or footing and replaces it with the current page number. PRTCOL does NOT recognize WordStar's ^K code. Any other dot commands encountered are treated like any other text. Antidisestablishmentarianisms and other freight trains PRTCOL uses a pushback stack, with IX as its pointer, to hold any portion of a word that won't fit in a column line. It pulls that word-beginning back off the stack to begin the next column line. In this program, a word is a character string bounded by spaces, tabs, EOLs (, , or ) or EOF. PRTCOL does not have WordStar's programmed ability to break up words into syllables, nor does it distinguish between alphanumerics and punctuation. That means that the following file-source string, familiar to anybody who's had to suffer through my files, is a single very long word: BLADES/Ampro[lies.961]--CHR$(13)16FEB86 The first version of PRTCOL shoved most of this onto the pushback stack, then filled page after page with blank lines, vainly looking for a line long enough to hold it, never seeing the EOF (^Z) that was next in the input stream. My way out of this is a kluge: if PRTCOL v1.0 finds such a long word, it shoves it into the footing buffer, plants a page- number symbol behind it, then continues as if nothing had happened. If it finds another one, it does it again, even if the first one hasn't been printed yet. In my case, that's the last thing I put in a file, to reassure me that I've got the last page printed out and to remind me of what disk on what machine has the file (and when I started the file). If you're fond of long words, though, or ASCII graphics, you're either going to make your column lines at least as long as such or you're going to have a problem. WS-FORMATTED COLUMNS: To preserve WordStar right-justification, follow these steps: 1. Reformat your text to the exact column width you want, using WordStar. [^OR ^QR ^QQB ] Put paragraph breaks anywhere you want them. The result should be a single, very long column. 2. Type in full-length (80h max) .HE and .FO lines anywhere they're wanted (keeping in mind the difference in the treatment of .HE lines between WS and PRTCOL v1.0). The dot-commands do NOT have to be capitalized to be recognized. 3. Save the result. 4. Harden the formatting with WSDOCON, TOPSTRIP, PIP, or anything else that resets bit d7 of every byte. TOPSTRIP has the dubious advantage of not generating yet another *.BAK file. 5. Run the file through PRTCOL, setting COLBYT to the exact column width. PRTCOL will read in the column lines, plugging them into place in its virtual page and finding that (surprise!) every line is cleanly done. It'll handle header and footing lines as described above. One improvement I have in mind is a switch to cause PRTCOL to strip off the top bits of soft spaces and then use them, rather than just throwing soft spaces and s away. For now, though, you'll have to flatten those bits to get the WS formatting. Hope this helps. 73 & GH --CHR$(13)WB1HKU/6 eof PRTCOL.DOC/Ampro[istuff.984]--CHR$(13)30JUN86