home *** CD-ROM | disk | FTP | other *** search
- Program HerschelCatalogDataBase (Input,Output);
-
- { This program is a simple data base manager for the Herschel catalog of
- deep sky objects, for amateur astronomers. }
-
- {$C-} { No user breaks - to speed screen output }
-
- Const
- NumberOfRecords = 2510; { Number of records currently in the data file }
- NumberOfConstellations = 88; { Serpens is treated as a single constellation }
- NumberOfSelectionSets = 9; { Used with the merge option - more than enough }
- Heading : String[70] = { The typed constant generates less object code }
- ' H Class RNGC R.A. Dec. Mag. Type Const';
-
- Type
- HRecord = Record { The main record description used throughout the program }
- HClass : Byte; { Byte types are used to save file space }
- HNum : Integer; { But some fields go over the 0..255 limit }
- NGC : Integer;
- RAHrs : Byte;
- RAMins : Byte;
- RASecs : Byte;
- DecDeg : Integer;
- DecMin : Integer; { A neg. DecMin value is used to indicate }
- Mag : Byte; { objects of Dec. 0d.,Xm. which are south }
- Class : Byte; { of the equator by X mins. (needed 'cause }
- Con : Byte; { you can't have a DecDeg integer with a }
- End; { Record } { value of -0) }
-
- { The following structure is used to build a linked-list which holds the
- entire data file while the program runs. This linked structure is used
- because there is not enough memory left in the data segment for an array. }
-
- HRecordPointer = ^HElement;
- HElement = Record
- Data : HRecord;
- Next : HRecordPointer;
- End; { Record }
-
- { The following record is used for calling DOS interrupts }
- Register = Record
- AX,BX,CX,DX,Bp,SI,DI,DS,ES,Flags: Integer;
- End; { Record }
-
- HClassSet = Set Of 1..8; { Set used in selecting H classes }
- HTypeSet = Set Of 1..7; { Set used in selecting object types }
- Cons = 0..NumberOfConstellations; { Range of constellation indices }
- ConNames = Array[Cons] Of String[3];
- { ConNames is the type description of the "Names" typed constant below }
- Types = Array[1..7] Of String[16];
- { Types is the type description of the "TypeNames" typed constant below }
- Classes = Array[1..8] Of String[4];
- { Classes is the type description of the "TypeNames" typed constant below }
- ObjectType = Array[1..7] Of Char;
- { ObjectType is the type description of the "ObjectTypes" typed constant }
- HArray = Array[1..NumberOfRecords] Of HRecord;
- PromptString = String[32]; { Parameter type for procedure GetInteger }
-
- SelectionSetType = Record { Used to hold user's selections }
- ClassSet : HClassSet;
- TypeSet : HTypeSet;
- LowNGC : Integer;
- HighNGC : Integer;
- LowRAHr : Integer;
- HighRAHr : Integer;
- LowRAMin : Integer;
- HighRAMin : Integer;
- LowDecDeg : Integer;
- HighDecDeg : Integer;
- LowDecMin : Integer;
- HighDecMin : Integer;
- LowMag : Real;
- HighMag : Real;
- Constel : Array[Cons] Of Boolean;
- End; { Record }
-
- { Misc. typed constants follow }
-
- Const
- { Typed constant array of constellation names (official abbreviations) }
- Names : ConNames=(' ','And','Ant','Aps','Aqr','Aql','Ara','Ari','Aur',
- 'Boo','Cae','Cam','Cnc','CVn','CMa','CMi','Cap','Car','Cas','Cen','Cep',
- 'Cet','Cha','Cir','Col','Com','CrA','CrB','Crv','Crt','Cru','Cyg','Del',
- 'Dor','Dra','Equ','Eri','For','Gem','Gru','Her','Hor','Hya','Hyi','Ind',
- 'Lac','Leo','LMi','Lep','Lib','Lup','Lyn','Lyr','Men','Mic','Mon','Mus',
- 'Nor','Oct','Oph','Ori','Pav','Peg','Per','Phe','Pic','Psc','PsA','Pup',
- 'Pyx','Ret','Sge','Sgr','Sco','Scl','Sct','Ser','Sex','Tau','Tel','Tri',
- 'TrA','Tuc','UMa','UMi','Vel','Vir','Vol','Vul');
-
- { Names of object types used for display }
- TypeNames : Types = ('Open Cluster ','Globular Cluster',
- 'Diffuse Nebula ','Planetary Nebula','Galaxy ','Cluster/Nebula ',
- 'Nonexistant ');
-
- { Object type abbreviations used for display }
- ObjectTypes : ObjectType = ('O','C','D','P','G','/','N');
-
- { Typed constant array of Herschel classes in Roman numeral form }
- ClassNames : Classes = (' I',' II',' III',' IV',' V',' VI',
- ' VII','VIII');
-
- Var { Misc. global variables }
- SelectionFile : File Of HRecord; { See procedure Inp }
- FirstPosition,CurrentPosition : HRecordPointer;
- SelectArray : HArray; { User's selected data }
- Row,Col,SelectPointer,LowNGC,HighNGC,LowDecDeg,EndOfArray,VideoOfs,
- HighDecDeg,LowDecMin,HighDecMin,InCount,Index,LowRAHr,HighRAHr,
- LowRAMin,HighRAMin,SelectionSetIndex,SetChoice,DisplayIndex : Integer;
- LowMag,HighMag,CurrentEpoch,StartTime,FinishTime : Real;
- Constel,TrueConArray : Array[Cons] Of Boolean;
- { The Constel array flags each constellation as selected or not }
- Object : HRecord; { The variable used to hold the current record }
- SortField,Ch : Char; { Variables used for reading key presses }
- OK,AllOK,EndOfInput,Done,Selected,NewSelection,Expanding,Merging,
- DiskInput : Boolean;
- CurrentSelectionSet : SelectionSetType; { See proc. Inp }
- SelectionSetArray : Array[1..NumberOfSelectionSets] Of SelectionSetType;
- Device : Text; { Procedure WriteALine writes to this file (screen or print) }
- ClassSet : HClassSet; { These 2 sets for object selection }
- TypeSet : HTypeSet;
-
- Procedure MemoryWrite(Ch: Char);
- { This procedure is a user-written I/O driver for screen output. It writes
- output directly to screen memory. This makes screen output much faster.
- Procedure View activates this driver, and de-activates it before returning
- to the main menu. }
- Const
- VideoSeg = $B000; { Video memory segment address }
- Var
- SChar : Integer;
- Begin { Procedure MemoryWrite }
- If Ch = #13 Then { Test for carriage return }
- Begin { Then }
- Row := Succ(Row); { Adjust row & col for new line }
- Col := 0;
- End { Then }
- Else
- Begin { Else }
- Col := Succ(Col); { New column for each character }
- SChar := ((Row-1)*160) + ((Col-1)*2); { Compute starting location }
- Mem[VideoSeg:VideoOfs + SChar] := Ord(Ch); { Put character in memory }
- End; { Else }
- End; { Procedure MemoryWrite }
-
- Procedure WaitForSpace; { Wait until user presses space bar }
- Begin { Procedure WaitForSpace }
- Repeat
- Read(Kbd,Ch);
- Until Ch = ' ';
- End; { Procedure WaitForSpace }
-
- Function Time: Real; { Get system time for calculating program run time }
- Var
- RecPack: Register;
- Ah,Al,Ch,Cl,Dh : Byte;
- Begin { Function Time }
- Ah := $2c; { Initial value before DOS call }
- With RecPack Do
- Ax := Ah Shl 8 + Al; { Prepare register value for interrupt }
- Intr($21,RecPack); { Ask DOS for the time }
- With RecPack Do { Calculate time in seconds }
- Time := (Cx Shr 8) * 3600.0 + (Cx Mod 256) * 60.0 + (Dx Shr 8);
- End; { Function Time }
-
- Procedure Terminate;
- { This procedure is called when the user Quits the program }
- Var
- ActiveTime,ActiveHours,ActiveMinutes,ActiveSeconds : Real;
- Begin { Procedure Terminate }
- If DiskInput Then { Selection file is open - close it }
- Close(SelectionFile);
- Window(1,1,80,25); { Restore full screen window }
- ClrScr; { Leave the DOS level screen uncluttered except for final message }
- FinishTime := Time; { Used To determine program run time }
- If FinishTime < StartTime Then
- FinishTime := FinishTime + 86400.0; { Add 24 hours after midnight }
- ActiveTime := FinishTime - StartTime; { Program run time in seconds }
- ActiveHours := Int(ActiveTime / 3600);
- ActiveMinutes := Int((ActiveTime - ActiveHours * 3600) / 60);
- ActiveSeconds := ActiveTime - ActiveHours * 3600 - ActiveMinutes * 60;
- Write('Hbase active for ');
- If ActiveHours > 0 Then
- If ActiveHours > 1 Then
- Write(ActiveHours:2:0,' hours ')
- Else
- Write(ActiveHours:2:0,' hour ');
- If ActiveMinutes > 0 Then
- If ActiveMinutes > 1 Then
- Write(ActiveMinutes:2:0,' minutes ')
- Else
- Write(ActiveMinutes:2:0,' minute ');
- If ActiveSeconds > 1 Then
- Write(ActiveSeconds:2:0,' seconds')
- Else
- Write(ActiveSeconds:2:0,' second');
- Writeln(' - returning to DOS ...');
- End; { Procedure Terminate }
-
- {$I SORT.BOX} { Include Borland's SORT.BOX toolbox include file }
-
- Procedure AssignSelections(AssignIndex : Integer);
- { Assign the raw selection variables to an element of the SelectionSetArray }
- Begin { Procedure AssignSelections }
- If AssignIndex < 10 Then { Valid index - proceed }
- Begin { Then }
- SelectionSetArray[AssignIndex].ClassSet := ClassSet;
- SelectionSetArray[AssignIndex].TypeSet := TypeSet;
- SelectionSetArray[AssignIndex].LowNGC := LowNGC;
- SelectionSetArray[AssignIndex].HighNGC := HighNGC;
- SelectionSetArray[AssignIndex].LowRAHr := LowRAHr;
- SelectionSetArray[AssignIndex].HighRAHr := HighRAHr;
- SelectionSetArray[AssignIndex].LowRAMin := LowRAMin;
- SelectionSetArray[AssignIndex].HighRAMin := HighRAMin;
- SelectionSetArray[AssignIndex].LowDecDeg := LowDecDeg;
- SelectionSetArray[AssignIndex].HighDecDeg := HighDecDeg;
- SelectionSetArray[AssignIndex].LowDecMin := LowDecMin;
- SelectionSetArray[AssignIndex].HighDecMin := HighDecMin;
- SelectionSetArray[AssignIndex].LowMag := LowMag;
- SelectionSetArray[AssignIndex].HighMag := HighMag;
- SelectionSetArray[AssignIndex].Constel := Constel;
- End { Then }
- Else { Index overflow }
- Begin { Else }
- ClrScr;
- Writeln('Too many selection sets selected. The maximum is 9.');
- Writeln('Program will terminate - press space.');
- WaitForSpace; { Let 'em read before calling Terminate }
- Terminate; { Not the best place to stop }
- Halt; { Terminate returns normally }
- End; { Else }
- End; { Procedure AssignSelections }
-
- Procedure ReadList;
- { This procedure supplies a single record of input to procedure Inp (below).
- ReadList reads from the static linked list containing the data file. This
- is the normal source of input when the program begins, or after the user
- has done an initialize. }
- Begin { Procedure ReadList }
- Object := CurrentPosition^.Data; { Place data in Object variable }
- CurrentPosition := CurrentPosition^.Next; { Advance 1 place in the list }
- EndOfInput := CurrentPosition = Nil; { Test for end-of-list }
- End; { Procedure ReadList }
-
- Procedure ReadArray;
- { This procedure supplies a single record of input to procedure Inp (below).
- ReadArray reads from the SelectArray, which contains the user's currently
- selected data. This array is the source of input whenever the user does a
- second select-and-sort without first reinitializing. }
- Begin { Procedure ReadArray }
- Object := SelectArray[SelectPointer]; { Place data in Object variable }
- SelectPointer := Succ(SelectPointer); { Advance 1 place in the array }
- EndOfInput := SelectPointer > EndOfArray; { Test for end-of-array }
- End; { Procedure ReadArray }
-
- Procedure ReadDisk;
- { This procedure supplies a single record of input to procedure Inp (below).
- ReadDisk reads from the HBASE.DAT disk file, which is slow, but possibly
- a user's only choice if he had insufficient free memory to load the data
- catalog into a linked list. }
- Begin { Procedure ReadDisk }
- Read(SelectionFile,Object); { Place data in Object variable }
- EndOfInput := EOF(SelectionFile); { Test for end of file }
- End; { Procedure ReadDisk }
-
- Function ObjectInCurrentSelectionSet : Boolean;
- { This function tests the current object under consideration to see whether
- it passes the tests against the values selcted & stored in the current
- selection set (if you are merging input, then the contents of the
- CurrentSelectionSet variables are being changed in proc. Inp.) }
- Begin { Function ObjectInCurrentSelectionSet }
- ObjectInCurrentSelectionSet := False;
- With Object,CurrentSelectionSet Do
- Begin { With }
- If { This giant if statement is at the heart of the selection process }
- Constel[Con] Then If
- (Class In TypeSet) Then If
- (NGC >= LowNGC) Then If
- (NGC <= HighNGC) Then If
- ((HighRAHr >= LowRAHr) And
- (((RAHrs > LowRAHr) Or
- ((RAHrs = LowRAHr) And
- (RAMins >= LowRAMin))) And
- ((RAHrs < HighRAHr) Or
- ((RAHrs = HighRAHr) And
- (RAMins <= HighRAMin))))) Or
- { The 2nd set of R.A. comparisons are for the "backwards" case
- Of LowRAHr > HighRAHr (to "wrap around" the 0 Hr. line.) }
- ((HighRAHr < LowRAHr) And
- (((RAHrs > LowRAHr) Or
- ((RAHrs = LowRAHr) And
- (RAMins >= LowRAMin))) Or { The "or" lets us select wrapped values }
- ((RAHrs < HighRAHr) Or
- ((RAHrs = HighRAHr) And
- (RAMins <= HighRAMin))))) Then If
- (DecDeg > LowDecDeg) Or
- ((DecDeg = LowDecDeg) And
- (DecDeg >= 0) And
- (DecMin >= LowDecMin)) Or { See comment in Object type desc. }
- ((DecDeg = LowDecDeg) And { concerning neg. DecMin values }
- (DecDeg < 0) And
- (DecMin <= LowDecMin)) Then If
- ((DecDeg < HighDecDeg) Or
- ((DecDeg = HighDecDeg) And
- (DecMin <= HighDecMin))) Then If
- (Mag >= LowMag) Then If
- (Mag <= HighMag) Then If
- (HClass In ClassSet)
- Then
- ObjectInCurrentSelectionSet := True;
- End; { With }
- End; { Function ObjectInCurrentSelectionSet }
-
- Procedure Inp;
- { This procedure is called by the Borland sort routines. This is where
- the program compares each object against the values chosen by the user
- creating selected input to the sort. }
- Var
- GoodObject : Boolean;
- SelectionSetCounter : Byte;
- Begin { Procedure Inp }
- SelectPointer := 1; { See proc. ReadArray }
- CurrentPosition := FirstPosition; { See proc. ReadList }
- EndOfInput := False; { For procs. ReadList & ReadArray }
- EndOfArray := InCount; { For proc. ReadArray }
- InCount := 0; { Var. to keep track of # of currently selected objects }
- { The following code advances the SelectionSetArray Index and stores the
- current selection values in the array so it will be accessable.}
- If (SelectionSetIndex = 0) Or Merging Then { Save values to selection set }
- SelectionSetIndex := Succ(SelectionSetIndex);
- AssignSelections(SelectionSetIndex); { In any case, we must save values }
- If DiskInput Then { Prepare to read from disk }
- Reset(SelectionFile); { Assigned in proc. Initialize }
- Writeln('Reading and selecting input data'); { Look familiar? }
- Repeat { Loop to extract all valid input to sort }
- If Expanding Or (Not Selected) Then
- If DiskInput Then
- ReadDisk { Insufficient memory for in-memory operation }
- Else
- ReadList { All new input required - get it from linked list }
- Else { Else we are selecting from pre-sorted data - use SelectArray }
- ReadArray;
- SelectionSetCounter := 0;
- GoodObject := False;
- Repeat { Loop to compare current object against all selections }
- SelectionSetCounter := Succ(SelectionSetCounter); { Check all sets }
- CurrentSelectionSet := SelectionSetArray[SelectionSetCounter];
- GoodObject := ObjectInCurrentSelectionSet; { & look no further }
- Until (SelectionSetCounter = SelectionSetIndex) Or GoodObject;
- If GoodObject Then
- Begin { Then }
- SortRelease(Object); { Release object to Borland's sort }
- InCount := Succ(InCount); { Keep count of objects selected }
- End; { Then }
- Until EndOfInput; { Set in procs. ReadList, ReadArray & ReadDisk }
- Selected := True; { User is creating a select array }
- Merging := False; { So further sorts don't increment SelectionSetIndex }
- Expanding := False; { Either from merge or manual toggle }
- Writeln(Incount,' records input to sort');
- Writeln('Sorting'); { You'll stare at this line during the actual sort }
- End; { Procedure Inp }
-
- Procedure Outp;
- { This procedure takes the output from the sort and writes it to the select
- array. This is the array on which all further operations will operate,
- until the user "initializes". This procedure is called from Borland's sort
- routines. }
- Begin { Procedure Outp }
- Writeln('Writing selected output data'); { The last sort screen message }
- For Index := 1 To Incount Do
- Begin { For }
- SortReturn(Object); { Return records in order from Borland's sort }
- SelectArray[Index] := Object; { Put 'em in the SelectArray }
- End; { For }
- End; { Procedure Outp }
-
- Function Less; { Foward declared from the include file as type boolean }
- { This procedure is called by the Borland sort routines. Here is where the
- actual comparison process for the sort takes place. The case statement
- controls the fields sorted on, depending on the user's choice.
- Note how multiple sort fields are used: R.A. is really R.A. Seconds within
- R.A. minutes within R.A. hours, and many fields use R.A. as a default
- secondary sort field. }
- Var
- FirstObject : HRecord Absolute X; { Records are passed to Borland's sort }
- SecondObject : HRecord Absolute Y; { by these absolute variables. }
- Begin { Function Less }
- Case SortField Of { The same char. the user asked for in proc. Sort }
- 'H','h' : Less := (FirstObject.HClass < SecondObject.HClass) Or
- ((FirstObject.HClass = SecondObject.HClass) And
- (FirstObject.HNum < SecondObject.HNum));
- 'N','n' : Less := FirstObject.NGC < SecondObject.NGC;
- 'R','r' : Less := (FirstObject.RAHrs < SecondObject.RAHrs) Or
- ((FirstObject.RAHrs = SecondObject.RAHrs) And
- (FirstObJect.RAMins < SecondObject.RAMins)) Or
- (((FirstObject.RAHrs = SecondObject.RAHrs) And
- (FirstObject.RAMins = SecondObject.RAMins) And
- (FirstObject.RASecs < SecondObject.RASecs)));
- 'D','d' : Less := (FirstObject.DecDeg < SecondObject.DecDeg) Or
- ((FirstObject.DecDeg = SecondObject.DecDeg) And
- (FirstObject.DecDeg < 0) And
- (FirstObject.DecMin > SecondObject.DecMin)) Or
- ((FirstObject.DecDeg = SecondObject.DecDeg) And
- (FirstObject.DecDeg >= 0) And
- (FirstObject.DecMin < SecondObject.DecMin));
- 'M','m' : Less := (FirstObject.Mag < SecondObject.Mag) Or
- ((FirstObject.Mag = SecondObject.Mag) And
- ((FirstObject.RAHrs < SecondObject.RAHrs) Or
- ((FirstObject.RAHrs = SecondObject.RAHrs) And
- (FirstObJect.RAMins < SecondObject.RAMins)) Or
- (((FirstObject.RAHrs = SecondObject.RAHrs) And
- (FirstObject.RAMins = SecondObject.RAMins) And
- (FirstObject.RASecs < SecondObject.RASecs)))));
- 'O','o' : Less := (FirstObject.Class < SecondObject.Class) Or
- ((FirstObject.Class = SecondObject.Class) And
- ((FirstObject.RAHrs < SecondObject.RAHrs) Or
- ((FirstObject.RAHrs = SecondObject.RAHrs) And
- (FirstObJect.RAMins < SecondObject.RAMins)) Or
- (((FirstObject.RAHrs = SecondObject.RAHrs) And
- (FirstObject.RAMins = SecondObject.RAMins) And
- (FirstObject.RASecs < SecondObject.RASecs)))));
- 'C','c' : Less := (FirstObject.Con < SecondObject.Con) Or
- ((FirstObject.Con = SecondObject.Con) And
- ((FirstObject.RAHrs < SecondObject.RAHrs) Or
- ((FirstObject.RAHrs = SecondObject.RAHrs) And
- (FirstObJect.RAMins < SecondObject.RAMins)) Or
- (((FirstObject.RAHrs = SecondObject.RAHrs) And
- (FirstObject.RAMins = SecondObject.RAMins) And
- (FirstObject.RASecs < SecondObject.RASecs)))));
- End; { Case }
- End; { Function Less }
-
- Procedure Error(ErrorNumber,ErrorAddress : Integer);
- { This procedure is a user written error handler. }
- { It will execute if an error occurs. }
- Begin { Procedure Error }
- ClrScr;
- Writeln('HBASE has crashed.'); { In case the user hadn't noticed }
- Writeln('Error code = ',ErrorNumber);
- Writeln('Address of error = ',ErrorAddress);
- Writeln('Consult the Turbo Pascal manual for explanation.');
- Halt; { Stop the program "manually" after reporting error }
- End; { Procedure Error }
-
- Procedure InitializeVariables;
- { This procedure initializes various variables to their origional state. It
- is called from procedure Initialize when the program first begins, and is
- also the procedure called by the initialize option from the main menu. }
- Begin { Procedure InitializeVariables }
- Selected := False; { No data selected yet - can't precess }
- CurrentEpoch := 1975.0; { The epoch of the data file }
- SortField := ' ';
- { The rest of the statements assign values to the selection variables that
- will select for all possible objects. Thus, you get everything until you
- narrow down these values in the selection procedures. }
- ClassSet := [1..8];
- TypeSet := [1..7];
- LowNGC := 0;
- HighNGC := 8000;
- LowRAHr := 0;
- HighRAHr := 24;
- LowRAMin := 0;
- HighRAMin := 0;
- LowDecDeg := -90;
- HighDecDeg := 90;
- LowDecMin := 0;
- HighDecMin := 0;
- LowMag := 0.0;
- HighMag := 170.0;
- Constel := TrueConArray; { Each element = true, all const. selected }
- End; { Procedure InitializeVariables }
-
- Procedure Tab(NumberOfSpaces : Byte);
- { Tab over a number of spaces rather than writing space constants }
- Begin { Procedure Tab }
- GoToXY(WhereX + NumberOfSpaces,WhereY);
- End; { Procedure Tab }
-
- Procedure WriteTitleScreen;
- { Please leave this in place - I don't ask for money - just my name in lights }
- Begin { Procedure WriteTitleScreen }
- Clrscr;
- Writeln; Writeln; Writeln;
- Tab(32); Writeln('║ ║ ');
- Tab(32); Writeln('╠═══╣ ');
- Tab(32); Writeln('║ ║ B A S E');
- Writeln; Writeln; LowVideo;
- Tab(13); Writeln('A project in amateur astronomy by G. Dean Williams');
- Writeln;
- Tab(14); Writeln('Data by Sir William Herschel and Dennis Donnelly');
- GoToXY(62,25); Write('Version 08 Mar. 87');
- End; { Procedure WriteTitleScreen }
-
- Procedure GetScreenType;
- { This procedure determines whether the system uses a monochrome or color
- screen. This information is needed in procedure memorywrite. }
- Var
- Registers : Register;
- Result : Integer;
- ScreenType : Byte;
- Begin { Procedure GetScreenType }
- INTR($11,Registers); { Interrupt to return screen type }
- Result := Registers.AX; { The raw result is in register AX }
- ScreenType := (Result Shl 10 ) Shr 14; { Extract screen type from result }
- If ScreenType = 2 Then
- VideoOfs := $8000 { Color system }
- Else
- VideoOfs := $0000; { Monochrome system }
- End; { Procedure GetScreenType }
-
- Procedure Initialize;
- { This procedure is called from the main program when the program starts.
- It initializes a few necessary variables. }
- Var
- InFile : File Of HArray;
- ConIndex : Byte;
- Begin { Procedure Initialize }
- StartTime := Time; { Used to calculate program run time }
- WriteTitleScreen;
- ErrorPtr := Ofs(Error); { Activate the error handler procedure }
- AuxOutPtr := ConOutPtr; { Save ConOutPtr }
- GetScreenType; { Monochrome or color system? }
- Done := False; { See main program block }
- For ConIndex := 0 To NumberOfConstellations Do { Used to select all cons }
- TrueConArray[ConIndex] := True;
- InitializeVariables; { The same proc. called from the main menu }
- Merging := False; { Can't do this in InitializeVariables - catch 22 }
- Expanding := False; { Same here }
- NewSelection := False;
- SelectionSetIndex := 0;
- InCount := 0; { Nothing is selected/sorted yet }
- Assign(InFile,'HBASE.DAT');
- {$I-} Reset(Infile); {SI+} { I/O checking in case it isn't there }
- If IOResult <> 0 Then { I/O error - file not found }
- Begin { Then }
- ClrScr; { The title screen just became unimportant }
- Write(^G); { Ring bell to alert user to error }
- Writeln('ERROR! - The file HBASE.DAT must be present in the current');
- Writeln('directory of the current drive. Replace disk & type "R" to');
- Write('retry, or type "H" to halt execution: ');
- Repeat
- Read(Kbd,Ch);
- Until Upcase(Ch) In ['R','H'];
- If Upcase(Ch) = 'R' Then
- Reset(InFile) { No I/O checking - last chance }
- Else
- Halt; { Not good to have to stop while initializing! }
- End; { Then }
- Read(InFile,SelectArray); { Load the select array with one big disk read }
- Close(InFile);
- DiskInput := False;
- If MemAvail < 4500 Then { Not enough memory to run the program }
- Begin { Then }
- Clrscr;
- Write(^G); { Ring bell to alert user to error }
- Writeln('Insufficient free memory. HBASE requires at least 200K of');
- Writeln('free memory to run free of disk I/O. You may remove any');
- Writeln('memory resident software & type "H" to halt execution for');
- Writeln('a re-boot, or you may type "D" to run the program from disk');
- Write('Your choice: ');
- Repeat
- Read(Kbd,Ch);
- Until Upcase(Ch) In ['H','D'];
- If Upcase(Ch) = 'D' Then
- DiskInput := True
- Else
- Begin { Else }
- Terminate; { Just to get run time & ending message }
- Halt; { Hopefully in preparation for re-boot }
- End; { Else }
- End { Then }
- Else
- Begin { Else }
- New(FirstPosition); { Starting place for linked list }
- CurrentPosition := FirstPosition; { Start at the start }
- For Index := 1 To NumberOfRecords - 1 Do
- Begin { For loop to load the linked list from the select array }
- CurrentPosition^.Data := SelectArray[Index]; { Load object to list }
- New(CurrentPosition^.Next); { Increment position in liked list }
- CurrentPosition := CurrentPosition^.Next; { Increment Position }
- End; { For }
- CurrentPosition^.Data := SelectArray[NumberOfRecords]; { Last object }
- CurrentPosition^.Next := Nil; { The last entry points nowhere }
- End; { Else }
- InCount := NumberOfRecords; { All objects are selected & sorted by H # }
- If DiskInput Then { Open the data file for duration of run }
- Assign(SelectionFile,'HBASE.DAT'); { We will close at end of run }
- End; { Procedure Initialize }
-
-
- Procedure Sort;
- { This procedure contains the sort menu, chosen from the main menu }
- Var
- SortFieldHold : Char;
- SortResult : Integer;
- Begin { Procedure Sort }
- ClrScr;
- Window(20,1,80,25); { Center sort menu screen }
- Ch := 'Y'; { In case we skip the following read }
- If ((InCount >= NumberOfRecords) And (Not NewSelection))
- Or (Not (Selected Or NewSelection) And (InCount = 0)) Then
- Begin { Then }
- Writeln;
- Write('Really sort the entire catalog? (Y/N): ');
- Repeat { Outer loop to catch those damn escape codes }
- Repeat
- Read(Kbd,Ch);
- Until Upcase(Ch) In ['Y','N',#27];
- If (Ch = #27) And Keypressed Then { Trap escape codes }
- Begin { Then }
- Read(Kbd,Ch); { Read 2nd char of escape code }
- Ch := 'a'; { Look out for escape code with "y" or "n" }
- End; { Then }
- Until Upcase(Ch) In ['Y','N'];
- Writeln(Ch);
- End; { Then }
- If Upcase(Ch) = 'Y' Then { We are going to sort - proceed }
- Begin { Then }
- { The next line saves SortField in case it gets clobbered with "Q" }
- SortFieldHold := SortField;
- Writeln;
- Writeln('You can sort on the following fields:');
- Writeln;
- HighVideo; Write(' H'); LowVideo; Writeln('erschel Class');
- HighVideo; Write(' N'); LowVideo; Writeln('GC Number');
- HighVideo; Write(' R'); LowVideo; Writeln('ight Ascension');
- HighVideo; Write(' D'); LowVideo; Writeln('eclination');
- HighVideo; Write(' M'); LowVideo; Writeln('agnitude');
- HighVideo; Write(' O'); LowVideo; Writeln('bject Type');
- HighVideo; Write(' C'); LowVideo; Writeln('onstellation');
- Writeln;
- Write('Type a letter to sort or "Q" to quit to previous screen: ');
- Repeat { Outer loop to catch unwanted escape codes }
- Repeat
- Read(Kbd,SortField);
- Until Upcase(SortField) In ['H','N','R','D','M','O','C','Q',#27];
- If (SortField = #27) And Keypressed Then { Trap out escape codes }
- Begin { Then }
- Read(Kbd,SortField); { Get 2nd char of escape code }
- SortField := 'a'; { So it isn't a sort field character }
- End; { Then }
- Until Upcase(SortField) In ['H','N','R','D','M','O','C','Q'];
- HighVideo; Writeln(SortField); LowVideo;
- Writeln;
- If Upcase(SortField) <> 'Q' Then { A real sort field was entered }
- Begin { Then }
- NewSelection := False; { Selections are being sorted }
- { The call to the actual sort is in the next line }
- SortResult := TurboSort(SizeOf(HRecord)); { Call sort function }
- If SortResult <> 0 Then { Report sort error }
- Begin { Then }
- Writeln('--- Error Occured During Sort ---');
- Case SortResult Of
- 3 : Writeln('Not enough free memory for sorting');
- 10,11 : Writeln('Probable disk I/O error or disk full');
- 12 : Writeln('Disk directory full');
- End; { Case SortResult }
- Write('Press Space To Continue');
- WaitForSpace;
- End; { Then }
- End { Then }
- Else { The user did a "Q", so restore SortField }
- SortField := SortFieldHold;
- End; { Then }
- End; { Procedure Sort }
-
- Procedure WriteALine;
- { This procedure writes a single line of output, either to the screen,
- or to the printer. It is called by procedures List and View. }
- Var
- RealMag : Real;
- Begin { Procedure WriteALine }
- With Object Do
- Begin { With }
- Write(Device,' ',ClassNames[HClass],'-');
- { Classnames are the roman numeral classes stored in ClassNames array }
- If HNum < 10 Then { We must test for & print all leading zeros so }
- Write(Device,'00') { that all field columns line up evenly. }
- Else
- If HNum < 100 Then
- Write(Device,'0');
- Write(Device,HNum,' ');
- If NGC < 10 Then
- Write(Device,'000')
- Else
- If NGC < 100 Then
- Write(Device,'00')
- Else
- If NGC < 1000 Then
- Write(Device,'0');
- Write(Device,NGC,' ');
- If RAHrs < 10 Then
- Write(Device,'0');
- Write(Device,RAHrs,'/');
- If RAMins < 10 Then
- Write(Device,'0');
- Write(Device,RAMins,'/');
- If RASecs < 10 Then
- Begin { Then }
- Write(Device,'0');
- Write(Device,RASecs:1,' ');
- End { Then }
- Else
- Write(Device,RASecs:2,' ');
- If (DecDeg < 0) Or (DecMin < 0) Then
- Write(Device,'-')
- Else
- Write(Device,' ');
- DecDeg := Abs(DecDeg); { We print neg. sign manually }
- If Decdeg < 10 Then
- Begin { Then }
- Write(Device,'0');
- Write(Device,DecDeg,'/');
- End { Then }
- Else
- Write(Device,DecDeg,'/');
- DecMin := Abs(DecMin); { See note in HRecord type description }
- If DecMin < 10 Then
- Write(Device,'0');
- Write(Device,DecMin,' ');
- RealMag := Mag;
- RealMag := RealMag / 10; { Magnitudes are all multiplied by 10 so }
- If RealMag < 10 Then { they can be stored as bytes & save space }
- Begin { Then }
- Write(Device,'0');
- Write(Device,RealMag:3:1,' ');
- End { Then }
- Else
- Write(Device,RealMag:4:1,' ');
- Write(Device,TypeNames[Class]);
- Write(Device,' ',Names[Con],#13); { Write carriage return at end }
- End; { With }
- End; { Procedure WriteALine }
-
- Procedure List;
- { This procedure sends the selected data to the printer }
- Const
- FormFeed = #12;
- Var
- NumberOfReports,CopyCount,LineCount : Byte;
- Begin { Procedure List }
- If NewSelection Then
- Sort; { User cannot list data until it is sorted }
- Assign(Device,'Lst:'); { So WriteALine will write to printer }
- Reset(Device);
- If InCount > 0 Then { There is something selected to print }
- Begin { Then }
- NumberOfReports := 1; { Default so user can just hit enter for 1 }
- Writeln;
- Repeat { Loop to get # of listings }
- Write('Enter desired number of copies (default is 1): ');
- {$I-} Readln(NumberOfReports) {$I+};
- OK := (IoResult = 0) And (NumberOfReports > 0) And
- (NumberOfReports < 251);
- If Not OK Then
- Write(^G); { Ring bell to alert user to entry error }
- If NumberOfReports > 250 Then
- Writeln('The maximum number of listings is 250!');
- Writeln;
- Until OK;
- ClrScr;
- Writeln('Ready printer and press space to proceed');
- Writeln('You can type "Q" at any time to stop printing ');
- WaitForSpace;
- CopyCount := 0;
- Repeat { Loop for number of copies }
- CopyCount := Succ(CopyCount);
- GotoXY(1,4); { So object count will stay put between copies }
- Writeln('List of selected objects going to printer.');
- For LineCount := 1 To 3 Do
- Writeln(Lst);
- Writeln(Lst,' ',Heading);
- Writeln(Lst);
- LineCount := 5;
- SelectPointer := 0;
- Repeat { Loop for writing all selected objects }
- SelectPointer := Succ(SelectPointer);
- GoToXY(1,5); { Position for the following write statements }
- Write(Succ(InCount) - SelectPointer,' objects left to print');
- Write(' on copy ',CopyCount,' of ',NumberOfReports,'. ');
- If KeyPressed Then
- Begin { Then }
- Read(Kbd,Ch); { Get the character }
- If (Ch = #27) And Keypressed Then { Extended scan code? }
- Begin { Then }
- Read(Kbd,Ch); { Get 2nd character of scan code }
- Ch := 'a'; { Trap unwanted "Q"s }
- End; { Then }
- If Upcase(Ch) = 'Q' Then
- SelectPointer := Incount; { Skip to end of list to stop }
- End; { Then }
- Object := SelectArray[SelectPointer]; { Get object to print }
- WriteALine; { Write it to Lst: device }
- Write(Lst,#10); { Line feed after carriage return from WriteALine }
- LineCount := Succ(LineCount); { Keep count of print lines }
- If LineCount > 62 Then { Time for new page }
- Begin { Then }
- Write(Lst,FormFeed); { Form Feed At End Of Each Page }
- For LineCount := 1 To 3 Do
- Writeln(Lst);
- Writeln(Lst,' ',Heading);
- Writeln(Lst);
- LineCount := 5; { Adjust for heading lines }
- End; { Then }
- Until SelectPointer = Incount; { The last object }
- Write(Lst,FormFeed); { Final form feed between copies }
- Until (CopyCount = NumberOfReports) Or (Upcase(Ch) = 'Q');
- End { Then }
- Else
- Begin { Else }
- ClrScr; { So we don't scroll off main menu messages }
- Write('No objects to list - Press Space To Continue ');
- WaitForSpace;
- End; { Else }
- End; { Procedure List }
-
- Procedure View;
- { This procedure contains the on-screen editor code }
- Const
- Escape = #27;
- Var
- PagePointer : Integer;
- MaxDetailLines,Count : Byte;
- FunKey,TopOfList,BottomOfList : Boolean;
-
- Procedure WriteScreen;
- { This procedure is contained in, and is called by procedure view. It's
- purpose is to write a screenful of output on the screen. }
- Begin { Procedure WriteScreen }
- ClrScr;
- MaxDetailLines := 23; { Maximum detail lines on the view screen }
- TopOfList := (PagePointer = 0);
- If TopOfList Then { Write ** Top Of List ** message at top }
- MaxDetailLines := Pred(MaxDetailLines); { Leave space for message }
- BottomOfList := (InCount - PagePointer < MaxDetailLines);
- If BottomOfList Then { Write ** Bottom Of List message at bottom }
- MaxDetailLines := Pred(MaxDetailLines); { Leave space for message }
- If InCount = 22 Then
- MaxDetailLines := 21; { Don't write all 22 lines without message }
- Row := 1; { For procedure MemoryWrite }
- Col := 1;
- Write(' Seq.',Heading,#13,#13); { Heading, CR, and & blank line }
- If TopOfList Then
- Write(' ***** Top Of List *****',#13);
- Count := 0;
- While (Count < MaxDetailLines) And (PagePointer + Count < InCount) Do
- Begin { While loop to write a screenful of object lines }
- Count := Succ(Count); { Index for SelectArray }
- Object := SelectArray[PagePointer + Count]; { Get object to list }
- Write(' ',PagePointer + Count:4); { Sequence # for listing }
- WriteALine; { Write object to Con: device }
- End; { While }
- If BottomOfList Then
- Write(' ***** Bottom Of List *****',#13);
- End; { Procedure WriteScreen }
-
- Procedure ViewHelp; { Display the viewer on-line help info }
- Begin { Procedure ViewHelp }
- Row := 1; { For procedure memorywrite }
- Col := 1;
- ClrScr;
- Write(#13); { This writes a blank line }
- Write('While in the viewer, the following keys apply:',#13,#13);
- Write('F1 : Display this viewer help information.',#13);
- Write('Page Up / Page Down.',#13);
- Write('Home : to top of list.',#13);
- Write('End : to end of list.',#13);
- Write('"S" : seek record of a given sequence number.',#13);
- Write('"E" : skip halfway from current position to end of file.',#13);
- Write('"B" : skip halfway from current position to beginning of file.');
- Write(#13,'"Q" : quit the viewer and return to the main menu.',#13);
- Write(#13);
- Write('Press the space bar to return to the view screen',#13);
- WaitForSpace;
- End; { Procedure ViewHelp }
-
- Begin { Procedure View }
- If NewSelection Then
- Sort; { User cannot view data until it is sorted }
- ConOutPtr := Ofs(MemoryWrite); { Activate screen output driver }
- Assign(Device,'Con:'); { So WriteALine will write to the screen }
- Reset(Device);
- FunKey := False; { A cursor control key has not been pressed }
- Window(1,1,80,25); { Set window size to entire screen }
- If InCount > 0 Then { There is something selected to view }
- Begin { Then }
- PagePointer := 0; { Index to top of SelectArray }
- WriteScreen; { Write initial screenful of output }
- Repeat { Accept keyboard input until user "q"uits }
- Repeat
- Read(Kbd,Ch);
- FunKey := (Ch = Escape) And KeyPressed;
- Until FunKey Or (Upcase(Ch) In ['Q','B','E','S']);
- If FunKey And (InCount > 21) Then { Respond to edit keys }
- Begin { Then }
- Read(Kbd,Ch); { Get 2nd character of code }
- Case Ch Of
- #59 : Begin { Case F1 (help) }
- ViewHelp;
- WriteScreen;
- End; { Case F1 }
- #71 : Begin { Case home }
- PagePointer := 0; { Top of list }
- WriteScreen;
- End; { Case home }
- #79 : Begin { Case end }
- PagePointer := (InCount - 22); { Bottom of list }
- If PagePointer < 0 Then
- PagePointer := 0;
- If InCount = 22 Then { Special case for TOL message }
- PagePointer := 1;
- WriteScreen;
- End; { Case end }
- #73 : Begin { Case page up }
- PagePointer := PagePointer - 23; { Up in list }
- If PagePointer < 0 Then { Exceeded top of list }
- PagePointer := 0; { Top }
- WriteScreen;
- End; { Case page up }
- #81 : Begin { Case page down }
- PagePointer := PagePointer + MaxDetailLines; { Down }
- If PagePointer > (InCount - 22) Then { Exceeded list }
- Begin { Then }
- PagePointer := (InCount - 22); { Bottom }
- If PagePointer < 0 Then
- PagePointer := 0;
- End; { Then }
- If InCount = 22 Then
- PagePointer := 1;
- WriteScreen;
- End; { Case page down }
- End; { Case }
- Ch := ' '; { Space out values which might be read as input }
- End { Then }
- Else
- If FunKey Then { Incount was < 21 so edit keys were ignored }
- Begin { Then }
- Read(Kbd,Ch); { Get 2nd char of extended scan code }
- If Ch = #59 Then { User pressed F1 for help }
- Begin { Then }
- ViewHelp; { Display the help info }
- WriteScreen; { After the help info clobbers the screen }
- End; { Case F1 }
- Ch := ' '; { Space out value in Ch }
- End; { Then }
- If (Upcase(Ch) In ['B','E','S']) And (InCount > 21) Then
- Begin { Then } { Skip halfway to beginning or end, }
- Case Ch Of { or skip to a particular sequence }
- 'B','b' : PagePointer := PagePointer Div 2; { 1/2 way to top }
- 'E','e' : Begin { Case E }
- PagePointer := PagePointer +
- (InCount - PagePointer) Div 2; { 1/2 way to end }
- If PagePointer > (InCount - 21) Then
- Begin { Then }
- PagePointer := (InCount - 21);
- If PagePointer < 0 Then
- PagePointer := 0;
- End; { Then }
- End; { Case E }
- 'S','s' : Begin { Case S }
- { Restore standard screen output driver }
- ConOutPtr := AuxOutPtr;
- { The viewer prints 1 object ahead of the }
- { pointer, so we'll add 1 for displaying it }
- PagePointer := Succ(PagePointer);
- ClrScr;
- Repeat { 2 repeat loops to get valid seek # }
- Repeat
- Write('The viewer is currently positioned');
- Writeln(' at sequence # ',PagePointer);
- Write('Enter sequence number between 1 and ');
- Write(InCount,' to seek: ');
- {$I-} Readln(PagePointer); {$I+}
- OK := IOResult = 0;
- If Not OK Then
- Write(^G); { Beep to indicate entry error }
- Writeln;
- Until OK;
- AllOK := (PagePointer >= 1) And
- (PagePointer <= InCount);
- If AllOK Then { Set pointer back for viewer }
- PagePointer := Pred(PagePointer)
- Else
- Write(^G); { Beep to indicate entry error }
- Until AllOK;
- If PagePointer > (InCount - 21) Then
- Begin { Then }
- PagePointer := (InCount - 21);
- If PagePointer < 0 Then
- PagePointer := 0;
- End; { Then }
- { Go back to IO driver for view screen }
- ConOutPtr := Ofs(MemoryWrite);
- End; { Case S }
- End; { Case }
- WriteScreen; { After "B","E", or "S" entry }
- End; { Then }
- Until Upcase(Ch) = 'Q'; { Until user quits the viewer }
- End { Then }
- Else
- Begin { Else }
- ClrScr; { So we don't scroll off main menu messages }
- Row := 1; { Row & col for printing error message }
- Col := 1;
- Write('No objects to view - Press Space To Continue ');
- WaitForSpace;
- ClrScr; { Clear the larger view window before returning to main menu }
- End; { Else }
- ConOutPtr := AuxOutPtr; { Restore standard screen output driver }
- End; { Procedure View }
-
- {$I SELECTS.INC} { Include parameter selection procedures }
-
- Procedure Precess;
- { This procedure precesses the selected data's celestial coordinates to
- another epoch. The algolrithm is taken from Eric Burgess' CELESTIAL BASIC,
- and it is not as accurate as I would like. If you improve on it (even at a
- loss of speed), please let me know, 'cause I could use it myself. }
- Var
- R1,D1,T2,ChangeInRA,ChangeInDec,NewEpoch,
- RealMins,Difference,X,Y,Z,LastYear : Real;
-
- Function Tan (AngleInDegrees : Real): Real;
- { Represents the tangent of its degree-valued argument }
- Var
- Angle : Real;
- Function ConvertToRadians(Angle : Real): Real;
- Begin { Function ConvertToRadians }
- ConvertToRadians := Angle * (Pi / 180);
- End; { Function ConvertToRadians }
- Begin { Function Tan }
- Angle := ConvertToRadians(AngleInDegrees);
- Tan := Sin(Angle) / Cos(Angle);
- End; { Function Tan }
-
- Begin { Procedure Precess }
- If NewSelection Then
- Sort; { User cannot precess data until it is sorted }
- If Selected And (InCount > 0) Then
- Begin { Then }
- ClrScr;
- LastYear := CurrentEpoch;
- Repeat
- Write('Enter the new epoch: ');
- {$I-} Readln(NewEpoch) {$I+};
- OK := (IOResult = 0);
- If Not OK Then
- Write(^G); { Ring bell to alert user to entry error }
- Writeln;
- Until OK;
- ClrScr;
- Writeln('Selected data being precessed to epoch ',NewEpoch:7:2);
- Difference := NewEpoch - LastYear;
- CurrentEpoch := NewEpoch;
- For Index := 1 To InCount Do
- Begin { For }
- Object := SelectArray[Index]; { Get next object to precess }
- With Object Do { Precess it }
- Begin { With }
- R1 := RAHrs + RAMins / 60 + RASecs / 3600;
- D1 := DecDeg + DecMin / 60;
- R1 := R1 * 15;
- T2 := ((LastYear + NewEpoch) / 2 - 1900) / 100;
- X := 3.07234 + (0.00186 * T2);
- Y := 20.0468 - (0.0085 * T2);
- Z := Y / 15;
- ChangeInRA := 0.0042 * Difference *
- (X + (Z * Sin(R1/57.29878) * Tan(D1/57.29878)));
- R1 := R1 + ChangeInRA;
- D1 := D1 + 0.00028 * Difference * Y * Cos(R1 / 57.29878);
- R1 := R1 / 15;
- If R1 > 24 Then
- R1 := R1 - 24;
- If R1 < 0 Then
- R1 := R1 + 24;
- RAHrs := Trunc(Int(R1));
- RealMins := (60 * (R1 - Int(R1)));
- RASecs := Trunc(60 * (RealMins - Int(RealMins)));
- RAMins := Trunc(RealMins);
- If D1 > 90 Then
- D1 := 90 - (D1 - Int(D1));
- DecDeg := Trunc(Int(D1));
- DecMin := Trunc((D1 - Int(D1)) * 60);
- If D1 < 0 Then
- Begin { Then }
- DecDeg := Trunc(Int(D1));
- D1 := Abs(D1);
- DecMin := Trunc(60 * (D1 - Int(D1)));
- End; { Then }
- End; { With }
- SelectArray[Index] := Object; { Put precessed object back }
- End; { For }
- End { Then }
- Else
- Begin { Else }
- If InCount > 0 Then { Selected = False }
- Writeln('No data has been selected for precession')
- Else { Incount = 0 }
- Writeln(' No objects to precess');
- Write (' Press space to continue ');
- WaitForSpace;
- End; { Else }
- End; { Procedure Precess }
-
- {$I HELP.INC} { Include the online help procedure }
-
- Procedure MainMenu;
- { This is the main menu called by the main program }
- Begin { Procedure MainMenu }
- ClrScr;
- Window(11,1,80,25); { Center the main menu screen }
- LowVideo; { Some procedures return in HighVideo mode }
- Writeln;
- If InCount <> 1 Then { Test to keep our grammar correct }
- Writeln('There are currently ',InCount,' objects selected.')
- Else
- Writeln('There is currently 1 object selected.');
- Writeln;
- HighVideo;
- If NewSelection Then { New selections not yet sorted - warn the user }
- Begin { Then }
- Writeln('New selections have not been sorted.');
- Writeln;
- End; { Then }
- If Expanding Then { Notify the user }
- Begin { Then }
- Writeln('Selections are being expanded.');
- Writeln;
- End; { Then }
- If Merging Then { Notify the user }
- Begin { Then }
- Write('Selections are being merged to selection set #');
- If Not Selected Then { SelectionSetIndex is minus 1 }
- Writeln(Succ(SelectionSetIndex))
- Else { It's OK after a sort }
- Writeln(SelectionSetIndex,'.');
- Writeln;
- End; { Then }
- LowVideo;
- Writeln('You can select a sub-listing by:');
- Writeln;
- HighVideo; Write(' H'); LowVideo; Writeln('erschel Class');
- HighVideo; Write(' N'); LowVideo; Writeln('GC Number');
- HighVideo; Write(' R'); LowVideo; Writeln('ight Ascension');
- HighVideo; Write(' D'); LowVideo; Writeln('eclination');
- HighVideo; Write(' B'); LowVideo; Writeln('rightness');
- HighVideo; Write(' O'); LowVideo; Writeln('bject Type');
- HighVideo; Write(' C'); LowVideo; Writeln('onstellation');
- Writeln;
- Write('Type a letter to select, or to ');
- HighVideo; Write('S'); LowVideo; Write('ort, ');
- HighVideo; Write('T'); LowVideo; Write('oggle expansion, ');
- HighVideo; Write('M'); LowVideo; Writeln('erge,');
- HighVideo; Write('E'); LowVideo; Write('xamine status, ');
- HighVideo; Write('I'); LowVideo; Write('nitialize, ');
- HighVideo; Write('V'); LowVideo; Write('iew, ');
- HighVideo; Write('L'); LowVideo; Write('ist, ');
- HighVideo; Write('P'); LowVideo; Write('recess, or ');
- HighVideo; Write('Q'); LowVideo; Writeln('uit.');
- Writeln;
- Write('You may type '); HighVideo; Write('F1 '); LowVideo;
- Writeln('for help.');
- Writeln;
- Write('Your Choice? ');
- Repeat
- Read(Kbd,Ch);
- Until Upcase(Ch) In ['H','N','R','D','M','C','O','E','B',
- #27,'T','I','S','V','L','P','Q'];
- HighVideo; Writeln(Ch); LowVideo;
- Writeln;
- Case Ch Of
- #27 : Begin { Check for PF1 (help) else ignore extended code keys }
- If Keypressed Then
- Read(Kbd,Ch); { Get 2nd character of extended scan code }
- If Ch = #59 Then { PF1 was pressed }
- MainMenuHelp
- Else
- Ch := ' '; { Space out unwanted 2nd character }
- End; { Case escape }
- 'H','h' : SelectH;
- 'N','n' : SelectNGC;
- 'R','r' : SelectRA;
- 'D','d' : SelectDec;
- 'B','b' : SelectMag;
- 'O','o' : SelectType;
- 'C','c' : SelectCon;
- 'L','l' : List;
- 'P','p' : Precess;
- 'V','v' : View;
- 'S','s' : Sort;
- 'E','e' : Begin { Case E }
- If Not Selected Then { SelectionSetIndex is 1 behind }
- Begin { Then }
- DisplayIndex := Succ(SelectionSetIndex);
- AssignSelections(DisplayIndex); { For displaying }
- End { Then }
- Else { Proc. Inp already incremented it to a proper value }
- DisplayIndex := SelectionSetIndex;
- ExamineStatus;
- End; { Case E }
- 'Q','q' : Begin { Case Q }
- Write('Exit to DOS? (Y/N): ');
- Repeat { Loop to catch those damn escape codes }
- Repeat
- Read(Kbd,Ch);
- Until Upcase(Ch) In ['Y','N',#27];
- If (Ch = #27) And Keypressed Then { Escape code pressed }
- Begin { Then }
- Read(Kbd,Ch); { Get 2nd char of escape code }
- Ch := 'a'; { Weed out unwanted "y"s & "n"s }
- End; { Then }
- Until Upcase(Ch) In ['Y','N'];
- Writeln(Ch);
- Done := Upcase(Ch) = 'Y';
- End; { Case Q }
- 'T','t' : Expanding := Not Expanding; { Toggle it }
- 'I','i' : Begin { Case I }
- Merging := False; { Note following 3 seperate assignments }
- Expanding := False;
- NewSelection := False;
- SelectionSetIndex := 0;
- InCount := 0; { Nothing is selected/sorted yet }
- InitializeVariables;
- End; { Then }
- 'M','m' : Begin { Case M }
- Merging := True;
- Expanding := True; { User will have to turn it off }
- If Not selected Then { The sort hasn't incremented index }
- SelectionSetIndex := Succ(SelectionSetIndex);
- AssignSelections(SelectionSetIndex); { Save selections }
- InitializeVariables; { Prepare for next set of selections }
- End; { Case M }
- End; { Case }
- End; { Procedure MainMenu }
-
- Begin { Program }
- Initialize;
- While Not Done Do
- MainMenu;
- Terminate;
- End. { Program }