123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- /* window.c, Ait, Kevin Bloom, BSD 3-Clause, 2023-2024 */
- #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;
- wp->w_mcol = 0;
- wp->w_mlen = 0;
- wp->w_recenter = 0;
- sprintf(wp->w_name, "W%d", ++win_cnt);
- return wp;
- }
- void one_window(window_t *wp)
- {
- window_mode = WINDOW_DEFAULT;
- wp->w_top = 0;
- wp->w_left = 0;
- wp->w_rows = LINES - 2;
- wp->w_cols = COLS;
- wp->w_next = NULL;
- wp->w_update = TRUE;
- wp->w_mcol = 0;
- }
- void delete_other_windows_local(int showmsg)
- {
- if (wheadp->w_next == NULL) {
- if(showmsg)
- msg("Only 1 window");
- return;
- }
- free_other_windows(curwp);
- }
- void split_window_local(int internal)
- {
- window_t *wp, *wp2;
- int ntru, ntrl;
- /* if(!internal && window_mode == WINDOW_HORIZ) {
- msg("Already in horizontal mode!");
- return;
- }
- */ if(!internal) {
- window_mode = WINDOW_HORIZ;
- delete_other_windows_local(FALSE);
- }
- if (curwp->w_rows < 3) {
- msg("Cannot split a %d line window", curwp->w_rows);
- return;
- }
- wp = new_window();
- if(curwp->w_bufp->b_next != NULL)
- associate_b2w(curwp->w_bufp->b_next,wp);
- else
- 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;
- curbp->b_reframe = TRUE;
- redraw(); /* mark the lot for update */
- }
- void split_window()
- {
- split_window_local(FALSE);
- }
- void tri_split_window()
- {
- window_t *wp, *wp2, *wp3;
- int ntru, leftovers = 0;
- window_mode = WINDOW_TRIHORIZ;
- delete_other_windows_local(FALSE);
- if (curwp->w_rows < 3) {
- msg("Cannot split a %d line window", curwp->w_rows);
- return;
- }
- wp = new_window();
- if(curwp->w_bufp->b_next != NULL)
- associate_b2w(curwp->w_bufp->b_next,wp);
- else
- associate_b2w(curwp->w_bufp,wp);
- b2w(wp); /* inherit buffer settings */
- wp2 = new_window();
- if(wp->w_bufp->b_next != NULL)
- associate_b2w(wp->w_bufp->b_next,wp2);
- else
- associate_b2w(curwp->w_bufp,wp2);
- b2w(wp2); /* inherit buffer settings */
- ntru = (LINES - 4) / 3; /* Upper size */
- // ntrl = (curwp->w_rows - 3) - ntru; /* Lower size */
- /* Old is upper window */
- curwp->w_rows = ntru;
- leftovers = LINES - (2*ntru) - 4;
- wp->w_top = curwp->w_top + ntru + 1;
- wp->w_rows = ntru;
- wp->w_cols = curwp->w_cols;
- wp->w_left = curwp->w_left;
- wp2->w_top = wp->w_top + ntru + 1;
- wp2->w_rows = leftovers;
- wp2->w_cols = curwp->w_cols;
- wp2->w_left = curwp->w_left;
- curbp->b_reframe = TRUE;
- /* If there is more than 1 line left over, distribute the
- difference to make it look cleaner
- */
- if(leftovers - ntru == 2) {
- wp->w_rows++;
- wp2->w_top++;
- wp2->w_rows--;
- }
- /* insert it in the list */
- wp3 = curwp->w_next;
- curwp->w_next = wp;
- wp->w_next = wp2;
- wp2->w_next = wp3;
- // curwp->w_next->w_next->w_bufp->b_reframe = TRUE;
- redraw(); /* mark the lot for update */
- }
- void chop_window_local(int internal)
- {
- window_t *wp, *wp2;
- int ntru, ntrl;
- /* if(!internal && window_mode == WINDOW_VERT) {
- msg("Already in vertical mode!");
- return;
- }
- */ if(!internal) {
- window_mode = WINDOW_VERT;
- delete_other_windows_local(FALSE);
- }
- if (curwp->w_cols < 22) {
- msg("Cannot split a %d columned window", curwp->w_cols);
- return;
- }
- wp = new_window();
- if(curwp->w_bufp->b_next != NULL)
- associate_b2w(curwp->w_bufp->b_next,wp);
- else
- 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;
- 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 chop_window()
- {
- chop_window_local(FALSE);
- }
- void tri_chop_window()
- {
- window_t *wp, *wp2, *wp3;
- int ntru, leftovers;
- window_mode = WINDOW_TRIVERT;
- delete_other_windows_local(FALSE);
- if (curwp->w_cols < 22) {
- msg("Cannot split a %d columned window", curwp->w_cols);
- return;
- }
- wp = new_window();
- if(curwp->w_bufp->b_next != NULL)
- associate_b2w(curwp->w_bufp->b_next,wp);
- else
- associate_b2w(curwp->w_bufp,wp);
- b2w(wp); /* inherit buffer settings */
- wp2 = new_window();
- if(wp->w_bufp->b_next != NULL)
- associate_b2w(wp->w_bufp->b_next,wp2);
- else
- associate_b2w(curwp->w_bufp,wp2);
- b2w(wp2); /* inherit buffer settings */
- ntru = (COLS - 2) / 3; /* Upper size */
- /* Old is upper window */
- curwp->w_cols = ntru;
- leftovers = COLS - (2*ntru) - 2;
- wp->w_rows = curwp->w_rows;
- wp->w_top = curwp->w_top;
- wp->w_left = curwp->w_left + ntru + 1;
- wp->w_cols = ntru;
- wp2->w_rows = curwp->w_rows;
- wp2->w_top = curwp->w_top;
- wp2->w_left = curwp->w_left + wp->w_left + ntru + 1;
- wp2->w_cols = leftovers;
- /* If there is more than 1 column left over, distribute the
- difference to make it look cleaner
- */
- if(leftovers - ntru == 2) {
- wp->w_cols++;
- wp2->w_left++;
- wp2->w_cols--;
- }
- /* insert it in the list */
- wp3 = curwp->w_next;
- curwp->w_next = wp;
- wp->w_next = wp2;
- wp2->w_next = wp3;
- 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 */
- curwp->w_update = TRUE; /* make sure modeline gets updated */
- if(curbp->b_point > curbp->b_epage ||
- curbp->b_point < curbp->b_page) {
- curbp->b_reframe = TRUE;
- }
- }
- void fib_left()
- {
- window_mode = WINDOW_FIBLEFT;
- delete_other_windows_local(FALSE);
- chop_window_local(TRUE);
- split_window_local(TRUE);
- next_window();
- next_window();
- next_buffer();
- next_window();
- }
- void fib_right()
- {
- window_mode = WINDOW_FIBRIGHT;
- delete_other_windows_local(FALSE);
- chop_window_local(TRUE);
- next_window();
- split_window_local(TRUE);
- next_window();
- next_window();
- }
- void quad_window()
- {
- window_mode = WINDOW_QUAD;
- delete_other_windows_local(FALSE);
- chop_window_local(TRUE);
- split_window_local(TRUE);
- next_window();
- next_window();
- next_buffer();
- split_window_local(TRUE);
- next_window();
- next_window();
- }
- void delete_other_windows()
- {
- delete_other_windows_local(TRUE);
- }
- 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 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 row = curwp->w_row - curwp->w_top;
- int shift = 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(row == curwp->w_rows - 1) // end of screen
- {
- shift = curwp->w_rows / 2;
- } else if(row == 0) // start of screen
- {
- shift = -1 * (curwp->w_rows - 1);
- }
- if(shift < 0) {
- for(int k = shift ; k < 0; k++) {
- new_page = upup(curbp, curwp, new_page);
- }
- if(*ptr(curbp, new_page) == '\n')
- new_page++;
- } else {
- for(int k = shift; k > 0; k--) {
- new_page = dndn(curbp, curwp, new_page);
- }
- }
- curbp->b_page = new_page;
- }
- void resize()
- {
- switch(window_mode) {
- case WINDOW_HORIZ:
- split_window();
- break;
- case WINDOW_VERT:
- chop_window();
- break;
- case WINDOW_TRIHORIZ:
- tri_split_window();
- break;
- case WINDOW_TRIVERT:
- tri_chop_window();
- break;
- case WINDOW_FIBLEFT:
- fib_left();
- break;
- case WINDOW_FIBRIGHT:
- fib_right();
- break;
- case WINDOW_QUAD:
- quad_window();
- break;
- default:
- one_window(curwp);
- break;
- }
- return;
- }
|