Skip to content
This repository has been archived by the owner on Jan 13, 2024. It is now read-only.

Incorrect SetFoldLevel signature #70

Closed
Ekopalypse opened this issue May 21, 2021 · 19 comments
Closed

Incorrect SetFoldLevel signature #70

Ekopalypse opened this issue May 21, 2021 · 19 comments
Assignees
Labels
bug py-converter-update-required Python converter files under /ToolsForMaintainersOfTheProjectTemplate requires modification

Comments

@Ekopalypse
Copy link

SetFoldLevel needs to have an integer type as its second parameter instead of the FoldLevel enum.

@mahee96
Copy link
Collaborator

mahee96 commented May 23, 2021

@Ekopalypse , There are auto generated enums in GatewayDomain.cs file, this was intentional to have more meaning to the flag grouping.

public enum FoldFlag
        {
            LINEBEFORE_EXPANDED = 0x0002,
            LINEBEFORE_CONTRACTED = 0x0004,
            LINEAFTER_EXPANDED = 0x0008,
            LINEAFTER_CONTRACTED = 0x0010,
            LEVELNUMBERS = 0x0040,
            LINESTATE = 0x0080
        }

Why don't you try using it instead, if you still face issue re-open this issue.

If you strongly feel it should be int/uint as per the official interface doc of Scintilla, then please open a new issue as question because it covers more fields than the FOLDFLAG alone and needs to be dealt separately.

@mahee96 mahee96 closed this as completed May 23, 2021
@Ekopalypse
Copy link
Author

Ekopalypse commented May 23, 2021

@mahee96
But FoldFlag enum is something else and is used by the call SCI_SETFOLDFLAGS.
SCI_SETFOLDLEVEL sets the current level per line and is used to determine which rows must be must be collapsed/expanded, while FoldFlags describe how folded/expanded rows should be visually displayed.

@mahee96
Copy link
Collaborator

mahee96 commented May 23, 2021

Oops sorry for the confusion, I meant to refer you to FoldLevel enum in the Gatewaydomain.cs, Could you please check that enum satisfies your request

@mahee96
Copy link
Collaborator

mahee96 commented May 23, 2021

@Ekopalypse checkout this

/// <summary>The number of display lines needed to wrap a document line (Scintilla feature SC_FOLDLEVEL)</summary> 
public enum FoldLevel { 
     BASE = 0x400, 
     WHITEFLAG = 0x1000, 
     HEADERFLAG = 0x2000, 
     NUMBERMASK = 0x0FFF 
}

@Ekopalypse
Copy link
Author

No, these are the flags which need to be used in combination with additional integers.
Let me give you an example, assume in the following code and we want to mark the { as the open folding tag and } as the closing tag like npp does.

        public enum FoldLevel
        {
            BASE = 0x400,
            WHITEFLAG = 0x1000,
            HEADERFLAG = 0x2000,
            NUMBERMASK = 0x0FFF
        }
        

To set the respective flags you would set to line
0 -> BASE
1 -> BASE | HEADERFLAG
2 - 6 -> BASE + 1
7 -> BASE

Now scintilla knows where to put the folding markers and how many lines to collapse or fold.

@Ekopalypse
Copy link
Author

Maybe this example is more descriptive

public
{
	{
		{
			value
		}
	}
}

The lines need to be set like
0x0400
0x2400
0x2401
0x2402
0x0403
0x0403
0x0402
0x0401
0x0400

@mahee96 mahee96 pinned this issue May 24, 2021
@mahee96 mahee96 self-assigned this May 24, 2021
@mahee96 mahee96 added bug py-converter-update-required Python converter files under /ToolsForMaintainersOfTheProjectTemplate requires modification labels May 24, 2021
@mahee96
Copy link
Collaborator

mahee96 commented May 24, 2021

okay there is a slight discrepancy in Scintilla.iface file and the official documentation which we have to fix.

The documentation states:

SCI_SETFOLDLEVEL(line line, int level)
SCI_GETFOLDLEVEL(line line) → int

whereas the Scintilla.iface file states:

# Set the fold level of a line.
# This encodes an integer level along with flags indicating whether the
# line is a header and whether it is effectively white space.
set void SetFoldLevel=2222(line line, FoldLevel level)

# Retrieve the fold level of a line.
get FoldLevel GetFoldLevel=2223(line line,)

I think while updating the converter, we missed some info which states the obvious for types and enumerations.

So essentially those enumerations if in C/C++ would be not typed but plain integers which could be combined using plain pipe/or operation. But in C# it needs to be of int type as the document states.

@mahee96 mahee96 reopened this May 24, 2021
@mahee96
Copy link
Collaborator

mahee96 commented May 24, 2021

@Ekopalypse , a quick fix can be made for this particular field for now, but the inventory of affected fields will be performed later some time and a fix will be given.

@mahee96
Copy link
Collaborator

mahee96 commented May 24, 2021

@Ekopalypse, The fix is created as a pull request, review the commit and see if the issue will be resolved after this merge.

Thanks.

@Ekopalypse
Copy link
Author

