/*                                                                        */
/* [klt.cpp]                   Klt                                */
/*                                                                        */
/* ---------------------------------------------------------------------- */
/*                                                                        */
/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>        */
/*                                                                        */
/* This file is part of Klt, an X terminal.                           */
/*                                                                        */
/* The material contained in here more or less directly orginates from    */
/* kvt, which is copyright (c) 1996 by Matthias Ettrich <ettrich@kde.org> */
/*                                                                        */
/* ---------------------------------------------------------------------- */



/*! \class Klt

    \brief Klt's main class and program

    The class Klt handles the application level. Mainly, it is responsible
    for the configuration, taken from several files, from the command line
    and from the user. It hardly does anything interesting.
    Everything is created as late as possible to make it startup fast.
*/

/*TODO:
  - allow to set codec
  - officially declare this file to be hacked to death. ;^)
  - merge into klt_part.
*/

/*STATE:

  klt/kwin session management, parts stuff, config, menues
  are all in bad need for a complete rewrite.

  While the emulation core (TEmulation, TEVt102, TEScreen, TEWidget)
  are pretty stable, the upper level material has certainly drifted.

  Everything related to Sessions, Configuration has to be redesigned.
  It seems that the klt now falls apart into individual sessions
  and a session manager.

Time to start a requirement list.

  - Rework the Emulation::setConnect logic.
    Together with session changing (Shift-Left/Right, Ctrl-D) it allows
    key events to propagate to other sessions.

  - Get rid of the unconfigurable, uncallable initial "Klt" session.
    Leads to code replication in klt_part and other issues. Related
    to the booting of klt, thus matter of redesign.
*/

/*FIXME:
  - All the material in here badly sufferes from the fact that the
    configuration can originate from many places, so all is duplicated
    and falls out of service. Especially the command line is badly broken.
    The sources are:
    - command line
    - menu
    - configuration files
    - other events (e.g. resizing)
    We have to find a single-place method to better maintain this.
  - In general, the material contained in here and in session.C
    should be rebalanced. Much more material now comes from configuration
    files and the overall routines should better respect this.
  - Font+Size list should go to a configuration file, too.
  - Controlling the widget is currently done by individual attributes.
    This lead to quite some amount of flicker when a whole bunch of
    attributes has to be set, e.g. in session swapping.
*/

#include <config.h>

#include <qspinbox.h>
#include <qcheckbox.h>
#include <qlayout.h>
#include <qpushbutton.h>
#include <qhbox.h>
#include <qfont.h>
#include <qfontdialog.h>

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

#include <kfiledialog.h>

#include <kfontdialog.h>
#include <kkeydialog.h>
#include <kstandarddirs.h>
#include <qpainter.h>
#include <kmenubar.h>
#include <kstatusbar.h>
#include <kmessagebox.h>
#include <krootpixmap.h>
#include <krun.h>
#include <kstdaction.h>
#include <klineeditdlg.h>
#include <kdebug.h>
#include <kipc.h>
#include <dcopclient.h>
#include <kglobalsettings.h>
#include <kwin.h>

#include <klocale.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <signal.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>

#include <kiconloader.h>
#include <kstringhandler.h>
#include <ktip.h>
#include <kprocctrl.h>

#include <kregexpeditorinterface.h>
#include <kparts/componentfactory.h>

#include "klt.h"
#include <netwm.h>

#define KONSOLEDEBUG    kdDebug(1211)

#ifndef HERE
#define HERE printf("%s(%d): %s\n",__FILE__,__LINE__,__FUNCTION__)
#endif
#define HERE 

int done_statusbar=0;
QString lls_qstring_title;

// KltFontSelectAction is now also used for selectSize!
class KltFontSelectAction : public KSelectAction {
public:
    KltFontSelectAction(const QString &text, int accel,
                            const QObject* receiver, const char* slot,
                            QObject* parent, const char* name = 0 )
        : KSelectAction(text, accel, receiver, slot, parent, name) {}
    KltFontSelectAction( const QString &text, const QIconSet& pix,
                             int accel, const QObject* receiver,
                             const char* slot, QObject* parent,
                             const char* name = 0 )
        : KSelectAction(text, pix, accel, receiver, slot, parent, name) {}

    virtual void slotActivated( int index );
};

void KltFontSelectAction::slotActivated(int index) {
    // emit even if it's already activated
    if (currentItem() == index) {
        KSelectAction::slotActivated();
        return;
    } else {
        KSelectAction::slotActivated(index);
    }
}

template class QPtrDict<TESession>;
template class QIntDict<KSimpleConfig>;
template class QPtrDict<KRadioAction>;

//
//	Fonts are selected by QFont ( not Qfont or qfont)
//	Change Family with  f.setFamily("Courier") in setFont()
const char * const fonts[] = {
 "20",
 "7",   // tiny font, never used
 "10",  // small font
 "13",  // medium
 "15",  // large
 "18", // huge  Huge
 "20", // giant
 "28", // Supersize
 "34", // Silly
 "-misc-console-medium-r-normal--16-160-72-72-c-160-iso10646-1", // "Linux"
 "-misc-fixed-medium-r-normal--15-140-75-75-c-90-iso10646-1",    // "Unicode"
 };
#define TOPFONT (sizeof(fonts)/sizeof(char*))
#define DEFAULTFONT TOPFONT

Klt::Klt(const QString &pgm, const QStrList &args,int is_restored)
	: KMainWindow(0, "Klt"),
	m_defaultSession(0) ,m_defaultSessionFilename(""), 
	te(0),se(0), menubar(0),
	m_rightButton(0) ,showMenubar(0) ,selectFont(0),
	n_keytab(0) ,n_defaultKeytab(0) ,m_menuCreated(false),
	skip_exit_query(false) // used to skip the query when closed by the session management
	,b_warnQuit(false) ,b_allowResize(true)
{
HERE;

// if( is_restored ) fprintf(stderr,"RESTORED DEFAULTFONT is %d\n",DEFAULTFONT);
 isRestored = is_restored;


  connect( kapp,SIGNAL(backgroundChanged(int)),this, SLOT(slotBackgroundChanged(int)));
  connect( &m_closeTimeout, SIGNAL(timeout()), this, SLOT(slotCouldNotClose()));

  no2command.setAutoDelete(true);
  no2tempFile.setAutoDelete(true);
  no2filename.setAutoDelete(true);
  menubar = menuBar();

  // create terminal emulation framework ////////////////////////////////////

  te = new TEWidget(this);
  //KONSOLEDEBUG<<"Klt ctor() after new TEWidget() "<<time.elapsed()<<" msecs elapsed"<<endl;
  // we need focus so that the auto-hide cursor feature works (Carsten)
  // but a part shouldn't force that it receives the focus, so we do it here (David)
  te->setFocus();

  // Transparency handler ///////////////////////////////////////////////////
  rootxpm = new KRootPixmap(te);
  //KONSOLEDEBUG<<"Klt ctor() after new RootPixmap() "<<time.elapsed()<<" msecs elapsed"<<endl;

  // create applications /////////////////////////////////////////////////////

  setCentralWidget(te);

  makeBasicGUI();
  //KONSOLEDEBUG<<"Klt ctor() after makeBasicGUI "<<time.elapsed()<<" msecs elapsed"<<endl;

  colors = new ColorSchemaList();
  colors->checkSchemas();

  KeyTrans::loadAll();
  //KONSOLEDEBUG<<"Klt ctor() after KeyTrans::loadAll() "<<time.elapsed()<<" msecs elapsed"<<endl;

  // read and apply default values ///////////////////////////////////////////
  QSize currentSize = size();
  KConfig * config = KGlobal::config();
  config->setDesktopGroup();
  applyMainWindowSettings(config);
  if (currentSize != size())
     defaultSize = size();

  KSimpleConfig *co;
//  if (!type.isEmpty())
    setDefaultSession("klt.desktop");
  co = defaultSession();

  co->setDesktopGroup();
  QString schema = co->readEntry("Schema");
  readProperties(config, schema, false);

//  newSession(co, _program, _args, _term, _icon, _title, _cwd, _font);

      setenv("WINDOWID",QString::number(winId()),1);

	newSession(co, pgm, args);
//	newSession();

	setAutoSaveSettings();
  toolBar()->hide();

  //KONSOLEDEBUG<<"Klt ctor() ends "<<time.elapsed()<<" msecs elapsed"<<endl;

  kapp->dcopClient()->setDefaultObject( "klt" );

//fprintf(stderr,"End of Klt Constructor\n");
}


Klt::~Klt()
{
HERE;
    while (detached.count()) {
        KltChild* child=detached.first();
        delete child;
        detached.remove(child);
    }

    sessions.first();
    while(sessions.current())
    {
      sessions.current()->closeSession();
      sessions.next();
    }
    // Wait a bit for all childs to clean themselves up.
#if KDE_VERSION >=306
    while(sessions.count() && KProcessController::theKProcessController->waitForProcessExit(1))
        ;
//#else
//    while(sessions.count())
//        ;
#endif

    sessions.setAutoDelete(true);

    resetScreenSessions();
    if (no2command.isEmpty())
       delete m_defaultSession;

    delete colors;
    colors=0;

    delete kWinModule;
    kWinModule = 0;
}

void Klt::run() {
HERE;
   kWinModule = new KWinModule();
   connect( kWinModule,SIGNAL(currentDesktopChanged(int)), this,SLOT(currentDesktopChanged(int)) );
HERE;
}

void Klt::setAutoClose(bool on)
{
HERE;
    if (sessions.first())
       sessions.first()->setAutoClose(on);
}

void Klt::showTip()
{
HERE;
   KTipDialog::showTip(this,QString::null,true);
}

