/*
- * Copyright (C) 1998-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1998-2014 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
static int signal_pipe;
-static struct win_data {
+static struct gui_window {
WINDOW *win;
size_t begx;
size_t begy;
static unsigned scroll_position;
-static int curses_active;
+static bool curses_active;
static pid_t cmd_pid;
-static int command_fds[2];
+static int command_fds[2] = {-1, -1};
static int stat_pipe = -1;
static struct gui_args_info conf;
enum {GETCH_MODE, COMMAND_MODE, EXTERNAL_MODE};
-#define COLOR_STATUSBAR 52
-#define COLOR_COMMAND 53
-#define COLOR_OUTPUT 54
-#define COLOR_MSG 55
-#define COLOR_ERRMSG 56
-#define COLOR_WELCOME 57
-#define COLOR_SEPARATOR 58
-#define COLOR_TOP 59
-#define COLOR_BOT 60
+/**
+ * Codes for various colors.
+ *
+ * Each status item has its own color pair. The ones defined here start at a
+ * higher number so that they do not overlap with these.
+ */
+enum gui_color_pair {
+ COLOR_STATUSBAR = NUM_STAT_ITEMS + 1,
+ COLOR_COMMAND,
+ COLOR_OUTPUT,
+ COLOR_MSG,
+ COLOR_ERRMSG,
+ COLOR_WELCOME,
+ COLOR_SEPARATOR,
+ COLOR_TOP,
+ COLOR_BOT,
+};
struct gui_command {
const char *key;
void (*handler)(void);
};
-struct stat_item {
- char name[MAXLINE];
- char prefix[MAXLINE];
- char postfix[MAXLINE];
- unsigned y;
- unsigned x;
- unsigned len;
- int fg, bg;
- int align;
- char content[MAXLINE];
-};
-
static struct gui_theme theme;
static int _argc;
xvasprintf(&msg, fmt, ap);
va_end(ap);
wmove(in.win, 0, 0);
- align_str(in.win, msg, sb.cols, LEFT);
+ align_str(in.win, msg, in.cols, LEFT);
free(msg);
wrefresh(in.win);
}
/*
* get the number of the oldest rbe that is (partially) visible. On return,
- * lines contains the sum of the number of lines of all visable entries. If the
+ * lines contains the sum of the number of lines of all visible entries. If the
* first one is only partially visible, lines is greater than bot.lines.
*/
static int first_visible_rbe(unsigned *lines)
static int add_output_line(char *line, void *data)
{
int color = *(int *)data? COLOR_ERRMSG : COLOR_OUTPUT;
+
if (!curses_active)
return 1;
rb_add_entry(color, para_strdup(line));
para_install_sighandler(SIGCHLD);
para_install_sighandler(SIGWINCH);
para_install_sighandler(SIGUSR1);
- para_sigaction(SIGHUP, SIG_IGN);
}
/* kill every process in the process group and exit */
if (!curses_active)
return;
def_prog_mode();
- curses_active = 0;
+ curses_active = false;
endwin();
}
/* (Re-)initialize the curses library. */
static void init_curses(void)
{
- curses_active = 1;
- if (top.win && refresh() == ERR) /* refesh is really needed */
+ curses_active = true;
+ if (top.win && refresh() == ERR) /* refresh is really needed */
msg_n_exit(EXIT_FAILURE, "refresh() failed\n");
if (LINES < theme.lines_min || COLS < theme.cols_min)
msg_n_exit(EXIT_FAILURE, "Error: Terminal (%dx%d) too small"
{
int ret;
pid_t pid;
+
reap_next_child:
ret = para_reap_child(&pid);
if (ret <= 0)
for (i = 0; i < conf.key_map_given; ++i) {
s = conf.key_map_arg[i];
if (!(*s))
- goto err_out;
+ goto out;
free(tmp);
tmp = para_strdup(s);
if (!split_key_map(tmp, &handler, &arg))
- goto err_out;
+ goto out;
if (strlen(handler) != 1)
- goto err_out;
+ goto out;
if (*handler != 'x'
&& *handler != 'd'
&& *handler != 'i'
&& *handler != 'p')
- goto err_out;
+ goto out;
if (*handler != 'i')
continue;
if (find_cmd_byname(arg) < 0)
- goto err_out;
+ goto out;
}
ret = 0;
-err_out:
+out:
free(tmp);
return ret;
}
}
return;
case SIGINT:
- PARA_WARNING_LOG("caught SIGINT, reset");
+ PARA_WARNING_LOG("caught SIGINT, reset\n");
/* Nothing to do. SIGINT killed our child which gets noticed
* by do_select and resets everything.
*/
return;
case SIGUSR1:
- PARA_NOTICE_LOG("got SIGUSR1, rereading configuration");
+ PARA_NOTICE_LOG("got SIGUSR1, rereading configuration\n");
com_reread_conf();
return;
case SIGCHLD:
flags[i] = 0;
}
if (ret < 0) {
- PARA_NOTICE_LOG("closing command fd %d: %s",
+ PARA_NOTICE_LOG("closing command fd %d: %s\n",
i, para_strerror(-ret));
close(command_fds[i]);
command_fds[i] = -1;
flags[i] = 0;
+ cbo[i] = 0;
if (command_fds[!i] < 0) /* both fds closed */
return 0;
}
if (cbo[i] == COMMAND_BUF_SIZE - 1) {
- PARA_NOTICE_LOG("discarding overlong line");
+ PARA_NOTICE_LOG("discarding overlong line\n");
cbo[i] = 0;
flags[i] = FELF_DISCARD_FIRST;
}
if (ret < 0)
goto fail;
if (do_select(COMMAND_MODE) >= 0)
- PARA_INFO_LOG("command complete");
+ PARA_INFO_LOG("command complete\n");
else
- PARA_NOTICE_LOG("command aborted");
+ PARA_NOTICE_LOG("command aborted\n");
print_in_bar(COLOR_MSG, " ");
return;
fail:
{
unsigned lines_total, filled = ringbuffer_filled(bot_win_rb);
int first_rbe = first_visible_rbe(&lines_total);
+
print_in_bar(COLOR_MSG, "scrolled view: %d-%d/%d\n", filled - first_rbe,
filled - scroll_position, ringbuffer_filled(bot_win_rb));
}
{
unsigned lines = 0;
int i = scroll_position;
+
while (lines < bot.lines && --i > 0) {
struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
if (!rbe)
*/
static void com_reread_conf(void)
{
- char *cf =configfile_exists();
+ char *cf = configfile_exists();
struct gui_cmdline_parser_params params = {
.override = 1,
.initialize = 1,
};
if (!cf) {
- PARA_WARNING_LOG("there is no configuration to read");
+ PARA_WARNING_LOG("there is no configuration to read\n");
return;
}
- PARA_INFO_LOG("rereading command line options and config file");
+ PARA_INFO_LOG("rereading command line options and config file\n");
gui_cmdline_parser_ext(_argc, _argv, &conf, ¶ms);
+ /*
+ * Despite .print_errors is set to 0, gengetopt will print to stderr
+ * anyway, and exit on errors. So we have to shutdown curses first.
+ */
+ shutdown_curses();
gui_cmdline_parser_config_file(cf, &conf, ¶ms);
- PARA_NOTICE_LOG("config file reloaded");
+ init_curses();
+ PARA_NOTICE_LOG("config file reloaded\n");
if (check_key_map_args() < 0)
finish(EXIT_FAILURE);
}
static void com_shrink_top_win(void)
{
if (top.lines <= theme.top_lines_min) {
- PARA_WARNING_LOG("can not decrease top window");
+ PARA_WARNING_LOG("can not decrease top window\n");
return;
}
init_wins(top.lines - 1);
static void com_enlarge_top_win(void)
{
if (bot.lines < 3) {
- PARA_WARNING_LOG("can not increase top window");
+ PARA_WARNING_LOG("can not increase top window\n");
return;
}
init_wins(top.lines + 1);
/* This seems to be needed twice, why? */
com_refresh();
com_refresh();
- PARA_NOTICE_LOG("new theme: %s", theme.name);
+ PARA_NOTICE_LOG("new theme: %s\n", theme.name);
}
static void com_next_theme(void)
{
int i;
- /* first check user's key bindings */
+ /* first check user-defined key bindings */
for (i = 0; i < conf.key_map_given; ++i) {
char *tmp, *handler, *arg;
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);
setlocale(LC_CTYPE, "");