[net.sources.mac] SKEL.c

bill@utastro.UUCP (William H. Jefferys) (07/18/85)

Here is the most recent version of SKEL.c, as requested several
weeks ago.  I had to wait for permission from Megamax to post 
the modified qdvars.h header file.

This is written for v. 2.0 of Megamax C; I do not have v. 2.1
yet.  I have used the "convert" program to make the names
compatible with the Lisa Pascal conventions.

	Bill Jefferys  8-%
	Astronomy Dept, University of Texas, Austin TX 78712   (USnail)
	{allegra,ihnp4}!{ut-sally,noao}!utastro!bill	(uucp)
	bill%utastro.UTEXAS@ut-sally.ARPA		(ARPANET)

---------------------Cut Here-----------------------------
# This is a shar archive.  Extract with sh, not csh.
echo x - SKEL.c
cat > SKEL.c << '!Funky!Stuff!'
/*

PROGRAM Skel;

Original Lisa Pascal version written by
                 Steve Maker
                 Academic Computing
                 Kiewit Computation Center
                 Dartmouth College
                 July 14, 1984
		 
Translated for Megamax C compiler by
		 Bill Jefferys
		 Astronomy Department
		 University of Texas
		 Austin TX 78712
		 March 11, 1985

Copyright notice:
           SKEL may be copied and used by anyone, so long as that use
           is not for commercial purposes.  Please send significant 
	   changes back to Steve Maker for incorporation into future 
	   versions.

Why SKEL?
           Skel is a skeleton demo program.  Its purpose is to illustrate
           in a clear fashion, isolated from any particular application,
           the basic code for handling a simple Macintosh user interface.

           It strives to be correct as far as it goes, without many 
	   short-cuts that would lead to trouble in larger applications.

           I think of SKEL as a program that does nothing, but does 
	   it well.

What does SKEL do?
           It handles:
               Events, carefully handling only those which are its
                       business, and passing the others on to their
                       respective handlers.
               A Window, which is filled with Dark Gray, and can be
                       activated or inactivated, updated, dragged
                       and grown but NOT scrolled or closed.
               Menus, including the Apple Menu.  An "About Skel" menu entry
                       is provided.  A File menu offers Rattle and
		       Frighten, which just invoke dialog boxes, and Quit.
		       Command key equivalents are supported.
               The Desk Accessories, supported in the Apple menu,
                       and correctly meshed with the other features.
                       NOT supported are Undo, Cut, Copy, Paste and Clear
                       (and keyboard equivalents) for desk accessories.
               A Modal Dialog Box, used to communicate with the user.
               Special icons for the application and its related files.
               The Finder information (in the resource file).

           In accordance with Macintosh guidelines, everything possible is
           kept in the resource file: window description, menus,
           dialog specification, and the "About Skel" and other strings.

           In addition, the resource file handles the Bundle, File
	   References, and Icons that determine what Skel's icon looks 
	   like, and other information for the Finder.

How do I use SKEL?
           Study it.  Modify it to test your knowledge.  Steal working
           pieces of code for your own programs.  Beat on it.  Subject
           it to cruel and unusual experiments.  Pay heed to its warnings.

What do I study first in SKEL?
           Initially you should ignore several sections of SKEL, and the
	   calls made to them.  I recommend X-ing them out in your listing.
           The sections to ignore on the first round of study are:

               Report: ignore the implementation
               SetUpMemory: ignore all of it
               DrawWindow: ignore the scroll bar and grow icon handling
               ReSize: ignore all of it
               DoCommand: ignore the Desk Accessory handling in the
	          Apple Menu
               MainEventLoop:
                  MouseDown handling: ignore inSysWindow, inDrag, inGrow
                  keyDown, autoKey handling: ignore this.

           In the resource definition file, SKEL.R:
               Finder information (offset by asterisks):
                  ignore this whole section, icons and all.

What should I read in Inside Macintosh?
           You should read the following sections of Inside Macintosh,
           in the order given.  At first, just lightly skim the sections
           with parenthesized names.  Read the others in some depth.  Read
           the starred (*) ones in great detail.  Eventually, you will
	   have to read all sections thoroughly, and many many times, 
	   I promise you.

           To start:
             * Inside Macintosh: A Road Map
               (User Interface Guidelines)
               Structure of a Macintosh Application
             * Putting Together a Macintosh Application

           Then, (low-level sections are listed first):
            *  Memory Mgr Intro
              (Memory Mgr)
            *  Resource Mgr (through "Using the Resource Mgr")
            *  QuickDraw
              (Desk Mgr)
            *  Event Mgr (through "Event Mgr routines")
               Window Mgr
               Menu Mgr
              (Dialog Mgr)

How do I get SKEL to run?
           With Version 2.0 of the Megamax Compiler, run "batch" with
	   the input file "Skel.bat".
	   	   
What is the history of SKEL?
      v1.0 July 14, 1984   sm: major revision of earlier version
           Sept 30, 1984   sm: used \14 for apple symbol in res. file,
                               bracketed OpenDeskAcc with Get and SetPort,
           Oct 11, 1984   sm:  changed FREF, BNDL resources from HEXA
                                  to readable,
                               nested some routines in SKEL,
                               added constants for FILE menu items,
      v2.0 Nov 12, 1984   sm:  made resources pre-loaded and/or purgeable,
                               turned off range-checking,
                               documented no Resume proc passed to
			          InitDialogs,
                               added SetUpMemory:
                                  calls MoreMasters, MaxApplZone,
                                  sets the NIL address to -1,
                                  lots of general memory doc.
                               added a warning about passing doubly-
                                  dereferenced handles,
                                  removed en/disabling of Rattle and 
				  Frighten items,
      v2.1 Dec 4, 1984    sm:  added menu key handling,
                               put Rattle and Frighten strings in res file,
                               rewrote intro documentation

      v2.2 Mar 6, 1985    sm:  converted to % describes,
                               Fixed SKELX for both 2.0 and 3.0 workshop,
                               set the event mask
      
      v2.2C Mar 11, 1985  whj: converted to Megamax "C"; future Megamax "C"
                               version numbers will have the same version
			       number as the corresponding Pascal version,
			       but with an appended "C".
      
      v2.2.1C April 1,1985 whj:Added in-place conversion of Pascal strings
      			       to C strings for the string resources.  Uses
			       new procedure "initStrRes", included in
			       this file.  This is a kludge required because
			       the RMaker program supplied does not
			       support C-Style strings.  v. 2.0 of Megamax C
			       is different in its handling of string
			       resources than v. 1.2, which necessitated this
			       change.  Strings resources must not be 
			       purgeable for this to work.  Also modified the
			       header file "qdvars.h" which was supplied with
			       Megamax C v. 2.0.  Use the new version in place
			       of the Megamax version; the interface will be
			       similar to the Lisa Pascal interface.
			       
	v.2.2.2C May 20,1985   Corrected two minor bugs reported on Usenet.
			       The bugs apparently had no effect on the operation
			       of the program.
			       
			       The distribution version of the program has been
			       converted to Inside Macintosh toolbox names using
			       Convert.  To use with Megamax C Compiler, use
			       Convert as distributed with Version 2.0, with the
			       "-L" argument to get a file containing all lowercase
			       toolbox calls.

*/


