/*
 *            kPPP: A front end for pppd for the KDE project
 *
 * $Id$
 *
 * Copyright (C) 1997 Bernd Johannes Wuebben
 *                    wuebben@math.cornell.edu
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <sys/types.h>
#include <kwin.h>
#include <khelpmenu.h>
#include <kiconloader.h>
#include "pppdata.h"
#include "modem.h"
#include "miniterm.h"
#include <klocale.h>
#include <kpopupmenu.h>
#include <kglobalsettings.h>
#include <kapplication.h>
#include <kmenubar.h>
#include <kstdguiitem.h>

#include <tqlayout.h>
#include <tqlabel.h>
#include <tqtimer.h>
#include <tqpopupmenu.h>


extern PPPData gpppdata;

MiniTerm::MiniTerm(TQWidget *parent, const char *name)
  : TQDialog(parent, name, true)
{
  setCaption(i18n("Kppp Mini-Terminal"));
  KWin::setIcons(winId(), kapp->icon(), kapp->miniIcon());

  m_file = new TQPopupMenu(this);
  m_file->insertItem( SmallIcon("fileclose"), i18n("&Close"), this, TQT_SLOT(cancelbutton()) );
  m_options = new TQPopupMenu(this);
  m_options->insertItem(i18n("&Reset Modem"),this,TQT_SLOT(resetModem()));
  m_help =
    new KHelpMenu(this,
		      i18n("MiniTerm - A terminal emulation for KPPP\n\n"
			   "(c) 1997 Bernd Johannes Wuebben <wuebben@kde.org>\n"
			   "(c) 1998 Harri Porten <porten@kde.org>\n"
			   "(c) 1998 Mario Weilguni <mweilguni@kde.org>\n\n"
			   "This program is published under the GNU GPL\n"
			   "(GNU General Public License)"
			   ));

  menubar = new KMenuBar(this);
  menubar->insertItem( i18n("&File"), m_file );
  menubar->insertItem( i18n("&Modem"), m_options );
  menubar->insertItem( KStdGuiItem::help().text(), m_help->menu());

  statusbar = new TQLabel(this);
  statusbar->setFrameStyle(TQFrame::Panel | TQFrame::Sunken);

  terminal = new MyTerm(this, "term");

  setupToolbar();

  TQVBoxLayout *tqlayout=new TQVBoxLayout(this);
  tqlayout->addWidget(menubar);
  tqlayout->addWidget(toolbar);
  tqlayout->addWidget(terminal);
  tqlayout->addWidget(statusbar);

  inittimer = new TQTimer(this);
  connect(inittimer,TQT_SIGNAL(timeout()),this,TQT_SLOT(init()));
  inittimer->start(500);

  resize(550,400);
}


MiniTerm::~MiniTerm() {
  delete toolbar;
  delete statusbar;
}


void MiniTerm::setupToolbar() {
  toolbar = new KToolBar( this );

  toolbar->insertButton("exit", 0,
		      TQT_SIGNAL(clicked()), TQT_TQOBJECT(this),
		      TQT_SLOT(cancelbutton()), TRUE, i18n("Close MiniTerm"));

  toolbar->insertButton("back", 0,
		      TQT_SIGNAL(clicked()), TQT_TQOBJECT(this),
		      TQT_SLOT(resetModem()), TRUE, i18n("Reset Modem"));

  toolbar->insertButton("help", 0,
		      TQT_SIGNAL(clicked()), TQT_TQOBJECT(this),
		      TQT_SLOT(help()), TRUE, i18n("Help"));

  toolbar->setBarPos( KToolBar::Top );
  toolbar->setMovingEnabled(false);
  toolbar->updateRects(true);
}


void MiniTerm::init() {
  inittimer->stop();
  statusbar->setText(i18n("Initializing Modem"));
  kapp->processEvents();

  int lock = Modem::modem->lockdevice();
  if (lock == 1) {
    statusbar->setText(i18n("Modem device is locked."));
    return;
  }

  if (lock == -1) {
    statusbar->setText(i18n("Unable to create modem lock file."));
    return;
  }

  if(Modem::modem->opentty()) {
    if(Modem::modem->hangup()) {
    // send a carriage return and then wait a bit so that the modem will
    // let us issue commands.
    if(gpppdata.modemPreInitDelay() > 0) {
      usleep(gpppdata.modemPreInitDelay() * 5000);
      Modem::modem->writeLine("");
      usleep(gpppdata.modemPreInitDelay() * 5000);
    }
    Modem::modem->writeLine(gpppdata.modemInitStr(0).local8Bit());
    usleep(gpppdata.modemInitDelay() * 10000);

      statusbar->setText(i18n("Modem Ready"));
      terminal->setFocus();

      kapp->processEvents();
      kapp->processEvents();

      Modem::modem->notify(TQT_TQOBJECT(this), TQT_SLOT(readChar(unsigned char)));
      return;
    }
  }

  // opentty() or hangup() failed
  statusbar->setText(Modem::modem->modemMessage());
  Modem::modem->unlockdevice();
}


void MiniTerm::readChar(unsigned char c) {

  switch((int)c) {
  case 8:
    terminal->backspace();
    break;
  case 10:
    terminal->mynewline();
    break;
  case 13:
    terminal->myreturn();
    break;
  case 127:
    terminal->backspace();
    break;
  default:
    terminal->insertChar(c);
  }
}


void MiniTerm::cancelbutton() {
  Modem::modem->stop();

  statusbar->setText(i18n("Hanging up..."));
  kapp->processEvents();
  KApplication::flushX();

  Modem::modem->hangup();

  Modem::modem->closetty();
  Modem::modem->unlockdevice();

  reject();
}


void MiniTerm::resetModem() {
  statusbar->setText(i18n("Resetting Modem"));
  terminal->newLine();
  kapp->processEvents();
  KApplication::flushX();

  Modem::modem->hangup();

  statusbar->setText(i18n("Modem Ready"));
}


void MiniTerm::closeEvent( TQCloseEvent *e ) {
  cancelbutton();
  e->accept();
}


void MiniTerm::help() {
  kapp->invokeHelp();
}


MyTerm::MyTerm(TQWidget *parent, const char* name)
  : TQMultiLineEdit(parent, name)
{
   setFont(KGlobalSettings::fixedFont());
}

void MyTerm::keyPressEvent(TQKeyEvent *k) {
  // ignore meta keys
  if (k->ascii() == 0)
    return;

  if(k->ascii() == 13)
    myreturn();

  Modem::modem->writeChar((unsigned char) k->ascii());
}


void MyTerm::insertChar(unsigned char c) {
  TQMultiLineEdit::insert(TQChar(c));
}


void MyTerm::newLine() {
  TQMultiLineEdit::newLine();
}


void MyTerm::del() {
  TQMultiLineEdit::del();
}


void MyTerm::backspace() {
  TQMultiLineEdit::backspace();
}


void MyTerm::myreturn() {
  int column;
  int line;

  getCursorPosition(&line,&column);
  for (int i = 0; i < column;i++)
    TQMultiLineEdit::cursorLeft();
}


void MyTerm::mynewline() {
  TQMultiLineEdit::end(FALSE);
  TQMultiLineEdit::newLine();
}

#include "miniterm.moc"