Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: now it is possible to get old commands from the List

File size: 8.2 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 * standard constructor
41 * @todo this constructor is not jet implemented - do it
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->historyLength = 10;
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 * adds one character to the inputLine
111 * @param character the character to add to the inputLine
112 */
113void ShellInput::addCharacter(char character)
114{
115  char* addCharLine = new char[strlen(this->inputLine)+2];
116
117  sprintf(addCharLine, "%s%c", this->inputLine, character);
118  delete[] this->inputLine;
119  this->inputLine = addCharLine;
120  this->setText(this->inputLine, true);
121}
122
123/**
124 * adds multiple Characters to thr inputLine
125 * @param characters a \\0 terminated char-array to add to the InputLine
126 */
127void ShellInput::addCharacters(const char* characters)
128{
129  char* addCharLine = new char[strlen(this->inputLine)+strlen(characters)+1];
130
131  sprintf(addCharLine, "%s%s", this->inputLine, characters);
132  delete[] this->inputLine;
133  this->inputLine = addCharLine;
134  this->setText(this->inputLine, true);
135}
136
137/**
138 * removes characterCount characters from the InputLine
139 * @param characterCount the count of Characters to remove from the input Line
140 */
141void ShellInput::removeCharacters(unsigned int characterCount)
142{
143  if (strlen(this->inputLine) == 0)
144    return;
145
146  if (characterCount > strlen(this->inputLine))
147    characterCount = strlen(this->inputLine);
148
149  char* removeCharLine = new char[strlen(this->inputLine)-characterCount+1];
150
151  strncpy(removeCharLine, this->inputLine, strlen(this->inputLine)-characterCount);
152  removeCharLine[strlen(this->inputLine)-characterCount] = '\0';
153  delete[] this->inputLine;
154  this->inputLine = removeCharLine;
155  this->setText(this->inputLine, true);
156}
157
158/**
159 * executes the command stored in the inputLine
160 * @return true if the command was commited successfully, false otherwise
161 */
162bool ShellInput::executeCommand()
163{
164  ShellBuffer::addBufferLineStatic("Execute Command: %s\n", this->inputLine);
165
166  char* newCommand = new char[strlen(this->inputLine)+1];
167  strcpy(newCommand, this->inputLine);
168
169  // removing the eventually added Entry (from scrolling) to the List
170  if (this->historyScrolling)
171  {
172    delete[] this->history->lastElement();
173    this->historyScrolling = false;
174  }
175
176  // adding the new Command to the History
177  this->history->add(newCommand);
178  if (this->history->getSize() > this->historyLength)
179  {
180    delete[] this->history->firstElement();
181    this->history->remove(this->history->firstElement());
182  }
183
184  ShellCommandBase::execute(this->inputLine);
185
186  this->flush();
187
188  return false;
189}
190
191
192/**
193 * moves one entry up in the history.
194 */
195void ShellInput::historyMoveUp()
196{
197  if (!this->historyScrolling)
198  {
199    char* newCommand = new char[strlen(this->inputLine)+1];
200    strcpy(newCommand, this->inputLine);
201    this->history->add(newCommand);
202    this->historyScrolling = true;
203    this->historyIT->lastElement();
204  }
205
206  char* prevElem = this->historyIT->prevStep();
207  if (prevElem == NULL)
208    return;
209  else
210  {
211    this->flush();
212    this->addCharacters(prevElem);
213  }
214
215}
216
217/**
218 * moves one entry down in the history
219 */
220void ShellInput::historyMoveDown()
221{
222  if (!this->historyScrolling)
223    return;
224  char* nextElem = this->historyIT->nextStep();
225  if (nextElem == NULL)
226    return;
227  else
228  {
229    this->flush();
230    this->addCharacters(nextElem);
231  }
232}
233
234
235/**
236 * prints out some nice help about the Shell
237 */
238void ShellInput::help(const char* className, const char* functionName)
239{
240  printf("%s::%s\n", className, functionName);
241
242  if (strlen(className) == 0)
243  {
244    PRINT(0)("Help for the most important Shell-commands\n");
245    PRINT(0)("F1 - HELP; F2 - DEBUG; ` - open/close shell\n");
246    PRINT(0)("input order:\n");
247    PRINT(0)("ClassName [objectName] function [parameter1, [parameter2 ...]]  or\n");
248    PRINT(0)("Alias [parameter]\n");
249    PRINT(0)("- Also try 'help className'");
250  }
251  else if (strlen (className) > 0 && strlen (functionName) == 0)
252  {
253    ShellCommandClass::help(className);
254    //PRINTF(1)("%s::%s\n", className, functionName);
255  }
256}
257
258/**
259 * ticks the ShellInput
260 * @param dt the time passed since the last update
261 */
262void ShellInput::tick(float dt)
263{
264  if (this->delayed > 0.0)
265    this->delayed -= dt;
266  else if (this->pressedKey != SDLK_FIRST )
267  {
268    this->delayed = this->repeatRate;
269    if (this->pressedKey == SDLK_BACKSPACE)
270      this->removeCharacters(1);
271    else if (pressedKey < 127)
272      this->addCharacter(this->pressedKey);
273  }
274}
275
276/**
277 * listens for some event
278 * @param event the Event happened
279 */
280void ShellInput::process(const Event &event)
281{
282  if (event.bPressed)
283  {
284    PRINTF(5)("Shell received command %s\n", SDLKToKeyname(event.type));
285    if (event.type == SDLK_F1)
286      this->help();
287    else if (event.type == SDLK_F2)
288      this->debug();
289    else if (event.type == SDLK_UP)
290      this->historyMoveUp();
291    else if (event.type == SDLK_DOWN)
292      this->historyMoveDown();
293    else if (event.type == SDLK_TAB)
294      this->completion->autoComplete();
295    else if (event.type == SDLK_BACKSPACE)
296    {
297      this->delayed = this->repeatDelay;
298      this->pressedKey = SDLK_BACKSPACE;
299      this->removeCharacters(1);
300    }
301    else if (event.type == SDLK_RETURN)
302      this->executeCommand();
303    /*
304    else if (event.type == SDLK_UP)
305    {
306//      this->flushInputLine();
307    tIterator<char>* iterator = this->commandList->getIterator();
308    char* command = iterator->lastElement();
309    while (command)
310    {
311    if (!strcmp (command, inputLine))
312    {
313    inputLine = iterator->prevElement();
314    return;
315  }
316    command = iterator->prevElement();
317  }
318    inputLine = iterator->lastElement();
319  }
320    */
321    else if (likely(event.type < 127))
322    {
323      Uint8 *keystate = SDL_GetKeyState(NULL);
324      this->delayed = this->repeatDelay;
325      if (unlikely( keystate[SDLK_LSHIFT] || keystate[SDLK_RSHIFT] ))
326      {
327        this->pressedKey = event.type-32;
328        this->addCharacter(event.type-32);
329      }
330      else
331      {
332        this->pressedKey = event.type;
333        this->addCharacter(event.type);
334      }
335    }
336  }
337  else // if(!event.bPressed)
338  {
339    if (this->pressedKey == event.type || (this->pressedKey == event.type - 32))
340    {
341      this->pressedKey = SDLK_FIRST;
342      this->delayed = 0.0;
343    }
344  }
345}
Note: See TracBrowser for help on using the repository browser.