
/******************************************************************************
* MODULE     : dir.gen.cc
* DESCRIPTION: manipulation of directories
* COPYRIGHT  : (C) 1999  Joris van der Hoeven
*******************************************************************************
* This software falls under the GNU general public license and comes WITHOUT
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
* If you don't have this file, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
******************************************************************************/

#include <tm_configure.gen.h>
#include <file.gen.h>
#include <dir.gen.h>
#include <path.gen.h>
#include <hashmap.gen.h>

#module code_dir
#import tm_configure
#import file
#import dir
#import path
#import hashmap (string, int)
#include <stddef.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

extern void initialize_data ();

static hashmap<string,int> tex_file_table (FALSE);

/******************************************************************************
* Getting attributes of a file
******************************************************************************/

static bool
get_attributes (string name, struct stat* buf, bool link_flag=FALSE) {
  bool flag;
  char* temp= as_charp (name);
  flag= (link_flag? lstat (temp, buf): stat (temp, buf));
  delete[] temp;
  return flag;
}

bool
is_regular (string name) {
  struct stat buf;
  if (get_attributes (name, &buf)) return FALSE;
  return S_ISREG (buf.st_mode);
}

bool
is_directory (string name) {
  struct stat buf;
  if (get_attributes (name, &buf)) return FALSE;
  return S_ISDIR (buf.st_mode);
}

bool
is_symbolic_link (string name) {
  struct stat buf;
  if (get_attributes (name, &buf, TRUE)) return FALSE;
  return S_ISLNK (buf.st_mode);
}

bool
is_newer (string which, string than) {
  struct stat which_stat;
  struct stat than_stat;
  if (get_attributes (which, &which_stat, TRUE)) return FALSE;
  if (get_attributes (than , &than_stat , TRUE)) return FALSE;
  return which_stat.st_mtime > than_stat.st_mtime;
}

/******************************************************************************
* Reading directories
******************************************************************************/

array<string>
read_directory (string name, bool& error_flag) {
  DIR* dp;
  char* temp= as_charp (name);
  dp= opendir (temp);
  delete[] temp;
  error_flag= (dp==NULL);
  if (error_flag) return array<string> ();

  array<string> dir;
  struct dirent* ep;
  while (TRUE) {
    ep= readdir (dp);
    if (ep==NULL) break;
    dir << string (ep->d_name);
  }
  (void) closedir (dp);
  merge_sort (dir);
  return dir;
}

static tree
directory_tree (string full_name, string name,
		bool& error_flag, bool only_dirs) {
  array<string> a= read_directory (full_name, error_flag);
  if (error_flag) return name;

  int i;
  bool flag;
  tree t (TUPLE, name);
  for (i=0; i<N(a); i++) {
    string rel_name= full_name * "/" * a[i];
    if (a[i] == ".") continue;
    if (a[i] == "..") continue;
    if (is_symbolic_link (rel_name)) {
      if (!only_dirs) t << tree (a[i]);
      continue;
    }
    if (is_regular (rel_name)) {
      if (!only_dirs) t << tree (a[i]);
      continue;
    }
    t << directory_tree (rel_name, a[i], flag, only_dirs);
  }
  return t;
}

tree
directory_tree (string name, bool& error_flag, bool only_dirs) {
  return directory_tree (name, name, error_flag, only_dirs);
}

/******************************************************************************
* Other functions on directories
******************************************************************************/

string
working_directory () {
  fatal_error ("not yet implemented", "working_directory", "dir.gen.cc");
  return ""; // Because of bug in certain versions of g++
}

string
home_directory () {
  fatal_error ("not yet implemented", "home_directory", "dir.gen.cc");
  return ""; // Because of bug in certain versions of g++
}

void
change_directory (string name) { (void) name;
  fatal_error ("not yet implemented", "change_directory", "dir.gen.cc");
}

/******************************************************************************
* Utilities
******************************************************************************/

string
complete_name (array<string> a, string s) {
  int i, j;
  string best_completion;
  for (i=0; i<N(a); i++) {
    if ((N(a[i]) >= N(s)) && (a[i] (0, N(s)) == s)) {
      if (N(best_completion) == 0) {
	best_completion= a[i];
	continue;
      }
      for (j=N(s); (j<N(best_completion)) && N(a[i]); j++)
	if (best_completion[j]!=a[i][j]) break;
      best_completion= best_completion (0, j);
    }
  }
  return best_completion;
}

