Forth Q and A
Volume Number: 1>replyPtr Issue Number: 6>replyPtr$ Column Tag: TECH NOTES>replyPtr@
FORTH Q&A>replyPtrS By Jörg Langowski>replyPtrk$EQ: How can I write text and numbers to a window and have automatic wrap->replyPtrw around?>replyPtr $PA: For one thing, Forth does not define the simple “.” or type words so as to>replyPtr Oprovide an automatic CR when the end of the window is reached. This makes sense in>replyPtr Fsome applications, such as printing out tables, when the window size is not known>replyPtr Sbeforehand. On the other hand, it is rather annoying if one wants to test a simple>replyPtr Edefinition to see half of the printout disappear off the right edge.>replyPtr $NYou might have noticed that the built-in Forth word, WORDS, does an automatic>replyPtr Uword wrap. So it almost looks like there is some hidden word in MacForth that tests for>replyPtr ^the end of the ‘screen’ and prints out a CR when it is reached. Lets look at the definition>replyPtr„ Wof WORDS, using the decompiler from an earlier issue of this journal. (I converted the>replyPtrÔ PBRANCHes to IFs etc. to make the code more readable). Please refer to figure 1.>fixBtnName: words>fixBtnName context @ ?dup>replyPtr if @ ?dup>replyPtr D if dup @ + ( stack now contains address of latest definition )>fixBtnName2< begin dup dup 1+ c@ swap c@ or while ( token <> 0 )>fixBtnName=F 2+ count 31 and 2dup 16 {2c7c} ( aha! hidden definition )>fixBtnNameH5 dup {2c58} ( another one ) type 2 spaces>replyPtr 2 + ( add name length, get next token )>fixBtnName^ repeat>replyPtr drop then>replyPtr then;>replyPtr Figure 1>replyPtr $PThe code is pretty sraightforward: The address of the CONTEXT vocabulary is put>fixBtnName Zon the stack and the offset to the LATEST definition added to it. Then, after making sure>fixBtnName [it is not at the end of the list (token = 0), WORDS gets the name string of the definition>replyPtr Tand, after some manipulations, types it. The manipulations are done by two of those>fixBtnName Sstrange tokens that have no name associated with them, {2C7C} and {2C58}. They are>replyPtr defined as follows:>fixBtnNameÈ: {2c7c} col @ over wmod 1+ ->fixBtnNameÙ5 dup {2c58} col @ if spaces else drop then ;>replyPtr
: {2c58} col @ +>replyPtr get.window +wbounds 6+ w@>replyPtr # get.window +wline.height @ 7->replyPtr+ w/ > if cr then ;>replyPtrC$MThe first one, {2C7C} tabs to the next integer multiple of n, where n is the>replyPtrO Tnumber on top of the stack, and wraps around if it would go beyond the limit of theapplication[ G window. The actual wraparound is done by {2C58}, which expects the number of>replyPtrg [characters to be output on top of the stack. It then compares the final cursor position to>replyPtrs G(right window edge)/(line height - 7), which is approximately the last column>replyPtr Uposition in the window. If the string would print beyond this last position, a carriage>replyPtr Sreturn is output first. The ‘approximately’, by the way, is the reason why WORDS>replyPtr Osometimes prints off the screen with non-standard text sizes. The remedy is to>replyPtr increase LINE.