Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: fixed a SegFault (that this worked before is some wonder :)

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