An example below of Fortran source calling the necessary Windows APIs to set the console to the correct mode. Calling Windows APIs makes this source inherently platform specific - there are also some compiler specific directives (ifort and gfortran variants provided) necessary to fully define the API interfaces.
The library for the Win32 kernel API's will also need to be accessible, but this is often installed (or required) as part of installing a compiler on Windows.
Some compilers provide modules with the relevant interfaces to the Windows API, saving you the trouble of having to write them yourself.
PROGRAM WriteAnsi
IMPLICIT NONE
CALL set_ansi
PRINT "(A)", &
ACHAR(27) // '[31m' // 'H' // &
ACHAR(27) // '[32m' // 'e' // &
ACHAR(27) // '[33m' // 'l' // &
ACHAR(27) // '[34m' // 'l' // &
ACHAR(27) // '[35m' // 'o' // &
ACHAR(27) // '[0m'
CONTAINS
SUBROUTINE set_ansi
USE, INTRINSIC :: ISO_C_BINDING, ONLY: &
DWORD => C_LONG, & ! C_INT32_T really, but this is per the docs
HANDLE => C_INTPTR_T, &
BOOL => C_INT
INTEGER(HANDLE), PARAMETER :: INVALID_HANDLE_VALUE = -1_HANDLE
INTERFACE
FUNCTION GetStdHandle(nStdHandle) BIND(C, NAME='GetStdHandle')
IMPORT :: DWORD
IMPORT :: HANDLE
IMPLICIT NONE
INTEGER(DWORD), INTENT(IN), VALUE :: nStdHandle
INTEGER(HANDLE) :: GetStdHandle
!DEC$ ATTRIBUTES STDCALL :: GetStdHandle
!GCC$ ATTRIBUTES STDCALL :: GetStdHandle
END FUNCTION GetStdHandle
END INTERFACE
INTEGER(DWORD), PARAMETER :: STD_INPUT_HANDLE = -10_DWORD
INTEGER(DWORD), PARAMETER :: STD_OUTPUT_HANDLE = -11_DWORD
INTEGER(DWORD), PARAMETER :: STD_ERROR_HANDLE = -12_DWORD
INTERFACE
FUNCTION GetConsoleMode(hConsoleHandle, lpMode) BIND(C, NAME='GetConsoleMode')
IMPORT :: HANDLE
IMPORT :: DWORD
IMPORT :: BOOL
IMPLICIT NONE
INTEGER(HANDLE), INTENT(IN), VALUE :: hConsoleHandle
INTEGER(DWORD), INTENT(OUT) :: lpMode
!DEC$ ATTRIBUTES REFERENCE :: lpMode
INTEGER(BOOL) :: GetConsoleMode
!DEC$ ATTRIBUTES STDCALL :: GetConsoleMode
!GCC$ ATTRIBUTES STDCALL :: GetConsoleMode
END FUNCTION GetConsoleMode
END INTERFACE
INTEGER(DWORD), PARAMETER :: ENABLE_ECHO_INPUT = INT(Z'0004', DWORD)
INTEGER(DWORD), PARAMETER :: ENABLE_INSERT_MODE = INT(Z'0020', DWORD)
INTEGER(DWORD), PARAMETER :: ENABLE_LINE_INPUT = INT(Z'0002', DWORD)
INTEGER(DWORD), PARAMETER :: ENABLE_MOUSE_INPUT = INT(Z'0010', DWORD)
INTEGER(DWORD), PARAMETER :: ENABLE_PROCESSED_INPUT = INT(Z'0001', DWORD)
INTEGER(DWORD), PARAMETER :: ENABLE_QUICK_EDIT_MODE = INT(Z'0040', DWORD)
INTEGER(DWORD), PARAMETER :: ENABLE_WINDOW_INPUT = INT(Z'0008', DWORD)
INTEGER(DWORD), PARAMETER :: ENABLE_VIRTUAL_TERMINAL_INPUT = INT(Z'0200', DWORD)
INTEGER(DWORD), PARAMETER :: ENABLE_PROCESSED_OUTPUT = INT(Z'0001', DWORD)
INTEGER(DWORD), PARAMETER :: ENABLE_WRAP_AT_EOL_OUTPUT = INT(Z'0002', DWORD)
INTEGER(DWORD), PARAMETER :: ENABLE_VIRTUAL_TERMINAL_PROCESSING = INT(Z'0004', DWORD)
INTEGER(DWORD), PARAMETER :: DISABLE_NEWLINE_AUTO_RETURN = INT(Z'00008', DWORD)
INTEGER(DWORD), PARAMETER :: ENABLE_LVB_GRID_WORLDWIDE = INT(Z'0010', DWORD)
INTERFACE
FUNCTION SetConsoleMode(hConsoleHandle, dwMode) BIND(C, NAME='SetConsoleMode')
IMPORT :: HANDLE
IMPORT :: DWORD
IMPORT :: BOOL
IMPLICIT NONE
INTEGER(HANDLE), INTENT(IN), VALUE :: hConsoleHandle
INTEGER(DWORD), INTENT(IN), VALUE :: dwMode
INTEGER(BOOL) :: SetConsoleMode
!DEC$ ATTRIBUTES STDCALL :: SetConsoleMode
!GCC$ ATTRIBUTES STDCALL :: SetConsoleMode
END FUNCTION SetConsoleMode
END INTERFACE
INTEGER(DWORD), PARAMETER :: ENABLE_EXTENDED_FLAGS = INT(Z'0080', DWORD)
INTEGER(HANDLE) :: output_handle
INTEGER(BOOL) :: api_result
INTEGER(DWORD) :: mode
output_handle = GetStdHandle(STD_OUTPUT_HANDLE)
IF (output_handle == INVALID_HANDLE_VALUE) THEN
ERROR STOP 'GetStdHandle failed'
END IF
api_result = GetConsoleMode(output_handle, mode)
IF (api_result == 0_BOOL) THEN
ERROR STOP 'GetConsoleMode failed'
END IF
api_result = SetConsoleMode( &
output_handle, &
IOR(mode, ENABLE_VIRTUAL_TERMINAL_PROCESSING) )
IF (api_result == 0_BOOL) THEN
ERROR STOP 'SetConsoleMode failed'
END IF
END SUBROUTINE set_ansi
END PROGRAM WriteAnsi