diff --git a/src/Runtime/XSharp.VFP.Tests/FoxArraytests.prg b/src/Runtime/XSharp.VFP.Tests/FoxArraytests.prg
index 353acde943..04906a9589 100644
--- a/src/Runtime/XSharp.VFP.Tests/FoxArraytests.prg
+++ b/src/Runtime/XSharp.VFP.Tests/FoxArraytests.prg
@@ -348,4 +348,117 @@ BEGIN NAMESPACE XSharp.VFP.Tests
Assert.Equal(100U, ALen(arr,1))
Assert.Equal(0U, ALen(arr,2))
END CLASS
+
+ CLASS ALinesTests
+ [Fact, Trait("Category", "ALines")];
+ METHOD BasicParsingTest() AS VOID
+ DIMENSION aTest[1]
+ LOCAL cText := e"Line1\r\nLine2\r\nLine3\r\nLine4" AS STRING
+
+ VAR nCount := aLines(aTest, cText)
+
+ Assert.Equal(4, (INT)nCount)
+ Assert.Equal(4, (INT)ALen(aTest))
+ Assert.Equal("Line1", aTest[1])
+ Assert.Equal("Line2", aTest[2])
+ Assert.Equal("Line3", aTest[3])
+ Assert.Equal("Line4", aTest[4])
+ END METHOD
+
+ [Fact, Trait("Category", "ALines")];
+ METHOD CustomSeparatorTest() AS VOID
+ DIMENSION aTest[1]
+ VAR nCount := aLines(aTest, "A,B,C", 0, ",")
+
+ Assert.Equal(3, (INT)nCount)
+ Assert.Equal("B", aTest[2])
+ END METHOD
+
+ [Fact, Trait("Category", "ALines")];
+ METHOD MultiSeparatorTest() AS VOID
+ DIMENSION aTest[1]
+ VAR nCount := aLines(aTest, "One.Two,Three;Four", 0, ".", ",", ";")
+
+ Assert.Equal(4, (INT)nCount)
+ Assert.Equal("Two", aTest[2])
+ Assert.Equal("Three", aTest[3])
+ END METHOD
+
+
+ [Fact, Trait("Category", "ALines")];
+ METHOD FlagTrimTest() AS VOID
+ DIMENSION aTest[1]
+ VAR cText := " Item1 , Item2 "
+
+ && Without Trim
+ aLines(aTest, cText, 0, ",")
+ Assert.Equal(" Item1 ", aTest[1])
+
+ && With Trim
+ aLines(aTest, cText, 1, ",")
+ Assert.Equal("Item1", aTest[1])
+ Assert.Equal("Item2", aTest[2])
+ END METHOD
+
+ [Fact, Trait("Category", "ALines")];
+ METHOD FlagNoEmptyTest() AS VOID
+ DIMENSION aTest[1]
+ VAR cText := "A,,B,,,C"
+
+ && Without flag (must include empty lines)
+ VAR nAll := aLines(aTest, cText, 0, ",")
+ Assert.Equal(6, (INT)nAll)
+
+ && With flag (just content)
+ VAR nNoEmpty := aLines(aTest, cText, 4, ",")
+ Assert.Equal(3, (INT)nNoEmpty)
+ Assert.Equal("B", aTest[2])
+ Assert.Equal("C", aTest[3])
+ END METHOD
+
+ [Fact, Trait("Category", "ALines")];
+ METHOD FlagCaseInsensitiveTest() AS VOID
+ DIMENSION aTest[1]
+ VAR cText := "User
Name
Age"
+
+ && No flag (case sensitive) -> do not cut
+ VAR nSensitive := aLines(aTest, cText, 0, "
")
+ Assert.Equal(2, (INT)nSensitive)
+
+ && With flag (case insensitive) -> cut
+ VAR nInsensitive := aLines(aTest, cText, 8, "
")
+ Assert.Equal(3, (INT)nInsensitive)
+ Assert.Equal("Age", aTest[3])
+ END METHOD
+
+ [Fact, Trait("Category", "ALines")];
+ METHOD FlagIncludeSeparatorTest() AS VOID
+ DIMENSION aTest[1]
+ VAR cText := "A,B"
+
+ VAR nCount := aLines(aTest, cText, 16, ",")
+ Assert.Equal(3, (INT)nCount)
+ Assert.Equal("A", aTest[1])
+ Assert.Equal(",", aTest[2])
+ Assert.Equal("B", aTest[3])
+ END METHOD
+
+ [Fact, Trait("Category", "ALines")];
+ METHOD FlagIncludeLastTest() AS VOID
+ DIMENSION aTest[1]
+ VAR cText := "A,B,"
+
+ && Case 1: without flag (default) -> "A", "B" (ignore last empty)
+ VAR nCount1 := aLines(aTest, cText, 0, ",")
+ Assert.Equal(2, (INT)nCount1)
+ Assert.Equal("B", aTest[2])
+
+ && Case 2: with flag -> "A", "B", "" (include last empty)
+ VAR nCount2 := aLines(aTest, cText, 2, ",")
+ Assert.Equal(3, (INT)nCount2)
+ Assert.Equal("", aTest[3])
+
+ END METHOD
+
+ END CLASS
END NAMESPACE
diff --git a/src/Runtime/XSharp.VFP/ArrayFunctions.prg b/src/Runtime/XSharp.VFP/ArrayFunctions.prg
index ddf8163e49..9706c29b21 100644
--- a/src/Runtime/XSharp.VFP/ArrayFunctions.prg
+++ b/src/Runtime/XSharp.VFP/ArrayFunctions.prg
@@ -5,6 +5,9 @@
//
USING XSharp.Internal
+USING System.Text.RegularExpressions
+USING System.Collections.Generic
+USING System.Text
INTERNAL FUNCTION FoxALen(a as ARRAY) AS DWORD
@@ -233,4 +236,92 @@ RETURN
END FUNCTION
+///
+FUNCTION ALines (ArrayName AS ARRAY, cExpression AS STRING, nFlags := 0 AS INT, cParseChars PARAMS STRING[]) AS DWORD
+ IF cExpression == null
+ cExpression := ""
+ ENDIF
+
+ VAR separators := List{}
+
+ IF cParseChars == NULL OR cParseChars:Length == 0
+ separators:Add(e"\r\n")
+ separators:Add(e"\r")
+ separators:Add(e"\n")
+ ELSE
+ separators:AddRange(cParseChars)
+ ENDIF
+
+ LOCAL lTrim := (nFlags & ALINES_TRIM) != 0 AS LOGIC // 1
+ LOCAL lIncludeLast := (nFlags & ALINES_INCLUDE_LAST) != 0 AS LOGIC // 2
+ LOCAL lNoEmpty := (nFlags & ALINES_NO_EMPTY) != 0 AS LOGIC // 4
+ LOCAL lIgnoreCase := (nFlags & ALINES_CASE_IGNORE) != 0 AS LOGIC // 8
+ LOCAL lIncludeSep := (nFlags & ALINES_INCLUDE_SEP) != 0 AS LOGIC // 16
+
+ var sbPattern := StringBuilder{}
+ FOREACH VAR sep IN separators
+ IF sbPattern:Length > 0
+ sbPattern:Append("|")
+ ENDIF
+
+ VAR safeSep := Regex.Escape(sep)
+ IF lIncludeSep
+ sbPattern:Append("(" + safeSep + ")")
+ ELSE
+ sbPattern:Append("(?:" + safeSep + ")")
+ ENDIF
+ NEXT
+
+ VAR regexOptions := RegexOptions.None
+ IF lIgnoreCase
+ regexOptions := RegexOptions.IgnoreCase
+ ENDIF
+
+ VAR aRawParts := Regex.Split(cExpression, sbPattern:ToString(), regexOptions)
+
+ VAR finalLines := List{}
+ VAR nIndex := 0
+
+ FOREACH VAR sLine IN aRawParts
+ VAR sTemp := sLine
+ VAR lIsSeparator := FALSE
+ IF lIncludeSep
+ lIsSeparator := (nIndex % 2) == 1
+ ENDIF
+
+ IF lTrim AND !lIsSeparator
+ sTemp := sTemp:Trim()
+ ENDIF
+
+ IF lNoEmpty AND String.IsNullOrEmpty(sTemp) AND !lIsSeparator
+ nIndex++
+ LOOP
+ ENDIF
+
+ finalLines:Add(sTemp)
+ nIndex++
+ NEXT
+
+ IF !lIncludeLast AND !lNoEmpty AND finalLines:Count > 0
+ VAR nLastIdx := finalLines:Count - 1
+ IF String.IsNullOrEmpty(finalLines[nLastIdx])
+ finalLines:RemoveAt(nLastIdx)
+ ENDIF
+ ENDIF
+
+ VAR nRows := (DWORD)finalLines:Count
+
+ IF nRows == 0 AND !lNoEmpty
+ nRows := 1
+ finalLines:Add("")
+ ENDIF
+
+ ASize(ArrayName, nRows)
+
+ FOR VAR i := 0 TO (INT)nRows - 1
+ ArrayName[i + 1] := finalLines[i]
+ NEXT
+
+ RETURN nRows
+END FUNCTION
diff --git a/src/Runtime/XSharp.VFP/Defines.prg b/src/Runtime/XSharp.VFP/Defines.prg
index f5fec7c0dd..fce31fe9bc 100644
--- a/src/Runtime/XSharp.VFP/Defines.prg
+++ b/src/Runtime/XSharp.VFP/Defines.prg
@@ -1490,3 +1490,10 @@ DEFINE STRCNV_UNIBE_SB := 18
DEFINE STRCNV_ID_LCID := 0
DEFINE STRCNV_ID_CODEPAGE := 1
DEFINE STRCNV_ID_CHARSET := 2
+
+// ALINES Flags
+DEFINE ALINES_TRIM := 1
+DEFINE ALINES_INCLUDE_LAST := 2
+DEFINE ALINES_NO_EMPTY := 4
+DEFINE ALINES_CASE_IGNORE := 8
+DEFINE ALINES_INCLUDE_SEP := 16
diff --git a/src/Runtime/XSharp.VFP/ToDo-A.prg b/src/Runtime/XSharp.VFP/ToDo-A.prg
index b77527bbd9..cadbcc0282 100644
--- a/src/Runtime/XSharp.VFP/ToDo-A.prg
+++ b/src/Runtime/XSharp.VFP/ToDo-A.prg
@@ -27,12 +27,6 @@ FUNCTION AGetFileVersion (ArrayName, cFileName)
THROW NotImplementedException{}
//RETURN 0
-/// -- todo --
-///
-FUNCTION ALines (ArrayName, cExpression , nFlags , cParseChar , cParseChar2 )
- THROW NotImplementedException{}
- //RETURN 0
-
/// -- todo --
///
FUNCTION AMembers (ArrayName, oObjectNameOrClassName , nArrayContentsID , cFlags)