Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

How to make the console output lines scrolling

reidar
New User
1,201 Views

I have a console application that does nothing but math operations.
To inform the user about the progress,  it prints messages to the screen like:
Step 1 completed…
Step 2 completed… etc
aso…

Instead I want the program to reprint or scroll on a single line by omitting the line feed.
In former days this could be  easily arranged with the statements:

WRITE(IDO,911)N
911     FORMAT('+'T5,'Step',I3,' Completed…')

But with IVF this does not work…. 
Do anybody have a clue how  a “scroll” function could be arranged?

 

0 Kudos
1 Solution
Nikitopoulos__Theodo
1,201 Views

You can try to use the carriagecontrol ='fortran' and the + character.  You can find an example in an older post:
https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/277417

 

View solution in original post

0 Kudos
11 Replies
Arjen_Markus
Honored Contributor I
1,201 Views

This is not so much a problem of Intel Fortran as a change in the behaviour of consoles in general in comparison with the old days.

A simple way to solve this - no guarantee though - is to use code like the small program below:

! noscroll.f90 --
!     Can we prevent scrolling?
!
program noscroll
    implicit none

    integer :: i

    do i = 1,10
        write(*,'(i4,a1)', advance = 'no') i, achar(13)
    enddo
endprogram noscroll

The "advance='no'" option makes sure no carriage return line feed is emitted, causing the console to start a new line and the achar(13) character is used to make the console "cursor" go back. The net effect: you write to the start of the same line with each iteration.

0 Kudos
Nikitopoulos__Theodo
1,202 Views

You can try to use the carriagecontrol ='fortran' and the + character.  You can find an example in an older post:
https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/277417

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,201 Views

You can also call a C Runtime Library routine to emit a character or null terminated string.

Jim Dempsey

0 Kudos
reidar
New User
1,201 Views

Thank you all for help.

The "advance=no" option seems to suppress both the LF and the position T5, thus produces an endless line........

So far I found the simplest solution was to open a user window with option "carriagecontrol='fortran' ".

0 Kudos
Arjen_Markus
Honored Contributor I
1,201 Views

Hm, odd, I adjusted the write statement in the program I posted to:

        write(*,'(t5,a1,i4,a1)', advance = 'no') '!', i, achar(13)            

and got:

    !  10

on the screen. Si in my case the T5 edit is working fine. "advance='no'" does suppress the carriage return AND the line feed. Which is why the write statement explicitly include writing the carriage return.

Using the carriagereturn option is definitely the easiest fix, but note that it is an Intel Fortran extension, whereas the above is standard Fortran ;).

0 Kudos
reidar
New User
1,201 Views

Ok, in my test I overlooked achar(13) in the output list, sorry. I tested once more, also by directly implementing the "write" statement from your example. However, it did not produce any output but from the "PRINT" statement.    A list of my program is shown below.  There must be something else which is different..

! The program is invoked from a dialogue in a Win32 program or from a command prompt 

   program TVSimulation
    
    USE TVA_CalcControl
    implicit none

    ! Variables
    INTEGER IDUM,ISTAT,i
    IUNI=401                ! defined in TVA_CalcControl 
!    open(file='user', unit=IUNI,carriagecontrol='FORTRAN')  ! This works
!    open(file='user', unit=IUNI)                            ! ... neither
!    print *, '************  START TVSIM  ************'

do i = 1,10 
!    write(IUNI,'(T5,i4,a1)', advance = 'no') i, achar(13)
    write(*,'(t5,a1,i4,a1)', advance = 'no') '!', i, achar(13)
    enddo 
    pause

    call TVSim(1,ISTAT)                         

    print *, 'PRESS RETURN TO EXCIT AND CLOSE WINDOW'
    READ(*,*)
    
    end program TVSimulation

 

0 Kudos
IanH
Honored Contributor II
1,201 Views

It may depend on ifort version, but try Arjen's method with a FLUSH statement on the console unit.

program noscroll_with_flush
  use, intrinsic :: iso_fortran_env, only: output_unit
  use ifport, only: sleepqq
  implicit none
  
  integer :: i
  
  do i = 1,99
    write(*,'(i2,a1)', advance = 'no') i, achar(13)
    flush(output_unit)        ! <-----------
    ! Slow down so we can see output.
    call sleepqq(100)
  end do
end program noscroll_with_flush

