Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: minor extension-addition to the Shell.

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