diff --git a/screen-redraw.c b/screen-redraw.c index dd5886b2..fc2817ce 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -49,9 +49,15 @@ const struct grid_cell screen_redraw_border_cell = { { { ' ' }, 0, 1, 1 }, GRID_ATTR_CHARSET, 0, 8, 8, 0 }; +enum screen_redraw_border_type { + SCREEN_REDRAW_OUTSIDE, + SCREEN_REDRAW_INSIDE, + SCREEN_REDRAW_BORDER +}; + /* Return if window has only two panes. */ static int -screen_redraw_two_panes(struct window *w) +screen_redraw_two_panes(struct window *w, int direction) { struct window_pane *wp; @@ -60,99 +66,176 @@ screen_redraw_two_panes(struct window *w) return (0); /* one pane */ if (TAILQ_NEXT(wp, entry) != NULL) return (0); /* more than two panes */ + if (direction == 0 && wp->xoff == 0) + return (0); + if (direction == 1 && wp->yoff == 0) + return (0); return (1); } -/* Check if cell is on the border of a particular pane. */ -static int -screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py, +/* Check if cell is on the border of a pane. */ +static enum screen_redraw_border_type +screen_redraw_pane_border(struct window_pane *wp, u_int px, u_int py, int pane_status) { u_int ex = wp->xoff + wp->sx, ey = wp->yoff + wp->sy; /* Inside pane. */ if (px >= wp->xoff && px < ex && py >= wp->yoff && py < ey) - return (0); + return (SCREEN_REDRAW_INSIDE); /* Left/right borders. */ if (pane_status == PANE_STATUS_OFF) { - if (screen_redraw_two_panes(wp->window)) { + if (screen_redraw_two_panes(wp->window, 0)) { if (wp->xoff == 0 && px == wp->sx && py <= wp->sy / 2) - return (2); + return (SCREEN_REDRAW_BORDER); if (wp->xoff != 0 && px == wp->xoff - 1 && py > wp->sy / 2) - return (1); + return (SCREEN_REDRAW_BORDER); } else { if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) { if (wp->xoff != 0 && px == wp->xoff - 1) - return (1); + return (SCREEN_REDRAW_BORDER); if (px == ex) - return (2); + return (SCREEN_REDRAW_BORDER); } } } else { if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= ey) { if (wp->xoff != 0 && px == wp->xoff - 1) - return (1); + return (SCREEN_REDRAW_BORDER); if (px == ex) - return (2); + return (SCREEN_REDRAW_BORDER); } } /* Top/bottom borders. */ if (pane_status == PANE_STATUS_OFF) { - if (screen_redraw_two_panes(wp->window)) { + if (screen_redraw_two_panes(wp->window, 1)) { if (wp->yoff == 0 && py == wp->sy && px <= wp->sx / 2) - return (4); + return (SCREEN_REDRAW_BORDER); if (wp->yoff != 0 && py == wp->yoff - 1 && px > wp->sx / 2) - return (3); + return (SCREEN_REDRAW_BORDER); } else { if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) { if (wp->yoff != 0 && py == wp->yoff - 1) - return (3); + return (SCREEN_REDRAW_BORDER); if (py == ey) - return (4); + return (SCREEN_REDRAW_BORDER); } } } else if (pane_status == PANE_STATUS_TOP) { if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) { if (wp->yoff != 0 && py == wp->yoff - 1) - return (3); + return (SCREEN_REDRAW_BORDER); } } else { if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= ex) { if (py == ey) - return (4); + return (SCREEN_REDRAW_BORDER); } } /* Outside pane. */ - return (-1); + return (SCREEN_REDRAW_OUTSIDE); } -/* Check if a cell is on the pane border. */ +/* Check if a cell is on a border. */ static int screen_redraw_cell_border(struct client *c, u_int px, u_int py, int pane_status) { struct window *w = c->session->curw->window; struct window_pane *wp; - int retval; + + /* On the window border? */ + if (px == w->sx || py == w->sy) + return (1); + + /* Outside the window? */ + if (px > w->sx || py > w->sy) + return (0); /* Check all the panes. */ TAILQ_FOREACH(wp, &w->panes, entry) { if (!window_pane_visible(wp)) continue; - retval = screen_redraw_cell_border1(wp, px, py, pane_status); - if (retval != -1) - return (!!retval); + switch (screen_redraw_pane_border(wp, px, py, pane_status)) { + case SCREEN_REDRAW_INSIDE: + return (0); + case SCREEN_REDRAW_BORDER: + return (1); + case SCREEN_REDRAW_OUTSIDE: + break; + } } return (0); } +/* Work out type of border cell from surrounding cells. */ +static int +screen_redraw_type_of_cell(struct client *c, u_int px, u_int py, + int pane_status) +{ + struct window *w = c->session->curw->window; + u_int sx = w->sx, sy = w->sy; + int borders = 0; + + /* + * Construct a bitmask of whether the cells to the left (bit 4), right, + * top, and bottom (bit 1) of this cell are borders. + */ + if (px == 0 || screen_redraw_cell_border(c, px - 1, py, pane_status)) + borders |= 8; + if (px <= sx && screen_redraw_cell_border(c, px + 1, py, pane_status)) + borders |= 4; + if (pane_status == PANE_STATUS_TOP) { + if (py != 0 && + screen_redraw_cell_border(c, px, py - 1, pane_status)) + borders |= 2; + } else { + if (py == 0 || + screen_redraw_cell_border(c, px, py - 1, pane_status)) + borders |= 2; + } + if (py <= sy && screen_redraw_cell_border(c, px, py + 1, pane_status)) + borders |= 1; + + /* + * Figure out what kind of border this cell is. Only one bit set + * doesn't make sense (can't have a border cell with no others + * connected). + */ + switch (borders) { + case 15: /* 1111, left right top bottom */ + return (CELL_JOIN); + case 14: /* 1110, left right top */ + return (CELL_BOTTOMJOIN); + case 13: /* 1101, left right bottom */ + return (CELL_TOPJOIN); + case 12: /* 1100, left right */ + return (CELL_TOPBOTTOM); + case 11: /* 1011, left top bottom */ + return (CELL_RIGHTJOIN); + case 10: /* 1010, left top */ + return (CELL_BOTTOMRIGHT); + case 9: /* 1001, left bottom */ + return (CELL_TOPRIGHT); + case 7: /* 0111, right top bottom */ + return (CELL_LEFTJOIN); + case 6: /* 0110, right top */ + return (CELL_BOTTOMLEFT); + case 5: /* 0101, right bottom */ + return (CELL_TOPLEFT); + case 3: /* 0011, top bottom */ + return (CELL_LEFTRIGHT); + } + return (CELL_OUTSIDE); +} + /* Check if cell inside a pane. */ static int screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status, @@ -160,13 +243,15 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status, { struct window *w = c->session->curw->window; struct window_pane *wp; - int borders, border; + int border; u_int right, line; *wpp = NULL; if (px > w->sx || py > w->sy) return (CELL_OUTSIDE); + if (px == w->sx || py == w->sy) /* window border */ + return (screen_redraw_type_of_cell(c, px, py, pane_status)); if (pane_status != PANE_STATUS_OFF) { wp = w->active; @@ -196,72 +281,16 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status, goto next2; *wpp = wp; - /* If outside the pane and its border, skip it. */ - if ((wp->xoff != 0 && px < wp->xoff - 1) || - px > wp->xoff + wp->sx || - (wp->yoff != 0 && py < wp->yoff - 1) || - py > wp->yoff + wp->sy) - goto next2; - - /* If definitely inside, return. If not on border, skip. */ - border = screen_redraw_cell_border1(wp, px, py, pane_status); - if (border == 0) + /* + * If definitely inside, return. If not on border, skip. + * Otherwise work out the cell. + */ + border = screen_redraw_pane_border(wp, px, py, pane_status); + if (border == SCREEN_REDRAW_INSIDE) return (CELL_INSIDE); - if (border == -1) + if (border == SCREEN_REDRAW_OUTSIDE) goto next2; - - /* - * Construct a bitmask of whether the cells to the left (bit - * 4), right, top, and bottom (bit 1) of this cell are borders. - */ - borders = 0; - if (px == 0 || - screen_redraw_cell_border(c, px - 1, py, pane_status)) - borders |= 8; - if (px <= w->sx && - screen_redraw_cell_border(c, px + 1, py, pane_status)) - borders |= 4; - if (pane_status == PANE_STATUS_TOP && - py != 0 && - screen_redraw_cell_border(c, px, py - 1, pane_status)) - borders |= 2; - else if (pane_status != PANE_STATUS_TOP && - (py == 0 || - screen_redraw_cell_border(c, px, py - 1, pane_status))) - borders |= 2; - if (py <= w->sy && - screen_redraw_cell_border(c, px, py + 1, pane_status)) - borders |= 1; - - /* - * Figure out what kind of border this cell is. Only one bit - * set doesn't make sense (can't have a border cell with no - * others connected). - */ - switch (borders) { - case 15: /* 1111, left right top bottom */ - return (CELL_JOIN); - case 14: /* 1110, left right top */ - return (CELL_BOTTOMJOIN); - case 13: /* 1101, left right bottom */ - return (CELL_TOPJOIN); - case 12: /* 1100, left right */ - return (CELL_TOPBOTTOM); - case 11: /* 1011, left top bottom */ - return (CELL_RIGHTJOIN); - case 10: /* 1010, left top */ - return (CELL_BOTTOMRIGHT); - case 9: /* 1001, left bottom */ - return (CELL_TOPRIGHT); - case 7: /* 0111, right top bottom */ - return (CELL_LEFTJOIN); - case 6: /* 0110, right top */ - return (CELL_BOTTOMLEFT); - case 5: /* 0101, right bottom */ - return (CELL_TOPLEFT); - case 3: /* 0011, top bottom */ - return (CELL_LEFTRIGHT); - } + return (screen_redraw_type_of_cell(c, px, py, pane_status)); next2: wp = TAILQ_NEXT(wp, entry); @@ -277,12 +306,12 @@ static int screen_redraw_check_is(u_int px, u_int py, int pane_status, struct window_pane *wp) { - int border; + enum screen_redraw_border_type border; - border = screen_redraw_cell_border1(wp, px, py, pane_status); - if (border == 0 || border == -1) - return (0); - return (1); + border = screen_redraw_pane_border(wp, px, py, pane_status); + if (border == SCREEN_REDRAW_BORDER) + return (1); + return (0); } /* Update pane status. */