Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

oroxnox/trunk: ShellInput and ShellCompletion more c++-like

File size: 7.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*/
[7343]43ShellInput::ShellInput ()
44  : Text ("")
[3365]45{
[5179]46  this->pressedKey = SDLK_FIRST;
[5202]47  this->setClassID(CL_SHELL_INPUT, "ShellInput");
[4320]48
[7221]49  this->inputLine = "";
[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  }
[7341]63  // unsubscribe unused TODO improve.
64  evh->unsubscribe(ES_SHELL, SDLK_BACKQUOTE);
65  evh->unsubscribe(ES_SHELL, SDLK_F12);
66  evh->unsubscribe(ES_SHELL, SDLK_PAGEUP);
67  evh->unsubscribe(ES_SHELL, SDLK_PAGEDOWN);
68
[3365]69}
[1853]70
[3245]71/**
[7343]72 * @brief standard deconstructor
73 */
[5178]74ShellInput::~ShellInput ()
[3543]75{
76}
[5179]77
78/**
[7343]79 * @brief sets the Repeate-delay and rate
[5179]80 * @param repeatDelay the Delay it takes, to repeate a key
81 * @param repeatRate the rate to repeate a pressed key
82 */
83void ShellInput::setRepeatDelay(float repeatDelay, float repeatRate)
84{
85  this->repeatDelay = repeatDelay;
86  this->repeatRate = repeatRate;
87}
88
89/**
[7343]90 * @brief deletes the InputLine
[5179]91 */
92void ShellInput::flush()
93{
[7221]94  this->inputLine.clear();
95  this->setText(this->inputLine);
[5179]96}
97
98/**
[7343]99 * @brief sets the entire text of the InputLine to text
[5244]100 * @param text the new Text to set as InputLine
101 */
[7221]102void ShellInput::setInputText(const std::string& text)
[5244]103{
[7221]104  this->inputLine = text;
105  this->setText(this->inputLine);
[5244]106}
107
108
109/**
[7343]110 * @brief adds one character to the inputLine
[5179]111 * @param character the character to add to the inputLine
112 */
113void ShellInput::addCharacter(char character)
114{
[5244]115  if (this->historyScrolling)
116  {
[5784]117    this->history.pop_back();
[5244]118    this->historyScrolling = false;
119  }
120
[7221]121  this->inputLine += character;
122  this->setText(this->inputLine);
[5179]123}
124
125/**
[7343]126 * @brief adds multiple Characters to thr inputLine
[5179]127 * @param characters a \\0 terminated char-array to add to the InputLine
128 */
[7221]129void ShellInput::addCharacters(const std::string& characters)
[5179]130{
[5244]131  if (this->historyScrolling)
132  {
[5784]133    this->history.pop_back();
[5244]134    this->historyScrolling = false;
135  }
136
[7221]137  this->inputLine += characters;
138  this->setText(this->inputLine);
[5179]139}
140
141/**
[7343]142 * @brief removes characterCount characters from the InputLine
[5179]143 * @param characterCount the count of Characters to remove from the input Line
144 */
145void ShellInput::removeCharacters(unsigned int characterCount)
146{
[5244]147  if (this->historyScrolling)
148  {
[5784]149    this->history.pop_back();
[5244]150    this->historyScrolling = false;
151  }
[7221]152  if (this->inputLine.size() < characterCount)
153    characterCount = this->inputLine.size();
[5244]154
[7221]155  this->inputLine.erase(this->inputLine.size() - characterCount, this->inputLine.size());
156  this->setText(this->inputLine);
[5179]157}
158
159/**
[7343]160 * @brief executes the command stored in the inputLine
[5179]161 * @return true if the command was commited successfully, false otherwise
162 */
163bool ShellInput::executeCommand()
164{
[7221]165  ShellBuffer::addBufferLineStatic("Execute Command: %s\n", this->inputLine.c_str());
[5179]166
[7221]167  if (this->inputLine.empty())
[5369]168    return false;
169
[7221]170  ShellCommand::execute(this->inputLine);
[5179]171
[5243]172  // removing the eventually added Entry (from scrolling) to the List
173  if (this->historyScrolling)
174  {
[5784]175    this->history.pop_back();
[5243]176    this->historyScrolling = false;
177  }
178
179  // adding the new Command to the History
[7221]180  this->history.push_back(this->inputLine);
[5784]181  if (this->history.size() > this->historyLength)
[5243]182  {
[5784]183    this->history.pop_front();
[5243]184  }
185
[5179]186  this->flush();
187
[5369]188  return true;
[5179]189}
190
[5180]191
192/**
[7343]193 * @brief moves one entry up in the history.
[5243]194 */
195void ShellInput::historyMoveUp()
196{
197  if (!this->historyScrolling)
198  {
[7221]199    this->history.push_back(this->inputLine);
[5243]200    this->historyScrolling = true;
[5785]201    this->historyIT = --this->history.end();
[5243]202  }
203
[5785]204  if(this->historyIT != this->history.begin())
[5243]205  {
[7221]206    std::string prevElem = *(--this->historyIT);
207    /*if (prevElem == NULL) /// TODO STD
[5785]208      return;
[7221]209    else */
[5785]210    {
211      this->flush();
212      this->setInputText(prevElem);
213    }
[5243]214  }
215}
216
217/**
[7343]218 * @brief moves one entry down in the history
[5243]219 */
220void ShellInput::historyMoveDown()
221{
222  if (!this->historyScrolling)
223    return;
[7342]224  if (!this->history.empty() && this->historyIT != --this->history.end())
[5243]225  {
[7221]226    std::string nextElem = *(++this->historyIT);
227    /*    if (nextElem == NULL) /// TODO FIX STD
[5785]228      return;
[7221]229    else */
[5785]230    {
231      this->flush();
232      this->setInputText(nextElem);
233    }
[5243]234  }
235}
236
237
238/**
[7343]239 * @brief prints out some nice help about the Shell
[5180]240 */
[7221]241void ShellInput::help(const std::string& className, const std::string& functionName)
[5180]242{
[7221]243  printf("%s::%s\n", className.c_str(), functionName.c_str());
[5207]244
[7221]245  if (className.empty())
[5204]246  {
247    PRINT(0)("Help for the most important Shell-commands\n");
[5248]248    PRINT(0)("F1 - HELP; F2 - DEBUG; '`' - open/close shell\n");
[5204]249    PRINT(0)("input order:\n");
250    PRINT(0)("ClassName [objectName] function [parameter1, [parameter2 ...]]  or\n");
251    PRINT(0)("Alias [parameter]\n");
252    PRINT(0)("- Also try 'help className'");
253  }
[7221]254  else if (!className.empty() && functionName.empty())
[5204]255  {
256    ShellCommandClass::help(className);
257    //PRINTF(1)("%s::%s\n", className, functionName);
258  }
[5180]259}
260
[5197]261/**
[7343]262 * @brief ticks the ShellInput
[5197]263 * @param dt the time passed since the last update
264 */
[5180]265void ShellInput::tick(float dt)
266{
267  if (this->delayed > 0.0)
268    this->delayed -= dt;
269  else if (this->pressedKey != SDLK_FIRST )
270  {
271    this->delayed = this->repeatRate;
[5786]272    switch (this->pressedKey )
273    {
274      case SDLK_BACKSPACE:
275        this->removeCharacters(1);
276        break;
277      case SDLK_UP:
278        this->historyMoveUp();
279        break;
280      case SDLK_DOWN:
281        this->historyMoveDown();
282        break;
283      default:
284      {
285        if (likely(pressedKey < 127))
286          this->addCharacter(this->pressedKey);
287      }
288    }
[5180]289  }
290}
291
292/**
[7343]293 * @brief listens for some event
[5180]294 * @param event the Event happened
295 */
296void ShellInput::process(const Event &event)
297{
298  if (event.bPressed)
299  {
300    PRINTF(5)("Shell received command %s\n", SDLKToKeyname(event.type));
301    if (event.type == SDLK_F1)
302      this->help();
303    else if (event.type == SDLK_F2)
[5786]304    {
[5248]305      ;//this->debug();
[5786]306    }
[5243]307    else if (event.type == SDLK_UP)
[5786]308    {
[5243]309      this->historyMoveUp();
[5786]310      this->pressedKey = event.type;
311    }
[5243]312    else if (event.type == SDLK_DOWN)
[5786]313    {
[5243]314      this->historyMoveDown();
[5786]315      this->pressedKey = event.type;
316    }
[5180]317    else if (event.type == SDLK_TAB)
[7343]318    {
319      this->completion.autoComplete(this->inputLine);
320      this->setText(this->inputLine);
321    }
[5180]322    else if (event.type == SDLK_BACKSPACE)
323    {
324      this->delayed = this->repeatDelay;
325      this->pressedKey = SDLK_BACKSPACE;
326      this->removeCharacters(1);
327    }
328    else if (event.type == SDLK_RETURN)
[5786]329    {
[5180]330      this->executeCommand();
[5786]331      this->pressedKey = event.type;
332    }
[5244]333    // any other keyboard key
[5180]334    else if (likely(event.type < 127))
335    {
[5786]336      this->addCharacter(event.x);
337      this->pressedKey = event.x;
[5180]338    }
[5786]339    this->delayed = this->repeatDelay;
[5180]340  }
341  else // if(!event.bPressed)
342  {
[5787]343    if (this->pressedKey == event.x || this->pressedKey == event.type)
[5180]344    {
[5786]345      this->pressedKey = 0;
[5180]346      this->delayed = 0.0;
347    }
348  }
349}
Note: See TracBrowser for help on using the repository browser.