|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
simon
Joined: 05 Jul 2006 Posts: 268
|
Posted: Mon Jun 07, 2021 11:32 pm Post subject: %ls list items corrupted |
|
|
The following program tries to create a drop-down list, but not all the listed items are printed correctly. The correct list is printed first, together with the number of items, and then the drop-down list is invoked. If the code in subroutine s1 is moved to the main program then the list seems to be ok.
Code: | Winapp
Program p
Use clrwin, Only: winio@
Integer, Parameter :: lc = 32, n = 10
Integer :: i, iw
Character(Len=lc), Dimension(n) :: t1
iw = winio@('%ca@&', 'List')
Call s1 ()
iw = winio@('')
Stop
Contains
Subroutine s1 ()
Do i = 1, n
Write (Unit=t1(i), Fmt='(I4)') 2000 + i
iw = winio@('%ws%nl&', t1(i))
End Do
i = 1
iw = winio@('%wd%nl%nl&', n)
iw = winio@('%`15ls%ff&', t1(:), n, i)
Return
End Subroutine s1
End Program p
|
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
Posted: Tue Jun 08, 2021 7:01 am Post subject: |
|
|
Simon
I have tested your program for both 32 bits and 64 bits and I can't see anything wrong.
I am using the latest DLLs that can be downloaded from the Support sticky post but that should not make any difference.
Passing t1( rather than just t1 seems strange to me but again that should not make any difference. |
|
Back to top |
|
|
simon
Joined: 05 Jul 2006 Posts: 268
|
Posted: Tue Jun 08, 2021 2:43 pm Post subject: |
|
|
My apologies, Paul. Somehow I posted the code that I simplified one step too far. I have been more deliberate about checking, and the list items are getting corrupted in the following (specifically 2001, 2009, and 2010 are not showing properly):
Code: | Winapp
Program p
Use clrwin, Only: winio@
Integer, Parameter :: lc = 32, n = 10
Type t
Character(Len=lc) :: c
End Type t
Type(t), Dimension(n) :: t1
Integer :: i, iw
iw = winio@('%ca@&', 'List')
Call s()
iw = winio@('')
Stop
Contains
Subroutine s()
Do i = 1, n
Write (Unit=t1(i)%c, Fmt='(I4)') 2000 + i
iw = winio@('%ws%nl&', t1(i)%c)
End Do
i = 1
iw = winio@('%wd%nl&', n)
iw = winio@('%`15ls%ff&', t1(:)%c, n, i)
Return
End Subroutine s
End Program p |
BTW, the reason I passed t1( rather than just t1 is simply for readability - I find it easier to see where and when I am passing an array rather than a scalar, and what its dimensions are. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
Posted: Tue Jun 08, 2021 5:48 pm Post subject: |
|
|
Simon
I am not surprised that this does not work. ClearWin+ expects a simple array of type CHARACTER where the length of an element is known and array elements are concatenated one after another. In this case the array is of user type with the CHARACTER variable as a member. The user type has only one member and its length is 32 so there might be no padding and you could be lucky in this instance but apparently not.
In short, you must use a simple array of type CHARACTER(len=n). |
|
Back to top |
|
|
simon
Joined: 05 Jul 2006 Posts: 268
|
Posted: Tue Jun 08, 2021 11:31 pm Post subject: |
|
|
Hi Paul,
That makes sense. I apologise for the back and forth on this question, but the following still does not work. If I move the executable lines in s1 into the main program the output is fine. So the call to s2 works from main but not from s1.
Code: | Winapp
Program p
Use clrwin, Only: winio@
Integer, Parameter :: lc = 5, n = 10
Integer :: i, iw
Type t
Character(Len=lc) :: c
End Type t
Type(t), Dimension(n) :: t1
iw = winio@('%ca@&', 'List')
Do i = 1, n
Write (Unit=t1(i)%c, Fmt='(I4)') 2000 + i
iw = winio@('%ws%nl&', t1(i)%c)
End Do
Call s1 ()
iw = winio@('')
Stop
Contains
SUbroutine s1()
i = 1
Call s2 (t1(:)%c, n, i)
Return
End Subroutine s1
Subroutine s2 (clist, n, i)
Use clrwin, Only: winio@
Integer, Intent(In) :: n
Character(Len=*), Dimension(:), Intent(In) :: clist
Integer, Intent(InOut) :: i
iw = winio@('%`15ls%ff&', clist(:), n, i)
Return
End Subroutine s2
End Program p |
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
Posted: Wed Jun 09, 2021 7:21 am Post subject: |
|
|
Simon
The array of character strings that arrives in ClearWin+ for clist in s2 is truncated so there must be something different about the size or the length parameters that are passed when you do it this way.
I don't think there is anything wrong with ClearWin+. You have simply pushed it beyond its design.
I suggest that you either simplify the coding or that you copy the strings to a simple local array before calling winio@. |
|
Back to top |
|
|
simon
Joined: 05 Jul 2006 Posts: 268
|
Posted: Wed Jun 09, 2021 10:21 pm Post subject: |
|
|
Thanks for the suggestion Paul. If I do the following then there is still a corruption. But if I move the definition of c1 into the main program then it works ok. I have reduced the program below from 100,000 lines. To declare all the relevant character arrays I would need would be quite awkward, but more specifically, it is unclear to me what the rules would be to get %ls to handle the character array properly. In the code below, I am passing %ls a character array that is uncoupled from a derived type, but why are there rules, and what are those rules, for where that array is declared? So given that my derived type declarations and calls to %ls are buried away in various modules, I am not sure how I would implement this work around in my original program.
Code: | Winapp
Program p
Use clrwin, Only: winio@
Integer, Parameter :: lc = 5, n = 10
Integer :: i, iw
Type t
Character(Len=lc) :: c
End Type t
Type(t), Dimension(n) :: t1
iw = winio@('%ca@&', 'List')
Do i = 1, n
Write (Unit=t1(i)%c, Fmt='(I4)') 2000 + i
iw = winio@('%ws%nl&', t1(i)%c)
End Do
Call s1 ()
iw = winio@('')
Stop
Contains
Subroutine s1()
Character(Len=lc), Dimension(n) :: c1
i = 1
c1(:) = t1(:)%c
Call s2 (c1(:), n, i)
Return
End Subroutine s1
Subroutine s2 (clist, n, i)
Use clrwin, Only: winio@
Integer, Intent(In) :: n
Character(Len=*), Dimension(:), Intent(In) :: clist
Integer, Intent(InOut) :: i
iw = winio@('%`15ls%ff&', clist(:), n, i
Return
End Subroutine s2
End Program p |
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
Posted: Thu Jun 10, 2021 7:32 am Post subject: |
|
|
Simon
The problem now is that the copied array of strings is temporary. For example, it works OK with the SAVE attribute...
Code: | Subroutine s1()
Character(Len=lc), Dimension(n),save :: c1
i = 1
c1 = t1%c
Call s2 (c1, n, i)
Return
End Subroutine s1 |
But you will need a SAVEd copy for each list that is in the winio@ sequence of statements for a given window.
This probably explains the original failure. Passing t1%c automatically creates a copy and the life time of the copy is not long enough for the strings to be accessed before the memory is used for something else. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
Posted: Thu Jun 10, 2021 8:21 am Post subject: |
|
|
Simon
I am thinking that it may be possible to improve ClearWin+ so that your original coding works (at least for fixed lists). ClearWin+ could make a copy of your character array when winio@ is processed so that the copy will still be live when later the window is created. It wouldn't work for editable combo boxes where there is feedback to the user's memory. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
|
Back to top |
|
|
simon
Joined: 05 Jul 2006 Posts: 268
|
Posted: Thu Jun 10, 2021 6:38 pm Post subject: |
|
|
Fantastic. Thanks Paul. Does that mean that my second posted code will work with the new version? |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
Posted: Thu Jun 10, 2021 8:31 pm Post subject: |
|
|
Yes I think so. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
Posted: Fri Jul 02, 2021 10:01 am Post subject: |
|
|
Simon
I have had to back-track on this fix. It breaks existing code that dynamically updates the list items.
In future you will need to add a new %ls option [constant_data] in order to get your code to work correctly. As you would expect, dynamic update of the list items will not be possible when this option is applied. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|