123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- /* window.c, Ait, Kevin Bloom, BSD 3-Clause, 2023 */
- #include "header.h"
- #include "termbox.h"
- int win_cnt = 0;
- window_t* new_window()
- {
- window_t *wp = (window_t *)malloc(sizeof(window_t));
- assert(wp != NULL); /* call fatal instead XXX */
- wp->w_next = NULL;
- wp->w_bufp = NULL;
- wp->w_point = 0;
- wp->w_mark = NOMARK;
- wp->w_top = 0;
- wp->w_left = 0;
- wp->w_rows = 0;
- wp->w_cols = 0;
- wp->w_update = FALSE;
- sprintf(wp->w_name, "W%d", ++win_cnt);
- windows[number_of_windows] = wp;
- number_of_windows++;
- return wp;
- }
- void one_window(window_t *wp)
- {
- wp->w_top = 0;
- wp->w_left = 0;
- wp->w_rows = LINES - 2;
- wp->w_cols = COLS;
- wp->w_next = NULL;
- for(int i = number_of_windows; i > -1; i--)
- windows[i] = NULL;
- number_of_windows = 1;
- windows[0] = wp;
- }
- void split_window()
- {
- window_t *wp, *wp2;
- int ntru, ntrl;
- if (curwp->w_rows < 3) {
- msg("Cannot split a %d line window", curwp->w_rows);
- return;
- }
- wp = new_window();
- associate_b2w(curwp->w_bufp,wp);
- b2w(wp); /* inherit buffer settings */
- ntru = (curwp->w_rows - 1) / 2; /* Upper size */
- ntrl = (curwp->w_rows - 1) - ntru; /* Lower size */
- /* Old is upper window */
- curwp->w_rows = ntru;
- wp->w_top = curwp->w_top + ntru + 1;
- wp->w_rows = ntrl;
- wp->w_cols = curwp->w_cols;
- wp->w_left = curwp->w_left;
- /* insert it in the list */
- wp2 = curwp->w_next;
- curwp->w_next = wp;
- wp->w_next = wp2;
- redraw(); /* mark the lot for update */
- }
- void chop_window()
- {
- window_t *wp, *wp2;
- int ntru, ntrl;
- if (curwp->w_cols < 3) {
- msg("Cannot split a %d columned window", curwp->w_cols);
- return;
- }
- wp = new_window();
- associate_b2w(curwp->w_bufp,wp);
- b2w(wp); /* inherit buffer settings */
- ntru = (curwp->w_cols - 1) / 2; /* Upper size */
- ntrl = (curwp->w_cols - 1) - ntru; /* Lower size */
- /* Old is upper window */
- curwp->w_cols = ntru - 1;
- wp->w_rows = curwp->w_rows;
- wp->w_top = curwp->w_top;
- wp->w_left = curwp->w_left + ntru + 1;
- wp->w_cols = ntrl;
- /* insert it in the list */
- wp2 = curwp->w_next;
- curwp->w_next = wp;
- wp->w_next = wp2;
- redraw(); /* mark the lot for update */
- }
- void next_window() {
- curwp->w_update = TRUE; /* make sure modeline gets updated */
- curwp = (curwp->w_next == NULL ? wheadp : curwp->w_next);
- curbp = curwp->w_bufp;
- if (curbp->b_cnt > 1)
- w2b(curwp); /* push win vars to buffer */
- }
- void delete_other_windows()
- {
- if (wheadp->w_next == NULL) {
- msg("Only 1 window");
- return;
- }
- free_other_windows(curwp);
- }
- void free_other_windows(window_t *winp)
- {
- window_t *wp, *next;
- for (wp = next = wheadp; next != NULL; wp = next) {
- next = wp->w_next; /* get next before a call to free() makes wp undefined */
- if (wp != winp) {
- disassociate_b(wp); /* this window no longer references its buffer */
- free(wp);
- }
- }
- wheadp = curwp = winp;
- one_window(winp);
- }
- void close_window()
- {
- window_t *wp, *next = NULL;
- int found = FALSE;
- if(number_of_windows == 1) {
- msg("Only 1 window.");
- return;
- }
- for(int i = 0 ; i < number_of_windows; i++) {
- if(windows[i] == curwp) {
- wp = curwp;
- found = TRUE;
- next = wp->w_next == NULL ? wheadp : wp->w_next;
- }
- if(i + 1 == number_of_windows)
- windows[i] = NULL;
- else if(found)
- windows[i] = windows[i+1];
- }
- number_of_windows--;
- if(number_of_windows == 1)
- one_window(next);
- else {
- if(curwp->w_left == next->w_left) { /* vertical */
- next->w_rows += curwp->w_rows + 1;
- next->w_top = curwp->w_top;
- }
- if(curwp->w_top == next->w_top) {
- next->w_cols += curwp->w_cols + 1;
- next->w_left = curwp->w_left;
- }
- }
- curwp = next;
- next_buffer();
- }
- void associate_b2w(buffer_t *bp, window_t *wp) {
- assert(bp != NULL);
- assert(wp != NULL);
- wp->w_bufp = bp;
- bp->b_cnt++;
- }
- void disassociate_b(window_t *wp) {
- assert(wp != NULL);
- assert(wp->w_bufp != NULL);
- wp->w_bufp->b_cnt--;
- }
- /* Recenters the screen whilst keeping the point.
- Will cycled from center, top, bottom.
- Because of odd number of rows, "middle" is considered anything that is in
- the range of [-1, 1].
- */
- void recenter()
- {
- int i = curwp->w_rows / 2;
- point_t new_page = curbp->b_page;
- int shift = curwp->w_row - i;
- int current, lastln;
- assert(curwp != NULL);
- assert(curbp != NULL);
- get_line_stats(¤t, &lastln, curbp);
- if(current == 0) {
- msg("Beginning of buffer, can't recenter");
- return;
- }
- if(shift == 0 || shift == 1 || shift == -1) // middle of screen
- {
- shift = curwp->w_rows / 2;
- } else if(curbp->b_row == curwp->w_rows - 1) // end of screen
- {
- shift = curwp->w_rows / 2;
- } else if(curbp->b_row == 0) // start of screen
- {
- shift = -1 * (curwp->w_rows - 1);
- }
- if(shift < 0) {
- for(int k = shift; k < 0; k++) {
- new_page = lnstart(curbp,new_page - 1);
- }
- if(*ptr(curbp, new_page) == '\n')
- new_page++;
- } else {
- int found_end = FALSE;
- for(int k = shift; k > 0; k--) {
- found_end = FALSE;
- while(found_end == FALSE) {
- if(*ptr(curbp, new_page) == '\n')
- found_end = TRUE;
- new_page++;
- }
- }
- }
- curbp->b_page = new_page;
- }
|