/* .h files needed by skeleton */

#include <mem.h>		/* use type defs in MemTypes unit */
#include <qd.h>			/* Search "Obj/Quickdraw" for  */
#include <win.h>		/*  the "QuickDraw" unit, etc. */
#include <qdvars.h>		
				/* Do NOT use the header file qdvars.h 
				   supplied by Megamax.  Instead, use the 
				   one supplied with this distribution. */
#include <os.h>
#include <menu.h>
#include <event.h>
#include <te.h>
#include <stdio.h>
#include <dialog.h>

/*
#include <pack.h>;                      {these are not needed for SKEL,}
#include <math.h>;                      {  but may be useful later.}
 
I don't know what Megamax C statements correspond to the following three Pascal
statements (WHJ):
      {$U Obj/Elems       } Elems,       {Assume normal SANE, not SANELIB}
      {$U Obj/Graf3D      } Graf3D,
      {$U Obj/MacPrint    } MacPrint;
*/

/*    
    The following two constants are not defined in any .h file.  They
    are described in "Inside Macintosh" - Event Manager, pp. 14-15.
*/
#define charcodemask 255  
#define cmdKey 256        

#define lastmenu 2		/* number of menus */
#define applemenu 1		/* menu ID for desk accessory menu */
#define filemenu 2		/* menu ID for File menu */

#define irattle 1		/* items in the File menu */
#define ifrighten 2
 /*-------*/
#define iquit 4

#define  aboutskelid 1		/* Resource ID of the string */
#define  rattleid 2
#define  frightenid 5

#define windowid 260		/* Resource ID for my window */



GrafPtr screenport;		/* a port for the whole screen */
WindowPtr mywindow;		/* our one window */
WindowRecord wrecord;		/* storage for window record */
Rect dragrect;			/* Rect to drag within */
Rect growrect;			/* bounds for the growth of the windows */
MenuHandle mymenus[lastmenu + 1];/* our menus */

