/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include "../cmCacheManager.h"
#include "../cmSystemTools.h"
#include "../cmVersion.h"
#include "../cmake.h"
#include "cmCursesMainForm.h"
#include "cmCursesStringWidget.h"
#include "cmCursesLabelWidget.h"
#include "cmCursesBoolWidget.h"
#include "cmCursesPathWidget.h"
#include "cmCursesFilePathWidget.h"
#include "cmCursesDummyWidget.h"
#include "cmCursesCacheEntryComposite.h"
#include "cmCursesLongMessageForm.h"


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

cmCursesMainForm::cmCursesMainForm(std::vector<std::string> const& args,
                                   int initWidth) :
  Args(args), InitialWidth(initWidth)
{
  this->NumberOfPages = 0;
  this->Fields = 0;
  this->Entries = 0;
  this->AdvancedMode = false;
  this->NumberOfVisibleEntries = 0;
  this->OkToGenerate = false;
  this->HelpMessage.push_back("Welcome to ccmake, curses based user interface for CMake.");
  this->HelpMessage.push_back("");
  this->HelpMessage.push_back(s_ConstHelpMessage);
  this->CMakeInstance = new cmake;
  this->CMakeInstance->SetCMakeEditCommand(
    cmSystemTools::GetCMakeCursesCommand());

  // create the arguments for the cmake object
  std::string whereCMake = cmSystemTools::GetProgramPath(this->Args[0].c_str());
  whereCMake += "/cmake";
  this->Args[0] = whereCMake;
  this->CMakeInstance->SetArgs(this->Args);
  this->SearchString = "";
  this->OldSearchString = "";
  this->SearchMode = false;
}

cmCursesMainForm::~cmCursesMainForm()
{
  if (this->Form)
    {
    unpost_form(this->Form);
    free_form(this->Form);
    this->Form = 0;
    }
  delete[] this->Fields;

  // Clean-up composites
  if (this->Entries)
    {
    std::vector<cmCursesCacheEntryComposite*>::iterator it;
    for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
      {
      delete *it;
      }
    }
  delete this->Entries;
  if (this->CMakeInstance)
    {
    delete this->CMakeInstance;
    this->CMakeInstance = 0;
    }
}

// See if a cache entry is in the list of entries in the ui.
bool cmCursesMainForm::LookForCacheEntry(const char* key)
{
  if (!key || !this->Entries)
    {
    return false;
    }

  std::vector<cmCursesCacheEntryComposite*>::iterator it;
  for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
    {
    if (!strcmp(key, (*it)->Key.c_str()))
      {
      return true;
      }
    }

  return false;
}

// Create new cmCursesCacheEntryComposite entries from the cache
void cmCursesMainForm::InitializeUI()
{
  // Create a vector of cmCursesCacheEntryComposite's
  // which contain labels, entries and new entry markers
  std::vector<cmCursesCacheEntryComposite*>* newEntries =
    new std::vector<cmCursesCacheEntryComposite*>;
  newEntries->reserve(this->CMakeInstance->GetCacheManager()->GetSize());

  // Count non-internal and non-static entries
  int count=0;
  for(cmCacheManager::CacheIterator i =
        this->CMakeInstance->GetCacheManager()->NewIterator();
      !i.IsAtEnd(); i.Next())
    {
    if ( i.GetType() != cmCacheManager::INTERNAL &&
         i.GetType() != cmCacheManager::STATIC  &&
         i.GetType() != cmCacheManager::UNINITIALIZED)
      {
      ++count;
      }
    }

  int entrywidth = this->InitialWidth - 35;

  cmCursesCacheEntryComposite* comp;
  if ( count == 0 )
    {
    // If cache is empty, display a label saying so and a
    // dummy entry widget (does not respond to input)
    comp = new cmCursesCacheEntryComposite("EMPTY CACHE", 30, 30);
    comp->Entry = new cmCursesDummyWidget(1, 1, 1, 1);
    newEntries->push_back(comp);
    }
  else
    {
    // Create the composites.

    // First add entries which are new
    for(cmCacheManager::CacheIterator i =
          this->CMakeInstance->GetCacheManager()->NewIterator();
        !i.IsAtEnd(); i.Next())
      {
      const char* key = i.GetName();
      if ( i.GetType() == cmCacheManager::INTERNAL ||
           i.GetType() == cmCacheManager::STATIC ||
           i.GetType() == cmCacheManager::UNINITIALIZED )
        {
        continue;
        }

      if (!this->LookForCacheEntry(key))
        {
        newEntries->push_back(new cmCursesCacheEntryComposite(key, i,
                                                              true, 30,
                                                              entrywidth));
        this->OkToGenerate = false;
        }
      }

    // then add entries which are old
    for(cmCacheManager::CacheIterator i =
          this->CMakeInstance->GetCacheManager()->NewIterator();
        !i.IsAtEnd(); i.Next())
      {
      const char* key = i.GetName();
      if ( i.GetType() == cmCacheManager::INTERNAL ||
           i.GetType() == cmCacheManager::STATIC ||
           i.GetType() == cmCacheManager::UNINITIALIZED )
        {
        continue;
        }

      if (this->LookForCacheEntry(key))
        {
        newEntries->push_back(new cmCursesCacheEntryComposite(key, i,
                                                              false, 30,
                                                              entrywidth));
        }
      }
    }

  // Clean old entries
  if (this->Entries)
    {
    // Have to call delete on each pointer
    std::vector<cmCursesCacheEntryComposite*>::iterator it;
    for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
      {
      delete *it;
      }
    }
  delete this->Entries;
  this->Entries = newEntries;

  // Compute fields from composites
  this->RePost();
}


