Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: splitted shell_command into shell_command and shell_command_class

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