EventRecord myevent;
WindowPtr whichwindow;		/* points to window of MouseDown */
int     windowcode;		/* what mouse was in when event posted */
boolean userdone;		/* true when user wants to exit program */

/* 
Print a string in dialog box
############################   Report   #################################

We put up a dialog box, show the string, and wait for user to hit OK.
*/

report (reportstr)
char   *reportstr;

#define rptboxid 257		/* ID of our report dialog in resource
				   file */
#define rpttext 2		/* Item # of dialog's report text */
{
    int     itemhit;		/* which Item was clicked on (only OK
				   avail) */
    DialogPtr reportptr;



    ParamText (reportstr, "", "", "");/* set text to display */
    reportptr = GetNewDialog (rptboxid, NULL, (long) - 1);
				/* get from Resource file; NIL => use heap
				   storage; -1 => make dlg frontmost */

    ModalDialog (NULL, &itemhit);
				/* carry out dialog; NIL => no FilterProc;
				   return Item Hit when done */
    DisposDialog (reportptr);	/* release storage and remove dialog from
				   screen */
}				/* Report */


/*

SetUps for handling memory
##########################   SetUpMemory   ############################
     This very important set of initializations can be left out of the
   first versions of a program. We are making sure that memory is laid
   out as we desire, with adequate protection against running out of
   memory, bad handles, etc.
*/

setupmemory () {


#define maxStackSize 8192	/* max size of stack; the heap gets the
				   rest */

    typedef long   *lomemptr;	/* a pointer to low memory locations */

    lomemptr nilptr;		/* will have value NIL */
    lomemptr stackbaseptr;	/* points to current stack base */

/* 
  If you define a GrowZone function to Handle bad memory problems,
  you should define it at the top level (not nested), and set it
  here. We don't.
*/
/*  SetGrowZone(&mygrowzone);     */

/* 
  Place a longint -1 (an odd and therefore illegal address) in the
  memory location that would be referenced by an accidentally-NULL
  Handle, so the error will be caught at Handle-reference time (as
  an Address error, ID=02) instead of later on.
*/

    nilptr = NULL;
    *nilptr = -1;

/* 
  If you needed to use an Application heap limit other than the
  default (which allows 8K for the stack), you'd set it here,
  possible using this technique of explicitly specifying the maximum
  stack size and allocating the rest to the heap.  Should be
  independent of memory size. */

    stackbaseptr = (lomemptr) 0x908;
				/* CurStackBase from Tlasm/sysequ.text */
    SetApplLimit ((Ptr) (*stackbaseptr - maxStackSize));

/* 
  Expand the application heap Zone to its maximum size, without
  purging any purgeable resources.  This saves memory compactions
  and heap expansions later.
*/

    maxapplzone ();

/* 
  get plenty of master pointers now; if we let the Memory Manager
  Allocate them as needed, they'd form non-relocatable islands in
  the heap.
*/

    MoreMasters ();
    MoreMasters ();
    MoreMasters ();

/* 
  Here you might install bulwarks against running out of memory
  unexpectedly.  One such (cheesy) technique is to here Allocate
  a large Handle, call it "CheeseBuf", which you can de-Allocate
  in your GrowZone function, when you must obtain more memory to
  avoid a crash.  While de-allocated, the program could prevent
  the user from doing anything requiring memory, and tell him he
  must discard windows or some such memory freeing action. Each
  time he does so, the program can try to re-Allocate CheeseBuf;
  if it succeeds, the user can go on doing memory-eating operations.
*/

}				/* SetUpMemory */

/*
############################   SetUpMenus   #############################

    Once-only initialization for menus
    We read in all menus from the resource file, and install them,
    and all desk accessories (drivers).
    
*/



setupmenus () {
    int     i;
    for (i = 1; i <= lastmenu; i++)/* get all my menus in */
	mymenus[i] = GetMenu (i);/* use the fact that our menu ID's start
				   at 1 */
    AddResMenu (mymenus[applemenu], "DRVR");
				/* pull in all desk accessories */
    for (i = 1; i <= lastmenu; i++)
	InsertMenu (mymenus[i], 0);/* insert menus; 0 => put at end */
    DrawMenuBar ();
}

/*
############################   initStrRes   ##############################
Changes strings in Resource Fork to NULL-terminated C formatted strings.
All strings in Resource Fork must be unpurgeable for this to work.  Sorry.
Perhaps this can go away when Apple provides an RMaker program that supports
C strings.
*/

initstrres()
{
	int i, numstrres;
	stringhandle str;
	numstrres = CountResources ("STR ");	/* Count the strings */
	for (i=1; i<=numstrres; i++)
	{
		str = GetIndResource ("STR ", i); /* Get Handle to string */
		ptocstr(*str);		/* Convert in place to C string */
	}
}

