{
    Ellipsis Launcher v0.1
    Copyright (c) 2008 TopHat Stuff
    http://www.tophatstuff.co.uk/
    
    ---------------------------------------
    
    Copyright (c) 2008 Ben Golightly

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use,
    copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following
    conditions:
    
    Except as contained in this notice, the name(s) of the above
    copyright holders shall not be used in advertising or otherwise
    to promote the sale, use or other dealings in this Software
    without prior written authorization.
    
    The end-user documentation included with the redistribution, if
    any, must include the following acknowledgment: "This product
    includes software developed by TopHat Stuff and its contributors",
    in the same place and form as other third-party acknowledgments.
    Alternately, this acknowledgment may appear in the software itself,
    in the same form and location as other such third-party
    acknowledgments.

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.

}

Program(icon:"Icons\launcher.ico")
   Uses launcherLib, basilisk, keyset
               
Const

    { Theme - Fonts }    
    THEME_FONT_APPNAME = 0
    MAX_THEME_FONTS = 1
    
    { Fonts }
    FONT_SIZE = 0
    FONT_STYLE = 1
    FONT_ALIAS = 2

    { Theme - Colours }    
    THEME_RAM_FGCOLOR = 0
    THEME_RAM_BGCOLOR = 1
    THEME_TIME_FGCOLOR = 2
    THEME_TIME_BGCOLOR = 3
    THEME_APPNAME_FGCOLOR = 4
    THEME_APPNAME_BGCOLOR = 5
    MAX_THEME_COLOURS = 6

    { Theme - Coordinates }
    THEME_COORD_TITLEBAR = 0
    THEME_COORD_CLOSE = 1
    THEME_COORD_ICON = 2
    THEME_COORD_RAM = 3
    THEME_COORD_TIME = 4
    THEME_COORD_RAMIMG = 5
    THEME_COORD_TIMEIMG = 6
    MAX_THEME_COORDS = 7
    
    { Coordinates }
    X1 = 0
    Y1 = 1
    X2 = 2
    Y2 = 3
    
    { Theme - Images }  
    THEME_IMAGE_MAIN = 0
    THEME_IMAGE_CANVAS = 1
    THEME_IMAGE_RAMIMG = 2
    THEME_IMAGE_TIMEIMG = 3
    THEME_IMAGE_CLOSE_N = 4
    THEME_IMAGE_CLOSE_H = 5
    MAX_THEME_IMAGES = 6
    
    { Theme - Properties }
    THEME_PROP_APPNAME = 0
    MAX_THEME_PROPERTIES = 1
    
    { Properties }
    PROPX = 0
    PROPY = 1
    PROPCX = 2
    PROPCY = 3
    PROPS = 4
    MAX_PROPS = 5 

Type Applications = Record
    AppName : String
    AppPath : String
    AppImg : Element
    AppTextImg : Element
    AppTime : Integer
    AppTotalTime : Integer
EndType    

Var
    ApplicationList : List of Applications
    Application : ^Applications

    themeFontNames : Array[MAX_THEME_FONTS] of String
    themeFontProps : Array[MAX_THEME_FONTS,3] of Integer
    themeColour : Array[MAX_THEME_COLOURS] of Integer
    themeCoords : Array[MAX_THEME_COORDS,4] of Integer
    themeImage : Array[MAX_THEME_IMAGES] of Element
    themeProperties : Array[MAX_THEME_PROPERTIES,MAX_PROPS] of Integer
    themePropertiesB : Array[MAX_THEME_PROPERTIES,MAX_PROPS] of Boolean

Procedure Init()
Var
    xpar: String