Recent Windows 10 includes a much enhanced console subsystem, that can basically emulate a terminal (if you are running Windows Subsytem for Linux, it is a terminal).  You can have all sorts of fun with it.

program noscroll_deluxe
  use ifwin, only:  &
      handle,  &
      std_output_handle,  &
      invalid_handle_value,  &
      getstdhandle,  &
      bool,  &
      dword,  &
      setconsolemode
  use ifport, only: sleepqq
  implicit none
  integer(handle) :: stdout_handle
  integer(bool) :: rc
  integer(dword) :: mode
  character(2) :: col
  integer :: i
  
  ! Not defined in 17.0.1's kernel32 module.
  integer(dword), parameter ::  &
      enable_virtual_terminal_processing = int(z'0004',dword)
  
  interface
    ! The description of this in ifort's kernel32.f90 is a bit wonky.
    function GetConsoleMode(hConsoleHandle, lpMode)  &
        bind(c, name='GetConsoleMode')
      use ifwinty
      integer(handle), value :: hConsoleHandle
      integer(dword), intent(out) :: lpMode
      !DEC$ ATTRIBUTES STDCALL :: GetConsoleMode
      integer(bool) :: GetConsoleMode
    end function GetConsoleMode
  end interface
  
  stdout_handle = getstdhandle(std_output_handle)
  if (stdout_handle == invalid_handle_value)  &
      error stop 'no stdout!'
  
  rc = getconsolemode(stdout_handle, mode)
  if (rc == 0)  &
      error stop 'stdout not a console!'
  
  mode = ior(mode, enable_virtual_terminal_processing)
  rc = setconsolemode(stdout_handle, mode)
  if (rc == 0)  &
      error stop 'windows version too old :('
  
  print "()"
  do i = 1,99
      write (col, '(i2)') mod(i,8) + 30
      print "(a,i2)",  char(27) // '[1F' // char(27) // '[' // col // 'm', i
      ! Slow down so we can see output.
      call sleepqq(100)
  end do
  print "(a)", char(27) // '[0m'
end program noscroll_deluxe

See https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx for information on the support escape codes.

0 Kudos
Arjen_Markus
Honored Contributor I
1,201 Views

I was curious about the PAUSE statement in your sample program, but it still works indeed :). The problem for which Ian proposes a FLUSH statement is simple: at the end of the do-loop the write position is again at the start of the line that holds the last output ("    ! 10"). So the message from PAUSE overwrites that.

An alternative could be:

program noscroll
	    implicit none
	    integer :: 

	    do i = 1,10
	        write(*,'(t5,a1,i4,a1)', advance = 'no') '!', i, achar(13)
	    enddo
            write(*,*) '' ! Force the output cursor to the next line
endprogram noscroll

 

 

0 Kudos
reidar
New User
1,201 Views

Thank you all for interesting suggestions!

Well, I checked my latest purchased textbook about Fortran, "Fortran 90 Explained" by M. Metcalf and J. Reid.  There is a chapter about Fortran carriage control which states: "The first character on each output record (eg to the lineprinter) must be of default kind. It is not printed but interpreted as a carriage control character...The carriage control characters defined by the standard are: b - to start a new line, + - to remain on the same line (overprint), 0 - to skip a line, 1 - to advance to the beginning of next page."  But of course the standard may have been changed..

With IVF you have to open a device with the carriagecontol="fortran" which is IVF specific extension to make the overprint work..  

 

0 Kudos
Arjen_Markus
Honored Contributor I
1,201 Views

Well, there is slightly more to it than that: the console has to cooperate. Just think of all those programming languages that do not use this Fortran (or perhaps FORTRAN) feature. C for instance requires you to explicitly specify a new line to go the next line in the console and any character will simply be printed. Apparently the CARRIAGECONTROL keyword arranges for the output to obey the conventions used by FORTRAN in the old days.

0 Kudos
Arjen_Markus
Honored Contributor I
1,201 Views

Well, there is slightly more to it than that: the console has to cooperate. Just think of all those programming languages that do not use this Fortran (or perhaps FORTRAN) feature. C for instance requires you to explicitly specify a new line to go the next line in the console and any character will simply be printed. Apparently the CARRIAGECONTROL keyword arranges for the output to obey the conventions used by FORTRAN in the old days.

0 Kudos
Reply