From: Christian Heller Date: Mon, 26 Aug 2013 00:33:43 +0000 (+0200) Subject: Added new class of errors to windows library to ensure yx_uint16-compatible maximum... X-Git-Tag: tce~1050 X-Git-Url: https://plomlompom.com/repos/%7B%7B%20web_path%20%7D%7D/decks/%7B%7Bdb.prefix%7D%7D/%7B%7Bprefix%7D%7D/templates?a=commitdiff_plain;h=f99786b7ced5d2c79473ce9c57c683f74c706da0;p=plomrogue Added new class of errors to windows library to ensure yx_uint16-compatible maximum size for virtual screen. --- diff --git a/src/windows.c b/src/windows.c index b62bfc5..ca1c5d3 100644 --- a/src/windows.c +++ b/src/windows.c @@ -1,7 +1,7 @@ /* windows.c */ #include "windows.h" -#include /* for uint8_t, uint16_t, uint32_t */ +#include /* for uint8_t, uint16_t, uint32_t, UINT16_MAX */ #include /* for typedefs WINDOW, chtype, wresize(), getmaxx(), */ /* getmaxy(), supbad(), delwin(), mvwaddch(), */ /* mvwaddstr(), newpad(), wnoutrefres(), erase(), */ @@ -13,7 +13,7 @@ /* Fit virtual screen's width to minimum width demanded by current windows' - * geometries. Returns 0 on success, 1 on (pad memory allocation) error. + * geometries. */ static uint8_t refit_pad(struct WinMeta * wmeta); @@ -21,8 +21,6 @@ static uint8_t refit_pad(struct WinMeta * wmeta); /* Update geometry (sizes, positions) of window "w" and its successors in the * window chain. For the positioning algorithm place_win() is used. - * - * update_wins() returns 0 on success, 1 on (pad/window memory alloc.) error. */ static uint8_t update_wins(struct WinMeta * wmeta, struct Win * w); static void place_win(struct WinMeta * wmeta, struct Win * w); @@ -67,13 +65,15 @@ static void shift_win_backward(struct WinMeta * wmeta); static uint8_t refit_pad(struct WinMeta * wmeta) { /* Determine rightmost window column. */ - uint16_t lastwincol = 0; + uint32_t lastwincol = 0; struct Win * w_p = wmeta->_chain_start; while (w_p != 0) { - if (w_p->_start.x + w_p->frame.size.x > lastwincol + 1) + if ((uint32_t) w_p->_start.x + (uint32_t) w_p->frame.size.x + > lastwincol + 1) { - lastwincol = w_p->_start.x + w_p->frame.size.x - 1; + lastwincol = (uint32_t) w_p->_start.x + + (uint32_t) w_p->frame.size.x - 1; } w_p = w_p->_next; } @@ -81,6 +81,10 @@ static uint8_t refit_pad(struct WinMeta * wmeta) /* Only resize the pad if the rightmost window column has changed. */ if (getmaxx(wmeta->padframe.curses_win) != lastwincol) { + if (lastwincol + 2 > UINT16_MAX) /* Abort if pad would grow beyond */ + { /* yx_uint16 confines. */ + return 2; + } return (ERR == wresize(wmeta->padframe.curses_win, getmaxy(wmeta->padframe.curses_win), lastwincol + 2)); @@ -97,18 +101,19 @@ static uint8_t update_wins(struct WinMeta * wmeta, struct Win * w) destroy_win(w); } place_win(wmeta, w); - if (0 != refit_pad(wmeta)) + uint8_t test_refit = refit_pad(wmeta); + if (0 != test_refit) { - return 1; + return test_refit; } - WINDOW * test = subpad(wmeta->padframe.curses_win, - w->frame.size.y, w->frame.size.x, - w->_start.y, w->_start.x); - if (NULL == test) + WINDOW * subpad_test = subpad(wmeta->padframe.curses_win, + w->frame.size.y, w->frame.size.x, + w->_start.y, w->_start.x); + if (NULL == subpad_test) { return 1; } - w->frame.curses_win = test; + w->frame.curses_win = subpad_test; if (0 != w->_next) { return update_wins(wmeta, w->_next); @@ -362,6 +367,11 @@ extern uint8_t init_win_meta(WINDOW * screen, struct WinMeta * wmeta) wmeta->_screen = screen; wmeta->padframe.size.y = getmaxy(screen); wmeta->padframe.size.x = getmaxx(screen); + if ( wmeta->padframe.size.y > UINT16_MAX + || wmeta->padframe.size.x > UINT16_MAX) + { + return 2; + } wmeta->_chain_start = 0; wmeta->_chain_end = 0; wmeta->pad_offset = 0; @@ -448,12 +458,13 @@ extern uint8_t suspend_win(struct WinMeta * wmeta, struct Win * w) { wmeta->active = w->_next; } - if (0 != update_wins(wmeta, w->_next)) /* Positioning of successor */ - { /* windows may be affected / */ - return 1; /* need correction. Note that */ - } /* update_wins() already */ - pad_refitted = 1; /* refits the pad, voiding */ - } /* later need for that. */ + uint8_t test = update_wins(wmeta, w->_next);/* Positioning of */ + if (0 != test) /* successor windows may */ + { /* be affected / need */ + return test; /* correction. Note that */ + } /* update_wins() already */ + pad_refitted = 1; /* refits the pad, voiding*/ + } /* later need for that. */ else { wmeta->_chain_end = w->_prev; diff --git a/src/windows.h b/src/windows.h index ce6d7cb..af84228 100644 --- a/src/windows.h +++ b/src/windows.h @@ -19,11 +19,13 @@ * that thrones over enough space to fit them in; failing that, they are placed * to the right of the window with the rightmost border. * + * Functions that return uint8_t return these error codes: + * 0 - success + * 1 - memory allocation error (of ncurses' pads/windows, or scroll hint texts) + * 2 - activity makes virtual screen grow beyond uint16 height/width confines + * * TODO: Think up a more intuitive window positioning algorithm or at least make * the chain that windows are positioned by visible. - * - * TODO: Ensure there are only windows as many / as big as fit into the maximum - * size of the virtual screen. */ #ifndef WINDOWS_H @@ -83,8 +85,6 @@ struct WinMeta * emptiness is marked by WinMeta.chain_start=0. Other struct values are also * initialized 0, except for the virtual screen (terminal screen height, width = * 1) and its terminal-sized frame. - * - * Returns 0 on success, 1 on (ncurses newpad() memory allocation) error. */ extern uint8_t init_win_meta(WINDOW * screen, struct WinMeta * wmeta); @@ -112,8 +112,6 @@ extern struct Win init_win(struct WinMeta * wmeta, char * title, * Appended windows will become active. Suspended active windows will move the * active window selection to their successor in the window chain or, failing * that, their predecessor; if no window remains, none will be active. - * - * Return 0 on success, and 1 on (ncurses window/pad memory allocation) error. */ extern uint8_t append_win(struct WinMeta * wmeta, struct Win * w); extern uint8_t suspend_win(struct WinMeta * wmeta, struct Win * w); @@ -133,8 +131,6 @@ extern void reset_pad_offset(struct WinMeta * wmeta, uint16_t new_offset); /* Apply new size "size" to the active window, but only if it provides for at * least one cell width/height and is in height at least one cell smaller than * the screen's vertical height (to provide space for the title bar). - * - * Returns 0 on success, 1 on (ncurses window/pad memory allocation) error. */ extern uint8_t resize_active_win(struct WinMeta * wmeta, struct yx_uint16 size); @@ -149,8 +145,6 @@ extern void cycle_active_win(struct WinMeta * wmeta, char dir); /* Move active window forwards (set dir="f") or backwards (set dir="b"). Wrap * around in the window chain if start / end of it is met. - * - * Returns 0 on success, 1 on (ncurses window/pad memory allocation) error. */ extern uint8_t shift_active_win(struct WinMeta * wmeta, char dir); @@ -159,8 +153,6 @@ extern uint8_t shift_active_win(struct WinMeta * wmeta, char dir); /* Draw virtual screen including all windows. Also add scroll hints (see comment * on draw_scroll_hint()) for where the edges of the terminal screen hit * non-edges of and inside the virtual screen. Then update the terminal screen. - * - * Returns 0 on success, 1 on error (of scroll hint text memory allocation). */ extern uint8_t draw_all_wins(struct WinMeta * wmeta); @@ -171,8 +163,6 @@ extern uint8_t draw_all_wins(struct WinMeta * wmeta); * a column or a row dependent on "dir" being *either* "<"/">" *or* something * else). It will consist of a line of "dir" symbols bracketing a descriptive * text stating the number of rows/columns further available beyond the hint. - * - * Return 0 on success, and 1 on error (of scroll hint text memory allocation). */ extern uint8_t draw_scroll_hint(struct Frame * frame, uint16_t pos, uint32_t dist, char dir);