Begin
    { Init Window }    
    SetAppName(VirtualString("win_apptitle"))   
    OpenScreen(160,100,VirtualInteger("win_depth"),FALSE,VirtualInteger("win_flags"))
    PositionScreen(VirtualInteger("win_pos"),VirtualInteger("win_xoffset"),VirtualInteger("win_yoffset"))
    FreeVirtualVariablesPrefixed("win_")
    
    { Settings }
    theme = VirtualString("opt_theme")
    themedir = VirtualString("opt_themedir")
    icodir = VirtualString("opt_icondir")
    aliasing = VirtualInteger("opt_antialiasing")
    FreeVirtualVariablesPrefixed("opt_")
    
    { Theme - Images }
    themeImage[THEME_IMAGE_MAIN] = LoadSprite(themedir+"main.png") ; Flip
    themeImage[THEME_IMAGE_CANVAS] = CreateSprite(160,100)
    themeImage[THEME_IMAGE_RAMIMG] = LoadSprite(themedir+"ram.png")
    themeImage[THEME_IMAGE_TIMEIMG] = LoadSprite(themedir+"time.png")
    themeImage[THEME_IMAGE_CLOSE_N] = LoadSprite(themedir+"close_normal.png")
    themeImage[THEME_IMAGE_CLOSE_H] = LoadSprite(themedir+"close_hover.png")
    
    { Theme - Colours }
    themeColour[THEME_RAM_FGCOLOR] = HexToRGBA(VirtualString("theme_ram_fgcolor"),VirtualInteger("theme_ram_fgalpha"))
    themeColour[THEME_RAM_BGCOLOR] = HexToRGBA(VirtualString("theme_ram_bgcolor"),VirtualInteger("theme_ram_bgalpha"))
    themeColour[THEME_TIME_FGCOLOR] = HexToRGBA(VirtualString("theme_time_fgcolor"),VirtualInteger("theme_time_fgalpha"))
    themeColour[THEME_TIME_BGCOLOR] = HexToRGBA(VirtualString("theme_time_bgcolor"),VirtualInteger("theme_time_bgalpha"))
    themeColour[THEME_APPNAME_FGCOLOR] = HexToRGBA(VirtualString("theme_appname_fgcolor"),VirtualInteger("theme_appname_fgalpha"))
    themeColour[THEME_APPNAME_BGCOLOR] = HexToRGBA(VirtualString("theme_appname_bgcolor"),VirtualInteger("theme_appname_bgalpha"))    
    
    { Theme - Fonts }
        { Appname }
        xpar = ExpressionParameters(VirtualString("theme_font_appname"))   
        themeFontNames[THEME_FONT_APPNAME] = ParameterAsString(xpar,1)
        themeFontProps[THEME_FONT_APPNAME,FONT_SIZE] = ParameterAsInteger(xpar,2)
        themeFontProps[THEME_FONT_APPNAME,FONT_STYLE] = ParameterAsInteger(xpar,3)
        themeFontProps[THEME_FONT_APPNAME,FONT_ALIAS] = ParameterAsInteger(xpar,4)
    
    { Theme - Coords }                                            
        { Titlebar }
        xpar = ExpressionParameters(VirtualString("theme_coord_titlebar"))   
        themeCoords[THEME_COORD_TITLEBAR,X1] = ParameterAsInteger(xpar,1)
        themeCoords[THEME_COORD_TITLEBAR,Y1] = ParameterAsInteger(xpar,2)
        themeCoords[THEME_COORD_TITLEBAR,X2] = ParameterAsInteger(xpar,3)+ParameterAsInteger(xpar,1)
        themeCoords[THEME_COORD_TITLEBAR,Y2] = ParameterAsInteger(xpar,4)+ParameterAsInteger(xpar,2)
        
        { Close }
        xpar = ExpressionParameters(VirtualString("theme_coord_close"))   
        themeCoords[THEME_COORD_CLOSE,X1] = ParameterAsInteger(xpar,1)
        themeCoords[THEME_COORD_CLOSE,Y1] = ParameterAsInteger(xpar,2)
        themeCoords[THEME_COORD_CLOSE,X2] = ParameterAsInteger(xpar,3)+ParameterAsInteger(xpar,1)
        themeCoords[THEME_COORD_CLOSE,Y2] = ParameterAsInteger(xpar,4)+ParameterAsInteger(xpar,2)
        PositionSprite(themeImage[THEME_IMAGE_CLOSE_N],ParameterAsInteger(xpar,1),ParameterAsInteger(xpar,2))
        PositionSprite(themeImage[THEME_IMAGE_CLOSE_H],ParameterAsInteger(xpar,1),ParameterAsInteger(xpar,2))
        SpriteAlpha(themeImage[THEME_IMAGE_CLOSE_N],255)
        SpriteAlpha(themeImage[THEME_IMAGE_CLOSE_H],0)
        
        { Icon }
        xpar = ExpressionParameters(VirtualString("theme_coord_icon"))   
        themeCoords[THEME_COORD_ICON,X1] = ParameterAsInteger(xpar,1)
        themeCoords[THEME_COORD_ICON,Y1] = ParameterAsInteger(xpar,2)

        { Ram Img }
        xpar = ExpressionParameters(VirtualString("theme_coord_ram_img"))   
        themeCoords[THEME_COORD_RAMIMG,X1] = ParameterAsInteger(xpar,1)
        themeCoords[THEME_COORD_RAMIMG,Y1] = ParameterAsInteger(xpar,2)
        PositionSprite(themeImage[THEME_IMAGE_RAMIMG],themeCoords[THEME_COORD_RAMIMG,X1],themeCoords[THEME_COORD_RAMIMG,Y1])

        { Ram }
        xpar = ExpressionParameters(VirtualString("theme_coord_ram"))   
        themeCoords[THEME_COORD_RAM,X1] = ParameterAsInteger(xpar,1)
        themeCoords[THEME_COORD_RAM,Y1] = ParameterAsInteger(xpar,2)
        themeCoords[THEME_COORD_RAM,X2] = ParameterAsInteger(xpar,3)
        themeCoords[THEME_COORD_RAM,Y2] = ParameterAsInteger(xpar,4)

        { Time Img }
        xpar = ExpressionParameters(VirtualString("theme_coord_time_img"))   
        themeCoords[THEME_COORD_TIMEIMG,X1] = ParameterAsInteger(xpar,1)
        themeCoords[THEME_COORD_TIMEIMG,Y1] = ParameterAsInteger(xpar,2)
        PositionSprite(themeImage[THEME_IMAGE_TIMEIMG],themeCoords[THEME_COORD_TIMEIMG,X1],themeCoords[THEME_COORD_TIMEIMG,Y1])

        { Time }
        xpar = ExpressionParameters(VirtualString("theme_coord_time"))   
        themeCoords[THEME_COORD_TIME,X1] = ParameterAsInteger(xpar,1)
        themeCoords[THEME_COORD_TIME,Y1] = ParameterAsInteger(xpar,2)
        themeCoords[THEME_COORD_TIME,X2] = ParameterAsInteger(xpar,3)
        themeCoords[THEME_COORD_TIME,Y2] = ParameterAsInteger(xpar,4)
    
    { Theme - Properties }
        { Appname }
        xpar = ExpressionParameters(VirtualString("theme_appname"))   
        themeProperties[THEME_PROP_APPNAME,PROPX] = ParameterAsInteger(xpar,1)
        themeProperties[THEME_PROP_APPNAME,PROPY] = ParameterAsInteger(xpar,2)
        themePropertiesB[THEME_PROP_APPNAME,PROPCX] = ParameterAsBoolean(xpar,3)
        themePropertiesB[THEME_PROP_APPNAME,PROPCY] = ParameterAsBoolean(xpar,4)
        themePropertiesB[THEME_PROP_APPNAME,PROPS] = ParameterAsBoolean(xpar,5)
                 
           
    FreeVirtualVariablesPrefixed("theme_")
    
    { Data }
    While VirtualVariableExists("EAPPLICATION")
        xpar = ExpressionParameters(VirtualString("EAPPLICATION"))        
        AddApplication(ParameterAsString(xpar,1), ParameterAsString(xpar,2), ParameterAsString(xpar,3), ParameterAsInteger(xpar,4))
        FreeVirtualVariable("EAPPLICATION")
    Wend
    
    FreeVirtualVariables()
