all repos — fluxbox @ 8b7464046cea5e521ac46811591b0fce0c45aca1

custom fork of the fluxbox windowmanager

added FbTk::CommandRegistry, decentralized command parsing, and made them auto-register
markt markt
commit

8b7464046cea5e521ac46811591b0fce0c45aca1

parent

daca07edafc2e75eb9ee04d35fe80759308a8583

M ChangeLogChangeLog

@@ -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)
M src/ClockTool.ccsrc/ClockTool.cc

@@ -26,7 +26,7 @@ #include "ClockTool.hh"

#include "ToolTheme.hh" #include "Screen.hh" -#include "CommandParser.hh" +#include "FbTk/CommandRegistry.hh" #include "CommandDialog.hh" #include "fluxbox.hh"

@@ -128,7 +128,7 @@ std::string resourcename = screen->name() + ".strftimeFormat";

CommandDialog *dialog = new CommandDialog(*screen, "Edit Clock Format", "SetResourceValue " + resourcename + " "); - FbTk::RefCount<FbTk::Command> cmd(CommandParser::instance().parseLine("reconfigure")); + FbTk::RefCount<FbTk::Command> cmd(FbTk::CommandRegistry::instance().parseLine("reconfigure")); dialog->setPostCommand(cmd); dialog->setText(screen->resourceManager().resourceValue(resourcename)); dialog->show();

@@ -169,7 +169,7 @@

m_button.setGC(m_theme.textGC()); // setup menu - FbTk::RefCount<FbTk::Command> saverc(CommandParser::instance().parseLine("saverc")); + FbTk::RefCount<FbTk::Command> saverc(FbTk::CommandRegistry::instance().parseLine("saverc")); FbTk::MenuItem *item = new ClockMenuItem(*this); item->setCommand(saverc); menu.insert(item);
M src/CommandDialog.ccsrc/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 @@

if (ks == XK_Return) { hide(); // hide and return focus to a FluxboxWindow // create command from line - auto_ptr<FbTk::Command> cmd(CommandParser::instance(). + auto_ptr<FbTk::Command> cmd(FbTk::CommandRegistry::instance(). parseLine(m_precommand + m_textbox.text())); if (cmd.get()) cmd->execute();

@@ -170,8 +170,8 @@ XBell(FbTk::App::instance()->display(), 0);

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<string> matches; for (; it != it_end; ++it) { if ((*it).first.find(prefix) == 0) {
D src/CommandParser.cc

@@ -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 <vector> - -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<string> 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; -}
D src/CommandParser.hh

@@ -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 <string> -#include <map> - -#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<std::string, CommandFactory *> 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
M src/CurrentWindowCmd.ccsrc/CurrentWindowCmd.cc

@@ -31,6 +31,95 @@ #include "Screen.hh"

#include "WinClient.hh" #include "FocusControl.hh" +#include "FbTk/CommandRegistry.hh" +#include "FbTk/stringstream.hh" +#include "FbTk/StringUtil.hh" + +#include <string> +#include <vector> + +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<void>::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 @@

(*it)->focus(); } +REGISTER_COMMAND(startmoving, StartMovingCmd); + void StartMovingCmd::real_execute() { const XEvent &last = Fluxbox::instance()->lastEvent(); if (last.type == ButtonPress) {

@@ -135,6 +264,41 @@ fbwindow().startMoving(be.x_root, be.y_root);

} } +FbTk::Command *StartResizingCmd::parse(const string &cmd, const string &args, + bool trusted) { + FluxboxWindow::ResizeModel mode = FluxboxWindow::DEFAULTRESIZE; + std::vector<string> tokens; + FbTk::StringUtil::stringtok<std::vector<string> >(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 @@ fbwindow().startResizing(x, y, fbwindow().getResizeDirection(x, y, m_mode));

} } +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 @@ fbwindow().x() + m_step_size_x,

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 @@ fbwindow().frame().titlebarHeight() + 10);

