//Write a C or C++ program that displays a text file on the screen 20 lines at a time.
//The input file name should be given as a command line argument. The program should
//display the next 20 lines after N has been typed, or display previous 20 lines after P
//has been entered (this is an elementary version of the more utility).
#include <stdio.h> //include common libraries
#include <stdlib.h>
#if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__) //incluce libray useful for windows
#define WIN
#define CLEAR() system("cls") //command to clear the screen in windows
#include <windows.h>
#else
#include <termios.h> //include library useful for linux
#include <sys/ioctl.h>
#include <unistd.h>
#define CLEAR() system("clear") //command to clear the screen in linux
#endif
#include <math.h> //for abs()...used later in the program
void Read_File(char *c, int max, FILE * ptr, int N); //prototype function
int getMaxX(void) //function computing the length of the console screen
{
#ifdef WIN
int maxX;
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
{
maxX = (int) csbi.dwSize.X;
if (maxX < 80)
maxX = 80;
}
else
maxX = 0;
return maxX;
#else
struct winsize size;
if (ioctl(STDIN_FILENO,TIOCGWINSZ, (char*) &size)<0)
return 0;
else
return size.ws_col;
#endif
}
int getMaxY(void) //function computing the width of the console screen
{ //It won't be used in the program , but I thought It could be useful
#ifdef WIN
int maxY;
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
{
maxY = (int) csbi.dwSize.Y;
}
else
maxY = 0;
return maxY;
#else
struct winsize size;
if (ioctl(STDIN_FILENO,TIOCGWINSZ, (char*) &size)<0)
return 0;
else
return size.ws_row;
#endif
}
int main(int argc, char **argv) { //main function with the arguments necessary for the command line
char *c; //string of character for my function fgets
FILE *cfptr; //pointer to FILE
int max; //variable that equals to the return value of getMaxX() which is the lenght of the console screen
max = getMaxX();
cfptr = fopen(*(argv +1), "r"); //*(argv+1) is similar to argv[1]
if (max == 0) printf("Error while trying to determine the width of the window\n");
else if (cfptr == NULL) {
printf(" Error while opening the file\n");
}
else {
c = (char *)malloc(max*sizeof(char)); //allocate memory
printf("File opened succesfully. Contents:\n\n");
Read_File(c, max, cfptr, abs(atoi(argv[2]))); //convert string to an integer, and take the absolute value of that integer .
} //which becomes the number of lines to pass as a argument to the function
free(c); //free memory
fclose(cfptr);
return 0;
}
void Read_File(char *c, int max, FILE * ptr, int N) { //the fourtfh argument N is for the number of lines
int i; //counter
int a=0; //index for array size
char user; //input value by user
long int *size = (long int*) malloc(sizeof(long int)); //allocate memory
size[a]=0;
do {
printf("\n\nPress N/n to continue. P/p to go backward. Q/q to exit the program.\n");
user = getchar();
getchar(); //I consider a character when we press enter
if ( (user == 'N') || (user == 'n')){
CLEAR(); //clear the screen
for (i = 0; (i < N )&& fgets (c, max, ptr) != NULL; i++ )
printf("%s", c);
fflush(stdout); //prevent data lost
a++;
if( a > sizeof(size)/sizeof(int))
size = realloc(size, sizeof(int)*(a+1)); //reallocate memory
size[a]= ftell(ptr); //determine current position
}
else if ((user == 'P') || (user == 'p')) {
CLEAR();
if (a >1){
a -= 2;
fseek(ptr, size[a], SEEK_SET); //reposition output stream
for (i = 0; (i < N) && fgets (c, max, ptr) != NULL; i++)
printf("%s", c);
fflush(stdout); }
}
else if((user == 'q') || (user == 'Q'))
exit(0); //quit the program
free(size);
} while (!feof(ptr));
}