Berk Geveci 24 лет назад
Родитель
Сommit
939d614978

+ 16 - 0
Modules/FindCurses.cmake

@@ -0,0 +1,16 @@
+#
+# Find the curses include file and library
+#
+
+FIND_PATH(CURSES_INCLUDE_PATH curses.h
+/usr/local/include
+/usr/include
+)
+
+FIND_LIBRARY(CURSES_LIBRARY curses
+PATHS /usr/lib /usr/local/lib
+)
+
+FIND_LIBRARY(FORM_LIBRARY form
+PATHS /usr/lib /usr/local/lib
+)

+ 7 - 1
Source/CMakeLists.txt

@@ -1,5 +1,4 @@
 INCLUDE (${CMAKE_ROOT}/Modules/FindFLTK.cmake)
-
 IF(FLTK_LIBRARY)
   IF(FLTK_INCLUDE_PATH)
     OPTION(BUILD_FLTK_GUI "Build FLTK CMake GUI." "ON")
@@ -47,6 +46,13 @@ IF (WIN32)
   ENDIF(NOT UNIX)
 ENDIF (WIN32)
 
+IF (UNIX)
+  INCLUDE (${CMAKE_ROOT}/Modules/FindCurses.cmake)
+  IF (CURSES_LIBRARY AND FORM_LIBRARY)
+    SUBDIRS(CursesDialog)
+  ENDIF (CURSES_LIBRARY AND FORM_LIBRARY)
+IF (UNIX)
+
 SOURCE_FILES(SRCS cmUnixMakefileGenerator.cxx)
 
 

+ 18 - 0
Source/CursesDialog/CMakeLists.txt

@@ -0,0 +1,18 @@
+SOURCE_FILES( CURSES_SRCS
+              cmCursesBoolWidget
+              cmCursesCacheEntryComposite
+              cmCursesDummyWidget
+              cmCursesFilePathWidget
+              cmCursesForm
+              cmCursesLabelWidget
+              cmCursesMainForm
+              cmCursesPathWidget
+              cmCursesStringWidget
+              cmCursesWidget
+              ccurses
+            )
+
+INCLUDE_DIRECTORIES(${CURSES_INCLUDE_PATH})
+LINK_LIBRARIES(${CURSES_LIBRARY} ${FORM_LIBRARY})
+
+ADD_EXECUTABLE(ccurses CURSES_SRCS)

+ 71 - 0
Source/CursesDialog/ccurses.cxx

@@ -0,0 +1,71 @@
+#include "cmCursesMainForm.h"
+#include "cmCacheManager.h"
+#include "cmSystemTools.h"
+
+#include <curses.h>
+#include <form.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+
+static cmCursesMainForm* myform=0;
+//std::ofstream log("log.txt", std::ios::out);
+
+void onsig(int sig)
+{
+  if (myform)
+    {
+    endwin();
+    WINDOW* w= initscr(); /* Initialization */ 
+    noecho(); /* Echo off */ 
+    cbreak(); /* nl- or cr not needed */ 
+    keypad(stdscr,TRUE); /* Use key symbols as 
+			    KEY_DOWN*/ 
+    refresh();
+    int x,y;
+    getmaxyx(w, y, x);
+    myform->SetWindow(w);
+    myform->Render(1,1,x,y);
+    std::cerr << "Size change: " << x << " " << y << std::endl;
+    }
+  signal(SIGWINCH, onsig);
+}
+
+int main(int argc, char** argv)
+{
+
+  if ( argc != 2 )
+    {
+    std::cerr << "Usage: " << argv[0] << " source_directory" 
+	      << std::endl;
+    return -1;
+    }
+
+  int newCache = false;
+  if (!cmCacheManager::GetInstance()->LoadCache(cmSystemTools::GetCurrentWorkingDirectory().c_str()))
+   {
+   newCache = true;
+   }
+
+
+  WINDOW* w=initscr(); /* Initialization */ 
+  noecho(); /* Echo off */ 
+  cbreak(); /* nl- or cr not needed */ 
+  keypad(stdscr,TRUE); /* Use key symbols as 
+                          KEY_DOWN*/ 
+
+  signal(SIGWINCH, onsig);
+
+  int x,y;
+  getmaxyx(w, y, x);
+
+  myform = new cmCursesMainForm(argv[1], newCache);
+  myform->InitializeUI(w);
+  myform->Render(1, 1, x, y);
+  myform->HandleInput();
+  
+  // Need to clean-up better
+  endwin();
+  delete myform;
+  return 0;
+
+}

+ 61 - 0
Source/CursesDialog/cmCursesBoolWidget.cxx