static void
make_path (string& s, string prefix, tree dir_tree, bool inner) {
  int i;
  string name;
  if (N(prefix)==0) name= dir_tree[0]->label;
  else name= prefix * '/' * dir_tree[0]->label;
  if (inner || (N(dir_tree)==1)) {
    if (N(s)!=0) s << ':';
    s << name;
  }
  for (i=1; i<N(dir_tree); i++)
    make_path (s, name, dir_tree[i], inner);
}

string
make_path (tree dir_tree, bool inner) {
  string s;
  make_path (s, "", dir_tree, inner);
  return s;
}

/******************************************************************************
* Merging paths
******************************************************************************/

static string
merge_paths_sub (string p1, string s) {
  int i, start;
  bool flag=FALSE;
  for (start=0, i=0; i<N(p1); i++)
    if (p1[i]==':') {
      if (p1(start,i)==s) flag= TRUE;
      start= i+1;
    }
  if (p1(start,i)==s) flag=TRUE;
  if (flag) return p1;
  else if (N(p1)==0) return s;
  else return p1 * ":" * s;
}

string
merge_paths (string p1, string p2) {
  int i, start;
  for (start=0, i=0; i<N(p2); i++)
    if (p2[i]==':') {
      p1= merge_paths_sub (p1, p2 (start, i));
      start= i+1;
    }
  if (i>start) p1= merge_paths_sub (p1, p2 (start, i));
  return p1;
}

/******************************************************************************
* Utilities for TeX
******************************************************************************/

int  default_dpi    = 300;
int  supports_ec    = FALSE;
int  install_status = 0;

static bool use_kpsepath  = FALSE;
static bool use_kpsewhich = FALSE;
static int  use_make_pk   = 0;
static int  use_make_tfm  = 0;
static bool use_texhash   = FALSE;

void
make_tex_tfm (string name) {
  string s;
  switch (use_make_tfm) {
  case 0:
    break;
  case 1:
    s= "MakeTeXTFM " * name;
    if (debug (0)) cout << "TeXmacs] Executing " << s << "\n";
    system (s);
    break;
  case 2:
    s= "mktextfm " * name;
    if (debug (0)) cout << "TeXmacs] Executing " << s << "\n";
    system (s);
    break;
  }
}

void
make_tex_pk (string name, int dpi, int design_dpi, string where) {
  string s;
  switch (use_make_pk) {
  case 0:
    break;
  case 1:
    s="MakeTeXPK " * name * " " *
      as_string (dpi) * " " * as_string (design_dpi) * " " *
      as_string (dpi) * "/" * as_string (design_dpi) * " " * where;
    if (debug (0)) cout << "TeXmacs] Executing " << s << "\n";
    system (s);
    break;
  case 2:
    s="mktexpk " *
      string ("--dpi ") * as_string (dpi) * " " *
      string ("--bdpi ") * as_string (design_dpi) * " " *
      string ("--mag ") * as_string (dpi)*"/"*as_string (design_dpi) * " " *
      string ("--destdir ") * where * " " *
      name;
    if (debug (0)) cout << "TeXmacs] Executing " << s << "\n";
    system (s);
    break;
  }
}

static string
get_kpsepath (string s) {
  if (!use_kpsepath) return "";
  string r= var_eval_system ("kpsepath " * s);
  if (N(r)==0) return "";

  int i, start, end;
  string p (".");
  for (i=0; i<N(r); i++) {
    while ((i<N(r)) && (r[i]=='!')) i++;
    start=i;
    while ((i<N(r)) && (r[i]!=':')) i++;
    end=i;
    while ((end>start) && (r[end-1]=='/')) end--;
    string dir= r (start, end);
    if (dir == ".") continue;

    bool error_flag;
    tree t= directory_tree (dir, error_flag, TRUE);
    if (!error_flag) p << ':' << make_path (t);
  }
  return p;
}

static string the_tfm_path;
static string the_pk_path;
static string user_tfm_path;
static string user_pk_path;

string
get_tfm_path () {
  return the_tfm_path;
}

string
get_pk_path () {
  return the_pk_path;
}

