#include "ColorSetup.hpp"

#include "StringUtils.hpp"

#ifdef __ultrix__
#include "Ultrix-Compatibility.hpp"
#endif

const ColorSetup ColorSetup::BUILT_IN= ColorSetup( "no=00:fi=00:di=01;34:ln=01:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:ex=01;31:*.tar=00;31:*.tgz=00;31:*.rpm=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31");

const string ColorSetup::BRIGHTER= "00";

const string ColorSetup::left_code= string(1,ESC) + "[", 
             ColorSetup::right_code= "m", 
             ColorSetup::end_code= string(1,ESC) + "[00m";

ColorSetup::ColorSetup() {
  char* setup_= getenv( "LS_COLORS" );
  if (setup_ != NULL) 
    *this= ColorSetup( setup_);
  else
    *this= BUILT_IN;
}
  
ColorSetup::ColorSetup( const string& setup): 
             code_str( setup),           // make a copy...
             do_colorization( true)
{
  // The color setup is a ':' separated sequence of strings like li=01;30 .
  string::size_type equal_sign;  // position of equal sign dividing description and value

  StringTokenizer ST( code_str, ":");
  while (ST.hasMoreTokens()) {
    string token= ST.getNextToken();

    equal_sign= token.find( '=');
    if ( equal_sign == string::npos)  continue;
    
    string descr= token.substr( 0, equal_sign);
    string value= token.substr( equal_sign+1);
    if      (descr=="no")  color_text= value;
    else if (descr=="fi")  color_file= value;
    else if (descr=="di")  color_dir= value;
    else if (descr=="ex")  color_exec= value;
    else if (descr=="ln")  color_symlink= value;
    else if (descr=="bd")  color_blockdev= value;
    else if (descr=="cd")  color_chardev= value;
    else if (descr=="pi")  color_pipe= value;
    else if (descr=="so")  color_socket= value;
  } // while
  
  // "intelligent" setup for default color value
  if (! color_text.empty())
    color_default= color_text;
  else
    color_default= "00";
}

string ColorSetup::format( string st, const string & color_str, bool colored)  const {
  if (colored) {
    st.insert( 0, left_code + color_str + right_code);
    st.append( end_code);
  }
  return st;
}

string ColorSetup::formatFilename( const UnixFile& f)  const {
  if (!do_colorization)  return f.getName();
  
  string col;
  // now decide which color code to use. The following statements' order is
  // very important!!!
  if (f.isNavigable())  col= color_dir;
  else 
    switch (f.getType()) {
      case UnixFile::SYMLINK: col= color_symlink;  break;
      case UnixFile::BLOCK_DEVICE: col= color_blockdev; break;
      case UnixFile::CHAR_DEVICE: col= color_chardev; break;
      case UnixFile::PIPE: col= color_pipe; break;
      case UnixFile::SOCKET: col= color_socket; break;
      default:      
        if (f.isExecutable())  col= color_exec;
        else {  // look for color code suitable for the file's extension:
          string filename= f.getName();
          string::size_type pos= filename.rfind('.');
          if (pos!=string::npos) {
            string extension= filename.substr( pos) + '=';  // dot, extension and '='
                // now search the complete LS_COLORS string for the extension.
            string::size_type code_pos= this->code_str.find( extension);
            if (code_pos!=string::npos) {
              StringTokenizer st( code_str, "=:", "", code_pos + extension.size());
              if (st.hasMoreTokens()) {
                string code= st.getNextToken();
                col= code;
              }
            }
          }
        }
    } // switch
    
  if (col.empty()) col= color_file;  // no suitable file type found yet.
  if (col.empty()) col= color_default;
  
  return format( f.getName(), col);
}


Documentation generated by mw@nemea on Mit Nov 24 00:09:18 CET 1999