.ps64,80.lm0.rm80.nhy .c;(Experimental) SMG version of VMS AnalytiCalc .c;--------------------------------------------- .s.nf by Chris Doran, Sira Ltd., South Hill, Chislehurst, Kent, England, BR7 5EH Tel: +44 81 467 2636 x 325, Fax: +44 81 467 6515 Telex: 896649 .f.p0 This is an attempt to meet Glenn Everhart's plea for a SMG version of AnalytiCalc. It turns out to be more difficult than you think because I/O is done, and files are opened and closed, all over the place. Further, it is frequently unclear whether you are reading/writing the terminal or a file, because you can do @TT_: (or @some__logical__name__assigned__to__the__terminal). .p The coward's way out would be to just translate TTYINI and SCRIND to do cursor-positioning using SMG, and allow FORTRAN I/O for the actual text (probably calling SMG$FLUSH__BUFFER a lot to make sure positioning was actually done). However, being a glutton for punishment, I decided to do it the hard way and try to translate ALL the screen I/O. .p Apart from the obvious complete rewrites of TTYINI and SCRIND (where ALL of the SMG code is placed), the following other changes/assumptions were necessary. This is undoubtedly not a complete set, and other changes may become apparent during later use. .list1 .le;LUNs 1, 5, and 6 are assumed to always be assigned to the terminal. Whether under names TT:, SYS$INPUT, SYS$OUTPUT, or SYS$COMMAND, is not checked. This has undoubtedly clobbered the facility suggested in one of the source files that you could redefine one of these names for test purposes. Sorry! .le;Any READs or WRITEs which explicitly access these LUNs, or may do so by having the LUN number in a variable (LEVEL etc.) are changed to CALL#LREAD(LUN,TEXT,N) or CALL#LWRITE(LUN,TEXT,N), where TEXT is a LOGICAL*1 array of N characters to be read or written. LREAD and LWRITE decide whether to do screen I/O via SMG or file I/O via READ or WRITE according to the value of LUN. [Author's note: The *@file.typ commands to read command procedures from within cells use Logical Unit 1 and will be broken by this. In fact there's no good reason to trap logical unit 1, though during *K (interactive calculator) mode lun 1 can be used. Units 5 and 6 are indeed used for terminal I/O at all times.] .le;LREAD also checks FOOBAR so that "automatic initialisation" works when AnalytiCalc is invoked from a command procedure. So that it starts up in this way, FOOBAR is initially set to 1 and cleared unless the title contains a tilde (~). This is the reverse of the previous code where FOOBAR was initialised to 0, and set to 1 if a tilde was found, but the effect should be the same. .le;Where something other than a text array is to be read or written, ENCODE or DECODE must be used in addition to LREAD or LWRITE. [Author's note: this is unfortunate in that it violates Fortran 77 standards. The Amiga version gets this stuff right, however, AND does ALL console I/O via a pair of subroutines. My VAX version never got all that cleaned up.] .le;Unfortunately, LWRITE requires you to count the number of characters in literal strings ('...'). Sorry! So that lengths are checked at compile time and not found to be wrong in some rarely-used routine months later, I've used Hollerith form for all strings. .LE;After an LWRITE call, the cursor stays at the end of the output. Most of the time this doesn't matter because the next thing to be output is a cursor position, or is what you want because the next thing to be input is the reply to a prompt. Where you really want a new line, either call LCRLF(6) or UVT100(NEL). .LE;SUBROUTINE GETTTL, called in only place in XQTCMD, uses SMG$READ__COMPOSED__LINE, which, with the aid of some SMG$ADD__KEY__DEFs in the startup, translates all the keypad keys for you. This eliminates all escape key parsing in AnalytiCalc itself, and allows some of the LK201 keyboard keys to be defined too. .le;The GOLD keys are implemented using the key state temporary lock feature of SMG$ADD__KEY__DEF. I haven't implemented GOLD-GOLD...-HELP, as no H1n help pages are yet available. I also no longer interpret the _^ command, which could give some problems somewhere. All this saves a lot of extra parsing in CMDMUN, but precludes display of "Gold#n" at the top right of the screen and use of the VT100 LEDs. Partly because of this, and mainly because esc#[#0q commands to turn off the LEDs cause the SMG$ALLOW__ESCAPE mechanism to abort, the %%% commands to delete the "Gold#n" message have been removed from the keypad command files. .LE;To avoid having to redefine keys such as HELP when you swap between enter-mostly and command-mostly modes, I have made GTMUNG ignore a leading '/' in both modes. Thus HELP can always be defined as '/H' etc.. In the previous version, a leading '/' in command-mostly mode seemed to cause the line to be ignored (as '*') so this is potentially dangerous if anyone has been assuming this is a feature. However, I don't recollect it being documented anywhere, so if they have, it serves them right. [Author's note: I agree; this was a side effect of ignoring anything that couldn't be understood. Anyone using that as a feature loses.] .le;Pressing GOLD no longer forces you into command-mostly mode. I assume that GOLD's cancellation of enter-mostly was more of a bug than a feature, so I've not tried to simulate it. [Author's note: this was a feature to allow the command files to work in a defined way. Since keypad command files are editable by anyone, I did not consider their behavior anything more than examples of how I set AnalytiCalc up.] .le;Files AKCA.CMD (GOLD-.), KYP.CMD (GOLD), and KYPA.CMD (GOLD-GOLD) are redundant. .le;To permit escape sequences to be included in key definition files' prompts and help text, the SMG$ALLOW__ESCAPE facility is set on for any output line which is found to contain escape, csi, ctrl/N or ctrl/O. This translates VT100 positioning sequences to actual terminal equivalents if necessary, so my old _.CM5 alternative key definition files are no longer required (although the VT52 keypad diagram still is). For some reason a ctrl/O had to be placed in the first line of the VT100 keypad diagrams, otherwise the lower-case characters therein came out as line-drawing characters. SMG$ALLOW__ESCAPE must NOT be left on permanently, as it seems to inhibit use of the rendition argument for SMG$PUT__CHARS etc. This may be a bug, but since SMG$ALLOW__ESCAPE is officially obsolete, I doubt whether an SPR would receive much sympathy. .LE;UVT100(SGR,n) implements all the available renditions: bold, underline, blinking, and reversed, since it was quite easy to do this. n=0 clears all renditions, n=1/4/5/7 sets the others, ORing them with the last value, so that you can get combinations. I'm not sure whether this matches what the very original UVT100 did. .le;I have implemented DECKPAM/DECKPNM to turn the keypad to/from applications mode. This is used instead of some literal esc#= and esc#> sequences written in certain places. Applications mode is turned off during spawned commands and interactive CALC. Rather than invent a new UVT100 function, I have used SM/RM with artificial values of 0 for DECKPAM and DECKPNM, there being no esc#[0h/esc#[0l (I hope). .LE;Wide/Narrow screen setting is supported by recognising the esc#[#?3#l/h code in a %%% prompt, and by implementation of UVT100(SM/RM,DECCOLM). A better way would be to have an "official" AnalytiCalc command, however. [Author's note: I didn't want AnalytiCalc to be that closely tied to particular terminal types. That's why no "official" widths were defined. This has proved handy in the Great New World of X windows.] .le;DECSC and DECRC (save/restore cursor) are implemented, and used in ERRMSG to counter the bug that used to leave you at row 2 after an interactive CALC error message. .LE;The once-only initialisation code of SCRIND sets the number of screen columns, DRWV, according to the screen width it finds the terminal set to. Perhaps it could also set the number of rows, but I'm not sure of all the things that have to be changed to do this (at least DCLV, LLCMD, and LLDSP, but there may be others). [Author's note: the page length command parts of the S command and the display bounds change commands of DB need to be handled at least. I believe DCLV, DRWV, LLCMD, and LLDSP are all one needs to modify. DCLV and DRWV are set by DB and specify how large the display sheet is for print and display purposes. LLCMD and LLDSP specify which row the "command entry" and "display of formula" lines appear on. My standard is that LLDSP=LLCMD+1, but that is my assumption. I don't recall anything particular depending on it.] .le;Lots more SMG routines could be used if one were to attack more source files, but in the interests of portability, I've kept all SMG routines to SCRIND and TTYINI. Other possibilities are to use SMG$PUT__HELP and SMG$CREATE__SUBPROCESS/SMG$EXECUTE__COMMAND. The advantage of using the latter would be that the subprocess you create on your first '}' command is left around for subsequent ones, which speeds their startup. .els0 .s ^&Other Changes\& .list1 .le;All HELP messages have been tidied up, and versions are supplied in English and American -- PCHELP.FVA for American, and PCHELP.FVE for English. Before compiling, COPY one of these to PCHELP.FVX. .p This may sound a bit finicky, but if you knew the amount of time I've wasted in cases where English and American mean the precise opposite to one another, you'd understand my paranoia about language! .le;In DSPSHT.FOR, OPEN list file STATUS='NEW' to avoid overwriting an existing one which might be wanted (default is STATUS='UNKNOWN'). .le;In CALC.FOR, OPEN SYS_$COMMAND with STATUS='OLD' to avoid compiler warning. .le;In XQTCMD.FOR, The default filetype for G and P commands has been set to PCC. .els0 .s ^&Are These Bugs, Features, or Pains?\& .list1 The following unexpected behaviours have caused much head-scratching and a general disinclination to use AnalytiCalc. However, after much searching through the code, they seem to be intentional:- .list1 .le;If VM is set, commands are not prompted for, and the cursor is all over the place. Inspection of XQTCMD.FOR shows that label 3608 has been moved to suppress the prompt in manual mode. Was this a good idea? [Author's note: this was never fully cleaned up. Some cursor positioning was moved into XQTCMD to make it unnecessary to call DSPSHT for just moving around. There should be some checks in XQTCMD to see if display is turned off, but these don't exist at the moment. Maybe I will add 'em.] .le;DF often fails if the target cell is filled with a non-zero value. E.g_. DF#A1#[I4] where A1 currently contains floating 123.0, will apparently be ignored. The reason is that the I4 format is tried out on floating 123.0, and the ENCODE's ERR=statement aborts the DF command, since the bit pattern for 123.0 is some huge integer. Since the intention is merely to test the specified format, perhaps that test should be carried out on some constant (e.g_. 0) rather than the actual contents of the cell. [Author's note: the TEst command can be used to put a value of zero into a cell so this problem is overcome. TE A5=0. for example will zero the cell value, leaving the formula alone. An RF recalculation will clean this. The Fortran runtime system is rather ugly when this kind of checking is not done, and will quickly reduce your screen to an illegible mess. That is why I added the test for validity. the CV command to do Copy Values from a cell with a zero in it (or an unused cell) can also zero a range without changing the formulas.] .p0 In a similar vein, DT often seems to do nothing, the reason being that the value in the cell is not converted between floating and integer. .p0 The combination of the above causes some mystification. Suppose you set up a lot of cells in default floating-point, and then decide they should be integers. Any combination of DFs and DTs seems to either fail completely, or leave the cells displayed as 0.00 when they are shown (below the prompt) as having non-zero values. There seems to be no way to change constants between floating and integer without zeroing the cells are re-entering all the values. The foolproof method is to do the DFs and DTs before you populate the sheet, but that assumes you have thought about what you want to do first! .le;Some commands seem to work only on the cells below and to the right of the cursor. I found this documented in some obscure place after much head-scratching. It should be made clearer in the full manual where this applies. [Author's note: the full manual has always had this. It gives significant flexibility to be able to load or save or modify partial sheets using the cursor as a fencepost. As for the DFs and DTs, you can do them anytime, but use CV or TE to zero the cells first if they don't contain labels. If a cell contains 123.456 and you give it a display format of I5, however, don't be surprised if your next recalculation causes your spreadsheet screen to scroll off the display due to error messages from the Fortran runtime.] .le;Lots of new commands don't seem to have made the documentation yet, not even the AAAREADME release notes. .LE;Gold 9 (AKNA.CMD) appears to use the top line of the display as workspace. This is OK, as it seems to get restored at the end, EXCEPT when that is part of the area you were trying to fill, when these cells end up containing mysterious *XQTM commands. [Author's note: Gold 9 uses cell A1 for work space. However, remember that these are examples of how to program for some functions. If a user dislikes any of the keypad command files, he or she is invited to change them. I needed a function to fill an area with the formula in its' upper left corner, suitably relocated. Generally I have cell A1 used for a label anyhow.] .els