void
reset_tfm_path (bool rehash) { (void) rehash;
  // if (rehash && use_texhash) system ("texhash");
  the_tfm_path= "$TEX_TFM_PATH:$TEXMACS_HOME_PATH/fonts/tfm";
  the_tfm_path= the_tfm_path * ":$TEXMACS_PATH/fonts/tfm";
  the_tfm_path= merge_paths (the_tfm_path, user_tfm_path);
  if ((use_make_tfm!=0) || use_texhash)
    the_tfm_path= merge_paths (the_tfm_path, get_kpsepath ("tfm"));
}

void
reset_pk_path (bool rehash) { (void) rehash;
  // if (rehash && use_texhash) system ("texhash");
  the_pk_path= "$TEX_TFM_PATH:$TEXMACS_HOME_PATH/fonts/pk";
  the_pk_path= the_pk_path * ":$TEXMACS_PATH/fonts/pk";
  the_pk_path= merge_paths (the_pk_path, user_pk_path);
  if ((use_make_pk!=0) || use_texhash)
    the_pk_path= merge_paths (the_pk_path, get_kpsepath ("pk"));
}

void
extra_tfm_path (string extra) {
  user_tfm_path= merge_paths (user_tfm_path, extra);
}

void
extra_pk_path (string extra) {
  user_pk_path= merge_paths (user_pk_path, extra);
}

bool
use_ec_fonts () {
  return supports_ec;
}

bool
tex_file_exists (string s) {
  if (!use_kpsewhich) return TRUE;
  if (tex_file_table->contains (s)) return tex_file_table [s];
  tex_file_table(s)= (var_eval_system ("kpsewhich " * s) != "");
  return tex_file_table [s];
}

/******************************************************************************
* Installation of TeX
******************************************************************************/

static void
locate (string name, string& p) {
  int start=0, i;
  string s= eval_system ("locate " * name);
  for (i=0; i<N(s); i++)
    if (s[i]=='\n') {
      int j;
      for (j=i-1; j>start; j--)
	if (s[j]=='/') break;
      p= merge_paths (p, s (start, j));
      start= i+1;
    }
}

static void
search_sub_dirs_sub (string p, tree t, string& tfm, string& pk, int status) {
  if (t[0]->label == "tfm") status= 1;
  if (t[0]->label == "pk")  status= 2;
  if (N(p)==0) p= t[0]->label;
  else p= p * "/" * t[0]->label;
  if ((N(t)==1) && (status==1)) tfm= merge_paths (tfm, p);
  if ((N(t)==1) && (status==2)) pk = merge_paths (pk, p);
  int i;
  for (i=1; i<N(t); i++)
    search_sub_dirs_sub (p, t[i], tfm, pk, status);
}

static void
search_sub_dirs (string p, string& tfm, string& pk) {
  int flag;
  tree t= directory_tree (p, flag, TRUE);
  if (!flag) {
    cerr << "TeXmacs] found TeX directory " << p << "\n";
    search_sub_dirs_sub ("", t, tfm, pk, 0);
  }
}

static string
line_read (string s, int& i) {
  int start= i, n= N(s);
  for (start=i; i<n; i++)
    if (s[i]=='\n') break;
  string r= s (start, i);
  if (i<n) i++;
  return r;
}

static bool
line_starts (string l, string s) {
  return (N(l)>N(s)) && (l(0,N(s))==s);
}

static string
line_argument (string l) {
  int i;
  for (i=0; i<N(l); i++)
    if (l[i]==' ') { i++; break; }
  return l (i,N(l));
}

static bool
try_dpi (int dpi, int test) {
  default_dpi= dpi;

  cerr << "TeXmacs] Trying to create ecrm10." << test
       << "pk from " << dpi << " dpi\n";
  make_tex_pk ("ecrm10", test, dpi, "localfont");
  reset_pk_path ();
  if (file_exists (the_pk_path, "ecrm10." * as_string (test) * "pk")) {
    supports_ec= TRUE;
    cerr << "TeXmacs] Metafont works with " << dpi << " dpi ec-fonts\n";
    return TRUE;
  }

  cerr << "TeXmacs] Trying to create cmr10." << test
       << "pk from " << dpi << " dpi\n";
  make_tex_pk ("cmr10", test, dpi, "localfont");
  reset_pk_path ();
  if (file_exists (the_pk_path, "cmr10." * as_string (test) * "pk")) {
    cerr << "TeXmacs] Metafont works with " << dpi << " dpi cm-fonts\n";
    return TRUE;
  }

  return FALSE;
}

