Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: better drawing of the Shell

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