Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/util/shell.cc @ 5103

Last change on this file since 5103 was 5103, checked in by bensch, 19 years ago

orxonox/trunk: better algorithm to find the ClassName.
Now this is done via the ClassList

File size: 13.9 KB
RevLine 
[4744]1/*
[1853]2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
[1855]10
11   ### File Specific:
[5068]12   main-programmer: Benjamin Grauer
[1855]13   co-programmer: ...
[1853]14*/
15
[3955]16//#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_
[1853]17
[5068]18#include "shell.h"
[1853]19
[5072]20#include "text_engine.h"
21#include "list.h"
[5093]22#include "graphics_engine.h"
23#include "event_handler.h"
[5072]24
[5100]25#include "load_param.h"
[5103]26#include "class_list.h"
[5093]27#include "debug.h"
[5075]28#include <stdarg.h>
29#include <stdio.h>
30
[1856]31using namespace std;
[1853]32
[1856]33
[3245]34/**
[4838]35 * standard constructor
[5068]36 */
37Shell::Shell ()
[3365]38{
[5072]39  this->setClassID(CL_SHELL, "Shell");
40  this->setName("Shell");
41
42  this->buffer = new tList<char>;
43
[5080]44  this->textSize = 10;
45
[5074]46  //this->bufferSize = 0;
[5080]47  this->bufferText = NULL;
[5072]48  this->setBufferSize(100);
[5083]49  this->setBufferDisplaySize(10);
[5095]50  this->setAbsCoor2D(3, GraphicsEngine::getInstance()->getResolutionY());
51  this->delayed = 0;
[5097]52  this->setRepeatDelay(.3, .05);
[5095]53  this->pressedKey = SDLK_FIRST;
[5074]54
[5080]55  this->inputLineText = TextEngine::getInstance()->createText("fonts/earth.ttf", 10, TEXT_DYNAMIC, 255, 0, 0);
[5095]56  this->inputLineText->setAlignment(TEXT_ALIGN_LEFT);
[5080]57  this->inputLineText->setText(NULL);
[5093]58  this->inputLine = new char[1];
59  this->inputLine[0] = '\0';
[5095]60  this->inputLineText->setParent2D(this);
[5093]61
[5103]62  this->completionList = NULL;
[5093]63
64  EventHandler* evh = EventHandler::getInstance();
[5096]65  evh->subscribe(this, ES_ALL, SDLK_BACKQUOTE);
[5095]66  for (int i = 1; i < SDLK_F15; i++)
67    evh->subscribe(this, ES_SHELL, i);
[5068]68}
[4320]69
[5068]70Shell* Shell::singletonRef = NULL;
[1853]71
[3245]72/**
[4838]73 * standard deconstructor
[5068]74 */
75Shell::~Shell ()
[3543]76{
[5099]77  // delete the displayable Buffers
[5080]78  for (int i = 0; i < this->bufferDisplaySize; i++)
79    delete this->bufferText[i];
[5079]80  delete this->bufferText;
[5093]81
[5099]82  // delete the inputLine
[5080]83  delete this->inputLineText;
[5093]84  delete this->inputLine;
[5079]85
[5099]86  // delete all the Chars in the Buffers
87  tIterator<char>* charIterator = this->buffer->getIterator();
88  char* charElem = charIterator->nextElement();
89  while (charElem != NULL)
90  {
91    delete charElem;
92    charElem = charIterator->nextElement();
93  }
94  delete charIterator;
95
[5103]96//  if (this->completionList != NULL)
97    //delete this->completionList;
98
[5068]99  Shell::singletonRef = NULL;
[3543]100}
[5068]101
[5074]102/**
103 * sets The count of Lines to display in the buffer.
104 * @param bufferDisplaySize the count of lines to display in the Shell-Buffer.
105 */
[5072]106void Shell::setBufferDisplaySize(unsigned int bufferDisplaySize)
107{
[5080]108  if (this->bufferText != NULL)
[5072]109  {
[5080]110    for (unsigned int i = 0; i < this->bufferDisplaySize; i++)
111      delete this->bufferText[i];
112    delete this->bufferText;
[5072]113  }
[5080]114
115  this->bufferText = new Text*[bufferDisplaySize];
116  for (unsigned int i = 0; i < bufferDisplaySize; i++)
[5072]117  {
[5080]118    this->bufferText[i] = TextEngine::getInstance()->createText("fonts/earth.ttf", this->textSize, TEXT_DYNAMIC, 255, 0, 0);
119    this->bufferText[i]->setAlignment(TEXT_ALIGN_LEFT);
[5095]120    this->bufferText[i]->setRelCoor2D(5, 12+12*i);
[5080]121    this->bufferText[i]->setText(NULL);
[5089]122    this->bufferText[i]->setParent2D(this);
[5072]123  }
[5080]124
125
126  this->bufferDisplaySize = bufferDisplaySize;
[5072]127}
[5068]128
129/**
130 * deletes all the Buffers
131 */
132void Shell::flushBuffers()
133{
[5072]134  // remove all chars from the BufferTexts.
[5080]135  if (this->bufferText)
136    for (int i; i < this->bufferDisplaySize; i++)
137    {
138      this->bufferText[i]->setText(NULL);
139    }
[5068]140
[5072]141
142  // delete all the Chars in the Buffers
143  tIterator<char>* charIterator = this->buffer->getIterator();
144  char* charElem = charIterator->nextElement();
145
146  while (charElem != NULL)
147  {
148    delete charElem;
149
150    charElem = charIterator->nextElement();
151  }
152  delete charIterator;
[5068]153}
154
155/**
156 * adds a new Line to the List of Buffers
157 * @param line the Line as in the first argument in printf
158 * @param args the arguments as a va_list
[5072]159 *
160 * @todo optimize
[5068]161 */
[5075]162bool Shell::addBufferLineStatic(const char* line, ...)
[5068]163{
[5075]164  va_list arguments;
165  va_start(arguments, line);
[5072]166
[5092]167#if DEBUG < 3
[5075]168  if (Shell::singletonRef == NULL)
[5089]169#endif
170
171  vprintf(line, arguments);
[5092]172#if DEBUG < 3
[5075]173  else
[5092]174#else
175  if (Shell::singletonRef != NULL)
[5089]176#endif
[5075]177    Shell::singletonRef->addBufferLine(line, arguments);
178  return true;
179}
[5080]180int curr = 0;
[5072]181
[5080]182/**
183 * add a Line to the List of Buffers
184 * @param line
185 * @param arguments
186 *
187 * This function Adds one line to the buffer.
188 * and displays the line as the First Line of the display-buffer
189 */
[5075]190void Shell::addBufferLine(const char* line, va_list arguments)
191{
[5078]192   vsprintf(this->bufferArray, line, arguments);
[5072]193
[5078]194   char* newLine = new char[strlen(this->bufferArray)+1];
195   strcpy(newLine, this->bufferArray);
[5073]196
[5080]197   this->buffer->add(newLine);
[5075]198
[5080]199   if (this->buffer->getSize() > this->bufferSize)
200   {
201     delete this->buffer->firstElement();
202     this->buffer->remove(this->buffer->firstElement());
203   }
204
205   if (likely(bufferText != NULL))
206   {
207     Text* moveText = this->bufferText[this->bufferDisplaySize-1];
208     for (int i = this->bufferDisplaySize-1; i > 0; i--)
209     {
210       this->bufferText[i] = this->bufferText[i-1];
211     }
212     this->bufferText[0] = moveText;
213   }
214   this->bufferText[0]->setText(newLine);
215   // this->bufferText->
216//  this->inputLineText->setText(newLine);
[5068]217}
218
219/**
220 * moves the buffer around lineCount lines upwards (negative values move down)
221 * @param lineCount the Count of lines to move upwards
[5072]222 *
223 * @todo
[5068]224 */
225void Shell::moveBuffer(int lineCount)
226{
227}
228
229/**
230 * @param lineNumber the n-th line from the bottom
231 * @returns the Buffer at Line lineNumber
232 */
233const char* Shell::getBufferLine(unsigned int lineNumber)
234{
[5072]235  tIterator<char>* charIterator = this->buffer->getIterator();
236  char* charElem = charIterator->nextElement();
237
238  int i = 1;
239  while (charElem != NULL)
240  {
241    if (i++ < lineNumber)
242    {
243      delete charIterator;
244      return charElem;
245    }
246
247    charElem = charIterator->nextElement();
248  }
249  delete charIterator;
[5068]250}
251
252
253/**
254 * deletes the InputLine
255 */
256void Shell::flushInputLine()
257{
[5072]258  if (likely(this->inputLine != NULL))
259  {
260    delete [] this->inputLine;
261  }
262  this->inputLine = new char[1];
263  *this->inputLine = '\0';
264
[5068]265}
266
267/**
268 * adds one character to the inputLine
269 * @param character the character to add to the inputLine
270 */
271void Shell::addCharacter(char character)
272{
[5072]273  char* addCharLine = new char[strlen(inputLine)+2];
274
275  sprintf(addCharLine, "%s%c", this->inputLine, character);
276  delete this->inputLine;
277  this->inputLine = addCharLine;
[5093]278  this->inputLineText->setText(inputLine);
[5068]279}
280
281/**
282 * adds multiple Characters to thr inputLine
283 * @param characters a '\0' terminated char-array to add to the InputLine
284 */
285void Shell::addCharacters(const char* characters)
286{
[5072]287  char* addCharLine = new char[strlen(inputLine)+strlen(characters)+1];
288
289  sprintf(addCharLine, "%s%s", this->inputLine, characters);
290  delete this->inputLine;
291  this->inputLine = addCharLine;
[5093]292  this->inputLineText->setText(inputLine);
[5068]293}
294
295/**
296 * removes characterCount characters from the InputLine
297 * @param characterCount the count of Characters to remove from the input Line
298 */
299void Shell::removeCharacters(unsigned int characterCount)
300{
[5093]301  if (strlen(this->inputLine) == 0)
302    return;
303
[5072]304  if (characterCount > strlen(this->inputLine))
305    characterCount = strlen(this->inputLine);
306
307  char* removeCharLine = new char[strlen(inputLine)-characterCount+1];
308
309  strncpy(removeCharLine, this->inputLine, strlen(inputLine)-characterCount);
[5093]310  removeCharLine[strlen(inputLine)-characterCount] = '\0';
[5072]311  delete this->inputLine;
312  this->inputLine = removeCharLine;
[5093]313  this->inputLineText->setText(inputLine);
[5068]314}
315
[5096]316/**
317 * executes the command stored in the inputLine
318 * @return true if the command was commited successfully, false otherwise
319 */
320bool Shell::executeCommand()
321{
322
323  this->addBufferLineStatic("Execute Command: %s\n", this->inputLine);
324  delete this->inputLine;
325  this->inputLine = new char[1];
326  this->inputLine[0]='\0';
327  this->inputLineText->setText(this->inputLine);
328  return false;
329}
330
[5097]331/**
332 * sets the Repeate-delay and rate
333 * @param repeatDelay the Delay it takes, to repeate a key
334 * @param repeatRate the rate to repeate a pressed key
335 */
336void Shell::setRepeatDelay(float repeatDelay, float repeatRate)
337{
338  this->repeatDelay = repeatDelay;
339  this->repeatRate = repeatRate;
340
341}
342
343
[5093]344#include "key_names.h"
[5069]345/**
346 * listens for some event
347 * @param event the Event happened
348 */
349void Shell::process(const Event &event)
350{
[5093]351  if (event.bPressed)
352  {
353    PRINTF(4)("Shell received command %s\n", SDLKToKeyname(event.type));
354    if (event.type == SDLK_BACKQUOTE)
355    {
356      if (EventHandler::getInstance()->getState() == ES_GAME)
[5094]357      {
[5093]358        EventHandler::getInstance()->setState(ES_SHELL);
[5094]359        this->setRelCoorSoft2D(0, GraphicsEngine::getInstance()->getResolutionY()-150, 1, 5);
360      }
361
[5093]362      else
[5094]363      {
[5093]364        EventHandler::getInstance()->setState(ES_GAME);
[5094]365        this->setRelCoorSoft2D(0, GraphicsEngine::getInstance()->getResolutionY()+10, 1, 5);
366      }
[5093]367    }
368    else if (event.type == SDLK_TAB)
369      this->autoComplete();
370    else if (event.type == SDLK_BACKSPACE)
[5095]371    {
372      this->delayed = this->repeatDelay;
373      this->pressedKey = SDLK_BACKSPACE;
[5093]374      this->removeCharacters(1);
[5095]375    }
[5096]376    else if (event.type == SDLK_RETURN)
377      this->executeCommand();
[5097]378    else if (likely(event.type < 127))
[5095]379    {
380      this->delayed = this->repeatDelay;
381      this->pressedKey = event.type;
[5093]382      this->addCharacter(event.type);
[5095]383    }
[5093]384  }
[5095]385  else // if(!event.bPressed)
386  {
387    if (this->pressedKey == event.type)
[5102]388    {
[5095]389      this->pressedKey = SDLK_FIRST;
[5102]390      this->delayed = 0.0;
391    }
[5095]392  }
[5069]393}
394
[5068]395/**
396 * ticks the Shell for dt Seconds
397 * @param dt the elapsed time since the last tick();
398 */
[5095]399void Shell::tick(float dt)
400{
401  if (this->delayed > 0.0)
402    this->delayed -= dt;
403  else if (this->pressedKey != SDLK_FIRST )
404  {
[5097]405    this->delayed = this->repeatRate;
[5095]406    if (this->pressedKey == SDLK_BACKSPACE)
407      this->removeCharacters(1);
408    else if (pressedKey < 127)
409      this->addCharacter(this->pressedKey);
410  }
411}
[5068]412
413/**
414 * displays the Shell
415 */
416void Shell::draw() const
417{
[5099]418  glPushMatrix();
419  // transform for alignment.
420  // setting the Blending effects
421
422  glColor4f(0.0f, 0.0f, 0.8f, .4);
423  glEnable(GL_BLEND);
424  glDisable(GL_TEXTURE_2D);
425  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
426
427//  glBindTexture(GL_TEXTURE_2D, this->texture);
428  glBegin(GL_QUADS);
429
430//  glTexCoord2f(this->texCoord.minU, this->texCoord.minV);
431  glVertex2f(this->getAbsCoor2D().x,   this->getAbsCoor2D().);
432
433//  glTexCoord2f(this->texCoord.maxU, this->texCoord.minV);
434  glVertex2f(this->getAbsCoor2D().x + 800, this->getAbsCoor2D().);
435
436//  glTexCoord2f(this->texCoord.maxU, this->texCoord.maxV);
437  glVertex2f(this->getAbsCoor2D().x + 800, this->getAbsCoor2D().y + 150);
438
439//  glTexCoord2f(this->texCoord.minU, this->texCoord.maxV);
440  glVertex2f(this->getAbsCoor2D().x, this->getAbsCoor2D().y + 150);
441
442  glEnd();
[5068]443}
444
445
446/**
447 * autocompletes the Shell's inputLine
448 * @returns true, if a result was found, false otherwise
[5100]449 *
450 * @todo implement it!!
[5068]451 */
452bool Shell::autoComplete()
453{
[5100]454  //PRINTF(3)("AutoCompletion not implemented yet\n");
455
456  char* completionLine = new char[strlen(inputLine)+1];
457  strcpy(completionLine, this->inputLine);
458
459   char* commandBegin = strrchr(completionLine, ' ');
460  if (commandBegin == NULL)
461    commandBegin = completionLine;
462  else
463  {
464    if(commandBegin >= completionLine + strlen(completionLine))
465      commandBegin = completionLine + strlen(completionLine);
466    else
467      commandBegin++;
468  }
469
[5102]470  this->classComplete(commandBegin);
471
[5103]472  delete[] completionLine;
[5102]473}
474
475/**
476 * autocompletes a className
477 * @param classBegin the Beginning of a String to autoComplete
478 * @return true on success, false otherwise
479 */
480bool Shell::classComplete(const char* classBegin)
481{
482  if (unlikely(classBegin == NULL))
483    return false;
[5103]484  const tList<const char>* classList = this->searchClassWithShort(classBegin);
[5102]485  if (classList->getSize() == 0)
486  {
[5100]487     //PRINTF(0)("no completion found for %s\n", commandBegin);
[5102]488    return false;
489  }
[5100]490
[5102]491  const char* addString = classList->firstElement();
492  unsigned int addLength = 0;
493  unsigned int inputLenght = strlen(classBegin);
[5100]494
[5102]495  if (addString != NULL)
496    addLength = strlen(addString);
497  tIterator<const char>* charIterator = classList->getIterator();
498  const char* charElem = charIterator->nextElement();
499  while (charElem != NULL)
500  {
501    PRINTF(0)("%s:: ", charElem);
502    {
503      for (unsigned int i = inputLenght; i < addLength; i++)
504        if (addString[i] != charElem[i])
505      {
506        addLength = i;
507        break;
508      }
509    }
510
511    charElem = charIterator->nextElement();
512  }
513  delete charIterator;
514
515  if (addLength >= inputLenght)
516  {
517    char* adder = new char[addLength+1];
518    strncpy(adder, addString, addLength);
519    adder[addLength] = '\0';
520    this->removeCharacters(inputLenght);
521    this->addCharacters(adder);
522//    this->addCharacters("::");
523    delete[] adder;
524  }
[5068]525}
526
[5102]527bool Shell::objectComplete(const char* objectBegin, ClassID classID)
528{
529
530}
531
532bool Shell::functionComplete(const char* functionBegin)
533{
534}
535
536
[5103]537/**
538 * searches for classes, which beginn with classNameBegin
539 * @param classNameBegin the beginning string of a Class
540 * @return a NEW char-array with ClassNames. The LIST should be deleted afterwards,
541 * !! The strings MUST NOT be deleted !!
542 */
543const tList<const char>* Shell::searchClassWithShort(const char* classNameBegin)
544{
545  unsigned int searchLength = strlen(classNameBegin);
546  if (this->completionList != NULL)
547    delete this->completionList;
548  this->completionList = new tList<const char>;
[5102]549
[5103]550//  tList<const char>* classList = ClassList::getClassList();
551
552  tIterator<const char>* iterator = ClassList::getClassList()->getIterator();
553  const char* enumString = iterator->nextElement();
554  while (enumString != NULL)
555  {
556    if (strlen(enumString)>searchLength+1 &&
557        !strncasecmp(enumString, classNameBegin, searchLength))
558    {
559      this->completionList->add(enumString);
560    }
561    enumString = iterator->nextElement();
562  }
563  delete iterator;
564
565  return this->completionList;
566}
567
568
569
[5068]570/**
571 * displays some nice output from the Shell
572 */
573void Shell::debug() const
574{
[5096]575  if (this->pressedKey != SDLK_FIRST)
576    printf("%s::%f %f\n", SDLKToKeyname(this->pressedKey), this->delayed, this->repeatDelay);
[5068]577}
Note: See TracBrowser for help on using the repository browser.