TweetFollow Us on Twitter

Object Activities
Volume Number:4
Issue Number:7
Column Tag:Forth Forum

Objective Activities in Forth

By Jörg Langowski, MacTutor Editorial Board

Objects in Forth, International Resources & A Priority TaskScheduler

One of Forth’s great advantages is its extensibility. Since the Forth compiler is just made up from other Forth words, and the data structures into which each new word is compiled are very well documented and accessible to the user, you can very easily rewrite the compiler and thereby define your own language. (These comments are obvious to the seasoned Forth user; I’ve just repeated them to emphasize the difference to the more ‘canonical’ languages like Pascal or C).

With a language as flexible as Forth (very much like LISP in that aspect), it is no surprise that many have set out to create their own language on top of a Forth kernel. Famous examples are the object-oriented extensions ForthTalk and, of course, NEON. While ForthTalk (which has been covered by Paul Snively in MacTutor V3#2) seems to be alive and well, and still offered by Creative Solutions in their newsletter, NEON seems to have been all but abandoned by their creator, Kriya Systems. After the 2.0 update, more than a year ago, no more NEON news. And it was such an elegant implementation of object-oriented programming! Judged from bulletin board posts and letters I receive every now and then, many of you must be more than disappointed at the slow disappearance of NEON from the scene of Macintosh languages.

It is about a recent attempt to extend and -maybe- resurrect NEON, and about several other projects of object-oriented extensions to Mach2 Forth, that I wish to report this month. A lot of the information I am presenting comes from discussions and postings on the Mach2 roundtable on GEnie; therefore this column is, again, somewhat biased towards Mach2. MacForth users, please, read on and comment; a standard for an object oriented Forth would be appreciated by most of us.

Object Orientation in Forth

Why would one choose Forth to implement an object-oriented language? Besides the built-in extensibility of the Forth compiler, some aspects of object orientation are already contained in Forth. As a reminder, an object is a structure that contains not only data, but also procedures: methods, which can operate on the contents of the object or on other data. Example: an array of integer numbers which, given an index n, automatically returns the address of the nth element. The classical Forth definition of a ‘defining word’ for arrays with 32 bit-size elements is:

: ARRAY  CREATE ( # - ) 4 * ALLOT   
( reserves # cells in the dictionary )
DOES>  ( n <adr> - adr ) SWAP 4 * + ; 

The definition of an array of 100 long integer numbers would then be 100 ARRAY myArray, while 47 myArray puts the address of the 47th element of myArray on the stack. When the array is first defined, the CREATE part of the definition is executed, and space is reserved in the dictionary for the array’s contents. In object-oriented lingo, this would be called creation of an ‘instance’ myArray of the ‘class’ ARRAY. myArray’s ‘instance variables’ would correspond to the space reserved in the dictionary for the 100 32-bit numbers, and its one and only ‘method’ would be the DOES> part of the definition, which is invoked when the word myArray is executed.

If you now extend the definition ARRAY like this:

: ARRAY  CREATE 4 * ALLOT   
 DOES>  swap( n <adr> msg - adr ) 
 CASE
 1 OF ( addr: ) SWAP 4 * + ENDOF
 2 OF ( at: ) SWAP 4 * + @ ENDOF
 3 OF ( to: ) SWAP 4 * + ! ENDOF
; 

and define

: addr: 1 ;
: at: 2 ;
: to: 3 ;

47 addr: myArray would return the address of the 47th element, 47 at: myArray would return its value, and 3 47 to: myArray would store 3 in that cell.

myArray can therefore be viewed as an ‘object’ to which you can send ‘messages’ that determine the method used on its contents. myArray has three methods defined, addr:, at:, and to:, which have the method selectors 1, 2 and 3.

This example showed you one aspect of object-orientation, encapsulation of the data structures: you access the object’s data by an interface given by the messages that are sent to it. No other access would be possible (although in this case it is easy to circumvent that restriction, if one does it deliberately). The other aspect - not covered by the example - is inheritance of methods and data structures: we also need super- and subclasses, automatic message passing to classes further up in the hierarchy, method override, and so on.

Also, the example I gave resolves method references at run time (‘late binding’). This takes time, and if message and object are already defined at compile time, the compiler should resolve the reference so that the code generated for i at: myArray does not take any longer than a simple indexed fetch (like myArray i 4 * + @). This case is called ‘early binding’.

Let me now describe the three projects of object-oriented extensions for Mach2 that I’m aware of and their basic differences.

Object Oriented Extensions for Mach2

One attempt to create a NEON-like environment to Mach2 came from Aleksey Novicov, of Palo Alto Shipping, who developed a preliminary version of his object oriented system, called OPEX, whose syntax is very NEON-like. Following parts of Aleksey’s description of OPEX:

Brief Introduction to OPEX (v0.50):

An Object-oriented Programming Extension for MACH 2

Aleksey Novicov

OPEX contains all of the elements of an object-oriented programming environment. This includes the ability to define CLASSES, public OBJECTS of various classes, INSTANCE VARIABLES, and METHODS that are called by SELECTORS. Also, a class can be defined as having a SUPER CLASS,and thus inherit all of the data structures and methods of that super class. All of the method/object binding is currently static only (i.e., only compile-time binding, no run-time binding yet).

Two new vocabularies are present called OBJECTS and IVARS. In normal operation no special consideration need be given to these vocabularies. However, if any public objects are to accessed, then the OBJECTS vocabulary must always be present in the search order.

This a list of words that currently are available in OPEX :

:CLASS  ;CLASS   ;M:M
BYTES   <SUPER   OBJECT   MW!
MW@SEGMENTPERMANENTINITALL
(abs)

Also, the following MACH 2 words have been enhanced to work with OPEX:

 WORKSPACENEW-SEGMENTTURNKEY

There are many things that still need to be implemented. Some of the obvious include dynamic binding, support of variable length ARRAYs, and dynamic object allocation on the heap. Also, the special objects, SELF and SUPER, still need to be implemented.

More extensive error handling will be implemented to aid the programmer. Hopefully, OPEX will become more robust as time goes on without sacrificing speed. Whatever the case however, it will still run quite fast by virtue of the subroutine-threaded FORTH that it was built upon.

The current version does not yet support multi-tasking. However, any programs written with OPEX that use a single task will work fine.” --Aleksey Novicov

In the following, some examples of actual OPEX code which shows the NEON-like syntax:

:CLASS INT <SUPER Object
    2 BYTES    

    :M PUT:  MW!  ;M
    :M GET:  MW@  ;M
;CLASS 

\ Class definitions must start with :CLASS, end with 
\ ;CLASS, and have a SUPER class.  Methods definitions 
\ must begin with :M and end with ;M.  Methods names must 
\ always end with a colon. MW! and MW@ respectively 
\ store and fetch a 16-bit integer to and from the object and 
\ data area that is pointed to by the topmost value on the 
\ object stack.

:CLASS Point <SUPER Object
    INT x
    INT y

    :M PUT:  PUT: y PUT: x  ;M
    :M GET:  GET: x GET: y  ;M
;CLASS


\ Selector or methods names can be reused without worry.  
\ The method of the class of a particular object will always 
\ be correctly called.


:CLASS REGION <SUPER Object
 ( for use with QuickDraw regions )
    LongINT RgnHandle
    
    :M OPEN:   CALL NewRgn  RgnHandle !  
 CALL OpenRgn  ;M
    :M CLOSE:   RgnHandle @  CALL CloseRgn  ;M
    :M DRAW:   RgnHandle @  CALL FrameRgn  ;M
    :M PAINT:   RgnHandle @  CALL PaintRgn  ;M
    :M ERASE:   RgnHandle @  CALL EraseRgn  ;M
    :M INVERT:   RgnHandle @  CALL InvertRgn  ;M

    :M WITHIN: ( ^location -- flag )
        @  RgnHandle @  CALL PtInRgn  ;M
 
    :M MOVE:{ dh dv -- }
        RgnHandle @  dh dv CALL OfSetRgn  ;M
;CLASS

\ In all of the above methods “GET: RgnHandle” could’ve 
\ been used instead of “RgnHandle @” and 
\ “PUT: RgnHandle” could’ve been used instead of 
\ “RgnHandle !”.  The advantage to accessing instance 
\ variables in this manner is speed.  Also note that any 
\ method can have its own set of local variables (see 
\ MOVE: method).

POINT thisPt
POINT thatPt
INT x INT y

3 put:  x   4 put: y
get: x  get: y  put: thisPt ( set thisPt to some value )
get: thisPt swap put: thatPt  ( swap x and y for thatPt )

OPEX seems like one good step forward on the way to a NEON-like environment in Mach2, even though some things still need to be implemented. The discussion on OPEX has been pretty inactive for the last few months; I encourage all of you to contact the author or Palo Alto Shipping on the GEnie RoundTable to make this project advance.

The second OOPS-Forth that can be found on GEnie has been written by Jim Straus. His package is much less NEON-like. In his own words:

OOPS-Forth

Jim Straus

“It is based on an article by Dick Pountain (of Byte fame) that appeared in the Journal of Forth Applications and Research (volume 3, number 3). The source code given in the article was modified to work with Mach2. This project was started because I’ve had a long standing interest in object oriented programming and I wanted an object oriented language where I could see what was going on inside. I started from the article by Dick Pountain so that I could see how someone else had done it. I figured that it would be easier to start with a basic outline for the extensions. While implementing this package, I have come across many things that I would do differently. Some of these include removing distinction between classes and instances, allow for “early binding”, and making the code for looking up method selectors much more efficient. I hope to get around to doing a second version, but I thought that people might want to try out an object oriented language in the mean time.

Included in this package are the files: ‘Object Oriented Forth-Mach’, which contains the defining words to create new classes and the definition of the root class %OBJECT. ‘Graphic Objects’ contains some demonstration classes and instances of those classes. The graphical objects are points, pens (which understand some Quick Draw messages, such as PenPat and many Logo turtle-like messages, such as right: and go:).

In an object oriented language you send messages to objects. The general syntax in this implementation is: <arguments> object \ methodselector

[different from the NEON syntax, which would be <arguments> selector: object --JL]

where the <arguments> depend on the method selected and “\” is the word that sends the message to “object” telling it to look for the method associated with “methodselector” and to execute the code for that method. In this implementation both classes and instances of classes are objects and may be sent messages. Classes define both the methods to which the class will responds and also the methods to which instances of that class will respond. [This is also different from NEON, where classes aren’t objects. --JL]

New classes inherit methods from their superclass. For example, the class %polygon defines its own methods, but polygons also recognize the methods of their superclass %pen. Also note that the class %polygon can override the methods in %pen to either replace or enhance them. The top of this hierarchy of classes is always the class %OBJECT. %OBJECT is special in that it handles creating new instances of a class, handles unrecognized method selectors and provides a general framework for what methods every object understands.

An instance of a class contains a pointer to its class and contains the actual storage needed by the instance. This allows each instance to have different values in its variables. For example, the two polygons “fred” and “sam” each understand all of the same methods, but when each is asked to “\ draw” itself, they display as different shapes and at different locations. This is because their values are different.

An object leaves its address on the stack. The word “\” (redefined from the Mach2 line commentor) calculates a hash value for the word following it (the method selector) and sends that value to the object. The object looks up the method selector with a case statement and executes its code. Any values needed by the method should be left on the stack beforehand. For example, “fred \ draw” would cause fred to draw itself and “10 bic \ go:” would cause bic to move 10 steps in whatever direction it was headed.” --Jim Strauss

Here is an empty class definition:

CLASS:- classname
SUPERCLASS:- %OBJECT

 ENDCLASSVARS;

 CLASS METHODS:-
 ENDMETHODS;

 ENDINSTVARS;

 INSTANCE METHODS:-
 ENDMETHODS;
ENDCLASS;

A code fragment written in this dialect would look like:

CLASS:- %polygon
SUPERCLASS:- %pen

 ENDCLASSVARS;

 CLASS METHODS:-
 ENDMETHODS;
 
 INT INSTVAR SIDES ( number of sides in polygon )
 INT INSTVAR LENGTH
 ( the length of the sides of the polygon )
 ENDINSTVARS;

 INSTANCE METHODS:-
 ~ init :: super\ init 20 LENGTH ! 4 SIDES ! ;;
 ~ print:: SIDES @ . LENGTH @ .
    super\ print
    .” \ length: \ sides: “ ;;
 ~ =    :: self \ class OVER \ related?
    IF DUP super\ =
 OVER \ sides SIDES @ = AND
 SWAP \ length LENGTH @ = AND
    ELSE DROP 0 THEN ;;
 ~ draw :: 168 ( 360d) SIDES @ / ( find angle )
    SIDES @ 0 DO
 LENGTH @ super\ go: DROP
 DUP self \ right: DROP
    LOOP DROP self ;;
 ~ go:  :: self \ length: \ draw ;;
 ~ sides: :: SIDES ! self ;;
 ~ sides:: SIDES @ ;;
 ~ length::: LENGTH ! self ;;
 ~ length :: LENGTH @ ;;
 ~ times: :: 168 ( 360d) OVER /
        SWAP 0 DO
 self \ draw DROP
 DUP self \ right: DROP
        LOOP DROP self ;;
 ENDMETHODS;

ENDCLASS;
DECIMAL

call frontwindow call setport
100 100 %pen \ setcenter DROP 
 ( initialize the class %pen )
0 integer bic    ( create a variable for a new object )
%pen \ new bic to( an instance of class %pen )
0 integer fred   ( a variable for a new box )
%polygon \ new fred to  
 ( an instance of class %polygon )
0 integer sam
%polygon \ new sam to( create another polygon )
0 integer poly
%polygon \ new poly to  ( create another polygon )

   

This example - although incomplete - may give you an impression how OOPS Forth code looks like in Jim Straus’ system. I’ll leave it with that; for a complete description and the source code you should check on the Mach2 roundtable on GEnie.

The third Mach2-OOPS, written by Wayne Joerding from Pullman, WA, is similar to the one just described in that it uses class defining objects (CDOs) to create instances or subclasses of a class. Wayne has prepared, and almost finished, a big article on his implementation which we’ll hopefully print in one of the next issues. The implementation allows early and late binding. Again, a code fragment probably serves best to explain the syntax:

\ ====== Variable size Array Class =========
Integer Define.Child.Class
 :Instance
 I.Var  Max.Index
 \ max size of array, for error checking
 I.Var  Length   
 \ number of current elements in array,
 \ measured by cells
 I.Pntr Start    
 \ points to the start of array memory
 Hide
 :M Describe
 cr
  .” ---- Instance Information --------------”
 Name
 cr .” Max Length in cells  = “ 
 Max.Index @ 1+ .
 cr .” Cell size in bytes   = “ Int @ .
 Pr.Imeths
 ;
 :M Store ( x i -- ) 
 \ Store value x in array for index = i,
 \  first cell has index of zero
 Max.Index @ over < over 0 < or IF 
 .” index out of bounds” abort THEN 
 \ <-- error checking
 Int @ * Start + ! ;
 :M Retrieve ( i -- )
 \ Retrieve value of array for index = i.
 Max.Index @ over < over 0 < or IF 
 .” index out of bounds” abort THEN 
 \ <-- error checking
 Int @  * Start + @;
 ;Instance

 :Class
 :M Make.Instance ( n c -- ) ( <name> -IN- )
 \ Array instance of size n cells, cell size of c
 CREATE immediate
 ins.Key @  
 ,  \ store key to methods of parent class
 dup ,  \ save cell size in ‘Int’ variable
 over 1-  , \ make and save Max.Index 
 \ of array for error checking
 0 ,    \ init current Length to zero
 * ins.Size @ + allot
 DOES> dup @ Selector( ins.PFA -- ins.PFA key )    
 ;
 ;Class
Integer Name.Child.Class  Array  ( n c -- )

You notice the strategy: The class INTEGER is just another object to which we can send the message Define.Child.Class, followed by a subclass definition; right after that definition, we send the message Name.Child.Class, followed by the subclass name. A bit unusual for those used to the NEON syntax, but it works very well. Typical code would look like:

\ -- Array test ----
100 Array Make.Instance myArray
3 47 myArray Store
47 myArray  Retrieve . cr

\ -- test of String ----
20 String Make.Instance StrHello
: hel .” This is StrHello” ;
‘ hel 4 + StrHello Store
: chk.StrOb StrHello Print ;

I hope you are anxious to see the actual article, which should follow soon.

NEON - still breathing (?!)

NEON’s problem has been - I think - to have been on the market too early; there were just too may bugs left in the first releases. NEON 2.0 always behaved quite nicely in my hands; others said it still crashed very often. Anyway, looking back one could perhaps consider NEON 2.0 the first mature release, and it is a shame that there has been only silence from Kriya Systems for so long.

Extending Neon

Jim Savidge

Recently, an avid NEON user, Jim Savidge, has taken the NEON kernel and built its own extensions on top of it, making it into an even more powerful system than NEON itself. I will give you a quick description of his enhancements.

(Excerpt from GEnie)

Category 2, Topic 14

Message 47 Sat Jan 02, 1988

J.T.SAVIDGE at 23:41 CST

For those who are interested I have made some very interesting and powerful extensions to Neon that might have some use in a Mach 2 implementation. I am at the moment trying to patch Neon to work on a Mac II. Now that Neon is no longer on the public market and that it uses self-modifying code etc.., wish me luck. I rather have my extensions in use in an expanding market. (hint hint Mach users) Here is a simple list of my extensions:

1) Multiple-inheritance w/ no limit to number of super classes, User can pick which class a message will be sent to, and which particular class variable it is sent to, (of the classes many superclasses.)

2) Private methods. The message name will no longer be recognized after the class definition is close off.

3) Local Procedures. At the Forth level. This allows a local Forth word, (a Forth definition inside a Forth definition) to access the local variables.

