Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7722 was 7676, checked in by bensch, 19 years ago

some POD's

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