Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: merged the christmas branche to the trunk
merged with command:
svn merge -r6165:HEAD christmas_branche/ ../trunk/
no conflicts

File size: 8.9 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 "compiler.h"
29#include "stdlibincl.h"
[5180]30#include "key_names.h"
[5179]31
[5180]32
[1856]33using namespace std;
[1853]34
[5202]35SHELL_COMMAND(help, ShellInput, help)
36    ->describe("retrieve some help about the input mode")
37    ->setAlias("help");
[5237]38
[3245]39/**
[5249]40 * constructor
41 * this also generates a ShellCompletion automatically.
[3245]42*/
[5306]43ShellInput::ShellInput () : Text ((const char*)NULL)
[3365]44{
[5179]45  this->pressedKey = SDLK_FIRST;
[5202]46  this->setClassID(CL_SHELL_INPUT, "ShellInput");
[4320]47
[5179]48  this->inputLine = new char[1];
49  this->inputLine[0] = '\0';
[5784]50  this->historyIT = this->history.begin();
[5245]51  this->setHistoryLength(50);
[5243]52  this->historyScrolling = false;
[5180]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++)
[5309]59  {
60    if (!evh->isSubscribed(ES_SHELL, i))
61      evh->subscribe(this, ES_SHELL, i);
62  }
[5184]63  this->completion = new ShellCompletion(this);
[3365]64}
[1853]65
[3245]66/**
[4838]67 * standard deconstructor
[3245]68*/
[5178]69ShellInput::~ShellInput ()
[3543]70{
71  // delete what has to be deleted here
[5181]72  delete[] this->inputLine;
73  delete this->completion;
[5182]74
[5784]75  while (!this->history.empty())
[5182]76  {
[5784]77    delete[] this->history.front();
78    this->history.pop_front();
[5182]79  }
[3543]80}
[5179]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/**
[5244]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/**
[5179]129 * adds one character to the inputLine
130 * @param character the character to add to the inputLine
131 */
132void ShellInput::addCharacter(char character)
133{
[5244]134  if (this->historyScrolling)
135  {
[5784]136    delete[] this->history.back();
137    this->history.pop_back();
[5244]138    this->historyScrolling = false;
139  }
140
[5182]141  char* addCharLine = new char[strlen(this->inputLine)+2];
[5179]142
143  sprintf(addCharLine, "%s%c", this->inputLine, character);
[5182]144  delete[] this->inputLine;
[5179]145  this->inputLine = addCharLine;
[5182]146  this->setText(this->inputLine, true);
[5179]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{
[5244]155  if (this->historyScrolling)
156  {
[5784]157    delete[] this->history.back();
158    this->history.pop_back();
[5244]159    this->historyScrolling = false;
160  }
161
[5182]162  char* addCharLine = new char[strlen(this->inputLine)+strlen(characters)+1];
[5179]163
164  sprintf(addCharLine, "%s%s", this->inputLine, characters);
[5182]165  delete[] this->inputLine;
[5179]166  this->inputLine = addCharLine;
[5182]167  this->setText(this->inputLine, true);
[5179]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{
[5244]176  if (this->historyScrolling)
177  {
[5784]178    delete[] this->history.back();
179    this->history.pop_back();
[5244]180    this->historyScrolling = false;
181  }
182
[5179]183  if (strlen(this->inputLine) == 0)
184    return;
185
186  if (characterCount > strlen(this->inputLine))
187    characterCount = strlen(this->inputLine);
188
[5182]189  char* removeCharLine = new char[strlen(this->inputLine)-characterCount+1];
[5179]190
[5182]191  strncpy(removeCharLine, this->inputLine, strlen(this->inputLine)-characterCount);
192  removeCharLine[strlen(this->inputLine)-characterCount] = '\0';
193  delete[] this->inputLine;
[5179]194  this->inputLine = removeCharLine;
[5182]195  this->setText(this->inputLine, true);
[5179]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
[5369]206  if (strlen(this->inputLine) == 0)
207    return false;
208
[5179]209  char* newCommand = new char[strlen(this->inputLine)+1];
210  strcpy(newCommand, this->inputLine);
211
[5636]212  ShellCommand::execute(newCommand);
[5369]213
[5243]214  // removing the eventually added Entry (from scrolling) to the List
215  if (this->historyScrolling)
216  {
[5784]217    delete[] this->history.back();
218    this->history.pop_back();
[5243]219    this->historyScrolling = false;
220  }
221
222  // adding the new Command to the History
[5784]223  this->history.push_back(newCommand);
224  if (this->history.size() > this->historyLength)
[5243]225  {
[5784]226    delete[] this->history.front();
227    this->history.pop_front();
[5243]228  }
229
[5179]230  this->flush();
231
[5369]232  return true;
[5179]233}
234
[5180]235
236/**
[5243]237 * moves one entry up in the history.
238 */
239void ShellInput::historyMoveUp()
240{
241  if (!this->historyScrolling)
242  {
[5244]243    char* currentText = new char[strlen(this->inputLine)+1];
244    strcpy(currentText, this->inputLine);
[5784]245    this->history.push_back(currentText);
[5243]246    this->historyScrolling = true;
[5785]247    this->historyIT = --this->history.end();
[5243]248  }
249
[5785]250  if(this->historyIT != this->history.begin())
[5243]251  {
[5785]252    char* prevElem = *(--this->historyIT);
253    if (prevElem == NULL)
254      return;
255    else
256    {
257      this->flush();
258      this->setInputText(prevElem);
259    }
[5243]260  }
261}
262
263/**
264 * moves one entry down in the history
265 */
266void ShellInput::historyMoveDown()
267{
268  if (!this->historyScrolling)
269    return;
[5785]270  if (this->historyIT != this->history.end())
[5243]271  {
[5785]272    char* nextElem = *(++this->historyIT);
273    if (nextElem == NULL)
274      return;
275    else
276    {
277      this->flush();
278      this->setInputText(nextElem);
279    }
[5243]280  }
281}
282
283
284/**
[5180]285 * prints out some nice help about the Shell
286 */
[5204]287void ShellInput::help(const char* className, const char* functionName)
[5180]288{
[5207]289  printf("%s::%s\n", className, functionName);
290
[5204]291  if (strlen(className) == 0)
292  {
293    PRINT(0)("Help for the most important Shell-commands\n");
[5248]294    PRINT(0)("F1 - HELP; F2 - DEBUG; '`' - open/close shell\n");
[5204]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  }
[5180]305}
306
[5197]307/**
308 * ticks the ShellInput
309 * @param dt the time passed since the last update
310 */
[5180]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;
[5786]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    }
[5180]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)
[5786]350    {
[5248]351      ;//this->debug();
[5786]352    }
[5243]353    else if (event.type == SDLK_UP)
[5786]354    {
[5243]355      this->historyMoveUp();
[5786]356      this->pressedKey = event.type;
357    }
[5243]358    else if (event.type == SDLK_DOWN)
[5786]359    {
[5243]360      this->historyMoveDown();
[5786]361      this->pressedKey = event.type;
362    }
[5180]363    else if (event.type == SDLK_TAB)
[5184]364      this->completion->autoComplete();
[5180]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)
[5786]372    {
[5180]373      this->executeCommand();
[5786]374      this->pressedKey = event.type;
375    }
[5244]376    // any other keyboard key
[5180]377    else if (likely(event.type < 127))
378    {
[5786]379      this->addCharacter(event.x);
380      this->pressedKey = event.x;
[5180]381    }
[5786]382    this->delayed = this->repeatDelay;
[5180]383  }
384  else // if(!event.bPressed)
385  {
[5787]386    if (this->pressedKey == event.x || this->pressedKey == event.type)
[5180]387    {
[5786]388      this->pressedKey = 0;
[5180]389      this->delayed = 0.0;
390    }
391  }
392}
Note: See TracBrowser for help on using the repository browser.