program card_book;

uses crt;

type
  stri1 = string ;
  stri2 = string ;
  pointer = ^item;
  item = record
    name :stri1;
    brand :stri1;
    sport :stri1;
    insert :stri2;
    repeats :stri2;
    number :stri2;
    year :stri2;
    price :stri2;
    next :pointer;
    end;
  dataitem = item;
  filtype = file of item;

var
  quit: boolean;
  start: pointer;
  pb: filtype;

  function load(var f:filtype;start:pointer):pointer; forward;

  procedure init;
  begin
    start := nil;
    assign(pb,'card.dat');
  end;

  function ucas(str:string):string;
  var i:integer;
  begin
    for i:=1 to length(str) do str[i]:=upcase(str[i]);
    ucas := str;
  end;

  procedure heading;
  begin
    clrscr;
    writeln(' Name          Brand          Sport       Year     Card#    Price     Rep   Ins');
    writeln(' ------------------------------------------------------------------------------');
  end;

  procedure display(card:pointer);
  begin
    if card<>nil then
    begin
      if wherey=25 then
      begin
        write('Press enter to continue.');
        readln;
        heading;
      end;
      gotoxy(2,wherey);
      write(card^.name);
      gotoxy(16,wherey);
      write(card^.brand);
      gotoxy(31,wherey);
      write(card^.sport);
      gotoxy(43,wherey);
      write(card^.year);
      gotoxy(52,wherey);
      write(card^.number);
      gotoxy(61,wherey);
      write(card^.price);
      gotoxy(71,wherey);
      write(card^.repeats);
      gotoxy(77,wherey);
      write(card^.insert);
      writeln;
    end;
  end;

  procedure find_name(start:pointer);
  var
    key: string;
  begin
    clrscr;
    gotoxy(20,13);
    write('Enter key word to search for: ');
    readln(key);
    key := ucas(key);
    heading;
    while start <> nil do
    begin
      if pos(key,start^.name)>0 then
      begin
        display(start);
      end;
      start := start^.next;
    end;
    readln;
  end;

  procedure find_number(start:pointer);
  var
    key: string;
  begin
    clrscr;
    gotoxy(20,13);
    write('Enter key word to search for: ');
    readln(key);
    key := ucas(key);
    heading;
    while start <> nil do
    begin
      if pos(key,start^.number)>0 then
      begin
        display(start);
      end;
      start := start^.next;
    end;
    readln;
  end;

  procedure find_price(start:pointer);
  var
    key: string;
  begin
    clrscr;
    gotoxy(20,13);
    write('Enter key word to search for: ');
    readln(key);
    key := ucas(key);
    heading;
    while start <> nil do
    begin
      if pos(key,start^.price)>0 then
      begin
        display(start);
      end;
      start := start^.next;
    end;
    readln;
  end;

  procedure find_sport(start:pointer);
  var
    key: string;
  begin
    clrscr;
    gotoxy(20,13);
    write('Enter key word to search for: ');
    readln(key);
    key := ucas(key);
    heading;
    while start <> nil do
    begin
      if pos(key,start^.sport)>0 then
      begin
        display(start);
      end;
      start := start^.next;
    end;
    readln;
  end;

  procedure find_insert(start:pointer);
  var
    key: string;
  begin
    clrscr;
    gotoxy(20,13);
    write('Enter key word to search for: ');
    readln(key);
    key := ucas(key);
    heading;
    while start <> nil do
    begin
      if pos(key,start^.insert)>0 then
      begin
        display(start);
      end;
      start := start^.next;
    end;
    readln;
  end;

  procedure find_year(start:pointer);
  var
    key: string;
  begin
    clrscr;
    gotoxy(20,13);
    write('Enter key word to search for: ');
    readln(key);
    key := ucas(key);
    heading;
    while start <> nil do
    begin
      if pos(key,start^.year)>0 then
      begin
        display(start);
      end;
      start := start^.next;
    end;
    readln;
  end;

  procedure find_brand(start:pointer);
  var
    key: string;
  begin
    clrscr;
    gotoxy(20,13);
    write('Enter key word to search for: ');
    readln(key);
    key := ucas(key);
    heading;
    while start <> nil do
    begin
      if pos(key,start^.brand)>0 then
      begin
        display(start);
      end;
      start := start^.next;
    end;
    readln;
  end;

  procedure find_repeats(start:pointer);
  var
    key: string;
  begin
    clrscr;
    gotoxy(20,13);
    write('Enter key word to search for: ');
    readln(key);
    key := ucas(key);
    heading;
    while start <> nil do
    begin
      if pos(key,start^.repeats)>0 then
      begin
        display(start);
      end;
      start := start^.next;
    end;
    readln;
  end;


  procedure save(var f:filtype;start:pointer);
  begin
    writeln('Saving file...');
    rewrite(f);
    while start <> nil do
    begin
      write(f,start^);
      start := start^.next;
    end;
  end;

  function load(var f:filtype;start:pointer):pointer;
  var
    temp,temp2: pointer;
    first: boolean;
  begin
    writeln('Loading file...');
    reset(f);
    start := nil;
    if not eof(f) then
    begin
      new(temp);
      read(f,temp^);
      temp^.next := nil;
      load := temp;
    end;
    while not eof(f) do
    begin
      new(temp2);
      read(f,temp2^);
      temp^.next := temp2;
      temp2 ^.next := nil;
      temp := temp2;
    end;
  end;

  procedure title;
  var i:integer;
  begin
    textbackground(blue);
    clrscr;
    textcolor(yellow);
    gotoxy(20,2);
    write('Card Holder v-1.6 written by Brock Wilcox');
    for i:=2 to 79 do
    begin
      gotoxy(i,1);
      write('Í');
      gotoxy(i,24);
      write('Í');
    end;
    for i:=2 to 23 do
    begin
      gotoxy(1,i);
      write('º');
      gotoxy(80,i);
      write('º');
    end;
    gotoxy(1,1);
    write('É');
    gotoxy(80,1);
    write('»');
    gotoxy(80,24);
    write('¼');
    gotoxy(1,24);
    write('È');
           { ³´µ¶·¸¹»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚ}

  end;

  function menu:char;
  var
    a:integer;
    ch:char;
  begin
    a := 35;
    clrscr;
    title;
    gotoxy(a,5);
    write('1) Add');
    gotoxy(a,7);
    write('3) View all');
    gotoxy(a,6);
    write('2) Delete');
    gotoxy(a,10);
    write('6) Save');
    gotoxy(a,11);
    write('7) Edit');
    gotoxy(a,12);
    write('8) Quit');
    gotoxy(a,8);
    write('4) Search');
    gotoxy(a,9);
    write('5) Totals');
    gotoxy(a-5,20);
    write('Enter selection: ');
    readln(ch);
    menu := ch;
  end;

  procedure del;
  var
    key: string[30];
    sta,last: pointer;
    done: boolean;
  begin
    clrscr;
    gotoxy(20,13);
    write('Enter name to delete: ');
    readln(key);
    key := ucas(key);
    if start^.name = key then
    begin
      start := start^.next;
    end else
    begin
      sta := start;
      done := false;
      while (sta <> nil) and (not done) do
      begin
        last := sta;
        sta := sta^.next;
        if sta^.name = key then
        begin
          last^.next := sta^.next;
          dispose(sta);
          done := true;
        end;
      end;
    end;
  end;

  function sear:char;
  var
    a:integer;
    ch:char;
  begin
    a := 35;
    clrscr;
    title;
    gotoxy(a,5);
    write('1) Name');
    gotoxy(a,7);
    write('3) Card number');
    gotoxy(a,6);
    write('2) Sport');
    gotoxy(a,10);
    write('6) Brand');
    gotoxy(a,11);
    write('7) Price');
    gotoxy(a,8);
    write('4) Insert');
    gotoxy(a,9);
    write('5) Repeats');
    gotoxy(a,12);
    write('8) Main Menu');
    gotoxy(a-5,20);
    write('Enter selection: ');
    readln(ch);
    sear := ch;
  end;

  procedure search(start:pointer);
  var
    ch:char;
  begin
    while ch<>'8' do
    begin
      ch := sear;
      case ch of
        '1' : find_name(start);
        '2' : find_sport(start);
        '3' : find_number(start);
        '4' : find_insert(start);
        '5' : find_repeats(start);
        '6' : find_brand(start);
        '7' : find_price(start);
      end;
    end;
  end;

  procedure add; forward;
  procedure view(start:pointer); forward;
  function store(info,start: pointer):pointer; forward;
  procedure edit_card(start:pointer); forward;

  function valu(str:string):real;
  var
    i,b,c,j:integer;
    a:real;
    s:string;
  begin
   val(str,a,i);
   if pos('.',str)>1 then
   begin
     i:=pos('.',str);
     for j:=i+1 to i+2 do s[j-i+1]:=str[i];
     val(s,b,c);
     a:=a+b/100;
   end;

   valu := a;
  end;

  procedure totals(start:pointer);
  var
    cards:integer;
    prices:real;
  begin
    prices := 0;
    cards := 0;
    while start<>nil do
    begin
      prices := (valu(start^.price)*valu(start^.repeats)) + prices;
      cards := cards + 1;
      start := start^.next;
    end;
    clrscr;
    writeln('There are ',cards,' cards.');
    writeln('Total price =  $',prices:7:2);
    readln;
  end;

  procedure go(ch:char);
  begin
    case ch of
      '1' : add;
      '3' : view(start);
      '7' : edit_card(start);
      '8' : quit := true;
      '2' : del;
      '6' : save(pb,start);
      '4' : search(start);
      '5' : totals(start);
    end;
  end;


  procedure input(var str:string);
  begin
    readln(str);
    str := ucas(str);
  end;


  procedure copy_card(var card,temp:pointer);
  begin
      card^.name:=temp^.name;
      card^.brand:=temp^.brand;
      card^.sport:=temp^.sport;
      card^.year:=temp^.year;
      card^.number:=temp^.number;
      card^.price:=temp^.price;
      card^.repeats:=temp^.repeats;
      card^.insert:=temp^.insert;
  end;

  procedure edit(var card:pointer;ne:boolean);
  var
    temp:pointer;
  begin
    if wherey=25 then
    begin
      write('type a ''.'' in name to stop.');
      heading;
      gotoxy(1,25);
      write('No name to exit.');
      gotoxy(1,3);
    end;
    new(temp);
    copy_card(temp,card);
    gotoxy(2,wherey);
    if ne=false then
    begin
      display(card);
      gotoxy(2,wherey-1);
    end;
    input(card^.name);
    if card^.name <> '.' then
    begin
      gotoxy(16,wherey-1);
      input(card^.brand);
      gotoxy(31,wherey-1);
      input(card^.sport);
      gotoxy(43,wherey-1);
      input(card^.year);
      gotoxy(52,wherey-1);
      input(card^.number);
      gotoxy(61,wherey-1);
      input(card^.price);
      gotoxy(71,wherey-1);
      input(card^.repeats);
      gotoxy(77,wherey-1);
      input(card^.insert);
      gotoxy(1,wherey);
      if card^.name='' then card^.name:=temp^.name;
      if card^.brand='' then card^.brand:=temp^.brand;
      if card^.sport='' then card^.sport:=temp^.sport;
      if card^.year='' then card^.year:=temp^.year;
      if card^.number='' then card^.number:=temp^.number;
      if card^.price='' then card^.price:=temp^.price;
      if card^.repeats='' then card^.repeats:=temp^.repeats;
      if card^.insert='' then card^.insert:=temp^.insert;
    end;
    dispose(temp);
  end;

  procedure edit_card(start:pointer);
  var
    key: string;
  begin
    clrscr;
    gotoxy(20,13);
    write('Enter key word to search for: ');
    readln(key);
    key := ucas(key);
    heading;
    while start <> nil do
    begin
      if pos(key,start^.name)>0 then
      begin
        edit(start,false);
      end;
      start := start^.next;
    end;
  end;

  procedure add;
  var
    info: pointer;
    done:boolean;
  begin
    done := false;
    heading;
    gotoxy(1,25);
    write('No name to exit.');
    gotoxy(1,3);
    while not done do
    begin
      new(info);
      info^.name := '';
      info^.brand := '';
      info^.year := '';
      info^.number := '';
      info^.repeats := '';
      info^.insert := '';
      info^.price := '';
      info^.sport := '';
      edit(info,true);
      if info^.name<>'' then start := store(info,start)
      else begin
        dispose(info);
        done := true;
      end;
    end;
  end;

  function store(info,start: pointer):pointer;
  var
    old,top: pointer;
    done: boolean;
  begin
    top := start;
    old := nil;
    done := false;
    if start = nil then {empty list}
    begin
      info^.next := nil;
      store := info;
    end else
    begin
      while (start <> nil) and (not done) do
      begin
        if start^.name < info^.name then
        begin
          old := start;
          start := start^.next;
        end else
        begin         {in middle}
          if old <> nil then
          begin
            old^.next := info;
            info ^.next := start;
            store := top;
            done := true;
          end else
          begin          {new first}
            info ^.next := start;
            store := info;
            done := true;
          end;
        end;
      end;
      if not done then
      begin
        start := info;      {Goes on end}
        info ^.next := nil;
        old ^.next := info;
        store := top;
      end;
    end;
  end;

  procedure view(start:pointer);
  var
    b: pointer;
  begin
    heading;
    while start<>nil do
    begin
      display(start);
      start := start^.next;
    end;
    writeln('Press return to continue');
    readln;
  end;

begin
  init;
 { new(start);
  start^.name := 'JOHN';
  start^.number := '763-4763';
  start^.next := nil;
  save(pb,start);}
  quit := false;
  start := load(pb,start);
  while not quit do
  begin
    go(menu);
  end;
end.