@@ -0,0 +1,61 @@
+#include "cmCursesBoolWidget.h"
+
+cmCursesBoolWidget::cmCursesBoolWidget(int width, int height, 
+				       int left, int top) :
+  cmCursesWidget(width, height, left, top)
+{
+  m_Type = cmCacheManager::BOOL;
+  set_field_fore(m_Field,  A_NORMAL);
+  set_field_back(m_Field,  A_STANDOUT);
+  field_opts_off(m_Field,  O_STATIC);
+  this->SetValueAsBool(false);
+}
+
+bool cmCursesBoolWidget::HandleInput(int& key, FORM* form, WINDOW* w)
+{
+  // 10 == enter
+  if (key == 10)
+    {
+    if (this->GetValueAsBool())
+      {
+      this->SetValueAsBool(false);
+      }
+    else
+      {
+      this->SetValueAsBool(true);
+      }
+
+    touchwin(w); 
+    wrefresh(w); 
+    return true;
+    }
+  else
+    {
+    return false;
+    }
+  
+}
+
+void cmCursesBoolWidget::SetValueAsBool(bool value)
+{
+  if (value)
+    {
+    this->SetValue("ON");
+    }
+  else
+    { 
+    this->SetValue("OFF");
+    }
+}
+
+bool cmCursesBoolWidget::GetValueAsBool()
+{
+  if (m_Value == "ON")
+    {
+    return true;
+    }
+  else
+    { 
+    return false;
+    }
+}

+ 28 - 0
Source/CursesDialog/cmCursesBoolWidget.h

@@ -0,0 +1,28 @@
+#ifndef __cmCursesBoolWidget_h
+#define __cmCursesBoolWidget_h
+
+#include "cmCursesWidget.h"
+
+class cmCursesBoolWidget : public cmCursesWidget
+{
+public:
+  cmCursesBoolWidget(int width, int height, int left, int top);
+  
+  // Description:
+  // Handle user input. Called by the container of this widget
+  // when this widget has focus. Returns true if the input was
+  // handled.
+  virtual bool HandleInput(int& key, FORM* form, WINDOW* w);
+
+  // Description:
+  // Set/Get the value (on/off).
+  void SetValueAsBool(bool value);
+  bool GetValueAsBool();
+
+protected:
+  cmCursesBoolWidget(const cmCursesBoolWidget& from);
+  void operator=(const cmCursesBoolWidget&);
+
+};
+
+#endif // __cmCursesBoolWidget_h

+ 73 - 0
Source/CursesDialog/cmCursesCacheEntryComposite.cxx

@@ -0,0 +1,73 @@
+#include "cmCursesCacheEntryComposite.h"
+#include "cmCursesStringWidget.h"
+#include "cmCursesLabelWidget.h"
+#include "cmCursesBoolWidget.h"
+#include "cmCursesPathWidget.h"
+#include "cmCursesFilePathWidget.h"
+#include "cmCursesDummyWidget.h"
+#include "cmSystemTools.h"
+
+cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(const char* key) :
+  m_Key(key)
+{
+  m_Label = new cmCursesLabelWidget(30, 1, 1, 1, key);
+  m_IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, " ");
+  m_Entry = 0;
+}
+
+cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
+  const char* key, const cmCacheManager::CacheEntry& value, bool isNew) :
+  m_Key(key)
+{
+  m_Label = new cmCursesLabelWidget(30, 1, 1, 1, key);
+  if (isNew)
+    {
+    m_IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, "*");
+    }
+  else
+    {
+    m_IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, " ");
+    }
+
+  m_Entry = 0;
+  switch ( value.m_Type )
+    {
+    case  cmCacheManager::BOOL:
+      m_Entry = new cmCursesBoolWidget(30, 1, 1, 1);
+      if (cmSystemTools::IsOn(value.m_Value.c_str()))
+	{
+	static_cast<cmCursesBoolWidget*>(m_Entry)->SetValueAsBool(true);
+	}
+      else
+	{
+	static_cast<cmCursesBoolWidget*>(m_Entry)->SetValueAsBool(false);
+	}
+      break;
+    case cmCacheManager::PATH:
+      m_Entry = new cmCursesPathWidget(30, 1, 1, 1);
+      static_cast<cmCursesPathWidget*>(m_Entry)->SetString(
+	value.m_Value.c_str());
+      break;
+    case cmCacheManager::FILEPATH:
+      m_Entry = new cmCursesFilePathWidget(30, 1, 1, 1);
+      static_cast<cmCursesFilePathWidget*>(m_Entry)->SetString(
+	value.m_Value.c_str());
+      break;
+    case cmCacheManager::STRING:
+      m_Entry = new cmCursesStringWidget(30, 1, 1, 1);
+      static_cast<cmCursesStringWidget*>(m_Entry)->SetString(
+	value.m_Value.c_str());
+      break;
+    default:
+      // TODO : put warning message here
+      break;
+    }
+
+}
+
+cmCursesCacheEntryComposite::~cmCursesCacheEntryComposite()
+{
+  delete m_Label;
+  delete m_IsNewLabel;
+  delete m_Entry;
+}