void Klt::showTipOnStart()
{
HERE;
   KTipDialog::showTip(this);
}

/* ------------------------------------------------------------------------- */
/*  Make menu                                                                */
/* ------------------------------------------------------------------------- */

// Be carefull !!
// This function consumes a lot of time, that's why it is called delayed on demand.
// Be careful not to introduce function calls which lead to the execution of this
// function when starting klt
// Be careful not to access stuff which is created in this function before this
// function was called ! you can check this using m_menuCreated, aleXXX
void Klt::makeGUI()
{
HERE;
   if (m_menuCreated) return;
   //not longer needed
   disconnect(m_session,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
   disconnect(m_options,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
   disconnect(m_rightButton,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
   disconnect(m_edit,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
#ifdef LLS_NOT_RESTRICT
   disconnect(m_help,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
   disconnect(m_view,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
#endif
   //KONSOLEDEBUG<<"Klt::makeGUI()"<<endl;
   connect(m_session,SIGNAL(aboutToShow()),this,SLOT(loadScreenSessions()));
   m_menuCreated=true;

   // Remove the empty separator Qt inserts if the menu is empty on popup,
   // not sure if this will be "fixed" in Qt, for now use this hack (malte)
   if(!(isRestored)) {
     if (sender() && sender()->inherits("QPopupMenu") &&
       static_cast<const QPopupMenu *>(sender())->count() == 1)
       const_cast<QPopupMenu *>(static_cast<const QPopupMenu *>(sender()))->removeItemAt(0);
       }

   KActionCollection* actions = actionCollection();

   // Send Signal Menu -------------------------------------------------------------
   m_signals = new KPopupMenu(this);
   m_signals->insertItem( i18n( "&Suspend Task" )   + " (STOP)", SIGSTOP);
   m_signals->insertItem( i18n( "&Continue Task" )  + " (CONT)", SIGCONT);
   m_signals->insertItem( i18n( "&Hangup" )         + " (HUP)", SIGHUP);
   m_signals->insertItem( i18n( "&Interrupt Task" ) + " (INT)", SIGINT);
   m_signals->insertItem( i18n( "&Terminate Task" ) + " (TERM)", SIGTERM);
   m_signals->insertItem( i18n( "&Kill Task" )      + " (KILL)", SIGKILL);
   m_signals->insertItem( i18n( "User Signal &1")   + " (USR1)", SIGUSR1);
   m_signals->insertItem( i18n( "User Signal &2")   + " (USR2)", SIGUSR2);
   connect(m_signals, SIGNAL(activated(int)), SLOT(sendSignal(int)));

   // Edit Menu ----------------------------------------------------------------
   m_copyClipboard->plug(m_edit);
   m_pasteClipboard->plug(m_edit);

   // Schema Options Menu -----------------------------------------------------
   m_schema = new KPopupMenu(this);
   m_schema->setCheckable(true);
   connect(m_schema, SIGNAL(activated(int)), SLOT(schema_menu_activated(int)));
   connect(m_schema, SIGNAL(aboutToShow()), SLOT(schema_menu_check()));

   // Keyboard Options Menu ---------------------------------------------------
   m_keytab = new KPopupMenu(this);
   m_keytab->setCheckable(true);
   connect(m_keytab, SIGNAL(activated(int)), SLOT(keytab_menu_activated(int)));

   //options menu
   // Menubar on/off
   showMenubar->plug ( m_options );

   // Select Bell
   selectBell = new KSelectAction(i18n("&Bell"), SmallIconSet( "bell"), 0 , this,
                                  SLOT(slotSelectBell()), actions);
   QStringList bellitems;
   bellitems << i18n("&None")
             << i18n("&System Notification")
             << i18n("&Visible Bell");
   selectBell->setItems(bellitems);
#ifdef LLS_NOT_RESTRICT
   selectBell->plug(m_options);
#endif


   // Select font
   selectFont = new KltFontSelectAction( i18n( "&Font" ),
          SmallIconSet( "text" ), 0, this, SLOT(slotSelectFont()), actions);
   QStringList it;
   it << i18n("&Normal")
      << i18n("&Tiny")
      << i18n("&Small")
      << i18n("&Medium")
      << i18n("&Large")
      << i18n("&Huge")
	/**
      << i18n("&Giant");
	**/
      << i18n("&Giant")
      << i18n("&SuperSize")
      << i18n("&SillyHuge");
/*
      << ""
      << i18n("L&inux")
      << i18n("&Unicode")
      << ""
      << i18n("&Custom...");
*/
   selectFont->setItems(it);
   selectFont->plug(m_options);

	// Auto resize option
   selectAutoresize = new KSelectAction(i18n("&AutoResize"), SmallIconSet( "bell"), 0 , this,
                                  SLOT(slotSelectAutoresize()), actions);
   QStringList autoresizeitems;
   autoresizeitems << i18n("&Yes")
             << i18n("&No");
   selectAutoresize->setItems(autoresizeitems);
   selectAutoresize->plug(m_options);

#ifdef LLS_NOT_RESTRICT
   m_options->insertItem( SmallIconSet( "key_bindings" ), i18n( "&Keyboard" ), m_keytab );
#endif

   // Schema
//#ifdef LLS_SCHEMA_NOT_RESTRICT
   m_options->insertItem( SmallIconSet( "colorize" ), i18n( "Sch&ema" ), m_schema);
//#endif

   // Select size
   selectSize = new KltFontSelectAction(i18n("S&ize"), 0, this,
                                  SLOT(slotSelectSize()), actions);
   QStringList sizeitems;
   sizeitems << i18n("40x15 (&Small)")
      << i18n("80x24 (&VT100)")
      << i18n("80x25 (&IBM PC)")
      << i18n("80x40 (&XTerm)")
      << i18n("80x52 (IBM V&GA)")
      << ""
      << i18n("&Custom...");
   selectSize->setItems(sizeitems);
#ifdef LLS_NOT_RESTRICT
   selectSize->plug(m_options);
#endif

   KAction *save_settings = KStdAction::saveOptions(this, SLOT(slotSaveSettings()), actions);
   save_settings->plug(m_options);
   m_options->insertSeparator();

#ifdef LLS_NOT_RESTRICT
   m_saveProfile->plug(m_options);
   m_options->insertSeparator();
#endif

#ifdef LLS_NOT_RESTRICT
   KStdAction::keyBindings(this, SLOT(slotConfigureKeys()), actionCollection())->plug(m_options);
   KAction *configure = KStdAction::preferences(this, SLOT(slotConfigure()), actions);
   configure->plug(m_options);
#endif

#ifdef LLS_NOT_RESTRICT
   if (KGlobalSettings::insertTearOffHandle())
     m_options->insertTearOffHandle();
   m_help->insertSeparator(1);
#endif

   //help menu
//   m_help->insertItem(SmallIcon( "idea" ), i18n("&Tip of the Day"),
//           this, SLOT(showTip()), 0, -1, 2);

   //the different session menus
   buildSessionMenus();

//   connect(m_session, SIGNAL(activated(int)), SLOT(newSession(int)));

   // Right mouse button menu
   showMenubar->plug ( m_rightButton );
   m_rightButton->insertSeparator();

   m_copyClipboard->plug(m_rightButton);
   m_pasteClipboard->plug(m_rightButton);

   m_rightButton->insertSeparator();

   m_rightButton->insertSeparator();
   m_rightButton->insertItem(i18n("S&ettings"), m_options);
   m_rightButton->insertSeparator();
   // m_closeSession->plug(m_rightButton );
   if (KGlobalSettings::insertTearOffHandle())
     m_rightButton->insertTearOffHandle();


   delete colors;
   colors = new ColorSchemaList();
   //KONSOLEDEBUG<<"Klt::makeGUI(): curr_schema "<<curr_schema<<" path: "<<s_schema<<endl;
   colors->checkSchemas();
   colors->sort();
   //KONSOLEDEBUG<<"Klt::makeGUI() updateSchemas()"<<endl;
   updateSchemaMenu();
   ColorSchema *sch=colors->find(s_schema);
   //KONSOLEDEBUG<<"Klt::makeGUI(): curr_schema "<<curr_schema<<" path: "<<s_schema<<endl;
   if (sch)
        curr_schema=sch->numb();
   else
        curr_schema = 0;
   for (uint i=0; i<m_schema->count(); i++)
      m_schema->setItemChecked(i,false);

   m_schema->setItemChecked(curr_schema,true);
   while (se == NULL) {}
   se->setSchemaNo(curr_schema);

   // insert keymaps into menu
   //FIXME: sort
   for (int i = 0; i < KeyTrans::count(); i++)
   {
      KeyTrans* ktr = KeyTrans::find(i);
      assert( ktr );
      m_keytab->insertItem(ktr->hdr(),ktr->numb());
   }
   applySettingsToGUI();
   isRestored = false;

   new KAction(i18n("Bigger Font"), 0, this, SLOT(biggerFont()), m_shortcuts, "bigger_font");
   new KAction(i18n("Smaller Font"), 0, this, SLOT(smallerFont()), m_shortcuts, "smaller_font");

   m_shortcuts->readShortcutSettings();
}

/*	RB Note - This appears to be the setup for the menu stuff */

void Klt::makeBasicGUI()
{
HERE;
  //KONSOLEDEBUG<<"Klt::makeBasicGUI()"<<endl;
  m_session = new KPopupMenu(this);
  m_edit = new KPopupMenu(this);
#ifdef LLS_NOT_RESTRICT
  m_view = new KPopupMenu(this);
  m_help =  helpMenu(0, false);
#endif

  m_options = new KPopupMenu(this);

  m_rightButton = new KPopupMenu(this);

  // For those who would like to add shortcuts here, be aware that
  // ALT-key combinations are heavily used by many programs. Thus,
  // activating shortcuts here means deactivating them in the other
  // programs.

  connect(m_session,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
  connect(m_options,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
  connect(m_rightButton,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
  connect(m_edit,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
#ifdef LLS_NOT_RESTRICT
  connect(m_view,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
  connect(m_help,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
#endif

  menubar->insertItem(i18n("Session") , m_session);
  menubar->insertItem(i18n("Edit"), m_edit);
#ifdef LLS_NOT_RESTRICT
  menubar->insertItem(i18n("View"), m_view);
  menubar->insertItem(i18n("Help"), m_help);
#endif
  menubar->insertItem(i18n("Settings"), m_options);

  m_shortcuts = new KActionCollection(this);

  m_copyClipboard = new KAction(i18n("&Copy"), "editcopy", 0, te,
                                 SLOT(copyClipboard()), m_shortcuts, "copy");
  m_pasteClipboard = new KAction(i18n("&Paste"), "editpaste", 0, te,
                                 SLOT(pasteClipboard()), m_shortcuts, "paste");

  showMenubar = new KToggleAction ( i18n( "Show &Menubar" ), "showmenu", 0, this,
                                    SLOT( slotToggleMenubar() ), m_shortcuts, "show_menubar" );

  m_saveProfile = new KAction( i18n( "Save Sessions &Profile..." ), 0, this,
                         SLOT( slotSaveSessionsProfile() ), m_shortcuts, "save_sessions_profile" );

/*
  m_closeSession = new KAction(i18n("&Quit"), "fileclose", 0, this,
                               SLOT(closeCurrentSession()), m_shortcuts, "close_session");
*/
  m_quit = new KAction(i18n("&Quit"), "exit", 0, this, SLOT( close() ), m_shortcuts, "quit");

  m_shortcuts->readShortcutSettings();
}

/**
   Make menubar available via escape sequence (Default: Ctrl+Alt+m)
 */
void Klt::activateMenu()
{
HERE;
  menubar->activateItemAt(0);
  if ( !showMenubar->isChecked() ) {
    menubar->show();
    showMenubar->setChecked(true);
	setColLin(te->Columns(), 24);
// fprintf(stderr,"Forcing 24 cols in activateMenuBar bitty\n");
  }
}
/**
   RB - Make statusbar visable
**/
void Klt::activateStatusBar(const QString& msg)
{
	if( !done_statusbar ) {
		statusbar = statusBar();
		statusbar->insertItem("",1,1,0);
		done_statusbar = 1;
	}
    statusbar->show();;
    statusbar->changeItem(msg,1);
	setColLin(te->Columns(), 24);
}
/**
   RB - Make statusbar invisable
**/
void Klt::clearStatusBar()
{
HERE;
	if( done_statusbar ){
		statusbar->hide();;
		/* Force XXX z 24 lines */
		setColLin(te->Columns(), 24);
	}
}


/**
   Ask for Quit confirmation - Martijn Klingens
   Asks for confirmation if there are still open shells when the 'Warn on
   Quit' option is set.

   Hacked by RB
 */
bool Klt::queryExit()
{
HERE;
/*
   if(skip_exit_query ) return true;
*/
HERE;

/* DEBUG
*{
*FILE *fp;
*fp=fopen("/tmp/klt.log","a");
*fprintf(fp,"Query Exit Title is '%s'\n",lls_qstring_title.latin1());
*if( lls_qstring_title.contains("MenuPath") != 0 ) {
*	fprintf(fp,"Query Exit Title in MenuPath\n");
*}
*fclose(fp);
*}
*/


	if( lls_qstring_title.contains("MenuPath") == 0 ) return true;

	KWin::deIconifyWindow(winId());
/*	KWin::setActiveWindow(winId()); */
	KMessageBox::sorry( this,
				 i18n( "You have programs still running in Klt windows.\n"
					   "Please exit them gracefully before logging out.\n"),
				 i18n("Logout Overridden"));
	return false;
}
/**
   Ask for Quit confirmation - Martijn Klingens
   Asks for confirmation if there are still open shells when the 'Warn on
   Quit' option is set.

   Hacked by RB
 */
bool Klt::queryClose()
{
HERE;
/*
   if(skip_exit_query ) return true;
*/
	/* 
		If this window title contains the magic string
		": MenuPath: " then we're running sommat from this menu
	*/
HERE;

/* DEBUG
*{
*FILE *fp;
*fp=fopen("/tmp/klt.log","a");
*if( lls_qstring_title.contains("MenuPath") != 0 ) {
*	fprintf(fp,"Query Close Title in MenuPath\n");
*}
*fclose(fp);
*}
*/

//	fprintf(stderr,"S is %X\n",(unsigned) s);
//	fprintf(stderr,"queryClose Precheck S is %s\n",s);
HERE;
	if( lls_qstring_title.contains("MenuPath") == 0 ) return true;
//	fprintf(stderr,"queryClose WARNING\n");
HERE;

	KWin::deIconifyWindow(winId());
	/* KWin::setActiveWindow(winId()); */
	KMessageBox::sorry( 0,
				 i18n( "You still have programs running.\n"
					   "Please return to a menu level before trying to close this window.\n"),
				 i18n("Window Closure Denied"));
	return false;
}
void Klt::slotCouldNotClose()
{
HERE;
    int result = KMessageBox::warningContinueCancel(this,
             i18n("The application running in Klt does not respond to the close request. "
                  "Do you want Klt to close anyway?"),
             i18n("Application Does Not Respond"),
             i18n("Close"));
    if (result == KMessageBox::Continue)
    {
        while(sessions.first())
        {
            doneSession(sessions.current());
        }
    }
}

/**
    sets application window to a size based on columns X lines of the te
    guest widget. Call with (0,0) for setting default size.
*/

static int save_132col_font=0;

void Klt::setColLin(int columns, int lines)
{
	int fontno, screenwidth;
HERE;
   if (m_menuCreated) {
	  int item = selectFont->currentItem();
	  setFont(item);
	}
	screenwidth= QApplication::desktop()->screenGeometry(0).width();

  if ((columns==0) || (lines==0))
  {
    if (defaultSize.isEmpty()) // not in config file : set default value
    {
      defaultSize = sizeForCentralWidgetSize(te->calcSize(80,24));
      notifySize(24,80); // set menu items (strange arg order !)
    }
//printf("**SetFixedSize**\n");
HERE;
    setFixedSize(defaultSize);
	setMinimumSize(defaultSize);
	setMaximumSize(defaultSize);
  } else {
//printf("**SetFixedSize**\n");
HERE;

//fprintf(stderr,"columns %d  lines %d font %d save_132col_font %d\n\r",columns,lines,sessions.current()->fontNo(),save_132col_font);

  if( !n_autoresize ) {
	  if( columns <= 80 && save_132col_font ) {
	//fprintf(stderr,"Wibble IX %d\n\r",save_132col_font);
		  //	Restore previous font
		  setFont(save_132col_font);
		  save_132col_font = 0;
	  }
	  if( (fontno=sessions.current()->fontNo()) >= 3 && columns > 80 && save_132col_font == 0 ) {
	//fprintf(stderr,"Wibble VII %d\n\r",fontno);
		  save_132col_font = fontno;
		  if ( fontno >= 3 ) {
			  if( screenwidth <= 1024 ) setFont(2);
			  else if (screenwidth <= 1280) setFont(4);
			  else setFont(6);
		}
	  } 
	//	NoNo this shrinks the font when 132col reset is called twice
	//else {
	//fprintf(stderr,"Wibble VIII\n\r");
	//	  save_132col_font = 0;
	//  }
   }

    setFixedSize(sizeForCentralWidgetSize(te->calcSize(columns, lines)));
	setMinimumSize(sizeForCentralWidgetSize(te->calcSize(columns, lines)));
	setMaximumSize(sizeForCentralWidgetSize(te->calcSize(columns, lines)));
    notifySize(lines,columns); // set menu items (strange arg order !)
  }
}

/* ------------------------------------------------------------------------- */
/*                                                                           */
/*                                                                           */
/* ------------------------------------------------------------------------- */

void Klt::configureRequest(TEWidget* te, int state, int x, int y)
{
HERE;
//printf("Klt::configureRequest(_,%d,%d)\n",x,y);
   if (!m_menuCreated)
      makeGUI();
  ( (state & ControlButton) ? m_session :
                              m_rightButton  )
  ->popup(te->mapToGlobal(QPoint(x,y)));
}

/* ------------------------------------------------------------------------- */
/*                                                                           */
/* Configuration                                                             */
/*                                                                           */
/* ------------------------------------------------------------------------- */

void Klt::slotSaveSessionsProfile()
{
HERE;
  KLineEditDlg dlg(i18n("Enter name under which the profile should be saved:"), QString::null, this);
  dlg.setCaption(i18n("Save Sessions Profile"));
  if (dlg.exec()) {
    QString path = locateLocal( "data", QString::fromLatin1( "klt/profiles/" ) +
                                dlg.text(), KGlobal::instance() );

    if ( QFile::exists( path ) )
      QFile::remove( path );

    KSimpleConfig cfg( path );
    saveProperties(&cfg);
    cfg.setGroup("WindowProperties1");
    saveMainWindowSettings(&cfg);
  }
}

void Klt::saveProperties(KConfig* config) {
  QString key;
  config->setDesktopGroup();

  if (config != KGlobal::config())
  {
     // called by the session manager
     skip_exit_query = true;
     sessions.first();
        config->writeEntry(QString("Title"), sessions.current()->Title());
        config->writeEntry(QString("Schema"), colors->find( sessions.current()->schemaNo() )->relPath());
        config->writeEntry(QString("Args"), sessions.current()->getArgs());
        config->writeEntry(QString("Pgm"), sessions.current()->getPgm());
        config->writeEntry(QString("Font"), sessions.current()->fontNo());
        config->writeEntry(QString("Term"), sessions.current()->Term());
        config->writeEntry(QString("KeyTab"), sessions.current()->keymap());
        config->writeEntry(QString("Icon"), sessions.current()->IconName());

        QString cwd=sessions.current()->getCwd();
        if (cwd.isEmpty())
          cwd=sessions.current()->getInitial_cwd();
        config->writeEntry(QString("Cwd"), cwd);

  }
  config->setDesktopGroup();
  config->writeEntry("font",n_defaultFont);
  config->writeEntry("defaultfont", defaultFont);
  config->writeEntry("schema",s_kconfigSchema);
  config->writeEntry("bellmode",n_bell);
  config->writeEntry("noautoresize",n_autoresize);
  config->writeEntry("keytab",KeyTrans::find(n_defaultKeytab)->id());
  config->writeEntry("class",name());
}


// Called by constructor (with config = KGlobal::config())
// and by session-management (with config = sessionconfig).
// So it has to apply the settings when reading them.
void Klt::readProperties(KConfig* config)
{
HERE;
    readProperties(config, QString::null, false);
}

// If --type option was given, load the corresponding schema instead of
// default
//
// When globalConfigOnly is true only the options that are shared among all
// klts are being read.
void Klt::readProperties(KConfig* config, const QString &schema, bool globalConfigOnly)
{
HERE;
   config->setDesktopGroup();
   //KONSOLEDEBUG<<"Klt::readProps()"<<endl;

   if (config==KGlobal::config())
   {
HERE;
     b_warnQuit=config->readBoolEntry( "WarnQuit", true );
     b_allowResize=config->readBoolEntry( "AllowResize", true);

     s_word_seps= config->readEntry("wordseps",":@-./_~");
     te->setWordCharacters(s_word_seps);

     te->setTerminalSizeHint( config->readBoolEntry("TerminalSizeHint",true) );

     b_framevis = config->readBoolEntry("has frame",true);
     te->setFrameStyle( b_framevis?(QFrame::WinPanel|QFrame::Sunken):QFrame::NoFrame );

     te->setBlinkingCursor(config->readBoolEntry("BlinkingCursor",true));
     te->setCtrlDrag(config->readBoolEntry("CtrlDrag",false));
     te->setCutToBeginningOfLine(config->readBoolEntry("CutToBeginningOfLine",false));
     te->setLineSpacing( config->readUnsignedNumEntry( "LineSpacing", 0 ) );

     b_xonXoff = config->readBoolEntry("XonXoff",false);
     config->setGroup("UTMP");
     b_addToUtmp = config->readBoolEntry("AddToUtmp",true);
     config->setDesktopGroup();
   }

HERE;
   ColorSchema* sch = 0;
   if (!globalConfigOnly)
   {
HERE;
      n_defaultKeytab=KeyTrans::find(config->readEntry("keytab","default"))->numb(); // act. the keytab for this session
      n_defaultFont = n_font = QMIN(config->readUnsignedNumEntry("font",5),TOPFONT);
      n_bell = QMIN(config->readUnsignedNumEntry("bellmode",TEWidget::BELLSYSTEM),1);
      n_autoresize = config->readUnsignedNumEntry("noautoresize",0);

      // Options that should be applied to all sessions /////////////
      // (1) set menu items and Klt members
       QFont tmpFont("fixed");
      // QFont tmpFont("bitstream vera");
      // QFont tmpFont("courier");
      // QFont tmpFont("Monospace");
      tmpFont.setFixedPitch(true);
      // tmpFont.setStyleHint(QFont::TypeWriter);
      // tmpFont.setStyleHint(QFont::Courier);
      defaultFont = config->readFontEntry("defaultfont", &tmpFont);
      setFont(QMIN(config->readUnsignedNumEntry("font",5),TOPFONT));

      //set the schema
      s_kconfigSchema=config->readEntry("schema", "");
      sch = colors->find(schema.isEmpty() ? s_kconfigSchema : schema);
      if (!sch)
      {
HERE;
/*
         kdWarning() << "Could not find schema named " <<s_kconfigSchema<< endl;
*/
         sch=(ColorSchema*)colors->at(0);  //the default one
      }
      if (sch->hasSchemaFileChanged()) sch->rereadSchemaFile();
      s_schema = sch->relPath();
      curr_schema = sch->numb();
      pmPath = sch->imagePath();
      te->setColorTable(sch->table()); //FIXME: set twice here to work around a bug

HERE;
	rootxpm->stop();
	pixmap_menu_activated(sch->alignment());
HERE;

      te->setColorTable(sch->table());
      // te->setBellMode(n_bell);

   }
HERE;

   if (m_menuCreated)
   {
      applySettingsToGUI();
      activateSession();
   };
HERE;
	
}

void Klt::applySettingsToGUI()
{
HERE;
   if (!m_menuCreated) return;
   selectFont->setCurrentItem(n_font);
   notifySize(te->Lines(),te->Columns());
   showMenubar->setChecked(!menuBar()->isHidden());
   selectBell->setCurrentItem(n_bell);
   selectAutoresize->setCurrentItem(n_autoresize);
   updateKeytabMenu();
}


/* ------------------------------------------------------------------------- */
/*                                                                           */
/*                                                                           */
/* ------------------------------------------------------------------------- */

void Klt::pixmap_menu_activated(int item)
{
HERE;
  if (item <= 1) pmPath = "";
  QPixmap pm(pmPath);
  if (pm.isNull()) {
    pmPath = "";
    item = 1;
    te->setBackgroundColor(te->getDefaultBackColor());
    return;
  }
  // FIXME: respect scrollbar (instead of te->size)
  n_render= item;
  switch (item)
  {
    case 1: // none
    case 2: // tile
            te->setBackgroundPixmap(pm);
    break;
    case 3: // center
            { QPixmap bgPixmap;
              bgPixmap.resize(te->size());
              bgPixmap.fill(te->getDefaultBackColor());
              bitBlt( &bgPixmap, ( te->size().width() - pm.width() ) / 2,
                                ( te->size().height() - pm.height() ) / 2,
                      &pm, 0, 0,
                      pm.width(), pm.height() );

              te->setBackgroundPixmap(bgPixmap);
            }
    break;
    case 4: // full
            {
              float sx = (float)te->size().width() / pm.width();
              float sy = (float)te->size().height() / pm.height();
              QWMatrix matrix;
              matrix.scale( sx, sy );
              te->setBackgroundPixmap(pm.xForm( matrix ));
            }
    break;
    default: // oops
             n_render = 1;
  }
}

void Klt::slotSelectBell() {
  n_bell = selectBell->currentItem();
  te->setBellMode(n_bell);
}

void Klt::slotSelectAutoresize() {
  n_autoresize = selectAutoresize->currentItem();
}

void Klt::slotSelectFont() {
	int columns= te->Columns();
  assert(se);
  int item = selectFont->currentItem();
  // KONSOLEDEBUG << "slotSelectFont " << item << endl;
//  if (item == DEFAULTFONT)
 // {
//    if ( KFontDialog::getFont(defaultFont, true) == QDialog::Rejected )
//    {
//      selectFont->setCurrentItem(n_font);
//      return;
//    }
//  }
  setFont(item);
  n_defaultFont = n_font; // This is the new default
#ifdef LLS_NOT_RESTRICT
  activateSession(); // activates the current
#endif
	//	RB Bodge.... Resize to N cols by 24 lines after font change
	/* Force XXX z 24 lines */
	setColLin(columns, 24);
	//	Now force redraw cos if we're going from a small to a large font
	//	the bottom RH of the screen doesn't get redrawn
	// emit changedImageSizeSignal(te->Lines(), te->Columns());
}

void Klt::schema_menu_activated(int item)
{
HERE;
  assert(se);
  //FIXME: save schema name
//        KONSOLEDEBUG << "Item " << item << " selected from schema menu"
//                << endl;
  setSchema(item);
  s_kconfigSchema = s_schema; // This is the new default
  // activateSession(); // activates the current
}

/* slot */ void Klt::schema_menu_check()
{
HERE;
        if (colors->checkSchemas())
        {
                colors->sort();
                updateSchemaMenu();
        }
}

void Klt::updateSchemaMenu()
{
HERE;
//        KONSOLEDEBUG << "Updating schema menu with "
//                << colors->count()
//                << " items."
//                << endl;

  m_schema->clear();
  for (int i = 0; i < (int) colors->count(); i++)
  {
     ColorSchema* s = (ColorSchema*)colors->at(i);
    assert( s );
    m_schema->insertItem(s->title(),s->numb(),0);
  }

  if (te && se)
  {
//        KONSOLEDEBUG << "Current session has schema "
//                << te->currentSession->schemaNo()
//                << endl;
        m_schema->setItemChecked(se->schemaNo(),true);
  }

}

void Klt::updateKeytabMenu()
{
HERE;
  if (m_menuCreated)
  {
     m_keytab->setItemChecked(n_keytab,false);
     m_keytab->setItemChecked(se->keymapNo(),true);
  };
  n_keytab = se->keymapNo();
}

void Klt::keytab_menu_activated(int item)
{
HERE;
  se->setKeymapNo(item);
  n_defaultKeytab = item;
  updateKeytabMenu();
}


void Klt::setFont(int fontno)
{
HERE;
  QFont f;
	bool ok; /* RG 190110 */
    /*	This seems to enable Giant Font 
     *	also disable bitmap fonts in dpkg-reconfigure fontconfig 
	 *	also make sure xfont-konsole and msttcorefonts packages are
	 *	installed.
	 *	*/

    f.setStyleHint(QFont::TypeWriter);
    /*f.setStyleStrategy(QFont::ForceOutline | QFont::PreferMatch); */
    f.setStyleStrategy(QFont::PreferMatch );
    
  if (fontno == DEFAULTFONT)
    f = defaultFont;
  else
  if (fonts[fontno][0] == '-')
  {
    f.setRawName( fonts[fontno] );
    f.setFixedPitch(true);
    f.setStyleHint(QFont::TypeWriter);
    if ( !f.exactMatch() && fontno != DEFAULTFONT)
    {
      // Ugly hack to prevent bug #20487
      fontNotFound_par=fonts[fontno];
      QTimer::singleShot(1,this,SLOT(fontNotFound()));
      return;
    }
  }
  else
  {
	// Original settings before Richard started playing around 190110
	// to find a nicer font: Family= fixed, no Weight specified
    f.setFamily("fixed");
    f.setFixedPitch(true);
    f.setStyleHint(QFont::TypeWriter);
    //
    //	Now richards Messing
    // f.setFamily("fixed");
    // f.setFamily("Courier");
    // f.setFamily("Courier New");
    // f.setFamily("Courier 10 Pitch");
    // f.setFamily("FreeMono");
	//	Weight 50 == Normal; 63==Demi Bold; 75 == Bold
	//	Demi Bold and Bold are the Same for Courier
    	// f.setWeight(50);
    	//
    f.setPixelSize(QString(fonts[fontno]).toInt());
	//
	// For Interactive testing/debugging you can use.....
	// f = QFontDialog::getFont( &ok, QFont( "ml_ttkarthika", 12 ));
	//
	// f = QFontDialog::getFont( &ok, QFont( "ml_ttkarthika", 12 ));
  }
  if (se) se->setFontNo(fontno);
  //	Error :-(
//	if( done_statusbar ) statusbar->setFontNo(fontno);

  if (m_menuCreated)
     selectFont->setCurrentItem(fontno);
  te->setVTFont(f);
  n_font = fontno;
}

void Klt::fontNotFound()
{
HERE;
  QString msg = i18n("Font `%1' not found.\nCheck README.linux.console for help.").arg(fontNotFound_par);
  KMessageBox::error(this,  msg);
}

/**
     Toggle the Menubar visibility
 */
void Klt::slotToggleMenubar() {
// fprintf(stderr,"In toggleMenuBar bitty\n");
  if ( showMenubar->isChecked() ) {
     menubar->show();

  } else {
     menubar->hide();
  }
  setColLin(te->Columns(), 24);
// fprintf(stderr,"Forcing 24 cols in toggleMenuBar bitty\n");
  if (!showMenubar->isChecked()) {
    setCaption(i18n("Use the right mouse button to bring back the menu"));
    QTimer::singleShot(5000,this,SLOT(updateTitle()));
  }
}

void Klt::slotSaveSettings()
{
HERE;
  KConfig *config = KGlobal::config();
  config->setDesktopGroup();
  saveProperties(config);
  saveMainWindowSettings(config);
  config->sync();
}

void Klt::slotConfigureKeys()
{
HERE;
   KKeyDialog::configure(m_shortcuts);
   m_shortcuts->writeShortcutSettings();
}


void Klt::slotConfigure()
{
HERE;
  QStringList args;
  args << "kcmklt";
  KApplication::kdeinitExec( "kcmshell", args );
}

void Klt::reparseConfiguration()
{
HERE;
  KGlobal::config()->reparseConfiguration();
  readProperties(KGlobal::config(), QString::null, true);
  buildSessionMenus();
}

// --| color selection |-------------------------------------------------------

void Klt::changeColumns(int columns)
{
HERE;
    setColLin(columns,te->Lines());
    te->update();
}
void Klt::changeLines(int lines)
{
HERE;
    setColLin(te->Columns(),lines);
    te->update();
}

void Klt::slotSelectSize() {
    int item = selectSize->currentItem();
    switch (item) {
    case 0: setColLin(40,15); break;
    case 1: setColLin(80,24); break;
    case 2: setColLin(80,25); break;
    case 3: setColLin(80,40); break;
    case 4: setColLin(80,52); break;
    case 5: SizeDialog dlg(te->Columns(), te->Lines(), this);
            if (dlg.exec())
              setColLin(dlg.columns(),dlg.lines());
            break;
   }
}


void Klt::notifySize(int lines, int columns)
{
	return;
HERE;
  if (m_menuCreated)
  {
    selectSize->blockSignals(true);
    selectSize->setCurrentItem(-1);
    if (columns==40&&lines==15)
        selectSize->setCurrentItem(0);
    else if (columns==80&&lines==24)
        selectSize->setCurrentItem(1);
    else if (columns==80&&lines==25)
        selectSize->setCurrentItem(2);
    else if (columns==80&&lines==40)
        selectSize->setCurrentItem(3);
    else if (columns==80&&lines==52)
        selectSize->setCurrentItem(4);
    else
        selectSize->setCurrentItem(5);
    selectSize->blockSignals(false);
  }

  if (n_render >= 3) pixmap_menu_activated(n_render);
// fprintf(stderr,"notifySize: %d,%d\n",te->size().width(),te->size().height());

// RB Playing
//	te->update();
//	update();
//   if (m_menuCreated) setFixedSize(size());

}


void Klt::updateTitle()
{
HERE;
  setCaption( lls_qstring_title=se->fullTitle() );
/*
* if( lls_qstring_title.contains("MenuPath") != 0 ) {
* 	fprintf(stderr,"In MenuPath\n");
* }
*/
HERE;
  setIconText( se->IconText() );
HERE;
}

void Klt::initFullScreen()
{
HERE;
  //This function is to be called from main.C to initialize the state of the Klt (fullscreen or not).  It doesn't appear to work
  //from inside the Klt constructor
   setColLin(80,24);
}

void Klt::initSessionFont(int fontNo) {
  if (fontNo == -1) return; // Don't change
  setFont(fontNo);
}

void Klt::initSessionKeyTab(const QString &keyTab) {
  se->setKeymap(keyTab);
  updateKeytabMenu();
}

/* --| sessions |------------------------------------------------------------ */

//FIXME: activating sessions creates a lot flicker in the moment.
//       it comes from setting the attributes of a session individually.
//       ONE setImage call should actually be enough to match all cases.
//       These can be quite different:
//       - The screen size might have changed while the session was
//         detached. A propagation of the resize should in this case
//         make the drawEvent.
//       - font, background image and color palette should be set in one go.

void Klt::clearAllListenToKeyPress()
{
HERE;
  for (TESession *ses = sessions.first(); ses; ses = sessions.next())
    ses->setListenToKeyPress(false);
}

void Klt::restoreAllListenToKeyPress()
{
HERE;
  if(se->isMasterMode())
    for (TESession *ses = sessions.first(); ses; ses = sessions.next())
      ses->setListenToKeyPress(true);
  else
    se->setListenToKeyPress(true);
}

void Klt::feedAllSessions(const QString &text)
{
HERE;
  for (TESession *ses = sessions.first(); ses; ses = sessions.next())
    ses->setListenToKeyPress(true);
  if (te)
    te->emitText(text);
  if(!se->isMasterMode()) {
    for (TESession *ses = sessions.first(); ses; ses = sessions.next())
      ses->setListenToKeyPress(false);
    se->setListenToKeyPress(true);
  }
}

void Klt::sendAllSessions(const QString &text)
{
HERE;
  QString newtext=text;
  newtext.append("\r");
  feedAllSessions(newtext);
}

KURL Klt::baseURL() const
{
HERE;
   KURL url;
   url.setPath(se->getCwd()+"/");
   return url;
}

void Klt::slotClearTerminal()
{
HERE;
  if (se) {
    se->getEmulation()->clearEntireScreen();
    se->getEmulation()->clearSelection();
  }
}

void Klt::slotResetClearTerminal()
{
HERE;
  if (se) {
    se->getEmulation()->reset();
    se->getEmulation()->clearSelection();
  }
}

void Klt::sendSignal(int sn)
{
HERE;
  if (se) se->sendSignal(sn);
}

void Klt::runSession(TESession* s)
{
HERE;
    KRadioAction *ra = session2action.find(s);
    ra->setChecked(true);
    activateSession();

    // give some time to get through the
    // resize events before starting up.
    QTimer::singleShot(100,s,SLOT(run()));
}

void Klt::addSession(TESession* s)
{
HERE;
   QString newTitle = s->Title();

  bool nameOk;
  int count = 1;
  do {
     nameOk = true;
     for (TESession *ses = sessions.first(); ses; ses = sessions.next())
     {
        if (newTitle == ses->Title())
        {
           nameOk = false;
           break;
        }
     }
     for (KltChild *child = detached.first(); child; child = detached.next())
     {
        if (newTitle == child->session()->Title())
        {
           nameOk = false;
           break;
        }
     }
     if (!nameOk)
     {
       count++;
       newTitle = i18n("abbreviation of number","%1 No. %2").arg(s->Title()).arg(count);
     }
  }
  while (!nameOk);

  s->setTitle(newTitle);

  // create an action for the session
  //  char buffer[30];
  //  int acc = CTRL+SHIFT+Key_0+session_no; // Lars: keys stolen by kwin.
  KRadioAction *ra = new KRadioAction(newTitle,
                                      s->IconName(),
                                      0,
                                      this,
                                      SLOT(activateSession()),
                                      this);
                                      //                                      buffer);
  ra->setExclusiveGroup("sessions");
  ra->setChecked(true);
  // key accelerator
  //  accel->connectItem(accel->insertItem(acc), ra, SLOT(activate()));

  action2session.insert(ra, s);
  session2action.insert(s,ra);
  sessions.append(s);
  if (sessions.count()>1) {
     if (!m_menuCreated)
        makeGUI();
     m_detachSession->setEnabled(true);
  }

}

QString Klt::currentSession()
{
HERE;
  return se->SessionId();
}

QString Klt::sessionId(const int position)
{
HERE;
  if (position<=0 || position>(int)sessions.count())
    return "";

  return sessions.at(position-1)->SessionId();
}

void Klt::listSessions()
{
HERE;
  int counter=0;
  KPopupMenu* m_sessionList = new KPopupMenu(this);
  m_sessionList->insertTitle(i18n("Session List:"));
#if KDE_VERSION >=306
  m_sessionList->setKeyboardShortcutsEnabled(true);
#endif
  for (TESession *ses = sessions.first(); ses; ses = sessions.next())
    m_sessionList->insertItem(SmallIcon(ses->IconName()),ses->Title(),++counter);
  connect(m_sessionList, SIGNAL(activated(int)), SLOT(activateSession(int)));
  m_sessionList->adjustSize();
  m_sessionList->popup(mapToGlobal(QPoint((width()/2)-(m_sessionList->width()/2),(height()/2)-(m_sessionList->height()/2))));
}

void Klt::activateSession(const int position)
{
HERE;
  if (position<=0 || position>(int)sessions.count())
    return;
  activateSession( sessions.at(position-1) );
}

void Klt::activateSession(const QString &sessionId)
{
HERE;
  TESession* activate=NULL;

  sessions.first();
  while(sessions.current())
  {
    if (sessions.current()->SessionId()==sessionId)
      activate=sessions.current();
    sessions.next();
  }

  if (activate)
    activateSession( activate );
}

/**
   Activates a session (from the menu or by pressing a button)
 */
void Klt::activateSession()
{
HERE;
  TESession* s = NULL;
  // finds the session based on which button was activated
  QPtrDictIterator<TESession> it( action2session ); // iterator for dict
  while ( it.current() )
  {
    KRadioAction *ra = (KRadioAction*)it.currentKey();
    if (ra->isChecked()) { s = it.current(); break; }
    ++it;
  }
  if (s!=NULL) activateSession(s);
}

void Klt::activateSession(TESession *s)
{
HERE;
  if (se)
  {
     se->setConnect(false);
     if(se->isMasterMode())
       for (TESession *se = sessions.first(); se; se = sessions.next())
         se->setListenToKeyPress(false);

     notifySessionState(se,NOTIFYNORMAL);
  }
  se_previous = se;
  se = s;
  session2action.find(se)->setChecked(true);
  if (s->schemaNo()!=curr_schema)
  {
     // the current schema has changed
     setSchema(s->schemaNo());
  }

  //  te->currentSession = se;
  if (s->fontNo() != n_font)
  {
      setFont(s->fontNo());
  }
  s->setConnect(true);
  if(se->isMasterMode())
    for (TESession *se = sessions.first(); se; se = sessions.next())
      se->setListenToKeyPress(true);
  updateTitle();
  if (!m_menuCreated)
     return;

  updateKeytabMenu(); // act. the keytab for this session
  masterMode->setChecked( se->isMasterMode() );
  sessions.find(se);
  uint position=sessions.at();
}

KSimpleConfig *Klt::defaultSession()
{
HERE;
  if (!m_defaultSession)
    setDefaultSession("klt.desktop");
  return m_defaultSession;
}

void Klt::setDefaultSession(const QString &filename)
{
HERE;
  delete m_defaultSession;
  m_defaultSession = new KSimpleConfig(locate("appdata", filename), true /* read only */);
  m_defaultSessionFilename=filename;
}

void Klt::newSession(const QString &pgm, const QStrList &args, const QString &term, const QString &icon, const QString &cwd)
{
HERE;
  KSimpleConfig *co = defaultSession();
  newSession(co, pgm, args, term, icon, QString::null, cwd);
}

QString Klt::newSession()
{
HERE;
  KSimpleConfig *co = defaultSession();
  return newSession(co, QString::null, QStrList());
}

void Klt::newSession(int i)
{
HERE;
  KSimpleConfig* co = no2command.find(i);
  if (co) {
    newSession(co);
    resetScreenSessions();
  }
}

QString Klt::newSession(const QString &type)
{
HERE;
  KSimpleConfig *co;
  if (type.isEmpty())
     co = defaultSession();
  else
     co = new KSimpleConfig(locate("appdata", type + ".desktop"), true /* read only */);
  return newSession(co);
}

QString Klt::newSession(KSimpleConfig *co, QString program, const QStrList &args, const QString &_term,const QString &_icon,const QString &_title, const QString &_cwd, const QString &_font)
{
HERE;
  QString emu = "klt";
  QString icon = "tractterm";
  QString key;
  QString sch = s_kconfigSchema;
  QString txt;
  QString cwd;
  unsigned int     fno=n_defaultFont;
  QStrList cmdArgs;

	
HERE;
//fprintf(stderr,"fno is %d default is %d\n",fno,n_defaultFont);

  if (co) {
     co->setDesktopGroup();
     emu = co->readEntry("Term", emu);
     key = co->readEntry("KeyTab", key);
     sch = co->readEntry("Schema", sch);
     txt = co->readEntry("Name");
     fno = co->readUnsignedNumEntry("Font", fno);
     icon = co->readEntry("Icon", icon);
     cwd = co->readPathEntry("Cwd");
  }

  if (!_term.isEmpty())
     emu = _term;

  if (!_icon.isEmpty())
     icon = _icon;

  if (!_title.isEmpty())
     txt = _title;

  if (!_cwd.isEmpty())
     cwd = _cwd;

  if (!program.isEmpty()) {
    cmdArgs = args;
 } else program="/bin/sh";

// else {
//    program = QFile::decodeName(klt_shell(cmdArgs));
//
//    if (co) {
//fprintf(stderr,"In CO Bitty\n\r");
//        co->setDesktopGroup();
//       QString cmd = co->readEntry("Exec");
//
//       if (!cmd.isEmpty()) {
//         cmdArgs.append("-c");
//         cmdArgs.append(QFile::encodeName(cmd));
//       }
//    }
//}

  ColorSchema* schema = colors->find(sch);
  if (!schema)
      schema=(ColorSchema*)colors->at(0);  //the default one
  int schmno = schema->numb();

  QString sessionId="session-"+QString::number(++sessionIdCounter);
  TESession* s = new TESession(te, QFile::encodeName(program),cmdArgs,emu,sessionId,cwd);
  s->enableFullScripting(b_fullScripting);
  // If you add any new signal-slot connection below, think about doing it in kltPart too
  connect( s,SIGNAL(done(TESession*)),
           this,SLOT(doneSession(TESession*)) );
  connect( te, SIGNAL(configureRequest(TEWidget*, int, int, int)),
           this, SLOT(configureRequest(TEWidget*,int,int,int)) );
  connect( s, SIGNAL( updateTitle() ),
           this, SLOT( updateTitle() ) );
  connect( s, SIGNAL( notifySessionState(TESession*, int) ),
           this, SLOT( notifySessionState(TESession*, int)) );
  connect( s, SIGNAL(clearAllListenToKeyPress()),
           this, SLOT(clearAllListenToKeyPress()) );
  connect( s, SIGNAL(restoreAllListenToKeyPress()),
           this, SLOT(restoreAllListenToKeyPress()) );
  connect( s->getEmulation(), SIGNAL(changeColumns(int)),
           this, SLOT(changeColumns(int)) );
  connect( s->getEmulation(), SIGNAL(activateStatusBar(const QString&)),
           this, SLOT(activateStatusBar(const QString&)) );
  connect( s->getEmulation(), SIGNAL(clearStatusBar()),
           this, SLOT(clearStatusBar()) );
  connect( s->getEmulation(), SIGNAL(ImageSizeChanged(int,int)),
           this, SLOT(notifySize(int,int)));

  s->setFontNo(QMIN(fno, TOPFONT));
  s->setSchemaNo(schmno);
  if (key.isEmpty())
    s->setKeymapNo(n_defaultKeytab);
  else
    s->setKeymap(key);
  s->setTitle(txt);
  s->setIconName(icon);
  s->setAddToUtmp(b_addToUtmp);
  s->setXonXoff(b_xonXoff);

  addSession(s);
  runSession(s); // activate and run
  return sessionId;
}

/*
 * Starts a new session based on URL.
 */
void Klt::newSession(const QString& sURL, const QString& title)
{
HERE;
   QStrList args;
   QString protocol, path, login, host;

   KURL url = KURL(sURL);
   if ((url.protocol() == "file") && (url.hasPath())) {
     KSimpleConfig *co = defaultSession();
     path = url.path();
     newSession(co, QString::null, QStrList(), QString::null, QString::null,
                title.isEmpty() ? path : title, path);
     return;
   }
   else if ((!url.protocol().isEmpty()) && (url.hasHost())) {
     protocol = url.protocol();
     args.append( protocol.latin1() ); /* argv[0] == command to run. */
     host = url.host();
     if (url.hasUser()) {
       login = url.user();
       args.append("-l");
       args.append(login.latin1());
     }
     args.append(host.latin1());
     newSession( NULL, protocol.latin1() /* protocol */, args /* arguments */,
                 QString::null /*term*/, QString::null /*icon*/,
 	        title.isEmpty() ? path : title /*title*/, QString::null /*cwd*/);
     return;
   }
   /*
    * We can't create a session without a protocol.
    * We should ideally popup a warning.
    */
}

void Klt::closeCurrentSession()
{
HERE;
  se->closeSession();
}

void Klt::doneChild(KltChild* child, TESession* session)
{
HERE;
  if (session)
    attachSession(session);
  detached.remove(child);
}

//FIXME: If a child dies during session swap,
//       this routine might be called before
//       session swap is completed.

void Klt::doneSession(TESession* s)
{
HERE;
	close();
	return;
}

void Klt::initMasterMode(bool state)
{
HERE;
	return;
  masterMode->setChecked(state);
  slotToggleMasterMode();
}

void Klt::slotToggleMasterMode()
{
HERE;
	return;
  bool _masterMode=masterMode->isChecked();
  se->setMasterMode( _masterMode );
  if(_masterMode)
    for (TESession *ses = sessions.first(); ses; ses = sessions.next())
      ses->setListenToKeyPress(true);
  else {
    for (TESession *ses = sessions.first(); ses; ses = sessions.next())
      ses->setListenToKeyPress(false);
    se->setListenToKeyPress(true);
  }
  notifySessionState(se,NOTIFYNORMAL);
}

void Klt::notifySessionState(TESession* session, int state)
{
HERE;
	return;
}

// --| Session support |-------------------------------------------------------

void Klt::buildSessionMenus()
{
HERE;
   m_session->clear();

   no2command.clear();
   no2tempFile.clear();
   no2filename.clear();

   cmd_serial = 0;
   cmd_first_screen = -1;

   loadSessionCommands();
   loadScreenSessions();

   m_session->insertSeparator();
   /*
   m_closeSession->plug(m_session);

   m_session->insertSeparator();
   */
   m_quit->plug(m_session);
}

static void insertItemSorted(KPopupMenu *menu, const QIconSet &iconSet, const QString &txt, int id)
{
HERE;
  const int defaultId = 1; // The id of the 'new' item.
  int index = menu->indexOf(defaultId);
  int count = menu->count();
  if (index >= 0)
  {
     index++; // Skip separator
     while(true)
     {
        index++;
        if (index >= count)
        {
           index = -1; // Insert at end
           break;
        }
        if (menu->text(menu->idAt(index)) > txt)
           break; // Insert before this item
     }
  }
  menu->insertItem(iconSet, txt, id, index);
}

void Klt::addSessionCommand(const QString &path)
{
HERE;
  KSimpleConfig* co;
  QString filename=path;
  if (path.isEmpty()) {
    co = new KSimpleConfig(locate("appdata", "klt.desktop"), true /* read only */);
    filename="klt.desktop";
  }
  else
    co = new KSimpleConfig(path,true);
  co->setDesktopGroup();
  QString typ = co->readEntry("Type");
  QString txt = co->readEntry("Name");

  // try to locate the binary
  QString exec= co->readEntry("Exec");
  if (exec.startsWith("su -c \'")) {
     exec = exec.mid(7,exec.length()-8);
  }

  exec = KRun::binaryName(exec, false);
  QString pexec = KGlobal::dirs()->findExe(exec);
  if (typ.isEmpty() || txt.isEmpty() || typ != "KltApplication"
      || ( !exec.isEmpty() && pexec.isEmpty() ) )
  {
    if (!path.isEmpty())
       delete co;
    return; // ignore

  }

  QString icon = co->readEntry("Icon", "tractterm");
  QString comment = co->readEntry("Comment");
  if (comment.isEmpty())
    comment=txt.prepend(i18n("New "));
  insertItemSorted( m_session, SmallIconSet( icon ), comment, cmd_serial );
  no2command.insert(cmd_serial,co);

  int j = filename.findRev('/');
  if (j > -1)
    filename = filename.mid(j+1);
  no2filename.insert(cmd_serial,new QString(filename));
}


void Klt::loadSessionCommands()
{
HERE;
  if (!kapp->authorize("tract_access"))
     return;
  addSessionCommand(QString::null);
  m_session->insertSeparator();

  QStringList lst = KGlobal::dirs()->findAllResources("appdata", "*.desktop", false, true);

  for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it )
    if (!(*it).endsWith("/klt.desktop"))
       addSessionCommand(*it);

}

void Klt::addScreenSession(const QString &path, const QString &socket)
{
HERE;
  KTempFile *tmpFile = new KTempFile();
  tmpFile->setAutoDelete(true);
  KSimpleConfig *co = new KSimpleConfig(tmpFile->name());
  co->setDesktopGroup();
  co->writeEntry("Name", socket);
  QString txt = i18n("Screen is a program controlling screens!", "Screen at %1").arg(socket);
  co->writeEntry("Comment", txt);
  co->writeEntry("Exec", QString::fromLatin1("SCREENDIR=%1 screen -r %2")
    .arg(path).arg(socket));
  QString icon = "tractterm"; // FIXME use another icon (malte)
  cmd_serial++;
  m_session->insertItem( SmallIconSet( icon ), txt, cmd_serial, cmd_serial - 1 );
  no2command.insert(cmd_serial,co);
  no2tempFile.insert(cmd_serial,tmpFile);
  no2filename.insert(cmd_serial,new QString(""));
}

void Klt::loadScreenSessions()
{
HERE;
  if (!kapp->authorize("tract_access"))
     return;
  QCString screenDir = getenv("SCREENDIR");
  if (screenDir.isEmpty())
    screenDir = QFile::encodeName(QDir::homeDirPath()) + "/.screen/";
  // Some distributions add a shell function called screen that sets
  // $SCREENDIR to ~/tmp. In this case the variable won't be set here.
  if (!QFile::exists(screenDir))
    screenDir = QFile::encodeName(QDir::homeDirPath()) + "/tmp/";
  QStringList sessions;
  // Can't use QDir as it doesn't support FIFOs :(
  DIR *dir = opendir(screenDir);
  if (dir)
  {
    struct dirent *entry;
    while ((entry = readdir(dir)))
    {
      QCString path = screenDir + "/" + entry->d_name;
      struct stat st;
      if (stat(path, &st) != 0)
        continue;

      int fd;
      if (S_ISFIFO(st.st_mode) && !(st.st_mode & 0111) && // xbit == attached
          (fd = open(path, O_WRONLY | O_NONBLOCK)) != -1)
      {
        ::close(fd);
        sessions.append(QFile::decodeName(entry->d_name));
      }
    }
    closedir(dir);
  }
  resetScreenSessions();
  for (QStringList::ConstIterator it = sessions.begin(); it != sessions.end(); ++it)
    addScreenSession(screenDir, *it);
}

void Klt::resetScreenSessions()
{
HERE;
  if (cmd_first_screen == -1)
    cmd_first_screen = cmd_serial + 1;
  else
  {
    for (int i = cmd_first_screen; i <= cmd_serial; ++i)
    {
      m_session->removeItem(i);
      no2command.remove(i);
      no2tempFile.remove(i);
      no2filename.remove(i);
    }
    cmd_serial = cmd_first_screen - 1;
  }
}

// --| Schema support |-------------------------------------------------------

void Klt::setSchema(int numb)
{
HERE;
  ColorSchema* s = colors->find(numb);
  if (!s)
  {
        kdWarning() << "No schema found. Using default." << endl;
        s=(ColorSchema*)colors->at(0);
  }
  if (s->numb() != numb)
  {
        kdWarning() << "No schema with number " << numb << endl;
  }

  if (s->hasSchemaFileChanged())
  {
        const_cast<ColorSchema *>(s)->rereadSchemaFile();
  }
  if (s) setSchema(s);
}

void Klt::setSchema(const QString & path)
{
HERE;
  ColorSchema* s = colors->find(path);
  if (!s)
  {
        kdWarning() << "Could not find schema named " << path << endl;
        s=(ColorSchema*)colors->at(0);
  }
  if (s->hasSchemaFileChanged())
  {
        const_cast<ColorSchema *>(s)->rereadSchemaFile();
  }
  if (s) setSchema(s);
}

void Klt::setSchema(ColorSchema* s)
{
HERE;
  if (!s) return;

//        KONSOLEDEBUG << "Checking menu items" << endl;
//  if (m_schema)
// {
//  m_schema->setItemChecked(curr_schema,false);
// m_schema->setItemChecked(s->numb(),true);
//}
//        KONSOLEDEBUG << "Remembering schema data" << endl;

  s_schema = s->relPath();
  curr_schema = s->numb();
  pmPath = s->imagePath();
  te->setColorTable(s->table()); //FIXME: set twice here to work around a bug

  if (s->useTransparency()) {
//        KONSOLEDEBUG << "Setting up transparency" << endl;
    rootxpm->setFadeEffect(s->tr_x(), QColor(s->tr_r(), s->tr_g(), s->tr_b()));
    rootxpm->start();
  } else {
//        KONSOLEDEBUG << "Stopping transparency" << endl;
    rootxpm->stop();
    pixmap_menu_activated(s->alignment());
  }

  te->setColorTable(s->table());
  if (se) se->setSchemaNo(s->numb());
}

void Klt::detachSession() {
#ifdef LLS_NOT_RESTRICT
  KRadioAction *ra = session2action.find(se);
  ra->unplug(m_view);
  session2action.remove(se);
  session2button.remove(se);
  action2session.remove(ra);
  int sessionIndex = sessions.findRef(se);
  sessions.remove(se);
  delete ra;

  disconnect( se,SIGNAL(done(TESession*)),
              this,SLOT(doneSession(TESession*)) );

  disconnect( se->getEmulation(),SIGNAL(ImageSizeChanged(int,int)), this,SLOT(notifySize(int,int)));
  disconnect( se->getEmulation(),SIGNAL(changeColumns(int)), this,SLOT(changeColumns(int)) );

  disconnect( se,SIGNAL(updateTitle()), this,SLOT(updateTitle()) );
  disconnect( se,SIGNAL(notifySessionState(TESession*,int)), this,SLOT(notifySessionState(TESession*,int)) );
  disconnect( se,SIGNAL(clearAllListenToKeyPress()), this,SLOT(clearAllListenToKeyPress()) );
  disconnect( se,SIGNAL(restoreAllListenToKeyPress()), this,SLOT(restoreAllListenToKeyPress()) );

  ColorSchema* schema = colors->find(curr_schema);
  KltChild* kltchild = new KltChild(se,te->Columns(),te->Lines(),false,
                                                b_framevis?(QFrame::WinPanel|QFrame::Sunken):QFrame::NoFrame,
                                                schema,te->font(),te->isBellMode(),te->wordCharacters(),
                                                te->blinkingCursor(),te->ctrlDrag(),te->isTerminalSizeHint(),
                                                te->lineSpacing(),te->cutToBeginningOfLine(),b_allowResize);
  detached.append(kltchild);
  kltchild->show();
  kltchild->run();

  connect( kltchild,SIGNAL(doneChild(KltChild*, TESession*)),
           this,SLOT(doneChild(KltChild*, TESession*)) );

  if (se == se_previous)
    se_previous=NULL;

  // pick a new session
  if (se_previous)
    se = se_previous;
  else
    se = sessions.at(sessionIndex ? sessionIndex - 1 : 0);
  session2action.find(se)->setChecked(true);
  QTimer::singleShot(1,this,SLOT(activateSession()));
  if (sessions.count()==1)
    m_detachSession->setEnabled(false);
#endif
}

void Klt::attachSession(TESession* session)
{
HERE;
  session->changeWidget(te);
  KRadioAction *ra = new KRadioAction(session->Title(), session->IconName(),
                                      0, this, SLOT(activateSession()), this);

  ra->setExclusiveGroup("sessions");
  ra->setChecked(true);

  action2session.insert(ra, session);
  session2action.insert(session,ra);
  sessions.append(session);
  if (sessions.count()>1)
    m_detachSession->setEnabled(true);

  connect( session,SIGNAL(done(TESession*)),
           this,SLOT(doneSession(TESession*)) );

  connect( session,SIGNAL(updateTitle()), this,SLOT(updateTitle()) );
  connect( session,SIGNAL(notifySessionState(TESession*,int)), this,SLOT(notifySessionState(TESession*,int)) );

  connect( session,SIGNAL(clearAllListenToKeyPress()), this,SLOT(clearAllListenToKeyPress()) );
  connect( session,SIGNAL(restoreAllListenToKeyPress()), this,SLOT(restoreAllListenToKeyPress()) );
  connect( session->getEmulation(),SIGNAL(ImageSizeChanged(int,int)), this,SLOT(notifySize(int,int)));
  connect( session->getEmulation(),SIGNAL(changeColumns(int)), this,SLOT(changeColumns(int)) );

  activateSession(session);
}

void Klt::initSessionTitle(const QString &_title) {
  KRadioAction *ra = session2action.find(se);

  se->setTitle(_title);
  ra->setText(_title);
  ra->setIcon( se->IconName() ); // I don't know why it is needed here
  updateTitle();
}

//////////////////////////////////////////////////////////////////////

SizeDialog::SizeDialog(const unsigned int columns,
                       const unsigned int lines,
                       QWidget *parent)
  : KDialogBase(Plain, i18n("Size Configuration"),
                Help | Default | Ok | Cancel, Ok,
                parent)
{
HERE;
  QFrame *mainFrame = plainPage();

  QHBoxLayout *hb = new QHBoxLayout(mainFrame);

  m_columns = new QSpinBox(20,1000,1,mainFrame);
  m_columns->setValue(columns);

  m_lines = new QSpinBox(4,1000,1,mainFrame);
  m_lines->setValue(lines);

  hb->addWidget(new QLabel(i18n("Number of columns:"), mainFrame));
  hb->addWidget(m_columns);
  hb->addSpacing(10);
  hb->addWidget(new QLabel(i18n("Number of lines:"), mainFrame));
  hb->addWidget(m_lines);

  setHelp("configure-size");
}

void SizeDialog::slotDefault()
{
HERE;
  m_columns->setValue(80);
  m_lines->setValue(24);
}

unsigned int SizeDialog::columns() const
{
HERE;
  return m_columns->value();
}

unsigned int SizeDialog::lines() const
{
HERE;
  return m_lines->value();
}

//////////////////////////////////////////////////////////////////////

KltFind::KltFind( QWidget *parent, const char *name, bool /*modal*/ )
  : KEdFind( parent, name, false ), m_editorDialog(0), m_editRegExp(0)
{
HERE;
  QHBox* row = new QHBox( (QWidget*)group );
  m_asRegExp = new QCheckBox( i18n("As &regular expression"), row, "asRegexp" );

  if (!KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty()) {
    m_editRegExp = new QPushButton( i18n("&Edit..."), row, "editRegExp" );
    connect( m_asRegExp, SIGNAL( toggled(bool) ), m_editRegExp, SLOT( setEnabled(bool) ) );
    connect( m_editRegExp, SIGNAL( clicked() ), this, SLOT( slotEditRegExp() ) );
    m_editRegExp->setEnabled( false );
  }
}

void KltFind::slotEditRegExp()
{
HERE;
  if ( m_editorDialog == 0 )
    m_editorDialog = KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor", QString::null, this );

  assert( m_editorDialog );

  KRegExpEditorInterface *iface = dynamic_cast<KRegExpEditorInterface *>( m_editorDialog );
  assert( iface );

  iface->setRegExp( getText() );
  bool ret = m_editorDialog->exec();
  if ( ret == QDialog::Accepted)
    setText( iface->regExp() );
}

bool KltFind::reg_exp() const
{
HERE;
  return m_asRegExp->isChecked();
}

//////////////////////////////////////////////////////////////////////

void Klt::slotBackgroundChanged(int desk)
{
HERE;
  ColorSchema* s = colors->find(curr_schema);
  if (s==0) return;

  // Only update rootxpm if window is visible on current desktop
  NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop );

  if (s->useTransparency() && info.desktop()==desk && (0 != rootxpm)) {
    //KONSOLEDEBUG << "Wallpaper changed on my desktop, " << desk << ", repainting..." << endl;
    //Check to see if we are on the current desktop. If not, delay the repaint
    //by setting wallpaperSource to 0. Next time our desktop is selected, we will
    //automatically update because we are saying "I don't have the current wallpaper"
    NETRootInfo rootInfo( qt_xdisplay(), NET::CurrentDesktop );
    rootInfo.activate();
    if( rootInfo.currentDesktop() == info.desktop() ) {
       //We are on the current desktop, go ahead and update
       //KONSOLEDEBUG << "My desktop is current, updating..." << endl;
       wallpaperSource = desk;
       rootxpm->repaint(true);
    }
    else {
       //We are not on the current desktop, mark our wallpaper source 'stale'
       //KONSOLEDEBUG << "My desktop is NOT current, delaying update..." << endl;
       wallpaperSource = 0;
    }
  }
}

void Klt::currentDesktopChanged(int desk) {
   //Get window info
   NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), NET::WMDesktop );
   bool bNeedUpdate = false;

   if( info.desktop()==NETWinInfo::OnAllDesktops ) {
      //This is a sticky window so it will always need updating
      bNeedUpdate = true;
   }
   else if( (info.desktop() == desk) && (wallpaperSource != desk) ) {
      bNeedUpdate = true;
   }
   else {
      //We are not sticky and already have the wallpaper for our desktop
      return;
   }

   //Check to see if we are transparent too
   ColorSchema* s = colors->find(curr_schema);
   if (s==0)
      return;

   //This window is transparent, update the root pixmap
   if( bNeedUpdate && s->useTransparency() ) {
      wallpaperSource = desk;
      rootxpm->repaint(true);
   }
}

///////////////////////////////////////////////////////////

void Klt::biggerFont(void) {
    assert(se);
    if (defaultFont.pixelSize() == -1)
        defaultFont.setPointSize( defaultFont.pointSize() + 1);
    else
        defaultFont.setPixelSize( defaultFont.pixelSize() + 2 );
    setFont( DEFAULTFONT );
    activateSession();
}

void Klt::smallerFont(void) {
    assert(se);
    if (defaultFont.pixelSize() == -1)
        defaultFont.setPointSize( defaultFont.pointSize() - 1);
    else
        defaultFont.setPixelSize( defaultFont.pixelSize() - 2 );
    setFont( DEFAULTFONT );
    activateSession();
}

bool Klt::processDynamic(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData)
{
HERE;
    if (b_fullScripting)
    {
      if (fun == "feedAllSessions(QString)")
      {
        QString arg0;
        QDataStream arg( data, IO_ReadOnly );
        arg >> arg0;
        feedAllSessions(arg0);
        replyType = "void";
        return true;
      }
      else if (fun == "sendAllSessions(QString)")
      {
        QString arg0;
        QDataStream arg( data, IO_ReadOnly );
        arg >> arg0;
        sendAllSessions(arg0);
        replyType = "void";
        return true;
      }
    }
    return KltIface::processDynamic(fun, data, replyType, replyData);
}

QCStringList Klt::functionsDynamic()
{
HERE;
    QCStringList funcs = KltIface::functionsDynamic();
    if (b_fullScripting)
    {
      funcs << "void feedAllSessions(QString text)";
      funcs << "void sendAllSessions(QString text)";
    }
    return funcs;
}

void Klt::enableFullScripting(bool b)
{
HERE;
    b_fullScripting = b;
    for (TESession *se = sessions.first(); se; se = sessions.next())
       se->enableFullScripting(b);
}

#include "klt.moc"
