[comp.sys.mac.programmer] The Crunched Shell

elcond@garnet.berkeley.edu (Gregory Dow) (07/21/88)

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

landman%hanami@Sun.COM (Howard A. Landman) (07/22/88)

In article <12362@agate.BERKELEY.EDU> elcond@garnet.berkeley.edu (Gregory Dow) writes:
>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.

Gee - this sounds like you can get multiple inheritance just by nesting
2 or more include files.  So why "single only"?  (Assuming no conflicts.)
Is it because you need to know which SuperClass to pass a message to if the
local Class can't handle it, so the dispatcher would get more complicated?

	Howard A. Landman
	landman@hanami.sun.com
	UUCP: sun!hanami!landman

mce@tc.fluke.COM (Brian McElhinney) (07/28/88)

elcond@garnet.berkeley.edu (Gregory Dow) writes:
> 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?

I have always been amazed that views (drawing areas inside windows) are tiled.
Overlapping views would have been far more useful, an indeed are rumored to be
a part of the next release (as are C++ and a symbolic debugger).  Also, you
should be able to nest views inside views.

A "real" text class would be wonderful.  It should be something like a text
item in MacDraw.

The dialog class has taken a beating at meetings and in the MacApp DA
newsletter (so I have avoided it).  It would be useful to have classes for each
of the basic dialog items (buttons, check boxes, etc.) such that they can
appear in any view.  I think this is also in the next release.

The only grouping mechanism is the list.  To the programmer it appears to be a
dynamic array, not a list (i.e there is no way to ask for the next object; you
must keep an index yourself).  Other data types would be useful, and I'm sure
will appear as MacApp evolves and matures.

The basic window class is, well, kind of basic.  Multi-pane windows (such as
in Excel) would be a great addition.

MacApp is a great tool, as it handles everything a commercial grade application
should (low memory, MultiFinder, printing), and makes many things much easier
(undo, updating multiple views of the same data, menu enable/disable).
Unfortunately, MacApp will not get the wide-spread use it deserves; not because
of faults in MacApp itself, but because using it means using MPW (i.e.: slow
and expensive).  Now if there was such a thing as LightspeedC++ ...


Brian McElhinney
mce@tc.fluke.com

lsr@Apple.COM (Larry Rosenstein) (07/29/88)

In article <4581@fluke.COM> mce@tc.fluke.COM (Brian McElhinney) writes:
>elcond@garnet.berkeley.edu (Gregory Dow) writes:
>> 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?
>
>I have always been amazed that views (drawing areas inside windows) are tiled.
>Overlapping views would have been far more useful, an indeed are rumored to be
>a part of the next release (as are C++ and a symbolic debugger).  Also, you
>should be able to nest views inside views.

Overlapping views are not directly supported in MacApp 2.0. Views can
overlap, but MacApp does nothing to prevent one view from interfering with
another.  The views will be drawn in a particular order and, one view will
end up covering part of another.

It should be easy to implement true overlapping views in the same way
overlapping windows are implemented.  You would have to maintain a visRgn
for each view in the list, and override the Focus method to clip to the
view's visRgn.

MacApp 2.0 does support arbitrary hierarchy of views.  The dialog unit is
completely redone, and dialogs done with MacApp don't use the Dialog
Manager.  Instead they are regular windows.  There are many view classes
predefined in the Dialog units, to correspond to all the standard controls,
as well as control-like objects that are not really controls (popup menus,
pictures, icons, lists of items, etc.).

The view hierarchy is defined by a resource, and there is work being done on
a graphical editor for view resources.

>The basic window class is, well, kind of basic.  Multi-pane windows (such as
>in Excel) would be a great addition.

You can do this in MacApp 1.1, and it will be a bit easier to do in MacApp
2.0.  MacApp directly supports windows with a fixed-size "palette" at the
top or left of the window.  More complicated window arrangements are
possible if you override the window class and implement code to resize and
move its subviews when the window resizes.

MacApp 2.0 does not directly support splitting a view into independently
scrollable parts that display the same information.  Again, the view
architecture in MacApp 2.0 makes this easier to implement than it was in the
old MacApp.

>of faults in MacApp itself, but because using it means using MPW (i.e.: slow
>and expensive).  Now if there was such a thing as LightspeedC++ ...

Well eventually, there will be Lighspeed Pascal 2.0.

		 Larry Rosenstein,  Object Specialist
 Apple Computer, Inc.  20525 Mariani Ave, MS 46-B  Cupertino, CA 95014
	    AppleLink:Rosenstein1    domain:lsr@Apple.COM
		UUCP:{sun,voder,nsc,decwrl}!apple!lsr