From: Keith F. <ven...@us...> - 2003-06-16 18:26:44
|
Update of /cvsroot/planeshift/planeshift/src/client/paws In directory sc8-pr-cvs1:/tmp/cvs-serv1925 Modified Files: chatwindow.h chatwindow.cpp Log Message: Chat window now has command history, using Up/Down arrows. Thanks to Jeremy Huddleston (eradicator) for this contribution. Index: chatwindow.h =================================================================== RCS file: /cvsroot/planeshift/planeshift/src/client/paws/chatwindow.h,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** chatwindow.h 5 May 2003 08:25:13 -0000 1.5 --- chatwindow.h 16 Jun 2003 18:26:42 -0000 1.6 *************** *** 33,36 **** --- 33,37 ---- class pawsMessageTextBox; class pawsEditTextBox; + class pawsChatHistory; /** Main Chat window for PlaneShift. *************** *** 126,129 **** --- 127,133 ---- /// The chat type csString chatType; + + /// Chat history + pawsChatHistory* chatHistory; }; *************** *** 145,148 **** --- 149,207 ---- }; + //-------------------------------------------------------------------------- + /** Class to store chat history. Implementation is a circular buffer + */ + class pawsChatHistory + { + public: + pawsChatHistory(size_t initSize = 100); + ~pawsChatHistory(); + + /// resize the buffer. This is how strings are stored. + /// returns: true on success + bool setSize(unsigned newSize); + + /// Returns the size of the buffer (how many can be stored) + unsigned getSize(); + + /// insert a string at the end of the buffer + /// also, resets the getLoc to 0. + void insert(const char *str); + + /// returns a copy of the stored string from 'n' commands back. + /// if n is invalid (ie, more than the number of stored commands or <= 0) + /// then a null pointer is returned. + const char *getCommand(int n); + + /// return the next (temporally) command from history + const char *getNext(); + + /// return the prev (temporally) command from history + const char *getPrev(); + + /// getLoc access functions + bool setGetLoc(unsigned n); + + /// getLoc access functions + unsigned getGetLoc(); + + private: + /// Array of strings to store our history + char **buffer; + + /// What is the loc to insert the NEXT command + /// The first nth one in history is at (loc - n % size) + unsigned insertLoc; + + /// Where are we now in the history viewing? This variable does NOT + /// hold the index of the next item to be viewed as that could be + /// ambiguous at 'insertLoc'. It holds the number to be passed to + /// getCommand() that would return the last-returned string. It is + /// reset to 0 upon an insert() + unsigned getLoc; + + /// Size of the buffer + unsigned size; + }; #endif Index: chatwindow.cpp =================================================================== RCS file: /cvsroot/planeshift/planeshift/src/client/paws/chatwindow.cpp,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** chatwindow.cpp 5 May 2003 08:25:13 -0000 1.7 --- chatwindow.cpp 16 Jun 2003 18:26:42 -0000 1.8 *************** *** 25,28 **** --- 25,30 ---- #include <iutil/evdefs.h> + #include <stdlib.h> + #include "iclient/psengine.h" *************** *** 52,55 **** --- 54,59 ---- #define CHAT_TYPES 4 + static const bool looseFucusOnSend = true; + ////////////////////////////////////////////////////////////////////// // Construction/Destruction *************** *** 59,63 **** : pawsWidget( manager ), psCmdBase( NULL,NULL, manager->GetObjectRegistry() ) - { SCF_CONSTRUCT_IBASE(0); --- 63,66 ---- *************** *** 66,74 **** havePlayerName = false; chatType = "/say"; } pawsChatWindow::~pawsChatWindow() { ! } --- 69,79 ---- havePlayerName = false; chatType = "/say"; + + chatHistory = new pawsChatHistory(); } pawsChatWindow::~pawsChatWindow() { ! delete chatHistory; } *************** *** 375,389 **** bool pawsChatWindow::OnKeyDown(int keyCode, int key, int modifiers ) { ! if ( keyCode == CSKEY_ENTER ) { ! SendChatLine(); } ! ! if ( isprint( (char)key ) ) ! { ! return true; ! } ! ! return parent->OnKeyDown( keyCode, key, modifiers ); } --- 380,440 ---- bool pawsChatWindow::OnKeyDown(int keyCode, int key, int modifiers ) { ! const char *cmd; ! pawsWidget *topParent; ! ! switch ( keyCode ) { ! case CSKEY_ENTER: ! { ! SendChatLine(); ! ! if(looseFucusOnSend) { ! for(topParent=this; topParent->GetParent(); topParent = topParent->GetParent()); ! windowManager->SetCurrentFocusedWidget(topParent); ! } ! ! break; ! } ! ! case CSKEY_UP: ! { ! cmd = chatHistory->getPrev(); ! ! if(cmd) ! { ! inputText->SetText(cmd); ! } ! ! break; ! } ! ! case CSKEY_DOWN: ! { ! cmd = chatHistory->getNext(); ! ! if(cmd) ! { ! inputText->SetText(cmd); ! } ! else ! { ! // We're here because we went to the next command at the end of our list. ! inputText->SetText(""); ! chatHistory->setGetLoc(0); ! } ! ! break; ! } ! ! default: { ! if ( !isprint( (char)key ) && parent) ! { ! return parent->OnKeyDown( keyCode, key, modifiers ); ! } ! break; ! } } ! ! return true; } *************** *** 391,395 **** { const char* textToSend = inputText->GetText(); - // Check to see if there is a command there. If not then default --- 442,445 ---- *************** *** 403,410 **** const char* errorMessage = cmdsource->Publish( temp ); - if ( errorMessage ) systemText->AddMessage( errorMessage ); delete[] temp; } --- 453,462 ---- const char* errorMessage = cmdsource->Publish( temp ); if ( errorMessage ) systemText->AddMessage( errorMessage ); + // Insert the command into the history + chatHistory->insert(temp); + delete[] temp; } *************** *** 414,417 **** --- 466,472 ---- if ( errorMessage ) systemText->AddMessage( errorMessage ); + + // Insert the command into the history + chatHistory->insert(textToSend); } } *************** *** 494,495 **** --- 549,707 ---- } } + + pawsChatHistory::pawsChatHistory(unsigned initSize) + { + unsigned i; + + insertLoc = getLoc = 0; + size = initSize > 0 ? initSize : 100; + buffer = (char **)calloc(size, sizeof(char *)); + } + + pawsChatHistory::~pawsChatHistory() + { + free(buffer); + } + + // resize the buffer. This is how strings are stored. + // returns: true on success + bool pawsChatHistory::setSize(unsigned newSize) + { + char **newBuffer; + unsigned newInsertLoc; + unsigned i, j; + + if(size <= 0) + { + return false; + } + + newBuffer = (char **)calloc(size, sizeof(char *)); + + if(!newBuffer) + { + return false; + } + + // Copy over data + for(i=0; insertLoc + i < size; i++) + { + if(i < newSize) + { + newBuffer[i] = buffer[insertLoc + i]; + newInsertLoc = i + 1; + } + else + { + if(buffer[insertLoc + i]) + free(buffer[insertLoc + i]); + } + } + + // And the loop around + for(j = 0; j < insertLoc; i++, j++) + { + if(i < newSize) + { + newBuffer[i] = buffer[j]; + newInsertLoc = i + 1; + } + else + { + if(buffer[j]) + free(buffer[j]); + } + } + + // Set all the new variables + if(getLoc > insertLoc) + { + getLoc = getLoc - insertLoc; + } + else + { + getLoc = getLoc - insertLoc + size; + } + + free(buffer); + buffer = newBuffer; + size = newSize; + insertLoc = newInsertLoc % size; + return true; + } + + unsigned pawsChatHistory::getSize() + { + return size; + } + + // insert a string at the end of the buffer + // returns: true on success + void pawsChatHistory::insert(const char *str) + { + // Copy over the string + delete buffer[insertLoc]; + buffer[insertLoc] = csStrNew(str); + + insertLoc = (insertLoc + 1) % size; + getLoc = 0; + } + + // returns a copy of the stored string from 'n' commands back. + // if n is invalid (ie, more than the number of stored commands) + // then a null pointer is returned. + const char *pawsChatHistory::getCommand(int n) + { + const char *retval; + int index = ((int)insertLoc - n) % (int)size; + + if(index < 0) + index += size; + + // n == 0 means "this command" according to our notation + if(n <= 0 || n > size) + { + return NULL; + } + + retval = buffer[index]; + + if(retval) + { + // This was a valid get, so update our state + getLoc = n; + } + + return retval; + } + + // return the next (temporally) command in history + const char *pawsChatHistory::getNext() + { + return getCommand(getLoc - 1); + } + + // return the prev (temporally) command from history + const char *pawsChatHistory::getPrev() + { + return getCommand(getLoc + 1); + } + + // getLoc access functions + bool pawsChatHistory::setGetLoc(unsigned n) + { + if(n <= size) + { + getLoc = n; + return true; + } + + return false; + } + + // getLoc access functions + unsigned pawsChatHistory::getGetLoc() + { + return getLoc; + } + |