{*************************************************************************
 ***                                                                   ***
 ***                     v4 OBSOLETE JIMMYS                            ***
 ***                                                                   ***
 *************************************************************************}
{$I compflgs}

{NB OldContact record in Tv4Company.Load is almost certainly wrong...}

{OLD OBJECTS - For use with the update program.  Old Objects no longer
used but that may exist in older systems}

{When an update, involving a complete jimmy file read & write, is done then
all the old code for old jimmy data versions is no longer required.  So
such objects are descended here, and somehow we have to reregister the
object sr type....}
unit Upv4Objs;

INTERFACE

uses kdirctry, inpfname, dattime, notes, kcompany,
			objects, smoney, kperson, jimmys, files;


type
	Pv4Company = ^Tv4Company;
	Tv4Company = object(TCompany)
		AddressLine : array[1..5] of string[35];
		Postcode : string[9];
		Country : string[3];
		telNo : array[1..4] of string[25];
		email : string[25];
		Contact : array[1..4] of longint;
		Ptr2Ref, Ptr2Inv : longint;
		function RecSize : Word; virtual;
		constructor Load(var S : TDataStream);
	end;


type
	Pv4Person = ^Tv4Person;
	Tv4Person = object(TPerson)
		AddressLine : array[1..7] of string;
		Postcode : string;
		Country : string[3];
		telNo : array[1..4] of string[25];
		email : string;
		Ptr2Ref, Ptr2Inv : longint;
		constructor Load(var S : TDataStream);
		function RecSize : Word; virtual;
	end;

 Pv4Member = ^Tv4Member;
 Tv4Member = object(TDirectoryItem)
	 Surname : string[30];
	 ForName : string[25];
	 Title   : string[10];

	 DearName: string[15];
	 CategoryCode : string[3];

	 MemNum			: string[20]; 					{Membership number}

	 Job : string[20];
	 Coy : string[30];   {place of work}

	 AddressLine : array[1..6] of string[35];
	 PostCode: string[9];
	 Country : string[3];
	 TelNo   : array[1..3] of string[25];

	 DOJoining : TDate; 							{Date of joining}
	 DOExpiry:	TDate;								{Date of membership expiry}
	 DOBirth : TDate; 							{Date of birth}

	 SearchCodes  : string[20];        {SearchCodes codes}
	 Comment : PFreeTextData;				{see inptext}

		function RecSize : Word; virtual;
		constructor Load(var S : TDataStream);
 end;

type
	PAltAddress = ^TAltAddress;
	TAltAddress = object(TJimmy)

		WhoFor : longint;

		DateRange : TDateRange;

		apType 		: word;

		AddressLine   : array[1..7] of string[35];
		Postcode  : string[9];
		Country   : string[3];

		TelNo     : array[1..2] of string[25];

