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.