4) A multi-window, single-stepping debugger, with multiple levels of break-pointing. (i.e. breakpoint to test a word, pop into debugger while testing, breakpoint test, continue last break, then even go back to where you were on the first breakpoint, etc..) Windows include: trace window, Tib window with In indicator, Stack window that shows decompiled meanings of Parameter, Return, and Methods stacks.

5) Unique-methods. Creating a single object with methods of its own.

6) Clone-Object and Copy-Object words.

7) Echo-to-disk

8) Saving off of Method and Ivar names for later Decompiling/Debugging.

9) Other “minor improvements”.

If anybody would like me to contribute to an object-extension to Mach 2 or in creating any new Forth/Object language *PLEASE* contact me.

James T. Savidge, Saturday, January 2, 1988.

Even for those not directly interesting in object-oriented programming, the definitions for local procedures and the multi-window debugger should be very worthwhile enhancements. For the object-oriented part, the multiple inheritance - allowing a new subclass to have several superclasses - is, of course, especially interesting.

A message to an object that has several superclasses, and which cannot be handles by the object itself, is first passed to the superclass which is defined first, if the superclass cannot handle it, it is passed further upward in the hierarchy, until the class OBJECT. If the method still can’t be found, the message is passed to the superclass which was defined second, and so on. An example of a class definition in Jim Savidge’s enhanced NEON would look like:

