foldkeys.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /****************************************************************************
  2. * Copyright (c) 2006 Free Software Foundation, Inc. *
  3. * *
  4. * Permission is hereby granted, free of charge, to any person obtaining a *
  5. * copy of this software and associated documentation files (the *
  6. * "Software"), to deal in the Software without restriction, including *
  7. * without limitation the rights to use, copy, modify, merge, publish, *
  8. * distribute, distribute with modifications, sublicense, and/or sell *
  9. * copies of the Software, and to permit persons to whom the Software is *
  10. * furnished to do so, subject to the following conditions: *
  11. * *
  12. * The above copyright notice and this permission notice shall be included *
  13. * in all copies or substantial portions of the Software. *
  14. * *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
  16. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
  18. * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
  19. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
  20. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
  21. * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
  22. * *
  23. * Except as contained in this notice, the name(s) of the above copyright *
  24. * holders shall not be used in advertising or otherwise to promote the *
  25. * sale, use or other dealings in this Software without prior written *
  26. * authorization. *
  27. ****************************************************************************/
  28. /*
  29. * Author: Thomas E. Dickey, 2006
  30. *
  31. * $Id: foldkeys.c,v 1.3 2006/12/09 16:54:07 tom Exp $
  32. *
  33. * Demonstrate a method for altering key definitions at runtime.
  34. *
  35. * This program reads the key definitions, merging those which have xterm-style
  36. * modifiers into their equivalents which have no modifiers. It does this
  37. * merging only for the keys which are defined in the terminal description.
  38. */
  39. #include <test.priv.h>
  40. #if defined(NCURSES_VERSION) && NCURSES_EXT_FUNCS
  41. #if TIME_WITH_SYS_TIME
  42. # include <sys/time.h>
  43. # include <time.h>
  44. #else
  45. # if HAVE_SYS_TIME_H
  46. # include <sys/time.h>
  47. # else
  48. # include <time.h>
  49. # endif
  50. #endif
  51. #define MY_LOGFILE "demo_foldkeys.log"
  52. #define MY_KEYS (KEY_MAX + 1)
  53. /*
  54. * Log the most recently-written line to our logfile
  55. */
  56. static void
  57. log_last_line(WINDOW *win)
  58. {
  59. FILE *fp;
  60. int y, x, n;
  61. char temp[256];
  62. if ((fp = fopen(MY_LOGFILE, "a")) != 0) {
  63. int need = sizeof(temp) - 1;
  64. if (need > COLS)
  65. need = COLS;
  66. getyx(win, y, x);
  67. wmove(win, y - 1, 0);
  68. n = winnstr(win, temp, need);
  69. while (n-- > 0) {
  70. if (isspace(UChar(temp[n])))
  71. temp[n] = '\0';
  72. else
  73. break;
  74. }
  75. wmove(win, y, x);
  76. fprintf(fp, "%s\n", temp);
  77. fclose(fp);
  78. }
  79. }
  80. /*
  81. * ncurses has no API for telling what the actual last key-code is. That is
  82. * a secret because the codes past KEY_MAX are computed at run-time and may
  83. * differ depending on the previous calls to newterm(), etc. It is unlikely
  84. * that one could have more than a thousand key definitions...
  85. */
  86. #define MAX_KEYS 2000
  87. typedef struct {
  88. const char *name;
  89. const char *value;
  90. int code;
  91. int state;
  92. } KeyInfo;
  93. static void
  94. demo_foldkeys(void)
  95. {
  96. KeyInfo info[MAX_KEYS];
  97. int info_len = 0;
  98. int merged = 0;
  99. int code;
  100. int j, k;
  101. /*
  102. * Tell ncurses that we want to use function keys. That will make it add
  103. * any user-defined keys that appear in the terminfo.
  104. */
  105. keypad(stdscr, TRUE);
  106. /*
  107. * List the predefined keys using the strnames[] array.
  108. */
  109. for (code = 0; code < STRCOUNT; ++code) {
  110. NCURSES_CONST char *name = strnames[code];
  111. NCURSES_CONST char *value = tigetstr(name);
  112. if (value != 0 && value != (NCURSES_CONST char *) -1) {
  113. info[info_len].name = strnames[code];
  114. info[info_len].code = key_defined(value);
  115. info[info_len].value = value;
  116. info[info_len].state = 0;
  117. if (info[info_len].code > 0)
  118. ++info_len;
  119. }
  120. }
  121. /*
  122. * We can get the names for user-defined keys from keyname(). It returns
  123. * a name like KEY_foo for the predefined keys, which tigetstr() does not
  124. * understand.
  125. */
  126. for (code = KEY_MAX; code < MAX_KEYS; ++code) {
  127. NCURSES_CONST char *name = keyname(code);
  128. if (name != 0) {
  129. info[info_len].name = name;
  130. info[info_len].code = code;
  131. info[info_len].value = tigetstr(name);
  132. info[info_len].state = 0;
  133. ++info_len;
  134. }
  135. }
  136. printw("Initially %d key definitions\n", info_len);
  137. /*
  138. * Look for keys that have xterm-style modifiers.
  139. */
  140. for (j = 0; j < info_len; ++j) {
  141. int first, second;
  142. char final[2];
  143. char *value;
  144. if (info[j].state == 0
  145. && sscanf(info[j].value,
  146. "\033[%d;%d%c",
  147. &first,
  148. &second,
  149. final) == 3
  150. && *final != ';'
  151. && (value = strdup(info[j].value)) != 0) {
  152. sprintf(value, "\033[%d%c", first, *final);
  153. for (k = 0; k < info_len; ++k) {
  154. if (info[k].state == 0
  155. && !strcmp(info[k].value, value)) {
  156. info[j].state = 1;
  157. break;
  158. }
  159. }
  160. if (info[j].state == 0) {
  161. sprintf(value, "\033O%c", *final);
  162. for (k = 0; k < info_len; ++k) {
  163. if (info[k].state == 0
  164. && !strcmp(info[k].value, value)) {
  165. info[j].state = 1;
  166. break;
  167. }
  168. }
  169. }
  170. if (info[j].state == 1) {
  171. if ((define_key(info[j].value, info[k].code)) != ERR) {
  172. printw("map %s to %s\n", info[j].value, info[k].value);
  173. keyok(info[j].code, FALSE);
  174. ++merged;
  175. } else {
  176. printw("? cannot define_key %d:%s\n", j, info[j].value);
  177. }
  178. } else {
  179. printw("? cannot merge %d:%s\n", j, info[j].value);
  180. }
  181. free(value);
  182. }
  183. }
  184. printw("Merged to %d key definitions\n", info_len - merged);
  185. }
  186. int
  187. main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
  188. {
  189. int ch;
  190. #if HAVE_GETTIMEOFDAY
  191. int secs, msecs;
  192. struct timeval current, previous;
  193. #endif
  194. unlink(MY_LOGFILE);
  195. newterm(0, stdout, stdin);
  196. (void) cbreak(); /* take input chars one at a time, no wait for \n */
  197. (void) noecho(); /* don't echo input */
  198. scrollok(stdscr, TRUE);
  199. keypad(stdscr, TRUE);
  200. move(0, 0);
  201. demo_foldkeys();
  202. #if HAVE_GETTIMEOFDAY
  203. gettimeofday(&previous, 0);
  204. #endif
  205. while ((ch = getch()) != ERR) {
  206. bool escaped = (ch >= MY_KEYS);
  207. const char *name = keyname(escaped ? (ch - MY_KEYS) : ch);
  208. #if HAVE_GETTIMEOFDAY
  209. gettimeofday(&current, 0);
  210. secs = current.tv_sec - previous.tv_sec;
  211. msecs = (current.tv_usec - previous.tv_usec) / 1000;
  212. if (msecs < 0) {
  213. msecs += 1000;
  214. --secs;
  215. }
  216. if (msecs >= 1000) {
  217. secs += msecs / 1000;
  218. msecs %= 1000;
  219. }
  220. printw("%6d.%03d ", secs, msecs);
  221. previous = current;
  222. #endif
  223. printw("Keycode %d, name %s%s\n",
  224. ch,
  225. escaped ? "ESC-" : "",
  226. name != 0 ? name : "<null>");
  227. log_last_line(stdscr);
  228. clrtoeol();
  229. if (ch == 'q')
  230. break;
  231. }
  232. endwin();
  233. ExitProgram(EXIT_SUCCESS);
  234. }
  235. #else
  236. int
  237. main(void)
  238. {
  239. printf("This program requires the ncurses library\n");
  240. ExitProgram(EXIT_FAILURE);
  241. }
  242. #endif