End

Procedure AddApplication(apath:String, aname:String, aimg: String, apause:Integer)
Begin
    Application = NewItem(ApplicationList)
    If Assigned(Application)
        Application.AppName = aname
        Application.AppPath = apath
        
        If FileExists(icodir+""+aimg) Then
            Application.AppImg = LoadSprite(icodir+""+aimg)
            PositionSprite(Application.AppImg,themeCoords[THEME_COORD_ICON,X1],themeCoords[THEME_COORD_ICON,Y1])
            SpriteAlpha(Application.AppImg,0)
            
            Application.AppTextImg = CreateSprite(160,100)

            AADraw(themeFontProps[THEME_FONT_APPNAME,FONT_ALIAS])
            SetFont(themeFontNames[THEME_FONT_APPNAME],themeFontProps[THEME_FONT_APPNAME,FONT_SIZE],themeFontProps[THEME_FONT_APPNAME,FONT_STYLE],Application.AppTextImg)
            
            PenColor(themeColour[THEME_APPNAME_BGCOLOR],Application.AppTextImg)
            If (themePropertiesB[THEME_PROP_APPNAME,PROPS]=1) then JustifiedText(themeProperties[THEME_PROP_APPNAME,PROPX]+1,themeProperties[THEME_PROP_APPNAME,PROPY]+1,Application.AppName,themePropertiesB[THEME_PROP_APPNAME,PROPCX],themePropertiesB[THEME_PROP_APPNAME,PROPCY],Application.AppTextImg)
            If (themePropertiesB[THEME_PROP_APPNAME,PROPS]=1) then JustifiedText(themeProperties[THEME_PROP_APPNAME,PROPX]+0,themeProperties[THEME_PROP_APPNAME,PROPY]+1,Application.AppName,themePropertiesB[THEME_PROP_APPNAME,PROPCX],themePropertiesB[THEME_PROP_APPNAME,PROPCY],Application.AppTextImg)
            If (themePropertiesB[THEME_PROP_APPNAME,PROPS]=1) then JustifiedText(themeProperties[THEME_PROP_APPNAME,PROPX]-1,themeProperties[THEME_PROP_APPNAME,PROPY]+1,Application.AppName,themePropertiesB[THEME_PROP_APPNAME,PROPCX],themePropertiesB[THEME_PROP_APPNAME,PROPCY],Application.AppTextImg)
            If (themePropertiesB[THEME_PROP_APPNAME,PROPS]=1) then JustifiedText(themeProperties[THEME_PROP_APPNAME,PROPX]+1,themeProperties[THEME_PROP_APPNAME,PROPY]-1,Application.AppName,themePropertiesB[THEME_PROP_APPNAME,PROPCX],themePropertiesB[THEME_PROP_APPNAME,PROPCY],Application.AppTextImg)
            If (themePropertiesB[THEME_PROP_APPNAME,PROPS]=1) then JustifiedText(themeProperties[THEME_PROP_APPNAME,PROPX]+0,themeProperties[THEME_PROP_APPNAME,PROPY]-1,Application.AppName,themePropertiesB[THEME_PROP_APPNAME,PROPCX],themePropertiesB[THEME_PROP_APPNAME,PROPCY],Application.AppTextImg)
            If (themePropertiesB[THEME_PROP_APPNAME,PROPS]=1) then JustifiedText(themeProperties[THEME_PROP_APPNAME,PROPX]-1,themeProperties[THEME_PROP_APPNAME,PROPY]-1,Application.AppName,themePropertiesB[THEME_PROP_APPNAME,PROPCX],themePropertiesB[THEME_PROP_APPNAME,PROPCY],Application.AppTextImg)
            
            PenColor(themeColour[THEME_APPNAME_FGCOLOR],Application.AppTextImg)
            JustifiedText(themeProperties[THEME_PROP_APPNAME,PROPX],themeProperties[THEME_PROP_APPNAME,PROPY],Application.AppName,themePropertiesB[THEME_PROP_APPNAME,PROPCX],themePropertiesB[THEME_PROP_APPNAME,PROPCY],Application.AppTextImg)

            AADraw(aliasing)
            
            SpriteAlpha(Application.AppTextImg,0)
        Else
            Error("Fatal Error: Could not load icon "+aimg+" at path "+icodir+""+aimg)
            RequestExit
        Endif
        
        Application.AppTime = apause
        Application.AppTotalTime = Application.AppTime
    Else
        Error("Fatal Error: Could not add application to list")
        RequestExit
    Endif
