#include once "windows.bi"

enum QListAction
    acAdd,acRemove,acInsert,acExchange,acClear,acModified
end enum

type QListEvent as sub(byref as object,as QListAction)

type PList as QList ptr
type QList extends Object
    protected:
    as integer fcount
    as any ptr fItems(any)
    public:
    as any ptr Owner
    declare property count as integer
    declare property count (as integer)
    declare property item(as integer) as any ptr
    declare property item(as integer, as any ptr)
    declare sub Add(as any ptr)
    declare sub Remove(as any ptr)
    declare sub Insert(as integer,as any ptr)
    declare sub Clear
    declare sub Exchange(index1 as any ptr,index2 as any ptr)
    declare function IndexOf(as any ptr) as integer
    declare operator cast as any ptr
    declare constructor
    declare destructor
    as QListEvent onChange
end type

type PStringList as QStringList ptr
type QStringList extends Object
    protected:
    as integer fcount
    as any ptr fobjects(any)
    as string fItems(any)
    public:
    as any ptr Owner
    declare property count as integer
    declare property count (as integer)
    declare property item(as integer) as string
    declare property item(as integer, as string)
    declare property object(as integer) as any ptr
    declare property object(as integer, as any ptr)
    declare sub Add(as string,as any ptr=0)
    declare sub Remove(as string)
    declare sub Insert(as integer,as string,as any ptr=0)
    declare sub Clear
    declare sub Exchange(index1 as string,index2 as string)
    declare sub Parse(as byte,s as string)
    declare function IndexOf(as string) as integer
    declare function IndexOfObject(as any ptr) as integer
    declare function IndexOfString(as string) as integer
    declare operator let(as string)
    declare operator cast as string
    declare operator cast as any ptr
    declare constructor
    declare destructor
    as QListEvent onChange
end type

/'QList'/
sub QList.Exchange(index1 as any ptr,index2 as any ptr)
    dim as any ptr it1,it2
    dim as integer i1=indexof(index1),i2=indexof(index2)
    If (i1 >= fCount) or (i1 < 0) or (i2 >= fCount) or (i2 < 0) then
       MessageBox GetActiveWindow ,"Out of range. Invalid string index.","QList",mb_iconerror or mb_topmost or mb_taskmodal or mb_applmodal
       Exit Sub
    End If
    it1=fitems(i1)
    it2=fitems(i2)
    fitems(i1)=it2
    fitems(i2)=it1
    if onchange then onchange(this,acExchange)
end sub

sub QList.Remove(v as any ptr)
    dim as integer x=indexof(v)
    for i as integer=x to ubound(fitems)-1
        fitems(i)=fitems(i+1)
    next
    redim preserve fitems(ubound(fitems)-1)
    if onchange then onchange(this,acRemove)
end sub

sub QList.Insert(idx as integer,v as any ptr)
    if idx>-1 and idx<ubound(fitems) then
       redim preserve fitems(ubound(fitems)+1)
       for i as integer=idx+1 to ubound(fitems)-1
           fitems(i)=fitems(i+1)
       next
       fitems(idx)=v
       if onchange then onchange(this,acInsert)
    else
        messageBox(getactivewindow,"Index out of range." & idx,"QList",mb_iconerror or mb_topmost or mb_applmodal or mb_taskmodal)
    end if
end sub

property QList.count as integer
    if ubound(fitems)>0 then fcount=ubound(fitems) else fcount=0
    return fcount
end property

property QList.count (v as integer)
    fcount=v
    redim preserve fitems(v)
    if onchange then onchange(this,acModified)
end property

property QList.item(i as integer) as any ptr
    if i>-1 and i<ubound(fitems) then
       return fitems(i)
    else
       messageBox(getactivewindow,"Index out of range." & i & ".." & ubound(fitems),"QList",mb_iconerror or mb_topmost or mb_applmodal or mb_taskmodal)
    end if
end property

property QList.item(i as integer,v as any ptr)
    if i>-1 and i<ubound(fitems) then
       fitems(i)=v
       if onchange then onchange(this,acModified)
    else
       messageBox(getactivewindow,"Index out of range." & i & ".." & ubound(fitems),"QList",mb_iconerror or mb_topmost or mb_applmodal or mb_taskmodal)
    end if
end property

sub QList.Clear
    erase fitems
    redim fitems(0)
    fcount=0
    if onchange then onchange(this,acRemove)
end sub

function QList.IndexOf(v as any ptr) as integer
    for i as integer=0 to ubound(fitems)-1
        if fitems(i)=v then return i
    next
    return -1
end function

sub QList.Add(v as any ptr)
    fcount+=1
    redim preserve fitems(fcount)
    fitems(fcount-1)=v
    if onchange then onchange(this,acAdd)
end sub

operator QList.cast as any ptr
    return @this
end operator

constructor QList
    clear
end constructor

destructor QList
    Clear
end destructor

/'QStringList'/
sub QStringList.Exchange(index1 as string,index2 as string)
    dim as string it1,it2
    dim as any ptr o1,o2
    dim as integer i1=indexof(index1),i2=indexof(index2)
    If (i1 >= fCount) or (i1 < 0) or (i2 >= fCount) or (i2 < 0) then
       MessageBox GetActiveWindow ,"Out of range. Invalid string index.","QList",mb_iconerror or mb_topmost or mb_taskmodal or mb_applmodal
       Exit Sub
    End If
    o1=fobjects(i1)
    o2=fobjects(i2)
    fobjects(i1)=o2
    fobjects(i2)=o1
    it1=fitems(i1)
    it2=fitems(i2)
    fitems(i1)=it2
    fitems(i2)=it1
    if onchange then onchange(this,acExchange)
