DATELET.DOC by Rick Charnes, San Francisco, Memorial Day weekend, 1988 Usage: Substitute your own address in all ZEX files, then: DATELET DATELET will begin a letter using the specified filename and word processor, inserting your address in the upper right corner followed immediately by the date and time. * * * I've been having the most superb fun imaginable with DateStamper in the last several months. I would VERY much urge all Z-System (as well as straight CP/M) users to install this marvelous operating environment on your system. Datestamping adds an entirely new and wondrous dimension to one's computing. I know -- neither did I think I would initially find much use for it. In fact I was rather making light of those who seemed to be so excited about it when it first started flooding the Z-System market. I don't run a business on my Morrow, I don't do my taxes on my Morrow, and I only do one thing that is really time-relevant: I keep a database for a local non-profit organization. But when I couldn't figure out which of the 3 backups of the database I had made was the most recent and therefore correct, I knew it was time to enter the brave new world of CP/M-compatible datestamping... CP/M-compatible datestamping is like Z-System generally; it grows on you. You find that things for which you initially had no use suddenly are offering new worlds of challenge, excitement, and -- oh, ok -- purpose. It feels quite different from MS-DOS datestamping. How? Well, in DOS everyone takes datestamping for granted. You'll have to search far and wide to find anyone who finds it particularly exciting. In our CP/M and Z-System worlds, however, since we've done without for so long it's all fresh and new and everything feels like a gift from the gods. In DOS, you have datestamping, and it's right there wedded to your DIR command, and lots of programs display the time for you, and it's no big deal and no one thinks twice about it. For us dinosaurs though, the thrill of discovery as you gradually add on datestamper support to more and more of your operations that had previously been barren as a leafless tree is an absolute delight. I think that at this stage in the game CP/M-and-compatible (that is, "CP/M and Z-System") datestamping is in many respects superior to that of MS-DOS. How dare I make such a brash statement? How dare I, indeed. Did you know that there is no way in DOS to keep track of a word-processed file's _original_ date of creation after being edited? It only knows the last modified date. Incredible! With our DateStamper we have a utility SAVSTAMP to do exactly that. For me, the joys of computing are the joys of discovery, learning and creativity. DateStamper has provided me with these many times over. Without datestamping one's computer operations are outside of history, existing in a timeless void. Put Plu*Perfect's DateStamper in your machine and watch it grow wings like an eagle. It is in this aquiline spirit that I offer DATELET, a combination ARUNZ alias/ZEX file that I whipped up as a result of a suggestion/question/phone conversation with Tony Parker. Tony, what an idea! * * * Jay Sage has been quietly turning ARUNZ into one of the most sophisticated extended command processors available for microcomputers today. The only thing of which I am aware that matches it is MS-DOS's Extended Batch Language. With version 09M ARUNZ is now provided with symbols for time and date if one is running DateStamper. Since it is unlikely, if not impossible, that a version of CP/M WordStar will ever support datestamping, DATELET attempts to perform one of these datestamping functions. It is a way of automatically dating your letters, putting your address in the upper right corner followed by today's date and time immediately below. You need simply to specify on the command line the word processor or editor you wish to use, along with the name of the file to be edited, and DATELET will load the wordprocessor/editor, open up your file, and write in the file your return address (or any text of your choice) along with the current date and time. The companion alias CONLET (CONtinue LETter) is for those long multi-entry letters written over a period of time, or any document in which you wish to keep a record of every editing. CONLET will (assuming WordStar-compatible commands) go to the bottom of the file, put a few blank lines, and write the current date and time. I should probably call it DATEDOC. You're of course free to rename CONLET, DATELET or any other alias. Those who have delved into the wondrous mysteries of ARUNZ know that rather than RE-naming one can simply and easily ADD multiple (alternate) names. Consult ARUNZ.HLP or Jay Sage's TCJ article for that... I am quite pleased with these alias and had a lot of fun writing them. They of course do nothing that one cannot do if one is running Plu*Perfect Systems' BackGrounder ii along with DateStamper. The former program provides two function-key-like keys that insert the time and date into any document. Rob Friefeld's NT42 does the same thing very nicely though you are limited to its very primitive editor. Like many of my aliases, DATELET has a slight flavor of hodgepodge. I say this without the slightest bit of aspersion upon myself but merely to draw attention to the fact that in the Z environment someone without assembly-or-other-language programming ability can, with a good knowledge of the "Z toolset" conceive and produce elegant, sophisticated and innovative "programs." And feel very proud at having done so. Obviously some of what DATELET does could probably be done much more "elegantly" with an assembly-language utility, but as I have said many times, for those like myself who are not "language" programmers ARUNZ and ZEX offer wonderful creative environments and a marvelous learning opportunity. You'll need to use the enclosed REGQ.COM. The aliases do a lot of setting of the ZCPR3 registers. This is a special version of REG.COM patched so that setting a register will not display anything to the screen even if the QUIET byte is OFF. Although I am leaning in that direction because of many applications I have that I like to keep clean, crisp and sparse, I have not yet configured my system to have the QUIET byte permanently on, so I have patched a number of my utilities of which REG.COM and RESOLVE.COM are two to permanently behave as they do when QUIET is ON. Furthermore, however, one thing that I have never liked about REG.COM is that even with the quite byte on, setting a register does display to the console a single digit: the new value of the register. I consider even this a distraction; hence, REGQ.COM for a completely clean display, utterly transparent to the user. The following section is an explanation of the alias and ZEX file, with some small compendium of tips that I have learned from the generous work of others that might be helpful for those wishing to write their own ARUNZ and ZEX scripts. * * * DATELET if ~nu $2;and ne $1 //;regq s2 $dm;go s3 $dd;go s4 $dc; /datelet2 $*;else;e ^js%>yntax: "$0 ^m^j;fi DL2 $zfi;zex datelet $1 $2 $rf03 $dy $rf04 $dn $da 'IF ~NU $2' and 'AND NE $1 //' simply check for the user using the wrong syntax and asking for help, respectively. I know that traditionally (or perhaps I should say "according to the Frank Gaude' alias-creation tradition") the syntax has been along the general lines of: if eq $1 //;or nu $1;echo [syntax message];else;[alias commands];fi but it seems this is backwards and wastes a good 2 or 3 nanoseconds for the normal-case scenario, that being when the user is _not_ requesting help or making an error in syntax. I think the [alias commands] should be first and the [syntax message] last, and that's how I have done it. Now for REGQ. I love using the ZCPR3 registers in my aliases. Does anyone else do this with any frequency? It's a wonderful use of the unique feature of Z-System's ability to carry messages back and forth among its utilities. I have an image of the registers as extraordinarily light and tiny, agile, ephemeral, darting beings -- dragonflies come closest to the image I have -- carrying messages back and forth for their larger, more ponderous hosts. The hosts come on stage, touch the dragonfly-messengers with their message, and exit. In a whir of beautiful lightness the messengers fly on wings of gossamer to their assigned destination, touch their new host, and themselves exit. In DATELET I use 3 registers. Why am I using registers? For one thing, we have to have some way of getting our ZEX file to print the name, rather than the number, of the month. With a great savings in code, I would imagine, Jay has the symbol '$dm' return the number, rather than name, of the month. For many purposes this suffices. For ours it does not, and we must find some way to produce the name from the number. I have utilized ZCPR3 register 2 and IF.COM's ability to test them for this purpose. (See the ZEX file for this). I originally was using 7, 8 and 9 but Paul Pomerleau is using these now with EASE v2.0, so we'll let EASE be the oldster on the block; I've switched to 2, 3 and 4. (FF.COM uses 1). Registers 3 and 4 are used in an interesting way that takes advantage of one of the new features that first appeared in ARUNZ v0.9L, the "floating decimal" expanded register symbol. I wasn't absolutely sure what this meant but through experimentation have found it to exactly suit my purpose here. Basically, the situation is as follows. The ARUNZ09M symbols '$dd' (the date of the month) and '$dc' (the hour) always will return a 2-digit number. This is fine when these in fact _are_ two digits, but what about when it is, for example, 1 in the morning of May 3? We don't want our letter to look like it was generated by a robot, as in: "May 03, 1988, 01:00 am." We want it to have the human feel: "May 3, 1988, 1:00 am". So we have to find some way of letting it remain two digits when appropriate but contract to one when _that_ is appropriate. Enter the "floating decimal" concept as implemented in the new '$rf' register symbol. It would be nice if we had the same concept with the time and date symbols themselves, but Jay certainly has to always concern himself with code size (not to mention time!). Besides, this way we get to experiment, create, and learn... So after we put the number of the month into register 2, we put the day into register 3 and the hour in 4. Note that we do this by re-running REGQ.COM with the GO command to save the extra time of re-loading it from disk. I might comment here that this is the second or third time in my alias-creation travels I have come across instances of where we _have_ a type-3 version of a utility that will run at 8000 hex (Bruce Morgen has given us REG11.CIM) --- ** but it is preferable to use the version that runs at 100h! ** (The GO command re-runs what is loaded at 100h. Of course, if you have REG in your RCP as I used to, you can simply quiet that using the techniques I described in my PLF10.LBR and you won't need REGQ at all.) Now with our 3 registers properly set we go to our second alias, DL2. Note that it is necessary to make a double-alias series out of this since the memory ($m) and register ($r) symbols in an alias ** only return the values present just _before_ the alias executes. ** (GOOD THING TO REMEMBER IN USING ARUNZ!!!) In any case, DL2 is simple. It simply runs ZEX and our companion script DATELET.ZEX using all the symbols we have created above as its parameters. The third and fifth parameters are the floating-decimal version of the day ('$rf03') and hour ($rf04') respectively about which we spoke previously. The year ($dy), hour ($dn) and AM/PM string ('$da') we send directly and need perform no 'floating-decimal-ization' since we always want them as two digits. ZEX DATELET $1 $2 $rf03 $dy $rf04 $dn $da | | | | | | | editor fn day year hour hour am/pm One more thing, though. Maybe I'm being overly purist about this, but I don't like seeing the time as '10:34 PM'; I like seeing it as '10:34 pm.' Maybe it's just the principle of the thing; I'm trying to overcome the way all command line parameters sent to ZEX come out as upper case. (I guess this is a feature/limitation of the CP/M-compatible operating systems; it's similar to how in our ECHO command we have to do special things to get things echoed in lower case whereas in DOS you don't.) When you look at the ZEX file you'll see what I mean. A few final comments about the aliases. I've assumed your terminal uses the standard ADM cursor positioning sequence, "ESC = X Y" and can clear the screen with CTL-Z. I've also enclosed in this library a version of RESOLVE.COM which is patched to not display its sign-on message even when the QUIET byte is OFF. My own feeling is that in _most_ applications of RESOLVE it is preferable that the user have no indication that it is running, hence the default should be NO DISPLAY. I originally included a command to turn the QUIET byte ON as part of this alias but I begin to feel that it's a waste of alias space and time. I would rather use a version of RESOLVE that _never_ displays its sign-on message. I'm thinking very seriously of changing my system environment to have the QUIET byte ON as the default, but I haven't yet done so and this is the remedy of choice for now. In any case, please replace your own copy of RESOLVE.COM with this one, or if you prefer to maintain a separate copy rename one or the other. Now for the ZEX file. The IF's, ELSE's and FI's are numerous and very carefully balanced here. The first thing I do is test $7, which is the string 'AM' or 'PM'. If we are returned 'AM' we stay in the first half of the file and ZEX sends the string "a.m." to our heading. The "ELSE" after the 'IF 2 12" marks the second or "p.m." half of the file. At first glance the file might seem overly long. One might think it shouldn't be necessary to have all those repetitions of one's address. You're right, it doesn't have to --- if you don't mind the name of the month appearing in the letter in all upper case letters. If you want the name of the month to be in mixed upper/lower case you need to allow ZEX to control it as I have done here. I'll explain in a minute. Given this limitation the problem here is that we have to somehow translate the _number_ of the month into the _name_ of the month, and the IF testing of the register that contains the appropriate number value is the best solution I could think of. You might think, "Well, why not at least just repeat the third line," as in: ^I^I^I^I^I^I^I^I1234 Main St. ^I^I^I^I^I^I^I^ILake Wobegon, MI 58585 ; if 2 1 ^I^I^I^I^I^I^I^IJanuary .... else if 2 2 ^I^I^I^I^I^I^I^IFebruary .... else if 2 3 ^I^I^I^I^I^I^I^IMarch .... Uh, uh. Look closely. Once you start having ZEX send out your address it's inside your editor and not at the Z command line. It can't be reading and responding to any IF's or ELSE's at this point. An 'IF' or 'ELSE' to ZEX right now would simply be a string of text like any other to be inserted into your file. But those who don't mind all upper case letters might find the alternate alias included here, DATELETR, (the terminal 'R' stands for RESOLVE since that utility is used in it) and its wonderfully simple associated ZEX file a very nice solution to the problem of a long and complex ZEX file. I think it's a rather innovative way of turning the _number_ into the _name_ of the month. The secret is its use of shell variables. Replace any SH.VAR file you may have in the last directory on the path on your own computer with the one in this library and you're all set. If you have shell variables in your present SH.VAR that you use and need, look at mine and see what I've done. Then add these 12 variables to your SH.VAR using SHDEFINE (arguably the least used of the classical Z utilities, save for brave souls such as Dreas Nielsen) and let 'er fly. To see the real key to this technique, look at the last parameter in the alias, %$rf02, and study, study, study. Works like a charm -- and it certainly does shorten the ZEX file... The longer file does use some of Jay's brilliant innovations in NZEX v1.0d. All text between the ^( and ^) is ignored if the flow state is false, which suits our purposes perfectly. The ^% symbol immediately preceding the $1 tells ZEX to go send its input into the application program mentioned on the same line, in this case our word processor. Lastly, the ^" symbol following the 'a.m.' or 'p.m.' string tells ZEX to allow user input, here the writing of our letter by the user. I had to use an interesting technique for handling flow control in DATELET.ZEX. I need to test for 12 possible conditions (12 months), yet Z's flow control only allows 8 'IF' levels. The problem is remedied by terminating the IF testing after 6 tests (the 'IF 2 6' block) and taking the IF level back to ONE, then resuming. Note, however, that I must put exactly six "FI"'s, and not a "ZIF" after this block, since I still need to keep one IF level active from the 'IF EQ $7 AM' test. I did some time tests on DATELET.ZEX vs. DATELETR.ZEX during May, measuring from the hit of the carriage return till the moment ZEX finished sending the date and time into the file. On my very slow and fragmented hard disk DATELET loaded in 22-23 seconds and DATELETR in 20. More noticeable was the difference in exiting time. After exiting LZED I was returned to the command line in 10-11 seconds with DATELET and 6 with DATELETR. Apparently the lack of the large number of flow control commands in the ZEX file _does_ significantly speed up operations, even considering the time spent for RESOLVE to load. And there is a wonderful elegance to the RESOLVE/%$rf02 shell variable/register technique. My hope is that this humble but elegant use of the shell variable file will inspire others to do more work with this neglected but fascinating area. By the way, if you like attractive displays I recommend making a couple of patches to ZEX.COM. In an alias such as DATELET I don't like to see ZEX's standard sign-on message "NZEX v1.0d ..." appear on my screen. It's too formal-looking. I prefer something like "Please stand by..." Go ahead and patch the sign-on message of your choice into ZEX.COM. The string starts at 01EC. Also, if you like as I do to have this string appear with terminal attributes turned on such as blink, reverse video, etc., you'll also have to change byte 0F2A from D2 to C3. Without this patch ZEX "translates" all control characters and escape sequences and they will appear verbatim/literally on the console, rather than being accepted as _commands_ by the terminal. With the patch they are accepted as commands. I'm not sure what untoward effects this patch may have (Jay might be able to tell us) but it's been working fine for me for a month or so. Thanks to George Borys for help in disassembling ZEX to find this byte. Lastly, despite all the nice changes Eric Meyer has made to VDE, it still doesn't run properly under ZEX. If you try to use any of these aliases ZEX has a hard time sending its input into VDE. After VDE loads it appears to be frozen and won't accept ZEX's input. Just keep hitting a key and one character from ZEX will appear for every keypress. As described at the beginning of this file, as a companion to DATELET(R) I have also provided CONLET and CONLETR (CONtinue LETter). They work similarly to DATELET and DATELETR, and CONLETR uses the same RESOLVE/register/shell variable technique as does DATELETR. These aliases may be used any time a date/time entry is desired at the beginning of a new editing to a text file. I very much hope people enjoy these aliases. Please give me a call at (415) 826-9448 if you have any comments. Thanks, Tony!