End

Procedure Update()
Var
    timepassed : Integer
Begin
    timepassed = Millisecs - lasttime
    
    If (CountList(ApplicationList) > 0) then
        Application = FirstItem(ApplicationList)
       
        SpriteAlpha(Application.AppImg,255)
        SpriteAlpha(Application.AppTextImg,255)

        If (timepassed > 1000) then
            lasttime = Millisecs
            
            Application.AppTime = Application.AppTime - 1
            UpdateDisplay(Application.AppTime, Application.AppTotalTime)
            
            If Application.AppTime < 0 then
                FreeSprite(Application.AppImg)
                FreeSprite(Application.AppTextImg)
                If Application.AppPath <> "NONE" Then
                    ExecFile(Application.AppPath,-1)
                Endif  
                Free(Application)
                UpdateDisplay()
            Endif
        Endif

    Else
        RequestExit
    Endif
End

Procedure UpdateDisplay(ptime: Integer=1, total: Integer=1)
Var
    ram : Real
    rtime : Real
Begin
    CLS(ToRGBA(0,0,0,0),themeImage[THEME_IMAGE_CANVAS])
    
    If MemorySize(1) > 0 then
        ram = ToReal(MemorySize(1)) / ToReal(MemorySize(0)) * ToReal(themeCoords[THEME_COORD_RAM,X2])
    Else
        ram = 0
    Endif
    
    If total > 0 then
        rtime = ToReal(ptime) / ToReal(total) * ToReal(themeCoords[THEME_COORD_TIME,X2])
    Else
        rtime = 0
    Endif
    
    { Ram Back }
    Rect(themeCoords[THEME_COORD_RAM,X1],themeCoords[THEME_COORD_RAM,Y1],themeCoords[THEME_COORD_RAM,X2],themeCoords[THEME_COORD_RAM,Y2],themeColour[THEME_RAM_BGCOLOR],TRUE,themeImage[THEME_IMAGE_CANVAS])

    { Ram Front }
    Rect(themeCoords[THEME_COORD_RAM,X1],themeCoords[THEME_COORD_RAM,Y1],ToInt(ram),themeCoords[THEME_COORD_RAM,Y2],themeColour[THEME_RAM_FGCOLOR],TRUE,themeImage[THEME_IMAGE_CANVAS])
    
    { Time Back }
    Rect(themeCoords[THEME_COORD_TIME,X1],themeCoords[THEME_COORD_TIME,Y1],themeCoords[THEME_COORD_TIME,X2],themeCoords[THEME_COORD_TIME,Y2],themeColour[THEME_TIME_BGCOLOR],TRUE,themeImage[THEME_IMAGE_CANVAS])    

    { Time Front }
    Rect(themeCoords[THEME_COORD_TIME,X1],themeCoords[THEME_COORD_TIME,Y1],ToInt(rtime),themeCoords[THEME_COORD_TIME,Y2],themeColour[THEME_TIME_FGCOLOR],TRUE,themeImage[THEME_IMAGE_CANVAS])
    
