Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/shell/shell.cc @ 5172

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

orxonox/trunk: minor bug-fix

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