Path: utzoo!attcan!uunet!husc6!mailrus!uwmcsd1!ig!agate!garnet.berkeley.edu!elcond From: elcond@garnet.berkeley.edu (Gregory Dow) Newsgroups: comp.sys.mac.programmer Subject: The Crunched Shell (long) Keywords: Object-oriented programming Message-ID: <12362@agate.BERKELEY.EDU> Date: 21 Jul 88 07:12:57 GMT References: <2328@pt.cs.cmu.edu> Sender: usenet@agate.BERKELEY.EDU Organization: University of California, Berkeley Lines: 138 Given the number of inquiries I have received about "The Cruched Shell", I believe that a Net posting is appropriate. I appreciate all the offers to help out, and will try to send individual responses to everyone who replied in the next few days. Implementation of the Shell: All code is in LSC, and there is no preprocessor. You type your code in the LSC editor and run it. The Shell is not a separate application. It is a library of source code, which is designed to be easily extended and modified by using the standard object-oriented technique of overriding functions of superclasses. Classes are defined by using 3 source files: A .c file which contains the code for each of the class's methods, and two header files -- one which declares the class's instance variables and the other which defines the message names and data structures. Inheritance (single only) is achieved through the miracle of nested #include files. The header files for a class #include the header files of its superclass. A class inherits ALL the instance variables and methods of its superclass. Instances of classes, or objects, are allocated as relocatable blocks in the heap (handles). Messages are sent to objects with the following syntax: SendMsg(theObject, theMessage, arguments...); This corresponds to the theObject.message(arguments...) syntax of many object-oriented languages. Our code is standard C, so we use the standard function call syntax. The first instance variable of all objects is a pointer to what I call a "dispatcher" function for its class. SendMsg is implemented with in-line assembly language which just jumps to the dispatcher function. A dispatcher function consists mainly of a switch statement which invokes the proper method based on theMessage. Messages not handled by a specific class are passed on to its superclass. Creating a new object is somewhat awkward. The instance variables for an object are defined by a struct, whose first field is the aforementioned class dispatcher function. The syntax is: theObject = (ObjectHandle) NewObject(sizeof(ObjectStruct), ClassDispatcher); The function NewObject returns a handle to a newly created object (which must be typecast to the proper type) given the size of the object's instance variables and a pointer to its class dispatcher function. Although cumbersome, this implementation provides the most flexibility. I have considered setting up a scheme where all the classes are "installed" with some initialization code and given some sort of identifier (this may require a global variable for each class). Something like, ObjectName = InstallClass(sizeof(ObjectStruct), ClassDispatcher); once in an initialization routine and then, theObject = (ObjectHandle) NewObject(ObjectName); when one actually wants to create an object. I am open to opinions and suggestions on this point. Since objects are just handles, the resource manager may conveniently be used for saving and retrieving objects. To access an object stored as a resource, the syntax is theObject = (ObjectHandle) NewResObject(resType, resID, ClassDispatcher); For OOP gurus: Since we only send messages to handles to objects, only late binding is possible. Also, since this is standard C, there is really no easy way to implement data encapsulation and hiding. Instance variables are just fields in a struct, accessible to any function which knows about the struct. Private methods are implemented as calls to functions defined as "static" in the class's .c file. Class Hierarchy: Many people asked about how the classes compared to those in MacApp. I have purposely stayed away from MacApp and have never used it (to avoid any possible legal problems -- half a :^) ). I only know what I have read about it in Kurt Schmucker's book -- I guess he talks about some version of MacApp 1.0. I know absolutely nothing about MacApp 2.0. The main classes in The Shell at the moment are: (this is not a complete list) Application - initialization stuff and the event loop (full support of MultiFinder suspend, resume, and mouseMoved events) Window - All the basic window stuff not dealing with the content region. Supports floating windows (any number) which work "correctly" with Desk Accessories. Custom WDEF's are also supplied. View - The stuff that goes inside a window. You need a different subclass of a view for each type of information you want to display, i.e., text, picture, bitmap, etc. Windows may have multiple views. WorkSet - Ties together windows, views, files, and anything else that deals with the information an application manipulates. A WorkSet is sort of a supervisor which controls the communication between various objects. In a typical application, a WorkSet would be responsible for creating a window, installing views in that window, and creating a file (or document) which is associated with the window. Menu - Standard Mac menus, pull-down, heirarchical, and pop-up. A custom MDEF supports tear-off menus (they become floating windows after being torn off). The usual commands from the Apple, File, and Edit menu are supported. Control - Standard controls: buttons, check boxes, radio buttons, scroll bars ItemPalette - A palette of items, such as the Tools and Patterns in a drawing or painting program. An ItemPalette may be used as the basis for a custom menu (A tear-off palette as in HyperCard) or installed as a view in a window (As in MacDraw). Future Plans: We keep adding new objects whenever we can. The focus is currently on developing a utility to generate skeletal code for a class (the structure of the header files and dispatcher functions are highly standardized and must adhere to a rather rigid format) and on making new view subclasses which actually perform useful work (such as drawing, painting, and text editing). Color support is severely lacking (I've done most of the work on an SE). We plan to port The Shell to C++ when it becomes available (with LS Pascal 2.0 supporting object Pascal and LSC 3.0 released, I hope the next big project at THINK is LS C++). I am always open to suggestions for additional features and comments about the implementation. I am especially interested in hearing from people who have used MacApp. People have commented that they have had difficulties or are not satisfied with MacApp. Does anyone have any SPECIFIC gripes which they would like share? Please e-mail any questions, comments, or requests for further information. Gregory Dow ARPA: elcond@garnet.berkeley.edu Chemical Engineering Dept. UUCP: {uwvax, decvax, ihnp4, ...}!ucbvax University of California !elcond%garnet.berkeley.edu Berkeley, CA 94720 BITNET: POLYDOW@UCBCMSA