:Class Qqq <Super Rrr
           <Super Sss
     Var Qqqvar

    :M Aaa: .” Qqq Message “ ;M

;Class

Qqq myObj

The message Aaa: can be handled directly by objects of class Qqq, while other messages are first passed to class Rrr, then to Sss. One more specialty is class picking; if you send Sss.Xxx: myObj, the message Xxx: will be passed directly to the superclass Sss.

Private methods which are only accessible from within the class definition can be defined through the following construct:

:CLASS FIRST <SUPER OBJECT

    :PRIVATE
        :M AAA: .” AAA “ ;M
        :M BBB: .” BBB “ ;M
    ;PRIVATE

    :M CCC: .” CCC “ aaa: self ;M 
    :M DDD: .” DDD “ bbb: self ;M 

;CLASS

FIRST  ONE

In this case, sending ccc: one would print ‘CCC AAA’, while aaa: one would result in an error message. A new level of information hiding which can be very useful.

I have tested all of the above, and more, on my MacII, and to my great surprise (I hadn’t tested NEON on the MacII yet) discovered that NEON 2.0 still runs on a MacII, even under Multifinder! It shouldn’t run, though, since my cache was turned on, and trap calls in NEON use self-modifying code (you know, the old trick where you drop the trap code just in front of your feet and step on it) so double surprise. Triple surprise, when Jim told me on the network that HIS MacII wouldn’t run NEON 2.0. Subtle differences in system configuration probably make a big difference here.

