diff options
author | Berk Geveci <berk.geveci@kitware.com> | 2001-11-04 23:05:21 (GMT) |
---|---|---|
committer | Berk Geveci <berk.geveci@kitware.com> | 2001-11-04 23:05:21 (GMT) |
commit | 939d614978ff6772aae619bfbc3ef89e27b69f73 (patch) | |
tree | 0b6d52df9911a29a10d25afc7650cf7a1c5ba2f1 /Source/CursesDialog | |
parent | ef74458b34dcf2d25b3948c535d59273c2307546 (diff) | |
download | CMake-939d614978ff6772aae619bfbc3ef89e27b69f73.zip CMake-939d614978ff6772aae619bfbc3ef89e27b69f73.tar.gz CMake-939d614978ff6772aae619bfbc3ef89e27b69f73.tar.bz2 |
Adding curses support.
Diffstat (limited to 'Source/CursesDialog')
22 files changed, 1136 insertions, 0 deletions
diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt new file mode 100644 index 0000000..63d958d --- /dev/null +++ b/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)
\ No newline at end of file diff --git a/Source/CursesDialog/ccurses.cxx b/Source/CursesDialog/ccurses.cxx new file mode 100644 index 0000000..21b07e3 --- /dev/null +++ b/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; + +} diff --git a/Source/CursesDialog/cmCursesBoolWidget.cxx b/Source/CursesDialog/cmCursesBoolWidget.cxx new file mode 100644 index 0000000..4057a3f --- /dev/null +++ b/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; + } +} diff --git a/Source/CursesDialog/cmCursesBoolWidget.h b/Source/CursesDialog/cmCursesBoolWidget.h new file mode 100644 index 0000000..a4dff63 --- /dev/null +++ b/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 diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx new file mode 100644 index 0000000..1391e0e --- /dev/null +++ b/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; +} diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.h b/Source/CursesDialog/cmCursesCacheEntryComposite.h new file mode 100644 index 0000000..e22f551 --- /dev/null +++ b/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 diff --git a/Source/CursesDialog/cmCursesDummyWidget.cxx b/Source/CursesDialog/cmCursesDummyWidget.cxx new file mode 100644 index 0000000..432b3e1 --- /dev/null +++ b/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; +} + diff --git a/Source/CursesDialog/cmCursesDummyWidget.h b/Source/CursesDialog/cmCursesDummyWidget.h new file mode 100644 index 0000000..ead9699 --- /dev/null +++ b/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 diff --git a/Source/CursesDialog/cmCursesFilePathWidget.cxx b/Source/CursesDialog/cmCursesFilePathWidget.cxx new file mode 100644 index 0000000..e1c7058 --- /dev/null +++ b/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; +} + diff --git a/Source/CursesDialog/cmCursesFilePathWidget.h b/Source/CursesDialog/cmCursesFilePathWidget.h new file mode 100644 index 0000000..7c8268b --- /dev/null +++ b/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 diff --git a/Source/CursesDialog/cmCursesForm.cxx b/Source/CursesDialog/cmCursesForm.cxx new file mode 100644 index 0000000..8d9c444 --- /dev/null +++ b/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; + } +} diff --git a/Source/CursesDialog/cmCursesForm.h b/Source/CursesDialog/cmCursesForm.h new file mode 100644 index 0000000..4924f2e --- /dev/null +++ b/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 diff --git a/Source/CursesDialog/cmCursesLabelWidget.cxx b/Source/CursesDialog/cmCursesLabelWidget.cxx new file mode 100644 index 0000000..6c8adcc --- /dev/null +++ b/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; +} diff --git a/Source/CursesDialog/cmCursesLabelWidget.h b/Source/CursesDialog/cmCursesLabelWidget.h new file mode 100644 index 0000000..b32eb0d --- /dev/null +++ b/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 diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx new file mode 100644 index 0000000..52d3ef3 --- /dev/null +++ b/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); + } +} diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h new file mode 100644 index 0000000..7e4a7f7 --- /dev/null +++ b/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 diff --git a/Source/CursesDialog/cmCursesPathWidget.cxx b/Source/CursesDialog/cmCursesPathWidget.cxx new file mode 100644 index 0000000..8f86272 --- /dev/null +++ b/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; +} + diff --git a/Source/CursesDialog/cmCursesPathWidget.h b/Source/CursesDialog/cmCursesPathWidget.h new file mode 100644 index 0000000..a1f9b23 --- /dev/null +++ b/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 diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx new file mode 100644 index 0000000..90ca05c --- /dev/null +++ b/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); +} diff --git a/Source/CursesDialog/cmCursesStringWidget.h b/Source/CursesDialog/cmCursesStringWidget.h new file mode 100644 index 0000000..29fb281 --- /dev/null +++ b/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 diff --git a/Source/CursesDialog/cmCursesWidget.cxx b/Source/CursesDialog/cmCursesWidget.cxx new file mode 100644 index 0000000..55c9e76 --- /dev/null +++ b/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(); +} diff --git a/Source/CursesDialog/cmCursesWidget.h b/Source/CursesDialog/cmCursesWidget.h new file mode 100644 index 0000000..3e0a8e4 --- /dev/null +++ b/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 |