diff options
author | Nicholas Marriott <nicholas.marriott@gmail.com> | 2007-11-20 21:42:29 +0000 |
---|---|---|
committer | Nicholas Marriott <nicholas.marriott@gmail.com> | 2007-11-20 21:42:29 +0000 |
commit | ceab127fac8b226ea2907261bdd6337b79d5d550 (patch) | |
tree | 558265c7e58356458b49a433d8fd3b43671251e6 /screen-display.c | |
parent | 0be6a3041ff58e716e6e44ff577dcc62685b3613 (diff) |
Mass screen.c rename/tidy. Add a actual size (ysize) as distinct from display size (now dx,dy). Move functions which work on the displayed area into screen-display.c and tidy. Use macros consistently when accessing screen data (may want to move everything about again later!). This the first step on the road to scrollback.
Diffstat (limited to 'screen-display.c')
-rw-r--r-- | screen-display.c | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/screen-display.c b/screen-display.c new file mode 100644 index 00000000..5f2790aa --- /dev/null +++ b/screen-display.c @@ -0,0 +1,430 @@ +/* $Id: screen-display.c,v 1.1 2007-11-20 21:42:29 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +#include <string.h> + +#include "tmux.h" + +/* + * Screen display modification functions. These alter the displayed portion + * of the screen. + */ + +/* Create a region of lines. */ +void +screen_display_make_lines(struct screen *s, u_int py, u_int ny) +{ + if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) + fatalx("bad value"); + screen_make_lines(s, screen_y(s, py), ny); +} + +/* Free a region of lines. */ +void +screen_display_free_lines(struct screen *s, u_int py, u_int ny) +{ + if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) + fatalx("bad value"); + screen_free_lines(s, screen_y(s, py), ny); +} + +/* Move a set of lines. */ +void +screen_display_move_lines(struct screen *s, u_int dy, u_int py, u_int ny) +{ + if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) + fatalx("bad value"); + if (!screen_in_y(s, dy) || !screen_in_y(s, dy + ny - 1) || dy == py) + fatalx("bad value"); + screen_move_lines(s, screen_y(s, dy), screen_y(s, py), ny); +} + +/* Fill a set of lines. */ +void +screen_display_fill_lines( + struct screen *s, u_int py, u_int ny, u_char data, u_char attr, u_char colr) +{ + if (ny == 0 || !screen_in_y(s, py) || !screen_in_y(s, py + ny - 1)) + fatalx("bad value"); + screen_fill_lines(s, screen_y(s, py), ny, data, attr, colr); +} + +/* Fill a set of cellss. */ +void +screen_display_fill_cells(struct screen *s, + u_int px, u_int py, u_int nx, u_char data, u_char attr, u_char colr) +{ + if (nx == 0 || !screen_in_x(s, px) || !screen_in_y(s, py)) + fatalx("bad value"); + screen_fill_cells( + s, screen_x(s, px), screen_y(s, py), nx, data, attr, colr); +} + +/* Fill entire screen. */ +void +screen_display_fill_screen( + struct screen *s, u_char data, u_char attr, u_char colr) +{ + screen_display_fill_lines(s, 0, screen_size_y(s), data, attr, colr); +} + +/* Fill end of screen from cursor. */ +void +screen_display_fill_cursor_eos( + struct screen *s, u_char data, u_char attr, u_char colr) +{ + screen_display_fill_cursor_eol(s, data, attr, colr); + if (s->cy != screen_last_y(s)) { + screen_display_fill_lines( + s, s->cy, screen_size_y(s) - s->cy, data, attr, colr); + } +} + +/* Fill beginning of screen from cursor. */ +void +screen_display_fill_cursor_bos( + struct screen *s, u_char data, u_char attr, u_char colr) +{ + screen_display_fill_lines(s, 0, s->cy, data, attr, colr); +} + +/* Fill a single line. */ +void +screen_display_fill_line( + struct screen *s, u_int py, u_char data, u_char attr, u_char colr) +{ + screen_display_fill_lines(s, py, 1, data, attr, colr); +} + +/* Fill cursor to beginning of line. */ +void +screen_display_fill_cursor_bol( + struct screen *s, u_char data, u_char attr, u_char colr) +{ + screen_display_fill_cells(s, 0, s->cy, s->cx, data, attr, colr); +} + +/* Fill cursor to end of line. */ +void +screen_display_fill_cursor_eol( + struct screen *s, u_char data, u_char attr, u_char colr) +{ + screen_display_fill_cells( + s, s->cx, s->cy, screen_size_x(s) - s->cx, data, attr, colr); +} + +/* Set character at cursor. */ +void +screen_display_cursor_set(struct screen *s, u_char ch) +{ + u_int px, py; + + px = screen_x(s, s->cx); + py = screen_y(s, s->cy); + + s->grid_data[py][px] = ch; + s->grid_attr[py][px] = s->attr; + s->grid_colr[py][px] = s->colr; +} + +/* Move cursor up and scroll if necessary. */ +void +screen_display_cursor_up(struct screen *s) +{ + if (s->cy == s->rupper) + screen_display_scroll_region_down(s); + else if (s->cy > 0) + s->cy--; +} + +/* Move cursor down and scroll if necessary. */ +void +screen_display_cursor_down(struct screen *s) +{ + if (s->cy == s->rlower) + screen_display_scroll_region_up(s); + else if (s->cy < screen_last_y(s)) + s->cy++; +} + +/* Scroll region up. */ +void +screen_display_scroll_region_up(struct screen *s) +{ + /* + * Scroll scrolling region up: + * - delete rupper + * - move rupper + 1 to rlower to rupper + * - make new line at rlower + * + * Example: region is 12 to 24. + * rlower = 24, rupper = 12 + * screen_free_lines(s, 12, 1); + * screen_move_lines(s, 12, 13, 12); + * screen_make_lines(s, 24, 1); + */ + + screen_display_free_lines(s, s->rupper, 1); + + if (s->rupper != s->rlower) { + screen_display_move_lines(s, + s->rupper, s->rupper + 1, s->rlower - s->rupper); + } + + screen_display_make_lines(s, s->rlower, 1); + screen_display_fill_lines( + s, s->rlower, 1, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); +} + +/* Scroll region down. */ +void +screen_display_scroll_region_down(struct screen *s) +{ + /* + * Scroll scrolling region down: + * - delete rlower + * - move rupper to rlower - 1 to rupper + 1 + * - make new line at rupper + * + * Example: region is 12 to 24. + * rlower = 24, rupper = 12 + * screen_free_lines(s, 24, 1); + * screen_move_lines(s, 13, 12, 12); + * screen_make_lines(s, 12, 1); + */ + + screen_display_free_lines(s, s->rlower, 1); + + if (s->rupper != s->rlower) { + screen_display_move_lines(s, + s->rupper + 1, s->rupper, s->rlower - s->rupper); + } + + screen_display_make_lines(s, s->rupper, 1); + screen_display_fill_lines( + s, s->rupper, 1, SCREEN_DEFDATA, SCREEN_DEFATTR, SCREEN_DEFCOLR); +} + +/* Insert lines. */ +void +screen_display_insert_lines(struct screen *s, u_int py, u_int ny) +{ + if (!screen_in_y(s, py)) + fatalx("bad value"); + if (ny == 0) + fatalx("bad value"); + + if (py + ny > screen_last_y(s)) + ny = screen_last_y(s) - py; + + /* + * Insert range of ny lines at py: + * - Free ny lines from end of screen. + * - Move from py to end of screen - ny to py + ny. + * - Create ny lines at py. + * + * Example: insert 2 lines at 4. + * sy = 10, py = 4, ny = 2 + * screen_free_lines(s, 8, 2); - delete lines 8,9 + * screen_move_lines(s, 6, 4, 4); - move 4,5,6,7 to 6,7,8,9 + * screen_make_lines(s, 4, 2); - make lines 4,5 + */ + + screen_display_free_lines(s, screen_size_y(s) - ny, ny); + + if (py != screen_last_y(s)) { + screen_display_move_lines( + s, py + ny, py, screen_size_y(s) - py - ny); + } + + screen_display_make_lines(s, py, ny); +} + +/* Insert lines in region. */ +void +screen_display_insert_lines_region(struct screen *s, u_int py, u_int ny) +{ + if (!screen_in_region(s, py)) + fatalx("bad value"); + if (ny == 0) + fatalx("bad value"); + + if (py + ny > s->rlower) + ny = s->rlower - py; + + /* + * Insert range of ny lines at py: + * - Free ny lines from end of screen. + * - Move from py to end of screen - ny to py + ny. + * - Create ny lines at py. + * + * Example: insert 2 lines at 4. + * ryu = 11, ryl = 16, py = 13, ny = 2 + * screen_free_lines(s, 15, 2); - delete lines 15,16 + * screen_move_lines(s, 13, 15, 2);- move 13,14 to 15,16 + * screen_make_lines(s, 13, 2); - make lines 13,14 + */ + + screen_display_free_lines(s, (s->rlower + 1) - ny, ny); + + if (py != s->rlower) { + screen_display_move_lines( + s, py + ny, py, (s->rlower + 1) - py - ny); + } + + screen_display_make_lines(s, py, ny); +} + +/* Delete lines. */ +void +screen_display_delete_lines(struct screen *s, u_int py, u_int ny) +{ + if (!screen_in_y(s, py)) + fatalx("bad value"); + if (ny == 0) + fatalx("bad value"); + + if (py + ny > screen_last_y(s)) + ny = screen_last_y(s) - py; + + /* + * Delete range of ny lines at py: + * - Free ny lines at py. + * - Move from py + ny to end of screen to py. + * - Free and recreate last ny lines. + * + * Example: delete lines 3,4. + * sy = 10, py = 3, ny = 2 + * screen_free_lines(s, 3, 2); - delete lines 3,4 + * screen_move_lines(s, 3, 5, 5); - move 5,6,7,8,9 to 3 + * screen_make_lines(s, 8, 2); - make lines 8,9 + */ + + screen_display_free_lines(s, py, ny); + + if (py != screen_last_y(s)) { + screen_display_move_lines( + s, py, py + ny, screen_size_y(s) - py - ny); + } + + screen_display_make_lines(s, screen_size_y(s) - ny, ny); +} + +/* Delete lines inside scroll region. */ +void +screen_display_delete_lines_region(struct screen *s, u_int py, u_int ny) +{ + if (!screen_in_region(s, py)) + fatalx("bad value"); + if (ny == 0) + fatalx("bad value"); + + if (py + ny > s->rlower) + ny = s->rlower - py; + + /* + * Delete range of ny lines at py: + * - Free ny lines at py. + * - Move from py + ny to end of region to py. + * - Free and recreate last ny lines. + * + * Example: delete lines 13,14. + * ryu = 11, ryl = 16, py = 13, ny = 2 + * screen_free_lines(s, 13, 2); - delete lines 13,14 + * screen_move_lines(s, 15, 16, 2);- move 15,16 to 13 + * screen_make_lines(s, 15, 16); - make lines 15,16 + */ + + screen_display_free_lines(s, py, ny); + + if (py != s->rlower) { + screen_display_move_lines( + s, py, py + ny, (s->rlower + 1) - py - ny); + } + + screen_display_make_lines(s, (s->rlower + 1) - ny, ny); +} + +/* Insert characters. */ +void +screen_display_insert_characters(struct screen *s, u_int px, u_int py, u_int nx) +{ + u_int mx; + + px = screen_x(s, px); + py = screen_y(s, py); + + if (!screen_in_x(s, px) || !screen_in_y(s, py)) + fatalx("bad value"); + + if (px + nx > screen_last_x(s)) + nx = screen_last_x(s) - px; + + /* + * Inserting a range of nx at px. + * + * - Move sx - (px + nx) from px to px + nx. + * - Clear the range at px. + */ + + if (px + nx != screen_last_x(s)) { + mx = screen_last_x(s) - (px + nx); + memmove(&s->grid_data[py][px + nx], &s->grid_data[py][px], mx); + memmove(&s->grid_attr[py][px + nx], &s->grid_attr[py][px], mx); + memmove(&s->grid_colr[py][px + nx], &s->grid_colr[py][px], mx); + } + memset(&s->grid_data[py][px], SCREEN_DEFDATA, nx); + memset(&s->grid_attr[py][px], SCREEN_DEFATTR, nx); + memset(&s->grid_colr[py][px], SCREEN_DEFCOLR, nx); +} + +/* Delete characters. */ +void +screen_display_delete_characters(struct screen *s, u_int px, u_int py, u_int nx) +{ + u_int mx; + + px = screen_x(s, px); + py = screen_y(s, py); + + if (!screen_in_x(s, px) || !screen_in_y(s, py)) + fatalx("bad value"); + + if (px + nx > screen_last_x(s)) + nx = screen_last_x(s) - px; + + /* + * Deleting the range from px to px + nx. + * + * - Move sx - (px + nx) from px + nx to px. + * - Clear the range from the last x - (rx - lx) to the last x. + */ + + if (px + nx != screen_last_x(s)) { + mx = screen_last_x(s) - (px + nx); + memmove(&s->grid_data[py][px], &s->grid_data[py][px + nx], mx); + memmove(&s->grid_attr[py][px], &s->grid_attr[py][px + nx], mx); + memmove(&s->grid_colr[py][px], &s->grid_colr[py][px + nx], mx); + } + + memset(&s->grid_data[py][screen_size_x(s) - nx], SCREEN_DEFDATA, nx); + memset(&s->grid_attr[py][screen_size_x(s) - nx], SCREEN_DEFATTR, nx); + memset(&s->grid_colr[py][screen_size_x(s) - nx], SCREEN_DEFCOLR, nx); +} |