The 68020 instruction cache will allow to use self-modifying code, if an address has been executed beforehand that is equal to (modified address modulo cache length), since then the instruction that was modified will always be fetched from memory. If one can make sure that the self-modifying code has stepped through at least 64 32-bit instructions in linear sequence before encountering the modified address, this might work. I have traced the NEON code for signs of such a behavior, but no luck. Somehow it works on my MacII and crashes on Jim’s strange and mysterious things going on here.

I bet you’ll all like to see a full article on the NEON extensions. As Jim told me, that, or a commercial package, is under consideration, a lot depends on the availability of a more recent NEON release, or even the complete NEON source. The future of NEON should definitely not end at this point, and any support from outside can only help the issue.

Feedback Dept. Europe

International Conversion

Peter Freund

Sweden

Here’s a letter from a reader in Sweden (again those international keyboards and characters ):

“I am one of those non-programming, yet admiring users, that enjoy MacTutor ‘cause there is something worth reading there.

I work for Software Plus, distributor in Sweden for several Macintosh and MS-DOS products. We represent products like TOPS, WriteNow, QuarkXPress, SuperPaint, Timbuktu, MacLink and companies like General Computer, SuperMac, Symantec (Living Videotext, Think Technologies), Farallon. I am the one that answers and handles communication products, but also companies “knowledge-base”. I also do some translation of programs and manuals.

I know that if an article (like mine) would be published in MacTutor, it would help spreading Macintosh on the international basis and also help our company (I would have less annoying work.) [Well, there you go! Take your vacation now --JL]

Take any text from the following letter, in any form, or please write any kind of program that shows how to use the “International Utility Package” (it ought to be quite easy) - so my and all non-english-spoken peoples’ job will be easier.

I also keep up a BBS (called Fenix) on a free basis when I am not working (using RedRyder Host). The number is +46 8 308356. (Either I or Fenix answers the phone.) My address is:

Software Plus
Att: Peter Freund
Box 2286
600 02 Norrköping
+46 11 181270
(leave a msg if I am not available)
+46 8 308356
(my usual number ((I work at home with translation of MORE right now)))

I also send some fun [a HyperCard stack for translating] I have created myself. Enjoy!

This is an article I have been wanting to write for a long time: Today 1988-10-05 (US format: 5/10/88...)

How to handle international characters

In the old days, before 8-bit-ASCII, different countries did their own modification to computers, so the national characters would work. In Sweden there even became two versions of 7-bit ASCII, “Swedish usual version” and “Swedish name version”.

For example the old Apple II was sold in Sweden with the following character set:

!”#$%&’()*+,-./ 0 9 : ; < = > ? @ A Y Z Ä Ö Å ^ _ ‘ a y z ä ö å ~

The ROM was specially modified for Sweden. The keyboard was also modified, in a similar way as a the swedish keyboard nowadays on a Macintosh.

Then came the Macintosh, with RAM-based fonts and complete 8-bit ASCII. Most of the european (all(?) west-european) characters can now be handled in a general way. This means that all well-written programs can be used internationally without modification.

Well, the problems are small compared to our friends in Norway and the IBM PC. When IBM designed their own version of 8-bit-ASCII, they “forgot” the norwegian/danish character Ø. (An error even Apple did with their early version of Courier in Apple LaserWriter ). This means that all ROMs in Norway/Denmark has to be specially made for any MS-DOS machine, and the two characters ¢ and ¥ is replaced by ø and Ø.

