Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/shell/shell.cc @ 5164

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

orxonox/trunk: ability to describe the presented options :)

File size: 22.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"
[5129]19#include "shell_command.h"
[1853]20
[5072]21#include "text_engine.h"
22#include "list.h"
[5093]23#include "graphics_engine.h"
24#include "event_handler.h"
[5129]25#include "debug.h"
[5113]26#include "class_list.h"
27
28#include "key_names.h"
[5075]29#include <stdarg.h>
30#include <stdio.h>
31
[1856]32using namespace std;
[1853]33
[5164]34SHELL_COMMAND(clear, Shell, clear)->describe("Clears the shell from unwanted lines (empties all buffers)");
[1856]35
[3245]36/**
[4838]37 * standard constructor
[5068]38 */
39Shell::Shell ()
[3365]40{
[5072]41  this->setClassID(CL_SHELL, "Shell");
42  this->setName("Shell");
43
[5127]44  this->keepBufferArray[0] = '\0';
45  this->keepBuffer = false;
46
[5113]47  this->bActive = false;
[5072]48  this->buffer = new tList<char>;
[5118]49  this->bufferIterator = this->buffer->getIterator();
[5072]50
[5129]51  this->inputHistory = new tList<char>;
52  //this->commandList = new tList<ShellCommand>;
53
[5113]54  this->textSize = 15;
55  this->lineSpacing = 5;
[5080]56
[5074]57  //this->bufferSize = 0;
[5080]58  this->bufferText = NULL;
[5158]59  this->setBufferSize(10);
[5113]60  this->bufferDisplaySize = 10;
61  this->setAbsCoor2D(3, -400);
[5095]62  this->delayed = 0;
[5097]63  this->setRepeatDelay(.3, .05);
[5095]64  this->pressedKey = SDLK_FIRST;
[5074]65
[5113]66  this->inputLineText = NULL;
[5093]67  this->inputLine = new char[1];
68  this->inputLine[0] = '\0';
69
[5113]70  this->rebuildText();
71  this->completionList = NULL;
[5093]72
[5113]73  // EVENT-Handler subscription of '`' to all States, and all other keyboard commands to ES_SEHLL
[5093]74  EventHandler* evh = EventHandler::getInstance();
[5096]75  evh->subscribe(this, ES_ALL, SDLK_BACKQUOTE);
[5119]76  for (int i = 1; i < SDLK_LAST; i++)
[5095]77    evh->subscribe(this, ES_SHELL, i);
[5068]78}
[4320]79
[5145]80
81void Shell::testI (int i)
82{
[5149]83  PRINTF(3)("This is the Test for one Int '%d'\n", i);
[5145]84}
85
86void Shell::testS (const char* s)
87{
[5149]88  PRINTF(3)("This is the Test for one String '%s'\n", s);
[5145]89}
90
[5152]91void Shell::testB (bool b)
92{
93  PRINTF(3)("This is the Test for one Bool: ");
94  if (b)
95    PRINTF(3)("true\n");
96  else
97    PRINTF(3)("false\n");
98}
[5145]99
[5152]100void Shell::testF (float f)
101{
102  PRINTF(3)("This is the Test for one Float '%f'\n", f);
103}
104
[5154]105void Shell::testSF (const char* s, float f)
106{
107  PRINTF(3)("This is the Test for one String '%s' and one Float '%f'\n",s , f);
108}
[5152]109
[5154]110
111
[5068]112Shell* Shell::singletonRef = NULL;
[1853]113
[3245]114/**
[4838]115 * standard deconstructor
[5068]116 */
117Shell::~Shell ()
[3543]118{
[5099]119  // delete the displayable Buffers
[5080]120  for (int i = 0; i < this->bufferDisplaySize; i++)
121    delete this->bufferText[i];
[5113]122  delete[] this->bufferText;
[5093]123
[5099]124  // delete the inputLine
[5080]125  delete this->inputLineText;
[5093]126  delete this->inputLine;
[5079]127
[5099]128  // delete all the Chars in the Buffers
[5118]129  char* charElem = this->bufferIterator->firstElement();
[5099]130  while (charElem != NULL)
131  {
132    delete charElem;
[5118]133    charElem = this->bufferIterator->nextElement();
[5099]134  }
[5118]135  delete this->bufferIterator;
[5099]136
[5113]137//  if (this->completionList != NULL)
138    //delete this->completionList;
139
[5068]140  Shell::singletonRef = NULL;
[3543]141}
[5068]142
[5119]143/**
144 * activates the shell
145 *
146 * This also feeds the Last few lines from the main buffers into the displayBuffer
147 */
[5113]148void Shell::activate()
149{
150  if (this->bActive == true)
151    PRINTF(3)("The shell is already active\n");
152  this->bActive = true;
153
154  EventHandler::getInstance()->setState(ES_SHELL);
155  this->setRelCoorSoft2D(0, 0, 1, 5);
[5118]156
157  this->bufferIterator->lastElement();
158  for (int i = 0; i < this->bufferDisplaySize; i++)
[5157]159    this->bufferText[i]->setText(this->bufferIterator->prevElement(), true);
[5113]160}
161
[5119]162/**
163 * deactiveates the Shell.
164 */
[5113]165void Shell::deactivate()
166{
167  if (this->bActive == false)
168    PRINTF(3)("The shell is already inactive\n");
169  this->bActive = false;
170
171  EventHandler::getInstance()->setState(ES_GAME);
172  this->setRelCoorSoft2D(0, -400, 1, 5);
[5118]173
[5157]174  this->bufferIterator->lastElement();
175  for (int i = 0; i < this->bufferDisplaySize; i++)
176    this->bufferText[i]->setText(this->bufferIterator->prevElement(), false);
[5113]177}
178
[5158]179
[5119]180/**
181 * sets the size of the text and spacing
182 * @param textSize the size of the Text in Pixels
183 * @param lineSpacing the size of the Spacing between two lines in pixels
184 *
185 * this also rebuilds the entire Text, inputLine and displayBuffer,
186 * to be accurate again.
187 */
[5113]188void Shell::setTextSize(unsigned int textSize, unsigned int lineSpacing)
189{
190  this->textSize = textSize;
191  this->lineSpacing = lineSpacing;
192
193  this->rebuildText();
194}
195
[5127]196/**
197 * rebuilds the Text's
198 *
199 * use this function, if you changed the Font/Size or something else.
200 */
[5113]201void Shell::rebuildText()
202{
203  if (this->inputLineText == NULL)
204    delete this->inputLineText;
[5122]205  this->inputLineText = TextEngine::getInstance()->createText("fonts/Aniron_Bold.ttf", this->textSize, TEXT_RENDER_DYNAMIC);
[5121]206  this->inputLineText->setColor(1, 0, 0);
[5113]207  this->inputLineText->setAlignment(TEXT_ALIGN_LEFT);
208  this->inputLineText->setText(NULL);
209  this->inputLineText->setParent2D(this);
[5124]210  this->inputLineText->setRelCoor2D(5, (this->textSize + this->lineSpacing)*this->bufferDisplaySize + this->textSize);
[5113]211
212  this->setBufferDisplaySize(this->bufferDisplaySize);
213}
214
[5074]215/**
216 * sets The count of Lines to display in the buffer.
217 * @param bufferDisplaySize the count of lines to display in the Shell-Buffer.
218 */
[5072]219void Shell::setBufferDisplaySize(unsigned int bufferDisplaySize)
220{
[5080]221  if (this->bufferText != NULL)
[5072]222  {
[5080]223    for (unsigned int i = 0; i < this->bufferDisplaySize; i++)
224      delete this->bufferText[i];
[5113]225    delete[] this->bufferText;
[5072]226  }
[5080]227
228  this->bufferText = new Text*[bufferDisplaySize];
229  for (unsigned int i = 0; i < bufferDisplaySize; i++)
[5072]230  {
[5122]231    this->bufferText[i] = TextEngine::getInstance()->createText("fonts/Aniron_Bold.ttf", this->textSize, TEXT_RENDER_DYNAMIC);
[5121]232    this->bufferText[i]->setColor(1, 0, 0);
[5080]233    this->bufferText[i]->setAlignment(TEXT_ALIGN_LEFT);
[5120]234    this->bufferText[i]->setRelCoor2D(calculateLinePosition(i));
[5080]235    this->bufferText[i]->setText(NULL);
[5089]236    this->bufferText[i]->setParent2D(this);
[5072]237  }
[5113]238  this->bufferDisplaySize = bufferDisplaySize;
[5111]239
[5113]240  this->shellHeight = (this->textSize + this->lineSpacing) * (bufferDisplaySize+1);
[5072]241}
[5068]242
243/**
244 * deletes all the Buffers
245 */
246void Shell::flushBuffers()
247{
[5072]248  // remove all chars from the BufferTexts.
[5080]249  if (this->bufferText)
[5125]250    for (int i = 0; i < this->bufferDisplaySize; i++)
[5080]251    {
[5125]252      this->bufferText[i]->setText(NULL, true);
[5080]253    }
[5068]254
[5072]255  // delete all the Chars in the Buffers
256  tIterator<char>* charIterator = this->buffer->getIterator();
[5115]257  char* charElem = charIterator->firstElement();
[5072]258  while (charElem != NULL)
259  {
260    delete charElem;
261
262    charElem = charIterator->nextElement();
263  }
264  delete charIterator;
[5125]265  delete this->buffer;
266  this->buffer = new tList<char>;
[5068]267}
268
269/**
270 * adds a new Line to the List of Buffers
271 * @param line the Line as in the first argument in printf
272 * @param args the arguments as a va_list
273 */
[5075]274bool Shell::addBufferLineStatic(const char* line, ...)
[5068]275{
[5075]276  va_list arguments;
277  va_start(arguments, line);
[5072]278
[5092]279#if DEBUG < 3
[5075]280  if (Shell::singletonRef == NULL)
[5089]281#endif
282
283  vprintf(line, arguments);
[5092]284#if DEBUG < 3
[5075]285  else
[5092]286#else
287  if (Shell::singletonRef != NULL)
[5089]288#endif
[5075]289    Shell::singletonRef->addBufferLine(line, arguments);
290  return true;
291}
[5072]292
[5080]293/**
294 * add a Line to the List of Buffers
295 * @param line
296 * @param arguments
297 *
298 * This function Adds one line to the buffer.
299 * and displays the line as the First Line of the display-buffer
300 */
[5075]301void Shell::addBufferLine(const char* line, va_list arguments)
302{
[5078]303   vsprintf(this->bufferArray, line, arguments);
[5072]304
[5127]305   char* inputEnd;
306   char* newLineBegin;
[5126]307   char* newLineEnd;
[5073]308
[5127]309   // check if we have something left in the buffers
310   if (unlikely(this->keepBuffer))
[5080]311   {
[5127]312     strcat(this->keepBufferArray, this->bufferArray);
313     inputEnd = this->keepBufferArray + strlen(this->keepBufferArray);
314     newLineBegin = this->keepBufferArray;
315     this->keepBuffer = false;
316   }
317   else
318   {
319     inputEnd = this->bufferArray + strlen(this->bufferArray);
320     newLineBegin = this->bufferArray;
321   }
322
323   // adding all the new Lines
324   while (newLineBegin < inputEnd)
325   {
[5126]326     newLineEnd = strchr(newLineBegin, '\n');
327     if (newLineEnd != NULL && *newLineEnd == '\n')
328       *newLineEnd = '\0';
329     else
[5127]330     {
331//       newLineEnd = newLineBegin + strlen(newLineBegin);
332       strcpy(this->keepBufferArray, newLineBegin);
333       this->keepBuffer = true;
[5126]334       break;
[5127]335     }
[5080]336
[5126]337     char* addLine = new char[strlen(newLineBegin)+1];
338     strcpy(addLine, newLineBegin);
339
340     this->buffer->add(addLine);
341
342     if (this->buffer->getSize() > this->bufferSize)
343     {
344       delete this->buffer->firstElement();
345       this->buffer->remove(this->buffer->firstElement());
346     }
347
348     if (this->bActive)
349     {
350       this->printToDisplayBuffer(addLine);
351     }
352     newLineBegin = newLineEnd+1;
[5118]353   }
354}
[5113]355
[5118]356/**
357 * prints out some text to the input-buffers
358 * @param text the text to output.
359 */
360void Shell::printToDisplayBuffer(const char* text)
361{
362  if(likely(bufferText != NULL))
363  {
364    Text* lastText = this->bufferText[this->bufferDisplaySize-1];
[5113]365
[5118]366    Text* swapText;
367    Text* moveText = this->bufferText[0];
[5120]368    this->bufferText[0]->setRelCoorSoft2D(this->calculateLinePosition(1),10);
[5118]369    for (unsigned int i = 1; i < this->bufferDisplaySize; i++)
370    {
371      if ( i < this->bufferDisplaySize-1)
[5120]372        this->bufferText[i]->setRelCoorSoft2D(this->calculateLinePosition(i+1),5);
[5118]373      swapText = this->bufferText[i];
374      this  ->bufferText[i] = moveText;
375      moveText = swapText;
376    }
[5120]377    lastText->setRelCoor2D(this->calculateLinePosition(0));
[5118]378    this->bufferText[0] = lastText;
379
[5122]380    this->bufferText[0]->setText(text, true);
[5118]381  }
[5068]382}
383
384/**
385 * moves the buffer around lineCount lines upwards (negative values move down)
386 * @param lineCount the Count of lines to move upwards
[5072]387 *
388 * @todo
[5068]389 */
[5160]390void Shell::moveBuffer(unsigned int lineCount)
[5068]391{
392}
393
394/**
395 * @param lineNumber the n-th line from the bottom
396 * @returns the Buffer at Line lineNumber
397 */
398const char* Shell::getBufferLine(unsigned int lineNumber)
399{
[5072]400  tIterator<char>* charIterator = this->buffer->getIterator();
[5115]401  char* charElem = charIterator->firstElement();
[5072]402
403  int i = 1;
404  while (charElem != NULL)
405  {
406    if (i++ < lineNumber)
407    {
408      delete charIterator;
409      return charElem;
410    }
411
412    charElem = charIterator->nextElement();
413  }
414  delete charIterator;
[5068]415}
416
417/**
418 * deletes the InputLine
419 */
420void Shell::flushInputLine()
421{
[5072]422  if (likely(this->inputLine != NULL))
423  {
[5125]424    delete[] this->inputLine;
[5072]425  }
426  this->inputLine = new char[1];
427  *this->inputLine = '\0';
[5125]428  this->inputLineText->setText(this->inputLine, true);
[5068]429}
430
431/**
432 * adds one character to the inputLine
433 * @param character the character to add to the inputLine
434 */
435void Shell::addCharacter(char character)
436{
[5072]437  char* addCharLine = new char[strlen(inputLine)+2];
438
439  sprintf(addCharLine, "%s%c", this->inputLine, character);
440  delete this->inputLine;
441  this->inputLine = addCharLine;
[5123]442  this->inputLineText->setText(inputLine, true);
[5068]443}
444
445/**
446 * adds multiple Characters to thr inputLine
447 * @param characters a '\0' terminated char-array to add to the InputLine
448 */
449void Shell::addCharacters(const char* characters)
450{
[5072]451  char* addCharLine = new char[strlen(inputLine)+strlen(characters)+1];
452
453  sprintf(addCharLine, "%s%s", this->inputLine, characters);
454  delete this->inputLine;
455  this->inputLine = addCharLine;
[5157]456  this->inputLineText->setText(inputLine, true);
[5068]457}
458
459/**
460 * removes characterCount characters from the InputLine
461 * @param characterCount the count of Characters to remove from the input Line
462 */
463void Shell::removeCharacters(unsigned int characterCount)
464{
[5093]465  if (strlen(this->inputLine) == 0)
466    return;
467
[5072]468  if (characterCount > strlen(this->inputLine))
469    characterCount = strlen(this->inputLine);
470
471  char* removeCharLine = new char[strlen(inputLine)-characterCount+1];
472
473  strncpy(removeCharLine, this->inputLine, strlen(inputLine)-characterCount);
[5093]474  removeCharLine[strlen(inputLine)-characterCount] = '\0';
[5072]475  delete this->inputLine;
476  this->inputLine = removeCharLine;
[5157]477  this->inputLineText->setText(inputLine, true);
[5068]478}
479
[5096]480/**
481 * executes the command stored in the inputLine
482 * @return true if the command was commited successfully, false otherwise
483 */
484bool Shell::executeCommand()
485{
486  this->addBufferLineStatic("Execute Command: %s\n", this->inputLine);
[5125]487
[5129]488  char* newCommand = new char[strlen(this->inputLine)+1];
489  strcpy(newCommand, this->inputLine);
490  this->inputHistory->add(newCommand);
491
[5135]492  ShellCommandBase::execute(this->inputLine);
[5125]493
494  this->flushInputLine();
495
[5096]496  return false;
497}
498
[5130]499void Shell::clear()
500{
501  this->flushBuffers();
502  this->addBufferLine("orxonox - shell\n ==================== \n", NULL);
503}
504
[5097]505/**
506 * sets the Repeate-delay and rate
507 * @param repeatDelay the Delay it takes, to repeate a key
508 * @param repeatRate the rate to repeate a pressed key
509 */
510void Shell::setRepeatDelay(float repeatDelay, float repeatRate)
511{
512  this->repeatDelay = repeatDelay;
513  this->repeatRate = repeatRate;
514
515}
516
[5069]517/**
518 * listens for some event
519 * @param event the Event happened
520 */
521void Shell::process(const Event &event)
522{
[5093]523  if (event.bPressed)
524  {
[5141]525    PRINTF(5)("Shell received command %s\n", SDLKToKeyname(event.type));
[5093]526    if (event.type == SDLK_BACKQUOTE)
527    {
528      if (EventHandler::getInstance()->getState() == ES_GAME)
[5113]529        this->activate();
[5093]530      else
[5113]531        this->deactivate();
[5093]532    }
[5119]533    else if (event.type == SDLK_F1)
534      this->help();
535    else if (event.type == SDLK_F2)
536      this->debug();
[5093]537    else if (event.type == SDLK_TAB)
538      this->autoComplete();
539    else if (event.type == SDLK_BACKSPACE)
[5095]540    {
541      this->delayed = this->repeatDelay;
542      this->pressedKey = SDLK_BACKSPACE;
[5093]543      this->removeCharacters(1);
[5095]544    }
[5096]545    else if (event.type == SDLK_RETURN)
546      this->executeCommand();
[5129]547    /*
548    else if (event.type == SDLK_UP)
549    {
550//      this->flushInputLine();
551      tIterator<char>* iterator = this->commandList->getIterator();
552      char* command = iterator->lastElement();
553      while (command)
554      {
555        if (!strcmp (command, inputLine))
556        {
557          inputLine = iterator->prevElement();
558          return;
559        }
560        command = iterator->prevElement();
561      }
562      inputLine = iterator->lastElement();
563    }
564    */
[5097]565    else if (likely(event.type < 127))
[5095]566    {
[5128]567      Uint8 *keystate = SDL_GetKeyState(NULL);
[5095]568      this->delayed = this->repeatDelay;
[5128]569      if (unlikely( keystate[SDLK_LSHIFT] || keystate[SDLK_RSHIFT] ))
570      {
571        this->pressedKey = event.type-32;
572        this->addCharacter(event.type-32);
573      }
574      else
575      {
576        this->pressedKey = event.type;
577        this->addCharacter(event.type);
578      }
[5095]579    }
[5093]580  }
[5095]581  else // if(!event.bPressed)
582  {
[5128]583    if (this->pressedKey == event.type || (this->pressedKey == event.type - 32))
[5113]584    {
[5095]585      this->pressedKey = SDLK_FIRST;
[5113]586      this->delayed = 0.0;
587    }
[5095]588  }
[5069]589}
590
[5068]591/**
592 * ticks the Shell for dt Seconds
593 * @param dt the elapsed time since the last tick();
594 */
[5095]595void Shell::tick(float dt)
596{
597  if (this->delayed > 0.0)
598    this->delayed -= dt;
599  else if (this->pressedKey != SDLK_FIRST )
600  {
[5097]601    this->delayed = this->repeatRate;
[5095]602    if (this->pressedKey == SDLK_BACKSPACE)
603      this->removeCharacters(1);
604    else if (pressedKey < 127)
605      this->addCharacter(this->pressedKey);
606  }
607}
[5068]608
609/**
610 * displays the Shell
611 */
612void Shell::draw() const
613{
[5099]614  glPushMatrix();
615  // transform for alignment.
616  // setting the Blending effects
617
618  glColor4f(0.0f, 0.0f, 0.8f, .4);
619  glEnable(GL_BLEND);
620  glDisable(GL_TEXTURE_2D);
621  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
622
[5158]623  glBindTexture(GL_TEXTURE_2D, 0);
624  glBegin(GL_TRIANGLE_STRIP);
[5099]625
[5158]626  glTexCoord2f(0, 0);
[5099]627  glVertex2f(this->getAbsCoor2D().x,   this->getAbsCoor2D().);
628
[5158]629  glTexCoord2f(1, 0);
[5113]630  glVertex2f(GraphicsEngine::getInstance()->getResolutionX() - this->getAbsCoor2D().x, this->getAbsCoor2D().);
[5099]631
[5158]632  glTexCoord2f(0, 1);
633  glVertex2f(this->getAbsCoor2D().x, this->getAbsCoor2D().y + this->shellHeight);
634
635  glTexCoord2f(1, 1);
[5113]636  glVertex2f(GraphicsEngine::getInstance()->getResolutionX() - this->getAbsCoor2D().x, this->getAbsCoor2D().y + this->shellHeight);
[5099]637
638  glEnd();
[5068]639}
640
641
642/**
643 * autocompletes the Shell's inputLine
644 * @returns true, if a result was found, false otherwise
[5100]645 *
646 * @todo implement it!!
[5068]647 */
648bool Shell::autoComplete()
649{
[5100]650  //PRINTF(3)("AutoCompletion not implemented yet\n");
651
652  char* completionLine = new char[strlen(inputLine)+1];
653  strcpy(completionLine, this->inputLine);
654
[5113]655  char* commandBegin = strrchr(completionLine, ' ');
[5100]656  if (commandBegin == NULL)
657    commandBegin = completionLine;
658  else
659  {
660    if(commandBegin >= completionLine + strlen(completionLine))
661      commandBegin = completionLine + strlen(completionLine);
662    else
663      commandBegin++;
664  }
665
[5113]666  char* objectStart;
667  if (objectStart = strstr(commandBegin, "::"))
668  {
669    char* classIdentity = new char[objectStart - commandBegin +1];
670    strncpy(classIdentity, commandBegin, objectStart - commandBegin);
671    classIdentity[objectStart - commandBegin] = '\0';
672    this->objectComplete(objectStart+2, ClassList::StringToID(classIdentity));
673    delete[] classIdentity;
674  }
675  else
676    this->classComplete(commandBegin);
[5102]677
[5113]678  delete[] completionLine;
679}
[5102]680
[5113]681/**
682 * autocompletes a className
683 * @param classBegin the Beginning of a String to autoComplete
684 * @return true on success, false otherwise
685 */
686bool Shell::classComplete(const char* classBegin)
687{
688  if (unlikely(classBegin == NULL))
689    return false;
690  const tList<const char>* clList = ClassList::getClassList();
691  if (clList != NULL)
692  {
693    const tList<const char>* classList = this->createCompleteList(clList, classBegin);
694    if (classList != NULL)
695      this->generalComplete(classList, classBegin, "%s::", "::");
696    else
697      return false;
698  }
699  else
700    return false;
701  return true;
[5105]702}
703
704/**
[5113]705 * autocompletes an ObjectName
706 * @param objectBegin the beginning string of a Object
707 * @param classID the ID of the Class to search for.
708 * @return true on success, false otherwise
709 */
710bool Shell::objectComplete(const char* objectBegin, long classID)
711{
712  printf("%s\n", objectBegin);
713
714  if (unlikely(objectBegin == NULL))
715    return false;
716  tList<BaseObject>* boList = ClassList::getList(classID);
717  if (boList != NULL)
718  {
719    printf("\n", boList->firstElement()->getName());
720    const tList<const char>* objectList = this->createCompleteList(boList, objectBegin);
721    if (objectList != NULL)
722      this->generalComplete(objectList, objectBegin, "%s");
723    else
724      return false;
725  }
726  else
727    return false;
728  return true;
729}
730
731bool Shell::functionComplete(const char* functionBegin)
732{
733}
734
735/**
736 * completes the inputline on grounds of an inputList
737 * @param stringList the List to parse through
738 * @param begin the String to search in the inputList, and to extend with it.
739 * @param displayAs how to display the found value to the user, printf-style, !!with only one %s!! ex.: "::%s::"
740 * @param addBack what should be added at the end of the completion
741 * @param addFront what should be added to the front of one finished completion
742 * @return true if ok, false otherwise
743 */
744bool Shell::generalComplete(const tList<const char>* stringList, const char* begin, const char* displayAs, const char* addBack, const char* addFront)
745{
746  if (stringList->getSize() == 0)
747    return false;
748
749  const char* addString = stringList->firstElement();
750  unsigned int addLength = 0;
751  unsigned int inputLenght = strlen(begin);
752
753  if (addString != NULL)
754    addLength = strlen(addString);
755  tIterator<const char>* charIterator = stringList->getIterator();
[5115]756  const char* charElem = charIterator->firstElement();
[5113]757  while (charElem != NULL)
758  {
759    PRINTF(0)(displayAs, charElem);
760    for (unsigned int i = inputLenght; i < addLength; i++)
761      if (addString[i] != charElem[i])
762    {
763      addLength = i;
764      break;
765    }
766    charElem = charIterator->nextElement();
767  }
768  delete charIterator;
769
770  if (addLength >= inputLenght)
771  {
772    char* adder = new char[addLength+1];
773    strncpy(adder, addString, addLength);
774    adder[addLength] = '\0';
775    this->removeCharacters(inputLenght);
776    this->addCharacters(adder);
777    if (addBack != NULL && stringList->getSize() == 1)
778      this->addCharacters("::");
779    delete[] adder;
780  }
781  return true;
782}
783
784/**
785 * searches for classes, which beginn with classNameBegin
786 * @param inputList the List to parse through
787 * @param classNameBegin the beginning string
788 * @return a NEW char-array with ClassNames. The LIST should be deleted afterwards,
789 * !! The strings MUST NOT be deleted !!
790 */
791const tList<const char>* Shell::createCompleteList(const tList<const char>* inputList, const char* classNameBegin)
792{
793  if (inputList == NULL || classNameBegin == NULL)
794    return NULL;
795  unsigned int searchLength = strlen(classNameBegin);
796  if (this->completionList != NULL)
797    delete this->completionList;
798  this->completionList = new tList<const char>;
799
800//  tList<const char>* classList = ClassList::getClassList();
801
802  tIterator<const char>* iterator = inputList->getIterator();
[5115]803  const char* enumString = iterator->firstElement();
[5113]804  while (enumString != NULL)
805  {
806    if (strlen(enumString)>searchLength+1 &&
807        !strncasecmp(enumString, classNameBegin, searchLength))
808    {
809      this->completionList->add(enumString);
810    }
811    enumString = iterator->nextElement();
812  }
813  delete iterator;
814
815  return this->completionList;
816}
817
818/**
819 * searches for classes, which beginn with classNameBegin
820 * @param inputList the List to parse through
821 * @param classNameBegin the beginning string
822 * @return a NEW char-array with ClassNames. The LIST should be deleted afterwards,
823 * !! The strings MUST NOT be deleted !!
824 */
825const tList<const char>* Shell::createCompleteList(const tList<BaseObject>* inputList, const char* classNameBegin)
826{
827  if (inputList == NULL || classNameBegin == NULL)
828    return NULL;
829  unsigned int searchLength = strlen(classNameBegin);
830  if (this->completionList != NULL)
831    delete this->completionList;
832  this->completionList = new tList<const char>;
833
834  tIterator<BaseObject>* iterator = inputList->getIterator();
[5115]835  BaseObject* enumBO = iterator->firstElement();
[5113]836  while (enumBO != NULL)
837  {
838    if (enumBO->getName() != NULL &&
839        strlen(enumBO->getName())>searchLength+1 &&
840        !strncasecmp(enumBO->getName(), classNameBegin, searchLength))
841    {
842      this->completionList->add(enumBO->getName());
843    }
844    enumBO = iterator->nextElement();
845  }
846  delete iterator;
847
848  return this->completionList;
849}
850
[5119]851void Shell::help() const
852{
853  PRINT(0)("Help for the most important Shell-commands\n");
854  PRINT(0)("F1 - HELP; F2 - DEBUG; ` - open/close shell\n");
855  PRINT(0)("input order:\n");
856  PRINT(0)("ClassName::objectName function [parameter1, [parameter2 ...]]  or\n");
857  PRINT(0)("Command [parameter]\n");
858}
859
[5120]860
861///////////////////////
862// HELPER FUNCTIONS  //
863///////////////////////
864Vector Shell::calculateLinePosition(unsigned int lineNumber)
865{
[5124]866  return Vector(5, (this->textSize + this->lineSpacing)*(this->bufferDisplaySize - lineNumber -1) + this->textSize, 0);
[5120]867}
868
869
870
[5113]871/**
[5068]872 * displays some nice output from the Shell
873 */
874void Shell::debug() const
875{
[5119]876  PRINT(3)("Debugging output to console (not this shell)\n");
877
[5096]878  if (this->pressedKey != SDLK_FIRST)
879    printf("%s::%f %f\n", SDLKToKeyname(this->pressedKey), this->delayed, this->repeatDelay);
[5119]880
881
882  char* tmpChar = this->bufferIterator->firstElement();
883  while(tmpChar != NULL)
884  {
885    printf(tmpChar);
886    tmpChar = this->bufferIterator->nextElement();
887  }
[5068]888}
Note: See TracBrowser for help on using the repository browser.