keyboard_indicators.c 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  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 "../slstatus.h"
  7. #include "../util.h"
  8. /*
  9. * fmt consists of uppercase or lowercase 'c' for caps lock and/or 'n' for num
  10. * lock, each optionally followed by '?', in the order of indicators desired.
  11. * If followed by '?', the letter with case preserved is included in the output
  12. * if the corresponding indicator is on. Otherwise, the letter is always
  13. * included, lowercase when off and uppercase when on.
  14. */
  15. const char *
  16. keyboard_indicators(const char *fmt)
  17. {
  18. Display *dpy;
  19. XKeyboardState state;
  20. size_t fmtlen, i, n;
  21. int togglecase, isset;
  22. char key;
  23. if (!(dpy = XOpenDisplay(NULL))) {
  24. warn("XOpenDisplay: Failed to open display");
  25. return NULL;
  26. }
  27. XGetKeyboardControl(dpy, &state);
  28. XCloseDisplay(dpy);
  29. fmtlen = strnlen(fmt, 4);
  30. for (i = n = 0; i < fmtlen; i++) {
  31. key = tolower(fmt[i]);
  32. if (key != 'c' && key != 'n')
  33. continue;
  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. buf[n] = 0;
  42. return buf;
  43. }