There exist more versions of 8-bit-ASCII (Digital Decmulti, Hewlett Packard Roman 8). PostScript use special names for characters. Now let us first look at Macintosh and IBM PC!

When translating between a Macintosh and a IBM PC, it is difficult to only use TOPS or Dynafile for text files. There has to be an international(!) version of MacLink for handling the international characters correctly. With Apple File Exchange for conversion between Apple II and Macintosh I probably obtain the usual []\ instead of ÅÄÖ.

For a very long time there was no program that correctly could use all 256 characters when communicating. Usually the program skipped everything above ASCII 127. Most program have an option nowadays (like Red Ryder 10.3) to turn masking of high bits off.

There is two programs on the Macintosh that handle communication with swedish characters correctly: MacTerminal (swedish version) and inTalk. The user can easily select if swedish (swedish 7-bit-ASCII) is to be used or not. In MacTerminal it is also possible to select if incoming characters, outgoing characters or both should be converted, and even both swedish standards are available.

How to communicate in Swedish?

I guess they use some kind of conversion table. If a Macintosh is to be used as a terminal to a mini in Sweden, there are two conversion tables necessary. Here is the scheme: First I press the swedish character Ä on my Macintosh. The Mac communication program checks if this character is anything that is used for terminal emulation. If not, we convert this character, using conversion table one, into a [. Then we send the character over.

When on the other hand the mini sends a character, we first check if it has anything to do with terminal emulation. Thereafter we convert the characters that is supposed to be sent to screen, using conversion table two.

When MacTerminal, or InTalk implemented the swedish character set, they did not let the user change the conversion tables. This means that if I want to communicate with a IBM PC and send text files over, I must use some special program again!

Does it really have to be that difficult? In MS-DOS-world there are several programs (Enable, ProComm, plus others), where it is easy to modify a conversion table, with all characters, any way I like. There even exists a TSR (Terminate and Stay Resident)-program (like an INIT) that patches the serial routines for Swedish, so the conversion almost always works.

It ought not to be too difficult to write a cdev that would alter the serial routines, in a similar way and that could be configurable/turned on/off through the Control Panel.

[Such a routine might actually be very useful in a number of circumstances. I can remember the case of Versaterm Pro v.2.0 not recognizing the new ISO Keyboard correctly (the one with the small return key). In that case, you wouldn’t be able to use the arrow keys anymore to walk across a VT100 screen. This problem has been solved in never versions of Versaterm, but for the meantime it would have been extremely useful to have a routine available that passes serial in/output through a conversion table like you suggested. If I can figure out how to do such a filter in a way that would satisfy the User Interface Thought Police, I might write a column on it].

To all hackers:

Yet what really would improve things would be if the manufacturers would think a little more internationally. (In Inside Mac there is an “International Utility Package” worth looking at!)

Now, let us look at some popular programs today (I guess most of you know them):

Very Good:

4th Dimension - sorts well, configurable, works even with chinese!

MacTerminal (swedish version).

QUED - sorts and works correctly.

MORE - sorts correctly, handles all characters/ date functions with class. But even the sun has its spots, I cannot use the name “Örjan” as registration name, because it starts with Ö.

Good(?):

WriteNow - can handle foreign characters, but the spelling-checker cannot suggest any foreign characters, and also cannot see the difference between upper case and lower case with international characters.

DiskTop - has a funny bug. Difficult to find by date, because DiskTop suggests international date format, but can only accept US-dates for input. (DiskTop 3.0.2)

Bad (most “famous” programs work pretty well nowadays):

FileMaker Plus - cannot sort correctly. For a DB-program, this is bad. (I think MS File, Reflex and Helix had/has(?) the same problem.)

Old MacPascal - not possible to write international characters at all (above 80 hex).

SuperPaint - cannot print on whole “A4 Letter size” (8 1/4" x 11 2/3").

RedRyderHost - uses a font that does not even contain ÅÄÖ.

A lot of programs use Command/] and Command/[ and other special characters for fast menu selection, that doesn’t work on international Systems.

Finally a suggestion to those “desktop publishing program”-makers that always seems to hunt for good, new features: “Overlay characters”!

Kerning is a modern thing nowadays. With kerning it is possible to combine two characters into one. In many languages it is very usual (as usual as an “e” in english) to combine normal letters (acenorsz) with characters like ´ ~^`´¨. [I recently found out to my surprise, when trying to type the address on a letter to Czechoslovakia, that Apple left out a c with an inverted circumflex, as shown below created in MacDraw, from their fonts. In fact, that diacritical mark does not seem to exist].

The problem with kerning in desktop publishing programs today is that a value has to be specified. Yet I in most (all?) cases want the top character to be centered above the lower one. I can, with some DTP-programs, put two characters in the same place with kerning, but when size or font changes, the position of the top character goes wrong..”

--Peter Freund

[Thank you, Peter, for these very interesting remarks on international compatibility issues, a specter that has haunted the Macintosh scene ever since this machine was introduced. The fact that changing keyboard layouts ‘on the fly’ became possible only with System 4.1 has always been embarrassing.

Note to our readers: Peter’s letter was accompanied by a file which contained the keyboard layout resources (KCHR) for over ten different countries. This file is included on this month’s source code disk for anybody who needs it. -JL]

A Priority Based Task Scheduler

Clive Maynard,

Western Australia

This contribution was sent to us from an Australian Macintosh user and Mach2 programmer. It implements a priority-based scheduling system for Mach2 tasks.

“Dear Jörg,

I have read your column in MacTutor for quite a time with considerable interest and have found it very useful.

I have enclosed on disk something which may be of interest to you for an article in MacTutor.

The software provides a demonstration priority based scheduler for Mach2.

The basic round robin is not removed for the Mach2 task and Editor together with a background scheduling task. Additional tasks are added in such a way that they put themselves to sleep on completion through the execution of a word SwitchTask and return control to the scheduler. The scheduler determines from the priorities of available tasks which should be woken next, puts itself to sleep and wakes up the correct task.

The result is that the minimum number of tasks are in the round robin when the normal Mach2 pause occurs.

Variations which could improve speed include coding the scheduling task in assembler but this was developed for student study of operating system functions not high performance.

Priorities may be changed through a Priority Terminal task window in the range 0 to 100. 0 corresponds to task suspension until the priority is raised back to a positive value. The initial default priority is 10 for each task.

[As you can see from the code, the scheduler creates a task table for a maximum of ten tasks. For each task, its current level, the priority value and its address are maintained in this table. The level is initialized to zero. In its main loop, the task scheduler decrements the level of each task by its priority value. Each time the decrement passes through zero, the task is woken up for one round of execution and the level reset to 100. --JL]

The three additional tasks run in the demonstration provide a simple quickdraw output. The tasks can have their priorities varied and easily show the effects of the priority allocation.

The only other features which may be of interest are:

1. The creation of a new word LVALLOT which allows for the creation of local arrays in words with local parameter and variable facilities.

2. #IN which is an intrinsic word in UR/FORTH for the IBM/PC is created here using LVALLOT and the SwitchTask function to prevent the suspension of the other tasks when new priority values are being entered.

Clive Maynard,

Wave=onic Associates

199 Watts Road,

Wilson 6107

Western Australia”

[One further remark is that one should minimize the use of PAUSE in this task-switching environment, and use SwitchTask instead to make the scheduling more effective. For this purpose, the word PTExpect redefines EXPECT to contain a SwitchTask. There are PAUSEs left (in ?TERMINAL and KEY), but this can’t be avoided.

The illustration shows the nice graphical output of Clive’s demo. --JL]

Fig. 2 Mach2 task scheduler output
(on JL’s usual crowded Multifinder desktop)

The Mach2 task scheduler

.( Priority based multitasking on the Macintosh ) cr
( Original concept: D.Bryant, G.Caunt, G.Else 1987 )
( Modifications and Generalisation: )
( C.A.Maynard 1988 Wave=onic Associates)
( Version 1.1 060488 )
Decimal
( -------------------------------------------------------- )
( Task and window configurations for the necessary tasks )
( -------------------------------------------------------- )
400 1000 background schedulertask
400 1000 terminal prioritytask

new.window PriorityWindow
“ PRIORITIES” PriorityWindow Title ( create priority window )
40 250 110 500 PriorityWindow Bounds
Document Visible NoCloseBox GrowBox PriorityWindow Items
PriorityWindow Add
( -------------------------------------------------------- )
( DEMO Tasks and windows )
( -------------------------------------------------------- )
400 1000 terminal task1
400 1000 terminal task2
400 1000 terminal task3

new.window Task1Window
“ TASK 1” Task1Window Title ( create the TASK 1 window )
140 20 310 180 Task1Window Bounds
Document Visible NoCloseBox NoGrowBox Task1Window Items
Task1Window Add

new.window Task2Window
“ TASK 2” Task2Window Title ( create the TASK 2 window )
140 180 310 340 Task2Window Bounds
Document Visible NoCloseBox NoGrowBox Task2Window Items
Task2Window Add

new.window Task3Window
“ TASK 3” Task3Window Title ( create the TASK 3 window )
140 340 310 500 Task3Window Bounds
Document Visible NoCloseBox NoGrowBox Task3Window Items
Task3Window Add
( -------------------------------------------------------- )
( USER Variable definitions )
( -------------------------------------------------------- )
72 user TaskWindow
220 user rleft
224 user rright
228 user rtop
232 user rbot
236 user diff 
 ( create rectangle coords as user variables for each task )
240 user angle
244 user rectangle ( space for 8 bytes needed. Next slot 252)
( -------------------------------------------------------- )
( Scheduling Task Definitions )
( -------------------------------------------------------- )
VARIABLE LevelAddr 
 ( Global temporary storage for the scheduler )
VARIABLE NTASKS  ( Number of runnable tasks  MAX 10)
0 NTASKS !  ( Initialise to zero )
VARIABLE PTASKS 120 VALLOT 
 ( Storage for Level, Priority and Task Address )
: Wakeup ( a1 - )
( Wakeup gets the next task running given the status address )
sleep status W!
wake swap W! pause ;

: SwitchTask 
( Call the scheduler to see who’s next )
sleep status W!
wake status task-> schedulertask W!
pause ;

: SCHED 
( Define a general task scheduling process )
activate
begin 
NTasks @ dup 0> if ( only execute defined tasks )
0 DO
 I 12 * PTasks + dup LevelAddr ! @ 
 ( Get the address and current level )
 LevelAddr @ 4 + @ ( Get priority setting )
 + dup LevelAddr @ ! ( Save new level )
 100 - dup 0> if ( Modify level if necessary )
 LevelAddr @ !
 LevelAddr @ 8 + @ Wakeup
 else
 drop
 then
LOOP
else drop then pause
again ;
( ------------------------------------------------------ )
cr
.( Clive Maynard’s Forth Environment extract ) cr
.( C.A.Maynard 020488 ) cr

also assembler

code LVALLOT ( n - addr )
( Set up a local buffer. )
( Only callable from a word with local variables )
( UNLK will clean up the stack. )
( USER beware of buffer overflow!!! )
 MOVE.L (A6)+,D0 ( GET SIZE IN BYTES )
 MOVEA.L(A7)+,A0 ( GET RETURN INFO )
 SUBA.L D0,A7    ( NEW SP )
 MOVE.L A7,-(A6) 
 ( COPY ADDRESS TO PARAMETER STACK )
 JMP  (A0)
end-code

-1 CONSTANT TRUE
0 CONSTANT FALSE

: #terminator? ( char - f ) 
( check for the terminator of a number: space or CR )
case
13 of true swap endof
32 of true swap endof
false swap
endcase ;

: PTexpect { buffad nchars | buffadd countup - }
( Fills a buffer but includes Priority Task switching )
buffad 1 + -> buffadd 0 -> countup
nchars 0 do
 begin 
 SwitchTask 
 ?terminal until 
 key dup emit dup buffadd C! 1 +> buffadd 1 +> countup
 #terminator? if leave then 
loop 
countup buffad c! ;

: #IN { | buffaddr - number }
( PC/FORTH intrinsic function!! )
( Collect into a 10 byte buffer and return a number input )
10 lvallot ( set up a local buffer very carefully )
 -> buffaddr
buffaddr 10 PTexpect
buffaddr number? drop ;
( -------------------------------------------------------- )
( A new task building word for Priority Tasks )
( -------------------------------------------------------- )
: PBUILD { TaskAddr | LevelAdr - }
( Initialise conditions for new tasks )
NTasks 10 = abort” Task Priority Table Full. New entry denied”
NTasks @ 12 * PTasks +    ( Get offset into table )
dup -> LevelAdr 0 swap !  ( Set Level to zero )
10 LevelAdr 4 + !  ( Set Priority to default of 10 )
TaskAddr BUILD   ( Now do an ordinary task build )
TaskAddr @ LevelAdr 8 + ! ( Save Status address )
NTasks @ 1+ NTasks ! ( Increase task count )
;
( ------------------------------------------------------ )
( The Priority Task Definition )
( ------------------------------------------------------ )
: getbuff { | taskno priority - }
( priority reallocation routine)
#in dup .” Task “ . -> taskno cr
taskno NTasks @ < taskno 0> and if 
#in dup 0< if drop 0 then dup .” Priority “ . -> priority 
 ( New priority determined )
 priority 101 < IF
 priority dup 0= if 
 cr .” Zero or negative priority halts the task” cr
  then 
 taskno 12 * 4 + PTasks + ! ( Get to storage location )
 ELSE cr .” Priority out of range. No change” cr THEN
else cr .” Task number out of range. No change” cr then ;

: setpriority ( priority allocation task)
activate
begin
taskwindow @ call SetPort
.” Enter the task number followed by” cr .” its desired priority” cr
.” Priorities can be from 0 to 100" cr
 ?terminal if
 getbuff cr then
 SwitchTask 
again ;
( ------------------------------------------------------ )
( The other tasks )
( ------------------------------------------------------ )
: DISKS 
activate
 ( Initialise variables )
-7 diff ! 0 angle !
10 rleft W! 20 rtop W!
150 rright W! 160 rbot W! 
( Loop through graphic changes in superb animation )
begin
 rectangle rleft W@ rtop W@ rright W@ rbot W@ call SetRect
 begin
 359 angle @ - 0>
 while
 taskwindow @ call SetPort
 angle @ 10 + angle !
 rectangle angle @ 10 call InvertArc
 SwitchTask
 repeat
 taskwindow @ call SetPort
 rright W@ diff @ + rright W!
 rbot W@ diff @ + rbot W!
 rright W@ rleft W@ - 5 < if
 7 diff ! then
 rright W@ rleft W@ - 140 > if
 rectangle 0 360 call EraseRect -7 diff ! then
 0 angle !
 SwitchTask ( Get back to the scheduler )
again ;
( -------------------------------------------------------- )
( Initiate the necessary tasking operations )
( -------------------------------------------------------- )
schedulertask build ( slot scheduler into round robin loop )
schedulertask sched
prioritywindow prioritytask Pbuild
prioritytask setpriority
( -------------------------------------------------------- )
.( Define task insertion words to show adding tasks to priority system 
) cr
.( Shrink Mach 2 window to top left corner ) cr
.( Execute  task words: atask, btask and ctask after loading the file 
) cr
.( Change priority through the priority task window ) cr
( -------------------------------------------------------- )
: Atask task1window task1 Pbuild
task1 disks ;

: Btask task2window task2 Pbuild
task2 disks ;

: Ctask task3window task3 Pbuild
task3 disks ;
 
AAPL
$97.67
Apple Inc.
+1.41
MSFT
$43.63
Microsoft Corpora
+0.89
GOOG
$511.17
Google Inc.
-13.34

MacTech Search:
Community Search:

Software Updates via MacUpdate

MenuMeters 1.8 - CPU, memory, disk, and...
MenuMeters is a set of CPU, memory, disk, and network monitoring tools for Mac OS X. Although there are numerous other programs which do the same thing, none had quite the feature set I was looking... Read more
Coda 2.5 - One-window Web development su...
Coda is a powerful Web editor that puts everything in one place. An editor. Terminal. CSS. Files. With Coda 2, we went beyond expectations. With loads of new, much-requested features, a few... Read more
Arq 4.6.1 - Online backup to Google Driv...
Arq is super-easy online backup for the Mac. Back up to your own Google Drive storage (15GB free storage), your own Amazon Glacier ($.01/GB per month storage) or S3, or any SFTP server. Arq backs up... Read more
Airfoil 4.8.10 - Send audio from any app...
Airfoil allows you to send any audio to AirPort Express units, Apple TVs, and even other Macs and PCs, all in sync! It's your audio - everywhere. With Airfoil you can take audio from any... Read more
Apple iMovie 10.0.6 - Edit personal vide...
With an all-new design, Apple iMovie lets you enjoy your videos like never before. Browse your clips more easily, instantly share your favorite moments, and create beautiful HD movies and Hollywood-... Read more
OnyX 2.8.8 - Maintenance and optimizatio...
OnyX is a multifunctional utility for OS X. It allows you to verify the startup disk and the structure of its System files, to run miscellaneous tasks of system maintenance, to configure the hidden... Read more
Parallels Desktop 10.1 - Run Windows app...
Parallels Desktop is simply the world's bestselling, top-rated, and most trusted solution for running Windows applications on your Mac. With Parallels Desktop for Mac, you can seamlessly run both... Read more
Apple Keynote 6.5 - Apple's present...
Apple Keynote makes it simple to create and deliver beautiful presentations. Powerful tools and dazzling effects bring your ideas to life. You can work seamlessly between Mac and iOS devices. And... Read more
OmniPlan 2.3.7 - Robust project manageme...
With OmniPlan, you can create logical, manageable project plans with Gantt charts, schedules, summaries, milestones, and critical paths. Break down the tasks needed to make your project a success,... Read more
Flavours 1.1.16 - Create and apply theme...
Flavours is a Mac application that allow users to create, apply and share beautifully designed themes. Classy Give your Mac a gorgeous new look by applying delicious themes! Easy Unleash your... Read more

Latest Forum Discussions

See All

My Very Hungry Caterpillar (Education)
My Very Hungry Caterpillar 1.0.0 Device: iOS Universal Category: Education Price: $3.99, Version: 1.0.0 (iTunes) Description: Care for your very own Very Hungry Caterpillar! My Very Hungry Caterpillar will captivate you as he crawls... | Read more »
Dungeon Dick (Games)
Dungeon Dick 1.1 Device: iOS Universal Category: Games Price: $.99, Version: 1.1 (iTunes) Description: Dungeon Dick is a fantasy adventure where you must discover the wicked plot to destroy the lands . 'Fling' at your foes and land... | Read more »
Here’s How the Apple Watch Could Transfo...
With the Apple Watch’s generic release date of, “early 2015” hovering on the horizon, it’s only a matter of time before gamers begin to ask “What’s in it for us?” The obvious choice would be to place entire games directly on the face of the watch,... | Read more »
Republique Episode 3: Ones & Zeroes...
Republique Episode 3: Ones & Zeroes is Available Now Posted by Rob Rich on October 17th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Loot Raiders Review
Loot Raiders Review By Campbell Bird on October 17th, 2014 Our Rating: :: PRESS BUTTON, GET LOOTUniversal App - Designed for iPhone and iPad This menu-based loot game is suitable to compel those with pretty extreme loot lust.   | Read more »
Angry Birds are Crashing Puzzle & Dr...
Angry Birds are Crashing Puzzle & Dragons Next Week Posted by Rob Rich on October 17th, 2014 [ permalink ] Next week, Puzzle & Dragons is getting a little angry. Because, you know, Angry Birds. It’s a… a pun. I thought… never mind. | Read more »
Incandescence Review
Incandescence Review By Andrew Fisher on October 17th, 2014 Our Rating: :: ALL TAPPED OUTUniversal App - Designed for iPhone and iPad Incandescence promises intense tapping action, but isn’t particularly fun.   | Read more »
Lion Pig (Games)
Lion Pig 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: "Leaving aside the biology of how a pig and a lion might meet, fall in love, and create this curious cross-breed, Lion Pig is a... | Read more »
Zero Lives (Games)
Zero Lives 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Zero Lives is a puzzle game. Simple and elegant at its core but deep and captivating the more you play. Each puzzle will challenge... | Read more »
#SUPERHYPER (Games)
#SUPERHYPER 001 Device: iOS Universal Category: Games Price: $.99, Version: 001 (iTunes) Description: "This is a game that fans of challenging minimalist arcade games, not to mention pixel art, should keep an eye on" - Touch Arcade "... | Read more »

Price Scanner via MacPrices.net

Apple Pay Available to Millions of Visa Cardh...
Visa Inc. brings secure, convenient payments to iPad Air 2 and iPad mini 3as well as iPhone 6 and 6 Plus. Starting October 20th, eligible Visa cardholders in the U.S. will be able to use Apple Pay,... Read more
Textkraft Pocket – the missing TextEdit for i...
infovole GmbH has announced the release and immediate availability of Textkraft Pocket 1.0, a professional text editor and note taking app for Apple’s iPhone. In March 2014 rumors were all about... Read more
C Spire to offer iPad Air 2 and iPad mini 3,...
C Spire on Friday announced that it will offer iPad Air 2 and iPad mini 3, both with Wi-Fi + Cellular, on its 4G+ LTE network in the coming weeks. C Spire will offer the new iPads with a range of... Read more
Belkin Announces Full Line of Keyboards and C...
Belkin International has unveiled a new lineup of keyboard cases and accessories for Apple’s newest iPads, featuring three QODE keyboards and a collection of thin, lightweight folios for both the... Read more
Verizon offers new iPad Air 2 preorders for $...
Verizon Wireless is accepting preorders for the new iPad Air 2, cellular models, for $100 off MSRP with a 2-year service agreement: - 16GB iPad Air 2 WiFi + Cellular: $529.99 - 64GB iPad Air 2 WiFi... Read more
Price drops on refurbished Mac minis, now ava...
The Apple Store has dropped prices on Apple Certified Refurbished previous-generation Mac minis, with models now available starting at $419. Apple’s one-year warranty is included with each mini, and... Read more
Apple refurbished 2014 MacBook Airs available...
The Apple Store has Apple Certified Refurbished 2014 MacBook Airs available for up to $180 off the cost of new models. An Apple one-year warranty is included with each MacBook, and shipping is free.... Read more
Refurbished 2013 MacBook Pros available for u...
The Apple Store has Apple Certified Refurbished 13″ and 15″ MacBook Pros available starting at $929. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz MacBook Pros (4GB RAM/... Read more
WaterField Designs Unveils Outback iPad Slip...
Fresh on the heels of Apple’s announcement Thursday, WaterField Designs unveils its new Outback Slip Case for the iPad Air 2 and iPad mini 3 — a custom-fitted case for the just-announced Apple iPads... Read more
Apple Introduces iPad Air 2 & iPad mini 3...
Apple on Thursday introduced iPad Air 2, slimmed down again to just 6.1 mm, and weighing less than a pound. iPad Air 2 also features an improved Retina display claimed to deliver enhanced contrast... Read more

Jobs Board

Position Opening at *Apple* - Apple (United...
**Job Summary** At the Apple Store, you connect business professionals and entrepreneurs with the tools they need in order to put Apple solutions to work in their Read more
Position Opening at *Apple* - Apple (United...
**Job Summary** The Apple Store is a retail environment like no other - uniquely focused on delivering amazing customer experiences. As an Expert, you introduce people Read more
Position Opening at *Apple* - Apple (United...
**Job Summary** As businesses discover the power of Apple computers and mobile devices, it's your job - as a Solutions Engineer - to show them how to introduce these Read more
Position Opening at *Apple* - Apple (United...
…Summary** As a Specialist, you help create the energy and excitement around Apple products, providing the right solutions and getting products into customers' hands. You Read more
Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.