window.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /* window.c, Ait, Kevin Bloom, BSD 3-Clause, 2023 */
  2. #include "header.h"
  3. #include "termbox.h"
  4. int win_cnt = 0;
  5. window_t* new_window()
  6. {
  7. window_t *wp = (window_t *)malloc(sizeof(window_t));
  8. assert(wp != NULL); /* call fatal instead XXX */
  9. wp->w_next = NULL;
  10. wp->w_bufp = NULL;
  11. wp->w_point = 0;
  12. wp->w_mark = NOMARK;
  13. wp->w_top = 0;
  14. wp->w_left = 0;
  15. wp->w_rows = 0;
  16. wp->w_cols = 0;
  17. wp->w_update = FALSE;
  18. sprintf(wp->w_name, "W%d", ++win_cnt);
  19. windows[number_of_windows] = wp;
  20. number_of_windows++;
  21. return wp;
  22. }
  23. void one_window(window_t *wp)
  24. {
  25. wp->w_top = 0;
  26. wp->w_left = 0;
  27. wp->w_rows = LINES - 2;
  28. wp->w_cols = COLS;
  29. wp->w_next = NULL;
  30. for(int i = number_of_windows; i > -1; i--)
  31. windows[i] = NULL;
  32. number_of_windows = 1;
  33. windows[0] = wp;
  34. }
  35. void split_window()
  36. {
  37. window_t *wp, *wp2;
  38. int ntru, ntrl;
  39. if (curwp->w_rows < 3) {
  40. msg("Cannot split a %d line window", curwp->w_rows);
  41. return;
  42. }
  43. wp = new_window();
  44. associate_b2w(curwp->w_bufp,wp);
  45. b2w(wp); /* inherit buffer settings */
  46. ntru = (curwp->w_rows - 1) / 2; /* Upper size */
  47. ntrl = (curwp->w_rows - 1) - ntru; /* Lower size */
  48. /* Old is upper window */
  49. curwp->w_rows = ntru;
  50. wp->w_top = curwp->w_top + ntru + 1;
  51. wp->w_rows = ntrl;
  52. wp->w_cols = curwp->w_cols;
  53. wp->w_left = curwp->w_left;
  54. /* insert it in the list */
  55. wp2 = curwp->w_next;
  56. curwp->w_next = wp;
  57. wp->w_next = wp2;
  58. redraw(); /* mark the lot for update */
  59. }
  60. void chop_window()
  61. {
  62. window_t *wp, *wp2;
  63. int ntru, ntrl;
  64. if (curwp->w_cols < 3) {
  65. msg("Cannot split a %d columned window", curwp->w_cols);
  66. return;
  67. }
  68. wp = new_window();
  69. associate_b2w(curwp->w_bufp,wp);
  70. b2w(wp); /* inherit buffer settings */
  71. ntru = (curwp->w_cols - 1) / 2; /* Upper size */
  72. ntrl = (curwp->w_cols - 1) - ntru; /* Lower size */
  73. /* Old is upper window */
  74. curwp->w_cols = ntru - 1;
  75. wp->w_rows = curwp->w_rows;
  76. wp->w_top = curwp->w_top;
  77. wp->w_left = curwp->w_left + ntru + 1;
  78. wp->w_cols = ntrl;
  79. /* insert it in the list */
  80. wp2 = curwp->w_next;
  81. curwp->w_next = wp;
  82. wp->w_next = wp2;
  83. redraw(); /* mark the lot for update */
  84. }
  85. void next_window() {
  86. curwp->w_update = TRUE; /* make sure modeline gets updated */
  87. curwp = (curwp->w_next == NULL ? wheadp : curwp->w_next);
  88. curbp = curwp->w_bufp;
  89. if (curbp->b_cnt > 1)
  90. w2b(curwp); /* push win vars to buffer */
  91. }
  92. void delete_other_windows()
  93. {
  94. if (wheadp->w_next == NULL) {
  95. msg("Only 1 window");
  96. return;
  97. }
  98. free_other_windows(curwp);
  99. }
  100. void free_other_windows(window_t *winp)
  101. {
  102. window_t *wp, *next;
  103. for (wp = next = wheadp; next != NULL; wp = next) {
  104. next = wp->w_next; /* get next before a call to free() makes wp undefined */
  105. if (wp != winp) {
  106. disassociate_b(wp); /* this window no longer references its buffer */
  107. free(wp);
  108. }
  109. }
  110. wheadp = curwp = winp;
  111. one_window(winp);
  112. }
  113. void close_window()
  114. {
  115. window_t *wp, *next = NULL;
  116. int found = FALSE;
  117. if(number_of_windows == 1) {
  118. msg("Only 1 window.");
  119. return;
  120. }
  121. for(int i = 0 ; i < number_of_windows; i++) {
  122. if(windows[i] == curwp) {
  123. wp = curwp;
  124. found = TRUE;
  125. next = wp->w_next == NULL ? wheadp : wp->w_next;
  126. }
  127. if(i + 1 == number_of_windows)
  128. windows[i] = NULL;
  129. else if(found)
  130. windows[i] = windows[i+1];
  131. }
  132. number_of_windows--;
  133. if(number_of_windows == 1)
  134. one_window(next);
  135. else {
  136. if(curwp->w_left == next->w_left) { /* vertical */
  137. next->w_rows += curwp->w_rows + 1;
  138. next->w_top = curwp->w_top;
  139. }
  140. if(curwp->w_top == next->w_top) {
  141. next->w_cols += curwp->w_cols + 1;
  142. next->w_left = curwp->w_left;
  143. }
  144. }
  145. curwp = next;
  146. next_buffer();
  147. }
  148. void associate_b2w(buffer_t *bp, window_t *wp) {
  149. assert(bp != NULL);
  150. assert(wp != NULL);
  151. wp->w_bufp = bp;
  152. bp->b_cnt++;
  153. }
  154. void disassociate_b(window_t *wp) {
  155. assert(wp != NULL);
  156. assert(wp->w_bufp != NULL);
  157. wp->w_bufp->b_cnt--;
  158. }
  159. /* Recenters the screen whilst keeping the point.
  160. Will cycled from center, top, bottom.
  161. Because of odd number of rows, "middle" is considered anything that is in
  162. the range of [-1, 1].
  163. */
  164. void recenter()
  165. {
  166. int i = curwp->w_rows / 2;
  167. point_t new_page = curbp->b_page;
  168. int shift = curwp->w_row - i;
  169. int current, lastln;
  170. assert(curwp != NULL);
  171. assert(curbp != NULL);
  172. get_line_stats(&current, &lastln, curbp);
  173. if(current == 0) {
  174. msg("Beginning of buffer, can't recenter");
  175. return;
  176. }
  177. if(shift == 0 || shift == 1 || shift == -1) // middle of screen
  178. {
  179. shift = curwp->w_rows / 2;
  180. } else if(curbp->b_row == curwp->w_rows - 1) // end of screen
  181. {
  182. shift = curwp->w_rows / 2;
  183. } else if(curbp->b_row == 0) // start of screen
  184. {
  185. shift = -1 * (curwp->w_rows - 1);
  186. }
  187. if(shift < 0) {
  188. for(int k = shift; k < 0; k++) {
  189. new_page = lnstart(curbp,new_page - 1);
  190. }
  191. if(*ptr(curbp, new_page) == '\n')
  192. new_page++;
  193. } else {
  194. int found_end = FALSE;
  195. for(int k = shift; k > 0; k--) {
  196. found_end = FALSE;
  197. while(found_end == FALSE) {
  198. if(*ptr(curbp, new_page) == '\n')
  199. found_end = TRUE;
  200. new_page++;
  201. }
  202. }
  203. }
  204. curbp->b_page = new_page;
  205. }