Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9869 was 9869, checked in by bensch, 18 years ago

orxonox/trunk: merged the new_class_id branche back to the trunk.
merged with command:
svn merge https://svn.orxonox.net/orxonox/branches/new_class_id trunk -r9683:HEAD
no conflicts… puh..

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