You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

162 lines
4.7 KiB

  1. #include "commands.h"
  2. #define LOG_MODULE "commands"
  3. #define LOG_ENABLE_DBG 0
  4. #include "log.h"
  5. #include "grid.h"
  6. #include "render.h"
  7. #include "selection.h"
  8. #include "terminal.h"
  9. #include "util.h"
  10. void
  11. cmd_scrollback_up(struct terminal *term, int rows)
  12. {
  13. if (term->grid == &term->alt)
  14. return;
  15. if (term->mouse_tracking != MOUSE_NONE)
  16. return;
  17. rows = min(rows, term->rows);
  18. assert(term->grid->offset >= 0);
  19. int new_view = term->grid->view - rows;
  20. while (new_view < 0)
  21. new_view += term->grid->num_rows;
  22. new_view %= term->grid->num_rows;
  23. assert(new_view >= 0);
  24. assert(new_view < term->grid->num_rows);
  25. /* Avoid scrolling in uninitialized rows */
  26. while (term->grid->rows[new_view] == NULL)
  27. new_view = (new_view + 1) % term->grid->num_rows;
  28. if (new_view == term->grid->view) {
  29. /*
  30. * This happens when scrolling up in a newly opened terminal;
  31. * every single line (except those already visible) are
  32. * uninitialized, and the loop above will bring us back to
  33. * where we started.
  34. */
  35. return;
  36. }
  37. /* Don't scroll past scrollback history */
  38. int end = (term->grid->offset + term->rows - 1) % term->grid->num_rows;
  39. if (end >= term->grid->offset) {
  40. /* Not wrapped */
  41. if (new_view >= term->grid->offset && new_view <= end)
  42. new_view = (end + 1) % term->grid->num_rows;
  43. } else {
  44. if (new_view >= term->grid->offset || new_view <= end)
  45. new_view = (end + 1) % term->grid->num_rows;
  46. }
  47. while (term->grid->rows[new_view] == NULL)
  48. new_view = (new_view + 1) % term->grid->num_rows;
  49. #if defined(_DEBUG)
  50. for (int r = 0; r < term->rows; r++)
  51. assert(term->grid->rows[(new_view + r) % term->grid->num_rows] != NULL);
  52. #endif
  53. LOG_DBG("scrollback UP: %d -> %d (offset = %d, end = %d, rows = %d)",
  54. term->grid->view, new_view, term->grid->offset, end, term->grid->num_rows);
  55. if (new_view == term->grid->view)
  56. return;
  57. int diff = -1;
  58. if (new_view < term->grid->view)
  59. diff = term->grid->view - new_view;
  60. else
  61. diff = (term->grid->num_rows - new_view) + term->grid->view;
  62. selection_view_up(term, new_view);
  63. term->grid->view = new_view;
  64. if (diff >= 0 && diff < term->rows) {
  65. term_damage_scroll(term, DAMAGE_SCROLL_REVERSE_IN_VIEW, (struct scroll_region){0, term->rows}, diff);
  66. term_damage_rows_in_view(term, 0, diff - 1);
  67. } else
  68. term_damage_view(term);
  69. render_refresh(term);
  70. }
  71. void
  72. cmd_scrollback_down(struct terminal *term, int rows)
  73. {
  74. if (term->grid == &term->alt)
  75. return;
  76. if (term->mouse_tracking != MOUSE_NONE)
  77. return;
  78. if (term->grid->view == term->grid->offset)
  79. return;
  80. rows = min(rows, term->rows);
  81. assert(term->grid->offset >= 0);
  82. int new_view = (term->grid->view + rows) % term->grid->num_rows;
  83. assert(new_view >= 0);
  84. assert(new_view < term->grid->num_rows);
  85. /* Prevent scrolling in uninitialized rows */
  86. bool all_initialized = false;
  87. do {
  88. all_initialized = true;
  89. for (int i = 0; i < term->rows; i++) {
  90. int row_no = (new_view + i) % term->grid->num_rows;
  91. if (term->grid->rows[row_no] == NULL) {
  92. all_initialized = false;
  93. new_view--;
  94. break;
  95. }
  96. }
  97. } while (!all_initialized);
  98. /* Don't scroll past scrollback history */
  99. int end = (term->grid->offset + term->rows - 1) % term->grid->num_rows;
  100. if (end >= term->grid->offset) {
  101. /* Not wrapped */
  102. if (new_view >= term->grid->offset && new_view <= end)
  103. new_view = term->grid->offset;
  104. } else {
  105. if (new_view >= term->grid->offset || new_view <= end)
  106. new_view = term->grid->offset;
  107. }
  108. #if defined(_DEBUG)
  109. for (int r = 0; r < term->rows; r++)
  110. assert(term->grid->rows[(new_view + r) % term->grid->num_rows] != NULL);
  111. #endif
  112. LOG_DBG("scrollback DOWN: %d -> %d (offset = %d, end = %d, rows = %d)",
  113. term->grid->view, new_view, term->grid->offset, end, term->grid->num_rows);
  114. if (new_view == term->grid->view)
  115. return;
  116. int diff = -1;
  117. if (new_view > term->grid->view)
  118. diff = new_view - term->grid->view;
  119. else
  120. diff = (term->grid->num_rows - term->grid->view) + new_view;
  121. selection_view_down(term, new_view);
  122. term->grid->view = new_view;
  123. if (diff >= 0 && diff < term->rows) {
  124. term_damage_scroll(term, DAMAGE_SCROLL_IN_VIEW, (struct scroll_region){0, term->rows}, diff);
  125. term_damage_rows_in_view(term, term->rows - diff, term->rows - 1);
  126. } else
  127. term_damage_view(term);
  128. render_refresh(term);
  129. }