X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=gui.c;h=9cf950650090cc263b8395c09088f7ad0e3178fd;hb=bf6e508841396f203b9b47552029a90f8709969e;hp=8ec009cc53506ba976d9c60f4c489935259d494e;hpb=2b8250e7d8b4bb34727470ee208fc9b725371bec;p=paraslash.git diff --git a/gui.c b/gui.c index 8ec009cc..9cf95065 100644 --- a/gui.c +++ b/gui.c @@ -34,8 +34,6 @@ static int signal_pipe; static struct gui_window { WINDOW *win; - size_t cols; - size_t lines; } top, bot, sb, in, sep; #define RINGBUFFER_SIZE 512 @@ -45,7 +43,6 @@ struct rb_entry { int color; }; static struct ringbuffer *bot_win_rb; -#define NUM_LINES(len) (1 + (len) / bot.cols) static unsigned scroll_position; @@ -203,6 +200,31 @@ static int find_cmd_byname(char *name) return -1; } +/* + * 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) { @@ -354,7 +376,7 @@ __printf_2_3 static void print_in_bar(int color, const char *fmt,...) 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); } @@ -365,7 +387,7 @@ static void print_status_bar(void) 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); free(tmp); } @@ -376,7 +398,8 @@ static void print_status_bar(void) */ static int first_visible_rbe(unsigned *lines) { - int i; + 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); @@ -384,10 +407,10 @@ static int first_visible_rbe(unsigned *lines) 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; - if (*lines >= bot.lines) + if (*lines >= bot_lines) return i; } return RINGBUFFER_SIZE - 1; @@ -398,7 +421,7 @@ returns number of first visible rbe, *lines is the number of lines drawn. */ 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; @@ -408,9 +431,10 @@ static int draw_top_rbe(unsigned *lines) 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 */ - 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; @@ -430,14 +454,14 @@ static int draw_top_rbe(unsigned *lines) static void redraw_bot_win(void) { unsigned lines; - int i; + 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; - 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++; @@ -564,75 +588,6 @@ __noreturn __printf_2_3 static void die(int exit_code, const char* fmt, ...) exit(exit_code); } -/* - * init all windows - */ -static void init_wins(int 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; - - assume_default_colors(theme.default_fg, theme.default_bg); - if (top.win) { - wresize(top.win, top.lines, top.cols); - mvwin(top.win, top_y, 0); - - wresize(sb.win, sb.lines, sb.cols); - mvwin(sb.win, sb_y, 0); - - wresize(sep.win, sep.lines, sep.cols); - mvwin(sep.win, sep_y, 0); - - wresize(bot.win, bot.lines, bot.cols); - mvwin(bot.win, bot_y, 0); - - wresize(in.win, in.lines, in.cols); - 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); - if (!top.win || !bot.win || !sb.win || !in.win || !sep.win) - die(EXIT_FAILURE, "Error: Cannot create curses windows\n"); - wclear(bot.win); - wclear(sb.win); - wclear(in.win); - scrollok(bot.win, 1); - wattron(sb.win, COLOR_PAIR(COLOR_STATUSBAR)); - wattron(sep.win, COLOR_PAIR(COLOR_SEPARATOR)); - wattron(bot.win, COLOR_PAIR(COLOR_BOT)); - wattron(top.win, COLOR_PAIR(COLOR_TOP)); - nodelay(top.win, 1); - nodelay(bot.win, 1); - nodelay(sb.win, 1); - nodelay(in.win, 0); - - keypad(top.win, 1); - keypad(bot.win, 1); - keypad(sb.win, 1); - keypad(in.win, 1); - } - wmove(sep.win, 0, 0); - whline(sep.win, theme.sep_char, COLS); - wclear(top.win); - //wclear(bot.win); - wnoutrefresh(top.win); - wnoutrefresh(bot.win); - print_status_bar(); - wnoutrefresh(sb.win); - wnoutrefresh(in.win); - wnoutrefresh(sep.win); - doupdate(); -} - /* * Print stat item #i to curses window */ @@ -641,11 +596,12 @@ static void print_stat_item(int 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); - 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); @@ -737,6 +693,72 @@ static void clear_all_items(void) } } +/* + * init all windows + */ +static void init_wins(int top_lines) +{ + int top_y = 0, bot_y = top_lines + 1, sb_y = LINES - 2, + in_y = LINES - 1, sep_y = top_lines; + 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) { + wresize(top.win, top_lines, COLS); + mvwin(top.win, top_y, 0); + + wresize(sb.win, sb_lines, COLS); + mvwin(sb.win, sb_y, 0); + + wresize(sep.win, sep_lines, COLS); + mvwin(sep.win, sep_y, 0); + + wresize(bot.win, bot_lines, COLS); + mvwin(bot.win, bot_y, 0); + + wresize(in.win, in_lines, COLS); + mvwin(in.win, in_y, 0); + } else { + 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); + wclear(sb.win); + wclear(in.win); + scrollok(bot.win, 1); + wattron(sb.win, COLOR_PAIR(COLOR_STATUSBAR)); + wattron(sep.win, COLOR_PAIR(COLOR_SEPARATOR)); + wattron(bot.win, COLOR_PAIR(COLOR_BOT)); + wattron(top.win, COLOR_PAIR(COLOR_TOP)); + nodelay(top.win, 1); + nodelay(bot.win, 1); + nodelay(sb.win, 1); + nodelay(in.win, 0); + + keypad(top.win, 1); + keypad(bot.win, 1); + keypad(sb.win, 1); + keypad(in.win, 1); + } + wmove(sep.win, 0, 0); + whline(sep.win, theme.sep_char, COLS); + wclear(top.win); + print_all_items(); + //wclear(bot.win); + wnoutrefresh(top.win); + wnoutrefresh(bot.win); + print_status_bar(); + wnoutrefresh(sb.win); + wnoutrefresh(in.win); + wnoutrefresh(sep.win); + doupdate(); +} + static void init_pair_or_die(short pair, short f, short b) { if (init_pair(pair, f, b) == ERR) @@ -787,7 +809,6 @@ static void init_curses(void) init_colors_or_die(); clear(); /* ignore non-fatal errors */ init_wins(theme.top_lines_default); - print_all_items(); // noecho(); /* don't echo input */ } @@ -824,36 +845,31 @@ err_out: return 0; } -static int check_key_map_args(void) +static void check_key_map_args_or_die(void) { - char *s; - int i, ret = -1; - char *tmp = NULL, *handler, *arg; + int i; + char *tmp = NULL; for (i = 0; i < conf.key_map_given; ++i) { - s = conf.key_map_arg[i]; - if (!(*s)) - goto out; + char *handler, *arg; + free(tmp); - tmp = para_strdup(s); + tmp = para_strdup(conf.key_map_arg[i]); if (!split_key_map(tmp, &handler, &arg)) - goto out; + break; if (strlen(handler) != 1) - goto out; - if (*handler != 'x' - && *handler != 'd' - && *handler != 'i' - && *handler != 'p') - goto out; + break; + if (*handler != 'x' && *handler != 'd' && *handler != 'i' + && *handler != 'p') + break; if (*handler != 'i') continue; if (find_cmd_byname(arg) < 0) - goto out; + break; } - ret = 0; -out: + if (i != conf.key_map_given) + die(EXIT_FAILURE, "invalid key map: %s\n", conf.key_map_arg[i]); free(tmp); - return ret; } /* @@ -1105,13 +1121,13 @@ static void print_scroll_msg(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 */ - 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; @@ -1141,9 +1157,9 @@ static void com_cancel_scrolling(void) 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; @@ -1161,7 +1177,7 @@ static void com_page_down(void) 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"); @@ -1170,7 +1186,7 @@ static void com_page_up(void) 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(); @@ -1180,7 +1196,7 @@ static void com_page_up(void) static void com_scroll_down(void) { struct rb_entry *rbe; - int rbe_lines; + int rbe_lines, bot_lines = get_num_lines(&bot); if (!scroll_position) { print_in_bar(COLOR_ERRMSG, "bottom of buffer is shown\n"); @@ -1190,7 +1206,7 @@ static void com_scroll_down(void) 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); @@ -1286,8 +1302,7 @@ static void com_reread_conf(void) gui_cmdline_parser_config_file(cf, &conf, ¶ms); init_curses(); PARA_NOTICE_LOG("config file reloaded\n"); - if (check_key_map_args() < 0) - die(EXIT_FAILURE, "invalid key map\n"); + check_key_map_args_or_die(); } static void com_help(void) @@ -1329,23 +1344,25 @@ static void com_help(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; } - init_wins(top.lines - 1); - print_all_items(); + init_wins(top_lines - 1); print_in_bar(COLOR_MSG, "%s", "decreased top window"); } static void com_enlarge_top_win(void) { - if (bot.lines < 3) { + 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; } - init_wins(top.lines + 1); - print_all_items(); + init_wins(top_lines + 1); print_in_bar(COLOR_MSG, "increased top window"); } @@ -1453,8 +1470,7 @@ int main(int argc, char *argv[]) gui_cmdline_parser_config_file(cf, &conf, ¶ms); loglevel = get_loglevel_by_name(conf.loglevel_arg); } - if (check_key_map_args() < 0) - die(EXIT_FAILURE, "invalid key map\n"); + check_key_map_args_or_die(); theme_init(conf.theme_arg, &theme); setup_signal_handling(); bot_win_rb = ringbuffer_new(RINGBUFFER_SIZE);