keyboard_indicators.c 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. /* See LICENSE file for copyright and license details. */
  2. #include <ctype.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <X11/Xlib.h>
  6. #include "../util.h"
  7. /*
  8. * fmt consists of uppercase or lowercase 'c' for caps lock and/or 'n' for num
  9. * lock, each optionally followed by '?', in the order of indicators desired.
  10. * If followed by '?', the letter with case preserved is included in the output
  11. * if the corresponding indicator is on. Otherwise, the letter is always
  12. * included, lowercase when off and uppercase when on.
  13. */
  14. const char *
  15. keyboard_indicators(const char *fmt)
  16. {
  17. Display *dpy;
  18. XKeyboardState state;
  19. size_t fmtlen, i, n;
  20. int togglecase, isset;
  21. char key;
  22. if (!(dpy = XOpenDisplay(NULL))) {
  23. warn("XOpenDisplay: Failed to open display");
  24. return NULL;
  25. }
  26. XGetKeyboardControl(dpy, &state);
  27. XCloseDisplay(dpy);
  28. fmtlen = strnlen(fmt, 4);
  29. for (i = n = 0; i < fmtlen; i++) {
  30. key = tolower(fmt[i]);
  31. if (key != 'c' && key != 'n') {
  32. continue;
  33. }
  34. togglecase = (i + 1 >= fmtlen || fmt[i + 1] != '?');
  35. isset = (state.led_mask & (1 << (key == 'n')));
  36. if (togglecase) {
  37. buf[n++] = isset ? toupper(key) : key;
  38. } else if (isset) {
  39. buf[n++] = fmt[i];
  40. }
  41. }
  42. buf[n] = 0;
  43. return buf;
  44. }