What's wrong here? (ClearWin+)
29 Jan 2026 9:11 (Edited: 29 Jan 2026 9:17)Thanks Ken. Fun is I tried this ^rf too but devilry clearly tricked me to make some typo that the code even did not compile so I gave up.
Welcome to our forums
Thanks Ken. Fun is I tried this ^rf too but devilry clearly tricked me to make some typo that the code even did not compile so I gave up.
Dan, You need to change %rf to %^rf with changeTimerDelay as the callback.
module PICrunControl
use clrwin
integer :: LastPICfileOutputNumber=0 !####
integer (7) hwFileCheckingInterval
real*8 :: FileCheckingInterval = 1
contains
integer recursive function FileCheckingCB ()
LastPICfileOutputNumber = LastPICfileOutputNumber + 1
call window_update@(LastPICfileOutputNumber)
FileCheckingCB = 2
end function FileCheckingCB
!...................................
integer function changeTimerDelay ()
print*, FileCheckingInterval !####
call CHANGE_TIMER_INTERVAL@(hwFileCheckingInterval, FileCheckingInterval)
changeTimerDelay = 2
end function
end module
!=============================================
Program Prog
use PICrunControl
k = WINIO@('Interval %ta%df%^rf%ff&', 1d0, FileCheckingInterval,changeTimerDelay ) !####
k = WINIO@('Caii number %ta%4rd%ff&', LastPICfileOutputNumber )
k = WINIO@('%dl&', FileCheckingInterval, FileCheckingCB)
k = WINIO@('%hw%es', hwFileCheckingInterval)
end
Congrats with the new updated and upgraded more spacious home for the forum.
Creating the program which checks some changes in the files ones per few seconds. The method I used as a first attempt kind of failing so I decided to use another one which employs timer control %dl . But it is also failing. Here is demo. Try to run it. Initially it works. It calls some function every second as it was preset and updates and displays the number of calls. But try to change the default interval time - no effect.
(Comment: I use recursive function just for additional safety: it has no effect in this specific demo but could be useful when the computer becomes very slow and due to that the timer will issue the call for the next such function while it is still not finished with the previous call - this will lead to crash)
module PICrunControl
integer LastPICfileOutputNumber
integer (7) hwFileCheckingInterval
real*8 :: FileCheckingInterval = 1
contains
integer recursive function FileCheckingCB ()
LastPICfileOutputNumber = LastPICfileOutputNumber + 1
call window_update@(LastPICfileOutputNumber)
FileCheckingCB = 2
end function FileCheckingCB
!...................................
integer function changeTimerDelay ()
call CHANGE_TIMER_INTERVAL@(hwFileCheckingInterval, FileCheckingInterval)
changeTimerDelay = 2
end function
end module
!=============================================
Program Prog
use PICrunControl
k = WINIO@('Interval %ta%df%rf%ff&', 1d0, FileCheckingInterval )
k = WINIO@('Caii number %ta%4rd%ff&', LastPICfileOutputNumber )
k = WINIO@('%dl&', FileCheckingInterval, FileCheckingCB)
k = WINIO@('%hw%es', hwFileCheckingInterval)
end
Thank you Paul, that's a very clear recommendation to be saved in to the AI's local user history.
Hi Dan: Have you received any feedback on this article, I have experienced several new bugs with the 64 bit system since the latest release, primarily using the sdbg debugger. When I start the system and go to a breakpoint, after it stops and then I resume execution in the sdbg system, it all of a sudden reverts to full execution, no longer allow the "step into", "stepover" commands, etc. I have received no response to the articles that I have written, Sid Kraft
Seems that the 64bit sdbg program has many errors now with the latest release. I have written articles about bug/nodebug, 64 bit debugging, etc., have had no responses about the 64 bit system. Sure would like to know the status of this system, would help with my coding situation. Sid Kraft
Ken
Thank you for the feedback.
FTN95 does not currently support the use of SPREAD as an approach to parallelisation. The outcome is that runtimes can be excessively long or sometimes it fails to compile.
This approach was recommended in the Fortran 95 book by Metcalf, Reid and Cohen, and Numerical Recipes in Fortran 90, but it is only useful when parallelisation is supported.
For FTN95, AI generated code that uses SPREAD in this way should be converted back to its simpler Fortran 77 form.
The following code exposes a bug, the assignment z = peaks(spread(x,2,n), spread(y,1,n)) fails with FTN95 (access violation).
program p
use iso_fortran_env
implicit none
integer, parameter :: n = 4
integer :: i, j
real*8 :: x(n), y(n), z(n,n), zt1(n,n), zt2(n,n)
write(*, '(a)') compiler_version()
print*
x = [0,1,2,3]
y = [-3,-2,-1,0]
write(*,'(a,1x,4(F10.5,2X))') 'X = ', x
write(*,'(a,1x,4(F10.5,2X))') 'Y = ', y
print*
z = peaks(spread(x,dim=2,ncopies=n), spread(y,dim=1,ncopies=n)) ! ### FTN95 fails here
write(*, '(a)')'z = peaks(spread(x,2,n), spread(y,1,n))'
do j = 1, n
write(*,'(4(F10.5,2X))') (z(i,j),i=1,n)
end do
print*
contains
elemental function peaks (x,y) result (val)
real*8, intent(in) :: x, y
real*8 :: val
val = 3.d0*(1.d0 - x)**2 * exp( -x**2 - (y+1.d0)**2 ) &
- 10.d0*(x/5.d0 - x**3 - y**5) * exp( -x**2 - y**2 ) &
- 1.d0/3.d0 * exp( -(x+1.d0)**2 - y**2 )
end function peaks
end program p
The compiler actually has to do a lot of work “under the bonnet” to get to the final result, and this AI generated line of code defeats FTN95!
I can think of at least two different ways to achieve the required end result in a much clearer way.
Nevertheless z = peaks(spread(x,2,n), spread(y,1,n)) is all Fortran 90 syntax, so looks like a bug to me.
Here is the program’s output from an alternative compiler.
GCC version 12.3.0
X = 0.00000 1.00000 2.00000 3.00000
Y = -3.00000 -2.00000 -1.00000 0.00000
z = peaks(spread(x,2,n), spread(y,1,n))
-0.24495 -0.10996 -0.00431 -0.00001
-4.75961 -2.10235 -0.06164 0.00042
-0.72391 -0.27292 0.49964 0.01301
0.98101 2.93693 1.41216 0.03312
Dan: Have same problem only cannot get sdgf step out, step over, etc. to work, just sits there and freezes?? Sid Kraft
Not sure what happened, downloaded the latest version of Silverfrost Fortran, compiled all of my subroutines in 64 bit debug, built and executed. Page comes up, tried to step over, step in, etc. the system does nothing, freezes? Not sure if i am doing something wrong or is an error, any advise? Sid Kraft
If I understand the physics correctly, if you crushed an object down smaller and smaller, this program tells you the size at which it would turn into a black hole, and how dense it would have to be.
The mass of the observable universe leads to a radius of 14 billion lightyears -- which is conveniently the approximate age of the universe.
Hello
Just a short code to illustrate the type functionality. Reading input from a data file, writing the formatted results to a file and also to the console as a check. There are even more basic routes to do the same, but interesting to explore the Fortran 95 syntax further.
module schwarzschild_mod
implicit none
!integer, parameter :: dp = selected_real_kind(12,100)
integer, parameter :: dp = kind(1.0d0)
!==============================
! Derived type definition
!==============================
type :: Schwartzschild_properties
real(dp) :: S_radius
real(dp) :: S_density
end type Schwartzschild_properties
contains
!==============================
! Schwarzschild function
!==============================
function GR_Schwartzschild(mass) result(properties)
implicit none
real(dp) :: mass
type(Schwartzschild_properties) :: properties
real(dp), parameter :: G = 6.67430e-11_dp
real(dp), parameter :: c_light = 2.99792458e8_dp
real(dp), parameter :: pi = 4.0_dp * atan(1.0_dp)
properties%S_radius = 2.0_dp * G * mass / c_light**2
properties%S_density = (3.0_dp * c_light**2) / &
(8.0_dp * pi * G * properties%S_radius**2)
end function GR_Schwartzschild
end module schwarzschild_mod
program RS1
use schwarzschild_mod
implicit none
integer :: i, n, ios, ierror
character(len=25) :: Mass_object
real(dp) :: mass
type(Schwartzschild_properties) :: results
open(22, file='objects1.dat', status='old', action='read', iostat=ierror)
if (ierror /= 0) stop 'Cannot open input file'
n = 0
do
read(22, *, iostat=ios)
if (ios /= 0) exit
n = n + 1
end do
rewind(22)
open(25, file='objects1-calc.dat', status='replace')
! write header for file
write(25,'(A)') '==========================================================================='
write(25,'(A)') ' Object Mass(kg) Radius (m) Density (kg m-3)'
write(25,'(A)') '==========================================================================='
! Check results at the console
print *, ' Object Mass(kg) Radius (m) Density (kg m-3)'
print *, '==========================================================================='
do i = 1, n
read(22, *) Mass_object, mass
results = GR_Schwartzschild(mass)
write(*,'(1x,A,1x,es12.5,3x,es12.5,5x,es12.5)') &
Mass_object,mass,results%S_radius,results%S_density ! check results at console
write(25,'(1x,A,1x,es12.5,3x,es12.5,5x,es12.5)') &
Mass_object, mass, results%S_radius, results%S_density ! write results to file
end do
close(22)
close(25)
end program RS1
For anyone interested, the test data (kg), a random selection, are:
Observable_universe,8.80e+52
Milky_Way,1.60e+42
SMBH_NGC4889,4.20e+40
SMBH_Messier_87,1.30e+40
SMBH_Andromeda_Galaxy,3.40e+38
RMC_R136A1,6.2685e32
SMBH_Sagittarius_A,8.20e+36
Sun,1.99e+30
Earth,5.972e+24
Moon,7.346e+22
Jupiter,1.90e+27
Plaskett's_Star_B,1.1144e32
Donald_Trump,110
Big_Mac,0.215
Planck_mass,2.18e-8
Lester
For a clean modern Fortran 95 syntax, the test code is better without the goto directive, a minor point.
program tst
implicit none
integer :: i
do i=1,5
! Test a given integer for odd or even
if(mod(i,2).eq.0) then
print *,i,' is even'
else
print *,i,' is odd'
cycle
endif
end do
end program tst
Lester
Sid Thank you for your post. We now have a new forum system (see https://forums.silverfrost.com/Forum/Topic/4640). The forum of necessity has a different URL because it has been made "secure" (changing from http: to https:) and this means that the current link from Plato does not work.
Your post has reminded me that this needs changing and it will be right for the next release of Plato.
The address of the form has changed and the link in Plato (built before the new forum went live) points to the old address.
The link to the Silverfrost Home page from Plato remains correct, and the link to the forum from there correctly points to the new forum. So you can still find the forum from within Plato.
I would suggest that you save the link to the new forum address as a "favorite" in you web browser.
Very strange, with the "new" system that now requires a password with 12 characters, upper case, lower case and special character, not sure that this has anything to do with this latest situation. when I execute sdbg 64 bit, get into the system to start "stepping over" or "stepping out", when I issue any of the debugger instructions, absolutely nothing happens, like the "deer in the headlights"? I did download and install the latest Silverfrost compiler from the site but still does not work. If I run in Plato, all works fine but can no longer "debug" any 64 bit programs. Will try 32 bit, any ideas? Sid Kraft
Hi Paul: Finally got into the Silverfrost site after going to the site in Google, entering my previous password, entering "forgot password", went to email to reset, went back to Silverfrost with Google, now able to log onto Silverfrost "Whew"! Apparently, someone at your site decided that all previous passwords were not enough different characters and had to reset all. However, I still cannot get to the forums by typing "help" in the Plato icon, says site not found, have to go through Google, rather a pain! Any advise? Sid Kraft P.S. have downloaded the latest version of the system, still cannot get in through Plato
When %cd was introduced in 2023, I spent a several weeks trying out the capabilities and integrating this into my code. I used get_filtered_file@() extensively, so I wanted a solution that would easily integrate (minimal changes). What follows is what I've been using now for nearly 3 years with nary a glitch. Since this was integrated into my existing code, there were a few specific function calls I had to remove from what you see here. If I didn't catch them all, I apologize. If some of the IF statements look a bit odd, it's because I had some debugging code that is not useful to you (application specific).
logical function GET_FILTERED_FILE_NEW(title,file,path,filternames,filterspecs,nfilters,mustexist,caller_window_parameters)
use mswin
! --- These parameters are used for file selections from a dialog
INTEGER,PARAMETER:: FILE_CAN_EXIST = 0 ! not required for the file to be present on the system (might be created as part of the processing)
INTEGER,PARAMETER:: FILE_MUST_EXIST = 1 ! system must find the file to return the name/values
INTEGER,PARAMETER:: FILE_SAVE_AS_SYSVERIFY = 2 ! uses the system verification, then applies the extent after the fact if needed (not necessarily the right thing)
INTEGER,PARAMETER:: FILE_SAVE_AS_NOVERIFY = 3 ! save as dialog, but with no verification
INTEGER,PARAMETER:: FILE_SAVE_AS_ALTVERIFY = 4 ! SAVE AS dialog, then with verification AFTER the extent has been added
integer*4 :: nfilters,mustexist ! can_exist = 0,must_exist=1,save_as = 2, save anyway = 3
integer(7) :: caller_window_parameters,window_handle
character*( * ) :: title,file,path,filternames(nfilters),filterspecs(nfilters)
! this function is an attempt to proceduralize the selecting of a file and applying a file extent semi-automatically in the process.
! there is a LOT of checking done in this function, and if you are using it, you may not need everything.
!!must_exist options FILE_CAN_EXIST = 0
!!must_exist options FILE_MUST_EXIST = 1
!!must_exist options FILE_SAVE_AS_SYSVERIFY = 2 ! do the save as dialog and verify that it is OK to overwrite
!!must_exist options FILE_SAVE_AS_NOVERIFY = 3 ! do the save as dialog but do not verify it is OK within the dialog; do it later
!!must_exist options FILE_SAVE_AS_ALTVERIFY = 4 ! do the save as dialog and verify that it is OK to overwrite AFTER extent post-pend is accomplished
! This uses the new (a/o August 2023) common dialog %cd
! %cd[] always returns from winio@ the flags for the dialog. By default, this is in the variable ii
! so, if the flags need to be changed (i.e. one removed) we use IAND and NOT(flag_name) along with II to accomplish the flag changing
! OFN_* enumerated types are found at: https://learn.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-openfilenamea
!
integer*4 :: i,ii,flags=z'00081004' ! OFN_EXPLORER(00080000)+OFN_FILEMUSTEXIST(00001000)+OFN_HIDEREADONLY(00000004) ! normal
! integer*4 :: i,ii,flags=z'00080006' ! OFN_EXPLORER(00080000) +OFN_HIDEREADONLY(00000004)+OFN_OVERWRITEPROMPT(00000002) ! [saving]
!
! more flags at the bottom of this function
logical*2 :: added_extent=.false.
integer*2:: i_2
character*260:: temp_file,short_file,temp_path,fullpath,file_only,file_extent,filt(1),spec(1),saved_cwd
character*260,external:: curdir@
character*(len(filterspecs(1))):: abcd
integer::n_index(nfilters),n_extent(1:1),filter_selected,all_files
integer:: x_pos=0,y_pos=0
integer,external:: log_mydata
integer,external:: button1,button2 ! for overwrite dialog alternate
integer(7),external:: get_global_handle
character*260:: local_directory ! directory attached at the start of this function
integer:: stack_value
saved_cwd = curdir@() ! just in case we need to do a different "attach"
GET_FILTERED_FILE_NEW = .false. ! initial value - no file selected
local_directory = curdir@()
do i = 1,nfilters ; n_index(i) = i ; end do ! initialize the integer array used to extract filter items
!temp_title = title
! make copies of all the information JIC we need to mess with it
temp_file = file
temp_path = path
short_file = ' '
filter_selected = 0 ! assume nothing is selected by extent
if(temp_file.eq.' '.and.nfilters.ge.1) filter_selected = 1 ! select the first filter if the file name is blank. Otherwise, let the system do it.
! Since not having a path name for the file means that a folder can be chosen IAW a set of rules that may not make sense,
! make a file-name-only file into a complete path by pre-pending the name of the folder, if a folder name has been given
if(index(temp_file,'\').eq.0) then ! this is just a file name. put a folder name in front of it
if(temp_path.ne.' ') then
i = len_trim(temp_path)
if(temp_path(i:i).ne.'\') then
temp_path = trim(temp_path)//'\'
endif
temp_file = trim(temp_path)//temp_file ! make a path so the designated folder is actually used.
endif
endif
if(temp_file(1:2).eq.'.\') then ! if root-relative, then use the current working directory to complete the relative part. makes things more definite!
temp_file = trim(saved_cwd)//temp_file(3:)
endif
! THE FOLLOWING SECTION EXTRACTS THE EXTENT OF THE FILE, IF POSSIBLE, TO SET THE FILTER INDEX IN USE FOR THAT FILE. Only valid if we have filters being used.
! If there is a PATH, then this will be used to set the initial directory. Otherwise, we'll use the supplied path from the caller
if(getfullpathname(temp_file,len(fullpath),fullpath,core4(0)).ne.0) then ! this should fail (==0) if the name is blank
continue
else
call attach@(local_directory,i_2)
!print *,'Undechiperable file name - getfullpathname',fullpath
return
endif
i=index(fullpath,'\',.true.) ! backscan to find the first backslash
if(i.ne.0) then ! we have a pointer to the name of the file itself
file_only = fullpath(i+1:) ! extract the file name
temp_path = fullpath(1:i)
temp_file = file_only
else
call attach@(local_directory,i_2)
!print *,'Undechiperable file name - after fullpath scan'
return
endif
if(nfilters.ge.1) then ! see which filter might be selected
i = index(file_only,'.',.true.) ! back scan the file name only for the decimal as the name of the extent
if(i.gt.1) then ! it does contain an extent and it doesn't start with a "."
file_extent = '*'//file_only(i:) ! grab the extent and the decimal and pre=pend the * for the comparison
call lcase@(file_extent) ! make it lower case to match the filters being supplied (if any)
! now that we have the file extent, find the specified extent in the list (if possible) and set the initial setting to this index
if(any(filterspecs(1:nfilters).eq.file_extent)) then
n_extent(1:1) = pack(n_index,filterspecs.eq.file_extent) ! we have to do a "vector" assignment because....
filter_selected = n_extent(1) !pick up only the one index we want to highlight
else
! DO NOTHING. wE CAN'T CHANGE ANYTHING
! IF WE MAKE IT MORE "ODD", WE COULD TAKE THE *.* TYPE TO THE TOP... AND REPLACE IT ALL AFTER THE FILE OPEN IS DONE OR ABORTED
! if(logging_file) write(log_mydata(log_level_setting),*))'g_f_f_c: extent[',trim(file_extent),'] did not match any existing pattern'
endif
! do i=1,nfilters
! if(logging_file) write(log_mydata(log_level_setting),*)'Selection ',int(i,1),':',trim(filternames(i)),' ',trim(filterspecs(i))
! end do
else
! there is no file extent
filter_selected = 1
endif
endif
!if(logging_file) write(log_mydata(log_level_setting),*)'On entry, Temp path:',trim(temp_path)
!if(logging_file) write(log_mydata(log_level_setting),*)'On entry, Temp file:',trim(temp_file)
call set_cursor_waiting@(0) ! this is required to make sure the cursor is released (allowing input)
! see if the handle given is really a valid window handle and use the global one if not.
if(.not.iswindow(caller_window_parameters)) then
window_handle = get_global_handle() ! this function gets the handle of the main window (could just set to 0)
if(.not.iswindow(window_handle)) then
continue
else
ii = winio@('%cd[hwndowner]&',window_handle)
endif
else
ii = winio@('%cd[hwndowner]&',caller_window_parameters)
endif
i = len_trim(title)
ii = winio@("%cd[title='"//title(1:i)//"']&")
flags = ii
ii = winio@('%cd[file]&',temp_file)
ii = winio@('%cd[shortfile]&',short_file)
if(temp_path(1:1).ne.'.') then ! JIC this path relative sneaks by
ii = winio@('%cd[initialdir]&',temp_path)! only set the initial dir if the path is not relative
endif
all_files = 0 ! assume that no "all files" filter has been set
do i=1,nfilters ! SET THE FILTER SPECIFICATIONS FOR THE DIALOG IN REAL-TIME (ALLOWS SYNTAX CHANGES, jic)
ii = winio@("%cd[filter='"//trim(filternames(i))//' ('//trim(filterspecs(i))//")']&")
if(index(filterspecs(i),'*.*').ne.0) then
all_files = i ! find the option that selects "all files" if any
endif
end do
if(filter_selected.eq.0) filter_selected = all_files ! if no extent on the file, use the "all files" filter, if any
ii = winio@('%cd[filter_item_selected]&',filter_selected) ! auto-select the appropriate filter. Zero says none is selected, so dialog chooses the first one if a list is given.
select case (mustexist) ! alter the FLAGS based on the kind of file opening
case (0)
! make this a "can exist"
ii = winio@('%cd[flags]&',iand(ii,not(OFN_FILEMUSTEXIST)))
case (1)
! no need to do anything here (file must exist)
case (2)
ii = winio@('%cd[saving]&') ! generate a Save As selection and check afterward if the filename exists, and verify the user wishes to use this if it does exist.
case (3,4)
ii = winio@('%cd[saving]&') ! generate a Save As selection, without system verification to overwrite
ii = winio@('%cd[flags]&',iand(ii,not(OFN_OVERWRITEPROMPT)))
end select
flags = ii ! save the current flag bits bewfore the dialog is created
call attach@(temp_path,i_2)
ii = winio@('%cd') ! open the dialog. Return zero if cancelled, returns non-zero if successful.
call attach@(local_directory,i_2)
if(ii.eq.0) then ! none of the input variables will have changed any values
call attach@(local_directory,i_2)
return ! do not change anything.
endif
GET_FILTERED_FILE_NEW = .true. ! a file was selected or a name entered, but we're not done yet
! this handles applying an extent to a file name only (i.e. typed in)
if(.not.(filter_selected.eq.all_files.or.filter_selected.eq.0)) then ! a valid filter has been specified, see if we can apply it
if(index(filterspecs(filter_selected),'*.*').eq.0) then ! pathological case, programming error
i = index(short_file,'.',.true.) ! back scan to look for an extent being present
if(i.eq.0) then ! there is no extent, so add the selected extent to the filename
file_extent = filterspecs(filter_selected)(2:) ! use the extent from the filter selected
temp_file = trim(temp_file)//file_extent ! make the file name with the extent
else
call set_suffix1@(temp_file,FILTERSPECS(filter_selected)(3:),added_extent) ! added_extent will be TRUE if the extent is already present
endif
endif
endif
! ask if OK to overwrite
if(mustexist.eq.FILE_SAVE_AS_ALTVERIFY) then
if(fexists@(temp_file,ii)) then
i = index(temp_file,'\',.true.)
ii = winio@('%ww[no_maxminbox,no_sysmenu]%si!&')
ii = winio@('%ca[Confirm Save As]&')
ii = winio@('%fn[Tahoma]%ts&',1.2d0)
ii = winio@('%bf'//trim(temp_file(i+1:))//'%`bf already exists.%2nlDo you want to replace it?&')
ii = winio@('%rj %^bt[Yes] %^bt[No]',button1,button2)
get_filtered_file_new = ii.eq.1 ! will return TRUE only if user agress to overwriiting the file
endif
endif
if(get_filtered_file_new) then ! only update the variables IFF we are supposed to return the name of the file to open.
i=index(temp_file,'\',.true.) ! backscan to find the first backslash
if(i.ne.0) then ! we have a pointer to the name of the file itself
file = temp_file
path = temp_file(1:i)
endif
endif
call attach@(local_directory,i_2)
return
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_ALLOWMULTISELECT = 512
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_CREATEPROMPT = 8192
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_ENABLEHOOK = 32
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_ENABLETEMPLATE = 64
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_ENABLETEMPLATEHANDLE = 128
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_EXTENSIONDIFFERENT = 1024
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_FILEMUSTEXIST = 4096
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_HIDEREADONLY = 4
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_NOCHANGEDIR = 8
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_NOLONGNAMES = 262144
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_NONETWORKBUTTON = 131072
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_NOREADONLYRETURN = 32768
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_NOTESTFILECREATE = 65536
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_NOVALIDATE = 256
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_OVERWRITEPROMPT = 2
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_PATHMUSTEXIST = 2048
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_READONLY = 1
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_SHAREAWARE = 16384
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_SHAREFALLTHROUGH = 2
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_SHARENOWARN = 1
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_SHAREWARN = 0
! Open Flags ! INTEGER(KIND=3), PARAMETER :: OFN_SHOWHELP = 16
end
In this case AntiGravity is writing C# using Microsoft's MVC framework. It can write Fortran though. I asked it to write a program to display a Mandlebrot set using ClearWin+ and FTN95. The code it produced was approximately what you see below. It got confused about callbacks (who doesn't) and after a few comments from me it got it to work:
WINAPP
PROGRAM MANDELBROT
IMPLICIT NONE
! Define the WINIO@ function
INTEGER :: WINIO@, DRAW_MANDELBROT,LW
EXTERNAL DRAW_MANDELBROT
INTEGER :: RESULT
! Create a window with:
! %ca: Caption "Mandelbrot Set"
! %gr: Graphics region of size 800x600, calling DRAW_MANDELBROT to repaint
! %lw: Leave window open (standard termination)
RESULT = WINIO@('%ca[Mandelbrot Set]%^gr%lw', &
& 800, 600, DRAW_MANDELBROT,LW)
END PROGRAM MANDELBROT
! ----------------------------------------------------------------------
! Subroutine to draw the Mandelbrot set
! Called by ClearWin+ whenever the graphics region needs updates
! ----------------------------------------------------------------------
SUBROUTINE DRAW_MANDELBROT()
IMPLICIT NONE
INTEGER :: X, Y
INTEGER :: MAX_ITER
INTEGER :: ITER
DOUBLE PRECISION :: CX, CY, ZX, ZY, TEMP_Z
INTEGER :: COL
! External ClearWin+ functions
INTEGER :: RGB@
EXTERNAL DRAW_LINE@, RGB@
MAX_ITER = 64
! Loop through each pixel of the graphics region
! Note: This simple per-pixel drawing might be slow for very large windows
! but creates the correct output.
DO Y = 0, 599
DO X = 0, 799
! Map screen coordinates (0..799, 0..599) to complex plane
! Real part (x): approx -2.0 to 1.0
! Imag part (y): approx -1.2 to 1.2
CX = -2.0D0 + (DBLE(X) / 800.0D0) * 3.0D0
CY = -1.2D0 + (DBLE(Y) / 600.0D0) * 2.4D0
ZX = 0.0D0
ZY = 0.0D0
ITER = 0
! Iterate z = z^2 + c
DO WHILE ((ZX*ZX + ZY*ZY < 4.0D0) .AND. (ITER < MAX_ITER))
TEMP_Z = ZX*ZX - ZY*ZY + CX
ZY = 2.0D0 * ZX * ZY + CY
ZX = TEMP_Z
ITER = ITER + 1
END DO
! Determine color
IF (ITER >= MAX_ITER) THEN
COL = 0 ! Black (inside set)
ELSE
! Generate a color based on iteration count
COL = RGB@(MOD(ITER * 10, 255), &
& MOD(ITER * 5 + 50, 255), &
& MOD(ITER * 2 + 100, 255))
END IF
! Draw the pixel (using line of 0 length)
CALL DRAW_LINE@(X, Y, X, Y, COL)
END DO
END DO
END SUBROUTINE DRAW_MANDELBROT