fbwindow().resize(w, h); } +FbTk::Command *MoveToCmd::parse(const string &cmd, const string &args, + bool trusted) { + typedef std::vector<string> StringTokens; + StringTokens tokens; + FbTk::StringUtil::stringtok<StringTokens>(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 @@ if (m_step_size_x > 0 && m_step_size_y > 0)

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<string> StringTokens; + StringTokens tokens; + FbTk::StringUtil::stringtok<StringTokens>(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),

@@ -239,6 +528,8 @@ fbwindow().setUnfocusedAlpha(new_alpha);

} else fbwindow().setUnfocusedAlpha(m_unfocus); } + +REGISTER_BOOLCOMMAND_WITH_ARGS(matches, MatchCmd); bool MatchCmd::real_execute() { return m_pat.match(winclient());
M src/CurrentWindowCmd.hhsrc/CurrentWindowCmd.hh

@@ -151,6 +151,8 @@ // begin resizing with mouse

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 @@ // move cmd, relative position

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 @@ // resize cmd, relative size

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 @@ IGNORE_X = 1 << 8,

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 @@

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:
D src/FbCommandFactory.cc

@@ -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 <string> - -#ifdef HAVE_CSTDIO - #include <cstdio> -#else - #include <stdio.h> -#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<BoolCommand>(boolcmd)); - } else if (command == "every") { - BoolCommand *boolcmd = parseBoolCommand(arguments, trusted); - if (!boolcmd) - return 0; - return new EveryCmd(RefCount<BoolCommand>(boolcmd)); - } else if (command == "not") { - BoolCommand *boolcmd = parseBoolCommand(arguments, trusted); - if (!boolcmd) - return 0; - RefCount<BoolCommand> ref(boolcmd); - return new NotCommand(ref); - } else if (command == "and") { - int pos = 0, err = 0; - AndCommand *andcmd = new AndCommand(); - string cmd; - - while (true) { - RefCount<BoolCommand> 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<BoolCommand> 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<BoolCommand> 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: - // <remove whitespace here><resname><one whitespace><value> - 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<FbTk::Command>(new FullscreenCmd()), arguments); - else if (command == "minimizewindow" || command == "minimize" || command == "iconify") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::iconify)), arguments); - else if (command == "maximizewindow" || command == "maximize") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::maximizeFull)), arguments); - else if (command == "maximizevertical") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::maximizeVertical)), arguments); - else if (command == "maximizehorizontal") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::maximizeHorizontal)), arguments); - else if (command == "setalpha") { - typedef vector<string> StringTokens; - StringTokens tokens; - FbTk::StringUtil::stringtok<StringTokens>(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<FbTk::Command>(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<string> tokens; - FbTk::StringUtil::stringtok<vector<string> >(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<FbTk::Command> 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<string> StringTokens; - StringTokens tokens; - FbTk::StringUtil::stringtok<StringTokens>(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<FbTk::Command>(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<FbTk::Command>(new MoveCmd(dx, dy)), pat); - } else if (command == "raise") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::raise)), arguments); - else if (command == "raiselayer") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::raiseLayer)), arguments); - else if (command == "lower") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::lower)), arguments); - else if (command == "lowerlayer") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::lowerLayer)), arguments); - else if (command == "activate" || command == "focus") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd((void (FluxboxWindow::*)())&FluxboxWindow::focus)), arguments); - else if (command == "close") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::close)), arguments); - else if (command == "closeallwindows") - return new CloseAllWindowsCmd(); - else if (command == "killwindow" || command == "kill") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::kill)), arguments); - else if (command == "shade" || command == "shadewindow") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::shade)), arguments); - else if (command == "shadeon" ) - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::shadeOn)), arguments); - else if (command == "shadeoff" ) - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::shadeOff)), arguments); - else if (command == "stick" || command == "stickwindow") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::stick)), arguments); - else if (command == "toggledecor") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(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<FbTk::Command>(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<FbTk::Command> 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<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::nextClient)), arguments); - else if (command == "prevtab") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::prevClient)), arguments); - else if (command == "movetableft") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::moveClientLeft)), arguments); - else if (command == "movetabright") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::moveClientRight)), arguments); - else if (command == "detachclient") - return new WindowListCmd(FbTk::RefCount<FbTk::Command>(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<n>' actions are deprecated! Use 'Workspace <n>' instead"<<endl; - return new JumpToWorkspaceCmd(getint(command.substr(9).c_str(), 1) - 1); - - } else if (command == "attach") { - int opts; // not used - string pat; - FocusableList::parseArgs(arguments, opts, pat); - return new AttachCmd(pat); - } else if (command == "nextwindow") { - int opts; - string pat; - FocusableList::parseArgs(arguments, opts, pat); - return new NextWindowCmd(opts, pat); - } else if (command == "nextgroup") { - int opts; - string pat; - FocusableList::parseArgs(arguments, opts, pat); - opts |= FocusableList::LIST_GROUPS; - return new NextWindowCmd(opts, pat); - } else if (command == "prevwindow") { - int opts; - string pat; - FocusableList::parseArgs(arguments, opts, pat); - return new PrevWindowCmd(opts, pat); - } else if (command == "prevgroup") { - int opts; - string pat; - FocusableList::parseArgs(arguments, opts, pat); - opts |= FocusableList::LIST_GROUPS; - return new PrevWindowCmd(opts, pat); - } else if (command == "gotowindow") { - 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); - } 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<FbTk::Command> 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<FbTk::Command> 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<BoolCommand> cond(0); - RefCount<Command> 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; -}
D src/FbCommandFactory.hh

@@ -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 -};
M src/FbCommands.ccsrc/FbCommands.cc

