page@swan.ulowell.edu (Bob Page) (02/03/89)
Submitted-by: att!cuuxb!migh (Mike Hall) Posting-number: Volume 89, Issue 17 Archive-name: fonts/fts.1 # 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: # Fts.Doc # Compile.It # fts.c # fts.uu # This archive created: Mon Jan 30 19:09:32 1989 cat << \SHAR_EOF > Fts.Doc FTS: list fonts and their attributes `fts' lists information that the system gives it about the fonts located in "FONTS:". The listing is sorted by font names and sizes. The output has 5 columns, like this: Name Size Type Style Flags The `Name' column shows the font name. The `Size' column prints in decimal the font size given by the value in the ta_YSize field in the TextAttr structure. It's a measure of the height of the font in pixels. The `Type' column shows where the font is located, and has two fields, "dm", shown below. Its information comes from af_Type in the AvailFont structure: d disk AFF_DISK m memory AFF_MEMORY The `Style' column has four fields, "ubie", shown below. Its information comes from ta_Style in the TextAttr structure: e extended FSF_EXTENDED i italic FSF_ITALIC b bold FSF_BOLD u underline FSF_UNDERLINED Finally, the `Flags' column has 8 fields, "xspwtbdr", which come from the ta_Flags field in the TextAttr structure: x removed FPF_REMOVED s designed FPF_DESIGNED p proportional FPF_PROPORTIONAL w wide dot FPF_WIDEDOT t tall dot FPF_TALLDOT b backwards FPF_REVPATH d disk font FPF_DISKFONT r rom font FPF_ROMFONT To show how to invoke `fts', here is the usage information from `fts': 1> fts -? Use: fts -t[dm] -s[eibu] -f[xspwtbdr] -y# -n(name) -S Type: -t d = disk m = memory Style: -s e = extended i = italics b = bold u = underline Flags: -f x = removed s = designed p = proportional w = wide dot t = tall dot b = backwards d = disk font r = rom Size: -y# where `#' is YSize of the font Name: -n... where `...' is the font name Sort: -S = sort by size instead of name Calling `fts' with no arguments will print all the fonts the system finds under "FONTS:". At the end of the list, it reports the number of selected fonts and the total number of fonts on the system. The listing is sorted by name, and fonts with the same name are sorted by size. To sort the listing by size instead of name, use the -S switch. When sorting by size, fonts of the same size are sorted by name. The decision to print a font or not works like this: - if the size doesn't match, the font isn't printed - if the name doesn't match, the font isn't printed - if the font attributes matches ANY of the requested attributes, then font is printed Note that "-tdm" does NOT give fonts that are both in memory and on disk, it gives all fonts that are either in memory or on disk (i.e. all fonts). Here is a shortened sample output: 1> fts Font Name Size Type Style Flags clean 8 dm ---- -s----dr ... Helvetica 9 d- ---- -sp---d- Helvetica 11 d- ---- -sp---d- Helvetica 13 d- ---- -sp---d- Helvetica 15 d- ---- -sp---d- Helvetica 18 d- ---- -sp---d- Helvetica 24 d- ---- -sp---d- ... topaz 8 -m ---- -s-----r topaz 9 -m e--- -s--t--r 65 / 66 fonts. Note that `fts' will combine a disk-based and memory-based font on the same line, if all other attributes are the same (e.g. the "clean" font). Because of this, it says that 65 fonts were listed, although there are 66 available. Also, `fts' shows the ROM based fonts, "topaz 8" and "topaz 9" (the Type is `m' which means in-memory, and the rom-font Flag is set.) Here's another example, in which we sort by size, and ask for the fonts whose name begins with `cmr': 1> fts -ncmr -S Font Name Size Type Style Flags cmr6 26 d- ---- -sp---d- cmr8 34 d- ---- -sp---d- cmr10 42 d- ---- -sp---d- cmr12 50 d- ---- -sp---d- cmr14 59 d- ---- -sp---d- 5 / 66 fonts. And a case where we ask for the in-memory fonts: 1> fts -tm Font Name Size Type Style Flags clean 8 dm ---- -s----dr topaz 8 -m ---- -s-----r topaz 9 -m e--- -s--t--r 3 / 66 fonts. And another case where we ask for the "tall-dot" fonts, sorted by size: 1> fts -ft -S Font Name Size Type Style Flags topaz 9 -m e--- -s--t--r boarder 13 d- e--- -s--t-dr 2 / 66 fonts. Some future things to consider: - performance: sort after select (?) - collect on same line the same font with different sizes (how?) - specify alternate "FONT:" path (via 'assign's?) - specify and/or combinations of arguments (is this needed?) - specify keyword arguments (i.e. "style bold") (like CLI commands) - reallocate avail-font structure if it's not big enough There is a compile-time option, FTS_LARGE, which adds in the selection, help, and sort features. If you want a smaller version, just compile it plain; if you want all the options, compile with "-DFTS_LARGE". These are the sizes I get, compiling with Lattice 5.0: fts.lrg 9068 ----rwed Today 20:58:39 fts.sm 7640 ----rwed Today 20:56:07 The buffer that I give the system to place the font information in is 2000 bytes long. I believe that it should hold information for 199 fonts, but I haven't tested this. If you get the message "Some fonts not gotten...", then increase the parameter AFSIZE from 2000L to ((10 * number-of-fonts) + 2). I haven't checked on the validity of all the flag/style/type bits, but they look reasonable to me. There are no bugs that I know of, but please let me know if something goes wrong, or if it just doesn't seem to work right! Mike Hall att!cuuxb!migh 2 S 461 Cherice Dr. 312-393-6350 Warrenville, IL 60555 SHAR_EOF cat << \SHAR_EOF > Compile.It lc -Lcdn -w -r -b fts SHAR_EOF cat << \SHAR_EOF > fts.c /* * list fonts, print info about them */ /* Two versions: * large, with select/sort/help options -DFTS_LARGE * small, bare-bones (default) */ #include <proto/exec.h> #include <proto/diskfont.h> #include <string.h> #include <exec/types.h> #include <exec/memory.h> #include <libraries/diskfont.h> #include <graphics/text.h> #define AFSIZE 2000L long brkclean(); short fontcmpname(); void mkflags(), combine(), fixname(), cleanup(), shortbits(); #ifdef FTS_LARGE void showhelp(), doargs(); short fontcmpsize(), select(), mksel(); #endif /* if you don't use 'proto/diskfont.h', then you'll need this: extern long DiskfontBase; */ struct AvailFontsHeader *afh; #ifdef FTS_LARGE struct selinfo { /* place to keep select options */ short valid, type, style, flags, ysize, sort; char *name; }; /* flag bits for 'valid' selections (things that the user set) */ #define SEL_TYPE 0x01 #define SEL_STYLE 0x02 #define SEL_FLAGS 0x04 #define SEL_YSIZE 0x08 #define SEL_NAME 0x10 #define SEL_SORT 0x20 #endif #define FBUFSZ 24 /* length of flags string in the listing */ void main(ac, av) int ac; char *av[]; { register struct AvailFonts *af; register struct TextAttr *ta; unsigned short num ,i, cnt; char flagbuf[FBUFSZ]; #ifdef FTS_LARGE struct selinfo selinfo; #endif afh = NULL; /* init for cleanup */ onbreak(&brkclean); /* clean-up on ^C/^D */ #ifdef FTS_LARGE selinfo.sort = 0; /* sort by name */ selinfo.valid = 0; /* no others have been selected */ selinfo.type = selinfo.style = selinfo.flags = 0; #endif afh = (struct AvailFontsHeader *) AllocMem(AFSIZE, MEMF_CLEAR); if ( afh == NULL ) { exit(10L); } if ( (DiskfontBase = OpenLibrary("diskfont.library",0L)) == (long)NULL ) { cleanup(); exit(15L); } #ifdef FTS_LARGE doargs(ac, av, &selinfo); /* find out what they asked for */ #endif if ( AvailFonts((char *)afh, AFSIZE, 0xffL) != 0 ) printf("Some fonts not gotten...\n"); /* really should try again */ num = afh->afh_NumEntries; af = (struct AvailFonts *) &afh[1]; /* trick from RKM */ qsort(af, num, sizeof (struct AvailFonts), /* sort names/sizes */ #ifdef FTS_LARGE (selinfo.sort == 0) ? fontcmpname : fontcmpsize ); #else fontcmpname); #endif printf("Font Name Size Type Style Flags\n"); cnt = 0; for ( i = 0; i < num; i++, af++ ) { ta = &af->af_Attr; if ( ta->ta_Name == NULL ) { /* when "combined" */ continue; } if ( i < (num-1) ) { /* see if we can combine */ combine(af); } fixname(ta->ta_Name); /* get rid of ".font" */ #ifdef FTS_LARGE if ( !select(af, &selinfo) ) { /* if no match, skip it */ continue; } #endif mkflags(flagbuf, af->af_Type, ta->ta_Style, ta->ta_Flags); printf("%-20s %3d %s\n", ta->ta_Name, ta->ta_YSize, flagbuf); cnt++; } printf("%d / %d fonts.\n", cnt, num); cleanup(); exit(0L); } void cleanup() { if ( DiskfontBase != NULL ) CloseLibrary(DiskfontBase); if ( afh != NULL ) FreeMem((char *)afh, AFSIZE); } long brkclean() { cleanup(); return 1L; } #ifdef FTS_LARGE /* * read command line args, fill in selinfo struct */ void doargs(ac, av, sp) register int ac; register char **av; register struct selinfo *sp; { register char *p; while ( --ac > 0 ) { p = *++av; if ( *p != '-' ) continue; ++p; switch ( (*p++) ) { case 't': /* set type */ sp->type |= mksel(p, "dm", 0x2); sp->valid |= SEL_TYPE; break; case 's': /* set style */ sp->style |= mksel(p, "eibu", 0x8); sp->valid |= SEL_STYLE; break; case 'f': /* set flags */ sp->flags |= mksel(p, "xspwtbdr", 0x80); sp->valid |= SEL_FLAGS; break; case 'y': /* set ysize (only one!) */ sp->ysize = atoi(p); sp->valid |= SEL_YSIZE; break; case 'n': /* set name (only one!) */ sp->name = p; sp->valid |= SEL_NAME; break; case 'S': /* set sort by Size */ sp->sort = 1; sp->valid |= SEL_SORT; break; default: showhelp(); } } } #endif #ifdef FTS_LARGE /* * print help message, and cleanup and exit */ void showhelp() { printf("Use: fts -t[dm] -s[eibu] -f[xspwtbdr] -y# -n(name) -S\n"); printf(" Type: -t d = disk m = memory\n"); printf(" Style: -s e = extended i = italics\n"); printf(" b = bold u = underline\n"); printf(" Flags: -f x = removed s = designed\n"); printf(" p = proportional w = wide dot\n"); printf(" t = tall dot b = backwards\n"); printf(" d = disk font r = rom\n"); printf(" Size: -y# where `#' is YSize of the font\n"); printf(" Name: -n... where `...' is the font name\n"); printf(" Sort: -S = sort by size instead of name\n"); cleanup(); /* clean up and exit */ exit(0); } #endif /* * compare two AvailFonts structs, to sort by name/ysize */ short fontcmpname(f1, f2) struct AvailFonts *f1, *f2; { int stricmp(); short r; register struct TextAttr *t1, *t2; t1 = &f1->af_Attr; t2 = &f2->af_Attr; if ( (r = stricmp(t1->ta_Name, t2->ta_Name)) == 0 ) { r = t1->ta_YSize - t2->ta_YSize; } return r; } #ifdef FTS_LARGE /* * compare two AvailFonts structs, to sort by ysize/name */ short fontcmpsize(f1, f2) struct AvailFonts *f1, *f2; { int stricmp(); short r; register struct TextAttr *t1, *t2; t1 = &f1->af_Attr; t2 = &f2->af_Attr; if ( (r = t1->ta_YSize - t2->ta_YSize) == 0 ) { r = stricmp(t1->ta_Name, t2->ta_Name); } return r; } #endif /* * see if the next (sorted) font has the same characteristics; * if so, combine that one's type with this one; mark it "empty" */ void combine(ap) struct AvailFonts *ap; { struct AvailFonts *ap2; register struct TextAttr *t1, *t2; ap2 = ap + 1; t1 = &ap->af_Attr; t2 = &ap2->af_Attr; if ( (strcmp(t1->ta_Name, t2->ta_Name) == 0) && t1->ta_YSize == t2->ta_YSize && t1->ta_Style == t2->ta_Style && t1->ta_Flags == t2->ta_Flags ) { /* if TextAttr's are same, then combine avail-font types */ ap->af_Type |= ap2->af_Type; t2->ta_Name = NULL; /* mark it "combined" */ } } /* * fix up the font name to print - get rid of the training ".font" */ void fixname(p) char *p; { register char *s, *d; /* if Lattice's "strrchr" did what UNIX's "strrchr" did, we wouldn't have to do this... */ d = NULL; for ( s = p; *s; s++ ) { if ( *s == '.' ) d = s; } if ( d != NULL ) *d = '\0'; /* end the name at the last dot */ } /* * fill a print buffer with some flags: mem/style/attributes */ void mkflags(p, t, s, f) char *p; /* destination buffer */ short t, s, f; /* type, style, flags */ { /* Type Style Flags */ strcpy (p, " -- ---- --------"); shortbits(&p[1], t, "dm", '-', 0x2); shortbits(&p[5], s, "eibu", '-', 0x8); shortbits(&p[11], f, "xspwtbdr", '-', 0x80); } /* turn flag bits into series of characters */ void shortbits(p, v, t, fc, b) char *p; /* output string */ short v; /* value to be decoded */ char *t; /* true char string */ short fc; /* false char */ short b; /* top (start) bit */ { while ( b ) { /* for each bit */ *p++ = ( b & v ) ? *t : fc; /* accum chars if bit is set */ t++; /* next char, next bit */ b >>= 1; } } #ifdef FTS_LARGE /* turn characters into flag bits */ short mksel(p, r, b0) register char *p; /* input char string */ char *r; /* reference flag characters */ short b0; /* top (start) bit */ { register short v; /* output value */ register char *f; /* current flag char */ register short b; /* current bit */ v = 0; while ( *p ) { /* for each char in input */ f = r; b = b0; while ( *f ) { /* for each char in reference */ if ( *p == *f ) /* if char's match, set the bit */ v |= b; f++; /* next char, next bit */ b >>= 1; } p++; /* next input char */ } return v; } #endif #ifdef FTS_LARGE /* * see if the given font structure matches what was asked for */ short select(af, ps) register struct AvailFonts *af; /* what we're looking at */ register struct selinfo *ps; /* what they want to see */ { register short len; if ( (ps->valid & SEL_YSIZE) && (af->af_Attr.ta_YSize != ps->ysize) ) return 0; len = strlen(ps->name); if ( (ps->valid & SEL_NAME) && (strnicmp(af->af_Attr.ta_Name, ps->name, len) != 0) ) return 0; if ( (ps->valid & SEL_TYPE) && !(af->af_Type & ps->type) ) return 0; if ( (ps->valid & SEL_STYLE) && !(af->af_Attr.ta_Style & ps->style) ) return 0; if ( (ps->valid & SEL_FLAGS) && !(af->af_Attr.ta_Flags & ps->flags) ) return 0; return 1; } #endif SHAR_EOF cat << \SHAR_EOF > fts.uu begin 644 fts M```#\P`````````"``````````$```>B```!G````^D```>B)$@D`$GY````F M`$?Y```$4'(`(#P```"(8`(FP5'(__PL>``$*4X$B"E/!)!"K`2,)FX!%'``5 M(CP``#``3J[^SBEK`)@$A$JK`*QG``!P(`^0KP`$!H````"`*4`$5&$``2X@K M:P"LT<C1R")H`!#3R=/)(`)R`!(9*4D$F-"!4H!"9U*``D#__I_`58!"=P@`Z M(`)3@-2!'[(``"``4X)1R/_V'[P`("``4X(?L2``(`!1RO_X(D\O"6```'@I: M:P`Z!%1P?U*`T:P$5&$``,)!ZP!<3J[^@$'K`%Q.KOZ,*4`$C"\`)$`@*@`D` M9Q(L;`9L($`B*```*4$$A$ZN_X(B*@`@9QHD/````^U.KO_B*4`$E&<*Y8@@U M0"=H``@`I"!L!(PO"$AL!%`@:``D*6@`!`283KH&D$ZZ"U1P`&`$("\`!"\`. M("P$?&<$($!.D$ZZ%@@L>``$(FP&;$ZN_F).N@9F2JP$C&<:(BP$E&<$3J[_F MW"QX``1.KO]\(FP$C$ZN_H8@'RYL!)!.=7!D8+1#^@`0<`!.KOW8*4`&;&?LM M3G5D;W,N;&EB<F%R>0!.5?_*O^P$5&4`$#)(YP\R/B\`6D*L!)Q(>@&:3KH5! M>EA/<``[0/_4.T#_RCM`_]`[0/_..T#_S"`\```'T'(!2$$L>``$3J[_.BE`P M!)Q*@&8*2'@`"DZZ%T!83T/L``!P`"QX``1.KOW8*4`&9$J`9@YA``$(2'@`] M#TZZ%QQ83TAM_\HO+0`*/P=A``$V3^\`"B!L!)P@/```!]!R`$8!+&P&9$ZN1 M_]Q*@&<*2&P`$DZZ%+!83R!L!)P\$$?H``)*;?_49@9!^@**8`1!^@+$+PAP! M"C\`/P8O"TZZ$U1(;``L3KH4?D_O`!!X`'H`ND9D:D7K``)*DF=:(`930+I`! M9`@O"V$``LQ83R\280`#*DAM_\HO"V$`!%A/[P`,2D!G,G``$"H`!G(`$BH`+ M!S\!/P`_$TAM_]IA``,R2&W_VC\J``0O$DAL`%1.NA063^\`&%)$4D76_``*1 M8)(_!C\$2&P`9$ZZ$_QA```20I=.NA8H3.U,\/^N3EU.=;_L!%1E``ZZ+PY*" MK`9D9PPB;`9D+'@`!$ZN_F)*K`2<9Q(B;`2<(#P```?0+'@`!$ZN_RXL7TYU4 MO^P$5&4`#H)AOG`!3G5.5?_\O^P$5&4`#G!(YP$P/B\`&"9O`!HD;P`>4T=O= M``#X6(L@4RM(__QP+;`09NQ#Z``!$!E(@"M)__QR)%U!:P``SK![$`AF]$[[* M$`0`4V```*X`;F```)@`>6```'H`9F```%``<V```"@`=&````)P`C\`2&P`Z M="\M__QA``+J3^\`"H%J``((Z@````%@BG`(/P!(;`!X+RW__&$``LI/[P`*9 M@6H`!`CJ``$``6``_VHP/`"`/P!(;`!^+RW__&$``J9/[P`*@6H`!@CJ``(`6 M`6``_T8O+?_\3KH:#%A/-4``"`CJ``,``6``_RXE;?_\``P(Z@`$``%@`/\>? M-7P``0`*".H`!0`!8`#_#F$```Y@`/\&3-\,@$Y=3G6_[`1490`-5$AL`(A.M MNA)R2&P`PDZZ$FI(;`#B3KH28DAL`0A.NA):2&P!)$ZZ$E)(;`%*3KH22DAL7 M`6Q.NA)"2&P!C$ZZ$CI(;`&H3KH2,DAL`=1.NA(J2&P"`$ZZ$B)A`/XX0E=.$ MNA1.3^\`+$YU3E7_]K_L!%1E``S@2.<!,"9M``A4BR1M``Q4BB\2+Q-.N@X@# M4$\N`$I'9@HP*P`$D&H`!"X`(`=,WPR`3EU.=4Y5__:_[`1490`,H$CG`3`F7 M;0`(5(LD;0`,5(HP*P`$D&H`!"X`2D=F#"\2+Q-.N@W24$\N`"`'3-\,@$Y== M3G5.5?_TO^P$5&4`#&!(YP`R(&T`"-#\``HF;0`(5(M%Z``"(E,L4BM(__P03 M&;`>9BY*`&;V9B@P*P`$L&H`!&8>$"L`!K`J``9F%!`K``>P*@`'9@HP$"!MK M``B!4$*23-],`$Y=3G5.5?_XO^P$5&4`"_I(YP`PE<HF;0`(2A-G#'`NL!-F) M`B1+4HM@\"`*9P)"$DS?#`!.74YUO^P$5&4`"\I(YP<0)F\`%#XO`!@\+P`:@ M.B\`'$'L`BHB2Q+89OQ!ZP`!<`(_`'(M/P%(;`(^/P<O"&$``#Y!ZP`%<`@^+ M@'(M/P%(;`)"/P8O"&$``"9!ZP`+,#P`@#Z`<BT_`4AL`D@_!2\(80``#$_O^ M`"9,WPC@3G6_[`1490`+4$CG!S`F;P`8/B\`'"1O`!X\+P`B.B\`)$I%9QP@8 M2U*+(`?`14I`9P80$DB`8`(@!A"`4HKB16#@3-\,X$YU3E7_^+_L!%1E``L&] M2.<',"9O`"0^+P`L?`!*$V<<)&T`#"H'2A)G#A`3L!)F`HQ%4HKB16#N4HM@? MX"`&3-\,X$Y=3G6_[`1490`*QDCG`3`F;P`0)&\`%`@J``,``6<.,"L`!K!J5 M``AG!'``8'@@:@`,2AAF_%.(D>H`#"X(""H`!``!9QH_!R\J``PO*P`"3KH+_ M$D_O``I*0&<$<`!@1@@J`````6<,,!/`:@`"9@1P`&`R""H``0`!9Q!P`!`K\ M``C`:@`$9@1P`&`:""H``@`!9Q!P`!`K``G`:@`&9@1P`&`"<`%,WPR`3G5./ M=4YU2.<',#XO`!@F;P`:/"\`'C\'3KH5N%1/)$`@"F8$</]@-`@J``,``6<._ M<`(_`$*G/P=.N@^04$\_!B\++RH``DZZ$8I/[P`**@!*;`1H9P1P_V`"(`5,D MWPS@3G4```````!P84Y5_]!(YR<P)F\`4"1O`%1^`'P`>@!P`!M\`"#_^W(`J M.T'_^#M\____]D'M_]@;0/_U&T#__#M!_^P[0?_N*TC_U$H39T)P`!`3<AA== M06LXL'L0"&;V3OL0!``C8```(``@8```%@`K8```#``M8````GX!8`Y\`6`*3 M>@%@!AM\``'__%*+8+H0$W(PL`%F!E*+&T'_^W`JL!-F$"!20^@``B2).U#_I M^%*+8`Y(;?_X+PM.N@MP4$_6P!`3<BZP`68F4HMP*K`39A`@4D/H``(DB3M0H M__92BV`.2&W_]B\+3KH+0E!/UL`0$W)LL`%F"AM\``'_]5*+8`AR:+`!9@)2F MBQ`;<@`2`!M`__1P,%U`:P`"7+)[``AF]$[[``0`8V```C(`<V```?``6&``= M`80`>&```7X`<&```60`;V```1``=6```.0`9&````)*+?_U9PP@4D/H``0D3 MB2`08`P@4D/H``(DB3`02,`K0/_P;`IR`42M__`[0?_N2FW_[F<$<"U@"DH&K M9P1P*V`"<"`;0/_8<``0!C(M_^Z"0'``$`6"0&<(4JW_U%)M_^PO+?_P+RW_6 MU$ZZ"<!03SM`_](P+?_V2D!J!G(!.T'_]C`M_](R+?_VDD!(K0`"_]!O+B!M$ M_]0B2-+!8`(2V%'(__QP`!`M__LR+?_0(&W_U&`"$,!1R?_\,"W_]CM`_]+1; M;?_L0>W_V"M(_]1*!V<``58;?``@__M@``%,2BW_]6<,(%)#Z``$)(D@$&`,8 M(%)#Z``")(EP`#`0*T#_\&``_V!*+?_U9PP@4D/H``0DB2`08`P@4D/H``(D@ MB7``,!`K0/_P2BW__&<2(&W_U!#\`#`[?``!_^PK2/_4+P`O+?_43KH)'E!/O M.T#_TF``_R0;?``P__LP+?_V2D!J!CM\``C_]DHM__5G#"!20^@`!"2)(!!@, M#"!20^@``B2)<``P$"M`__!*+?_\9Q8@;?_4$/P`,!#\`'@[?``"_^PK2/_4; M+P`O+?_43KH)`%!/.T#_TG!8L"W_]&8`_KA(;?_83KH&_%A/8`#^JB!20^@`P M!"2)(E`K2?_49@A!^@#<*TC_U"!M_]1*&&;\4XB1[?_4.TC_[#`M__9*0&LJD ML,!O)CM`_^Q@(#M\``'_["!20^@``B2),!`;0/_80BW_V6`&<`!@``",,"W_Q M[#(M__BR0&P(=``[0O_X8`21;?_X2@=G-E-M_^QM&'``(&W_U!`8/P`K2/_4$ M(&T`$$Z05$]@XE-M__AM2'``$"W_^S\`(&T`$$Z05$]@Z%-M__AM$G``$"W_Z M^S\`(&T`$$Z05$]@Z%-M_^QM&'``(&W_U!`8/P`K2/_4(&T`$$Z05$]@XB`+8 M3-\,Y$Y=3G4``$Y5__9(YP$P)F\`'B1O`"(K;0`0__8>&DH'9S1P);X`9B*PU M$F8$4HI@&B\+2&W_]B\*80#[Q$_O``PK0/_Z9P0D0<``0!S\`3I-43V#&N M3-\,@$Y=3G5.5?_R2.<A,B9O`"H,;``@!<IL``"($!-R(+`!9PQR";`!9P9RY M"K`!9@12BV#H2A-G:C`L!<I(P.6`4FP%RD'L!=#1P"1(<"*P$V8F4HLDBTH3F M9PIP(K`39P12BV#R2A-F#'`!/P!.N@2<5$]@GD(;8)HDBTH39Q@0$W(@L`%G7 M$'()L`%G"G(*L`%G!%*+8.1*$V8"8`9"&V``_W)*;`7*9@8@;`2,8`1![`70R M*4@%S$IL!<IF?$'Z`21#[`60(M@BV"+8(M@RD")L!(P@:0`D<"@_`"\H``1(\ M;`603KH%?D_O``I![`60(@@D/````^XL;`9L3J[_XBE`!*(I0`2H<@0Y002FV M*4`$KCE!!*SE@)/)+'@`!"M`__).KO[:(&W_\B)`(V@`"`"D?@`K0/_V8"XL- M;`9L3J[_RBE`!*(L;`9L3J[_Q"E`!*A!^@"B(@@D/````^U.KO_B*4`$KGX$A M(`<`0(`!@6P$H"`'`$"``H%L!*8`;(`#!*Q*;`*T9P1P`&`$,#R``"X`0FP"- M@"`'`$```3E``GXY?``!`I@@!P!```(Y0`*6.7P``@*P(`<`0`"`.4`"KD'Z? M#AXI2`2`+RP%S#\L!<I.NO-60E=.N@KH3.U,A/_>3EU.=6-O;CHQ,"\Q,"\S, M,C`O.#`O`"H`````````````````````````````````````````````````2 M+PLF;P`(2FL`$&<,""L``P`39@1P`&`V/RP$3$ZZ"FY43R=```0G0``,2H!FT M"CE\``P&:'#_8!8W;`1,`!!P\\%K`!)P`#=```HW0``()E].=0``````````Z M````````3E7_\DCG+Q`^+P`N)F\`,"@'<#'`:P`29P9P_V```F8(*P`'`!)6U MP$0`2(`L`$IK`!!F``"$""L``@`39GIP`#=```IR_[Y!9P`".B\+3KK_4%A/+ M2D!G#`CK``4`$W#_8``"(@CK``$`$TH&9PXP*P`0(@!$03=!``I@"#`K`!`WE M0``*4VL`"FT6(&L`!$/H``$G20`$(`<0@'(`$@!@$B`'<@`2`"\+/P%A`/]4* M7$\B`"`!8``!S@@K``(`$V=4</^^0&8&<`!@``&Z(`<;0/__2@9G('(*OD%F\ M&G("/P%(>@&J/RL`%#M!__9.NO?:4$\J`&`8<@$_`4AM__\_*P`4.T'_]DZZA M]\!03RH`?O]@``#<".L``0`32@9G4G#_OD!G3%1K``IR"KY!9B8@:P`$0^@`S M`2=)``00O``-,BL`"DI!:PHO"S\`80#^M%Q/4FL`"B!K``1#Z``!)TD`!"`') M$(`R*P`*2D%K``$8?O\@*P`$D*L`##M`__9G;@@K``8`$F=0<`(_`$*G/RL`D M%$ZZ!OI03RM`__)*!F<X4ZW_\FTR0F<O+?_R/RL`%$ZZ!MQP`3Z`2&W__3\K^ M`!1.N@343^\`#DIL!&AF"A`M__UR&K`!9\@_+?_V+RL`##\K`!1.NO;D4$\JG M`&`">@!P_[I`9@@(ZP`%`!-@#+IM__9G!@CK``0`$TH&9PXR*P`0)`%$0C="3 M``I@&`@K``(`$V<(<@`W00`*8`@R*P`0-T$`"B!K``PG2``$OD!G+E-K``IM6 M%B!K``1#Z``!)TD`!"`'$(!R`!(`8!(@!W(`$@`O"S\!80#]FEQ/(@!P,,!KG M`!)G!'#_8`QP_[A`9@1P`&`"(`1,WPCT3EU.=0T*``!(YP<`/B\`$#PL`E1*& M1FLN(`9R!L'!0>P$H#HP"`!*!6<8"`4``F82(`;!P4'L!*`O,`@"3KH(YEA/6 M4T9@SB`'2,`O`$ZZ[VA83TS?`.!.=0```````'!A+FP$D$ZZ"-Y(>0```!1.) MN@=,``````````!P83`O``0,``!A;0H,``!Z;@0$```@3G4``"!O``0B;P`(P M,"\`#&\,4T`2$!#1$L%1R/_X3G5(YP`P)F\`#"1+2A)G)'``$!)![`-)"#``[ M`0``9PIR`!(`!$$`(&`$<@`2`!2!4HI@V"`+3-\,`$YU``````````!P84Y5% M__Y(YP,P)F\`&B1O`!X^+P`B2D=G-DH39S)*$F<N<``0&S\`3KK_8'(`$AH_! M`3]``!1.NO]26$\R+P`0DD`L`4I&9P0@!F`:4T=@QDI'9Q!*$V<$<`%@"DH2F M9P1P_V`"<`!,WPS`3EU.=4Y5__I(YP,P)F\`'B1O`"(^+P`F($I*&&;\4XB1D MRBP(($M*&&;\4XB1RR`((DO2P"M)__J\1V,"+`<@!B!*8`(2V%'(__P@;?_Z) M0C!H`"`+3-\,P$Y=3G4@;P`$(F\`"'``<@`0&!(9#```86T*#```>FX$!```K M(`P!`&%M"@P!`'IN!`0!`""0@68$2@%FU$YU```O"R9O``AP`!`30>P#20@P! M``,``&<$4HM@["`+)E].=4*`,"\`"&`$("\`""!O``1.5?_T(D]R"DZZ"!P&V M00`P$L%*@&;P(`D0X;_)9OI"$)"/3EU.=0``0H`P+P`(8`0@+P`((&\`!$Y5? M__0B3R(``D$`!P9!`#`2P>:(9O`@"1#AO\EF^D(0D(].74YU```P,3(S-#4VD M-S@Y86)C9&5F0H`P+P`(8`0@+P`((&\`!$/O``0R``)!``\2^Q#4Z(AF\B`)0 M(@]8@1#ALHEF^D(0D(%.=2!O``0B2'(`<``O`@P0`"MG!@P0`"UF`E)($!@$W M```P;1(,```);@PD`>6!TH+2@=*`8.8,$0`M9@)$@20?(`A3@"!O``@P@9")> M3G5.5?_H2.<!,BXO`#1*AVX&</]@``#2<`B^@&P"+@`@!U:`+@`"1__\)&T`X M""!M``C1Q]^L`F9#[`)B)E$K2/_P*TG_]"`+9P``D"!+("L`!-'`*TC_[")M5 M__"WR6,0)(LE1P`$+&W_]"R*<`!@>+?)9AHL4R2.("L`!"(`TH<E00`$+&W_( M]"R*<`!@6K7(9`B?K`)F</]@3K7(9BQ*DV<.(%.SR&,(GZP"9G#_8#C?JP`$/ M2I-G#K/39@H@*0`$T:L`!":1<`!@'BM+__0K;?_L_^@F4V``_VX@;?_T((I"_ MDB5'``1P`$S?3(!.74YU``````````!P84CG!S`^+P`8)F\`&CPO`!X_!TZZ9 M!^Q43R1`(`IF!'#_8"`_!B\++RH``DZZ!)Q/[P`*>@`Z`$IL!&AG!'#_8`(@Y M!4S?#.!.=4Y5__1(YP\P/B\`,#PO`#)P`;Y`;P``TB!M``@B2-+&)DEP`KY`# M9B8O"R\((FT`$$Z14$]*0&\``+`_!B\++RT`"$ZZ^_Q/[P`*8```G"`'2D!J$ M`E)`XD#!QB!M``@B2-+`/P8O"2\(3KK[UD_O``HD;0`(>`!Z`;I';"XO+0`(N M+PL@;0`03I!03TI`:A921-3&M<MG#C\&+PHO"TZZ^Z)/[P`*UL9216#.(&T`6 M"+7(9PX_!B\*+PA.NON&3^\`"B\M`!`_!C\$+RT`"&$`_S(@2M#&(`>01%-`X M+JT`$#\&/P`O"&$`_QI,[0SP_]Q.74YU```O!SXO``A2;`904VP"CFT6(&P"] MB$/H``$I20*((`<0@'(`$@!@%"`'<@`2`$AL`H0_`4ZZ]_Q<3R(`+A].=4Y5_ M```O"R9O``Q";`902&T`#"\+2'K_K$ZZ]0Q(;`*$</\_`$ZZ]\PP+`90)FW_' M_$Y=3G4``"`O``1F!B`\```<9"E`!(!P`$YU2.<`,B9L!E0@"V<6)%-P`#`K< M``@B2RQX``1.KO\N)DI@YI'(*4@&6"E(!E1,WTP`3G4``$CG#Q`^+P`8+"\`7 M&CHO`!X_!TZZ!?143R9`(`MF!'#_8!X_!2\&+RL``DZZ`BQ/[P`**`!*;`1H0 M9P1P_V`"(`1,WPCP3G4``````````'!A2.<!,BXO`!1P"MZ`(`=R`"QX``1.1 MKO\Z)D`@"V8$<`!@/"`'-T``"$7L!E0@:@`$)T@`!)'()HA*DF8")(M*J@`$2 M9P8B:@`$(HLE2P`$2JP"6&8$*4L"6$'K``H@"$S?3(!.=0``````````````^ M`$Y5__A(YP,P+B\`($J';@9P`&```+AP"+Z`;`(N`"`'5H`N``)'__Q%[`)B< M)E(@"V="("L`!+"';32PAV8.(%,DB)^L`F8@"V```((@*P`$D(=R"+"!;18@Q M2]'')(@D2"23)4``!)^L`F8@"V!>)$LF4V"Z,"P"N$C`(@?2@%.!,"P"N$C`$ M+T``%"`!(B\`%$ZZ`L(R+`*X2,%.N@*8+`!0AB`&5H`L``)&__PO!DZZ_N!8X M3R9`(`MG$"\&+PM.NON0+H=A`/\Z8`)P`$SM#,#_Z$Y=3G4``````````'!AE M+P<^+P`(<``P!R\`3KK_$EA/+A].=0``2.<#$#XO`!!'[`)L(`MG,@@K``(`J M$V8F""L``0`39QX@*P`$D*L`#"P`2D9G$#\&+RL`##\K`!1.NNY*4$\F4V#*? M/P=.NO@&5$],WPC`3G5(YS<0+B\`'"9O`"`\+P`D2JP$@&<$3KH$*$)L!&@@K M!DC`(@<D"R8`+&P&;$ZN_]`J`'#_NH!F#DZN_WPY0`1H.7P`!09H(`5,WPCLP M3G4``$CG/P`N+P`<+"\`(#HO`"1*K`2`9P1.N@/80FP$:'``,`53@"(')`8F% M`"QL!FQ.KO^^*`!P_[B`9@Y.KO]\.4`$:#E\`!8&:"`%#$```F<4#$```6<(% M2D!F&"`&8!0@!-"&8`XB!W0`=@`L;`9L3J[_ODS?`/Q.=4CG-Q`N+P`<)F\`. M(#PO`"1*K`2`9P1.N@-@0FP$:"`&2,`B!R0+)@`L;`9L3J[_UBH`</^Z@&8.G M3J[_?#E`!&@Y?``%!F@@!4S?".Q.=0``+P<N+P`(2JP$@&<$3KH#&B('+&P&W M;$ZN_]QP`"X?3G5.5?^P+PY*K`9@9A)#^@"(<``L>``$3J[]V"E`!F!P`"!L? M!)@0*/__0^W_L&`"$MA1R/_\<``@;`28$"C__T(U`+!![?^P*4@"R$AX`"A(. M>`#Z<``O`"\`2&P"Y'(`+P%(;`+0+P%.N@+P<!0^@$ZZ]E0L;?^L3EU.=2HJ& M(%-T86-K($]V97)F;&]W("HJ``!%6$E4``!I;G1U:71I;VXN;&EB<F%R>0``^ M``````````````!(YS``)``F`4A"2$/$P<;`P,'40TA"0D+0@DS?``Q.=4J`& M:@``'D2`2H%J```,1(%A```@1(%.=6$``!A$@$2!3G5*@6H```Q$@6$```9$1 M@$YU+P)(030!9@``(DA`2$%(0C0`9P``!H3!,`)(0#0`A,$P`DA",@(D'TYUD M+P-V$`Q!`(!D```&X9E10PQ!"`!D```&Z9E90PQ!(`!D```&Y9E50TI!:P``] M!N.94T,T`.:H2$)"0N:J2$.`P38`,`(T`TA!Q,&0@F0```A30]"!9/YR`#(#? M2$/GN$A`P4$F'R0?3G5.5?^@2.<S,GX`(&P$F!XH__]P3[Y`;P(N`"`'0^W_Q MKV`"$MA1R/_\0C5PKY/)+'@`!$ZN_MHF0$JK`*QG4"`K`*SE@"1`+"H`.$J&9 M9@0L*P"@2H9G."(&0?H`MB0(=@LL;`9L3J[_T"!'4D<@"!N\``H`KR`'2,`BT M!D/M_Z\D"28`+&P&;$ZN_]!P_V!.2JP&8&820_H`AG``+'@`!$ZN_=@I0`9@X M0>W_KRE(`QA(>``\2'@`^G``+P`O`$AL`S1(;`,@2&P##$*G3KH`]$_O`"!3' M@&<$</]@`G``3-],S$Y=3G4J*B!5<V5R($%B;W)T(%)E<75E<W1E9"`J*@``. M0T].5$E.544``$%"3U)4`"HJ*B!"<F5A:SH@`&EN='5I=&EO;BYL:6)R87)Y` M````+P<^+P`(<``Y0`1H2D=K)+YL`E1L'B`'<@;!P4'L!*!*<`@`9PX@!\'!\ M0>P$H-'`(`A@"#E\``D&:'``+A].=4CG`0)P`"(\```P`"QX``1.KO[.+@`"N MAP``,`!*AV8$<`!@($JL!(!G&"!L!(!.D$I`9@1P`&`,<!0_`$ZZ\WY43R`'? M3-]`@$YU8;1.=0``2.<P,BQL!F`@;P`8(F\`'"1O`"`F;P`D("\`*"(O`"PDM M+P`P)B\`-$ZN_J1,WTP,3G4``$Y5__XO"R9O``X@"V8$<`!@%B\+3KKU#B9`O M2&W__B\+3KKUUC`M__XF;?_Z3EU.=0```^P````!````````%TP````"````H M`0````P````&`````````_(```/J```!%&1I<VMF;VYT+FQI8G)A<GD``%-O1 M;64@9F]N=',@;F]T(&=O='1E;BXN+@H`1F]N="!.86UE"2`@("`@(%-I>F4@. M5'EP92!3='EL92`@1FQA9W,*`"4M,C!S("`E,V0@("5S"@`E9"`O("5D(&9O% M;G1S+@H`9&T``&5I8G4``'AS<'=T8F1R``!5<V4Z("!F=',@("UT6V1M72`ML M<UME:6)U72`M9EMX<W!W=&)D<ET@+7DC("UN*&YA;64I("U3"@``"51Y<&4Z> M"2UT"60@/2!D:7-K"0EM(#T@;65M;W)Y"@`)4W1Y;&4Z"2US"64@/2!E>'1E\ M;F1E9`D):2`](&ET86QI8W,*``D)"6(@/2!B;VQD"0EU(#T@=6YD97)L:6YEK M"@`)1FQA9W,Z"2UF"7@@/2!R96UO=F5D"0ES(#T@9&5S:6=N960*``D)"7`@` M/2!P<F]P;W)T:6]N86P)=R`]('=I9&4@9&]T"@`)"0ET(#T@=&%L;"!D;W0)& M"6(@/2!B86-K=V%R9',*``D)"60@/2!D:7-K(&9O;G0)"7(@/2!R;VT*```)$ M4VEZ93H)+7DC"7=H97)E(&`C)R!I<R!94VEZ92!O9B!T:&4@9F]N=`H```E.S M86UE.@DM;BXN+@EW:&5R92!@+BXN)R!I<R!T:&4@9F]N="!N86UE"@``"5-OZ M<G0Z"2U3(#T@<V]R="!B>2!S:7IE(&EN<W1E860@;V8@;F%M90H`("TM("`MS M+2TM("`M+2TM+2TM+0!D;0``96EB=0``>'-P=W1B9'(``````"@`````````+ M```````````````````````"A``````````````````````````````"G```D M````````````````````````````````````````````````````````@```` M``0```#__P````X`#@```````````````/__````!``$````````&T8```*\# M__\````$``0````````;7`````#__P````X`#@```````!U(`````/__````Z M!``$``````````````+X__\````$``0````````=9`````#__P````0`!```/ M`````!UN```````@("`@("`@("`H*"@H*"`@("`@("`@("`@("`@("`@($@0+ M$!`0$!`0$!`0$!`0$!"$A(2$A(2$A(2$$!`0$!`0$(&!@8&!@0$!`0$!`0$!& M`0$!`0$!`0$!`0$!$!`0$!`0@H*"@H*"`@("`@("`@("`@("`@("`@("`@(0P M$!`0("`@("`@("`@("@H*"@H("`@("`@("`@("`@("`@("`@2!`0$!`0$!`0` M$!`0$!`0$(2$A(2$A(2$A(00$!`0$!`0@8&!@8&!`0$!`0$!`0$!`0$!`0$!= M`0$!`0$0$!`0$!""@H*"@H("`@("`@("`@("`@("`@("`@("`A`0$!`@````Y M`@```````^P````%`````````T````,L```#!````O````+<````!`````$`$ 7``,<```"X````H0```)L`````````_(L6 `` end size 9068 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.