void
install_tex () {
  string s;

  ///////////////////////////////
  // First execution of TeXmacs?
  ///////////////////////////////

  if (load_string ("$TEXMACS_HOME_PATH/system", "TEX_PATHS", s)) {
    cerr << "Welcome to TeXmacs 1.0.0.1\n";
    cerr << "------------------------------------------------------------\n";
    cerr << "Since this seems to be the first time you run this\n";
    cerr << "version of TeXmacs, I will first analyze your system\n";
    cerr << "in order to set up some TeX paths in the correct way.\n";
    cerr << "This may take some seconds; the result can be found in\n\n";
    cerr << "\t$TEXMACS_HOME_PATH/system/TEX_PATHS\n\n";
    cerr << "By default, $TEXMACS_HOME_PATH contains ~/.TeXmacs\n";
    cerr << "------------------------------------------------------------\n";
    string buffer;

    /////////////////////////////////////////////////////////
    // Test which programs have been installed on the system
    /////////////////////////////////////////////////////////

    buffer << "VERSION= 1.0.0.1\n";

    use_kpsepath= file_exists ("$PATH", "kpsepath");
    if (use_kpsepath) {
      cerr << "TeXmacs] kpsepath works with your TeX distribution\n";
      buffer << "KPSEPATH= TRUE\n";
    }
    else {
      cerr << "TeXmacs] kpsepath does not work with your TeX distribution\n";
      buffer << "KPSEPATH= FALSE\n";
    }

    use_kpsewhich= file_exists ("$PATH", "kpsewhich");
    if (use_kpsepath) {
      cerr << "TeXmacs] kpsewhich works with your TeX distribution\n";
      buffer << "KPSEWHICH= TRUE\n";
    }
    else {
      cerr << "TeXmacs] kpsewhich does not work with your TeX distribution\n";
      buffer << "KPSEWHICH= FALSE\n";
    }

    if (file_exists ("$PATH", "mktextfm")) {
      use_make_tfm= 2;
      cerr << "TeXmacs] mktextfm works with your TeX distribution\n";
      buffer << "MAKETFM= mktextfm\n";
    }
    else if (file_exists ("$PATH", "MakeTeXTFM")) {
      use_make_tfm= 1;
      cerr << "TeXmacs] MakeTeXTFM works with your TeX distribution\n";
      buffer << "MAKETFM= MakeTeXTFM\n";
    }
    else {
      use_make_tfm= 0;
      cerr << "TeXmacs] MakeTeXTFM does not work with your TeX distribution\n";
      buffer << "MAKETFM= FALSE\n";
    }

    if (file_exists ("$PATH", "mktexpk")) {
      use_make_pk= 2;
      cerr << "TeXmacs] mktexpk works with your TeX distribution\n";
      buffer << "MAKEPK= mktexpk\n";
    }
    else if (file_exists ("$PATH", "MakeTeXPK")) {
      use_make_pk= 1;
      cerr << "TeXmacs] MakeTeXPK works with your TeX distribution\n";
      buffer << "MAKEPK= MakeTeXPK\n";
    }
    else {
      use_make_pk= 0;
      cerr << "TeXmacs] MakeTeXPK does not work with your TeX distribution\n";
      buffer << "MAKEPK= FALSE\n";
    }

    use_texhash= file_exists ("$PATH", "texhash");
    if (use_texhash) {
      cerr << "TeXmacs] texhash works with your TeX distribution\n";
      buffer << "TEXHASH= TRUE\n";
    }
    else {
      cerr << "TeXmacs] texhash does not work with your TeX distribution\n";
      buffer << "TEXHASH= FALSE\n";
    }

    ////////////////////////////////////////////////////
    // If kpsepath does not work, find PK and TFM paths
    ////////////////////////////////////////////////////

    if (!use_kpsepath) {

      // Try locate

      string tfm, pk;
      string test= eval_system ("locate cmr10.tfm");
      if (N(test)==0)
	cerr << "TeXmacs] locate does not work; I will try something else\n";
      else {
	locate (".tfm", tfm);
	locate (".300pk", pk);
	locate (".360pk", pk);
	locate (".400pk", pk);
	locate (".600pk", pk);
	locate (".1200pk", pk);
	if (N(tfm)>0) cerr << "TeXmacs] located tfm files in path "<<tfm<<"\n";
	else cerr << "TeXmacs] I could not locate any tfm files\n";
	if (N(pk)>0) cerr << "TeXmacs] located pk files in path "<<pk<<"\n";
	else cerr << "TeXmacs] I could not locate any pk files\n";
      }

      // Try some 'standard' directories

      search_sub_dirs ("/usr/lib/texmf/fonts", tfm, pk);
      search_sub_dirs ("/var/texfonts", tfm, pk);
      search_sub_dirs ("/usr/TeX/lib/texmf/fonts", tfm, pk);
      search_sub_dirs ("/usr/local/lib/texmf/fonts", tfm, pk);
      
      buffer << "TFM= " << tfm << "\n";
      buffer << "PK= " << pk << "\n";
      user_tfm_path= tfm;
      user_pk_path = pk;
      
      if (((N(tfm)==0) && (get_env ("TEX_TFM_PATH")=="")) ||
	  ((N(pk )==0) && (get_env ("TEX_PK_PATH" )==""))) {
	cerr<<"------------------------------------------------------------\n";
	cerr << "I could not find a TeX system on your system\n";
	cerr << "If you did install one, please set the system variables\n\n";
	cerr << "\tTEX_TFM_PATH\n";
	cerr << "\tTEX_PK_PATH\n\n";
	cerr << "with the paths where the tfm resp. pk file\n";
	cerr << "can be found on your system and restart 'TeXmacs'\n";
	cerr<<"------------------------------------------------------------\n";
	exit (1);
      }
    }
    
    //////////////////////////////////////////////////////
    // Test which default dpi's are supported by metafont
    //////////////////////////////////////////////////////
    
    default_dpi= 300;
    supports_ec= FALSE;
    if (use_make_pk != 0) {
      if (try_dpi (300, 123));
      else if (try_dpi (600, 234));
      else if (try_dpi (1200, 345));
      else {
	cerr << "TeXmacs] Your mktexpk/MakeTeXPK does not seem to work well\n";
	default_dpi= 300;
      }
    }
    buffer << "DPI= " << as_string (default_dpi) << "\n";
    if (supports_ec) buffer << "EC= TRUE\n";
    else buffer << "EC= FALSE\n";

    //////////////////
    // Save diagnosis
    //////////////////
    
    if (save_string ("$TEXMACS_HOME_PATH/system", "TEX_PATHS", buffer, FALSE)||
	load_string ("$TEXMACS_HOME_PATH/system", "TEX_PATHS", s)) {
      cerr << "------------------------------------------------------------\n";
      cerr << "I could not save or reload the file\n\n";
      cerr << "\t$TEXMACS_HOME_PATH/system/TEX_PATHS\n\n";
      cerr << "Please give me full access control over this file and\n";
      cerr << "rerun 'TeXmacs'. By default, $TEXMACS_HOME_PATH ";
      cerr << "contains ~/.TeXmacs\n";
      cerr << "------------------------------------------------------------\n";
      exit (1);
    }

    cerr << "------------------------------------------------------------\n";
    cerr << "Installation completed succesfully !\n";
    cerr << "I will now start up the editor\n";
    cerr << "------------------------------------------------------------\n";

    string from_dir= "$TEXMACS_PATH/doc/english/startup/";
    string to= "$TEXMACS_HOME_PATH/doc/english/startup/upgrade-hist.tex";
    system ("cp " * from_dir * "upgrade-0.tex " * to);
    system ("cat " * from_dir * "upgrade-2.tex >> " * to);
    system ("cat " * from_dir * "upgrade-3.tex >> " * to);
    install_status= 1;
  }

  ////////////////////////////////////////////
  // TeXmacs has already been executed before
  ////////////////////////////////////////////
  
  int i= 0;
  string l= line_read (s, i);

  string install_version;
  if (line_starts (l, "VERSION= ")) {
    install_version= line_argument (l);
    l= line_read (s, i);
  }
  if (install_version != "1.0.0.1") {
    cerr << "------------------------------------------------------------\n";
    cerr << "I found the TeXmacs <-> TeX configuration file\n\n";
    cerr << "\t$TEXMACS_HOME_PATH/system/TEX_PATHS\n\n";
    cerr << "for version " << install_version << " on your harddisk.\n";
    cerr << "I will now perform the upgrade to version 1.0.0.1.\n";
    cerr << "The old configuration file will be moved to\n\n";
    cerr << "\t$TEXMACS_HOME_PATH/system/TEX_PATHS.bak\n\n";
    cerr << "------------------------------------------------------------\n";
    string name= "$TEXMACS_HOME_PATH/system/TEX_PATHS";
    system ("mv -f " * name * " " * name * ".bak");
    install_tex ();

    string from_dir= "$TEXMACS_PATH/doc/english/startup/";
    string to= "$TEXMACS_HOME_PATH/doc/english/startup/upgrade-last.tex";
    system ("cp " * from_dir * "upgrade-1.tex " * to);
    if (path_inf (as_path (install_version), as_path ("0.3.3.24"))) {
      system ("cat " * from_dir * "upgrade-2.tex >> " * to);
      install_status= 2;
    }
    if (path_inf_eq (as_path (install_version), as_path ("0.3.4.9"))) {
      system ("cat " * from_dir * "upgrade-3.tex >> " * to);
      install_status= 2;
    }
    else {
      system ("rm " * to);
      install_status= 0;
    }
    return;
  }

  if (line_starts (l, "KPSEPATH= ")) {
    use_kpsepath= (line_argument (l) == "TRUE");
    l= line_read (s, i);
  }
  else use_kpsepath= FALSE;

  if (line_starts (l, "KPSEWHICH= ")) {
    use_kpsewhich= (line_argument (l) == "TRUE");
    l= line_read (s, i);
  }
  else use_kpsewhich= FALSE;

  if (line_starts (l, "MAKETFM= ")) {
    string arg= line_argument (l);
    l= line_read (s, i);
    if (arg == "MakeTeXTFM") use_make_tfm= 1;
    else if (arg == "mktextfm") use_make_tfm= 2;
    else use_make_tfm= 0;
  }
  else use_make_tfm= 0;

  if (line_starts (l, "MAKEPK= ")) {
    string arg= line_argument (l);
    l= line_read (s, i);
    if (arg == "MakeTeXPK") use_make_pk= 1;
    else if (arg == "mktexpk") use_make_pk= 2;
    else use_make_pk= 0;
  }
  else use_make_pk= 0;

  if (line_starts (l, "TEXHASH= ")) {
    use_texhash= (line_argument (l) == "TRUE");
    l= line_read (s, i);
  }
  else use_texhash= FALSE;

  if (line_starts (l, "TFM= ")) {
    extra_tfm_path (line_argument (l));
    l= line_read (s, i);
  }
  reset_tfm_path (FALSE);

  if (line_starts (l, "PK= ")) {
    extra_pk_path (line_argument (l));
    l= line_read (s, i);
  }
  reset_pk_path (FALSE);

  if (line_starts (l, "DPI= ")) {
    string arg= line_argument (l);
    default_dpi= as_int (arg);
    l= line_read (s, i);
  }
  else default_dpi= 300;

  if (line_starts (l, "EC= ")) {
    supports_ec= (line_argument (l) == "TRUE");
    l= line_read (s, i);
  }
  else supports_ec= FALSE;
}

