Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/shell/shell_input.cc

Last change on this file was 10618, checked in by bknecht, 17 years ago

merged cleanup into trunk (only improvements)

File size: 10.3 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:
[5254]12   main-programmer: Benjamin Grauer
[1855]13   co-programmer: ...
[1853]14*/
15
[7374]16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_SHELL
[1853]17
[5178]18#include "shell_input.h"
[1853]19
[5181]20#include "shell_command.h"
[5639]21#include "shell_command_class.h"
[5179]22
23#include "debug.h"
24#include "compiler.h"
[5180]25#include "key_names.h"
[5179]26
[10618]27#include "game_world.h"
28#include "state.h"
[9869]29
[10618]30
[7374]31namespace OrxShell
[3365]32{
[9869]33  ObjectListDefinition(ShellInput);
[5180]34
[7374]35  /**
36   * @brief constructor
37   * this also generates a ShellCompletion automatically.
38  */
39  ShellInput::ShellInput ()
[7458]40      : Text ("")
[5309]41  {
[9869]42    this->registerObject(this, ShellInput::_objectList);
43
[7374]44    this->pressedKey = SDLK_FIRST;
[7341]45
[7729]46    this->historyIT = ShellInput::history.begin();
[7374]47    this->setHistoryLength(50);
48    this->historyScrolling = false;
49    this->delayed = 0;
50    this->setRepeatDelay(.3, .05);
[1853]51
[7868]52    // subscribe all keyboard commands to ES_SHELL
[7374]53    for (int i = 1; i < SDLK_LAST; i++)
54    {
[8339]55      //if (!this->isEventSubscribed(ES_SHELL, i))
[9869]56      this->subscribeEvent(ES_SHELL, i);
[7374]57    }
58    // unsubscribe unused TODO improve.
[7868]59    this->unsubscribeEvent(ES_SHELL, SDLK_BACKQUOTE);
60    this->unsubscribeEvent(ES_SHELL, SDLK_F12);
61    this->unsubscribeEvent(ES_SHELL, SDLK_PAGEUP);
62    this->unsubscribeEvent(ES_SHELL, SDLK_PAGEDOWN);
[7374]63  }
[5179]64
[7729]65  std::list<std::string> ShellInput::history;
66
[7374]67  /**
68   * @brief standard deconstructor
69   */
70  ShellInput::~ShellInput ()
[7729]71  {}
[5179]72
[7374]73  /**
74   * @brief sets the Repeate-delay and rate
75   * @param repeatDelay the Delay it takes, to repeate a key
76   * @param repeatRate the rate to repeate a pressed key
77   */
78  void ShellInput::setRepeatDelay(float repeatDelay, float repeatRate)
[5244]79  {
[7374]80    this->repeatDelay = repeatDelay;
81    this->repeatRate = repeatRate;
[5244]82  }
83
[7374]84  /**
85   * @brief deletes the InputLine
86   */
87  void ShellInput::flush()
[5244]88  {
[9869]89    this->inputLineBegin.clear();
90    this->inputLineEnd.clear();
91    this->clear();
[5244]92  }
93
[7374]94  /**
95   * @brief sets the entire text of the InputLine to text
96   * @param text the new Text to set as InputLine
97   */
98  void ShellInput::setInputText(const std::string& text)
[5244]99  {
[9869]100    this->inputLineBegin = text;
101    this->inputLineEnd.clear();
102    this->setText(text);
[5244]103  }
104
[5179]105
[7374]106  /**
107   * @brief adds one character to the inputLine
108   * @param character the character to add to the inputLine
109   */
110  void ShellInput::addCharacter(char character)
111  {
112    if (this->historyScrolling)
113    {
114      this->history.pop_back();
115      this->historyScrolling = false;
116    }
[5179]117
[9869]118    this->inputLineBegin += character;
119    this->setText(this->inputLineBegin + this->inputLineEnd);
[7374]120  }
[5369]121
[7374]122  /**
123   * @brief adds multiple Characters to thr inputLine
124   * @param characters a \\0 terminated char-array to add to the InputLine
125   */
126  void ShellInput::addCharacters(const std::string& characters)
127  {
128    if (this->historyScrolling)
129    {
130      this->history.pop_back();
131      this->historyScrolling = false;
132    }
[5179]133
[9869]134    this->inputLineBegin += characters;
135    this->setText(this->inputLineBegin + this->inputLineEnd);
[5243]136  }
137
[7374]138  /**
139   * @brief removes characterCount characters from the InputLine
140   * @param characterCount the count of Characters to remove from the input Line
141   */
142  void ShellInput::removeCharacters(unsigned int characterCount)
[5243]143  {
[7374]144    if (this->historyScrolling)
145    {
146      this->history.pop_back();
147      this->historyScrolling = false;
148    }
[9869]149    if (this->inputLineBegin.size() < characterCount)
150      characterCount = this->inputLineBegin.size();
[7374]151
[9869]152    this->inputLineBegin.erase(this->inputLineBegin.size() - characterCount, this->inputLineBegin.size());
153    this->setText(this->inputLineBegin + this->inputLineEnd);
[5243]154  }
155
[7374]156  /**
157   * @brief executes the command stored in the inputLine
158   * @return true if the command was commited successfully, false otherwise
159   */
160  bool ShellInput::executeCommand()
161  {
[9869]162    if (this->getInput().empty())
[7374]163      return false;
[9869]164    DebugBuffer::addBufferLineStatic("Execute Command: %s\n", this->getInput().c_str());
[5179]165
[9869]166    ShellCommand::execute(this->getInput());
[5180]167
[7374]168    // removing the eventually added Entry (from scrolling) to the List
169    if (this->historyScrolling)
170    {
171      this->history.pop_back();
172      this->historyScrolling = false;
173    }
174
175    // adding the new Command to the History
[9869]176    if (history.empty() || history.back() != this->getInput())
177      this->history.push_back(this->getInput());
[7374]178    if (this->history.size() > this->historyLength)
179    {
180      this->history.pop_front();
181    }
182
183    this->flush();
184
185    return true;
[5243]186  }
187
[7374]188
189  /**
190   * @brief moves one entry up in the history.
191   */
192  void ShellInput::historyMoveUp()
[5243]193  {
[7374]194    if (!this->historyScrolling)
[5785]195    {
[9869]196      this->history.push_back(this->getInput());
[7374]197      this->historyScrolling = true;
198      this->historyIT = --this->history.end();
[5785]199    }
[7374]200
201    if(this->historyIT != this->history.begin())
202    {
203      std::string prevElem = *(--this->historyIT);
204      /*if (prevElem == NULL) /// TODO STD
205        return;
206      else */
207      {
208        this->flush();
209        this->setInputText(prevElem);
210      }
211    }
[5243]212  }
213
[7374]214  /**
215   * @brief moves one entry down in the history
216   */
217  void ShellInput::historyMoveDown()
[5243]218  {
[7374]219    if (!this->historyScrolling)
[5785]220      return;
[7374]221    if (!this->history.empty() && this->historyIT != --this->history.end())
[5785]222    {
[7374]223      std::string nextElem = *(++this->historyIT);
224      /*    if (nextElem == NULL) /// TODO FIX STD
225        return;
226      else */
227      {
228        this->flush();
229        this->setInputText(nextElem);
230      }
[5785]231    }
[5243]232  }
233
[9869]234  /**
235   * @brief moves the cursor chars Characters to the right.
236   * @param chars how much to move the cursor.
237   */
238  void ShellInput::moveCursor(int chars)
239  {
240    if (chars > 0)
241    {
242      PRINTF(5)("move cursor %d to the right\n", chars);
243      if (chars >= (int) this->inputLineEnd.size())
244        chars = inputLineEnd.size();
245      this->inputLineBegin += this->inputLineEnd.substr(0, chars);
246      this->inputLineEnd.erase(0, chars);
247    }
248    else if (chars < 0)
249    {
250      chars = -chars;
251      PRINTF(5)("move cursor %d to the left\n", chars);
[5243]252
[9869]253      if (chars >= (int) this->inputLineBegin.size())
254        chars = inputLineBegin.size();
255      this->inputLineEnd = this->inputLineBegin.substr(this->inputLineBegin.size() - chars) + this->inputLineEnd;
256      this->inputLineBegin.erase(this->inputLineBegin.size() - chars);
257    }
258  }
259
260
[7374]261  /**
262   * @brief prints out some nice help about the Shell
263   */
264  void ShellInput::help(const std::string& className, const std::string& functionName)
265  {
266    if (className.empty())
267    {
[9869]268      PRINT(0)("== Help for the most important Shell-commands\n");
269      PRINT(0)("  F1 - HELP; F2 - DEBUG; '`' - open/close shell\n");
270      PRINT(0)("  input order:\n");
271      PRINT(0)("   ClassName [objectName] function [parameter1, [parameter2 ...]]  or\n");
272      PRINT(0)("   Alias [parameter]\n");
273      PRINT(0)("- Also try 'help className' or pushing 'TAB'\n");
[7374]274    }
275    else if (!className.empty() && functionName.empty())
276    {
277      ShellCommandClass::help(className);
278      //PRINTF(1)("%s::%s\n", className, functionName);
279    }
[5204]280  }
[5180]281
[7374]282  /**
283   * @brief ticks the ShellInput
284   * @param dt the time passed since the last update
285   */
286  void ShellInput::tick(float dt)
[5180]287  {
[7374]288    if (this->delayed > 0.0)
[10618]289    {
290      StoryEntity* storyEntity = State::getCurrentStoryEntity();
291      float speed = 1;
292      if ( storyEntity && storyEntity->isA( GameWorld::staticClassID() ) )
293      {
294        speed = ((GameWorld*)storyEntity)->getSpeed();
295      }
296      this->delayed -= dt / speed;
297    }
[7374]298    else if (this->pressedKey != SDLK_FIRST )
[5786]299    {
[7374]300      this->delayed = this->repeatRate;
301      switch (this->pressedKey )
[5786]302      {
[7374]303        case SDLK_BACKSPACE:
[9869]304        this->removeCharacters(1);
305        break;
[7374]306        case SDLK_UP:
[9869]307        this->historyMoveUp();
308        break;
[7374]309        case SDLK_DOWN:
[9869]310        this->historyMoveDown();
311        break;
[7374]312        default:
[9869]313        {
314          if (likely(pressedKey < 127))
315            this->addCharacter(this->pressedKey);
316        }
[5786]317      }
318    }
[5180]319  }
320
[7374]321  /**
322   * @brief listens for some event
323   * @param event the Event happened
324   */
325  void ShellInput::process(const Event &event)
[5180]326  {
[7374]327    if (event.bPressed)
[5786]328    {
[7676]329      PRINTF(5)("Shell received command %s\n", SDLKToKeyname(event.type).c_str());
[7374]330      if (event.type == SDLK_F1)
331        this->help();
332      else if (event.type == SDLK_F2)
333      {
334        ;//this->debug();
335      }
336      else if (event.type == SDLK_UP)
337      {
338        this->historyMoveUp();
339        this->pressedKey = event.type;
[7919]340        this->pressedEvent = event.type;
[7374]341      }
342      else if (event.type == SDLK_DOWN)
343      {
344        this->historyMoveDown();
345        this->pressedKey = event.type;
[7919]346        this->pressedEvent = event.type;
[7374]347      }
[9869]348      else if (event.type == SDLK_LEFT)
349      {
350        this->moveCursor(-1);
351        this->pressedKey = event.type;
352        this->pressedEvent = event.type;
353      }
354      else if (event.type == SDLK_RIGHT)
355      {
356        this->moveCursor(+1);
357        this->pressedKey = event.type;
358        this->pressedEvent = event.type;
359      }
[7374]360      else if (event.type == SDLK_TAB)
361      {
[9869]362        this->completion.autoComplete(this->inputLineBegin);
363        this->setText(this->getInput());
[7374]364      }
365      else if (event.type == SDLK_BACKSPACE)
366      {
367        this->delayed = this->repeatDelay;
368        this->pressedKey = SDLK_BACKSPACE;
[7919]369        this->pressedEvent = SDLK_BACKSPACE;
[7374]370        this->removeCharacters(1);
371      }
[9869]372      else if (event.type == SDLK_DELETE)
373      {
374        if (!this->inputLineEnd.empty())
375        {
376          this->inputLineEnd.erase(0, 1);
377          this->setText(this->getInput());
378        }
379      }
[7374]380      else if (event.type == SDLK_RETURN)
381      {
382        this->executeCommand();
383        this->pressedKey = event.type;
[7919]384        this->pressedEvent = event.type;
[7374]385      }
386      // any other keyboard key
387      else if (likely(event.type < 127))
388      {
389        this->addCharacter(event.x);
390        this->pressedKey = event.x;
[7858]391        this->pressedEvent = event.type;
[7374]392      }
[5180]393      this->delayed = this->repeatDelay;
394    }
[7374]395    else // if(!event.bPressed)
[5786]396    {
[7858]397      if (this->pressedEvent == event.type)
[7374]398      {
[7858]399        this->pressedEvent = 0;
[7374]400        this->pressedKey = 0;
401        this->delayed = 0.0;
402      }
[5786]403    }
[5180]404  }
[7374]405
[5180]406}
Note: See TracBrowser for help on using the repository browser.