Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5112 was 5111, checked in by bensch, 20 years ago

orxonox/trunk: reverted the last steps, because they created a huge pack of seg-faults

File size: 11.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"
[5111]22#include "array.h"
[5093]23#include "graphics_engine.h"
24#include "event_handler.h"
[5072]25
[5100]26#include "load_param.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
[5111]44  this->textSize = 10;
[5080]45
[5074]46  //this->bufferSize = 0;
[5080]47  this->bufferText = NULL;
[5072]48  this->setBufferSize(100);
[5083]49  this->setBufferDisplaySize(10);
[5111]50  this->setAbsCoor2D(3, GraphicsEngine::getInstance()->getResolutionY());
[5095]51  this->delayed = 0;
[5097]52  this->setRepeatDelay(.3, .05);
[5095]53  this->pressedKey = SDLK_FIRST;
[5074]54
[5111]55  this->inputLineText = TextEngine::getInstance()->createText("fonts/earth.ttf", 10, TEXT_DYNAMIC, 255, 0, 0);
56  this->inputLineText->setAlignment(TEXT_ALIGN_LEFT);
57  this->inputLineText->setText(NULL);
[5093]58  this->inputLine = new char[1];
59  this->inputLine[0] = '\0';
[5111]60  this->inputLineText->setParent2D(this);
[5093]61
62
63  EventHandler* evh = EventHandler::getInstance();
[5096]64  evh->subscribe(this, ES_ALL, SDLK_BACKQUOTE);
[5095]65  for (int i = 1; i < SDLK_F15; i++)
66    evh->subscribe(this, ES_SHELL, i);
[5068]67}
[4320]68
[5068]69Shell* Shell::singletonRef = NULL;
[1853]70
[3245]71/**
[4838]72 * standard deconstructor
[5068]73 */
74Shell::~Shell ()
[3543]75{
[5099]76  // delete the displayable Buffers
[5080]77  for (int i = 0; i < this->bufferDisplaySize; i++)
78    delete this->bufferText[i];
[5111]79  delete this->bufferText;
[5093]80
[5099]81  // delete the inputLine
[5080]82  delete this->inputLineText;
[5093]83  delete this->inputLine;
[5079]84
[5099]85  // delete all the Chars in the Buffers
86  tIterator<char>* charIterator = this->buffer->getIterator();
[5111]87  char* charElem = charIterator->nextElement();
[5099]88  while (charElem != NULL)
89  {
90    delete charElem;
91    charElem = charIterator->nextElement();
92  }
93  delete charIterator;
94
[5068]95  Shell::singletonRef = NULL;
[3543]96}
[5068]97
[5074]98/**
99 * sets The count of Lines to display in the buffer.
100 * @param bufferDisplaySize the count of lines to display in the Shell-Buffer.
101 */
[5072]102void Shell::setBufferDisplaySize(unsigned int bufferDisplaySize)
103{
[5080]104  if (this->bufferText != NULL)
[5072]105  {
[5080]106    for (unsigned int i = 0; i < this->bufferDisplaySize; i++)
107      delete this->bufferText[i];
[5111]108    delete this->bufferText;
[5072]109  }
[5080]110
111  this->bufferText = new Text*[bufferDisplaySize];
112  for (unsigned int i = 0; i < bufferDisplaySize; i++)
[5072]113  {
[5111]114    this->bufferText[i] = TextEngine::getInstance()->createText("fonts/earth.ttf", this->textSize, TEXT_DYNAMIC, 255, 0, 0);
[5080]115    this->bufferText[i]->setAlignment(TEXT_ALIGN_LEFT);
[5111]116    this->bufferText[i]->setRelCoor2D(5, 12+12*i);
[5080]117    this->bufferText[i]->setText(NULL);
[5089]118    this->bufferText[i]->setParent2D(this);
[5072]119  }
[5111]120
121
[5106]122  this->bufferDisplaySize = bufferDisplaySize;
[5072]123}
[5068]124
125/**
126 * deletes all the Buffers
127 */
128void Shell::flushBuffers()
129{
[5072]130  // remove all chars from the BufferTexts.
[5080]131  if (this->bufferText)
132    for (int i; i < this->bufferDisplaySize; i++)
133    {
134      this->bufferText[i]->setText(NULL);
135    }
[5068]136
[5072]137
138  // delete all the Chars in the Buffers
139  tIterator<char>* charIterator = this->buffer->getIterator();
[5111]140  char* charElem = charIterator->nextElement();
[5072]141
142  while (charElem != NULL)
143  {
144    delete charElem;
145
146    charElem = charIterator->nextElement();
147  }
148  delete charIterator;
[5068]149}
150
151/**
152 * adds a new Line to the List of Buffers
153 * @param line the Line as in the first argument in printf
154 * @param args the arguments as a va_list
[5111]155 *
156 * @todo optimize
[5068]157 */
[5075]158bool Shell::addBufferLineStatic(const char* line, ...)
[5068]159{
[5075]160  va_list arguments;
161  va_start(arguments, line);
[5072]162
[5092]163#if DEBUG < 3
[5075]164  if (Shell::singletonRef == NULL)
[5089]165#endif
166
167  vprintf(line, arguments);
[5092]168#if DEBUG < 3
[5075]169  else
[5092]170#else
171  if (Shell::singletonRef != NULL)
[5089]172#endif
[5075]173    Shell::singletonRef->addBufferLine(line, arguments);
174  return true;
175}
[5111]176int curr = 0;
[5072]177
[5080]178/**
179 * add a Line to the List of Buffers
180 * @param line
181 * @param arguments
182 *
183 * This function Adds one line to the buffer.
184 * and displays the line as the First Line of the display-buffer
185 */
[5075]186void Shell::addBufferLine(const char* line, va_list arguments)
187{
[5078]188   vsprintf(this->bufferArray, line, arguments);
[5072]189
[5078]190   char* newLine = new char[strlen(this->bufferArray)+1];
191   strcpy(newLine, this->bufferArray);
[5073]192
[5080]193   this->buffer->add(newLine);
[5075]194
[5080]195   if (this->buffer->getSize() > this->bufferSize)
196   {
197     delete this->buffer->firstElement();
198     this->buffer->remove(this->buffer->firstElement());
199   }
200
[5111]201   if (likely(bufferText != NULL))
[5080]202   {
[5111]203     Text* moveText = this->bufferText[this->bufferDisplaySize-1];
204     for (int i = this->bufferDisplaySize-1; i > 0; i--)
[5080]205     {
[5111]206       this->bufferText[i] = this->bufferText[i-1];
[5080]207     }
[5111]208     this->bufferText[0] = moveText;
[5080]209   }
[5111]210   this->bufferText[0]->setText(newLine);
211   // this->bufferText->
212//  this->inputLineText->setText(newLine);
[5068]213}
214
215/**
216 * moves the buffer around lineCount lines upwards (negative values move down)
217 * @param lineCount the Count of lines to move upwards
[5072]218 *
219 * @todo
[5068]220 */
221void Shell::moveBuffer(int lineCount)
222{
223}
224
225/**
226 * @param lineNumber the n-th line from the bottom
227 * @returns the Buffer at Line lineNumber
228 */
229const char* Shell::getBufferLine(unsigned int lineNumber)
230{
[5072]231  tIterator<char>* charIterator = this->buffer->getIterator();
[5111]232  char* charElem = charIterator->nextElement();
[5072]233
234  int i = 1;
235  while (charElem != NULL)
236  {
237    if (i++ < lineNumber)
238    {
239      delete charIterator;
240      return charElem;
241    }
242
243    charElem = charIterator->nextElement();
244  }
245  delete charIterator;
[5068]246}
247
[5111]248
[5068]249/**
250 * deletes the InputLine
251 */
252void Shell::flushInputLine()
253{
[5072]254  if (likely(this->inputLine != NULL))
255  {
256    delete [] this->inputLine;
257  }
258  this->inputLine = new char[1];
259  *this->inputLine = '\0';
[5111]260
[5068]261}
262
263/**
264 * adds one character to the inputLine
265 * @param character the character to add to the inputLine
266 */
267void Shell::addCharacter(char character)
268{
[5072]269  char* addCharLine = new char[strlen(inputLine)+2];
270
271  sprintf(addCharLine, "%s%c", this->inputLine, character);
272  delete this->inputLine;
273  this->inputLine = addCharLine;
[5093]274  this->inputLineText->setText(inputLine);
[5068]275}
276
277/**
278 * adds multiple Characters to thr inputLine
279 * @param characters a '\0' terminated char-array to add to the InputLine
280 */
281void Shell::addCharacters(const char* characters)
282{
[5072]283  char* addCharLine = new char[strlen(inputLine)+strlen(characters)+1];
284
285  sprintf(addCharLine, "%s%s", this->inputLine, characters);
286  delete this->inputLine;
287  this->inputLine = addCharLine;
[5093]288  this->inputLineText->setText(inputLine);
[5068]289}
290
291/**
292 * removes characterCount characters from the InputLine
293 * @param characterCount the count of Characters to remove from the input Line
294 */
295void Shell::removeCharacters(unsigned int characterCount)
296{
[5093]297  if (strlen(this->inputLine) == 0)
298    return;
299
[5072]300  if (characterCount > strlen(this->inputLine))
301    characterCount = strlen(this->inputLine);
302
303  char* removeCharLine = new char[strlen(inputLine)-characterCount+1];
304
305  strncpy(removeCharLine, this->inputLine, strlen(inputLine)-characterCount);
[5093]306  removeCharLine[strlen(inputLine)-characterCount] = '\0';
[5072]307  delete this->inputLine;
308  this->inputLine = removeCharLine;
[5093]309  this->inputLineText->setText(inputLine);
[5068]310}
311
[5096]312/**
313 * executes the command stored in the inputLine
314 * @return true if the command was commited successfully, false otherwise
315 */
316bool Shell::executeCommand()
317{
[5111]318
[5096]319  this->addBufferLineStatic("Execute Command: %s\n", this->inputLine);
320  delete this->inputLine;
321  this->inputLine = new char[1];
322  this->inputLine[0]='\0';
323  this->inputLineText->setText(this->inputLine);
324  return false;
325}
326
[5097]327/**
328 * sets the Repeate-delay and rate
329 * @param repeatDelay the Delay it takes, to repeate a key
330 * @param repeatRate the rate to repeate a pressed key
331 */
332void Shell::setRepeatDelay(float repeatDelay, float repeatRate)
333{
334  this->repeatDelay = repeatDelay;
335  this->repeatRate = repeatRate;
336
337}
338
[5111]339
340#include "key_names.h"
[5069]341/**
342 * listens for some event
343 * @param event the Event happened
344 */
345void Shell::process(const Event &event)
346{
[5093]347  if (event.bPressed)
348  {
349    PRINTF(4)("Shell received command %s\n", SDLKToKeyname(event.type));
350    if (event.type == SDLK_BACKQUOTE)
351    {
352      if (EventHandler::getInstance()->getState() == ES_GAME)
[5094]353      {
[5111]354        EventHandler::getInstance()->setState(ES_SHELL);
355        this->setRelCoorSoft2D(0, GraphicsEngine::getInstance()->getResolutionY()-150, 1, 5);
[5094]356      }
357
[5093]358      else
[5094]359      {
[5111]360        EventHandler::getInstance()->setState(ES_GAME);
361        this->setRelCoorSoft2D(0, GraphicsEngine::getInstance()->getResolutionY()+10, 1, 5);
[5094]362      }
[5093]363    }
364    else if (event.type == SDLK_TAB)
365      this->autoComplete();
366    else if (event.type == SDLK_BACKSPACE)
[5095]367    {
368      this->delayed = this->repeatDelay;
369      this->pressedKey = SDLK_BACKSPACE;
[5093]370      this->removeCharacters(1);
[5095]371    }
[5096]372    else if (event.type == SDLK_RETURN)
373      this->executeCommand();
[5097]374    else if (likely(event.type < 127))
[5095]375    {
376      this->delayed = this->repeatDelay;
377      this->pressedKey = event.type;
[5093]378      this->addCharacter(event.type);
[5095]379    }
[5093]380  }
[5095]381  else // if(!event.bPressed)
382  {
383    if (this->pressedKey == event.type)
384      this->pressedKey = SDLK_FIRST;
[5111]385    this->delayed = 0.0;
[5095]386  }
[5069]387}
388
[5068]389/**
390 * ticks the Shell for dt Seconds
391 * @param dt the elapsed time since the last tick();
392 */
[5095]393void Shell::tick(float dt)
394{
395  if (this->delayed > 0.0)
396    this->delayed -= dt;
397  else if (this->pressedKey != SDLK_FIRST )
398  {
[5097]399    this->delayed = this->repeatRate;
[5095]400    if (this->pressedKey == SDLK_BACKSPACE)
401      this->removeCharacters(1);
402    else if (pressedKey < 127)
403      this->addCharacter(this->pressedKey);
404  }
405}
[5068]406
407/**
408 * displays the Shell
409 */
410void Shell::draw() const
411{
[5099]412  glPushMatrix();
413  // transform for alignment.
414  // setting the Blending effects
415
416  glColor4f(0.0f, 0.0f, 0.8f, .4);
417  glEnable(GL_BLEND);
418  glDisable(GL_TEXTURE_2D);
419  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
420
421//  glBindTexture(GL_TEXTURE_2D, this->texture);
422  glBegin(GL_QUADS);
423
424//  glTexCoord2f(this->texCoord.minU, this->texCoord.minV);
425  glVertex2f(this->getAbsCoor2D().x,   this->getAbsCoor2D().);
426
427//  glTexCoord2f(this->texCoord.maxU, this->texCoord.minV);
[5111]428  glVertex2f(this->getAbsCoor2D().x + 800, this->getAbsCoor2D().);
[5099]429
430//  glTexCoord2f(this->texCoord.maxU, this->texCoord.maxV);
[5111]431  glVertex2f(this->getAbsCoor2D().x + 800, this->getAbsCoor2D().y + 150);
[5099]432
433//  glTexCoord2f(this->texCoord.minU, this->texCoord.maxV);
[5111]434  glVertex2f(this->getAbsCoor2D().x, this->getAbsCoor2D().y + 150);
[5099]435
436  glEnd();
[5068]437}
438
439
440/**
441 * autocompletes the Shell's inputLine
442 * @returns true, if a result was found, false otherwise
[5100]443 *
444 * @todo implement it!!
[5068]445 */
446bool Shell::autoComplete()
447{
[5100]448  //PRINTF(3)("AutoCompletion not implemented yet\n");
449
450  char* completionLine = new char[strlen(inputLine)+1];
451  strcpy(completionLine, this->inputLine);
452
[5111]453   char* commandBegin = strrchr(completionLine, ' ');
[5100]454  if (commandBegin == NULL)
455    commandBegin = completionLine;
456  else
457  {
458    if(commandBegin >= completionLine + strlen(completionLine))
459      commandBegin = completionLine + strlen(completionLine);
460    else
461      commandBegin++;
462  }
463
[5111]464  printf("%s\n",commandBegin);
465   Array<char*>* classArray = LoadClassDescription::searchClassWithShort(commandBegin);
466   if (classArray->getCount() == 0)
467   {
468     delete[] completionLine;
469     delete classArray;
470     //PRINTF(0)("no completion found for %s\n", commandBegin);
471     return false;
472   }
[5102]473
[5111]474   for (unsigned int i = 0; i < classArray->getCount(); i++)
475   {
476     PRINTF(0)("%s\n", classArray->getEntry(i));
477   }
478   if (classArray->getCount() == 1)
479   {
480     this->removeCharacters(strlen(commandBegin));
481     this->addCharacters(classArray->getEntry(0));
482     this->addCharacter(' ');
483   }
[5102]484
[5111]485   delete[] completionLine;
486   delete classArray;
[5105]487}
488
489/**
[5068]490 * displays some nice output from the Shell
491 */
492void Shell::debug() const
493{
[5096]494  if (this->pressedKey != SDLK_FIRST)
495    printf("%s::%f %f\n", SDLKToKeyname(this->pressedKey), this->delayed, this->repeatDelay);
[5111]496
[5068]497}
Note: See TracBrowser for help on using the repository browser.