@@ -33,6 +33,9 @@ #include "MenuCreator.hh"

#include "FbTk/Theme.hh" #include "FbTk/Menu.hh" +#include "FbTk/CommandRegistry.hh" +#include "FbTk/StringUtil.hh" +#include "FbTk/stringstream.hh" #include <sys/types.h> #include <unistd.h>

@@ -120,6 +123,10 @@ }

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) { }

@@ -168,6 +175,27 @@ exit(0);

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 @@ }

} } +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 @@ else

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) { }

@@ -244,6 +284,8 @@ Fluxbox::instance()->save_rc();

FbTk::ThemeManager::instance().load(m_filename, 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);

@@ -260,9 +302,21 @@ 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();

@@ -285,6 +339,8 @@ m_menu = new ClientMenu(*screen, m_list, 0);

::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 @@ return;

::showMenu(*screen, **m_menu); } +REGISTER_COMMAND(rootmenu, FbCommands::ShowRootMenuCmd); + void ShowRootMenuCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0)

@@ -306,6 +364,8 @@

::showMenu(*screen, screen->rootMenu()); } +REGISTER_COMMAND(workspacemenu, FbCommands::ShowWorkspaceMenuCmd); + void ShowWorkspaceMenuCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0)

@@ -314,10 +374,13 @@

::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();

@@ -339,6 +402,8 @@

screen->updateWorkspaceNamesAtom(); Fluxbox::instance()->save_rc(); } + +REGISTER_COMMAND(setworkspacenamedialog, FbCommands::WorkspaceNameDialogCmd); void WorkspaceNameDialogCmd::execute() {

@@ -351,6 +416,8 @@ win->setText(screen->currentWorkspace()->name());

win->show(); } +REGISTER_COMMAND(commanddialog, FbCommands::CommandDialogCmd); + void CommandDialogCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0)

@@ -375,6 +442,8 @@ return;

