/*
    $Id: kfontmanager.cpp,v 1.28 2000/05/02 21:27:00 bieker Exp $

    Copyright (C) 1997 Bernd Johannes Wuebben <wuebben@math.cornell.edu>
    Copyright (C) 2000 Hans Petter Bieker <bieker@kde.org>

    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; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
#include <qstrlist.h> 
#include <qfile.h>
#include <qtextstream.h> 
#include <qlayout.h>
#include <qlabel.h>
#include <qpushbutton.h>
#include <qlistbox.h>

#include <kapp.h>
#include <kglobal.h>
#include <kcharsets.h>
#include <klocale.h>
#include <kstddirs.h>
#include <kmessagebox.h>

#include "kfontmanager.h"
#include "main.h"

#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#define HEIGHT 160
#define WIDTH  200

KFontManager::KFontManager (QWidget * parent, const char *name)
    : QWidget (parent, name)
{
  QLabel *label;
  QVBoxLayout *top = new QVBoxLayout(this,10,10);

  QHBoxLayout *hbox = new QHBoxLayout(top);
  
  QVBoxLayout *vbox = new QVBoxLayout(hbox);
  label = new QLabel(i18n("Available X11 Fonts"), this);
//  label->setAlignment(AlignCenter);
  vbox->addWidget(label);
  availableFontsList = new QListBox(this);
  availableFontsList->setMinimumSize(WIDTH,HEIGHT);
  connect(availableFontsList,SIGNAL(highlighted(int)),
	  this,SLOT(display_available_example(int)));
  vbox->addWidget(availableFontsList,1);

  vbox = new QVBoxLayout(hbox);
  label = new QLabel(i18n("Fonts made available to KDE"), this);
//  label->setAlignment(AlignCenter);
  vbox->addWidget(label);
  selectedFontsList = new QListBox(this);
  selectedFontsList->setMinimumSize(WIDTH,HEIGHT);
  connect(selectedFontsList,SIGNAL(highlighted(int)),
	  this,SLOT(display_selected_example(int)));
  vbox->addWidget(selectedFontsList,1);

  example_label = new QLabel(this);
  example_label->setAlignment(AlignCenter);
//  example_label->setBackgroundColor(white);
  example_label->setFrameStyle( QFrame::WinPanel | QFrame::Sunken );
  /* the following example string uses all letters in alphabet */
  example_label->setText(i18n("The Quick Brown Fox Jumps Over The Lazy Dog\n"
			      "AaBbCc123"));
  example_label->setMinimumSize(2*WIDTH,40);	// fixed size !!
  example_label->setMaximumSize(2*WIDTH,40);
  
  hbox = new QHBoxLayout(top);
  hbox->addWidget(example_label);

  QVBoxLayout *butbox = new QVBoxLayout(hbox);

  add = new QPushButton(i18n("Add"), this);
  connect(add,SIGNAL(clicked()),this,SLOT(add_slot()));
  butbox->addWidget(add);

  remove = new QPushButton(i18n("Remove"), this);
  connect(remove,SIGNAL(clicked()),this,SLOT(remove_slot()));
  butbox->addWidget(remove);

  queryFonts();
  
  top->activate();

  setColors();
  connect(KApplication::kApplication(),SIGNAL(kdisplayPaletteChanged()),
	  this,SLOT(setColors()));
}

void KFontManager::defaults()
{
  // just copy every item from availableFontsList to selectedFontsList

  selectedFontsList->clear();

  for ( int i = 0; i < (int)availableFontsList->count(); i++ ) {
    QString str = availableFontsList->text( i );
    selectedFontsList->insertItem( str );
  }
}

void KFontManager::load()
{
  selectedFontsList->clear(); // perhaps loadKDEInstalledFonts should do this?
  loadKDEInstalledFonts();
}

void KFontManager::save()
{
  writeKDEInstalledFonts();
}

void KFontManager::remove_slot()
{
  if(selectedFontsList->currentItem() != -1) {
    selectedFontsList->removeItem(selectedFontsList->currentItem());
    emit changed();
  } else
    QApplication::beep();
}

void KFontManager::add_slot()
{
  if(availableFontsList->currentItem() != -1) {
    QString new_item = availableFontsList->text(availableFontsList->currentItem());
    QString string;

    for (uint i  = 0; i < selectedFontsList->count();i++) {
      string = selectedFontsList->text(i);
      if ( string == new_item) {
	// already in KDE font list
         QApplication::beep();
	 return;
      }
    }
    selectedFontsList->inSort(new_item);

    emit changed();
  }
  else
    QApplication::beep();
}

void KFontManager::display_available_example(int i)
{
  QString string = availableFontsList->text(i);
  QFont fnt(string, 14);
  KGlobal::charsets()->setQFont(fnt);
  example_label->setFont(fnt);
}

