window.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  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. return wp;
  20. }
  21. void one_window(window_t *wp)
  22. {
  23. window_mode = WINDOW_DEFAULT;
  24. wp->w_top = 0;
  25. wp->w_left = 0;
  26. wp->w_rows = LINES - 2;
  27. wp->w_cols = COLS;
  28. wp->w_next = NULL;
  29. wp->w_update = TRUE;
  30. }
  31. void delete_other_windows_local(int showmsg)
  32. {
  33. if (wheadp->w_next == NULL) {
  34. if(showmsg)
  35. msg("Only 1 window");
  36. return;
  37. }
  38. free_other_windows(curwp);
  39. }
  40. void split_window_local(int internal)
  41. {
  42. window_t *wp, *wp2;
  43. int ntru, ntrl;
  44. if(!internal && window_mode == WINDOW_HORIZ) {
  45. msg("Already in horizontal mode!");
  46. return;
  47. }
  48. if(!internal) {
  49. window_mode = WINDOW_HORIZ;
  50. delete_other_windows_local(FALSE);
  51. }
  52. if (curwp->w_rows < 3) {
  53. msg("Cannot split a %d line window", curwp->w_rows);
  54. return;
  55. }
  56. wp = new_window();
  57. if(curwp->w_bufp->b_next != NULL)
  58. associate_b2w(curwp->w_bufp->b_next,wp);
  59. else
  60. associate_b2w(curwp->w_bufp,wp);
  61. b2w(wp); /* inherit buffer settings */
  62. ntru = (curwp->w_rows - 1) / 2; /* Upper size */
  63. ntrl = (curwp->w_rows - 1) - ntru; /* Lower size */
  64. /* Old is upper window */
  65. curwp->w_rows = ntru;
  66. wp->w_top = curwp->w_top + ntru + 1;
  67. wp->w_rows = ntrl;
  68. wp->w_cols = curwp->w_cols;
  69. wp->w_left = curwp->w_left;
  70. /* insert it in the list */
  71. wp2 = curwp->w_next;
  72. curwp->w_next = wp;
  73. wp->w_next = wp2;
  74. redraw(); /* mark the lot for update */
  75. }
  76. void split_window()
  77. {
  78. split_window_local(FALSE);
  79. }
  80. void tri_split_window()
  81. {
  82. window_t *wp, *wp2, *wp3;
  83. int ntru;
  84. if(window_mode == WINDOW_TRIHORIZ) {
  85. msg("Already in triple horizontal mode!");
  86. return;
  87. }
  88. window_mode = WINDOW_TRIHORIZ;
  89. delete_other_windows_local(FALSE);
  90. if (curwp->w_rows < 3) {
  91. msg("Cannot split a %d line window", curwp->w_rows);
  92. return;
  93. }
  94. wp = new_window();
  95. if(curwp->w_bufp->b_next != NULL)
  96. associate_b2w(curwp->w_bufp->b_next,wp);
  97. else
  98. associate_b2w(curwp->w_bufp,wp);
  99. b2w(wp); /* inherit buffer settings */
  100. wp2 = new_window();
  101. if(wp->w_bufp->b_next != NULL)
  102. associate_b2w(wp->w_bufp->b_next,wp2);
  103. else
  104. associate_b2w(curwp->w_bufp,wp2);
  105. b2w(wp2); /* inherit buffer settings */
  106. ntru = (curwp->w_rows - 1) / 3; /* Upper size */
  107. // ntrl = (curwp->w_rows - 3) - ntru; /* Lower size */
  108. /* Old is upper window */
  109. curwp->w_rows = ntru;
  110. wp->w_top = curwp->w_top + ntru + 1;
  111. wp->w_rows = ntru;
  112. wp->w_cols = curwp->w_cols;
  113. wp->w_left = curwp->w_left;
  114. wp2->w_top = wp->w_top + ntru + 1;
  115. wp2->w_rows = ntru + ((curwp->w_rows-2) % 3 != 0 ? 1 : 0);
  116. wp2->w_cols = curwp->w_cols;
  117. wp2->w_left = curwp->w_left;
  118. /* insert it in the list */
  119. wp3 = curwp->w_next;
  120. curwp->w_next = wp;
  121. wp->w_next = wp2;
  122. wp2->w_next = wp3;
  123. redraw(); /* mark the lot for update */
  124. }
  125. void chop_window_local(int internal)
  126. {
  127. window_t *wp, *wp2;
  128. int ntru, ntrl;
  129. if(!internal && window_mode == WINDOW_VERT) {
  130. msg("Already in vertical mode!");
  131. return;
  132. }
  133. if(!internal) {
  134. window_mode = WINDOW_VERT;
  135. delete_other_windows_local(FALSE);
  136. }
  137. if (curwp->w_cols < 22) {
  138. msg("Cannot split a %d columned window", curwp->w_cols);
  139. return;
  140. }
  141. wp = new_window();
  142. if(curwp->w_bufp->b_next != NULL)
  143. associate_b2w(curwp->w_bufp->b_next,wp);
  144. else
  145. associate_b2w(curwp->w_bufp,wp);
  146. b2w(wp); /* inherit buffer settings */
  147. ntru = (curwp->w_cols - 1) / 2; /* Upper size */
  148. ntrl = (curwp->w_cols - 1) - ntru; /* Lower size */
  149. /* Old is upper window */
  150. curwp->w_cols = ntru;
  151. wp->w_rows = curwp->w_rows;
  152. wp->w_top = curwp->w_top;
  153. wp->w_left = curwp->w_left + ntru + 1;
  154. wp->w_cols = ntrl;
  155. /* insert it in the list */
  156. wp2 = curwp->w_next;
  157. curwp->w_next = wp;
  158. wp->w_next = wp2;
  159. redraw(); /* mark the lot for update */
  160. }
  161. void chop_window()
  162. {
  163. chop_window_local(FALSE);
  164. }
  165. void tri_chop_window()
  166. {
  167. window_t *wp, *wp2, *wp3;
  168. int ntru;
  169. if(window_mode == WINDOW_TRIVERT) {
  170. msg("Already in triple vertical mode!");
  171. return;
  172. }
  173. window_mode = WINDOW_TRIVERT;
  174. delete_other_windows_local(FALSE);
  175. if (curwp->w_cols < 22) {
  176. msg("Cannot split a %d columned window", curwp->w_cols);
  177. return;
  178. }
  179. wp = new_window();
  180. if(curwp->w_bufp->b_next != NULL)
  181. associate_b2w(curwp->w_bufp->b_next,wp);
  182. else
  183. associate_b2w(curwp->w_bufp,wp);
  184. b2w(wp); /* inherit buffer settings */
  185. wp2 = new_window();
  186. if(wp->w_bufp->b_next != NULL)
  187. associate_b2w(wp->w_bufp->b_next,wp2);
  188. else
  189. associate_b2w(curwp->w_bufp,wp2);
  190. b2w(wp2); /* inherit buffer settings */
  191. ntru = (curwp->w_cols - 2) / 3; /* Upper size */
  192. /* Old is upper window */
  193. curwp->w_cols = ntru;
  194. wp->w_rows = curwp->w_rows;
  195. wp->w_top = curwp->w_top;
  196. wp->w_left = curwp->w_left + ntru + 1;
  197. wp->w_cols = ntru;
  198. wp2->w_rows = curwp->w_rows;
  199. wp2->w_top = curwp->w_top;
  200. wp2->w_left = curwp->w_left + wp->w_left + ntru + 1;
  201. wp2->w_cols = ntru;
  202. /* insert it in the list */
  203. wp3 = curwp->w_next;
  204. curwp->w_next = wp;
  205. wp->w_next = wp2;
  206. wp2->w_next = wp3;
  207. redraw(); /* mark the lot for update */
  208. }
  209. void next_window()
  210. {
  211. curwp->w_update = TRUE; /* make sure modeline gets updated */
  212. curwp = (curwp->w_next == NULL ? wheadp : curwp->w_next);
  213. curbp = curwp->w_bufp;
  214. if (curbp->b_cnt > 1)
  215. w2b(curwp); /* push win vars to buffer */
  216. }
  217. void fib_left()
  218. {
  219. if(window_mode == WINDOW_FIBLEFT) {
  220. msg("Already in Fibonacci left mode!");
  221. return;
  222. }
  223. window_mode = WINDOW_FIBLEFT;
  224. delete_other_windows_local(FALSE);
  225. chop_window_local(TRUE);
  226. split_window_local(TRUE);
  227. next_window();
  228. next_window();
  229. next_buffer();
  230. next_window();
  231. }
  232. void fib_right()
  233. {
  234. if(window_mode == WINDOW_FIBRIGHT) {
  235. msg("Already in Fibonacci right mode!");
  236. return;
  237. }
  238. window_mode = WINDOW_FIBRIGHT;
  239. delete_other_windows_local(FALSE);
  240. chop_window_local(TRUE);
  241. next_window();
  242. split_window_local(TRUE);
  243. next_window();
  244. next_window();
  245. }
  246. void quad_window()
  247. {
  248. if(window_mode == WINDOW_QUAD) {
  249. msg("Already in quad-window mode!");
  250. return;
  251. }
  252. window_mode = WINDOW_QUAD;
  253. delete_other_windows_local(FALSE);
  254. chop_window_local(TRUE);
  255. split_window_local(TRUE);
  256. next_window();
  257. next_window();
  258. next_buffer();
  259. split_window_local(TRUE);
  260. next_window();
  261. next_window();
  262. }
  263. void delete_other_windows()
  264. {
  265. delete_other_windows_local(TRUE);
  266. }
  267. void free_other_windows(window_t *winp)
  268. {
  269. window_t *wp, *next;
  270. for (wp = next = wheadp; next != NULL; wp = next) {
  271. next = wp->w_next; /* get next before a call to free() makes wp undefined */
  272. if (wp != winp) {
  273. disassociate_b(wp); /* this window no longer references its buffer */
  274. free(wp);
  275. }
  276. }
  277. wheadp = curwp = winp;
  278. one_window(winp);
  279. }
  280. void associate_b2w(buffer_t *bp, window_t *wp) {
  281. assert(bp != NULL);
  282. assert(wp != NULL);
  283. wp->w_bufp = bp;
  284. bp->b_cnt++;
  285. }
  286. void disassociate_b(window_t *wp) {
  287. assert(wp != NULL);
  288. assert(wp->w_bufp != NULL);
  289. wp->w_bufp->b_cnt--;
  290. }
  291. /* Recenters the screen whilst keeping the point.
  292. Will cycled from center, top, bottom.
  293. Because of odd number of rows, "middle" is considered anything that is in
  294. the range of [-1, 1].
  295. */
  296. void recenter()
  297. {
  298. int i = curwp->w_rows / 2;
  299. point_t new_page = curbp->b_page;
  300. int row = curwp->w_row - curwp->w_top;
  301. int shift = row - i;
  302. int current, lastln;
  303. assert(curwp != NULL);
  304. assert(curbp != NULL);
  305. get_line_stats(&current, &lastln, curbp);
  306. if(current == 0) {
  307. msg("Beginning of buffer, can't recenter");
  308. return;
  309. }
  310. if(shift == 0 || shift == 1 || shift == -1) // middle of screen
  311. {
  312. shift = curwp->w_rows / 2;
  313. } else if(row == curwp->w_rows - 1) // end of screen
  314. {
  315. shift = curwp->w_rows / 2;
  316. } else if(row == 0) // start of screen
  317. {
  318. shift = -1 * (curwp->w_rows - 1);
  319. }
  320. if(shift < 0) {
  321. for(int k = shift ; k < 0; k++) {
  322. new_page = upup(curbp, curwp, new_page);
  323. }
  324. if(*ptr(curbp, new_page) == '\n')
  325. new_page++;
  326. } else {
  327. for(int k = shift; k > 0; k--) {
  328. new_page = dndn(curbp, curwp, new_page);
  329. }
  330. }
  331. curbp->b_page = new_page;
  332. }