/*
    This file is part of Advanced Strategic Command; http://www.asc-hq.de
    Copyright (C) 1994-2001  Martin Bickel, Marc Schellenberger and
    Steffen Froehlich
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; see the file COPYING. If not, write to the 
    Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
    Boston, MA  02111-1307  USA
*/
// Version v2.0 , change also GENERAL


#include <stdio.h>
#include <stdlib.h>
#include <algorithm>

#include "../tpascal.inc"
#include "../typen.h"
#include "../basestrm.h"
#include "../misc.h"
#include "../sgstream.h"
#include "../buildingtype.h"
#include "../vehicletype.h"
#include "../errors.h"
#include "../graphicset.h"
#include "../ascstring.h"
#include "../itemrepository.h"
#include "../strtmesg.h"
#include "../basegfx.h"
#include "../loadpcx.h"

#ifdef WIN32
#undef main
#endif



// including the command line parser, which is generated by genparse
#include "../clparser/weaponguide.cpp"



const char* tableParam = " class=\"wg\" border=\"1\" ";

FILE* createFile ( const ASCString& filename )
{
   return fopen ( filename.c_str(), "w" );
}


void printIndex ( FILE* fp, const ASCString& index, const ASCString& param = "" )
{
   fprintf ( fp, "<tr><th class=\"wg\" %s > %s  </th>" , param.c_str(), index.c_str() );
}

void printValue ( FILE* fp, const ASCString& data, const ASCString& param = "" )
{
   fprintf( fp, "<td class=\"wg\" %s > %s </td>", param.c_str(), data.c_str() );
}

void printValue ( FILE* fp, int data )
{
   printValue( fp, strrr(data)  );
}


void printLineEnd ( FILE* fp )
{
   fprintf ( fp, "</tr>\n" );
}


void printMainLine ( FILE* fp, const ASCString& index, const ASCString& value )
{
  printIndex ( fp, index );
  printValue( fp, value );
  printLineEnd ( fp );
}

void printMainLine ( FILE* fp, const ASCString& index, int value )
{
   printMainLine ( fp, index, strrr ( value ));
}


ASCString getHeightImgString( int height )
{
   ASCString s;
   for ( int j = 0; j < 8 ; j++ )
      if ( height & ( 1 << j)) {
         ASCString s2;
         s2.format("<img src=\"../hoehe%d.gif\" alt=\"%s\"><br>",j, choehenstufen[j]);
         s += s2;
      }
   return s;
}

   const int maxFileSize = 10000000;
   char s[maxFileSize];
   char d[maxFileSize];


void copyFile( const ASCString& src, const ASCString& dst )
{
   FILE* i = fopen ( src.c_str(), filereadmode );
   FILE* o = fopen ( dst.c_str(), filereadmode );
   bool copy = false;

   if ( !i )
      fatalError ("copyFile :: Could not open input file " + src);

   if ( !o ) {
      copy = true;
      fclose ( i );
   } else {

      int s1 = fread ( s, 1, maxFileSize, i );
      int s2 = fread ( d, 1, maxFileSize, o );
      if ( s1 != s2 )
         copy = true;
      else {
         for ( int i = 0; i < s1; i++ )
            if ( s[i] != d[i] ) {
               copy = true;
               break;
            }
      }
      fclose( o );
      fclose( i );
   }
   if ( copy ) {
      i = fopen ( src.c_str(), filereadmode );
      o = fopen ( dst.c_str(), filewritemode );
      int s1 = fread ( s, 1, maxFileSize, i );
      fwrite ( s, 1, s1, o );
      fclose( o );
      fclose( i );
      printf("*");
   }
   remove ( src.c_str() );
}

