Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: one Parameter safe now

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