Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: Windows runs again without any segfaults
it seems, that windows links object files differently… and extremely strange

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