Article View: comp.sys.mac
Article #13941Re: Print Manager Info
From: Vann
Date: Fri, 19 Dec 1986 04:38
Date: Fri, 19 Dec 1986 04:38
704 lines
31065 bytes
31065 bytes
> I have recently become an owner of Turbo Pascal. Included among the files
> for use with the compiler (sample examples of Pascal programming) is one
> which generates a listing of a source file. It is entitled Lister.pas.
>
> I have been in the process of modifying the program to attempt to get it
> to do two things:
>
> (1) Print line numbers (right-justified) for each source line
>
> (2) Improve the efficiency of the program when printing all or a
> portion of a file.
>
> I have been able to get the line numbers prepended to each line, but the
> efficiency problem is still escaping me. Inside Macintosh shows a method
> of avoiding the unnecessary looping through all pages of a document when
> only a portion is to be printed. (See pgs. II-155,156) But still the
> printing seems to be considerably slower than Macintosh applications I
> have purchased.
>
> My question for those of you who know a great deal about this, is whether
> there are some tricks that I can perform to speed up the spooling of the
> file to the disk. Will any of this be possible in Pascal via existing
> Toolbox routines, or are we talking about some work in Assembler, etc?
>
> I'd be glad to post a summary of any comments I receive. Thanks in advance.
>
e P.S. For any of you who might have been curious, Turbo Pascal seems to be a
> very slick package. From the comments on the net concerning the speed of
> LSP and LSC, I should think this package is in the ballpark. But most of all
> I liked the documentation. There are some nicely stated insights into the
> Macintosh in general, and into the programming of the Mac in specific. Novice
> programmers of the Mac will no doubt find this a welcome addition to their
> programming arsenal.
>
> I should wonder if any of you have suggestions for a debugger other than the
> MACSBUG debugger that comes with the package?
>
>
> --
> Eric Geoffrey Vann
> Analysts International (Chicago Branch)
> (312) 882-4673
> ..!ihnp4!aicchi!egv
Here is a copy of the source about which I wrote:
program Lister;
{$B+} { set the bundle bit }
{$R-} { turn off range checking }
{$I-} { turn off I/O checking }
{$U-} { turn off autolink to runtime units }
{$T APPLLIST} { Set TYPE and CREATOR }
{$R Lister.Rsrc} { Link the resource file }
uses PasInOut,Memtypes,QuickDraw,OSIntf,ToolIntf,PackIntf,MacPrint;
const
MenuCnt = 6; { total # of menus }
ApplMenu = 1000; { resource ID of Apple Menu }
FileMenu = 1001; { resource ID of File Menu }
EditMenu = 1002; { resource ID of Edit Menu }
OptnMenu = 1003; { resource ID of Options Menu }
FontMenu = 1004; { resource ID for Font Menu }
SizeMenu = 1005; { resource ID for Size Menu }
AM = 1; { index into MenuList for ApplMenu }
FM = 2; { ditto for File Menu }
EM = 3; { ditto for Edit Menu }
OM = 4; { ditto for Options Menu }
TM = 5; { ditto for Font Menu }
SM = 6; { ditto for Size Menu }
MainID = 1000; { resource ID for Main Window }
AboutID = 1000; { resource ID for dialog box }
Text1ID = 1000; { resource IDs for 'About...' text }
Text2ID = 1001;
Text3ID = 1002;
MyCursID = 1000; { resource ID for myCursor }
MyCursor = 5; { array index for myCursor }
LeftMargin = 10; { left margin offset }
type
CursorList = array[iBeamCursor..myCursor] of CursHandle;
var
FontName : str255; { text name of selected font }
FontNumber : integer; { number of selected font }
PrintRecord : THPrint;
{
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Here is a description of the THPrint record so that some of the code
below makes more sense:
TYPE THPrint = ^TPPrint;
TPPrint = ^TPrint;
TPrint = RECORD
iPrVersion: INTEGER; Printing Manager version
prInfo : TPrInfo; printer info subrecord
rPaper : Rect; paper rectangle
prStl : TPrStl; additional device information
prInfoPT : TPrInfo; use internally
prXInfo : TPrXInfo; additional device information
prJob : TPrJob; job subrecord
printX : not used
Array[1..19] of Integer
END;
TPrInfo = RECORD
iDev : INTEGER; used internally
iVRes : INTEGER; vertical resolution of printer
iHRes : INTEGER; horizontal resolution of printer
rPage : Rect page rectangle
END;
Rect = RECORD CASE INTEGER OF
0 : (top : INTEGER;
left : INTEGER;
bottom : INTEGER;
right : INTEGER);
1 : (topLeft: Point;
botRight: Point)
END;
VHSelect = (v,h);
Point = RECORD CASE INTEGER OF
0 : (v: INTEGER: vertical coordinate
h: INTEGER); horizontal coordinate
1 : (vh: ARRAY[VHSelect] OF INTEGER)
END;
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
}
Reply : SFReply;
Quit : Boolean;
MenuList : array[1..MenuCnt] of MenuHandle; { holds menu info }
MainPtr : WindowPtr; { pointer to main window }
MainRec : WindowRecord; { holds data for main window }
MainPeek : WindowPeek; { pointer to MainRec }
ScreenPort : GrafPtr; { pointer to entire screen }
FrontWindow : WindowPtr; { pointer to active window }
TH,TV : Integer;
ScreenArea : Rect; { defines screen dimensions }
CursList : CursorList; { used to hold cursor handles }
ExpIncludes : Boolean; { global flag for expanding inc }
FontItem : integer; { current font menu item number }
SizeItem : integer; { global size menu item number }
LineSize : Integer; { heigth of a printed line }
procedure Debugger; inline $A9FF;
procedure PrinterError;
var
SavePrPort : GrafPtr;
ErrorString : str255;
begin
GetPort(SavePrPort);
SetPort(ScreenPort);
MoveTo(200,200);
NumToString(PrError,ErrorString);
ErrorString := 'Printer Error # '+ErrorString;
DrawString(ErrorString);
SetPort(SavePrPort);
end;
procedure DoPageSetup;
var
dummy : boolean;
begin
dummy := PrValidate(PrintRecord); { validate print information }
dummy := PrStlDialog(PrintRecord); { page setup dialog }
end;
procedure OutputText(TextLine : str255; var OutputLine : integer);
var
I : integer;
CurrentPoint : Point;
LineString : Str255;
Blanks : Str255;
begin
NumToString(OutputLine,LineString);
Blanks := '';
for I := 1 to 5-Length(LineString) do
Blanks := Blanks+Chr(20);
TextLine := Blanks+LineString+TextLine;
MoveTo(LeftMargin,OutputLine * LineSize);
{ Moveto X,Y page coordinates... }
for I := 1 to Length(TextLine) do
begin
GetPen(CurrentPoint);
{ if next character will go off the right side of the
page, then go to first print position of the next line }
if CurrentPoint.h+CharWidth(TextLine[I]) > PrintRecord^^.prInfo.rPage.right then
begin
OutputLine := OutputLine + 1;
NumToString(OutputLine,LineString);
Blanks := '';
for I := 1 to 5-Length(LineString) do
Blanks := Blanks+Chr(20);
TextLine := Blanks+LineString+TextLine;
MoveTo(LeftMargin,OutputLine * LineSize);
end;
DrawString(TextLine[I]);
end;
OutputLine := OutputLine+1;
end;
procedure DoPrintFile;
{ procedure that prints the file to the printer
using the Print Manager macintosh calls }
var
AString : str255;
PrinterPort : TPPrPort;
LinesPerPage : Integer; { # of text lines to print on a page }
FileFilter : SFTypeList; { file filter type list }
f,fi : text; { the text file variables for main and inc }
Secs : LongInt;
TextLine : str255; { the text line to be printed }
topLeft : Point;
theErr : OSErr;
PrintStatus : TPrStatus;
DoneWithFile : Boolean; { main file end of file flag }
DoneWithInc : Boolean; { include file end of file flag }
myRefNum : Integer;
SystemTime : str255;
SystemDate : str255;
PageWidth : Integer; { # of columns per page }
PageHeight : Integer; { # of lines per page }
CurrentLine : Integer; { current print line on the page }
PageNumber : Integer; { listing page number counter }
PageString : str255;
HeaderText : str255; { string used to build the listing header }
FontName : str255; { text name of selected font }
FontNumber : integer; { number of selected font }
SizeName : str255; { text name of font size }
FontSize : LongInt; { font size value }
AfterDigits : integer;
FirstNonBlank : Integer; { index for first char of include name }
FoundInclude : Integer; { flag for finding $I include directive }
EndName : Integer; { index for end of include file name }
IncludeFName : str255; { include file name scanned from source }
begin
topLeft.h := 90; { top left horiz point for Get File dialog }
topLeft.v := 80; { top left vert " " " " " }
FileFilter[0] := 'TEXT'; { file filter for text files }
{ Get Font and Size Information }
GetItem(MenuList[TM],FontItem,FontName);
GetFNum(FontName,FontNumber);
GetItem(MenuList[SM],SizeItem,SizeName);
AfterDigits := Pos(' ',SizeName);
Delete(SizeName,AfterDigits,99);
StringToNum(SizeName,FontSize);
{ get a file to print dialog }
{ The 2nd paramater in SFGETFILE is no }
{ longer being used. It was a string that }
{ could be displayed as a prompt... }
SFGetFile(topLeft,'',nil,1,FileFilter,nil,Reply);
if Reply.good then { if they selected a file}
begin
if PrJobDialog(PrintRecord) then
{ Post the dialog that requests info about}
{ Quality, Page Range, Number of Copies, &}
{ Paper Feed... }
begin
PrinterPort := PrOpenDoc(PrintRecord,nil,nil);
{ Initializes a printing grafPort for use }
{ in printing a document, makes it the }
{ current port, and returns its pointer...}
PageNumber := 1;
DoneWithFile := False;
PageWidth := Round(((PrintRecord^^.prInfo.rPage.right)
/ (PrintRecord^^.prInfo.iHRes)) * 72) - LeftMargin;
PageHeight := Round(((PrintRecord^^.prInfo.rPage.bottom)
/ (PrintRecord^^.prInfo.iVRes)) * 72);
LineSize := FontSize + 4; { line size depends on font size }
LinesPerPage := (PageHeight DIV LineSize) - 4;
theErr := SetVol(nil,Reply.vRefNum);
Reset(f,Reply.fName); { Open file as text using name gotten }
{ from the SFGetFile subroutine... }
GetDateTime(Secs); { get raw values for date and time... }
{ Convert the raw values into ASCII }
{ strings for display in header of page }
IUDateString(Secs,abbrevDate,SystemDate);
IUTimeString(Secs,true,SystemTime);
repeat
if PrError = noErr then
begin
PrOpenPage(PrinterPort,nil); { start a new page }
if PrError = noErr then
begin
CurrentLine := 1;
TextFont(monaco); { set font for header }
TextSize(12); { set text size for header }
TextFace([bold]); { set bold for header }
NumToString(PageNumber,PageString);
HeaderText := 'File: '+Reply.fname+' '+SystemDate+' ';
HeaderText := HeaderText+SystemTime+' Page: '+PageString;
MoveTo(LeftMargin + (PageWidth DIV 2)
- (StringWidth(HeaderText) DIV 2),CurrentLine * LineSize);
DrawString(HeaderText); { print header text }
CurrentLine := CurrentLine + 2;
TextFont(FontNumber); { set selected font }
TextSize(FontSize); { set selected font size }
TextFace([]); { set plain text type }
repeat
Readln(f,TextLine); { read text line from file }
OutputText(TextLine,CurrentLine); { print it out... }
{ scan for $I includes - see if expansion is required }
if ExpIncludes then
begin
FoundInclude := Pos('{$I ',TextLine);
if FoundInclude > 0 then { found $I - get filename }
begin
{ search for first non blank after $I }
FirstNonBlank := FoundInclude+3;
repeat
FirstNonBlank := FirstNonBlank + 1;
until (TextLine[FirstNonBlank] <> ' ')
or (FirstNonBlank > length(TextLine));
EndName := FirstNonBlank;
repeat
EndName := EndName + 1;
until (TextLine[EndName] = ' ')
or (TextLine[EndName] = '}')
or (EndName > length(TextLine));
{ get the include file name }
IncludeFName := copy(TextLine,FirstNonBlank,
EndName-FirstNonBlank);
reset(fi,IncludeFName); { open include file }
if IOResult = 0 then { if file exists }
begin
DoneWithInc := false;
{ process through include file }
OutputText('[INCLUDE FILE EXPANSION]',CurrentLine);
repeat
ReadLn(fi,TextLine); { read include line }
OutputText(TextLine,CurrentLine); { output the text }
if eof(fi) then { test end of inc }
DoneWithInc := true;
until DoneWithInc; { until end of inc }
close(fi); { close include file }
OutputText('[END OF INCLUDE FILE]',CurrentLine);
end;
end;
end;
if Eof(f) then { test end of main }
DoneWithFile := true;
until (CurrentLine > LinesPerPage) or DoneWithFile;
end
else
PrinterError;
PrClosePage(PrinterPort); { print the page }
end
else
PrinterError;
PageNumber := PageNumber + 1;
until (PrError <> noErr) or DoneWithFile;
Close(f);
PrCloseDoc(PrinterPort);
if (PrintRecord^^.prJob.bjDocLoop = bSpoolLoop) AND (PrError = noErr) then
PrPicFile(PrintRecord,nil,nil,nil,PrintStatus);
if PrError <> noErr then
PrinterError;
end;
end;
end;
procedure DoExpandIncludes(ItemNum : Integer);
{ sets/resets check mark and option for exapnding include files }
var
Ch : char;
begin
ExpIncludes := not ExpIncludes; { toggle the flag }
if ExpIncludes { if flag is True... }
then Ch := Chr(CheckMark) { then check item in menu }
else Ch := Chr(NoMark); { else clear any checkmark }
SetItemMark(MenuList[OM],ItemNum,Ch); { put char by item in menu }
end;
procedure DoFontMenu(ItemNum : Integer);
var
ChCheckMark, NoCheckMark : char;
begin
ChCheckMark := Chr(CheckMark);
NoCheckMark := Chr(NoMark);
SetItemMark(MenuList[TM],FontItem,NoCheckMark); { turn off prev mark }
SetItemMark(MenuList[TM],ItemNum,ChCheckMark); { turn on new mark }
FontItem := ItemNum; { update current pos }
end;
procedure DoSizeMenu(ItemNum : Integer);
var
ChCheckMark, NoCheckMark : char;
begin
ChCheckMark := Chr(CheckMark);
NoCheckMark := Chr(NoMark);
SetItemMark(MenuList[SM],SizeItem,NoCheckMark); { turn off prev mark }
SetItemMark(MenuList[SM],ItemNum,ChCheckMark); { turn on new mark }
SizeItem := ItemNum; { update current pos }
end;
procedure DoAbout;
var
theItem : Integer;
AboutPtr : DialogPtr;
S1,S2,S3 : StringHandle;
begin
SetCursor(CursList[myCursor]^^); { set to my cursor }
ShowCursor; { and turn it back on }
S1 := GetString(Text1ID); { get text from resource file }
S2 := GetString(Text2ID);
S3 := GetString(Text3ID);
ParamText(S1^^,S2^^,S3^^,''); { and set up as parameter text }
AboutPtr := getNewDialog(AboutID,NIL,Pointer(-1)); { get dialog box}
ModalDialog(NIL,theItem); { put dialog box up; get result }
DisposDialog(AboutPtr); { get rid of dialog box }
end; { of proc DoAbout }
procedure DoDeskAcc(Item : Integer);
var
SavePort : GrafPtr;
RefNum : Integer;
DName : String;
begin
GetPort(SavePort); { save port before starting it }
GetItem(MenuList[AM],Item,DName); { get name of desk accessory }
refNum := OpenDeskAcc(DName); { and start that sucker up! }
SetPort(SavePort); { restore grafport and continue }
end; { of proc DoDeskAcc }
procedure ProcessMenu(CodeWord : LongInt);
var
MenuNum : Integer; { Res ID# of the menu Selected }
ItemNum : Integer; { The item number in the menu }
begin
MenuNum := HiWord(CodeWord); { get the menu number }
ItemNum := LoWord(CodeWord); { get the item number }
if ItemNum > 0 then { ok to handle the menu? }
begin
case MenuNum of
ApplMenu :
case ItemNum of
1: DoAbout
otherwise
DoDeskAcc(ItemNum)
end;
FileMenu :
case ItemNum of
1: DoPageSetup;
2: DoPrintFile;
3: Quit := true;
end;
EditMenu :
if not SystemEdit(ItemNum - 1) then begin end;
OptnMenu :
case ItemNum of
1 : DoExpandIncludes(ItemNum); { expand includes }
end;
FontMenu : DoFontMenu(ItemNum);
SizeMenu : DoSizeMenu(ItemNum);
end; { of case menuNum of }
end; { of if CodeWord... }
HiliteMenu(0);
end; { of process menu }
procedure ClearWindow(WPtr : WindowPtr);
begin
if (WPtr = MainPtr) and (Wptr = FrontWindow ) then begin
EraseRect(WPtr^.portRect); { clear rect area of window }
end
end; { of proc ClearWindow }
procedure DoUpdate(Event : EventRecord);
var
SavePort,theWindow : WindowPtr;
begin
theWindow := WindowPtr(Event.Message); { find which window }
if theWindow = MainPtr then begin { only update ours }
SetCursor(CursList[MyCursor]^^); { set my cursor }
GetPort(SavePort); { save current grafport }
SetPort(theWindow); { set as current port }
BeginUpdate(theWindow); { signal start of update}
{ nothing to do }
EndUpdate(theWindow); { signal end of update }
SetPort(SavePort); { restore grafport }
end
end; { of proc DoUpdate }
procedure DoActivate(Event : EventRecord);
var
I : Integer;
AFlag : Boolean;
theWindow : WindowPtr;
begin
with Event do
begin
theWindow := WindowPtr(Message); { get the window }
AFlag := Odd(Modifiers); { get activate/deactive }
if AFlag then begin { if it's activated... }
SetPort(theWindow); { make it the port }
FrontWindow := theWindow; { know it's in front }
DrawGrowIcon(theWindow); { set size box }
end
else begin
SetPort(ScreenPort); { else reassign port }
if theWindow = FrontWindow { if it's in front }
then FrontWindow := NIL { ...then forget that }
end;
end
end; { of proc DoActivate }
procedure CursorAdjust;
var
MousePt : Point;
begin
if MainPtr = FrontWindow then
SetCursor(CursList[MyCursor]^^)
end; { of proc CursorAdjust }
procedure EventHandler;
var
Event : EventRecord; { Filled by Get next event }
windowLoc : integer; { the mouse location }
mouseLoc : point; { the area it was in }
theWindow : WindowPtr; { Dummy,cause we have no windows}
begin
repeat { do this until we selected quit}
SystemTask; { Take care of desk accessories }
CursorAdjust; { update which cursor }
if GetNextEvent(everyEvent,Event) then
begin
case Event.what of { case out on the event type }
mouseDown : { we had a mouse-down event }
begin
mouseLoc := Event.where; { where's the pesky mouse }
windowLoc := FindWindow(mouseLoc,theWindow); { find out where }
case windowLoc of { now case on the location }
inMenuBar :
ProcessMenu(MenuSelect(MouseLoc)); { Handle the selection }
inSysWindow:
SystemClick(Event,theWindow); {It was in a desk acc }
end;
end;
updateEvt : DoUpdate(Event); { window need updating }
activateEvt : DoActivate(Event) { window made act/inact }
end;
end;
until Quit;
end;{ of Event Handler }
procedure Initialize;
var
Indx : Integer;
begin
{ initialize all the different managers }
InitGraf(@thePort); { create a grafport for the screen }
MoreMasters; { allocate a block of master Ptr's }
MoreMasters; { and another }
InitFonts; { start up the font manager }
InitWindows; { start up the window manager }
InitMenus; { start up the menu manager }
TEInit; { start up the text manager for DAs }
InitDialogs(NIL); { start up the dialog manager }
FlushEvents(EveryEvent,0); { clear events from previous state }
{ set up printer stuff }
PrintRecord := THPrint(NewHandle(SizeOf(TPrint)));
{ allocate data record from }
{ applicaton heap to handle printer }
{ data... }
PrintDefault(PrintRecord); { set printer defaults...reads from }
{ printer resource file the default }
{ values to be placed in the data }
{ record allocated above... }
HLock(Handle(PrintRecord)); { Prevents the relocatable block }
{ pointed at by PrintRecord from }
{ being moved during heap compaction }
{ get four standard system cursors, }
{ plus one custom one }
for Indx := iBeamCursor to watchCursor do begin
CursList[Indx]:=GetCursor(Indx); { read in from system resource }
HLock(Handle(CursList[Indx])) { lock the handle down }
end;
CursList[MyCursor] := GetCursor(MyCursID); { get cursor from resources }
HLock(Handle(CursList[MyCursor])); { and lock it down }
{ set up menus }
MenuList[AM] := GetMenu(ApplMenu);{ read menus in from resource fork }
{ This needs to be done PRIOR to }
{ bringing in the DA's... }
AddResMenu(MenuList[AM],'DRVR'); { pull in all desk accessories from }
{ resource file on disk }
MenuList[FM] := GetMenu(FileMenu);{ All of these menus are read in }
MenuList[EM] := GetMenu(EditMenu);{ from the resource file. They are }
MenuList[OM] := GetMenu(OptnMenu);{ then inserted into the array }
MenuList[TM] := GetMenu(FontMenu);{ MenuList[]...of menu handles }
ExpIncludes := False; { set expand includes flag to false }
{ This flag tells us whether or not }
{ to try and print the include files }
{ associated with a given programs }
{ source listing... }
AddResMenu(MenuList[TM],'FONT'); { pull in all fonts }
FontItem := 2; { choose second font in list as the }
{ default font... }
DoFontMenu(FontItem); { post the menu of fonts with the }
{ second one checked... }
MenuList[SM] := GetMenu(SizeMenu);{ get font size menu from resource }
{ file... }
SizeItem := 3; { let the 3rd size be checked... }
DoSizeMenu(SizeItem); { post menu with size checked... }
for Indx := 1 to MenuCnt do { place menus in menu bar }
InsertMenu(MenuList[Indx],0);
DrawMenuBar; { draw updated menu bar to screen }
{ set up window stuff }
{ To use the Window Manager, you must have previously called InitGraf }
{ to initialize QuickDraw and InitFonts to initialize the Font Mgr... }
{ The first Window Manager routine to call is the initialization rou- }
{ tine InitWindows, which draws the desktop and the (empty) menu bar. }
{ InitWindows initializes the Window Manager, creating the Window }
{ Manager port. GetWMgrPort returns a pointer to this port... }
GetWMgrPort(ScreenPort); { get grafport for all windows }
SetPort(ScreenPort); { and keep handy just in case }
MainPtr := GetNewWindow(MainID,@MainRec,POINTER(-1)); { get window }
SetPort(MainPtr); { set window to current graf port }
SelectWindow(MainPtr); { and make window active }
FrontWindow := MainPtr; { remember that it's in front }
MainPeek := WindowPeek(MainPtr); { get pointer to window record }
MainPeek^.windowKind := UserKind; { set window type = user kind (ID=8) }
ScreenArea := screenBits.Bounds; { get size of screen (don't assume) }
Quit := False; { set program terminator to false }
SetCursor(CursList[myCursor]^^); { bring up my cursor }
ShowCursor; { turn it back on }
end; { of proc Initialize }
begin
Initialize; { Initialize all of the managers }
PrOpen; { open the print manager }
if PrError = noErr then { if no error then go handle events }
begin
EventHandler; { Start handling Events }
PrClose; { close the print manager }
PrDrvrClose; { close driver opened by PrOpen... }
end
else { else, print manager error }
PrinterError; { display error messageand exit }
end.
]End-of-file enountered...
--
Eric Geoffrey Vann
Analysts International (Chicago Branch)
(312) 882-4673
..!ihnp4!aicchi!egv
Technical Details
Message-ID:
<878@aicchi.UUCP>Path:
arc1-ca.pugleaf.net!utzoo!mnetor!seismo!rutgers!clyde!cuae2!ihnp4!aicchi!egvReferences:
<875@aicchi.UUCP>Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: arc1-ca.pugleaf.net!utzoo!mnetor!seismo!rutgers!clyde!cuae2!ihnp4!aicchi!egv From: egv@aicchi.UUCP (Vann) Newsgroups: comp.sys.mac Subject: Re: Print Manager Info Message-ID: <878@aicchi.UUCP> Date: Thu, 18-Dec-86 23:38:51 EST Article-I.D.: aicchi.878 Posted: Thu Dec 18 23:38:51 1986 Date-Received: Sat, 20-Dec-86 00:08:46 EST References: <875@aicchi.UUCP> Organization: Analysts International Corp; Chicago Branch Lines: 704