+ 28 - 0
Source/CursesDialog/cmCursesCacheEntryComposite.h

@@ -0,0 +1,28 @@
+#ifndef __cmCursesCacheEntryComposite_h
+#define __cmCursesCacheEntryComposite_h
+
+#include "cmCursesLabelWidget.h"
+#include "cmCacheManager.h"
+
+class cmCursesCacheEntryComposite
+{
+public:
+  cmCursesCacheEntryComposite(const char* key);
+  cmCursesCacheEntryComposite(const char* key,
+			      const cmCacheManager::CacheEntry& value, 
+			      bool isNew);
+  ~cmCursesCacheEntryComposite();
+
+  friend class cmCursesMainForm;
+
+protected:
+  cmCursesCacheEntryComposite(const cmCursesCacheEntryComposite& from);
+  void operator=(const cmCursesCacheEntryComposite&);
+
+  cmCursesLabelWidget* m_Label;
+  cmCursesLabelWidget* m_IsNewLabel;
+  cmCursesWidget* m_Entry;
+  std::string m_Key;
+};
+
+#endif // __cmCursesCacheEntryComposite_h

+ 15 - 0
Source/CursesDialog/cmCursesDummyWidget.cxx

@@ -0,0 +1,15 @@
+#include "cmCursesDummyWidget.h"
+
+cmCursesDummyWidget::cmCursesDummyWidget(int width, int height, 
+					   int left, int top) :
+  cmCursesWidget(width, height, left, top)
+{
+  m_Type = cmCacheManager::INTERNAL;
+}
+
+
+bool cmCursesDummyWidget::HandleInput(int& key, FORM* form, WINDOW* w)
+{
+  return false;
+}
+

+ 23 - 0
Source/CursesDialog/cmCursesDummyWidget.h

@@ -0,0 +1,23 @@
+#ifndef __cmCursesDummyWidget_h
+#define __cmCursesDummyWidget_h
+
+#include "cmCursesWidget.h"
+
+class cmCursesDummyWidget : public cmCursesWidget
+{
+public:
+  cmCursesDummyWidget(int width, int height, int left, int top);
+  
+  // Description:
+  // Handle user input. Called by the container of this widget
+  // when this widget has focus. Returns true if the input was
+  // handled.
+  virtual bool HandleInput(int& key, FORM* form, WINDOW* w);
+
+protected:
+  cmCursesDummyWidget(const cmCursesDummyWidget& from);
+  void operator=(const cmCursesDummyWidget&);
+
+};
+
+#endif // __cmCursesDummyWidget_h

+ 9 - 0
Source/CursesDialog/cmCursesFilePathWidget.cxx

@@ -0,0 +1,9 @@
+#include "cmCursesFilePathWidget.h"
+
+cmCursesFilePathWidget::cmCursesFilePathWidget(int width, int height, 
+					   int left, int top) :
+  cmCursesStringWidget(width, height, left, top)
+{
+  m_Type = cmCacheManager::FILEPATH;
+}
+

+ 17 - 0
Source/CursesDialog/cmCursesFilePathWidget.h

@@ -0,0 +1,17 @@
+#ifndef __cmCursesFilePathWidget_h
+#define __cmCursesFilePathWidget_h
+
+#include "cmCursesStringWidget.h"
+
+class cmCursesFilePathWidget : public cmCursesStringWidget
+{
+public:
+  cmCursesFilePathWidget(int width, int height, int left, int top);
+
+protected:
+  cmCursesFilePathWidget(const cmCursesFilePathWidget& from);
+  void operator=(const cmCursesFilePathWidget&);
+
+};
+
+#endif // __cmCursesFilePathWidget_h

+ 16 - 0
Source/CursesDialog/cmCursesForm.cxx

@@ -0,0 +1,16 @@
+#include "cmCursesForm.h"
+
+cmCursesForm::cmCursesForm()
+{
+  m_Form = 0;
+}
+
+cmCursesForm::~cmCursesForm()
+{
+  if (m_Form)
+    {
+    unpost_form(m_Form);
+    free_form(m_Form);
+    m_Form = 0;
+    }
+}

+ 28 - 0
Source/CursesDialog/cmCursesForm.h

