/***************************************************************************
 *   Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org>             *
 *   Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr>           *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/
#include "hexword_gui.h"

#include <tqtimer.h>

#include "common/gui/number_gui.h"
#include "common/common/misc.h"

//-----------------------------------------------------------------------------
HexValueValidator::HexValueValidator(uint nbChars, TQObject *parent)
  : TQValidator(parent, "hex_value_validator"), _nbChars(nbChars) {}

TQValidator::State HexValueValidator::validate(TQString &input, int &) const
{
  if ( input.length()==0 ) return Acceptable;
  if ( input.length()>_nbChars ) return Invalid;
  for (uint i=0; i<input.length(); i++)
    if ( !isxdigit(input[i].latin1()) && input[i]!='-' ) return Invalid;
  return Acceptable;
}

//-----------------------------------------------------------------------------
GenericHexWordEditor::GenericHexWordEditor(uint nbChars, bool hasBlankValue, TQWidget *parent)
  : KLineEdit(parent, "hex_word_editor"), _nbChars(nbChars), _hasBlankValue(hasBlankValue)
{
  setFocusPolicy(TQ_ClickFocus);
  setValidator(new HexValueValidator(nbChars, TQT_TQOBJECT(this)));
  connect(this, TQT_SIGNAL(textChanged(const TQString &)), TQT_SLOT(slotTextChanged()));
  setFrame(false);
}

void GenericHexWordEditor::slotTextChanged()
{
  if ( text().length()!=_nbChars ) return;
  if ( changeValue() ) emit moveNext();
}

bool GenericHexWordEditor::changeValue()
{
  if ( !isValid() ) return false;
  TQString s = text();
  BitValue v = blankValue();
  if ( s!=TQString(repeat("-", _nbChars)) ) {
    s = s.leftJustify(_nbChars, '0', true);
    for (uint i=0; i<_nbChars; i++)
      if ( !isxdigit(s[i].latin1()) ) s[i] = '0';
    v = normalizeWord(fromHex(s, 0));
    setText(toHex(v, _nbChars));
  }
  if ( v==word() ) return false;
  setWord(v);
  emit modified();
  return true;
}

void GenericHexWordEditor::set()
{
  blockSignals(true);
  setEnabled(isValid());
  if ( !isValid() ) clear();
  else {
    BitValue value = word();
    if ( _hasBlankValue && value==blankValue() ) setText(repeat("-", _nbChars));
    else setText(toHex(normalizeWord(value), _nbChars));
  }
  blockSignals(false);
}

bool GenericHexWordEditor::event(TQEvent *e)
{
  switch (e->type()) {
  case TQEvent::FocusOut:
    changeValue();
    break;
  case TQEvent::FocusIn:
    TQTimer::singleShot(0, this, TQT_SLOT(selectAll())); // ugly but it works
    break;
  case TQEvent::KeyPress:
    switch ( TQT_TQKEYEVENT(e)->key() ) {
      case Key_Next:
        emit moveNextPage();
        return true;
      case Key_Tab:
      case Key_Enter:
      case Key_Return:
        emit moveNext();
        return true;
      case Key_Prior:
        emit movePrevPage();
        return true;
      case Key_BackTab:
        emit movePrev();
        return true;
      case Key_Down:
        emit moveDown();
        return true;
      case Key_Up:
        emit moveUp();
        return true;
      case Key_Home:
        emit moveFirst();
        return true;
      case Key_End:
        emit moveLast();
        return true;
      case Key_Right:
        if ( cursorPosition()!=int(text().length()) ) break;
        emit moveNext();
        return true;
      case Key_Left:
        if ( cursorPosition()!=0 ) break;
        emit movePrev();
        return true;
    }
   default: break;
  }
  return TQLineEdit::event(e);
}

TQSize GenericHexWordEditor::sizeHint() const
{
  return TQSize(maxCharWidth(NumberBase::Hex, font()) * (_nbChars+1), fontMetrics().height());
}

TQSize GenericHexWordEditor::minimumSizeHint() const
{
  return TQSize(maxCharWidth(NumberBase::Hex, font()) * (_nbChars+1), fontMetrics().height());
}
