|  | @@ -0,0 +1,1037 @@
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +Copyright (C) 2005  Remco Mulder
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +This program is free software; you can redistribute it and/or modify
 | 
	
		
			
				|  |  | +it under the terms of the GNU General Public License as published by
 | 
	
		
			
				|  |  | +the Free Software Foundation; either version 2 of the License, or
 | 
	
		
			
				|  |  | +(at your option) any later version.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +This program is distributed in the hope that it will be useful,
 | 
	
		
			
				|  |  | +but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
	
		
			
				|  |  | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
	
		
			
				|  |  | +GNU General Public License for more details.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +You should have received a copy of the GNU General Public License
 | 
	
		
			
				|  |  | +along with this program; if not, write to the Free Software
 | 
	
		
			
				|  |  | +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +For source notes please refer to Notes.txt
 | 
	
		
			
				|  |  | +For license terms please refer to GPL.txt.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +These files should be stored in the root of the compression you 
 | 
	
		
			
				|  |  | +received this source in.
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +// This unit controls all processing and recording of data
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +unit
 | 
	
		
			
				|  |  | +  Process;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +interface
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +uses
 | 
	
		
			
				|  |  | +  Core,
 | 
	
		
			
				|  |  | +  Observer,
 | 
	
		
			
				|  |  | +  SysUtils,
 | 
	
		
			
				|  |  | +  DataBase,
 | 
	
		
			
				|  |  | +  Classes;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +type
 | 
	
		
			
				|  |  | +  TSectorPosition = (spNormal, spPorts, spPlanets, spShips, spMines, spTraders);
 | 
	
		
			
				|  |  | +  TDisplay = (dNone, dSector, dDensity, dWarpLane, dCIM, dPortCIM, dPort, dWarpCIM);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  TModExtractor = class(TTWXModule, IModExtractor)
 | 
	
		
			
				|  |  | +  private
 | 
	
		
			
				|  |  | +    FCurrentSectorIndex : Integer;
 | 
	
		
			
				|  |  | +    FSectorPosition     : TSectorPosition;
 | 
	
		
			
				|  |  | +    FCurrentDisplay     : TDisplay;
 | 
	
		
			
				|  |  | +    FLastWarp           : Integer;
 | 
	
		
			
				|  |  | +    FSectorSaved        : Boolean;
 | 
	
		
			
				|  |  | +    FCurrentTrader      : TTrader;
 | 
	
		
			
				|  |  | +    FCurrentShip        : TShip;
 | 
	
		
			
				|  |  | +    FCurrentMessage     : string;
 | 
	
		
			
				|  |  | +    FTraderList,
 | 
	
		
			
				|  |  | +    FShipList,
 | 
	
		
			
				|  |  | +    FPlanetList         : TList;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    FCurrentLine,
 | 
	
		
			
				|  |  | +    FCurrentANSILine    : string;
 | 
	
		
			
				|  |  | +    FCurrentSector      : TSector;
 | 
	
		
			
				|  |  | +    FInAnsi             : Boolean;
 | 
	
		
			
				|  |  | +    FMenuKey            : Char;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    procedure SectorCompleted;
 | 
	
		
			
				|  |  | +    procedure ResetSectorLists;
 | 
	
		
			
				|  |  | +    procedure ProcessPrompt(Line : string);
 | 
	
		
			
				|  |  | +    procedure AddWarp(SectNum, Warp : Integer);
 | 
	
		
			
				|  |  | +    procedure ProcessWarpLine(Line : String);
 | 
	
		
			
				|  |  | +    procedure ProcessCIMLine(Line : String);
 | 
	
		
			
				|  |  | +    procedure ProcessSectorLine(Line : String);
 | 
	
		
			
				|  |  | +    procedure ProcessLine(Line : String);
 | 
	
		
			
				|  |  | +    procedure ProcessPortLine(Line : String);
 | 
	
		
			
				|  |  | +    procedure StripANSI(var S : string);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  protected
 | 
	
		
			
				|  |  | +    function GetMenuKey: Char;
 | 
	
		
			
				|  |  | +    procedure SetMenuKey(Value: Char);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  public
 | 
	
		
			
				|  |  | +    procedure AfterConstruction; override;
 | 
	
		
			
				|  |  | +    procedure BeforeDestruction; override;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    procedure Reset;
 | 
	
		
			
				|  |  | +    procedure ProcessInBound(var InData : string);
 | 
	
		
			
				|  |  | +    function ProcessOutBound(OutData : string; ClientIndex : Byte) : Boolean;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    property CurrentLine: string read FCurrentLine write FCurrentLine;
 | 
	
		
			
				|  |  | +    property CurrentANSILine: string read FCurrentANSILine write FCurrentANSILine;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  published
 | 
	
		
			
				|  |  | +    property MenuKey: Char read GetMenuKey write SetMenuKey;
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +implementation
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +uses
 | 
	
		
			
				|  |  | +  Global,
 | 
	
		
			
				|  |  | +  Utility,
 | 
	
		
			
				|  |  | +  Ansi;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.AfterConstruction;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  inherited;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Create lists to store ships, traders and planets
 | 
	
		
			
				|  |  | +  FShipList := TList.Create;
 | 
	
		
			
				|  |  | +  FTraderList := TList.Create;
 | 
	
		
			
				|  |  | +  FPlanetList := TList.Create;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  MenuKey := '$';
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.BeforeDestruction;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  ResetSectorLists;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  FShipList.Free;
 | 
	
		
			
				|  |  | +  FTraderList.Free;
 | 
	
		
			
				|  |  | +  FPlanetList.Free;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  inherited;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.Reset;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  // Reset state values
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  CurrentLine := '';
 | 
	
		
			
				|  |  | +  CurrentANSILine := '';
 | 
	
		
			
				|  |  | +  FInAnsi := FALSE;
 | 
	
		
			
				|  |  | +  ResetSectorLists;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function TModExtractor.GetMenuKey: Char;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  Result := FMenuKey;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.SetMenuKey(Value: Char);
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  FMenuKey := Value;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// ********************************************************************
 | 
	
		
			
				|  |  | +// Process inbound data
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.ResetSectorLists;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  // Reset all ship, planet and trader lists
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  while (FShipList.Count > 0) do
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    FreeMem(FShipList[0], SizeOf(TShip));
 | 
	
		
			
				|  |  | +    FShipList.Delete(0);
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  while (FPlanetList.Count > 0) do
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    FreeMem(FPlanetList[0], SizeOf(TPlanet));
 | 
	
		
			
				|  |  | +    FPlanetList.Delete(0);
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  while (FTraderList.Count > 0) do
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    FreeMem(FTraderList[0], SizeOf(TTrader));
 | 
	
		
			
				|  |  | +    FTraderList.Delete(0);
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.SectorCompleted;
 | 
	
		
			
				|  |  | +var
 | 
	
		
			
				|  |  | +  I,
 | 
	
		
			
				|  |  | +  WarpIndex : Integer;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  if (FCurrentSectorIndex = 0) then
 | 
	
		
			
				|  |  | +    Exit;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  FCurrentSector.UpDate := Now;
 | 
	
		
			
				|  |  | +  FCurrentSector.Explored := etHolo;
 | 
	
		
			
				|  |  | +  FSectorSaved := TRUE;
 | 
	
		
			
				|  |  | +  WarpIndex := 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  for I := 1 to 6 do
 | 
	
		
			
				|  |  | +    if (FCurrentSector.Warp[I] = 0) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      WarpIndex := I;
 | 
	
		
			
				|  |  | +      Break;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (WarpIndex = 0) then
 | 
	
		
			
				|  |  | +    FCurrentSector.Warps := 0
 | 
	
		
			
				|  |  | +  else if (FCurrentSector.Warp[WarpIndex] = 0) then
 | 
	
		
			
				|  |  | +    FCurrentSector.Warps := WarpIndex - 1
 | 
	
		
			
				|  |  | +  else
 | 
	
		
			
				|  |  | +    FCurrentSector.Warps := 6;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  TWXDatabase.SaveSector(FCurrentSector, FCurrentSectorIndex, FShipList, FTraderList, FPlanetList);
 | 
	
		
			
				|  |  | +  FCurrentSectorIndex := 0;
 | 
	
		
			
				|  |  | +  ResetSectorLists;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.ProcessPrompt(Line : string);
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  // This procedure checks command prompts.  It is called from both
 | 
	
		
			
				|  |  | +  // processline and processinbound, as it can come in as part of
 | 
	
		
			
				|  |  | +  // a large packet or still be waiting for the user.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (Copy(Line, 1, 12) = 'Command [TL=') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Save current sector if not done already
 | 
	
		
			
				|  |  | +    if not (FSectorSaved) then
 | 
	
		
			
				|  |  | +      SectorCompleted;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // No displays anymore, all done
 | 
	
		
			
				|  |  | +    FCurrentDisplay := dNone;
 | 
	
		
			
				|  |  | +    FLastWarp := 0;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 23) = 'Probe entering sector :') or (Copy(Line, 1, 20) = 'Probe Self Destructs') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // mid probe - save the sector
 | 
	
		
			
				|  |  | +    if not (FSectorSaved) then
 | 
	
		
			
				|  |  | +      SectorCompleted;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // No displays anymore, all done
 | 
	
		
			
				|  |  | +    FCurrentDisplay := dNone;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 21) = 'Computer command [TL=') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // in computer prompt, kill all displays and clear warp data
 | 
	
		
			
				|  |  | +    FCurrentDisplay := dNone;
 | 
	
		
			
				|  |  | +    FLastWarp := 0;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 25) = 'Citadel treasury contains') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // In Citadel - Save current sector if not done already
 | 
	
		
			
				|  |  | +    if not (FSectorSaved) then
 | 
	
		
			
				|  |  | +      SectorCompleted;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // No displays anymore, all done
 | 
	
		
			
				|  |  | +    FCurrentDisplay := dNone;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 19) = 'Stop in this sector') or (Copy(Line, 1, 21) = 'Engage the Autopilot?') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Save current sector if not done already
 | 
	
		
			
				|  |  | +    if not (FSectorSaved) then
 | 
	
		
			
				|  |  | +      SectorCompleted;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // No displays anymore, all done
 | 
	
		
			
				|  |  | +    FCurrentDisplay := dNone;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 2) = ': ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // at the CIM prompt
 | 
	
		
			
				|  |  | +    if (FCurrentDisplay <> dCIM) then
 | 
	
		
			
				|  |  | +      FCurrentDisplay := dNone;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    FLastWarp := 0;
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  TWXInterpreter.TextEvent(CurrentLine, FALSE);
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.AddWarp(SectNum, Warp : Integer);
 | 
	
		
			
				|  |  | +var
 | 
	
		
			
				|  |  | +  S     : TSector;
 | 
	
		
			
				|  |  | +  I,
 | 
	
		
			
				|  |  | +  X,
 | 
	
		
			
				|  |  | +  Pos   : Integer;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  // Used by ProcessWarpLine to add a warp to a sector
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  S := TWXDatabase.LoadSector(SectNum);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // see if the warp is already in there
 | 
	
		
			
				|  |  | +  for I := 1 to 6 do
 | 
	
		
			
				|  |  | +    if (S.Warp[I] = Warp) then
 | 
	
		
			
				|  |  | +      Exit;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // find where it should fit
 | 
	
		
			
				|  |  | +  Pos := 7;
 | 
	
		
			
				|  |  | +  for I := 1 to 6 do
 | 
	
		
			
				|  |  | +    if (S.Warp[I] > Warp) or (S.Warp[I] = 0) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      Pos := I;
 | 
	
		
			
				|  |  | +      Break;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (Pos = 1) then
 | 
	
		
			
				|  |  | +    X := 2
 | 
	
		
			
				|  |  | +  else
 | 
	
		
			
				|  |  | +    X := Pos;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // move them all up one
 | 
	
		
			
				|  |  | +  if (Pos < 6) then
 | 
	
		
			
				|  |  | +    for I := 6 downto X do
 | 
	
		
			
				|  |  | +      S.Warp[I] := S.Warp[I - 1];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (Pos < 7) then
 | 
	
		
			
				|  |  | +    S.Warp[Pos] := Warp;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (S.Explored = etNo) then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    S.Constellation := '???' + ANSI_9 + ' (warp calc only)';
 | 
	
		
			
				|  |  | +    S.Explored := etCalc;
 | 
	
		
			
				|  |  | +    S.Update := Now;
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  TWXDatabase.SaveSector(S, SectNum, nil, nil, nil);
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.ProcessWarpLine(Line : String);
 | 
	
		
			
				|  |  | +var
 | 
	
		
			
				|  |  | +  I,
 | 
	
		
			
				|  |  | +  CurSect,
 | 
	
		
			
				|  |  | +  LastSect : Integer;
 | 
	
		
			
				|  |  | +  S        : String;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  // A WarpLine is a line of warps plotted using the ship's computer.  Add new warps to
 | 
	
		
			
				|  |  | +  // any sectors listed in the warp lane (used extensively for ZTM).
 | 
	
		
			
				|  |  | +  // e.g:  3 > 300 > 5362 > 13526 > 149 > 434
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  LastSect := FLastWarp;
 | 
	
		
			
				|  |  | +  StripChar(Line, ')');
 | 
	
		
			
				|  |  | +  StripChar(Line, '(');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  I := 1;
 | 
	
		
			
				|  |  | +  S := GetParameter(Line, I);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  while (S <> '') do
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    if (S <> '>') then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      CurSect := StrToIntSafe(S);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (CurSect < 1) or (CurSect > TWXDatabase.DBHeader.Sectors) then
 | 
	
		
			
				|  |  | +        // doesn't look like this line is what we thought it was.
 | 
	
		
			
				|  |  | +        // Best to leave it alone
 | 
	
		
			
				|  |  | +        exit;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (LastSect > 0) then
 | 
	
		
			
				|  |  | +        AddWarp(LastSect, CurSect);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      LastSect := CurSect;
 | 
	
		
			
				|  |  | +      FLastWarp := CurSect;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    Inc(I);
 | 
	
		
			
				|  |  | +    S := GetParameter(Line, I);
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.ProcessCIMLine(Line : String);
 | 
	
		
			
				|  |  | +  function GetCIMValue(M : String; Num : Integer) : Integer;
 | 
	
		
			
				|  |  | +  var
 | 
	
		
			
				|  |  | +    S : String;
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    S := GetParameter(M, Num);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (S = '') then
 | 
	
		
			
				|  |  | +      Result := 0
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +    try
 | 
	
		
			
				|  |  | +      Result := StrToInt(S);
 | 
	
		
			
				|  |  | +    except
 | 
	
		
			
				|  |  | +      Result := -1;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +var
 | 
	
		
			
				|  |  | +  Sect   : Integer;
 | 
	
		
			
				|  |  | +  S      : TSector;
 | 
	
		
			
				|  |  | +  X,
 | 
	
		
			
				|  |  | +  I,
 | 
	
		
			
				|  |  | +  Len,
 | 
	
		
			
				|  |  | +  Ore,
 | 
	
		
			
				|  |  | +  Org,
 | 
	
		
			
				|  |  | +  Equip,
 | 
	
		
			
				|  |  | +  POre,
 | 
	
		
			
				|  |  | +  POrg,
 | 
	
		
			
				|  |  | +  PEquip : Integer;
 | 
	
		
			
				|  |  | +  M      : String;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  if (FCurrentDisplay = dWarpCIM) then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // save warp CIM data
 | 
	
		
			
				|  |  | +    Sect := GetCIMValue(Line, 1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (Sect <= 0) or (Sect > TWXDatabase.DBHeader.Sectors) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      FCurrentDisplay := dNone;
 | 
	
		
			
				|  |  | +      Exit;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    S := TWXDatabase.LoadSector(Sect);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    for I := 1 to 6 do
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      X := GetCIMValue(Line, I + 1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (X < 0) or (X > TWXDatabase.DBHeader.Sectors) then
 | 
	
		
			
				|  |  | +      begin
 | 
	
		
			
				|  |  | +        FCurrentDisplay := dNone;
 | 
	
		
			
				|  |  | +        Exit;
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        S.Warp[I] := X;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (S.Explored = etNo) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      S.Constellation := '???' + ANSI_9 + ' (warp calc only)';
 | 
	
		
			
				|  |  | +      S.Explored := etCalc;
 | 
	
		
			
				|  |  | +      S.Update := Now;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    TWXDatabase.SaveSector(S, Sect, nil, nil, nil);
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // save port CIM data
 | 
	
		
			
				|  |  | +    Sect := GetCIMValue(Line, 1);
 | 
	
		
			
				|  |  | +    Len := Length(IntToStr(TWXDatabase.DBHeader.Sectors));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (Sect <= 0) or (Sect > TWXDatabase.DBHeader.Sectors) or (Length(Line) < Len + 36) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      FCurrentDisplay := dNone;
 | 
	
		
			
				|  |  | +      Exit;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    M := StringReplace(Line, '-', '', [rfReplaceAll]);
 | 
	
		
			
				|  |  | +    M := StringReplace(M, '%', '', [rfReplaceAll]);
 | 
	
		
			
				|  |  | +    S := TWXDatabase.LoadSector(Sect);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    Ore := GetCIMValue(M, 2);
 | 
	
		
			
				|  |  | +    Org := GetCIMValue(M, 4);
 | 
	
		
			
				|  |  | +    Equip := GetCIMValue(M, 6);
 | 
	
		
			
				|  |  | +    POre := GetCIMValue(M, 3);
 | 
	
		
			
				|  |  | +    POrg := GetCIMValue(M, 5);
 | 
	
		
			
				|  |  | +    PEquip := GetCIMValue(M, 7);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (Ore < 0) or (Org < 0) or (Equip < 0)
 | 
	
		
			
				|  |  | +     or (POre < 0) or (POre > 100)
 | 
	
		
			
				|  |  | +     or (POrg < 0) or (POrg > 100)
 | 
	
		
			
				|  |  | +     or (PEquip < 0) or (PEquip > 100) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      FCurrentDisplay := dNone;
 | 
	
		
			
				|  |  | +      Exit;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    S.SPort.ProductAmount[ptFuelOre] := Ore;
 | 
	
		
			
				|  |  | +    S.SPort.ProductAmount[ptOrganics] := Org;
 | 
	
		
			
				|  |  | +    S.SPort.ProductAmount[ptEquipment] := Equip;
 | 
	
		
			
				|  |  | +    S.SPort.ProductPercent[ptFuelOre] := POre;
 | 
	
		
			
				|  |  | +    S.SPort.ProductPercent[ptOrganics] := POrg;
 | 
	
		
			
				|  |  | +    S.SPort.ProductPercent[ptEquipment] := PEquip;
 | 
	
		
			
				|  |  | +    S.SPort.UpDate := Now;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (S.SPort.Name = '') then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      // port not saved/seen before - get its details
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (Line[Len + 2] = '-') then
 | 
	
		
			
				|  |  | +        S.SPort.BuyProduct[ptFuelOre] := TRUE
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        S.SPort.BuyProduct[ptFuelOre] := FALSE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (Line[Len + 14] = '-') then
 | 
	
		
			
				|  |  | +        S.SPort.BuyProduct[ptOrganics] := TRUE
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        S.SPort.BuyProduct[ptOrganics] := FALSE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (Line[Len + 26] = '-') then
 | 
	
		
			
				|  |  | +        S.SPort.BuyProduct[ptEquipment] := TRUE
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        S.SPort.BuyProduct[ptEquipment] := FALSE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (S.SPort.BuyProduct[ptFuelOre]) and (S.SPort.BuyProduct[ptOrganics]) and (S.SPort.BuyProduct[ptEquipment]) then
 | 
	
		
			
				|  |  | +        S.SPort.ClassIndex := 8
 | 
	
		
			
				|  |  | +      else if (S.SPort.BuyProduct[ptFuelOre]) and (S.SPort.BuyProduct[ptOrganics]) and not (S.SPort.BuyProduct[ptEquipment]) then
 | 
	
		
			
				|  |  | +        S.SPort.ClassIndex := 1
 | 
	
		
			
				|  |  | +      else if (S.SPort.BuyProduct[ptFuelOre]) and not (S.SPort.BuyProduct[ptOrganics]) and (S.SPort.BuyProduct[ptEquipment]) then
 | 
	
		
			
				|  |  | +        S.SPort.ClassIndex := 2
 | 
	
		
			
				|  |  | +      else if not (S.SPort.BuyProduct[ptFuelOre]) and (S.SPort.BuyProduct[ptOrganics]) and (S.SPort.BuyProduct[ptEquipment]) then
 | 
	
		
			
				|  |  | +        S.SPort.ClassIndex := 3
 | 
	
		
			
				|  |  | +      else if not (S.SPort.BuyProduct[ptFuelOre]) and not (S.SPort.BuyProduct[ptOrganics]) and (S.SPort.BuyProduct[ptEquipment]) then
 | 
	
		
			
				|  |  | +        S.SPort.ClassIndex := 4
 | 
	
		
			
				|  |  | +      else if not (S.SPort.BuyProduct[ptFuelOre]) and (S.SPort.BuyProduct[ptOrganics]) and not (S.SPort.BuyProduct[ptEquipment]) then
 | 
	
		
			
				|  |  | +        S.SPort.ClassIndex := 5
 | 
	
		
			
				|  |  | +      else if (S.SPort.BuyProduct[ptFuelOre]) and not (S.SPort.BuyProduct[ptOrganics]) and not (S.SPort.BuyProduct[ptEquipment]) then
 | 
	
		
			
				|  |  | +        S.SPort.ClassIndex := 6
 | 
	
		
			
				|  |  | +      else if not (S.SPort.BuyProduct[ptFuelOre]) and not (S.SPort.BuyProduct[ptOrganics]) and not (S.SPort.BuyProduct[ptEquipment]) then
 | 
	
		
			
				|  |  | +        S.SPort.ClassIndex := 7;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      S.SPort.Name := '???';
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (S.Explored = etNo) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      S.Constellation := '???' + ANSI_9 + ' (port data/calc only)';
 | 
	
		
			
				|  |  | +      S.Explored := etCalc;
 | 
	
		
			
				|  |  | +      S.Update := Now;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    TWXDatabase.SaveSector(S, Sect, nil, nil, nil);
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.ProcessSectorLine(Line : String);
 | 
	
		
			
				|  |  | +var
 | 
	
		
			
				|  |  | +  S         : String;
 | 
	
		
			
				|  |  | +  I         : Integer;
 | 
	
		
			
				|  |  | +  NewPlanet : PPlanet;
 | 
	
		
			
				|  |  | +  NewShip   : PShip;
 | 
	
		
			
				|  |  | +  NewTrader : PTrader;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  if (Copy(Line, 1, 10) = 'Beacon  : ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Get beacon text
 | 
	
		
			
				|  |  | +    FCurrentSector.Beacon := Copy(Line, 11, length(Line) - 10);
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 10) = 'Ports   : ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Save port data
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (Pos('<=-DANGER-=>', Line) > 0) then
 | 
	
		
			
				|  |  | +      // Port is destroyed
 | 
	
		
			
				|  |  | +      FCurrentSector.SPort.Dead := TRUE
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      FCurrentSector.SPort.Dead := FALSE;
 | 
	
		
			
				|  |  | +      FCurrentSector.SPort.BuildTime := 0;
 | 
	
		
			
				|  |  | +      FCurrentSector.SPort.Name := Copy(Line, 11, Pos(', Class', Line) - 11);
 | 
	
		
			
				|  |  | +      FCurrentSector.SPort.ClassIndex := StrToIntSafe(Copy(Line, Pos(', Class', Line) + 8, 1));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (Line[length(Line) - 3] = 'B') then
 | 
	
		
			
				|  |  | +        FCurrentSector.SPort.BuyProduct[ptFuelOre] := TRUE
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        FCurrentSector.SPort.BuyProduct[ptFuelOre] := FALSE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (Line[length(Line) - 2] = 'B') then
 | 
	
		
			
				|  |  | +        FCurrentSector.SPort.BuyProduct[ptOrganics] := TRUE
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        FCurrentSector.SPort.BuyProduct[ptOrganics] := FALSE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (Line[length(Line) - 1] = 'B') then
 | 
	
		
			
				|  |  | +        FCurrentSector.SPort.BuyProduct[ptEquipment] := TRUE
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        FCurrentSector.SPort.BuyProduct[ptEquipment] := FALSE;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    FSectorPosition := spPorts;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 10) = 'Planets : ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Get planet data
 | 
	
		
			
				|  |  | +    NewPlanet := AllocMem(SizeOf(TPlanet));
 | 
	
		
			
				|  |  | +    TWXDatabase.NULLPlanet(NewPlanet^);
 | 
	
		
			
				|  |  | +    NewPlanet^.Name := Copy(Line, 11, length(Line) - 10);
 | 
	
		
			
				|  |  | +    FPlanetList.Add(NewPlanet);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    FSectorPosition := spPlanets;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 10) = 'Traders : ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Save traders
 | 
	
		
			
				|  |  | +    I := Pos(', w/', Line);
 | 
	
		
			
				|  |  | +    FCurrentTrader.Name := Copy(Line, 11, I - 11);
 | 
	
		
			
				|  |  | +    S := Copy(Line, I + 5, Pos(' ftrs', Line) - I - 5);
 | 
	
		
			
				|  |  | +    StripChar(S, ',');
 | 
	
		
			
				|  |  | +    FCurrentTrader.Figs := StrToIntSafe(S);
 | 
	
		
			
				|  |  | +    FSectorPosition := spTraders;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 10) = 'Ships   : ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Save ships
 | 
	
		
			
				|  |  | +    I := Pos('[Owned by]', Line);
 | 
	
		
			
				|  |  | +    FCurrentShip.Name := Copy(Line, 11, I - 12);
 | 
	
		
			
				|  |  | +    FCurrentShip.Owner := Copy(Line, I + 11, Pos(', w/', Line) - I - 11);
 | 
	
		
			
				|  |  | +    I := Pos(', w/', Line);
 | 
	
		
			
				|  |  | +    S := Copy(Line, I + 5, Pos(' ftrs,', Line) - I - 5);
 | 
	
		
			
				|  |  | +    StripChar(S, ',');
 | 
	
		
			
				|  |  | +    FCurrentShip.Figs := StrToIntSafe(S);
 | 
	
		
			
				|  |  | +    FSectorPosition := spShips;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 10) = 'Fighters: ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Get fig details
 | 
	
		
			
				|  |  | +    S := GetParameter(Line, 2);
 | 
	
		
			
				|  |  | +    StripChar(S, ',');
 | 
	
		
			
				|  |  | +    FCurrentSector.Figs.Quantity := StrToIntSafe(S);
 | 
	
		
			
				|  |  | +    I := GetParameterPos(Line, 3) + 1;
 | 
	
		
			
				|  |  | +    FCurrentSector.Figs.Owner := Copy(Line, I, Pos(')', Line) - I);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (Copy(Line, length(Line) - 5, 6) = '[Toll]') then
 | 
	
		
			
				|  |  | +      FCurrentSector.Figs.FigType := ftToll
 | 
	
		
			
				|  |  | +    else if (Copy(Line, length(Line) - 10, 11) = '[Defensive]') then
 | 
	
		
			
				|  |  | +      FCurrentSector.Figs.FigType := ftDefensive
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      FCurrentSector.Figs.FigType := ftOffensive;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 10) = 'NavHaz  : ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    S := GetParameter(Line, 3);
 | 
	
		
			
				|  |  | +    S := Copy(S, 1, length(S) - 1);
 | 
	
		
			
				|  |  | +    FCurrentSector.NavHaz := StrToIntSafe(S);
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 10) = 'Mines   : ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Save mines
 | 
	
		
			
				|  |  | +    FSectorPosition := spMines;
 | 
	
		
			
				|  |  | +    I := GetParameterPos(Line, 7) + 1;
 | 
	
		
			
				|  |  | +    S := Copy(Line, I, length(Line) - I);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (GetParameter(Line, 6) = 'Armid)') then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      FCurrentSector.Mines_Armid.Quantity := StrToIntSafe(GetParameter(Line, 3));
 | 
	
		
			
				|  |  | +      FCurrentSector.Mines_Armid.Owner := S;
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      FCurrentSector.Mines_Limpet.Quantity := StrToIntSafe(GetParameter(Line, 3));
 | 
	
		
			
				|  |  | +      FCurrentSector.Mines_Limpet.Owner := S;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 8) = '        ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Continue from last occurance
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (FSectorPosition = spMines) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      I := GetParameterPos(Line, 6) + 1;
 | 
	
		
			
				|  |  | +      FCurrentSector.Mines_Limpet.Quantity := StrToIntSafe(GetParameter(Line, 2));
 | 
	
		
			
				|  |  | +      FCurrentSector.Mines_Limpet.Owner := Copy(Line, I, length(Line) - I);
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +    else if (FSectorPosition = spPorts) then
 | 
	
		
			
				|  |  | +      FCurrentSector.SPort.BuildTime := StrToIntSafe(GetParameter(Line, 4))
 | 
	
		
			
				|  |  | +    else if (FSectorPosition = spPlanets) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      // Get planet data
 | 
	
		
			
				|  |  | +      NewPlanet := AllocMem(SizeOf(TPlanet));
 | 
	
		
			
				|  |  | +      TWXDatabase.NULLPlanet(NewPlanet^);
 | 
	
		
			
				|  |  | +      NewPlanet^.Name := Copy(Line, 11, length(Line) - 10);
 | 
	
		
			
				|  |  | +      FPlanetList.Add(NewPlanet);
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +    else if (FSectorPosition = spTraders) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      if (GetParameter(Line, 1) = 'in') then
 | 
	
		
			
				|  |  | +      begin
 | 
	
		
			
				|  |  | +        // Still working on one trader
 | 
	
		
			
				|  |  | +        NewTrader := AllocMem(SizeOf(TTrader));
 | 
	
		
			
				|  |  | +        I := GetParameterPos(Line, 2);
 | 
	
		
			
				|  |  | +        NewTrader^.ShipName := Copy(Line, I, Pos('(', Line) - I - 1);
 | 
	
		
			
				|  |  | +        I := Pos('(', Line);
 | 
	
		
			
				|  |  | +        NewTrader^.ShipType := Copy(Line, I + 1, Pos(')', Line) - I - 1);
 | 
	
		
			
				|  |  | +        NewTrader^.Name := FCurrentTrader.Name;
 | 
	
		
			
				|  |  | +        NewTrader^.Figs := FCurrentTrader.Figs;
 | 
	
		
			
				|  |  | +        FTraderList.Add(NewTrader);
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +      begin
 | 
	
		
			
				|  |  | +        // New trader
 | 
	
		
			
				|  |  | +        I := Pos(', w/', Line);
 | 
	
		
			
				|  |  | +        FCurrentTrader.Name := Copy(Line, 11, I - 11);
 | 
	
		
			
				|  |  | +        S := Copy(Line, I + 5, Pos(' ftrs', Line) - I - 5);
 | 
	
		
			
				|  |  | +        StripChar(S, ',');
 | 
	
		
			
				|  |  | +        FCurrentTrader.Figs := StrToIntSafe(S);
 | 
	
		
			
				|  |  | +      end;
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +    else if (FSectorPosition = spShips) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      if (Copy(Line, 12, 1) = '(') then
 | 
	
		
			
				|  |  | +      begin
 | 
	
		
			
				|  |  | +        // Get the rest of the ship info
 | 
	
		
			
				|  |  | +        NewShip := AllocMem(SizeOf(TShip));
 | 
	
		
			
				|  |  | +        NewShip^.Name := FCurrentShip.Name;
 | 
	
		
			
				|  |  | +        NewShip^.Owner := FCurrentShip.Owner;
 | 
	
		
			
				|  |  | +        NewShip^.Figs := FCurrentShip.Figs;
 | 
	
		
			
				|  |  | +        NewShip^.ShipType := Copy(Line, 13, Pos(')', Line) - 13);
 | 
	
		
			
				|  |  | +        FShipList.Add(NewShip);
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +      begin
 | 
	
		
			
				|  |  | +        // New ship
 | 
	
		
			
				|  |  | +        I := Pos('[Owned by]', Line);
 | 
	
		
			
				|  |  | +        FCurrentShip.Name := Copy(Line, 11, I - 12);
 | 
	
		
			
				|  |  | +        FCurrentShip.Owner := Copy(Line, I + 11, Pos(', w/', Line) - I - 11);
 | 
	
		
			
				|  |  | +        I := Pos(', w/', Line);
 | 
	
		
			
				|  |  | +        S := Copy(Line, I + 5, Pos(' ftrs,', Line) - I - 5);
 | 
	
		
			
				|  |  | +        StripChar(S, ',');
 | 
	
		
			
				|  |  | +        FCurrentShip.Figs := StrToIntSafe(S);
 | 
	
		
			
				|  |  | +        FSectorPosition := spShips;
 | 
	
		
			
				|  |  | +      end;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 9, 1) = ':') then
 | 
	
		
			
				|  |  | +    FSectorPosition := spNormal  
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 20) = 'Warps to Sector(s) :') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    StripChar(Line, '(');
 | 
	
		
			
				|  |  | +    StripChar(Line, ')');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Get sector warps
 | 
	
		
			
				|  |  | +    FCurrentSector.Warp[1] := StrToIntSafe(GetParameter(Line, 5));
 | 
	
		
			
				|  |  | +    FCurrentSector.Warp[2] := StrToIntSafe(GetParameter(Line, 7));
 | 
	
		
			
				|  |  | +    FCurrentSector.Warp[3] := StrToIntSafe(GetParameter(Line, 9));
 | 
	
		
			
				|  |  | +    FCurrentSector.Warp[4] := StrToIntSafe(GetParameter(Line, 11));
 | 
	
		
			
				|  |  | +    FCurrentSector.Warp[5] := StrToIntSafe(GetParameter(Line, 13));
 | 
	
		
			
				|  |  | +    FCurrentSector.Warp[6] := StrToIntSafe(GetParameter(Line, 15));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // sector done
 | 
	
		
			
				|  |  | +    if not (FSectorSaved) then
 | 
	
		
			
				|  |  | +      SectorCompleted;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // No displays anymore, all done
 | 
	
		
			
				|  |  | +    FCurrentDisplay := dNone;
 | 
	
		
			
				|  |  | +    FSectorPosition := spNormal;
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.ProcessPortLine(Line : String);
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  // Process a line from the CR port display
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.ProcessLine(Line : String);
 | 
	
		
			
				|  |  | +var
 | 
	
		
			
				|  |  | +  S,
 | 
	
		
			
				|  |  | +  X       : String;
 | 
	
		
			
				|  |  | +  I       : Integer;
 | 
	
		
			
				|  |  | +  Sect    : TSector;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  // Every line is passed to this procedure to be processed and recorded
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (FCurrentMessage <> '') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    if (Line <> '') then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      if (FCurrentMessage = 'Figs') then
 | 
	
		
			
				|  |  | +        TWXGUI.AddToHistory(htFighter, TimeToStr(Time) + '  ' + StripChars(Line))
 | 
	
		
			
				|  |  | +      else if (FCurrentMessage = 'Comp') then
 | 
	
		
			
				|  |  | +        TWXGUI.AddToHistory(htComputer, TimeToStr(Time) + '  ' + StripChars(Line))
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        TWXGUI.AddToHistory(htMsg, TimeToStr(Time) + '  ' + StripChars(Line));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      FCurrentMessage := '';
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 2) = 'R ') or (Copy(Line, 1, 2) = 'F ') then
 | 
	
		
			
				|  |  | +    TWXGUI.AddToHistory(htMsg, TimeToStr(Time) + '  ' + StripChars(Line))
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 2) = 'P ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    if (GetParameter(Line, 2) <> 'indicates') then
 | 
	
		
			
				|  |  | +      TWXGUI.AddToHistory(htMsg, TimeToStr(Time) + '  ' + StripChars(Line))
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 26) = 'Incoming transmission from') or (Copy(Line, 1, 28) = 'Continuing transmission from') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Transmission with ansi off
 | 
	
		
			
				|  |  | +    I := GetParameterPos(Line, 4);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (Copy(Line, Length(Line) - 9, 10) = 'comm-link:') then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      // Fedlink
 | 
	
		
			
				|  |  | +      FCurrentMessage := 'F ' + Copy(Line, I, Pos(' on Federation', Line) - I) + ' ';
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +    else if (GetParameter(Line, 5) = 'Fighters:') then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      // Fighters
 | 
	
		
			
				|  |  | +      FCurrentMessage := 'Figs';
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +    else if (GetParameter(Line, 5) = 'Computers:') then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      // Computer
 | 
	
		
			
				|  |  | +      FCurrentMessage := 'Comp';
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +    else if (Pos(' on channel ', Line) <> 0) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      // Radio
 | 
	
		
			
				|  |  | +      FCurrentMessage := 'R ' + Copy(Line, I, Pos(' on channel ', Line) - I) + ' ';
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      // hail
 | 
	
		
			
				|  |  | +      FCurrentMessage := 'P ' + Copy(Line, I, Length(Line) - I) + ' ';
 | 
	
		
			
				|  |  | +    end
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 31) = 'Deployed Fighters Report Sector') then
 | 
	
		
			
				|  |  | +    TWXGUI.AddToHistory(htFighter, TimeToStr(Time) + '  ' + Copy(Line, 19, Length(Line)))
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 20) = 'Shipboard Computers ') then
 | 
	
		
			
				|  |  | +    TWXGUI.AddToHistory(htComputer, TimeToStr(Time) + '  ' + Copy(Line, 21, Length(Line)))
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 19) = 'The shortest path (') or (Copy(Line, 1, 7) = '  TO > ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    FCurrentDisplay := dWarpLane;
 | 
	
		
			
				|  |  | +    FLastWarp := 0;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (FCurrentDisplay = dWarpLane) then
 | 
	
		
			
				|  |  | +    ProcessWarpLine(Line)
 | 
	
		
			
				|  |  | +  else if (FCurrentDisplay = dWarpCIM) or (FCurrentDisplay = dPortCIM) then
 | 
	
		
			
				|  |  | +    ProcessCIMLine(Line)
 | 
	
		
			
				|  |  | +  else if (FCurrentDisplay = dCIM) then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // find out what kind of CIM this is
 | 
	
		
			
				|  |  | +    if (Length(Line) > 2) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      if (Line[Length(Line) - 1] = '%') then
 | 
	
		
			
				|  |  | +      begin
 | 
	
		
			
				|  |  | +        TWXDatabase.LastPortCIM := Now;
 | 
	
		
			
				|  |  | +        FCurrentDisplay := dPortCIM;
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +        FCurrentDisplay := dWarpCIM;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      ProcessCIMLine(Line);
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 10) = 'Sector  : ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Check if this is a probe or holoscan (no warp pickup)
 | 
	
		
			
				|  |  | +    if not (FSectorSaved) then
 | 
	
		
			
				|  |  | +      SectorCompleted;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Begin recording of sector data
 | 
	
		
			
				|  |  | +    FCurrentDisplay := dSector;
 | 
	
		
			
				|  |  | +    FSectorSaved := FALSE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Clear sector variables
 | 
	
		
			
				|  |  | +    TWXDatabase.NULLSector(FCurrentSector);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    FCurrentSectorIndex := StrToIntSafe(GetParameter(Line, 3));
 | 
	
		
			
				|  |  | +    I := GetParameterPos(Line, 5);
 | 
	
		
			
				|  |  | +    FCurrentSector.Constellation := Copy(Line, I, length(Line) - I + 1);
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (FCurrentDisplay = dSector) then
 | 
	
		
			
				|  |  | +    ProcessSectorLine(Line)
 | 
	
		
			
				|  |  | +  else if (FCurrentDisplay = dPort) then
 | 
	
		
			
				|  |  | +    ProcessPortLine(Line)
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 27, 16) = 'Relative Density') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // A density scanner is being used - lets grab some data
 | 
	
		
			
				|  |  | +    FCurrentDisplay := dDensity;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (FCurrentDisplay = dDensity) and (Copy(Line, 1, 6) = 'Sector') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Save all density data into sector database
 | 
	
		
			
				|  |  | +    X := Line;
 | 
	
		
			
				|  |  | +    StripChar(X, '(');
 | 
	
		
			
				|  |  | +    StripChar(X, ')');
 | 
	
		
			
				|  |  | +    I := StrToIntSafe(GetParameter(X, 2));
 | 
	
		
			
				|  |  | +    Sect := TWXDatabase.LoadSector(I);
 | 
	
		
			
				|  |  | +    S := GetParameter(X, 4);
 | 
	
		
			
				|  |  | +    StripChar(S, ',');
 | 
	
		
			
				|  |  | +    Sect.Density := StrToIntSafe(S);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (GetParameter(X, 13) = 'Yes') then
 | 
	
		
			
				|  |  | +      // Sector has anomoly
 | 
	
		
			
				|  |  | +      Sect.Anomoly := TRUE
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      Sect.Anomoly := FALSE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    S := GetParameter(X, 10);
 | 
	
		
			
				|  |  | +    S := Copy(S, 1, length(S) - 1);
 | 
	
		
			
				|  |  | +    Sect.NavHaz := StrToIntSafe(S);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    Sect.Warps := StrToIntSafe(GetParameter(X, 7));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (Sect.Explored in [etNo, etCalc]) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      // Sector hasn't been scanned or seen before
 | 
	
		
			
				|  |  | +      Sect.Constellation := '???' + ANSI_9 + ' (Density only)';
 | 
	
		
			
				|  |  | +      Sect.Explored := etDensity;
 | 
	
		
			
				|  |  | +      Sect.Update := Now;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    TWXDatabase.SaveSector(Sect, I, nil, nil, nil);
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 28) = 'What sector is the port in? ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // begin port data download
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (Copy(Line, 1, 2) = ': ') then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // begin CIM download
 | 
	
		
			
				|  |  | +    FCurrentDisplay := dCIM;
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  TWXInterpreter.TextLineEvent(Line, FALSE);
 | 
	
		
			
				|  |  | +  ProcessPrompt(Line);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Reactivate script triggers
 | 
	
		
			
				|  |  | +  TWXInterpreter.ActivateTriggers;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.StripANSI(var S : String);
 | 
	
		
			
				|  |  | +var
 | 
	
		
			
				|  |  | +  I    : Integer;
 | 
	
		
			
				|  |  | +  X    : String;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  // Remove ANSI codes from text
 | 
	
		
			
				|  |  | +  X := '';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  for I := 1 to length(S) do
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    if (S[I] = #27) then
 | 
	
		
			
				|  |  | +      FInAnsi := TRUE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (FInAnsi = FALSE) then
 | 
	
		
			
				|  |  | +      X := X + S[I];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if ((Byte(S[I]) >= 65) and (Byte(S[I]) <= 90)) or ((Byte(S[I]) >= 97) and (Byte(S[I]) <= 122)) then
 | 
	
		
			
				|  |  | +      FInAnsi := FALSE;
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  S := X;
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +procedure TModExtractor.ProcessInBound(var InData : String);
 | 
	
		
			
				|  |  | +var
 | 
	
		
			
				|  |  | +  X        : Integer;
 | 
	
		
			
				|  |  | +  I        : Integer;
 | 
	
		
			
				|  |  | +  S,
 | 
	
		
			
				|  |  | +  ANSIS,
 | 
	
		
			
				|  |  | +  ANSILine,
 | 
	
		
			
				|  |  | +  Line     : string;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  S := InData;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Remove null chars
 | 
	
		
			
				|  |  | +  StripChar(S, #0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // strip the ANSI
 | 
	
		
			
				|  |  | +  AnsiS := S;
 | 
	
		
			
				|  |  | +  StripANSI(S);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  TWXLog.DoLogData(S, InData);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Remove linefeed
 | 
	
		
			
				|  |  | +  StripChar(S, #10);
 | 
	
		
			
				|  |  | +  StripChar(AnsiS, #10);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Form and process lines out of data
 | 
	
		
			
				|  |  | +  I := 1;
 | 
	
		
			
				|  |  | +  Line := CurrentLine + S;
 | 
	
		
			
				|  |  | +  AnsiLine := CurrentANSILine + AnsiS;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  while (I <= Length(Line)) do
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    if (Line[I] = #13) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      // find the matching carriage return in the ansi line
 | 
	
		
			
				|  |  | +      X := 1;
 | 
	
		
			
				|  |  | +      
 | 
	
		
			
				|  |  | +      if (Length(ANSILine) > 0) then
 | 
	
		
			
				|  |  | +        while (ANSILine[X] <> #13) and (X < Length(ANSILine)) do
 | 
	
		
			
				|  |  | +          Inc(X);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      CurrentLine := Copy(Line, 1, I - 1);
 | 
	
		
			
				|  |  | +      CurrentANSILine := Copy(ANSILine, 1, X - 1);
 | 
	
		
			
				|  |  | +      ProcessLine(CurrentLine);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (I < Length(Line)) then
 | 
	
		
			
				|  |  | +      begin
 | 
	
		
			
				|  |  | +        Line := Copy(Line, I + 1, Length(Line) - I);
 | 
	
		
			
				|  |  | +        ANSILine := Copy(ANSILine, X + 1, Length(ANSILine) - X);
 | 
	
		
			
				|  |  | +      end
 | 
	
		
			
				|  |  | +      else
 | 
	
		
			
				|  |  | +      begin
 | 
	
		
			
				|  |  | +        Line := '';
 | 
	
		
			
				|  |  | +        ANSILine := '';
 | 
	
		
			
				|  |  | +        Break;
 | 
	
		
			
				|  |  | +      end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      I := 0;
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    Inc(I);
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Process what we have left
 | 
	
		
			
				|  |  | +  CurrentLine := Line;
 | 
	
		
			
				|  |  | +  CurrentANSILine := ANSILine;
 | 
	
		
			
				|  |  | +  ProcessPrompt(CurrentLine);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// ********************************************************************
 | 
	
		
			
				|  |  | +// Process outbound data
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +function TModExtractor.ProcessOutBound(OutData : string; ClientIndex : Byte) : Boolean;
 | 
	
		
			
				|  |  | +begin
 | 
	
		
			
				|  |  | +  Result := TRUE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (OutData[1] = MenuKey) and (TWXMenu.CurrentMenu = nil) then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    // Activate menu
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if not (TWXClient.Connected) then
 | 
	
		
			
				|  |  | +    begin
 | 
	
		
			
				|  |  | +      // User trying to access database while not connected
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if not (TWXDatabase.DataBaseOpen) then
 | 
	
		
			
				|  |  | +        TWXServer.ClientMessage(endl + ANSI_12 + 'Warning: This database is corrupt or does not exist.  No data is available.' + ANSI_7 + endl);
 | 
	
		
			
				|  |  | +    end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    TWXMenu.OpenMenu('TWX_MAIN', ClientIndex);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // run the rest of the text through the menus
 | 
	
		
			
				|  |  | +    if (Length(OutData) > 1) then
 | 
	
		
			
				|  |  | +      ProcessOutBound(Copy(OutData, 2, Length(OutData)), ClientIndex);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    Result := FALSE;
 | 
	
		
			
				|  |  | +  end
 | 
	
		
			
				|  |  | +  else if (TWXMenu.CurrentMenu <> nil) then
 | 
	
		
			
				|  |  | +  begin
 | 
	
		
			
				|  |  | +    if (OutData[1] = MenuKey) then
 | 
	
		
			
				|  |  | +      // De-activate menu
 | 
	
		
			
				|  |  | +      TWXMenu.CloseMenu(TRUE)
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      // Send commands to menu
 | 
	
		
			
				|  |  | +      TWXMenu.MenuText(OutData, ClientIndex);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    Result := FALSE;
 | 
	
		
			
				|  |  | +  end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // don't return a value if trigger had this key
 | 
	
		
			
				|  |  | +  if (Result) and (OutData <> '') then
 | 
	
		
			
				|  |  | +    Result := not TWXInterpreter.TextOutEvent(OutData, nil);
 | 
	
		
			
				|  |  | +end;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +end.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 |