| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- #include "../cmCacheManager.h"
- #include "../cmSystemTools.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"
- const int cmCursesMainForm::MIN_WIDTH = 65;
- const int cmCursesMainForm::MIN_HEIGHT = 6;
- const int cmCursesMainForm::IDEAL_WIDTH = 80;
- const int cmCursesMainForm::MAX_WIDTH = 512;
- inline int ctrl(int z)
- {
- return (z&037);
- }
- 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 < cmCursesMainForm::MIN_WIDTH ||
- height < cmCursesMainForm::MIN_HEIGHT )
- {
- return;
- }
- height -= 5;
- 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->UpdateStatusBar();
- this->PrintKeys();
- touchwin(m_Window);
- refresh();
- }
- void cmCursesMainForm::PrintKeys()
- {
- int x,y;
- getmaxyx(m_Window, y, x);
- if ( x < cmCursesMainForm::MIN_WIDTH ||
- y < cmCursesMainForm::MIN_HEIGHT )
- {
- return;
- }
- char firstLine[512], secondLine[512];
- sprintf(firstLine, "C)onfigure G)enerate and Exit");
- sprintf(secondLine, "Q)uit H)elp");
- move(y-2,0);
- printw(firstLine);
- move(y-1,0);
- printw(secondLine);
- pos_form_cursor(m_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()
- {
- int x,y;
- getmaxyx(m_Window, y, x);
- if ( x < cmCursesMainForm::MIN_WIDTH ||
- y < cmCursesMainForm::MIN_HEIGHT )
- {
- move(0,0);
- printw("Window is too small. A size of at least %dx%d is required.",
- cmCursesMainForm::MIN_WIDTH, cmCursesMainForm::MIN_HEIGHT);
- touchwin(m_Window);
- wrefresh(m_Window);
- return;
- }
- FIELD* cur = current_field(m_Form);
- int index = field_index(cur);
- char* curField = field_buffer(m_Fields[index-2], 0);
- char version[128];
- sprintf(version,"(CMake Version %d.%d)", cmMakefile::GetMajorVersion(),
- cmMakefile::GetMinorVersion());
- char bar[cmCursesMainForm::MAX_WIDTH];
- int i, curFieldLen = strlen(curField);
- int versionLen = strlen(version);
- int leftLen = cmCursesMainForm::IDEAL_WIDTH - versionLen;
- if (curFieldLen >= leftLen)
- {
- strncpy(bar, curField, leftLen);
- }
- else
- {
- strcpy(bar, curField);
- for(i=curFieldLen; i < leftLen; ++i) { bar[i] = ' '; }
- }
- strcpy(bar+leftLen, version);
- if ( x < cmCursesMainForm::MAX_WIDTH )
- {
- if (x > cmCursesMainForm::IDEAL_WIDTH )
- {
- for(i=cmCursesMainForm::IDEAL_WIDTH; i < x; i++)
- {
- bar[i] = ' ';
- }
- }
- bar[x] = '\0';
- }
- else
- {
- for(i=cmCursesMainForm::IDEAL_WIDTH;
- i < cmCursesMainForm::MAX_WIDTH-1; i++)
- {
- bar[i] = ' ';
- }
- bar[cmCursesMainForm::MAX_WIDTH-1] = '\0';
- }
- move(y-3,0);
- attron(A_STANDOUT);
- printw(bar);
- attroff(A_STANDOUT);
- 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");
- if (m_WhereSource != "")
- {
- 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()
- {
- std::string tmpString;
-
- 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)
- {
- tmpString = (*m_Entries)[i]->m_Entry->GetValue();
- // Remove trailing spaces
- entry->m_Value = tmpString.substr(0,tmpString.find_last_not_of(" ")+1);
- }
- }
- }
- void cmCursesMainForm::HandleInput()
- {
- if (!m_Form)
- {
- return;
- }
- FIELD* currentField;
- cmCursesWidget* currentWidget;
- while(1)
- {
- this->UpdateStatusBar();
- this->PrintKeys();
- int key = getch();
- currentField = current_field(m_Form);
- currentWidget = reinterpret_cast<cmCursesWidget*>(field_userptr(
- currentField));
- if (!currentWidget || !currentWidget->HandleInput(key, m_Form, m_Window))
- {
- // quit
- if ( key == 'q' )
- {
- break;
- }
- // if not end of page, next field otherwise next page
- else if ( key == KEY_DOWN || key == ctrl('n') )
- {
- 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);
- }
- }
- // if not beginning of page, previous field, otherwise previous page
- else if ( key == KEY_UP || key == ctrl('p') )
- {
- 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);
- }
- }
- // pg down
- else if ( key == KEY_NPAGE || key == ctrl('d') )
- {
- form_driver(m_Form, REQ_NEXT_PAGE);
- }
- // pg up
- else if ( key == KEY_PPAGE || key == ctrl('u') )
- {
- form_driver(m_Form, REQ_PREV_PAGE);
- }
- // configure
- else if ( key == 'c' )
- {
- this->RunCMake(false);
- }
- // generate and exit
- else if ( key == 'g' )
- {
- this->RunCMake(true);
- break;
- }
- // delete cache entry
- else if ( key == 'd' )
- {
- FIELD* cur = current_field(m_Form);
- int index = field_index(cur);
- // make the next or prev. current field after deletion
- FIELD* nextCur;
- if ( index == 2 )
- {
- }
- else if ( index == 3*m_Entries->size()-1 )
- {
- nextCur = m_Fields[index-5];
- }
- else
- {
- nextCur = m_Fields[index+1];
- }
- // Get the label widget
- cmCursesWidget* lbl = reinterpret_cast<cmCursesWidget*>(field_userptr(
- m_Fields[index-2]));
- cmCacheManager::GetInstance()->RemoveCacheEntry(lbl->GetValue());
- std::string nextVal (reinterpret_cast<cmCursesWidget*>(field_userptr(nextCur))->GetValue());
- int x,y;
- getmaxyx(m_Window, y, x);
- this->InitializeUI(m_Window);
- this->Render(1, 1, x, y);
- // make the next or prev. current field after deletion
- nextCur = 0;
- std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = m_Entries->begin(); it != m_Entries->end(); ++it)
- {
- if (nextVal == (*it)->m_Key)
- {
- nextCur = (*it)->m_Entry->m_Field;
- }
- }
- if (nextCur)
- {
- set_current_field(m_Form, nextCur);
- }
- }
- }
- touchwin(m_Window);
- wrefresh(m_Window);
- }
- }
|