void cmCursesMainForm::RePost()
{
  // Create the fields to be passed to the form.
  if (this->Form)
    {
    unpost_form(this->Form);
    free_form(this->Form);
    this->Form = 0;
    }
  delete[] this->Fields;
  if (this->AdvancedMode)
    {
    this->NumberOfVisibleEntries = this->Entries->size();
    }
  else
    {
    // If normal mode, count only non-advanced entries
    this->NumberOfVisibleEntries = 0;
    std::vector<cmCursesCacheEntryComposite*>::iterator it;
    for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
      {
      cmCacheManager::CacheIterator mit =
        this->CMakeInstance->GetCacheManager()->GetCacheIterator((*it)->GetValue());
      if (mit.IsAtEnd() ||
          (!this->AdvancedMode && mit.GetPropertyAsBool("ADVANCED")))
        {
        continue;
        }
      this->NumberOfVisibleEntries++;
      }
    }
  // there is always one even if it is the dummy one
  if(this->NumberOfVisibleEntries == 0)
    {
    this->NumberOfVisibleEntries = 1;
    }
  // Assign the fields: 3 for each entry: label, new entry marker
  // ('*' or ' ') and entry widget
  this->Fields = new FIELD*[3*this->NumberOfVisibleEntries+1];
  size_t cc;
  for ( cc = 0; cc < 3 * this->NumberOfVisibleEntries+1; cc ++ )
    {
    this->Fields[cc] = 0;
    }

  // Assign fields
  int j=0;
  std::vector<cmCursesCacheEntryComposite*>::iterator it;
  for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
    {
    cmCacheManager::CacheIterator mit =
      this->CMakeInstance->GetCacheManager()->GetCacheIterator((*it)->GetValue());
    if (mit.IsAtEnd() ||
        (!this->AdvancedMode && mit.GetPropertyAsBool("ADVANCED")))
      {
      continue;
      }
    this->Fields[3*j]    = (*it)->Label->Field;
    this->Fields[3*j+1]  = (*it)->IsNewLabel->Field;
    this->Fields[3*j+2]  = (*it)->Entry->Field;
    j++;
    }
  // if no cache entries there should still be one dummy field
  if(j == 0)
    {
    it = this->Entries->begin();
    this->Fields[0]    = (*it)->Label->Field;
    this->Fields[1]  = (*it)->IsNewLabel->Field;
    this->Fields[2]  = (*it)->Entry->Field;
    this->NumberOfVisibleEntries = 1;
    }
  // Has to be null terminated.
  this->Fields[3*this->NumberOfVisibleEntries] = 0;
}

