MainPanel.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. htop - ColumnsPanel.c
  3. (C) 2004-2015 Hisham H. Muhammad
  4. (C) 2020 Red Hat, Inc. All Rights Reserved.
  5. Released under the GNU GPLv2+, see the COPYING file
  6. in the source distribution for its full text.
  7. */
  8. #include "config.h" // IWYU pragma: keep
  9. #include "MainPanel.h"
  10. #include <ctype.h>
  11. #include <stdlib.h>
  12. #include <sys/types.h>
  13. #include "CRT.h"
  14. #include "FunctionBar.h"
  15. #include "Machine.h"
  16. #include "Platform.h"
  17. #include "ProvideCurses.h"
  18. #include "Row.h"
  19. #include "RowField.h"
  20. #include "Settings.h"
  21. #include "Table.h"
  22. #include "XUtils.h"
  23. static const char* const MainFunctions[] = {"Help ", "Setup ", "Search", "Filter", "Tree ", "SortBy", "Nice -", "Nice +", "Kill ", "Quit ", NULL};
  24. static const char* const MainFunctions_ro[] = {"Help ", "Setup ", "Search", "Filter", "Tree ", "SortBy", " ", " ", " ", "Quit ", NULL};
  25. void MainPanel_updateLabels(MainPanel* this, bool list, bool filter) {
  26. FunctionBar* bar = MainPanel_getFunctionBar(this);
  27. FunctionBar_setLabel(bar, KEY_F(5), list ? "List " : "Tree ");
  28. FunctionBar_setLabel(bar, KEY_F(4), filter ? "FILTER" : "Filter");
  29. }
  30. static void MainPanel_idSearch(MainPanel* this, int ch) {
  31. Panel* super = (Panel*) this;
  32. pid_t id = ch - 48 + this->idSearch;
  33. for (int i = 0; i < Panel_size(super); i++) {
  34. const Row* row = (const Row*) Panel_get(super, i);
  35. if (row && row->id == id) {
  36. Panel_setSelected(super, i);
  37. break;
  38. }
  39. }
  40. this->idSearch = id * 10;
  41. if (this->idSearch > 10000000) {
  42. this->idSearch = 0;
  43. }
  44. }
  45. static const char* MainPanel_getValue(Panel* this, int i) {
  46. Row* row = (Row*) Panel_get(this, i);
  47. return Row_sortKeyString(row);
  48. }
  49. static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
  50. MainPanel* this = (MainPanel*) super;
  51. Machine* host = this->state->host;
  52. Htop_Reaction reaction = HTOP_OK;
  53. HandlerResult result = IGNORED;
  54. /* Let supervising ScreenManager handle resize */
  55. if (ch == KEY_RESIZE)
  56. return IGNORED;
  57. /* reset on every normal key */
  58. bool needReset = ch != ERR;
  59. #ifdef HAVE_GETMOUSE
  60. /* except mouse events while mouse support is disabled */
  61. if (!(ch != KEY_MOUSE || host->settings->enableMouse))
  62. needReset = false;
  63. #endif
  64. if (needReset)
  65. this->state->hideSelection = false;
  66. Settings* settings = host->settings;
  67. ScreenSettings* ss = settings->ss;
  68. if (EVENT_IS_HEADER_CLICK(ch)) {
  69. int x = EVENT_HEADER_CLICK_GET_X(ch);
  70. int hx = super->scrollH + x + 1;
  71. RowField field = RowField_keyAt(settings, hx);
  72. if (ss->treeView && ss->treeViewAlwaysByPID) {
  73. ss->treeView = false;
  74. ss->direction = 1;
  75. reaction |= Action_setSortKey(settings, field);
  76. } else if (field == ScreenSettings_getActiveSortKey(ss)) {
  77. ScreenSettings_invertSortOrder(ss);
  78. } else {
  79. reaction |= Action_setSortKey(settings, field);
  80. }
  81. reaction |= HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR | HTOP_SAVE_SETTINGS;
  82. result = HANDLED;
  83. } else if (EVENT_IS_SCREEN_TAB_CLICK(ch)) {
  84. int x = EVENT_SCREEN_TAB_GET_X(ch);
  85. reaction |= Action_setScreenTab(this->state, x);
  86. result = HANDLED;
  87. } else if (ch != ERR && this->inc->active) {
  88. bool filterChanged = IncSet_handleKey(this->inc, ch, super, MainPanel_getValue, NULL);
  89. if (filterChanged) {
  90. host->activeTable->incFilter = IncSet_filter(this->inc);
  91. reaction = HTOP_REFRESH | HTOP_REDRAW_BAR;
  92. }
  93. if (this->inc->found) {
  94. reaction |= Action_follow(this->state);
  95. reaction |= HTOP_KEEP_FOLLOWING;
  96. }
  97. result = HANDLED;
  98. } else if (ch == 27) {
  99. this->state->hideSelection = true;
  100. return HANDLED;
  101. } else if (ch != ERR && ch > 0 && ch < KEY_MAX && this->keys[ch]) {
  102. reaction |= (this->keys[ch])(this->state);
  103. result = HANDLED;
  104. } else if (0 < ch && ch < 255 && isdigit((unsigned char)ch)) {
  105. MainPanel_idSearch(this, ch);
  106. } else {
  107. if (ch != ERR) {
  108. this->idSearch = 0;
  109. } else {
  110. reaction |= HTOP_KEEP_FOLLOWING;
  111. }
  112. }
  113. if ((reaction & HTOP_REDRAW_BAR) == HTOP_REDRAW_BAR) {
  114. MainPanel_updateLabels(this, settings->ss->treeView, host->activeTable->incFilter);
  115. }
  116. if ((reaction & HTOP_RESIZE) == HTOP_RESIZE) {
  117. result |= RESIZE;
  118. }
  119. if ((reaction & HTOP_UPDATE_PANELHDR) == HTOP_UPDATE_PANELHDR) {
  120. result |= REDRAW;
  121. }
  122. if ((reaction & HTOP_REFRESH) == HTOP_REFRESH) {
  123. result |= REFRESH;
  124. }
  125. if ((reaction & HTOP_RECALCULATE) == HTOP_RECALCULATE) {
  126. result |= RESCAN;
  127. }
  128. if ((reaction & HTOP_SAVE_SETTINGS) == HTOP_SAVE_SETTINGS) {
  129. host->settings->changed = true;
  130. }
  131. if ((reaction & HTOP_QUIT) == HTOP_QUIT) {
  132. return BREAK_LOOP;
  133. }
  134. if ((reaction & HTOP_KEEP_FOLLOWING) != HTOP_KEEP_FOLLOWING) {
  135. host->activeTable->following = -1;
  136. Panel_setSelectionColor(super, PANEL_SELECTION_FOCUS);
  137. }
  138. return result;
  139. }
  140. int MainPanel_selectedRow(MainPanel* this) {
  141. const Row* row = (const Row*) Panel_getSelected((Panel*)this);
  142. return row ? row->id : -1;
  143. }
  144. bool MainPanel_foreachRow(MainPanel* this, MainPanel_foreachRowFn fn, Arg arg, bool* wasAnyTagged) {
  145. Panel* super = (Panel*) this;
  146. bool ok = true;
  147. bool anyTagged = false;
  148. for (int i = 0; i < Panel_size(super); i++) {
  149. Row* row = (Row*) Panel_get(super, i);
  150. if (row->tag) {
  151. ok &= fn(row, arg);
  152. anyTagged = true;
  153. }
  154. }
  155. if (!anyTagged) {
  156. Row* row = (Row*) Panel_getSelected(super);
  157. if (row) {
  158. ok &= fn(row, arg);
  159. }
  160. }
  161. if (wasAnyTagged)
  162. *wasAnyTagged = anyTagged;
  163. return ok;
  164. }
  165. static void MainPanel_drawFunctionBar(Panel* super, bool hideFunctionBar) {
  166. MainPanel* this = (MainPanel*) super;
  167. // Do not hide active search and filter bar.
  168. if (hideFunctionBar && !this->inc->active)
  169. return;
  170. IncSet_drawBar(this->inc, CRT_colors[FUNCTION_BAR]);
  171. if (this->state->pauseUpdate) {
  172. FunctionBar_append("PAUSED", CRT_colors[PAUSED]);
  173. }
  174. }
  175. static void MainPanel_printHeader(Panel* super) {
  176. MainPanel* this = (MainPanel*) super;
  177. Machine* host = this->state->host;
  178. Table_printHeader(host->settings, &super->header);
  179. }
  180. const PanelClass MainPanel_class = {
  181. .super = {
  182. .extends = Class(Panel),
  183. .delete = MainPanel_delete
  184. },
  185. .eventHandler = MainPanel_eventHandler,
  186. .drawFunctionBar = MainPanel_drawFunctionBar,
  187. .printHeader = MainPanel_printHeader
  188. };
  189. MainPanel* MainPanel_new(void) {
  190. MainPanel* this = AllocThis(MainPanel);
  191. this->processBar = FunctionBar_new(MainFunctions, NULL, NULL);
  192. this->readonlyBar = FunctionBar_new(MainFunctions_ro, NULL, NULL);
  193. FunctionBar* activeBar = Settings_isReadonly() ? this->readonlyBar : this->processBar;
  194. Panel_init((Panel*) this, 1, 1, 1, 1, Class(Row), false, activeBar);
  195. this->keys = xCalloc(KEY_MAX, sizeof(Htop_Action));
  196. this->inc = IncSet_new(activeBar);
  197. Action_setBindings(this->keys);
  198. Platform_setBindings(this->keys);
  199. return this;
  200. }
  201. void MainPanel_setState(MainPanel* this, State* state) {
  202. this->state = state;
  203. }
  204. void MainPanel_setFunctionBar(MainPanel* this, bool readonly) {
  205. this->super.defaultBar = readonly ? this->readonlyBar : this->processBar;
  206. this->inc->defaultBar = this->super.defaultBar;
  207. }
  208. void MainPanel_delete(Object* object) {
  209. Panel* super = (Panel*) object;
  210. MainPanel* this = (MainPanel*) object;
  211. MainPanel_setFunctionBar(this, false);
  212. FunctionBar_delete(this->readonlyBar);
  213. Panel_done(super);
  214. IncSet_delete(this->inc);
  215. free(this->keys);
  216. free(this);
  217. }