
/**
 * Tries to find hadifix and mbrola by looking onto the hard disk. This is
 * neccessary because both hadifix and mbrola do not have standard
 * installation directories.
 */
void findInitialConfig() {
   TQString hadifixDataPath = findHadifixDataPath();
   
   defaultHadifixExec = findExecutable("txt2pho", hadifixDataPath+"/../");
   
   TQStringList list; list += "mbrola"; list += "mbrola-linux-i386";
   defaultMbrolaExec = findExecutable(list, hadifixDataPath+"/../../mbrola/");
   
   defaultVoices = findVoices (defaultMbrolaExec, hadifixDataPath);
}

/** Tries to find the hadifix data path by looking into a number of files. */
TQString findHadifixDataPath () {
   TQStringList files;
   files += "/etc/txt2pho";
   files += TQDir::homeDirPath()+"/.txt2phorc";
   
   TQStringList::iterator it;
   for (it = files.begin(); it != files.end(); ++it) {

      TQFile file(*it);
      if ( file.open(IO_ReadOnly) ) {
         TQTextStream stream(&file);
         
         while (!stream.atEnd()) {
            TQString s = stream.readLine().stripWhiteSpace();
	    // look for a line "DATAPATH=..."
	    
	    if (s.startsWith("DATAPATH")) {
	       s = s.mid(8, s.length()-8).stripWhiteSpace();
	       if (s.startsWith("=")) {
	          s = s.mid(1, s.length()-1).stripWhiteSpace();
		  if (s.startsWith("/"))
		     return s;
		  else {
		     TQFileInfo info (TQFileInfo(*it).dirPath() + "/" + s);
		     return info.absFilePath();
		  }
	       }
	    }
         }
         file.close();
      }
   }
   return "/usr/local/txt2pho/";
}

/** Tries to find the an executable by looking onto the hard disk. */
TQString findExecutable (const TQStringList &names, const TQString &possiblePath) {
   // a) Try to find it directly
   TQStringList::ConstIterator it;
   TQStringList::ConstIterator itEnd = names.constEnd();
   for (it = names.constBegin(); it != itEnd; ++it) {
      TQString executable = TDEStandardDirs::findExe (*it);
      if (!executable.isNull() && !executable.isEmpty())
         return executable;
   }

   // b) Try to find it in the path specified by the second parameter
   for (it = names.constBegin(); it != itEnd; ++it) {
      TQFileInfo info (possiblePath+*it);
      if (info.exists() && info.isExecutable() && info.isFile()) {
         return info.absFilePath();
      }
   }

   // Both tries failed, so the user has to locate the executable.
   return TQString();
}

/** Tries to find the voice files by looking onto the hard disk. */
TQStringList findVoices(TQString mbrolaExec, const TQString &hadifixDataPath) {
   
   // First of all:
   // dereference links to the mbrola executable (if mbrolaExec is a link).
   for (int i = 0; i < 10; ++i) {
      // If we have a chain of more than ten links something is surely wrong.
      TQFileInfo info (mbrolaExec);
      if (info.exists() && info.isSymLink())
            mbrolaExec = info.readLink();
   }

   // Second:
   // create a list of directories that possibly contain voice files
   TQStringList list;
   
   // 2a) search near the mbrola executable
   TQFileInfo info (mbrolaExec);
   if (info.exists() && info.isFile() && info.isExecutable()) {
      TQString mbrolaPath = info.dirPath (true);
      list += mbrolaPath;
   }

   // 2b) search near the hadifix data path
   info.setFile(hadifixDataPath + "../../mbrola");
   TQString mbrolaPath = info.dirPath (true) + "/mbrola";
   if (!list.contains(mbrolaPath))
      list += mbrolaPath;

   // 2c) broaden the search by adding subdirs (with a depth of 2)
   TQStringList subDirs = findSubdirs (list);
   TQStringList subSubDirs = findSubdirs (subDirs);
   list += subDirs;
   list += subSubDirs;

   // Third:
   // look into each of these directories and search for voice files.
   TQStringList result;
   TQStringList::iterator it;
   for (it = list.begin(); it != list.end(); ++it) {
      TQDir baseDir (*it, TQString(),
                    TQDir::Name|TQDir::IgnoreCase, TQDir::Files);
      TQStringList files = baseDir.entryList();

      TQStringList::iterator iter;
      for (iter = files.begin(); iter != files.end(); ++iter) {
         // Voice files start with "MBROLA", but are afterwards binary files
	 TQString filename = *it + "/" + *iter;
         TQFile file (filename);
         if (file.open(IO_ReadOnly)) {
            TQTextStream stream(&file);
            if (!stream.atEnd()) {
               TQString s = stream.readLine();
               if (s.startsWith("MBROLA"))
	          if (HadifixProc::determineGender(mbrolaExec, filename)
		   != HadifixProc::NoVoice
		  )
                     result += filename;
               file.close();
            }
         }
      }
   }
   return result;
}

/** Returns a list of subdirs (with absolute paths) */
TQStringList findSubdirs (const TQStringList &baseDirs) {
   TQStringList result;

   TQStringList::ConstIterator it;
   TQStringList::ConstIterator itEnd = baseDirs.constEnd();
   for (it = baseDirs.constBegin(); it != itEnd; ++it) {
      // a) get a list of directory names
      TQDir baseDir (*it, TQString(),
                    TQDir::Name|TQDir::IgnoreCase, TQDir::Dirs);
      TQStringList list = baseDir.entryList();

      // b) produce absolute paths
      TQStringList::ConstIterator iter;
      TQStringList::ConstIterator iterEnd = list.constEnd();
      for (iter = list.constBegin(); iter != iterEnd; ++iter) {
         if ((*iter != ".") && (*iter != ".."))
            result += *it + "/" + *iter;
      }
   }
   return result;
}
