Silverfrost Forums

Welcome to our forums

Latest Posts

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.

What's wrong here? (ClearWin+)

29 Jan 2026 6:42

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

What's wrong here? (ClearWin+)

29 Jan 2026 4:31 (Edited: 29 Jan 2026 4:44)

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.

SDBG64 defects (64-bit)

29 Jan 2026 1:55

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

64 Bit Problems (64-bit)

29 Jan 2026 1:51

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

SDBG64 defects (64-bit)

27 Jan 2026 12:58

Dan: Have same problem only cannot get sdgf step out, step over, etc. to work, just sits there and freezes?? Sid Kraft

sdbg 64 bit debug (64-bit)

27 Jan 2026 12:56

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.

Type definition for Schwartzschild equations (Code Samples)

26 Jan 2026 11:37 (Edited: 26 Jan 2026 11:39)

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

Break Point (64-bit)

26 Jan 2026 11:10

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

Break Point (64-bit)

26 Jan 2026 7:18

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.

debug/nodebug (64-bit)

25 Jan 2026 5:46

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.

debug/nodebug (64-bit)

25 Jan 2026 1:45

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

Break Point (64-bit)

25 Jan 2026 1:13

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

Windows 11? (General)

22 Jan 2026 11:46 (Edited: 23 Jan 2026 2:16)

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

The New Forum System (General)

20 Jan 2026 9:12 (Edited: 20 Jan 2026 9:38)

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