/*
body of SetUp
Once-only initialization for Skel
############################   SetUp   ##############################

   Initialize our program.  It seems best to Handle:
   Memory inits first, ToolBox inits second, then the program variables'
   inits. Note that the order of inits is important; see "Using the
   Dialog Manager" in the Dialog Mgr section.

*/

setup () {
/* 
  The following function is not defined in <win.h>, although
  that is where you would expect it.  - WHJ 3/10/85
*/
    extern  WindowPtr GetNewWindow ();

    Rect screenrect;		/* size of screen; could be
				   machine-dependent */

    setupmemory ();		/*  init memory layout and protection */

/*  init QuickDraw, and everybody else */
    InitGraf (&thePort);
    InitFonts ();
    InitWindows ();
    InitMenus ();
    TEInit ();
    InitDialogs (NULL);		/* NULL => no Restart proc; see Dialog Mgr
				   and System Error Handler */
    InitCursor ();
    initstrres();		/* Convert Pascal strings in Resource
    				   Fork to C formatted strings*/

/* 
  Init the system event mask, in case the previous program left
  it in a bad state.  If you set it non-standard here, FIX IT
  BEFORE EXITING, because the Finder (1.1g) does NOT set it.
*/
    SetEventMask (everyEvent - keyUpMask);/* standard setting */
/* 
  Get the port which is the whole screen, to use when deactivating
  our window.  This prevents the current grafPort pointer from
  ever dangling.
*/
    GetWMgrPort (&screenport);	/* get whole screen port that window mgr
				   uses */
    SetPort (screenport);	/* and start off with it */

/* 
  get window: use wRecord storage.  Port is set to that of the
  new window.
  GetNewWindow posts an update event for the new window,
  so it will be redrawn right away.
*/
    mywindow = GetNewWindow (windowid, &wrecord, (long) - 1);
				/* -1 => frontmost window */

/* set up dragRect; we can drag the window within it */
    screenrect.a.top = screenBits.bounds.a.top;
				/* don't assume screen size */
    screenrect.a.left = screenBits.bounds.a.left;
    screenrect.a.bottom = screenBits.bounds.a.bottom;
    screenrect.a.right = screenBits.bounds.a.right;

/* 
  set drag Rect to avoid menu bar, and keep at least 4 pixels
  on screen
*/
    SetRect (&dragrect, 4, 24, screenrect.a.right - 4, screenrect.a.bottom - 4);

/* set up GrowRect, for limits on window growing */
    SetRect (&growrect, 48, 14, screenrect.a.right - 7, screenrect.a.bottom - 7);

/* pull in and set up our menus */
    setupmenus ();

}

/* 
Redraw my window
############################   DrawWindow   #############################

   We draw all the contents of our one window, myWindow.  Note that this
   must include scroll bar areas and the grow icon; the Window Manager
   will NOT Handle those for us. Since there are no scroll bars, we
   must erase the Region they would be in.  Echh.
*/

drawwindow () {
    Rect arect;			/* rectangle to erase */

    FillRect (&mywindow -> portRect, &dkGray);
				/*  first, fill the window with dark gray;
				   this fills scroll bars, too */

/*  second, erase the scroll bars and draw the grow icon */

/*  erase the horizontal scroll bar */
    SetRect (&arect,		/* cover the horizontal bar */
	    mywindow -> portRect.a.left,
	    mywindow -> portRect.a.bottom - 15,
	    mywindow -> portRect.a.right - 15,
	    mywindow -> portRect.a.bottom);
    FillRect (&arect, &white);	/* fill with white */

/*  erase the vertical scroll bar */
    SetRect (&arect,		/* cover the vertical bar */
	    mywindow -> portRect.a.right - 15,
	    mywindow -> portRect.a.top,
	    mywindow -> portRect.a.right,
	    mywindow -> portRect.a.bottom - 15);
    FillRect (&arect, &white);	/* fill with white */

    DrawGrowIcon (mywindow);	/* draw the size box in the corner of the
				   window */

}				/* DrawWindow */

/*

Update the contents of the given window
############################   UpdateWindow   ##########################

   This is our response to receipt of an update event for myWindow.
   Since the window is likely to be inactive, the current grafPort
   will be elsewhere.  We must change it for drawing, yet leave it
   as it was.
*/

updatewindow (awindow)
WindowPtr awindow;
{
    GrafPtr saveport;		/* to save and restore the old port */

    BeginUpdate (awindow);	/* reset ClipRgn etc to only redraw what's
				   necessary. */

    GetPort (&saveport);	/* don't trash the port; we might be
				   updating an inactive window */
    SetPort (awindow);		/* work in the specified window */

    drawwindow ();		/* redraw contents of window */

    SetPort (saveport);		/* all nice and tidy as before */

    EndUpdate (awindow);

}				/* UpdateWindow */