@@ -0,0 +1,28 @@
+#ifndef __cmCursesForm_h
+#define __cmCursesForm_h
+
+#include <curses.h>
+#include <form.h>
+
+class cmCursesForm
+{
+public:
+  cmCursesForm();
+  virtual ~cmCursesForm();
+  
+  // Description:
+  // Handle user input.
+  virtual void HandleInput() = 0;
+
+  // Description:
+  // Display form.
+  virtual void Render(int left, int top, int width, int height) = 0;
+
+protected:
+  cmCursesForm(const cmCursesForm& from);
+  void operator=(const cmCursesForm&);
+
+  FORM* m_Form;
+};
+
+#endif // __cmCursesForm_h

+ 21 - 0
Source/CursesDialog/cmCursesLabelWidget.cxx

@@ -0,0 +1,21 @@
+#include "cmCursesLabelWidget.h"
+
+cmCursesLabelWidget::cmCursesLabelWidget(int width, int height, 
+					 int left, int top,
+					 const std::string& name) :
+  cmCursesWidget(width, height, left, top)
+{
+  field_opts_off(m_Field,  O_EDIT);
+  field_opts_off(m_Field,  O_ACTIVE);
+  this->SetValue(name.c_str());
+}
+
+cmCursesLabelWidget::~cmCursesLabelWidget()
+{
+}
+
+bool cmCursesLabelWidget::HandleInput(int& key, FORM* form, WINDOW* w)
+{
+  // Static text. No input is handled here.
+  return false;
+}

+ 28 - 0
Source/CursesDialog/cmCursesLabelWidget.h

@@ -0,0 +1,28 @@
+#ifndef __cmCursesLabelWidget_h
+#define __cmCursesLabelWidget_h
+
+#include <iostream>
+#include <curses.h>
+#include <form.h>
+#include "cmCursesWidget.h"
+
+
+class cmCursesLabelWidget : public cmCursesWidget
+{
+public:
+  cmCursesLabelWidget(int width, int height, int left, int top,
+		      const std::string& name);
+  virtual ~cmCursesLabelWidget();
+  
+  // Description:
+  // Handle user input. Called by the container of this widget
+  // when this widget has focus. Returns true if the input was
+  // handled
+  virtual bool HandleInput(int& key, FORM* form, WINDOW* w);
+
+protected:
+  cmCursesLabelWidget(const cmCursesLabelWidget& from);
+  void operator=(const cmCursesLabelWidget&);
+};
+
+#endif // __cmCursesLabelWidget_h

+ 381 - 0
Source/CursesDialog/cmCursesMainForm.cxx