void KFontManager::display_selected_example(int i)
{
  QString string = selectedFontsList->text(i);
  QFont fnt(string, 14);
  KGlobal::charsets()->setQFont(fnt);
  example_label->setFont(fnt);
}

bool KFontManager::loadKDEInstalledFonts()
{
  QString fontfilename = locate("config", "kdefonts");
  QFile fontfile(fontfilename);

  if (!fontfile.exists())
    return false;

  if (!fontfile.open(IO_ReadOnly))
    return false;

  if (!fontfile.isReadable())
    return false;
  
  QTextStream t(&fontfile);

  while ( !t.eof() ) {
    QString s = t.readLine();
    s = s.stripWhiteSpace();
    if (!s.isEmpty())
      selectedFontsList->insertItem( s );
  }

  fontfile.close();

  selectedFontsList->update();
  
  return true;
}

bool KFontManager::writeKDEInstalledFonts()
{
  QString fontfilename;

  fontfilename =  locate("config", "kdefonts");
  if (fontfilename.isEmpty())
    fontfilename = locateLocal("config", "kdefonts");

  QFile fontfile(fontfilename);

  if (!fontfile.open(IO_WriteOnly | IO_Truncate)) {
    KMessageBox::sorry(this,
		 i18n("Can not create:\n%1\n").arg(fontfilename));
    return false;
  }

  if (!fontfile.isWritable()) {
    KMessageBox::sorry(this,
		 i18n("%1 exists but\n"
		      "is not writeable\n"
		      "Can't save KDE Fontlist.").arg(fontfilename));
    return false;
  }

  QTextStream t(&fontfile);
  
  int number = selectedFontsList->count();

  if( number >  0) {
    QString fontname;
    for(int i = 0; i < number; i++){
      fontname = selectedFontsList->text(i);
      fontname = fontname.stripWhiteSpace();
      if (!fontname.isEmpty())
	t << fontname << '\n';
    }
  }

  fontfile.close();
  
  return true;
}

void KFontManager::queryFonts()
{
  int numFonts;
  QString qfontname;

  QStrList fontlist(TRUE);
  QStrList installedfontlist(TRUE);
  
  bool have_installed = loadKDEInstalledFonts();

  char **fontNames = XListFonts(qt_xdisplay(), "*", 32767, &numFonts);
  char **fontNames_copy = fontNames;

  for( int k = 0; k < numFonts; k++) {
    if (**fontNames != '-') {// font name doesn't start with a dash -- an alias
      /*
      qfontname = "";
      qfontname = *fontNames;
      if(fontlist.find(qfontname) == -1)
          fontlist.inSort(qfontname);
      */

      fontNames ++;
      continue;
    };
      
    qfontname = *fontNames;
    int dash = qfontname.find ('-', 1, TRUE); // find next dash

    if (dash == -1) { // No such next dash -- this shouldn't happen.
                      // let's skip it.
      fontNames ++;
      continue;
    }

    // the font family name is between the second and third dash therefore
    // let's find the third dash:

    int dash_two = qfontname.find ('-', dash + 1 , TRUE); 

    if (dash == -1) { // No such next dash -- this shouldn't happen.
                      // let's skip it.
      fontNames ++;
      continue;
    }

    // fish the font family name out of the font info string

    qfontname = qfontname.mid(dash +1, dash_two - dash -1);

    if(fontlist.find(qfontname) == -1)
      fontlist.inSort(qfontname);

    if(!have_installed){

      // we don't have a kdefontlist file yet -- prepare a default list 
      // of installed fonts
      
      if( !qfontname.contains("open look", TRUE)){
	if(qfontname != "nil"){
	  if(installedfontlist.find(qfontname) == -1)
	    installedfontlist.inSort(qfontname);
	}
      }
    }

    fontNames ++;
  }

  for(fontlist.first(); fontlist.current(); fontlist.next())
   availableFontsList->insertItem(fontlist.current());

  if(!have_installed) {
    for (installedfontlist.first(); installedfontlist.current(); installedfontlist.next())
      selectedFontsList->insertItem(installedfontlist.current());
  }

  availableFontsList->update();
  selectedFontsList->update();

  XFreeFontNames(fontNames_copy);
}


void KFontManager::setColors() {
 
  /* this is to the the backgound of a widget to white and the
     text color to black -- some lables such as the one of the
     font manager really shouldn't follow colorschemes The
     primary task of those label is to display the text clearly
     an visibly and not to look pretty ...*/

  QPalette mypalette = (example_label->palette()).copy();

  QColorGroup cgrp = mypalette.normal();
  QColorGroup ncgrp(black,cgrp.background(),
		    cgrp.light(),cgrp.dark(),cgrp.mid(),black,white);

  mypalette.setNormal(ncgrp);
  mypalette.setDisabled(ncgrp);
  mypalette.setActive(ncgrp);

  example_label->setPalette(mypalette);
  example_label->setBackgroundColor(white);
}

#include "kfontmanager.moc"
