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@�(&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