int main(int argc, char *argv[] )
{
   Cmdline cl ( argc, argv );

   if ( cl.v() ) {
      cout << argv[0] << " " << getVersionString() << endl;
      exit(0);
   }

   verbosity = cl.r();

   initFileIO( cl.c(), 4 );  // passing the filename from the command line options
   ASCString prefixDir = cl.d();
   if ( !prefixDir.empty() )
      appendbackslash ( prefixDir );

   #ifdef _WIN32_
   ASCString tempPath = getenv("temp");
   appendbackslash(tempPath);
   #else
   ASCString tempPath = "/tmp/";
   #endif


   try {

      printf("Loading data for generating unit documentation. Please wait...");
      loadpalette();
      printf(".");
      loadbi3graphics();
      printf(".");

      loadAllData( false );
      printf(".");
      loadUnitSets();
      printf(".");


      char* wildcard;

      if ( cl.next_param() < argc ) {
         wildcard = argv[cl.next_param()];
         // if a command line parameter is specified, use it as wildcard
         // for example: weaponguide s*.veh
      }
      else {
         wildcard =  "*";
         // else use all verhicles
      }

      FILE* overview  = createFile ( tempPath+"overview.html" );
      FILE* overview1 = createFile ( tempPath+"overview1.html" );
      // opens a file for writing and assigns the file pointer overview to it

      // Beginn des HTML Files HEAD und BODY
      //  \n is the sequence to start a new line

      fprintf ( overview , "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
                "<html>\n"
                "<HEAD>\n"
                "<meta http-equiv=\"content-type\" content=\"text/html; charset=ISO-8859-1\">"
                "<TITLE>UNITGUIDE OVERVIEW LEFT</TITLE>\n"
                "<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"%s\">\n"
                "</HEAD>\n"
                "\n"
                "<BODY class=\"wg\">\n"
                "<table width=\"100%\"  class=\"wg\" >\n"
                "<tr><td><a href=\"overview1.html\">SEE PICTURES</a></td></tr><tr><td></td></tr>\n", cl.t().c_str() );

      fprintf ( overview1 , "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
                "<html>\n"
                "<HEAD>\n"
                "<meta http-equiv=\"content-type\" content=\"text/html; charset=ISO-8859-1\">"
                "<TITLE>WEAPONGUIDE OVERVIEW PICTURES</TITLE>\n"
                "<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"%s\">\n"
                "</HEAD>\n"
                "\n"
                "<BODY class=\"wg\">\n"
                "<table class=\"wgov\" align=\"center\">\n", cl.t().c_str() );

      for ( int unit = 0; unit < vehicleTypeRepository.getNum(); unit++ ) {
         pvehicletype  ft = vehicleTypeRepository.getObject_byPos ( unit );
         ASCString fileName = extractFileName_withoutSuffix( ft->filename );
         fileName.toLower();


         bool setmatch = false;
         if ( cl.s() > 0 ) {
            for ( std::vector<SingleUnitSet*>::iterator i = unitSets.begin(); i != unitSets.end(); i++  )
               if ( (*i)->ID == cl.s() )
                  if ( (*i)->isMember( ft->id ))
                     setmatch = true;
         } else
            setmatch = true;


         if ( patimat ( wildcard, ft->filename.c_str() ) && setmatch ) {

            printf(" processing unit %s , ID %d ... ", ft->description.c_str(), ft->id );

            FILE* framePage = createFile ( tempPath + fileName + ".html" );
            FILE* generalPage = createFile ( tempPath + fileName + "1.html" );
            FILE* movePage = createFile ( tempPath + fileName + "2.html" );
            FILE* weaponPage = createFile ( tempPath + fileName + "3.html" );
            FILE* constructionPage = createFile ( tempPath + fileName + "4.html" );
            FILE* transportPage = createFile ( tempPath + fileName + "5.html" );
            FILE* infoPage = createFile ( tempPath + fileName + "6.html" );
            FILE* researchPage = createFile ( tempPath + fileName + "7.html" );

            const int pageNum = 7;
            FILE* files[pageNum] = { generalPage, movePage, weaponPage, constructionPage, transportPage, infoPage, researchPage };

            // Beginn Einzelfiles
            // UNIT FRAME

            
            fprintf ( framePage, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/html4/frameset.dtd\">\n"
                      "<html>\n"
                      "<HEAD>\n"
                      "<meta http-equiv=\"content-type\" content=\"text/html; charset=ISO-8859-1\">"
                      "<TITLE>UNITGUIDE FRAME</TITLE>\n"
                      "<frameset  cols=\"40%%,*\" border=0 >\n"
                      "<frame name=\"over\" src=\"%s1.html\" marginheight=\"0\">\n"
                      "<frame name=\"under\" src=\"%s6.html\" marginheight=\"2\">\n"
                      "<noframes><body class=\"wg\"><p><A HREF=\"%s1.html\">General Information</A><p>\n<A HREF=\"%s2.html\">Movement </A><p>\n<A HREF=\"%s3.html\">Weapon systems</A><p>\n<A HREF=\"%s4.html\">Construction</A><p>\n<A HREF=\"%s5.html\">Transportation</A><p>\n<A HREF=\"%s6.html\">Infotext</A><p>\n </body></noframes>\n"
                      "</frameset>\n"
                      "</html>\n", fileName.c_str() , fileName.c_str(), fileName.c_str(), fileName.c_str(), fileName.c_str(), fileName.c_str(), fileName.c_str(), fileName.c_str() );

            const char* header = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
                      "<html>\n"
                      "<HEAD>\n"
                      "<meta http-equiv=\"content-type\" content=\"text/html; charset=ISO-8859-1\">"
                      "<TITLE>%s</TITLE>\n"
                      "<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"%s\">\n"
                      "</HEAD>\n"
                      "\n"
                      "<BODY  class=\"%s\">\n<p>\n";

            // UNIT GENERAL
            fprintf ( generalPage, header, "general", cl.t().c_str(), "wgleft" );

            // UNIT TERRAIN
            fprintf ( movePage, header, "movement", cl.t().c_str(), "wg" );

            // UNIT WEAPONS
            fprintf ( weaponPage, header, "terrain", cl.t().c_str(), "wg" );

            // UNIT FUNCTIONS
            fprintf ( constructionPage, header, "unitguide functions", cl.t().c_str(), "wg" );

            // UNIT LOADING
            fprintf ( transportPage, header, "transportation", cl.t().c_str(), "wg" );

            // UNIT DESCRIPTION
            fprintf ( infoPage, header, "description", cl.t().c_str(), "wg" );

            fprintf ( researchPage, header, "research", cl.t().c_str(), "wg" );

            // OVERVIEW LEFT
            fprintf ( overview, " <tr><td><A HREF=\"%s.html\">", fileName.c_str() );
            fprintf ( overview, "%s", ft->getName().c_str() );
            fprintf ( overview, " </A></td></tr>\n" );

            // OVERVIEW RIGHT
            fprintf ( overview1, " <tr><td class=\"wgov\">" );
            fprintf ( overview1, "<img src=\"%s\" alt=\"image of unit\" width=\"%d\" height=\"%d\"> </td>", (fileName + ".gif").c_str(), cl.z(), cl.z() );
            fprintf ( overview1, "<td class=\"wgov\" ><A HREF=\"%s.html\">%s</A><br><a href=\"%s.html\">%s</a></td></tr>\n", fileName.c_str(), ft->name.c_str(), fileName.c_str(), ft->description.c_str() );

            // END OVERVIEW RIGHT

            // we are adding a link to the overview file.
            // to put a singile " into a string we must use double quotes ( "" ), because a single quote is interpreted as the end of the string by C
            // %s tells C to insert a string there. The strings are appended at the end of the command
            // at the first %s the filename in s is inserted, at the second %s the unit variable 'description'

            // UNIT GENERAL
            /*
            fprintf ( generalPage, "<table width=\"100%\" border=\"1\" class=\"wg\"> \n"
                      "<tr><td colspan=\"2\"></td><td id=\"H9\" align=\"right\">UNIT GUIDE v2.1 </td></tr>"
                      "<tr><td width=\"50\">" );

            // if there is a big image for this unit, insert it
            if ( exist ( b1.c_str() ))
               fprintf ( generalPage, "<img src=\"%s\">", b1.c_str() );

            fprintf ( generalPage, "</td>\n<td>" );

            fprintf ( generalPage, "<table class=\"wg\"> \n" );
            fprintf ( generalPage, "<tr>  <th class=\"wg\"> Name</th>  <td align=\"center\" colspan=\"4\">%s</td> </tr>\n", ft->name.c_str() );

            */
            fprintf( generalPage, "<h2>General Information</h2>\n" );

            fprintf ( generalPage, "<table %s> \n", tableParam );

            printMainLine ( generalPage, "Name", ft->name );
            ASCString sze = strrr( cl.z() );
            printMainLine ( generalPage, "Image", ASCString("<img src=\"") + fileName + ".gif\" width=\""+sze+"\" height=\""+sze+"\" alt=\"image of unit\">" );
            printMainLine ( generalPage, "Description", ft->description );
            printMainLine ( generalPage, "ID", ft->id );
            printMainLine ( generalPage, "Empty weight", ft->weight );
            printMainLine ( generalPage, "Full weight", ft->weight + ft->tank.material * resourceWeight[1] / 1000 + ft->tank.fuel * resourceWeight[2] / 1000 + ft->tank.energy * resourceWeight[0] / 1000 );
            printMainLine ( generalPage, "Group", cmovemalitypes[ft->movemalustyp] );
            printMainLine ( generalPage, "Armor", ft->armor );
            printMainLine ( generalPage, "View",  ft->view );
            printMainLine ( generalPage, "Radar Jamming", ft->jamming );
            printMainLine ( generalPage, "Production Cost Material", ft->productionCost.material );
            printMainLine ( generalPage, "Production Cost energy", ft->productionCost.energy );
            printMainLine ( generalPage, "Unit can attack after moving", ft->wait ? "no": "yes" );
            printMainLine ( generalPage, "Unit can move after attacking", ft->functions & cf_moveafterattack ? "yes": "no" );

            ASCString funcs;
            for ( int i = 0; i<cvehiclefunctionsnum; i++)
               if ( ft->functions & ( 1 << i ))
                  funcs += ASCString(cvehiclefunctions[i]) + "<br>";
            printMainLine ( generalPage, "Functions &amp; Properties", funcs );

            printMainLine ( generalPage, "Auto Repair Rate [%]", ft->autorepairrate );
            printMainLine ( generalPage, "Resource detection radius", ft->digrange );

            fprintf ( generalPage, "</table>\n" );

            /*
            fprintf ( generalPage, "</td>\n\n<td class=\"wg\">" );
            if ( exist ( b2.c_str() ))
               fprintf ( generalPage, "<img src=\"%s\">", b2.c_str() );
            fprintf ( generalPage, "</td></tr></table>\n" );
            */

            const char* pages[pageNum] = { "Basic Data", "Movement", "Weapon&nbsp;Systems", "Construction", "Transportation", "Description", "Research" };

            for ( int i = 1; i < pageNum; i++ ) {
               for  ( int j = 1; j < pageNum; j++ )
                  if ( i != j )
                    fprintf ( files[i], "<a href=\"%s%d.html\">%s</a> " , fileName.c_str(), j+1, pages[j] );
                  else
                    fprintf ( files[i], "%s " , pages[j] );
            }


            // END UNIT GENERAL

            // some details about the unit; %d tells C to insert a decimal number there
            // take a look at the vehicletype class in vehicletype.h for the names of all variables that make a vehicletype
            // be carefuel not to make a , at the end of the first lines, since this would seperate the string in to several independant strings

            // choehenstufen is a global array that contains the names of the height levels


            // BEGIN MOVEMENT

            fprintf( movePage, "\n<h2>Movement</h2>\n" );

            fprintf( movePage, "\n<h3>Speed and Levels of Height</h3>\n" );

            // Hoehenstufen
            int i,w;
            // Tabellenbeginn
            fprintf( movePage, "<TABLE %s> \n<tr>", tableParam );
            //  "<TR><th colspan=\"9\" class=\"wg\">Levels of height:</th></tr>\n<tr>");
            // Spaltentitel
            fprintf ( movePage, "<td></td>" );
            for ( i = 0; i < 8; i++ ) {
               fprintf ( movePage, " <Th class=\"wg\"><IMG src=\"../hoehe%d.gif\" alt=\"%s\"></th>", i, choehenstufen[i]);
            }
            fprintf( movePage, "</TR>\n<TR>");

            // Spaltenwerte Haken
            fprintf ( movePage, "<th>Reachable</th>" );
            for ( i = 0; i < 8; i++ )
               if ( ft->height & ( 1 << i ))
                  fprintf ( movePage, " <TD><img src=\"../haken.gif\" alt=\"tick\"></TD>" );
               else
                  fprintf ( movePage, " <TD></TD>"  );
            fprintf( movePage, "</TR>\n<TR>");
            // Spaltenwerte pro Runde
            fprintf ( movePage, "<th>Movement</th>" );

            for ( i = 0; i < 8 ; i++ )
               if ( ft->height & ( 1 << i ))
                  fprintf ( movePage, " <TD align=\"center\">%d</TD>", (ft->movement[i]/10) );
               else
                  fprintf ( movePage, " <TD></TD>"  );
            fprintf( movePage, "</TR>\n</TABLE>\n");



            // Einzelne Werte
            // Tabellenbeginn
            fprintf( movePage, "\n<h3>Range and Capacities</h3>\n" );

            fprintf( movePage, "<TABLE %s>\n",tableParam );
            printMainLine ( movePage, "Fuel tank", ft->tank.fuel );
            printMainLine ( movePage, "Energy tank", ft->tank.energy );
            printMainLine ( movePage, "Material tank", ft->tank.material );
            printMainLine ( movePage, "Fuel Consumption", ft->fuelConsumption );
            printMainLine ( movePage, "Range", ft->fuelConsumption ? strrr(ft->tank.fuel/ft->fuelConsumption) : "--" );
            printMainLine ( movePage, "max. Wind", ft->maxwindspeedonwater >= 255 ? "-" : strrr( ft->maxwindspeedonwater ) );

            fprintf( movePage, "</TABLE>\n");

            fprintf( movePage, "\n<h3>Accessible Terrain</h3>\n" );

            fprintf( movePage, "<TABLE %s>\n", tableParam );
            fprintf( movePage, "<tr><th class=\"wg\">terrain type</th><th class=\"wg\">accessible</th><th class=\"wg\">required</th><th class=\"wg\">not accessible</th><th class=\"wg\">fatal</th></tr>");

            for ( i = 0; i < cbodenartennum ; i++ ) {
               printIndex ( movePage, cbodenarten[i] );

               if ( ft->terrainaccess.terrain.test(i) )
                  printValue ( movePage, "<img src=\"../haken.gif\" alt=\"tick\">", "align=\"center\"" );
               else
                  printValue ( movePage, "" );

               if ( ft->terrainaccess.terrainreq.test(i) )
                  printValue ( movePage, "<img src=\"../exkl.gif\" alt=\"exklamation\">", "align=\"center\"" );
               else
                  printValue ( movePage, "" );

               if ( ft->terrainaccess.terrainnot.test(i) )
                  printValue ( movePage, "<img src=\"../hakenrot.gif\" alt=\"exklamation\">", "align=\"center\"" );
               else
                  printValue ( movePage, "" );

               if ( ft->terrainaccess.terrainkill.test(i) )
                  printValue ( movePage, "<img src=\"../hakenrot.gif\" alt=\"exklamation\">", "align=\"center\"" );
               else
                  printValue ( movePage, "" );


               printLineEnd( movePage );
            } /* endfor */

            fprintf ( movePage, "</table>\n" );

            fprintf( movePage, "\n<h3>Height Change Methods</h3>\n" );

            if ( ft->heightChangeMethodNum ) {
               fprintf( movePage, "<TABLE %s>\n", tableParam );

               printIndex ( movePage, "Method" );
               for ( int w = 0; w < ft->heightChangeMethodNum ; w++)
                  fprintf ( movePage, "<th class=\"wg\">%d </th>", w);
               printLineEnd ( movePage );

               printIndex ( movePage, "Starting height");
               for ( int w = 0; w < ft->heightChangeMethodNum ; w++) {
                   ASCString hstring;
                   for ( int h = 7; h >= 0; h-- )
                      if ( ft->heightChangeMethod[w].startHeight & (1 << h ) & ft->height ) {
                         ASCString s;
                         s.format ( "<IMG src=\"../hoehe%d.gif\" alt=\"%s\"> <br>", h, choehenstufen[h] );
                         hstring += s;
                      } else {
                         ASCString s;
                         s.format ( "<IMG src=\"../hoehetrans.gif\" alt=\"height %s not accessible\"> <br>", choehenstufen[h] ) ;
                         hstring += s;
                      }
                   printValue ( movePage, hstring );
               }
               printLineEnd ( movePage );

               printIndex ( movePage, "Height Change:");
               for ( int w = 0; w < ft->heightChangeMethodNum ; w++) {
                  ASCString v;
                  if ( ft->heightChangeMethod[w].heightDelta > 0 )
                     v.format ( "+%s", strrr(ft->heightChangeMethod[w].heightDelta));
                  else
                     v.format ( "%s", strrr(ft->heightChangeMethod[w].heightDelta));
                     
                   printValue ( movePage, v );
               }
               printLineEnd ( movePage );

               printIndex ( movePage, "Movement Cost:");
               for ( int w = 0; w < ft->heightChangeMethodNum ; w++) 
                   printValue ( movePage, ft->heightChangeMethod[w].moveCost );
               printLineEnd ( movePage );

               printIndex ( movePage, "Can attack afterwards:");
               for ( int w = 0; w < ft->heightChangeMethodNum ; w++)
                   printValue ( movePage, ft->heightChangeMethod[w].canAttack ? "yes" : "no" );
               printLineEnd ( movePage );
               
               printIndex ( movePage, "Distance:");
               for ( int w = 0; w < ft->heightChangeMethodNum ; w++)
                   printValue ( movePage, ft->heightChangeMethod[w].dist );
               printLineEnd ( movePage );
               
               fprintf ( movePage, "</table>\n" );
            } else
               fprintf( movePage, "<p>This unit can not change its level of height\n" );



            // BEGIN WEAPONS
            // Waffen NR-AMMO-DISTANCE-STRENGS-SHOT FROM-ATTACK TO-TYP

            fprintf( weaponPage, "<h2>Weapon Systems</h2>\n" );

            if ( ft->weapons.count ) {
               fprintf ( weaponPage, "<table %s> \n", tableParam );



               printIndex ( weaponPage, "Weapon system" );
               // fprintf ( weaponPage, "<tr><th class=\"wg\">Weapon system </th>");
               for ( int w = 0; w < ft->weapons.count ; w++)
                  fprintf ( weaponPage, "<th class=\"wg\">%d </th>", w);
               printLineEnd ( weaponPage );


               printIndex ( weaponPage, "Name");
               for ( int w = 0; w < ft->weapons.count ; w++)
                  printValue ( weaponPage, ft->weapons.weapon[w].getName() );
               printLineEnd ( weaponPage );


               printIndex ( weaponPage, "Min Range");
               for ( int w = 0; w < ft->weapons.count ; w++)
                  printValue ( weaponPage, (ft->weapons.weapon[w].mindistance+9)/10 );
               printLineEnd ( weaponPage );

               printIndex ( weaponPage, "Max Range");
               for ( int w = 0; w < ft->weapons.count ; w++)
                  printValue ( weaponPage, ft->weapons.weapon[w].maxdistance/10 );
               printLineEnd ( weaponPage );


               printIndex ( weaponPage, "Punch @ min. range");
               for ( int w = 0; w < ft->weapons.count ; w++)
                  printValue ( weaponPage, ft->weapons.weapon[w].maxstrength );
               printLineEnd ( weaponPage );

               printIndex ( weaponPage, "Punch @ max. range");
               for ( int w = 0; w < ft->weapons.count ; w++)
                  printValue ( weaponPage, ft->weapons.weapon[w].minstrength );
               printLineEnd ( weaponPage );

               printIndex ( weaponPage, "Ammo");
               for ( int w = 0; w < ft->weapons.count ; w++)
                  printValue ( weaponPage, ft->weapons.weapon[w].count );
               printLineEnd ( weaponPage );

               bool laser = false;
               for ( int w = 0; w < ft->weapons.count ; w++)
                  if ( ft->weapons.weapon[w].gettype() & cwlaserb )
                     laser = true;

               if ( laser ) {
                  printIndex ( weaponPage, "Laser recharge rate");
                  for ( int w = 0; w < ft->weapons.count ; w++)
                     printValue ( weaponPage, ft->weapons.weapon[w].laserRechargeRate );
                  printLineEnd ( weaponPage );

                  printIndex ( weaponPage, "Resources to recharge laser");
                  for ( int w = 0; w < ft->weapons.count ; w++) {
                     ASCString s;
                     for ( int r = 0; r < 3; r++ )
                        if ( ft->weapons.weapon[w].laserRechargeCost.resource(r)) {
                           if ( !s.empty() )
                              s += "; ";
                           s += strrr(ft->weapons.weapon[w].laserRechargeCost.resource(r));
                           s += " " ;
                           s += resourceNames[r] ;
                        }
                     printValue ( weaponPage, s );
                  }
                  printLineEnd ( weaponPage );
                  
               }


               printIndex ( weaponPage, "Can be fired");
               for ( int w = 0; w < ft->weapons.count ; w++)
                  if ( ft->weapons.weapon[w].shootable() )
                     printValue ( weaponPage, "<img src=\"../haken.gif\" alt=\"tick\">" );
                  else
                     printValue ( weaponPage, "" );
               printLineEnd ( weaponPage );

               printIndex ( weaponPage, "Can transfer ammo");
               for ( int w = 0; w < ft->weapons.count ; w++)
                  if ( ft->weapons.weapon[w].canRefuel() )
                     printValue ( weaponPage, "<img src=\"../haken.gif\" alt=\"tick\">" );
                  else
                     printValue ( weaponPage, "" );
               printLineEnd ( weaponPage );

               fprintf(weaponPage, "<tr><th colspan=\"%d\"><h3>Operating Height</h3></th></tr>\n", ft->weapons.count+1 );

               printIndex( weaponPage, "Targets" );
               for ( int w = 0; w < ft->weapons.count ; w++) {
                   ASCString hstring;
                   for ( int h = 0; h < 8; h++ )
                      if ( ft->weapons.weapon[w].targ & (1 << h )) {
                         ASCString s;
                         s.format ( "<IMG src=\"../hoehe%d.gif\" alt=\"%s\"> <br>", h, choehenstufen[h] );
                         hstring += s;
                      } else {
                         ASCString s;
                         s.format ( "<IMG src=\"../hoehetrans.gif\" alt=\"height %s not accessible\"> <br>", choehenstufen[h] ) ;
                         hstring += s;
                      }
                   printValue ( weaponPage, hstring );
               }
               printLineEnd ( weaponPage );


               printIndex( weaponPage, "Usable on" );
               for ( int w = 0; w < ft->weapons.count ; w++) {
                   ASCString hstring;
                   for ( int h = 0; h < 8; h++ )
                      if ( ft->weapons.weapon[w].sourceheight & (1 << h )) {
                         ASCString s;
                         s.format ( "<IMG src=\"../hoehe%d.gif\" alt=\"%s\"> <br>", h, choehenstufen[h] );
                         hstring += s;
                      } else {
                         ASCString s;
                         s.format ( "<IMG src=\"../hoehetrans.gif\" alt=\"height %s not accessible\"> <br>", choehenstufen[h] ) ;
                         hstring += s;
                      }
                   printValue ( weaponPage, hstring );
               }
               printLineEnd ( weaponPage );


               fprintf(weaponPage, "<tr><th colspan=\"%d\"><h3>Targeting Accuracy: Target Types</h3></th></tr>\n", ft->weapons.count+1 );


               for ( int h = 0; h < cmovemalitypenum; h++ ) {
                  fprintf ( weaponPage, "<tr><th class=\"wg\" >%s </th>", cmovemalitypes[h] );
                  for ( int w = 0; w < ft->weapons.count ; w++)
                     fprintf ( weaponPage, "<td>%d %% </td>", ft->weapons.weapon[w].targetingAccuracy[h] );
                  fprintf ( weaponPage, "</tr>");
               }

               fprintf(weaponPage, "<tr><th colspan=\"%d\"><h3>Targeting Accuracy: Altitude Difference</h3></th></tr>\n", ft->weapons.count+1 );

               for ( int h = 0; h < 13; h++ ) {
                  fprintf ( weaponPage, "<tr><th class=\"wg\" >%i </th>", h-6 );
                  for ( int w = 0; w < ft->weapons.count ; w++)
                     if ( ft->weapons.weapon[w].efficiency[h] > 0 )
                        fprintf ( weaponPage, " <TD>%d %%</TD>", ft->weapons.weapon[w].efficiency[h] );
                     else
                        fprintf ( weaponPage, " <TD> </TD>"  );

                  fprintf ( weaponPage, "</tr>");
               }

               fprintf ( weaponPage, "</table> \n" );
            } else
               fprintf ( weaponPage, "This unit does not have any weapon systems \n" );
            //ENDE WAFFEN





            //BEGINN CONSTRUCTIOn

            fprintf( constructionPage, "<h2>Construction</h2>\n" );


            int size = 0;

            fprintf ( constructionPage, "<table %s>\n", tableParam );

            ASCString names;
            for ( unsigned int i = 0; i < ft->objectsBuildable.size(); i++ ) {
               for ( int b = 0; b < objectTypeRepository.getNum(); b++ ) {
                  pobjecttype obj = objectTypeRepository.getObject_byPos ( b );
                  if (     obj->id >= ft->objectsBuildable[i].from
                        && obj->id <= ft->objectsBuildable[i].to ) {
                     ASCString s;
                     s.format ( "%s (ID %d) <br>", obj->name.c_str(), obj->id );
                     names += s;
                     ++size;
                  }
               }
            }
            if ( !names.empty() )
               printMainLine ( constructionPage, "Constructable Objects", names);

             // Objekte abreissbar
            names = "";
            for ( unsigned int i = 0; i < ft->objectsRemovable.size(); i++ ) {
               for ( int b = 0; b < objectTypeRepository.getNum(); b++ ) {
                  pobjecttype obj = objectTypeRepository.getObject_byPos ( b );
                  if (     obj->id >= ft->objectsRemovable[i].from
                        && obj->id <= ft->objectsRemovable[i].to ) {
                     ASCString s;
                     s.format ( "%s (ID %d) <br>", obj->name.c_str(), obj->id );
                     names += s;
                     ++size;
                  }
               }
            }
            if ( !names.empty() )
               printMainLine ( constructionPage, "Destructable Objects", names);

            names = "";
            for ( vector<IntRange>::iterator  i = ft->objectGroupsBuildable.begin(); i != ft->objectGroupsBuildable.end(); ++i ) {
               ASCString s;
               if ( i->from != i->to )
                  s.format ( "%d - %d <br>", i->from, i->to );
               else
                  s.format ( "%d <br>", i->from );
               names += s;
               ++size;
            }
            if ( !names.empty() )
               printMainLine ( constructionPage, "Constructable Object-Groups", names);

             // Objekte abreissbar
            names = "";
            for ( vector<IntRange>::iterator i = ft->objectGroupsRemovable.begin(); i != ft->objectGroupsRemovable.end(); ++i ) {
               ASCString s;
               if ( i->from != i->to )
                  s.format ( "%d - %d <br>", i->from, i->to );
               else
                  s.format ( "%d <br>", i->from );
               names += s;
               ++size;
            }
            if ( !names.empty() )
               printMainLine ( constructionPage, "Destructable Object-Groups", names);


            // UNITS
            names = "";
            for ( unsigned int i = 0; i < ft->vehiclesBuildable.size(); i++ ) {
               for ( int b = 0; b < vehicleTypeRepository.getNum(); b++ ) {
                  pvehicletype veh = vehicleTypeRepository.getObject_byPos ( b );
                  if (     veh->id >= ft->vehiclesBuildable[i].from
                        && veh->id <= ft->vehiclesBuildable[i].to ) {
                     ASCString filename = extractFileName_withoutSuffix( veh->filename ) + ".html";
                     ASCString s;
                     s.format ( "<A HREF=\"%s\" target=\"_parent\">%s (ID %d)</A> <br>", filename.c_str(), veh->getName().c_str(), veh->id );
                     names += s;
                     ++size;
                  }
               }
            }
            if ( !names.empty() )
               printMainLine ( constructionPage, "Constructable Units", names);

            // Geb&auml;ude
            names = "";
            for ( unsigned int i = 0; i < ft->buildingsBuildable.size(); i++ ) {
               for ( int b = 0; b < buildingTypeRepository.getNum(); b++ ) {
                  pbuildingtype bld = buildingTypeRepository.getObject_byPos ( b );
                  if (     bld->id >= ft->buildingsBuildable[i].from
                           && bld->id <= ft->buildingsBuildable[i].to ) {
                     ASCString s;
                     s.format ( "%s (ID %d) <br>", bld->name.c_str(), bld->id );
                     names += s;
                     ++size;
                  }
               }
            }
            if ( !names.empty() )
               printMainLine ( constructionPage, "Constructable Buildings", names);

            if ( !size )
               fprintf ( constructionPage, "<tr><td>This unit can not build or remove anything</td></tr>" );
            fprintf ( constructionPage, "</table>\n" );



            //ENDE FUNKTIONS





            //BEGINN LOADING

            fprintf( transportPage, "<h2>Transportation</h2>\n" );

            fprintf ( transportPage, "<table %s>\n", tableParam );
            printMainLine ( transportPage, "Max. loadable units", ft->maxLoadableUnits );
            if ( ft->maxLoadableUnits ) {
               printMainLine ( transportPage, "Max. total cargo weight", ft->maxLoadableWeight );
               printMainLine ( transportPage, "Max. single cargo weight", ft->maxLoadableUnitSize );


               ASCString type;
               for ( int h = 0; h < cmovemalitypenum; h++ )
                  if ( ft->vehicleCategoriesStorable & (1 << h)) {
                     type += cmovemalitypes[h];
                     type += "<br>";
                  }
               printMainLine ( transportPage, "Units from these groups can be loaded", type );

               fprintf ( transportPage, "</table>\n" );


               if ( !ft->entranceSystems.empty() ) {
                  fprintf ( transportPage, "<h2>Entrance System</h2>\n" );
                  fprintf ( transportPage, "<table %s>\n", tableParam );


                  printIndex ( transportPage, "Mode" );
                  for ( ContainerBaseType::EntranceSystems::iterator i = ft->entranceSystems.begin(); i != ft->entranceSystems.end(); i++ ) {
                      ASCString s;
                      if ( i->mode & ContainerBaseType::TransportationIO::In )
                         s += "In<br>";
                      if ( i->mode & ContainerBaseType::TransportationIO::Out )
                         s += "Out<br>";
                      if ( i->mode & ContainerBaseType::TransportationIO::Docking )
                         s += "Docking<br>";
                      printValue ( transportPage, s );
                  }
                  printLineEnd( transportPage );

                  printIndex ( transportPage, "Absolute height of loadable units" );
                  for ( ContainerBaseType::EntranceSystems::iterator i = ft->entranceSystems.begin(); i != ft->entranceSystems.end(); i++ )
                      printValue ( transportPage, getHeightImgString( i->height_abs) );

                  printLineEnd( transportPage );

                  printIndex ( transportPage, "Relative height of loadable units" );
                  for ( ContainerBaseType::EntranceSystems::iterator i = ft->entranceSystems.begin(); i != ft->entranceSystems.end(); i++ ) {
                     if ( i->height_rel != -100 )
                        printValue ( transportPage, strrr(i->height_rel) );
                     else
                        printValue ( transportPage, "-" );
                  }
                  printLineEnd( transportPage );

                  printIndex ( transportPage, "The transport must be on this height" );
                  for ( ContainerBaseType::EntranceSystems::iterator i = ft->entranceSystems.begin(); i != ft->entranceSystems.end(); i++ )
                      printValue ( transportPage, getHeightImgString( i->height_abs & ft->height) );
                  printLineEnd( transportPage );


                  printIndex ( transportPage, "Absolute docking height" );
                  for ( ContainerBaseType::EntranceSystems::iterator i = ft->entranceSystems.begin(); i != ft->entranceSystems.end(); i++ )
                     if ( i->mode & ContainerBaseType::TransportationIO::Docking )
                         printValue ( transportPage, getHeightImgString( i->dockingHeight_abs) );
                     else
                         printValue ( transportPage, "" );
                  printLineEnd( transportPage );

                  printIndex ( transportPage, "Relative height of loadable units" );
                  for ( ContainerBaseType::EntranceSystems::iterator i = ft->entranceSystems.begin(); i != ft->entranceSystems.end(); i++ ) {
                     if ( i->mode & ContainerBaseType::TransportationIO::Docking &&  i->dockingHeight_rel != -100 )
                        printValue ( transportPage, strrr(i->dockingHeight_rel) );
                     else
                        printValue ( transportPage, "" );
                  }
                  printLineEnd( transportPage );

                  printIndex ( transportPage, "Excluded unit groups" );
                  for ( ContainerBaseType::EntranceSystems::iterator i = ft->entranceSystems.begin(); i != ft->entranceSystems.end(); i++ ) {
                      ASCString s;
                      for ( int h = 0; h < cmovemalitypenum; h++ )
                         if ( !(i->vehicleCategoriesLoadable & (1 << h))) {
                            s += cmovemalitypes[h] ;
                            s += "<br>";
                         }

                      printValue ( transportPage, s );
                  }
                  printLineEnd( transportPage );

                  printIndex ( transportPage, "Unit can attack afterwards" );
                  for ( ContainerBaseType::EntranceSystems::iterator i = ft->entranceSystems.begin(); i != ft->entranceSystems.end(); i++ )
                     printValue ( transportPage, i->disableAttack ? "No": "Yes" );

                  printLineEnd( transportPage );

                  printIndex ( transportPage, "Require unit functions" );
                  for ( ContainerBaseType::EntranceSystems::iterator i = ft->entranceSystems.begin(); i != ft->entranceSystems.end(); i++ ) {
                     ASCString funcs;
                     for ( int j = 0; j<cvehiclefunctionsnum; j++)
                        if ( i->requireUnitFunction & ( 1 << j ))
                           funcs += ASCString(cvehiclefunctions[j]) + "<br>";
                     printValue ( transportPage, funcs );
                  }

                  printLineEnd( transportPage );



                  printIndex ( transportPage, "Movement cost override" );
                  for ( ContainerBaseType::EntranceSystems::iterator i = ft->entranceSystems.begin(); i != ft->entranceSystems.end(); i++ )
                     if ( i->movecost >= 0 )
                        printValue ( transportPage, strrr(i->movecost) );
                     else
                        printValue ( transportPage, "-" );

                  printLineEnd( transportPage );
               }
            }
            fprintf ( transportPage, "</table>\n" );




            //BEGINN DESCRIPTION
            fprintf ( infoPage, "<H2>Information about this Unit</H2>\n<p>" );


            FILE* fp = fopen ( ASCString(prefixDir + fileName + ".jpg").c_str(), "r" );
            if ( fp ) {
               fclose ( fp );
               fprintf( infoPage, "<p>\n<img src=\"%s.jpg\"><p>\n", fileName.c_str() );
            }

            if ( !ft->infotext.empty() ) {
               ASCString text = ft->infotext;
               while ( text.find ( "#crt#" ) != ASCString::npos )
                  text.replace ( text.find  ("#crt#"), 5, "<p>");
               while ( text.find ( "#CRT#" ) != ASCString::npos )
                  text.replace ( text.find  ("#CRT#"), 5, "<p>");
               while ( text.find ( "\n" ) != ASCString::npos )
                  text.replace ( text.find  ("\n"), 1, "<p>");
               while ( text.find ( "\r" ) != ASCString::npos )
                  text.replace ( text.find  ("\r"), 1, "");

               ASCString::size_type begin = 0;
               ASCString::size_type end = 0;
               do {
                  begin = text.find ( "#", end );
                  if ( begin != ASCString::npos && begin+1 < text.length() ) {
                     end = text.find ( "#", begin+1 );
                     if ( end != ASCString::npos ) {
                        text.erase ( begin, end-begin+1 );
                        begin = 0;
                        end = 0;
                     }
                  } else
                     end = ASCString::npos;
               } while ( end != ASCString::npos );

               fprintf ( infoPage, "%s", text.c_str() );
            }
            else {
               fprintf ( infoPage, "no information available " );
            }

            //ENDE DESCRIPTION




            fprintf ( researchPage, "<H2>Technology Dependencies</H2>\n<p>" );


            #ifdef USE_GRAPHVIZ
            ASCString temptechfilename = tempPath + fileName + "_tech";
            {
               tn_file_buf_stream f ( temptechfilename + ".dot", tnstream::writing );

               f.writeString ( "digraph \"Tech Dependency\" { \nnode [color=gray]\n", false );


               ft->techDependency.writeInvertTreeOutput( ft->getName() + " ", f );
               f.writeString ( "\"" + ft->getName() + " \" [shape=diamond] \n", false );

               f.writeString ( "}\n", false );
            }

            fprintf ( researchPage, "<img src=\"%s_tech.png\">\n<p>", fileName.c_str() );

            ASCString sysCommand = "dot " + temptechfilename + ".dot  -Tpng -o" + temptechfilename + ".png";
            int res = system ( sysCommand.c_str() );
            if ( res != 0 )
               printf("error running command  %s \n", sysCommand.c_str() );
            else
               copyFile ( temptechfilename + ".png", prefixDir + fileName + "_tech.png" );
            #endif


            // ABSCHLU˜ DER DOKUMENTE

            fprintf ( generalPage, "</body></html>\n");
            fprintf ( movePage, "</body></html>\n");
            fprintf ( weaponPage, "</body></html>\n");
            fprintf ( constructionPage, "</body></html>\n");
            fprintf ( transportPage, "</body></html>\n");
            fprintf ( infoPage, "</body></html>\n");
            fprintf ( researchPage, "</body></html>\n");
            // Ende des Einheiten Dokuments

            fclose ( framePage );
            fclose ( generalPage );
            fclose ( movePage );
            fclose ( weaponPage );
            fclose ( constructionPage );
            fclose ( transportPage );
            fclose ( infoPage );
            fclose ( researchPage );
            // closing the file


            for ( int i = 0; i <= pageNum; i++ ) {
               ASCString nm = fileName;
               if ( i > 0 )
                 nm += strrr(i);
               nm += ".html";
               copyFile ( tempPath + nm, prefixDir + nm );
            }

            if ( cl.i() ) {
               tvirtualdisplay sb(100,100,255);
               putspriteimage ( 0, 0, ft->picture[0] );
               pal[255][0] = 254;
               pal[255][1] = 253;
               pal[255][2] = 252;
               #ifdef _WIN32_
               ASCString command = "convert " + tempPath + "weaponguide.pcx -transparent \"#f8f4f0\" "; // -transparent 255
               command += tempPath + fileName;
               command += ".gif";
               writepcx ( tempPath+"weaponguide.pcx", 0, 0, fieldsizex, fieldsizey, pal );
               #else
               ASCString command = "convert /tmp/weaponguide.pcx -transparent \"#f8f4f0\" "; // -transparent 255
               command += tempPath + fileName;
               command += ".gif";
               writepcx ( "/tmp/weaponguide.pcx", 0, 0, fieldsizex, fieldsizey, pal );
               #endif
               // printf("%s\n", command.c_str() );
               printf("creating image...");
               system( command.c_str() );
               copyFile( tempPath + fileName+ ".gif", prefixDir + fileName+ ".gif" );
               remove ( (tempPath+"weaponguide.pcx").c_str() );
            }
            
            printf(" done \n" );
            // we are writing this not to a file, but the screen

         }

      }

      // Dokument Übersicht Ende

      fprintf( overview , "</table></body></html>\n" );
      fprintf ( overview1, "</table></body></html>\n" );

      fclose ( overview );
      fclose ( overview1 );

      copyFile ( tempPath + "overview.html", prefixDir + "overview.html" );
      copyFile ( tempPath + "overview1.html", prefixDir + "overview1.html" );

      printf("Generating unit listings");

      int counter = 0;
      for ( std::vector<SingleUnitSet*>::iterator i = unitSets.begin(); i != unitSets.end(); i++  ) {
         if ( (*i)->ID == cl.s() || !cl.s() ) {

            printf(".");
            ASCString filename = prefixDir + "unitset";
            if ( cl.s() > 0 )
               filename+=ASCString("_ID")+strrr(cl.s());
            else
               filename+=strrr(counter++);

            ASCString groupFile = filename + ".groups";
            FILE* ff = fopen ( groupFile.c_str(), "w" );

            fprintf(ff, "%s;asc.css;-;\n", (*i)->name.c_str() );


            const int groupNum = 6;
            const char* groupNames[groupNum] = { "trooper", "ground units", "aircraft", "marine units", "turrets", "misc" };

            for ( int j = 0; j < groupNum; j++ ) {
               fprintf(ff, ".%s;asc.css;-;\n", groupNames[j] );
               vector<ASCString> units;

               for ( int unit = 0; unit < vehicleTypeRepository.getNum(); unit++ ) {
                  pvehicletype  ft = vehicleTypeRepository.getObject_byPos ( unit );
                  if ( (*i)->isMember( ft->id )) {
                     int group;
                     switch ( ft->movemalustyp ) {
                         case 7:  //   "trooper"
                                 group = 0;
                                 break;
                         case 1:  // "light tracked vehicle"
                         case 2:  // "medium tracked vehicle"
                         case 3:  // "heavy tracked vehicle",
                         case 4:  // "light wheeled vehicle",
                         case 5:  //  "medium wheeled vehicle",
                         case 6:  //  "heavy wheeled vehicle",
                         case 8:   // "rail vehicle",
                                  group = 1;
                                  break;
                         case 9:   // "medium aircraft",
                         case 12:  // "light aircraft",
                         case 13:  // "heavy aircraft",
                         case 16:  //  "helicopter",
                                  group = 2;
                                  break;
                         case 10:  // "medium ship",
                         case 14:  // "light ship",
                         case 15:  // "heavy ship",
                                  group = 3;
                                  break;

                         case 11:  // "building / turret / object",
                                  group = 4;
                                  break;

                         case 0:  // default",
                         case 17: // "hoovercraft"
                         default:
                                  group = 5;
                                  break;
                     };
                     if ( group == j ) {
                        ASCString unitFileName = ASCString(extractFileName_withoutSuffix( ft->filename )) + ".html";
                        ASCString linkpref = cl.l();
                        #ifndef _WIN32_
                        if ( !linkpref.empty() )
                           appendbackslash( linkpref );
                        #else
                        if ( !linkpref.empty()  && linkpref[ linkpref.length() -1] != '/' )
                           linkpref += '/' ;
                        #endif
                           
                        ASCString line = "..";
                        line += ft->getName() + ";" + cl.m() + ";\"" + linkpref + unitFileName + "\" target = \"" + cl.f() + "\";\n"; 
                        // line.format("..%s;%s;\"%s%s\" target=\"%s\";\n", ft->getName().c_str(), cl.m.c_str(), linkpref.c_str(), unitFileName.c_str(), );
                        units.push_back(line);
                     }
                  }
               }
               sort ( units.begin(), units.end());
               for ( int u = 0; u < units.size(); u++ )
                  fprintf(ff, "%s",units[u].c_str() );

            }

            map<int,Vehicletype*> byID;

            for ( int unit = 0; unit < vehicleTypeRepository.getNum(); unit++ ) {
               pvehicletype  ft = vehicleTypeRepository.getObject_byPos ( unit );
               if ( (*i)->isMember( ft->id ))
                  byID[ft->id] = ft;
            }


            fprintf(ff, ".Sorted by ID;asc.css;-;\n");
            for ( map<int,Vehicletype*>::iterator j = byID.begin(); j != byID.end(); j++ ) {
               ASCString unitFileName = ASCString(extractFileName_withoutSuffix( j->second->filename )) + ".html";
               ASCString linkpref = cl.l();
               if ( !linkpref.empty()  && linkpref[ linkpref.length() -1] != '/' )
                  linkpref += '/' ;

                fprintf(ff,"..%d (%s);asc.css;\"%s%s\" target=\"%s\";\n", j->second->id, j->second->getName().c_str(), linkpref.c_str(), unitFileName.c_str(), cl.f().c_str() );
            }


            fclose(ff);
         }

      }
      printf("\n");

      if ( cl.s() <= 0 ) {
         ASCString filename = prefixDir + "allUnits.groups";
         FILE* ff = fopen ( filename.c_str(), "w" );

         for ( int i = 0; i < counter; i++ )
            fprintf(ff, "#unitset%d.groups\n", i );
         fclose (ff);
      }

      
   } /* endtry */
   catch ( tfileerror err ) {
      fatalError("fatal error accessing file " + err.getFileName() );
      return 1;
   } /* endcatch */
   catch ( ASCmsgException err ) {
      fatalError("a fatal exception occured: " + err.getMessage() );
      return 2;
   } /* endcatch */
   catch ( ASCexception ) {
      fatalError("\na fatal exception occured\n" );
      return 2;
   } /* endcatch */

   return 0;
};