/*
Handle a command given through a menu selection
############################   DoCommand   ##############################

   We carry out the command indicated by mResult.
   If it was Quit, we return true, else false.  Since the menu was
   highlighted by MenuSelect, we must finish by unhighlighting it
   to indicate we're done.
*/
int     docommand (mresult)
long    mresult;


{
    int     refnum;
    int     themenu,
            theitem;
    char    name[255];
    GrafPtr saveport;		/* for saving current port in when opening
				   a desk accessory */
    stringhandle astr;		/* a utility string */
    int     returns;

    returns = 0;		/* assume Quit not selected */
    themenu = HiWord (mresult);	/* get the menu selected */
    theitem = LoWord (mresult);	/* ... and the Item of that menu */
    switch (themenu) {
	case 0: 
	    break;		/* user made no selection; do nothing */

	case applemenu: 

	    if (theitem == 1) {	/* get string, and tell about Skel */

/* 
  It's important not to pass Report a de-referenced
  Handle; if Report were in another segment, loading
  it could cause a memory compaction; the de-referenced
  Handle could become invalid.  Watch out for this
  and similar nasties everywhere in your program.
  See the Memory Manager and the Segment Loader.
*/
		astr = GetString (aboutskelid);

		report (*astr);
	    }
	    else {		/* run a desk accessory; make sure port is
				   preserved */
		GetPort (&saveport);
		GetItem (mymenus[applemenu], theitem, name);
				/* get name */
		refnum = OpenDeskAcc (name);/* run the desk accessory */
		SetPort (saveport);
	    }
	    break;

	case filemenu: 
	    switch (theitem) {
		case irattle: 	/* Rattle */
		    astr = GetString (rattleid);
		    report (*astr);
		    break;
		case ifrighten: /* Frighten */
		    astr = GetString (frightenid);
		    report (*astr);
		    break;
		case iquit: 
		    returns = 1;/* Quit */

	    }			/* fileMenu case */

    }				/* menu case */

    HiliteMenu (0);		/* turn off hilighting on the menu just
				   used */
    return (returns);
}				/* DoCommand */

/* 
Change the size of the given window
############################   ReSize   ###############################
  
  Called on a mouse-down in the grow box, this allows the user to change
  the size of the window.  We change the size, then
  claim that the whole of the window contents is no longer validly drawn,
  because we're too lazy to do so for just the scroll bar regions
  that are actually subject to change.  See the Window Manager.
*/

resize (a_window, downpt)
WindowPtr a_window;
Point * downpt;
{
    int     w,
            h;			/* new width and height of the sized
				   window */
    long    newsize;		/* the new size */

    newsize = GrowWindow (a_window, downpt, &growrect);
 /* find new size */
    w = LoWord (newsize);	/* find the width */
    h = HiWord (newsize);	/* find the height */

    SizeWindow (a_window, w, h, 1);/* change to the new window size */

/* 
  place whole window into update Region to be sure it all gets
  updated. This is more than is strictly necessary, but a lot
  easier than just invalidating the regions that actually may have
  changed.
*/
    InvalRect (&a_window -> portRect);

}				/* ReSize */


/* 
the main loop that handles events
############################   MainEventLoop  ##########################
  
  Brace yourself: here's where the action is.  Most Mac programs just
  wait for events (as do we all), and then process them.  There are
  two sorts of events: those directly initiated by the user, like key
  presses and mouse-downs, and those consequent events posted by the
  Event Manager, like update and activate events.  The latter MUST be
  handled correctly and carefully.  In particular, it's important for
  all events to make sure that the event occurred in or for the window
  you expect -- it's possible to get events which are not for one of
  our windows, despite GetNextEvent's return value.  Similarly,
  be sure to check that the window it occured in is the active one,
  if it matters.
  
  A common mistake in handling update and activate events is in finding
  out which window they are for.  It is "(WindowPtr)myevent.message "
  that gives this information, NOT "whichwindow" (the WindowPtr returned
  by FindWindow).  The latter pointer merely tells you what window
  the mouse was in at the time the event was posted -- completely
  irrelevant for Update and Activate events.  Think it through carefully.
  
*/

