Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5366 was 5309, checked in by bensch, 19 years ago

orxonox/trunk: Ckeck if an Event is already subscribed via isSubscribed, and using it in the ShellInput

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