End

Procedure UpdateMouse()
Var
    mx, my : Integer
    mh, md : Boolean
    
    { Move }
    ofx, ofy : Static Integer
	mov, nomov : Static Boolean   
Begin
    mx = MouseX
    my = MouseY
    mh = (MouseHits()>0)
    md = MouseDown()


    { Move Window }
    If mov then
       	If (mx <> 0) then ScreenX(ScreenX+mx-ofx)
        If (my <> 0) then ScreenY(ScreenY+my-ofy)
        mov = md
    Else
      	ofx = mx
	    ofy = my
    Endif

	If md and (MouseIn(mx,my,themeCoords[THEME_COORD_TITLEBAR,X1],themeCoords[THEME_COORD_TITLEBAR,Y1],themeCoords[THEME_COORD_TITLEBAR,X2],themeCoords[THEME_COORD_TITLEBAR,Y2])=FALSE) then nomov = TRUE
    If (md = FALSE) then nomov = FALSE
    If md and MouseIn(mx,my,themeCoords[THEME_COORD_TITLEBAR,X1],themeCoords[THEME_COORD_TITLEBAR,Y1],themeCoords[THEME_COORD_TITLEBAR,X2],themeCoords[THEME_COORD_TITLEBAR,Y2]) and (nomov=FALSE) then mov = TRUE
    
    
    { Close }
    If MouseIn(mx,my,themeCoords[THEME_COORD_CLOSE,X1],themeCoords[THEME_COORD_CLOSE,Y1],themeCoords[THEME_COORD_CLOSE,X2],themeCoords[THEME_COORD_CLOSE,Y2]) then
        SpriteAlpha(themeImage[THEME_IMAGE_CLOSE_N],0)
        SpriteAlpha(themeImage[THEME_IMAGE_CLOSE_H],255)
        If mh then RequestExit
    Else    
        SpriteAlpha(themeImage[THEME_IMAGE_CLOSE_N],255)
        SpriteAlpha(themeImage[THEME_IMAGE_CLOSE_H],0)
    Endif
End

Var
    aliasing : Integer
    theme : String
    themedir : String
    icodir : String
    timestart : Integer
    lasttime : Integer
Begin

    InitBasilisk(TRUE)
    ReadSettings("Config\Launcher\init.bsd")
    Init()
    AADraw(aliasing)
    UpdateDisplay()
    FlushMouse()
    timestart = Millisecs
    lasttime = timestart

    While Not ExitRequested        
        Update()
        UpdateMouse()
        Flip
        Pause(1)
        If (KeyHits(VK_ESCAPE) > 0) then RequestExit 
    Wend
   
End