void cmCursesMainForm::Render(int left, int top, int width, int height)
{

  if (this->Form)
    {
    FIELD* currentField = current_field(this->Form);
    cmCursesWidget* cw = reinterpret_cast<cmCursesWidget*>
      (field_userptr(currentField));
    // If in edit mode, get out of it
    if ( cw->GetType() == cmCacheManager::STRING ||
         cw->GetType() == cmCacheManager::PATH   ||
         cw->GetType() == cmCacheManager::FILEPATH )
      {
      cmCursesStringWidget* sw = static_cast<cmCursesStringWidget*>(cw);
      sw->SetInEdit(false);
      }
    // Delete the previous form
    unpost_form(this->Form);
    free_form(this->Form);
    this->Form = 0;
    }

  // Wrong window size
  if ( width < cmCursesMainForm::MIN_WIDTH  ||
       width < this->InitialWidth               ||
       height < cmCursesMainForm::MIN_HEIGHT )
    {
    return;
    }

  // Leave room for toolbar
  height -= 7;

  if (this->AdvancedMode)
    {
    this->NumberOfVisibleEntries = this->Entries->size();
    }
  else
    {
    // If normal, display only non-advanced entries
    this->NumberOfVisibleEntries = 0;
    std::vector<cmCursesCacheEntryComposite*>::iterator it;
    for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
      {
      cmCacheManager::CacheIterator mit =
        this->CMakeInstance->GetCacheManager()->GetCacheIterator((*it)->GetValue());
      if (mit.IsAtEnd() ||
          (!this->AdvancedMode && mit.GetPropertyAsBool("ADVANCED")))
        {
        continue;
        }
      this->NumberOfVisibleEntries++;
      }
    }

  // Re-adjust the fields according to their place
  this->NumberOfPages = 1;
  if (height > 0)
    {
    bool isNewPage;
    int i=0;
    std::vector<cmCursesCacheEntryComposite*>::iterator it;
    for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
      {
      cmCacheManager::CacheIterator mit =
        this->CMakeInstance->GetCacheManager()->GetCacheIterator((*it)->GetValue());
      if (mit.IsAtEnd() ||
          (!this->AdvancedMode && mit.GetPropertyAsBool("ADVANCED")))
        {
        continue;
        }
      int row = (i % height) + 1;
      int page = (i / height) + 1;
      isNewPage = ( page > 1 ) && ( row == 1 );

      if (isNewPage)
        {
        this->NumberOfPages++;
        }
      (*it)->Label->Move(left, top+row-1, isNewPage);
      (*it)->IsNewLabel->Move(left+32, top+row-1, false);
      (*it)->Entry->Move(left+33, top+row-1, false);
      (*it)->Entry->SetPage(this->NumberOfPages);
      i++;
      }
    }

  // Post the form
  this->Form = new_form(this->Fields);
  post_form(this->Form);
  // Update toolbar
  this->UpdateStatusBar();
  this->PrintKeys();

  touchwin(stdscr);
  refresh();
}

void cmCursesMainForm::PrintKeys(int process /* = 0 */)
{
  int x,y;
  getmaxyx(stdscr, y, x);
  if ( x < cmCursesMainForm::MIN_WIDTH  ||
       x < this->InitialWidth               ||
       y < cmCursesMainForm::MIN_HEIGHT )
    {
    return;
    }

  // Give the current widget (if it exists), a chance to print keys
  cmCursesWidget* cw = 0;
  if (this->Form)
    {
    FIELD* currentField = current_field(this->Form);
    cw = reinterpret_cast<cmCursesWidget*>(field_userptr(currentField));
    }

  if (cw)
    {
    cw->PrintKeys();
    }

//    {
//    }
//  else
//    {
  char firstLine[512]="";
  char secondLine[512]="";
  char thirdLine[512]="";
  if (process)
    {
    const char* clearLine =
      "                                                                    ";
    strcpy(firstLine, clearLine);
    strcpy(secondLine, clearLine);
    strcpy(thirdLine, clearLine);
    }
  else
    {
    if (this->OkToGenerate)
      {
      sprintf(firstLine,
              "Press [c] to configure       Press [g] to generate and exit");
      }
    else
      {
      sprintf(firstLine,  "Press [c] to configure                                   ");
      }
    {
      const char* toggleKeyInstruction =
        "Press [t] to toggle advanced mode (Currently %s)";
      sprintf(thirdLine,
              toggleKeyInstruction,
              this->AdvancedMode ? "On" : "Off");
    }
    sprintf(secondLine,
            "Press [h] for help           "
            "Press [q] to quit without generating");
    }

  curses_move(y-4,0);
  char fmt[512] = "Press [enter] to edit option";
  if ( process )
    {
    strcpy(fmt, "                           ");
    }
  printw(fmt);
  curses_move(y-3,0);
  printw(firstLine);
  curses_move(y-2,0);
  printw(secondLine);
  curses_move(y-1,0);
  printw(thirdLine);

  if (cw)
    {
    sprintf(firstLine, "Page %d of %d", cw->GetPage(), this->NumberOfPages);
    curses_move(0,65-static_cast<unsigned int>(strlen(firstLine))-1);
    printw(firstLine);
    }
//    }

  pos_form_cursor(this->Form);

}

