[comp.sources.amiga] v89i122: julia - draw julia set

page%swap@Sun.COM (Bob Page) (05/10/89)

Submitted-by: mott@ucscd.ucsc.edu (Hung H. Le)
Posting-number: Volume 89, Issue 122
Archive-name: graphics/julia.1

Enclosed is JuliaIIM, a program to draw the Julia Set (related to
Mandelbrot set).  I also include "qmenu" (previously posted) for
completeness since it is needed to compile JuliaIIM.

[uuencoded executable included.  ..bob]

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	JuliaIIM.c
#	JuliaIIM.doc
#	JuliaIIM.uu
#	Makefile.qmenu
#	Readme.qmenu
#	mtst.c
#	qmenu.c
#	qmenu.h
#	request.h
# This is archive 1 of a 1-part kit.
# This archive created: Tue May  9 21:08:00 1989
echo "extracting JuliaIIM.c"
sed 's/^X//' << \SHAR_EOF > JuliaIIM.c
X/*
X * JuliaIIM -- Quick a dirty way to look at the Julia Set
X *
X * April 27, 89 --
X *	Clean up for public distribution.
X *	Menus are generated using the "qmenu" package
X *	Requester is genrated using "blk"
X * 		both packages are written by
X *				Stuart Ferguson		1/89
X *				(shf@well.UUCP)
X *		and are availabe in the Public Domain.
X *	The scaling of the pictures left much to be desired.
X *  One thing I really would like to work on is the "Imanginary Map".
X *	I would like to draw a Mandelbrot picture there and let the user
X * 	pick the value by clicking on the Mandelbrot map. This will give a
X *	very nice illustration that the Mandelbrot picture is really a 
X *	dictionary of the Julia Set.
X *	I had planned to work on this some more but finals are coming up.
X *
X *	You may use this codes if they are useful to you.
X *
X * compiles using 3.4a Manx
X * 1> cc JuliaIIM.c
X * 1> ln JuliaIIM.o qmenu.o -lm -lc
X */
X#include "functions.h"
X#include "exec/types.h"
X#include "graphics/gfxmacros.h"
X#include "intuition/intuition.h"
X#include "math.h"
X
X#define INTUITION_REV 0L
X#define GRAPHICS_REV 0L
X/* Write out Text */
X#define MyText(r,x,y,b) Move((r),(x), (y)); Text((r), (b), (long) strlen(b))
X/* Clear Screen */
X#define MyClear(r,x,y) SetAPen((r), 0L); RectFill((r), 0L, 0L, (x), (y))
X
X/* external for qmenu.o and request.h */
Xstruct TextAttr ta = { (UBYTE*) "topaz.font", 8,0,0 };
X
X/* global variables */
Xstruct IntuitionBase *IntuitionBase = 0L;
Xstruct GfxBase *GfxBase = 0L;
Xstruct Window *Window = 0L;
Xstruct RastPort *RastPort = 0L;
X
Xstruct NewWindow nw =
X{
X	50, 10,			/* leftedge, topedge */
X	340, 150,		/* width, height */
X	-1, -1,			/* detail pen, block pen (default) */
X	CLOSEWINDOW | MENUPICK | MOUSEBUTTONS | REQCLEAR | GADGETDOWN,	/* IDCMP Flag */
X	SMART_REFRESH | WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | ACTIVATE | GIMMEZEROZERO | WINDOWSIZING,
X	NULL, NULL,		/* first gadget, check mark */ 
X	(UBYTE *) "Julia IIM Window",		/* title */
X	NULL, NULL,		/* screen, bitmap */
X	100, 50,		/* minwidth, minheight */
X	640, 200,		/* maxwidth, maxheight */
X	WBENCHSCREEN	/* type */
X};
X
X#define PI 3.14159
X#define HALF_PI 1.57079
X#define X_RES 640.0
X#define Y_RES 200.0
X
X/* global variables */
XUBYTE Buf[20];
Xdouble x, y, cx, cy;
Xint offset_width, offset_height;
Xint MaxDots;
XSTATIC BOOL Stop, Show, Clear, Pixel_Mode;
X
X/* gadget */
X#define CAN_ID  0x80 
X#define OK_ID	0x81  
X#define STR_ID  0x82 
X#define NUMCHR 20
XUBYTE undo[NUMCHR];
X#define REQ mot_req
X#define REQ_BUF mot_nbuf
X#include "request.h"
X/* gadget end */
X
X/* Menu Stuffs */
X#include "qmenu.h"
X
X#define NILSUB	{NULL,NULL}
X
X/* STOP MENU */
X#define STOP 0
Xchar *ms_str[] = 
X{
X	"!=SStop Calculation",
X	NULL 
X};
X
Xstruct NewMenu ms_sub[] = 
X{
X	NILSUB,
X};
X
Xchar *stop_str[] = 
X{
X	"Julia IIM",
X	NULL 
X};
X
Xstruct NewMenu stop_sub[] = 
X{
X	{ ms_str, ms_sub },
X};
X
Xstruct NewMenu stop_menu = { stop_str, stop_sub };
Xstruct Menu *MenuStop;
X
X/* MAIN MENU */
X
X/* MENU PROJECT */
X/* Menu Project About Strings */
Xchar *mpa_str[] =
X{
X	"!bHung Le (mott@ucscb.UCSC.EDU)",
X	NULL
X};
X
X/* Menu Project Strings */
X#define NEW 0
X#define ABOUT 1
X/* 2 is the line separating ABOUT and QUIT */
X#define QUIT 3
Xchar *mp_str[] = 
X{
X	"!=NNew",
X	"About",
X	"-",
X	"!=QQuit",
X	NULL 
X};
X
X/* Menu Project SubMenu */
Xstruct NewMenu mp_sub[] = 
X{
X	NILSUB,
X	{ mpa_str, NULL },
X	NILSUB,
X};
X
X/* OPTIONS MENU */
X/* Menu Option Count Strings */
Xchar *moc_str[]=
X{
X	"!c!0111111   100",
X	"!c!1011111   500",
X	"!+!1101111  1000",
X	"!c!1110111  2000",
X	"!c!1111011  3000",
X	"!c!1111101  5000",
X	"!c!1111110 10000",
X	NULL
X};
X
X#define MODE_PIXEL 0
X#define MODE_CIRCLE 1
Xchar *mom_str[] =
X{
X	"!+!01Pixel",
X	"!c!10Circle",
X	NULL
X};
X/* Menu Option Strings */
X#define PIXEL_COUNTS 0
X#define PIXEL_MODE 1
X#define SHOW_PARS 2
X#define CLEAR_SCREEN 3
X#define ENTER_C 4
X#define IMAGINARY_MAP 5
Xchar *mo_str[] = {
X	"Pixels Count",
X	"Pixel Mode",
X	"!+!t!=SShow Parameters",
X	"!+!t!=CClear Screen",
X	"!=PEnter C parameters ...",
X	"!=MImaginary Map",
X	NULL 
X};
X
X/* Menu Option SubMenus */
Xstruct NewMenu mo_sub[] = {
X	{ moc_str, NULL },
X	{ mom_str, NULL },
X	NILSUB,
X	NILSUB,
X	NILSUB,
X	NILSUB,
X};
X/* PRESET MENU */
X#define  CIRCLE 1 
X#define  TRIEYES 2 
X#define  INVERSE_S 3 
X#define  CRACK 4 
X#define  FOURSOME 5 
X#define  TWIST  6 
X#define  DIAMOND 7 
X
X/* These names reflects somewhat the state of my mind during
X   the early morning hours
X */
Xchar * mpreset_str[] =
X{
X	"!=1Circle",
X	"!=2TriEyes",
X	"!=3Inverser S",
X	"!=4Crack",
X	"!=5Foursome",
X	"!=6Twist",
X	"!=7Diamond",
X	"!=8Siegel Disk",
X	NULL
X};
X
Xstruct NewMenu mpreset_sub[] =
X{
X	NILSUB,
X	NILSUB,
X	NILSUB,
X	NILSUB,
X	NILSUB,
X	NILSUB,
X	NILSUB,
X	NILSUB,
X};
X
X/* MAIN MENU */
X/* Menu Main String */
Xchar *main_str[] = {
X	"Project",
X	"Options",
X	"Presets",
X	NULL 
X};
X
X/* Menu Main SubMenu */
X#define PROJECT 0
X#define OPTION 1
X#define PRESETS 2
Xstruct NewMenu main_sub[] = {
X	{ mp_str, mp_sub},
X	{ mo_str, mo_sub},
X	{ mpreset_str, mpreset_sub},
X};
X
Xstruct NewMenu main_menu = { main_str, main_sub};
Xstruct Menu *MenuMain;
X
X/* Menu ends */
Xstruct data
X{
X	double x, y;
X};
Xstruct data presets[8] =
X{
X	/* #define  CIRCLE 1 */ 
X	{ 0.00, 0.00 },
X	/* #define  TRIEYES 2 */ 
X	{ -1.00, 0.00 },
X	/* #define  INVERSE_S 3  */
X	{ 0.2 , 0.3 },
X	/* #define  CRACK 4  */
X	{ 0.00, 1.00 },
X	/* #define  FOURSOME 5  */
X	{ 0.25, 0.00 },
X	/* #define  TWIST  6  */
X	{ -0.9, 0.12 },
X	/* #define  DIAMOND 7  */
X	{ -0.3, 0.00 },
X	/* #define SEIGEL_DISK 8 */
X	{ -0.39054, -0.58679 },
X};
X
X/* for MANX */
X_cli_parse() {}
X_wb_parse() {}
X
Xmain()
X{
X
X	/* initialize data */
X	cx =  0.2;
X	cy =  0.3;
X	x  =  y = 1.0;
X	MaxDots = 1000;
X	offset_width = 0;
X	offset_height = 0;
X	sprintf(REQ_BUF[0], "%8f", cx);
X	sprintf(REQ_BUF[1], "%8f", cy);
X
X	Stop = FALSE;
X	Show = Clear = Pixel_Mode = TRUE;
X
X	/* open libraries */
X	open_libs();
X
X	/* open display window */
X	if ( (Window = (struct Window *)OpenWindow(&nw) ) == NULL)
X		clean_up();
X
X	/* using "qmenu" package. Thanks Stuart ! */
X	if (!(MenuStop = GenMenu (&stop_menu))) 
X		clean_up();
X	if (!(MenuMain = GenMenu (&main_menu))) 
X		clean_up();
X
X	RastPort = Window->RPort;
X
X	SetAPen(RastPort, 1L);
X	Julia();
X
X	while(1)
X	{
X		Wait( 1L << Window->UserPort->mp_SigBit);
X		HandleEvent();
X	}
X}
X
X/*
X * does the Julia set
X */
XJulia()
X{
X	int i;
X	double m, n;
X	UBYTE buffer[81];
X
X	/* Set offset */
X	offset_width = (X_RES - Window->Width) / 2;
X	offset_height = (Y_RES - Window->Height) / 2;
X	ClearMenuStrip(Window);
X	SetMenuStrip (Window, MenuStop);
X	Stop = FALSE;
X
X	/* Just want be sure that Z is in the Julia Set 
X	   so we discard the first 10 terms
X	 */
X	for (i = 0; i < 10 ; i++)
X		Iteration();
X
X	if (Show)
X	{
X		sprintf(buffer, "f(z) = z^2 + ((%8f) + (%8f)i)", cx, cy);
X		MyText(RastPort, 2L, 10L, buffer);
X		sprintf(buffer, "Current Dot: ");
X		MyText(RastPort, 2L, 20L, buffer);
X	}
X
X	for (i = 0; ((i < MaxDots) && (Stop == FALSE)) ; i++)
X	{
X		HandleStopEvent();
X		Iteration();
X		Scale(&m, &n);
X		Center(&m, &n);
X		if (Show)
X		{
X			sprintf(buffer, "%8d", i);
X			MyText(RastPort, 100L, 20L, buffer);
X		}
X		if (Pixel_Mode)
X			WritePixel(RastPort, (long)m, (long)n);
X		else
X			DrawCircle(RastPort, (long) m, (long) n, 1L);
X	}
X	ClearMenuStrip(Window);
X	SetMenuStrip(Window, MenuMain);
X}
X
X/*
X * The main inverse iteration loop
X */
XIteration()
X{
X		double wx, wy, radius, theta;
X		extern double x, y, dx, dy;
X
X		wx = x - cx;
X		wy = y - cy;
X
X		/* current theta */
X		theta = atan(wy / wx);
X		if (wx < 0)
X			/* rotate the angle */
X			theta = PI + theta;
X		else if (wx == 0)
X			theta = HALF_PI;
X
X		/* does square root */
X		/* for the angle, all we need to do is to take half of the angle */
X		theta = theta/2;
X		/* magnitude of Z */
X		radius = (sqrt(wx*wx + wy*wy));
X		/* for sake of different paths */
X		if (ran() > 0.5)
X			radius = -sqrt(radius);
X		else
X			radius = sqrt(radius);
X
X		/* new Z */
X		x = radius * cos(theta);
X		y = radius * sin(theta);
X}
X
X/*
X * Scale(int *m, *n)
X * 	. scale the two global variables x, y (world coordinates)
X *    to m, n (display coordinates) 
X */
XScale(m, n)
Xdouble *m, *n;
X{
X		extern double x, y;
X
X		*m = ((x+4) * X_RES / 8);
X		*n = ((2 - y) * Y_RES / 4);
X}
X
X/*
X * Center the picture
X */
XCenter(m,n)
Xdouble *m, *n;
X{
X	extern int offset_width, offset_height;
X
X	*m = *m - offset_width + 0.77;
X	*n = *n - offset_height;
X}
X
X/*
X * clean up intuition, try to do the right things
X */
Xclean_up()
X{
X	struct IntuiMessage *messg;
X
X	/* Window is the the main and only window */
X	if (Window)
X	{
X		/* Drain the IDCMP */
X		while (messg = (struct IntuiMessage *) (GetMsg (Window->UserPort)))
X			ReplyMsg(messg);
X		if (MenuStop) FreeMenu (MenuStop);
X		if (MenuMain) FreeMenu (MenuMain);
X		ClearMenuStrip(Window);
X		CloseWindow(Window);
X	}
X
X	/* Close down libraries */
X	if (GfxBase) 		CloseLibrary(GfxBase);
X	if (IntuitionBase) 	CloseLibrary(IntuitionBase);
X
X	exit(FALSE);
X}
X
X/* take care of IDCMP */
XHandleEvent()
X{
X	struct IntuiMessage *imessg;
X
X	/* while there are messages take look at */
X	while (imessg = (struct IntuiMessage *) (GetMsg (Window->UserPort)))
X	{
X		/* make a copy */
X		ULONG class = imessg->Class;
X		USHORT code = imessg->Code;
X		/* reply to it */
X		ReplyMsg(imessg);
X		/* identify message */
X		switch(class)
X		{
X			case CLOSEWINDOW:
X				clean_up();
X				break;
X			case MENUPICK:
X				/* in case user does several things at once */
X				while (code != MENUNULL)
X				{
X					do_menu(code);
X					code = ItemAddress(MenuMain, code)->NextSelect;
X				};
X				break;
X
X			default:
X				break;
X		}
X	}
X}
X
Xdo_menu(code)
XUSHORT code;
X{
X	switch(MENUNUM(code))
X	{
X		case PROJECT:
X			do_project(code);
X			break;
X
X		case OPTION:
X			do_option(code);
X			break;
X
X		case PRESETS:
X			do_presets(code);
X			break;
X
X		default:
X			break;
X	}
X}
Xdo_presets(code)
XUSHORT code;
X{
X	int item;
X	item = ITEMNUM(code);
X	cx = presets[item].x; 
X	cy = presets[item].y; 
X	sprintf(REQ_BUF[0], "%8f", cx);
X	sprintf(REQ_BUF[1], "%8f", cy);
X	if (Clear)
X	{
X		MyClear(RastPort, (long) Window->Width, (long) Window->Height);
X	}
X	SetAPen(RastPort, 1L);
X	Julia();
X}
X
Xdo_project(code)
XUSHORT code;
X{
X	switch(ITEMNUM(code))
X	{
X		case NEW:
X			if (Clear)
X			{
X				MyClear(RastPort, (long) Window->Width, (long) Window->Height);
X			}
X			SetAPen(RastPort, 1L);
X			Julia();
X			break;
X
X		case QUIT:
X			clean_up();
X			break;
X
X		case ABOUT:
X		default:
X			break;
X	}
X}
X
Xdo_option(code)
XUSHORT code;
X{
X	struct MenuItem *mi;
X
X	switch(ITEMNUM(code))
X	{
X		case PIXEL_COUNTS:
X			mi = (MenuMain[OPTION].FirstItem[PIXEL_COUNTS].SubItem);
X			if (mi[0].Flags & CHECKED)
X				MaxDots =   100;
X			else if (mi[1].Flags & CHECKED)
X				MaxDots =   500;
X			else if (mi[2].Flags & CHECKED)
X				MaxDots =   1000;
X			else if (mi[3].Flags & CHECKED)
X				MaxDots =   2000;
X			else if (mi[4].Flags & CHECKED)
X				MaxDots =   3000;
X			else if (mi[5].Flags & CHECKED)
X				MaxDots =   5000;
X			else if (mi[6].Flags & CHECKED)
X				MaxDots =   10000;
X			break;
X
X		case PIXEL_MODE:
X			mi = (MenuMain[OPTION].FirstItem[PIXEL_MODE].SubItem);
X			if (mi[MODE_PIXEL].Flags & CHECKED)
X				Pixel_Mode = TRUE;
X			else if (mi[MODE_CIRCLE].Flags & CHECKED)
X				Pixel_Mode = FALSE;
X			break;
X
X		case SHOW_PARS:
X			if (MenuMain[OPTION].FirstItem[SHOW_PARS].Flags & CHECKED)
X				Show = TRUE;
X			else
X				Show= FALSE;
X			break;
X
X		case CLEAR_SCREEN:
X			if (MenuMain[OPTION].FirstItem[CLEAR_SCREEN].Flags & CHECKED)
X				Clear = TRUE;
X			else
X				Clear = FALSE;
X			break;
X
X		case ENTER_C:
X			enter_c();
X			break;
X
X		case IMAGINARY_MAP:
X			imaginary_map();
X			break;
X
X		default:
X			break;
X	}
X}
X
Ximaginary_map()
X{
X	int width, height;
X	struct IntuiMessage *imessg;
X	float new_cx, new_cy;
X
X	width = Window->Width;
X	height = Window->Height;
X
X	/* Clear the Screen */
X	MyClear(RastPort, (long) width, (long) height);
X
X	SetAPen(RastPort, 3L);
X	MyText(RastPort, 5L, 10L, "Click on plane for a C value");
X
X	/* Draw Axis for now */
X	SetAPen(RastPort, 2L);
X	Move(RastPort, 2L, (long) (Window->Height / 2));
X	Draw(RastPort, (long) (Window->Width), (long)(Window->Height / 2));
X	Move(RastPort, (long) (Window->Width / 2), 10L);
X	Draw(RastPort, (long) (Window->Width / 2), (long)(Window->Height - 2));
X
X	Wait( 1L << Window->UserPort->mp_SigBit);
X	/* while there are messages take look at */
X	while (imessg = (struct IntuiMessage *) (GetMsg (Window->UserPort)))
X	{
X		/* make a copy */
X		ULONG class = imessg->Class;
X		USHORT code = imessg->Code;
X		SHORT mouseX = imessg->MouseX;
X		SHORT mouseY = imessg->MouseY;
X		/* reply to it */
X		ReplyMsg(imessg);
X		/* identify message */
X		switch(class)
X		{
X			case MOUSEBUTTONS:
X				if (code == SELECTDOWN)
X				{
X					/* Decenter */
X					new_cx = mouseX + offset_width - 0.77;
X					new_cy = mouseY + offset_height - 10;
X					/* Descale */
X					new_cx = (new_cx * ( 8 / X_RES)) - 4;
X					new_cy = -((new_cy * ( 4 / Y_RES)) - 2);
X					/*
X					printf("new cx %f; new cy %f\n", new_cx, new_cy);
X					*/
X					cx = new_cx;
X					cy = new_cy;
X					sprintf(REQ_BUF[0], "%8f", cx);
X					sprintf(REQ_BUF[1], "%8f", cy);
X					if (Clear)
X					{
X						MyClear(RastPort, (long) Window->Width, (long) Window->Height);
X					}
X					SetAPen(RastPort, 1L);
X					Julia();
X				}
X				break;
X
X			default:
X				break;
X		}
X	}
X}
X
Xenter_c()
X{
X
X/* Here come gadget */
X   struct IntuiMessage *im;
X
X   BOOL looping = TRUE;
X   ULONG class;
X   struct Gadget *gadget;
X
X   REQ.LeftEdge = 5;
X   REQ.TopEdge = 12;
X   Request (&REQ,Window);
X
X   while (looping) 
X   {
X     if ((im = (struct IntuiMessage *) GetMsg(Window->UserPort)) == 0L)
X	 {
X	 	Wait(1L << Window->UserPort->mp_SigBit);
X		continue;
X	 }
X        class = im->Class;
X		gadget = (struct Gadget *) im->IAddress;
X        ReplyMsg (im);
X		if (class == REQCLEAR)
X			looping = FALSE;
X		if (class == GADGETDOWN)
X		{
X			switch(gadget->GadgetID)
X			{
X				case OK_ID:
X					if (sscanf(REQ_BUF[0], "%lf", &cx) && sscanf(REQ_BUF[1], "%lf", &cy))
X					;
X					else
X					{
X						sprintf(REQ_BUF[0], "%8f", cx);
X						sprintf(REQ_BUF[1], "%8f", cy);
X					}
X					break;
X
X				case CAN_ID:
X					sprintf(REQ_BUF[0], "%8f", cx);
X					sprintf(REQ_BUF[1], "%8f", cy);
X					break;
X			}
X		}
X	}
X	while (im = (struct IntuiMessage *) GetMsg(Window->UserPort))
X	 	ReplyMsg(im);
X}
X/* End gadget */
X
XHandleStopEvent()
X{
X	struct IntuiMessage *imessg;
X
X	/* while there are messages take look at */
X	while (imessg = (struct IntuiMessage *) (GetMsg (Window->UserPort)))
X	{
X		/* make a copy */
X		ULONG class = imessg->Class;
X		USHORT code = imessg->Code;
X		/* reply to it */
X		ReplyMsg(imessg);
X		/* identify message */
X		switch(class)
X		{
X			case MENUPICK:
X				if (MENUNUM(code) != MENUNULL)
X					if ((MENUNUM(code) == STOP) && (ITEMNUM(code) == STOP))
X						Stop = TRUE;
X				break;
X			default:
X				Stop = FALSE;
X				break;
X		}
X	}
X}
X
X/* open Intuition and Graphics libraries */
Xopen_libs()
X{
X	IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", INTUITION_REV);
X	if (IntuitionBase == NULL)	clean_up();
X
X	GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", GRAPHICS_REV);
X	if (GfxBase == NULL) 		clean_up();
X}
SHAR_EOF
echo "extracting JuliaIIM.doc"
sed 's/^X//' << \SHAR_EOF > JuliaIIM.doc
X	JuliaIIM - quick a dirty way to see the Julia Set using the
X		Inverse Iteration Method.
X
X	I am not a mathematician so what I am saying about the Julia Set
X	below should be taken with a grain of salt (or something like that ;-).
X
X				 -- THE JULIA SET --
X
X	The Julia Set named after the French mathematician Gaston Julia
X	is a chaotic set.
X
X	To see how this set is formed, let's look at a simple dynamical
X	system represented as:
X		F(z) = z^2;
X
X		COMPLEX NUMBER:
X		z: a complex number that is z = x + iy
X			x, y: real number; i = squrt(-1);
X
X		to find z^2:
X			z^2 = (x + iy) (x + iy)
X			    = x^2 + i^2y^2 + 2ixy
X				= x^2 - y^2 + i(2xy)
X
X		So complex number has two components, real and imaginary. With these
X		two components we can map a set of complex numbers into a Cartesian
X		coordinate plane.
X		x-axis :  real number
X		y-axis :  imaginary number
X
X		ITERATION:
X		is a repeated process of feeding the result back into its own function.
X		that is 
X		Step
X		1. F(z) = F(z)
X		2. F(z) = F(F(z))
X		3. F(z) = F(F(F(z)))
X		and so on ....
X
X	If we apply the iteration process to F(z) using an initial Z number
X	and varying Z throughout the whole plane,
X	we will find out that
X
X	Note: Z = x + iy and |Z| = squrt(x^2 + y^2)
X
X	if 0 < |Z| < 1 then F(z) -> 0
X	if |Z| > 1 then F(z) -> inf.
X	if |Z| == 1 then F(z) forms an unit circle
X
X	The points form the unit circle lies in the chaotic set because
X	points outside the circles are moving toward inf. while points
X	inside the circles are tending toward zero.
X
X	The unit circle above is an example of a Julia Set.
X
X	Interesting shapes will form if we add a constant term such that
X	F(z) = z^2 + c
X	c: also an imaginary number.
X
X
X	INVERSE ITERATION METHOD:
X	Let us work with F(z) = z^2.
X	Given Z, we ask which points map Z under F(z). The answer is squrt(Z).
X	In a way, we are computing the backward orbit of Z. In general, we can 
X	pick any Z because after a few terms any of them will converge to the
X	Julia Set of F(z). By varying Z throughout the whole plane, we will get
X	a picture of a Julia Set.
X
X	RELATION BETWEEN THE MANDELBROT SET AND JULIA SET:
X	We can regard the mandelbrot set as a dictionary of the Julia Set. Each
X	point in the Mandelbrot set represents a different Julia Set.
X
XREFERENCES:
X
X	Barnsley, M. F.
X	Fractal Everywhere (Academic Press, 1988)
X
X	Dewdney, A, K
X	Computer Recreation: ... Mandelbrot ... Julia set
X	Scientific American (11/1987) 140-144
X
X	Julia, G
X	Sur l'iteration des fonctions rationnelles
X	Journal de Math, Pure et Appl. 8(1918) 47-245
X
X	Mandelbrot, B.B
X	The Fractal Geometry of Nature
X	(W.H. Freeman and Co., New York, 1982)
X
X	Peitgen, H.-O. and Richter, P.H
X	The Beauty of Fractals
X	(Springer-Verlag, Berlin, 1986)
X
X	Peitgen, H.-O. and Saupe Dietmar, editors
X	The Science of Fractal Images
X	(Springer-Verlag, Berlin, 1988)
X
X
X		-- JuliaIIM --
X
XProject Menu:
X	NEW:	Generate the Julia set
X	ABOUT: 	My Email address
X	QUIT:	as it says
X
XOptions Menu:
X	PIXEL COUNT:	Limit for the iteration loop. Higher the number
X		the longer the iteration will take
X	PIXEL MODE:	Two choices: pixel or circle
X	SHOW PARS:	Show the function and pixel count.
X	CLEAR SCREEN:	Clear screen before drawing the next one.
X	ENTER C PARS:	Enter your choice of parameters
X		Should choose "NEW" to generate the new graph
X		after you have entered the new parameters.
X	IMAGI. MAP:		Enter C parameters by clicking on a Complex plane
X		I had planned to draw a Mandelbrot set there instead
X		of an empty plane but finals are coming up so I don't
X		think I will have time to do it.
XPresets Menu:
X	The names of these presets may not make much sense to you. Don't worry
X	they don't make sense to me either. And I named them!!!
X	You may use these presets as starting point for exploration.
X	Choose a preset, then use the "Enter C pars" menu to vary the C
X	parameters and see what happens.
X
XEnjoy,
X
X hung le --
X
X mott@ucscb.ucsc.edu		...!ucbvax!ucscc!ucscb!mott
X
X
X	This package is released to Public Domain.
X
SHAR_EOF
echo "extracting JuliaIIM.uu"
sed 's/^X//' << \SHAR_EOF > JuliaIIM.uu
X
Xbegin 600 JuliaIIM
XM```#\P`````````#``````````(```N+```!]P````$```/I```+BT[Z)WITI
XM;W!A>BYF;VYT``!*=6QI82!)24T@5VEN9&]W``!#(%9!3%5%`%)E86P@3G5M?
XM8F5R.@!);6%G($YU;6)E<CH`3VL`0V%N8V5L`"$]4U-T;W`@0V%L8W5L871I]
XM;VX`2G5L:6$@24E-`"%B2'5N9R!,92`H;6]T=$!U8W-C8BY50U-#+D5$52D`D
XM(3U.3F5W`$%B;W5T`"T`(3U1475I=```(6,A,#$Q,3$Q,2`@(#$P,``A8R$Q2
XM,#$Q,3$Q("`@-3`P`"$K(3$Q,#$Q,3$@(#$P,#``(6,A,3$Q,#$Q,2`@,C`PK
XM,``A8R$Q,3$Q,#$Q("`S,#`P`"%C(3$Q,3$Q,#$@(#4P,#``(6,A,3$Q,3$QY
XM,"`Q,#`P,```(2LA,#%0:7AE;``A8R$Q,$-I<F-L90``4&EX96QS($-O=6YT'
XM`%!I>&5L($UO9&4`(2LA="$]4U-H;W<@4&%R86UE=&5R<P`A*R%T(3U#0VQED
XM87(@4V-R965N`"$]4$5N=&5R($,@<&%R86UE=&5R<R`N+BX`(3U-26UA9VEN@
XM87)Y($UA<``A/3%#:7)C;&4`(3TR5')I17EE<P`A/3-);G9E<G-E<B!3`"$]P
XM-$-R86-K`"$]-49O=7)S;VUE`"$]-E1W:7-T`"$]-T1I86UO;F0`(3TX4VEER
XM9V5L($1I<VL``%!R;VIE8W0`3W!T:6]N<P!0<F5S971S`$Y5``!.74YU3E4``
XM`$Y=3G5.50``*7S,S,T^AZ0I?)F9FC^'K"E\@```08><*7R```!!AY0Y?`/H1
XMAX)";(=^0FR'@$*G+RR'I$AZ`+A(;(!*3KH4^$_O`!!"IR\LAZQ(>@"F2&R`-
XM7DZZ%.)/[P`00FR',CE\``&'.#E\``&'-CE\``&'-$ZZ#6I(;(`:3KHK8%A/Q
XM*4"`$F8$3KH$CDAL@[I.N@VR6$\I0(>$9@1.N@1Z2&R$^DZZ#9Y83RE`AXAFL
XM!$ZZ!&8@;(`2*6@`,H`62'@``2\L@!9.NBJF4$]A+"!L@!(B:`!6<``0*0`/9
XM<@'AH2\!3KHJ*EA/3KH$N&#@3EU.=24X9@`E.&8`3E7_G"!L@!(R*``(2,$@'
XM`4ZZ(R@B`"`\H```2DZZ(JHB/(```$).NB,(3KHBDCE`AWX@;(`2,B@`"DC!H
XM(`%.NB+Z(@`@/,@``$A.NB)\(CR```!"3KHBVDZZ(F0Y0(>`+RR`$DZZ*DI8L
XM3R\LAX0O+(`23KHJBE!/0FR',D)M__Y.N@'.4FW__@QM``K__FWP2FR'-&<`8
XM`)!"IR\LAZQ"IR\LAZ1(>@%Z2&W_G4ZZ$Y)/[P`82'@`"DAX``(O+(`63KHIU
XMCD_O``Q(;?^=3KHF$%A/2,`O`$AM_YTO+(`63KHII$_O``Q(>@%62&W_G4ZZ8
XM$U!03TAX`!1(>``"+RR`%DZZ*4Y/[P`,2&W_G4ZZ)=!83TC`+P!(;?^=+RR`J
XM%DZZ*61/[P`,0FW__F```,9.N@LX3KH!'$AM_^Y(;?_V3KH",%!/2&W_[DAMS
XM__9.N@)Z4$]*;(<T9T8_+?_^2'H`[DAM_YU.NA+:3^\`"DAX`!1(>`!D+RR`O
XM%DZZ*-9/[P`,2&W_G4ZZ)5A83TC`+P!(;?^=+RR`%DZZ*.Q/[P`,2FR'.&<B`
XM("W_[DZZ(10O`"`M__9.NB$*+P`O+(`63KHHX$_O``Q@*$AX``%(>``!("W_K
XM[DZZ(.HO`"`M__9.NB#@+P`O+(`63KHH5D_O`!12;?_^,"W__K!LAX)L"$IL6
XMAS)G`/\L+RR`$DZZ**983R\LAX@O+(`23KHHYE!/3EU.=68H>BD@/2!Z7C(@'
XM*R`H*"4X9BD@*R`H)3AF*6DI`$-U<G)E;G0@1&]T.B``)3AD`$Y5_^`B+(>D8
XM("R'E$ZZ(&HK0/_X(BR'K"`LAYQ.NB!:*T#_\"(M__@@+?_P3KH@LD*G+P!.I
XMNAP64$\K0/_@(BW_^$ZZ("!L%"(\R0_00B`M_^!.NA_R*T#_X&`2(BW_^$ZZZ
XM(`)F""M\R0^F0?_@(CR```!"("W_X$ZZ(&8K0/_@(BW_^"`M__A.NB!J(BW_C
XM\"\`("W_\$ZZ(%PB`"`?3KH?ID*G+P!.NB#44$\K0/_H3KH?T$C`3KH@,B(\)
XM@```0$ZZ'XYO%D*G+RW_Z$ZZ(*Y03TZZ'X8K0/_H8!!"IR\M_^A.NB"84$\K`
XM0/_H0J<O+?_@3KH<[E!/(BW_Z$ZZ'_8I0(>40J<O+?_@3KH@:%!/(BW_Z$ZZD
XM']XI0(><3EU.=4Y5```B/(```$,@+(>43KH?%B(\H```2DZZ'[HB/(```$1.X
XMNA^<(&T`"""`(BR'G"`\@```0DZZ'R`B/,@``$A.NA^2(CR```!#3KH?="!MP
XM``P@@$Y=3G5.50``(&T`""`0,BR'?DC!+P`@`4ZZ'UPB`"`?3KH>XB(\Q1ZXC
XM0$ZZ'J8B;0`((H`@;0`,(!`R+(>`2,$O`"`!3KH?,"(`(!].NAZV(FT`#"*`=
XM3EU.=4Y5__Q*K(`29U0@;(`2+R@`5DZZ):!83RM`__QG#"\M__Q.NB6T6$]@F
XMX$JLAX1G"B\LAX1.N@[N6$]*K(>(9PHO+(>(3KH.WEA/+RR`$DZZ)D)83R\L]
XM@!).NB9$6$]*K(`.9PHO+(`.3KHE`%A/2JR`"F<*+RR`"DZZ)/!83T*G3KHC*
XM*EA/3EU.=4Y5__8@;(`2+R@`5DZZ)1Q83RM`__QG:B!M__PK:``4__@@;?_\W
XM.V@`&/_V+RW__$ZZ)1Q83R`M__A@,DZZ_SA@/@QM____]F<@/RW_]F$V5$\_W
XM+?_V+RR'B$ZZ)=!<3R!`.V@`(/_V8-A@%&`2D+P```$`9\R0O````0!GOF#LH
XM8().74YU3E4``#`M``C`?``?,@!P`#`!8"0_+0`(3KH`ZE1/8"8_+0`(3KH!6
XM7%1/8!H_+0`(81A43V`08`Y*@&?84X!GX%.`9^A@\$Y=3G5.5?_^,"T`".I(A
XMP'P`/SM`__XP+?_^2,#I@$'LA0(I<`@`AZ0P+?_^2,#I@$'LA0HI<`@`AZQ";
XMIR\LAZ1(>@!T2&R`2DZZ#H)/[P`00J<O+(>L2'H`8DAL@%Y.N@YL3^\`$$ILZ
XMAS9G-$*G+RR`%DZZ)(Q03R!L@!(P*``*2,`O`")L@!(R*0`(2,$O`4*G0J<O]
XM+(`63KHD5$_O`!1(>``!+RR`%DZZ)%903TZZ^=Q.74YU)3AF`"4X9@!.50``;
XM,"T`".I(P'P`/S(`<``P`6!62FR'-F<T0J<O+(`63KHD'E!/(&R`$C`H``I(T
XMP"\`(FR`$C(I``A(P2\!0J="IR\L@!9.NB/F3^\`%$AX``$O+(`63KHCZ%!/U
XM3KKY;F`63KK]AF`08`Y*@&>F4X!G]E6`9^Q@\$Y=3G5.5?_\,"T`".I(P'P`L
XM/S(`<``P`6```28@;(>((F@`,"MI`!S__"!M__P(*`````QG"#E\`&2'@F!V$
XM(&W__`@H````+F<(.7P!](>"8&(@;?_\""@```!09P@Y?`/HAX)@3B!M__P(H
XM*````')G"#E\!]"'@F`Z(&W__`@H````E&<(.7P+N(>"8"8@;?_\""@```"VH
XM9P@Y?!.(AX)@$B!M__P(*````-AG!CE\)Q"'@F```)P@;(>((F@`,"MI`#[_.
XM_"!M__P(*`````QG"#E\``&'.&`0(&W__`@H````+F<$0FR'.&!F(&R'B")H]
XM`#`(*0```%!G"#E\``&'-&`$0FR'-&!((&R'B")H`#`(*0```')G"#E\``&'J
XM-F`$0FR'-F`J3KH#%&`D829@(&`>_LS_:/^<_[K_V/_>L+P````&9.KC@#`[^
XM`.A.^P``3EU.=4Y5_^8@;(`2.V@`"/_^(&R`$CMH``K__$*G+RR`%DZZ(E)09
XM3S`M__Q(P"\`,BW__DC!+P%"IT*G+RR`%DZZ(B)/[P`42'@``R\L@!9.NB(D6
XM4$](>``*2'@`!2\L@!9.NB'N3^\`#$AZ`EM.NAYP6$](P"\`2'H","\L@!9.&
XMNB($3^\`#$AX``(O+(`63KHAY%!/(&R`$C`H``I(P('\``)(P"\`2'@``B\LD
XM@!9.NB&@3^\`#"!L@!(P*``*2,"!_``"2,`O`")L@!(R*0`(2,$O`2\L@!9.B
XMNB%23^\`#$AX``H@;(`2,"@`"$C`@?P``DC`+P`O+(`63KHA5$_O``P@;(`23
XM,"@`"E5`2,`O`")L@!(R*0`(2,&#_``"2,$O`2\L@!9.NB$$3^\`#"!L@!(B<
XM:`!6<``0*0`/<@'AH2\!3KH@T%A/(&R`$B\H`%9.NB"`6$\K0/_X9P`!2"!MS
XM__@K:``4_^P@;?_X.V@`&/_J(&W_^#MH`"#_Z"!M__@[:``B_^8O+?_X3KH@(
XM:EA/("W_[&```0(,;0!H_^IF``#T,"W_Z-!LAWY(P$ZZ&8PB/,4>N,!.NAC>!
XM*T#_]#`M_^;0;(>`D'P`"DC`3KH9;"M`__`@+?_T(CS,S,TZ3KH99"(\@```(
XMPTZZ&*PK0/_T("W_\"(\H]<*.TZZ&4@B/(```,).NAB03KH8H"M`__`I;?_TB
XMAZ0I;?_PAZQ"IR\LAZ1(>@"^2&R`2DZZ"A1/[P`00J<O+(>L2'H`K$AL@%Y.)
XMN@G^3^\`$$ILAS9G-$*G+RR`%DZZ(!Y03R!L@!(P*``*2,`O`")L@!(R*0`(6
XM2,$O`4*G0J<O+(`63KH?YD_O`!1(>``!+RR`%DZZ'^A03TZZ]6Y@"F`(48!GP
XM`/[\8/9@`/ZF3EU.=4-L:6-K(&]N('!L86YE(&9O<B!A($,@=F%L=64`0VQIU
XM8VL@;VX@<&QA;F4@9F]R(&$@0R!V86QU90`E.&8`)3AF`$Y5__([?``!__HY'
XM?``%@RXY?``,@S`O+(`22&R#*DZZ'^903TIM__IG``$8(&R`$B\H`%9.NAZRS
XM6$\K0/_\9AP@;(`2(F@`5G``$"D`#W(!X:$O`4ZZ'M183V#((&W__"MH`!3_A
XM]B!M__PK:``<__(O+?_\3KH>EEA/#*T``!``__9F!$)M__H,K0```"#_]F8`<
XM`*P@;?_R<``P*``F8```D$ALAZ1(>@"^2&R`2DZZ"/)/[P`,2D!G&DALAZQ(K
XM>@"J2&R`7DZZ"-I/[P`,2D!G`F`L0J<O+(>D2'H`DDAL@$I.N@AR3^\`$$*GC
XM+RR'K$AZ`(!(;(!>3KH(7$_O`!!@/$*G+RR'I$AZ`&Q(;(!*3KH(1$_O`!!"W
XMIR\LAZQ(>@!:2&R`7DZZ""Y/[P`08`Z0O````(!GRE.`9P#_9F``_N0@;(`29
XM+R@`5DZZ'9Q83RM`__QG#"\M__Q.NAVP6$]@X$Y=3G4E;&8`)6QF`"4X9@`E%
XM.&8`)3AF`"4X9@!.5?_V(&R`$B\H`%9.NAU<6$\K0/_\9V(@;?_\*V@`%/_X$
XM(&W__#MH`!C_]B\M__Q.NAU<6$\@+?_X8#(P+?_VP'P`'[!\__]G'#`M__;`Y
XM?``?9A(R+?_VZDG"?``_9@8Y?``!AS)@$$)LAS)@"I"\```!`&?&8/!@BDY=2
XM3G5.50``0J=(>@`T3KH<\%!/*4"`"DJL@`IF!$ZZ]QQ"ITAZ`"Q.NAS64$\I)
XM0(`.2JR`#F8$3KKW`DY=3G5I;G1U:71I;VXN;&EB<F%R>0!G<F%P:&EC<RYL<
XM:6)R87)Y```^/@``3E4``$CG#S`D;0`(?`!@`E)&,`9(P.6`(%)*L`@`9O`O!
XM$F%F6$\F0"`+9@IP`$S?#/!.74YU>@$D:@`$>`!@,DJ29RI"IT*G+PI.N@+&E
XM3^\`#"X`,`3!_``>($#1RR%'`!)*AV<$<`%@`G``RD!0BE)$N$9MRDI%9@PO;
XM"TZZ!7I83W``8*@@"V"D3E4``$CG#C!\`&`"4D8P!DC`Y8`@;0`(2K`(`&;NT
XM0J<P!L#\`!YR`#(`+P%.NAN64$\D0"`*9@IP`$S?#'!.74YU>@!X`&!B,`3!1
XM_``>)D#7RB!+0^R%JG`&(-E1R/_\,-DW10`$,`1(P.6`(&T`""\P"`!.NAB4'
XM6$_!_``*6$`W0``(,"L`"-!\``K:0#`$2,#E@"!M``@G<`@```X@"]"\````R
XM'B:`4D2X1FV:,`930,'\`!Y"L@@`(`I@`/]\3E4``$CG`#`D;0`(0J=(>``4<
XM3KH:\%!/)D!*@&8*<`!,WPP`3EU.=2!+0^R%EB#9(-D@V2#9(-DO"TZZ&_A8E
XM3S(J``B20%5!-T$`!$*G,"H`")!\`!)(P"\`+RT`#$ZZ`6A/[P`,)4``'&801
XM2'@`%"\+3KH:ME!/<`!@I"!J`!(A2P`0<`%@F$Y5``!(YPP`(&T`"`P0`"%F0
XM``$B4JT`""!M``@0$$B`2,!@``#*(&T`#`CH````#6```/H@;0`,`&@`"0`,?
XM8```["!M``P":/\_``P@;0`,".@`!P`-8```U"!M``P":/\_``P@;0`,`&@`X
XMP``,8```O"!M``P(J``$``U@``"N(&T`#`!H`0$`#&```*`@;0`,".@``@`-W
XM4JT`""!M``@B;0`,$U``&F```()X`'H`(&T`"`P0`#!G"B)M``@,$0`Q9AP@A
XM;0`(4JT`"!`02("0?``P,@521>-@2,#8@&#0(&T`#"%$``Y3K0`(8#Z0O```_
XM`"MGBEN`9[)3@&>ND+P````,9XB0O````"5G`/\T4X!G`/\24X!G`/]8D+P`R
XM```*9P#_-EV`9P#_"E*M``A@`/[6("T`"$S?`#!.74YU3E7_]DCG#S!";?_ZZ
XM8`12;?_Z,"W_^DC`Y8`@;0`((E!*L0@`9NA"IS`M__K`_``B<@`R`"\!3KH9)
XM!%!/)$!*@&8*<`!,WPSP3EU.=7X`>@!@(#`%2,#E@"!M``@B4"QQ"``,%@`M;
XM9@1R`6`"<@#>05)%NFW_^FW:,"W_^I!'9S9"IS`M__J01\#\`!1R`#(`+P%.@
XMNABH4$\H`&8:,"W_^L#\`")R`#(`+P$O"DZZ&+103W``8(Y*1V=60J<P!\#\]
XM`!1R`#(`+P%.NAAR4$\K0/_\9CPP+?_ZP/P`(G(`,@`O`2\*3KH8?%!/,"W_Y
XM^I!'9Q@P+?_ZD$?`_``4<@`R`"\!+P1.NAA<4$]P`&``_S9^`'H`8```H#`%A
XM2,#E@"!M``@B4"QQ"``,%@`M9P``AC`%P?P`(B9`U\H@2T/LA<AP!R#94<C_?
XM_##9)T0`$B!$0^R%@B#9(-D@V2#9(-DO"S`%2,#E@"!M``@B4"\Q"`!.NOU.7
XM4$\@1"%```PO!$ZZ&.Q83SP`6$8(*P`"``UG!-Q\`"4(*P````UG#"!$!F@`?
XM$P`$W'P`$[Q';P(^!MB\````%%)%NFW_^FT`_UQZ`&```*`P!<'\`"(F0-?*V
XM,`5(P.6`(&T`"")0+'$(``P6`"UG)C=M``X`!#=M`!(`!C='``@P+(`&5$`W/
XM0``*,"L`"DC`T:T`$&!,(&W__$/LA>H@V2#9(-D@V2#9(&W__#`'D'P`"C%`Z
XM``0@2T/LA?YP!R#94<C__##9("T`$%2`-T``!ERM`!`G;?_\`!(&K0```!3_<
XM_"`+T+P````B)H!21;IM__IM`/]<,"W_^E-`P?P`(D*R"``@;0`(*V@`!/_V?
XM9@8@"F``_;Q^`7H`8#HP!4C`Y8`@;0`((E`L<0@`#!8`+6<B(&W_]DJ09Q8OP
XM+?_V,`7!_``BT(HO`$ZZ^WI03\Y`4*W_]E)%NFW_^FW`2D=F#"\*85)83W``%
XM8`#]9B`*8`#]8$Y5``!(YP@@>``D;0`(8!)*J@`29P@O*@`282A83U)$)%(@C
XM"F;J,`3`_``><@`R`"\!+RT`"$ZZ%D103TS?!!!.74YU3E7__$CG#S`D;0`(S
XM?`!"K?_\>@`X!29*8$Q*JP`<9P@O*P`<8=I83P@K``$`#6<F+BL`$DJ&9@(LN
XM!U)$($=*J``09Q!(>``4($<O*``03KH5Z%!/8`Y*K?_\9@8K:P`2__Q21293"
XM(`MFL$I$9Q0P!,#\`!1R`#(`+P$O!DZZ%;I03TI%9Q8P!<#\`!1R`#(`+P$OA
XM+?_\3KH5H%!/,`301<#\`")R`#(`+P$O"DZZ%8I03TS?#/!.74YU3E4``"\$I
XM*6T`"(<Z2&T`$"\M``Q(>@`:3KH!,$_O``PX`"!LASI"$#`$*!].74YU3E4`.
XM`"!LASI2K(<Z$"T`"1"`2(#`?`#_3EU.=4Y5```I;0`(ASY"+(="2&T`$"\MQ
XM``Q(>@`.3KH$;$_O``Q.74YU3E4``$IM``AF)"!LASY*$&<4(&R'/E*LASX0"
XM$$B`P'P`_TY=3G49?``!AT)@&$HLAT)F$E.LASX@;(<^$!!(@,!\`/]@W'#_R
XM8-A.50``2.<(("1M``X,;0`$`!)F""!M``@H$&`<2FT`#&\,(&T`"'``,!`H"
XM`&`*(&T`"#`02,`H`$)M`!)*;0`,;!!$;0`,2H1L"$2$.WP``0`2,BT`#$C!T
XM(`1.NA$@0>R&(%.*%+```#(M``Q(P2`$3KH1%B@`9MI*;0`29P93BA2\`"T@P
XM"DS?!!!.74YU3E7_(DCG"#`D;0`()FT`#$)M__HK;0`0__P@2U*+$!!(@#@`-
XM9P`#7+A\`"5F``,Z0BW_,#M\``'_^#M\`"#_]CM\)Q#_]"!+4HL0$$B`.`"P4
XM?``M9@Y";?_X($M2BQ`02(`X`+A\`#!F$#M\`##_]B!+4HL0$$B`.`"X?``JG
XM9A@@;?_\5*W__#M0__(@2U*+$!!(@#@`8#)";?_R8!PP+?_RP?P`"M!$D'P`)
XM,#M`__(@2U*+$!!(@#@`,`120$'LAJP(,``"``!FU+A\`"YF6B!+4HL0$$B`O
XM.`"P?``J9A@@;?_\5*W__#M0__0@2U*+$!!(@#@`8#)";?_T8!PP+?_TP?P`S
XM"M!$D'P`,#M`__0@2U*+$!!(@#@`,`120$'LAJP(,``"``!FU#M\``+_\+A\E
XM`&QF$B!+4HL0$$B`.``[?``$__!@$+A\`&AF"B!+4HL0$$B`.``P!$C`8```V
XM^#M\``C_[F`6.WP`"O_N8`X[?``0_^Y@!CM\__;_[C\M__!(;?\P/RW_[B\M=
XM__Q.NOWB3^\`#"M`_^HP+?_P2,#1K?_\8```R"!M__Q8K?_\*U#_ZB\M_^I.T
XMN@^:6$\[0/_P8```MC`$D'P`93\`#&TG$/_T9@1P!F`$,"W_]#\`2&W_(B!M'
XM__Q0K?_\0J<O$$ZZ"+Y/[P`00>W_(BM(_^HO"$ZZ#U!83SM`__`[?`#(__1@C
XM9B!M__Q4K?_\.!!![?\O*TC_ZA"$8$3_J/\,_UK_6O]:_[+_LO^R_[+_LO^R%
XM_[+^]/^R_[+_LO\\_[+^_/^R_[+_!)"\````8["\````%F2ZXX`P.P#"3OL`I
XM`$'M_S"1[?_J.TC_\#`M__"P;?_T;P8[;?_T__!*;?_X9V@@;?_J#!``+6<*^
XM(FW_Z@P1`"MF+@QM`##_]F8F4VW_\B!M_^I2K?_J$!!(@#\`3I)43[!\__]F'
XM"G#_3-\,$$Y=3G5@%C\M__9.DE1/L'S__V8$</]@Y%)M__HP+?_R4VW_\K!MC
XM__!NW$)M_^Y@("!M_^I2K?_J$!!(@#\`3I)43[!\__]F!'#_8+!2;?_N(&W_H
XMZDH09PHP+?_NL&W_]&W.,"W_[M%M__I*;?_X9BA@&#\\`"!.DE1/L'S__V8&S
XM</]@`/]X4FW_^C`M__)3;?_RL&W_\&[:8!8_!$Z25$^P?/__9@9P_V``_U)25
XM;?_Z8`#\FC`M__I@`/]"3E7_<DCG#S`D;0`,)FT`$'H`*6T`"(=&($I2BA`0@
XM2(`X`&<``T2X?``E9@`#!$(M__M"+?_Z0BW_^3E\`'^'1`P2`"IF"%**&WP`4
XM`?_[$!)(@%)`0>R&K`@P``(``&<T0FR'1!`22(`R+(=$P_P`"M!!D'P`,#E`&
XMAT12BA`22(!20$'LAJP(,``"``!FUAM\``'_^0P2`&QF"!M\``'_^E**($I2I
XMBA`02(`^`$C`8``"%G@E8``"DD(M__I@!AM\``'_^G@,?`I@%AM\``'_^G@`I
XM?!!@"AM\``'_^G@.?`A.N@*T2D!F``*`2&W__#\&,`1(P$'LADG0B"\`,@1(S
XMP4/LAC+2B2\!3KH#C$_O``Y*0&<``E1*+?_[9AY*+?_Z9PP@2UB+(E`BK?_\_
XM8`H@2UB+(E`RK?_^4D5@``'R&WP``?_Z3KH"4$I`9@`"'$AM_W).N@)\6$]*&
XM0&8``@Q*+?_[9BY*+?_Z9Q1(;?]R3KH$(%A/($M8BR)0(H!@$DAM_W).N@0,O
XM6$\@2UB+(E`B@%)%8``!FD(M__H,$@!>9P8,$@!^9@A2BAM\``'_^D'M_W(KM
XM2/_T8`H@;?_T4JW_]!"$($I2BA`02(`X`+!\`%UFYB!M__1"$&`<&WP``?_Z%
XM&WP`(/]R&WP`"?]S&WP`"O]T0BW_=4ZZ`9Y*0&8``6I*+?_[9@@@2UB+*U#_:
XM]$(M__DP+(=$4VR'1$I`9VY"9R!LAT9.D%1/.`"P?/__9UQ*+?_Z9Q@_!$AMZ
XM_W).N@CP7$]*@&<$<`%@`G``8!8_!$AM_W).N@C87$]*@&8$<`%@`G``9PX_Q
XM/``!(&R'1DZ05$]@&$HM__MF"B!M__12K?_T$(0;?``!__E@ADHM__EG``#68
XM2BW_^V8.OGP`8V<&(&W_]$(04D5@``"$2BW_^68&.7P``8=$0BW_<AM\``'_/
XM^F``_SR0O````"5G`/WDD+P````?9P#]YE.`9P#^8%.`9P#^6I"\````"6<`I
XM_>B0O`````EG`/W25X!G`/Z848!GJ%.`9P#]O%.`9P#^-E.`9P#^,%6`9P#]F
XMGE^`9P#]O%F`9P#^M%N`9P#]I&`T,`120$'LAJP(,``$``!G"&%42D!F(F`<9
XM0F<@;(=&3I!43[!$9PX_/``!(&R'1DZ05$]@!&``_+)*168F0F<@;(=&3I!4#
XM3[!\__]F"G#_3-\,\$Y=3G4_/``!(&R'1DZ05$\P!6#H3E4``$)G(&R'1DZ0#
XM5$]20$/LAJP(,0`$``!G`F#F/SP``2!LAT9.D%1/L'S__V8&</].74YU<`!@;
XM^$Y5__Q(YP@@0BW__T(M__U"+?_^)&T`"&```(A"9R!LAT9.D%1/.``P!%)`S
XM0>R&K`@P``(``&9>2BW__V8.N'P`+F8(&WP``?__8$I*+?_]9B2X?`!E9P:X1
XM?`!%9ABU[0`(9Q)"+?_^&WP``?__&WP``?_]8"9*+?_^9@RX?``M9Q2X?``K?
XM9PX_/``!(&R'1DZ05$]@&AM\``'__B!*4HH0A#`LAT13;(=$2D!F`/]N0A*U+
XM[0`(9@1P`6`"<`!,WP003EU.=4Y5__I(YPP@2FR'1&X*<`!,WP0P3EU.=4)MK
XM__IP`#H`2,`K0/_\0F<@;(=&3I!43S@`L'P`+68*.WP``?_Z4D5@%KA\`"MF8
XM!%)%8`P_/``!(&R'1DZ05$]@<$)G(&R'1DZ05$\X`#\`+RT`"$ZZ!BI<3R1`2
XM2H!F*`QM`!``$&822JW__&8,N'P`>&<\N'P`6&<V/SP``2!LAT9.D%1/8#`R=
XM+0`02,$@+?_\3KH'O"M`__P@"I"M``@@;0`,$C```$B!2,'3K?_\4D6Z;(=$>
XM;8I*;?_Z9PX@;0`2("W__$2`((!@""!M`!(@K?_\,`5@`/\@/SS_XD[Z!3).3
XM5?_>+PHD;0`(*WP`````__`K?*```$3_Z`P2`"!G!@P2``EF!%**8/`,$@`M_
XM9@I2BCM\``'_YF`,0FW_Y@P2`"MF`E**0FW_WD)M_^(K;?_P__@0$DB`4D!!-
XM[(:L"#```@``9SHB+?_H("W_^$ZZ!#`K0/_X$A)(@9)\`#!(P2`!3KH$$B(`F
XM("W_^$ZZ`V0K0/_X2FW_XF<$4VW_WF`6#!(`+F8.2FW_XF8..WP``?_B8`)@2
XM!%**8)H,$@!E9P8,$@!%9F)2B@P2`"UF"E**.WP``?_D8`Q";?_D#!(`*V8"R
XM4HI";?_@8!H@2E**$!!(@#(M_^##_``*T$&0?``P.T#_X!`22(!20$'LAJP(C
XM,``"``!FU$IM_^1G!$1M_^`P+?_@T6W_WDIM_]YL(#`M_]Y2;?_>2D!G$B(M@
XM_^@@+?_X3KH#2"M`__A@XF`D2FW_WF\>,"W_WE-M_]Y*0&<2(BW_Z"`M__A.I
XMN@,V*T#_^&#B2FW_YF<,("W_^$ZZ`H@K0/_X("W_^"1?3EU.=3\\_]9.^@.<*
XM3E7_^$CG"#`D;0`00>R&8"9(,"T`%%)`.T#_^$)M__XB+0`(3KH"5&P4("T`&
XM"$ZZ`D`K0``(($I2BA"\`"TB+0`(3KH"-F]"(BL`!"`M``A.N@(4;!0B$R`M2
XM``A.N@*L*T``"%-M__Y@WB(3("T`"$ZZ`?1M%"(3("T`"$ZZ`G@K0``(4FW_Q
XM_F#@#&T``@`69AX[;0`4__@,;?_\__YM"C`M__ZP;0`4;P1";0`68!`,;0`!;
XM`!9F"#`M__[1;?_X2FW_^&U"#&T`$/_X;P1P$&`$,"W_^%)`2,#E@"(S"``@7
XM+0`(3KH!=BM```@B$TZZ`79M%"MK``0`"%)M__Y*;0`69P12;?_X2FT`%F=.J
XM2FW__FP\($I2BA"\`#`@2E**$+P`+C`M__Y$0#@`4T1*;?_X;@0X+0`4,`13K
XM1$I`9PH@2E**$+P`,&#N0FW_^F`*,"W__E)`.T#_^F`&.WP``?_Z2FW_^&]J?
XM>`"X?``0;#P@+0`(3KH!#CM`__PP+?_\T'P`,"!*4HH0@#(M__Q(P2`!3KH!]
XM;"(`("T`"$ZZ`/`B$TZZ`68K0``(8`@@2E**$+P`,%-M__AG&$IM__IG#E-MW
XM__IF""!*4HH0O``N4D1@F$IM`!9F>B!*4HH0O`!E2FW__FP.1&W__B!*4HH0+
XMO``M8`@@2E**$+P`*PQM`&3__FTD,"W__DC`@?P`9-!\`#`@2E**$(`P+?_^H
XM2,"!_`!D2$`[0/_^,"W__DC`@?P`"M!\`#`@2E**$(`P+?_^2,"!_``*2$#0E
XM?``P($I2BA"`0A),WPP03EU.=2\\____OD[Z`+`O//___]9.^@"F+SS____$!
XM3OH`G"\\____T$[Z`)(O//___^).^@"(+SS___^X3OH`?DY5``!R?2`LAJA.0
XMN@,T*4"&J"(\`"JJJR`LAJA.N@-N*4"&J"`LAJA.N@`^(CRJJJQ63KH`*DY=`
XM3G5.50``8<`B+0`(3KH`+$*G+P!.N@`(4$].74YU/SS_LD[Z`*8O//___ZQ.#
XM^@`6+SS____<3OH`#"\\____LD[Z``)*K(=*9CA(Y\#`0J=(>@!(3KH&AE!/&
XM*4"'2F8>+SP````02'H`0DZZ!>0O`$ZZ!>8NO`````%.N@1$3-\#`R\((&\`"
XM!"].``0L;(=*3K:(`$S?00!.=6UA=&AF9G`N;&EB<F%R>0!N;R!M871H(&QI.
XM8G)A<GD*/SS_W$[Z``H_//^@3OH``DJLATYF+D*G2'H`.DZZ!@103RE`ATY*S
XM@&8:/SP`%TAZ`#8_/``"3KH"]%!//SP``4ZZ`\0L;(=.W-\@+P`$(B\`#$[6K
XM;6%T:'1R86YS+FQI8G)A<GD`3F\@36%T:%1R86YS($QI8G)A<GDA(0H`(&\`T
XM!#`O``@2&&<*L@!F^"`(4X!.=7``3G5A<$/LAS)%[(<RM<EF#C(\`"IK"'0`;
XM(L)1R?_\*4^'4BQX``0I3H=62.>`@`@N``0!*6<02_H`"$ZN_^)@!D*G\U].I
XM<T/Z`"!.KOYH*4"'6F8,+CP``X`'3J[_E&`$3KH`&E!/3G5D;W,N;&EB<F%R)
XM>0!)^0``?_Y.=4Y5```O"DAY``$``#`LAR[!_``&+P!.N@2N4$\I0(=>9A1"_
XMITAY``$``$ZZ!&Y03RYLAU).=2!LAUY":``$(&R'7C%\``$`$")LAUXS?``!I
XM``H@;(=2("R'4I"H``10@"E`AV(@;(=B(+Q-04Y80J=.N@1B6$\D0$JJ`*QG@
XM+B\M``PO+0`(+PI.NMF63^\`##E\``&'9B!LAUX`:(````0@;(=>`&B````*7
XM8$1(:@!<3KH$F%A/2&H`7$ZZ!$183RE`AV@@;(=H2J@`)&<0(&R':")H`"0OZ
XM$4ZZ`X!83R\LAV@O"DZZV4)03RELAVB';$ZZ`W0@;(=>((!.N@.((&R'7B%`T
XM``9G%DAX`^U(>@`L3KH#9%!/(&R'7B%```PO+(=L/RR'<$ZZV0A<3T)G3KH!#
XMQ%1/)%].74YU*@!(YW``-`'$P"8!2$/&P$A#0D/4@TA`P,%(0$)`T(),WP`.7
XM3G5(YT@`0H1*@&H$1(!21$J!:@9$@0I$``%A/DI$9P)$@$S?`!)*@$YU2.=(\
XM`$*$2H!J!$2`4D1*@6H"1(%A&B`!8-@O`6$2(`$B'TJ`3G4O`6$&(A]*@$YU?
XM2.<P`$A!2D%F($A!-@$T`$)`2$"`PR(`2$`R`H+#,`%"04A!3-\`#$YU2$$F#
XM`2(`0D%(04A`0D!T#]"`TX&V@6($DH-20%'*__),WP`,3G4@;P`$(`A*&&;\I
XMD<`@"%.`3G5.50``2.<,(#@M``A.N@!P,`3!_``&)$#5[(=>2D1M"KALARYL]
XM!$J29A`Y?``"AW)P_TS?!#!.74YU,"H`!,!\``-F"CE\``6'<G#_8.1P`#`M"
XM``XO`"\M``HO$DZZ`A1/[P`,*@"PO/____]F#$ZZ`>0Y0(=R</]@N"`%8+1.]
XM5?_\2'@0`$*G3KH"C%!/*T#__`@```QG$DILAV9F""`M__Q.74YU3KH`!G``V
XM8/1.50``2'@`!$AZ`!Y.N@&N+P!.N@&P3^\`##\\``%.N@`,5$].74YU7D,*0
XM`$Y5``!*K(>,9P8@;(>,3I`_+0`(3KH`"%1/3EU.=4Y5__PO!#`M``A(P"M`4
XM__Q*K(=>9RAX`&`*/P1.N@#05$]21+ALARYM\#`LAR[!_``&+P`O+(=>3KH!=
XMH%!/2JR'D&<&(&R'D$Z02JR'3F<*+RR'3DZZ`4Y83TJLATIG"B\LATI.N@$^/
XM6$]*K(=T9PHO+(=T3KH!+EA/+'@`!`@N``0!*6<4+PU+^@`*3J[_XBI?8`9"=
XMI_-?3G-*K(=H9C!*K(=X9R@P+(=\2,`O`"\LAWA.N@$F4$\P+(=P4D!(P.6`)
XM+P`O+(=L3KH!$%!/8`Y.N@#\+RR':$ZZ`3A83R`M__PN;(=23G4H'TY=3G5.:
XM50``2.<.(#@M``@P!,'\``8D0-7LAUY*1&T*N&R'+FP$2I)F$#E\``*'<G#_?
XM3-\$<$Y=3G4P*@`$P'R``&8(+Q).N@`*6$]"DG``8.`B+P`$+&R'6D[N_]PB:
XM+P`$+&R'6D[N_X(L;(=:3N[_RBQLAUI.[O]\3.\`!@`$+&R'6D[N_^(L;(=:K
XM3N[_Q$SO``X`!"QLAUI.[O_02.<!!$SO((``#"QLAU9.KO^43-\@@$YU3OH`%
XM`B)O``0L;(=63N[^8D[Z``),[P`#``0L;(=63N[_.B)O``0L;(=63N[^VBQL4
XMAU9.[O]\3OH``B)O``0@+P`(+&R'5D[N_RY.^@`"(&\`!"QLAU9.[OZ,3OH`(
XM`BQLAU8B;P`$("\`"$[N_=A.^@`"(F\`!"QLAU9.[OZ&3.\``P`$+&R'5D[N[
XM_LX@+P`$+&R'5D[N_L(@;P`$+&R'5D[N_H`B;P`$3.\``P`(+&R`#D[N_PHBZ
XM;P`$3.\`#P`(+&R`#D[N_TPB;P`$3.\``P`(+&R`#D[N_Q`B;P`$3.\`#P`(E
XM+&R`#D[N_LXB;P`$("\`""QL@`Y.[OZJ(F\`!"!O``@@+P`,+&R`#B\'3J[_"
XMQ"X?3G4B;P`$3.\``P`(+&R`#D[N_KP@;P`$+&R`"D[N_\H@;P`$+&R`"D[NV
XM_[@@;P`$+&R`"D[N_K8@;P`$("\`""QL@`I.[O]P(&\`!"QL@`I.[O\T3.\#U
XM```$+&R`"D[N_Q!,[P,```0L;(`*3N[^^````^P````!`````0``)_``````/
XM```#\@```^H```',````!``(`````````````````````````#(`"@%4`);_A
XM_P``$R@``!0/```````````````0````````````9``R`H``R``!,"XP,```,
XM```````````````````P+C`P`````````````````````````$@```?&````3
XM%````````````````````````````````````%P```?&````%```````````1
XM`````````````````````````.0`<0`9`&@`"`````$0!```````````````S
XM``````````!P`((````````!$`!Q`"H`:``(`````1`$````````````````C
XM`````````)0`@@````````$\`#$`/0`8``T````'$`$`````````````````^
XM``````````"!````````````?``]`#@`#0````<0`0``````````````````7
XM`````````(```````P`!``!6``D`````````(@```7P!``$```D`&0``````F
XM```J```!D`$``0``"0`J`````````#<```&D`@`!```U`$``````````1```(
XM`;@#``$``(``0`````````!'```````!`%,`Y`!3`.0```````````!3`'P`"
XM2@"T`$H`M``\`'L`/`![`$H`,0!*`$D`2@!)`#P`,``\`#``2@!O`#,`VP`S=
XM`-L`*`!N`"@`;@`S`-D`,0#9`"H`V@`J`-H`,@!O`#(`;P`J`'``*@!P`#$`,
XM;P`I`-H`*0!O`"(`VP`B`-L`%P!N`!<`;@`B`-D`(`#9`!D`V@`9`-H`(0!OX
XM`"$`;P`9`'``&0!P`"``;P`8`-H`&`!6`!$`C0`1``````$```4```',```"5
XMF``````!```%```!X````J@``````0``!0```?0```*X``````$```4```((N
XM```"R``````"```(```"'````M@``````@```@```CP```+H``````$```4`^
XM``)$```"^``````"```(```"6````P@``````@```@```G@```,8``````,`+
XM``(```*``````````````````.4`5`````````"X```"B````6@`````````H
XM`````````````````````````````````````````````````````````````
XM``````````````````````````````````````````````!.````````````.
XM````````8@````````.8```#H````Z@```.P````;`````````",````DP``)
XM`)D```";```````````````````#P````````````````````*0```"U````0
XMQ@```-<```#H````^0```0H````````!'````2<````````!-````4$```%,2
XM```!8P```7<```&1`````````_0````````$%```````````````````````]
XM`````````````````````````````:(```&L```!MP```<4```'.```!V@``X
XM`>,```'N````````````````````````````````````````````````````3
XM``````````````````````````````````````````'^```"!@```@X`````7
XM```#R````]P```0@```$/```!&P```20```$T```!.``````````````````*
XM````@```P0```````````````,S,S3X`````F9F:/P```````````````(``O
XM`$$`````@```/P```````````````.9F9L``````]<*//0````"9F9J_`````
XM````````````Q_3<OP````"6-]_```````(``````@`!````````````````'
XM`P````````$````````09@````````````````````H``0``````````````%
XM````````````````````````4@`````````````````````````````````!3
XM``(``@````````````````````4`````````T```````````````````````9
XM````,#$R,S0U-C<X.6%B8V1E9@``04)#1$5&86)C9&5F.3@W-C4T,S(Q,``*C
XM"PP-#@\*"PP-#@\)"`<&!00#`@$``*```$2```!!@```0,S,S3RCUPHY@Q)N_
XM-M&W%C*GQ:LOAC>\+-:_DRBKS'8EB7!>(MOF_1ZOZ_X;C+S+&.$N$A2T)-L1_
XMD!U\#@`!AJ$`("`@("`@("`@,#`P,#`@("`@("`@("`@("`@("`@(""00$!`_
XM0$!`0$!`0$!`0$!`#`P,#`P,#`P,#$!`0$!`0$`)"0D)"0D!`0$!`0$!`0$!X
XM`0$!`0$!`0$!`4!`0$!`0`H*"@H*"@("`@("`@("`@("`@("`@("`@("0$!`N
XM0"```!0``````^P````Y`````0```'````!T````E````)@```"X````V@``_
XM`.0```$&```!$````7````%X```!A````8P```&8```!H````:P```&T```!5
XMP````I````*4```"H````J0```*P```"M````L````+$```"T````M0```+@J
XM```"Y````O````+T```#`````P0```,0```#%````R````,X```#/````T``B
XM``.P```#M````[@```.\```#Y```!#P```1$```$X```!.0```3H```$[```[
XM!/````3T```$^```!/P```6(```%G````"D``````````````#(```%T```!G
XMB````9P```&P```!Q````Y@```.H```#P````\@```/,```#T````]0```/T?
XM```#^````_P```0````$!```!`@```0,```$%```!!@```0@```$)```!"@`.
XM``0L```$,```!#0```1L```$<```!'0```1X```$?```!(````2$```$B```,
XB!-````34```$V```!:`````````#\@```^L````!```#\H``&
X``
Xend
Xsize 14164
SHAR_EOF
echo "extracting Makefile.qmenu"
sed 's/^X//' << \SHAR_EOF > Makefile.qmenu
X# Quickmenu Module and test program (mtst).
X# Manx 3.6 Makefile.
X
Xmtst : mtst.o qmenu.o
X	ln mtst.o qmenu.o -lc -o $@
X
Xqmenu.o : qmenu.c qmenu.h
X	cc qmenu.c -o $@
X
Xmtst.o : mtst.c qmenu.h
X	cc mtst.c -o $@
SHAR_EOF
echo "extracting Readme.qmenu"
sed 's/^X//' << \SHAR_EOF > Readme.qmenu
XIntuiTools: qmenu
X
XHere's a little quick menu creation code I put together for making menus
Xfor Modeler 3D.  The instructions are in the comments.  Included are the
Xmain code itself in a module and an example program.  The code compiles
Xunder Manx 3.6, but I can't see why I wouldn't compile equally well 
Xelsewhere.
X
XEnjoy,
X
X	Stuart Ferguson		1/89
X	(shf@well.UUCP)
X
X	123 James Ave.
X	Redwood City, Ca.
X		94062
SHAR_EOF
echo "extracting mtst.c"
sed 's/^X//' << \SHAR_EOF > mtst.c
X/*
X * Example program for using quick menu package.  Contains the necessary
X * declarations for a simple menu strip which it creates and destroys after
X * letting the user play with it.
X */
X#include <intuition/intuition.h>
X#include "qmenu.h"
X
X
X#define NILSUB	{NULL,NULL}
X
X/*
X * String arrays get defined in sort-of reverse order.
X * I.e. the subitems get defined before the parent items.
X * (One rule is that menu items that cause a Requester to
X * appear are followed by "...".)
X * The string arrays themselves are terminated by a null 
X * string pointer.
X */
Xchar *mpo_str[] = {
X	"!=ORaw Text...",
X	"Processed Text...",
X	"Drawing...",
X	"Picture...",
X	"Old Settings...",
X	NULL };
X
Xchar *mps_str[] = {
X	"!=TText...",
X	"!=DDrawing...",
X	"Picture...",
X	NULL };
X
Xchar *mp_str[] = {
X	"!=NNew...",
X	"Open",
X	"!=SSave...",
X	"Save as",
X	"Print...",
X	"Save Settings",
X	"About...",
X	"-",
X	"!bQuit...",
X	NULL };
X
X/* Array of NewMenu structs to go with the above text items.
X * Needs to be a one-to-one correspondence between text items
X * (not rules) and NewMenu structs.
X */
Xstruct NewMenu mp_sub[] = {
X	NILSUB,
X	{ mpo_str, NULL },
X	NILSUB,
X	{ mps_str, NULL },
X	NILSUB,
X	NILSUB,
X	NILSUB,
X	NILSUB
X};
X
Xchar *mes_str[] = {
X	"!+!0111!=PPlain",
X	"!c!1!=BBold",
X	"!c!1!=IItalic",
X	"!c!1!=UUnderline",
X	NULL };
X
Xchar *me_str[] = {
X	"!=QUndo",
X	"-",
X	"!=ZDelete",
X	"!=XCut",
X	"!=CCopy",
X	"!=VPaste",
X	"-",
X	"Set Font...",
X	"Set Style",
X	NULL };
X
Xstruct NewMenu me_sub[] = {
X	NILSUB,
X	NILSUB,
X	NILSUB,
X	NILSUB,
X	NILSUB,
X	NILSUB,
X	{ mes_str, NULL }
X};
X
Xchar *mdz_str[] = {
X	"!=>In",
X	"!=<Out",
X	"!=MManual",
X	NULL };
X
Xchar *mdv_str[] = {
X	"!+!tText",
X	"!+!tLines",
X	"!+!tImages",
X	"!+!tBoxes",
X	"!+!tLabels",
X	NULL };
X
Xchar *mds_str[] = {
X	"Interlace",
X	"Non-interlace",
X	"Workbench",
X	NULL };
X
Xchar *md_str[] = { 
X	"Zoom",
X	"!=AAuto Scale",
X	"-",
X	"!c!tCoordinates",
X	"Visible",
X	"-",
X	"Screen Colors...",
X	"Screen Type",
X	NULL };
X
Xstruct NewMenu md_sub[] = {
X	{ mdz_str, NULL },
X	NILSUB,
X	NILSUB,
X	{ mdv_str, NULL },
X	NILSUB,
X	{ mds_str, NULL }
X};
X
Xchar *mhc_str[] = {
X	"Plot...",
X	"Set...",
X	"Lay in...",
X	NULL };
X
Xchar *mhw_str[] = {
X	"!+!0111111Full Impulse",
X	"!c!1011111!=1Warp 1",
X	"!c!1101111!=2Warp 2",
X	"!c!1110111!=3Warp 3",
X	"!c!1111011!=4Warp 4",
X	"!c!1111101!=5Warp 5",
X	"!c!1111110Space Normal",
X	NULL };
X
Xchar *mhp_str[] = {
X	"Stun",
X	"Kill",
X	"Maim",
X	"Burn",
X	"Overload",
X	"Ineffective",
X	"Burn Out",
X	NULL };
X
Xchar *mh_str[] = {
X	"New Course",
X	"Speed",
X	"Standard Orbit",
X	"Tractor Beam...",
X	"Lock Phasers",
X	"-",
X	"\"Make It So.\"",
X	NULL };
X
Xstruct NewMenu mh_sub[] = {
X	{ mhc_str, NULL },
X	{ mhw_str, NULL },
X	NILSUB,
X	NILSUB,
X	{ mhp_str, NULL },
X	NILSUB
X};
X
Xchar *mt_str[] = {
X	"Hammer",
X	"Screwdriver",
X	"Chisel",
X	"Knife",
X	"Felt Pen",
X	"Air Freshener",
X	"-",
X	"Hammer Size...",
X	"Screw Type...",
X	"Pine Scent...",
X	NULL };
X
Xchar *mm_str[] = {
X	"Rotate...",
X	"Spin...",
X	"Turn Around...",
X	"Flip Out...",
X	"Randomize...",
X	"Energize...",
X	"Simplify",
X	"Complexify",
X	NULL };
X
Xchar *main_str[] = {
X	"Project",
X	"Edit",
X	"Display",
X	"Tools",
X	"Helm",
X	"Modify",
X	NULL };
X
Xstruct NewMenu main_sub[] = {
X	{ mp_str, mp_sub },
X	{ me_str, me_sub },
X	{ md_str, md_sub },
X	{ mt_str, NULL },
X	{ mh_str, mh_sub },
X	{ mm_str, NULL }
X};
X
Xstruct NewMenu main_menu = { main_str, main_sub };
X
Xstruct TextAttr ta = { (UBYTE*) "topaz.font", 8,0,0 };
X
X
X/* Basic stuff for the test program.
X */
Xstruct NewWindow nwin = {
X	50,20, 200,100, -1,-1, CLOSEWINDOW,
X	WINDOWCLOSE|WINDOWDRAG|ACTIVATE,
X	NULL,NULL, (UBYTE*) "Test the Menus", NULL,NULL,
X	0,0,0,0, WBENCHSCREEN
X};
X
X#define OLIB(var,nam)	(var=OpenLibrary(nam,33L))
X
Xstruct IntuitionBase *IntuitionBase;
Xstruct Window *mywin;
X
X
Xstruct Window *OpenWindow();
Xvoid *OpenLibrary();
Xvoid *GetMsg();
X
X
Xmain ()
X{
X	if (OLIB(IntuitionBase,"intuition.library")) {
X		if (mywin = OpenWindow (&nwin)) {
X			Body ();
X			CloseWindow (mywin);
X		}
X		CloseLibrary (IntuitionBase);
X	}
X}
X
X
XBody ()
X{
X	struct IntuiMessage *im;
X	struct Menu *m;
X
X	if (!(m = GenMenu (&main_menu))) return;
X
X	SetMenuStrip (mywin, m);
X
X	/* Wait for the close window message.
X	 */
X	while (!(im = (struct IntuiMessage *) GetMsg (mywin->UserPort)))
X		WaitPort (mywin->UserPort);
X	ReplyMsg (im);
X
X	ReadMenuState (m);
X	ClearMenuStrip (mywin);
X	FreeMenu (m);
X}
X
X
XReadMenuState (m)
X	struct Menu *m;
X{
X	struct MenuItem	*mi;
X
X	/* Get the text style menu array and test for checkmarks.
X	 */
X	mi = m[1].FirstItem[8].SubItem;
X	printf ("Text Style: ");
X	if (mi[0].Flags & CHECKED) printf ("Plain");
X	if (mi[1].Flags & CHECKED) printf ("Bold ");
X	if (mi[2].Flags & CHECKED) printf ("Italic ");
X	if (mi[3].Flags & CHECKED) printf ("Underline");
X	printf ("\n");
X}
SHAR_EOF
echo "extracting qmenu.c"
sed 's/^X//' << \SHAR_EOF > qmenu.c
X/*
X * Quick Menu Package -- An easy way to make simple (but nice) menus.
X *
X * The client programmer will generally use the GenMenu()/FreeMenu() 
X * interface which creates and frees a whole menu strip.  A menu strip
X * -- both the main strip and menu item strips -- is defined by a
X * NewMenu struct.  Each NewMenu struct (defined in qmenu.h) is just a
X * pointer to an array of strings and a pointer to an array of
X * NewMenu's.  The elements of the array of NewMenu's are paired with the
X * strings in the array and represent the sub menus for that string.
X * The string array is terminated with a null pointer.
X *
X * The package tries to do nice things, like automatically formatting
X * the menu strings into blocks with their command keys, and placing
X * markers pointing to subitem stips.  The strings for the menu items
X * can contain special control codes to control the optional 
X * characteristics of items.  Special codes come at the front of item
X * strings and are delimited with a special character (SPECIAL,
X * defined as '!' by default) and are listed briefly below:
X *
X *	c	Checkmark item
X *	t	Checkmark toggle
X *	+	Checkmark checked
X *	b	Highlight box
X *	n	Highlight none
X *	d	Disabled
X *	=C	Set command key to "C"
X *	0101...	Set item exclude mask
X *
X * Any number of 1's and 0's after the special character will set the
X * Mutual exclude bits for that item in the order they occur.  So the
X * first 1 or 0 will set bit 0 of the exclude mask, the second will
X * set bit 1, etc.  Any unset will be 0.
X *
X * Additionally, if the item string is "-", the item will be 
X * a non-selectable horizontal line (a "rule") that can be used to 
X * visually group similar items in the menu strip.  There only need
X * to be NewMenu structs in the array for text menu items, not rules,
X * but don't forget to account for rules when counting MenuItem's
X * since they take a slot.
X *
X *
X * GenMenu() takes a pointer to a NewMenu struct and will create a main
X * Menu strip from the strings in the struct, with menu items from the
X * associated NewMenu's.  It returns a pointer to a Menu struct which is
X * the first element in the list for this strip.
X *
X * GenStrip() takes a pointer to an array of strings and creates a
X * top-level set of Menu structs for the main menu strip.
X *
X * FreeMenu() frees a Menu strip created with either GenMenu() or
X * GenStrip().
X *
X * GenItems() takes a pointer to a NewMenu struct and creates a single
X * list of MenuItem's from the description.  It also takes an X and Y
X * offset for all the elements in the list.
X *
X * FreeMItem() frees structures created by the above function.
X *
X * AttachSubMenu() takes a single MenuItem and a NewMenu struct and
X * attaches the MenuItems created from that NewMenu struct to the
X * parent MenuItem.  The parent should also have been created with
X * GenItems() in order to work correctly.  AttachSubMenu() places a
X * little maker on the parent item to show that it has subitems.  It
X * returns 1 for sucess and 0 for failure.
X *
X * -- WARNING:
X *
X * The client programmer is completely responsible for keeping the
X * menus within the bounds of the screen and for keeping within the
X * limits of Intuition.  The menu structures will not adjust as they
X * hit the borders of the screen (which might be a nice enhancement).
X * The strings in the NewMenu structures cannot be changed or deleted
X * while the Menus are in use, although they can be used to create
X * multiple Menus from the same strings.
X *
X **
X * This code can be used and modified freely.  Do let me know of any
X * improvements or enhancements you may add, and be sure to give credit
X * where credit is due (in the comments) if you redistribute this code.
X *
X *	Stuart Ferguson		1/89
X *	(shf@well.UUCP)
X */
X#include <intuition/intuition.h>
X#include "qmenu.h"
X
X/*
X * Some useful macros for allocating and freeing structures and
X * arrays of structures.
X */
X#define NEW(typ)	(typ*)AllocMem((long)sizeof(typ),0L)
X#define FREI(p)		FreeMem(p,(long)sizeof(*p))
X
X#define NEW_N(typ,n)	(typ*)AllocMem((long)((n)*sizeof(typ)),0L)
X#define FREI_N(p,n)	FreeMem(p,(long)((n)*sizeof(*p)))
X
Xchar * AllocMem();
X
X/*
X * Definitions for formatting the menus.  Glossary:
X *
X *	TEXTCOLOR	- color of the text items in the menus.
X *	MARKCOLOR	- color of the subitem marker.
X *	RULECOLOR	- color of the horizontal lines in the menus.
X *	RULEHEIGHT	- vertical thickness of the horizontal rules.
X *	RULEGAP		- vertical blank space around the rules.
X *	RULEMARGIN	- horizontal blank space around the rules.
X *	TEXTGAP		- vertical blank space around the text items.
X *	TEXTMARGIN	- horizontal blank space around the text items.
X *	MAINWID		- width of the text font on the main menu.
X *	MAINGAP		- spacing between items on the main menu strip.
X *	SUBINDENT	- overlap between items and their subitems.
X *	SUBDOWN		- vertical shift between items and their subitems.
X */
X#define TEXTCOLOR	2
X#define MARKCOLOR	3
X#define RULECOLOR	0
X#define RULEHEIGHT	2
X#define RULEGAP		4
X#define RULEMARGIN	10
X#define TEXTGAP		2
X#define TEXTMARGIN	4
X#define MAINWID		10
X#define MAINGAP		10
X#define SUBINDENT	18
X#define SUBDOWN		0
X
X/*
X * Escape character for special control codes in text items strings.
X */
X#define SPECIAL		'!'
X
X/*
X * The extern "ta" is set by the client program for
X * the font to use for these menus.
X */
Xextern struct TextAttr ta;
X
X/*
X * Generic templates to use for creating the dynamic menu structures. 
X */
Xstatic struct IntuiText
X  generic_itext = {TEXTCOLOR, 0, JAM1, TEXTMARGIN/2, TEXTGAP/2, &ta,NULL,NULL},
X  /*
X  generic_smark = {MARKCOLOR, 0, JAM1, 0, TEXTGAP/2, &ta, (UBYTE *) ";", NULL};
X  */
X  generic_smark = {MARKCOLOR, 0, JAM1, 0, TEXTGAP/2, &ta, (UBYTE *) ">>", NULL};
X
Xstatic struct Menu
X  generic_main = {NULL, 0, 0, 0, 10, MENUENABLED, NULL, NULL};
X
Xstatic struct MenuItem
X  generic_mitem = {
X	 NULL, 0, 0, 0, 0,
X	 ITEMTEXT | ITEMENABLED | HIGHCOMP,
X	 0, NULL, NULL, 0, NULL, 0
X};
X
X/* Image struct with no imagery for the horizontal lines.
X */
Xstatic struct Image
X  generic_hrule = {0, 0, 1, RULEHEIGHT, 2, NULL, 0, RULECOLOR, NULL};
X
Xstatic struct MenuItem
X  generic_hitem = {
X	 NULL, RULEMARGIN/2, 0, 0, 0,
X	 ITEMENABLED | HIGHNONE,
X	 0, NULL, NULL, 0, NULL, 0
X};
X
X
X/*
X * Takes an array of strings and associated array of NewMenu structs
X * (as a single NewMenu struct) and constructs a menu strip from the
X * descripton.  This is the main high-level call that most clients
X * will make.
X */
Xstruct Menu * GenMenu (nmen)
X	register struct NewMenu *nmen;
X{
X	register short  i, ok, n;
X	register struct Menu *mm;
X	register struct MenuItem *mi;
X
X	/* Count menus to be generated and create top level structure.
X	 */
X	for (n = 0; nmen->str[n]; n++) ;
X	mm = GenStrip (nmen->str);
X	if (!mm) return NULL;
X
X	/* Create the item strip for each main menu and attach to the
X	 * top level Menu structure.  Any failure causes the whole
X	 * thing to crumble to dust.
X	 */
X	ok = 1;
X	nmen = nmen->submenu;
X	for (i = 0; i < n; i++) {
X		if (nmen->str) {
X			mi = GenItems (nmen, 0L, 0L);
X			mm[i].FirstItem = mi;
X			ok &= (mi != NULL);
X		}
X		nmen ++;
X	}
X	if (!ok) {
X		FreeMenu (mm);
X		return NULL;
X	}
X	return mm;
X}
X
X
X/*
X * Generate a menu strip.  Just creates the top level Menu structures,
X * linked together and intialized.  Takes an array of pointers to
X * strings.
X */
Xstruct Menu * GenStrip (str)
X	char **str;
X{
X	register short  i, x, num;
X	register struct Menu *mm, *m;
X
X	/*
X	 * Create enough struct Menu's for the menu strip. 
X	 */
X	for (num = 0; str[num]; num++) ;
X	mm = NEW_N (struct Menu, num);
X	if (!mm) return NULL;
X
X	/*
X	 * Init the structures using the generic Menu struct as a template.
X	 * NOTE: the size of the font for these item labels is unknown for
X	 *       windows on the Workbench screen, so a size should be used
X	 *       that will work with 60 & 80 column fonts. 
X	 */
X	x = 0;
X	for (i = 0; i < num; i++) {
X		m = &mm[i];
X		*m = generic_main;
X		m->LeftEdge = x;
X		m->Width = strlen (str[i]) * MAINWID + TEXTMARGIN;
X		x += m->Width + MAINGAP;
X		m->MenuName = str[i];
X		m->NextMenu = m + 1;
X	}
X	mm[num - 1].NextMenu = NULL;
X	return mm;
X}
X
X
X/*
X * Attach a submenu to a MenuItem.  Takes the parent MenuItem and a
X * NewMenu structure that will be attached as a sub-menu.  
X * Attaches a ";" mark at the end of the parent item and calls
X * GenItems() to create the sub-menu strip.
X */
XBOOL AttachSubMenu (mi, nmen)
X	register struct MenuItem	*mi;
X	struct NewMenu			*nmen;
X{
X	register struct IntuiText *it;
X
X	/* Create an IntuiText with the marker and position it
X	 * at the right edge of the item.
X	 */
X	if (!(it = NEW (struct IntuiText))) return FALSE;
X	*it = generic_smark;
X	it->LeftEdge = mi->Width - IntuiTextLength (it) - 2;
X
X	/* Create the subitem structure and attach to the main item.
X	 */
X	if (!(mi->SubItem = GenItems
X	      (nmen, (LONG) (mi->Width - SUBINDENT), (LONG) SUBDOWN))) {
X		FREI (it);
X		return FALSE;
X	}
X
X	/* Only if it all worked attach the new text structure.
X	 */
X	((struct IntuiText *) mi->ItemFill)->NextText = it;
X	return TRUE;
X}
X
X
X/*
X * Takes the given menu text item and skips past the special control
X * codes while adjusting the associated MenuItem appropriately.
X * Special codes are in the form of "!x", where "x" is:
X *
X *	c	Checkmark item
X *	t	Checkmark toggle
X *	b	Highlight box
X *	n	Highlight none
X *	d	Disabled
X *	+	Checkmark checked
X *	=C	Set command key to "C"
X *	1010...	Set item exclude mask
X *
X * Takes the mostly defined MenuItem and diddles it.  Returns a pointer
X * to the item text with control codes stripped.
X */
Xstatic UBYTE * ProcessSpecialStuff (str, mi)
X	char *str;
X	struct MenuItem *mi;
X{
X	register LONG	x;
X	register int	i;
X
X	while (*str == SPECIAL) {
X		switch (*++str) {
X		    case 'c':
X			mi->Flags |= CHECKIT;
X			break;
X		    case 't':
X			mi->Flags |= CHECKIT | MENUTOGGLE;
X			break;
X		    case 'b':
X			mi->Flags &= ~HIGHFLAGS;
X			mi->Flags |= HIGHBOX;
X			break;
X		    case 'n':
X			mi->Flags &= ~HIGHFLAGS;
X			mi->Flags |= HIGHNONE;
X			break;
X		    case 'd':
X			mi->Flags &= ~ITEMENABLED;
X			break;
X		    case '+':
X			mi->Flags |= CHECKIT | CHECKED;
X			break;
X		    case '=':
X			mi->Flags |= COMMSEQ;
X			mi->Command = *++str;
X			break;
X		    case '0':
X		    case '1':
X			x = 0;
X			i = 0;
X			while (*str == '0' || *str == '1')
X				x += (*str++ - '0') << (i++);
X			mi->MutualExclude = x;
X			str--;
X			break;
X		}
X		str++;
X	}
X	return (UBYTE*) str;
X}
X
X
X/*
X * Construct a basic item list for a menu.  Takes a NewMenu structure
X * which contains a pointer to an array of pointers to strings and a 
X * pointer to an array of NewMenu structures.  The strings contain the
X * item text for each menu plus optional special control codes.  If the
X * string is "-", the item will be a horizontal rule rather than a text
X * item.  The NewMenu structures, if not NULL, are the sub-menu's for
X * each menu in the array.
X * "x" and "y" are the horizontal and vertical offsets of this set of
X * MenuItems.  These are set by AttachSubMenu() for positioning submenus
X * under their parent items.
X */
Xstruct MenuItem *GenItems (nmen, x, y)
X	struct NewMenu *nmen;
X	LONG	x, y;
X{
X	register struct MenuItem *mi, *cmi;
X	register struct IntuiText *itext;
X	struct Image   *img;
X	register short  i, len, max;
X	short           n;
X	struct NewMenu *sub;
X
X	/* Count menu items (n) and allocate an array for the strip.
X	 */
X	for (n = 0; nmen->str[n]; n++) ;
X	if (!(mi = NEW_N (struct MenuItem, n))) return NULL;
X
X	/* Counts the number of rules in the menu ("-" strings)
X	 * and allocates the structures for the lines and the text items.
X	 */
X	max = 0;
X	for (i = 0; i < n; i++) max += (*nmen->str[i] == '-');
X	if (n - max)
X		if (!(itext = NEW_N (struct IntuiText, n - max))) {
X			FREI_N (mi, n);
X			return NULL;
X		}
X	if (max)
X		if (!(img = NEW_N (struct Image, max))) {
X			FREI_N (mi, n);
X			if (n - max) FREI_N (itext, n - max);
X			return NULL;
X		}
X
X	/* Loop through text menu items and initialize the
X	 * associated IntuiText structures.  Compute the maximum
X	 * width of the menu taking command keys into account while
X	 * assigning all the other parts of the text MenuItem's.
X	 */
X	max = 0;
X	for (i = 0; i < n; i++) {
X		if (*nmen->str[i] == '-') continue;	/* skip rules */
X
X		/* Init the text MenuItem to point to the assocd IntuiText.
X		 */
X		cmi = &mi[i];
X		*cmi = generic_mitem;
X		cmi->ItemFill = (APTR) itext;
X
X		/* Init the IntuiText and adjust the MenuItem from the
X		 * flags set in the menu text string.
X		 */
X		*itext = generic_itext;
X		itext->IText = ProcessSpecialStuff (nmen->str[i], cmi);
X
X		/* Make a first cut at measuring the length of the item.
X		 */
X		len = IntuiTextLength (itext) + TEXTMARGIN;
X
X		/* If command key set, add to length.
X		 */
X		if (cmi->Flags & COMMSEQ) len += COMMWIDTH + MAINWID;
X
X		/* If this is a checkmark item, shift the text over to
X		 * make room and add that to the length.
X		 * Compute the max length.
X		 */
X		if (cmi->Flags & CHECKIT) {
X			itext->LeftEdge += CHECKWIDTH;
X			len += CHECKWIDTH;
X		}
X		if (len > max) max = len;
X		itext ++;
X	}
X
X	/* Secondary assignment loop.  Position the text MenuItems and
X	 * init the horizontal lines.
X	 */
X	for (i = 0; i < n; i++) {
X		cmi = &mi[i];
X
X		if (*nmen->str[i] != '-') {
X			cmi->LeftEdge = x;
X			cmi->TopEdge = y;
X			cmi->Width = max;
X			cmi->Height = ta.ta_YSize + TEXTGAP;
X			y += cmi->Height;
X		} else {
X
X			/* Rule items point to their Image structure
X			 * and are just a little narrower than the
X			 * menu itself.
X			 */
X			*img = generic_hrule;
X			img->Width = max - RULEMARGIN;
X			*cmi = generic_hitem;
X			cmi->TopEdge = y + RULEGAP/2;
X			y += RULEHEIGHT + RULEGAP;
X			cmi->ItemFill = (APTR) img;
X			img ++;
X		}
X		cmi->NextItem = cmi + 1;
X	}
X	mi[n - 1].NextItem = NULL;
X
X	/* Attach submenu's, if any.
X	 */
X	if (!(sub = nmen->submenu)) return mi;
X
X	/* Use "max" as a flag for the success of the attachments.
X	 */
X	max = 1;
X	for (i = 0; i < n; i++) {
X		if (*nmen->str[i] == '-') continue;
X		if (sub->str)
X			max &= AttachSubMenu (&mi[i], sub);
X		sub ++;
X	}
X	if (!max) {
X		FreeMItem (mi);
X		return NULL;
X	}
X	return mi;
X}
X
X
X/*
X * Free a Menu structure created by GenStrip() that has items 
X * created with GenItems().
X */
Xvoid FreeMenu (mm)
X	struct Menu    *mm;
X{
X	register short  i;
X	register struct Menu *t;
X
X	i = 0;
X	for (t = mm; t; t = t->NextMenu) {
X		if (t->FirstItem) FreeMItem (t->FirstItem);
X		i++;
X	}
X	FREI_N (mm, i);
X}
X
X
X/*
X * Free a MenuItem structure created by GenItems().
X */
Xvoid FreeMItem (mi)
X	register struct MenuItem *mi;
X{
X	register short  nit, nimg;
X	register struct MenuItem *c;
X	register struct IntuiText *it = NULL, *it1;
X	struct Image   *img = NULL;
X
X	/* Scan the MenuItem structures and count the number of images
X	 * and IntuiText structures.  Find the pointer to the first of
X	 * each structure in the set.  That will be the first element
X	 * in the array that was allocated as a unit.
X	 */
X	nit = nimg = 0;
X	for (c = mi; c; c = c->NextItem) {
X		if (c->SubItem) FreeMItem (c->SubItem);
X		if (c->Flags & ITEMTEXT) {
X			it1 = (struct IntuiText *) c->ItemFill;
X			if (!it) it = it1;
X			nit++;
X
X			/* Free the subitem marker, if any.
X			 */
X			if (it1->NextText) FREI (it1->NextText);
X		} else {
X			if (!img) img = (struct Image *) c->ItemFill;
X			nimg++;
X		}
X	}
X
X	/* Free the arrays of structures of images and texts, as
X	 * well as the main array of MenuItem structures themselves.
X	 */
X	if (nit) FREI_N (it, nit);
X	if (nimg) FREI_N (img, nimg);
X	FREI_N (mi, nit + nimg);
X}
SHAR_EOF
echo "extracting qmenu.h"
sed 's/^X//' << \SHAR_EOF > qmenu.h
Xstruct NewMenu {
X	char **str;
X	struct NewMenu *submenu;
X};
X
X
Xstruct Menu *GenMenu();
Xstruct Menu *GenStrip();
Xstruct MenuItem *GenItems();
XLONG AttachSubItem();
Xvoid FreeMenu();
Xvoid FreeMItem();
SHAR_EOF
echo "extracting request.h"
sed 's/^X//' << \SHAR_EOF > request.h
XUBYTE mot_nbuf[2][NUMCHR] = {
X "0.00", "0.00"
X};
X
Xstruct StringInfo mot_sinfo[] = {
X  {&mot_nbuf[0][0],undo,0,NUMCHR,0},
X  {&mot_nbuf[1][0],undo,0,NUMCHR,0}
X};
X
Xstruct Gadget mot_gad[] = {
X  {&mot_gad[1],113,25,104,8,
X   GADGHCOMP,RELVERIFY,STRGADGET|REQGADGET,
X   NULL,NULL,NULL,0,(APTR)&mot_sinfo[0],STR_ID,NULL},
X  {&mot_gad[2],113,42,104,8,
X   GADGHCOMP,RELVERIFY,STRGADGET|REQGADGET,
X   NULL,NULL,NULL,0,(APTR)&mot_sinfo[1],STR_ID,NULL},
X  {&mot_gad[3],49,61,24,13,
X   GADGHCOMP,ENDGADGET|GADGIMMEDIATE|RELVERIFY,BOOLGADGET|REQGADGET,
X   NULL,NULL,NULL,0,NULL,OK_ID,NULL},
X  {NULL,124,61,56,13,
X   GADGHCOMP,ENDGADGET|GADGIMMEDIATE|RELVERIFY,BOOLGADGET|REQGADGET,
X   NULL,NULL,NULL,0,NULL,CAN_ID,NULL}
X};
X
Xstruct IntuiText mot_txt[] = {
X  {3,0,JAM2,86,9,&ta,(UBYTE*)"C VALUE",&mot_txt[1]},
X  {1,0,JAM2,9,25,&ta,(UBYTE*)"Real Number:",&mot_txt[2]},
X  {1,0,JAM2,9,42,&ta,(UBYTE*)"Imag Number:",&mot_txt[3]},
X  {2,0,JAM2,53,64,&ta,(UBYTE*)"Ok",&mot_txt[4]},
X  {3,0,JAM2,128,64,&ta,(UBYTE*)"Cancel",NULL}
X};
X
Xshort mot_brd_XY[] = {
X  1,83, 228,83, 228,0, 0,0, 0,83, 
X  124,74, 180,74, 180,60, 123,60, 123,74, 
X  49,74, 73,74, 73,60, 48,60, 48,74, 
X  111,51, 219,51, 219,40, 110,40, 110,51, 
X  217,49, 217,42, 218,42, 218,50, 111,50, 111,42, 112,42, 112,49, 
X  111,41, 218,41, 
X  111,34, 219,34, 219,23, 110,23, 110,34, 
X  217,32, 217,25, 218,25, 218,33, 111,33, 111,25, 112,25, 112,32, 
X  111,24, 218,24, 
X  86,17, 141,17
X};
Xstruct Border mot_brd[] = {
X  {0,0,1,0,JAM1,5,&mot_brd_XY[0],&mot_brd[1]},
X  {0,0,1,0,JAM1,5,&mot_brd_XY[10],&mot_brd[2]},
X  {0,0,1,0,JAM1,5,&mot_brd_XY[20],&mot_brd[3]},
X  {0,0,1,0,JAM1,5,&mot_brd_XY[30],&mot_brd[4]},
X  {0,0,2,0,JAM1,8,&mot_brd_XY[40],&mot_brd[5]},
X  {0,0,2,0,JAM1,2,&mot_brd_XY[56],&mot_brd[6]},
X  {0,0,1,0,JAM1,5,&mot_brd_XY[60],&mot_brd[7]},
X  {0,0,2,0,JAM1,8,&mot_brd_XY[70],&mot_brd[8]},
X  {0,0,2,0,JAM1,2,&mot_brd_XY[86],&mot_brd[9]},
X  {0,0,3,0,JAM1,2,&mot_brd_XY[90],NULL}
X};
X
X
Xstruct Requester mot_req = {
X  NULL,0,0,229,84,0,0,mot_gad,mot_brd,mot_txt,0,0,
X  NULL,{NULL},NULL,NULL,{NULL}};
SHAR_EOF
echo "End of archive 1 (of 1)"
# if you want to concatenate archives, remove anything after this line
exit