@mahee96 - just to be clear, I am a C# noob.
This is my very first C# project, so my knowledge of C# is actually .... non-existent.
The PR makes an int out of the enums and, yes, that's what I need.
However, according to my research, the C# int type is a 32bit signed integer and thus is actually wrong, since Scintilla defines positions and lines as IntPtr.
But of course I can understand if someone argues that it makes little or no sense to use files with
2000 million lines, but on the other hand it may be that someone wants to write a C# plugin to scan large data and possibly edit sections in Npp.
So whatever is decided is fine with me.

@kbilsted
Copy link
Owner

I agree, we should use an enum

@mahee96
Copy link
Collaborator

mahee96 commented May 25, 2021

@Ekopalypse, That's great finding, I for once, forgot about the .NET runtime being managed and the standard int size(32-bit signed) is limiting when the actual data is a pointer type value.

In unmanaged code the int datatype is 32-bit signed on both x86/x64 but a Pointer type is dependent on the addressability ie, 32-bit unsigned on x86, 64-bit unsigned on x64.
In managed code since pointers are unsafe and not recommended a type safe IntPtr type represents the equivalent of the pointer type as in unmanaged code.

IntPtr size is machine dependent, also it is a signed integer containers which can hold unsigned pointers from unmanaged code.

So as you said, the IntPtr is the appropriate one to be used here, because even scintilla document states the same.

This should be the reason for the issue #68 where the type of the underlying marshalled call to C++ application code returns a pointer type of 8bytes on x64 which doesn't fit on the 32-bit signed integer and overflowed data is lost.

Long cannot be used since it would essentially work for 64 bit space but in 32-bit space it would again cause the same issue where the structures/layout no longer maps to the underlying data structure in memory.
ex: struct A{ int* var; int data; }; is not same as struct A{ long var; int data; } on 32-bit machine but is same in 64 bit machine when using long as a container type for pointer.

This is because in 64 bit space the struct size would be 8(int*)+4(int) = 12 bytes but on 32-bit space it will be 4(int*)+4(int) = 8 bytes. Hence this data when interpreted in managed code based on 8(long)+4(int) will always map to 12 bytes and will break the 32-bit plugin.

Reverse happens when using struct A{ int var; int data; } where 32-bit space plugins will work fine and 64-bit space plugins will break.

So using a IntPtr should take care of automatic pointer size space allocation in structs which should then provide correct mappings of layouts.

The other part to using IntPtr would be the pointer arithmetic, there is no direct pointer arithmetic such as +,- etc when dealing with IntPtr. static methods such as IntPtr.Add(ptr, off)...etc is present to handle these situations, but is not sufficient. We need to manually write the wrapper classes which perform pointer arithmetic if in case.
ex:

public class Position : IEquatable<Position>
    {
        private readonly long pos;

        public Position(IntPtr pos)
        {
            this.pos = IntPtr.Size == sizeof(Int32)? pos.ToInt32(): pos.ToInt64();
        }

        public static Position operator +(Position a, Position b)
        {
           
            return new Position(IntPtr.Size == sizeof(Int32)? new IntPtr((int)(a.pos+b.pos)): new IntPtr(a.pos+b.pos));
        }

        public static Position operator -(Position a, Position b)
        {
            return new Position(IntPtr.Size == sizeof(Int32)? new IntPtr((int)(a.pos-b.pos)): new IntPtr(a.pos-b.pos));
        }
. . . . . . . . . .

@mahee96
Copy link
Collaborator

mahee96 commented May 25, 2021

@kbilsted, I don't think its about enum anymore, its about the underlying struct mappings that are now causing problems due to mismatch in the types to be used, ex: using int is incorrect when scintilla says to use intptr_t whose equivalent in C# is IntPtr.

Let me know your thoughts on these.

@mahee96
Copy link
Collaborator

mahee96 commented May 25, 2021

+1 using IntPtr would only increase burden on the developer who is using this template, since for arithmetic they have to perform cast to long/ulong/int/uint (considering fact that pointers are unsigned) even for 32-bit (putting 4 byte pointers into 8-byte containers doesn't hurt).

@mahee96
Copy link
Collaborator

mahee96 commented May 25, 2021

Note for int, position, line scintilla states it uses intptr_t whose equivalent in C# should be IntPtr

scintilla

@mahee96 mahee96 linked a pull request May 26, 2021 that will close this issue
@Ekopalypse
Copy link
Author

Just for my understanding, there are no open issues that concern me, meaning where I should/can help or provide information?
Please do not misunderstand this post, no pressure should be built. I am aware that this is an open source project and everyone here sacrifices their free time to provide others with a helpful tool. Thank you very much for that. So if there is something where I can support, with my non-existent C# knowledge, then bring it on.

@guidomarcel
Copy link

Changing the struct as @mahee96 did in the development branch solved one of my issues. We could merge the development branch into the master branch. What do you think @kbilsted ?

@guidomarcel
Copy link

guidomarcel commented Feb 1, 2022

@kbilsted , @mahee96 one more comment. I tested the NotepadPlusPlusPluginPack. in VS2022 Community Edition succesfully

@mahee96
Copy link
Collaborator

mahee96 commented Nov 17, 2022

we are aware of this issue and will fix if it resurfaces to prevent regression.

Closing issue.

@mahee96 mahee96 closed this as completed Nov 17, 2022
@mahee96 mahee96 unpinned this issue Nov 17, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug py-converter-update-required Python converter files under /ToolsForMaintainersOfTheProjectTemplate requires modification
Projects
None yet
4 participants