screen->resourceManager().setResourceValue(m_resname, m_value); Fluxbox::instance()->save_rc(); } + +REGISTER_COMMAND(setresourcevaluedialog, FbCommands::SetResourceValueDialogCmd); void SetResourceValueDialogCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen();

@@ -385,6 +454,8 @@ FbTk::FbWindow *win = new CommandDialog(*screen, "Type resource name and the value", "SetResourceValue ");

win->show(); }; +REGISTER_UNTRUSTED_COMMAND_WITH_ARGS(bindkey, FbCommands::BindKeyCmd); + BindKeyCmd::BindKeyCmd(const string &keybind):m_keybind(keybind) { } void BindKeyCmd::execute() {

@@ -397,6 +468,41 @@ ofile<<m_keybind<<endl;

} } } + +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) { }
M src/FbCommands.hhsrc/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 @@

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;
A 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 <iostream> + +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
A 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 <string> +#include <map> + +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 <typename Cmd, typename Ret> +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<classname, FbTk::Command>); \ + } + +template <typename Cmd, typename Ret> +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<classname, FbTk::Command>); \ + } + +#define REGISTER_BOOLCOMMAND_WITH_ARGS(name, classname) \ + namespace { \ + static const bool p_register_##name = FbTk::CommandRegistry::instance().registerBoolCommand(#name, FbTk::CommandCreatorWithArgs<classname, FbTk::BoolCommand>); \ + } + +template <typename Cmd, typename Ret> +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<classname, FbTk::Command>); \ + } + +template <typename Cmd, typename Ret> +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<classname, FbTk::Command>); \ + } + +/* 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<string, CreateFunction *> CreatorMap; + typedef std::map<string, BoolCreateFunction *> 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
M src/FbTk/LogicCommands.ccsrc/FbTk/LogicCommands.cc

@@ -23,7 +23,100 @@ // $Id: $

#include "LogicCommands.hh" +#include "CommandRegistry.hh" +#include "StringUtil.hh" + +using FbTk::StringUtil::removeFirstWhitespace; +using FbTk::StringUtil::toLower; +using std::string; + namespace FbTk { + +namespace { + +template <typename M> +M *addCommands(M *macro, const string &args, bool trusted) { + int pos = 0, err = 0; + string cmd; + + while (true) { + RefCount<BoolCommand> 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<BoolCommand> ref(boolcmd); + return new NotCommand(ref); + } else if (command == "and") + return addCommands<AndCommand>(new AndCommand(), args, trusted); + else if (command == "or") + return addCommands<OrCommand>(new OrCommand(), args, trusted); + else if (command == "xor") + return addCommands<XorCommand>(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<BoolCommand> cond(0); + RefCount<Command> 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<BoolCommand> &com) { m_commandlist.push_back(com);
M src/FbTk/LogicCommands.hhsrc/FbTk/LogicCommands.hh

@@ -27,6 +27,7 @@

#include "Command.hh" #include "RefCount.hh" +#include <string> #include <vector> namespace FbTk {

@@ -43,7 +44,8 @@ if (*m_t) m_t->execute();

} else if (*m_f) m_f->execute(); } - + static Command *parse(const std::string &cmd, const std::string &args, + bool trusted); private: RefCount<BoolCommand> m_cond; RefCount<Command> m_t, m_f;
M src/FbTk/MacroCommand.ccsrc/FbTk/MacroCommand.cc

@@ -23,7 +23,55 @@ // $Id$

#include "MacroCommand.hh" +#include "CommandRegistry.hh" +#include "StringUtil.hh" + +#include <string> + namespace FbTk { + +namespace { + +template <typename M> +M *addCommands(M *macro, const std::string &args, bool trusted) { + + std::string cmd; + int err = 0; + int pos = 0; + + while (true) { + RefCount<Command> 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<MacroCommand>(new MacroCommand, args, trusted); + else if (command == "togglecmd") + return addCommands<ToggleCommand>(new ToggleCommand, args, trusted); + return 0; +} + +REGISTER_COMMAND_PARSER(macrocmd, parseMacroCmd); +REGISTER_COMMAND_PARSER(togglecmd, parseMacroCmd); + +}; // end anonymous namespace void MacroCommand::add(RefCount<Command> &com) { m_commandlist.push_back(com);
M src/FbTk/Makefile.amsrc/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 \
M src/FbTk/StringUtil.ccsrc/FbTk/StringUtil.cc