@@ -0,0 +1,381 @@
+#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 "cmCacheManager.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+cmCursesMainForm::cmCursesMainForm(const char* whereSource, 
+				   bool newCache) :
+  m_WhereSource(whereSource)
+{
+  m_Fields = 0;
+  m_Window = 0;
+  m_Height = 0;
+  m_Entries = 0;
+}
+
+cmCursesMainForm::~cmCursesMainForm()
+{
+  if (m_Form)
+    {
+    unpost_form(m_Form);
+    free_form(m_Form);
+    m_Form = 0;
+    }
+  delete[] m_Fields;
+
+  // Clean-up composites
+  if (m_Entries)
+    {
+    std::vector<cmCursesCacheEntryComposite*>::iterator it;
+    for (it = m_Entries->begin(); it != m_Entries->end(); ++it)
+      {
+      delete *it;
+      }
+    }
+  delete m_Entries;
+}
+
+bool cmCursesMainForm::LookForCacheEntry(const char* key)
+{
+  if (!key || !m_Entries)
+    {
+    return false;
+    }
+
+  std::vector<cmCursesCacheEntryComposite*>::iterator it;
+  for (it = m_Entries->begin(); it != m_Entries->end(); ++it)
+    {
+    if (!strcmp(key, (*it)->m_Key.c_str()))
+      {
+      return true;
+      }
+    }
+  
+  return false;
+}
+
+void cmCursesMainForm::InitializeUI(WINDOW* w)
+{
+  m_Window = w;
+
+  // Get the cache entries.
+  const cmCacheManager::CacheEntryMap &cache = 
+    cmCacheManager::GetInstance()->GetCacheMap();
+
+  std::vector<cmCursesCacheEntryComposite*>* newEntries =
+    new std::vector<cmCursesCacheEntryComposite*>;
+  newEntries->reserve(cache.size());
+
+  // Count non-internal and non-static entries
+  int count=0;
+  for(cmCacheManager::CacheEntryMap::const_iterator i = cache.begin();
+      i != cache.end(); ++i)
+    {
+    const cmCacheManager::CacheEntry& value = i->second;
+    if ( value.m_Type != cmCacheManager::INTERNAL &&
+	 value.m_Type != cmCacheManager::STATIC )
+      {
+      ++count;
+      }
+    }
+
+  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");
+    comp->m_Entry = new cmCursesDummyWidget(1, 1, 1, 1);
+    newEntries->push_back(comp);
+    }
+  else
+    {
+    // Create the composites.
+
+    // First add entries which are new
+    for(cmCacheManager::CacheEntryMap::const_iterator i = cache.begin();
+	i != cache.end(); ++i)
+      {
+      const char* key = i->first.c_str();
+      const cmCacheManager::CacheEntry& value = i->second;
+      if ( value.m_Type == cmCacheManager::INTERNAL || 
+	   value.m_Type == cmCacheManager::STATIC )
+	{
+	continue;
+	}
+
+      if (!this->LookForCacheEntry(key))
+	{
+	newEntries->push_back(new cmCursesCacheEntryComposite(key, value,
+							      true));
+	}
+      }
+
+    // then add entries which are old
+    for(cmCacheManager::CacheEntryMap::const_iterator i = cache.begin();
+	i != cache.end(); ++i)
+      {
+      const char* key = i->first.c_str();
+      const cmCacheManager::CacheEntry& value = i->second;
+      if ( value.m_Type == cmCacheManager::INTERNAL || 
+	   value.m_Type == cmCacheManager::STATIC )
+	{
+	continue;
+	}
+
+      if (this->LookForCacheEntry(key))
+	{
+	newEntries->push_back(new cmCursesCacheEntryComposite(key, value,
+							      false));
+	}
+      }
+    }
+  
+  if (m_Entries)
+    {
+    std::vector<cmCursesCacheEntryComposite*>::iterator it;
+    for (it = m_Entries->begin(); it != m_Entries->end(); ++it)
+      {
+      delete *it;
+      }
+    }
+  delete m_Entries;
+  m_Entries = newEntries;
+  
+  // Create the fields to be passed to the form.
+  if (m_Form)
+    {
+    unpost_form(m_Form);
+    free_form(m_Form);
+    m_Form = 0;
+    }
+  delete[] m_Fields;
+  int size = m_Entries->size();
+  m_Fields = new FIELD*[3*size+1];
+  for(int j=0; j < size; j++)
+    {
+    m_Fields[3*j]    = (*m_Entries)[j]->m_Label->m_Field;
+    m_Fields[3*j+1]  = (*m_Entries)[j]->m_IsNewLabel->m_Field;
+    m_Fields[3*j+2]  = (*m_Entries)[j]->m_Entry->m_Field;
+    }
+  // Has to be null terminated.
+  m_Fields[3*size] = 0;
+}
+
+void cmCursesMainForm::Render(int left, int top, int width, int height)
+{
+
+  if (m_Form)
+    {
+    FIELD* currentField = current_field(m_Form);
+    cmCursesWidget* cw = reinterpret_cast<cmCursesWidget*>
+      (field_userptr(currentField));
+    if ( cw->GetType() == cmCacheManager::STRING ||
+	 cw->GetType() == cmCacheManager::PATH   ||
+	 cw->GetType() == cmCacheManager::FILEPATH )
+      {
+      cmCursesStringWidget* sw = static_cast<cmCursesStringWidget*>(cw);
+      sw->SetInEdit(false);
+      }
+    unpost_form(m_Form);
+    free_form(m_Form);
+    m_Form = 0;
+    }
+  if ( width < 22 || height < 2 )
+    {
+    return;
+    }
+
+  std::cerr << "Rendering again." << std::endl;
+  
+  height -= 3;
+  m_Height = height;
+
+  int size = m_Entries->size();
+  bool isNewPage;
+  for(int i=0; i < size; i++)
+    {
+    int row = (i % height) + 1;  
+    int page = (i / height) + 1;
+    isNewPage = ( page > 1 ) && ( row == 1 );
+
+    (*m_Entries)[i]->m_Label->Move(left, top+row-1, isNewPage);
+    (*m_Entries)[i]->m_IsNewLabel->Move(left+32, top+row-1, false);
+    (*m_Entries)[i]->m_Entry->Move(left+33, top+row-1, false);
+    }
+  m_Form = new_form(m_Fields);
+  post_form(m_Form);
+  this->UpdateCurrentEntry();
+  touchwin(m_Window); 
+  refresh();
+}
+
+void cmCursesMainForm::UpdateCurrentEntry()
+{
+  FIELD* cur = current_field(m_Form);
+  int index = field_index(cur);
+  char* text = field_buffer(m_Fields[index-2], 0);
+
+  int x,y;
+  getmaxyx(m_Window, y, x);
+  move(y-1,0);
+  printw(text);
+
+  char version[128];
+  sprintf(version,"CMake Version %d.%d", cmMakefile::GetMajorVersion(),
+	  cmMakefile::GetMinorVersion());
+  int len = strlen(version);
+  move(y-1, x-len);
+  printw(version);
+
+  pos_form_cursor(m_Form);
+}
+
+void cmCursesMainForm::RunCMake(bool generateMakefiles)
+{
+
+  int x,y;
+  getmaxyx(m_Window, y, x);
+  
+  endwin();
+  // always save the current gui values to disk
+  this->FillCacheManagerFromUI();
+  cmCacheManager::GetInstance()->SaveCache(cmSystemTools::GetCurrentWorkingDirectory().c_str());
+
+  // create a cmake object
+  cmake make;
+  // create the arguments for the cmake object
+  std::vector<std::string> args;
+  args.push_back("cmake");
+  std::string arg;
+  arg = m_WhereSource;
+  args.push_back(arg);
+  // run the generate process
+  if(make.Generate(args, generateMakefiles) != 0)
+    {
+    // TODO : error message here
+    cmSystemTools::ResetErrorOccuredFlag();
+    }
+
+  m_Window = initscr(); /* Initialization */ 
+  noecho(); /* Echo off */ 
+  cbreak(); /* nl- or cr not needed */ 
+  keypad(m_Window,TRUE); /* Use key symbols as 
+			  KEY_DOWN*/ 
+  
+  this->InitializeUI(m_Window);
+  this->Render(1, 1, x, y);
+  
+}
+
+// copy from the list box to the cache manager
+void cmCursesMainForm::FillCacheManagerFromUI()
+{ 
+
+  cmCacheManager::GetInstance()->GetCacheMap();
+  int size = m_Entries->size();
+  for(int i=0; i < size; i++)
+    {
+    cmCacheManager::CacheEntry *entry = 
+      cmCacheManager::GetInstance()->GetCacheEntry(
+	(*m_Entries)[i]->m_Key.c_str());
+    if (entry)
+      {
+      entry->m_Value = (*m_Entries)[i]->m_Entry->GetValue();
+      }
+    }
+}
+
+void cmCursesMainForm::HandleInput()
+{
+  if (!m_Form)
+    {
+    return;
+    }
+
+  FIELD* currentField;
+  cmCursesWidget* currentWidget;
+  while(1)
+    {
+    this->UpdateCurrentEntry();
+    int key = getch();
+
+    currentField = current_field(m_Form);
+    currentWidget = reinterpret_cast<cmCursesWidget*>(field_userptr(
+      currentField));
+
+    if (!currentWidget || !currentWidget->HandleInput(key, m_Form, m_Window))
+      {
+      if ( key == 'q' )
+	{
+	break;
+	}
+      else if ( key == KEY_DOWN )
+	{
+	int x,y;
+	getmaxyx(m_Window, y, x);
+	FIELD* cur = current_field(m_Form);
+	int index = field_index(cur);
+	if ( index == 3*m_Entries->size()-1 )
+	  {
+	  continue;
+	  }
+	if ( (index < 3*m_Entries->size()-1) && new_page(m_Fields[index+1]))
+	  {
+	  form_driver(m_Form, REQ_NEXT_PAGE);
+	  }
+	else
+	  {
+	  form_driver(m_Form, REQ_NEXT_FIELD);
+	  }
+	}
+      else if ( key == KEY_UP )
+	{
+	int x,y;
+	getmaxyx(m_Window, y, x);
+	FIELD* cur = current_field(m_Form);
+	int index = field_index(cur);
+	if ( index == 2 )
+	  {
+	  continue;
+	  }
+	if ( new_page(m_Fields[index-2]) )
+	  {
+	  form_driver(m_Form, REQ_PREV_PAGE);
+	  set_current_field(m_Form, m_Fields[index-3]);
+	  }
+	else
+	  {
+	  form_driver(m_Form, REQ_PREV_FIELD);
+	  }
+	}
+      else if ( key == KEY_NPAGE )
+	{
+	form_driver(m_Form, REQ_NEXT_PAGE);
+	}
+      else if ( key == KEY_PPAGE )
+	{
+	form_driver(m_Form, REQ_PREV_PAGE);
+	}
+      else if ( key == 'c' )
+	{
+	this->RunCMake(false);
+	}
+      else if ( key == 'o' )
+	{
+	this->RunCMake(true);
+	break;
+	}
+      }
+
+    touchwin(m_Window); 
+    wrefresh(m_Window); 
+    }
+}

