Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: stuff, that has been done (removed todo's)

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