end sub

property QStringList.count as integer
    if ubound(fitems)>0 then fcount=ubound(fitems) else fcount=0
    return fcount
end property

property QStringList.count (v as integer)
    fcount=v
    redim preserve fitems(v)
    if onchange then onchange(this,acModified)
end property

property QStringList.item(i as integer) as string
    if i>-1 and i<ubound(fitems) then
       return fitems(i)
    else
       messageBox(getactivewindow,"Index out of range." & i & ".." & ubound(fitems),"QStringList",mb_iconerror or mb_topmost or mb_applmodal or mb_taskmodal)
    end if
end property

property QStringList.item(i as integer,v as string)
    if i>-1 and i<ubound(fitems) then
       fitems(i)=v
       if onchange then onchange(this,acModified)
    else
       messageBox(getactivewindow,"Index out of range." & i & ".." & ubound(fitems),"QStringList",mb_iconerror or mb_topmost or mb_applmodal or mb_taskmodal)
    end if
end property

property QStringList.object(i as integer) as any ptr
    if i>-1 and i<ubound(fobjects) then
       return fobjects(i)
    else
       messageBox(getactivewindow,"Index out of range." & i & ".." & ubound(fitems),"QStringList",mb_iconerror or mb_topmost or mb_applmodal or mb_taskmodal)
    end if
end property

property QStringList.object(i as integer,v as any ptr)
    if i>-1 and i<ubound(fobjects) then
       fobjects(i)=v
       if onchange then onchange(this,acModified)
    else
       messageBox(getactivewindow,"Index out of range." & i & ".." & ubound(fitems),"QStringList",mb_iconerror or mb_topmost or mb_applmodal or mb_taskmodal)
    end if
end property

sub QStringList.Add(v as string,o as any ptr=0)
    fcount+=1
    redim preserve fitems(fcount)
    fitems(fcount-1)=v
    redim preserve fobjects(fcount)
    fobjects(fcount-1)=o
    if onchange then onchange(this,acAdd)
end sub

sub QStringList.Remove(v as string)
    dim as integer x=indexof(v)
    for i as integer=x to ubound(fitems)-1
        fitems(i)=fitems(i+1)
    next
    for i as integer=x to ubound(fobjects)-1
        fobjects(i)=fobjects(i+1)
    next
    redim preserve fitems(ubound(fitems)-1)
    redim preserve fobjects(ubound(fobjects)-1)
    if onchange then onchange(this,acRemove)
end sub

sub QStringList.Insert(idx as integer,v as string,o as any ptr=0)
    if idx>-1 and idx<ubound(fitems) then
       redim preserve fitems(ubound(fitems)+1)
       redim preserve fobjects(ubound(fobjects)+1)
       for i as integer=idx+1 to ubound(fitems)-1
           fitems(i)=fitems(i+1)
       next
       fitems(idx)=v
       for i as integer=idx+1 to ubound(fobjects)-1
           fobjects(i)=fobjects(i+1)
       next
       fobjects(idx)=o
       if onchange then onchange(this,acInsert)
    else
        messageBox(getactivewindow,"Index out of range." & idx,"QStringList",mb_iconerror or mb_topmost or mb_applmodal or mb_taskmodal)
    end if
end sub

sub QStringList.Clear
    erase fitems
    erase fobjects
    redim fitems(0)
    redim fobjects(0)
    fcount=0
    if onchange then onchange(this,acClear)
end sub

function QStringList.IndexOf(v as string) as integer
    for i as integer=0 to ubound(fitems)-1
        if lcase(fitems(i))=lcase(v) then return i
    next
    return -1
end function

function QStringList.IndexOfObject(v as any ptr) as integer
    for i as integer=0 to ubound(fobjects)-1
        if fobjects(i)=v then return i
    next
    return -1
end function

function QStringList.IndexOfString(v as string) as integer
    for i as integer=0 to ubound(fitems)-1
        if fitems(i)=v then return i
    next
    return -1
end function

sub QStringList.Parse(v as byte,s as string)
    clear
    dim as string temp=""
    for i as integer=0 to len(s)
        if s[i]=v then
           temp=temp+chr(10)
        else
           temp=temp+chr(s[i])
        end if
    next
    this=temp
    if onchange then onchange(this,acModified)
end sub

operator QStringList.cast as string
    dim as string s=""
    for i as integer=0 to fcount-1
        if i<fcount-1 then
           s=s+fitems(i)+chr(10)
        elseif i=fcount-1 then
           s=s+fitems(i)+chr(0)
        end if
    next
    return s
end operator

operator QStringList.let(v as string)
    clear
    dim as string s=""
    for i as integer=0 to len(v)
        s=s+chr(v[i])
        if v[i]=10 or i=len(v) then
           if i<len(v) then s=mid(s,1,len(s)-1)
           fcount+=1
           redim preserve fitems(fcount)
           fitems(fcount-1)=s
           redim preserve fobjects(fcount)
           s=""
        end if
    next
    if onchange then onchange(this,acModified)
end operator

operator QStringList.cast as any ptr
    return @this
end operator

constructor QStringList
    clear
end constructor

destructor QStringList
    Clear
end destructor