+ 55 - 0
Source/CursesDialog/cmCursesMainForm.h

@@ -0,0 +1,55 @@
+#ifndef __cmCursesMainForm_h
+#define __cmCursesMainForm_h
+
+#include <iostream>
+#include <curses.h>
+#include <form.h>
+#include "cmCursesForm.h"
+
+class cmCursesCacheEntryComposite;
+
+class cmCursesMainForm : public cmCursesForm
+{
+public:
+  cmCursesMainForm(const char* whereSource, bool newCache);
+  virtual ~cmCursesMainForm();
+  
+  // Description:
+  // Set the widgets which represent the cache entries.
+  void InitializeUI(WINDOW* w);
+  
+  // Description:
+  // Handle user input.
+  virtual void HandleInput();
+
+  // Description:
+  // Display form. Use a window of size width x height, starting
+  // at top, left.
+  virtual void Render(int left, int top, int width, int height);
+
+  // Description:
+  // Change the window containing the form.
+  void SetWindow(WINDOW* w)
+    { m_Window = w; }
+
+  // Description:
+  // Returns true if an entry with the given key is in the
+  // list of current composites.
+  bool LookForCacheEntry(const char* key);
+
+protected:
+  cmCursesMainForm(const cmCursesMainForm& from);
+  void operator=(const cmCursesMainForm&);
+
+  void UpdateCurrentEntry();
+  void RunCMake(bool generateMakefiles);
+  void FillCacheManagerFromUI();
+
+  std::vector<cmCursesCacheEntryComposite*>* m_Entries;
+  FIELD** m_Fields;
+  WINDOW* m_Window;
+  std::string m_WhereSource;
+  int m_Height;
+};
+
+#endif // __cmCursesMainForm_h

