diff --git a/wrapper.cpp b/wrapper.cpp new file mode 100644 index 0000000..ec83642 --- /dev/null +++ b/wrapper.cpp @@ -0,0 +1,153 @@ +// wrapper.cpp +// A small wrapper program around Jay Bromley's keyboard layout information class. +// +// Compilation: +// g++ -o xkblayout-state XKeyboard.cpp wrapper.cpp -lX11 +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. + +#include +#include +#include +#include "XKeyboard.h" + +using namespace std; + +void print_usage(string progname) +{ + cerr << endl + << "xkblayout-state v1" << endl + << endl + << "Usage: " << endl + << endl + << "To get the current layout(s):" << endl + << " " << progname << " -p format" << endl + << endl + << "This causes the 'format' string to be printed on stdout with the following substitutions:" << endl + << " %c -> current layout number" << endl + << " %n -> current layout name" << endl + << " %s -> current layout symbol" << endl + << " %v -> current layout variant" << endl + << " %e -> current layout variant (equals to %s if %v is empty)" << endl + << " %C -> layout count" << endl + << " %N -> layout names (one per line)" << endl + << " %S -> layout symbols (one per line)" << endl + << " %V -> layout variants (one per line)" << endl + << " %E -> layout variants (one per line; layout symbol is used if variant is empty)" << endl + << " %% -> A literal '%'" << endl + << endl + << "For example:" << endl + << " " << progname << " -p \"Current layout: %s(%e)\"" << endl + << endl + << "To set the current layout:" << endl + << " " << progname << " -s layout_number" << endl + << endl + << "Here 'layout_number' is the number of the layout to be set (starting from 0)" << endl + << "and can be either absolute (default) or relative (if preceded with a plus or minus sign)." << endl + << endl + << "For example:" << endl + << " " << progname << " -s 1" << endl + << " " << progname << " -s +1" << endl + << endl; +} + +void print_status(XKeyboard& xkb, string format) { + for (size_t i = 0; i < format.length(); ++i) { + if (format[i] == '%' && i < format.length()-1) { + switch (format[i+1]) { + case 'c': + cout << xkb.currentGroupNum(); + break; + case 'n': + cout << xkb.currentGroupName(); + break; + case 's': + cout << xkb.currentGroupSymbol(); + break; + case 'v': + cout << xkb.currentGroupVariant(); + break; + case 'e': + if (xkb.currentGroupVariant().empty()) + cout << xkb.currentGroupSymbol(); + else + cout << xkb.currentGroupVariant(); + break; + + case 'C': + cout << xkb.groupCount(); + break; + case 'N': + for (size_t j = 0; j < xkb.groupNames().size(); ++j) + cout << xkb.groupNames()[j] << endl; + break; + case 'S': + for (size_t j = 0; j < xkb.groupSymbols().size(); ++j) + cout << xkb.groupSymbols()[j] << endl; + break; + case 'V': + for (size_t j = 0; j < xkb.groupVariants().size(); ++j) + cout << xkb.groupVariants()[j] << endl; + break; + case 'E': + for (size_t j = 0; j < xkb.groupVariants().size(); ++j) + if (xkb.groupVariants()[j].empty()) + cout << xkb.groupSymbols()[j] << endl; + else + cout << xkb.groupVariants()[j] << endl; + break; + + default: + cout << format[i+1]; + break; + } + ++i; + } else { // not '%' + cout << format[i]; + } + } +} + +bool set_group(XKeyboard& xkb, string group) { + bool relative = (group[0] == '+' || group[0] == '-'); + int group_int = atoi(group.c_str()); + if (relative) + return xkb.changeGroup(group_int); + else + return xkb.setGroupByNum(group_int); +} + + +int main(int argc, char* argv[]) +{ + try { + XKeyboard xkb; + + if (argc != 3) { + print_usage(string(argv[0])); + return EXIT_FAILURE; + } else { + string command(argv[1]); + if (command == "-p") { + print_status(xkb, string(argv[2])); + return EXIT_SUCCESS; + } else if (command == "-s") { + if (!set_group(xkb, string(argv[2]))) { + cerr << "Failed to set layout" << endl; + return EXIT_FAILURE; + } + } else { + print_usage(string(argv[0])); + return EXIT_FAILURE; + } + } + } + catch (exception e) { + cerr << e.what() << endl; + return EXIT_FAILURE; + } +} +