Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5721 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
RevLine 
[4744]1/*
[1853]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.
[1855]10
11   ### File Specific:
[5254]12   main-programmer: Benjamin Grauer
[1855]13   co-programmer: ...
[1853]14*/
15
[3955]16//#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_
[1853]17
[5178]18#include "shell_input.h"
[1853]19
[5181]20
21
22#include "shell_command.h"
[5639]23#include "shell_command_class.h"
[5181]24#include "shell_completion.h"
[5180]25#include "event_handler.h"
[5179]26
27#include "debug.h"
28#include "list.h"
29#include "compiler.h"
30#include "stdlibincl.h"
[5180]31#include "key_names.h"
[5179]32
[5180]33
[1856]34using namespace std;
[1853]35
[5202]36SHELL_COMMAND(help, ShellInput, help)
37    ->describe("retrieve some help about the input mode")
38    ->setAlias("help");
[5237]39
[3245]40/**
[5249]41 * constructor
42 * this also generates a ShellCompletion automatically.
[3245]43*/
[5306]44ShellInput::ShellInput () : Text ((const char*)NULL)
[3365]45{
[5179]46  this->pressedKey = SDLK_FIRST;
[5202]47  this->setClassID(CL_SHELL_INPUT, "ShellInput");
[4320]48
[5179]49  this->inputLine = new char[1];
50  this->inputLine[0] = '\0';
[5243]51  this->history = new tList<char>;
52  this->historyIT = this->history->getIterator();
[5245]53  this->setHistoryLength(50);
[5243]54  this->historyScrolling = false;
[5180]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++)
[5309]61  {
62    if (!evh->isSubscribed(ES_SHELL, i))
63      evh->subscribe(this, ES_SHELL, i);
64  }
[5184]65  this->completion = new ShellCompletion(this);
[3365]66}
[1853]67
[3245]68/**
[4838]69 * standard deconstructor
[3245]70*/
[5178]71ShellInput::~ShellInput ()
[3543]72{
73  // delete what has to be deleted here
[5181]74  delete[] this->inputLine;
75  delete this->completion;
[5182]76
[5243]77  char* histEl = this->historyIT->firstElement();
[5182]78  while (histEl != NULL)
79  {
80    delete[] histEl;
[5243]81    histEl = this->historyIT->nextElement();
[5182]82  }
[5243]83  delete this->historyIT;
84  delete this->history;
[3543]85}
[5179]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/**
[5244]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/**
[5179]134 * adds one character to the inputLine
135 * @param character the character to add to the inputLine
136 */
137void ShellInput::addCharacter(char character)
138{
[5244]139  if (this->historyScrolling)
140  {
141    delete[] this->history->lastElement();
142    this->history->remove(this->history->lastElement());
143    this->historyScrolling = false;
144  }
145
[5182]146  char* addCharLine = new char[strlen(this->inputLine)+2];
[5179]147
148  sprintf(addCharLine, "%s%c", this->inputLine, character);
[5182]149  delete[] this->inputLine;
[5179]150  this->inputLine = addCharLine;
[5182]151  this->setText(this->inputLine, true);
[5179]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{
[5244]160  if (this->historyScrolling)
161  {
162    delete[] this->history->lastElement();
163    this->history->remove(this->history->lastElement());
164    this->historyScrolling = false;
165  }
166
[5182]167  char* addCharLine = new char[strlen(this->inputLine)+strlen(characters)+1];
[5179]168
169  sprintf(addCharLine, "%s%s", this->inputLine, characters);
[5182]170  delete[] this->inputLine;
[5179]171  this->inputLine = addCharLine;
[5182]172  this->setText(this->inputLine, true);
[5179]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{
[5244]181  if (this->historyScrolling)
182  {
183    delete[] this->history->lastElement();
184    this->history->remove(this->history->lastElement());
185    this->historyScrolling = false;
186  }
187
[5179]188  if (strlen(this->inputLine) == 0)
189    return;
190
191  if (characterCount > strlen(this->inputLine))
192    characterCount = strlen(this->inputLine);
193
[5182]194  char* removeCharLine = new char[strlen(this->inputLine)-characterCount+1];
[5179]195
[5182]196  strncpy(removeCharLine, this->inputLine, strlen(this->inputLine)-characterCount);
197  removeCharLine[strlen(this->inputLine)-characterCount] = '\0';
198  delete[] this->inputLine;
[5179]199  this->inputLine = removeCharLine;
[5182]200  this->setText(this->inputLine, true);
[5179]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
[5369]211  if (strlen(this->inputLine) == 0)
212    return false;
213
[5179]214  char* newCommand = new char[strlen(this->inputLine)+1];
215  strcpy(newCommand, this->inputLine);
216
[5636]217  ShellCommand::execute(newCommand);
[5369]218
[5243]219  // removing the eventually added Entry (from scrolling) to the List
220  if (this->historyScrolling)
221  {
222    delete[] this->history->lastElement();
[5244]223    this->history->remove(this->history->lastElement());
[5243]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
[5179]235  this->flush();
236
[5369]237  return true;
[5179]238}
239
[5180]240
241/**
[5243]242 * moves one entry up in the history.
243 */
244void ShellInput::historyMoveUp()
245{
246  if (!this->historyScrolling)
247  {
[5244]248    char* currentText = new char[strlen(this->inputLine)+1];
249    strcpy(currentText, this->inputLine);
250    this->history->add(currentText);
[5243]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();
[5244]261    this->setInputText(prevElem);
[5243]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();
[5244]278    this->setInputText(nextElem);
[5243]279  }
280}
281
282
283/**
[5180]284 * prints out some nice help about the Shell
285 */
[5204]286void ShellInput::help(const char* className, const char* functionName)
[5180]287{
[5207]288  printf("%s::%s\n", className, functionName);
289
[5204]290  if (strlen(className) == 0)
291  {
292    PRINT(0)("Help for the most important Shell-commands\n");
[5248]293    PRINT(0)("F1 - HELP; F2 - DEBUG; '`' - open/close shell\n");
[5204]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  }
[5180]304}
305
[5197]306/**
307 * ticks the ShellInput
308 * @param dt the time passed since the last update
309 */
[5180]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)
[5248]336      ;//this->debug();
[5243]337    else if (event.type == SDLK_UP)
338      this->historyMoveUp();
339    else if (event.type == SDLK_DOWN)
340      this->historyMoveDown();
[5180]341    else if (event.type == SDLK_TAB)
[5184]342      this->completion->autoComplete();
[5180]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();
[5244]351    // any other keyboard key
[5180]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.