Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5142 was 5141, checked in by bensch, 20 years ago

orxonox/trunk: moved helper-functions to helper-functions.cc

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