@@ -233,6 +233,18 @@ }

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
M src/FbTk/StringUtil.hhsrc/FbTk/StringUtil.hh

@@ -64,6 +64,9 @@ /// removes the first whitespace characters of the string

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 <typename Container> static void
M src/IconbarTool.ccsrc/IconbarTool.cc

@@ -33,7 +33,7 @@ #include "IconButton.hh"

#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 @@ using namespace FbTk;

// setup use pixmap item to reconfig iconbar and save resource on click MacroCommand *save_and_reconfig = new MacroCommand(); RefCount<Command> reconfig(new SimpleCommand<IconbarTool>(*this, &IconbarTool::renderTheme)); - RefCount<Command> save(CommandParser::instance().parseLine("saverc")); + RefCount<Command> save(FbTk::CommandRegistry::instance().parseLine("saverc")); save_and_reconfig->add(reconfig); save_and_reconfig->add(save); RefCount<Command> s_and_reconfig(save_and_reconfig);
M src/Keys.ccsrc/Keys.cc

@@ -32,7 +32,7 @@ #include "FbTk/StringUtil.hh"

#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 @@

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;
M src/LayerMenu.hhsrc/LayerMenu.hh

@@ -64,7 +64,7 @@

/// 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(); };
M src/Makefile.amsrc/Makefile.am

@@ -118,8 +118,6 @@ Xinerama.hh \

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 @@ ${newwmspec_SOURCE} ${gnome_SOURCE} \

${REMEMBER_SOURCE} ${TOOLBAR_SOURCE} -LDADD=FbTk/libFbTk.a defaults.$(OBJEXT) +LDADD=FbTk/libFbTk.a FbTk/LogicCommands.o defaults.$(OBJEXT)
M src/MenuCreator.ccsrc/MenuCreator.cc

@@ -26,7 +26,7 @@ #include "MenuCreator.hh"

#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 @@ menu.insert(_FB_XTEXT(Menu, Icons, "Icons", "Iconic windows menu title"));

else menu.insert(str_label, submenu); } else if (str_key == "exit") { // exit - FbTk::RefCount<FbTk::Command> exit_cmd(CommandParser::instance().parseLine("exit")); + FbTk::RefCount<FbTk::Command> 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 @@ menu.insert(str_label, exit_cmd);

} else if (str_key == "exec") { // execute and hide menu using namespace FbTk; - RefCount<Command> exec_cmd(CommandParser::instance().parseLine("exec " + str_cmd)); - RefCount<Command> hide_menu(CommandParser::instance().parseLine("hidemenus")); + RefCount<Command> exec_cmd(FbTk::CommandRegistry::instance().parseLine("exec " + str_cmd)); + RefCount<Command> 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 @@ RefCount<Command> exec_and_hide_cmd(exec_and_hide);

menu.insert(str_label, exec_and_hide_cmd); } else if (str_key == "macrocmd") { using namespace FbTk; - RefCount<Command> macro_cmd(CommandParser::instance().parseLine("macrocmd " + str_cmd)); - RefCount<Command> hide_menu(CommandParser::instance().parseLine("hidemenus")); + RefCount<Command> macro_cmd(FbTk::CommandRegistry::instance().parseLine("macrocmd " + str_cmd)); + RefCount<Command> 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 @@ }

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<FbTk::Command> command(CommandParser::instance().parseLine(line)); + FbTk::RefCount<FbTk::Command> command(FbTk::CommandRegistry::instance().parseLine(line)); if (*command != 0) { // special NLS default labels if (str_label.empty()) {
M src/Screen.ccsrc/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 @@ True, XA_STRING, &xa_ret_type, &ret_format, &ret_nitems,

&ret_bytes_after, (unsigned char **)&str); } - FbTk::RefCount<FbTk::Command> cmd(CommandParser::instance().parseLine(str, false)); + FbTk::RefCount<FbTk::Command> cmd(FbTk::CommandRegistry::instance().parseLine(str, false)); if (cmd.get()) cmd->execute(); XFree(str);

