From 8b7464046cea5e521ac46811591b0fce0c45aca1 Mon Sep 17 00:00:00 2001 From: markt Date: Thu, 13 Dec 2007 05:48:00 +0000 Subject: added FbTk::CommandRegistry, decentralized command parsing, and made them auto-register --- ChangeLog | 5 + src/ClockTool.cc | 6 +- src/CommandDialog.cc | 8 +- src/CommandParser.cc | 124 ------- src/CommandParser.hh | 81 ----- src/CurrentWindowCmd.cc | 291 ++++++++++++++++ src/CurrentWindowCmd.hh | 10 + src/FbCommandFactory.cc | 833 -------------------------------------------- src/FbCommandFactory.hh | 35 -- src/FbCommands.cc | 110 +++++- src/FbCommands.hh | 6 + src/FbTk/CommandRegistry.cc | 92 +++++ src/FbTk/CommandRegistry.hh | 130 +++++++ src/FbTk/LogicCommands.cc | 93 +++++ src/FbTk/LogicCommands.hh | 4 +- src/FbTk/MacroCommand.cc | 48 +++ src/FbTk/Makefile.am | 1 + src/FbTk/StringUtil.cc | 12 + src/FbTk/StringUtil.hh | 3 + src/IconbarTool.cc | 4 +- src/Keys.cc | 4 +- src/LayerMenu.hh | 2 +- src/Makefile.am | 4 +- src/MenuCreator.cc | 14 +- src/Screen.cc | 12 +- src/Slit.hh | 2 +- src/ToggleMenu.hh | 2 +- src/ToolFactory.cc | 6 +- src/Toolbar.cc | 4 +- src/Toolbar.hh | 2 +- src/WorkspaceCmd.cc | 120 +++++++ src/WorkspaceCmd.hh | 8 + src/WorkspaceMenu.cc | 4 +- 33 files changed, 966 insertions(+), 1114 deletions(-) delete mode 100644 src/CommandParser.cc delete mode 100644 src/CommandParser.hh delete mode 100644 src/FbCommandFactory.cc delete mode 100644 src/FbCommandFactory.hh create mode 100644 src/FbTk/CommandRegistry.cc create mode 100644 src/FbTk/CommandRegistry.hh diff --git a/ChangeLog b/ChangeLog index b95d844..c942584 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ (Format: Year/Month/Day) Changes for 1.0.1: +*07/12/13: + * Moved command parsing code all over the place -- expect any patches that + add new commands to be broken (Mark, Simon) + Added FbTk/CommandRegistry.cc/hh + Removed FbCommandFactory.cc/hh CommandParser.cc/hh *07/12/11: * Added new resize modes for key command StartResizing: NearestEdge, Left, Right, Top, Bottom (Mark) diff --git a/src/ClockTool.cc b/src/ClockTool.cc index 0bfa136..55973fb 100644 --- a/src/ClockTool.cc +++ b/src/ClockTool.cc @@ -26,7 +26,7 @@ #include "ToolTheme.hh" #include "Screen.hh" -#include "CommandParser.hh" +#include "FbTk/CommandRegistry.hh" #include "CommandDialog.hh" #include "fluxbox.hh" @@ -128,7 +128,7 @@ public: CommandDialog *dialog = new CommandDialog(*screen, "Edit Clock Format", "SetResourceValue " + resourcename + " "); - FbTk::RefCount cmd(CommandParser::instance().parseLine("reconfigure")); + FbTk::RefCount cmd(FbTk::CommandRegistry::instance().parseLine("reconfigure")); dialog->setPostCommand(cmd); dialog->setText(screen->resourceManager().resourceValue(resourcename)); dialog->show(); @@ -169,7 +169,7 @@ ClockTool::ClockTool(const FbTk::FbWindow &parent, m_button.setGC(m_theme.textGC()); // setup menu - FbTk::RefCount saverc(CommandParser::instance().parseLine("saverc")); + FbTk::RefCount saverc(FbTk::CommandRegistry::instance().parseLine("saverc")); FbTk::MenuItem *item = new ClockMenuItem(*this); item->setCommand(saverc); menu.insert(item); diff --git a/src/CommandDialog.cc b/src/CommandDialog.cc index e19cd53..436a942 100644 --- a/src/CommandDialog.cc +++ b/src/CommandDialog.cc @@ -27,7 +27,7 @@ #include "Screen.hh" #include "FbWinFrameTheme.hh" #include "WinClient.hh" -#include "CommandParser.hh" +#include "FbTk/CommandRegistry.hh" #include "FocusControl.hh" #include "fluxbox.hh" @@ -139,7 +139,7 @@ void CommandDialog::keyPressEvent(XKeyEvent &event) { if (ks == XK_Return) { hide(); // hide and return focus to a FluxboxWindow // create command from line - auto_ptr cmd(CommandParser::instance(). + auto_ptr cmd(FbTk::CommandRegistry::instance(). parseLine(m_precommand + m_textbox.text())); if (cmd.get()) cmd->execute(); @@ -170,8 +170,8 @@ void CommandDialog::tabComplete() { return; } - CommandParser::CommandFactoryMap::const_iterator it = CommandParser::instance().factorys().begin(); - const CommandParser::CommandFactoryMap::const_iterator it_end = CommandParser::instance().factorys().end(); + FbTk::CommandRegistry::CreatorMap::const_iterator it = FbTk::CommandRegistry::instance().commandMap().begin(); + const FbTk::CommandRegistry::CreatorMap::const_iterator it_end = FbTk::CommandRegistry::instance().commandMap().end(); vector matches; for (; it != it_end; ++it) { if ((*it).first.find(prefix) == 0) { diff --git a/src/CommandParser.cc b/src/CommandParser.cc deleted file mode 100644 index a1e52e5..0000000 --- a/src/CommandParser.cc +++ /dev/null @@ -1,124 +0,0 @@ -// CommandParser.cc for Fluxbox - an X11 Window manager -// Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org) -// and Simon Bowden (rathnor at users.sourceforge.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -// $Id$ - -#include "CommandParser.hh" -#include "FbTk/StringUtil.hh" - -#include - -using std::string; -using std::vector; -using FbTk::StringUtil::removeFirstWhitespace; -using FbTk::StringUtil::toLower; - - -CommandParser *CommandParser::s_singleton = 0; - -CommandFactory::CommandFactory() { - -} - -CommandFactory::~CommandFactory() { - // remove all associations with this factory - CommandParser::instance().removeAssociation(*this); - -} - -void CommandFactory::addCommand(const std::string &command_name) { - CommandParser::instance().associateCommand(command_name, *this); -} - -// ensure it is singleton -CommandParser::CommandParser() { - if (s_singleton != 0) - throw std::string("CommandParser currently meant ot be singleton"); -} - -CommandParser &CommandParser::instance() { - if (s_singleton == 0) - s_singleton = new CommandParser(); - - return *s_singleton; -} - -FbTk::Command *CommandParser::parseLine(const std::string &line, bool trusted) { - - // parse arguments and command - string command = line; - string arguments; - string::size_type first_pos = removeFirstWhitespace(command); - FbTk::StringUtil::removeTrailingWhitespace(command); - string::size_type second_pos = command.find_first_of(" \t", first_pos); - if (second_pos != string::npos) { - // ok we have arguments, parsing them here - arguments = command.substr(second_pos); - removeFirstWhitespace(arguments); - command.erase(second_pos); // remove argument from command - } - - // now we have parsed command and arguments - command = toLower(command); - - // we didn't find any matching command in default commands, - // so we search in the command creators modules for a - // matching command string - return toCommand(command, arguments, trusted); - -} - -FbTk::Command *CommandParser::toCommand(const std::string &command_str, - const std::string &arguments, bool trusted) { - if (m_commandfactorys[command_str] != 0) - return m_commandfactorys[command_str]->stringToCommand(command_str, arguments, trusted); - - return 0; -} - -void CommandParser::associateCommand(const std::string &command, CommandFactory &factory) { - // we shouldnt override other commands - if (m_commandfactorys[command] != 0) - return; - - m_commandfactorys[command] = &factory; -} - -void CommandParser::removeAssociation(CommandFactory &factory) { - // commands that are associated with the factory - vector commands; - // find associations - CommandFactoryMap::iterator factory_it = m_commandfactorys.begin(); - const CommandFactoryMap::iterator factory_it_end = m_commandfactorys.end(); - for (; factory_it != factory_it_end; ++factory_it) { - if ((*factory_it).second == &factory) - commands.push_back((*factory_it).first); - } - // remove all associations - while (!commands.empty()) { - m_commandfactorys.erase(commands.back()); - commands.pop_back(); - } - - if (m_commandfactorys.empty()) - delete s_singleton; -} diff --git a/src/CommandParser.hh b/src/CommandParser.hh deleted file mode 100644 index 1bc3094..0000000 --- a/src/CommandParser.hh +++ /dev/null @@ -1,81 +0,0 @@ -// CommandParser.hh for Fluxbox - an X11 Window manager -// Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org) -// and Simon Bowden (rathnor at users.sourceforge.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -// $Id$ - -#ifndef COMMANDPARSER_HH -#define COMMANDPARSER_HH - -#include -#include - -#include "RefCount.hh" - -namespace FbTk { -class Command; -}; - -/// Creates commands from command and argument. -/// Used for modules to add new commands in compile/run time -class CommandFactory { -public: - CommandFactory(); - virtual ~CommandFactory(); - virtual FbTk::Command *stringToCommand(const std::string &command, - const std::string &arguments, - bool trusted) = 0; -protected: - void addCommand(const std::string &value); -}; - -/// Parses text into a command -class CommandParser { -public: - typedef std::map CommandFactoryMap; - - /// @return parses and returns a command matching the line - FbTk::Command *parseLine(const std::string &line, bool trusted = true); - - CommandParser(); - - /// @return instance of command parser - static CommandParser &instance(); - /// @return map of factorys - const CommandFactoryMap &factorys() const { return m_commandfactorys; } -private: - // so CommandFactory can associate it's commands - friend class CommandFactory; - /// associate a command with a factory - void associateCommand(const std::string &name, CommandFactory &factory); - /// remove all associations with the factory - void removeAssociation(CommandFactory &factory); - - /// search for a command in our command factory map - FbTk::Command *toCommand(const std::string &command, - const std::string &arguments, bool trusted); - - CommandFactoryMap m_commandfactorys; ///< a string to factory map - - static CommandParser *s_singleton; -}; - -#endif // COMMANDPARSER_HH diff --git a/src/CurrentWindowCmd.cc b/src/CurrentWindowCmd.cc index 78f3aa1..33d8e8a 100644 --- a/src/CurrentWindowCmd.cc +++ b/src/CurrentWindowCmd.cc @@ -31,6 +31,95 @@ #include "WinClient.hh" #include "FocusControl.hh" +#include "FbTk/CommandRegistry.hh" +#include "FbTk/stringstream.hh" +#include "FbTk/StringUtil.hh" + +#include +#include + +namespace { + +FbTk::Command *createCurrentWindowCmd(const std::string &command, + const std::string &args, bool trusted) { + if (command == "minimizewindow" || command == "minimize" || command == "iconify") + return new CurrentWindowCmd(&FluxboxWindow::iconify); + else if (command == "maximizewindow" || command == "maximize") + return new CurrentWindowCmd(&FluxboxWindow::maximizeFull); + else if (command == "maximizevertical") + return new CurrentWindowCmd(&FluxboxWindow::maximizeVertical); + else if (command == "maximizehorizontal") + return new CurrentWindowCmd(&FluxboxWindow::maximizeHorizontal); + else if (command == "raise") + return new CurrentWindowCmd(&FluxboxWindow::raise); + else if (command == "raiselayer") + return new CurrentWindowCmd(&FluxboxWindow::raiseLayer); + else if (command == "lower") + return new CurrentWindowCmd(&FluxboxWindow::lower); + else if (command == "lowerlayer") + return new CurrentWindowCmd(&FluxboxWindow::lowerLayer); + else if (command == "activate" || command == "focus") + return new CurrentWindowCmd((void (FluxboxWindow::*)())&FluxboxWindow::focus); + else if (command == "close") + return new CurrentWindowCmd(&FluxboxWindow::close); + else if (command == "killwindow" || command == "kill") + return new CurrentWindowCmd(&FluxboxWindow::kill); + else if (command == "shade" || command == "shadewindow") + return new CurrentWindowCmd(&FluxboxWindow::shade); + else if (command == "shadeon" ) + return new CurrentWindowCmd(&FluxboxWindow::shadeOn); + else if (command == "shadeoff" ) + return new CurrentWindowCmd(&FluxboxWindow::shadeOff); + else if (command == "stick" || command == "stickwindow") + return new CurrentWindowCmd(&FluxboxWindow::stick); + else if (command == "toggledecor") + return new CurrentWindowCmd(&FluxboxWindow::toggleDecoration); + else if (command == "nexttab") + return new CurrentWindowCmd(&FluxboxWindow::nextClient); + else if (command == "prevtab") + return new CurrentWindowCmd(&FluxboxWindow::prevClient); + else if (command == "movetableft") + return new CurrentWindowCmd(&FluxboxWindow::moveClientLeft); + else if (command == "movetabright") + return new CurrentWindowCmd(&FluxboxWindow::moveClientRight); + else if (command == "detachclient") + return new CurrentWindowCmd(&FluxboxWindow::detachCurrentClient); + else if (command == "windowmenu") + return new CurrentWindowCmd(&FluxboxWindow::popupMenu); + return 0; +} + +REGISTER_COMMAND_PARSER(minimizewindow, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(minimize, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(iconify, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(maximizewindow, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(maximize, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(maximizevertical, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(maximizehorizontal, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(raise, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(raiselayer, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(lower, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(lowerlayer, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(activate, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(focus, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(close, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(killwindow, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(kill, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(shade, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(shadewindow, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(shadeon, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(shadeoff, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(stick, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(stickwindow, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(toggledecor, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(nexttab, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(prevtab, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(movetableft, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(movetabright, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(detachclient, createCurrentWindowCmd); +REGISTER_COMMAND_PARSER(windowmenu, createCurrentWindowCmd); + +}; // end anonymous namespace void WindowHelperCmd::execute() { if (WindowCmd::window() || FocusControl::focusedFbWindow()) @@ -68,6 +157,44 @@ void CurrentWindowCmd::real_execute() { (fbwindow().*m_action)(); } +namespace { + +FbTk::Command *parseIntCmd(const string &command, const string &args, + bool trusted) { + int num = (command == "sethead" ? 0 : 1); + FbTk_istringstream iss(args.c_str()); + iss >> num; + if (command == "sethead") + return new SetHeadCmd(num); + else if (command == "tab") + return new GoToTabCmd(num); + else if (command == "sendtonextworkspace") + return new SendToNextWorkspaceCmd(num); + else if (command == "sendtoprevworkspace") + return new SendToPrevWorkspaceCmd(num); + else if (command == "taketonextworkspace") + return new TakeToNextWorkspaceCmd(num); + else if (command == "taketoprevworkspace") + return new TakeToPrevWorkspaceCmd(num); + else if (command == "sendtoworkspace") + // workspaces appear 1-indexed to the user, hence the minus 1 + return new SendToWorkspaceCmd(num-1); + else if (command == "taketoworkspace") + return new TakeToWorkspaceCmd(num-1); + return 0; +} + +REGISTER_COMMAND_PARSER(sethead, parseIntCmd); +REGISTER_COMMAND_PARSER(tab, parseIntCmd); +REGISTER_COMMAND_PARSER(sendtonextworkspace, parseIntCmd); +REGISTER_COMMAND_PARSER(sendtoprevworkspace, parseIntCmd); +REGISTER_COMMAND_PARSER(taketonextworkspace, parseIntCmd); +REGISTER_COMMAND_PARSER(taketoprevworkspace, parseIntCmd); +REGISTER_COMMAND_PARSER(sendtoworkspace, parseIntCmd); +REGISTER_COMMAND_PARSER(taketoworkspace, parseIntCmd); + +}; // end anonymous namespace + void SetHeadCmd::real_execute() { fbwindow().setOnHead(m_head); } @@ -127,6 +254,8 @@ void GoToTabCmd::real_execute() { (*it)->focus(); } +REGISTER_COMMAND(startmoving, StartMovingCmd); + void StartMovingCmd::real_execute() { const XEvent &last = Fluxbox::instance()->lastEvent(); if (last.type == ButtonPress) { @@ -135,6 +264,41 @@ void StartMovingCmd::real_execute() { } } +FbTk::Command *StartResizingCmd::parse(const string &cmd, const string &args, + bool trusted) { + FluxboxWindow::ResizeModel mode = FluxboxWindow::DEFAULTRESIZE; + std::vector tokens; + FbTk::StringUtil::stringtok >(tokens, args); + if (!tokens.empty()) { + string arg = FbTk::StringUtil::toLower(tokens[0]); + if (arg == "nearestcorner") + mode = FluxboxWindow::QUADRANTRESIZE; + else if (arg == "nearestedge") + mode = FluxboxWindow::NEARESTEDGERESIZE; + else if (arg == "center") + mode = FluxboxWindow::CENTERRESIZE; + else if (arg == "topleft") + mode = FluxboxWindow::TOPLEFTRESIZE; + else if (arg == "top") + mode = FluxboxWindow::TOPRESIZE; + else if (arg == "topright") + mode = FluxboxWindow::TOPRIGHTRESIZE; + else if (arg == "left") + mode = FluxboxWindow::LEFTRESIZE; + else if (arg == "right") + mode = FluxboxWindow::RIGHTRESIZE; + else if (arg == "bottomleft") + mode = FluxboxWindow::BOTTOMLEFTRESIZE; + else if (arg == "bottom") + mode = FluxboxWindow::BOTTOMRESIZE; + else if (arg == "bottomright") + mode = FluxboxWindow::BOTTOMRIGHTRESIZE; + } + return new StartResizingCmd(mode); +} + +REGISTER_COMMAND_PARSER(startresizing, StartResizingCmd::parse); + void StartResizingCmd::real_execute() { const XEvent &last = Fluxbox::instance()->lastEvent(); if (last.type == ButtonPress) { @@ -147,6 +311,33 @@ void StartResizingCmd::real_execute() { } } +FbTk::Command *MoveCmd::parse(const string &command, const string &args, + bool trusted) { + FbTk_istringstream is(args.c_str()); + int dx = 0, dy = 0; + is >> dx >> dy; + + if (command == "moveright") + dy = 0; + else if (command == "moveleft") { + dy = 0; + dx = -dx; + } else if (command == "movedown") { + dy = dx; + dx = 0; + } else if (command == "moveup") { + dy = -dx; + dx = 0; + } + return new MoveCmd(dx, dy); +} + +REGISTER_COMMAND_PARSER(move, MoveCmd::parse); +REGISTER_COMMAND_PARSER(moveright, MoveCmd::parse); +REGISTER_COMMAND_PARSER(moveleft, MoveCmd::parse); +REGISTER_COMMAND_PARSER(moveup, MoveCmd::parse); +REGISTER_COMMAND_PARSER(movedown, MoveCmd::parse); + MoveCmd::MoveCmd(const int step_size_x, const int step_size_y) : m_step_size_x(step_size_x), m_step_size_y(step_size_y) { } @@ -156,6 +347,28 @@ void MoveCmd::real_execute() { fbwindow().y() + m_step_size_y); } +FbTk::Command *ResizeCmd::parse(const string &command, const string &args, + bool trusted) { + FbTk_istringstream is(args.c_str()); + int dx = 0, dy = 0; + is >> dx >> dy; + if (command == "resizehorizontal") + dy = 0; + else if (command == "resizevertical") { + dy = dx; + dx = 0; + } + + if (command == "resizeto") + return new ResizeToCmd(dx, dy); + return new ResizeCmd(dx, dy); +} + +REGISTER_COMMAND_PARSER(resize, ResizeCmd::parse); +REGISTER_COMMAND_PARSER(resizeto, ResizeCmd::parse); +REGISTER_COMMAND_PARSER(resizehorizontal, ResizeCmd::parse); +REGISTER_COMMAND_PARSER(resizevertical, ResizeCmd::parse); + ResizeCmd::ResizeCmd(const int step_size_x, const int step_size_y) : m_step_size_x(step_size_x), m_step_size_y(step_size_y) { } @@ -170,6 +383,53 @@ void ResizeCmd::real_execute() { fbwindow().resize(w, h); } +FbTk::Command *MoveToCmd::parse(const string &cmd, const string &args, + bool trusted) { + typedef std::vector StringTokens; + StringTokens tokens; + FbTk::StringUtil::stringtok(tokens, args); + + if (tokens.size() < 2) + return 0; + + unsigned int refc = MoveToCmd::UPPER|MoveToCmd::LEFT; + int dx = 0, dy = 0; + + if (tokens[0][0] == '*') + refc |= MoveToCmd::IGNORE_X; + else + dx = atoi(tokens[0].c_str()); + + if (tokens[1][0] == '*' && ! (refc & MoveToCmd::IGNORE_X)) + refc |= MoveToCmd::IGNORE_Y; + else + dy = atoi(tokens[1].c_str()); + + if (tokens.size() >= 3) { + tokens[2] = FbTk::StringUtil::toLower(tokens[2]); + if (tokens[2] == "left" || tokens[2] == "upperleft" || tokens[2] == "lowerleft") { + refc |= MoveToCmd::LEFT; + refc &= ~MoveToCmd::RIGHT; + } else if (tokens[2] == "right" || tokens[2] == "upperright" || tokens[2] == "lowerright") { + refc |= MoveToCmd::RIGHT; + refc &= ~MoveToCmd::LEFT; + } + + if (tokens[2] == "upper" || tokens[2] == "upperleft" || tokens[2] == "upperright") { + refc |= MoveToCmd::UPPER; + refc &= ~MoveToCmd::LOWER; + } else if (tokens[2] == "lower" || tokens[2] == "lowerleft" || tokens[2] == "lowerright") { + refc |= MoveToCmd::LOWER; + refc &= ~MoveToCmd::UPPER; + } + } + + return new MoveToCmd(dx, dy, refc); + +} + +REGISTER_COMMAND_PARSER(moveto, MoveToCmd::parse); + MoveToCmd::MoveToCmd(const int step_size_x, const int step_size_y, const unsigned int refc) : m_step_size_x(step_size_x), m_step_size_y(step_size_y), m_refc(refc) { } @@ -205,11 +465,40 @@ void ResizeToCmd::real_execute() { fbwindow().resize(m_step_size_x, m_step_size_y); } +REGISTER_COMMAND(fullscreen, FullscreenCmd); + FullscreenCmd::FullscreenCmd() { } void FullscreenCmd::real_execute() { fbwindow().setFullscreen(!fbwindow().isFullscreen()); } +FbTk::Command *SetAlphaCmd::parse(const string &command, const string &args, + bool trusted) { + typedef std::vector StringTokens; + StringTokens tokens; + FbTk::StringUtil::stringtok(tokens, args); + + int focused, unfocused; + bool relative, un_rel; + + if (tokens.empty()) { // set default alpha + focused = unfocused = 256; + relative = un_rel = false; + } else { + relative = un_rel = (tokens[0][0] == '+' || tokens[0][0] == '-'); + focused = unfocused = atoi(tokens[0].c_str()); + } + + if (tokens.size() > 1) { // set different unfocused alpha + un_rel = (tokens[1][0] == '+' || tokens[1][0] == '-'); + unfocused = atoi(tokens[1].c_str()); + } + + return new SetAlphaCmd(focused, relative, unfocused, un_rel); +} + +REGISTER_COMMAND_PARSER(setalpha, SetAlphaCmd::parse); + SetAlphaCmd::SetAlphaCmd(int focused, bool relative, int unfocused, bool un_relative) : m_focus(focused), m_unfocus(unfocused), @@ -240,6 +529,8 @@ void SetAlphaCmd::real_execute() { fbwindow().setUnfocusedAlpha(m_unfocus); } +REGISTER_BOOLCOMMAND_WITH_ARGS(matches, MatchCmd); + bool MatchCmd::real_execute() { return m_pat.match(winclient()); } diff --git a/src/CurrentWindowCmd.hh b/src/CurrentWindowCmd.hh index c8e6242..7ef1184 100644 --- a/src/CurrentWindowCmd.hh +++ b/src/CurrentWindowCmd.hh @@ -151,6 +151,8 @@ protected: class StartResizingCmd: public WindowHelperCmd { public: explicit StartResizingCmd(FluxboxWindow::ResizeModel mode):m_mode(mode) { } + static FbTk::Command *parse(const std::string &command, + const std::string &args, bool trusted); protected: void real_execute(); private: @@ -161,6 +163,8 @@ private: class MoveCmd: public WindowHelperCmd { public: explicit MoveCmd(const int step_size_x, const int step_size_y); + static FbTk::Command *parse(const std::string &command, + const std::string &args, bool trusted); protected: void real_execute(); @@ -173,6 +177,8 @@ private: class ResizeCmd: public WindowHelperCmd{ public: explicit ResizeCmd(int step_size_x, int step_size_y); + static FbTk::Command *parse(const std::string &command, + const std::string &args, bool trusted); protected: void real_execute(); @@ -194,6 +200,8 @@ public: IGNORE_Y = 1 << 9 }; explicit MoveToCmd(const int step_size_x, const int step_size_y, const unsigned int refc); + static FbTk::Command *parse(const std::string &command, + const std::string &args, bool trusted); protected: void real_execute(); @@ -224,6 +232,8 @@ protected: class SetAlphaCmd: public WindowHelperCmd { public: SetAlphaCmd(int focus, bool rel, int unfocus, bool unrel); + static FbTk::Command *parse(const std::string &command, + const std::string &args, bool trusted); protected: void real_execute(); private: diff --git a/src/FbCommandFactory.cc b/src/FbCommandFactory.cc deleted file mode 100644 index 902461c..0000000 --- a/src/FbCommandFactory.cc +++ /dev/null @@ -1,833 +0,0 @@ -// FbCommandFactory.cc for Fluxbox Window manager -// Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org) -// and Simon Bowden (rathnor at users.sourceforge.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -// $Id$ - -#include "FbCommandFactory.hh" - -#include "FocusableList.hh" -#include "CurrentWindowCmd.hh" -#include "FbCommands.hh" -#include "Window.hh" -#include "WorkspaceCmd.hh" -#include "fluxbox.hh" -#include "SimpleCommand.hh" -#include "Screen.hh" - -#include "FbTk/StringUtil.hh" -#include "FbTk/LogicCommands.hh" -#include "FbTk/MacroCommand.hh" -#include "FbTk/stringstream.hh" - -#include - -#ifdef HAVE_CSTDIO - #include -#else - #include -#endif - -using std::string; -using std::vector; -using std::cerr; -using std::endl; - -using namespace FbTk; -using FbTk::StringUtil::removeFirstWhitespace; -using FbTk::StringUtil::toLower; - -// autoregister this module to command parser -FbCommandFactory FbCommandFactory::s_autoreg; - -namespace { - -static int getint(const char *str, int defaultvalue) { - sscanf(str, "%d", &defaultvalue); - return defaultvalue; -} - -BoolCommand *parseBoolCommand(string &line, bool trusted) { - // parse arguments and command - string command = line; - string arguments; - string::size_type first_pos = removeFirstWhitespace(command); - FbTk::StringUtil::removeTrailingWhitespace(command); - string::size_type second_pos = command.find_first_of(" \t", first_pos); - if (second_pos != string::npos) { - // ok we have arguments, parsing them here - arguments = command.substr(second_pos); - removeFirstWhitespace(arguments); - command.erase(second_pos); // remove argument from command - } - - // now we have parsed command and arguments - command = toLower(command); - - if (command == "matches") { - return new MatchCmd(arguments); - } else if (command == "some") { - BoolCommand *boolcmd = parseBoolCommand(arguments, trusted); - if (!boolcmd) - return 0; - return new SomeCmd(RefCount(boolcmd)); - } else if (command == "every") { - BoolCommand *boolcmd = parseBoolCommand(arguments, trusted); - if (!boolcmd) - return 0; - return new EveryCmd(RefCount(boolcmd)); - } else if (command == "not") { - BoolCommand *boolcmd = parseBoolCommand(arguments, trusted); - if (!boolcmd) - return 0; - RefCount ref(boolcmd); - return new NotCommand(ref); - } else if (command == "and") { - int pos = 0, err = 0; - AndCommand *andcmd = new AndCommand(); - string cmd; - - while (true) { - RefCount tmp(0); - err = StringUtil::getStringBetween(cmd, arguments.c_str() + pos, - '{', '}', " \t\n", true); - pos += err; - if (err == 0) - break; - - tmp = parseBoolCommand(cmd, trusted); - if (*tmp) - andcmd->add(tmp); - } - - if (andcmd->size() > 0) - return andcmd; - delete andcmd; - } else if (command == "or") { - int pos = 0, err = 0; - OrCommand *orcmd = new OrCommand(); - string cmd; - - while (true) { - RefCount tmp(0); - err = StringUtil::getStringBetween(cmd, arguments.c_str() + pos, - '{', '}', " \t\n", true); - pos += err; - if (err == 0) - break; - - tmp = parseBoolCommand(cmd, trusted); - if (*tmp) - orcmd->add(tmp); - } - - if (orcmd->size() > 0) - return orcmd; - delete orcmd; - } else if (command == "xor") { - int pos = 0, err = 0; - XorCommand *xorcmd = new XorCommand(); - string cmd; - - while (true) { - RefCount tmp(0); - err = StringUtil::getStringBetween(cmd, arguments.c_str() + pos, - '{', '}', " \t\n", true); - pos += err; - if (err == 0) - break; - - tmp = parseBoolCommand(cmd, trusted); - if (*tmp) - xorcmd->add(tmp); - } - - if (xorcmd->size() > 0) - return xorcmd; - delete xorcmd; - } - - return 0; -} - -}; // end anonymous namespace - -FbCommandFactory::FbCommandFactory() { - // setup commands that we can handle - const char* commands[] = { - "activate", - "addworkspace", - "arrangewindows", - "attach", - "bindkey", - "clientmenu", - "close", - "closeallwindows", - "commanddialog", - "cond", - "custommenu", - "deiconify", - "detachclient", - "export", - "exec", - "execcommand", - "execute", - "exit", - "focus", - "focusup", - "focusdown", - "focusleft", - "focusright", - "fullscreen", - "gotowindow", - "hidemenus", - "iconify", - "if", - "keymode", - "kill", - "killwindow", - "leftworkspace", - "lower", - "lowerlayer", - "macrocmd", - "maximize", - "maximizehorizontal", - "maximizevertical", - "maximizewindow", - "minimize", - "minimizewindow", - "moveto", - "move", - "movedown", - "moveleft", - "moveright", - "movetableft", - "movetabright", - "moveup", - "nextgroup", - "nexttab", - "nextwindow", - "nextworkspace", - "prevgroup", - "prevtab", - "prevwindow", - "prevworkspace", - "quit", - "raise", - "raiselayer", - "reconfig", - "reconfigure", - "reloadstyle", - "removelastworkspace", - "resizeto", - "resize", - "resizehorizontal", - "resizevertical", - "restart", - "rightworkspace", - "rootmenu", - "saverc", - "sendtoworkspace", - "sendtonextworkspace", - "sendtoprevworkspace", - "setalpha", - "setenv", - "sethead", - "setstyle", - "setworkspacename", - "setworkspacenamedialog", - "setresourcevalue", - "setresourcevaluedialog", - "shade", - "shadeon", - "shadeoff", - "shadewindow", - "showdesktop", - "startmoving", - "startresizing", - "stick", - "stickwindow", - "tab", - "taketoworkspace", - "taketonextworkspace", - "taketoprevworkspace", - "togglecmd", - "toggledecor", - "windowmenu", - "workspace", - /* NOTE: The following are DEPRECATED and subject to removal */ - "workspace1", - "workspace2", - "workspace3", - "workspace4", - "workspace5", - "workspace6", - "workspace7", - "workspace8", - "workspace9", - "workspace10", - "workspace11", - "workspace12", - /* end note */ - "workspacemenu", - 0 - }; - - for (int i=0; commands[i]; ++i) - addCommand(commands[i]); -} - -FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command, - const std::string &arguments, bool trusted) { - using namespace FbCommands; - // - // WM commands - // - if (command == "restart" && trusted) - return new RestartFluxboxCmd(arguments); - else if (command == "reconfigure" || command == "reconfig") - return new ReconfigureFluxboxCmd(); - else if (command == "setstyle") - return new SetStyleCmd(arguments); - else if (command == "reloadstyle") - return new ReloadStyleCmd(); - else if (command == "keymode") - return new KeyModeCmd(arguments); - else if (command == "saverc") - return new SaveResources(); - else if (command == "execcommand" || command == "execute" || command == "exec") { - if (!trusted) return 0; - return new ExecuteCmd(arguments); // execute command on key screen - } else if (command == "exit" || command == "quit") - return new ExitFluxboxCmd(); - else if ((command == "setenv" || command == "export") && trusted) { - - string name = arguments; - FbTk::StringUtil::removeFirstWhitespace(name); - FbTk::StringUtil::removeTrailingWhitespace(name); - size_t pos = name.find_first_of(command == "setenv" ? " \t" : "="); - if (pos == string::npos || pos == name.size()) - return 0; - - string value = name.substr(pos + 1); - name = name.substr(0, pos); - return new ExportCmd(name, value); - } else if (command == "commanddialog") // run specified fluxbox command - return new CommandDialogCmd(); - else if (command == "bindkey" && trusted) - return new BindKeyCmd(arguments); - else if (command == "setresourcevalue" && trusted) { - // we need to parse arguments as: - // - string name = arguments; - FbTk::StringUtil::removeFirstWhitespace(name); - size_t pos = name.find_first_of(" \t"); - // we need an argument to resource name - if (pos == std::string::npos || pos == name.size()) - return 0; - // +1 so we only remove the first whitespace - // i.e so users can set space before workspace name and so on - string value = name.substr(pos + 1); - name = name.substr(0, pos); - return new SetResourceValueCmd(name, value); - } else if (command == "setresourcevaluedialog") - return new SetResourceValueDialogCmd(); - else if (command == "addworkspace") - return new AddWorkspaceCmd(); - else if (command == "removelastworkspace") - return new RemoveLastWorkspaceCmd(); - // - // Current focused window commands - // - else if (command == "fullscreen") - return new WindowListCmd(FbTk::RefCount(new FullscreenCmd()), arguments); - else if (command == "minimizewindow" || command == "minimize" || command == "iconify") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::iconify)), arguments); - else if (command == "maximizewindow" || command == "maximize") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::maximizeFull)), arguments); - else if (command == "maximizevertical") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::maximizeVertical)), arguments); - else if (command == "maximizehorizontal") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::maximizeHorizontal)), arguments); - else if (command == "setalpha") { - typedef vector StringTokens; - StringTokens tokens; - FbTk::StringUtil::stringtok(tokens, arguments); - - int focused, unfocused; - bool relative, un_rel; - - if (tokens.empty()) { // set default alpha - focused = unfocused = 256; - relative = un_rel = false; - } else { - relative = un_rel = (tokens[0][0] == '+' || tokens[0][0] == '-'); - focused = unfocused = atoi(tokens[0].c_str()); - } - - if (tokens.size() > 1) { // set different unfocused alpha - un_rel = (tokens[1][0] == '+' || tokens[1][0] == '-'); - unfocused = atoi(tokens[1].c_str()); - } - - string pat; - string::size_type pos = arguments.find('('); - if (pos != string::npos && pos != arguments.size()) - pat = arguments.c_str() + pos; - - return new WindowListCmd(FbTk::RefCount(new SetAlphaCmd(focused, relative, unfocused, un_rel)), pat); - } else if (command == "startmoving") - return new StartMovingCmd(); - else if (command == "startresizing") { - FluxboxWindow::ResizeModel mode = FluxboxWindow::DEFAULTRESIZE; - vector tokens; - FbTk::StringUtil::stringtok >(tokens, arguments); - if (!tokens.empty()) { - string arg = FbTk::StringUtil::toLower(tokens[0]); - if (arg == "nearestcorner") - mode = FluxboxWindow::QUADRANTRESIZE; - else if (arg == "nearestedge") - mode = FluxboxWindow::NEARESTEDGERESIZE; - else if (arg == "center") - mode = FluxboxWindow::CENTERRESIZE; - else if (arg == "topleft") - mode = FluxboxWindow::TOPLEFTRESIZE; - else if (arg == "top") - mode = FluxboxWindow::TOPRESIZE; - else if (arg == "topright") - mode = FluxboxWindow::TOPRIGHTRESIZE; - else if (arg == "left") - mode = FluxboxWindow::LEFTRESIZE; - else if (arg == "right") - mode = FluxboxWindow::RIGHTRESIZE; - else if (arg == "bottomleft") - mode = FluxboxWindow::BOTTOMLEFTRESIZE; - else if (arg == "bottom") - mode = FluxboxWindow::BOTTOMRESIZE; - else if (arg == "bottomright") - mode = FluxboxWindow::BOTTOMRIGHTRESIZE; - } - return new StartResizingCmd(mode); - } else if (command == "resize" || command == "resizeto" || - command == "resizehorizontal" || command == "resizevertical") { - FbTk_istringstream is(arguments.c_str()); - int dx = 0, dy = 0; - is >> dx >> dy; - if (command == "resizehorizontal") - dy = 0; - else if (command == "resizevertical") { - dy = dx; - dx = 0; - } - - string pat; - string::size_type pos = arguments.find('('); - if (pos != string::npos && pos != arguments.size()) - pat = arguments.c_str() + pos; - - FbTk::RefCount cmd; - if (command == "resizeto") - cmd = new ResizeToCmd(dx, dy); - else - cmd = new ResizeCmd(dx, dy); - - return new WindowListCmd(cmd, pat); - } else if (command == "moveto") { - typedef vector StringTokens; - StringTokens tokens; - FbTk::StringUtil::stringtok(tokens, arguments); - - if (tokens.size() < 2) { - cerr<<"*** WARNING: missing arguments for MoveTo\n"; - return NULL; - } - - unsigned int refc = MoveToCmd::UPPER|MoveToCmd::LEFT; - int dx = 0; - int dy = 0; - - if (tokens[0][0] == '*') - refc |= MoveToCmd::IGNORE_X; - else - dx = atoi(tokens[0].c_str()); - - if (tokens[1][0] == '*' && ! (refc & MoveToCmd::IGNORE_X)) - refc |= MoveToCmd::IGNORE_Y; - else - dy = atoi(tokens[1].c_str()); - - if (tokens.size() >= 3) { - tokens[2] = FbTk::StringUtil::toLower(tokens[2]); - if (tokens[2] == "left" || tokens[2] == "upperleft" || tokens[2] == "lowerleft") { - refc |= MoveToCmd::LEFT; - refc &= ~MoveToCmd::RIGHT; - } else if (tokens[2] == "right" || tokens[2] == "upperright" || tokens[2] == "lowerright") { - refc |= MoveToCmd::RIGHT; - refc &= ~MoveToCmd::LEFT; - } - - if (tokens[2] == "upper" || tokens[2] == "upperleft" || tokens[2] == "upperright") { - refc |= MoveToCmd::UPPER; - refc &= ~MoveToCmd::LOWER; - } else if (tokens[2] == "lower" || tokens[2] == "lowerleft" || tokens[2] == "lowerright") { - refc |= MoveToCmd::LOWER; - refc &= ~MoveToCmd::UPPER; - } - } - - string pat; - string::size_type pos = arguments.find('('); - if (pos != string::npos && pos != arguments.size()) - pat = arguments.c_str() + pos; - - return new WindowListCmd(FbTk::RefCount(new MoveToCmd(dx, dy, refc)), pat); - } else if (command == "move" || command == "moveright" || - command == "moveleft" || command == "moveup" || - command == "movedown") { - FbTk_istringstream is(arguments.c_str()); - int dx = 0, dy = 0; - is >> dx >> dy; - - if (command == "moveright") - dy = 0; - else if (command == "moveleft") { - dy = 0; - dx = -dx; - } else if (command == "movedown") { - dy = dx; - dx = 0; - } else if (command == "moveup") { - dy = -dx; - dx = 0; - } - - string pat; - string::size_type pos = arguments.find('('); - if (pos != string::npos && pos != arguments.size()) - pat = arguments.c_str() + pos; - - return new WindowListCmd(FbTk::RefCount(new MoveCmd(dx, dy)), pat); - } else if (command == "raise") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::raise)), arguments); - else if (command == "raiselayer") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::raiseLayer)), arguments); - else if (command == "lower") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::lower)), arguments); - else if (command == "lowerlayer") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::lowerLayer)), arguments); - else if (command == "activate" || command == "focus") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd((void (FluxboxWindow::*)())&FluxboxWindow::focus)), arguments); - else if (command == "close") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::close)), arguments); - else if (command == "closeallwindows") - return new CloseAllWindowsCmd(); - else if (command == "killwindow" || command == "kill") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::kill)), arguments); - else if (command == "shade" || command == "shadewindow") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::shade)), arguments); - else if (command == "shadeon" ) - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::shadeOn)), arguments); - else if (command == "shadeoff" ) - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::shadeOff)), arguments); - else if (command == "stick" || command == "stickwindow") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::stick)), arguments); - else if (command == "toggledecor") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::toggleDecoration)), arguments); - else if (command == "sethead") { - int num = 0; - string pat; - FbTk_istringstream iss(arguments.c_str()); - iss >> num; - string::size_type pos = arguments.find('('); - if (pos != string::npos && pos != arguments.size()) - pat = arguments.c_str() + pos; - return new WindowListCmd(FbTk::RefCount(new SetHeadCmd(num)), pat); - } else if (command == "tab" || command == "sendtonextworkspace" || - command == "sendtoprevworkspace" || - command == "taketonextworkspace" || - command == "taketoprevworkspace" || - command == "sendtoworkspace" || command == "taketoworkspace") { - // workspaces appear 1-indexed to the user, hence the minus 1 - int num = 1; - string pat; - FbTk_istringstream iss(arguments.c_str()); - iss >> num; - string::size_type pos = arguments.find('('); - if (pos != string::npos && pos != arguments.size()) - pat = arguments.c_str() + pos; - FbTk::RefCount cmd; - - if (command == "tab") - cmd = new GoToTabCmd(num); - else if (command == "sendtonextworkspace") - cmd = new SendToNextWorkspaceCmd(num); - else if (command == "sendtoprevworkspace") - cmd = new SendToPrevWorkspaceCmd(num); - else if (command == "taketonextworkspace") - cmd = new TakeToNextWorkspaceCmd(num); - else if (command == "taketoprevworkspace") - cmd = new TakeToPrevWorkspaceCmd(num); - else if (command == "sendtoworkspace") - cmd = new SendToWorkspaceCmd(num-1); - else - cmd = new TakeToWorkspaceCmd(num-1); - return new WindowListCmd(cmd, pat); - } else if (command == "nexttab") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::nextClient)), arguments); - else if (command == "prevtab") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::prevClient)), arguments); - else if (command == "movetableft") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::moveClientLeft)), arguments); - else if (command == "movetabright") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::moveClientRight)), arguments); - else if (command == "detachclient") - return new WindowListCmd(FbTk::RefCount(new CurrentWindowCmd(&FluxboxWindow::detachCurrentClient)), arguments); - else if (command == "windowmenu") - return new CurrentWindowCmd(&FluxboxWindow::popupMenu); - // - // Workspace commands - // - else if (command == "nextworkspace") - return new NextWorkspaceCmd(getint(arguments.c_str(), 1)); - else if (command == "prevworkspace") - return new PrevWorkspaceCmd(getint(arguments.c_str(), 1)); - else if (command == "rightworkspace") - return new RightWorkspaceCmd(getint(arguments.c_str(), 1)); - else if (command == "leftworkspace") - return new LeftWorkspaceCmd(getint(arguments.c_str(), 1)); - else if (command == "workspace") - // workspaces appear 1-indexed to the user, hence the minus 1 - return new JumpToWorkspaceCmd(getint(arguments.c_str(), 1) - 1); - else if (command.substr(0, 9) == "workspace" && command[9] >= '0' && command[9] <= '9') { - cerr<<"*** WARNING: 'Workspace' actions are deprecated! Use 'Workspace ' instead"<> num; - string::size_type pos = arguments.find_first_of("({"); - if (pos != string::npos && pos != arguments.size()) - args = arguments.c_str() + pos; - FocusableList::parseArgs(args, opts, pat); - return new GoToWindowCmd(num, opts, pat); - } else if (command == "clientmenu") { - int opts; - string pat; - FocusableList::parseArgs(arguments, opts, pat); - return new ShowClientMenuCmd(opts, pat); - } else if (command == "focusup") - return new DirFocusCmd(FocusControl::FOCUSUP); - else if (command == "focusdown") - return new DirFocusCmd(FocusControl::FOCUSDOWN); - else if (command == "focusleft") - return new DirFocusCmd(FocusControl::FOCUSLEFT); - else if (command == "focusright") - return new DirFocusCmd(FocusControl::FOCUSRIGHT); - else if (command == "arrangewindows") - return new ArrangeWindowsCmd(); - else if (command == "showdesktop") - return new ShowDesktopCmd(); - else if (command == "hidemenus") - return new HideMenuCmd(); - else if (command == "rootmenu") - return new ShowRootMenuCmd(); - else if (command == "custommenu") - return new ShowCustomMenuCmd(arguments.c_str()); - else if (command == "workspacemenu") - return new ShowWorkspaceMenuCmd(); - else if (command == "setworkspacename") { - if (arguments.empty()) - return new SetWorkspaceNameCmd("empty"); - else - return new SetWorkspaceNameCmd(arguments); - } - else if (command == "setworkspacenamedialog") - return new WorkspaceNameDialogCmd(); - // - // special commands - // - else if (command == "deiconify") { - - FbTk_istringstream iss(arguments.c_str()); - string mode; - string d; - DeiconifyCmd::Destination dest; - - iss >> mode; - if (iss.fail()) - mode="lastworkspace"; - mode= FbTk::StringUtil::toLower(mode); - - iss >> d; - if (iss.fail()) - d="current"; - d= FbTk::StringUtil::toLower(d); - if (d == "origin" ) - dest= DeiconifyCmd::ORIGIN; - else if (d == "originquiet") - dest= DeiconifyCmd::ORIGINQUIET; - else - dest= DeiconifyCmd::CURRENT; - - if ( mode == "all" ) - return new DeiconifyCmd(DeiconifyCmd::ALL, dest); - else if ( mode == "allworkspace" ) - return new DeiconifyCmd(DeiconifyCmd::ALLWORKSPACE, dest); - else if ( mode == "last" ) - return new DeiconifyCmd(DeiconifyCmd::LAST, dest); - else // lastworkspace, default - return new DeiconifyCmd(DeiconifyCmd::LASTWORKSPACE, dest); - - } else if (command == "macrocmd") { - string cmd; - int err= 0; - int parse_pos= 0; - FbTk::MacroCommand* macro= new FbTk::MacroCommand(); - - while (true) { - parse_pos+= err; - err= FbTk::StringUtil::getStringBetween(cmd, arguments.c_str() + - parse_pos, - '{', '}', " \t\n", true); - if ( err > 0 ) { - string c, a; - string::size_type first_pos = - FbTk::StringUtil::removeFirstWhitespace(cmd); - string::size_type second_pos = - cmd.find_first_of(" \t", first_pos); - if (second_pos != string::npos) { - a= cmd.substr(second_pos); - FbTk::StringUtil::removeFirstWhitespace(a); - cmd.erase(second_pos); - } - c= FbTk::StringUtil::toLower(cmd); - - FbTk::Command* fbcmd= stringToCommand(c,a,trusted); - if (fbcmd) { - FbTk::RefCount rfbcmd(fbcmd); - macro->add(rfbcmd); - } - } else - break; - } - - if ( macro->size() > 0 ) - return macro; - - delete macro; - } else if (command == "togglecmd") { - string cmd; - int err= 0; - int parse_pos= 0; - FbTk::ToggleCommand* macro= new FbTk::ToggleCommand(); - - while (true) { - parse_pos+= err; - err= FbTk::StringUtil::getStringBetween(cmd, arguments.c_str() + - parse_pos, - '{', '}', " \t\n", true); - if ( err > 0 ) { - string c, a; - string::size_type first_pos = - FbTk::StringUtil::removeFirstWhitespace(cmd); - string::size_type second_pos= - cmd.find_first_of(" \t", first_pos); - if (second_pos != string::npos) { - a= cmd.substr(second_pos); - FbTk::StringUtil::removeFirstWhitespace(a); - cmd.erase(second_pos); - } - c= FbTk::StringUtil::toLower(cmd); - - FbTk::Command* fbcmd= stringToCommand(c,a,trusted); - if (fbcmd) { - FbTk::RefCount rfbcmd(fbcmd); - macro->add(rfbcmd); - } - } else - break; - } - - if ( macro->size() > 0 ) - return macro; - - delete macro; - } else if (command == "if" || command == "cond") { - string cmd; - int err = 0, pos = 0; - RefCount cond(0); - RefCount t(0), f(0); - - err = FbTk::StringUtil::getStringBetween(cmd, arguments.c_str(), - '{', '}', " \t\n", true); - if (err > 0) - cond = parseBoolCommand(cmd, trusted); - if (err == 0 || *cond == 0) - return 0; - - pos = err; - err = FbTk::StringUtil::getStringBetween(cmd, arguments.c_str() + pos, - '{', '}', " \t\n", true); - if (err == 0) - return 0; - t = CommandParser::instance().parseLine(cmd, trusted); - - pos += err; - err = FbTk::StringUtil::getStringBetween(cmd, arguments.c_str() + pos, - '{', '}', " \t\n", true); - if (err > 0) - f = CommandParser::instance().parseLine(cmd, trusted); - if (err == 0 || *t == 0 && *f == 0) - return 0; - - return new FbTk::IfCommand(cond, t, f); - } - return 0; -} diff --git a/src/FbCommandFactory.hh b/src/FbCommandFactory.hh deleted file mode 100644 index 4b68499..0000000 --- a/src/FbCommandFactory.hh +++ /dev/null @@ -1,35 +0,0 @@ -// FbCommandFactory.hh for Fluxbox Window manager -// Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org) -// and Simon Bowden (rathnor at users.sourceforge.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -// $Id$ - -#include "CommandParser.hh" - -class FbCommandFactory: public CommandFactory { -public: - FbTk::Command *stringToCommand(const std::string &command, - const std::string &arguments, bool trusted); - -private: - FbCommandFactory(); - static FbCommandFactory s_autoreg; ///< autoregister variable -}; diff --git a/src/FbCommands.cc b/src/FbCommands.cc index de14f73..0d4e0e3 100644 --- a/src/FbCommands.cc +++ b/src/FbCommands.cc @@ -33,6 +33,9 @@ #include "FbTk/Theme.hh" #include "FbTk/Menu.hh" +#include "FbTk/CommandRegistry.hh" +#include "FbTk/StringUtil.hh" +#include "FbTk/stringstream.hh" #include #include @@ -120,6 +123,10 @@ void showMenu(const BScreen &screen, FbTk::Menu &menu) { namespace FbCommands { +REGISTER_UNTRUSTED_COMMAND_WITH_ARGS(exec, FbCommands::ExecuteCmd); +REGISTER_UNTRUSTED_COMMAND_WITH_ARGS(execute, FbCommands::ExecuteCmd); +REGISTER_UNTRUSTED_COMMAND_WITH_ARGS(execcommand, FbCommands::ExecuteCmd); + ExecuteCmd::ExecuteCmd(const string &cmd, int screen_num):m_cmd(cmd), m_screen_num(screen_num) { } @@ -169,6 +176,27 @@ int ExecuteCmd::run() { return pid; // compiler happy -> we are happy ;) } +FbTk::Command *ExportCmd::parse(const string &command, const string &args, + bool trusted) { + string name = args; + FbTk::StringUtil::removeFirstWhitespace(name); + if (command != "setresourcevalue") + FbTk::StringUtil::removeTrailingWhitespace(name); + size_t pos = name.find_first_of(command == "export" ? "=" : " \t"); + if (pos == string::npos || pos == name.size() || !trusted) + return 0; + + string value = name.substr(pos + 1); + name = name.substr(0, pos); + if (command == "setresourcevalue") + return new SetResourceValueCmd(name, value); + return new ExportCmd(name, value); +} + +REGISTER_COMMAND_PARSER(setenv, ExportCmd::parse); +REGISTER_COMMAND_PARSER(export, ExportCmd::parse); +REGISTER_COMMAND_PARSER(setresourcevalue, ExportCmd::parse); + ExportCmd::ExportCmd(const string& name, const string& value) : m_name(name), m_value(value) { } @@ -205,15 +233,21 @@ void ExportCmd::execute() { } } +REGISTER_COMMAND(exit, FbCommands::ExitFluxboxCmd); +REGISTER_COMMAND(quit, FbCommands::ExitFluxboxCmd); void ExitFluxboxCmd::execute() { Fluxbox::instance()->shutdown(); } +REGISTER_COMMAND(saverc, FbCommands::SaveResources); + void SaveResources::execute() { Fluxbox::instance()->save_rc(); } +REGISTER_UNTRUSTED_COMMAND_WITH_ARGS(restart, FbCommands::RestartFluxboxCmd); + RestartFluxboxCmd::RestartFluxboxCmd(const string &cmd):m_cmd(cmd){ } @@ -224,16 +258,22 @@ void RestartFluxboxCmd::execute() { Fluxbox::instance()->restart(m_cmd.c_str()); } +REGISTER_COMMAND(reconfigure, FbCommands::ReconfigureFluxboxCmd); +REGISTER_COMMAND(reconfig, FbCommands::ReconfigureFluxboxCmd); + void ReconfigureFluxboxCmd::execute() { Fluxbox::instance()->reconfigure(); } +REGISTER_COMMAND(reloadstyle, FbCommands::ReloadStyleCmd); void ReloadStyleCmd::execute() { SetStyleCmd cmd(Fluxbox::instance()->getStyleFilename()); cmd.execute(); } +REGISTER_COMMAND_WITH_ARGS(setstyle, FbCommands::SetStyleCmd); + SetStyleCmd::SetStyleCmd(const string &filename):m_filename(filename) { } @@ -245,6 +285,8 @@ void SetStyleCmd::execute() { Fluxbox::instance()->getStyleOverlayFilename()); } +REGISTER_COMMAND_WITH_ARGS(keymode, FbCommands::KeyModeCmd); + KeyModeCmd::KeyModeCmd(const string &arguments):m_keymode(arguments),m_end_args("None Escape") { string::size_type second_pos = m_keymode.find_first_of(" \t", 0); if (second_pos != string::npos) { @@ -260,10 +302,22 @@ void KeyModeCmd::execute() { Fluxbox::instance()->keys()->keyMode(m_keymode); } +REGISTER_COMMAND(hidemenus, FbCommands::HideMenuCmd); + void HideMenuCmd::execute() { FbTk::Menu::hideShownMenu(); } +FbTk::Command *ShowClientMenuCmd::parse(const string &command, + const string &args, bool trusted) { + int opts; + string pat; + FocusableList::parseArgs(args, opts, pat); + return new ShowClientMenuCmd(opts, pat); +} + +REGISTER_COMMAND_PARSER(clientmenu, ShowClientMenuCmd::parse); + void ShowClientMenuCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0) @@ -285,6 +339,8 @@ void ShowClientMenuCmd::execute() { ::showMenu(*screen, **m_menu); } +REGISTER_COMMAND_WITH_ARGS(custommenu, FbCommands::ShowCustomMenuCmd); + ShowCustomMenuCmd::ShowCustomMenuCmd(const string &arguments) : custom_menu_file(arguments) {} void ShowCustomMenuCmd::execute() { @@ -298,6 +354,8 @@ void ShowCustomMenuCmd::execute() { ::showMenu(*screen, **m_menu); } +REGISTER_COMMAND(rootmenu, FbCommands::ShowRootMenuCmd); + void ShowRootMenuCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0) @@ -306,6 +364,8 @@ void ShowRootMenuCmd::execute() { ::showMenu(*screen, screen->rootMenu()); } +REGISTER_COMMAND(workspacemenu, FbCommands::ShowWorkspaceMenuCmd); + void ShowWorkspaceMenuCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0) @@ -314,10 +374,13 @@ void ShowWorkspaceMenuCmd::execute() { ::showMenu(*screen, screen->workspaceMenu()); } - +REGISTER_COMMAND_WITH_ARGS(setworkspacename, FbCommands::SetWorkspaceNameCmd); SetWorkspaceNameCmd::SetWorkspaceNameCmd(const string &name, int spaceid): - m_name(name), m_workspace(spaceid) { } + m_name(name), m_workspace(spaceid) { + if (name.empty()) + m_name = "empty"; +} void SetWorkspaceNameCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); @@ -340,6 +403,8 @@ void SetWorkspaceNameCmd::execute() { Fluxbox::instance()->save_rc(); } +REGISTER_COMMAND(setworkspacenamedialog, FbCommands::WorkspaceNameDialogCmd); + void WorkspaceNameDialogCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); @@ -351,6 +416,8 @@ void WorkspaceNameDialogCmd::execute() { win->show(); } +REGISTER_COMMAND(commanddialog, FbCommands::CommandDialogCmd); + void CommandDialogCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0) @@ -376,6 +443,8 @@ void SetResourceValueCmd::execute() { Fluxbox::instance()->save_rc(); } +REGISTER_COMMAND(setresourcevaluedialog, FbCommands::SetResourceValueDialogCmd); + void SetResourceValueDialogCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0) @@ -385,6 +454,8 @@ void SetResourceValueDialogCmd::execute() { win->show(); }; +REGISTER_UNTRUSTED_COMMAND_WITH_ARGS(bindkey, FbCommands::BindKeyCmd); + BindKeyCmd::BindKeyCmd(const string &keybind):m_keybind(keybind) { } void BindKeyCmd::execute() { @@ -398,6 +469,41 @@ void BindKeyCmd::execute() { } } +FbTk::Command *DeiconifyCmd::parse(const string &command, const string &args, + bool trusted) { + FbTk_istringstream iss(args.c_str()); + string mode; + string d; + Destination dest; + + iss >> mode; + if (iss.fail()) + mode="lastworkspace"; + mode= FbTk::StringUtil::toLower(mode); + + iss >> d; + if (iss.fail()) + d="current"; + d = FbTk::StringUtil::toLower(d); + if (d == "origin" ) + dest = ORIGIN; + else if (d == "originquiet") + dest = ORIGINQUIET; + else + dest = CURRENT; + + if (mode == "all") + return new DeiconifyCmd(DeiconifyCmd::ALL, dest); + else if (mode == "allworkspace") + return new DeiconifyCmd(DeiconifyCmd::ALLWORKSPACE, dest); + else if (mode == "last") + return new DeiconifyCmd(DeiconifyCmd::LAST, dest); + // lastworkspace, default + return new DeiconifyCmd(DeiconifyCmd::LASTWORKSPACE, dest); +} + +REGISTER_COMMAND_PARSER(deiconify, DeiconifyCmd::parse); + DeiconifyCmd::DeiconifyCmd(Mode mode, Destination dest) : m_mode(mode), m_dest(dest) { } diff --git a/src/FbCommands.hh b/src/FbCommands.hh index c130050..566b17a 100644 --- a/src/FbCommands.hh +++ b/src/FbCommands.hh @@ -57,6 +57,8 @@ class ExportCmd : public FbTk::Command { public: ExportCmd(const std::string& name, const std::string& value); void execute(); + static FbTk::Command *parse(const std::string &command, + const std::string &args, bool trusted); private: std::string m_name; std::string m_value; @@ -121,6 +123,8 @@ public: ShowClientMenuCmd(int option, std::string &pat): m_option(option|FocusableList::LIST_GROUPS), m_pat(pat.c_str()) { } void execute(); + static FbTk::Command *parse(const std::string &command, + const std::string &args, bool trusted); private: const int m_option; const ClientPattern m_pat; @@ -208,6 +212,8 @@ public: DeiconifyCmd(Mode mode= LASTWORKSPACE, Destination dest= CURRENT); void execute(); + static FbTk::Command *parse(const std::string &command, + const std::string &args, bool trusted); private: Mode m_mode; Destination m_dest; diff --git a/src/FbTk/CommandRegistry.cc b/src/FbTk/CommandRegistry.cc new file mode 100644 index 0000000..1d16c75 --- /dev/null +++ b/src/FbTk/CommandRegistry.cc @@ -0,0 +1,92 @@ +// CommandRegistry.cc for FbTk +// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id: $ + +#include "CommandRegistry.hh" +#include "Command.hh" +#include "StringUtil.hh" + +#include + +namespace FbTk { + +CommandRegistry &CommandRegistry::instance() { + static CommandRegistry s_instance; + return s_instance; +} + + +bool CommandRegistry::registerCommand(string name, + CreateFunction createFunction) { + name = StringUtil::toLower(name); + m_commandCreators[name] = createFunction; + return true; +} + +bool CommandRegistry::registerBoolCommand(string name, + BoolCreateFunction createFunction) { + name = StringUtil::toLower(name); + m_boolcommandCreators[name] = createFunction; + return true; +} + +Command *CommandRegistry::parseLine(const string &line, bool trusted) const { + // parse args and command + string command, args; + StringUtil::getFirstWord(line, command, args); + + // now we have parsed command and args + command = StringUtil::toLower(command); + return getCommand(command, args, trusted); +} + +BoolCommand *CommandRegistry::parseBoolLine(const string &line, bool trusted) const { + // parse args and command + string command, args; + StringUtil::getFirstWord(line, command, args); + + // now we have parsed command and args + command = StringUtil::toLower(command); + return getBoolCommand(command, args, trusted); +} + +Command *CommandRegistry::getCommand(const string &name, const string &args, + bool trusted) const { + string lc = StringUtil::toLower(name); + CreatorMap::const_iterator it = m_commandCreators.find(lc.c_str()); + if (it == m_commandCreators.end()) + return 0; + else + return it->second(name, args, trusted); +} + +BoolCommand *CommandRegistry::getBoolCommand(const string &name, + const string &args, bool trusted) const { + string lc = StringUtil::toLower(name); + BoolCreatorMap::const_iterator it = m_boolcommandCreators.find(lc.c_str()); + if (it == m_boolcommandCreators.end()) + return 0; + else + return it->second(name, args, trusted); +} + +}; // end namespace FbTk diff --git a/src/FbTk/CommandRegistry.hh b/src/FbTk/CommandRegistry.hh new file mode 100644 index 0000000..f3b6880 --- /dev/null +++ b/src/FbTk/CommandRegistry.hh @@ -0,0 +1,130 @@ +// CommandRegistry.hh for FbTk +// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id: $ + +#ifndef COMMANDREGISTRY_HH +#define COMMANDREGISTRY_HH + +#include +#include + +using std::string; + +namespace FbTk { +class Command; +class BoolCommand; + +#define REGISTER_COMMAND_PARSER(name, parser) \ + namespace { \ + static const bool p_register_##name = FbTk::CommandRegistry::instance().registerCommand(#name, parser); \ + } + +#define REGISTER_BOOLCOMMAND_PARSER(name, parser) \ + namespace { \ + static const bool p_register_##name = FbTk::CommandRegistry::instance().registerBoolCommand(#name, parser); \ + } + +/* Include some basic command creators */ +template +Ret *CommandCreator(const string &name, const string &args, bool trusted) { + return new Cmd(); +} + +#define REGISTER_COMMAND(name, classname) \ + namespace { \ + static const bool p_register_##name = FbTk::CommandRegistry::instance().registerCommand(#name, FbTk::CommandCreator); \ + } + +template +Ret *CommandCreatorWithArgs(const string &name, const string &args, + bool trusted) { + return new Cmd(args); +} + +#define REGISTER_COMMAND_WITH_ARGS(name, classname) \ + namespace { \ + static const bool p_register_##name = FbTk::CommandRegistry::instance().registerCommand(#name, FbTk::CommandCreatorWithArgs); \ + } + +#define REGISTER_BOOLCOMMAND_WITH_ARGS(name, classname) \ + namespace { \ + static const bool p_register_##name = FbTk::CommandRegistry::instance().registerBoolCommand(#name, FbTk::CommandCreatorWithArgs); \ + } + +template +Ret *UntrustedCommandCreator(const string &name, const string &args, + bool trusted) { + if (!trusted) return 0; + return new Cmd(); +} + +#define REGISTER_UNTRUSTED_COMMAND(name, classname) \ + namespace { \ + static const bool p_register_##name = FbTk::CommandRegistry::instance().registerCommand(#name, FbTk::UntrustedCommandCreator); \ + } + +template +Ret * UntrustedCommandCreatorWithArgs(const string &name, const string &args, + bool trusted) { + if (!trusted) return 0; + return new Cmd(args); +} + +#define REGISTER_UNTRUSTED_COMMAND_WITH_ARGS(name, classname) \ + namespace { \ + static const bool p_register_##name = FbTk::CommandRegistry::instance().registerCommand(#name, FbTk::UntrustedCommandCreatorWithArgs); \ + } + +/* Not built to be virtual at the moment */ +class CommandRegistry { +public: + typedef Command * CreateFunction(const string &name, const string &args, bool trusted); + typedef BoolCommand * BoolCreateFunction(const string &name, + const string &args, bool trusted); + typedef std::map CreatorMap; + typedef std::map BoolCreatorMap; + + static CommandRegistry &instance(); + + Command *parseLine(const string &line, bool trusted = true) const; + BoolCommand *parseBoolLine(const string &line, bool trusted = true) const; + Command *getCommand(const string &name, const string &args, bool trusted) const; + BoolCommand *getBoolCommand(const string &name, const string &args, + bool trusted) const; + + /* Note: the ownership of this object passes to this class */ + bool registerCommand(string name, CreateFunction createFunction); + bool registerBoolCommand(string name, BoolCreateFunction bcf); + + const CreatorMap commandMap() const { return m_commandCreators; } + +private: + CommandRegistry() {} + ~CommandRegistry() {} + + CreatorMap m_commandCreators; + BoolCreatorMap m_boolcommandCreators; +}; + +}; // end namespace FbTk + +#endif // COMMANDREGISTRY_HH diff --git a/src/FbTk/LogicCommands.cc b/src/FbTk/LogicCommands.cc index 99b5b53..1c6f238 100644 --- a/src/FbTk/LogicCommands.cc +++ b/src/FbTk/LogicCommands.cc @@ -23,8 +23,101 @@ #include "LogicCommands.hh" +#include "CommandRegistry.hh" +#include "StringUtil.hh" + +using FbTk::StringUtil::removeFirstWhitespace; +using FbTk::StringUtil::toLower; +using std::string; + namespace FbTk { +namespace { + +template +M *addCommands(M *macro, const string &args, bool trusted) { + int pos = 0, err = 0; + string cmd; + + while (true) { + RefCount tmp(0); + err = StringUtil::getStringBetween(cmd, args.c_str() + pos, + '{', '}', " \t\n", true); + pos += err; + if (err == 0) + break; + + tmp = CommandRegistry::instance().parseBoolLine(cmd, trusted); + if (*tmp) + macro->add(tmp); + } + + if (macro->size() > 0) + return macro; + delete macro; + return 0; +} + +BoolCommand *parseLogicCommand(const string &command, const string &args, + bool trusted) { + if (command == "not") { + BoolCommand *boolcmd = + CommandRegistry::instance().parseBoolLine(args, trusted); + if (!boolcmd) + return 0; + RefCount ref(boolcmd); + return new NotCommand(ref); + } else if (command == "and") + return addCommands(new AndCommand(), args, trusted); + else if (command == "or") + return addCommands(new OrCommand(), args, trusted); + else if (command == "xor") + return addCommands(new XorCommand(), args, trusted); + return 0; +} + +REGISTER_BOOLCOMMAND_PARSER(not, parseLogicCommand); +REGISTER_BOOLCOMMAND_PARSER(and, parseLogicCommand); +REGISTER_BOOLCOMMAND_PARSER(or, parseLogicCommand); +REGISTER_BOOLCOMMAND_PARSER(xor, parseLogicCommand); + +}; // end anonymous namespace + +Command *IfCommand::parse(const std::string &command, const std::string &args, + bool trusted) { + std::string cmd; + int err = 0, pos = 0; + RefCount cond(0); + RefCount t(0), f(0); + + err = StringUtil::getStringBetween(cmd, args.c_str(), + '{', '}', " \t\n", true); + if (err > 0) + cond = CommandRegistry::instance().parseBoolLine(cmd, trusted); + if (err == 0 || *cond == 0) + return 0; + + pos = err; + err = StringUtil::getStringBetween(cmd, args.c_str() + pos, + '{', '}', " \t\n", true); + if (err == 0) + return 0; + t = CommandRegistry::instance().parseLine(cmd, trusted); + + pos += err; + err = StringUtil::getStringBetween(cmd, args.c_str() + pos, + '{', '}', " \t\n", true); + if (err > 0) + f = CommandRegistry::instance().parseLine(cmd, trusted); + if (err == 0 || *t == 0 && *f == 0) + return 0; + + return new IfCommand(cond, t, f); +} + +REGISTER_COMMAND_PARSER(if, IfCommand::parse); +REGISTER_COMMAND_PARSER(cond, IfCommand::parse); + void OrCommand::add(RefCount &com) { m_commandlist.push_back(com); } diff --git a/src/FbTk/LogicCommands.hh b/src/FbTk/LogicCommands.hh index 4f20864..3eb3e8c 100644 --- a/src/FbTk/LogicCommands.hh +++ b/src/FbTk/LogicCommands.hh @@ -27,6 +27,7 @@ #include "Command.hh" #include "RefCount.hh" +#include #include namespace FbTk { @@ -43,7 +44,8 @@ public: } else if (*m_f) m_f->execute(); } - + static Command *parse(const std::string &cmd, const std::string &args, + bool trusted); private: RefCount m_cond; RefCount m_t, m_f; diff --git a/src/FbTk/MacroCommand.cc b/src/FbTk/MacroCommand.cc index 491b01e..20e91e4 100644 --- a/src/FbTk/MacroCommand.cc +++ b/src/FbTk/MacroCommand.cc @@ -23,8 +23,56 @@ #include "MacroCommand.hh" +#include "CommandRegistry.hh" +#include "StringUtil.hh" + +#include + namespace FbTk { +namespace { + +template +M *addCommands(M *macro, const std::string &args, bool trusted) { + + std::string cmd; + int err = 0; + int pos = 0; + + while (true) { + RefCount next(0); + pos += err; + err = StringUtil::getStringBetween(cmd, args.c_str() + pos, + '{', '}', " \t\n", true); + if (err == 0) + break; + if (err > 0) + next = CommandRegistry::instance().parseLine(cmd, trusted); + if (*next != 0) + macro->add(next); + } + + if (macro->size() > 0) + return macro; + + delete macro; + return 0; +} + +Command *parseMacroCmd(const std::string &command, const std::string &args, + bool trusted) { + if (command == "macrocmd") + return addCommands(new MacroCommand, args, trusted); + else if (command == "togglecmd") + return addCommands(new ToggleCommand, args, trusted); + return 0; +} + +REGISTER_COMMAND_PARSER(macrocmd, parseMacroCmd); +REGISTER_COMMAND_PARSER(togglecmd, parseMacroCmd); + +}; // end anonymous namespace + void MacroCommand::add(RefCount &com) { m_commandlist.push_back(com); } diff --git a/src/FbTk/Makefile.am b/src/FbTk/Makefile.am index 2bf9da7..f3e928d 100644 --- a/src/FbTk/Makefile.am +++ b/src/FbTk/Makefile.am @@ -16,6 +16,7 @@ imlib2_SOURCE= ImageImlib2.hh ImageImlib2.cc endif libFbTk_a_SOURCES = App.hh App.cc Color.cc Color.hh Command.hh \ + CommandRegistry.hh CommandRegistry.cc \ FileUtil.hh FileUtil.cc \ EventHandler.hh EventManager.hh EventManager.cc \ FbWindow.hh FbWindow.cc Font.cc Font.hh FontImp.hh \ diff --git a/src/FbTk/StringUtil.cc b/src/FbTk/StringUtil.cc index 869a3b5..9b4928b 100644 --- a/src/FbTk/StringUtil.cc +++ b/src/FbTk/StringUtil.cc @@ -233,6 +233,18 @@ string::size_type removeTrailingWhitespace(string &str) { return first_pos; } +void getFirstWord(const std::string &in, std::string &word, std::string &rest) { + word = in; + string::size_type first_pos = StringUtil::removeFirstWhitespace(word); + string::size_type second_pos = word.find_first_of(" \t", first_pos); + if (second_pos != string::npos) { + rest = word.substr(second_pos); + word.erase(second_pos); + removeFirstWhitespace(rest); + removeTrailingWhitespace(rest); + } +} + }; // end namespace StringUtil }; // end namespace FbTk diff --git a/src/FbTk/StringUtil.hh b/src/FbTk/StringUtil.hh index b45d6a2..7f0cf54 100644 --- a/src/FbTk/StringUtil.hh +++ b/src/FbTk/StringUtil.hh @@ -64,6 +64,9 @@ std::string basename(const std::string &basename); std::string::size_type removeFirstWhitespace(std::string &str); std::string::size_type removeTrailingWhitespace(std::string &str); +/// removes the first part of a string and returns the two pieces +void getFirstWord(const std::string &in, std::string &first, std::string &rest); + /// Breaks a string into tokens template static void diff --git a/src/IconbarTool.cc b/src/IconbarTool.cc index 2574762..f0179d1 100644 --- a/src/IconbarTool.cc +++ b/src/IconbarTool.cc @@ -33,7 +33,7 @@ #include "Workspace.hh" #include "FbMenu.hh" #include "BoolMenuItem.hh" -#include "CommandParser.hh" +#include "FbTk/CommandRegistry.hh" #include "WinClient.hh" #include "FocusControl.hh" #include "FbCommands.hh" @@ -282,7 +282,7 @@ IconbarTool::IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme, // setup use pixmap item to reconfig iconbar and save resource on click MacroCommand *save_and_reconfig = new MacroCommand(); RefCount reconfig(new SimpleCommand(*this, &IconbarTool::renderTheme)); - RefCount save(CommandParser::instance().parseLine("saverc")); + RefCount save(FbTk::CommandRegistry::instance().parseLine("saverc")); save_and_reconfig->add(reconfig); save_and_reconfig->add(save); RefCount s_and_reconfig(save_and_reconfig); diff --git a/src/Keys.cc b/src/Keys.cc index 06a0d48..e102029 100644 --- a/src/Keys.cc +++ b/src/Keys.cc @@ -32,7 +32,7 @@ #include "FbTk/App.hh" #include "FbTk/Command.hh" -#include "CommandParser.hh" +#include "FbTk/CommandRegistry.hh" #include "FbTk/I18n.hh" #ifdef HAVE_CONFIG_H @@ -395,7 +395,7 @@ bool Keys::addBinding(const string &linebuffer) { const char *str = FbTk::StringUtil::strcasestr(linebuffer.c_str(), val[argc].c_str() + 1); // +1 to skip ':' if (str) - current_key->m_command = CommandParser::instance().parseLine(str); + current_key->m_command = FbTk::CommandRegistry::instance().parseLine(str); if (!str || *current_key->m_command == 0 || mod) { delete first_new_key; diff --git a/src/LayerMenu.hh b/src/LayerMenu.hh index fcc4edb..4f4a0a9 100644 --- a/src/LayerMenu.hh +++ b/src/LayerMenu.hh @@ -64,7 +64,7 @@ private: /// Create a layer menu inside from the given menu class LayerMenu : public ToggleMenu { public: - LayerMenu(MenuTheme &tm, FbTk::ImageControl &imgctrl, + LayerMenu(class MenuTheme &tm, FbTk::ImageControl &imgctrl, FbTk::XLayer &layer, LayerObject *item, bool save_rc); void show(); }; diff --git a/src/Makefile.am b/src/Makefile.am index 3ecc610..e718092 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -118,8 +118,6 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \ Xutil.hh Xutil.cc \ CurrentWindowCmd.hh CurrentWindowCmd.cc \ WorkspaceCmd.hh WorkspaceCmd.cc \ - CommandParser.hh CommandParser.cc \ - FbCommandFactory.hh FbCommandFactory.cc \ Shape.hh Shape.cc \ MenuTheme.hh MenuTheme.cc \ Container.hh Container.cc \ @@ -156,4 +154,4 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \ ${REMEMBER_SOURCE} ${TOOLBAR_SOURCE} -LDADD=FbTk/libFbTk.a defaults.$(OBJEXT) +LDADD=FbTk/libFbTk.a FbTk/LogicCommands.o defaults.$(OBJEXT) diff --git a/src/MenuCreator.cc b/src/MenuCreator.cc index 8cc483a..b98287b 100644 --- a/src/MenuCreator.cc +++ b/src/MenuCreator.cc @@ -26,7 +26,7 @@ #include "defaults.hh" #include "Screen.hh" -#include "CommandParser.hh" +#include "FbTk/CommandRegistry.hh" #include "fluxbox.hh" #include "Window.hh" #include "WindowCmd.hh" @@ -247,7 +247,7 @@ static void translateMenuItem(Parser &parse, ParseItem &pitem, FbTk::StringConve else menu.insert(str_label, submenu); } else if (str_key == "exit") { // exit - FbTk::RefCount exit_cmd(CommandParser::instance().parseLine("exit")); + FbTk::RefCount exit_cmd(FbTk::CommandRegistry::instance().parseLine("exit")); if (str_label.empty()) menu.insert(_FB_XTEXT(Menu, Exit, "Exit", "Exit Command"), exit_cmd); else @@ -255,8 +255,8 @@ static void translateMenuItem(Parser &parse, ParseItem &pitem, FbTk::StringConve } else if (str_key == "exec") { // execute and hide menu using namespace FbTk; - RefCount exec_cmd(CommandParser::instance().parseLine("exec " + str_cmd)); - RefCount hide_menu(CommandParser::instance().parseLine("hidemenus")); + RefCount exec_cmd(FbTk::CommandRegistry::instance().parseLine("exec " + str_cmd)); + RefCount hide_menu(FbTk::CommandRegistry::instance().parseLine("hidemenus")); MacroCommand *exec_and_hide = new FbTk::MacroCommand(); exec_and_hide->add(hide_menu); exec_and_hide->add(exec_cmd); @@ -264,8 +264,8 @@ static void translateMenuItem(Parser &parse, ParseItem &pitem, FbTk::StringConve menu.insert(str_label, exec_and_hide_cmd); } else if (str_key == "macrocmd") { using namespace FbTk; - RefCount macro_cmd(CommandParser::instance().parseLine("macrocmd " + str_cmd)); - RefCount hide_menu(CommandParser::instance().parseLine("hidemenus")); + RefCount macro_cmd(FbTk::CommandRegistry::instance().parseLine("macrocmd " + str_cmd)); + RefCount hide_menu(FbTk::CommandRegistry::instance().parseLine("hidemenus")); MacroCommand *exec_and_hide = new FbTk::MacroCommand(); exec_and_hide->add(hide_menu); exec_and_hide->add(macro_cmd); @@ -364,7 +364,7 @@ static void translateMenuItem(Parser &parse, ParseItem &pitem, FbTk::StringConve else { // ok, if we didn't find any special menu item we try with command parser // we need to attach command with arguments so command parser can parse it string line = str_key + " " + str_cmd; - FbTk::RefCount command(CommandParser::instance().parseLine(line)); + FbTk::RefCount command(FbTk::CommandRegistry::instance().parseLine(line)); if (*command != 0) { // special NLS default labels if (str_label.empty()) { diff --git a/src/Screen.cc b/src/Screen.cc index 79a75ef..1651824 100644 --- a/src/Screen.cc +++ b/src/Screen.cc @@ -60,7 +60,7 @@ #include "WinClient.hh" #include "FbWinFrame.hh" #include "Strut.hh" -#include "CommandParser.hh" +#include "FbTk/CommandRegistry.hh" #include "AtomHandler.hh" #include "HeadArea.hh" #include "FbCommands.hh" @@ -815,7 +815,7 @@ void BScreen::propertyNotify(Atom atom) { &ret_bytes_after, (unsigned char **)&str); } - FbTk::RefCount cmd(CommandParser::instance().parseLine(str, false)); + FbTk::RefCount cmd(FbTk::CommandRegistry::instance().parseLine(str, false)); if (cmd.get()) cmd->execute(); XFree(str); @@ -1531,9 +1531,9 @@ void BScreen::initMenu() { if (m_rootmenu.get() == 0) { _FB_USES_NLS; m_rootmenu.reset(createMenu(_FB_XTEXT(Menu, DefaultRootMenu, "Fluxbox default menu", "Title of fallback root menu"))); - FbTk::RefCount restart_fb(CommandParser::instance().parseLine("restart")); - FbTk::RefCount exit_fb(CommandParser::instance().parseLine("exit")); - FbTk::RefCount execute_xterm(CommandParser::instance().parseLine("exec xterm")); + FbTk::RefCount restart_fb(FbTk::CommandRegistry::instance().parseLine("restart")); + FbTk::RefCount exit_fb(FbTk::CommandRegistry::instance().parseLine("exit")); + FbTk::RefCount execute_xterm(FbTk::CommandRegistry::instance().parseLine("exec xterm")); m_rootmenu->setInternalMenu(); m_rootmenu->insert("xterm", execute_xterm); m_rootmenu->insert(_FB_XTEXT(Menu, Restart, "Restart", "Restart command"), @@ -1578,7 +1578,7 @@ void BScreen::setupConfigmenu(FbTk::Menu &menu) { FbTk::RefCount saverc_cmd(new FbTk::SimpleCommand( *Fluxbox::instance(), &Fluxbox::save_rc)); - FbTk::RefCount reconf_cmd(CommandParser::instance().parseLine("reconfigure")); + FbTk::RefCount reconf_cmd(FbTk::CommandRegistry::instance().parseLine("reconfigure")); FbTk::RefCount reconftabs_cmd(new FbTk::SimpleCommand( *this, diff --git a/src/Slit.hh b/src/Slit.hh index 06a8a25..aa88a5d 100644 --- a/src/Slit.hh +++ b/src/Slit.hh @@ -177,7 +177,7 @@ private: FbTk::Resource m_rc_placement; FbTk::Resource m_rc_direction; FbTk::Resource m_rc_alpha, m_rc_on_head; - FbTk::Resource m_rc_layernum; + FbTk::Resource m_rc_layernum; }; diff --git a/src/ToggleMenu.hh b/src/ToggleMenu.hh index 10c8594..66f33c4 100644 --- a/src/ToggleMenu.hh +++ b/src/ToggleMenu.hh @@ -32,7 +32,7 @@ */ class ToggleMenu: public FbMenu { public: - ToggleMenu(MenuTheme &tm, FbTk::ImageControl &imgctrl, + ToggleMenu(class MenuTheme &tm, FbTk::ImageControl &imgctrl, FbTk::XLayer &layer):FbMenu(tm, imgctrl, layer) {} virtual ~ToggleMenu() {} diff --git a/src/ToolFactory.cc b/src/ToolFactory.cc index 3fa8714..c54dd19 100644 --- a/src/ToolFactory.cc +++ b/src/ToolFactory.cc @@ -36,7 +36,7 @@ #include "WorkspaceNameTheme.hh" #include "ButtonTheme.hh" -#include "CommandParser.hh" +#include "FbTk/CommandRegistry.hh" #include "Screen.hh" #include "Toolbar.hh" #include "fluxbox.hh" @@ -107,7 +107,7 @@ ToolbarItem *ToolFactory::create(const std::string &name, const FbTk::FbWindow & } else if (name == "nextworkspace" || name == "prevworkspace") { - FbTk::RefCount cmd(CommandParser::instance().parseLine(name)); + FbTk::RefCount cmd(FbTk::CommandRegistry::instance().parseLine(name)); if (*cmd == 0) // we need a command return 0; @@ -127,7 +127,7 @@ ToolbarItem *ToolFactory::create(const std::string &name, const FbTk::FbWindow & } else if (name == "nextwindow" || name == "prevwindow") { - FbTk::RefCount cmd(CommandParser::instance().parseLine(name)); + FbTk::RefCount cmd(FbTk::CommandRegistry::instance().parseLine(name)); if (*cmd == 0) // we need a command return 0; diff --git a/src/Toolbar.cc b/src/Toolbar.cc index 55ae1d3..3e446d8 100644 --- a/src/Toolbar.cc +++ b/src/Toolbar.cc @@ -44,7 +44,7 @@ #endif // XINERAMA #include "Strut.hh" -#include "CommandParser.hh" +#include "FbTk/CommandRegistry.hh" #include "Layer.hh" #include "FbTk/I18n.hh" @@ -823,7 +823,7 @@ void Toolbar::setupMenus(bool skip_new_placement) { "Toolbar", "Title of Toolbar menu")); RefCommand reconfig_toolbar(new ToolbarCommand(*this, &Toolbar::reconfigure)); - RefCommand save_resources(CommandParser::instance().parseLine("saverc")); + RefCommand save_resources(FbTk::CommandRegistry::instance().parseLine("saverc")); MacroCommand *toolbar_menuitem_macro = new MacroCommand(); toolbar_menuitem_macro->add(reconfig_toolbar); toolbar_menuitem_macro->add(save_resources); diff --git a/src/Toolbar.hh b/src/Toolbar.hh index 243ce52..4062f83 100644 --- a/src/Toolbar.hh +++ b/src/Toolbar.hh @@ -178,7 +178,7 @@ private: FbTk::Resource m_rc_auto_hide, m_rc_maximize_over, m_rc_visible; FbTk::Resource m_rc_width_percent; FbTk::Resource m_rc_alpha; - FbTk::Resource m_rc_layernum; + FbTk::Resource m_rc_layernum; FbTk::Resource m_rc_on_head; FbTk::Resource m_rc_placement; FbTk::Resource m_rc_height; diff --git a/src/WorkspaceCmd.cc b/src/WorkspaceCmd.cc index 536019c..5498b38 100644 --- a/src/WorkspaceCmd.cc +++ b/src/WorkspaceCmd.cc @@ -33,6 +33,8 @@ #include "WindowCmd.hh" #include "FbTk/KeyUtil.hh" +#include "FbTk/CommandRegistry.hh" +#include "FbTk/stringstream.hh" #ifdef HAVE_CMATH #include @@ -42,6 +44,8 @@ #include #include +using std::string; + void WindowListCmd::execute() { if (m_pat.error()) { m_cmd->execute(); @@ -66,6 +70,20 @@ void WindowListCmd::execute() { } } +FbTk::BoolCommand *SomeCmd::parse(const string &command, const string &args, + bool trusted) { + BoolCommand *boolcmd = + FbTk::CommandRegistry::instance().parseBoolLine(args, trusted); + if (!boolcmd) + return 0; + if (command == "some") + return new SomeCmd(FbTk::RefCount(boolcmd)); + return new EveryCmd(FbTk::RefCount(boolcmd)); +} + +REGISTER_BOOLCOMMAND_PARSER(some, SomeCmd::parse); +REGISTER_BOOLCOMMAND_PARSER(every, SomeCmd::parse); + bool SomeCmd::bool_execute() { BScreen *screen = Fluxbox::instance()->keyScreen(); if (screen != 0) { @@ -108,6 +126,37 @@ bool EveryCmd::bool_execute() { return true; } +namespace { + +FbTk::Command *parseWindowList(const string &command, + const string &args, bool trusted) { + int opts; + string pat; + FocusableList::parseArgs(args, opts, pat); + if (command == "attach") + return new AttachCmd(pat); + else if (command == "nextwindow") + return new NextWindowCmd(opts, pat); + else if (command == "nextgroup") { + opts |= FocusableList::LIST_GROUPS; + return new NextWindowCmd(opts, pat); + } else if (command == "prevwindow") + return new PrevWindowCmd(opts, pat); + else if (command == "prevgroup") { + opts |= FocusableList::LIST_GROUPS; + return new PrevWindowCmd(opts, pat); + } + return 0; +} + +REGISTER_COMMAND_PARSER(attach, parseWindowList); +REGISTER_COMMAND_PARSER(nextwindow, parseWindowList); +REGISTER_COMMAND_PARSER(nextgroup, parseWindowList); +REGISTER_COMMAND_PARSER(prevwindow, parseWindowList); +REGISTER_COMMAND_PARSER(prevgroup, parseWindowList); + +}; // end anonymous namespace + void AttachCmd::execute() { BScreen *screen = Fluxbox::instance()->keyScreen(); if (screen != 0) { @@ -140,6 +189,21 @@ void PrevWindowCmd::execute() { screen->cycleFocus(m_option, &m_pat, true); } +FbTk::Command *GoToWindowCmd::parse(const string &command, + const string &arguments, bool trusted) { + int num, opts; + string args, pat; + FbTk_istringstream iss(arguments.c_str()); + iss >> num; + string::size_type pos = arguments.find_first_of("({"); + if (pos != string::npos && pos != arguments.size()) + args = arguments.c_str() + pos; + FocusableList::parseArgs(args, opts, pat); + return new GoToWindowCmd(num, opts, pat); +} + +REGISTER_COMMAND_PARSER(gotowindow, GoToWindowCmd::parse); + void GoToWindowCmd::execute() { BScreen *screen = Fluxbox::instance()->keyScreen(); if (screen != 0) { @@ -149,6 +213,24 @@ void GoToWindowCmd::execute() { } } +FbTk::Command *DirFocusCmd::parse(const string &command, + const string &args, bool trusted) { + if (command == "focusup") + return new DirFocusCmd(FocusControl::FOCUSUP); + else if (command == "focusdown") + return new DirFocusCmd(FocusControl::FOCUSDOWN); + else if (command == "focusleft") + return new DirFocusCmd(FocusControl::FOCUSLEFT); + else if (command == "focusright") + return new DirFocusCmd(FocusControl::FOCUSRIGHT); + return 0; +} + +REGISTER_COMMAND_PARSER(focusup, DirFocusCmd::parse); +REGISTER_COMMAND_PARSER(focusdown, DirFocusCmd::parse); +REGISTER_COMMAND_PARSER(focusleft, DirFocusCmd::parse); +REGISTER_COMMAND_PARSER(focusright, DirFocusCmd::parse); + void DirFocusCmd::execute() { BScreen *screen = Fluxbox::instance()->keyScreen(); if (screen == 0) @@ -159,18 +241,51 @@ void DirFocusCmd::execute() { screen->focusControl().dirFocus(*win, m_dir); } +REGISTER_COMMAND(addworkspace, AddWorkspaceCmd); + void AddWorkspaceCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen != 0) screen->addWorkspace(); } +REGISTER_COMMAND(removelastworkspace, RemoveLastWorkspaceCmd); + void RemoveLastWorkspaceCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen != 0) screen->removeLastWorkspace(); } +namespace { + +FbTk::Command *parseIntCmd(const string &command, const string &args, + bool trusted) { + int num = 1; + FbTk_istringstream iss(args.c_str()); + iss >> num; + if (command == "nextworkspace") + return new NextWorkspaceCmd(num); + else if (command == "prevworkspace") + return new PrevWorkspaceCmd(num); + else if (command == "rightworkspace") + return new RightWorkspaceCmd(num); + else if (command == "leftworkspace") + return new LeftWorkspaceCmd(num); + else if (command == "workspace") + // workspaces appear 1-indexed to the user, hence the minus 1 + return new JumpToWorkspaceCmd(num - 1); + return 0; +} + +REGISTER_COMMAND_PARSER(nextworkspace, parseIntCmd); +REGISTER_COMMAND_PARSER(prevworkspace, parseIntCmd); +REGISTER_COMMAND_PARSER(rightworkspace, parseIntCmd); +REGISTER_COMMAND_PARSER(leftworkspace, parseIntCmd); +REGISTER_COMMAND_PARSER(workspace, parseIntCmd); + +}; // end anonymous namespace + void NextWorkspaceCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen != 0) @@ -210,6 +325,7 @@ void JumpToWorkspaceCmd::execute() { } } +REGISTER_COMMAND(arrangewindows, ArrangeWindowsCmd); /** try to arrange the windows on the current workspace in a 'clever' way. @@ -335,6 +451,8 @@ void ArrangeWindowsCmd::execute() { } } +REGISTER_COMMAND(showdesktop, ShowDesktopCmd); + void ShowDesktopCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0) @@ -349,6 +467,8 @@ void ShowDesktopCmd::execute() { } } +REGISTER_COMMAND(closeallwindows, CloseAllWindowsCmd); + void CloseAllWindowsCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0) diff --git a/src/WorkspaceCmd.hh b/src/WorkspaceCmd.hh index eeacc16..fa8cb58 100644 --- a/src/WorkspaceCmd.hh +++ b/src/WorkspaceCmd.hh @@ -32,6 +32,8 @@ #include "FbTk/RefCount.hh" +#include + class WindowListCmd: public FbTk::Command { public: WindowListCmd(FbTk::RefCount cmd, const std::string &pat): @@ -49,6 +51,8 @@ public: SomeCmd(FbTk::RefCount cmd): m_cmd(cmd) { } bool bool_execute(); + static FbTk::BoolCommand *parse(const std::string &command, + const std::string &args, bool trusted); private: FbTk::RefCount m_cmd; @@ -97,6 +101,8 @@ public: GoToWindowCmd(int num, int option, std::string &pat): m_num(num), m_option(option), m_pat(pat.c_str()) { } void execute(); + static FbTk::Command *parse(const std::string &command, + const std::string &args, bool trusted); private: const int m_num; const int m_option; @@ -107,6 +113,8 @@ class DirFocusCmd: public FbTk::Command { public: explicit DirFocusCmd(const FocusControl::FocusDir dir): m_dir(dir) { } void execute(); + static FbTk::Command *parse(const std::string &command, + const std::string &args, bool trusted); private: const FocusControl::FocusDir m_dir; }; diff --git a/src/WorkspaceMenu.cc b/src/WorkspaceMenu.cc index 43cd3a3..23d4007 100644 --- a/src/WorkspaceMenu.cc +++ b/src/WorkspaceMenu.cc @@ -27,7 +27,7 @@ #include "Workspace.hh" #include "WorkspaceCmd.hh" #include "MenuCreator.hh" -#include "CommandParser.hh" +#include "FbTk/CommandRegistry.hh" #include "FbCommands.hh" #include "Layer.hh" @@ -147,7 +147,7 @@ void WorkspaceMenu::init(BScreen &screen) { remove_workspace_macro->add(saverc_cmd); RefCount remove_last_cmd(remove_workspace_macro); - RefCount start_edit(CommandParser::instance().parseLine("setworkspacenamedialog")); + RefCount start_edit(FbTk::CommandRegistry::instance().parseLine("setworkspacenamedialog")); insert(new FbTk::MenuSeparator()); insert(_FB_XTEXT(Workspace, NewWorkspace, "New Workspace", "Add a new workspace"), -- cgit v0.11.2