選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

186 行
3.9KB

  1. #include <stdio.h>
  2. #include <readline/readline.h>
  3. #include <readline/history.h>
  4. #include "global.h"
  5. #include "build.h"
  6. #include <ncurses.h>
  7. static int input_available = 0;
  8. static int input_char;
  9. char input_line[PATLEN + 1];
  10. /* used for saving a line not [Enter]-ed yet,
  11. * so its not lost if the user scrolls the history
  12. */
  13. static struct PARTIAL_LINE {
  14. bool is_active;
  15. char* line;
  16. int pos;
  17. } partial_line = {
  18. .line = NULL,
  19. .is_active = true
  20. };
  21. static inline void previous_history_proxy(void);
  22. static inline void next_history_proxy(void);
  23. bool interpret(int c) {
  24. /* A switch is faster then binding Readline to a billion functions
  25. * and since KEY_* values can't be bound anyways (values too large
  26. * (because while the first argument of rl_bind_key() is an int,
  27. * only unsigned chars are valid)), handling everything here
  28. * creates consistency too.
  29. */
  30. switch(c){
  31. case KEY_BACKSPACE:
  32. rl_rubout(1, 0);
  33. break;
  34. case KEY_UP:
  35. previous_history_proxy();
  36. break;
  37. case KEY_DOWN:
  38. next_history_proxy();
  39. break;
  40. case ESC:
  41. case ctrl('X'):
  42. process_mouse();
  43. break;
  44. default:
  45. input_char = c;
  46. input_available = 1;
  47. rl_callback_read_char();
  48. return 0;
  49. }
  50. //XXX:
  51. // rl_bind_key(ctrl('\\'), /**/); /* bypass bindings */
  52. window_change |= CH_INPUT;
  53. return 0;
  54. }
  55. static int getc_function(FILE *ignore) {
  56. UNUSED(ignore);
  57. input_available = 0;
  58. return input_char;
  59. }
  60. static int input_available_hook() {
  61. return input_available;
  62. }
  63. static void redisplay_function() {
  64. window_change |= CH_INPUT;
  65. }
  66. static void callback_handler(char *line) {
  67. if(!line) {
  68. input_mode = INPUT_NORMAL;
  69. return;
  70. }
  71. add_history(line);
  72. switch(input_mode) {
  73. case INPUT_NORMAL: {
  74. strncpy(input_line, line, PATLEN);
  75. search(input_line);
  76. horswp_window();
  77. curdispline = 0;
  78. current_page = 0;
  79. PCS_reset();
  80. } break;
  81. case INPUT_CHANGE_TO: {
  82. strncpy(newpat, line, PATLEN);
  83. change = (bool *)calloc(totallines, sizeof(*change));
  84. input_mode = INPUT_CHANGE;
  85. force_window();
  86. } return;
  87. case INPUT_APPEND: {
  88. char filename[PATHLEN + 1];
  89. FILE* file;
  90. char ch;
  91. shellpath(filename, sizeof(filename), line);
  92. file = fopen(filename, "a+");
  93. seekpage(0);
  94. while ((ch = getc(refsfound)) != EOF) {
  95. putc(ch, file);
  96. }
  97. fclose(file);
  98. input_mode = INPUT_NORMAL;
  99. } return;
  100. case INPUT_READ: {
  101. char filename[PATHLEN + 1];
  102. shellpath(filename, sizeof(filename), line);
  103. if (!readrefs(filename)) {
  104. postmsg("Ignoring an empty file");
  105. }
  106. window_change |= CH_INPUT | CH_RESULT;
  107. input_mode = INPUT_NORMAL;
  108. } return;
  109. }
  110. switch(field) {
  111. case CHANGE:
  112. if(totallines == 0){ return; }
  113. input_mode = INPUT_CHANGE_TO;
  114. force_window();
  115. break;
  116. case DEFINITION:
  117. case FILENAME:
  118. if(totallines == 1) { editref(0); }
  119. break;
  120. }
  121. }
  122. static inline void previous_history_proxy(){
  123. HIST_ENTRY* i = previous_history();
  124. if(i){
  125. if(partial_line.is_active){
  126. free(partial_line.line);
  127. partial_line = (struct PARTIAL_LINE){
  128. .line = rl_line_buffer,
  129. .pos = rl_point,
  130. .is_active = false
  131. };
  132. }else{
  133. free(rl_line_buffer);
  134. }
  135. //
  136. rl_line_buffer = strdup(i->line);
  137. rl_point = strlen(rl_line_buffer);
  138. }
  139. }
  140. static inline void next_history_proxy(){
  141. HIST_ENTRY* i = next_history();
  142. if(i){
  143. free(rl_line_buffer);
  144. rl_line_buffer = strdup(i->line);
  145. rl_point = strlen(rl_line_buffer);
  146. }else if(!partial_line.is_active){
  147. rl_line_buffer = strdup(partial_line.line);
  148. rl_point = partial_line.pos;
  149. partial_line.is_active = true;
  150. }
  151. }
  152. void rlinit() {
  153. rl_readline_name = PROGRAM_NAME;
  154. using_history();
  155. rl_catch_signals = 0;
  156. rl_catch_sigwinch = 0;
  157. rl_prep_term_function = NULL;
  158. rl_deprep_term_function = NULL;
  159. rl_change_environment = 0;
  160. rl_getc_function = getc_function;
  161. rl_input_available_hook = input_available_hook;
  162. rl_redisplay_function = redisplay_function;
  163. rl_callback_handler_install("", callback_handler);
  164. }