// Print the key of the current entry and the CMake version
// on the status bar. Designed for a width of 80 chars.
void cmCursesMainForm::UpdateStatusBar(const char* message)
{
  int x,y;
  getmaxyx(stdscr, y, x);
  // If window size is too small, display error and return
  if ( x < cmCursesMainForm::MIN_WIDTH  ||
       x < this->InitialWidth               ||
       y < cmCursesMainForm::MIN_HEIGHT )
    {
    curses_clear();
    curses_move(0,0);
    char fmt[] = "Window is too small. A size of at least %dx%d is required.";
    printw(fmt,
           (cmCursesMainForm::MIN_WIDTH < this->InitialWidth ?
            this->InitialWidth : cmCursesMainForm::MIN_WIDTH),
           cmCursesMainForm::MIN_HEIGHT);
    touchwin(stdscr);
    wrefresh(stdscr);
    return;
    }

  // Get the key of the current entry
  FIELD* cur = current_field(this->Form);
  int findex = field_index(cur);
  cmCursesWidget* lbl = 0;
  if ( findex >= 0 )
    {
    lbl = reinterpret_cast<cmCursesWidget*>(field_userptr(this->Fields[findex-2]));
    }
  char help[128] = "";
  const char* curField = "";
  if ( lbl )
    {
    curField = lbl->GetValue();

    // Get the help string of the current entry
    // and add it to the help string
    cmCacheManager::CacheIterator it =
      this->CMakeInstance->GetCacheManager()->GetCacheIterator(curField);
    if (!it.IsAtEnd())
      {
      const char* hs = it.GetProperty("HELPSTRING");
      if ( hs )
        {
        strncpy(help, hs, 127);
        help[127] = '\0';
        }
      else
        {
        help[0] = 0;
        }
      }
    else
      {
      sprintf(help," ");
      }
    }

  // Join the key, help string and pad with spaces
  // (or truncate) as necessary
  char bar[cmCursesMainForm::MAX_WIDTH];
  size_t i, curFieldLen = strlen(curField);
  size_t helpLen = strlen(help);

  size_t width;
  if (x < cmCursesMainForm::MAX_WIDTH )
    {
    width = x;
    }
  else
    {
    width = cmCursesMainForm::MAX_WIDTH;
    }

  if ( message )
    {
    curField = message;
    curFieldLen = strlen(message);
    if ( curFieldLen < width )
      {
      strcpy(bar, curField);
      for(i=curFieldLen; i < width; ++i)
        {
        bar[i] = ' ';
        }
      }
    else
      {
      strncpy(bar, curField, width);
      }
   }
  else
    {
    if (curFieldLen >= width)
      {
      strncpy(bar, curField, width);
      }
    else
      {
      strcpy(bar, curField);
      bar[curFieldLen] = ':';
      bar[curFieldLen+1] = ' ';
      if (curFieldLen + helpLen + 2 >= width)
        {
        strncpy(bar+curFieldLen+2, help, width
                - curFieldLen - 2);
        }
      else
        {
        strcpy(bar+curFieldLen+2, help);
        for(i=curFieldLen+helpLen+2; i < width; ++i)
          {
          bar[i] = ' ';
          }
        }
      }
    }


  bar[width] = '\0';


  // Display CMake version info on the next line
  // We want to display this on the right
  char version[cmCursesMainForm::MAX_WIDTH];
  char vertmp[128];
  sprintf(vertmp,"CMake Version %s", cmVersion::GetCMakeVersion());
  size_t sideSpace = (width-strlen(vertmp));
  for(i=0; i<sideSpace; i++) { version[i] = ' '; }
  sprintf(version+sideSpace, "%s", vertmp);
  version[width] = '\0';

  // Now print both lines
  curses_move(y-5,0);
  attron(A_STANDOUT);
  char format[] = "%s";
  printw(format, bar);
  attroff(A_STANDOUT);
  curses_move(y-4,0);
  printw(version);
  pos_form_cursor(this->Form);
}

void cmCursesMainForm::UpdateProgress(const char *msg, float prog, void* vp)
{
  cmCursesMainForm* cm = static_cast<cmCursesMainForm*>(vp);
  if ( !cm )
    {
    return;
    }
  char tmp[1024];
  const char *cmsg = tmp;
  if ( prog >= 0 )
    {
    sprintf(tmp, "%s %i%%",msg,(int)(100*prog));
    }
  else
    {
    cmsg = msg;
    }
  cm->UpdateStatusBar(cmsg);
  cm->PrintKeys(1);
  curses_move(1,1);
  touchwin(stdscr);
  refresh();
}

