(* UpcaseStr converts a string to upper case *) function UpcaseStr(S : Str80) : Str80; var P : Integer; begin for P := 1 to Length(S) do S[P] := Upcase(S[P]); UpcaseStr := S; end; (* ConstStr returns a string with N characters of value C *) function ConstStr(C : Char; N : Integer) : Str80; var S : string[80]; begin if N < 0 then N := 0; S[0] := Chr(N); FillChar(S[1],N,C); ConstStr := S; end; (* Beep sounds the terminal bell or beeper *) procedure Beep; begin Write(^G); end; procedure InputStr(var S : AnyStr; L,X,Y : Integer; Term : CharSet; var TC : Char ); const UnderScore = '_'; var P : Integer; Ch : Char; begin GotoXY(X + 1,Y + 1); Write(S,ConstStr(UnderScore,L - Length(S))); P := 0; repeat GotoXY(X + P + 1,Y + 1); Read(Kbd,Ch); case Ch of #32..#126 : if P < L then begin if Length(S) = L then Delete(S,L,1); P := P + 1; Insert(Ch,S,P); Write(Copy(S,P,L)); end else Beep; ^S : if P > 0 then P := P - 1 else Beep; ^D : if P < Length(S) then P := P + 1 else Beep; ^A : P := 0; ^F : P := Length(S); ^G : if P < Length(S) then begin Delete(S,P + 1,1); Write(Copy(S,P + 1,L),UnderScore); end; ^H,#127 : if P > 0 then begin Delete(S,P,1); Write(^H,Copy(S,P,L),UnderScore); P := P - 1; end else Beep; ^Y : begin Write(ConstStr(UnderScore,Length(S) - P)); Delete(S,P + 1,L); end; else if not (Ch in Term) then Beep; end; {of case} until Ch in Term; P := Length(S); GotoXY(X + P + 1,Y + 1); Write('' :L - P); TC := Ch; end; procedure Select( Prompt : Str80; Term : CharSet; var TC : Char ); var Ch : Char; begin GotoXY(1,23); Write(Prompt,'? ' ); ClrEol; repeat Read(Kbd,Ch); TC := Upcase(Ch); if not (TC in Term) then Beep; until TC in Term; Write(Ch); end; (* ClearFrame clears the display frame, I.E. Lines 3 to 20 *) procedure ClearFrame; var I : Integer; begin for I := 3 to 20 do begin GotoXY(1,I + 1); ClrEol ; end; end; (* OutForm displays the entry form on the screen *) procedure OutForm; begin GotoXY(7,5); Write('Code :'); GotoXY(29,5); Write('Date :'); GotoXY(1,7); Write('First name :'); GotoXY(29,7); Write('Last name :'); GotoXY(4,9); Write('Company :'); GotoXY(2,10); Write('Address 1 :'); GotoXY(2,11); Write('Address 2 :'); GotoXY(6,13); Write('Phone :'); GotoXY(29,13); Write('Extension :'); GotoXY(2,15); Write('Remarks 1 :'); GotoXY(2,16); Write('Remarks 2 :'); GotoXY(2,17); Write('Remarks 3 :'); end; (* ClearForm clears all fields in the entry form *) procedure ClearForm; begin GotoXY(13,5); Write('' :15); GotoXY(35,5); ClrEol; GotoXY(13,7); Write('' :15); GotoXY(40,7); ClrEol; GotoXY(13,9); ClrEol; GotoXY(13,10); ClrEol; GotoXY(13,11); ClrEol; GotoXY(13,13); Write('' :15); GotoXY(40,13); ClrEol; GotoXY(13,15); ClrEol; GotoXY(13,16); ClrEol; GotoXY(13,17); ClrEol; end; procedure InputCust(var Cust : CustRec); const Term : CharSet = [^E,^I,^M,^X,^Z]; var L : Integer; TC : Char; begin L := 1; with Cust do repeat case L of 1 : InputStr(CustCode,15,12,4,Term,TC); 2 : InputStr(EntryDate,8,34,4,Term,TC); 3 : InputStr(FirstName,15,12,6,Term,TC); 4 : InputStr(LastName,30,39,6,Term,TC); 5 : InputStr(Company,40,12,8,Term,TC); 6 : InputStr(Addr1,30,12,9,Term,TC); 7 : InputStr(Addr2,30,12,10,Term,TC); 8 : InputStr(Phone,15,12,12,Term,TC); 9 : InputStr(PhoneExt,5,39,12,Term,TC); 10 : InputStr(Remarks1,40,12,14,Term,TC); 11 : InputStr(Remarks2,40,12,15,Term,TC); 12 : InputStr(Remarks3,40,12,16,Term,TC); end; if (TC = ^I) or (TC = ^M) or (TC = ^X) then if L = 12 then L := 1 else L := L + 1 else if TC = ^E then if L = 1 then L := 12 else L := L - 1; until (TC = ^M) and (L = 1) or (TC = ^Z); end; (* OutCust displays the customer data contained in Cust *) procedure OutCust(var Cust : CustRec); begin with Cust do begin GotoXY(13,5); Write(CustCode,'' :15 - Length(CustCode)); GotoXY(35,5); Write(EntryDate); ClrEol ; GotoXY(13,7); Write(FirstName,'' :15 - Length(FirstName)); GotoXY(40,7); Write(LastName); ClrEol; GotoXY(13,9); Write(Company); ClrEol; GotoXY(13,10); Write(Addr1); ClrEol; GotoXY(13,11); Write(Addr2); ClrEol; GotoXY(13,13); Write(Phone,'' :15 - Length(Phone)); GotoXY(40,13); Write(PhoneExt); ClrEol; GotoXY(13,15); Write(Remarks1); ClrEol; GotoXY(13,16); Write(Remarks2); ClrEol; GotoXY(13,17); Write(Remarks3); ClrEol; end; end; function KeyFromName(LastNm : Str15; FirstNm : Str10) : Str25; const Blanks = ' '; begin KeyFromName := UpcaseStr(LastNm) + Copy(Blanks,1,15 - Length(LastNm)) + UpcaseStr(FirstNm); end; (* Update is used to update the data base *) procedure Update; var Ch : Char; (* Add is used to add customers *) procedure Add; var DataF : Integer; Ccode : string[15]; KeyN : string[25]; Cust : CustRec; begin with Cust do begin FillChar(Cust,SizeOf(Cust),0); repeat InputCust(Cust); Ccode := CustCode; FindKey(CodeIndexFile, DataF,Ccode); if OK then begin GotoXY(6,19); Write('ERROR : Duplicate customer code'); Beep; end; until not OK; AddRec(DatF,DataF,Cust); AddKey(CodeIndexFile, DataF,CustCode); KeyN := KeyFromName(LastName,FirstName); AddKey(NameIndexFile, DataF,KeyN); GotoXY(6,19); ClrEol; end; end; (* Find is used to find, edit and delete customers *) procedure Find; var D,L,I : Integer; Ch, TC : Char; Ccode, PCode, FirstNm : string[15]; KeyN, PNm : string[25]; LastNm : string[30]; Cust : CustRec; begin if UsedRecs(DatF) > 0 then begin Ccode := ''; repeat InputStr(Ccode,15,12,4,[^M,^Z],TC); if Ccode <> '' then begin FindKey(CodeIndexFile,D,Ccode); if OK then begin GetRec(DatF,D,Cust); OutCust(Cust); end else begin GotoXY(6,19); Write('ERROR : Customer code not found'); Beep; end; end; until OK or (Ccode = ''); GotoXY(6,19); ClrEol; if Ccode = '' then begin L := 1; FirstNm := ''; LastNm := ''; repeat case L of 1 : InputStr(FirstNm,15,12,6,[^I,^M,^Z],TC); 2 : InputStr(LastNm,30,39,6,[^I,^M,^Z],TC); end; if (TC = ^I) or (TC = ^M) then L := 3 - L; until (TC = ^M) and (L = 1) or (TC = ^Z); KeyN := KeyFromName(LastNm,FirstNm); SearchKey(NameIndexFile, D,KeyN); if not OK then PrevKey(NameIndexFile,D,KeyN); repeat GetRec(DatF,D,Cust); OutCust(Cust); Select('Find : N)ext, P)revious, Q)uit',['N','P','Q'],Ch); case Ch of 'N' : repeat NextKey(NameIndexFile, D,KeyN) until OK; 'P' : repeat PrevKey(NameIndexFile, D,KeyN) until OK; end; until Ch = 'Q'; end; Select('Find : E)dit, D)elete, Q)uit',['E','D','Q'],Ch); with Cust do case Ch of 'E' : begin PCode := CustCode; PNm := KeyFromName(LastName,FirstName); repeat InputCust(Cust); if CustCode = PCode then OK := false else begin Ccode := CustCode; FindKey(CodeIndexFile, I,Ccode); if OK then Beep; end; until not OK; PutRec(DatF,D,Cust); if CustCode <> PCode then begin DeleteKey(CodeIndexFile, D,PCode); AddKey(CodeIndexFile, D,CustCode); end; KeyN := KeyFromName(LastName,FirstName); if KeyN <> PNm then begin DeleteKey(NameIndexFile, D,PNm); AddKey(NameIndexFile, D,KeyN); end; end; 'D' : begin DeleteKey(CodeIndexFile,D,CustCode); KeyN := KeyFromName(LastName,FirstName); DeleteKey(NameIndexFile,D,KeyN); DeleteRec(DatF,D); end; end; end { of UsedRecs(DatF) > 0 .. } else Beep; end; begin(* Update*) OutForm; repeat Select('Update : A)dd, F)ind, Q)uit',['A','F','Q'],Ch); case Ch of 'A' : Add; 'F' : Find; end; if Ch <> 'Q' then begin GotoXY(60,2); Write(UsedRecs(DatF) :5); ClearForm; end; until Ch = 'Q'; end; (* List is used to list customers *) procedure List; label Escape; var D,L,LD : Integer; Ch,CO,CS : Char; Ccode : string[15]; KeyN : string[25]; Name : string[35]; Cust : CustRec; begin Select('Output device : P)rinter, S)creen',['P','S'],CO); Select('Sort by : C)ode, N)ame, U)nsorted',['C','N','U'],CS); GotoXY(1,23); Write('Press to abort'); ClrEol; ClearKey(CodeIndexFile); ClearKey(NameIndexFile); D := 0; LD := FileLen(DatF) - 1; L := 3; repeat if KeyPressed then begin Read(Kbd,Ch); if Ch = #27 then goto Escape; end; case CS of 'C' : NextKey(CodeIndexFile,D,Ccode); 'N' : NextKey(NameIndexFile,D,KeyN); 'U' : begin OK := false; while (D < LD) and not OK do begin D := D + 1; GetRec(DatF,D,Cust); OK := Cust.CustStatus = 0; end; end; end; if OK then with Cust do begin if CS <> 'U' then GetRec(DatF,D,Cust); Name := LastName; if FirstName <> '' then Name := Name + ', ' + FirstName; if CO = 'P' then begin Write(Lst,CustCode,'' :16 - Length(CustCode)); Write(Lst,Name,'' :36 - Length(Name)); Writeln(Lst,Copy(Company,1,25)); end else begin if L = 21 then begin GotoXY(1,23); Write('Press to continue'); Write(' or to abort'); ClrEol; repeat Read(Kbd,Ch) until (Ch = ^M) or (Ch = #27); if Ch = #27 then goto Escape; GotoXY(1,23); Write('Press to abort'); ClrEol; ClearFrame; L := 3; end; GotoXY(1,L + 1); Write(CustCode); GotoXY(17,L + 1); Write(Name); GotoXY(53,L + 1); Write(Copy(Company,1,25)); L := L + 1; end; { of with Cust do .. } end; { of if OK .. } until not OK; if CO = 'S' then begin GotoXY(1,23); Write('Press '); ClrEol; repeat Read(Kbd,Ch) until Ch = ^M; end; Escape : end;