Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5156 was 5154, checked in by bensch, 20 years ago

orxonox/trunk: better comparison

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