Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/world_entities/src/lib/shell/shell_input.cc @ 5574

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

orxonox/trunk: saver font-changing in the Shell

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