// Program written by Maarten Meuris AKA Nyerguds
program dune_edit;
uses crt, dos;

TYPE
   chset  = array [1..8] of byte;
   coords = array [1..4] of integer;
   keymapper = Record
      up, down, left, right, space, enter, esc :char;
   end;
   option = Record
      typeid: Integer;
      {
      0 = unsigned byte (HEX)
      1 = signed byte (DEC)
      3 = 2-byte (DEC)
      4 = 4-byte (HEX)
      5 = owner
      6 = command
      7 = Movement type
      8 = weapon type
      9 = structure
      10 = unit
      }
      text: String[20];
   end;

var level: integer;
    keyread:char;
    select,scroll,max,len:array [1..3] of integer;
const
    lenlist:array [1..2] of integer = (27,19);
    lenopts:array [1..2] of integer = (47,70);
    framechar:array[1..2] of chset = (
                         ($DA, $BF, $C0, $D9, $C4, $B3, $C2, $C1),
                         ($C9, $BB, $C8, $BC, $CD, $BA, $CB, $CA));
    selectBoundaries:array[1..3] of coords = (
                         (3,4,25,5), (3,9,25,23), (32,4,54,23));

    mainlist:array[0..1] of String[20] = ('Units       ','Structures  ');

    unitlist:array[0..26] of String[20] = (
             'Carryall    ','''Thopter    ','Infantry    ','Troopers    ',
             'Soldier     ','Trooper     ','Saboteur    ','Launcher    ',
             'Deviator    ','Tank        ','Siege Tank  ','Devastator  ',
             'Sonic Tank  ','Trike       ','Raider Trike','Quad        ',
             'Harvester   ','MCV         ','Death Hand  ','Rocket      ',
             'ARocket     ','GRocket     ','MiniRocket  ','Bullet      ',
             'Sonic Blast ','Sandworm    ','Frigate     ');
    structlist:array[0..18] of String[20] = (
             'Concrete    ','Concrete4   ','Palace      ','Light Fctry ',
             'Heavy Fctry ','Hi Tech     ','IX          ','WOR         ',
             'Const Yard  ','Windtrap    ','Barracks    ','Starport    ',
             'Refinery    ','Repair      ','Wall        ','Turret      ',
             'R-Turret    ','Spice Silo  ','Outpost     ');

    unitoptions:array[0..46] of option = (
              (typeid: 3; text: 'Short name ID       '),
              (typeid: 4; text: 'Name code ref.      '),
              (typeid: 2; text: 'Long name ID        '),
              (typeid: 4; text: 'WSA file code ref.  '),
              (typeid: 3; text: 'Unknown 005         '),
              (typeid: 3; text: 'Unknown 006         '),
              (typeid: 3; text: 'Hit points          '),
              (typeid: 3; text: 'Unknown 008         '),
              (typeid: 3; text: 'Sidebar icon gfxID  '),
              (typeid: 3; text: 'Cost                '),
              (typeid: 3; text: 'Build Time          '),
              (typeid: 3; text: 'Tech level          '),
              (typeid: 9; text: 'Prerequisites       '),
              (typeid: 3; text: 'Unknown 014         '),
              (typeid: 1; text: 'Unknown 015         '),
              (typeid: 1; text: 'Upgrades needed     '),
              (typeid: 6; text: 'Sidebar command #1  '),
              (typeid: 6; text: 'Sidebar command #2  '),
              (typeid: 6; text: 'Sidebar command #3  '),
              (typeid: 6; text: 'Sidebar command #4  '),
              (typeid: 3; text: 'Unknown 021         '),
              (typeid: 1; text: 'Unknown 022         '),
              (typeid: 3; text: 'Unknown 023         '),
              (typeid: 3; text: 'Unknown 024         '),
              (typeid: 5; text: 'Owner               '),
              (typeid: 3; text: 'Unknown 026         '),
              (typeid: 3; text: 'Unknown 027         '),
              (typeid: 1; text: 'Unknown 028         '),
              (typeid: 1; text: 'Unknown 029         '),
              (typeid: 1; text: 'Unknown 030         '),
              (typeid: 1; text: 'Unknown 031         '),
              (typeid: 3; text: 'Sight               '),
              (typeid: 7; text: 'Movement type       '),
              (typeid: 3; text: 'Unknown 034         '),
              (typeid: 3; text: 'Speed               '),
              (typeid: 3; text: 'Unknown 036         '),
              (typeid: 3; text: 'Unit gfxID          '),
              (typeid: 3; text: 'Turret gfxID        '),
              (typeid: 3; text: 'Unknown 039         '),
              (typeid: 3; text: 'Unknown 040         '),
              (typeid: 3; text: 'Unknown 041         '),
              (typeid: 3; text: 'Weapon rate of fire '),
              (typeid: 3; text: 'Weapon range        '),
              (typeid: 3; text: 'Weapon damage       '),
              (typeid: 3; text: 'Unknown 045         '),
              (typeid: 8; text: 'Weapon type         '),
              (typeid: 3; text: 'Unknown 047         '));

      keymap:keymapper = (up:    char(72);
                          down:  char(80);
                          left:  char(75);
                          right: char(77);
                          space: char(32);
                          enter: char(13);
                          esc:   char(27));

procedure cntin;
var pause: char;
begin
   write('Press any key to continue.');
   repeat until keypressed;
    pause:=ReadKey();
end; {cntin}

procedure drawLine(x,y,len:integer; c:char);
var count:integer;
begin
   for count:=0 to (len) do
    begin
      gotoxy(x,y+count);
      write(c);
    end;
end;

procedure drawFrame1(x,y,w,h:integer; active:boolean );
var charset,count:integer;
begin
   if active then charset:=2
   else charset:=1;
   gotoxy(x,y);
   write(char(framechar[charset,1]));
   for count:=1 to (w-2) do
    write(char(framechar[charset,5]));
   write(char(framechar[charset,2]));
   for count:=1 to (h-2) do
    begin
      gotoxy(x,y+count);
      write(char(framechar[charset,6]));
      gotoxy(x+w-1,y+count);
      write(char(framechar[charset,6]));
    end;
   gotoxy(x,y+h-1);
   write(char(framechar[charset,3]));
   for count:=1 to (w-2) do
    write(char(framechar[charset,5]));
   write(char(framechar[charset,4]));
   gotoxy(0,0);
end; {drawFrame1}

procedure drawFrame2(x,y,w,h,m:integer; active:boolean );
var charset,count:integer;
begin
   if active then charset:=2
   else charset:=1;
   gotoxy(x,y);
   write(char(framechar[charset,1]));
   for count:=1 to (w-2) do
    write(char(framechar[charset,5]));
   write(char(framechar[charset,2]));
   gotoxy(x+m-1,y);
   write(char(framechar[charset,7]));
   for count:=1 to (h-2) do
    begin
      gotoxy(x,y+count);
      write(char(framechar[charset,6]));
      gotoxy(x+m-1,y+count);
      write(char(framechar[charset,6]));
      gotoxy(x+w-1,y+count);
      write(char(framechar[charset,6]));
    end;
   gotoxy(x,y+h-1);
   write(char(framechar[charset,3]));
   for count:=1 to (w-2) do
    write(char(framechar[charset,5]));
   write(char(framechar[charset,4]));
    gotoxy(x+m-1,y+h-1);
   write(char(framechar[charset,8]));
   gotoxy(0,0);
end; {drawFrame}

procedure drawSelect(l:integer);
begin
  drawLine(selectBoundaries[l][1],selectBoundaries[l][2],max[l],' ');
  gotoxy(selectBoundaries[l][1],selectBoundaries[l][2]+select[l]);
  write('[');
  drawLine(selectBoundaries[l][3],selectBoundaries[l][2],max[l],' ');
  gotoxy(selectBoundaries[l][3],selectBoundaries[l][2]+select[l]);
  write(']');
end;

procedure drawSelect();
begin
  drawSelect(level);
end;

function openFile(filename:String ) : file;
var
  status:integer;
begin
  assign(openFile,filename);
  {$I-}
  reset(openFile,1);
  status:=IOResult;
  if status<>0 then
   begin
    writeln();
    writeln('Error opening "',filename,'"');
    {$I+}
   end;
end; {openFile}

procedure closeFile(f:file);
begin
  close(f);
  {$I+}
end; {closeFile}

procedure drawList(l:integer);
var i,last:integer;
    showlist:array [0..19] of String[20];
    opt:option;
begin
    last:=len[l];
    if max[l]<len[l] then last:=max[l];
    if l=1 then
     for i:=0 to last do showlist[i]:=mainlist[(i+scroll[i])]
    else if l=2 then
      if select[1]=0 then
        begin
          len[l]:=26;
          last:=len[l];
          if max[l]<len[l] then last:=max[l];
          for i:=0 to last do showlist[i]:=unitlist[(i+scroll[i])];
        end
      else if select[1]=1 then
        begin
          len[l]:=18;
          last:=len[l];
          if max[l]<len[l] then last:=max[l];
          for i:=0 to last do showlist[i]:=structlist[(i+scroll[i])];
        end;
{    else if l=3 then
      if select[1]=0 then
        begin
          len[l]:=46;
          last:=len[l];
          if max[l]<len[l] then last:=max[l];
          for i:=0 to last do
            begin
              opt:=unitoptions[(1+scroll[i])];
              showlist[i]:=(opt.text);
            end;
            write('[[[[[[');
            write (opt.text);
            write(']]]]]]');
        end
      else if select[1]=1 then
        begin
          len[l]:=46;
          last:=len[l];
          if max[l]<len[l] then last:=max[l];
          for i:=0 to last do
            begin
              opt:=unitoptions[(1+scroll[i])];
              showlist[i]:=(opt.text);
            end;
        end;}
    for i:=0 to last do
     begin
      gotoxy(selectBoundaries[l][1]+2,selectBoundaries[l][2]+i);
      write(showlist[i]);
     end;
end;


procedure drawList();
begin
   drawList(level);
end;

procedure MoveDown(level:integer);
begin
  if (select[level]=max[level]) and ((len[level]-max[level])>0) and (scroll[level]<(len[level]-max[level])) then
     begin
      scroll[level]:=scroll[level]+1;
      drawList();
     end
  else if select[level]<>max[level] then
    select[level]:=select[level]+1;
  if level=1 then drawList(2);
end;

procedure MoveUp(level:integer);
begin
  if (select[level]=0) and (scroll[level]>0) then
     begin
      scroll[level]:=scroll[level]-1;
      drawList();
     end
  else if select[level]<>0 then
    select[level]:=select[level]-1;
  if level=1 then drawList(2);
end;


procedure init();
var i: integer;
begin
  for i:=1 to 25 do
  begin
    gotoxy(1,i);
    clreol;
  end;
  gotoxy(1,1);
  for i:=1 to 80 do
    write(char(framechar[2,5]));
  gotoxy(3,1);
  write(' Dune II Editor ');
  gotoxy(65,1);
  write(' by Nyerguds ');
  level:=1;
  len[1]:=1;
  len[2]:=27;
  len[3]:=47;
  for i:=1 to 3 do
  begin
   select[i]:=0;
   scroll[i]:=0;
   max[i]:=selectBoundaries[i][4]-selectBoundaries[i][2];
  end;
  drawList(1);
  drawList(2);
end;


procedure drawLayout();
var i: integer;
begin
  if level<4 then
  begin
    drawFrame1(1,3,27,4,level=1);
    drawFrame1(1,8,27,17,level=2);
    drawFrame2(30,3,50,22,27,level=3);
    drawSelect();
  end
  else
  begin
    drawFrame1(3,3,75,22,true);
  end;
  gotoxy(1,25);
end;

procedure input();
begin
 if (keyread=keymap.ESC) and (level=4) then drawLayout();
 if (keyread=keymap.ESC) and (level=1) then keyread:=char(255)
 else if (keyread=keymap.RIGHT) and (level=3) then level:=1
 else if (keyread=keymap.ENTER) or (keyread=keymap.SPACE) or (keyread=keymap.RIGHT) then level:=level+1
 else if (level<>1) and (keyread=keymap.LEFT) or (keyread=keymap.ESC) then level:=level-1
 else if (keyread=keymap.DOWN) then MoveDown(level)
 else if (keyread=keymap.UP) then   MoveUp(level)
end;

begin
  init();
  drawLayout();
  keyread:=char(0);
    while keyread <> char(255) do
    begin
      keyread:=ReadKey();
      gotoxy(1,25);
      input();
      drawLayout();
    end;
end.

