Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/shell/shell_input.cc @ 9861

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

Changed the ShellBuffer to DebugBuffer, as the dependency is only one way, and it makes no sense for the rest of Orxonox Modules to know the Shell

File size: 8.7 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_SHELL
17
18#include "shell_input.h"
19
20#include "shell_command.h"
21#include "shell_command_class.h"
22
23#include "debug.h"
24#include "compiler.h"
25#include "key_names.h"
26
27
28namespace OrxShell
29{
30  SHELL_COMMAND(help, ShellInput, help)
31  ->describe("retrieve some help about the input mode")
32  ->setAlias("help");
33
34  ObjectListDefinition(ShellInput);
35
36  /**
37   * @brief constructor
38   * this also generates a ShellCompletion automatically.
39  */
40  ShellInput::ShellInput ()
41      : Text ("")
42  {
43    this->registerObject(this, ShellInput::_objectList);
44
45    this->pressedKey = SDLK_FIRST;
46
47    this->inputLine = "";
48    this->historyIT = ShellInput::history.begin();
49    this->setHistoryLength(50);
50    this->historyScrolling = false;
51    this->delayed = 0;
52    this->setRepeatDelay(.3, .05);
53
54    // subscribe all keyboard commands to ES_SHELL
55    for (int i = 1; i < SDLK_LAST; i++)
56    {
57      //if (!this->isEventSubscribed(ES_SHELL, i))
58        this->subscribeEvent(ES_SHELL, i);
59    }
60    // unsubscribe unused TODO improve.
61    this->unsubscribeEvent(ES_SHELL, SDLK_BACKQUOTE);
62    this->unsubscribeEvent(ES_SHELL, SDLK_F12);
63    this->unsubscribeEvent(ES_SHELL, SDLK_PAGEUP);
64    this->unsubscribeEvent(ES_SHELL, SDLK_PAGEDOWN);
65
66  }
67
68  std::list<std::string> ShellInput::history;
69
70  /**
71   * @brief standard deconstructor
72   */
73  ShellInput::~ShellInput ()
74  {}
75
76  /**
77   * @brief sets the Repeate-delay and rate
78   * @param repeatDelay the Delay it takes, to repeate a key
79   * @param repeatRate the rate to repeate a pressed key
80   */
81  void ShellInput::setRepeatDelay(float repeatDelay, float repeatRate)
82  {
83    this->repeatDelay = repeatDelay;
84    this->repeatRate = repeatRate;
85  }
86
87  /**
88   * @brief deletes the InputLine
89   */
90  void ShellInput::flush()
91  {
92    this->inputLine.clear();
93    this->setText(this->inputLine);
94  }
95
96  /**
97   * @brief sets the entire text of the InputLine to text
98   * @param text the new Text to set as InputLine
99   */
100  void ShellInput::setInputText(const std::string& text)
101  {
102    this->inputLine = text;
103    this->setText(this->inputLine);
104  }
105
106
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    }
118
119    this->inputLine += character;
120    this->setText(this->inputLine);
121  }
122
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    }
134
135    this->inputLine += characters;
136    this->setText(this->inputLine);
137  }
138
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)
144  {
145    if (this->historyScrolling)
146    {
147      this->history.pop_back();
148      this->historyScrolling = false;
149    }
150    if (this->inputLine.size() < characterCount)
151      characterCount = this->inputLine.size();
152
153    this->inputLine.erase(this->inputLine.size() - characterCount, this->inputLine.size());
154    this->setText(this->inputLine);
155  }
156
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  {
163    DebugBuffer::addBufferLineStatic("Execute Command: %s\n", this->inputLine.c_str());
164
165    if (this->inputLine.empty())
166      return false;
167
168    ShellCommand::execute(this->inputLine);
169
170    // removing the eventually added Entry (from scrolling) to the List
171    if (this->historyScrolling)
172    {
173      this->history.pop_back();
174      this->historyScrolling = false;
175    }
176
177    // adding the new Command to the History
178    if (history.empty() || history.back() != this->inputLine)
179      this->history.push_back(this->inputLine);
180    if (this->history.size() > this->historyLength)
181    {
182      this->history.pop_front();
183    }
184
185    this->flush();
186
187    return true;
188  }
189
190
191  /**
192   * @brief moves one entry up in the history.
193   */
194  void ShellInput::historyMoveUp()
195  {
196    if (!this->historyScrolling)
197    {
198      this->history.push_back(this->inputLine);
199      this->historyScrolling = true;
200      this->historyIT = --this->history.end();
201    }
202
203    if(this->historyIT != this->history.begin())
204    {
205      std::string prevElem = *(--this->historyIT);
206      /*if (prevElem == NULL) /// TODO STD
207        return;
208      else */
209      {
210        this->flush();
211        this->setInputText(prevElem);
212      }
213    }
214  }
215
216  /**
217   * @brief moves one entry down in the history
218   */
219  void ShellInput::historyMoveDown()
220  {
221    if (!this->historyScrolling)
222      return;
223    if (!this->history.empty() && this->historyIT != --this->history.end())
224    {
225      std::string nextElem = *(++this->historyIT);
226      /*    if (nextElem == NULL) /// TODO FIX STD
227        return;
228      else */
229      {
230        this->flush();
231        this->setInputText(nextElem);
232      }
233    }
234  }
235
236
237  /**
238   * @brief prints out some nice help about the Shell
239   */
240  void ShellInput::help(const std::string& className, const std::string& functionName)
241  {
242    printf("%s::%s\n", className.c_str(), functionName.c_str());
243
244    if (className.empty())
245    {
246      PRINT(0)("Help for the most important Shell-commands\n");
247      PRINT(0)("F1 - HELP; F2 - DEBUG; '`' - open/close shell\n");
248      PRINT(0)("input order:\n");
249      PRINT(0)("ClassName [objectName] function [parameter1, [parameter2 ...]]  or\n");
250      PRINT(0)("Alias [parameter]\n");
251      PRINT(0)("- Also try 'help className'");
252    }
253    else if (!className.empty() && functionName.empty())
254    {
255      ShellCommandClass::help(className);
256      //PRINTF(1)("%s::%s\n", className, functionName);
257    }
258  }
259
260  /**
261   * @brief ticks the ShellInput
262   * @param dt the time passed since the last update
263   */
264  void ShellInput::tick(float dt)
265  {
266    if (this->delayed > 0.0)
267      this->delayed -= dt;
268    else if (this->pressedKey != SDLK_FIRST )
269    {
270      this->delayed = this->repeatRate;
271      switch (this->pressedKey )
272      {
273        case SDLK_BACKSPACE:
274          this->removeCharacters(1);
275          break;
276        case SDLK_UP:
277          this->historyMoveUp();
278          break;
279        case SDLK_DOWN:
280          this->historyMoveDown();
281          break;
282        default:
283          {
284            if (likely(pressedKey < 127))
285              this->addCharacter(this->pressedKey);
286          }
287      }
288    }
289  }
290
291  /**
292   * @brief listens for some event
293   * @param event the Event happened
294   */
295  void ShellInput::process(const Event &event)
296  {
297    if (event.bPressed)
298    {
299      PRINTF(5)("Shell received command %s\n", SDLKToKeyname(event.type).c_str());
300      if (event.type == SDLK_F1)
301        this->help();
302      else if (event.type == SDLK_F2)
303      {
304        ;//this->debug();
305      }
306      else if (event.type == SDLK_UP)
307      {
308        this->historyMoveUp();
309        this->pressedKey = event.type;
310        this->pressedEvent = event.type;
311      }
312      else if (event.type == SDLK_DOWN)
313      {
314        this->historyMoveDown();
315        this->pressedKey = event.type;
316        this->pressedEvent = event.type;
317      }
318      else if (event.type == SDLK_TAB)
319      {
320        this->completion.autoComplete(this->inputLine);
321        this->setText(this->inputLine);
322      }
323      else if (event.type == SDLK_BACKSPACE)
324      {
325        this->delayed = this->repeatDelay;
326        this->pressedKey = SDLK_BACKSPACE;
327        this->pressedEvent = SDLK_BACKSPACE;
328        this->removeCharacters(1);
329      }
330      else if (event.type == SDLK_RETURN)
331      {
332        this->executeCommand();
333        this->pressedKey = event.type;
334        this->pressedEvent = event.type;
335      }
336      // any other keyboard key
337      else if (likely(event.type < 127))
338      {
339        this->addCharacter(event.x);
340        this->pressedKey = event.x;
341        this->pressedEvent = event.type;
342      }
343      this->delayed = this->repeatDelay;
344    }
345    else // if(!event.bPressed)
346    {
347      if (this->pressedEvent == event.type)
348      {
349        this->pressedEvent = 0;
350        this->pressedKey = 0;
351        this->delayed = 0.0;
352      }
353    }
354  }
355
356}
Note: See TracBrowser for help on using the repository browser.