int cmCursesMainForm::Configure(int noconfigure)
{
  int xi,yi;
  getmaxyx(stdscr, yi, xi);

  curses_move(1,1);
  this->UpdateStatusBar("Configuring, please wait...");
  this->PrintKeys(1);
  touchwin(stdscr);
  refresh();
  this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress, this);

  // always save the current gui values to disk
  this->FillCacheManagerFromUI();
  this->CMakeInstance->GetCacheManager()->SaveCache(
    this->CMakeInstance->GetHomeOutputDirectory());
  this->LoadCache(0);

  // Get rid of previous errors
  this->Errors = std::vector<std::string>();

  // run the generate process
  this->OkToGenerate = true;
  int retVal;
  if ( noconfigure )
    {
    retVal = this->CMakeInstance->DoPreConfigureChecks();
    this->OkToGenerate = false;
    if ( retVal > 0 )
      {
      retVal = 0;
      }
    }
  else
    {
    retVal = this->CMakeInstance->Configure();
    }
  this->CMakeInstance->SetProgressCallback(0, 0);

  keypad(stdscr,TRUE); /* Use key symbols as
                          KEY_DOWN*/

  if( retVal != 0 || !this->Errors.empty())
    {
    // see if there was an error
    if(cmSystemTools::GetErrorOccuredFlag())
      {
      this->OkToGenerate = false;
      }
    int xx,yy;
    getmaxyx(stdscr, yy, xx);
    cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(
      this->Errors,
      cmSystemTools::GetErrorOccuredFlag()
      ? "Errors occurred during the last pass." :
      "CMake produced the following output.");
    // reset error condition
    cmSystemTools::ResetErrorOccuredFlag();
    CurrentForm = msgs;
    msgs->Render(1,1,xx,yy);
    msgs->HandleInput();
    // If they typed the wrong source directory, we report
    // an error and exit
    if ( retVal == -2 )
      {
      return retVal;
      }
    CurrentForm = this;
    this->Render(1,1,xx,yy);
    }

  this->InitializeUI();
  this->Render(1, 1, xi, yi);

  return 0;
}

int cmCursesMainForm::Generate()
{
  int xi,yi;
  getmaxyx(stdscr, yi, xi);

  curses_move(1,1);
  this->UpdateStatusBar("Generating, please wait...");
  this->PrintKeys(1);
  touchwin(stdscr);
  refresh();
  this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress, this);

  // Get rid of previous errors
  this->Errors = std::vector<std::string>();

  // run the generate process
  int retVal = this->CMakeInstance->Generate();

  this->CMakeInstance->SetProgressCallback(0, 0);
  keypad(stdscr,TRUE); /* Use key symbols as
                          KEY_DOWN*/

  if( retVal != 0 || !this->Errors.empty())
    {
    // see if there was an error
    if(cmSystemTools::GetErrorOccuredFlag())
      {
      this->OkToGenerate = false;
      }
    // reset error condition
    cmSystemTools::ResetErrorOccuredFlag();
    int xx,yy;
    getmaxyx(stdscr, yy, xx);
    const char* title = "Messages during last pass.";
    if(cmSystemTools::GetErrorOccuredFlag())
      {
      title = "Errors occurred during the last pass.";
      }
    cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(this->Errors,
                                                                title);
    CurrentForm = msgs;
    msgs->Render(1,1,xx,yy);
    msgs->HandleInput();
    // If they typed the wrong source directory, we report
    // an error and exit
    if ( retVal == -2 )
      {
      return retVal;
      }
    CurrentForm = this;
    this->Render(1,1,xx,yy);
    }

  this->InitializeUI();
  this->Render(1, 1, xi, yi);

  return 0;
}

void cmCursesMainForm::AddError(const char* message, const char*)
{
  this->Errors.push_back(message);
}

void cmCursesMainForm::RemoveEntry(const char* value)
{
  if (!value)
    {
    return;
    }

  std::vector<cmCursesCacheEntryComposite*>::iterator it;
  for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
    {
    const char* val = (*it)->GetValue();
    if (  val && !strcmp(value, val) )
      {
      this->CMakeInstance->UnwatchUnusedCli(value);
      this->Entries->erase(it);
      break;
      }
    }
}

// copy from the list box to the cache manager
void cmCursesMainForm::FillCacheManagerFromUI()
{
  size_t size = this->Entries->size();
  for(size_t i=0; i < size; i++)
    {
    cmCacheManager::CacheIterator it =
      this->CMakeInstance->GetCacheManager()->GetCacheIterator(
        (*this->Entries)[i]->Key.c_str());
    if (!it.IsAtEnd())
      {
      std::string oldValue = it.GetValue();
      std::string newValue = (*this->Entries)[i]->Entry->GetValue();
      std::string fixedOldValue;
      std::string fixedNewValue;
      this->FixValue(it.GetType(), oldValue, fixedOldValue);
      this->FixValue(it.GetType(), newValue, fixedNewValue);

      if(!(fixedOldValue == fixedNewValue))
        {
        // The user has changed the value.  Mark it as modified.
        it.SetProperty("MODIFIED", true);
        it.SetValue(fixedNewValue.c_str());
        }
      }
    }
}