maineventloop () {

/* body of MainEventLoop */

    FlushEvents (everyEvent, 0);/* discard leftover events */

/* get next event, and Handle it appropriately, until user QUITs */

    userdone = 0;
    do {
	SystemTask ();		/* Handle desk accessories */
	if (GetNextEvent (everyEvent, &myevent)) {
				/* get event; if for us... */
	    switch (myevent.what) {/* Handle each kind of event */
		case mouseDown: /* find out what window the mouse went
				   down in, and where in it */
		    windowcode = FindWindow (&myevent.where, &whichwindow);
		    switch (windowcode) {
				/* Handle mouse-down for each place */
			case inSysWindow: 
				/* Handle the desk accessories */
			    SystemClick (&myevent, whichwindow);
			    break;/* inSysWindow */
			case inMenuBar: /* Handle the command */
			    userdone = docommand (MenuSelect (&myevent.where));
			    break;/* inMenuBar */
			case inDrag: /* drag the window */
			    DragWindow (whichwindow, &myevent.where, &dragrect);
			    break;
			case inContent: 
				/* includes inGrow if window inactive.
				   Activate window */
			    if (whichwindow == mywindow)
				/* make sure it's for mine */
				if (whichwindow != FrontWindow ())
				    SelectWindow (whichwindow);
				/* make it active */
			    break;
			case inGrow: 
				/* window is already active; change its
				   size */
			    if (whichwindow == mywindow)
				/* moke sure it's for mine */
				resize (mywindow, &myevent.where);
			    break;/* inGrow */
			case inGoAway: 
				/* we don't have a GoAway Region */
			/* break;  I got a compiler error here with the
			   break left in.  Good C programming Style would
			   have a break even after the last case - WHJ
			   3/11/85 */
		    }
		    break;	/* switch */

		case keyDown: 
		case autoKey: 	/* if command key, pass the char to
				   MenuKey */
		    if ((myevent.modifiers & cmdKey) != 0)
			userdone = docommand (MenuKey ((char) (myevent.message & charcodemask)));
		case updateEvt: /* if it's for our window, update it */
		    if ((WindowPtr) (myevent.message) == mywindow)
			updatewindow (mywindow);
				/* redraw the window contents */
		    break;
		case activateEvt: 
				/* if for our window, set port as nec. */
		    if ((WindowPtr) (myevent.message) == mywindow) {
				/* my window */
			DrawGrowIcon (mywindow);
				/* redraw grow icon to reflect new state 
				*/
			if (myevent.modifiers & 1)
				/* odd means an activate event */
			    SetPort (mywindow);
				/* activate evt: work in our own port */
			else
			    SetPort (screenport);
				/* deactivate evt: our port is gone; keep
				   port from dangling */
		    } break;
	    }
	}

    } while (userdone == 0);
}

/*
  body of Skel
*/


main () {
    setup ();
    maineventloop ();
}
!Funky!Stuff!
echo x - SKEL.R
cat > SKEL.R << '!Funky!Stuff!'
*  SkelR -- Resource definition file for small skeleton application
*                Written by Steve Maker
*		 Modified for Macintosh RMaker program 
*		   by Bill Jefferys 3/8/85

* Tell RMAKER what to name the resource file
* It is most convenient during the development cycle to append
* the resources to SKEL, which is the output file from 
* the BATCH file we are using.
!SKEL
APPLSKEL

* Version data for the finder
*    Our signature is "SKEL"
*    res. ID = 0, by convention
*    finder version data
*    Note that the blank in 'STR ' is significant 3/8/85 WHJ
TYPE SKEL = STR 
  ,0
  Skel 2.2.2C -- May 20, 1985

