Uses Crt, Dos;
{-------------------------Global variables-----------------------------------}
Const
 lnTR             = 1;
 lnTH             = 2;
 lnTD             = 4;

 alNon            = 0;
 alLeft           = 1;
 alCenter         = 2;
 alRight          = 4;

 spNon            = 0;
 spRow            = 1;
 spCol            = 2;

type
 Str4           = String[4];

 PBound = ^TBound;
 TBound = record
  S            : String;
  Mode         : Byte;
  Align        : Byte;
  Span         : Byte;
   Num         : Byte;  {number of span col/row}
 end;

const
 LineLen        : Byte    = 80;
 LineStart      : Str4    = '<TR>';
 LineTH         : Str4    = '<TH>';
 LineTD         : Str4    = '<TD>';

var
 Fin, Fout      : Text;
 Table          : Array [1..100,1..100] of PBound; {Y*X}
 MaxLen         : Array [1..100] of Integer;
 MaxX, MaxY     : Integer;
{-------------------------Global voids---------------------------------------}

 function Str2Byte (S:String) : Byte;
 var
  Err           : Integer;
  Temp          : Integer;
 begin
  Val(S,Temp, Err);
  Str2Byte := - Temp;
 end;


{----------------------------------------------------------------------------}
{****************************************************************************}
{----------------------------------------------------------------------------}
 procedure Task1;
 var
  S, Stmp, HorLine     : String;
  Mess, TopLine        : String;
  Direc                : Str4;
  CurPosX, CurPosY     : Integer;
  CurMode, i,j, Where  : Integer;
 begin
  {----READ DATA--------}
  CurPosY:=1;
  while not Eof(Fin) do
  begin
   ReadLn(Fin, S);
   S := Copy(S, 5, Length(S));
   CurPosX := 1;

   repeat
    Direc := Copy (S, 1, 5);

    if Direc = LineTH then CurMode := lnTH
     else
     if Direc = LineTD then CurMode := lnTD;

     S := Copy(S, 5, Length(S));
     i := 1;
     While S[i]<>'<' do Inc(I);

     GetMem (Table[CurPosY,CurPosX], SizeOf(TBound));
     Stmp:=Copy(S,1,I-1);;
     i:=2;
     repeat
      if (Stmp[i-1]=' ') and (Stmp[i]=' ') then Delete(Stmp,i-1,2)
      else
       Inc(i);
     until i>Length(Stmp);
     Table[CurPosY, CurPosX]^.S := Stmp;
     Table[CurPosY, CurPosX]^.Mode := CurMode;
     S := Copy(S,I,Length(S));

     Inc(CurPosX);
    until S='';
   Inc(CurPosY);
  end;

  MaxX := CurPosX - 1;
  MaxY := CurPosY - 1;

  {--ANALISE TABLE--}
  for I:=1 to MaxX do
   begin
    MaxLen[I]:=-32767;
    for J:=1 to MaxY do
    begin
     If Length(Table[J,I]^.S)>MaxLen[I] then
       MaxLen[I] := Length(Table[J,I]^.S);
    end;
   end;

  {MAKING TOP UNDER LINE}
  S:='+';
  for i:=1 to MaxX do
  begin
   Stmp[0]:=#255;
   FillChar(Stmp[1],255,#45);
   Stmp[0]:=Char(MaxLen[i]);
   S := S +  '-'+Stmp + '-';
  end;
  S:=S+ '-' + '+';
  TopLine := S;

  {MAKING HORIZONTAL UNDER LINE}
  S:='|';
  for i:=1 to MaxX do
  begin
   Stmp[0]:=#255;
   FillChar(Stmp[1],255,#45);
   Stmp[0]:=Char(MaxLen[i]);
   S := S + '-' + Stmp + '-'+'+';
  end;
  S[Length(S)]:='|';
  HorLine := S;

  WriteLn(Fout, TopLine);

  {-FORMATTING----DATA----}
  for j:=1 to MaxY do
  begin
   S:='';
   for i:=1 to MaxX do
   begin
    Stmp[0]:=#255;
    FillChar(Stmp[1],255,#32);
    Where:=1;
    if Table[j,i]^.Mode = lnTH then
      Where := (MaxLen[i] - Length(Table[j,i]^.S)) div 2 + 1;
    Move(Table[j,i]^.S[1],Stmp[Where],Length(Table[j,i]^.S));
    Stmp[0]:=Char(MaxLen[i]);
    S := S + '|' + ' '+Stmp + ' ';
   end;
   S := S + '|';
   WriteLn(Fout,S);
   if j<>MaxY then WriteLn(Fout,HorLine);
  end;

  WriteLn(Fout, TopLine);

 end;


{----------------------------------------------------------------------------}
{****************************************************************************}
{----------------------------------------------------------------------------}
 procedure Task2;
 var
  S, Stmp, HorLine     : String;
  Mess, TopLine        : String;
  Direc                : Str4;
  CurPosX, CurPosY     : Integer;
  CurMode, i,j, Where  : Integer;
  Extend               : Byte;  {0 = false , 1 = true}
 begin
  {----READ DATA--------}
  CurPosY:=1;
  while not Eof(Fin) do
  begin
   ReadLn(Fin, S);
   S := Copy(S, 5, Length(S));
   CurPosX := 1;

   repeat
    GetMem (Table[CurPosY,CurPosX], SizeOf(TBound));

    case S[3] of
     'H'  : CurMode := lnTH;
     'D'  : CurMode := lnTD;
    end;
    Table[CurPosY, CurPosX]^.Mode := CurMode;
    Table[CurPosY, CurPosX]^.Align := alNon;

    if S[4]=' ' then      {EXTENTED with align!!!}
    begin
     case S[11] of
      'L'  : begin
              CurMode := alLeft;
              S := Copy(S,16, Length(S));
             end;
      'R'  :
             begin
              CurMode := alRight;
              S := Copy(S,17,Length(S));
             end;
      'C'  : begin
              CurMode := alCenter;
              S := Copy(S,18,Length(S));
             end;
     end;
     Table[CurPosY, CurPosX]^.Align := CurMode;
    end
     else
     begin
      S := Copy(S,5,Length(S));
     end;

    i := 1;
    While S[i]<>'<' do Inc(I);

    Stmp:=Copy(S,1,I-1);
    S:=Copy(S,I,Length(S));
    i:=2;
    repeat
     if (Stmp[i-1]=' ') and (Stmp[i]=' ') then Delete(Stmp,i-1,2)
     else
      Inc(i);
    until i>Length(Stmp);

    Table[CurPosY, CurPosX]^.S := Stmp;

    Inc(CurPosX);
    until S='';
   Inc(CurPosY);
  end;

  MaxX := CurPosX - 1;
  MaxY := CurPosY - 1;

  {--ANALISE TABLE--}
  for I:=1 to MaxX do
   begin
    MaxLen[I]:=-32767;
    for J:=1 to MaxY do
    begin
     If Length(Table[J,I]^.S)>MaxLen[I] then
       MaxLen[I] := Length(Table[J,I]^.S);
    end;
   end;

  {MAKING TOP UNDER LINE}
  S:='+';
  for i:=1 to MaxX do
  begin
   Stmp[0]:=#255;
   FillChar(Stmp[1],255,#45);
   Stmp[0]:=Char(MaxLen[i]);
   S := S +  '-'+Stmp + '-';
  end;
  S:=S+ '-' + '+';
  TopLine := S;

  {MAKING HORIZONTAL UNDER LINE}
  S:='|';
  for i:=1 to MaxX do
  begin
   Stmp[0]:=#255;
   FillChar(Stmp[1],255,#45);
   Stmp[0]:=Char(MaxLen[i]);
   S := S + '-' + Stmp + '-'+'+';
  end;
  S[Length(S)]:='|';
  HorLine := S;

  WriteLn(Fout, TopLine);

  {-FORMATTING----DATA----}
  for j:=1 to MaxY do
  begin
   S:='';
   for i:=1 to MaxX do
   begin
    Stmp[0]:=#255;
    FillChar(Stmp[1],255,#32);
    Where:=1;

    if Table[j,i]^.Mode = lnTH then
      Where := (MaxLen[i] - Length(Table[j,i]^.S)) div 2 + 1;

    case Table[j,i]^.Align of
     alLeft  :  Where := 1;
     alRight :  Where := MaxLen[i] - Length(Table[j,i]^.S) + 1;
     alCenter:  Where := (MaxLen[i] - Length(Table[j,i]^.S)) div 2 + 1;
    end;

    Move(Table[j,i]^.S[1],Stmp[Where],Length(Table[j,i]^.S));
    Stmp[0]:=Char(MaxLen[i]);
    S := S + '|' + ' '+Stmp + ' ';
   end;
   S := S + '|';
   WriteLn(Fout,S);
   if j<>MaxY then WriteLn(Fout,HorLine);
  end;

  WriteLn(Fout, TopLine);

 end;


{----------------------------------------------------------------------------}
{****************************************************************************}
{----------------------------------------------------------------------------}
 procedure Task3;
 var
  S, Stmp, HorLine     : String;
  Mess, TopLine        : String;
  Direc                : Str4;
  CurPosX, CurPosY     : Integer;
  CurMode, i,j, Where  : Integer;
  Extend               : Byte;  {0 = false , 1 = true}
 begin
  {----READ DATA--------}
  CurPosY:=1;
  while not Eof(Fin) do
  begin
   ReadLn(Fin, S);
   S := Copy(S, 5, Length(S));
   CurPosX := 1;
   if CurPosY<>1 then
    if Table[CurPosY,CurPosX]=Table[CurPosY-1,CurPosX] then Inc(CurPosX);

   repeat
    GetMem (Table[CurPosY,CurPosX], SizeOf(TBound));

    case S[3] of
     'H'  : CurMode := lnTH;
     'D'  : CurMode := lnTD;
    end;
    Table[CurPosY, CurPosX]^.Mode := CurMode;
    Table[CurPosY, CurPosX]^.Span := spNon;

    if S[4]=' ' then      {EXTENTED with !!!}
    begin
     case S[5] of
      'C'  : CurMode := spCol;
      'R'  : CurMode := spRow;
     end;
     Table[CurPosY, CurPosX]^.Span := CurMode;
     i:=13; Stmp:='';
     while S[i]<>'>' do
     begin
      Stmp:=Stmp+S[i];
      Inc(I);
     end;
     Table[CurPosY, CurPosX]^.Num := - Str2Byte(Stmp);
     S := Copy(S, i+1, Length(S));

     for i:=1 to Table[CurPosY, CurPosX]^.Num - 1 do
     begin
      case Table[CurPosY, CurPosX]^.Span of
       spRow :  Table[CurPosY+i, CurPosX]:=Table[CurPosY, CurPosX];
       spCol :  Table[CurPosY,CurPosX+i]:=Table[CurPosY, CurPosX];
      end;
     end;

    end
     else
     begin
      S := Copy(S,5,Length(S));
     end;

    i := 1;
    While S[i]<>'<' do Inc(I);

    Stmp:=Copy(S,1,I-1);
    S:=Copy(S,I,Length(S));
    i:=2;
    repeat
     if (Stmp[i-1]=' ') and (Stmp[i]=' ') then Delete(Stmp,i-1,2)
     else
      Inc(i);
    until i>Length(Stmp);

    Table[CurPosY, CurPosX]^.S := Stmp;

    i:=CurPosX;

    while Table[CurPosY,i]=Table[CurPosY, CurPosX] do Inc(CurPosX);
    until S='';
   Inc(CurPosY);
  end;


  MaxX := CurPosX - 1;
  MaxY := CurPosY - 1;

  {--ANALISE TABLE--}
  for I:=1 to MaxX do
   begin
    MaxLen[I]:=-32767;
    for J:=1 to MaxY do
    begin
     If Length(Table[J,I]^.S)>MaxLen[I] then
       MaxLen[I] := Length(Table[J,I]^.S);
    end;
   end;

  {MAKING TOP UNDER LINE}
  S:='+';
  for i:=1 to MaxX do
  begin
   Stmp[0]:=#255;
   FillChar(Stmp[1],255,#45);
   Stmp[0]:=Char(MaxLen[i]);
   S := S +  '-'+Stmp + '-';
  end;
  S:=S+ '-' + '+';
  TopLine := S;


  WriteLn(Fout, TopLine);

  {-FORMATTING----DATA----}
  for j:=1 to MaxY do
  begin
   S:='';
   i:=1;
   while i<=MaxX do
   begin
    if Table[j,i]^.Span=spNon then
    begin
     Stmp[0]:=#255;
     FillChar(Stmp[1],255,#32);
     Where:=1;

     if Table[j,i]^.Mode=lnTH then
     begin
      Where:=(MaxLen[i]-Length(Table[j,i]^.S)) div 2 + 1;
     end;

     Move(Table[j,i]^.S[1],Stmp[Where],Length(Table[j,i]^.S));
     Stmp[0]:=Char(MaxLen[i]);

    end
     else    {EXTENDED with span!!!}
     begin
      Where:=1;
      if (Table[j,i]^.Span=spCol) and (Table[j,i]^.Mode=lnTh) then
       Where:=(Table[j,i]^.Num*MaxLen[i]+MaxLen[i]-1-Length(Table[j,i]^.S)) div 2+1;
     end;
    S := S + '|' + ' '+Stmp + ' ';
   end;
   S := S + '|';
   WriteLn(Fout,S);
   {if j<>MaxY then WriteLn(Fout,HorLine);}
  end;

  WriteLn(Fout, TopLine);

 end;



var
 I       : Byte;
begin
 I:=0;

 if ParamCount=3 then
 begin
  LineLen := Str2Byte(ParamStr(I+1));
  I:=I+1;
 end;

 Assign(Fin,ParamStr(I+1));
 ReSet(Fin);

 Assign(Fout,ParamStr(I+2));
 ReWrite(Fout);


 Task1;
 Task2;
 Task3;

 Close(Fin);
 Close(Fout);
end.