void cmCursesMainForm::FixValue(cmCacheManager::CacheEntryType type,
                                const std::string& in, std::string& out) const
{
  out = in.substr(0,in.find_last_not_of(" ")+1);
  if(type == cmCacheManager::PATH || type == cmCacheManager::FILEPATH)
    {
    cmSystemTools::ConvertToUnixSlashes(out);
    }
  if(type == cmCacheManager::BOOL)
    {
    if(cmSystemTools::IsOff(out.c_str()))
      {
      out = "OFF";
      }
    else
      {
      out = "ON";
      }
    }
}

#include <unistd.h>

void cmCursesMainForm::HandleInput()
{
  int x=0,y=0;

  if (!this->Form)
    {
    return;
    }

  FIELD* currentField;
  cmCursesWidget* currentWidget;

  char debugMessage[128];

  for(;;)
    {
    this->UpdateStatusBar();
    this->PrintKeys();
    if ( this->SearchMode )
      {
      std::string searchstr = "Search: " + this->SearchString;
      this->UpdateStatusBar( searchstr.c_str() );
      this->PrintKeys(1);
      curses_move(y-5,static_cast<unsigned int>(searchstr.size()));
      //curses_move(1,1);
      touchwin(stdscr);
      refresh();
      }
    int key = getch();

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

    currentField = current_field(this->Form);
    currentWidget = reinterpret_cast<cmCursesWidget*>(field_userptr(
      currentField));

    bool widgetHandled=false;

    if ( this->SearchMode )
      {
      if ( key == 10 || key == KEY_ENTER )
        {
        this->SearchMode = false;
        if ( this->SearchString.size() > 0 )
          {
          this->JumpToCacheEntry(this->SearchString.c_str());
          this->OldSearchString = this->SearchString;
          }
        this->SearchString = "";
        }
      /*
      else if ( key == KEY_ESCAPE )
        {
        this->SearchMode = false;
        }
      */
      else if ((key >= 'a' && key <= 'z') ||
               (key >= 'A' && key <= 'Z') ||
               (key >= '0' && key <= '9') ||
               (key == '_' ))
        {
        if ( this->SearchString.size() < static_cast<std::string::size_type>(x-10) )
          {
          this->SearchString += static_cast<char>(key);
          }
        }
      else if ( key == ctrl('h') || key == KEY_BACKSPACE || key == KEY_DC )
        {
        if ( this->SearchString.size() > 0 )
          {
          this->SearchString.resize(this->SearchString.size()-1);
          }
        }
      }
    else if (currentWidget && !this->SearchMode)
      {
      // Ask the current widget if it wants to handle input
      widgetHandled = currentWidget->HandleInput(key, this, stdscr);
      if (widgetHandled)
        {
        this->OkToGenerate = false;
        this->UpdateStatusBar();
        this->PrintKeys();
        }
      }
    if ((!currentWidget || !widgetHandled) && !this->SearchMode)
      {
      // If the current widget does not want to handle input,
      // we handle it.
      sprintf(debugMessage, "Main form handling input, key: %d", key);
      cmCursesForm::LogMessage(debugMessage);
      // quit
      if ( key == 'q' )
        {
        break;
        }
      // if not end of page, next field otherwise next page
      // each entry consists of fields: label, isnew, value
      // therefore, the label field for the prev. entry is index-5
      // and the label field for the next entry is index+1
      // (index always corresponds to the value field)
      else if ( key == KEY_DOWN || key == ctrl('n') )
        {
        FIELD* cur = current_field(this->Form);
        size_t findex = field_index(cur);
        if ( findex == 3*this->NumberOfVisibleEntries-1 )
          {
          continue;
          }
        if (new_page(this->Fields[findex+1]))
          {
          form_driver(this->Form, REQ_NEXT_PAGE);
          }
        else
          {
          form_driver(this->Form, REQ_NEXT_FIELD);
          }
        }
      // if not beginning of page, previous field, otherwise previous page
      // each entry consists of fields: label, isnew, value
      // therefore, the label field for the prev. entry is index-5
      // and the label field for the next entry is index+1
      // (index always corresponds to the value field)
      else if ( key == KEY_UP || key == ctrl('p') )
        {
        FIELD* cur = current_field(this->Form);
        int findex = field_index(cur);
        if ( findex == 2 )
          {
          continue;
          }
        if ( new_page(this->Fields[findex-2]) )
          {
          form_driver(this->Form, REQ_PREV_PAGE);
          set_current_field(this->Form, this->Fields[findex-3]);
          }
        else
          {
          form_driver(this->Form, REQ_PREV_FIELD);
          }
        }
      // pg down
      else if ( key == KEY_NPAGE || key == ctrl('d') )
        {
        form_driver(this->Form, REQ_NEXT_PAGE);
        }
      // pg up
      else if ( key == KEY_PPAGE || key == ctrl('u') )
        {
        form_driver(this->Form, REQ_PREV_PAGE);
        }
      // configure
      else if ( key == 'c' )
        {
        this->Configure();
        }
      // display help
      else if ( key == 'h' )
        {
        getmaxyx(stdscr, y, x);

        FIELD* cur = current_field(this->Form);
        int findex = field_index(cur);
        cmCursesWidget* lbl = reinterpret_cast<cmCursesWidget*>(field_userptr(
          this->Fields[findex-2]));
        const char* curField = lbl->GetValue();
        const char* helpString=0;
        cmCacheManager::CacheIterator it =
          this->CMakeInstance->GetCacheManager()->GetCacheIterator(curField);
        if (!it.IsAtEnd())
          {
          helpString = it.GetProperty("HELPSTRING");
          }
        if (helpString)
          {
          char* message = new char[strlen(curField)+strlen(helpString)
                                  +strlen("Current option is: \n Help string for this option is: \n")+10];
          sprintf(message,"Current option is: %s\nHelp string for this option is: %s\n", curField, helpString);
          this->HelpMessage[1] = message;
          delete[] message;
          }
        else
          {
          this->HelpMessage[1] = "";
          }

        cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(this->HelpMessage,
                                                                    "Help.");
        CurrentForm = msgs;
        msgs->Render(1,1,x,y);
        msgs->HandleInput();
        CurrentForm = this;
        this->Render(1,1,x,y);
        set_current_field(this->Form, cur);
        }
      // display last errors
      else if ( key == 'l' )
        {
        getmaxyx(stdscr, y, x);
        cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(this->Errors,
                                                                    "Errors occurred during the last pass.");
        CurrentForm = msgs;
        msgs->Render(1,1,x,y);
        msgs->HandleInput();
        CurrentForm = this;
        this->Render(1,1,x,y);
        }
      else if ( key == '/' )
        {
        this->SearchMode = true;
        this->UpdateStatusBar("Search");
        this->PrintKeys(1);
        touchwin(stdscr);
        refresh();
        }
      else if ( key == 'n' )
        {
        if ( this->OldSearchString.size() > 0 )
          {
          this->JumpToCacheEntry(this->OldSearchString.c_str());
          }
        }
      // switch advanced on/off
      else if ( key == 't' )
        {
        if (this->AdvancedMode)
          {
          this->AdvancedMode = false;
          }
        else
          {
          this->AdvancedMode = true;
          }
        getmaxyx(stdscr, y, x);
        this->RePost();
        this->Render(1, 1, x, y);
        }
      // generate and exit
      else if ( key == 'g' )
        {
        if ( this->OkToGenerate )
          {
          this->Generate();
          break;
          }
        }
      // delete cache entry
      else if ( key == 'd' && this->NumberOfVisibleEntries )
        {
        this->OkToGenerate = false;
        FIELD* cur = current_field(this->Form);
        size_t findex = field_index(cur);

        // make the next or prev. current field after deletion
        // each entry consists of fields: label, isnew, value
        // therefore, the label field for the prev. entry is findex-5
        // and the label field for the next entry is findex+1
        // (findex always corresponds to the value field)
        FIELD* nextCur;
        if ( findex == 2 )
          {
          nextCur=0;
          }
        else if ( findex == 3*this->NumberOfVisibleEntries-1 )
          {
          nextCur = this->Fields[findex-5];
          }
        else
          {
          nextCur = this->Fields[findex+1];
          }

        // Get the label widget
        // each entry consists of fields: label, isnew, value
        // therefore, the label field for the is findex-2
        // (findex always corresponds to the value field)
        cmCursesWidget* lbl
          = reinterpret_cast<cmCursesWidget*>(
            field_userptr(this->Fields[findex-2]));
        if ( lbl )
          {
          this->CMakeInstance->GetCacheManager()->RemoveCacheEntry(lbl->GetValue());

          std::string nextVal;
          if (nextCur)
            {
            nextVal = (reinterpret_cast<cmCursesWidget*>(field_userptr(nextCur))->GetValue());
            }

          getmaxyx(stdscr, y, x);
          this->RemoveEntry(lbl->GetValue());
          this->RePost();
          this->Render(1, 1, x, y);

          if (nextCur)
            {
            // make the next or prev. current field after deletion
            nextCur = 0;
            std::vector<cmCursesCacheEntryComposite*>::iterator it;
            for (it = this->Entries->begin(); it != this->Entries->end(); ++it)
              {
              if (nextVal == (*it)->Key)
                {
                nextCur = (*it)->Entry->Field;
                }
              }

            if (nextCur)
              {
              set_current_field(this->Form, nextCur);
              }
            }
          }
        }
      }

    touchwin(stdscr);
    wrefresh(stdscr);
    }
}

