Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7387 was 7374, checked in by bensch, 19 years ago

orxonox/trunk: added new Files shell_completion_plugin for the new Plugin Structure.
Also created the first namespace: OrxShell

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