aboutsummaryrefslogtreecommitdiff
path: root/toys/pending/more.c
blob: 78eb4e9c5a0e898877f221a057cb8c5f30c1a965 (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
111
112
113
114
115
116
117
118
119
120
121
/* more.c - View FILE (or stdin) one screenful at a time.
 *
 * Copyright 2013 Bilal Qureshi <bilal.jmi@gmail.com>
 *
 * No Standard

USE_MORE(NEWTOY(more, NULL, TOYFLAG_USR|TOYFLAG_BIN))

config MORE
  bool "more"
  default n
  help
    Usage: more [FILE]...

    View FILE (or stdin) one screenful at a time.
*/

#define FOR_more
#include "toys.h"
#include <signal.h>

GLOBALS(
  struct termios inf;
  int cin_fd;
)

static void signal_handler(int sig)
{
  tcsetattr(TT.cin_fd, TCSANOW, &TT.inf);
  xputc('\n');
  signal(sig, SIG_DFL);
  raise(sig);
  _exit(sig | 128);
}

static void do_cat_operation(int fd, char *name)
{
  char *buf = NULL;
  
  if(toys.optc > 1) printf(":::::::::::::::::::::::\n"
      "%s\n:::::::::::::::::::::::\n",name);
  for (; (buf = get_line(fd)); free(buf)) printf("%s\n", buf);
}

void more_main()
{
  int ch, lines, input_key = 0, disp_more, more_msg_len;
  unsigned rows = 24, cols = 80;
  struct stat st;  
  struct termios newf;
  FILE *fp, *cin;

  if (!isatty(STDOUT_FILENO) || !(cin = fopen("/dev/tty", "r"))) {
    loopfiles(toys.optargs, do_cat_operation);
    toys.exitval = 0;
    return;
  }

  TT.cin_fd = fileno(cin);
  tcgetattr(TT.cin_fd,&TT.inf);
  //Prepare terminal for input
  memcpy(&newf, &TT.inf, sizeof(struct termios));
  newf.c_lflag &= ~(ICANON | ECHO);
  newf.c_cc[VMIN] = 1;
  newf.c_cc[VTIME] = 0;
  tcsetattr(TT.cin_fd, TCSANOW, &newf);

  sigatexit(signal_handler);

  do {
    fp = stdin;
    if (*toys.optargs && !(fp = fopen(*toys.optargs, "r"))) {
        perror_msg("'%s'", *toys.optargs);
        continue;
    }
    st.st_size = disp_more = more_msg_len = lines = 0;
    fstat(fileno(fp), &st);
    terminal_size(&cols, &rows);
    rows--;
    if(toys.optc > 1) {
      printf(":::::::::::::::::::::::\n"
          "%s\n:::::::::::::::::::::::\n",*toys.optargs);
      rows -= 3;
    }

    while ((ch = getc(fp)) != EOF) {
      if (input_key != 'r' && disp_more) {
        more_msg_len = printf("--More-- ");
        if (st.st_size) 
          more_msg_len += printf("(%d%% of %lld bytes)",
              (int) (100 * ( (double) ftell(fp) / (double) st.st_size)), 
              st.st_size);
        fflush(NULL);

        while (1) {
          input_key = getc(cin);
          input_key = tolower(input_key);
          printf("\r%*s\r", more_msg_len, ""); // Remove previous msg
          if (input_key == ' ' || input_key == '\n' || input_key == 'q' 
              || input_key == 'r') break;
          more_msg_len = printf("(Enter:Next line Space:Next page Q:Quit R:Show the rest)");
        }
        more_msg_len = lines = disp_more = 0;
        if (input_key == 'q') goto stop; 
        terminal_size(&cols, &rows);
        rows--;
      }

      if (ch == '\n') 
        if (++lines >= rows || input_key == '\n') disp_more = 1;
      putchar(ch);
    }
    fclose(fp);
    fflush(NULL);
  } while (*toys.optargs && *++toys.optargs);

stop:
  tcsetattr(TT.cin_fd, TCSANOW, &TT.inf);
  fclose(cin);
  toys.exitval = 0;
}