int cmCursesMainForm::LoadCache(const char *)

{
  int r = this->CMakeInstance->LoadCache();
  if(r < 0)
    {
    return r;
    }
  this->CMakeInstance->SetCacheArgs(this->Args);
  this->CMakeInstance->PreLoadCMakeFiles();
  return r;
}

void cmCursesMainForm::JumpToCacheEntry(const char* astr)
{
  std::string str;
  if ( astr )
    {
    str = cmSystemTools::LowerCase(astr);
    }

  if(str.empty())
    {
    return;
    }
  FIELD* cur = current_field(this->Form);
  int start_index = field_index(cur);
  int findex = start_index;
  for(;;)
    {
    if ( str.size() > 0 )
      {
      cmCursesWidget* lbl = 0;
      if ( findex >= 0 )
        {
        lbl = reinterpret_cast<cmCursesWidget*>(field_userptr(this->Fields[findex-2]));
        }
      if ( lbl )
        {
        const char* curField = lbl->GetValue();
        if ( curField )
          {
          std::string cfld = cmSystemTools::LowerCase(curField);
          if ( cfld.find(str) != cfld.npos && findex != start_index )
            {
            break;
            }
          }
        }
      }
    if ( size_t(findex) >= 3* this->NumberOfVisibleEntries-1 )
      {
      set_current_field(this->Form, this->Fields[2]);
      }
    else if (new_page(this->Fields[findex+1]))
      {
      form_driver(this->Form, REQ_NEXT_PAGE);
      }
    else
      {
      form_driver(this->Form, REQ_NEXT_FIELD);
      }
    /*
    char buffer[1024];
    sprintf(buffer, "Line: %d != %d / %d\n", findex, idx, this->NumberOfVisibleEntries);
    touchwin(stdscr);
    refresh();
    this->UpdateStatusBar( buffer );
    usleep(100000);
    */
    cur = current_field(this->Form);
    findex = field_index(cur);
    if ( findex == start_index )
      {
      break;
      }
    }
}


