page@swan.ulowell.edu (Bob Page) (03/08/89)
Submitted-by: well!shf (Stuart H. Ferguson) Posting-number: Volume 89, Issue 27 Archive-name: intuition/qmenu.1 [uuencoded test program included. ..Bob] # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # ReadMe # Makefile # qmenu.c # qmenu.h # mtst.c # mtst.uu # This archive created: Tue Mar 7 21:10:08 1989 cat << \SHAR_EOF > ReadMe IntuiTools: qmenu Here's a little quick menu creation code I put together for making menus for Modeler 3D. The instructions are in the comments. Included are the main code itself in a module and an example program. The code compiles under Manx 3.6, but I can't see why I wouldn't compile equally well elsewhere. Enjoy, Stuart Ferguson 1/89 (shf@well.UUCP) 123 James Ave. Redwood City, Ca. 94062 SHAR_EOF cat << \SHAR_EOF > Makefile # Quickmenu Module and test program (mtst). # Manx 3.6 Makefile. mtst : mtst.o qmenu.o ln mtst.o qmenu.o -lc -o $@ qmenu.o : qmenu.c qmenu.h cc qmenu.c -o $@ mtst.o : mtst.c qmenu.h cc mtst.c -o $@ SHAR_EOF cat << \SHAR_EOF > qmenu.c /* * Quick Menu Package -- An easy way to make simple (but nice) menus. * * The client programmer will generally use the GenMenu()/FreeMenu() * interface which creates and frees a whole menu strip. A menu strip * -- both the main strip and menu item strips -- is defined by a * NewMenu struct. Each NewMenu struct (defined in qmenu.h) is just a * pointer to an array of strings and a pointer to an array of * NewMenu's. The elements of the array of NewMenu's are paired with the * strings in the array and represent the sub menus for that string. * The string array is terminated with a null pointer. * * The package tries to do nice things, like automatically formatting * the menu strings into blocks with their command keys, and placing * markers pointing to subitem stips. The strings for the menu items * can contain special control codes to control the optional * characteristics of items. Special codes come at the front of item * strings and are delimited with a special character (SPECIAL, * defined as '!' by default) and are listed briefly below: * * c Checkmark item * t Checkmark toggle * + Checkmark checked * b Highlight box * n Highlight none * d Disabled * =C Set command key to "C" * 0101... Set item exclude mask * * Any number of 1's and 0's after the special character will set the * Mutual exclude bits for that item in the order they occur. So the * first 1 or 0 will set bit 0 of the exclude mask, the second will * set bit 1, etc. Any unset will be 0. * * Additionally, if the item string is "-", the item will be * a non-selectable horizontal line (a "rule") that can be used to * visually group similar items in the menu strip. There only need * to be NewMenu structs in the array for text menu items, not rules, * but don't forget to account for rules when counting MenuItem's * since they take a slot. * * * GenMenu() takes a pointer to a NewMenu struct and will create a main * Menu strip from the strings in the struct, with menu items from the * associated NewMenu's. It returns a pointer to a Menu struct which is * the first element in the list for this strip. * * GenStrip() takes a pointer to an array of strings and creates a * top-level set of Menu structs for the main menu strip. * * FreeMenu() frees a Menu strip created with either GenMenu() or * GenStrip(). * * GenItems() takes a pointer to a NewMenu struct and creates a single * list of MenuItem's from the description. It also takes an X and Y * offset for all the elements in the list. * * FreeMItem() frees structures created by the above function. * * AttachSubMenu() takes a single MenuItem and a NewMenu struct and * attaches the MenuItems created from that NewMenu struct to the * parent MenuItem. The parent should also have been created with * GenItems() in order to work correctly. AttachSubMenu() places a * little maker on the parent item to show that it has subitems. It * returns 1 for sucess and 0 for failure. * * -- WARNING: * * The client programmer is completely responsible for keeping the * menus within the bounds of the screen and for keeping within the * limits of Intuition. The menu structures will not adjust as they * hit the borders of the screen (which might be a nice enhancement). * The strings in the NewMenu structures cannot be changed or deleted * while the Menus are in use, although they can be used to create * multiple Menus from the same strings. * ** * This code can be used and modified freely. Do let me know of any * improvements or enhancements you may add, and be sure to give credit * where credit is due (in the comments) if you redistribute this code. * * Stuart Ferguson 1/89 * (shf@well.UUCP) */ #include <intuition/intuition.h> #include "qmenu.h" /* * Some useful macros for allocating and freeing structures and * arrays of structures. */ #define NEW(typ) (typ*)AllocMem((long)sizeof(typ),0L) #define FREI(p) FreeMem(p,(long)sizeof(*p)) #define NEW_N(typ,n) (typ*)AllocMem((long)((n)*sizeof(typ)),0L) #define FREI_N(p,n) FreeMem(p,(long)((n)*sizeof(*p))) char * AllocMem(); /* * Definitions for formatting the menus. Glossary: * * TEXTCOLOR - color of the text items in the menus. * MARKCOLOR - color of the subitem marker. * RULECOLOR - color of the horizontal lines in the menus. * RULEHEIGHT - vertical thickness of the horizontal rules. * RULEGAP - vertical blank space around the rules. * RULEMARGIN - horizontal blank space around the rules. * TEXTGAP - vertical blank space around the text items. * TEXTMARGIN - horizontal blank space around the text items. * MAINWID - width of the text font on the main menu. * MAINGAP - spacing between items on the main menu strip. * SUBINDENT - overlap between items and their subitems. * SUBDOWN - vertical shift between items and their subitems. */ #define TEXTCOLOR 2 #define MARKCOLOR 3 #define RULECOLOR 0 #define RULEHEIGHT 2 #define RULEGAP 4 #define RULEMARGIN 10 #define TEXTGAP 2 #define TEXTMARGIN 4 #define MAINWID 10 #define MAINGAP 10 #define SUBINDENT 18 #define SUBDOWN 0 /* * Escape character for special control codes in text items strings. */ #define SPECIAL '!' /* * The extern "ta" is set by the client program for * the font to use for these menus. */ extern struct TextAttr ta; /* * Generic templates to use for creating the dynamic menu structures. */ static struct IntuiText generic_itext = {TEXTCOLOR, 0, JAM1, TEXTMARGIN/2, TEXTGAP/2, &ta,NULL,NULL}, generic_smark = {MARKCOLOR, 0, JAM1, 0, TEXTGAP/2, &ta, (UBYTE *) ";", NULL}; static struct Menu generic_main = {NULL, 0, 0, 0, 10, MENUENABLED, NULL, NULL}; static struct MenuItem generic_mitem = { NULL, 0, 0, 0, 0, ITEMTEXT | ITEMENABLED | HIGHCOMP, 0, NULL, NULL, 0, NULL, 0 }; /* Image struct with no imagery for the horizontal lines. */ static struct Image generic_hrule = {0, 0, 1, RULEHEIGHT, 2, NULL, 0, RULECOLOR, NULL}; static struct MenuItem generic_hitem = { NULL, RULEMARGIN/2, 0, 0, 0, ITEMENABLED | HIGHNONE, 0, NULL, NULL, 0, NULL, 0 }; /* * Takes an array of strings and associated array of NewMenu structs * (as a single NewMenu struct) and constructs a menu strip from the * descripton. This is the main high-level call that most clients * will make. */ struct Menu * GenMenu (nmen) register struct NewMenu *nmen; { register short i, ok, n; register struct Menu *mm; register struct MenuItem *mi; /* Count menus to be generated and create top level structure. */ for (n = 0; nmen->str[n]; n++) ; mm = GenStrip (nmen->str); if (!mm) return NULL; /* Create the item strip for each main menu and attach to the * top level Menu structure. Any failure causes the whole * thing to crumble to dust. */ ok = 1; nmen = nmen->submenu; for (i = 0; i < n; i++) { if (nmen->str) { mi = GenItems (nmen, 0L, 0L); mm[i].FirstItem = mi; ok &= (mi != NULL); } nmen ++; } if (!ok) { FreeMenu (mm); return NULL; } return mm; } /* * Generate a menu strip. Just creates the top level Menu structures, * linked together and intialized. Takes an array of pointers to * strings. */ struct Menu * GenStrip (str) char **str; { register short i, x, num; register struct Menu *mm, *m; /* * Create enough struct Menu's for the menu strip. */ for (num = 0; str[num]; num++) ; mm = NEW_N (struct Menu, num); if (!mm) return NULL; /* * Init the structures using the generic Menu struct as a template. * NOTE: the size of the font for these item labels is unknown for * windows on the Workbench screen, so a size should be used * that will work with 60 & 80 column fonts. */ x = 0; for (i = 0; i < num; i++) { m = &mm[i]; *m = generic_main; m->LeftEdge = x; m->Width = strlen (str[i]) * MAINWID + TEXTMARGIN; x += m->Width + MAINGAP; m->MenuName = str[i]; m->NextMenu = m + 1; } mm[num - 1].NextMenu = NULL; return mm; } /* * Attach a submenu to a MenuItem. Takes the parent MenuItem and a * NewMenu structure that will be attached as a sub-menu. * Attaches a ";" mark at the end of the parent item and calls * GenItems() to create the sub-menu strip. */ BOOL AttachSubMenu (mi, nmen) register struct MenuItem *mi; struct NewMenu *nmen; { register struct IntuiText *it; /* Create an IntuiText with the marker and position it * at the right edge of the item. */ if (!(it = NEW (struct IntuiText))) return FALSE; *it = generic_smark; it->LeftEdge = mi->Width - IntuiTextLength (it) - 2; /* Create the subitem structure and attach to the main item. */ if (!(mi->SubItem = GenItems (nmen, (LONG) (mi->Width - SUBINDENT), (LONG) SUBDOWN))) { FREI (it); return FALSE; } /* Only if it all worked attach the new text structure. */ ((struct IntuiText *) mi->ItemFill)->NextText = it; return TRUE; } /* * Takes the given menu text item and skips past the special control * codes while adjusting the associated MenuItem appropriately. * Special codes are in the form of "!x", where "x" is: * * c Checkmark item * t Checkmark toggle * b Highlight box * n Highlight none * d Disabled * + Checkmark checked * =C Set command key to "C" * 1010... Set item exclude mask * * Takes the mostly defined MenuItem and diddles it. Returns a pointer * to the item text with control codes stripped. */ static UBYTE * ProcessSpecialStuff (str, mi) char *str; struct MenuItem *mi; { register LONG x; register int i; while (*str == SPECIAL) { switch (*++str) { case 'c': mi->Flags |= CHECKIT; break; case 't': mi->Flags |= CHECKIT | MENUTOGGLE; break; case 'b': mi->Flags &= ~HIGHFLAGS; mi->Flags |= HIGHBOX; break; case 'n': mi->Flags &= ~HIGHFLAGS; mi->Flags |= HIGHNONE; break; case 'd': mi->Flags &= ~ITEMENABLED; break; case '+': mi->Flags |= CHECKIT | CHECKED; break; case '=': mi->Flags |= COMMSEQ; mi->Command = *++str; break; case '0': case '1': x = 0; i = 0; while (*str == '0' || *str == '1') x += (*str++ - '0') << (i++); mi->MutualExclude = x; str--; break; } str++; } return (UBYTE*) str; } /* * Construct a basic item list for a menu. Takes a NewMenu structure * which contains a pointer to an array of pointers to strings and a * pointer to an array of NewMenu structures. The strings contain the * item text for each menu plus optional special control codes. If the * string is "-", the item will be a horizontal rule rather than a text * item. The NewMenu structures, if not NULL, are the sub-menu's for * each menu in the array. * "x" and "y" are the horizontal and vertical offsets of this set of * MenuItems. These are set by AttachSubMenu() for positioning submenus * under their parent items. */ struct MenuItem *GenItems (nmen, x, y) struct NewMenu *nmen; LONG x, y; { register struct MenuItem *mi, *cmi; register struct IntuiText *itext; struct Image *img; register short i, len, max; short n; struct NewMenu *sub; /* Count menu items (n) and allocate an array for the strip. */ for (n = 0; nmen->str[n]; n++) ; if (!(mi = NEW_N (struct MenuItem, n))) return NULL; /* Counts the number of rules in the menu ("-" strings) * and allocates the structures for the lines and the text items. */ max = 0; for (i = 0; i < n; i++) max += (*nmen->str[i] == '-'); if (n - max) if (!(itext = NEW_N (struct IntuiText, n - max))) { FREI_N (mi, n); return NULL; } if (max) if (!(img = NEW_N (struct Image, max))) { FREI_N (mi, n); if (n - max) FREI_N (itext, n - max); return NULL; } /* Loop through text menu items and initialize the * associated IntuiText structures. Compute the maximum * width of the menu taking command keys into account while * assigning all the other parts of the text MenuItem's. */ max = 0; for (i = 0; i < n; i++) { if (*nmen->str[i] == '-') continue; /* skip rules */ /* Init the text MenuItem to point to the assocd IntuiText. */ cmi = &mi[i]; *cmi = generic_mitem; cmi->ItemFill = (APTR) itext; /* Init the IntuiText and adjust the MenuItem from the * flags set in the menu text string. */ *itext = generic_itext; itext->IText = ProcessSpecialStuff (nmen->str[i], cmi); /* Make a first cut at measuring the length of the item. */ len = IntuiTextLength (itext) + TEXTMARGIN; /* If command key set, add to length. */ if (cmi->Flags & COMMSEQ) len += COMMWIDTH + MAINWID; /* If this is a checkmark item, shift the text over to * make room and add that to the length. * Compute the max length. */ if (cmi->Flags & CHECKIT) { itext->LeftEdge += CHECKWIDTH; len += CHECKWIDTH; } if (len > max) max = len; itext ++; } /* Secondary assignment loop. Position the text MenuItems and * init the horizontal lines. */ for (i = 0; i < n; i++) { cmi = &mi[i]; if (*nmen->str[i] != '-') { cmi->LeftEdge = x; cmi->TopEdge = y; cmi->Width = max; cmi->Height = ta.ta_YSize + TEXTGAP; y += cmi->Height; } else { /* Rule items point to their Image structure * and are just a little narrower than the * menu itself. */ *img = generic_hrule; img->Width = max - RULEMARGIN; *cmi = generic_hitem; cmi->TopEdge = y + RULEGAP/2; y += RULEHEIGHT + RULEGAP; cmi->ItemFill = (APTR) img; img ++; } cmi->NextItem = cmi + 1; } mi[n - 1].NextItem = NULL; /* Attach submenu's, if any. */ if (!(sub = nmen->submenu)) return mi; /* Use "max" as a flag for the success of the attachments. */ max = 1; for (i = 0; i < n; i++) { if (*nmen->str[i] == '-') continue; if (sub->str) max &= AttachSubMenu (&mi[i], sub); sub ++; } if (!max) { FreeMItem (mi); return NULL; } return mi; } /* * Free a Menu structure created by GenStrip() that has items * created with GenItems(). */ void FreeMenu (mm) struct Menu *mm; { register short i; register struct Menu *t; i = 0; for (t = mm; t; t = t->NextMenu) { if (t->FirstItem) FreeMItem (t->FirstItem); i++; } FREI_N (mm, i); } /* * Free a MenuItem structure created by GenItems(). */ void FreeMItem (mi) register struct MenuItem *mi; { register short nit, nimg; register struct MenuItem *c; register struct IntuiText *it = NULL, *it1; struct Image *img = NULL; /* Scan the MenuItem structures and count the number of images * and IntuiText structures. Find the pointer to the first of * each structure in the set. That will be the first element * in the array that was allocated as a unit. */ nit = nimg = 0; for (c = mi; c; c = c->NextItem) { if (c->SubItem) FreeMItem (c->SubItem); if (c->Flags & ITEMTEXT) { it1 = (struct IntuiText *) c->ItemFill; if (!it) it = it1; nit++; /* Free the subitem marker, if any. */ if (it1->NextText) FREI (it1->NextText); } else { if (!img) img = (struct Image *) c->ItemFill; nimg++; } } /* Free the arrays of structures of images and texts, as * well as the main array of MenuItem structures themselves. */ if (nit) FREI_N (it, nit); if (nimg) FREI_N (img, nimg); FREI_N (mi, nit + nimg); } SHAR_EOF cat << \SHAR_EOF > qmenu.h struct NewMenu { char **str; struct NewMenu *submenu; }; struct Menu *GenMenu(); struct Menu *GenStrip(); struct MenuItem *GenItems(); LONG AttachSubItem(); void FreeMenu(); void FreeMItem(); SHAR_EOF cat << \SHAR_EOF > mtst.c /* * Example program for using quick menu package. Contains the necessary * declarations for a simple menu strip which it creates and destroys after * letting the user play with it. */ #include <intuition/intuition.h> #include "qmenu.h" #define NILSUB {NULL,NULL} /* * String arrays get defined in sort-of reverse order. * I.e. the subitems get defined before the parent items. * (One rule is that menu items that cause a Requester to * appear are followed by "...".) * The string arrays themselves are terminated by a null * string pointer. */ char *mpo_str[] = { "!=ORaw Text...", "Processed Text...", "Drawing...", "Picture...", "Old Settings...", NULL }; char *mps_str[] = { "!=TText...", "!=DDrawing...", "Picture...", NULL }; char *mp_str[] = { "!=NNew...", "Open", "!=SSave...", "Save as", "Print...", "Save Settings", "About...", "-", "!bQuit...", NULL }; /* Array of NewMenu structs to go with the above text items. * Needs to be a one-to-one correspondence between text items * (not rules) and NewMenu structs. */ struct NewMenu mp_sub[] = { NILSUB, { mpo_str, NULL }, NILSUB, { mps_str, NULL }, NILSUB, NILSUB, NILSUB, NILSUB }; char *mes_str[] = { "!+!0111!=PPlain", "!c!1!=BBold", "!c!1!=IItalic", "!c!1!=UUnderline", NULL }; char *me_str[] = { "!=QUndo", "-", "!=ZDelete", "!=XCut", "!=CCopy", "!=VPaste", "-", "Set Font...", "Set Style", NULL }; struct NewMenu me_sub[] = { NILSUB, NILSUB, NILSUB, NILSUB, NILSUB, NILSUB, { mes_str, NULL } }; char *mdz_str[] = { "!=>In", "!=<Out", "!=MManual", NULL }; char *mdv_str[] = { "!+!tText", "!+!tLines", "!+!tImages", "!+!tBoxes", "!+!tLabels", NULL }; char *mds_str[] = { "Interlace", "Non-interlace", "Workbench", NULL }; char *md_str[] = { "Zoom", "!=AAuto Scale", "-", "!c!tCoordinates", "Visible", "-", "Screen Colors...", "Screen Type", NULL }; struct NewMenu md_sub[] = { { mdz_str, NULL }, NILSUB, NILSUB, { mdv_str, NULL }, NILSUB, { mds_str, NULL } }; char *mhc_str[] = { "Plot...", "Set...", "Lay in...", NULL }; char *mhw_str[] = { "!+!0111111Full Impulse", "!c!1011111!=1Warp 1", "!c!1101111!=2Warp 2", "!c!1110111!=3Warp 3", "!c!1111011!=4Warp 4", "!c!1111101!=5Warp 5", "!c!1111110Space Normal", NULL }; char *mhp_str[] = { "Stun", "Kill", "Maim", "Burn", "Overload", "Ineffective", "Burn Out", NULL }; char *mh_str[] = { "New Course", "Speed", "Standard Orbit", "Tractor Beam...", "Lock Phasers", "-", "\"Make It So.\"", NULL }; struct NewMenu mh_sub[] = { { mhc_str, NULL }, { mhw_str, NULL }, NILSUB, NILSUB, { mhp_str, NULL }, NILSUB }; char *mt_str[] = { "Hammer", "Screwdriver", "Chisel", "Knife", "Felt Pen", "Air Freshener", "-", "Hammer Size...", "Screw Type...", "Pine Scent...", NULL }; char *mm_str[] = { "Rotate...", "Spin...", "Turn Around...", "Flip Out...", "Randomize...", "Energize...", "Simplify", "Complexify", NULL }; char *main_str[] = { "Project", "Edit", "Display", "Tools", "Helm", "Modify", NULL }; struct NewMenu main_sub[] = { { mp_str, mp_sub }, { me_str, me_sub }, { md_str, md_sub }, { mt_str, NULL }, { mh_str, mh_sub }, { mm_str, NULL } }; struct NewMenu main_menu = { main_str, main_sub }; struct TextAttr ta = { (UBYTE*) "topaz.font", 8,0,0 }; /* Basic stuff for the test program. */ struct NewWindow nwin = { 50,20, 200,100, -1,-1, CLOSEWINDOW, WINDOWCLOSE|WINDOWDRAG|ACTIVATE, NULL,NULL, (UBYTE*) "Test the Menus", NULL,NULL, 0,0,0,0, WBENCHSCREEN }; #define OLIB(var,nam) (var=OpenLibrary(nam,33L)) struct IntuitionBase *IntuitionBase; struct Window *mywin; struct Window *OpenWindow(); void *OpenLibrary(); void *GetMsg(); main () { if (OLIB(IntuitionBase,"intuition.library")) { if (mywin = OpenWindow (&nwin)) { Body (); CloseWindow (mywin); } CloseLibrary (IntuitionBase); } } Body () { struct IntuiMessage *im; struct Menu *m; if (!(m = GenMenu (&main_menu))) return; SetMenuStrip (mywin, m); /* Wait for the close window message. */ while (!(im = (struct IntuiMessage *) GetMsg (mywin->UserPort))) WaitPort (mywin->UserPort); ReplyMsg (im); ReadMenuState (m); ClearMenuStrip (mywin); FreeMenu (m); } ReadMenuState (m) struct Menu *m; { struct MenuItem *mi; /* Get the text style menu array and test for checkmarks. */ mi = m[1].FirstItem[8].SubItem; printf ("Text Style: "); if (mi[0].Flags & CHECKED) printf ("Plain"); if (mi[1].Flags & CHECKED) printf ("Bold "); if (mi[2].Flags & CHECKED) printf ("Italic "); if (mi[3].Flags & CHECKED) printf ("Underline"); printf ("\n"); } SHAR_EOF cat << \SHAR_EOF > mtst.uu begin 644 mtst M```#\P`````````#``````````(```=@```!E@````$```/I```'8$[Z#*0AF M/4]287<@5&5X="XN+@!0<F]C97-S960@5&5X="XN+@!$<F%W:6YG+BXN`%!I+ M8W1U<F4N+BX`3VQD(%-E='1I;F=S+BXN```A/51497AT+BXN`"$]1$1R87=I! M;F<N+BX`4&EC='5R92XN+@`A/4Y.97<N+BX`3W!E;@`A/5-3879E+BXN`%-AU M=F4@87,`4')I;G0N+BX`4V%V92!3971T:6YG<P!!8F]U="XN+@`M`"%B475I* M="XN+@`A*R$P,3$Q(3U04&QA:6X`(6,A,2$]0D)O;&0`(6,A,2$]24ET86QIW M8P`A8R$Q(3U556YD97)L:6YE```A/5%5;F1O`"T`(3U:1&5L971E`"$]6$-U] M=``A/4-#;W!Y`"$]5E!A<W1E`"T`4V5T($9O;G0N+BX`4V5T(%-T>6QE`"$]V M/DEN`"$]/$]U=``A/4U-86YU86P``"$K(71497AT`"$K(71,:6YE<P`A*R%T3 M26UA9V5S`"$K(71";WAE<P`A*R%T3&%B96QS``!);G1E<FQA8V4`3F]N+6ENR M=&5R;&%C90!7;W)K8F5N8V@`6F]O;0`A/4%!=71O(%-C86QE`"T`(6,A=$-O@ M;W)D:6YA=&5S`%9I<VEB;&4`+0!38W)E96X@0V]L;W)S+BXN`%-C<F5E;B!44 M>7!E`%!L;W0N+BX`4V5T+BXN`$QA>2!I;BXN+@``(2LA,#$Q,3$Q,49U;&P@* M26UP=6QS90`A8R$Q,#$Q,3$Q(3TQ5V%R<"`Q`"%C(3$Q,#$Q,3$A/3)787)PY M(#(`(6,A,3$Q,#$Q,2$],U=A<G`@,P`A8R$Q,3$Q,#$Q(3TT5V%R<"`T`"%C* M(3$Q,3$Q,#$A/35787)P(#4`(6,A,3$Q,3$Q,%-P86-E($YO<FUA;`!3='5N3 M`$MI;&P`36%I;0!"=7)N`$]V97)L;V%D`$EN969F96-T:79E`$)U<FX@3W5TZ M`$YE=R!#;W5R<V4`4W!E960`4W1A;F1A<F0@3W)B:70`5')A8W1O<B!"96%MQ M+BXN`$QO8VL@4&AA<V5R<P`M`")-86ME($ET(%-O+B(``$AA;6UE<@!38W)E, M=V1R:79E<@!#:&ES96P`2VYI9F4`1F5L="!096X`06ER($9R97-H96YE<@`MA M`$AA;6UE<B!3:7IE+BXN`%-C<F5W(%1Y<&4N+BX`4&EN92!38V5N="XN+@!2T M;W1A=&4N+BX`4W!I;BXN+@!4=7)N($%R;W5N9"XN+@!&;&EP($]U="XN+@!2& M86YD;VUI>F4N+BX`16YE<F=I>F4N+BX`4VEM<&QI9GD`0V]M<&QE>&EF>0!0A M<F]J96-T`$5D:70`1&ES<&QA>0!4;V]L<P!(96QM`$UO9&EF>0``=&]P87HN^ M9F]N=```5&5S="!T:&4@365N=7,``$Y5``!(>``A2'H`.$ZZ&*103RE`A@9G= M)DAL@MY.NAD@6$\I0(8*9PQA*B\LA@I.NACV6$\O+(8&3KH8'EA/3EU.=6EN2 M='5I=&EO;BYL:6)R87)Y`$Y5__A(;(+.3KH!&EA/*T#_^&8$3EU.=2\M__@O3 M+(8*3KH8U%!/(&R&"B\H`%9.NA@>6$\K0/_\9A`@;(8*+R@`5DZZ&$Q83V#<Q M+RW__$ZZ&")83R\M__AA&%A/+RR&"DZZ&&183R\M__A.N@:P6$]@HDY5__P@! M;0`((F@`,"MI`2S__$AZ`&Y.N@P<6$\@;?_\""@````,9PI(>@!E3KH,!EA// M(&W__`@H````+F<*2'H`54ZZ"_!83R!M__P(*````%!G"DAZ`$5.N@O:6$\@, M;?_\""@```!R9PI(>@`W3KH+Q%A/2'H`-TZZ"[I83TY=3G5497AT(%-T>6QEC M.B``4&QA:6X`0F]L9"``271A;&EC(`!5;F1E<FQI;F4`"@``NP!.50``2.</Q M,"1M``A\`&`"4D8P!DC`Y8`@4DJP"`!F\"\286983R9`(`MF"G``3-\,\$Y=> M3G5Z`21J``1X`&`R2I)G*D*G0J<O"DZZ`L9/[P`,+@`P!,'\`!X@0-'+(4<`- M$DJ'9P1P`6`"<`#*0%"*4D2X1FW*2D5F#"\+3KH%>EA/<`!@J"`+8*1.50``S M2.<.,'P`8`)21C`&2,#E@"!M``A*L`@`9NY"IS`&P/P`'G(`,@`O`4ZZ%CA0D M3R1`(`IF"G``3-\,<$Y=3G5Z`'@`8&(P!,'\`!XF0-?*($M#[(,V<`8@V5'(W M__PPV3=%``0P!$C`Y8`@;0`(+S`(`$ZZ!?983\'\``I80#=```@P*P`(T'P`8 M"MI`,`1(P.6`(&T`""=P"```#B!+T?P````>)HA21+A&;9HP!E-`P?P`'D*R^ M"``@"F``_WQ.50``2.<`,"1M``A"ITAX`!1.NA624$\F0$J`9@IP`$S?#`!.( M74YU($M#[(,B(-D@V2#9(-D@V2\+3KH6-%A/,BH`"))`54$W00`$0J<P*@`(" MD'P`$DC`+P`O+0`,3KH!:$_O``PE0``<9A!(>``4+PM.NA584$]P`&"D(&H`/ M$B%+`!!P`6"83E4``$CG#``@;0`(#!``(68``2)2K0`((&T`"!`02(!(P&``< M`,H@;0`,".@````-8```^B!M``P`:``)``Q@``#L(&T`#`)H_S\`#"!M``P(* MZ``'``U@``#4(&T`#`)H_S\`#"!M``P`:`#```Q@``"\(&T`#`)H_^\`#&``# M`*X@;0`,`&@!`0`,8```H"!M``P(Z``"``U2K0`((&T`"")M``P34``:8```I M@G@`>@`@;0`(#!``,&<*(&T`"`P0`#%F'"!M``A2K0`($!!(@)!\`#`R!5)%X MXV!(P-B`8-`@;0`,(40`#E.M``A@/I"\````*V>*6X!GLE.`9ZZ0O`````QG( MB)"\````)6<`_S13@&<`_Q)3@&<`_UB0O`````IG`/\V78!G`/\*4JT`"&``5 M_M8@+0`(3-\`,$Y=3G5.5?_V2.</,$)M__I@!%)M__HP+?_Z2,#E@"!M``@BV M4$JQ"`!FZ$*G,"W_^L#\`")R`#(`+P%.NA.F4$\D0$J`9@IP`$S?#/!.74YU5 M?@!Z`&`@,`5(P.6`(&T`"")0('$(``P0`"UF!'`!8`)P`-Y`4D6Z;?_Z;=HP\ M+?_ZD$=G-D*G,"W_^I!'P/P`%'(`,@`O`4ZZ$TI03R@`9AHP+?_ZP/P`(G(`F M,@`O`2\*3KH35E!/<`!@CDI'9U9"IS`'P/P`%'(`,@`O`4ZZ$Q103RM`__QFU M/#`M__K`_``B<@`R`"\!+PI.NA,>4$\P+?_ZD$=G&#`M__J01\#\`!1R`#(`B M+P$O!$ZZ$OY03W``8`#_-GX`>@!@``"@,`5(P.6`(&T`"")0('$(``P0`"UG) M``"&,`7!_``B)D#7RB!+0^R#5'`'(-E1R/_\,-DG1``2($1#[(,.(-D@V2#9K M(-D@V2\+,`5(P.6`(&T`"")0+S$(`$ZZ_4Y03R!$(4``#"\$3KH3*%A//`!8Q M1@@K``(`#6<$W'P`)0@K````#6<,($0&:``3``3<?``3O$=O`CX&V+P````47 M4D6Z;?_Z;0#_7'H`8```H#`%P?P`(B9`U\HP!4C`Y8`@;0`((E`@<0@`#!``R M+6<F-VT`#@`$-VT`$@`&-T<`"#`L@MI40#=```HP*P`*2,#1K0`08$P@;?_\N M0^R#=B#9(-D@V2#9(-D@;?_\,`>0?``*,4``!"!+0^R#BG`'(-E1R/_\,-D@C M+0`05(`W0``&7*T`$"=M__P`$@:M````%/_\($O1_````"(FB%)%NFW_^FT`V M_UPP+?_Z4T#!_``B0K((`"!M``@K:``$__9F!B`*8`#]O'X!>@!@.C`%2,#ED M@"!M``@B4"!Q"``,$``M9R(@;?_V2I!G%B\M__8P!<'\`"+0BB\`3KK[>E!/5 MSD!0K?_V4D6Z;?_Z;<!*1V8,+PIA4EA/<`!@`/UF(`I@`/U@3E4``$CG""!X& M`"1M``A@$DJJ`!)G""\J`!)A*%A/4D0D4B`*9NHP!,#\`!YR`#(`+P$O+0`(G M3KH0YE!/3-\$$$Y=3G5.5?_\2.</,"1M``A\`$*M__QZ`#@%)DI@3$JK`!QG@ M""\K`!QAVEA/""L``0`-9R8N*P`22H9F`BP'4D0@1TJH`!!G$$AX`!0@1R\H, M`!!.NA"*4$]@#DJM__QF!BMK`!+__%)%)E,@"V:P2D1G%#`$P/P`%'(`,@`OQ M`2\&3KH07%!/2D5G%C`%P/P`%'(`,@`O`2\M__Q.NA!"4$\P!-!%P/P`(G(`7 M,@`O`2\*3KH0+%!/3-\,\$Y=3G4@;P`$(`A*&&;\D<`@"%.`3G5A<$/LA@)%N M[(8"M<EF#C(\`!5K"'0`(L)1R?_\*4^&#BQX``0I3H822.>`@`@N``0!*6<06 M2_H`"$ZN_^)@!D*G\U].<T/Z`"!.KOYH*4"&%F8,+CP``X`'3J[_E&`$3KH`Q M&E!/3G5D;W,N;&EB<F%R>0!)^0``?_Y.=4Y5```O"DAY``$``#`LA?C!_``&A M+P!.N@]:*4"&&E!/9A1"ITAY``$``$ZZ#QI03RYLA@Y.=2!LAAI":``$(&R&: M&C%\``$`$"!LAAHQ?``!``H@;(8.("R&#I"H``10@"E`AAX@;(8>(+Q-04Y85 M0J=.N@\.)$!*J@"L6$]G+B\M``PO+0`(+PI.N@"N.7P``88B(&R&&@!H@```[ M!"!LAAH`:(````I/[P`,8$)(:@!<3KH//$AJ`%Q.N@[R*4"&)"!LAB1*J``DD M4$]G$"!LAB0B:``D+Q%.N@X&6$\O+(8D+PI.N@)H*6R&)(8H4$].N@X&(&R&G M&B"`3KH.)B!LAAHA0``&9Q9(>`/M2'H`*DZZ#@(@;(8:(4``#%!/+RR&*#\LF MABQ.NO7@0F=.N@P@4$\D7TY=3G4J`$Y5``!(YPPP)&T`$"!M``A*J`"L9Q@@G M;0`(("@`K.6`*``@1"`H`!#E@"9`8`0F;(7Z$!-(@$C`T*T`#%2`.4"&+D*G8 M,"R&+DC`+P!.N@WL*4"&,%!/9@A,WPPP3EU.=1`32(`Z`#\%($M2B"\(+RR&/ M,$ZZ`7XP!4C`($#1[(8P0_H!1!#99OP_+0`.+PHO+(8P3KH!.B!LAC!",%``? M.7P``88L,`5(P-"LAC`F0%*+)$M/[P`4$!-(@#H`L'P`(&<8NGP`"6<2NGP`Y M#&<,NGP`#6<&NGP`"F8$4HM@V`P3`"!M>@P3`")F+E*+($M2BQ`02(`Z`&<>U M($I2BA"%NGP`(F80#!,`(F8$4HM@!D(J__]@`F#68#@@2U*+$!!(@#H`9R:ZB M?``@9R"Z?``)9QJZ?``,9Q2Z?``-9PZZ?``*9P@@2E**$(5@SB!*4HI"$$I%W M9@)3BU)LABQ@`/]:0A)"IS`LABQ20$C`Y8`O`$ZZ#,HI0(8H4$]F"$)LABQ@J M`/[8>@`F;(8P8"0P!4C`Y8`@;(8H(8L(`"!+(`A*&&;\D<!3B#`(4D!(P-?`8 M4D6Z;(8L;=8P!4C`Y8`@;(8H0K`(`&``_I0@`#`\?_]@!#`O``P@;P`$2AAFN M_%-((F\`"%-`$-E7R/_\9P)"$"`O``1.=4SO`P``!"`(,B\`#&`"$-E7R?_\4 M9P9206`"0AA1R?_\3G5.50``2.<.,"1M``A"ITAZ`(Y.N@Q<*4"&-%!/9@A,B MWPQP3EU.=2!M``PB:``D+RD`!$ZZ#)0H`%A/9U)(>@!M($0O*``V3KH,9B9`< M2H!03V<T2'@#[2\+3KH+;"P`4$]G)"`&Y8`J`"!%)6@`"`"D)48`G$AX`^U(5 M>@`X3KH+2"5``*!03R\$3KH,,EA/+RR&-$ZZ"WY"K(8T6$]@@&EC;VXN;&EBT M<F%R>0!724Y$3U<`*@!.50``2&T`#"\M``A(>@1@3KH`F$_O``Q.74YU3E4`I M`$CG""`D;0`.#&T`!``29@@@;0`(*!!@'$IM``QO#"!M``AP`#`0*`!@"B!M> M``@P$$C`*`!";0`22FT`#&P01&T`#$J$;`A$A#M\``$`$C(M``Q(P2`$3KH#L MD$'L@ZQ3BA2P```R+0`,2,$@!$ZZ`X8H`&;:2FT`$F<&4XH4O``M(`I,WP007 M3EU.=4Y5_R)(YP@P)&T`""9M``Q";?_Z*VT`$/_\($M2BQ`02(`X`&<``NZX3 M?``E9@`"S$(M_S`[?``!__@[?``@__8[?"<0__0@2U*+$!!(@#@`L'P`+68.$ M0FW_^"!+4HL0$$B`.`"X?``P9A`[?``P__8@2U*+$!!(@#@`N'P`*F88(&W_4 M_%2M__P[4/_R($M2BQ`02(`X`&`R0FW_\F`<,"W_\L'\``K01)!\`#`[0/_R; M($M2BQ`02(`X`#`$4D!![(.^"#```@``9M2X?``N9EH@2U*+$!!(@#@`L'P`& M*F88(&W__%2M__P[4/_T($M2BQ`02(`X`&`R0FW_]&`<,"W_],'\``K01)!\Y M`#`[0/_T($M2BQ`02(`X`#`$4D!![(.^"#```@``9M0[?``"__"X?`!L9A(@. M2U*+$!!(@#@`.WP`!/_P8!"X?`!H9@H@2U*+$!!(@#@`,`1(P&!Z.WP`"/_N8 M8!8[?``*_^Y@#CM\`!#_[F`&.WS_]O_N/RW_\$AM_S`_+?_N+RW__$ZZ_>0K( M0/_J,"W_\$C`T:W__$_O``Q@7"!M__Q8K?_\(E`K2?_J(`E*&6;\D\!3B3M)T M__!@2B!M__Q4K?_\.!!![?\O*TC_ZA"$8"B0O````&-GXE.`9Y*0O`````MG[ M`/]R68!GLE6`9P#_<%>`9P#_<F#,0>W_,)'M_^H[2/_P,"W_\+!M__1O!CMM8 M__3_\$IM__AG:"!M_^H,$``M9PH@;?_J#!``*V8N#&T`,/_V9B93;?_R(&W_' MZE*M_^H0$$B`/P!.DK!\__]43V8*</],WPP03EU.=6`6/RW_]DZ2L'S__U1/^ M9@1P_V#D4FW_^C`M__)3;?_RL&W_\&[<0FW_[F`@(&W_ZE*M_^H0$$B`/P!.9 MDK!\__]43V8$</]@L%)M_^X@;?_J2A!G"C`M_^ZP;?_T;<XP+?_NT6W_^DIM" M__AF*&`8/SP`($Z2L'S__U1/9@9P_V``_WA2;?_Z,"W_\E-M__*P;?_P;MI@B M%C\$3I*P?/__5$]F!G#_8`#_4E)M__I@`/T(,"W_^F``_T)(YT@`0H1*@&H$; M1(!21$J!:@9$@0I$``%A/DI$9P)$@$S?`!)*@$YU2.=(`$*$2H!J!$2`4D1*F M@6H"1(%A&B`!8-@O`6$2(`$B'TJ`3G4O`6$&(A]*@$YU2.<P`$A!2D%F($A!_ M-@$T`$)`2$"`PR(`2$`R`H+#,`%"04A!3-\`#$YU2$$F`2(`0D%(04A`0D!TN M#]"`TX&V@6($DH-20%'*__),WP`,3G5.50``2&R$5C\M``A.N@`(7$].74YU+ M3E4``"\$."T`""\M``H_!$ZZ`#"X?``*7$]F)"!M``H0*``,2(`(```'9Q0_# M//__+RT`"DZZ`/1<3R@?3EU.=6#X3E4``"\*)&T`"B!2L>H`!&48,"T`",!\Z M`/\_`"\*3KH`R%Q/)%].74YU(%)2DA`M``D0@$B`P'P`_V#H3E4``"\*0>R$G M0"1(($K5_````!8O"&$06$]![(7XM<AEZB1?3EU.=4Y5``!(YP@@)&T`"'@`^ M(`IF"G#_3-\$$$Y=3G5**@`,9U`(*@`"``QG##\\__\O"F%2.`!<3Q`J``U(W M@#\`3KH%'(A`""H``0`,5$]G"B\J``A.N@(N6$\(*@`%``QG$B\J`!).N@+`T M+RH`$DZZ`A103T*20JH`!$*J``A"*@`,,`1@D$Y5__Y(YP@@)&T`"$'Z_T8IU M2(8X""H`!``,9PIP_TS?!!!.74YU""H``@`,9S`@4I'J``@X"#\$+RH`"!`J_ M``U(@#\`3KH"@+!$4$]G$`CJ``0`#$*20JH`!'#_8,`,;?__``QF$`BJ``(`J M#$*20JH`!'``8*A*J@`(9@@O"DZZ`)I83PQJ``$`$&8J&VT`#?__/SP``4AM/ M__\0*@`-2(`_`$ZZ`B*P?``!4$]FH#`M``Q@`/]J)*H`"#`J`!!(P-"J``@EK M0``$".H``@`,(%)2DA`M``T0@$B`P'P`_V``_SY.50``+PI![(1`)$A**@`,- M9QC5_````!9![(7XM<AE"'``)%].74YU8.)"DD*J``1"J@`((`I@ZDY5__PO6 M"B1M``@_/`0`3KH`P"M`__Q43V88-7P``0`0($K1_`````XE2``()%].74YU> M-7P$```0".H``0`,)6W__``($"H`#4B`/P!.N@#B2D!43V<&`"H`@``,8,Y.= M50``2.<`,"1LA@)@%"92("H`!%"`+P`O"DZZ!%903R1+(`IFZ$*LA@),WPP`3 M3EU.=4Y5```O"D'Z_\8I2(8\0J<@+0`(4(`O`$ZZ!``D0$J`4$]F"'``)%]." M74YU)*R&`B5M``@`!"E*A@(@"E"`8.9.50``<``P+0`(+P!ALEA/3EU.=4Y5# M``!(YP`PE\LD;(8"8`X@;0`(48BQRF<2)DHD4B`*9NYP_TS?#`!.74YU(`MGS M!":28`0I4H8"("H`!%"`+P`O"DZZ`ZAP`%!/8-A.50``+PHP+0`(P?P`!B1`+ MU>R&&DIM``AM#C`M``BP;(7X;`1*DF8..7P``H9`</\D7TY=3G4P+0`(P?P`8 M!B!LAAHO,`@`3KH"QDJ`6$]G!'`!8`)P`SE4``"\M``A.N@*02H!83V8.& M3KH"FCE`AD!P_TY=3G5P`Ϥ``$CG#"`X+0`(3KH`<#`$P?P`!B1`U>R&- M&DI$;0JX;(7X;`1*DF80.7P``H9`</],WP0P3EU.=3`J``3`?``#9@HY?``%" MAD!P_V#D<``P+0`.+P`O+0`*+Q).N@)F*@"PO/____]/[P`,9@Q.N@(:.4"&+ M0'#_8+@@!6"T3E7__$AX$`!"ITZZ`MXK0/_\"```#%!/9Q)*;(8B9@@@+?_\E M3EU.=4ZZ``9P`&#T3E4``$AX``1(>@`<3KH!\"\`3KH"`C\\``%.N@`.3^\`) M#DY=3G5>0PH`3E4``$JLACAG!B!LACA.D#\M``A.N@`(5$].74YU3E7__"\$Y M,"T`"$C`*T#__$JLAAIG*'@`8`H_!$ZZ`/Y43U)$N&R%^&WP,"R%^,'\``8OE M`"\LAAI.N@'T4$]*K(8\9P8@;(8\3I!*K(7^9PHO+(7^3KH!:%A/2JR&0F<(U M(&R&0B"LAD9*K(9*9PHO+(9*3KH!A%A/2JR&3F<*+RR&3DZZ`7183TJLAE)G% M"B\LAE).N@%D6$]*K(969PHO+(963KH!5%A/+'@`!`@N``0!*6<4+PU+^@`*A M3J[_XBI?8`9"I_-?3G-*K(8D9C!*K(8P9R@P+(8N2,`O`"\LAC!.N@%,,"R&( M+%)`2,#E@"\`+RR&*$ZZ`3A/[P`08`Y.N@$B+RR&)$ZZ`5Y83R`M__PN;(8.4 M3G4H'TY=3G5.50``2.<.(#@M``@P!,'\``8D0-7LAAI*1&T*N&R%^&P$2I)FY M$#E\``*&0'#_3-\$<$Y=3G4(*@`'``1F""\23KH`"EA/0I)P`&#B(B\`!"QLA MAA9.[O_<(B\`!"QLAA9.[O^"(B\`!"QLAA9.[O^X+&R&%D[N_\HL;(863N[_= M?"(O``0L;(863N[_*$SO``8`!"QLAA9.[O_B+&R&%D[N_\1.^@`"(B\`!"QLH MAA9.[O^F3.\`#@`$+&R&%D[N_]!(YP$$3.\@@``,+&R&$DZN_Y1,WR"`3G5._ M^@`"(F\`!"QLAA).[OYB3OH``DSO``,`!"QLAA).[O\Z(F\`!"QLAA).[O[:G M+&R&$D[N_WQ.^@`"(F\`!"`O``@L;(823N[_+D[Z``(@;P`$+&R&$D[N_HQ.7 M^@`"+&R&$B)O``0@+P`(3N[]V$[Z``(B;P`$+&R&$D[N_H9,[P`#``0L;(82J M3N[^SD[Z``(@;P`$+&R&$D[N_H!,[P,```0L;(8T3N[_H"!O``0L;(8T3N[_> MIB!O``0L;(8T3N[_LB!O``0L;(8&3N[_RB!O``0L;(8&3N[_N"!O``0L;(8&5 M3N[^MB!O``0L;(8&3N[_-$SO`P``!"QLA@9.[O[X``````/L`````0````$`? M``T:`````````_(```/J```!@`````0````3````)0```#`````[````````Q M`$P```!7````90````````!P````>@```'\```"*````D@```)L```"I````1 ML@```+0`````````````````````````````````````````&```````````^ M`````````````````````````````````````````+X```#.````V@```.@`. M````````^@```0(```$$```!#@```14```$=```!)@```2@```$T````````* M````````````````````````````````````````````````````````````` M`````)`````````!/@```40```%+`````````58```%?```!:0```70```%^U M`````````8H```&4```!H@````````&L```!L0```;\```'!```!T0```=D`0 M``';```![`````````$$``````````````````````````````$4````````C M```````````!+`````````'X```"`````@<````````"$@```BD```(]```"Q M40```F4```)Y```"C0````````*D```"J0```JX```*S```"N````L$```+-$ M`````````M8```+A```"YP```O8```,&```#$P```Q4````````!D```````D M``&@``````````````````````````````'````````````````````#)```) M`RL```,W```#/@```T0```--```#6P```UT```-L```#>@````````.(```#X MD@```YH```.I```#M0```\(```/.```#UP````````/B```#Z@```^\```/W! M```#_0``!`(`````````*````%````"D````S````3P```%@```",```````^ M``'@```"`````EP````````"@````IP```0*``@````R`!0`R`!D__\```(`I M```0"@`````````````$%@```````````````````````0(``````@`!```"\ MU````````````P````````$```+4```%G`````````````````````H``0``: M````````````````````````````````````4@``````````````````````2 M```````````!``(``@````````````````````4`````````T```````````: M````````````````,#$R,S0U-C<X.6%B8V1E9@```"`@("`@("`@(#`P,#`PR M("`@("`@("`@("`@("`@("`@D$!`0$!`0$!`0$!`0$!`0`P,#`P,#`P,#`Q`( M0$!`0$!`"0D)"0D)`0$!`0$!`0$!`0$!`0$!`0$!`0%`0$!`0$`*"@H*"@H"( M`@("`@("`@("`@("`@("`@("`D!`0$`@``````````````````$``````0``( M```````````````````!`0````$``````````````````````0(````!````' M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M`````````````````````!0``````````````^P````7`````0```%@```!H; M````_````6````%X```!B````@````((```"(````IP```*@```"I````J@`= M``*L```"L````K0```*\```"P````L0```+,```"T````Q0```,H````9```B M````````````!`````@````,````$````!@````<````(````"@````L````0 M,````#0````X````/````$````!$````2````)````"4````F````)P```"D@ M````J````*P```"P````M````+@```"\````P````,0```$$```!"````0P`+ M``$4```!&````1P```$@```!)````2P```$P```!-````3P```%````!1```G M`4@```%,```!4````50```%8```!D````90```&8```!H````:0```&H```!$ MK````;````&T```!N````<````'$```!R````<P```'0```!U````=@```'@' M```!Y````>@```'L```!\````?0```'X```",````C0```(X```"/````D``\ M``)$```"2````DP```)0```"5````EP```)@```"9````F@```)L```"<```V M`G0```)X```"@````H0```*(```"C````I````*4```"U````O8```,L````U 1`````_(```/K`````0```_*(A `` end size 9692 SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.