Printing for tax reports part 2

We are looking inside the printing code to understand why the report printed on a file has several blank lines, spaces, etc. Two functions are called inside the loop and the first is not the problem: removing it the result doesn’t change.

The loop is simple, it just prints the data, using just one lookup. But just before looping it updates a field in the current data base row…

IF record_lock( FORCE )
   REPL FIELD->FIELD_1 WITH iif( value = 1, FIELD->FIELD_2, variable )
   GOTO RecNo()
ENDIF
UNLOCK

I think there are some flaws in this code. The first one is the GOTO RecNo() that should be not necessary. The other one is more philosophical: here the program is printing the tax filing reports and instead of locking one record at time, I’d lock the whole file, to avoid that someone, during the 2 hour period the printing needed, could change the data. Working on a data file exclusively should speed up the job but at the time it didn’t matter: the dot-matrix printer was the slowest in the chain.

Anyway, I went to the record_lock() function, that was decompiled. Decompilation doesn’t change instruction order: compiler optimizer can. But I don’t even know if Clipper 87 had one.

I opened the source file, searched the function and… oh…. code is… is… a mess !

Just a little snippet, the first few lines:

FUNCTION record_lock( ..., wait, ... )
   PRIVATE row,col,time,video

   row = Row()
   col = Col()
   time = wait
   video = SaveScreen( 21, 0, 23, 79 )
   IF RLock()
      csrput( row, col )
      RETURN .T.
   ENDIF
   DO WHILE .T. // Loop for RLock() retries

What’s wrong here? Well, strictly speaking, this code has been working for 25 years so it can’t be “wrong”. Would you accept this code from a programmer working for you? I won’t.

Not when this function is called in a “tight loop”, looping, in my test case, 15600 times. The function calls 15600 times Row(), 15600 times Col(), assigns 15600 times the time variabile and 15600 times saves a block of the screen. And if the RLock() works at the first try, 15600 times the cursor coordinates are reset… but… where did we move the cursor?

I got it: Maurizio already warned me in the comments that csrput(), a function from Funcky that I rewrote, was not correct.

My version:

FUNCTION csrput( y, x )
   @ y,x SAY ""
   RETURN .T.

Maurizio version:

FUNCTION csrput( y, x )
   SetPos( y, x )
   return nil

Actually Maurizio was right. My version of csrput() did addeall that empty lines in the printing. Since the cursor was always reset to the same position, the number of empty rows was fixed, and a form feed added.

Problem found. Compiled, linked, run a new print test. Now the printing seems ok, except for the totals. Imagine a report “framed” by a 76 columns * 66 rows box printed with | and – symbols. Also the columns are divided by a | between them.

At the end of each page a subtotal is printed. I don’t know if it is the total of the page or the total of the values printed so far, the important is that when opening the printed file I got a strange result.

This is how it looks in vim:
Errore_stampa_totali

Looking at the source code, the program prints a line with code similar to this:

@ PROW()+1, 5 say "|            |            |"
@ PROW(), 6 say value PICTURE __PICT

@ PRow()+1 means to print on the following line, forcing the printer to go up one line. @ PRow() means to print on the same line… 6 is > of 5, but 6 is < of PCol(). Something strange here… but, hey, what are that strange blu symbols in the file?

Think again at the dot-matrix era. Or better, at the time of the type-writer. How did you write some letters in bold? Or underlined? You just shifted the roll to the right and typed over the previous letters to have a bold result, or typed a sequence of minus symbol after rotating the roll a bit. Actually, you over-typed. And here is the same.

Dot-matrix printers have 2 different commands: one tells the printing head to go back at column 0 (carriage-return) and the other to move the paper one step (line feed). There are many other commands, like form-feed to go to the next sheet of paper (^L) and the ones to set compressed or expanded fonts (or CPI, characters per inch). ^L is present in all reports, font selection just in a few.

So now it should be clear which was the trick used by the programmer: write one line of the box, carriage return (^M), over write the values, then ^M^L, not shown in the image since it is the standard EOL.

When I will write the converter to create a PDF from the printed file I’ll need to handle these control characters.

I think that the printing test is now completed. Test-printing to a file works with very little changes to the printing source code (just one line added) but for the real changes more code is needed.
This test also shown that some library code needs a good refactoring, something I will do in the next post.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>