Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/std/src/lib/shell/shell_input.cc @ 7207

Last change on this file since 7207 was 7207, checked in by bensch, 18 years ago

orxonox/trunk: evil was within

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