summaryrefslogtreecommitdiff
path: root/util-linux/more.c
blob: 65409999b09d8aba7f1813773cb1ba9d13b18b2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "internal.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#define BB_MORE_TERM

#ifdef BB_MORE_TERM
	#include <termios.h>
	#include <signal.h>

	FILE *cin;
	struct termios initial_settings, new_settings;

	void gotsig(int sig) { 
		tcsetattr(fileno(cin), TCSANOW, &initial_settings);
		exit(0);
	}
#endif

const char	more_usage[] = "more [file]\n"
"\n"
"\tDisplays a file, one page at a time.\n"
"\tIf there are no arguments, the standard input is displayed.\n";

extern int
more_fn(const struct FileInfo * i)
{
	FILE *	f = stdin;
	int	c;
	int	lines = 0, tlines = 0;
	int	next_page = 0;
	int	rows = 24, cols = 79;
#ifdef BB_MORE_TERM
	long sizeb = 0;
	struct stat st;	
	struct winsize win;
#endif
	
	if ( i ) {
		if (! (f = fopen(i->source, "r") )) {
			name_and_error(i->source);
			return 1;
		}
		fstat(fileno(f), &st);
		sizeb = st.st_size / 100;
	}
		
#ifdef BB_MORE_TERM
	cin = fopen("/dev/tty", "r");
	tcgetattr(fileno(cin),&initial_settings);
	new_settings = initial_settings;
	new_settings.c_lflag &= ~ICANON;
	new_settings.c_lflag &= ~ECHO;
	tcsetattr(fileno(cin), TCSANOW, &new_settings);
	
	(void) signal(SIGINT, gotsig);

	ioctl(STDOUT_FILENO, TIOCGWINSZ, &win);
	if (win.ws_row > 4)	rows = win.ws_row - 2;
	if (win.ws_col > 0)	cols = win.ws_col - 1;


#endif

	while ( (c = getc(f)) != EOF ) {
		if ( next_page ) {
			char	garbage;
			int	len;
			tlines += lines;
			lines = 0;
			next_page = 0;		//Percentage is based on bytes, not lines.
			if ( i && i->source )	//It is not very acurate, but still useful.
				len = printf("%s - %%%2ld - line: %d", i->source, (ftell(f) - sizeb - sizeb) / sizeb, tlines);
			else
				len = printf("line: %d", tlines);
				
			fflush(stdout);
#ifndef BB_MORE_TERM		
			read(2, &garbage, 1);
#else				
			do {
				fread(&garbage, 1, 1, cin);	
			} while ((garbage != ' ') && (garbage != '\n'));
			
			if (garbage == '\n') {
				lines = rows;
				tlines -= rows;
			}					
			garbage = 0;				
			//clear line, since tabs don't overwrite.
			while(len-- > 0)	putchar('\b');
			while(len++ < cols)	putchar(' ');
			while(len-- > 0)	putchar('\b');
			fflush(stdout);
#endif								
		}
		putchar(c);
		if ( c == '\n' && ++lines == (rows + 1) )
			next_page = 1;
	}
	if ( f != stdin )
		fclose(f);
#ifdef BB_MORE_TERM
	gotsig(0);
#endif	
	return 0;
}