+ 9 - 0
Source/CursesDialog/cmCursesPathWidget.cxx

@@ -0,0 +1,9 @@
+#include "cmCursesPathWidget.h"
+
+cmCursesPathWidget::cmCursesPathWidget(int width, int height, 
+					   int left, int top) :
+  cmCursesStringWidget(width, height, left, top)
+{
+  m_Type = cmCacheManager::PATH;
+}
+

+ 17 - 0
Source/CursesDialog/cmCursesPathWidget.h

@@ -0,0 +1,17 @@
+#ifndef __cmCursesPathWidget_h
+#define __cmCursesPathWidget_h
+
+#include "cmCursesStringWidget.h"
+
+class cmCursesPathWidget : public cmCursesStringWidget
+{
+public:
+  cmCursesPathWidget(int width, int height, int left, int top);
+
+protected:
+  cmCursesPathWidget(const cmCursesPathWidget& from);
+  void operator=(const cmCursesPathWidget&);
+
+};
+
+#endif // __cmCursesPathWidget_h

+ 106 - 0
Source/CursesDialog/cmCursesStringWidget.cxx

@@ -0,0 +1,106 @@
+#include "cmCursesStringWidget.h"
+inline int ctrl(int z)
+{
+    return (z&037);
+} 
+
+cmCursesStringWidget::cmCursesStringWidget(int width, int height, 
+					   int left, int top) :
+  cmCursesWidget(width, height, left, top)
+{
+  m_InEdit = false;
+  m_Type = cmCacheManager::STRING;
+  set_field_fore(m_Field,  A_NORMAL);
+  set_field_back(m_Field,  A_STANDOUT);
+  field_opts_off(m_Field,  O_STATIC);
+}
+
+
+bool cmCursesStringWidget::HandleInput(int& key, FORM* form, WINDOW* w)
+{
+  // 10 == enter
+  if (!m_InEdit && ( key != 10 ) )
+    {
+    return false;
+    }
+
+  char* originalStr=0;
+
+  // <Enter> is used to change edit mode (like <Esc> in vi).
+  while(1) 
+    {
+    if (!m_InEdit && ( key != 10 ) )
+      {
+      return false;
+      }
+    // 10 == enter
+    if (key == 10) 
+      {
+      if (m_InEdit)
+	{
+	m_InEdit = false;
+	delete[] originalStr;	
+	// trick to force forms to update the field buffer
+	form_driver(form, REQ_NEXT_FIELD);
+	form_driver(form, REQ_PREV_FIELD);
+	return true;
+	}
+      else
+	{
+	m_InEdit = true;
+	char* buf = field_buffer(m_Field, 0);
+	originalStr = new char[strlen(buf)+1];
+	strcpy(originalStr, buf);
+	}
+      }
+    else if (key == 27)
+      {
+      if (m_InEdit)
+	{
+	m_InEdit = false;
+	this->SetString(originalStr);
+	delete[] originalStr;
+	touchwin(w); 
+	wrefresh(w); 
+	return true;
+	}
+      }
+    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('d') || key == 127 )
+      {
+      form_driver(form, REQ_DEL_PREV);
+      }
+    else
+      {
+      form_driver(form, key);
+      }
+
+    touchwin(w); 
+    wrefresh(w); 
+
+    key=getch(); 
+    }
+}
+
+void cmCursesStringWidget::SetString(const char* value)
+{
+  this->SetValue(value);
+}
+
+const char* cmCursesStringWidget::GetString()
+{
+  return this->GetValue();
+}
+
+const char* cmCursesStringWidget::GetValue()
+{
+  std::cout << field_buffer(m_Field, 0) << std::endl;
+  return field_buffer(m_Field, 0);
+}

