/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmCursesStringWidget.cxx,v $
  Language:  C++
  Date:      $Date: 2012/03/29 17:21:09 $
  Version:   $Revision: 1.1.1.1 $

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "cmCursesStringWidget.h"
#include "cmCursesMainForm.h"

inline int ctrl(int z)
{
    return (z&037);
} 

cmCursesStringWidget::cmCursesStringWidget(int width, int height, 
                                           int left, int top) :
  cmCursesWidget(width, height, left, top)
{
  this->InEdit = false;
  this->Type = cmCacheManager::STRING;
  set_field_fore(this->Field,  A_NORMAL);
  set_field_back(this->Field,  A_STANDOUT);
  field_opts_off(this->Field,  O_STATIC);
}

void cmCursesStringWidget::OnTab(cmCursesMainForm*, WINDOW*)
{
  //FORM* form = fm->GetForm();
}

void cmCursesStringWidget::OnReturn(cmCursesMainForm* fm, WINDOW*)
{
  FORM* form = fm->GetForm();
  if (this->InEdit)
    {
    cmCursesForm::LogMessage("String widget leaving edit.");
    this->InEdit = false;
    fm->PrintKeys();
    delete[] this->OriginalString;
    // trick to force forms to update the field buffer
    form_driver(form, REQ_NEXT_FIELD);
    form_driver(form, REQ_PREV_FIELD);
    this->Done = true;
    }
  else
    {
    cmCursesForm::LogMessage("String widget entering edit.");
    this->InEdit = true;
    fm->PrintKeys();
    char* buf = field_buffer(this->Field, 0);
    this->OriginalString = new char[strlen(buf)+1];
    strcpy(this->OriginalString, buf);
    }
}

void cmCursesStringWidget::OnType(int& key, cmCursesMainForm* fm, WINDOW*)
{
  form_driver(fm->GetForm(), key);
}

bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm, 
                                       WINDOW* w)
{
  int x,y;

  FORM* form = fm->GetForm();
  // 10 == enter
  if (!this->InEdit && ( key != 10 && key != KEY_ENTER ) )
    {
    return false;
    }

  this->OriginalString=0;
  this->Done = false;

  char debugMessage[128];

  // <Enter> is used to change edit mode (like <Esc> in vi).
  while(!this->Done)
    {
    sprintf(debugMessage, "String widget handling input, key: %d", key);
    cmCursesForm::LogMessage(debugMessage);

    fm->PrintKeys();

    getmaxyx(stdscr, y, x);
    // If window too small, handle 'q' only
    if ( x < cmCursesMainForm::MIN_WIDTH  || 
         y < cmCursesMainForm::MIN_HEIGHT )
      {
      // quit
      if ( key == 'q' )
        {
        return false;
        }
      else
        {
        key=getch(); 
        continue;
        }
      }

    // If resize occured during edit, move out of edit mode
    if (!this->InEdit && ( key != 10 && key != KEY_ENTER ) )
      {
      return false;
      }
    // 10 == enter
    if (key == 10 || key == KEY_ENTER) 
      {
      this->OnReturn(fm, w);
      }
    else if ( key == KEY_DOWN || key == ctrl('n') ||
              key == KEY_UP || key == ctrl('p') ||
              key == KEY_NPAGE || key == ctrl('d') ||
              key == KEY_PPAGE || key == ctrl('u'))
      {
      this->InEdit = false;
      delete[] this->OriginalString;     
      // trick to force forms to update the field buffer
      form_driver(form, REQ_NEXT_FIELD);
      form_driver(form, REQ_PREV_FIELD);
      return false;
      }
    // esc
    else if (key == 27)
      {
      if (this->InEdit)
        {
        this->InEdit = false;
        fm->PrintKeys();
        this->SetString(this->OriginalString);
        delete[] this->OriginalString;
        touchwin(w); 
        wrefresh(w); 
        return true;
        }
      }
    else if ( key == 9 )
      {
      this->OnTab(fm, w);
      }
    else if ( key == KEY_LEFT || key == ctrl('b') )
      {
      form_driver(form, REQ_PREV_CHAR);
      }
    else if ( key == KEY_RIGHT || key == ctrl('f') )
      {
      form_driver(form, REQ_NEXT_CHAR);
      }
    else if ( key == ctrl('k') )
      {
      form_driver(form, REQ_CLR_EOL);
      }
    else if ( key == ctrl('a') || key == KEY_HOME )
      {
      form_driver(form, REQ_BEG_FIELD);
      }
    else if ( key == ctrl('e') || key == KEY_END )
      {
      form_driver(form, REQ_END_FIELD);
      }
    else if ( key == ctrl('d') || key == 127 || 
              key == KEY_BACKSPACE || key == KEY_DC )
      {
      if ( form->curcol > 0 )
        {
        form_driver(form, REQ_DEL_PREV);
        }
      }
    else
      {
      this->OnType(key, fm, w);
      }
    if ( !this->Done )
      {
      touchwin(w); 
      wrefresh(w); 
      
      key=getch(); 
      }
    }
  return true;
}

void cmCursesStringWidget::SetString(const char* value)
{
  this->SetValue(value);
}

const char* cmCursesStringWidget::GetString()
{
  return this->GetValue();
}

const char* cmCursesStringWidget::GetValue()
{
  return field_buffer(this->Field, 0);
}

bool cmCursesStringWidget::PrintKeys()
{
  int x,y;
  getmaxyx(stdscr, y, x);
  if ( x < cmCursesMainForm::MIN_WIDTH  || 
       y < cmCursesMainForm::MIN_HEIGHT )
    {
    return false;
    }
  if (this->InEdit)
    {
    char firstLine[512];
    // Clean the toolbar
    for(int i=0; i<512; i++)
      {
      firstLine[i] = ' ';
      }
    firstLine[511] = '\0';
    curses_move(y-4,0);
    printw(firstLine);
    curses_move(y-3,0);
    printw(firstLine);
    curses_move(y-2,0);
    printw(firstLine);
    curses_move(y-1,0);
    printw(firstLine);

    sprintf(firstLine,  "Editing option, press [enter] to leave edit.");
    curses_move(y-3,0);
    printw(firstLine);
    return true;
    }
  else
    {
    return false;
    }
}
