Scrolling text in terminal, from input file

I would like to create a program that reads a TXT file (say, a poem or a song) and then it outputs it on the terminal screen in a scrolling way, like at the bottom of the window, making it to appear from the bottom right, scrolling to the left and disappearing.

I thought I could start with:

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
  #include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(void)
{
ifstream infile;
infile.open("POEM.txt", ios::in);

if (!infile)
{
   cout<<"File does not exist";
   return EXIT_FAILURE;
}
std::string text_from file;
while (getline(infile, text_from_file))
{
   cout << text_from_file << "\n";
}

cout << "Paused. Press enter to continue.\n"
cin.ignore(10000, '\n');

return EXIT_SUCCESS;
}



But then I am completely stuck with the scrolling part. Any help? Thank you so much!
@VonNeumann

Here's a small program I threw together, that displays a section of a sentence at a time, till the whole sentence scrolls across the bottom of the screen. This should give you ideas on you can add it to your program..

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
#include <iostream>
#include <string>
#include <Windows.h>

using namespace std;

HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
COORD CursorPosition;

void gotoXY(int x, int y);

int main()
{
	string rotating_string = "This is a moving marquee, that shows an IMPORTANT
 message... It could also be a poem, or short story : ";
	string partial_string="";
	int len = rotating_string.length();
	char letter_holder;
	do
	{
		gotoXY(38, 28);
		partial_string = "";
		for(int y=0;y<30;y++)
			partial_string+= rotating_string[y];
		cout << partial_string;
		Sleep(100);
		letter_holder = rotating_string[0];
		for (int x = 1; x<len; x++)
		{
			rotating_string[x-1] = rotating_string[x];
		}
		rotating_string[len-1] = letter_holder;

	} while (true);
	return 0;
}

void gotoXY(int x, int y)
{
	CursorPosition.X = x;
	CursorPosition.Y = y;
	SetConsoleCursorPosition(console, CursorPosition);
}
Last edited on
Thank you so much for the inputs! Just one thing: I run the program on Mac, hence #include <windows.h> doesn't work...
@VonNeumann

I don't know/use a Mac, but I'm thinking you can find a library that lets you use the gotoXY function, of placing text at a specified location. That's all the Windows.h library is used for my program.
You can try this from SO:
https://stackoverflow.com/questions/7581347/gotoxy-function-with-c-linux-unix
1
2
3
4
void gotoxy(int x,int y)
{
  printf("%c[%d;%df",0x1B,y,x);
}
It doesn't work...
Also I am still stuck on how to make the program to read a text file, and not just a phrase written inside the code
It is possible to do this without some OS-specific code, but not as well as with it.

Here is something you can play with that is about the bare-minimum necessary to work.
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
#include <iostream>
#include <string>

#ifdef _WIN32

  #ifndef NOMINMAX
  #define NOMINMAX
  #endif
  #include <windows.h>
  
  bool iskeypressed( unsigned timeout_ms )
  {
    HANDLE h = GetStdHandle( STD_INPUT_HANDLE );
    DWORD n = WaitForSingleObject( h, timeout_ms );
    if (n == WAIT_OBJECT_0)
    {
      static thread_local INPUT_RECORD buffer[ 200 ];
      PeekConsoleInputW( h, buffer, 200, &n );
      for (INPUT_RECORD* b = buffer; b != buffer + n; b++)
        if ((b->EventType == KEY_EVENT)
        and (b->Event.KeyEvent.bKeyDown))
          return true;
    }
    return false;
  }
  
  int getconsolewidth()
  {
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &csbi );
    return csbi.srWindow.Right - csbi.srWindow.Left + 1;
  }
  
#else // POSIX

  #include <poll.h>
  #include <stdlib.h>
  #include <sys/ioctl.h>
  #include <termios.h>
  #include <unistd.h>
  
  bool iskeypressed( unsigned timeout_ms )
  {
    struct pollfd pls[ 1 ];
    pls[ 0 ].fd     = STDIN_FILENO;
    pls[ 0 ].events = POLLIN | POLLPRI;
    return poll( pls, 1, timeout_ms ) > 0;
  }
  
  int getconsolewidth()
  {
    struct winsize ws;
    ioctl( 0, TIOCGWINSZ, &ws );
    return ws.ws_col;
  }

#endif

int main()
{
  std::string s;
  std::cout << "message? ";
  getline( std::cin, s );
  
  // -1 to avoid causing line wrap on the screen
  int width = getconsolewidth() - 1; 
  
  // The string display buffer
  s.resize( width, ' ' );
  
  // We will advance roughly every 150 ms
  while (!iskeypressed( 150 ))
  {
    // Display the string
    std::cout << s << "\r";
    // Wrap the string to the left one character
    s = s.substr( 1 ) + s.substr( 0, 1 );
  }
  
  std::cout << "\n";
}

Hope this helps.
@Duthomhas

VonNeumann said he's using a Mac, and therefore cannot use the Windows.h library

@whitenite1,
that's the point of #ifdef _WIN32.
The code will be included only on Windows.

On Non-Windows systems the code inside #else // POSIX will be included.
@Thomas1965

Sorry. I've never used the #ifdef functions in my program, so when I saw the #include <Windows.h>, I figured it would be used. I too, hope it helps VonNeumann.
Topic archived. No new replies allowed.