vegastrike  0.5.1.r1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
command.cpp
Go to the documentation of this file.
1 #include "command.h"
2 #include "cs_python.h"
3 #include <pyerrors.h>
4 #include <pythonrun.h>
5 #include "gldrv/winsys.h"
6 #include "main_loop.h"
7 #include "vs_random.h"
8 #include "python/python_class.h"
9 #include <vector>
10 
11 #ifdef HAVE_SDL
12 # include <SDL/SDL.h>
13 #endif
14 
15 #include <string>
16 #include <iomanip>
17 #include <sstream>
18 
19 using std::string;
20 using std::cout;
21 using std::endl;
22 using std::ostringstream;
23 using std::ios;
24 using std::setiosflags;
25 using std::setw;
26 using std::exception;
27 
28 //Introduction Comments {{{
29 //The {{{ and }}} symbols are VIM Fold Markers.
30 //They FOLD up the page so a user only needs to see a general outline of the entire huge file
31 //and be able to quickly get to exactly what part they need.
32 //It helps when a 300 line function is wrapped up to a one line comment
33 /*
34  * Index:
35  * 1) Example Commands
36  * 2) Argument Types
37  * 3) PolyMorphic Behavior
38  * 4) Multiple Arguments
39  * 5) Multiple Command Processors made easy with Inheritence
40  */
41 /* *******************************************************************
42 * 1) Example Commands:
43 * class WalkControls {
44 * public:
45 * WalkControls() {
46 * // ****************************** 1
47 * Functor<WalkControls> *ctalk = new Functor<WalkControls>(this, &WalkControls::talk);
48 * // Please notice the NEW, do _not_ delete this. It will be deleted for
49 * // you when remCommand is run, or when the command processor destructor
50 * // is called :)
51 *
52 *
53 *
54 *
55 *
56 * CommandInterpretor->addCommand(ctalk, "say", ARG_1STR); //1 c++ string argument,
57 * // CommandInterpretor is a global (defined in vs_globals.h or
58 * // vegastrike.h (don't remember which) and created in main.cpp
59 * // ******************************* 2
60 * Functor<WalkControls> *ctalk = new Functor<WalkControls>(this, &WalkControls::talk);
61 * CommandInterpretor->addCommand(ctalk, "order", ARG_1STRVEC);
62 * // easy way to scroll through arguments to make logical desicions aboot them.
63 * // use std::vector<std::string *>::iterator iter = d->begin();
64 * // and (*(iter))->c_str() or (*(iter))->compare etc. iter++ to go up
65 * // iter-- to go down, and if(iter >= d->end()) to check and see if it's at the end.
66 * // ******************************* 3
67 * Functor<WalkControls> *dWalkLeft = new Functor<WalkControls>(this, &WalkControls::WalkLeft);
68 * CommandInterpretor->addCommand(dWalkLeft, "left", ARG_1BOOL);
69 * //to use this, there'd need to be a mechanism to bind
70 * //a single charactor to a full command, then when that
71 * //charactor is passed alone to execute it should translate it to
72 * //whatever command it's bound to, then it can pass it to findCommand
73 * //and call findCommand("left", 0) instead of findCommand("a", 0);
74 * // ******************************** That's enuf.
75 * // Full list of supported argument types can be seen in commands.h (bottom)
76 * // for information about the actual supported callback methods
77 * // (all the functions below are be compatible, and then some)
78 * // see functors.h, commandI::fexecute, and the enum at the bottom of command.h
79 * }
80 * void talk(std::string &in);
81 * void order(std::vector<std::string *> *d);
82 * void WalkLeft(bool KeyIsDown);
83 * void WalkRight(bool KeyIsDown);
84 * void Jump(bool KeyIsDown);
85 * void setGravity(int &amount);
86 * }
87 * Then to get the commands to initiate, simply:
88 * static WalkControls done; // and when the program starts, this variable will be made.
89 ******************************************************************* */
90 
91 /* *******************************************************************
92 * 2) Argument type details
93 *
94 * Usually:
95 * std::string &entire_command_typed
96 * std::vector<std::string *> *Commands_Typed_BrokenUp_At_Spaces
97 * bool is_the_Key_Pressed_Down_Or_Up(True for down, false for up)
98 * int first argument translated through atoi, or 0 if first word is not entered
99 * const char * first argument, if there is no first argument, it sends NULL
100 * const char *, const char * first two arguments, sends NULl if not defined
101 *
102 * are enough.
103 *
104 * If you use std::string &, the name of your command will be at
105 * string &in[0]; followed by a space
106 *
107 * if you use std::vector<std::string *>* you can use:
108 * std::vector<std::string *>::iterator iter = in->begin();
109 * the very first iterator will point to the name of the command entered
110 * not what the user inputed, findCommand will auto-finish commands entered
111 * then use in->size() to see how many arguments were passed, and do whatever
112 *
113 * 1 Bool is for single keys bound to commands. An external layor to translate
114 * the number of a key when pressed from sdl to a command is needed to
115 * use this practically
116 *
117 *
118 *
119 * A note about const char * types. If the user doesn't sent input, it
120 * will pass NULL. So if you have two of them, and the user sends no
121 * input, it will send them both as NULL. If the user types one
122 * argument, the second one will be NULL, the first will be their argument.
123 * If your function needs an argument, and NULL is passed, you can safely
124 * throw an error message, either an std::exception or a const char *
125 * so you can do: if(argument1 == NULL && argument2 == NULL) throw "I need at least one argument!";
126 * else if(argument2 == NULL) do_something_with_argument1, or maybe throw an error
127 * else we_have_both_arg1_and_arg2
128 * const char *'s are the prefered method, std::exceptions get other error
129 * text appended to them, and is mostly for detecting bugs in the std library
130 *
131 *
132 *
133 * If you need to add a new argument type, or callback type, see functors.h
134 * (Callbacks don't have to be on objects, there just is no support for that
135 * in the functor class, and can be added as needed to make callbacks to existing
136 * just do the 4 steps to makeing a new argument type in the functor, ignore the object part, it should be fairly trivial.
137 *
138 * Sometimes this is useful, like with servers when passing a socket arond
139 * to functions to complete requests.
140 *
141 *
142 * To use a return value if support is added, the functor Call method returns
143 * a void *, which by default is a casted reference to the return_type object
144 * (see functors.h again) so it can be casted back with the string named "s"
145 * extracted, which could have data if someone made a function that returned
146 * an std::string and set it.
147 *
148 *
149 * )
150 ******************************************************************* */
151 /* *******************************************************************
152 * (****** 3 ******)
153 * PolyMorphic Behaviors:
154 * If you have the command "left" on the object "flight-mode"
155 * the flight-mode object may always be in memory, but imagine you want to land
156 * on a planet, where the command "left" might need to toggle a different vector
157 * to get it to perform different physics equations.
158 * You could create a new object: (psuedo)
159 * class walkOnPlanet {
160 * Functor<WOP> *leftCommand;
161 * walkOnPlanet() {
162 * leftCommand = new Functor<WOP>(This, &walkOnPlanet::left);
163 * CommandInterpretor->addCommand(leftCommand, "left"); //adding the second left command will automagically override the first
164 * }
165 * ~walkOnPlanet() {
166 * CommandInterpretor->remCommand(leftCommand); //by passing it by pointer we can be assured the right one will be removed, in case commands are added/removed out of order
167 * }
168 * void left(bool isDown) {
169 * perform different ops
170 * }
171 *
172 * then create it, and it will ovverride the existing command with the access word "left"
173 *
174 ******************************************************************* */
175 
176 /*
177  * (***** 4 *****)
178  * A quick comment on Multiple Arguments
179  * Imagine you have:
180  * void MyClass::myFunction(const char *arg1, const char *arg2)
181  *
182  * if you do:
183  * myFunction "a four word name" "some arguments"
184  * it will send "a four word name" as arg1,
185  * and "some arguments" as arg2 (With the quotes edited out.)
186  *
187  * Everything except std::string does this, std::string passess the entire input string
188  * If you need a quote to pass through the command processor to a function, use \" the same way you'd pass a quote to a variable in c++ ;)
189  *
190  *
191  */
192 /* ********************
193  * (****** 5 ******)
194  * Multiple Command Processors:
195  * Creating a custom command processor to do job X.
196  * Example abstract usage: Imbedded HTTP servers, objects which can be placed in game that can execute their own commands (then "taken-over" or "possessed", or given somehow to the player to be used)
197  *
198  * Example with psuedo:
199  * class HTTPserver : public commandI {
200  * class clients {
201  * friend class HTTPserver;
202  * friend class std::vector<clients>;
203  * clients(int &sock, char *addy) {
204  * socket = sock;
205  * ipaddress.append(addy);
206  * };
207  * clients(const clients &in) {
208  * socket = in.socket;
209  * ipaddress.append(in.ipaddress);
210  * }
211  * int socket;
212  * std::string ipaddress;
213  * };
214  * class Packet {
215  * public:
216  * int socket;
217  * char *data;
218  * };
219  * public:
220  * HTTPserver(char *port) : commandI() {
221  * setupserveronport(atoi(port));
222  * Functor<HTTPserver> *get = new Functor<HTTPserver>(this, &HTTPserver::GET);
223  * commandI::addCommand(get, "GET");
224  *
225  * Functor<HTTPserver> *post = new Functor<HTTPserver(this, &HTTPserver::POST);
226  * commandI::addCommand(post, "POST");
227  *
228  *
229  * fork() {
230  * while(SOMEBREAKVARIABLE)
231  * runserver();
232  * }
233  * }
234  * std::vector<clients> myclients;
235  * runServer() {
236  * bool incfound = socketlayor->listen4new();
237  * if(incfound) {
238  * while(clients newclient(socketlayor->getANewOne() ) != NULL)
239  * {
240  * myclients.push_back(newclient);
241  * }
242  * }
243  * Packet *incomingpacket = socketlayor->listen();
244  * if(incomingpacket != NULL) {
245  * std::string ConvertDataToString(incomingpacket->data);
246  * std::string buffer;
247  * for(unsigned int counter = 0; counter < CDTS.size(); counter++)
248  * {
249  * if(CDTS[counter] == '\n') {
250  * commandI::execute(buffer, true, socket);
251  * buffer.erase();
252  * } else {
253  * buffer += CDTS[counter];
254  * }
255  * } if(buffer.size() > 0) { //POSTS don't end post data with anything, so if we want to process it, we do it now. Headers all terminate with \r\n.
256  * commandI::execute(buffer, true, socket);
257  * }
258  *
259  * delete incomingpacket;
260  * }
261  * }
262  * void GET(std::string &page, int socket) {
263  * securityformat(page);
264  * std::string getPage = Utilities.loadFile(page);
265  * std::string buildHeader(page, getPage.size(), option1, option2, etc);
266  * socketlayor->send(buildheader, socket);
267  * socketlayor->send(getPage, socket);
268  * }
269  * void POST(std::string &page, int socket) {
270  * setMode(POST) ;// do whatever we want posts to do on the server
271  * }
272  * }
273  ********************* */
274 //}}}
275 
276 //Coms object {{{
277 
278 
280 {
281  functor = t_in;
282 }
283 
284 coms::coms( coms *oldCom )
285 {
286  if (oldCom->Name.size() > 0)
287  Name.append( oldCom->Name );
288  functor = oldCom->functor;
289 }
290 
291 coms::coms( const coms &in )
292 {
293  if (in.Name.size() > 0)
294  Name.append( in.Name );
295  functor = in.functor;
296 }
297 
299 {
300 //std::cout << "Destroying coms object\n";
301 }
302 
303 //}}}
304 class HoldCommands;
306 bool rcCMDEXISTS = false; //initialize to false
307 
308 class HoldCommands //Hold the commands here{{{
309 {
310 /*
311  * // Large comment about why and what {{{
312  * what:
313  * It creates "procs" objects which hold a pointer to a memory address(of the command processor) and the list of commands
314  * that processor has. It holds this list of "procs" in a global variable, which has a single bool to notify command
315  * interpretors when it needs to be created (So if there are 0 command interpretors in memory while the program is running,
316  * HoldCommands won't take up any space as a running object)
317  *
318  * It contains 3 utility functions which take the "this" pointer
319  * addCMD: adds a command and takes a this pointer, if the command processor is not found in HoldCommands vector, it
320  * creates a new one, adds the command to the new one. Otherwise it adds it to the proper one.
321  * popProc: Pop a processor off the list (Not the usual pop_back type, it actually calls std::vector::erase(iterator))
322  * getProc: returns the procs object owned by the command interpretor calling it
323  *
324  * why:
325  * To support multiple command processors, while still allowing commands to be added to a _Global_ command processor or two
326  * before they have allocated their internal variables and run their constructors. (If you add something to a vector
327  * on a global object before the object has initialized, that thing will get lost.)
328  * class B;
329  * extern B globalB;
330  * class A {
331  * public:
332  * A() { cout << "A created\n"; globalB.list.push_back(1); };
333  * }
334  * class B {
335  * public:
336  * B() { cout << "B created\n"; };
337  * vector<int> list;
338  * }
339  * A anA(); //A is defined BEFORE B. Very important
340  * B globalB();
341  * int main() {
342  * cout << globalB.list.size(); // gives me zero. Should be one.
343  * }
344  * (Normally, this wouldn't happen, IF we were working with just one file.
345  * But because we are working with multiple files that can be compiled in pretty much any order
346  * we have limited control of what order our globals are declared in. So we take advantage of the fact we can
347  * still run functions on a global object before it's initialized, and initialize what we need by hand at the
348  * exact time it's needed, which would be at any commandI::addCommand call, at any time.)
349  * // }}} I love folds so I can see only what I need ;) (ViM)
350  */
351  friend class commandI;
352  bool finishmeoff;
353  class procs
354  {
355 public:
356  virtual ~procs()
357  {
358  while (rc.size() > 0)
359  rc.pop_back();
360  }
361  procs( commandI *processor, coms *initcmd )
362  {
363  proc = processor;
364  rc.push_back( initcmd );
365  }
366  procs( const procs &in )
367  {
368  procs *blah = const_cast< procs* > (&in);
369  proc = blah->proc;
370  for (vector< coms >::iterator iter = blah->rc.begin(); iter < blah->rc.end(); iter++)
371  rc.push_back( ( *(iter) ) );
372  }
373  commandI *proc;
374  vector< coms >rc;
375  };
376  HoldCommands()
377  {
378  if (rcCMD != 0x0)
379  cout<<"Error, there shouldn't be 2 holdCommands objects!\n";
380  rcCMD = this;
381  finishmeoff = false;
382  }
383  vector< procs >cmds; //for multiple command processors.
384  void addCMD( coms &commandin, commandI *proc2use )
385  {
386  bool found = false;
387  for (vector< procs >::iterator iter = cmds.begin(); iter < cmds.end(); iter++)
388  if ( ( *(iter) ).proc == proc2use ) {
389  found = true;
390  ( *(iter) ).rc.insert( ( *(iter) ).rc.begin(), commandin );
391  iter = cmds.end();
392  }
393  if (!found) {
394  procs newproc( &(*proc2use), &commandin );
395  cmds.push_back( newproc );
396  }
397  }
398  void popProc( commandI *proc2use )
399  {
400  for (vector< procs >::iterator iter = cmds.begin(); iter < cmds.end(); iter++) {
401  if (proc2use == ( *(iter) ).proc)
402  cmds.erase( iter );
403  ;
404  }
405  if (cmds.size() == 0) finishmeoff = true;
406  }
407  procs * getProc( commandI *in )
408  {
409  for (vector< procs >::iterator iter = cmds.begin(); iter < cmds.end(); iter++)
410  if (in == ( *(iter) ).proc) return &( *(iter) );
411  return NULL;
412  }
413 };
414 
415 //mmoc initclientobject;
416 
417 //Formerly RegisterPythonWithCommandInterp f***ingsonofat***w***lioness;
418 
419 //We use a pointer so we can initialize it in addCommand, which can, and does
420 //run before the command interpretor constructor, and before all local variables
421 //on the command interpretor itself might be initialized.
422 
423 //}}}
424 
425 //{{{ command interpretor constructor
426 
428 {
429  cout<<"Command Interpretor Created\n\r";
430  //{{{ add some base commands
431 
432  Functor< commandI > *dprompt = new Functor< commandI > ( this, &commandI::prompt );
433  //fill with dummy function.
434  dprompt->attribs.hidden = true;
435  addCommand( dprompt, "prompt" );
436 
437  Functor< commandI > *newFunct = new Functor< commandI > ( this, &commandI::dummy );
438  newFunct->attribs.hidden = true;
439  addCommand( newFunct, "dummy" );
440 
441  Functor< commandI > *dcommands = new Functor< commandI > ( this, &commandI::pcommands );
442  addCommand( dcommands, "commands" );
443 
445  addCommand( dhelp, "help" );
446  //}}}
447  //set some local object variables {{{
448  menumode = false;
449  immortal = false;
450  console = false;
451  new RegisterPythonWithCommandInterpreter( this ); //mem leak - not cleaned up at end of program.
452  //}}}
453 }
454 
455 //}}}
456 //{{{ command interpretor destructor
457 
459 {
460  {
461  HoldCommands::procs *findme = rcCMD->getProc( this );
462  if (findme->rc.size() > 0) {
463  coms *iter = &findme->rc.back();
464  while (findme->rc.size() > 0) {
465  iter = &findme->rc.back();
466  delete iter->functor;
467  findme->rc.pop_back();
468  }
469  }
470  }
471  {
472  menu *iter;
473  while (menus.size() > 0) {
474  iter = menus.back();
475  delete iter;
476  menus.pop_back();
477  }
478  }
479  if (rcCMDEXISTS) {
480  rcCMD->popProc( this );
481  if (rcCMD->finishmeoff) {
482  rcCMDEXISTS = false;
483  delete rcCMD;
484  }
485  }
486 }
487 
488 //}}}
489 //{{{ Menu object destructor
490 
492 {
493  for (mItem *iter;
494  items.size() > 0;) {
495  iter = items.back();
496  delete iter;
497  items.pop_back();
498  }
499 }
500 
501 //}}}
502 
503 //{{{ UNFINISHED HELP COMMAND
504 
505 void commandI::help( string &helponthis )
506 {
507  string buf;
508  buf.append( "Sorry, there is no help system yet\n\r " );
509  buf.append( "But most commands are self supporting, just type them to see what they do.\n\r" );
510 //conoutf(this, &buf);
511 }
512 
513 //}}}
514 //{{{ send prompt ONLY when 0 charactors are sent with a newline
515 
517 {
518  string l;
519  l.append( "Wooooooooooo\n" );
520  conoutf( l );
521 //std::cout << "Prompt called :)\n";
522 }
523 
524 //}}}
525 //{{{ dummy function
526 
527 void commandI::dummy( vector< string* > *d )
528 {
529  //{{{
530  string outs;
531  int rand = vsrandom.genrand_int32();
532  if (rand%2 == 0)
533  outs.append( "Wtf?\n\r" );
534  else
535  outs.append( "Try: commands\n\r" );
536  conoutf( outs );
537  //}}}
538 }
539 
540 //}}}
541 //list all the commands {{{
542 
544 {
545  int x = 0;
546  ostringstream cmd;
547  cmd<<"\n\rCommands available:\n\r";
548  vector< coms >::iterator iter;
549  HoldCommands::procs *commands = rcCMD->getProc( this );
550  for (iter = commands->rc.begin(); iter < commands->rc.end(); iter++)
551  if (!( *(iter) ).functor->attribs.hidden && !( *(iter) ).functor->attribs.webbcmd) {
552  if ( ( *(iter) ).functor->attribs.immcmd == true ) {
553  if (immortal) {
554  if (x != 5) cmd<<setiosflags( ios::left )<<setw( 19 );
555  cmd<<( *(iter) ).Name.c_str();
556  x++;
557  } //we don't want to add the command if we arn't immortal
558  } else {
559  if (x != 5) cmd<<setiosflags( ios::left )<<setw( 10 );
560  cmd<<( *(iter) ).Name.c_str();
561  x++;
562  }
563  if (x == 5) {
564  cmd<<"\n\r";
565  x = 0;
566  }
567  }
568  if (x != 5)
569  cmd<<"\n\r";
570  string cmd2;
571  cmd2.append( cmd.str() );
572  conoutf( cmd2 );
573 }
574 
575 //}}}
576 //{{{ addCommand - Add a command to the interpreter
577 
578 void commandI::addCommand( TFunctor *com, const char *name )
579 {
580  cout<<"Adding command: "<<name<<endl;
581  coms *newOne = new coms( com );
582  //See the very bottom of this file for comments about possible optimization
583  newOne->Name.append( name );
584  //push the new command back the vector.
585  if (!rcCMDEXISTS && rcCMD == 0x0) {
586  if (rcCMD != 0x0)
587  cout<<"Apparently rcCMD is not 0x0.. \n";
588  rcCMD = new HoldCommands();
589  rcCMDEXISTS = true;
590  }
591  rcCMD->addCMD( *newOne, this );
592 //rcCMD->rc.push_back(newOne);
593 }
594 
595 //}}}
596 //{{{ Remove a command remCommand(char *name)
597 
598 void commandI::remCommand( char *name )
599 {
600  HoldCommands::procs *findme = rcCMD->getProc( this );
601  if (findme->rc.size() < 1) return;
602  for (vector< coms >::iterator iter = findme->rc.begin(); iter < findme->rc.end(); iter++)
603  if ( ( *(iter) ).Name.compare( name ) == 0 ) {
604  cout<<"Removing: "<<name<<endl;
605  delete ( *(iter) ).functor;
606  findme->rc.erase( iter );
607  return;
608  }
609  cout<<"Error, command "<<name
610  <<" not removed, try using the TFunctor *com version instead. Also, this is case sensitive ;)\n";
611 }
612 
614 {
615  HoldCommands::procs *findme = rcCMD->getProc( this );
616  if (findme->rc.size() < 1) return;
617  for (vector< coms >::iterator iter = findme->rc.begin(); iter < findme->rc.end(); iter++)
618  if ( ( *(iter) ).functor == com ) {
619  cout<<"Removing: "<<( *(iter) ).Name<<endl;
620  delete ( *(iter) ).functor;
621  findme->rc.erase( iter );
622  return;
623  }
624  cout<<"Error, couldn't find the command that owns the memory area: "<<com<<endl;
625 }
626 
627 //}}}
628 //{{{ Find a command in the command interpretor
629 
630 coms* commandI::findCommand( const char *comm, int &sock_in )
631 {
632  HoldCommands::procs *findme = rcCMD->getProc( this );
633  if (findme->rc.size() < 1) throw "Error, commands vector empty, this shouldn't happen!\n";
634  ostringstream in_s;
635  if (!comm) ;
636  else in_s<<comm; //this is actually a hack
637  //comm shouldn't ever be null if it gets this far.
638  //but for some fucking reason it is sometimes..
639  string name;
640  name.append( in_s.str() );
641  size_t x;
642 //remove \n and \r's (4 possible network input) {{{
643  for ( x = name.find( ' ' ); x != string::npos; x = name.find( ' ', x+1 ) )
644  name.erase( name.begin()+x );
645  for ( x = name.find( '\n' ); x != string::npos; x = name.find( '\n', x+1 ) )
646  name.erase( name.begin()+x );
647  for ( x = name.find( '\r' ); x != string::npos; x = name.find( '\r', x+1 ) )
648  name.erase( name.begin()+x );
649 //}}}
650 //if the input is less than one return prompt function{{{
651  if (name.size() < 1) {
652  vector< coms >::iterator iter = findme->rc.begin();
653  bool breaker = true;
654  while (breaker == true) {
655  if ( iter >= findme->rc.end() ) {
656  iter--;
657  breaker = false;
658  continue;
659  } else if ( ( *(iter) ).Name.compare( "prompt" ) == 0 ) {
660  return &( *(iter) );
661  } else {iter++; }}
662  return &( *(iter) ); //assign testCom to the iterator
663  }
664 //}}}
665 //transform name (the word in) to lowercase {{{
666  bool golower = true;
667  if (golower)
668  transform( name.begin(), name.end(), name.begin(), static_cast< int (*)( int ) > (tolower) );
669 //}}}
670 //Start testing command names against the command entered {{{
671  coms *fuzzymatch = NULL;
672  vector< coms >::iterator iter;
673  for (iter = findme->rc.begin(); iter < findme->rc.end(); iter++) {
674  //set the test variable to the iterator of something in the command vector
675  coms &testCom = ( ( *(iter) ) );
676  //clear the temporary buffer used for holding the name of this command
677  string temp;
678  //define a string to possibly print something to the user
679  string printer;
680  //if the length of the commands name is larger than what was entered {{{
681  if ( testCom.Name.length() >= name.length() ) {
682  //append the size of the command entered of the test commands name
683  //to the temporary test string
684  temp.append( testCom.Name, 0, name.size() );
685  //transform the partial name to lowercase
686  bool golower = true;
687  if (golower)
688  transform( temp.begin(), temp.end(), temp.begin(), static_cast< int (*)( int ) > (tolower) );
689  //compare them
690  if (temp.compare( name ) == 0 && name.size() > 0) {
691  //they match {{{
692  //If it is an immortal command
693  bool returnit = true;
694  if (testCom.functor->attribs.immcmd == true) {
695  //if we are immortal all's good, go on
696  if (immortal) {} else {
697  //if we arn't immortal move on to the next command
698  //this allows commands to have immortal/mortal versions
699  //that call different functions.
700  returnit = false;
701  }
702  //iter = findme->rc.begin();
703 //iter++;
704 //testCom = (*(iter));
705  }
706  //if it's an immortal command and we are an immortal simply don't return it.
707  if (returnit) {
708  if ( name.size() == testCom.Name.size() )
709  return &testCom;
710  if (fuzzymatch == NULL)
711  fuzzymatch = &testCom;
712  }
713  //}}}
714  }
715 //} }}}
716 //else {{{}
717  //the command entered is larger than the commands length
718  //if it's at most 1 larger try shaving off the last 1
719  //try fuzzy match
720  } else if (testCom.Name.length() < name.length() && testCom.Name.length() >= name.length()-1) {
721  temp.append( testCom.Name );
722  string commandentered2;
723  commandentered2.append( name, 0, testCom.Name.size() );
724  //transform them to lowercase
725  transform( temp.begin(), temp.end(), temp.begin(), static_cast< int (*)( int ) > (tolower) );
726  transform( commandentered2.begin(), commandentered2.end(), commandentered2.begin(),
727  static_cast< int (*)( int ) > (tolower) );
728  if (temp.compare( commandentered2 ) == 0) {
729  //they match {{{
730  //If it is an immortal command
731  bool returnit = true;
732  if (testCom.functor->attribs.immcmd == true) {
733  //if we are immortal all's good, go on
734  if (immortal) ;
735  else
736  //if we arn't immortal move on to the next command
737  returnit = false;
738  }
739  //if it's an immortal command and we are an immortal simply don't return it.
740  if (returnit)
741  if (fuzzymatch == NULL)
742  fuzzymatch = &testCom;
743  //}}}
744  }
745  }
746  //}}}
747  }
748  if (fuzzymatch != NULL) return fuzzymatch;
749 //}}}
750  iter = findme->rc.begin();
751  for (; iter < findme->rc.end(); iter++)
752  if ( ( *(iter) ).Name.find( "dummy" ) == 0 )
753  return &( *(iter) );
754  //shouldn't get here.
755  return NULL;
756 }
757 
759 //strips up command, extracts the first word and runs
760 //findCommand on it,
761 //then tries to execute the member function.
762 //If one is not found, it will call commandI::dummy() .
763 //{{{ Main execute entrace, all input comes in here, this sends it to the menusystem, then in the return at the very last line executes the fexecute function which actually parses and finds commands, if the menusystem allows. This way the menusystem can manipulate user input, ie insert command names into the input to make it go to any function.
764 bool commandI::execute( string *incommand, bool isDown, int sock_in )
765 {
766  int socket = sock_in;
767  //use the menusystem ONLY if the sock_in is the same as socket{{{
768  {
769  if (menumode && sock_in == socket) {
770  string l;
771  string y;
772  size_t x = incommand->find( " " );
773  if (x < string::npos)
774  l.append( incommand->substr( 0, x ) );
775  else
776  l.append( incommand->c_str() );
777  string t;
778  t.append( ( *(incommand) ) );
779  if (x < string::npos)
780  y.append( incommand->substr( x, incommand->size()-1 ) );
781  else
782  y.append( incommand->c_str() );
783  if (l.compare( "\r\n" ) == 0) {} else {
784  size_t lv = l.find( "\r" );
785  while (lv < string::npos) {
786  l.replace( lv, 1, "" );
787  lv = l.find( "\r" );
788  }
789  lv = l.find( "\n" );
790  while (lv < string::npos) {
791  l.replace( lv, 1, "" );
792  lv = l.find( "\n" );
793  }
794  lv = y.find( "\r" );
795  while (lv < string::npos) {
796  y.replace( lv, 1, "" );
797  lv = y.find( "\r" );
798  }
799  lv = y.find( "\n" );
800  while (lv < string::npos) {
801  y.replace( lv, 1, "" );
802  lv = y.find( "\n" );
803  }
804  }
805  char *name_out = NULL;
806  if (l.size() > 0) name_out = (char*) l.c_str();
807  if ( callMenu( name_out, (char*) y.c_str(), t ) ) return false;
808  *incommand = string();
809  incommand->append( t ); //t may have changed if we got this far
810  }
811  }
812  //}}}
813  return fexecute( incommand, isDown, sock_in );
814 }
815 
816 //}}}
817 //broken up into two execute functions
818 //the one below is the real execute, the one above uses the menusystem
819 //it's broken up so the menusystem can call fexecute themself at the right
820 //time
821 //Main Execute Function {{{
822 
823 bool commandI::fexecute( string *incommand, bool isDown, int sock_in )
824 {
825  size_t ls, y;
826  bool breaker = false;
827 //************
828  while (breaker == false) {
829  ls = incommand->find( " " );
830  if (ls != 0)
831  breaker = true;
832  else
833  incommand->replace( ls, 1, "" );
834  }
835  for ( y = incommand->find( "\r\n" ); y != string::npos; y = incommand->find( "\r\n", y+1 ) )
836  incommand->replace( y, 2, "" );
837  for ( y = incommand->find( " " ); y != string::npos; y = incommand->find( " ", y+1 ) )
838  incommand->replace( y, 1, "" );
839  breaker = false; //reset our exit bool
840  //************ try to replace erase leading space if there is one
841  //eg, someone types: " do_something" instead of "do_something"
842  while (breaker == false) {
843  ls = incommand->find( " " );
844  if (ls != 0)
845  breaker = true;
846  else
847  incommand->erase( ls, 1 );
848  }
849 //Print back what the user typed.. {{{
850 //.. Sometimes people believe they typed python print "hello world\n"
851 //(and saw what they typed when they typed it)
852 //but may have actually typed oython print "hello world\n"
853 //and don't want to admit it, so they blame the system.
854 //So the system must sometimes politely tell the user what they typed
855  {
856  bool printit = false;
857  if (menumode) {
858 //if(menu_in->selected) {
859 //if(menu_in->iselected->inputbit || menu_in->iselected->inputbit2) printit = true;
860 //}
861  } else if (console) {
862  printit = true;
863  }
864  if (printit) {
865  string webout;
866  webout.append( incommand->c_str() );
867  webout.append( "\n\r" );
868  conoutf( webout );
869  }
870  }
871 //}}}
872  //replace \r\n with a space {{{
873  for ( y = incommand->find( "\r\n" ); y != string::npos; y = incommand->find( "\r\n", y+1 ) )
874  incommand->replace( y, 2, " " );
875  //}}}
876  //remove multiple spaces {{{
877  for ( y = incommand->find( " " ); y != string::npos; y = incommand->find( " ", y+1 ) )
878  incommand->replace( y, 1, "" );
879  //}}}
880  //{{{ ! to the last command typed
881  {
882  size_t x = incommand->find( "!" );
883  if (x == 0)
884  incommand->replace( 0, 1, lastcommand );
885  //}}}
886  //{{{ : to python
887  x = incommand->find( ":" );
888  if (x == 0)
889  incommand->replace( 0, 1, "python " );
890  }
891  //}}}
892 
893  breaker = false; //reset our exit bool
894 
895  //done with formatting
896  //now make what our vector<string> {{{
897  vector< string >strvec; //to replace newincommand
898  //to reduce data replication by one;
899  {
900  string::const_iterator scroller = incommand->begin();
901  size_t last = 0, next = 0;
902  bool quote = false;
903  bool escape = false;
904  next = incommand->find( " " );
905  for (next = incommand->find( "\"\"", 0 );
906  ( next = incommand->find( "\"\"", last ), (last != string::npos) );
907  last = (next != string::npos) ? next+1 : string::npos)
908  if (next < string::npos)
909  incommand->replace( next, 2, "\" \"" );
910  //replace "" with " "
911  string starter( "" );
912  strvec.push_back( starter );
913  for (scroller = incommand->begin(); scroller < incommand->end(); scroller++) {
914  if (*scroller == '\\') {
915  escape = true;
916  continue;
917  }
918  if (escape) {
919  if (*scroller == '\"') strvec[strvec.size()-1] += *scroller;
920  continue;
921  }
922  if (*scroller == '\"') {
923  if (quote)
924  quote = false;
925  else
926  quote = true;
927  continue;
928  }
929  if (*scroller == ' ' && !quote) {
930  strvec.push_back( starter );
931  continue;
932  }
933  strvec[strvec.size()-1] += *scroller;
934  }
935  }
936  //}}}
937  {
938  //if the last argument is a space, erase it. {{{
939  vector< string >::iterator iter = strvec.end();
940  iter--;
941  if ( ( *(iter) ).compare( " " ) == 0 )
942  strvec.erase( iter );
943  //}}}
944  }
945  try {
946  coms &theCommand = *findCommand( (char*) strvec[0].c_str(), sock_in );
947 //Now, we try to replace what was typed with the name returned by findCommand {{{
948 //to autocomplete words (EX: translate gos into gossip so the gossip
949 //command only has to find it's access name and not all possible
950 //methods of accessing it.)
951  if (theCommand.Name.compare( "dummy" ) != 0) {
952  size_t x = incommand->find_first_of( strvec[0] );
953  if (x != string::npos) {
954  strvec[0].erase();
955  strvec[0].append( theCommand.Name );
956  }
957 //}}}
958  lastcommand.erase();
959  lastcommand.append( *incommand ); //set the
960  //last command entered - use ! to trigger
961  }
962  //Try to execute now {{{
963  try {
964  //maybe if/else if would be more efficient, if this ever
965  //gets really large.
966  theCommand.functor->Call( strvec, sock_in, &isDown );
967  //try to catch any errors that occured while executing
968  }
969  catch (const char *in) {
970  string l;
971  l.append( in );
972  conoutf( l ); //print the error to the console
973  }
974  catch (exception e) {
975  string l;
976  l.append( "Command processor: Exception occured: " );
977  l.append( e.what() );
978  l.append( "\n\r" );
979  cout<<l;
980  conoutf( l );
981  }
982  catch (...) {
983  string y;
984  y.append(
985  "Command processor: exception occurered: Unknown, most likely cause: Wrong Arg_type arguement sent with addCommand.\n\r" );
986  cout<<y;
987  conoutf( y );
988  }
989 
990  //}}}
991  }
992  catch (const char *in) {
993  //catch findCommand error
994  cout<<in;
995  }
996  return true;
997 }
998 
999 //}}}
1000 
1001 string commandI::display( string &in )
1002 {
1003  //If the menusystem has a value to display, eg:
1004  //Editing User
1005  //1) Change Username - Current Name: XXX
1006  //and XXX is replaced with a value here
1007  //basically, call: string.replace(xxx,3, display("uname") )
1008  //then display does:
1009  //if(in.compare(uname) == 0) return current_mob_editing.Name;
1010  //The value to pass to display is set when creating a menuitem
1011  string f;
1012  f.append( "FAKE" );
1013  return f;
1014 }
1015 
1016 //{{{ menusystem
1017 /* ***************************************
1018 * An example of how the menusystem is used:
1019 * (the very first menu when a player logs onto the ANT-Engine http://daggerfall.dynu.com:5555/player1/index.html OR telnet://daggerfall.dynu.com:5555 )
1020 *
1021 * {
1022 * menu *m = new menu("newuser", "Welcome to the <GREEN>ANT<NORM> engine", "\r\n");
1023 * m->autoselect = true; //automatically select a menuitem, MUST BE SET
1024 * m->noescape = true; //no escaping this menu except by forcing it
1025 * addMenu(m); //add the menu to the command processor
1026 * mItem *mi = new mItem; //make a new menuitem
1027 * mi->Name.append(" "); //argument to access menu //must have a name
1028 * mi->action.append("UNAME "); //adds this to the function 2 call as the argument
1029 * mi->action.append(seccode); //add the security code.
1030 * mi->display.append(" "); // menu's display name
1031 * mi->func2call.append("loginfunc"); //function 2 call
1032 * mi->inputbit = true; // set single-line input mode
1033 * mi->selectstring.append("Enter a username"); //string to display when this menuitem is selected
1034 * addMenuItem(mi);// add the menuitem to the command processor, by default
1035 * // added to the last menu added, can be overredden by passing
1036 * // a menu * pointer as the second argument, eg:
1037 * // addMenuItem(mi, m);
1038 * m->aselect = mi; //this is the menu item to automatically select
1039 * }
1040 *
1041 *************************************** */
1042 //add a menu {{{
1043 bool commandI::addMenu( menu *menu_in )
1044 {
1045  menus.push_back( menu_in );
1046  lastmenuadded = menu_in;
1047  return true;
1048 }
1049 //}}}
1050 //{{{ display menu function
1052 {
1053  if (menumode) {
1054  ostringstream ps;
1055  ps<<menu_in->Display<<"\n";
1056  for (vector< mItem* >::iterator iter = menu_in->items.begin();
1057  iter < menu_in->items.end(); iter++) {
1058  ps<<( *(iter) )->Name<<" "<<( *(iter) )->display;
1059  if ( ( *(iter) )->predisplay.size() > 0 )
1060  ps<<" "<<display( ( *(iter) )->predisplay );
1061  ps<<"\n";
1062  }
1063  string buf;
1064  buf.append( ps.str() );
1065  if (menu_in->autoselect == true) {
1066  if (menu_in->selected == true) {
1067  buf.append( menu_in->iselected->selectstring );
1068  buf.append( ": " );
1069  }
1070  } else {
1071  if (!menu_in->noescape) {
1072  buf.append( "Use: " );
1073  if (menu_in->escape.compare( "\r\n" ) == 0)
1074  buf.append( "enter" );
1075  else
1076  buf.append( menu_in->escape );
1077  buf.append( " to quit: \n" );
1078  } else {
1079  buf.append( "Enter your selection: \n" );
1080  }
1081  }
1082  return buf;
1083 //conoutf(buf);
1084  }
1085  string buf;
1086  buf.append( "Error, not in menumode!" );
1087  return buf;
1088 }
1089 //}}}
1090 //menuitem to be appended to the last menu appended, or an existing menu if {{{
1091 //the menu2use is specified
1092 bool commandI::addMenuItem( mItem *mi, menu *menuin )
1093 {
1094  menu *menu2use;
1095  if (menuin == NULL)
1096  menu2use = lastmenuadded;
1097  else
1098  menu2use = menu_in;
1099  //if the command isn't found it will return dummy or prompt.
1100  for (vector< menu* >::iterator iter = menus.begin(); iter < menus.end(); iter++)
1101  if ( menu2use == ( *(iter) ) ) {
1102  menu2use->items.push_back( mi ); //doh! :)
1103  return true;
1104  }
1105  return false;
1106 }
1107 //}}}
1108 //call a menu with arguements {{{
1109 bool commandI::callMenu( char *name_in, char *args_in, string &d )
1110 {
1111  //if there is a menu operation return true;
1112  string name;
1113  if (name_in != NULL)
1114  name.append( name_in );
1115 //bool freturnfalse = false; //force return false
1116  //{{{ if the name_in is the menu_in's escape charactor
1117  //change the menu_in to the last menu on menustack if there is
1118  //one, and pop the stack. If there is no menustack, set menumode
1119  //off.
1120  if (menumode) {
1121  if (!menu_in->selected) {
1122  if (!menu_in->noescape) {
1123  if (name.compare( menu_in->escape ) == 0) {
1124  if (menustack.size() > 0) {
1125  vector< menu* >::iterator iter = menustack.end();
1126  iter--;
1127  menu_in = ( *(iter) );
1128  menustack.pop_back();
1129  //return true;
1130  } else {
1131  menu_in = NULL;
1132  menumode = false;
1133  return true;
1134  }
1135  }
1136  }
1137  }
1138  }
1139  //}}}
1140  if (menumode) {
1141  if (menu_in->selected) {
1142  //Input mode 1 {{{
1143  if (menu_in->iselected->inputbit == true && menu_in->iselected->inputbit2 == false) {
1144  menu_in->selected = false;
1145  string arg;
1146  arg.append( menu_in->iselected->action );
1147  string funcn;
1148  funcn.append( menu_in->iselected->func2call );
1149  string dreplace;
1150  dreplace.append( d );
1151  d.erase();
1152  d.append( funcn );
1153  d.append( " " );
1154  d.append( arg );
1155  d.append( " " );
1156  d.append( dreplace );
1157  //setMenus {{{
1158  if (funcn.compare( "setMenu" ) == 0) {
1159  string l;
1160  l.append( setMenu( arg ) );
1161  conoutf( l );
1162  return true;
1163  }
1164  //}}}
1165  size_t ylast = 0, xasd = 0;
1166  //login function {{{
1167  if (funcn.compare( "loginfunc" ) == 0) {
1168  vector< string* >d_out;
1169  d.append( " " );
1170  for ( size_t x = d.find( "\r\n" ); x < string::npos; x = d.find( "\r\n", x+3 ) )
1171  d.replace( x, 1, " \r\n" );
1172  for (size_t iter = 0; iter < d.size(); iter++) {
1173  if (d[iter] == 32) {
1174  string *xs = new string();
1175  xs->append( d.substr( ylast, xasd-ylast ) );
1176  ylast = xasd;
1177  d_out.push_back( xs );
1178  }
1179  xasd++;
1180  }
1181 //loginfunc(&d_out); //login function
1182  vector< string* >::iterator itera = d_out.begin();
1183  while (d_out.size() > 0) {
1184  string *s = ( *(itera) );
1185  delete s;
1186  d_out.erase( itera );
1187  itera = d_out.begin();
1188  }
1189  return true;
1190  }
1191  //}}}
1192  //autoreprint {{{
1193  if (menu_in->iselected->autoreprint == true) {
1194  fexecute( &d, true, 0 );
1195  string x;
1196  x.append( displaymenu() );
1197  conoutf( x );
1198  return true;
1199  }
1200  //}}}
1201  return false;
1202  }
1203  //}}}
1204  //input mode 2 {{{
1205  if (menu_in->iselected->inputbit == false && menu_in->iselected->inputbit2 == true) {
1206  //wait until we find an escape seqence alone {{{
1207  if (name.compare( menu_in->escape ) == 0) {
1208  menu_in->selected = false;
1209  string arg;
1210  arg.append( menu_in->iselected->action );
1211  string funcn;
1212  funcn.append( menu_in->iselected->func2call );
1213  d.erase();
1214  d.append( funcn );
1215  d.append( " " );
1216  d.append( arg );
1217  d.append( " " );
1218  {
1219  size_t l = 0;
1220  bool y = false;
1221  for ( size_t x = menu_in->iselected->menubuf.find( "\r\n" );
1222  x < string::npos;
1223  x = menu_in->iselected->menubuf.find( "\r\n", x+1 ) ) {
1224  menu_in->iselected->menubuf.replace( x, 2, "<BR>" );
1225  l = x;
1226  y = true;
1227  }
1228  if (y)
1229  menu_in->iselected->menubuf.replace( l, 4, "" ); //replace the last <BR>
1230  }
1231  d.append( menu_in->iselected->menubuf );
1232  d.append( " " );
1233  menu_in->iselected->menubuf.erase();
1234  if (funcn.compare( "setMenu" ) == 0) {
1235  string buf;
1236  buf.append( setMenu( arg ) );
1237  conoutf( buf );
1238  return true;
1239  }
1240  if (funcn.compare( "loginfunc" ) == 0) {
1241  vector< string* >d_out;
1242  d.append( " " );
1243  for ( size_t x = d.find( "\r\n" ); x < string::npos; x = d.find( "\r\n", x+1 ) )
1244  d.replace( x, 2, "<BR>" );
1245  size_t ylast = 0, xasd = 0;
1246  for (size_t iter = 0; iter < d.size(); iter++) {
1247  if (d[iter] == 32) {
1248  string *xs = new string();
1249  xs->append( d.substr( ylast, xasd-ylast ) );
1250  ylast = xasd;
1251  d_out.push_back( xs );
1252  }
1253  xasd++;
1254  }
1255 //loginfunc(&d_out); //login function
1256  vector< string* >::iterator itera = d_out.begin();
1257  while (d_out.size() > 0) {
1258  string *s = ( *(itera) );
1259  delete s;
1260  d_out.erase( itera );
1261  itera = d_out.begin();
1262  }
1263  return true;
1264  }
1265  if (menu_in->iselected->autoreprint == true) {
1266  fexecute( &d, true, 0 );
1267  string x;
1268  x.append( displaymenu() );
1269  conoutf( x );
1270  return true;
1271  }
1272  return false;
1273  //}}}
1274  //or we append the input to the buffer {{{
1275  } else {
1276  menu_in->iselected->menubuf.append( d );
1277  //}}}
1278  }
1279  return true;
1280  }
1281  //}}}
1282  }
1283  //if we don't have anything selected, select one.. {{{
1284  if (!menu_in->selected) {
1285  for (vector< mItem* >::iterator iter = menu_in->items.begin();
1286  iter < menu_in->items.end(); iter++)
1287  if ( ( *(iter) )->Name.compare( name ) == 0 ) {
1288  menu_in->selected = true;
1289  menu_in->iselected = ( *(iter) );
1290 //if(menu_in->iselected->predisplay.size() > 0) {
1291 //display(menu_in->iselected->predisplay);
1292 //}
1293  if (menu_in->iselected->inputbit2) {
1294  string buf;
1295  buf.append( menu_in->iselected->selectstring );
1296  buf.append( "\n\r" );
1297  buf.append( "Use: " );
1298  if (menu_in->escape.compare( "\r\n" ) == 0)
1299  buf.append( "enter" );
1300  else
1301  buf.append( menu_in->escape );
1302  buf.append( " to confirm: " );
1303 
1304  conoutf( buf );
1305  } else if (menu_in->iselected->inputbit) {
1306  string buf;
1307  buf.append( menu_in->iselected->selectstring );
1308  buf.append( ": " );
1309  conoutf( buf );
1310  }
1311  }
1312  if (menu_in->selected) {
1313  if (!menu_in->iselected->inputbit && !menu_in->iselected->inputbit2) {
1314  menu_in->selected = false;
1315  string arg;
1316  arg.append( menu_in->iselected->action );
1317  string funcn;
1318  funcn.append( menu_in->iselected->func2call );
1319  string dreplace;
1320  dreplace.append( d );
1321  d = string();
1322  d.append( funcn );
1323  d.append( " " );
1324  d.append( arg );
1325  d.append( " " );
1326  d.append( dreplace );
1327  if (funcn.compare( "setMenu" ) == 0) {
1328  string l;
1329  l.append( setMenu( arg ) );
1330  conoutf( l );
1331  return true;
1332  }
1333  return false;
1334  }
1335  return true;
1336  } else if (menu_in->defaultInput) {
1337  menu_in->selected = true;
1338  menu_in->iselected = menu_in->idefaultInput;
1339  execute( &d, true, 0 );
1340  return true;
1341  }
1342  }
1343  //}}}
1344  }
1345  if (menumode && !menu_in->selected) {
1346  //we're in a menu but don't have anything selected {{{
1347  string y;
1348  y.append( displaymenu() );
1349  conoutf( y );
1350  return true;
1351  }
1352  //}}}
1353  return false;
1354 }
1355 
1356 //}}}
1357 
1358 //set a menu {{{
1359 
1360 string commandI::setMenu( string name_in )
1361 {
1362  string name;
1363  name.append( name_in );
1364  if (name[0] == 32) name.replace( 0, 1, "" );
1365  for (vector< menu* >::iterator iter = menus.begin();
1366  iter < menus.end(); iter++)
1367  if ( ( *(iter) )->Name.compare( name ) == 0 ) {
1368  if (!menumode)
1369  menumode = true;
1370  else
1371  menustack.push_back( menu_in );
1372  menu_in = ( *(iter) );
1373  menu_in->selected = false;
1374  if (menu_in->autoselect == true) {
1375  menu_in->selected = true;
1376  menu_in->iselected = menu_in->aselect;
1377  }
1378  iter = menus.end();
1379  }
1380  return displaymenu();
1381 }
1382 
1383 //}}}
1384 
1386 {
1387  while (menustack.size() > 0)
1388  menustack.pop_back();
1389  menu_in = NULL;
1390  menumode = false;
1391 }
1392 
1393 //}}}
1394 
1396 
1397 //{{{ Python object
1398 
1400 {
1403  addTo->addCommand( l, "python" );
1404 }
1405 
1406 //run a python string
1408 {
1409  string pyRunString;
1410  pyRunString.append( argsin ); //append the arguments in to the string to run
1411  size_t x = pyRunString.find( "python " ); //strip out the name of the command
1412  //and the first space
1413  if (x == 0)
1414  pyRunString.replace( x, 7, "" ); //replace here
1415 //this method was copied from somewhere else in the vegastrike source
1416  //now replace <BR> with \r\n
1417  {
1418  size_t x = pyRunString.find( "<BR>" );
1419  while (x != string::npos) {
1420  pyRunString.replace( x, 4, "\r\n" );
1421  x = pyRunString.find( "<BR>" );
1422  }
1423  }
1424 
1425  char *temppython = strdup( pyRunString.c_str() ); //copy to a char *
1426  PyRun_SimpleString( temppython ); //run it
1427  Python::reseterrors();
1428  free( temppython ); //free the copy char *
1429 }
1430 
1431 //}}};
1432 
1433 /*---------------------------------------------------------------------------*/
1440 //if(!keypress(event.key.keysym.sym, event.key.state==SDL_PRESSED, event.key.keysym.unicode))
1441 void commandI::keypress( int code, int modifiers, bool isDown, int x, int y )
1442 {
1443  if (CommandInterpretor && CommandInterpretor->console) {
1444  if (code == WSK_ESCAPE) {
1445  CommandInterpretor->console = false;
1447 //SDL_EnableUNICODE(false);
1448  return;
1449  }
1450  if (code == WSK_RETURN && isDown) {
1451  string commandBuf = CommandInterpretor->getcurcommand();
1452  commandBuf.append( "\r\n" );
1453  CommandInterpretor->execute( &commandBuf, isDown, 0 ); //execute console on enter
1454  //don't return so the return get's processed by
1455  //CommandInterpretor->ConsoleKeyboardI, so it can clear the
1456  //command buffer
1457  }
1458  CommandInterpretor->ConsoleKeyboardI( code, isDown );
1459  return;
1460  } else {
1462  return;
1463  }
1464 }
1465 
1466 /* Proposed (Would need a couple commands inserted into the command processor
1467  * // one to read a keymap file and one to re-map a single key
1468  * // (and the keymap file would have to be read at startup)
1469  * // struct keym { int code; char * name; char * action; }; or so
1470  * vector<KeyMapObject>::iterator iter = keyMapVector.begin();
1471  * while(iter < keyMapVector.end()) {
1472  * keym *tester = &(*(iter));
1473  * if(tester->code == code){
1474  * // lookup in keymap and execute
1475  * if(tester->action)
1476  * execCommand(tester->action, isdown);
1477  * return true;
1478  * }
1479  * iter++;
1480  * }
1481  * }
1482  *
1483  *
1484  *
1485  */
1486 
1487 /* ***************************************************************
1488 * Possible Optimizations:
1489 *
1490 * Optimizations discussed here arn't the tiny little save 2 or 3 cpu ops by reforming a for loop.
1491 * These optimizations may make an impact on very very slow machines, or
1492 * when ram is limited for copying objects, or when certain copies or types
1493 * arn't ever needed.
1494 *
1495 * Possible optimization for findCommand (small optimization, less game-time copying overhead (after boot, while playing))
1496 * copy a coms object when adding a command to the real command vector, (as it is now in addCommand)
1497 *
1498 * return a reference to the coms object from findCommand, to avoid
1499 * copying every time a key is pressed or a command is entered.
1500 * (change coms findCommand to coms *findCommand)
1501 *
1502 *
1503 *
1504 *
1505 * Possible optimization for the main execute function ( medium optimization, less unneeded allocated variables in the execute function when not needed)
1506 * Move findCommand higher up, before the string vector and 1str array are
1507 * built, and build those depending on the argument type, to avoid
1508 * excessive string copying when it's not needed, such as when not in
1509 * console mode but in game mode, when 1 bool is enough to tell
1510 * the function being called wether the key is pressed or not.
1511 * - This might make it a little more difficult to read the execute function
1512 *
1513 *
1514 *************************************************************** */
1515 
1516 namespace ConsoleKeys
1517 {
1518 void BringConsole( const KBData&, KBSTATE newState )
1519 {
1520  //this way, keyboard state stays synchronized
1521  if (newState == RELEASE) {
1522  if (CommandInterpretor) {
1523  winsys_set_keyboard_func( (winsys_keyboard_func_t) &commandI::keypress );
1524  CommandInterpretor->console = true;
1525 #ifdef HAVE_SDL
1526  SDL_EnableUNICODE( true );
1527 #endif
1528  }
1529  }
1530 }
1531 }
1532 
1533 //footer, leave at bottom
1534 /*
1535  * Local variables:
1536  * tab-width: 4
1537  * c-basic-offset: 4
1538  * End:
1539  * vim600: sw=4 ts=4 fdm=marker
1540  * vim<600: sw=4 ts=4
1541  */
1542