{		constructor Init(const Param : Pointer);{}

		constructor Load(var S : TDataStream);

		function RecSize : word; virtual;
		function srType : word; virtual;
 end;

{============= OLD v1-4 SPLIT LETTER TYPES ==================}
{const
	Tv4LetterSize = 50;{}

	{--- Base type ----}
	Pv4Letter = ^Tv4Letter;
	Tv4Letter = object(TJimmy)

		Date      : TDate;                 {Date of writing}
		ToWho     : longint;               {Pointer to who it is to}
		ReWho     : longint;
		ByWho     : longint;               {Who typed it}
		Codes     : string[12];            {Description codes}
		Ref       : string[6];             {Any old reference string}
		Header    : string[8];             {Header form name}
		Copies    : byte;                  {No. copies}

		Ext 			 : string;
		PAth      : string;
		FileEditor : TFileEditorProc;
		DescendantsrType    : word;

{		constructor Init(Params : pointer);{}
		destructor Done; virtual;
		procedure CommonInit; virtual;

		constructor Load(var S : TDataStream);
	end;

	{--- std letter base type ----}
	PStdLetter = ^TStdLetter;
	TStdLetter = object(Tv4Letter)

		{Uses header form as form name}

		procedure CommonInit; virtual;

		constructor  Load(var S : TDataStream);
		function RecSize : word; virtual;
	end;

	{--- Editor letter ---}
	PEDLtr = ^TEDLtr;
	TEDLtr = object(Tv4Letter)

		Body      : PLetterData;
		Width     : longint;  {width of line}

		procedure CommonInit; virtual;
		destructor Done; virtual;

		constructor Load(var S : TDataStream);
		function RecSize : word;         virtual;
		function srType : word; virtual;

	end;

	{--- std editor letter ---}
	PStdEdLetter = ^TStdEdLetter;
	TStdEdLetter = object(TStdLetter)
		function srType : word; virtual;
	end;

	{--- wordperfect letter ----}
	PWPLtr = ^TWPLtr;
	TWPLtr = object(Tv4Letter)

		FirstTextRec : longint;             {Ptr to first in chain of text blocks}

		Loaded : boolean;                   {Marker for whether text is loaded}

		WPVer : byte;                        {version of WP used at the time of storage}
																			 {50 = 5.0, 51 = 5.1, 60 = 6.0 etc}
{		constructor Init(P : pointer);{}
		procedure CommonInit; virtual;

		constructor Load(var S : TDataStream);
		function RecSize : word; virtual;
		function srType : word; virtual;

		procedure   LoadText(InsBegin4Edit : boolean);
	end;

	{--- std wp letter ---}
	PStdWPLetter = ^TStdWPLetter;
	TStdWPLetter = object(TStdLetter)
		procedure CommonInit; virtual;

		function srType : word; virtual;
	end;

	Pv4Product = ^Tv4Product;
	Tv4Product = object(TJimmy)

		CategoryIdx : longint;
		Category2Idx : longint;
		CodeIdx : longint;

		Categories : string[11];
		Desc : string[20];
		Code : string[20];			{for catalogue code/etc reference}

		Units : array[0..3] of string[3];

		Supplier : longint;
		Quoter    : string[20];  {name of quoter}
		QuoteDate : TDate;
		QuotedCost : array[0..3] of TSimpleMoney;

		PriceBand : array[1..3] of record
			Band : string[3];
			Margin : integer;
			Price : array[0..3] of TSimpleMoney;
		end;

		NumInStock : array[0..3] of integer;       {Number in stock}
		OnOrder		: array[0..3] of integer;       {committed}
		Sold		 : array[0..3] of integer;       {committed}
		WarningLevel : array[0..3] of integer;			{Warning level for number left in stock}

		Location : string[11]; {Sentence code line}

		constructor Load(var S : TDataStream);
		function RecSize : word; virtual;
		function srType : word; virtual;
	end;

{used by kperson, kcompany as part of load if ver check fails}
function TPersonLoad(const Person : PJimmy; const Ver : byte; var S : TDataStream) : boolean;
function TCompanyLoad(const Company : PJimmy; const Ver : byte; var S : TDataStream) : boolean;

IMPLEMENTATION


uses  help,
			minilib,
			global, lstrings, editfile, scodes, dos, kwplink, address, tuimsgs;

const
	{make sure this one is registered first, so that it puts the new one}
 ROldSCodeItem : TStreamRec = (
	 ObjType : OldsrSCode;
	 VmtLink : Ofs(TypeOf(TSCodeItem)^);
	 Load : @TSCodeItem.Load;
	 Store : @TSCodeItem.Store
 );

const
	{make sure this one is registered first, so that it puts the new one}
 Rv3DirCatSCodeItem : TStreamRec = (
	 ObjType : srv3DirCatSCodeItem;
	 VmtLink : Ofs(TypeOf(TSCodeItem)^);
	 Load : @TSCodeItem.Load;
	 Store : @TSCodeItem.Store
 );



{********************************************************
 ***                                                  ***
 ***           OLD COMPANY (v1-4 PRE-ADDRESSING)      ***
 ***                                                  ***
 ********************************************************}

const
	 {--- Required for Stream ----}
	 Rv4Company : TStreamRec = (
		ObjType : srOldCompany;
		 VmtLink : Ofs(TypeOf(Tv4Company)^);
		 Load : @Tv4Company.Load;
		 Store : @Tv4Company.Store
	 );

function Tv4Company.RecSize : Word;
begin RecSize := 450 + 30; end;

constructor Tv4Company.Load;
var CategoryCode : TSCOde;
		Ver : byte;
		I : integer;
		OldContact : array[1..4] of record
			Desc : string[10];
			FilePtr : longint;
		end;
		OldComment : string;
		TempS : string;
		R : longint;

begin
	Ptr2Addresses := -1;
	Ptr2Ref := -1;
	Ptr2Inv := -1;
	DeptFor := -1;
	Ptr2Contacts := -1;
	Ptr2Accounts := -1;
	for I := 1 to 5 do CategoryIdx[I] := -1;

	R := S.GetPos-2;

	S.Read(Ver, 1);
	case Ver of
		8: begin
			{15/12/93 Splitting of Company vs Person, multi-index, etc}

			CommonInit;

			S.Read(Dat2Idx, sizeof(dat2idx));
			S.Read(AliasIdx, sizeof(AliasIdx));
			S.Read(CategoryIdx[1], 4);
			S.Read(ArchiveIdx, sizeof(ArchiveIdx));

			DOReg.Load(S);

			S.Read(Ptr2History, 4);
			S.Read(Ptr2More, 4);
			S.Read(LockTerminal,1);       {NB Lock position fixed - see Load/StoreLock below}
			S.Read(Deleted, sizeof(Deleted));

			RecNo := -1;  {not set yet}

			CategoryIdx[1] := -1;;

			{Company name also stored in index}
			CompanyName  := S.ReadStr;
			Alias := S.ReadStr;{}
{DebugNote('UOLDOBJS','Reading Old Company ver 8 "'+CompanyName+'" #'+N2Str(R));{}

			S.Read(CategoryCode, sizeof(CategoryCode)); CategoryCode := delspace(CategoryCode);

			{and change category code to new code standards}
			if CategoryCode = '4' then CategoryCode := 'CUS';
			if CategoryCode = '5' then CategoryCode := 'PRO';
			if CategoryCode = '6' then CategoryCode := 'SUP';
			if CategoryCode = '7' then CategoryCode := 'STA';

			for I := 1 to 5 do AddressLine[I] := S.ReadStr;
			PostCode := S.ReadStr;
			S.Read(Country, sizeof(Country));

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			email := '';

			for I := 1 to 4 do begin
				S.Read(OldContact, sizeof(OldContact));
				Contact[I] := OldCOntact[I].FilePtr;
			end;

			CategoryCodes := delspace(delspaceR(CategoryCode) + ' '+S.ReadStr);
			OldComment  := S.ReadStr; LSAppendStr(Comment^.Text, OldComment); Comment^.Loaded := True;
		end;
		9: begin
			{28/7/94 Added text comment}

			CommonInit;

			S.Read(Dat2Idx, sizeof(dat2idx));
			S.Read(AliasIdx, sizeof(AliasIdx));
			S.Read(CategoryIdx[1], 4);
			S.Read(ArchiveIdx, sizeof(ArchiveIdx));

			DOReg.Load(S);

			S.Read(Ptr2History, 4);
			S.Read(Ptr2More, 4);
			S.Read(LockTerminal,1);       {NB Lock position fixed - see Load/StoreLock below}
			S.Read(Deleted, sizeof(Deleted));

			RecNo := -1;  {not set yet}

			CategoryIdx[1] := -1;;

			{Company name also stored in index}
			CompanyName  := S.ReadStr;
			Alias := S.ReadStr;{}
{DebugNote('UOLDOBJS','Reading Old Company ver 9 "'+CompanyName+'" #'+N2Str(R));{}

			S.Read(CategoryCode, sizeof(CategoryCode)); CategoryCode := delspace(CategoryCode);

			{and change category code to new code standards}
			if CategoryCode = '4' then CategoryCode := 'CUS';
			if CategoryCode = '5' then CategoryCode := 'PRO';
			if CategoryCode = '6' then CategoryCode := 'SUP';
			if CategoryCode = '7' then CategoryCode := 'STA';

			for I := 1 to 5 do AddressLine[I] := S.ReadStr;
			PostCode := S.ReadStr;
			S.Read(Country, sizeof(Country));

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			email := '';


			for I := 1 to 4 do begin
				S.Read(OldContact, sizeof(OldContact));
				Contact[I] := OldCOntact[I].FilePtr;
			end;

			CategoryCodes := delspace(delspaceR(CategoryCode) + ' '+S.ReadStr);
			Comment^.Load(S);
		end;
		10: begin
			{15/8/94 Removed description field from contact - leave user to put that
			in job title field, which then appears on inputdir line}

			CommonInit;

			S.Read(Dat2Idx, sizeof(dat2idx));
			S.Read(AliasIdx, sizeof(AliasIdx));
			S.Read(CategoryIdx[1], 4);
			S.Read(ArchiveIdx, sizeof(ArchiveIdx));

			DOReg.Load(S);

			S.Read(Ptr2History, 4);
			S.Read(Ptr2More, 4);
			S.Read(LockTerminal,1);       {NB Lock position fixed - see Load/StoreLock below}
			S.Read(Deleted, sizeof(Deleted));

			RecNo := -1;  {not set yet}

			CategoryIdx[1] := -1;;

			{Company name also stored in index}
			CompanyName  := S.ReadStr;
			Alias := S.ReadStr;{}
{DebugNote('UOLDOBJS','Reading Old Company ver 10 "'+CompanyName+'" #'+N2Str(R));{}

			S.Read(CategoryCode, sizeof(CategoryCode)); CategoryCode := delspace(CategoryCode);

			{and change category code to new code standards}
			if CategoryCode = '4' then CategoryCode := 'CUS';
			if CategoryCode = '5' then CategoryCode := 'PRO';
			if CategoryCode = '6' then CategoryCode := 'SUP';
			if CategoryCode = '7' then CategoryCode := 'STA';

			for I := 1 to 5 do AddressLine[I] := S.ReadStr;
			PostCode := S.ReadStr;
			S.Read(Country, sizeof(Country));

			for I := 1 to 4 do TelNo[I] := S.ReadStr;
{DebugNote('UOLDOBJS  Reading tels of '+CompanyName,TelNo[1]+#13+TelNo[2]+#13+TelNo[3]);{}

			email := '';

			for I := 1 to 4 do S.Read(Contact[I], sizeof(Contact[I]));

			CategoryCodes := delspace(delspaceR(CategoryCode) + ' '+S.ReadStr);
			Comment^.Load(S);
		end;

		11: begin
			{17/7/95 added email address}

			CommonInit;

			S.Read(Dat2Idx, sizeof(dat2idx));
			S.Read(AliasIdx, sizeof(AliasIdx));
			S.Read(CategoryIdx[1], 4);
			S.Read(ArchiveIdx, sizeof(ArchiveIdx));

			DOReg.Load(S);

			S.Read(Ptr2History, 4);
			S.Read(Ptr2More, 4);
			S.Read(LockTerminal,1);       {NB Lock position fixed - see Load/StoreLock below}
			S.Read(Deleted, sizeof(Deleted));

			RecNo := -1;  {not set yet}


			CategoryIdx[1] := -1;;

			{Company name also stored in index}
			CompanyName  := S.ReadStr;
			Alias := S.ReadStr;{}
{DebugNote('UOLDOBJS','Reading Old Company ver 11 "'+CompanyName+'" #'+N2Str(R));{}

			S.Read(CategoryCode, 4); CategoryCode := delspace(CategoryCode);

			{and change category code to new code standards}
			if CategoryCode = '4' then CategoryCode := 'CUS';
			if CategoryCode = '5' then CategoryCode := 'PRO';
			if CategoryCode = '6' then CategoryCode := 'SUP';
			if CategoryCode = '7' then CategoryCode := 'STA';

			for I := 1 to 5 do AddressLine[I] := S.ReadStr;
			PostCode := S.ReadStr;
			S.Read(Country, sizeof(Country));

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			email := S.ReadStr;

			for I := 1 to 4 do S.Read(Contact[I], sizeof(Contact[I]));

			CategoryCodes := delspace(delspaceR(CategoryCode) + ' '+S.ReadStr);
			Comment^.Load(S);
		end;
	else
		ProgramError('Loading v4 Company'#13'Unrecognised ver '+N2Str(Ver),hcInternalErrorMsg);
		fail;
	end;
end;


{********************************************************
 ***                                                  ***
 ***           v1-4 PERSON (PRE-ADDRESSING)           ***
 ***                                                  ***
 ********************************************************}

const
	 {--- Required for Stream ----}
	 Rv4Person : TStreamRec = (
		 ObjType : srOldPerson;
		 VmtLink : Ofs(TypeOf(Tv4Person)^);
		 Load : @Tv4Person.Load;
		 Store : @Tv4Person.Store
	 );

function Tv4Person.RecSize : Word;
begin RecSize := 500 + 30; end;



constructor Tv4Person.Load;
var CategoryCode : TSCode;
		Ver : byte;
		I : integer;
begin
	Ptr2Addresses := -1;
	Ptr2Ref := -1;
	Ptr2Inv := -1;
	ContactFor := -1;
	Ptr2Contacts := -1;
	Ptr2Accounts := -1;
	for I := 1 to 5 do CategoryIdx[I] := -1;

	S.Read(Ver, 1);

	case Ver of
		9 : begin
			{23/7/94 Changed comment string to an inputString type (See inptext)}

			CommonInit;

			S.Read(Dat2Idx, sizeof(dat2idx));
			S.Read(AliasIdx, sizeof(AliasIdx));
			S.Read(CategoryIdx[1], 4);
			S.Read(ArchiveIdx, sizeof(ArchiveIdx));

			DOReg.Load(S);

			S.Read(Ptr2History, 4);
			S.Read(Ptr2More, 4);
			S.Read(LockTerminal,1);       {NB Lock position fixed - see Load/StoreLock below}
			S.Read(Deleted, sizeof(Deleted));

			RecNo := -1;  {not set yet}

			CategoryIdx[1] := -1;;

			{Surname/Forename also stored in index}
			Surname  := S.ReadStr;
			ForName  := S.ReadStr;
			Title    := S.ReadStr;
			DearName := S.ReadStr;
			S.Read(ContactFor, 4);
			S.Read(CategoryCode, 4); CategoryCode := delspaceR(CategoryCode); {was category}

			{and change category code to new code standards}
			if CategoryCode = '4' then CategoryCode := 'CUS';
			if CategoryCode = '5' then CategoryCode := 'PRO';
			if CategoryCode = '6' then CategoryCode := 'SUP';
			if CategoryCode = '7' then CategoryCode := 'STA';

			for I := 1 to 7 do AddressLine[I] := S.ReadStr;
			PostCode := S.ReadStr;
			S.Read(Country, sizeof(Country));

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			email := '';
			for I := 1 to 4 do if pos('@',TelNo[I])>0 then email := TelNo[I];

			CategoryCodes := delspace(delspaceR(CategoryCode) + ' '+S.ReadStr);
			Comment^.Load(S);

			S.Read(Ptr2Inv, 4);
			S.Read(Ptr2Ref, 4);

		end;
		10 : begin
			{23/7/94 Changed comment string to an inputString type (See inptext)}
			{15/12/95 Combined category/search codes}

			CommonInit;

			S.Read(Dat2Idx, sizeof(dat2idx));
			S.Read(AliasIdx, sizeof(AliasIdx));
			S.Read(CategoryIdx[1], 4);
			S.Read(ArchiveIdx, sizeof(ArchiveIdx));

			DOReg.Load(S);

			S.Read(Ptr2History, 4);
			S.Read(Ptr2More, 4);
			S.Read(LockTerminal,1);       {NB Lock position fixed - see Load/StoreLock below}
			S.Read(Deleted, sizeof(Deleted));

			RecNo := -1;  {not set yet}

			CategoryIdx[1] := -1;;

			{Surname/Forename also stored in index}
			Surname  := S.ReadStr;
			ForName  := S.ReadStr;
			Title    := S.ReadStr;
			DearName := S.ReadStr;
			S.Read(ContactFor, 4);
			S.Read(CategoryCode, 4); CategoryCode := delspaceR(CategoryCode); {was category}

			{and change category code to new code standards}
			if CategoryCode = '4' then CategoryCode := 'CUS';
			if CategoryCode = '5' then CategoryCode := 'PRO';
			if CategoryCode = '6' then CategoryCode := 'SUP';
			if CategoryCode = '7' then CategoryCode := 'STA';

			for I := 1 to 7 do AddressLine[I] := S.ReadStr;
			PostCode := S.ReadStr;
			S.Read(Country, sizeof(Country));

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			email := S.ReadStr;

			CategoryCodes := delspace(CategoryCode + ' '+S.ReadStr);
			Comment^.Load(S);

			S.Read(Ptr2Inv, 4);
			S.Read(Ptr2Ref, 4);

		end;

	else
		ProgramError('Loading Person'#13'Unrecognised ver '+N2Str(Ver),hcInternalErrorMsg);
		fail;
	end;
end;

{********************************************************
 ***                                                  ***
 ***           v1-4 MEMBER                            ***
 ***                                                  ***
 ********************************************************}

const
	 {--- Required for Stream ----}
	 Rv4Member : TStreamRec = (
		 ObjType : srv4Member;
		 VmtLink : Ofs(TypeOf(Tv4Member)^);
		 Load : @Tv4Member.Load;
		 Store : @Tv4Member.Store
	 );

function Tv4Member.RecSize : Word;
begin RecSize := 500 + 30; end;



constructor Tv4Member.Load;
var	Ver : byte;
		I : integer;
		Ch,Ch2 : char;
begin
	Ptr2Addresses := -1;
	Ptr2Contacts := -1;
	Ptr2Accounts := -1;
	for I := 1 to 5 do CategoryIdx[I] := -1;

	S.Read(Ver, 1);

	case Ver of
		1 : begin

			CommonInit;

			S.Read(Dat2Idx, sizeof(dat2idx));
			S.Read(AliasIdx, sizeof(AliasIdx));
			S.Read(CategoryIdx[1], 4);
			S.Read(ArchiveIdx, sizeof(ArchiveIdx));

			DOReg.Load(S);

			S.Read(Ptr2History, 4);
			S.Read(Ptr2More, 4);
			S.Read(LockTerminal,1);       {NB Lock position fixed - see Load/StoreLock below}
			S.Read(Deleted, sizeof(Deleted));

			RecNo := -1;  {not set yet}

			Ptr2More := -1;
			Ptr2History := -1; {clear history/more lists for conservative club}

			{Surname/Forename also stored in index}
			Surname  := S.ReadStr;
			ForName  := S.ReadStr;
			Title    := S.ReadStr;
			DearName := S.ReadStr;
			S.Read(CategoryCode, sizeof(CategoryCode));

			Job := '';
			Coy := '';

			for I := 1 to 6 do AddressLine[I] := S.ReadStr;
			PostCode := S.ReadStr;
			S.Read(Country, sizeof(Country));

			for I := 1 to 3 do TelNo[I] := S.ReadStr;

			{defunct membership number}
			repeat	S.Read(Ch,1); until Ch<>#0; S.Seek(S.GetPos-1);

			DOJoining.Load(S);
			DOExpiry.Load(S);
			DOBirth.Clear;

			MemNum := '';
			{it might be a date following, one of the later TMembers with DOB}
{			S.Read(ch,1);
			S.Read(Ch2,1);
			S.Seek(S.GetPos-2);
			if (Ch<#32) and (Ch2<=#12) then DOBirth.Load(S);

			SearchCodes := S.ReadStr;
			Comment^.Load(S);{}
			SearchCodes := CategoryCode;
		end;
	else
		ProgramError('Loading Member'#13'Unrecognised ver '+N2Str(Ver),hcInternalErrorMsg);
	end;
end;


{********************************************************
 ***                                                  ***
 ***           v1-4 ALT ADDRESSES                     ***
 ***                                                  ***
 ********************************************************}
const
	{--- Required for Stream ----}
	RAltAddress : TStreamRec = (
		ObjType : srAltAddress;
		VmtLink : Ofs(TypeOf(TAltAddress)^);
		Load : @TAltAddress.Load;
		Store : @TAltAddress.Store
	);


{Just changed the srtype, still quite a few around, on my database anyway}
	{--- Required for Stream ----}
	Rv2AltAddress : TStreamRec = (
		ObjType : srv2AltAddress;
		VmtLink : Ofs(TypeOf(TAltAddress)^);
		Load : @TAltAddress.Load;
		Store : @TAltAddress.Store
	);{}



{constructor TAltAddress.Init;
begin
	inherited Init;
	if Param <> nil then WhoFor := Plongint(Param)^ else WhoFor := -1;
end;{}

function TAltAddress.RecSize : word;
begin RecSize := 380; end;

function TAltAddress.srtype;
begin srtype := srv2AltAddress; end;

constructor TAltAddress.Load(var S : TDataStream);
var I : integer;
		Ver : byte;
		DearName, AddressName : string; {old and rubbish}

begin
	S.Read(Ver, 1);
	apType := apCorrespondence;

	case Ver of
	4 : begin
		{11/11/94 Checkbox adhtypes not radio button.}

		S.Read(WhoFor, 4);

		DateRange.Start.Load(S);
		DateRange.Finish.Load(S);

		S.Read(apType, 2);

		for I := 1 to 7 do AddressLine[I] := S.ReadStr;
		Postcode  := S.ReadStr;
		Country   := S.ReadStr;

    for I := 1 to 2 do TelNo[I]   := S.ReadStr;
  end;
	3 : begin

		S.Read(WhoFor, 4);

    DateRange.Start.Load(S);
    DateRange.Finish.Load(S);

		S.Read(apType, 2); apType := Exp2(apType); {convert from radio button format to checkbox bits}

		for I := 1 to 7 do AddressLine[I] := S.ReadStr;
    Postcode  := S.ReadStr;
		Country   := S.ReadStr;

    for I := 1 to 2 do TelNo[I]   := S.ReadStr;
	end;
	2 : begin

		S.Read(WhoFor, 4);

		DateRange.Start.Load(S);
    DateRange.Finish.Load(S);

		DearName  := S.ReadStr;
		AddressName := S.ReadStr;
		for I := 1 to 7 do AddressLine[I] := S.ReadStr;
    Postcode  := S.ReadStr;
		Country   := S.ReadStr;

		for I := 1 to 2 do TelNo[I]   := S.ReadStr;
  end;
  1 : begin

		S.Read(WhoFor, 4);

    DateRange.Start.Load(S);
		DateRange.Finish.Load(S);

		DearName  := S.ReadStr;
		AddressName := S.ReadStr;
		for I := 1 to 7 do AddressLine[I] := S.ReadStr;
		Postcode  := S.ReadStr;
    Country   := S.ReadStr;

		for I := 1 to 2 do TelNo[I]   := S.ReadStr;

	end else
		ProgramWarning('Version '+N2Str(Ver)+' not understood'#13'Alt Address Load',hcInternalErrorMsg);
	end;
end;


{********************************************************
 ***                                                  ***
 ***           v1-4 LETTERS (SPLIT TYPES)             ***
 ***                                                  ***
 ********************************************************}

{********************************
 ***      ROOT LETTER         ***
 ********************************}
{constructor Tv4Letter.Init;
begin
	inherited Init;
	Date.SetToToday;
	ToWho := -1;      {Default's to who the letter is about}
{	ReWho := -1;      {Who the letter is about}
{	ByWho := -1;      {Ought to default to user}
{	Copies := 1;
	Header := 'LETTER';  {Default to Letter header}
	{EditorType := edNone;{}

{	if Params <> nil then ToWho := Plongint(Params)^;
end;

{Used by constructors Init and Load}
procedure Tv4Letter.CommonInit;
begin
	inherited CommonInit;
	SCodeCollection[scLetters]^.LogOn;

	FileAdmin(fiJimmys)^.LogOn;

	{default to standard text type}
	Ext := 'HDR';
	Path := '';
	DescendantsrType := 0;
	FileEditor := EditTextFile;
end;

destructor Tv4Letter.Done;
begin
	SCodeCollection[scLetters]^.LogOff;
	FileAdmin(fiJimmys)^.LogOff;
	inherited Done;
end;


constructor Tv4Letter.Load(var S : TDataStream);
var Ver : byte;
begin
	S.Read(Ver, 1);

	case ver of
		1 : begin
			{This one would overflow if codes was too long}
			Date.Load(S);
			S.Read(ToWho, 4);
			S.Read(ByWho, 4);
			Codes := S.ReadStr;
			S.Read(Ref,   sizeof(Ref));
			S.Read(Header, sizeof(Header));
			S.Read(Copies, sizeof(Copies));
			S.Read(rewho, 4); {rubbish}
			S.Read(reWho, 4);
		end;
		2 : begin
			Date.Load(S);
			S.Read(ToWho, 4);
			S.Read(ByWho, 4);
			Codes := S.ReadFixedStr(12);
			Ref := S.ReadFixedStr(6);
			Header := S.ReadFixedStr(8);
			S.Read(Copies, sizeof(Copies));
			S.Read(rewho, 4); {rubbish}
			S.Read(ReWho, 4);
		end;
	end; {Case}

	Codes := DelSpace(Codes);
	CommonInit;  {Log on to JimmyStream & check codes are open}
end;

{********************************
 ***    STD ROOT LETTER       ***
 ********************************}
procedure TStdLetter.CommonInit;
begin
	inherited CommonInit;
	Ext := 'STL'; {override to provide standard forms for Header type}
	DescendantsrType := srStdEdLetter;
end;

constructor TStdLetter.Load(var S : TDAtaStream);
var Ver : byte;
begin
	S.Read(Ver, 1);
	if Ver =1 then begin
		{Ver1 was before stdletter was made a descendant of Tv4Letter, rather than a sister}
		CommonInit;
		Date.Load(S);
		S.Read(Header, sizeof(Header));
		S.Read(Copies, sizeof(Copies));
		S.Read(Towho, 4); {rubbish}
		S.Read(ToWho, 4);
		ReWho := ToWho;
		ByWho := -1;
	end else begin {the old load - as above - was ver 1.  The one below starts at ver 2 at this stage}
		S.Seek(S.GetPos-1);  {Wind back to read ver again}
		inherited Load(S);
	end;
end;

function TStdLetter.Recsize;
begin RecSize := 50; end;

{********************************
 ***    EDITOR LETTER         ***
 ********************************}
const
	{--- Required for Stream ----}
	REdLtr : TStreamRec = (
		ObjType : srEdLtr;
		VmtLink : Ofs(TypeOf(TEdLtr)^);
		Load : @TEdLtr.Load;
		Store : @TEdLtr.Store
	);

{--- Inititalise - set ptrs to SC ---}
procedure TEdLtr.CommonInit;
begin
	inherited CommonInit;
	New(Body, init);
	DescendantsrType := srEdLtr;
end;

destructor TEDLtr.Done;
begin
	Dispose(body, done);
	inherited Done;
end;

constructor TEDLtr.Load(var S : TDataStream);
begin
	inherited Load(S);{}

	body^.Load(S);
end;

function TEDltr.RecSize;
begin RecSize := 60; end;

function TEDLtr.srtype;
begin srtype := srEDLtr; end;


{********************************
 ***    STD EDITOR LETTER     ***
 ********************************}

const
	{--- Required for Stream ----}
	RStdEdLetter : TStreamRec = (
		ObjType : srStdEdLetter;
		VmtLink : Ofs(TypeOf(TStdEdLetter)^);
		Load : @TStdEdLetter.Load;
		Store : @TStdEdLetter.Store
	);

function TStdEdLetter.srtype;
begin srtype := srStdEdLetter; end;


{********************************
 ***      WP LETTER           ***
 ********************************}

{--- Inititalise - set ptrs to SC ---}
{constructor TWPLtr.Init;
begin
	inherited Init(P);
	FirstTextRec := -1;
	WPVer := 0;
	Loaded := False;   {Will always need to load at least header}
{end;{}

procedure TWPLtr.CommonInit;
begin
	inherited CommonInit;
	Path := WPSetup.FormsPath;
	DescendantsrType := srWPLtr;
	FileEditor := EditWPFile;
end;


const
	{--- Required for Stream ----}
	RWPLtr : TStreamRec = (
		ObjType : srWPLtr;
		VmtLink : Ofs(TypeOf(TWPLtr)^);
		Load : @TWPLtr.Load;
		Store : @TWPLtr.Store
	);

constructor TWPLtr.Load(var S : TDataStream);
begin
	inherited Load(S);
	S.Read(FirstTextRec, 4);
	S.Read(WPVer, 1); if (WPVer<50) or (WPVer>60) then WPVer := 51; {default to 5.1}

	Loaded := False;
end;

function TWPltr.RecSize;
begin RecSize := 55; end;

function TWPLtr.srtype;
begin srtype := srWPLtr; end;

{Convert text chain straight into WP letter}
procedure TWPLtr.LoadText(InsBegin4Edit : boolean);
var WPLtrFile : Text;
		WPLtrStream : PWPStream;
		TextFile : PTextStream;
		TextItem : pointer;
		TextRec : longint;
		Attr : word;
		Control : word;
		InString, OutString : string;


begin
	ThinkingOn('Converting to WP');

	{---- Add Header ----}
	{Expand form to temp file on disk}
	New(WPLtrStream, init(WPSetup.LocalPath + Header));

	SetFormCodes(WPLtrStream^.FormCodes);
	WPLtrStream^.StartPrint('',WPSetup.FormsPath+Header);                 {Output standard form to file TEMP}

	{-- add beginner marker ---}
	if WPLtrStream^.FormFound then {only do beginner marker if header found}
		if InsBegin4Edit then WPLtrStream^.WriteStr(WPSetup.BeginMarker); {Mark end of header if editing - not if printing}

	if WPltrStream^.Status<>stOK then begin
		ProgramError('Could not create WP header',hcInternalErrorMsg);
		Loaded := False;  {Make sure marked as unloaded}
		ThinkingOff;
		exit;
	end;

	{---- Add Body ------}
	if FirstTextRec = -1 then begin               {If new}
		 WPLtrStream^.PrintForm(WPSetup.FormsPath + Header+'.FRM');        {add Standard form}
	end else begin
		 Outstring := ''; {for decoding each line below}
		 New(TextFile, init('WPLTRS.DAT', TLetterItemSize, StreamBufSize));
		 TextRec := FirstTextRec;
		 while TextRec > -1 do begin
				TextItem := TextFile^.GetNext(TextRec);
				if TextItem = nil then begin
					ProgramError('Could not retrieve Text Item for letter'
							+#13'FirstRec #'+N2Str(FirstTextRec),hcInternalErrorMsg);
					TextRec := -1;
				end else begin
					if TextRec = -1 then PTextItem(TextItem)^.Data := DelNulR(PTextItem(TextItem)^.Data);  {Delete last nuls if last one}

					if InsBegin4Edit then {if editing, just write out line as found}
						WPLtrStream^.writeStr(PTextItem(TextItem)^.Data)
					else begin
						{if not, need to decode any codes...}
						{split into two parts as Data may be 255 chars causing overflow if outstring has anything}
						OutString := Outstring + copy(PTextItem(TextItem)^.Data,1,100);
						WPLtrStream^.WriteCodedstr(OutString); {decodes & writes string, leaving outstring with remainder}

						if Length(OutString)>100 then begin
							WPltrStream^.WriteStr(Copy(Outstring,1,length(Outstring)-50)); {do up to last 50 chars}
							Outstring := Right(Outstring, 50);
						end;

						OutString := Outstring + copy(PTextItem(TextItem)^.Data,101,256);
						WPLtrStream^.WriteCodedstr(OutString); {decodes & writes string, leaving outstring with remainder}

						if Length(OutString)>100 then begin
							WPltrStream^.WriteStr(Copy(Outstring,1,length(Outstring)-50)); {do up to last 50 chars}
							Outstring := Right(Outstring, 50);
						end;

					end; {decoding & writing}
					Dispose(PTextItem(TextItem), done);
				end; {text item valid}
		 end; {while}
		 Dispose(TextFile, done);
		 if Outstring<>'' then
			WPLtrStream^.writecodedstr(OutString);
	end;


	WPLtrStream^.EndPrint; {tidy up}
	Dispose(WPLtrStream, done);

	Loaded := True;

	ThinkingOff;
end;


{********************************
 ***       STD WP LETTER      ***
 ********************************}
const
	{--- Required for Stream ----}
	RStdWPLetter : TStreamRec = (
		ObjType : srStdWPLetter;
		VmtLink : Ofs(TypeOf(TStdWPLetter)^);
		Load : @TStdWPLetter.Load;
		Store : @TStdWPLetter.Store
	);

procedure TStdWPLetter.CommonInit;
begin
	inherited CommonInit;
	Ext := 'STL';
	Path := WPSetup.FormsPath;
	DescendantsrType := srStdWPLetter;
	FileEditor := EditWPFile;
end;

function TStdWPLetter.srtype;
begin srtype := srStdWPLetter; end;



{********************************************************
 ***                                                  ***
 ***           v1-4 PRODUCTS                          ***
 ***                                                  ***
 ********************************************************}
const
	{--- Required for Stream ----}
	Rv4Product : TStreamRec = (
		ObjType : srv4Product;
		VmtLink : Ofs(TypeOf(Tv4Product)^);
		Load : @Tv4Product.Load;
		Store : @Tv4Product.Store
	);
function Tv4product.recsize;
begin recsize := 250; end;

function tv4product.srtype;
begin srtype := srv4product; end;


constructor Tv4Product.Load;
var Ver : byte;
		I,L : longint;

begin
	CommonInit;  {defaults, etc}
	S.Read(Ver, 1);
	RecNo := -1; {not set yet}
	Category2Idx := -1;

	for I := 0 to 3 do begin
		NumInStock[I] := 0;
		Sold[I] := 0;
		OnOrder[I] := 0;
		WarningLevel[I] := 0;
	end;

	{NB - Version 4 has a changed file structure - 250 bytes per product instead
	of 100 - so all others are strictly invalid - the record should have been converted}
	case Ver of
		7 : begin
			{6/12/95 Added 2nd index}
			S.Read(CategoryIdx, sizeof(CategoryIdx));
			S.Read(CodeIdx, sizeof(CodeIdx));
			S.Read(LockTerminal, 1);
			S.Read(Category2Idx, 4);
			S.Read(Deleted, sizeof(Deleted));

			Categories := S.ReadStr;
			Desc := S.ReadStr;
			Code := S.ReadStr;

			for I := 0 to 3 do S.Read(Units[I], sizeof(TSCode));

			S.Read(Supplier, sizeof(Supplier));
			QuoteDate.Load(S);
			S.Read(Quoter, sizeof(Quoter));
			for I := 0 to 3 do QuotedCost[I].Load(S);

			for L := 1 to 3 do begin
				S.Read(PriceBand[L].Band, sizeof(TSCode));
				S.Read(PriceBand[L].Margin,2);
				for I := 0 to 3 do PriceBand[L].Price[I].Load(S);
			end;

			Location := S.ReadStr;
			for I := 0 to 3 do S.Read(NumInStock[I], sizeof(NumInStock[I]));
			for I := 0 to 3 do S.Read(OnOrder[I], sizeof(OnOrder[I]));
			for I := 0 to 3 do S.Read(Sold[I], sizeof(Sold[I]));
			for I := 0 to 3 do S.Read(WarningLevel[I], sizeof(WarningLevel[I]));
		end;
		6 : begin
			{30/11/94 Added unit stock bits}
			S.Read(CategoryIdx, sizeof(CategoryIdx));
			S.Read(CodeIdx, sizeof(CodeIdx));
			S.Read(LockTerminal, 1);
			S.Read(Deleted, sizeof(Deleted));

			Categories := S.ReadStr;
			Desc := S.ReadStr;
			Code := S.ReadStr;

			for I := 0 to 3 do S.Read(Units[I], sizeof(TSCode));

			S.Read(Supplier, sizeof(Supplier));
			QuoteDate.Load(S);
			S.Read(Quoter, sizeof(Quoter));
			for I := 0 to 3 do QuotedCost[I].Load(S);

			for L := 1 to 3 do begin
				S.Read(PriceBand[L].Band, sizeof(TSCode));
				S.Read(PriceBand[L].Margin,2);
				for I := 0 to 3 do PriceBand[L].Price[I].Load(S);
			end;

			Location := S.ReadStr;
			for I := 0 to 3 do S.Read(NumInStock[I], sizeof(NumInStock[I]));
			for I := 0 to 3 do S.Read(OnOrder[I], sizeof(OnOrder[I]));
			for I := 0 to 3 do S.Read(Sold[I], sizeof(Sold[I]));
			for I := 0 to 3 do S.Read(WarningLevel[I], sizeof(WarningLevel[I]));
		end;
		5 : begin
			{Stored desc & code as part of main record - not only in index}
			S.Read(CategoryIdx, sizeof(CategoryIdx));
			S.Read(CodeIdx, sizeof(CodeIdx));
			S.Read(LockTerminal, 1);
			S.Read(Deleted, sizeof(Deleted));

			Categories := S.ReadStr;
			Desc := S.ReadStr;
			Code := S.ReadStr;

			for I := 0 to 3 do S.Read(Units[I], sizeof(TSCode));

			S.Read(Supplier, sizeof(Supplier));
			QuoteDate.Load(S);
			S.Read(Quoter, sizeof(Quoter));
			for I := 0 to 3 do QuotedCost[I].Load(S);

			for L := 1 to 3 do begin
				S.Read(PriceBand[L].Band, sizeof(TSCode));
				S.Read(PriceBand[L].Margin,2);
				for I := 0 to 3 do PriceBand[L].Price[I].Load(S);
			end;

			Location := S.ReadStr;
		end;
		4 : begin
			{Stored desc & code as part of main record - not only in index}
			S.Read(CategoryIdx, sizeof(CategoryIdx));
			S.Read(CodeIdx, sizeof(CodeIdx));
			S.Read(LockTerminal, 1);
			S.Read(Deleted, sizeof(Deleted));

			S.Read(Categories, 4);
			Categories := Categories + S.ReadStr;
			Desc := S.ReadStr;
			Code := S.ReadStr;

			for I := 0 to 3 do S.Read(Units[I], sizeof(TSCode));

			S.Read(Supplier, sizeof(Supplier));
			QuoteDate.Load(S);
			S.Read(Quoter, sizeof(Quoter));
			for I := 0 to 3 do QuotedCost[I].Load(S);

			for L := 1 to 3 do begin
				S.Read(PriceBand[L].Band, sizeof(TSCode));
				PriceBand[L].Margin := 0;
				for I := 0 to 3 do PriceBand[L].Price[I].Load(S);
			end;

			Location := S.ReadStr;
		end;
	else
		DBaseMessage(@S, 'Version '+N2Str(Ver)+' not recognised'#13#10'Tv4Product.Load, UOldObjs.pas',mfError,hcInternalErrorMsg);
		fail;
	end; {case}
end; {proc}


{*******************************************************
 ***           LOAD PERSON                           ***
 *******************************************************}
function TPersonLoad;
var I,L : integer;
		NatID : string;
		TelNo : array[1..4] of string;
		Address : PAddress;
		Company : PCompany;
		Ptr2Inv, Ptr2Ref : longint;
		B : byte;
		LoadedOK : boolean;

begin
	LoadedOK := True; {loaded OK}
	with PPerson(Person)^ do case Ver of
		1 : begin
			{15/12/95 new v4.1 - cat/search codes, addresses, etc}
			CommonInit;

			S.Read(LockTerminal, 1);
			S.Read(Deleted, 1);

			S.Read(ArchiveIdx, 32); {all located one after the other}

			S.Read(Ptr2More, 12);

			S.Read(AddressID, 4);

			DOReg.Load(S);

			{Surname/Forename also stored in index}
			Surname  := S.ReadStr;
			ForName  := S.ReadStr;
			Title    := S.ReadStr;
			DearName := S.ReadStr;

			JobTitle := S.ReadStr;
			Dept := S.ReadStr;
			S.Read(ContactFor, 4);

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			CategoryCodes := S.ReadStr;

			S.Read(Ptr2Inv, 4);
			S.Read(Ptr2Ref, 4);
			NatID := '';
		end;
		2,4 : begin
			{2 - May 96 v4.1b - jimmy handles index/hook ptr storing, not kdirctry}
			{4 - removed natid - placed that onto TSTaff}
			CommonInit;

			S.Read(LockTerminal, 1);
			S.Read(Deleted, 1);

			S.Read(ArchiveIdx, 32); {all located one after the other}

			S.Read(Ptr2More, 12);

			S.Read(AddressID, 4);

			DOReg.Load(S);

			{Surname/Forename also stored in index}
			Surname  := S.ReadStr;
			ForName  := S.ReadStr;
			Title    := S.ReadStr;
			DearName := S.ReadStr;

			JobTitle := S.ReadStr;
			Dept := S.ReadStr;
			S.Read(ContactFor, 4);

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			CategoryCodes := S.ReadStr;

			S.Read(Ptr2Inv, 4);
			S.Read(Ptr2Ref, 4);
			NatID := '';
		end;
		3 : begin
			{added national ID}
			CommonInit;

			S.Read(LockTerminal, 1);
			S.Read(Deleted, 1);

			S.Read(ArchiveIdx, 32); {all located one after the other}

			S.Read(Ptr2More, 12);

			S.Read(AddressID, 4);

			DOReg.Load(S);

			{Surname/Forename also stored in index}
			Surname  := S.ReadStr;
			ForName  := S.ReadStr;
			Title    := S.ReadStr;
			DearName := S.ReadStr;

			JobTitle := S.ReadStr;
			Dept := S.ReadStr;
			S.Read(ContactFor, 4);
			NatID := S.REadStr;

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			CategoryCodes := S.ReadStr;

			S.Read(Ptr2Inv, 4);
			S.Read(Ptr2Ref, 4);
		end;
		5 : begin
			{added tags, contacts list, accounts list, removed telnos to address}
			CommonInit;

			S.Read(LockTerminal, 1);
			S.Read(B, 1); Deleted := (B and $01)>0;

			S.Read(ArchiveIdx, 32); {all located one after the other}

			S.Read(Ptr2More, 20);

			S.Read(AddressID, 4);

			DOReg.Load(S);

			{Surname/Forename also stored in index}
			Surname  := S.ReadStr;
			ForName  := S.ReadStr;
			Title    := S.ReadStr;
			DearName := S.ReadStr;

			JobTitle := S.ReadStr;
			Dept := S.ReadStr;
			S.Read(ContactFor, 4);

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			CategoryCodes := S.ReadStr;

			{botch fix?}
			if (AddressID=-1) and (ContactFor<>-1) then begin
				Company := PCompany(GetJimmy(ContactFor));
				AddressID := Company^.AddressID;
				dispose(Company, done);
			end;
		end;
	else
		DBaseMessage(@S, 'Version '+N2Str(Ver)+' not recognised'#13#10'UP41A_E: TPersonLoad',mfError,hcInternalErrorMsg);
		LoadedOK := False; {failed to load}
	end;

	if LoadedOK then with PPerson(Person)^ do begin
		Tel := nil;
{		Fax := '';{}

		{add telephone/fax to address}
		if AddressID=-1 then begin
			New(Address, init(nil));
			Address^.ForWho := RecNo;
		end else
			Address := PAddress(GetJimmy(AddressID));

		{find fax num}
		L := 1;
		for I := 1 to 4 do begin
			if pos('FAX', ucase(TelNo[I]))>0 then
				Address^.Fax := NewStr(TelNo[I])
			else if delspace(TelNo[I])<>'' then begin
				Address^.Tel[L] := NewStr(TelNo[I]);
				inc(L);
			end;
		end;

		if Address^.recNo = -1 then
			if not Address^.Blank then Address^.StoreSelf
		else
			PutJimmy(Address);

		AddressID := Address^.RecNo;
	end;

	TPersonLoad := LoadedOK;
end;

{*******************************************************
 ***           LOAD COMPANY                          ***
 *******************************************************}
function TCompanyLoad;
var L,I : integer;
		Ptr2Inv, Ptr2Ref : longint;
		TelNo : array[1..4] of string;
		Add :PAddress;
		ParentCoy : PCompany;
		LoadedOK : boolean;

begin
	LoadedOK := True;
	with PCompany(Company)^ do case Ver of
		1: begin
			{26/7/95 New v4.1 - removed contacts, new address, etc}
			CommonINit;

			S.Read(LockTerminal, 1);
			S.Read(Deleted, 1);
			Tag := False;

			S.Read(ArchiveIdx, 32); {all located one after the other}

			S.Read(Ptr2More, 12); {reads ptr2history, more, address}

			S.Read(AddressID, 4);

			DOReg.Load(S);

			{Company name also stored in index}
			CompanyName  := S.ReadStr;
			Alias := S.ReadStr;{}

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			S.Read(Ptr2Inv, 4);
			S.Read(Ptr2Ref, 4);

			CategoryCodes := S.ReadStr;

			Ptr2Contacts := -1;
			Ptr2Accounts := -1;
			DeptFor := -1;
		end;
		2: begin
			{May 96 v4.1b - jimmy handles index/hook ptr storing, not kdirctry}
			CommonInit;

			S.Read(LockTerminal, 1);
			S.Read(Deleted, 1);
			Tag := False;

			S.Read(ArchiveIdx, 32); {all located one after the other}

			S.Read(Ptr2More, 12); {reads ptr2history, more, address}

			S.Read(AddressID, 4);

			DOReg.Load(S);


			{Company name also stored in index}
			CompanyName  := S.ReadStr;
			Alias := S.ReadStr;{}

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			S.Read(Ptr2Inv, 4);
			S.Read(Ptr2Ref, 4);

			CategoryCodes := S.ReadStr;

			Ptr2Contacts := -1;
			Ptr2Accounts := -1;
			DeptFor := -1;
		end;
		3: begin
			{Sep 96 - added accounts list, & contact for}
			CommonInit;

			S.Read(LockTerminal, 1);
			S.Read(Deleted, 1);
			Tag := False;

			S.Read(ArchiveIdx, 32); {all located one after the other}

			S.Read(Ptr2More, 20); {reads ptr2history, more, address, contacts, bills}

			S.Read(AddressID, 4);

			DOReg.Load(S);

			CompanyName  := S.ReadStr;
			Alias := S.ReadStr;{}

			for I := 1 to 4 do TelNo[I] := S.ReadStr;

			S.Read(Ptr2Inv, 4); {ptr2inv}
			S.Read(Ptr2Ref, 4); {ptr2ref}

			CategoryCodes := S.ReadStr;

			S.Read(DeptFor, 4);

			if (AddressID=-1) and (DeptFor<>-1) then begin
				ParentCoy := PCompany(GetJimmy(DeptFor));
				AddressID := ParentCoy^.AddressID;
				dispose(ParentCoy, done);
			end;
		end;
	else
		DBaseMessage(@S, 'Version '+N2Str(Ver)+' not recognised'#13#10'UP41_42: TCompanyLoad',mfError,hcInternalErrorMsg);
		LoadedOK := False;
	end;

	if LoadedOK then with PCompany(Company)^ do begin
		{add telephone/fax to address}
		if AddressID=-1 then begin
			New(Add, init(nil));
			Add^.ForWho := RecNo;
		end else
			Add := PAddress(GetJimmy(AddressID));

		{find fax num}
		L := 1;
		for I := 1 to 4 do begin
			if pos('FAX', ucase(TelNo[I]))>0 then
				Add^.Fax := NewStr(TelNo[I])
			else if delspace(TelNo[I])<>'' then begin
				Add^.Tel[L] := NewStr(TelNo[I]);
				inc(L);
			end;
		end;

		if Add^.recNo = -1 then begin
			if not Add^.Blank then Add^.StoreSelf
		end else
			PutJimmy(Add);

		AddressID := Add^.RecNo;
	end;

	TCompanyLoad := LoadedOK;
end;


{****************************************888
 ***           REGISTER ALL              ***
 *******************************************}

begin
	RegisterType(ROldSCodeItem);  {Register first, so it's there for retrieving but not for saving}
	RegisterType(Rv3DirCatSCodeItem);  {Register first, so it's there for retrieving but not for saving}

	RegisterType(Rv4Company); {remember to comment out registertype in company}
	RegisterType(Rv4Person); {ditto}
	RegisterType(Rv4Member); {ditto}

	RegisterType(Rv2AltAddress); {Register for streams}
	RegisterType(RAltAddress); {Register for streams}

	RegisterSCodeType(scLetters, 'KLetters.SC', 'Letter Types', StdScodeCreator);

	RegisterType(RWPLtr);
	RegisterType(RStdWPLetter);

	RegisterType(REdLtr);
	RegisterType(RStdEdLetter);

	RegisterType(Rv4Product);
end.