/******************************************************************************
* Installation of TeXmacs
******************************************************************************/

void
install_texmacs () {
  initialize_data ();

  // Get main TeXmacs path
  string edit= get_env ("TEXMACS_PATH");
  while ((N(edit)>0) && (edit[N(edit)-1] == '/'))
    edit= edit (0, N(edit)-1);

  // Setup guile
  string guile= get_env ("GUILE_LOAD_PATH");
  while ((N(guile)>0) && (guile[N(guile)-1] == '/'))
    guile= guile (0, N(guile)-1);
  if (guile == "") guile= edit * "/progs";
  else guile= edit * "/progs:" * guile;
  set_env ("GUILE_LOAD_PATH", guile);
  if (!file_exists ("$GUILE_LOAD_PATH", "init-texmacs.scm")) {
    cerr << "\nTeXmacs]\n";
    cerr << "TeXmacs] The GUILE_LOAD_PATH is "
	 << get_env ("GUILE_LOAD_PATH") << "\n\n";
    cerr << "TeXmacs] Installation problem: please send a bug report.\n";
    cerr << "TeXmacs] The initialization file init-texmacs.scm"
	 << " could not be found.\n";
    cerr << "TeXmacs] Please check the values of the environment variables\n";
    cerr << "TeXmacs] TEXMACS_PATH and GUILE_LOAD_PATH."
	 << " init-texmacs.scm should\n";
    cerr << "TeXmacs] be readable and in the directory $TEXMACS_PATH/progs.\n";
    cerr << "TeXmacs]\n";
    exit (1);
  }
  if (!file_exists ("$GUILE_LOAD_PATH", "ice-9/boot-9.scm")) {
    int i;
    string guile_data    = var_eval_system ("guile-config info datadir");
    string guile_version = var_eval_system ("guile-config info top_srcdir");
    for (i=N(guile_version); i>0; i--)
      if (guile_version[i-1] == '-') break;
    guile_version= guile_version (i, N (guile_version));
    for (i=0; i<N(guile_version); i++)
      if (guile_version[i] == '/') {
	guile_version= guile_version (0, i);
	break;
      }
    string guile_dir= guile_data * "/guile/" * guile_version;
    guile= guile * ":" * guile_dir;
    set_env ("GUILE_LOAD_PATH", guile);
    if (!file_exists ("$GUILE_LOAD_PATH", "ice-9/boot-9.scm"))
      fatal_error ("guile seems not to be installed on your system",
		   "install_texmacs");
  }

  // Get TeXmacs user home path
  string root= get_env ("HOME");
  while ((N(root)>0) && (root[N(root)-1] == '/')) root= root (0, N(root)-1);
  if (get_env ("TEXMACS_HOME_PATH") == "")
    set_env ("TEXMACS_HOME_PATH", root * "/.TeXmacs");
  string home= get_env ("TEXMACS_HOME_PATH");
  while ((N(home)>0) && (home[N(home)-1] == '/')) home= home (0, N(home)-1);
  if (home == "") {
    cerr << "\nTeXmacs]\n";
    cerr << "TeXmacs] Installation problem: please send a bug report.\n";
    cerr << "TeXmacs] 'TEXMACS_HOME_PATH' could not be set to '~/.TeXmacs'.\n";
    cerr << "TeXmacs] You may try to set this environment variable manually\n";
    cerr << "TeXmacs]\n";
    exit (1);
  }
  if (!is_directory (home))
    system ("mkdir $TEXMACS_HOME_PATH");
  if (!is_directory (home * "/doc"))
    system ("mkdir $TEXMACS_HOME_PATH/doc");
  if (!is_directory (home * "/doc/english"))
    system ("mkdir $TEXMACS_HOME_PATH/doc/english");
  if (!is_directory (home * "/doc/english/startup"))
    system ("mkdir $TEXMACS_HOME_PATH/doc/english/startup");
  if (!is_directory (home * "/fonts"))
    system ("mkdir $TEXMACS_HOME_PATH/fonts");
  if (!is_directory (home * "/fonts/enc"))
    system ("mkdir $TEXMACS_HOME_PATH/fonts/enc");
  if (!is_directory (home * "/fonts/error"))
    system ("mkdir $TEXMACS_HOME_PATH/fonts/error");
  if (!is_directory (home * "/fonts/pk"))
    system ("mkdir $TEXMACS_HOME_PATH/fonts/pk");
  if (!is_directory (home * "/fonts/tfm"))
    system ("mkdir $TEXMACS_HOME_PATH/fonts/tfm");
  if (!is_directory (home * "/fonts/virtual"))
    system ("mkdir $TEXMACS_HOME_PATH/fonts/virtual");
  if (!is_directory (home * "/langs"))
    system ("mkdir $TEXMACS_HOME_PATH/langs");
  if (!is_directory (home * "/langs/mathematical"))
    system ("mkdir $TEXMACS_HOME_PATH/langs/mathematical");
  if (!is_directory (home * "/langs/mathematical/syntax"))
    system ("mkdir $TEXMACS_HOME_PATH/langs/mathematical/syntax");
  if (!is_directory (home * "/langs/natural"))
    system ("mkdir $TEXMACS_HOME_PATH/langs/natural");
  if (!is_directory (home * "/langs/natural/dic"))
    system ("mkdir $TEXMACS_HOME_PATH/langs/natural/dic");
  if (!is_directory (home * "/langs/natural/hyphen"))
    system ("mkdir $TEXMACS_HOME_PATH/langs/natural/hyphen");
  if (!is_directory (home * "/langs/programming"))
    system ("mkdir $TEXMACS_HOME_PATH/langs/programming");
  if (!is_directory (home * "/misc"))
    system ("mkdir $TEXMACS_HOME_PATH/misc");
  if (!is_directory (home * "/misc/pixmaps"))
    system ("mkdir $TEXMACS_HOME_PATH/misc/pixmaps");
  if (!is_directory (home * "/progs"))
    system ("mkdir $TEXMACS_HOME_PATH/progs");
  if (!is_directory (home * "/styles"))
    system ("mkdir $TEXMACS_HOME_PATH/styles");
  if (!is_directory (home * "/system"))
    system ("mkdir $TEXMACS_HOME_PATH/system");
  if (!is_directory (home * "/texts"))
    system ("mkdir $TEXMACS_HOME_PATH/texts");

  // Get TeXmacs style path
  if (get_env ("TEXMACS_STYLE_PATH") == "")
    set_env ("TEXMACS_STYLE_PATH", ".:" *
	     home * "/styles:" * edit * "/styles");
  string sty= get_env ("TEXMACS_STYLE_PATH");
  while ((N(sty)>0) && (sty[N(sty)-1] == '/')) sty= sty (0, N(sty)-1);

  // Get TeXmacs file path
  if (get_env ("TEXMACS_FILE_PATH") == "")
    set_env ("TEXMACS_FILE_PATH", sty * ":" *
	     home * "/texts:" * edit * "/texts");

  // Get TeXmacs documentation path
  if (get_env ("TEXMACS_DOC_PATH") == "")
    set_env ("TEXMACS_DOC_PATH", home * "/doc");

  // Get TeXmacs syntax path
  if (get_env ("TEXMACS_SYNTAX_PATH") == "")
    set_env ("TEXMACS_SYNTAX_PATH",
	     edit * "/langs/mathematical/syntax:" *
	     home * "/langs/mathematical/syntax");

  // Get TeXmacs pixmaps path
  if (get_env ("TEXMACS_PIXMAPS_PATH") == "")
    set_env ("TEXMACS_PIXMAPS_PATH",
	     edit * "/misc/pixmaps:" *
	     home * "/misc/pixmaps");

  // Check for old Init.scm and Init-buffer.scm files
  string prgs= home * "/progs";
  if (file_exists (prgs, "Init.scm") &&
      (!file_exists (prgs, "my-init-texmacs.scm")))
    system ("sed 's/Init.scm/init-texmacs.scm/' " * prgs * "/Init.scm > " *
	    prgs * "/my-init-texmacs.scm; rm " * prgs * "/Init.scm");
  if (file_exists (prgs, "Init-buffer.scm") &&
      (!file_exists (prgs, "my-init-buffer.scm")))
    system ("sed 's/Init-buffer.scm/init-buffer.scm/' " *
	    prgs * "/Init-buffer.scm > " *
	    prgs * "/my-init-buffer.scm; rm " * prgs * "/Init-buffer.scm");

  // Check for Maxima
  if (get_env ("MAXIMA_DIRECTORY") == "")
    if (file_exists ("$PATH", "maxima")) {
      string where= get_unique_file_name ("$PATH", "maxima");
      string s    = var_eval_system ("grep 'MAXIMA_DIRECTORY=' " * where);
      string dir  = s (search_forwards ("=", s) + 1, N(s));
      set_env ("MAXIMA_DIRECTORY", dir);
    }

  // Check for Reduce
  if (get_env ("reduce") == "")
    if (file_exists ("$PATH", "reduce")) {
      string where= get_unique_file_name ("$PATH", "reduce");
      string grep = "grep 'setenv reduce ' " * where;
      string sed  = "sed 's/setenv reduce //'";
      string dir  = var_eval_system (grep * " | " * sed);
      set_env ("reduce", dir);
    }
}

#endmodule // code_dir