@@ -1531,9 +1531,9 @@

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<FbTk::Command> restart_fb(CommandParser::instance().parseLine("restart")); - FbTk::RefCount<FbTk::Command> exit_fb(CommandParser::instance().parseLine("exit")); - FbTk::RefCount<FbTk::Command> execute_xterm(CommandParser::instance().parseLine("exec xterm")); + FbTk::RefCount<FbTk::Command> restart_fb(FbTk::CommandRegistry::instance().parseLine("restart")); + FbTk::RefCount<FbTk::Command> exit_fb(FbTk::CommandRegistry::instance().parseLine("exit")); + FbTk::RefCount<FbTk::Command> 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 @@ FbTk::MacroCommand *s_a_reconftabs_macro = new FbTk::MacroCommand();

FbTk::RefCount<FbTk::Command> saverc_cmd(new FbTk::SimpleCommand<Fluxbox>( *Fluxbox::instance(), &Fluxbox::save_rc)); - FbTk::RefCount<FbTk::Command> reconf_cmd(CommandParser::instance().parseLine("reconfigure")); + FbTk::RefCount<FbTk::Command> reconf_cmd(FbTk::CommandRegistry::instance().parseLine("reconfigure")); FbTk::RefCount<FbTk::Command> reconftabs_cmd(new FbTk::SimpleCommand<BScreen>( *this,
M src/Slit.hhsrc/Slit.hh

@@ -177,7 +177,7 @@ FbTk::Resource<bool> m_rc_auto_hide, m_rc_maximize_over;

FbTk::Resource<Slit::Placement> m_rc_placement; FbTk::Resource<Slit::Direction> m_rc_direction; FbTk::Resource<int> m_rc_alpha, m_rc_on_head; - FbTk::Resource<Layer> m_rc_layernum; + FbTk::Resource<class Layer> m_rc_layernum; };
M src/ToggleMenu.hhsrc/ToggleMenu.hh

@@ -32,7 +32,7 @@ * so that each toggle item gets updated

*/ 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() {}
M src/ToolFactory.ccsrc/ToolFactory.cc

@@ -36,7 +36,7 @@ #include "IconbarTheme.hh"

#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 @@ item = new ClockTool(parent, m_clock_theme, screen(), tbar.menu());

} else if (name == "nextworkspace" || name == "prevworkspace") { - FbTk::RefCount<FbTk::Command> cmd(CommandParser::instance().parseLine(name)); + FbTk::RefCount<FbTk::Command> cmd(FbTk::CommandRegistry::instance().parseLine(name)); if (*cmd == 0) // we need a command return 0;

@@ -127,7 +127,7 @@

} else if (name == "nextwindow" || name == "prevwindow") { - FbTk::RefCount<FbTk::Command> cmd(CommandParser::instance().parseLine(name)); + FbTk::RefCount<FbTk::Command> cmd(FbTk::CommandRegistry::instance().parseLine(name)); if (*cmd == 0) // we need a command return 0;
M src/Toolbar.ccsrc/Toolbar.cc

@@ -44,7 +44,7 @@ #include "Xinerama.hh"

#endif // XINERAMA #include "Strut.hh" -#include "CommandParser.hh" +#include "FbTk/CommandRegistry.hh" #include "Layer.hh" #include "FbTk/I18n.hh"

@@ -823,7 +823,7 @@ menu().setLabel(_FB_XTEXT(Toolbar, Toolbar,

"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);
M src/Toolbar.hhsrc/Toolbar.hh

@@ -178,7 +178,7 @@ // resources

FbTk::Resource<bool> m_rc_auto_hide, m_rc_maximize_over, m_rc_visible; FbTk::Resource<int> m_rc_width_percent; FbTk::Resource<int> m_rc_alpha; - FbTk::Resource<Layer> m_rc_layernum; + FbTk::Resource<class Layer> m_rc_layernum; FbTk::Resource<int> m_rc_on_head; FbTk::Resource<Placement> m_rc_placement; FbTk::Resource<int> m_rc_height;
M src/WorkspaceCmd.ccsrc/WorkspaceCmd.cc

@@ -33,6 +33,8 @@ #include "FocusControl.hh"

#include "WindowCmd.hh" #include "FbTk/KeyUtil.hh" +#include "FbTk/CommandRegistry.hh" +#include "FbTk/stringstream.hh" #ifdef HAVE_CMATH #include <cmath>

@@ -41,6 +43,8 @@ #include <math.h>

#endif #include <algorithm> #include <functional> + +using std::string; void WindowListCmd::execute() { if (m_pat.error()) {

@@ -66,6 +70,20 @@ WindowCmd<void>::setClient(old);

} } +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<FbTk::BoolCommand>(boolcmd)); + return new EveryCmd(FbTk::RefCount<FbTk::BoolCommand>(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 @@ }

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 @@ if (screen != 0)

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 @@ screen->focusControl().goToWindowNumber(*win_list, m_num, &m_pat);

} } +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 @@ if (win)

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 @@ screen->changeWorkspaceID(actual);

} } +REGISTER_COMMAND(arrangewindows, ArrangeWindowsCmd); /** try to arrange the windows on the current workspace in a 'clever' way.

@@ -335,6 +451,8 @@ y_offs += cal_height;

} } +REGISTER_COMMAND(showdesktop, ShowDesktopCmd); + void ShowDesktopCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen(); if (screen == 0)

@@ -348,6 +466,8 @@ if ((*it)->getWindowType() != Focusable::TYPE_DESKTOP)

(*it)->iconify(); } } + +REGISTER_COMMAND(closeallwindows, CloseAllWindowsCmd); void CloseAllWindowsCmd::execute() { BScreen *screen = Fluxbox::instance()->mouseScreen();
M src/WorkspaceCmd.hhsrc/WorkspaceCmd.hh

@@ -32,6 +32,8 @@ #include "FocusControl.hh"

#include "FbTk/RefCount.hh" +#include <string> + class WindowListCmd: public FbTk::Command { public: WindowListCmd(FbTk::RefCount<FbTk::Command> cmd, const std::string &pat):

@@ -49,6 +51,8 @@ public:

SomeCmd(FbTk::RefCount<FbTk::BoolCommand> cmd): m_cmd(cmd) { } bool bool_execute(); + static FbTk::BoolCommand *parse(const std::string &command, + const std::string &args, bool trusted); private: FbTk::RefCount<FbTk::BoolCommand> 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; };
M src/WorkspaceMenu.ccsrc/WorkspaceMenu.cc

@@ -27,7 +27,7 @@ #include "Screen.hh"

#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 @@ remove_workspace_macro->add(rmworkspace);

remove_workspace_macro->add(saverc_cmd); RefCount<Command> remove_last_cmd(remove_workspace_macro); - RefCount<Command> start_edit(CommandParser::instance().parseLine("setworkspacenamedialog")); + RefCount<Command> start_edit(FbTk::CommandRegistry::instance().parseLine("setworkspacenamedialog")); insert(new FbTk::MenuSeparator()); insert(_FB_XTEXT(Workspace, NewWorkspace, "New Workspace", "Add a new workspace"),