Пример #1
0
static void flag_change(void)
{
	int keypress;

	clear_line();
	bb_putchar('-');
	keypress = less_getch(1);

	switch (keypress) {
	case 'M':
		option_mask32 ^= FLAG_M;
		break;
	case 'm':
		option_mask32 ^= FLAG_m;
		break;
	case 'E':
		option_mask32 ^= FLAG_E;
		break;
	case '~':
		option_mask32 ^= FLAG_TILDE;
		break;
	case 'S':
		option_mask32 ^= FLAG_S;
		buffer_fill_and_print();
		break;
#if ENABLE_FEATURE_LESS_LINENUMS
	case 'N':
		option_mask32 ^= FLAG_N;
		re_wrap();
		buffer_fill_and_print();
		break;
#endif
	}
}
Пример #2
0
static void buffer_up(int nlines)
{
	cur_fline -= nlines;
	if (cur_fline < 0) cur_fline = 0;
	read_lines();
	buffer_fill_and_print();
}
Пример #3
0
/* Move the buffer up and down in the file in order to scroll */
static void buffer_down(int nlines)
{
	cur_fline += nlines;
	read_lines();
	cap_cur_fline(nlines);
	buffer_fill_and_print();
}
Пример #4
0
static void buffer_line(int linenum)
{
	if (linenum < 0)
		linenum = 0;
	cur_fline = linenum;
	read_lines();
	if (linenum + max_displayed_line > max_fline)
		linenum = max_fline - max_displayed_line + TILDES;
	if (linenum < 0)
		linenum = 0;
	cur_fline = linenum;
	buffer_fill_and_print();
}
Пример #5
0
/* Reinitialize everything for a new file - free the memory and start over */
static void reinitialize(void)
{
	unsigned i;

	if (flines) {
		for (i = 0; i <= max_fline; i++)
			free(MEMPTR(flines[i]));
		free(flines);
		flines = NULL;
	}

	max_fline = -1;
	cur_fline = 0;
	max_lineno = 0;
	open_file_and_read_lines();
	buffer_fill_and_print();
}
Пример #6
0
static ssize_t getch_nowait(char* input, int sz)
{
    ssize_t rd;
    struct pollfd pfd[2];

    pfd[0].fd = STDIN_FILENO;
    pfd[0].events = POLLIN;
    pfd[1].fd = kbd_fd;
    pfd[1].events = POLLIN;
again:
    tcsetattr(kbd_fd, TCSANOW, &term_less);
    /* NB: select/poll returns whenever read will not block. Therefore:
     * if eof is reached, select/poll will return immediately
     * because read will immediately return 0 bytes.
     * Even if select/poll says that input is available, read CAN block
     * (switch fd into O_NONBLOCK'ed mode to avoid it)
     */
    rd = 1;
    if (max_fline <= cur_fline + max_displayed_line
            && eof_error > 0 /* did NOT reach eof yet */
       ) {
        /* We are interested in stdin */
        rd = 0;
    }
    /* position cursor if line input is done */
    if (less_gets_pos >= 0)
        move_cursor(max_displayed_line + 2, less_gets_pos + 1);
    fflush(stdout);
    safe_poll(pfd + rd, 2 - rd, -1);

    input[0] = '\0';
    rd = safe_read(kbd_fd, input, sz); /* NB: kbd_fd is in O_NONBLOCK mode */
    if (rd < 0 && errno == EAGAIN) {
        /* No keyboard input -> we have input on stdin! */
        read_lines();
        buffer_fill_and_print();
        goto again;
    }
    set_tty_cooked();
    return rd;
}
Пример #7
0
static int getch_nowait(void)
{
	int rd;
	struct pollfd pfd[2];

	pfd[0].fd = STDIN_FILENO;
	pfd[0].events = POLLIN;
	pfd[1].fd = kbd_fd;
	pfd[1].events = POLLIN;
 again:
	tcsetattr(kbd_fd, TCSANOW, &term_less);
	/* NB: select/poll returns whenever read will not block. Therefore:
	 * if eof is reached, select/poll will return immediately
	 * because read will immediately return 0 bytes.
	 * Even if select/poll says that input is available, read CAN block
	 * (switch fd into O_NONBLOCK'ed mode to avoid it)
	 */
	rd = 1;
	/* Are we interested in stdin? */
//TODO: reuse code for determining this
	if (!(option_mask32 & FLAG_S)
	   ? !(max_fline > cur_fline + max_displayed_line)
	   : !(max_fline >= cur_fline
	       && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
	) {
		if (eof_error > 0) /* did NOT reach eof yet */
			rd = 0; /* yes, we are interested in stdin */
	}
	/* Position cursor if line input is done */
	if (less_gets_pos >= 0)
		move_cursor(max_displayed_line + 2, less_gets_pos + 1);
	fflush_all();

	if (kbd_input[0] == 0) { /* if nothing is buffered */
#if ENABLE_FEATURE_LESS_WINCH
		while (1) {
			int r;
			/* NB: SIGWINCH interrupts poll() */
			r = poll(pfd + rd, 2 - rd, -1);
			if (/*r < 0 && errno == EINTR &&*/ winch_counter)
				return '\\'; /* anything which has no defined function */
			if (r) break;
		}
#else
		safe_poll(pfd + rd, 2 - rd, -1);
#endif
	}

	/* We have kbd_fd in O_NONBLOCK mode, read inside read_key()
	 * would not block even if there is no input available */
	rd = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2);
	if (rd == -1) {
		if (errno == EAGAIN) {
			/* No keyboard input available. Since poll() did return,
			 * we should have input on stdin */
			read_lines();
			buffer_fill_and_print();
			goto again;
		}
		/* EOF/error (ssh session got killed etc) */
		less_exit(0);
	}
	set_tty_cooked();
	return rd;
}
Пример #8
0
int less_main(int argc, char **argv)
{
	int keypress;

	INIT_G();

	/* TODO: -x: do not interpret backspace, -xx: tab also */
	/* -xxx: newline also */
	/* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */
	getopt32(argv, "EMmN~I" IF_FEATURE_LESS_DASHCMD("S"));
	argc -= optind;
	argv += optind;
	num_files = argc;
	files = argv;

	/* Another popular pager, most, detects when stdout
	 * is not a tty and turns into cat. This makes sense. */
	if (!isatty(STDOUT_FILENO))
		return bb_cat(argv);

	if (!num_files) {
		if (isatty(STDIN_FILENO)) {
			/* Just "less"? No args and no redirection? */
			bb_error_msg("missing filename");
			bb_show_usage();
		}
	} else {
		filename = xstrdup(files[0]);
	}

	if (option_mask32 & FLAG_TILDE)
		empty_line_marker = "";

	kbd_fd = open(CURRENT_TTY, O_RDONLY);
	if (kbd_fd < 0)
		return bb_cat(argv);
	ndelay_on(kbd_fd);

	tcgetattr(kbd_fd, &term_orig);
	term_less = term_orig;
	term_less.c_lflag &= ~(ICANON | ECHO);
	term_less.c_iflag &= ~(IXON | ICRNL);
	/*term_less.c_oflag &= ~ONLCR;*/
	term_less.c_cc[VMIN] = 1;
	term_less.c_cc[VTIME] = 0;

	get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
	/* 20: two tabstops + 4 */
	if (width < 20 || max_displayed_line < 3)
		return bb_cat(argv);
	max_displayed_line -= 2;

	/* We want to restore term_orig on exit */
	bb_signals(BB_FATAL_SIGS, sig_catcher);
#if ENABLE_FEATURE_LESS_WINCH
	signal(SIGWINCH, sigwinch_handler);
#endif

	buffer = xmalloc((max_displayed_line+1) * sizeof(char *));
	reinitialize();
	while (1) {
#if ENABLE_FEATURE_LESS_WINCH
		while (WINCH_COUNTER) {
 again:
			winch_counter--;
			get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
			/* 20: two tabstops + 4 */
			if (width < 20)
				width = 20;
			if (max_displayed_line < 3)
				max_displayed_line = 3;
			max_displayed_line -= 2;
			free(buffer);
			buffer = xmalloc((max_displayed_line+1) * sizeof(char *));
			/* Avoid re-wrap and/or redraw if we already know
			 * we need to do it again. These ops are expensive */
			if (WINCH_COUNTER)
				goto again;
			re_wrap();
			if (WINCH_COUNTER)
				goto again;
			buffer_fill_and_print();
			/* This took some time. Loop back and check,
			 * were there another SIGWINCH? */
		}
#endif
		keypress = less_getch(-1); /* -1: do not position cursor */
		keypress_process(keypress);
	}
}