const char* cmCursesMainForm::s_ConstHelpMessage =
"CMake is used to configure and generate build files for software projects. "
"The basic steps for configuring a project with ccmake are as follows:\n\n"
"1. Run ccmake in the directory where you want the object and executable files to be placed (build directory). If the source directory is not the same as this build directory, you have to specify it as an argument on the command line.\n\n"
"2. When ccmake is run, it will read the configuration files and display the current build options. "
"If you have run CMake before and have updated the configuration files since then, any new entries will be displayed on top and will be marked with a *. "
"On the other hand, the first time you run ccmake, all build options will be new and will be marked as such. "
"At this point, you can modify any options (see keys below) you want to change. "
"When you are satisfied with your changes, press 'c' to have CMake process the configuration files. "
"Please note that changing some options may cause new ones to appear. These will be shown on top and will be marked with *. "
"Repeat this procedure until you are satisfied with all the options and there are no new entries. "
"At this point, a new command will appear: G)enerate and Exit. You can now hit 'g' to have CMake generate all the build files (i.e. makefiles or project files) and exit. "
"At any point during the process, you can exit ccmake with 'q'. However, this will not generate/change any build files.\n\n"
"ccmake KEYS:\n\n"
"Navigation: "
"You can use the arrow keys and page up, down to navigate the options. Alternatively, you can use the following keys: \n"
" C-n : next option\n"
" C-p : previous options\n"
" C-d : down one page\n"
" C-u : up one page\n\n"
"Editing options: "
"To change an option  press enter or return. If the current options is a boolean, this will toggle it's value. "
"Otherwise, ccmake will enter edit mode. In this mode you can edit an option using arrow keys and backspace. Alternatively, you can use the following keys:\n"
" C-b : back one character\n"
" C-f : forward one character\n"
" C-a : go to the beginning of the field\n"
" C-e : go to the end of the field\n"
" C-d : delete previous character\n"
" C-k : kill the rest of the field\n"
" Esc : Restore field (discard last changes)\n"
" Enter : Leave edit mode\n"
"You can also delete an option by pressing 'd'\n\n"
"Commands:\n"
" q : quit ccmake without generating build files\n"
" h : help, shows this screen\n"
" c : process the configuration files with the current options\n"
" g : generate build files and exit, only available when there are no "
"new options and no errors have been detected during last configuration.\n"
" l : shows last errors\n"
" t : toggles advanced mode. In normal mode, only the most important options are shown. In advanced mode, all options are shown. We recommend using normal mode unless you are an expert.\n"
" / : search for a variable name.\n";