+ 39 - 0
Source/CursesDialog/cmCursesStringWidget.h

@@ -0,0 +1,39 @@
+#ifndef __cmCursesStringWidget_h
+#define __cmCursesStringWidget_h
+
+#include "cmCursesWidget.h"
+
+class cmCursesStringWidget : public cmCursesWidget
+{
+public:
+  cmCursesStringWidget(int width, int height, int left, int top);
+  
+  // Description:
+  // Handle user input. Called by the container of this widget
+  // when this widget has focus. Returns true if the input was
+  // handled.
+  virtual bool HandleInput(int& key, FORM* form, WINDOW* w);
+
+  // Description:
+  // Set/Get the string.
+  void SetString(const char* value);
+  const char* GetString();
+  virtual const char* GetValue();
+
+  // Description:
+  // Set/Get InEdit flag. Can be used to tell the widget to leave
+  // edit mode (in case of a resize for example).
+  void SetInEdit(bool inedit)
+    { m_InEdit = inedit; }
+  bool GetInEdit()
+    { return m_InEdit; }
+
+protected:
+  cmCursesStringWidget(const cmCursesStringWidget& from);
+  void operator=(const cmCursesStringWidget&);
+
+  // true if the widget is in edit mode
+  bool m_InEdit;
+};
+
+#endif // __cmCursesStringWidget_h

+ 46 - 0
Source/CursesDialog/cmCursesWidget.cxx

@@ -0,0 +1,46 @@
+#include "cmCursesWidget.h"
+
+cmCursesWidget::cmCursesWidget(int width, int height, int left, int top)
+{
+  m_Field = new_field(height, width, top, left, 0, 0);
+  set_field_userptr(m_Field, reinterpret_cast<char*>(this));
+  field_opts_off(m_Field,  O_AUTOSKIP);
+}
+
+cmCursesWidget::~cmCursesWidget()
+{
+  if (m_Field)
+    {
+    free_field(m_Field);
+    m_Field = 0;
+    }
+}
+
+void cmCursesWidget::Move(int x, int y, bool isNewPage)
+{
+  if (!m_Field)
+    {
+    return;
+    }
+
+  move_field(m_Field, y, x);
+  if (isNewPage)
+    {
+    set_new_page(m_Field, TRUE);
+    }
+  else
+    {
+    set_new_page(m_Field, FALSE);
+    }
+}
+
+void cmCursesWidget::SetValue(const char* value)
+{
+  m_Value = value;
+  set_field_buffer(m_Field, 0, value);
+}
+
+const char* cmCursesWidget::GetValue()
+{
+  return m_Value.c_str();
+}

+ 47 - 0
Source/CursesDialog/cmCursesWidget.h

@@ -0,0 +1,47 @@
+#ifndef __cmCursesWidget_h
+#define __cmCursesWidget_h
+
+#include <curses.h>
+#include <form.h>
+#include "cmCacheManager.h"
+
+class cmCursesWidget
+{
+public:
+  cmCursesWidget(int width, int height, int left, int top);
+  virtual ~cmCursesWidget();
+  
+  // Description:
+  // Handle user input. Called by the container of this widget
+  // when this widget has focus. Returns true if the input was
+  // handled
+  virtual bool HandleInput(int& key, FORM* form, WINDOW* w) = 0;
+
+  // Description:
+  // Change the position of the widget. Set isNewPage to true
+  // if this widget marks the beginning of a new page.
+  virtual void Move(int x, int y, bool isNewPage);
+
+  // Description:
+  // Set/Get the value (setting the value also changes the contents
+  // of the field buffer).
+  virtual void SetValue(const char* value);
+  virtual const char* GetValue();
+
+  // Description:
+  // Get the type of the widget (STRING, PATH etc...)
+  cmCacheManager::CacheEntryType GetType()
+    { return m_Type; }
+
+  friend class cmCursesMainForm;
+
+protected:
+  cmCursesWidget(const cmCursesWidget& from);
+  void operator=(const cmCursesWidget&);
+
+  cmCacheManager::CacheEntryType m_Type;
+  std::string m_Value;
+  FIELD* m_Field;
+};
+
+#endif // __cmCursesWidget_h