Previous: 10 Proper Toolbars, using %tb or %ib
Next: 12 Printing graphics
In this section:
Printed output is as old as Fortran itself. Early mainframes tended to have line printers attached that printed on fanfold paper with about 132 columns of characters, and the font (as such) was monospaced so that it was comparatively easy to get columns of print to line up. The printer would assemble all the print for a particular line and print that in one impact, which tended to make the line printers rather noisy, but for those of us who were used to the progress of a teletype or typewriter the line printers were astonishingly fast.
There tended to be Hobson’s choice as to which printer to use because the mainframe would have typically Fortran logical unit number 6 preconnected to a single line printer.
Computers that operated with time-sharing, terminal access, tended to map unit numbers 5 and 6 respectively to the keyboard and screen, and this was the norm with Fortran on personal computers prior to the advent of Windows.
Much of the output from Fortran programs in those past eras tended to be tables of numbers.
It may still be necessary to display those tables.
Early personal computers tended to be attached to dotmatrix printers of which the dominant type typically printed 80 characters across in paper that was also fanfold and sprocket driven. If one spent more money, then wide-carriage printers could match the 132 columns of the old line printers, while using 15 inch wide (and thus more expensive) paper. Most printers could be switched between 8 and 10 characters per inch, and many offered alternate character sets and effects such as bold or italic type with or without underlining, and sometimes with non-Roman character sets. Printers tended to be connected to the parallel (Centronics) port of a PC, or less commonly to an RS232 serial port, but neither style of connection is common on modern personal computers and by not common I mean as rare as hens’ teeth!
In those old days, communication with the printer and switching between character sets, effects and so on could be done using escape codes. Escape codes are sequences of characters beginning with No. 27 in the ASCII code sequence, which is called ‘Escape’ or simply ESC. Anyone fascinated with such computer archaeology could well buy a second-hand copy of what I had found it useful at the time: a book written by Stephen Morris and entitled Newnes PC Printers Pocket Book (published by Butterworth-Heinemann). Early laser printers had similar sorts of connection and either used an escape code based language or if one was prepared to spend a great deal more money, the page description language Postscript. By far the majority of laser printers used A4 paper10, which was one step up further in the expense of running the things, especially when combined with the cost of toner cartridges. Although A3 printers were available using laser technology they tended to be disproportionately expensive to buy and to run. Interestingly enough, the PC Printers Pocket Book is still available second-hand, and covers both various printer control languages and Postscript.
Most dot matrix printer types were supplanted by inkjet printers which tended to offer colour and a higher resolution, and all dot matrix, laser and inkjet printer types could print graphics if they had the right driver software, which Windows ultimately simplified because printer manufacturers almost always provided a Windows-compatible driver. Finally, we got to the situation where many printers of the laser or inkjet kind will only function if connected to Windows whether directly or via a network. Windows will print on these devices by treating them as graphics devices and so even printing text as a sort of sophisticated graphics. Usually, Windows is configured so that one can print to a default printing device or to another one that the user selects specifically.
Annoyingly, some cheap printers don’t get updated drivers for later versions of Windows, and this means that perfectly serviceable hardware has to be discarded. Sometimes, as was the case with Lexmark’s inkjet printers, a manufacturer withdrew entirely from a particular type of product, annoyingly abandoning every user who had bought their product (like me!).
FTN95 considers that a variety of unit numbers are ‘preconnected’ to the screen and keyboard of a PC, notably 5 (keyboard) and 6 (screen) and * (both). If you simply WRITE to device 6, or PRINT or WRITE to device *, then the printout will appear in a scrollable window. This Window will be a command window (DOS box) if WINAPP is absent, or if the WINAPP directive is given, the output goes to the same sort of scrollable window, but with a Windows-style, black text on white background, appearance. Despite being scrollable, there is no way to capture the output from the Window (except as a screen grab), and as the text is stored in a buffer, there is a sizeable, but limited, amount of data that can be displayed. While the window is resizable, it has no command buttons, thus limiting its usefulness as a dialog. It should be useful for debugging output if you do that by inserting output commands at various points in the source code, particularly if you prefer that way to learning the operation of FTN95’s debugger.
Every now and again, I read something that leaves me completely puzzled. One of those things is the so-called ClearWin+ window. While it might seem that it’s a hangover from the early days of ClearWin+ it is in fact rather more useful than you might imagine. You can, for example, change the font, the text colour, or various other effects not available if you just link the printer to Fortran output.
In the example that follows, a ClearWin+ window is opened as the client area to an independent dialog box, and this window will remain open to accept anything written to unit 99 until the dialog is closed. With %ww the dialog has minimise and maximise buttons on the caption bar, and the ClearWin+ window, although set to 70 characters wide and 30 lines high, actually takes a pivot so that it can respond to RESIZE events (without programmer intervention). The window also has scroll bars so that the contents can be reviewed even if the window is shrunk to a smaller size.
The text that appears is monospaced. The WINIO@ calls to set up an independent dialog containing a ClearWin Window that can be written to using unit 99 is:
IA = WINIO@ ('%ca[Text output to Unit 99]%2nl&') IA = WINIO@ ('%ww&') IA = WINIO@ ('%pv%70.30cw[vscroll,hscroll]&', 99) IA = WINIO@ ('%lw', KONTROL_HANDLE)
The %lw windows handle allows the window to be closed by setting its value to 0. ClearWin+ windows can, of course, be of fixed size, and if desired, be combined in a dialog with other controls. It is possible to use the standard callback ‘COPY’ with a ClearWin+ window in order to capture highlighted text to the clipboard, which requires the callback to be linked to a button or toolbar, or even a menu item, but it is unusual for menus to be provided for dialogs.
The mechanism for changing fonts and colours and font effects is somewhat long-winded. The advice from Silverfrost is that ClearWin+ windows are obsolete, and I think that on balance my advice would be to avoid them as well, although you might find them to be the solution you’re looking for. In that case, they are documented in the online help file.
Personally, I think that neither of the foregoing methods fits well with a Windows paradigm, where logically the results of an analysis should be presented graphically, and tabulated outputs, if they have any role at all, need to be kept in a disk file for archival record purposes or be printed out as hard copy.
A particular use of mine that did require printouts of tabulated data was where I needed to give groups of students a sheet of angles and distances so that they could go out into the field and set-out part of a road alignment. The quantity of data was actually quite small in every case and would fit on a single sheet. There was no disadvantage in using a monospaced font in a reasonably large point size, and printing each group’s data on a separate sheet was actually an advance on having to tear up pieces from a fanfold printout.
A related case, not from my experience but from a colleague’s, was the need to present the results of a structural analysis for submission to a building control office in support of a design. They knew very well that many pages of printout would never be looked at seriously and his printout needed to be brief and authoritative as well as simple to understand, graphical, as well as needing to be correct.
It is not therefore that there is never a need for tabulated output, but that it is very desirable to think about whether or not you need to see columns of numbers in the first instance or to preserve them in paper form. The first of those considerations needs to be considered in the light of what you will do with those numbers. If it is to plot a picture, then the sensible thing to do is to get the computer to plot the picture and not bother with the numbers, at least, not in the first instance, or use the numbers as annotations to the picture.
Taking all the above into consideration and noting that there are instances where tabulated data needs to be printed out then we need to look at how it should be done.
The PC Fortran traditional approach of identifying the printer in an OPEN statement, e.g. as in:
OPEN ( LPT1: )
no longer works and so we have to identify the logical unit number with the printer in some other way. One way is via the standard callback PRINTER_OPEN or PRINTER_OPEN1. Standard callbacks are always supplied to WINIO@ in quotes. Here’s the way I do it, in the following example by connecting logical unit LUN to the printer:
LUN = 10 IB = WINIO@ ('%mn[[Print]]&', 'PRINTER_OPEN', LUN, KB_PRINT)
The equivalent that allows the user to select which printer is used (if there is a choice) uses ‘PRINTER_OPEN1’. I have a choice of two physical printers, but even when there is no printer connected, there may well be other choices such as ‘print to PDF’ that I want to select.
Will you get confused between ‘PRINTER_OPEN’ and ‘OPEN_PRINTER’? The answer depends a lot on how you work, but I certainly do. Then, I have to consult the online help.
What you print is up to you, but do remember that ordinary Fortran printing was designed for continuous media, and modern printers usually operate with sheets. With sheets, it is advisable to provide headings on every sheet, and count the lines output. You may find that other information needs to be printed on each sheet (see section 12.5).
Remember to use CLOSE (LUN) to ensure that the last sheet is printed and to disconnect that unit number from the printer.
In one particular program of mine, the user has a set of choices on what to print, and how to print it, the how including whether to print a file copy in monospaced font and cramming a lot on the page, or in a display format for a noticeboard, using large, proportionately-spaced fonts. There was a risk that the File/Print menu command would have rather a lot of options, including whether or not to print on the default printer. To keep to a single menu item (incidentally, also linked to a toolbar) I programmed the File/Print menu command to bring up a ‘Print Station’ –a dialog with all the options. Rather than duplicate the options with ‘PRINTER_OPEN’ and ‘PRINTER_OPEN1’, I was able to put a single %`rb tick box on the dialog with a status variable iPrint_on_Default (preset to 1 for using the default, but user changeable). Then, the Print Tables button on the Print Station dialog launched another Window that was not only invisible, but also started up by associating the printer with logical unit number 9 (or any number I had chosen), and closing itself, while leaving the printer and unit still associated:
IF (iPrint_on_Default .EQ. 1) THEN IB = WINIO@('%ww[invisible]%sc', 'PRINTER_OPEN1', 9, NULLISH) ELSE IB = WINIO@('%ww[invisible]%sc', 'PRINTER_OPEN', 9, NULLISH) ENDIF
The code appeared in every callback from the Print Station. I found it useful to have another tick box for ‘Keep Print Station open’, which facilitated printing different things without returning to the main menu system or toolbar icon.
Perhaps I could have named the callback simply by the name NULL, but deep down that shorter name signifies something to me, so perhaps a name for the callback function such as JUST_RETURN might do equally well instead, or something with a KB_ prefix.
INTEGER FUNCTION NULLISH() C ========================== NULLISH = 0 RETURN END
After you have identified logical unit 9 with the default or other printer, then it is simply a matter of producing formatted output using WRITE and the appropriate FORMATs. This approach uses a monospaced font, and in every respect other than quality, which is usually higher on modern printers than anything we fantasised about having in lineprinter or inkjet printer days, is the same. After printing output to unit 9, printing is simply terminated with CLOSE (9).
Considering how much effort goes into producing any sort of a Windows app, and in my case, how I recognised that I would probably never have the time to commit to produce an editor program, an alternative presents itself, and that is to use a third-party program that already exists to display voluminous tabulated data. This could include the much-maligned Windows Notepad application.
A very simple way to invoke NOTEPAD.EXE would be to use would be to use START_PROCESS@ or START_PPROCESS@ as we did to launch the hypertext help program HH.EXE early in the development of our source code back in Chapter 2. You could save your tabulated data in a file, and then launch NOTEPAD.EXE with the name of that file. FTN95 has a routine for generating unique filenames for temporary use. If your file was not particularly long, then it might still even be in the disk cache and therefore read slightly more quickly than if it was only on a hard disk, although there is still the time taken to load NOTEPAD. Increasingly, computers are equipped with solid-state disks which are faster than spinning hard drives, but the disk cache is even faster.
Instead of opening a file through the Windows dialog, a filename is found by means of the following code:
CHARACTER*(long enough) FILENAME INTEGER*2 IERROR CALL TEMP_FILE@ (FILENAME, IERROR) OPEN (FILE= FILENAME, UNIT=LUN etc) write the contents CLOSE (LUN) CALL START_PROCESS@ ('NOTEPAD.EXE', FILENAME)
Note that the returned error code is INTEGER*2 (or KIND=2 if you prefer) because TEMP_FILE@ goes way back into the prehistory of FTN77. Even a rather trivial Windows accessory such as NOTEPAD is comparatively sophisticated, allows printing, cut-and-paste and various other operations that would be quite hard to program for yourself no matter how adept you are at Fortran and however good and supportive you find the facilities of ClearWin+.
I well remember my early days using a computer where my efforts in programming led to a rather substantial heap of print out in the form of listings, and when finally, the program worked, every run would lead to yet another addition to the pile. Notwithstanding several clear-outs when I moved offices, on retirement I had to dispose of even the things I had saved that were covered in dust and cobwebs and the spiders whose diet consisted of whatever bugs were eating the paper. I knew many PhD students and even some academic staff together with many people in industry who were amassing similar piles of paper that were very rarely if ever looked at again. In many cases there had been a voluminous output which was scanned for very few but critical data values, and the rest was just padding.
I also knew PhD students whose seeming main role in life was to take data from those printouts and construct various diagrams and graphs, either for their theses or for a paper to be submitted to a scientific journal. The point therefore is why should you really want to print out vast quantities of data or even just display them in a scrollable list on a computer monitor. Surely the computer can do the presentation work far more effectively than the harassed PhD student. Windows, in combination with FTN95 and ClearWin+ can do that for you, particularly in the case of your analysis where you probably know in advance what sort of presentation of data or results is likely to be required.
Personally, therefore, I should eschew both the display of large quantities of tabulated data and indeed, printing out the same, and prefer some display of what the data values actually mean. That is not to say that there is no value in the generation of those results, but their interpretation really does require a bit more imagination than poring over long lists of numbers.
In a previous chapter I have discussed what you might save in the way of input data and results. I made the suggestion that you consider appending the results to the data in the same file, and therefore, should the datafile be opened at a later date, your program would not need
to perform any analysis but could simply operate on the results in the file. Certainly, if the runtime of the analysis is of any concern at all (and sometimes it is not), then to follow that approach could represent a substantial saving to the user. Moreover, as a file of results in any case is rather meaningless without a record of the input data, then your program quite possibly saves both at the same time already, although perhaps not in a format that can be easily re-read by a computer unless the application has been programmed to do so.
The best thing to do with voluminous printouts is not to generate them in the first place, but instead to keep them archived on some sort or readable storage medium (which is what paper is, I suppose, but I mean computer-readable). The problems associated with storage on computer-readable media include:
There may be some forms of removable media that lose their data over time, especially optical media such as CD and DVD.
As for whether or not the media remain readable, I have used in the past 8”, 5.25” and 3.5” floppy disks, with the 5.25” and 3.5” disks of various formats and densities, including whether they are single or double sided. There were other media such as ZIP and JAZZ disks, CDs and DVDs (Blu Ray anyone?), the rarer 3” floppy disks, magnetic tapes and so on. The problem is that by and large many of those media are not readable on current generation PCs.
Paper turns out in the end to be just as ephemeral as everything else!
As to whether or not you can find what you are looking for, that is a matter of the file storage system in use and the file naming convention employed. It is therefore helpful for your application to generate file names automatically and at the same time maintain some form of database of what the contents of those files contain. That is a matter of programming outside of ClearWin+.
Footnotes:
10. US letter size in the US and Canada, A4 in the rest of the world.
FORTRAN and the ART of Windows Programming, Copyright © Eddie Bromhead, 2023.