/* * cmdhandler.cpp - Author: Keith Fulton * * Copyright (C) 2001 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include "util/pserror.h" #include "util/psstring.h" #include "net/msghandler.h" #include "cmdhandler.h" CmdHandler::CmdHandler(iObjectRegistry *newobjreg) { objreg = newobjreg; } CmdHandler::~CmdHandler() { } bool CmdHandler::Subscribe(const char *cmd, iCmdSubscriber *subscriber) { for ( size_t x = 0; x < subscribers.Length(); x++ ) { if (subscribers[x]->cmd == cmd && subscribers[x]->subscriber == subscriber) { // Already subscribed => Do nothing return true; // No error so return true. } } // Create a new subscribtion CmdSubscription* p = new CmdSubscription; p->subscriber = subscriber; p->cmd = cmd; subscribers.Push(p); return true; } bool CmdHandler::Unsubscribe(const char *cmd, iCmdSubscriber *subscriber) { for ( size_t x = 0; x < subscribers.Length(); x++ ) { if (subscribers[x]->cmd == cmd && subscribers[x]->subscriber == subscriber) { subscribers.DeleteIndex(x); return true; } } return false; } bool CmdHandler::UnsubscribeAll(iCmdSubscriber *subscriber) { bool unsubscribed_commands(false); for (size_t x = subscribers.Length() - 1; x != (size_t)-1; x--) { if (subscribers[x]->subscriber == subscriber) { subscribers.DeleteIndex(x); unsubscribed_commands = true; } } return unsubscribed_commands; } const char *CmdHandler::Publish(const char *cmd) { if (subscribers.Length() == 0) return "No command handlers installed!"; char command[100]; // Get first word of line if there is a space, or get entire line if one word const char *space = strchr(cmd,' '); if (space) { int len = space-cmd; if (len>99) len=99; strncpy(command,cmd,len); command[len] = 0; } else { strncpy(command,cmd,100); command[99] = 0; } int count=0; const char *err=NULL,*ret; for ( size_t x = 0; x < subscribers.Length(); x++ ) { if (subscribers[x]->cmd == command) { count++; ret = subscribers[x]->subscriber->HandleCommand(cmd); if (ret) err = ret; // This structure is needed in case several classes handle the same command. } } // Only last error returned will be shown. // This should be ok since most commands will only have one subscriber. return count ? err : "Sorry. Unknown command (use /help)."; } void CmdHandler::Execute(const char *script, bool breakSemiColon) { if (!script || !strlen(script) ) return; /** * script is assumed to be null terminated * with each command on a new line OR separated by semicolon. */ psString copy(script),linefeed("\n"),semicolon(";"),line; size_t start=0; size_t end=0; while ( end < copy.Length() ) { end = copy.FindSubString(linefeed,(int) start); if (end == SIZET_NOT_FOUND) { if ( breakSemiColon ) { end = copy.FindSubString(semicolon,(int)start); if (end == SIZET_NOT_FOUND) end = copy.Length(); } else { end = copy.Length(); } } copy.GetSubString(line,start,end); line.LTrim(); Publish(line); // This executes each line start = end+1; } } void CmdHandler::GetSubscribedCommands(BinaryRBTree& tree) { for ( size_t x = 0; x < subscribers.Length(); x++ ) { psString *str = new psString(subscribers[x]->cmd); tree.Insert(str); } }