The curses library provides the getmaxyx() macro to obtain the window
geometry. It's better to use these instead of storing the number of
lines and columns in the gui_window structure because with getmaxyx()
there is no risk to have stale values gui_window structure.
While the ncurses implementation provides getmaxx() and getmaxy()
to get only the number of lines or columns, respectively, only
getmaxyx() is described in the XSI Curses standard. Hence we provide
our own version of the former two functions. These call getmaxyx()
and return one of the two numbers.
With the ->cols and ->lines fields of struct gui_window gone, all
callers had to be adjusted to use either getmaxyx() or one of the
new functions.
static struct gui_window {
WINDOW *win;
static struct gui_window {
WINDOW *win;
- size_t cols;
- size_t lines;
} top, bot, sb, in, sep;
#define RINGBUFFER_SIZE 512
} top, bot, sb, in, sep;
#define RINGBUFFER_SIZE 512
int color;
};
static struct ringbuffer *bot_win_rb;
int color;
};
static struct ringbuffer *bot_win_rb;
-#define NUM_LINES(len) (1 + (len) / bot.cols)
static unsigned scroll_position;
static unsigned scroll_position;
+/*
+ * Even though ncurses provides getmaxx and getmaxy, these functions/macros are
+ * not described in the XSI Curses standard.
+ */
+static int get_num_lines(struct gui_window *w)
+{
+ int lines;
+ __a_unused int cols; /* avoid "set but not used" warnings */
+
+ getmaxyx(w->win, lines, cols);
+ return lines;
+}
+
+static int get_num_cols(struct gui_window *w)
+{
+ __a_unused int lines; /* avoid "set but not used" warnings */
+ int cols;
+
+ getmaxyx(w->win, lines, cols);
+ return cols;
+}
+
+/** Number of lines of the window are occupied by an output line. */
+#define NUM_LINES(len) (1 + (len) / get_num_cols(&bot))
+
/* isendwin() returns false before initscr() was called */
static bool curses_active(void)
{
/* isendwin() returns false before initscr() was called */
static bool curses_active(void)
{
xvasprintf(&msg, fmt, ap);
va_end(ap);
wmove(in.win, 0, 0);
xvasprintf(&msg, fmt, ap);
va_end(ap);
wmove(in.win, 0, 0);
- align_str(in.win, msg, in.cols, LEFT);
+ align_str(in.win, msg, get_num_cols(&in), LEFT);
free(msg);
wrefresh(in.win);
}
free(msg);
wrefresh(in.win);
}
tmp = para_strdup("para_gui " PACKAGE_VERSION " (hit ? for help)");
wmove(sb.win, 0, 0);
tmp = para_strdup("para_gui " PACKAGE_VERSION " (hit ? for help)");
wmove(sb.win, 0, 0);
- align_str(sb.win, tmp, sb.cols, CENTER);
+ align_str(sb.win, tmp, get_num_cols(&sb), CENTER);
*/
static int first_visible_rbe(unsigned *lines)
{
*/
static int first_visible_rbe(unsigned *lines)
{
+ int i, bot_lines = get_num_lines(&bot);
+
*lines = 0;
for (i = scroll_position; i < RINGBUFFER_SIZE; i++) {
struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
*lines = 0;
for (i = scroll_position; i < RINGBUFFER_SIZE; i++) {
struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
if (!rbe)
return i - 1;
rbe_lines = NUM_LINES(rbe->len);
if (!rbe)
return i - 1;
rbe_lines = NUM_LINES(rbe->len);
- if (rbe_lines > bot.lines)
+ if (rbe_lines > bot_lines)
return -1;
*lines += rbe_lines;
return -1;
*lines += rbe_lines;
- if (*lines >= bot.lines)
+ if (*lines >= bot_lines)
return i;
}
return RINGBUFFER_SIZE - 1;
return i;
}
return RINGBUFFER_SIZE - 1;
*/
static int draw_top_rbe(unsigned *lines)
{
*/
static int draw_top_rbe(unsigned *lines)
{
- int ret, fvr = first_visible_rbe(lines);
+ int bot_cols, bot_lines, ret, fvr = first_visible_rbe(lines);
struct rb_entry *rbe;
size_t bytes_to_skip, cells_to_skip, width;
struct rb_entry *rbe;
size_t bytes_to_skip, cells_to_skip, width;
rbe = ringbuffer_get(bot_win_rb, fvr);
if (!rbe)
return -1;
rbe = ringbuffer_get(bot_win_rb, fvr);
if (!rbe)
return -1;
- if (*lines > bot.lines) {
+ getmaxyx(bot.win, bot_lines, bot_cols);
+ if (*lines > bot_lines) {
/* rbe is partially visible multi-line */
/* rbe is partially visible multi-line */
- cells_to_skip = (*lines - bot.lines) * bot.cols;
+ cells_to_skip = (*lines - bot_lines) * bot_cols;
ret = skip_cells(rbe->msg, cells_to_skip, &bytes_to_skip);
if (ret < 0)
return ret;
ret = skip_cells(rbe->msg, cells_to_skip, &bytes_to_skip);
if (ret < 0)
return ret;
static void redraw_bot_win(void)
{
unsigned lines;
static void redraw_bot_win(void)
{
unsigned lines;
+ int i, bot_lines = get_num_lines(&bot);
wmove(bot.win, 0, 0);
wclear(bot.win);
i = draw_top_rbe(&lines);
if (i <= 0)
goto out;
wmove(bot.win, 0, 0);
wclear(bot.win);
i = draw_top_rbe(&lines);
if (i <= 0)
goto out;
- while (i > 0 && lines < bot.lines) {
+ while (i > 0 && lines < bot_lines) {
struct rb_entry *rbe = ringbuffer_get(bot_win_rb, --i);
if (!rbe) {
lines++;
struct rb_entry *rbe = ringbuffer_get(bot_win_rb, --i);
if (!rbe) {
lines++;
char *tmp;
struct stat_item_data d = theme.data[i];
char *c = stat_content[i];
char *tmp;
struct stat_item_data d = theme.data[i];
char *c = stat_content[i];
+ int top_lines = get_num_lines(&top);
if (!curses_active() || !d.len || !c)
return;
tmp = make_message("%s%s%s", d.prefix, c, d.postfix);
if (!curses_active() || !d.len || !c)
return;
tmp = make_message("%s%s%s", d.prefix, c, d.postfix);
- wmove(top.win, d.y * top.lines / 100, d.x * COLS / 100);
+ wmove(top.win, d.y * top_lines / 100, d.x * COLS / 100);
wrefresh(top.win);
wattron(top.win, COLOR_PAIR(i + 1));
align_str(top.win, tmp, d.len * COLS / 100, d.align);
wrefresh(top.win);
wattron(top.win, COLOR_PAIR(i + 1));
align_str(top.win, tmp, d.len * COLS / 100, d.align);
{
int top_y = 0, bot_y = top_lines + 1, sb_y = LINES - 2,
in_y = LINES - 1, sep_y = top_lines;
{
int top_y = 0, bot_y = top_lines + 1, sb_y = LINES - 2,
in_y = LINES - 1, sep_y = top_lines;
-
- top.lines = top_lines;
- bot.lines = LINES - top.lines - 3;
- sb.lines = in.lines = sep.lines = 1;
-
- top.cols = bot.cols = sb.cols = in.cols = sep.cols = COLS;
+ int bot_lines = LINES - top_lines - 3, sb_lines = 1, in_lines = 1,
+ sep_lines = 1;
assume_default_colors(theme.default_fg, theme.default_bg);
if (top.win) {
assume_default_colors(theme.default_fg, theme.default_bg);
if (top.win) {
- wresize(top.win, top.lines, top.cols);
+ wresize(top.win, top_lines, COLS);
mvwin(top.win, top_y, 0);
mvwin(top.win, top_y, 0);
- wresize(sb.win, sb.lines, sb.cols);
+ wresize(sb.win, sb_lines, COLS);
- wresize(sep.win, sep.lines, sep.cols);
+ wresize(sep.win, sep_lines, COLS);
mvwin(sep.win, sep_y, 0);
mvwin(sep.win, sep_y, 0);
- wresize(bot.win, bot.lines, bot.cols);
+ wresize(bot.win, bot_lines, COLS);
mvwin(bot.win, bot_y, 0);
mvwin(bot.win, bot_y, 0);
- wresize(in.win, in.lines, in.cols);
+ wresize(in.win, in_lines, COLS);
mvwin(in.win, in_y, 0);
} else {
mvwin(in.win, in_y, 0);
} else {
- sep.win = newwin(sep.lines, sep.cols, sep_y, 0);
- top.win = newwin(top.lines, top.cols, top_y, 0);
- bot.win = newwin(bot.lines, bot.cols, bot_y, 0);
- sb.win = newwin(sb.lines, sb.cols, sb_y, 0);
- in.win = newwin(in.lines, in.cols, in_y, 0);
+ sep.win = newwin(sep_lines, COLS, sep_y, 0);
+ top.win = newwin(top_lines, COLS, top_y, 0);
+ bot.win = newwin(bot_lines, COLS, bot_y, 0);
+ sb.win = newwin(sb_lines, COLS, sb_y, 0);
+ in.win = newwin(in_lines, COLS, in_y, 0);
if (!top.win || !bot.win || !sb.win || !in.win || !sep.win)
die(EXIT_FAILURE, "Error: Cannot create curses windows\n");
wclear(bot.win);
if (!top.win || !bot.win || !sb.win || !in.win || !sep.win)
die(EXIT_FAILURE, "Error: Cannot create curses windows\n");
wclear(bot.win);
static void com_scroll_top(void)
{
static void com_scroll_top(void)
{
- int i = RINGBUFFER_SIZE - 1;
+ int i = RINGBUFFER_SIZE - 1, bot_lines = get_num_lines(&bot);
unsigned lines = 0;
while (i > 0 && !ringbuffer_get(bot_win_rb, i))
i--;
/* i is oldest entry */
unsigned lines = 0;
while (i > 0 && !ringbuffer_get(bot_win_rb, i))
i--;
/* i is oldest entry */
- for (; lines < bot.lines && i >= 0; i--) {
+ for (; lines < bot_lines && i >= 0; i--) {
struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
if (!rbe)
break;
struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
if (!rbe)
break;
static void com_page_down(void)
{
unsigned lines = 0;
static void com_page_down(void)
{
unsigned lines = 0;
- int i = scroll_position;
+ int i = scroll_position, bot_lines = get_num_lines(&bot);
- while (lines < bot.lines && --i > 0) {
+ while (lines < bot_lines && --i > 0) {
struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
if (!rbe)
break;
struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
if (!rbe)
break;
static void com_page_up(void)
{
unsigned lines;
static void com_page_up(void)
{
unsigned lines;
- int fvr = first_visible_rbe(&lines);
+ int fvr = first_visible_rbe(&lines), bot_lines = get_num_lines(&bot);
if (fvr < 0 || fvr + 1 >= ringbuffer_filled(bot_win_rb)) {
print_in_bar(COLOR_ERRMSG, "top of buffer is shown\n");
if (fvr < 0 || fvr + 1 >= ringbuffer_filled(bot_win_rb)) {
print_in_bar(COLOR_ERRMSG, "top of buffer is shown\n");
scroll_position = fvr + 1;
for (; scroll_position > 0; scroll_position--) {
first_visible_rbe(&lines);
scroll_position = fvr + 1;
for (; scroll_position > 0; scroll_position--) {
first_visible_rbe(&lines);
- if (lines == bot.lines)
+ if (lines == bot_lines)
break;
}
redraw_bot_win();
break;
}
redraw_bot_win();
static void com_scroll_down(void)
{
struct rb_entry *rbe;
static void com_scroll_down(void)
{
struct rb_entry *rbe;
+ int rbe_lines, bot_lines = get_num_lines(&bot);
if (!scroll_position) {
print_in_bar(COLOR_ERRMSG, "bottom of buffer is shown\n");
if (!scroll_position) {
print_in_bar(COLOR_ERRMSG, "bottom of buffer is shown\n");
rbe = ringbuffer_get(bot_win_rb, scroll_position);
rbe_lines = NUM_LINES(rbe->len);
wscrl(bot.win, rbe_lines);
rbe = ringbuffer_get(bot_win_rb, scroll_position);
rbe_lines = NUM_LINES(rbe->len);
wscrl(bot.win, rbe_lines);
- wmove(bot.win, bot.lines - rbe_lines, 0);
+ wmove(bot.win, bot_lines - rbe_lines, 0);
wattron(bot.win, COLOR_PAIR(rbe->color));
waddstr(bot.win, rbe->msg);
wrefresh(bot.win);
wattron(bot.win, COLOR_PAIR(rbe->color));
waddstr(bot.win, rbe->msg);
wrefresh(bot.win);
static void com_shrink_top_win(void)
{
static void com_shrink_top_win(void)
{
- if (top.lines <= theme.top_lines_min) {
+ int top_lines = get_num_lines(&top);
+
+ if (top_lines <= theme.top_lines_min) {
PARA_WARNING_LOG("can not decrease top window\n");
return;
}
PARA_WARNING_LOG("can not decrease top window\n");
return;
}
- init_wins(top.lines - 1);
+ init_wins(top_lines - 1);
print_in_bar(COLOR_MSG, "%s", "decreased top window");
}
static void com_enlarge_top_win(void)
{
print_in_bar(COLOR_MSG, "%s", "decreased top window");
}
static void com_enlarge_top_win(void)
{
+ int top_lines = get_num_lines(&top), bot_lines = get_num_lines(&bot);
+
+ if (bot_lines < 3) {
PARA_WARNING_LOG("can not increase top window\n");
return;
}
PARA_WARNING_LOG("can not increase top window\n");
return;
}
- init_wins(top.lines + 1);
+ init_wins(top_lines + 1);
print_in_bar(COLOR_MSG, "increased top window");
}
print_in_bar(COLOR_MSG, "increased top window");
}