123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- /*
- layoutswitch - a simple utility that shells out to `setxkbmap` to quickly
- alternate between two or more predefined keyboard layouts.
- USAGE: layoutswitch
- Switches to your next X11 layout, or back to your previous one.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- // number of layouts to be used:
- #define NUM_LAYOUTS 2
- // This array holds all our "desired" keyboard layouts to be cycled.
- // You need, however, to initiate it with a #define directive because C
- // will not accept a const statement (C++ apparently does)
- char* layoutholder[NUM_LAYOUTS];
- // this function queries `setxkbmap` and parses the value in there.
- char *
- getlayout()
- {
- char* layout = malloc(3); // hard assumption that layouts are always two letters (reasonable *most* of the times)
- FILE *p;
- p = popen("setxkbmap -query | grep layout | cut -d ' ' -f 6", "r");
- if (p == NULL) {
- printf("Error: setxkbmap not found. Please install it in this system.\n");
- return "er";
- }
- else {
- int ch; // counter for chars being read...
- int i = 0; // counter for new chars!
- while ((ch = fgetc(p)) != EOF) {
- layout[i] = ch;
- i++;
- }
- pclose(p);
- // patch up the string with NULL before you leave:
- layout[2] = '\0';
- return layout;
- }
- }
- void
- switchlayout(char* curlayout)
- {
- FILE* p;
- char stmt[15] = "setxkbmap "; // "prepared statement" a-la SQl
- for (int i = 0; i < NUM_LAYOUTS; i++) {
- // if there's a match go to the next layout in the array
- if (strncmp(curlayout, layoutholder[i], 2) == 0) {
- // however, if it's the last element, switch to #1:
- if ((i + 1) == NUM_LAYOUTS) {
- printf("Switching to %s layout.\n", layoutholder[0]);
- strcat(stmt, layoutholder[0]);
- p = popen(stmt, "r");
- break;
- }
- else {
- printf("Switching to %s layout.\n", layoutholder[i+1]);
- strcat(stmt, layoutholder[i+1]);
- p = popen(stmt, "r");
- break;
- }
- }
- }
- pclose(p);
- }
- int
- main(int argc, char* argv[])
- {
- layoutholder[0] = "us";
- layoutholder[1] = "br";
- // add as many layoutN as you wish to cycle through. i.e.:
- // layoutholder[2] = "be";
- // However, if you do, make sure you change the NUM_LAYOUTS constant!
- char* layout = getlayout();
- if (strncmp(layout, "er", 2) == 0) {
- // not able to query value. Clean up and quit.
- printf("Unable to query keyboard value.\n");
- free(layout);
- return 1;
- }
- switchlayout(layout);
- free(layout); // NECESSARY. Avoid the leak!
- return 0;
- }
|