- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm using ifwin in my program to control the position of the cursor in the console window in Windows.
How can I run the same program in Linux but force it to ignore all the calls in windows APIs, without me having to comment out all the relevant lines? Or is there even a more general way to accurately control the cursor position that would work in both Windows and Linux/
Thank you
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can put Intel Fortran preprocessor directives anywhere in your program:
program test
!dec$ if defined(__linux)
print*, 'Hello from Linux'
!dec$ else
print*, 'Hello from Windows?'
!dec$ end if
end program
Using them to set a Fortran variable, as you do with os (= "w" or "l"), won't stop the compiler from attempting to compile subsequent lines that only get invoked for a particular value of os. What you want to do is enclose any platform specific code in a conditionally compiled block, i.e.
!dec$ if defined(__linux)
! Don't do anything here
!dec$ else
! Windows specific code
!dec$ end if
Note that our suggestion to use fpp directives rather than Intel specific pre-processor directives is in case you want to use a different compiler, say gfortran.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You could use the Fortran preprocessor, fpp (https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/optimization-and-programming-guide/fpp-preprocessing.html) to conditionally compile Win32 API code on Windows only.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can put Intel Fortran preprocessor directives anywhere in your program:
program test
!dec$ if defined(__linux)
print*, 'Hello from Linux'
!dec$ else
print*, 'Hello from Windows?'
!dec$ end if
end program
Using them to set a Fortran variable, as you do with os (= "w" or "l"), won't stop the compiler from attempting to compile subsequent lines that only get invoked for a particular value of os. What you want to do is enclose any platform specific code in a conditionally compiled block, i.e.
!dec$ if defined(__linux)
! Don't do anything here
!dec$ else
! Windows specific code
!dec$ end if
Note that our suggestion to use fpp directives rather than Intel specific pre-processor directives is in case you want to use a different compiler, say gfortran.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you. I didn't know you could put those everywhere in the program, even before implicit none.
I understand it will not be compatible with other compilers other than Intel Fortran but it will do for now until I eventually use the fpp directives
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The syntax for preprocessing with the option /fpp is illustrated below:
program fpp
#ifdef X
write(*,*) 'Hello, X'
#else
write(*,*) 'Hello, someone else'
#endif
end program fpp
You can define the macro X via /D. For instance : ifort /DX /fpp fpp.f90 would define the macro X and the program will print the first line.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You could also consider encapsulating the API calls inside specific routines that are in a specific source file and have a file with different of dummy routines for linux.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I very much prefer the approach of abstraction to a set of procedures in a set of platform specific files approach, mentioned by andrew_4619. Put the logic operating system specific decisions into whatever build system you are using - build systems have to know what sort of operating system they are running on. This can obviate use of the pre-processor entirely.
A simple example using that approach, also with an example of using ansi escape sequences, because I'm not sure what "them" refers to in "how do I use them?"
Operating system independent:
! In ansi.f90
PROGRAM Ansi
USE ansi_support
USE ansi_common
IMPLICIT NONE
CALL set_ansi
PRINT "(A)", &
go_red() // 'H' // &
go_green() // 'e' // &
go_yellow() // 'l' // &
go_blue() // 'l' // &
go_magenta() // go_down() // 'o' // &
go_reset()
END PROGRAM WriteAnsi
! In ansi_common.f90
MODULE ansi_common
IMPLICIT NONE
CONTAINS
FUNCTION go_reset() RESULT(seq)
CHARACTER(4) :: seq
seq = ACHAR(27) // '[0m'
END FUNCTION go_reset
FUNCTION go_black() RESULT(seq)
CHARACTER(5) :: seq
seq = ACHAR(27) // '[30m'
END FUNCTION go_black
FUNCTION go_red() RESULT(seq)
CHARACTER(5) :: seq
seq = ACHAR(27) // '[31m'
END FUNCTION go_red
FUNCTION go_green() RESULT(seq)
CHARACTER(5) :: seq
seq = ACHAR(27) // '[32m'
END FUNCTION go_green
FUNCTION go_yellow() RESULT(seq)
CHARACTER(5) :: seq
seq = ACHAR(27) // '[33m'
END FUNCTION go_yellow
FUNCTION go_blue() RESULT(seq)
CHARACTER(5) :: seq
seq = ACHAR(27) // '[34m'
END FUNCTION go_blue
FUNCTION go_magenta() RESULT(seq)
CHARACTER(5) :: seq
seq = ACHAR(27) // '[35m'
END FUNCTION go_magenta
FUNCTION go_cyan() RESULT(seq)
CHARACTER(5) :: seq
seq = ACHAR(27) // '[36m'
END FUNCTION go_cyan
FUNCTION go_white() RESULT(seq)
CHARACTER(5) :: seq
seq = ACHAR(27) // '[37m'
END FUNCTION go_white
FUNCTION go_up() RESULT(seq)
CHARACTER(4) :: seq
seq = ACHAR(27) // '[1A'
END FUNCTION go_up
FUNCTION go_down() RESULT(seq)
CHARACTER(4) :: seq
seq = ACHAR(27) // '[1B'
END FUNCTION go_down
FUNCTION go_forward() RESULT(seq)
CHARACTER(4) :: seq
seq = ACHAR(27) // '[1C'
END FUNCTION go_forward
FUNCTION go_back() RESULT(seq)
CHARACTER(4) :: seq
seq = ACHAR(27) // '[1D'
END FUNCTION go_back
END MODULE ansi_common
(See one of the plethora of online sources for details on the escape sequences.)
For windows, ansi_support looks like (should also be compilable by gfortran - if you used the ifort provided modules such as IFWIN, this would be shorter):
! In ansi_support-win.f90
MODULE ansi_support
IMPLICIT NONE
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 MODULE ansi_support
On linux, the corresponding module is a bit shorter....
! In ansi_support-other.f90
MODULE ansi_support
IMPLICIT NONE
CONTAINS
SUBROUTINE set_ansi
! Does nothing.
END SUBROUTINE set_ansi
END MODULE ansi_support
Compile on windows (using my advanced build system - the command prompt):
ifort /exe:ansi.exe ansi_common.f90 ansi_support-win.f90 ansi.f90
On linux substitute ansi_support-other.f90 for ansi_support-win.f90.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Every time I see references to ANSI escape sequences, I fondly remember the DEC VT100 terminal, the first to support them and so popular that people referred to "VT100 escape sequences".
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This library does not seem to provide cursor control, but it might be useful for other features of ANSI escape sequences - http://foul.sourceforge.net/
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Recent versions of the windows console can support ansi escape sequences, which will also be supported on linux terminals. Activating ansi support on the console requires a single console API call, which makes it very easy to isolate the operating system dependency. Some of the alternative windows terminals support those sequences for all programs without the need for the console api call.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page