IncSet.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. htop - IncSet.c
  3. (C) 2005-2012 Hisham H. Muhammad
  4. Released under the GNU GPLv2+, see the COPYING file
  5. in the source distribution for its full text.
  6. */
  7. #include "config.h" // IWYU pragma: keep
  8. #include "IncSet.h"
  9. #include <ctype.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include "CRT.h"
  13. #include "ListItem.h"
  14. #include "Object.h"
  15. #include "ProvideCurses.h"
  16. #include "XUtils.h"
  17. static void IncMode_reset(IncMode* mode) {
  18. mode->index = 0;
  19. mode->buffer[0] = 0;
  20. }
  21. void IncSet_reset(IncSet* this, IncType type) {
  22. IncMode_reset(&this->modes[type]);
  23. }
  24. void IncSet_setFilter(IncSet* this, const char* filter) {
  25. IncMode* mode = &this->modes[INC_FILTER];
  26. size_t len = String_safeStrncpy(mode->buffer, filter, sizeof(mode->buffer));
  27. mode->index = len;
  28. this->filtering = true;
  29. }
  30. static const char* const searchFunctions[] = {"Next ", "Prev ", "Cancel ", " Search: ", NULL};
  31. static const char* const searchKeys[] = {"F3", "S-F3", "Esc", " "};
  32. static const int searchEvents[] = {KEY_F(3), KEY_F(15), 27, ERR};
  33. static inline void IncMode_initSearch(IncMode* search) {
  34. memset(search, 0, sizeof(IncMode));
  35. search->bar = FunctionBar_new(searchFunctions, searchKeys, searchEvents);
  36. search->isFilter = false;
  37. }
  38. static const char* const filterFunctions[] = {"Done ", "Clear ", " Filter: ", NULL};
  39. static const char* const filterKeys[] = {"Enter", "Esc", " "};
  40. static const int filterEvents[] = {13, 27, ERR};
  41. static inline void IncMode_initFilter(IncMode* filter) {
  42. memset(filter, 0, sizeof(IncMode));
  43. filter->bar = FunctionBar_new(filterFunctions, filterKeys, filterEvents);
  44. filter->isFilter = true;
  45. }
  46. static inline void IncMode_done(IncMode* mode) {
  47. FunctionBar_delete(mode->bar);
  48. }
  49. IncSet* IncSet_new(FunctionBar* bar) {
  50. IncSet* this = xMalloc(sizeof(IncSet));
  51. IncMode_initSearch(&(this->modes[INC_SEARCH]));
  52. IncMode_initFilter(&(this->modes[INC_FILTER]));
  53. this->active = NULL;
  54. this->defaultBar = bar;
  55. this->filtering = false;
  56. this->found = false;
  57. return this;
  58. }
  59. void IncSet_delete(IncSet* this) {
  60. IncMode_done(&(this->modes[0]));
  61. IncMode_done(&(this->modes[1]));
  62. free(this);
  63. }
  64. static void updateWeakPanel(const IncSet* this, Panel* panel, Vector* lines) {
  65. const Object* selected = Panel_getSelected(panel);
  66. Panel_prune(panel);
  67. if (this->filtering) {
  68. int n = 0;
  69. const char* incFilter = this->modes[INC_FILTER].buffer;
  70. for (int i = 0; i < Vector_size(lines); i++) {
  71. ListItem* line = (ListItem*)Vector_get(lines, i);
  72. if (String_contains_i(line->value, incFilter, true)) {
  73. Panel_add(panel, (Object*)line);
  74. if (selected == (Object*)line) {
  75. Panel_setSelected(panel, n);
  76. }
  77. n++;
  78. }
  79. }
  80. } else {
  81. for (int i = 0; i < Vector_size(lines); i++) {
  82. Object* line = Vector_get(lines, i);
  83. Panel_add(panel, line);
  84. if (selected == line) {
  85. Panel_setSelected(panel, i);
  86. }
  87. }
  88. }
  89. }
  90. static bool search(const IncSet* this, Panel* panel, IncMode_GetPanelValue getPanelValue) {
  91. int size = Panel_size(panel);
  92. for (int i = 0; i < size; i++) {
  93. if (String_contains_i(getPanelValue(panel, i), this->active->buffer, true)) {
  94. Panel_setSelected(panel, i);
  95. return true;
  96. }
  97. }
  98. return false;
  99. }
  100. void IncSet_activate(IncSet* this, IncType type, Panel* panel) {
  101. this->active = &(this->modes[type]);
  102. panel->currentBar = this->active->bar;
  103. panel->cursorOn = true;
  104. this->panel = panel;
  105. IncSet_drawBar(this, CRT_colors[FUNCTION_BAR]);
  106. }
  107. static void IncSet_deactivate(IncSet* this, Panel* panel) {
  108. this->active = NULL;
  109. Panel_setDefaultBar(panel);
  110. panel->cursorOn = false;
  111. FunctionBar_draw(this->defaultBar);
  112. }
  113. static bool IncMode_find(const IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue, int step) {
  114. int size = Panel_size(panel);
  115. int here = Panel_getSelectedIndex(panel);
  116. int i = here;
  117. for (;;) {
  118. i += step;
  119. if (i == size) {
  120. i = 0;
  121. }
  122. if (i == -1) {
  123. i = size - 1;
  124. }
  125. if (i == here) {
  126. return false;
  127. }
  128. if (String_contains_i(getPanelValue(panel, i), mode->buffer, true)) {
  129. Panel_setSelected(panel, i);
  130. return true;
  131. }
  132. }
  133. }
  134. bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) {
  135. if (ch == ERR)
  136. return true;
  137. IncMode* mode = this->active;
  138. int size = Panel_size(panel);
  139. bool filterChanged = false;
  140. bool doSearch = true;
  141. if (ch == KEY_F(3) || ch == KEY_F(15)) {
  142. if (size == 0)
  143. return true;
  144. IncMode_find(mode, panel, getPanelValue, ch == KEY_F(3) ? 1 : -1);
  145. doSearch = false;
  146. } else if (0 < ch && ch < 255 && isprint((unsigned char)ch)) {
  147. if (mode->index < INCMODE_MAX) {
  148. mode->buffer[mode->index] = (char) ch;
  149. mode->index++;
  150. mode->buffer[mode->index] = 0;
  151. if (mode->isFilter) {
  152. filterChanged = true;
  153. if (mode->index == 1) {
  154. this->filtering = true;
  155. }
  156. }
  157. }
  158. } else if (ch == KEY_BACKSPACE || ch == 127) {
  159. if (mode->index > 0) {
  160. mode->index--;
  161. mode->buffer[mode->index] = 0;
  162. if (mode->isFilter) {
  163. filterChanged = true;
  164. if (mode->index == 0) {
  165. this->filtering = false;
  166. IncMode_reset(mode);
  167. }
  168. }
  169. } else {
  170. doSearch = false;
  171. }
  172. } else if (ch == KEY_RESIZE) {
  173. doSearch = (mode->index > 0);
  174. } else {
  175. if (mode->isFilter) {
  176. filterChanged = true;
  177. if (ch == 27) {
  178. this->filtering = false;
  179. IncMode_reset(mode);
  180. }
  181. } else {
  182. if (ch == 27) {
  183. IncMode_reset(mode);
  184. }
  185. }
  186. IncSet_deactivate(this, panel);
  187. doSearch = false;
  188. }
  189. if (doSearch) {
  190. this->found = search(this, panel, getPanelValue);
  191. }
  192. if (filterChanged && lines) {
  193. updateWeakPanel(this, panel, lines);
  194. }
  195. return filterChanged;
  196. }
  197. const char* IncSet_getListItemValue(Panel* panel, int i) {
  198. const ListItem* l = (const ListItem*) Panel_get(panel, i);
  199. return l ? l->value : "";
  200. }
  201. void IncSet_drawBar(const IncSet* this, int attr) {
  202. if (this->active) {
  203. if (!this->active->isFilter && !this->found)
  204. attr = CRT_colors[FAILED_SEARCH];
  205. int cursorX = FunctionBar_drawExtra(this->active->bar, this->active->buffer, attr, true);
  206. this->panel->cursorY = LINES - 1;
  207. this->panel->cursorX = cursorX;
  208. } else {
  209. FunctionBar_draw(this->defaultBar);
  210. }
  211. }
  212. int IncSet_synthesizeEvent(IncSet* this, int x) {
  213. if (this->active) {
  214. return FunctionBar_synthesizeEvent(this->active->bar, x);
  215. } else {
  216. return FunctionBar_synthesizeEvent(this->defaultBar, x);
  217. }
  218. }