* Menus
*   ID (4 => pre-load the resource; MUST NOT be purgeable!)
*   menu title: an Apple symbol (in hex) for the Apple menu.
*   menu entries, one per line. ( means it's initially disabled.
*   An entry of  (-  means a disabled line of dashes.
*   A trailing /Q means a command-key equivalent.
*   blank line at end of menu.
Type MENU
  ,1(4)
  \14
    About Skel
    (-

Type MENU
  ,2(4)
  File
    Rattle
    Frighten
    (-
    Quit/Q

* A Window template
*   ID,(4 => pre-load the resource; 32 => purgeable)
*    title
*    BoundsRect (global Top, Left, Bottom, Right): where it appears on the screen
*    Vis NoGo: it's visible, does not have close box
*    ProcId: this is a standard type of window
*    Refcon, for program's use.  Skel doesn't use it.
Type WIND
  ,260(36)
  A Skeleton Application
  85 128 256 384
  Visible NoGoAway
  0
  0

* Strings (kept here for ease of change)
*   ID,(4 => pre-load the resource)
*   These strings had better not be purgeable for the
*        in-place conversion to C-style NULL-terminated strings
*        to work consistently!
* A string for "About Skel"
* Rattle string
* Frighten String
type STR         ;; Note blank inserted here!
   ,1(4)
  Skel 2.2 by Steve Maker; Version 2.2.1C by Bill Jefferys 4/1/85
   ,2(4) 
                            Too tired to Rattle them bones.
   ,5(4)
                                                 Boo!

* dialog box for Report
*   ID (4 => pre-load the resource; MUST NOT be purgeable!)
*   title
*   BoundsRect(global: TLBR)
*   Vis NoGo: it's visible, but has no close box
*   ProcID: Window type is modal dialog
*   RefCon: Unused user variable
*   res. ID of item list
Type DLOG
  ,257(4)
  Report Box
  80 20 131 492
  Visible NoGoAway
  1
  0
  257

* dialog item list for Report
*   ID (4 => pre-loaded; 32 => purgeable - it should always be purgeable.)
*   # Items
*   the first item:
*      a Button you can select
*      display rect (local coords)
*      title
*   the second item:
*     Static text, disabled (i.e. can't select it)
*     display rect
*     text to be set by ParamText
Type DITL
  ,257(36)
  2
    button Enabled
    25 186 46 286
OK

    staticText Disabled
    5 25 20 450
^0

****************************************************************************
****        This section contains information for the Finder;           ****
****     the program SKEL never accesses this information directly.     ****
****        The entire section can be omitted from the first versions   ****
****     of a program (you must then set the application's type to      ****
****     APPL, the creator to ????, and don't set the bundle bit);      ****
****     the default application icon will be used.                     ****
****        For more info, read "Putting together a Mac Application"    ****
****     and "The Structure of a Mac Application".                      ****
*
*   To make the finder show your application's special icon on the desktop,
*   make documents of your type show their icons, make an
*   application start when a document is opened,
*   and move all files associated with your application
*   when a copy is done, you must:
*       For documents of new types:
*             - set the document's type to the new type (here BONE)
*               (often the program that creates them will do this)
*             - if you want the application to start when a document file
*               is opened, set the file's creator to the signature of
*               the application, here SKEL; otherwise, to ????.
*       For the application:
*             - set the application's type to APPL ("it's an application")
*             - set the creator to its signature, here SKEL
*             - set the bundle bit. This tells the finder that it should read
*               this info from the SKEL resource file and use it when displaying
*               SKEL's icon.
*   If you use SendOne, these items will have to be set with SetFile the first
*   time, and then not again; if you use MacCom, they are set every time
*   (usually in the exec file).
*   If you change the icon, the change may not have effect on the desktop,
*   until you reboot with the command and option keys held down.  This tells
*   the Finder to reconstruct the desktop; the correct icons will be displayed,
*   but all folders will be lost.

* a Bundle: contains references to other finder info, (below)
*   ID (32 => purgeable)
*   Bundle owner: SKEL (our signature), Res ID of version data = 0
*   "ICN#" (means icon list), # of icon resources in bndl = 2
*   local ID 0 maps to global ID 128 (the FREF uses a local ID, to refer to
*      an icon which has a global ID. See the FREF resource, below);
*      local ID 1 maps to global ID 129
*   "FREF" (means file reference), # of FREF res in bndl = 2
*   local ID 0 maps to global ID 128; local ID 1 maps to global ID 129

Type BNDL
   ,128(32)
   SKEL 0
   ICN# 2
   0 128 1 129
   FREF 2
   0 128 1 129

* a File Reference
*   ID, (32 => purgeable)
*   "APPL" : a file of type APPL (SKEL itself) gets the following icon (a skull);
*       local icon ID; maps to global ID as specified in BNDL
*   name of file that must accompany application if transferred; omit if none.
  Type FREF
   ,128(32)
   APPL 0

* Another File Reference
*   ID, (32 => purgeable)
*   "BONE" : a file of type BONE gets the following icon (crossbones); local icon ID
*   no filename
Type FREF
   ,129(32)
   BONE 1

* An icon list for the application icon (a skull)
*   ID (the application icon), (32 => purgeable)
*   Data is Hex data (.H)
*   the icon data: 32 lines of 8 hex chars each
*   the icon mask: 32 lines of 8 hex chars each
Type ICN# = GNRL
 ,128(32)
.H
001F F000 01E0 0F00 0700 01C0 0C00 0060
1878 3C30 10CC 6610 3184 4318 2104 4108
2104 4108 218C 6308 20F8 3E08 3000 0018
1000 0010 0800 0020 0402 8040 0302 8180
0182 8300 0082 8200 0040 0400 0040 0400
0040 0400 004F E400 005B B400 005B B400
007F FC00 0020 0800 0030 1800 0018 3000
0007 E000 0000 0000 0000 0000 0000 0000
001F F000 01FF FF00 07FF FFC0 0FFF FFE0
1FFF FFF0 1FFF FFF0 3FFF FFF8 3FFF FFF8
3FFF FFF8 3FFF FFF8 3FFF FFF8 3FFF FFF8
1FFF FFF0 0FFF FFE0 07FF FFC0 03FF FF80
01FF FF00 00FF FE00 007F FC00 007F FC00
007F FC00 007F FC00 007F FC00 007F FC00
007F FC00 003F F800 003F F800 001F F000
0007 E000 0000 0000 0000 0000 0000 0000

* An icon list for a file of type BONE (crossbones)
*   ID (the icon for BONE files), (32 => purgeable)
*   Data is Hex data (.H)
*   the icon data: 32 lines of 8 hex chars each
*   the icon mask: 32 lines of 8 hex chars each
,129(32)
.H
03C0 00F0 0660 0198 0430 0308 1C30 030E
3020 0103 2030 0301 2018 0601 300C 0C03
1F06 183E 0D83 306C 00C1 E0C0 0060 C180
0030 6300 0018 3600 000C 1C00 000E 0C00
001B 0600 0031 8300 0060 C180 00C1 E0C0
0183 3060 0306 1830 1E0C 0C1E 3018 0603
2030 0301 2060 0181 2040 0081 2040 0081
3040 0083 18C0 00C6 0F80 007C 0000 0000
03C0 00F0 07E0 01F8 07F0 03F8 1FF0 03FE
3FE0 01FF 3FF0 03FF 3FF8 07FF 3FFC 0FFF
1FFE 1FFE 0DFF 3FEC 00FF FFC0 007F FF80
003F FF00 001F FE00 000F FC00 000F FC00
001F FE00 003F FF00 007F FF80 00FF FFC0
01FF 3FE0 03FE 1FF0 1FFC 0FFE 3FF8 07FF
3FF0 03FF 3FE0 01FF 3FC0 00FF 3FC0 00FF
3FC0 00FF 1FC0 00FE 0F80 007C 0000 0000

****    end of information for the finder                          ****
***********************************************************************


!Funky!Stuff!
echo x - qdvars.h
cat > qdvars.h << '!Funky!Stuff!'
/*    quickdraw globals, defined in qd1.o

      Based on Megamax C v. 2.0.  Modified for 
      conformity with Lisa Pascal.  This file 
      is not the original file as distributed by 
      Megamax, Inc., but is modified from their code.
      Copyright (C) 1984, 1985 by Megamax, Inc.
*/

#ifndef systemFont
#include <font.h>
#endif

typedef struct {
    FMOutPut qdfontdata;
    FMOutPtr qdfontptr;
    long qdontadj;
    Point qdpatalign;
    int qdpolymax;
    PolyHandle qdthepoly;
    int qdplayindex;
    PicHandle qdplaypic;
    int qdrgnmax;
    int qdrgnindex;
    qdhandle qdrgnbuf;
    Region qdwidedata;
    RgnPtr qdwidemaster;
    RgnHandle qdwideopen;
    long qdrandseed;
    BitMap qdscreenbits;
    Cursor qdarrow;
    Pattern qddkgray;
    Pattern qdltgray;
    Pattern qdgray;
    Pattern qdblack;
    Pattern qdwhite;
    GrafPtr QDthePort;
} qdvar;
extern qdvar qdvars;

#define fontData (qdvars.qdfontdata)
#define fontPtr (qdvars.qdfontptr)
#define ontadj (qdvars.qdontadj)
#define patAlign (qdvars.qdpatalign)
#define polyMax (qdvars.qdpolymax)
#define thePoly (qdvars.qdthepoly)
#define playIndex (qdvars.qdplayindex)
#define playPic (qdvars.qdplaypic)
#define rgnMax (qdvars.qdrgnmax)
#define rgnIndex (qdvars.qdrgnindex)
#define rgnBuf (qdvars.qdrgnbuf)
#define wideData (qdvars.qdwidedata)
#define wideMaster (qdvars.qdwidemaster)
#define wideOpen (qdvars.qdwideopen)
#define randSeed (qdvars.qdrandseed)
#define screenBits (qdvars.qdscreenbits)
#define arrow (qdvars.qdarrow)
#define dkGray (qdvars.qddkgray)
#define ltGray (qdvars.qdltgray)
#define gray (qdvars.qdgray)
#define black (qdvars.qdblack)
#define white (qdvars.qdwhite)
#define thePort (qdvars.QDthePort)
!Funky!Stuff!
echo x - SKEL.bat
cat > SKEL.bat << '!Funky!Stuff!'
mmcc skel.c
mmlink SKEL skel.o
rmaker SKEL.R
SKEL!Funky!Stuff!