X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=gui.c;h=38addd9815cc5bf2775c80278679a1e9c64e872e;hp=8e70dd93b4d3a5d3d7b35a3c7ec65723d7639f24;hb=69a7e7aa11d8bf9b05d6431c57276befbc9b35a3;hpb=7584638594109184f329bead008f1dcdd9030767 diff --git a/gui.c b/gui.c index 8e70dd93..38addd98 100644 --- a/gui.c +++ b/gui.c @@ -109,6 +109,8 @@ static void com_scroll_up(void); static void com_scroll_down(void); static void com_page_up(void); static void com_page_down(void); +static void com_cancel_scrolling(void); +static void com_scroll_top(void); static struct gui_command command_list[] = { { @@ -186,6 +188,16 @@ static struct gui_command command_list[] = { .name = "page_down", .description = "scroll down one page", .handler = com_page_down + }, { + .key = "", + .name = "scroll_top", + .description = "scroll to top of buffer", + .handler = com_scroll_top + }, { + .key = "", + .name = "cancel_scroll", + .description = "deactivate scroll mode", + .handler = com_cancel_scrolling }, { .handler = NULL } @@ -230,6 +242,14 @@ static char *km_keyname(int c) sprintf(buf, ""); return buf; } + if (c == KEY_HOME) { + sprintf(buf, ""); + return buf; + } + if (c == KEY_END) { + sprintf(buf, ""); + return buf; + } if (c < 256 && c > -128 && iscntrl((unsigned char) c)) { if (c < 0) c += 256; @@ -380,11 +400,13 @@ static int draw_top_rbe(unsigned *lines) rbe = ringbuffer_get(bot_win_rb, fvr); if (!rbe) return -1; - /* first rbe might be only partially visible */ - offset = (*lines - bot.lines) * bot.cols; len = strlen(rbe->msg); - if (offset < 0 || len < offset) - return -1; + if (*lines > bot.lines) { + /* first rbe is only partially visible */ + offset = (*lines - bot.lines) * bot.cols; + assert(offset <= len); + } else + offset = 0; wattron(bot.win, COLOR_PAIR(rbe->color)); waddstr(bot.win, rbe->msg + offset); *lines = NUM_LINES(len - offset); @@ -635,14 +657,6 @@ static void init_wins(int top_lines) doupdate(); } -static void check_geometry(void) -{ - if (LINES < theme.lines_min || COLS < theme.cols_min) - msg_n_exit(EXIT_FAILURE, "Error: Terminal (%dx%d) too small" - " (need at least %dx%d)\n", COLS, LINES, - theme.cols_min, theme.lines_min); -} - /* * Print stat item #i to curses window */ @@ -747,53 +761,60 @@ static void clear_all_items(void) } } -static void init_colors(void) +static void init_pair_or_die(short pair, short f, short b) +{ + if (init_pair(pair, f, b) == ERR) + msg_n_exit(EXIT_FAILURE, "fatal: init_pair() failed\n"); +} + +static void init_colors_or_die(void) { int i; if (!has_colors()) - msg_n_exit(EXIT_FAILURE, "Error: No color term\n"); - start_color(); + msg_n_exit(EXIT_FAILURE, "fatal: No color term\n"); + if (start_color() == ERR) + msg_n_exit(EXIT_FAILURE, "fatal: failed to start colors\n"); FOR_EACH_STATUS_ITEM(i) if (theme.data[i].len) - init_pair(i + 1, theme.data[i].fg, theme.data[i].bg); - init_pair(COLOR_STATUSBAR, theme.sb_fg, theme.sb_bg); - init_pair(COLOR_COMMAND, theme.cmd_fg, theme.cmd_bg); - init_pair(COLOR_OUTPUT, theme.output_fg, theme.output_bg); - init_pair(COLOR_MSG, theme.msg_fg, theme.msg_bg); - init_pair(COLOR_ERRMSG, theme.err_msg_fg, theme.err_msg_bg); - init_pair(COLOR_WELCOME, theme.welcome_fg, theme.welcome_bg); - init_pair(COLOR_SEPARATOR, theme.sep_fg, theme.sep_bg); - init_pair(COLOR_TOP, theme.default_fg, theme.default_bg); - init_pair(COLOR_BOT, theme.default_fg, theme.default_bg); + init_pair_or_die(i + 1, theme.data[i].fg, + theme.data[i].bg); + init_pair_or_die(COLOR_STATUSBAR, theme.sb_fg, theme.sb_bg); + init_pair_or_die(COLOR_COMMAND, theme.cmd_fg, theme.cmd_bg); + init_pair_or_die(COLOR_OUTPUT, theme.output_fg, theme.output_bg); + init_pair_or_die(COLOR_MSG, theme.msg_fg, theme.msg_bg); + init_pair_or_die(COLOR_ERRMSG, theme.err_msg_fg, theme.err_msg_bg); + init_pair_or_die(COLOR_WELCOME, theme.welcome_fg, theme.welcome_bg); + init_pair_or_die(COLOR_SEPARATOR, theme.sep_fg, theme.sep_bg); + init_pair_or_die(COLOR_TOP, theme.default_fg, theme.default_bg); + init_pair_or_die(COLOR_BOT, theme.default_fg, theme.default_bg); } -/* - * (re-)initialize the curses library FIXME: Error checking - */ +/* (Re-)initialize the curses library. */ static void init_curses(void) { curses_active = 1; - if (top.win && refresh() == ERR) { /* refesh is really needed */ + if (top.win && refresh() == ERR) /* refesh is really needed */ msg_n_exit(EXIT_FAILURE, "refresh() failed\n"); - } - check_geometry(); + if (LINES < theme.lines_min || COLS < theme.cols_min) + msg_n_exit(EXIT_FAILURE, "Error: Terminal (%dx%d) too small" + " (need at least %dx%d)\n", COLS, LINES, + theme.cols_min, theme.lines_min); curs_set(0); /* make cursor invisible, ignore errors */ -// if (noraw() == ERR); -// msg_n_exit(EXIT_FAILURE, "can not place terminal out of " -// "raw mode\n"); - nonl(); /* tell curses not to do NL->CR/NL on output */ - noecho(); /* don't echo input */ - cbreak(); /* take input chars one at a time, no wait for \n */ - //reset_prog_mode(); - init_colors(); - clear(); + nonl(); /* do not NL->CR/NL on output, always returns OK */ + /* don't echo input */ + if (noecho() == ERR) + msg_n_exit(EXIT_FAILURE, "fatal: noecho() failed\n"); + /* take input chars one at a time, no wait for \n */ + if (cbreak() == ERR) + msg_n_exit(EXIT_FAILURE, "fatal: cbreak() failed\n"); + init_colors_or_die(); + clear(); /* ignore non-fatal errors */ init_wins(theme.top_lines_default); print_all_items(); - noecho(); /* don't echo input */ + // noecho(); /* don't echo input */ } - static void check_sigchld(void) { int ret; @@ -1097,6 +1118,41 @@ static void print_scroll_msg(void) filled - scroll_position, ringbuffer_filled(bot_win_rb)); } +static void com_scroll_top(void) +{ + int i = RINGBUFFER_SIZE - 1; + unsigned lines = 0; + + while (i > 0 && !ringbuffer_get(bot_win_rb, i)) + i--; + /* i is oldest entry */ + for (; lines < bot.lines && i >= 0; i--) { + struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i); + if (!rbe) + break; + lines += NUM_LINES(strlen(rbe->msg)); + } + i++; + if (lines > 0 && scroll_position != i) { + scroll_position = i; + redraw_bot_win(); + print_scroll_msg(); + return; + } + print_in_bar(COLOR_ERRMSG, "top of buffer is shown\n"); +} + +static void com_cancel_scrolling(void) +{ + + if (scroll_position == 0) { + print_in_bar(COLOR_ERRMSG, "bottom of buffer is shown\n"); + return; + } + scroll_position = 0; + redraw_bot_win(); +} + static void com_page_down(void) { unsigned lines = 0; @@ -1228,7 +1284,8 @@ static void com_reread_conf(void) .override = 1, .initialize = 1, .check_required = 0, - .check_ambiguity = 0 + .check_ambiguity = 0, + .print_errors = 0, }; if (!cf) { @@ -1236,8 +1293,11 @@ static void com_reread_conf(void) return; } PARA_INFO_LOG("rereading command line options and config file"); - gui_cmdline_parser(_argc, _argv, &conf); - gui_cmdline_parser_config_file(cf, &conf, ¶ms); + gui_cmdline_parser_ext(_argc, _argv, &conf, ¶ms); + if (gui_cmdline_parser_config_file(cf, &conf, ¶ms) != 0) { + PARA_EMERG_LOG("errors in config file"); + finish(EXIT_FAILURE); + } PARA_NOTICE_LOG("config file reloaded"); if (check_key_map_args() < 0) finish(EXIT_FAILURE); @@ -1394,17 +1454,9 @@ int main(int argc, char *argv[]) _argc = argc; _argv = argv; - if (gui_cmdline_parser(argc, argv, &conf)) { - fprintf(stderr, "parse error while reading command line\n"); + if (gui_cmdline_parser(argc, argv, &conf) != 0) exit(EXIT_FAILURE); - } HANDLE_VERSION_FLAG("gui", conf); - init_theme(0, &theme); - top.lines = theme.top_lines_default; - if (check_key_map_args() < 0) { - fprintf(stderr, "invalid key map\n"); - exit(EXIT_FAILURE); - } cf = configfile_exists(); if (!cf && conf.config_file_given) { fprintf(stderr, "can not read config file %s\n", @@ -1416,15 +1468,19 @@ int main(int argc, char *argv[]) .override = 0, .initialize = 0, .check_required = 0, - .check_ambiguity = 0 + .check_ambiguity = 0, + .print_errors = 1, }; - gui_cmdline_parser_config_file(cf, &conf, ¶ms); + if (gui_cmdline_parser_config_file(cf, &conf, ¶ms) != 0) + exit(EXIT_FAILURE); } loglevel = get_loglevel_by_name(conf.loglevel_arg); if (check_key_map_args() < 0) { - fprintf(stderr, "invalid key map in config file\n"); + fprintf(stderr, "invalid key map\n"); exit(EXIT_FAILURE); } + init_theme_or_die(conf.theme_arg, &theme); + top.lines = theme.top_lines_default; setup_signal_handling(); bot_win_rb = ringbuffer_new(RINGBUFFER_SIZE); initscr(); /* needed only once, always successful */