home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Carousel
/
CAROUSEL.cdr
/
mactosh
/
code
/
c_smplet.sit
< prev
next >
Wrap
Text File
|
1988-06-20
|
69KB
|
2,331 lines
18-Jun-88 14:44:01-MDT,71786;000000000000
Return-Path: <u-lchoqu%sunset@cs.utah.edu>
Received: from cs.utah.edu by SIMTEL20.ARPA with TCP; Sat, 18 Jun 88 14:42:14 MDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
id AA22611; Sat, 18 Jun 88 14:42:05 MDT
Received: by sunset.utah.edu (5.54/utah-2.0-leaf)
id AA24770; Sat, 18 Jun 88 14:41:57 MDT
Date: Sat, 18 Jun 88 14:41:57 MDT
From: u-lchoqu%sunset@cs.utah.edu (Lee Choquette)
Message-Id: <8806182041.AA24770@sunset.utah.edu>
To: rthum@simtel20.arpa
Subject: SimpleTools.c.shar
#! /bin/sh
#
# This is a shell archive. Save this into a file, edit it
# and delete all lines above this comment. Then give this
# file to sh by executing the command "sh file". The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# 3 STools.info
# 12 SimpleDemo.c
# 31 SimpleTools.c
# 19 SimpleTools.doc
#
echo 'Extracting STools.info'
if test -f STools.info; then echo 'shar: will not overwrite STools.info'; else
sed 's/^X//' << '________This_Is_The_END________' > STools.info
XFrom: erik@ucbssl.CC.Berkeley.EDU (Erik Kilk)
X
X!rSimpleTalk.text
X
XHere is an updated version of SimpleTools. Included are the SimpleTools
Xsources, a MacWrite document, and an example using some of the easy and
Xadvanced features in the SimpleTools library.
X
XSimpleTools is a set of subroutines which greatly ease the use of the
XMacintosh toolbox. It is mainly intended to be used for your smaller
Xapplications where you would rather not be too concerned with reading
XInside Macintosh over again. The subroutines are currently written in C
Xand were done so using the Megamax compiler. They are designed to be
Xcompiled into an object file. Your program will then link in this object
Xfile at the same time it links in the toolbox interface. When you receive
Xthe SimpleTools source, you should compile it into SimpleTools.o. You can
Xthen compile the demo, SimpleDemo, and link it to SimpleTools.o.
X
XFor example, lets say you want the menu items named "Zoom" and "Widen"
Xunder the menu "View". You would like the procedure:
X
X zoom()
X {
X zoomfactor++;
X }
X
Xto be executed when the user selects Zoom and:
X
X widen()
X {
X zoomfactor--;
X }
X
Xto execute when Widen is selected. You would both create the menus on the
Xmenu bar AND inform SimpleTools what to do with the calls:
X
X menu ("View", "Zoom", zoom);
X menu ("View", "Widen", widen);
X
XThen, your program would run by repeatedly calling SimpleEvents, like:
X
X main()
X {
X setup();
X for (;;) SimpleEvents();
X }
X
XSeveral other features are included in SimpleTools:
X
X1. Window creation with assignment of procedures to be executed on window
Xactivation, deactivation, when the mouse is clicked in it, and when an
Xupdate occurs.
X
X2. Assignment of procedures to be "run" each time SimpleEvents() is
Xcalled. This can easily make it look like multi-subroutines are running
Xconcurrently.
X
X3. Generic prompt() and message() routines which pop up a small dialog box
Xfor you. For example:
X
X prompt("What is your name?", answer)
X
Xis all yo have to do to get a dialog box up requesting the user's name.
XThe answer goes into the string answer.
X
X4. Automatic setup of the Apple, File, and Edit menu so even your simplest
Xof programs will still have Desk Accessories.
X
X5. Many, many, hidden options that you will never know about unless you
Xcare to know about them. (This was a major design goal of SimpleTools--
Xhide options and use the most common default.)
X
XThis has just been a summary of the SimpleTools routines. I'm sure you
Xcould find them very useful. Many users of SimpleTools have been very
Xpleased with this idea and have saved many hours of studying and
Xprogramming. To those people, thanks for your letters, they are very
Xhighly appreciated.
X
X Erik
X
XP.S. If you don't have access to the network library, feel free to send a
Xself-addressed, stamped envelope and a disk (full of any goodies you have)
Xto Erik Kilk, 1325 Nord Ave #155, Chico, CA 95926, and I'll copy my master
Xdisk for you.
________This_Is_The_END________
if test `wc -l < STools.info` -ne 84; then
echo 'shar: STools.info was damaged during transit'
echo ' (should have been 84 bytes)'
fi
fi ; : end of overwriting check
echo 'Extracting SimpleDemo.c'
if test -f SimpleDemo.c; then echo 'shar: will not overwrite SimpleDemo.c'; else
sed 's/^X//' << '________This_Is_The_END________' > SimpleDemo.c
X
X/*
X Title : SimpleDemo.c
X Author : Erik Kilk
X Date : June 9, 1985
X Revised : July 17, 1985
X
X Synopsis: A demonstration of the use of SimpleTools with
X other toolbox calls. This demonstrates a very
X advanced use of SimpleTools. I've always disliked
X being given simple examples. So, this example
X uses many, many optional features of SimpleTools.
X
X The SimpleTools routines are being freely distributed.
X You may use them, distribute your applications which use them,
X and copy them if you send $10 or more to:
X
X Erik Kilk
X 325 San Leandro Way
X San Francisco, CA 94127
X
X Link this demonstration program with SimpleTools.o.
X
X*/
X
X#define TRUE -1 /* Common boolean constants */
X#define FALSE 0
X
X/*******************************/
X/* INCLUDE FILES FOR TOOLBOX */
X/*******************************/
X
X#include <qd.h>
X#include <event.h>
X#include <mem.h>
X#include <font.h>
X#include <qdvars.h>
X#include <misc.h>
X#include <win.h>
X#include <string.h>
X#include <stdio.h>
X
X/***********************************************/
X/* DEFINITIONS FOR THE SIMPLETOOLS MENU CALL */
X/***********************************************/
X
X#define itemdisable 0L
X#define itemenable 1L
X#define itemcheck 2L
X#define itemuncheck 3L
X
X/**************************************/
X/* GLOBAL VARIABLES AND FUNCTIONS */
X/**************************************/
X
Xint circspeed = 50; /* rate of drawing new circles */
Xint ourpensize = 1; /* global pen size instead of windows */
Xrect drag; /* for moving our free mem manually */
X
Xextern windowptr windowpoint(); /* defined in SimpleTools */
Xextern char applestring[]; /* defined in SimpleTools */
Xextern int windmenu; /* defined in SimpleTools */
Xextern int dogoaway; /* defined in SimpleTools */
Xextern int wprocid; /* defined in SimpleTools */
X
X/*********************/
X/* Odds and Ends */
X/*********************/
X
Xleave() /* Attached to the Quit menu */
X{
X exit(0);
X}
X
Xnop() /* Attached as a null pointer */
X{
X}
X
X/******************************/
X/* Clear the front window */
X/******************************/
X
Xourclear() /* attatched to Clear during sketching */
X{
X rect therect; /* rectangle to clear */
X if ((long)frontwindow() != 0L) { /* if there is a front window */
X setport (frontwindow()); /* set it for output */
X setrect ( &therect, 0, 0, 512, 400);/* make a rectangle */
X fillrect ( &therect, qdvars.qdwhite); /* erase the rectangle in window */
X }
X}
X
X/***********************/
X/* Sketch Window */
X/***********************/
X
Xsketactivate() /* Attached to sketch's activate */
X{ /* Disable the whole sketch menu */
X menu ("Sketch", "", itemenable);
X menu ("Edit", "Clear", ourclear); /* put our clear routine into place */
X}
X
Xsketdeactivate() /* Attached to sketch's deactivate */
X{ /* Enable the whole sketch menu */
X menu ("Sketch", "", itemdisable);
X menu ("Edit", "Clear", nop); /* take off our clear routine */
X}
X
Xsketch(x,y) /* follow mouse while it's down */
Xint x,y; /* we will get passed the mouse point */
X{
X point xy, lastxy; /* points of interest */
X windowptr ourport;
X
X getport (&ourport);
X pensize (ourpensize, ourpensize);
X moveto (x, y); /* position pen at mouse down point */
X while ( stilldown() ) { /* while the button is pressed */
X getmouse (&xy); /* read the mouse position */
X if ( (xy.a.v != lastxy.a.v) || (xy.a.h != lastxy.a.h) ) {
X lineto (xy.a.h, xy.a.v); /* if mouse moved, draw a line to it */
X lastxy.a.v = xy.a.v; /* record position so we can detect */
X lastxy.a.h = xy.a.h; /* a move. */
X } /* could runruns here to have circles */
X runruns(0L);
X setport (ourport);
X }
X}
X
Xsetpensize(size) /* Attached to pen size menus */
Xchar *size; /* menu item name given to us */
X{
X static char lastsize[5]={'1','\0'}; /* keep last setting */
X menu ("Sketch", lastsize, itemuncheck); /* remove old check mark */
X menu ("Sketch", size, itemcheck); /* install a new check mark */
X strcpy (lastsize, size); /* save size for the next setpensize */
X ourpensize = atoi (size); /* convert to a number */
X}
X
X/**************************/
X/* The Circles Window */
X/**************************/
X
Xint newabs(x) /* an absolute value funtion */
Xint x;
X{
X if (x < 0)
X x = -x;
X return (x);
X}
X
Xcircles() /* draw a random sized circle */
X{
X static windowptr wind = (windowptr) 0; /* keep "circle" windowptr */
X static int speed = 1; /* current count between new circles */
X register int cx, cy; /* center of the circle */
X int r, b, rd; /* right and bottom edges */
X register pattern *color; /* color for the circle */
X rect therect; /* rectangle to draw circle in */
X if ( --speed == 0) { /* count, and if it reaches zero... */
X speed = circspeed; /* reset the count */
X if ((long)wind == 0L) /* get window pointer if we need */
X wind = windowpoint ("Circles"); /* save window for next time */
X setport (wind); /* set output to the circle window */
X r = wind->portrect.a.right; /* get current size of window */
X b = wind->portrect.a.bottom;
X cx = newabs(random()) % (r-30) + 1; /* pick a random location */
X cy = newabs(random()) % (b-30) + 1;
X rd = newabs(random()) % 25 + 5; /* and size */
X setrect ( &therect, cx, cy, cx+rd, cy+rd); /* make a rectangle */
X switch ( newabs(random()) % 4) { /* pick a color */
X case 0: color = (pattern *)(&dkgray); break;
X case 1: color = (pattern *)(<gray); break;
X case 2: color = (pattern *)(&gray); break;
X case 3: color = (pattern *)(&black); break;
X }
X filloval ( &therect, color); /* make the circle */
X }
X}
X
Xsetspeed(name) /* attached to circle's menu */
Xchar *name;
X{
X menu ("Circles","Slow/S", itemuncheck); /* another way to uncheck last */
X menu ("Circles","Medium/M", itemuncheck); /* just uncheck everything */
X menu ("Circles","Fast/F", itemuncheck);
X menu ("Circles", name, itemcheck); /* then check the current */
X if (strcmp("Slow/S", name) ==0) circspeed = 100; /* set the reset count */
X else if (strcmp("Medium/M", name) ==0) circspeed = 50;
X else if (strcmp("Fast/F", name) ==0) circspeed = 1;
X}
X
X/***********************************************/
X/* Generate a new sketch window by command */
X/***********************************************/
X
Xnwindow() /* command to attatch to new window menu */
X{
X static topplace = 100; /* remember where to put next window */
X char newname[255]; /* string storage for window's name */
X strcpy (newname, "New Window"); /* default window name */
Xretry: /* prompt for the name from user */
X if (prompt ("Give me a unique name for the new window:", newname)) {
X if ( (long)windowpoint(newname) != 0L ) {
X if (message ("Sorry, a window by that name already exists."))
X goto retry; /* if exists, ask for another name */
X } else {
X if ( strlen(newname) > 0) { /* if ok, make the new window */
X /* then it is new */
X window (newname, 20,topplace, 200,topplace+60,
X sketactivate, sketdeactivate, nop, sketch);
X topplace += 5; /* adjust top for next new window */
X if (topplace > 300) topplace = 100; /* reset top if too low */
X }
X }
X }
X}
X
X/**********************/
X/* About SimpleDemo */
X/**********************/
X
Xusageinfo() /* messages for Usage Info menu choice */
X{
X char mess[255]; /* string to form a message */
X strcpy (mess,"You may use, distribute your programs which use, ");
X strcat (mess,"and copy SimpleTools if you send ");
X strcat (mess,"$10 or more to ...");
X if (message (mess)) { /* if OK pressed for first message */
X strcpy (mess, "Erik Kilk\r325 San Leandro Way\r");
X strcat (mess, "San Francisco, CA 94127");
X if (message (mess)) /* if OK pressed for 2nd message */
X message ("Thank you for your support."); /* show final message */
X }
X}
X
Xtellabout() /* for the About SimpleDemo menu choice */
X{
X char mess[255]; /* string to form a message */
X strcpy (mess,"SimpleDemo -- Copyright 1985 Erik Kilk\r");
X strcat (mess,"A demonstration of the use of SimpleTools");
X strcat (mess," as a Macintosh toolbox aid.");
X if (message (mess)) /* display the string in a dialog */
X usageinfo();
X}
X
X/**************************/
X/* The free memory window */
X/**************************/
X
Xwritemem(forsure) /* write the freemem value */
Xint forsure; /* true if force write */
X{ /* false if only on change */
X static long lastmem;
X long mem;
X int foo;
X char thestring[10], outstr[10];
X rect erasearea;
X mem = freemem(); /* get new free memory */
X foo = mem != lastmem; /* compare it to last reading */
X if ( forsure | foo ) { /* if forsure or different */
X withwindow ("FreeMem"); /* set window for output */
X setrect (&erasearea, 0, 0, 100, 20);
X eraserect (&erasearea); /* erase old value */
X moveto (0, 12); /* write new value */
X numtostring (mem, thestring);
X strcpy (outstr, " Free ");
X strcat (outstr, thestring);
X drawstring (outstr);
X lastmem = mem; /* record this for next time */
X }
X}
X
Xshowmem(windp) /* write freemem on an update */
Xwindowptr windp;
X{
X endupdate (windp); /* allow use of entire window */
X writemem(TRUE); /* clear and write new value */
X beginupdate (windp);
X}
X
Xnewmemvalue() /* write freemem occasionally */
X{
X writemem(FALSE); /* write only if value changed */
X}
X
X/* This is a special, non-standard, method of moving a window. Our
X free memory window does not have a title bar. So, I have decided
X to allow it to be moved if the mouse is clicked in its content
X region. This routine is attached to the free memory in content
X procedure with SimpleTools. SimpleTools convenienly gives us
X various parameters, here we need the window pointer and the event
X record. The event record has the coordinates of the mouse in
X globals */
X
Xmovemem(x,y,windp,event) /* free mem's incontent procedure */
Xint x,y; /* SimpleTools gives us these for */
Xwindowptr windp; /* an in-content procedure */
Xeventrecord *event;
X{
X dragwindow (windp, &(event->where), &drag);
X}
X
X/**********************/
X/* Initialization */
X/**********************/
X
Xsetup() /* to be called with Start Demo menu choice */
X{
X int temp;
X setrect (&drag, 4, 24, 508, 338); /* drag area for free mem window */
X windmenu = FALSE; /* modify default values, optional */
X dogoaway = FALSE; /* optional change */
X window("Circles", 20, 55, 245, 315,nop, nop, nop, nop); /* circles */
X temp = wprocid; /* save value for an optional change */
X wprocid = 3; /* optional change to set to altDBoxProc */
X window ("FreeMem", 407, 322, 497, 337, nop, nop, showmem, movemem);
X wprocid = temp; /* return to defaults */
X windmenu = TRUE;
X dogoaway = TRUE;
X window ("Sketch", 265, 55, 490, 315,sketactivate,sketdeactivate,
X nop, sketch); /* display the sketch pad window */
X menu ( applestring, "About SimpleDemo", tellabout);
X menu ( applestring, "About SimpleDemo", itemenable);
X menu ( "File", "New", nwindow); /* setup File menu */
X menu ( "File", "New", itemenable);
X menu ( "File", "Quit", leave);
X menu ("Circles", "Speed", itemdisable); /* install circles menu */
X menu ("Circles", "Slow/S", setspeed); /* optional key equivs */
X menu ("Circles", "Medium/M", setspeed);
X menu ("Circles", "Fast/F", setspeed);
X menu ("Circles", "Medium/M", itemcheck);
X menu ("Sketch", "Pen Size", itemdisable); /* install sketches menu */
X menu ("Sketch", "", itemdisable);
X menu ("Sketch", "1", setpensize);
X menu ("Sketch", "1", itemcheck);
X menu ("Sketch", "2", setpensize);
X menu ("Sketch", "3", setpensize);
X menu ("Sketch", "4", setpensize);
X menu ("Sketch", "5", setpensize);
X menu ("Sketch", "6", setpensize);
X run (circles); /* keep drawing circles */
X run (newmemvalue); /* check if mem changed occasionally */
X}
X
Xmain()
X{
X simpletools("About SimpleDemo"); /* setup Apple and Edit menus */
X setup(); /* setup our program */
X for (;;) simpleevents(); /* process events */
X}
________This_Is_The_END________
if test `wc -l < SimpleDemo.c` -ne 351; then
echo 'shar: SimpleDemo.c was damaged during transit'
echo ' (should have been 351 bytes)'
fi
fi ; : end of overwriting check
echo 'Extracting SimpleTools.c'
if test -f SimpleTools.c; then echo 'shar: will not overwrite SimpleTools.c'; else
sed 's/^X//' << '________This_Is_The_END________' > SimpleTools.c
X
X/*
X Title : SimpleTools.c
X Author : Erik Kilk Copyright 1985
X Date : June 7, 1985
X
X Version : 1.2
X Revisions:
X 09/05/85 EK Removed fix needed for a old compiler bug
X 07/13/85 EK Fixed menu unhilighting with D.A.'s menus.
X 07/16/85 EK Resettable default for new window type and has goaway.
X Included menu command key usage.
X 07/17/85 EK Removed menu changes to avoid flicker.
X Added return codes to most functions.
X Fixed in-content call from changing event record.
X
X Synopsis: A collection of subroutines to simplify programming
X the Macintosh in C. These are for those little programs
X you are tempted not to write because of all the hassles
X you have to go through writing programs for the Macintosh
X environment.
X
X Copyright: These routines are copyrighted by Erik Kilk. You
X may use them for your programming, as examples for your
X own programming, in your programs, in programs you
X distribute, copy them, and give copies to others who will
X abide by these rules if you send $10 or more to:
X Erik Kilk
X 325 San Leandro Way
X San Francisco, CA 94127
X You use this software "as is". The author make no
X promises and is not responsible nor liable for anything
X due to your use of these subroutines.
X
X Thank you for your support.
X
X
X Summary of User Routines:
X
X simpletools ("About SimpleTools"); Initialize
X simpleevents (); Process next event
X menu ("Search", "Find", findroutine); Add a menu
X window ("Sketch", 50,50,200,200,
X activate,deactivate,update,content); Add a window
X withwindow ("Sketch"); Set output to window
X run (routine); Periodically call a routine
X stop (routine); Stop periodic call
X message ("Welcome to SimpleTools"); Display dialog message
X prompt ("What is your name?", answer); Ask a question
X
X simpletools("Name");
X Call this once at the very beginning of your program. Pass
X it the name of your program if you want an "About Name" menu
X entry, otherwise pass it just "" as the name. It initializes
X the data structures used by SimpleTools. It also does all of
X the toolbox initializing and
X installs the Apple, File, and Edit menus. Only base pointers
X to linked structures and a few flags and scratch variables are
X set. All other data is dynamically allocated with relocatable
X blocks through the Macintosh memory manager for each new menu
X and window created with these SimpleTools routines.
X
X simpleevents();
X Repeatedly call this routine as fast as you can. Often this
X routine is in a for(;;) loop in the main procedure. This routine
X handles menu selection, desk accessory startups, window moves,
X window resizes, close-box clicks, all window events, and the
X periodic calling of routines. It will only handle menus, windows,
X and periodic routines installed with simpletools(), menu(),
X window(), and run().
X This routine does the systemtask() and getnextevent() calls
X so you don't have to process them yourself.
X At times simpleevents() will be looking up assigned procedures
X to be executed. These procedures are passed some of information
X particular to its situation. With Magamax C (and possibly others)
X the called procedure need not declare or use this passed data if
X it has no need for it. The kind of data passed is described below.
X For key down and autokey events, the procedures set in
X keydownproc and autokeyproc are passed the address to the event
X record. By default, keydownproc and autokeyproc are set to
X a no op procedure.
X
X menu ("Settings", "Trace Execution", hideproc );
X Call this routine for each menu to install or modify. The
X first argument is the menu bar title, the second is the item name,
X and the third is either the procedure to be executed when that
X item is selected or a modifier ( 0L, itemdisable; 1L, itemenable;
X 2L, itemcheck, 3L, itemuncheck). The first call with a particular
X menu/item pair will install the menu/item with either a procedure
X or modifier (in which case it is assigned a no op procedure.)
X Subseqent calls are used to change either the assigned procedure or
X the current active modifiers. Calling it with a null item name
X will disable or enable the entire menu if the menu already exists
X and the third parameter is either a 0L or 1L as listed above.
X Assigned procedures will be called with a (char *) pointing to
X the item name chosen.
X
X menuhandle mhand ("Settings");
X This function returns the handle to a given menu bar selection
X so that you can call the Menu manager routines yourself.
X
X window ("Trace Output", 256, 50, 500, 300, activateproc,
X deactivateproc, updateproc, incontentproc);
X Call this routine for each window to install or modify. The
X first argument is the window's name. Then the (x,y) of the top
X left corner and the (x,y) of the bottom right corner. These
X coordinates are only used for installing a window and will be
X ignored for subsequent calls. Then comes four procedure names.
X Activateproc is called when the window becomes the active window.
X Deactivate when another window is activated. Updateproc when
X windows have moved and the window needs redrawn. And incontentproc
X when the mouse is clicked inside the window.
X New windows are given a menu selection of their name under
X a menu bar title of "Windows." Menu() is used to install these.
X The procedure called for each window name is a procedure to
X bring back the window if it was closed by clicking its closebox or
X activate it (in case it is hidden and can't be clicked on.
X When the close-box of a window is clicked, the window is just
X hidden, it isn't really closed.
X The assigned "in content" procedure will be called with two
X (int)s. The x and y of the mouse position in that window's
X local coordinates. Each assigned window procedure is also called
X with a (windowptr) to the target window and an address to
X the event record which just occured. Before each is called,
X the current port is set to the target window.
X
X withwindow ("Trace Output");
X Call this routine to set the current output port to the
X asked for window. Remember that proper scrolling of text in the
X window is only taken care of for the active window though output
X can be to any window.
X
X windowptr windowpoint ("Trace Output");
X This function returns a pointer to the given window name in
X case you want to use one of the Window manager routines your
X self.
X
X run (flashsquareproc);
X Call this routine to install a procedure to be periodically
X executed. Up do 100 procedures may be installed at once. These
X procedure are called just after each i/o event is read. They are
X called with the address of the current unprocessed eventrecord.
X
X stop (flashsquaresproc);
X Call this to remove a procedure from the list of procedures
X running periodically as installed with run().
X
X message ("Are you sure you want to quit?");
X Puts up a dialog with your message and an OK and Cancel
X button. Returns true if OK is clicked, false if Cancel hit.
X Memory for the dialog is allocated when it is put up and
X returned to the heap when a button is clicked.
X
X prompt ("What is your name?", answer);
X Where answer is a string set to a default value. Puts up
X a dialog with your question, an editable answer field with you
X default answer, the OK and Cancel buttons. Returns true when
X OK or RETURN is entered, false if Cancel is clicked.
X*/
X
Xoverlay "simpletools" /* remove or change this if needed */
X
X#include <mem.h> /* include type defs and constants */
X#include <qd.h> /* for the Macintosh tool box */
X#include <qdvars.h>
X#include <misc.h>
X#include <event.h>
X#include <res.h>
X#include <win.h>
X#include <te.h>
X#include <dialog.h>
X#include <menu.h>
X#include <string.h>
X#include <stdio.h>
X
X#define TRUE (-1) /* local definitions */
X#define FALSE 0
X#define itemdisable 0 /* constants for menu modifiers */
X#define itemenable 1
X#define itemcheck 2
X#define itemuncheck 3
X#define maxsruns 50 /* procedure table size */
X#define MESSN 30 /* array size for message dialog items */
X#define QUESN 40 /* array size for prompt dialog items */
X
Xtypedef struct { /* structure for an item */
X char itemname[40]; /* to allow reference by name */
X int itemno; /* item number within menu */
X int menuid; /* menu id in case menu info is needed */
X menuhandle menuhand; /* item's menu's handle */
X procptr menurun; /* procedure to run */
X ptr next; /* pointer to the next item */
X} itemdatum;
X
Xtypedef struct { /* structure for a menu */
X char menuname[20]; /* to allow reference by name */
X int menuid; /* menu id used to create the menu */
X menuhandle menuhand; /* menu handle used to reference menu */
X itemdatum **itemlist; /* pointer to the list of items */
X ptr next; /* pointer to the next menu */
X} menudatum;
X
Xtypedef struct { /* structure for a window */
X char windname[80]; /* the window's name and reference */
X windowptr wptr; /* the window's pointer reference */
X procptr wact; /* the activate procedure */
X procptr wdeact; /* the deactivate procedure */
X procptr wupdate; /* the update procedure */
X procptr wcontent; /* the content procedure */
X ptr next; /* pointer to the next window */
X} winddatum;
X
Xmenudatum **simplemenus; /* handle to menu data */
Xchar accname[80]; /* desk accessory name to open */
Xrect dragrect, sizerect; /* limits for moving windows */
Xint wprocid = documentprod; /* window procedure id */
Xint dogoaway = TRUE; /* if window has go away box */
Xwinddatum **simplewinds; /* handle to window data */
Xint firstwind; /* true if no windows have been made */
Xprocptr keydownproc,
X autokeyproc; /* routines for key down events */
Xprocptr simpleruns[maxsruns]; /* list of procedures to run */
Xchar applestring[2]
X = {'\024', '\0'}; /* name of apple menu */
Xwindowptr debugw; /* a window pointer for debugging */
Xint windmenu = TRUE; /* whether or not a window menu is made */
X
X/******************************************************************/
X/* Dialog lists. These were calculated by using the new resource */
X/* editor to make a template for a dialog and then using fedit to */
X/* list the hex listing of the item list for the dialog. */
X/******************************************************************/
X
Xint messd[MESSN] = {2,0,0,0x38,0xf1,0x4c,0x12d,0x402,0x4f4b,0,0,5,5,
X 0x36,0x12d,0x800,0,0,0x38,0xac,0x4c,0xe8,0x406,
X 0x4361,0x6e63,0x656c};
Xint quesd[QUESN] = {3,0,0,0x21,0xf0,0x35,0x12c,0x402,0x4f4b,0,0,8,8,
X 0x28,0xe8,0x800,0,0,0x2b,8,0x4b,0xe8,0x1000,0,0,
X 8,0xf0,0x1c,0x12c,0x406,0x4361,0x6e63,0x656c};
X
Xstnop() /* a no op procedure for defaults */
X{
X}
X
X/* Given a menu name, find our data structure for it. Return a handle
X to this structure.
X*/
X
Xmenudatum **getourmenuhandle (name)
Xchar *name; /* name of menu bar menu */
X{
X menudatum **here; /* a handle to our menu structure */
X here = simplemenus;
X
X /* find the menu name or the end of out menu list */
X while ( (strcmp(name,(**here).menuname) != 0) &
X ((**here).next != (ptr)0L) )
X here = (menudatum **)(**here).next;
X
X /* see if we found it or just the end of the list */
X if (strcmp(name,(**here).menuname) == 0)
X return (here);
X else
X return ((menudatum **)0L); /* return 0 if not found */
X}
X
X/* Given a menu name, return the real menu handle as used by most
X of the Macintosh toolbox menu manager routines.
X*/
X
Xmenuhandle mhand (name) /* find menuhandle */
Xchar *name; /* given name of menu */
X{
X menudatum **menu; /* a handle to our data */
X menu = getourmenuhandle(name);
X if ( (long) menu != 0L )
X return ( (**menu).menuhand); /* return menu handle */
X else
X return ( (menuhandle) 0 ); /* return 0 if not found */
X}
X
X/* This takes a handle to our personal item record and either a
X procedure name or a modifier code. If it got a procedure name,
X it sets it to the item's procedure to run when the item is chosen.
X If it got a modifier code, it changes the state of the menu's item
X to checked, unchecked, enabled, or disabled. It especially keeps
X track of the standard Edit menu items so we can restore them after
X a desk accessory is finished.
X*/
X
Xsetitem ( items, routine) /* set a menu item's routine or display */
Xitemdatum **items; /* if items is neg, then whole menu */
Xprocptr routine;
X{
X int inumber;
X menuhandle mhand;
X
X /* check to see if a procedure pointer was given to us */
X if ( (((long)items)>0L) && (routine > (procptr)0x1000L)) {
X /* a good procedure value */
X (**items).menurun = routine;
X return;
X }
X
X /* Calculate which item number we are going to modify */
X if ( (long)items < 0L) { /* the whole menu */
X mhand = (menuhandle) (0L - (long)items);
X inumber = 0;
X }
X else { /* just one item */
X mhand = (**items).menuhand;
X inumber = (**items).itemno;
X }
X
X /* If a NULL procedure pointer, then set to a no_op routine */
X if ( (inumber > 0) && ((**items).menurun == (procptr)0L) )
X (**items).menurun = stnop;
X
X /* Now change the state of a menu item */
X switch ((int)routine) {
X case itemdisable:
X disableitem(mhand,inumber); break;
X case itemenable:
X enableitem(mhand, inumber); break;
X case itemcheck:
X checkitem(mhand, inumber, TRUE); break;
X case itemuncheck:
X checkitem(mhand, inumber, FALSE); break;
X }
X if (inumber == 0) drawmenubar(); /* if main menu was changed */
X
X}
X
X/* This routine is described above. It takes care of our menu data
X structure by adding or modifying menu entries.
X*/
X
Xmenu (name, item, routine) /* install or change a menu */
Xchar *name; /* the menu name */
Xchar *item; /* the item name */
Xchar * routine; /* a procedure or modifier */
X{
X menudatum **here; /* a roving handle to our data */
X menudatum **ourmhandle; /* another handle to our data */
X itemdatum **items; /* a handle to the item */
X menuhandle mhandle; /* a handle to the real menu */
X int lastid, lastitem;
X
X /* get the handle to menu named 'name' */
X if ((ourmhandle = getourmenuhandle (name)) == 0L) {
X
X /* make a new menu entry by finding the end of the list */
X here = simplemenus;
X while ((**here).next != 0L)
X here = (menudatum **)(**here).next;
X
X /* make a structure for our new entry */
X lastid = (**here).menuid;
X (**here).next = (ptr)newhandle ( (long)sizeof(menudatum));
X here = (menudatum **)(**here).next;
X strcpy ( (**here).menuname, name);
X (**here).menuid = ++lastid;
X (**here).next = (ptr) 0L;
X
X /* make a new item structure */
X (**here).itemlist = (itemdatum **)newhandle (
X (long)sizeof(itemdatum));
X
X /* make a new menu entry for the Macintosh */
X (**here).menuhand = newmenu (lastid, name);
X mhandle = (**here).menuhand;
X items = (**here).itemlist;
X strcpy ((**items).itemname, item);
X (**items).itemno = 1;
X (**items).menuid = lastid;
X (**items).menuhand = (**here).menuhand;
X (**items).menurun = (procptr) 0L;
X (**items).next = 0L;
X
X /* install and display the menu */
X appendmenu ((**here).menuhand, item);
X insertmenu ((**here).menuhand,0);
X setitem (items, routine);
X drawmenubar();
X return(TRUE);
X }
X else {
X if (strlen(item) == 0) {
X /* then adjust main menu */
X setitem( 0L - (long) ((**ourmhandle).menuhand), routine);
X return(FALSE);
X }
X /* see if item is in list */
X items = (**ourmhandle).itemlist;
X while ( (strcmp(item,(**items).itemname) != 0) &
X ((**items).next != (ptr)0L)) {
X items = (itemdatum **)(**items).next;
X }
X if (strcmp(item,(**items).itemname) ==0) {
X setitem( items, routine);
X return(FALSE);
X }
X else {
X /* make new item entry */
X lastitem = (**items).itemno;
X (**items).next =(ptr)newhandle(
X (long)sizeof(itemdatum));
X items = (itemdatum **)(**items).next;
X strcpy ((**items).itemname, item);
X (**items).itemno = ++lastitem;
X (**items).menuid = (**ourmhandle).menuid;
X (**items).menuhand = (**ourmhandle).menuhand;
X (**items).menurun = (procptr) 0L;
X (**items).next = 0L;
X
X /* and install the item in the menu bar */
X appendmenu ((**ourmhandle).menuhand,item);
X setitem (items, routine);
X return(TRUE);
X }
X }
X}
X
X/* This routine is called by the simpletools() initial routine. It gets
X the pointer list of menus started, loads the desk accessories into
X the Apple menu, and loads up some standard menu entries. The reason
X menu File has a New entry, and none others, is because as this code
X currently stands, a menu must have at least one item. And since we
X want File before Edit, I had to make an entry. The most commonly used
X item under File is Quit. But we like quit to be at the end of the list.
X So, since New is usually always first when it is used, that the one
X chosen to start File.
X*/
X
Xinitsmenus(about) /* init simpletools' menus */
Xchar *about;
X{
X itemdatum **items;
X simplemenus = (menudatum **) newhandle ( (long)sizeof(menudatum));
X strcpy ( (**simplemenus).menuname, applestring);
X (**simplemenus).menuid = 1;
X (**simplemenus).next = (ptr) 0L;
X (**simplemenus).menuhand = newmenu (1, (**simplemenus).menuname);
X (**simplemenus).itemlist = (itemdatum **)newhandle (
X (long)sizeof(itemdatum));
X items = (itemdatum **) (**simplemenus).itemlist;
X strcpy ((**items).itemname, about);
X (**items).itemno = 1;
X (**items).menuid = 1;
X (**items).menuhand = (**simplemenus).menuhand;
X (**items).menurun = stnop;
X (**items).next = 0L;
X appendmenu ((**simplemenus).menuhand, about);
X disableitem ((**simplemenus).menuhand, 1);
X menu (applestring, "-", (procptr) itemdisable);
X addresmenu ((**simplemenus).menuhand, "DRVR");
X insertmenu ((**simplemenus).menuhand, 0);
X menu ("File", "New", (procptr)itemdisable);
X menu ("Edit", "Undo", stnop);
X menu ("Edit", "-", (procptr)itemdisable);
X menu ("Edit", "Cut/X", stnop);
X menu ("Edit", "Copy/C", stnop);
X menu ("Edit", "Paste/V", stnop);
X menu ("Edit", "Clear", stnop);
X}
X
X/* Given a window's name, return its window pointer so that other
X Macintosh Window Manager routines can be called for that window. */
X
Xwindowptr windowpoint(name) /* get window pointer */
Xchar *name; /* given window's name */
X{
X winddatum **wind; /* handle to our window data */
X if (firstwind) return ((windowptr)0); /* forget if there aren't any */
X wind = simplewinds; /* look for the named window */
X while ( (strcmp ((**wind).windname, name) != 0) &
X ((**wind).next != (ptr) 0)) {
X wind = (winddatum **) (**wind).next;
X }
X if ( strcmp ((**wind).windname, name) ==0)
X return ( (**wind).wptr); /* return pointer */
X else
X return ( (windowptr) 0); /* or zero if it wasn't found */
X}
X
X/* This routine is for the Windows menu item. The Windows menu is
X set up when new windows are added. It is used to bring forward and
X bring into view windows that may be under other windows or have been
X sent hiding by a click on their close box.
X*/
X
Xshowawindow(name) /* show the named window */
Xchar *name;
X{
X windowptr foo;
X foo = windowpoint(name); /* get its window pointer */
X if ( (long)foo != 0L ) {
X showwindow(foo); /* show it on the screen */
X setport (foo); /* set further output to it */
X if ( foo != frontwindow()) /* if it isn't active, */
X selectwindow (foo); /* activate it */
X }
X}
X
X/* This routine installs a new window onto the screen. It also gives
X that window an item in the Window menu. This routine is also used
X to modify a window's associated routines. The x,y positions are the
X top left and bottom right corners of where the window should originally
X be placed. The coordinates are never used when this routine is called
X to update an already existing window. But the spaces must be filled,
X so you can use zeros if you want. Once the window has been displayed in
X its original position, the user has complete control of its size and
X placement with the mouse.
X*/
X
Xwindow(name, xtop, ytop, xbot, ybot, a, d, u, c)
Xchar *name; /* window's name */
Xint xtop, ytop, xbot, ybot; /* position if this is a new window */
Xprocptr a, d, u, c; /* activate, deactivate, update, and */
X{ /* content procedure names */
X winddatum **wind; /* handle to our window data */
X winddatum **newentry; /* another handle */
X rect newplace; /* a rectable for the window's placement */
X if (a == (procptr) 0)
X a = stnop;
X if (d == (procptr) 0)
X d = stnop;
X if (u == (procptr) 0)
X u = stnop;
X if (c == (procptr) 0)
X c = stnop;
X if ( !firstwind ) {
X
X /* see if window is in the list */
X wind = simplewinds;
X while ( (strcmp ((**wind).windname, name) != 0) &
X ((**wind).next != (ptr) 0)) {
X wind = (winddatum **) (**wind).next;
X }
X if ( strcmp ((**wind).windname, name) ==0) {
X
X /* reset the found window's parameters */
X (**wind).wact = (procptr) a;
X (**wind).wdeact = (procptr) d;
X (**wind).wupdate = (procptr) u;
X (**wind).wcontent = (procptr) c;
X setport ( (**wind).wptr); /* set output to window */
X return(FALSE);
X }
X }
X
X /* make a new window entry */
X newentry = (winddatum **)newhandle ( (long) sizeof (winddatum));
X if (firstwind)
X simplewinds = newentry;
X else
X (**wind).next = (ptr) newentry;
X firstwind = 0;
X strcpy ((**newentry).windname, name);
X setrect (&newplace, xtop, ytop, xbot, ybot);
X (**newentry).wptr = newwindow (0L, &newplace, name, -1,
X wprocid, -1L, dogoaway, newentry);
X (**newentry).wact = (procptr) a;
X (**newentry).wdeact = (procptr) d;
X (**newentry).wupdate = (procptr) u;
X (**newentry).wcontent = (procptr) c;
X (**newentry).next = (ptr) 0;
X if (windmenu)
X menu ("Windows", name, showawindow);/* make a menu entry for it */
X setport ( (**newentry).wptr); /* set output to it */
X return(TRUE);
X}
X
Xwinddatum **wdatum(windpt) /* return handle to window data */
Xwindowptr windpt;
X{
X winddatum **wind;
X if (firstwind) return ((winddatum **) 0L);
X wind = simplewinds;
X while ( ((**wind).wptr != windpt) & /* search for window's name */
X ((**wind).next != (ptr) 0)) {
X wind = (winddatum **) (**wind).next;
X }
X if ( (**wind).wptr == windpt)
X return (wind);
X else
X return ((winddatum **) 0L); /* zero if not found */
X}
X
Xwithwindow(name) /* set output to a window by name */
Xchar *name; /* give it the window's name */
X{ /* returns boolean if window exists */
X winddatum **wind;
X wind = simplewinds;
X if (firstwind) return(FALSE); /* search for the window's name */
X while ( (strcmp ((**wind).windname, name) != 0) &
X ((**wind).next != (ptr) 0)) {
X wind = (winddatum **) (**wind).next;
X }
X if ( strcmp ((**wind).windname, name) ==0) {
X setport ( (**wind).wptr); /* set output to it */
X return(TRUE);
X }
X else
X return(FALSE);
X}
X
X/* This run procedure is used to install routines to be occasionally
X run. The routine will be run once for each call to simpleevents()
X*/
X
Xrun(routine) /* install a run procedure */
Xprocptr routine; /* give it the procedure */
X{ /* return TRUE if successful */
X int i;
X i = 0; /* add it to the end of the list */
X while ( simpleruns[i] != (procptr) 0L) i++;
X if (i < maxsruns) {
X simpleruns[i] = routine;
X simpleruns[i+1] = (procptr) 0L;
X return(TRUE);
X }
X else
X return(FALSE);
X}
X
X/* This routine removes a procedure from the list of run procedures */
Xstop(routine) /* stop a procedure from running */
Xprocptr routine; /* give the procedure */
X{ /* return TRUE if successful */
X int i;
X i = 0;
X while ( (simpleruns[i] != routine) & (simpleruns[i] != (procptr) 0L))i++;
X if (simpleruns[i] == (procptr) 0L)
X return(FALSE);
X else {
X while ( simpleruns[i] != (procptr)0 ) {
X simpleruns[i] = simpleruns[i+1];
X i++;
X }
X return(TRUE);
X }
X}
X
Xrunruns(event) /* run all the installed run procedures */
Xeventrecord *event; /* returns number of routines run */
X{
X int i;
X i = 0;
X while ( simpleruns[i] != 0 )
X (*(simpleruns[i++])) (event);
X return(i);
X}
X
Xstdialog( question, answer, type) /* a general dialog displayer */
Xchar *question;
Xchar *answer;
Xint type; /* type: 1=prompt, 2=message */
X{
X dialogptr dialog; /* dialog reference */
X handle item, items; /* handles for the dialog items */
X rect screen, box; /* rectangles for dialog/items */
X int dtype, hit, canc; /* item type and which was hit */
X char tempanswer[255]; /* address where answer is */
X
X items = newhandle (512L); /* get memory for items list */
X hlock (items); /* lock it down */
X if (type == 1)
X blockmove (quesd, *items, (long) QUESN * 2L); /* fill it with list */
X else
X blockmove (messd, *items, (long) MESSN * 2L);
X setrect (&screen, 103, 50, 409, 137); /* position window */
X dialog = newdialog (0L, &screen, "", 0, dboxproc, -1L, 0, 0L, items);
X getditem (dialog, 2, &dtype, &item, &box); /* get item#2 handle */
X setitext (item, question); /* set item#2 text */
X if (type == 1) { /* set default answer */
X getditem (dialog, 3, &dtype, &item, &box);
X setitext (item, answer);
X canc = 4;
X }
X else
X canc = 3;
X showwindow (dialog); /* display the dialog */
X do {
X modaldialog (0L, &hit); /* process the dialog */
X } while ( (hit != 1) & (hit != canc) );
X if (type == 1) {
X getditem (dialog, 3, &dtype, &item, &box); /* get item#3 handle */
X hlock (item);
X getitext (item, tempanswer); /* get item#3 text */
X strcpy (answer, tempanswer); /* make a copy of it */
X hunlock (item);
X }
X hunlock(items); /* unlock items memory */
X hpurge(items); /* purge it */
X disposdialog (dialog); /* get rid of dialog */
X return ( hit==1 ); /* return true if ok */
X}
X
Xprompt ( question, answer) /* dialog box question/answer */
Xchar *question;
Xchar *answer;
X{
X return (stdialog (question, answer, 1));
X}
X
Xmessage ( message ) /* dialog box message */
Xchar *message;
X{
X return (stdialog (message, message, 2));
X}
X
Xdocommand (which, thisevent)
Xlong which;
Xeventrecord *thisevent;
X{
X int themenu, theitem;
X long size;
X char *cpoint;
X grafptr tempport;
X menudatum **here;
X itemdatum **items;
X char **myreshandle;
X handle myhandle;
X themenu = hiword (which);
X theitem = loword (which);
X if ((themenu == 1) && (theitem != 1)) {
X /* start up a desk accessory */
X getitem ((**simplemenus).menuhand,
X theitem, accname);
X setresload (FALSE);
X myreshandle = getnamedresource ("DRVR", accname);
X setresload (TRUE);
X size = sizeresource (myreshandle);
X myhandle = newhandle ( size + 3072L);
X if (myhandle == 0L)
X message ("Not enough memory to do that.");
X else {
X disposhandle (myhandle);
X getport (&tempport);
X opendeskacc(accname);
X setport (tempport);
X }
X return;
X }
X if (themenu ==3) {
X /* do any system edits */
X if (systemedit(theitem -1) != FALSE)
X return;
X }
X
X /* now we run an installed menu procedure */
X here = simplemenus;
X
X /* find out menu structure given the menu id */
X while ( ((**here).menuid != themenu) &
X ((**here).next != (ptr)0L) )
X here = (menudatum **)(**here).next;
X
X if ((**here).menuid == themenu) {
X /* now find the item structure */
X items = (**here).itemlist;
X while ( ((**items).itemno != theitem) &
X ((**items).next != (ptr) 0L) )
X items = (itemdatum **)(**items).next;
X
X /* prepare to give the item name to the procedure */
X cpoint = (**items).itemname;
X if ((**items).itemno == theitem)
X /* if we found the item, call its procedure */
X (*((**items).menurun))(cpoint,thisevent) ;
X }
X}
X
Xdomousedown(thisevent) /* respond to mouse down events */
Xeventrecord *thisevent; /* passed the event record */
X{
X windowptr whichwindow;
X int code, x, y;
X char *cpoint;
X menudatum **omhand;
X winddatum **thewdatum;
X long newplace;
X point temp;
X code = findwindow(&(thisevent->where), &whichwindow);
X switch (code) {
X case inmenubar:
X docommand(menuselect(&(thisevent->where)),thisevent);
X break;
X case insyswindow:
X systemclick(thisevent, whichwindow); break;
X case indrag:
X dragwindow(whichwindow, &(thisevent->where),
X &dragrect); break;
X case ingrow:
X newplace= growwindow(whichwindow, &(thisevent->where),
X &sizerect);
X sizewindow(whichwindow, loword(newplace),
X hiword(newplace), TRUE);
X break;
X case ingoaway:
X if ( trackgoaway(whichwindow, &(thisevent->where))) {
X hidewindow (whichwindow);
X }
X break;
X case incontent:
X
X /* make the window active if it isn't yet */
X if (whichwindow != frontwindow()) {
X selectwindow(whichwindow);
X }
X
X /* find our window data */
X thewdatum = wdatum (whichwindow);
X if ((long) thewdatum != 0L) {
X
X /* convert the point of click to the window's
X own coordinates since this will be always
X more useful than the global coordintates */
X temp = thisevent->where;
X setport (whichwindow);
X globaltolocal (&temp);
X x = temp.a.h;
X y = temp.a.v;
X
X /* call the window's in content routine */
X (*((**thewdatum).wcontent))(x, y, whichwindow,
X thisevent);
X }
X break;
X }
X}
X
Xsimpletools(about) /* to be called at the beginning of program */
Xchar *about;
X{
X maxapplzone(); /* allow maximum heap expansion */
X flushevents (everyevent,0); /* ignore left over events */
X initgraf (&theport); /* initialize the screen */
X initfonts();
X initwindows();
X initmenus();
X initcursor(); /* make the arrow cursor */
X teinit();
X initdialogs(0L);
X setrect ( &sizerect, 20, 50, 250, 330);
X /*
X debugw = newwindow(0L,&sizerect,"Debug",-1,documentproc,-1L,-1L,0L);
X */
X simpleruns[0] = (procptr) 0; /* empty the run list */
X /* These are the bounds we are allowed to size a window or
X move a window to.
X */
X setrect ( &sizerect, 20, 20, 511, 341);
X setrect ( &dragrect, 4, 24, 507, 337);
X firstwind = 1; /* empty window table */
X keydownproc = stnop; /* default key hit procedures */
X autokeyproc = stnop;
X initsmenus(about); /* install the menus */
X}
X
Xsimpleevents() /* to be called in the main loop */
X{
X eventrecord newevent;
X winddatum **thewdatum;
X systemtask(); /* Do the system D.A. etc. stuff */
X hilitemenu(0);
X getnextevent(everyevent, &newevent);
X runruns(&newevent); /* Do our run procedures */
X switch (newevent.what) {
X case mousedown:
X domousedown(&newevent); break;
X case keydown:
X if ((newevent.modifiers & cmdkey) != 0)
X docommand(menukey((char)(newevent.message & 0xffL)),
X &newevent);
X (*(keydownproc))(&newevent);
X break;
X case autokey:
X if ((newevent.modifiers & cmdkey) != 0)
X docommand(menukey((char)(newevent.message & 0xffL)),
X &newevent);
X (*(autokeyproc))(&newevent);
X break;
X case activateevt:
X thewdatum = wdatum(newevent.message);
X if ((long)thewdatum != 0L) {
X setport(newevent.message);
X if ((newevent.modifiers & 1) == 1) {
X (*((**thewdatum).wact))(newevent.message,
X &newevent);
X }
X else {
X (*((**thewdatum).wdeact))(newevent.message,
X &newevent);
X }
X }
X break;
X case updateevt:
X thewdatum = wdatum(newevent.message);
X if ((long)thewdatum != 0L) {
X setport (newevent.message);
X beginupdate (newevent.message);
X (*((**thewdatum).wupdate))(newevent.message,
X &newevent);
X endupdate (newevent.message);
X }
X break;
X }
X}
X
________This_Is_The_END________
if test `wc -l < SimpleTools.c` -ne 911; then
echo 'shar: SimpleTools.c was damaged during transit'
echo ' (should have been 911 bytes)'
fi
fi ; : end of overwriting check
echo 'Extracting SimpleTools.doc'
if test -f SimpleTools.doc; then echo 'shar: will not overwrite SimpleTools.doc'; else
sed 's/^X//' << '________This_Is_The_END________' > SimpleTools.doc
X
X
XSimpleTools
X
XCopyright (c) 1985 Erik Kilk
X
X
X
X
X
XWhat is SimpleTools?
X
XSimpleTools is a collection of subroutines (presently written for the C
Xlanguage) to aid the programmer in using the most common of the
XMacintosh user interfaces: menus, windows, mouse control, and dialogs.
XIts purpose is to allow the programmer to get on with programming
Xhis/her application without spending much effort on how to incorporate
Xthe standard Macintosh user interfaces into the application. It was
Xdesigned mainly to allow you to program those simple little programs
Xwhich you are tempted not to write due to all the work needed to make a
Xprogram look like a Macintosh program. It is not intended for use in large,
Xcomplicated programs which may need a larger variety of display
Xinterfaces.
X
X
X
XDue to the slowness of a human user in selecting menus and manipulating
Xwindows, SimpleTools is not noticably slow. It was not intended to be
Xefficient for the user, but rather easy for the programmer to use. Aren't
Xyou tired of constantly looking up how to use so-and-so routine in Inside
XMacintosh? Menus and windows are referenced by name, not by a number
Xor complex data structure. One routine, simpleevents(), processes the next
XMacintosh event, including calling the appropriate routine when a menu or
Xwindow is selected. Most of the other routines are used to "install" menus
Xand windows so that simpleevents() knows what to do.
X
X
X
XCopyright and Usage Info
X
XSimpleTools is supplied AS IS with absolutely no warrenties, promises, or
X
Xliability from or to the author. You may use, copy, give others copies of,
Xand sell applications developed with SimpleTools after submitting a $10
Xor more fee to:
X
X Erik Kilk
X
X 325 San Leandro Way
X
X San Francisco, CA 94127
X
X
X
XSummary of SimpleTools
X
XThe purpose of SimpleTools is to aid the use of the Macintosh user
Xinterface. The routines take care of most of the work needed to maintain
Xwindows and menus. It is intended to be most effectively used in tandom
Xwith the Macintosh toolbox routines.
X
X
X
XSimpleTools works by maintaining several "lists of things to do" when
Xcertain events occure. The programmer must supply the procedure to do
Xfor certain events. To document this procedure, a step-by-step tutorial
Xtype discussion will be given. Please note that NOT EVERYTHING useful to
Xknow about SimpleTools is contained here. This is meant to get you
Xstarted. Please take a look at the source code, SimpleTools.c, for more
Xadvanced usages.
X
X
X
XPlease report SimpleTools bugs to Erik Kilk, 325 San Leandro Way, San
XFrancisco, CA 94127.
X
X
X
XThe Main SimpleTools' Routines
X
X simpletools() -- install the apple, file, and edit menus
X
X menu() -- install your own menu
X
X window() -- install your own window
X
X withwindow() -- send output to your window
X
X run() -- install a routine to run periodically
X
X stop() -- remove a routine from the "run" list
X
X message() -- display a message in a dialog box
X
X prompt() -- ask a question, get an answer in dialog
X
X simpleevents() -- handle all events
X
X
X
XReferences to all menus and windows are by a string containing the name
X
Xof the menu, item, or window. There is no need to remember such things
X
Xas menu ids, item ids, menu handles, and window pointers.
X
X
X
XHow to Use SimpleTools
X
XFor the following discussion, assume the following main() routine is
Xcoded:
X
X main()
X
X {
X
X simpletools("Documentation Tutorial");
X
X mysetup();
X
X for (;;) simpleevents();
X
X }
X
XThis is a typical main() routine while using SimpleTools. We will now
X
Xdiscuss what is happening.
X
X
X
XAfter you have compiled your program, you must use your linker to link
XSimpleTools.o to your object file.
X
X
X
Xsimpletools("Documentation Tutorial");
X
XThis routine initializes the other SimpleTools routines. It must be called
X
Xbefore any other SimpleTools routines are called. It is called with the
X
Xname of the menu item to appear just under the apple menu (usually this
X
Xwill be something like "About MyProgram").
X
X
X
XThe apple, file, and edit menus will be installed and displayed on the
X
Xmenu bar. Under the apple menu will be the name you supplied (disabled),
X
Xa dashed line (disabled), and the available desk accessories. Under the
X
Xfile menu will be the item "New" disabled. Under the edit menu will be
X
Xundo, a dashed line (disabled), cut, copy, paste, and clear.
X
X
X
X
X
XWhat Can Go In or Replace MySetup()
X
XBefore you start repeatedly calling simpleevents(), you'll probably want
X
Xto set up some windows and more menues than those installed by
X
Xsimpletools(). BUT, YOU DON'T HAVE TO! Your program will run with
X
Xjust the lines:
X
X main()
X
X {
X
X simpletools("My Program Name");
X
X for (;;) simpleevents();
X
X }
X
XThis little program will just give you a skeleton application and about
X
Xall you will be able to do is run desk accessories.
X
X
X
XThe following routines can be used to setup your application before you
X
Xrun the simpleevents() loop.
X
X
X
Xmenu ("File", "Quit", leave);
X
XLet us say you have previously defined the procedure:
X
X leave()
X
X {
X
X exit(0);
X
X }
X
XThen the statement:
X
X menu ("File", "Quit", leave);
X
Xwill install under the File menu an item named Quit. It will also store
X
Xthe procedure 'leave' as the routine to execute if the user picks Quit
X
Xfrom the File menu.
X
X
X
XUsing this menu() statement, you can install or modify menu entries. Each
X
Xcall to menu() must have three arguments. The first is the menu name you
X
Xwish to reference, the second is the item name within the menu, and the
X
Xthird is either a procedure pointer or either 0L, 1L, 2L, or 3L (this will be
Xexplained).
X
X
X
XIf you want to install a new menu/item pair, first define the procedure you
X
Xwould like to run when that item is selected. It can be a no op, like:
X
X nop()
X
X {
X
X }
X
XSo you can say:
X
X menu ("Commands", "Start Demo", nop);
X
X
X
X
X
XIf you want to change the procedure to run when an menu/item pair is
Xselected, just call menu() again with the new procedure. For example, if
Xyou had:
X
X beep()
X
X {
X
X sysbeep(10);
X
X }
X
Xyou can say (at any time, not just during your setup):
X
X menu ("Commands", "Start Demo", beep);
X
X
X
XYou may use a name such as "Medium/M" or "Slow/S" and then
X
Xyou may use the keys Command-M or Command-S to invoke the menu item
Xinstead of using the mouse. Any reference to the item name must
Xinclude the /K addition to the name.
X
X
X
XDisabling, Enabling, Checking, or Unchecking Menu Items
X
XIf you want to disable, enable, check, or uncheck an item, you would pass
X
Xeither 0L, 1L, 2L, or 3L. It is best if you define constants like:
X
X #define itemdisable 0L
X
X #define itemenable 1L
X
X #define itemcheck 2L
X
X #define itemuncheck 3L
X
Xthen you can say:
X
X menu ("Commands", "Start Demo", itemdisable);
X
Xor:
X
X menu ("Commands", "Start Demo", itemcheck);
X
X
X
XWhat you would probably do is have the procedure assigned to the
Xmenu/item handle the checking and unchecking. And you would have the
Xprocedures which deactivate and activate windows do the job of disabling
Xand enabling menus. For example, take a look at this complete program:
X
X #define itemcheck 2L
X
X #define itemuncheck 3L
X
X #define normal 0
X
X #define wide 1
X
X int pensize = normal;
X
X
X
X setwidepen()
X
X {
X
X if (pensize == normal) {
X
X menu ("Commands", "Wide Pen", itemcheck);
X
X pensize = wide;
X
X } else {
X
X menu ("Commands", "Wide Pen", itemuncheck);
X
X pensize = normal;
X
X }
X
X }
X
X
X
X main()
X
X {
X
X simpletools("Check-Uncheck Test");
X
X menu ("Commands", "Wide Pen", setwidepen);
X
X for (;;) simpleevents();
X
X }
X
X
X
XIf you call menu() to disable/enable/check/uncheck an item with a
Xmenu/item not already installed, that menu/item will be installed with a
Xno_op procedure before disabling/enabling/checking/unchecking.
X
X
X
XThe "About" Entry Under the Apple Menu
X
XTo assign a procedure or enable the first item under the apple menu, you
X
Xwould use exactly the same menu() routine. The difficult part is what
X
Xto call the Apple menu. I thought about making a special case for the
X
XApple menu so you might just say, menu ("Apple", "About MyProgram",
Xroutine), but that would put a "special case" into menu()'s use which I
Xdidn't want to have to remember. Instead, you must pass a regular C string
Xwith the Apple character as its contents (since that is the name of the
Xmenu.) To simplify making such a string, I have one already defined which
Xyou can link into your program by using extern. If you add the line:
X
X extern char applestring[];
X
Xyou will then have a string containing the apple character. You can then
X
Xsay:
X
X #define itemenable 1L
X
X extern char applestring[];
X
X
X
X tellaboutme() /* displays a dialog box */
X
X {
X
X message ("Hi. I'm a practice program");
X
X }
X
X
X
X main()
X
X {
X
X simpletools("About Practice");
X
X menu (applestring,"About Practice",tellaboutme);
X
X menu (applestring,"About Practice",itemenable);
X
X for (;;) simpleevents();
X
X }
X
X
X
XInstalling a Window
X
XAs a tutorial example, let's say we want to put up a single window on the
X
Xscreen. Let's say that nothing "extra" will happen with the window is
X
Xactivated, deactivated, updated or when the mouse button is pressed inside
X
Xof it. This window will be movable, sizable, and hadeable by the user
X
Xwhile simpleevents() is being repeatedly run. Take a look at this program:
X
X nop()
X
X {
X
X }
X
X
X
X main()
X
X {
X
X simpletools("Window Demo");
X
X window ("My Window", 50, 50, 500, 300, nop, nop,
X nop, nop);
X
X for (;;) simpleevents();
X
X }
X
XThis program will first install the standard apple, file, and edit menus.
X
XIt will then place a document window on the screen with its top left
Xcorner at 50, 50 and its bottom right corner at 500, 300. Nop is used for
Xthe "thing to do" when the window is activated, deactivated, updated, or
Xwhen the mouse is clicked in the window.
X
X
X
XAn additional menu item is added under a menu title of Windows with the
Xname of the window. This item is enabled and when selected will bring
Xthe named window to the front and visable. The installation of this menu
Xitem may be turned off and on as windows are created in case there are
Xsome windows you don't want in this Windows menu. To turn this feature
Xoff, you must set the external variable "windmenu" to false while you
Xmake the window() call. You get access to this variable with the line:
X
X extern int windmenu;
X
X
X
X
X
X
X
XMore Detail On Window()
X
XThe window() procedure installs or modifies the "things to do" lists for
X
Xa window. Its first argument is the name of the window. The next four
X
Xarguments are integers describing where the window is to be placed and
X
Xhow big it is. These positioning arguments are only used to orginally
X
Xinstall the window. They will be ignored if the window has already been
X
Xmade! This is so that the user has complete control of the placement of
X
Xthe window once the programmer has put one onto the screen. The next
X
Xfour arguments are procedures to run when the system receives an event
Xto activate, deactivate, update, or that a mouse has clicked inside the
X
Xwindow.
X
X
X
XHere is an example of a program which uses windows with the window's
X
X"things to do" list not just no_ops:
X
X #define itemenable 1L
X
X #define itemdisable 0L
X
X
X
X nop()
X
X {
X
X }
X
X
X
X myactivate() /* to be done when window is activated */
X
X {
X
X menu ("Edit", "Clear", itemenable);
X
X }
X
X
X
X mydeactivate() /* when window is deactivate */
X
X {
X
X menu ("Edit", "Clear", itemdisable);
X
X }
X
X
X
X myupdate() /* when window needs redrawn */
X
X {
X
X moveto (10,10);
X
X puts("Hi There");
X
X }
X
X
X
X mycontent() /* when mouse is clicked in window */
X
X {
X
X sysbeep(10);
X
X }
X
X
X
X myclear()
X
X {
X
X /* something to erase the contents of the window */
X
X }
X
X
X
X main()
X
X {
X
X simpletools("More Window Demo");
X
X menu ("Edit", "Clear", myclear);
X
X window ("My Demo Window", 50, 50, 300, 300,
X myactivate,mydeactivate, myupdate, mycontent);
X
X for (;;) simpleevents();
X
X }
X
X
X
XThe Run and Stop Routines
X
XEach time simpleevents() is run, it calls (in addition to handling all
X
Xsystem events) any procedures you have asked it to call with the run()
X
Xcommand. By using run(), you can make procedures look as if they are
X
Xrunning in the "background". For example, a run procedure might display
X
Xrandom sized circles in a particular window. Then, while anything else
X
Xis happening in your program, as long as it keeps calling simpleevents()
X
Xyou will get random sized circles appearing in a window.
X
X
X
XYou may install up to 50 procedures to execute each time
X
Xsimpleevents is called. For example, if you would like to count how
X
Xmany times simpleevents() is running, you could have:
X
X long count = 0L;
X
X countcalls()
X
X {
X
X count++;
X
X }
X
Xand then say:
X
X run (countcalls)
X
Xsomewhere in your program whenever you want to start executing
Xcountcalls. The run() procedure DOES NOT RUN the routine you give it. It
Xonly adds it to the list of things to run.
X
X
X
XPROCEDURE ASSIGNED TO BE RUN SHOULD END QUICKLY. If they don't, other
X
Xevents will be hung up. Also, if a procedure to be run calls simpleevents(),
Xyou'll get into an infinate loop with no way out.
X
X
X
XThe stop() procedure is used to remove an item from the run list. For
X
Xexample, in the above example we could have said:
X
X long count = 0L;
X
X countcalls()
X
X {
X
X if (count++ > 100000) {
X
X sysbeep (10);
X
X count = 0L;
X
X stop (countcalls);
X
X }
X
X }
X
Xand then said:
X
X run (countcalls)
X
Xafter a while, you'll hear a beep and countcalls() will be removed from
X
Xthe list of procedures to run.
X
X
X
XDirecting Output to a Window of Your Choice
X
XLet us say you have installed a window named "My First Window". If you
X
Xwant to direct output to this window, use:
X
X withwindow ("My First Window");
X
Xand all output (graphics and text) will go to that window. This is
X
Xthe same as using the toolbox's setport() routine except you don't
X
Xhave to know the window's grafport pointer.
X
X
X
XA Message Dialog
X
XYou may display a dialog box with a message by using a line like:
X
X message ("Sorry, a window by that name already exists.");
X
X
X
X
X
XMessage() returns either TRUE or FALSE depending on whether OK or Cancel
Xwas clicked by the user. There is enough room for a three line message.
XYou may place Carriage Return characters to force using the next line.
XThis is done in C with:
X
X message ("First line\rSecond line");
X
X
X
XA Prompt Dialog
X
XYou may ask the user a question by using a dialog box with a question, an
Xeditable window for the answer, and the OK and Cancel buttons. An
Xexample:
X
X char answer[255];
X
X strcpy (answer, "New Window");
X
X prompt("Give me a unique name for the new window:",
X
X answer);
X
X
X
X
X
XPrompt() returns TRUE if either the OK button is pressed or RETURN is
Xtyped. FALSE is returned if Cancel was clicked by the user. Make sure you
Xset the answer string to at least a null string. Random data in the answer
Xstring will generate a random default answer.
X
X
X
X+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
X
X
X
XAdvanced Notes:
X
X
X
X1) Each procedure called when a menu item is selected is passed the
X
Xaddress of a string containing the name of the item which was
X
Xselected. This is convenient if you want several menu/items to call
X
Xthe same procedure. For example, if you had a list of baud rate
X
Xsettings in a menu. Each item can be assigned the same routine
X
Xto run. The routine might look like:
X
X int brate;
X
X
X
X setbaudrate( itemselected )
X
X char *itemselected;
X
X {
X
X brate = atoi ( itemselected);
X
X }
X
X
X
X2) Simpleevents() will set the output port to the proper window before
X
Xit calls the procedures assigned to that window. This means that those
X
Xprocedures do not have to set output to any window. Output will
X
Xautomatically go to the window which is being activated, deactivated,
Xupdated, or for which the mouse has been pressed.
X
X
X
X3) Each window content procedure assigned to one of your windows is
X
Xpassed the x and y position of the mouse in that window's local
X
Xcoordinates. You could declare one of these procedures like:
X
X dotinmywindow(x,y)
X
X int x,y;
X
X {
X
X moveto (x,y);
X
X lineto (x,y);
X
X }
X
Xand used dotinmywindow() as a window's procedure to run when the mouse
X
Xis clicked in that window.
X
X
X
X4) Each window procedure is passed the relavant window pointer and
X
Xthe address of the event record which caused that window to have some
X
Xaction taken on it.
X
X
X
X5) Each run procedure is passed the address of the next event record
X
Xto be processed by simpleevents(). Maybe your run procedure would
X
Xlike to monitor this or even change it?
X
X
X
X6) A very useful function is:
X
X windowptr windowpoint ("My Window")
X
XThis returns the window pointer to your window named "My Window". This
Xallows you to call nearly all of the toolbox routines which manipulate
Xwindows. You could say things like:
X
X setport ( windowpoint ("My Window"));
X
X hidewindow ( windowpoint ("My Window"));
X
X showwindow ( windowpoint ("My Window"));
X
X selectwindow ( windowpoint ("My Window"));
X
X if (frontwindow() !=windowpoint("My Window")) {};
X
X
X
XYou can have access to this fuction after the definition:
X
X extern windowptr windowpoint();
X
X
X
X7) Another useful fuction is:
X
X menuhandle mhand ("Edit")
X
XThis returns a menuhandle to the named menu. This allows you to call
Xnearly all of the toolbox routines which manipulate menus.
X
X
X
XYou can have access to this function after the definition:
X
X extern menuhandle mhand();
X
X
X
X8) Several of the SimpleTools routines return result codes. You may
Xchoose to ignore these. In case you want to use them, here is what they
Xare:
X
X menu () TRUE if a new item was added
X
X FALSE if it already existed
X
X
X
X window () TRUE if a new window was added
X
X FALSE if it already existed
X
X
X
X withwindow ()
X
X TRUE if window exists
X
X FALSE if not
X
X
X
X run () TRUE if installation worked
X
X FALSE if not (too many installs)
X
X
X
X stop () TRUE if procedure was found
X
X FALSE if not
X
X
X
X runruns() # of routines runned
X
X
X
X9) Three external integers may be modified to affect how the window()
Xcommand works. They are originally set to default values. You can ignore
Xthese variables. If you want to change them, they stay changed until you
Xchange them back to their original value.
X
X
X
X wprocid The window procedure id.
X
X 0 standard document window (default)
X
X 1 alert box
X
X 2 plain box
X
X 3 plain box with shadow
X
X 4 document window without size
X
X 16 rounded corner box (DA type)
X
X
X
X dogoaway TRUE if go away box is used (default)
X
X
X
X windmenu TRUE if entry is made into Window menu
X
X
X
________This_Is_The_END________
if test `wc -l < SimpleTools.doc` -ne 919; then
echo 'shar: SimpleTools.doc was damaged during transit'
echo ' (should have been 919 bytes)'
fi
fi ; : end of overwriting check
exit 0