click here for a plain text version
$my_version = "2.6"
$my_shortname = "corz clock" ; used in quite a few places
$data_parent = @AppDataDir & "\corz\" & $my_shortname ; like here

#cs
    corz clock (I made it my own!)

    for more information, see here..
    http://corz.org/windows/software/clock/

    If you are compiling this yourself, you need to use "AutoIt Wrapper"
    to add the extra icons. You will also need to use AT LEAST version
    1.9.3 of AutoIt Wrapper for the paths to work correctly. You can
    download it here..

        http://www.autoitscript.com/autoit3/scite/downloads.shtml

    have fun!

    ;o)

    © 2007-> Cor @ corz.org ;o)

#ce


##include <Constants.au3>
##include <GUIConstants.au3>

    const $TRAY_EVENT_PRIMARYDOWN = -7

    const $GUI_EVENT_CLOSE = -3
    const $GUI_EVENT_PRIMARYDOWN = -7
    const $GUI_EVENT_DROPPED = -13
    const $GUI_CHECKED = 1
    const $GUI_UNCHECKED = 4
    const $GUI_DROPACCEPTED = 8
    const $GUI_FOCUS = 256
    const $GUI_SHOW = 16
    const $GUI_HIDE = 32
    const $GUI_ENABLE = 64
    const $GUI_DISABLE = 128

    const $LBS_SORT        = 0x0002
    const $LBS_NOTIFY        = 0x0001

    const $WS_VSCROLL = 0x00200000
    const $WS_CAPTION = 0x00C00000
    const $WS_POPUP = 0x80000000
    const $WS_EX_ACCEPTFILES = 0x00000010
    const $WS_EX_TOOLWINDOW = 0x00000080
    const $WS_EX_TOPMOST = 0x00000008
    const $WS_BORDER    = 0x00800000

    const $ES_LEFT    = 0
    const $ES_NUMBER = 8192
    const $ES_AUTOHSCROLL = 128

    const $CBS_DROPDOWN = 0x0002
    const $CBS_AUTOHSCROLL = 0x0040
    const $CBS_SORT = 0x0100

    const $SS_CENTER = 1
    const $SS_NOTIFY = 0x0100

    const $BS_CENTER = 0x0300
    const $BS_PUSHLIKE = 0x1000
    const $BS_VCENTER = 0x0C00

    const $TCS_FLATBUTTONS = 0x0008
    const $TCS_HOTTRACK = 0x0040
    const $TCS_BUTTONS = 0x0100
    const $TCS_TOOLTIPS = 0x4000

    const $TBS_NOTICKS = 0x0010

    ; user32.dll constants (for drag)
    const $HTCAPTION        = 2
    const $WM_NCLBUTTONDOWN    = 0xA1

#include "Include\corz_essentials.au3"
#include "Include\color pickin chooser.au3"
#include "Include\corz_gui_fx.au3"
#include "Include\corz_colors.au3"
#include "Include\corz_tips.au3"
#include <Date.au3>

AutoItSetOption("GUIOnEventMode", 1)
AutoItSetOption("TrayOnEventMode", 1)
AutoItSetOption("TrayMenuMode", 9)

; get ini(t) values..
;
func clock_ini() ; dummy function so I can jump here in my editor ;o)
endfunc
;

if not FileExists($data_parent) then DirCreate($data_parent)
$ini_path = $data_parent & "\" & $my_shortname & ".ini"
global $prefs_open = false ; a nice idea

; got ini?..
FileInstall(".\stuff\clock-default.ini"$ini_path, 0)

; got noise?
if not FileExists($data_parent & "\alerts") then DirCreate($data_parent & "\alerts")
FileInstall(".\stuff\alarm.wav"$data_parent & "\alerts\alarm.wav", 0)
FileInstall(".\stuff\clockchime.wav"$data_parent & "\alerts\chime.wav", 0)

; got tips?
FileInstall(".\stuff\clock-tips.txt"$data_parent & "\tips.txt", 0)
global $tips_file = $data_parent & "\tips.txt"
$no_tips = IniReadCheckboxValue($ini_path$my_shortname"no_tips"$GUI_UNCHECKED)

; and alerts?
$ini_path_alerts = $data_parent & "\alerts.ini"
if not FileExists($ini_path_alerts) then FileInstall(".\stuff\default-alerts.ini"$ini_path_alerts, 0)

global $AlarmStatus[3] = ["Off""On", 0]; off, on, and currently selected
global $chimes_status[5] = ["""On""""""Off"; checkbox logic is funner!
global $check_master_enabled$check_chimes$keys_unset

$size = IniRead($ini_path$my_shortname"size", 250)
$clock_x = IniRead($ini_path$my_shortname"x", @DesktopWidth/2 - $size)
$clock_y = IniRead($ini_path$my_shortname"y", @DesktopHeight/2 - $size)

if ($size < 10) or ($size > @DesktopWidth) then
    $size = 250
    $clock_x = -1
    $clock_y = -1
endif

$fade_in = IniReadCheckboxValue($ini_path$my_shortname"fade_in", 1)
$start_with_windows = IniReadCheckboxValue($ini_path$my_shortname"start_with_windows", 0)

$on_top = IniReadCheckboxValue($ini_path$my_shortname"always_on_top", 0)
$click_drag_to_move = IniReadCheckboxValue($ini_path$my_shortname"click_drag_to_move", 4)
$do_chime =  IniReadCheckboxValue($ini_path$my_shortname"do_chime", 1)
$chime_minute = IniRead($ini_path$my_shortname"chime_minute""00")
if $chime_minute = 0 then $chime_minute = "00"

; these will likely be overridden..
$speech_voice = IniRead($ini_path$my_shortname"speech_voice""Sam")
$speech_volume = IniRead($ini_path$my_shortname"speech_volume", 50)
$speech_rate = IniRead($ini_path$my_shortname"speech_rate", 0)
$chime_done = 0
$current_preset = IniRead($ini_path$my_shortname"current_preset""unsaved alarm")
$missed_minutes = IniRead($ini_path$my_shortname"missed_minutes", 60)

global $previous_combo_alarms[501] = [500] ; for storing previous combobox selections
global $previous_combo_schemes[501] = [500] ; redimming is slow, memory is cheap.
global $previous_combo_alerts[501] = [500]

; and what about those schemes..
$current_scheme = IniRead($ini_path$my_shortname"scheme""default")
$ini_path_schemes = @AppDataDir & "\corz\" & $my_shortname & "\schemes.ini"
FileInstall(".\stuff\default-schemes.ini"$ini_path_schemes, 0)
global $uncheck_item = 0

global $recent_collection = IniRead($ini_path$my_shortname"recent_collection""corz clock collected settings")

$mid = $size / 2 ;radius
$ClockActive = 1
$gdi_dll = DllOpen("gdi32.dll")
$user32_dll = DllOpen("user32.dll")
const $PI = 3.1415926535897932384626433832795 ; accuracy! :/
global $last_alarm_min$play_idx$last_exclusion

LoadScheme($current_scheme)

global $Labels[13], $Sec
global $OldFontSize$Radius = $mid
global $MousePos$WinPos$PosDiff[2]

; work-around for Aero + GetPixel() = soup..
$vista = false
if StringInStr(@OSVersion, "vista") then $vista = true
global $disable_cpc = IniReadCheckboxValue($ini_path_schemes$current_scheme"disable_cpc"$GUI_UNCHECKED)


$ini_path_alarms = $data_parent & "\alarms.ini"
$AlarmStatus[2] = IniRead($ini_path$my_shortname"alarms_active", 1)
$alert = IniRead($ini_path$my_shortname"alert""simple")

StopSound()
GetAlarms()

; create the gui..
;
$gui = GUICreate($my_shortname$mid*2, $mid*2, $clock_x$clock_y$WS_POPUP$WS_EX_TOOLWINDOW)

; gui events..
;
GUISetOnEvent($GUI_EVENT_PRIMARYDOWN"Drag"$gui; dodgy

; basic appearance..
GUISetBkColor("0x" & $face_color)
GUISetFont($mid/15, 800)


$a = CreateRoundRectRgn(0, 0, $mid*2, $mid*2, $mid*2, $mid*2)
SetWindowRgn($gui$a)

$curSecX = $mid + Cos(TimeTorad("sec", @SEC)) * $SecRad
$curSecY = $mid - Sin(TimeTorad("sec", @SEC)) * $SecRad
$curMinX = $mid + Cos(TimeTorad("min", @MIN)) * $MinRad
$curMinY = $mid - Sin(TimeTorad("min", @MIN)) * $MinRad
$curHourX = $mid + Cos(TimeTorad("hour", @HOUR)) * $HourRad
$curHourY = $mid - Sin(TimeTorad("hour", @HOUR)) * $HourRad

#cs
sometimes restart won't work because the old instance is still doing *feck knows
what* as it finishes up. clearly, putting this inside the $switch cases would
prevent this, at the possible cost of having the old instance hang around for a
wee while. But that's stupid; if clock is running after "restart", you could
easily launch a second instance by clicking the icon. Bugger!
#ce
; pfff..
ce_Singleton("corzclock", 1)

; command-line parameters..
$switch = ""
$startup_tips = false
if $CmdLine[0] then $switch = $CmdLine[$CmdLine[0]]
debug(@ScriptLineNumber & ": " & "switch: " & "->" & $switch & "<-"; & @CRLF

switch $switch ; I've been dying to do this for ages! haha
    case "restart"
        GUISetState(@SW_SHOW, $gui)
    case "startup"
        Sleep(5000) ; we'll give the system time to get itself together
        continuecase
    case else
        CheckMissedAlarms()
        FadeIn()
        $startup_tips = true
endswitch

; main context menu..
;
global $ContextMenu
ContextMenuMain()

; system tray..
;
SystemTrayMain()

DrawNumerals()
UpdateTrans()
AllThatGoodStuff(1)

; Toggle The Toggles! (I like this reset technique)
ToggleOnTop(1)
ToggleOnTop(1)
ToggleStartWithWindows(1)
ToggleStartWithWindows(1)
ToggleFadeAtStartup(1)
ToggleFadeAtStartup(1)
ToggleClickDrag(1)
ToggleClickDrag(1)
ToggleChime(1)
ToggleChime(1)


; tricks and tips..
if $startup_tips and $no_tips = $GUI_UNCHECKED or ce_IsPressed(10) then
    ShowTips()
endif


; see notes inside CheckClockStuff()..
SetHotKeys()


; main loop..
$audio_check = 0
while 1
    CheckClockStuff()
    Sleep(25)
    $audio_check +=1
    if $audio_check >= 500 then
        ; delete any temporary wavs, if sound is stopped.
        CheckSound() ; around two checks a minute
    $audio_check = 0
    endif
wend


; fin!


func CheckClockStuff($special=0)

    if not WinActive($gui) then $ClockActive = 0
    if WinActive($gui) and $ClockActive = 0 then
        AllThatGoodStuff(2)
        $ClockActive = 1
        if $keys_unset = 1 then
            SetHotKeys()
            $keys_unset = 0
        endif
    endif
    if $Sec <> @SEC then
        AllThatGoodStuff($special)
    endif

    ; this is looking like a better method for HotKey control..
    ; simply unset them when not in focus.
    ; when all your AutoIt apps do this, they don't interfere
    ; with each other, even multiple instances of the same app.
    if $ClockActive = 0 and not $keys_unset then
        UnSetHotKeys()
        $keys_unset = 1
    endif
    ; it also means the HotKey functions go from seven+ lines of code, to one.
    ; (there's no need to check if we are active or any of that)

    ; hourly chimes first..
    if @MIN = $chime_minute then
        if not $chime_done then DoChime()
        $chime_done = 1
    endif
    if @MIN <> $chime_minute then $chime_done = 0 ; we do more of this sort of thing, later..

    if $AlarmStatus[$AlarmStatus[2]] then ; master alarms switch is enabled
        for $index = 1 to $alarm_names[0] ; run through alarms, checking for any matches..

            if $my_alarms[$index][7] = 1 and $primed[$index] = 1 then ; this alarm is active (enabled) & primed
                switch $my_alarms[$index][0]

                    case "One Date"
                        if @YEAR = $my_alarms[$index][6] and @MON = $my_alarms[$index][4] _
                            and @MDAY = $my_alarms[$index][5] and @MIN = $my_alarms[$index][2] then
                            CheckTheHour($index)
                        endif

                    case "Weekdays"
                        if _DateToDayOfWeekSpecial(@YEAR, @MON, @MDAY) <= 4 and @MIN = $my_alarms[$index][2] then
                            CheckTheHour($index)
                        endif

                    case "Weekends"
                        if _DateToDayOfWeekSpecial(@YEAR, @MON, @MDAY) > 4 and @MIN = $my_alarms[$index][2] then
                            CheckTheHour($index)
                        endif

                    case "Custom"
                        if @YEAR = $my_alarms[$index][6] and @MON = $my_alarms[$index][4] _
                            and @MDAY = $my_alarms[$index][5] and @MIN = $my_alarms[$index][2] then
                            if CheckTheHour($index) then
                                Reschedule($index)
                            endif
                        endif

                    case else
                        if @MIN = $my_alarms[$index][2] then
                            CheckTheHour($index)
                        endif

                endswitch
            endif
            ; to play, an alarm must be "primed". This is the normal state. The are "unprimed" only for a minute.
            if $primed[$index] = 0 and $last_alarm_min <> @MIN then
                $primed[$index] = 1 ; reset $primed on next minute
                ; this alarm played just fine, we can reset the "missed" flag now..
                if IniRead($ini_path_alarms$alarm_names[$index], "missed""foo") = "no" and _
                    $my_alarms[$index][0] <> "One Date" then _
                        IniDelete($ini_path_alarms$alarm_names[$index], "missed")
            endif
        next
    endif
endfunc

; I guess we could check $primed, to prevent double play when user is
; messing with prefs during the alarm's active minute. But it's no biggie.



; This next function is a wee bit smaller now.
;
; And in case you were thinking it some lovely stroke of lateral thinking...
;
; In fact, only after writing the HumanTimeToHour() function for CheckMissedAlarms()
; did I realize I could re-use the same function to shave away most of the code here.
;
; It's always worth going back over old code to see where new functionality can
; save bytes and increase simplicity; especially if it isn't your code! <- note to self ;o)
;
func CheckTheHour($index)
    if HumanTimeToHour($my_alarms[$index][1], $my_alarms[$index][3]) = @HOUR then
        IGuessItsAlarmTime($index)
        return true
    endif
endfunc


; runs once at startup..
; (which is quite enough for such a mess of code)
func CheckMissedAlarms()

    for $index = 1 to $alarm_names[0]

        ; check if alarm is in the past..
        $24hours = HumanTimeToHour($my_alarms[$index][1], $my_alarms[$index][3]) ; here comes another nice function..
        $time_diff_min = _DateDiff("n", @Year & "/" & @Mon & "/" & @Mday & " " & @Hour & ":" & @Min & ":00", _
            $my_alarms[$index][6] & "/" & $my_alarms[$index][4] & "/" & $my_alarms[$index][5] & " " & $24hours _
                                                                            & ":" & $my_alarms[$index][2] & ":00")
        $post_missed_alarm = false

        select
            ; negative result, must be in the past
            case $time_diff_min < 0 and ($my_alarms[$index][0] = "One Date" or $my_alarms[$index][0] = "One Date")
                $post_missed_alarm = true

            ; notify only if launched within an hour (default) of these alarms    (see "missed_minutes")
            case $time_diff_min < 0 and $time_diff_min > -($missed_minutes + 1) and _
                ($my_alarms[$index][0] = "Daily" or $my_alarms[$index][0] = "Weekdays" or $my_alarms[$index][0] = "Weekends")
                $post_missed_alarm = true
        endselect

        ; alarm was missed, post a notice..


        if $post_missed_alarm then

            if $my_alarms[$index][16] <> "no" and $my_alarms[$index][16] <> "yes" then
                $missed_str = @CRLF & "Alarm set for: " & $my_alarms[$index][6] & "/" & $my_alarms[$index][4] & "/" & _
                    $my_alarms[$index][5] & " @ " & $my_alarms[$index][1] & ":" & $my_alarms[$index][2] & $my_alarms[$index][3] & @CRLF

                if $my_alarms[$index][8] <> "" then $missed_str &= @CRLF & "'" & $my_alarms[$index][8] & "'" & @CRLF
                MsgBox(48, "Missed Alarm!",    "You missed the following alarm: '" & $alarm_names[$index] & "'" & @CRLF & $missed_str)

                ; reschedule recurring alarms..
                if $my_alarms[$index][0] = "Custom" then Reschedule($index)
                if $my_alarms[$index][0] = "One Date" then _
                    IniWrite($ini_path_alarms$alarm_names[$index], "missed""yes")

            elseif $my_alarms[$index][16] = "yes" or _
                ($my_alarms[$index][16] = "no" and $my_alarms[$index][0] = "One Date") then
                    ; do nothing
            else
                ; reset this, and we're done. it's all good..
                IniDelete($ini_path_alarms$alarm_names[$index], "missed")
            endif

        endif
    next
endfunc


; novel and effective..
;
; The "trick" to recurring alarms is; after playing the alarm, we immediately re-save
; it, except with a new date. Thanks to _DateAdd(), it's a trivial matter to retrieve
; that by simply adding the user's custom schedule to the old alarm date.
;
; Respect to Jos van der Zande for _DateAdd() and _DateDiff() which make all this possible.
; Very nice.
;
func Reschedule($index)
    $current_custom_date = $my_alarms[$index][6] & "/" & $my_alarms[$index][4] & "/" & $my_alarms[$index][5]
    switch $my_alarms[$index][14]
        case "Months"
            $type = "M"
        case "Weeks"
            $type = "w"
        case "Days"
            $type = "D"
        case else
            $type = "Y"
    endswitch

    $new_date = _DateAdd($type$my_alarms[$index][15], $current_custom_date)
    $new_schedule = StringSplit($new_date"/")
    $my_alarms[$index][6] = $new_schedule[1] "Year"
    $my_alarms[$index][4] = $new_schedule[2] "Month"
    $my_alarms[$index][5] = $new_schedule[3] "Day"

    SaveAlarm($index)
    GetAlarms()
    $primed[$index] = 0 ; prevent Reschedule() setting off same alarm again. GetAlarms() resets it.
    $last_alarm_min = @MIN ; set this so it can be succesfully re-primed (above)
endfunc


func AllThatGoodStuff($FirstRun = 0)
    $GUIHDC = DllCall($user32_dll,"int","GetDC","hwnd"$gui)
    if $FirstRun = 1 then
        UpdateColors()
    endif

    ; erase old hands..
    if $curHourX <> $mid + Cos(TimeTorad("hour", @HOUR)) * $HourRad or _
        $curHourY <> $mid - Sin(TimeTorad("hour", @HOUR)) * $HourRad then
        DllCall($gdi_dll"hwnd""SelectObject""hwnd"$GUIHDC[0], "hwnd"$BackgroundPens[2])
        DllCall($gdi_dll"int""MoveToEx""hwnd"$GUIHDC[0], "int"$mid"int"$mid"ptr", 0)
        DllCall($gdi_dll"int""LineTo""hwnd"$GUIHDC[0], "int"$curHourX"int"$curHourY)
        $curHourX = $mid + Cos(TimeTorad("hour", @HOUR)) * $HourRad
        $curHourY = $mid - Sin(TimeTorad("hour", @HOUR)) * $HourRad
    endif
    if $curMinX <> $mid + Cos(TimeTorad("min", @MIN)) * $MinRad or _
        $curMinY <> $mid - Sin(TimeTorad("min", @MIN)) * $MinRad then
        DllCall($gdi_dll"hwnd""SelectObject""hwnd"$GUIHDC[0], "hwnd"$BackgroundPens[1])
        DllCall($gdi_dll"int""MoveToEx""hwnd"$GUIHDC[0], "int"$mid"int"$mid"ptr", 0)
        DllCall($gdi_dll"int""LineTo""hwnd"$GUIHDC[0], "int"$curMinX"int"$curMinY)
        $curMinX = $mid + Cos(TimeTorad("min", @MIN)) * $MinRad
        $curMinY = $mid - Sin(TimeTorad("min", @MIN)) * $MinRad
    endif
    DllCall($gdi_dll"hwnd""SelectObject""hwnd"$GUIHDC[0], "hwnd"$BackgroundPens[0])
    DllCall($gdi_dll"int""MoveToEx""hwnd"$GUIHDC[0], "int"$mid"int"$mid"ptr", 0)
    DllCall($gdi_dll"int""LineTo""hwnd"$GUIHDC[0], "int"$curSecX"int"$curSecY)

    ; draw new hands..
    DllCall($gdi_dll"hwnd""SelectObject""hwnd"$GUIHDC[0], "hwnd"$ClockPens[2])
    DllCall($gdi_dll"int""MoveToEx""hwnd"$GUIHDC[0], "int"$mid"int"$mid"ptr", 0)
    DllCall($gdi_dll"int""LineTo""hwnd"$GUIHDC[0], "int"$mid + Cos(TimeTorad("hour", @HOUR)) * _
                                            $HourRad"int"$mid - Sin(TimeTorad("hour", @HOUR)) * $HourRad)
    DllCall($gdi_dll"hwnd""SelectObject""hwnd"$GUIHDC[0], "hwnd"$ClockPens[1])
    DllCall($gdi_dll"int""MoveToEx""hwnd"$GUIHDC[0], "int"$mid"int"$mid"ptr", 0)
    DllCall($gdi_dll"int""LineTo""hwnd"$GUIHDC[0], "int"$mid + Cos(TimeTorad("min", @MIN)) * _
                                            $MinRad"int"$mid - Sin(TimeTorad("min", @MIN)) * $MinRad)
    DllCall($gdi_dll"hwnd""SelectObject""hwnd"$GUIHDC[0], "hwnd"$ClockPens[0])
    DllCall($gdi_dll"int""MoveToEx""hwnd"$GUIHDC[0], "int"$mid"int"$mid"ptr", 0)
    DllCall($gdi_dll"int""LineTo""hwnd"$GUIHDC[0], "int"$mid + Cos(TimeTorad("sec", @SEC)) * _
                                            $SecRad"int"$mid - Sin(TimeTorad("sec", @SEC)) * $SecRad)

    UpdatePips() ; much better!

    DllCall($user32_dll,"int","ReleaseDC","int",$GUIHDC[0],"hwnd",$gui)
    $curSecX = $mid + Cos(TimeTorad("sec", @SEC)) * $SecRad
    $curSecY = $mid - Sin(TimeTorad("sec", @SEC)) * $SecRad
    $Sec = @SEC
endfunc


func UpdatePips()

    if $draw_pips = $GUI_UNCHECKED then return

    $GUIHDC = DllCall($user32_dll,"int","GetDC","hwnd"$gui)
    DllCall($gdi_dll"hwnd""SelectObject""hwnd"$GUIHDC[0], "hwnd"$ClockPens[3])
    $Tempcounter = 0

    ; values are "close enough" - you can set it anywhichway in the prefs.
    $outer = $Radius*(100-$pips_outer_rim-14)/100
    $inner = $Radius*(100-$minute_pips_size-14)/100
    $big_inner = $Radius*(100-$hour_pips_size-14)/100

    if $draw_numerals = $GUI_UNCHECKED then
        $outer = $Radius*(100-$pips_outer_rim)/100        ; it would be trivial to have separate
        $inner = $Radius*(100-$minute_pips_size)/100    ; outer rims for hour and minute pips.
        $big_inner = $Radius*(100-$hour_pips_size)/100
    endif

    for $i = 0 To 2*$PI Step $PI/30
        if Mod($Tempcounter, 5) = 0 then ; hour pips
            DllCall($gdi_dll"hwnd""SelectObject""hwnd"$GUIHDC[0], "hwnd"$ClockPens[4])
            DllCall($gdi_dll"int""MoveToEx""hwnd"$GUIHDC[0], "int"$mid + Cos($i)*$big_inner"int"$mid - Sin($i)*$big_inner"ptr", 0)
            DllCall($gdi_dll"int""LineTo""hwnd"$GUIHDC[0], "int"$mid + Cos($i)*$outer"int"$mid - Sin($i)*$outer)
            DllCall($gdi_dll"hwnd""SelectObject""hwnd"$GUIHDC[0], "hwnd"$ClockPens[3])
        else ; minute pips..
            DllCall($gdi_dll"int""MoveToEx""hwnd"$GUIHDC[0], "int"$mid + Cos($i)*$inner"int"$mid - Sin($i)*$inner"ptr", 0)
            DllCall($gdi_dll"int""LineTo""hwnd"$GUIHDC[0], "int"$mid + Cos($i)*$outer"int"$mid - Sin($i)*$outer)
        endif
        $Tempcounter += 1
    next
endfunc


; out on its own now - it will be well used.
; note separate pens for all hands and pips..
func UpdateColors()

        GUISetBkColor("0x" & $face_color$gui)
        $background_pen = ConvertColorValue($face_color"vc")
        global $BackgroundPens[3], $ClockPens[5]

        ; these pens draw in the ghosts that would be left by the hands, so they need to be updated, too..
        $BkgrndPen = DllCall($gdi_dll"hwnd""CreatePen""int""0""int""0""hwnd"$background_pen); small background pen
        $BackgroundPens[0] = $BkgrndPen[0]
        $BkgrndPen = DllCall($gdi_dll"hwnd""CreatePen""int""0""int""2""hwnd"$background_pen); medium background pen
        $BackgroundPens[1] = $BkgrndPen[0]
        $BkgrndPen = DllCall($gdi_dll"hwnd""CreatePen""int""0""int""3""hwnd"$background_pen); large background pen
        $BackgroundPens[2] = $BkgrndPen[0]

        $BlackPen = DllCall($gdi_dll"hwnd""CreatePen""int""0""int""0""hwnd", ConvertColorValue($second_hand_color"vc"))    ; (second hand)
        $ClockPens[0] = $BlackPen[0]
        $BlackPen = DllCall($gdi_dll"hwnd""CreatePen""int""0""int""2""hwnd", ConvertColorValue($minute_pen"vc"))    ; (minute hand)
        $ClockPens[1] = $BlackPen[0]
        $BlackPen = DllCall($gdi_dll"hwnd""CreatePen""int""0""int""3""hwnd", ConvertColorValue($hour_pen"vc"))    ; (hour hand)
        $ClockPens[2] = $BlackPen[0]

        if $draw_pips = $GUI_CHECKED then
            $BlackPen = DllCall($gdi_dll"hwnd""CreatePen""int""0""int""0""hwnd", ConvertColorValue($pips_pen"vc")) ; wee pips
            $ClockPens[3] = $BlackPen[0]
            $BlackPen = DllCall($gdi_dll"hwnd""CreatePen""int""0""int""0""hwnd", ConvertColorValue($big_pips_pen"vc")) ; wee pips
            $ClockPens[4] = $BlackPen[0]
        endif
        UpdateNumeralLabels()
        UpdateTrans()
endfunc

func UpdateTrans()
    WinSetTrans($gui"", (100 - $WinTrans) * 2.55)
endfunc


; now, isn't this a better way to draw those numerals..
;
; this could definitely be refined (a challenge for you)
; but some quick math means we can open with an any-sized clock..
;
func DrawNumerals()
    $rim = $mid - $mid / 12 ; a fairly arbitrary 12, this one.
    $count  = 1
    for $a = 0 to ((2 * $PI) - (2.0 * $PI / 12.5)) step 2.0 * $PI / 12 ; slightly over 12, to ensure the "12" is written
        $px = $rim * Cos(($a - $PI / 3)) + ($rim / 2 + $mid / 2) ; half-way between $mid and $rim! Mean($mid$rim) !
        $py = $rim * Sin(($a - $PI / 3)) + ($rim / 2 + $mid / 2)
        $Labels[$count] = GUICtrlCreateLabel(string($count), $px$py)
        $count += 1
    next
    UpdateNumeralLabels()
endfunc

func UpdateNumeralLabels()
    for $i = 1 To 12
        if  $draw_numerals = 1 then
            GUICtrlSetColor($Labels[$i], "0x" & $numerals_color)
        else
            ; a slightly alternative way of hiding them..
            GUICtrlSetColor($Labels[$i], "0x" & $face_color)
        endif
    next
endfunc


; length of hands..
func UpdateHandSizes()
    global $SecRad = $mid * ($second_hand_size/100)
    global $MinRad = $mid * ($minute_hand_size/100)
    global $HourRad = $mid * ($hour_hand_size/100)
endfunc


; system tray..
;
; the first few items here, you might notice, produce the optical illusion
; of being curved, don't you think? scroll slowly...
func SystemTrayMain()

    global $TrayItemAbout = TrayCreateItem("About..")
    TrayItemSetOnEvent($TrayItemAbout"DoAbout")

    TrayCreateItem("")

    global $TrayItemAlarmStatus = TrayCreateItem("Alarms are " & $AlarmStatus[$AlarmStatus[2]])
    TrayItemSetOnEvent(-1, "ToggleAlarm")

    global $TrayItemChimeStatus = TrayCreateItem("Chimes are " & $chimes_status[$do_chime])
    TrayItemSetOnEvent(-1, "MenuToggleChime")

    TrayCreateItem("")


    global $TrayItemPrefsDialog = TrayCreateItem("Alarms and Chimes..    F5")
    TrayItemSetOnEvent(-1, "AlarmPrefs")

    global $TrayItemPrefsDialog = TrayCreateItem("Scheme Settings..    F6")
    TrayItemSetOnEvent(-1, "ColorPrefs")

    global $TrayItemAudioPrefs = TrayCreateItem("Audio Settings..    F7")
    TrayItemSetOnEvent(-1, "LaunchAudioPrefs")

    TrayCreateItem("")


    global $TrayItemOpenDataFolder = TrayCreateItem("Access Color Pickin Chooser..    F8")
    TrayItemSetOnEvent(-1, "GoColorPickinChooser")

    TrayCreateItem("")


    global $TrayItemOpenDataFolder = TrayCreateItem("Open Clock Data Folder..")
    TrayItemSetOnEvent(-1, "OpenDataFolder")

    TrayCreateItem("")


    global $TrayItemStartWithWindows = TrayCreateItem("Start with Windows")
    TrayItemSetOnEvent(-1, "MenuToggleStartWithWindows")

    global $TrayItemFadeAtStartup = TrayCreateItem("Fade-in at Startup")
    TrayItemSetOnEvent(-1, "MenuToggleFadeAtStartup")
    TrayCreateItem("")


    global $TrayItemExit = TrayCreateItem("Handy Tips and Tricks..    F1", -1)
    TrayItemSetOnEvent($TrayItemExit"ShowTips")
    TrayCreateItem("")

    global $TrayItemExit = TrayCreateItem("Exit", -1)
    TrayItemSetOnEvent($TrayItemExit"DoQuit")


    TraySetToolTip(" left-click to toggle the clock " & @CRLF & " right-click to bring up the menu ")
    TraySetOnEvent($TRAY_EVENT_PRIMARYDOWN"MenuToggleWindow"; left-click
    TraySetState() ; show the tray menu
    TraySetClick(8) ; right-click to bring up the menu
endfunc


func ContextMenuMain()

    global $ContextMenu
    $ContextMenu = GUICtrlCreateContextMenu()

    $MenuItemAbout = GUICtrlCreateMenuitem("About.."$ContextMenu)
    GUICtrlSetOnEvent(-1, "DoAbout")

    GUICtrlCreateMenuitem(""$ContextMenu)


    $MenuItemResizeClock = GUICtrlCreateMenuitem("Resize Clock    F2"$ContextMenu)
    GUICtrlSetOnEvent(-1, "ResizeTheClock")

    $MenuItemMoveClock = GUICtrlCreateMenuitem("Move Clock    F3"$ContextMenu)
    GUICtrlSetOnEvent(-1, "MoveTheClock")

    GUICtrlCreateMenuitem(""$ContextMenu)


    $MenuItemTransparency = GUICtrlCreateMenuitem("Set Transparency    F4"$ContextMenu)
    GUICtrlSetOnEvent(-1, "DialogSetTrans")

    GUICtrlCreateMenuitem(""$ContextMenu)

    ; schemes sub-menu..
    ; this is another good reason why we restart the clock..
    if FileExists($ini_path_schemes) then
        $MenuSchemes = GUICtrlCreateMenu("Schemes.."$ContextMenu)
        global $scheme_menu_items[$scheme_names[0]+1]
        for $i = 1 to $scheme_names[0]
            if $scheme_names[$i] <> '' then
            $scheme_menu_items[$i] = GUICtrlCreateMenuItem($scheme_names[$i], $MenuSchemes)
            ; when re-built, $scheme_menu_items[$i] = 0, always. even when we delete the whole thing first (?)
            if $scheme_names[$i] = $current_scheme then
                $uncheck_item = $i
                GUICtrlSetState(-1, $GUI_CHECKED)
            endif
            GUICtrlSetOnEvent(-1, "MenuSwitchScheme")
            endif
        next
    endif
    GUICtrlCreateMenuitem(""$ContextMenu)

    global $MenuItemOnTop = GUICtrlCreateMenuitem("Always On Top"$ContextMenu)
    GUICtrlSetOnEvent(-1, "MenuToggleOnTop")
    GUICtrlSetState(-1, $on_top)

    global $MenuItemClickDrag = GUICtrlCreateMenuitem("Click+Drag To Move    F9"$ContextMenu)
    GUICtrlSetOnEvent(-1, "MenuToggleClickDrag")
    GUICtrlSetState(-1, $click_drag_to_move)

    GUICtrlCreateMenuitem(""$ContextMenu)

    $MenuItemExit = GUICtrlCreateMenuitem("Exit"$ContextMenu)
    GUICtrlSetOnEvent($MenuItemExit"DoQuit")
endfunc


func TimeTorad($TimeType$TimeVal=@SEC)
    local $Rads
    switch $TimeType
        case "sec"
            $Rads = $PI/2 -($TimeVal * $PI/30)
        case "min"
            $Rads = $PI/2 -($TimeVal * $PI/30) - Int(@SEC/10)*$PI/180
        case "hour"
            $Rads = $PI/2 -($TimeVal * $PI/6) -(@MIN/12)*$PI/30
    endswitch
    return $Rads
endfunc

func CreateRoundRectRgn($l$t$w$h$e1$e2)
    $ret = DllCall("gdi32.dll""long""CreateRoundRectRgn""long"$l"long"$t, _
                                "long"$l + $w"long"$t + $h"long"$e1"long"$e2)
    return $ret[0]
endfunc

func SetWindowRgn($h_win$rgn)
    DllCall("user32.dll""long""SetWindowRgn""hwnd"$h_win"long"$rgn"int", 1)
endfunc


func F2ResizeTheClock()
    if $click_drag_to_move = $GUI_CHECKED then ToggleClickDrag()
    ResizeTheClock()
endfunc

func ResizeTheClock()
    local $last_mouse_coord = AutoItSetOption("MouseCoordMode", 2)
    GUISetCursor(13, 1, $gui)
    ToolTip(" click and drag (left-right) to resize the clock. release to set the size. ")
    while 1
        $MousePos = MouseGetPos()
        $WinPos = WinGetPos($gui)
        if not IsArray($MousePos) or not IsArray($WinPos) then continueloop

        $PosDiff[0] = $WinPos[2] - $MousePos[0]
        $PosDiff[1] = $WinPos[1] - $MousePos[1]
        if ce_IsPressed(01) then
            while ce_IsPressed(01) ; mouse down
                $MousePos = MouseGetPos()
                WinMove($my_shortname""$WinPos[0], $WinPos[1], $MousePos[0] + $PosDiff[0], $MousePos[0] + $PosDiff[0])
                $WinPos = WinGetPos($gui)
                $a = CreateRoundRectRgn(0, 0, $WinPos[2], $WinPos[3], $WinPos[2], $WinPos[3])
                SetWindowRgn($gui$a)
                $mid = $WinPos[2]/2
                $Radius = $mid
                UpdateHandSizes()
                if $OldFontSize <> Int($mid/15) then
                    for $i = 1 To 12
                        GUICtrlSetFont($Labels[$i], Int($mid/15), 800)
                    next
                    $OldFontSize = Int($mid/15)
                endif
                CheckClockStuff(2)
                Sleep(10)
            wend
            ExitLoop
        endif
        CheckClockStuff()
        Sleep(10)
    wend
    IniWrite($ini_path$my_shortname"size"$WinPos[2])
    ToolTip("")
    GUISetCursor()
    AllThatGoodStuff(2)
    AutoItSetOption("MouseCoordMode"$last_mouse_coord)
    MoveTheClock()
endfunc

func F3MoveTheClock()
    if $click_drag_to_move = $GUI_CHECKED then ToggleClickDrag()
    MoveTheClock()
endfunc

func MoveTheClock()
    GUISetCursor(9, 1, $gui)
    ToolTip(" click and drag to move the clock.  release to set the position. ")
    while 1
        $MousePos = MouseGetPos()
        $WinPos = WinGetPos($gui)

        if not IsArray($MousePos) or not IsArray($WinPos) then continueloop

        $PosDiff[0] = $WinPos[0] - $MousePos[0]
        $PosDiff[1] = $WinPos[1] - $MousePos[1]
        if ce_IsPressed(01) then
            while ce_IsPressed(01)
                $MousePos = MouseGetPos()
                WinMove($gui""$MousePos[0] + $PosDiff[0], $MousePos[1] + $PosDiff[1])
                $WinPos = WinGetPos($gui)
                if($WinPos[0] < -10) or($WinPos[1] < -10) or($WinPos[0] + $WinPos[2] > @DesktopWidth + 10) or _
                   ($WinPos[1] + $WinPos[3] > @DesktopHeight + 10) then
                    CheckClockStuff(2)
                else
                    CheckClockStuff()
                endif
                Sleep(10)
            wend
            exitloop
        endif
        CheckClockStuff()
        Sleep(10)
    wend
    ToolTip("")
    GUISetCursor()
    RefreshClock()
    SaveXYPrefs()
    AllThatGoodStuff(2)
endfunc

func TransUp()
    $WinTrans += 1
    SetTrans()
endfunc
func TransDown()
    $WinTrans -= 1
    SetTrans()
endfunc
func BigTransUp()
    $WinTrans += 10
    SetTrans()
endfunc
func BigTransDown()
    $WinTrans -= 10
    SetTrans()
endfunc

func F4DialogSetTrans()
    DialogSetTrans()
    CheckClockStuff(2)
endfunc

func DialogSetTrans()
    DialogOpen()
    local $last_event_mode = AutoItSetOption("GUIOnEventMode", 0)
    local $last_coord_mode = AutoItSetOption("GUICoordMode", 1)

    $trans_x = IniRead($ini_path$my_shortname"trans_x", -1)
    $trans_y = IniRead($ini_path$my_shortname"trans_y", -1)

    $GUI_Trans = GUICreate(" set clock transparency..", 300, 120, $trans_x$trans_y)
    $label_ud_notice = GUICtrlCreateLabel("Note: You can also use the UP/DOWN arrow keys, and Page Up/Page Down keys for this.", _
                                                                                20, 11, 260, 40, $SS_CENTER)

    $GUI_Trans_Slider = GUICtrlCreateSlider(10, 47, 280, 35)
    GUICtrlSetLimit($GUI_Trans_Slider, 99, 0)
    GUICtrlSetData($GUI_Trans_Slider$WinTrans)
    $GUI_Trans_OK = GUICtrlCreateButton("OK", 100, 90, 100, 25)

    WinSetOnTop($GUI_Trans"", 1)
    GUISetState()
    while 1
        $msg = GUIGetMsg()
        switch $msg
            case $GUI_EVENT_CLOSE$GUI_Trans_OK
                $WinTrans = GUICtrlRead($GUI_Trans_Slider)
                $size_array = WinGetPos($GUI_Trans)
                if IsArray($size_array) then
                    IniWrite($ini_path$my_shortname"trans_x"$size_array[0])
                    IniWrite($ini_path$my_shortname"trans_y"$size_array[1])
                endif
                GUIDelete($GUI_Trans)
                RefreshClock()
                exitloop
        endswitch
        WinSetTrans($gui"", (100 - GUICtrlRead($GUI_Trans_Slider)) * 2.5)
        WinSetTitle($GUI_Trans""" set clock transparency..   [" & GUICtrlRead($GUI_Trans_Slider) & "%]")
        CheckClockStuff(2)
        Sleep(50)
    wend

    SaveSchemePref($current_scheme"transparency"$WinTrans)

    AutoItSetOption("GUIOnEventMode"$last_event_mode)
    AutoItSetOption("GUICoordMode"$last_coord_mode)
    DialogClose()
endfunc

func SetTrans()
    if $WinTrans <= -1 then $WinTrans = 0
    if $WinTrans >= 100 then $WinTrans = 99
    UpdateTrans()
    SaveSchemePref($current_scheme"transparency"$WinTrans)
endfunc


; These need a wrapper, because menus and such don't send parameters
; even otional parameters will fail!(?) This solves it..
func AlarmPrefs()
    PrefsDialog(1)
endfunc

func ColorPrefs()
    PrefsDialog(2)
endfunc

func LaunchAudioPrefs()
    PrefsDialog(3)
endfunc


; the (large) prefs dialog..
;
func PrefsDialog($choose_tab)

    $prefs_open = true
    global $show_prefs = true
    global $seen_switch_msg = false
    UnsetHotKeys()
    DialogOpen()
    StopSound()
    $play_idx = 0

    AutoItSetOption("GUIOnEventMode", 0)
    global $changes[50]
    local $new_alert = ""
    local $init_prefs = 0
    local $alert_is_wav = false
    local $current_flash_color = "FF0000"
    local $remember_wav = ""

    GetAlertNames()
    global $current_alert = $alert_names[$alert_names[0]]

    global $current_preset = IniRead($ini_path$my_shortname"current_preset""unsaved alarm")
    if not InArray($alarm_names$current_preset) then $current_preset = $alarm_names[1]
    local $prefs_dialog_Min$butt_save_alarm$lc = 50 ; loop-counter

    global $prefs_x = IniRead($ini_path$my_shortname"prefs_x", -1)
    global $prefs_y = IniRead($ini_path$my_shortname"prefs_y", -1)

    global $prefs_dialog = GUICreate(" Preferences", 440, 340, $prefs_x$prefs_y, -1, _
                                        BitOr($WS_EX_ACCEPTFILES$WS_EX_TOOLWINDOW), $gui)
    WinSetOnTop($prefs_dialog"", 1)

    ; relative positioning, methinks..
    AutoItSetOption("GUICoordMode", 0)

    ; do this first so it persists on all tabs..
    GUISetCoord(370, 314) ; <- I like these, then--V--V-- = ZERO,ZERO (best of both worlds)
    $butt_done = GUICtrlCreateButton("all &done!", 0, 0, 64, 22)
    GUICtrlSetTip(-1, " close the preferences ")


    ; Tab container..
    ;
    GUISetCoord(0, 0)
    global $tab_prefs = GUICtrlCreateTab(-2, 1, 444, 344, BitOr($TCS_HOTTRACK$TCS_TOOLTIPS))


    ; First tab..
    ;
    $tab_prefs_title = GUICtrlCreateTabItem( " Alarms and Chimes " )
    GUICtrlSetTip($tab_prefs_title" Alarms and Chimes preferences.. ")

    ; time..

        GUISetCoord(5, 25) ; this whole "block" could be moved as a group, see.

        $pref_group_alarm_time = GUICtrlCreateGroup("Alarm Time..", 0, 0, 210, 45)

        $Alarm_Hour = GUICtrlCreateCombo("", 5, 16, 48, 20)
        GUICtrlSetData(-1, "1|2|3|4|5|6|7|8|9|10|11|12")
        GUICtrlSetTip(-1, " set the hour of the alarm ")
        GUICtrlCreateLabel(":", 51, 0)
        GUICtrlSetFont(-1, 12, 700)

        $prefs_dialog_Min = GUICtrlCreateCombo("", 11, 0, 48, 20)
        GUICtrlSetData(-1, "00|01|02|03|04|05|06|07|08|09|")
        for $i = 10 To 59
            GUICtrlSetData(-1, $i & "|")
        next
        GUICtrlSetTip(-1, " set the minute of the alarm ")

        $Alarm_AMPM = GUICtrlCreateCombo("", 60, 0, 40, 20)
        GUICtrlSetData(-1, "am|pm")
        GUICtrlSetTip(-1, " wee small oors/morning (am) or afternoon/evening (pm) ")

        $butt_now = GUICtrlCreateButton("no&w", 46, 1, 30, 20)
        GUICtrlSetTip(-1, " set the time to right now ")

    ; date..

        GUISetCoord(5, 75)

        $pref_group_alarm_date = GUICtrlCreateGroup("Alarm Date..", 0, 0, 210, 190)
        $Alarm_Cal = GUICtrlCreateMonthCal("", 5, 20, 200, 165)

    ; chimes..

        GUISetCoord(5, 270)

        $group_chimes = GUICtrlCreateGroup("Chimes..", 0, 0, 210, 66)
        $chime_minute = IniRead($ini_path$my_shortname"chime_minute", 0)
        if $chime_minute = 0 then $chime_minute = "00" ; catches text, too.

        $check_chimes = GUICtrlCreateCheckbox("Hourly Chimes Every..", 10, 18)
        GUICtrlSetTip(-1, " Hourly Chimes can happen on the hour, or at any minute you specify.. ")
        GUICtrlSetState(-1, $do_chime)

        global $icon_chime_test = GUICtrlCreateIcon("shell32.dll", 246, 135, 0, 16, 16)
        GUICtrlSetImage(-1, "shell32.dll", 246, 0)
        GUICtrlSetTip(-1, " test your chime ")


        $combo_chime_minute = GUICtrlCreateCombo("", 18, -2, 40, 20)
        GUICtrlSetTip(-1, " at what minute of the hour would you like your chimes (usually 00) ")
        GUICtrlSetData(-1, "00|01|02|03|04|05|06|07|08|09|")
        for $i = 10 To 59
            GUICtrlSetData($combo_chime_minute$i & "|"$chime_minute)
        next

        $label_chime = GUICtrlCreateLabel("Chime: ", -153, 28, 32, 20)
        GUICtrlSetTip(-1, " click this label to reset the chime to the default (a 4000Hz tone) ")

        global $combo_chimes = GUICtrlCreateCombo("", 40, -5, 153, 20)
        GUICtrlSetTip(-1, " enter a Hz value (37-19999, for a tone sound) or some words (for a spoken message) " & @CRLF & _
                            " you can also enter the full path to a WAV file (something short!). " & @CRLF & _
                            " [recent spoken chimes and WAVs are available from the drop-down] ")
        GetChimesList()

        if $do_chime <> 1 then
            GUICtrlSetState($icon_chime_test$GUI_HIDE)
            GUICtrlSetState($combo_chime_minute$GUI_DISABLE)
            GUICtrlSetState($label_chime$GUI_DISABLE)
            GUICtrlSetState($combo_chimes$GUI_DISABLE)
        endif


    ; alarm presets..

        GUISetCoord(220, 25)

        $group_presets = GUICtrlCreateGroup("Alarm Presets..", 0, 0, 218, 45)

        $ex_tip = @CRLF & " right-click for the alarms export menu "
        global $combo_alarm_presets = GUICtrlCreateCombo("", 5, 16, 115, 20, _
                BitOR($CBS_SORT$CBS_DROPDOWN$CBS_AUTOHSCROLL$WS_VSCROLL))
        GUICtrlSetTip(-1, " your alarm presets " & @CRLF & _
                          " you can add to these, update, and delete them from here " & @CRLF & _
                          " note: for a presets to play, it needs to be ENABLED (at the bottom) ")
        for $i = 1 to $alarm_names[0]
            GUICtrlSetData(-1, $alarm_names[$i])
        next
        GUICtrlSetState(-1, $GUI_DROPACCEPTED)


        $butt_del_alarm = GUICtrlCreateButton("x", 119, 0, 16, 20)
        GUICtrlSetTip(-1, " delete the current alarm preset")

        $butt_revert_alarm = GUICtrlCreateButton("&revert", 19, 0, 36, 20)
        GUICtrlSetTip(-1, " revert back to the last saved settings ")

        $butt_save_alarm = GUICtrlCreateButton("&save", 38, 0, 32, 20)
        GUICtrlSetTip(-1, " save this alarm preset with the current settings ")


    ; frequency options..

        local $Alarm_Dates[4]
        GUISetCoord(220, 75)

        $group_alarm_freq = GUICtrlCreateGroup("Alarm Frequency..", 0, 0, 218, 60)

        $combo_frequency = GUICtrlCreateCombo("Daily", 8, 20, 75)
        GUICtrlSetData(-1, "Weekdays|Weekends|One Date|Custom")
        GUICtrlSetTip(-1, " how many? ")

        $label_custom_frequency = GUICtrlCreateLabel("repeat alarm every..", 95, -7, 140)

        $combo_interval_period = GUICtrlCreateCombo("1", 0, 16, 36)
        for $i = 2 To 100
            GUICtrlSetData(-1, $i & "|")
        next
        GUICtrlSetTip(-1, " how many? ")

        $combo_interval_type = GUICtrlCreateCombo("Years", 40, 0, 64)
        GUICtrlSetData(-1, "Months|Weeks|Days")

    ; alarm options..

        GUISetCoord(220, 140)

        GUICtrlCreateGroup("Alarm Options..", 0, 0, 218, 125)

        $label_flash_color = GUICtrlCreateLabel("Flash Colour: ", 8, 25, 69, 20); 228, 145,
        GUICtrlSetTip(-1, " when your alarm sounds, the clock face will also flash. what colour? " & @CRLF & _
                          " click this label to set the flash colour to the last saved value (aka. revert) ")
        $butt_flash_color = GUICtrlCreateButton("", 71, -2, 48, 16)
        GUICtrlSetTip(-1, " choose this alarm's flash colour ")
        GUICtrlSetBkColor($butt_flash_color"0x" & $my_alarms[1][9])


        $label_alert = GUICtrlCreateLabel("Alert: ", -71, 28, 32)
        GUICtrlSetTip(-1, " what alert would you like to use for this alarm? " & @CRLF & _
                          " click this label to revert the alert to the last saved value " & @CRLF & _
                          " (beep alerts use the peecee speaker, WAV alerts use the windows sound system) ")
        global $combo_alert = GUICtrlCreateCombo("", 32, -5, 130, 20, _
            BitOR($CBS_SORT$CBS_DROPDOWN$CBS_AUTOHSCROLL$WS_VSCROLL))
        GUICtrlSetState(-1, $GUI_DROPACCEPTED)
        GUICtrlSetTip(-1,    " choose which alert to use (see the 'Audio' tab to easily create your own) " & @CRLF & _
                            " alternatively, you can use a WAV file - add it to your alerts by dropping it " & @CRLF & _
                            " on here (the best way), or browsing for a file (click the button to the right). ")
        GetAlertNames()

        $icon_alert_in = GUICtrlCreateIcon("shell32.dll", 4, 136, 0, 16, 16)
        GUICtrlSetTip(-1, " browse for a WAV file to use as an alert sound ")

        global $icon_alert_test = GUICtrlCreateIcon("shell32.dll", 246, 22, 1, 16, 16)
        GUICtrlSetTip(-1, " test the current alert (and flash color) ")
        GUICtrlSetImage(-1, "shell32.dll", 246, 0)

        $label_message = GUICtrlCreateLabel("Spoken Message.. ", -190, 28, 188)
        GUICtrlSetTip(-1, " enter some text (or the path to a text file), and have it spoken after the alarm sound " & @CRLF & _
                          " (click this label to adjust the speech settings for this message) ")
        global $combo_message = GUICtrlCreateCombo("", -1, 17, 186)
        GUICtrlSetTip(-1, " e.g. 'You have a meeting with the Bank Manager in ONE HOUR!' " & @CRLF & _
                          " (note: for all speech inputs, you can also enter the full path to a plain text file or URL," & _
                          " and have it spoken) ")

        global $icon_msg_test = GUICtrlCreateIcon("shell32.dll", 246, 190, 3, 16, 16)
        GUICtrlSetTip(-1, " test the current alarm message using the current voice settings ")
        GUICtrlSetImage(-1, "shell32.dll", 246, 0)

        GetMessagesList()

    ; alarm switches

        GUISetCoord(224, 270)

        $this_label = " Enable/Disable the current alarm preset (takes effect immediately) "
        $label_alarm_enabled = GUICtrlCreateLabel("This alarm preset is.. ", 0, 0, 105)
        GUICtrlSetTip(-1, $this_label)
        global $check_alarm_enabled = GUICtrlCreateCheckbox("enabled.", 103, -3)
        GUICtrlSetTip(-1, $this_label)


        $this_label = " Enable/Disable the master alarm switch (takes effect immediately) "
        $label_master_enabled = GUICtrlCreateLabel("Master alarms switch is.. ", -103, 22, 120)
        GUICtrlSetTip(-1, $this_label)
        global $check_master_enabled = GUICtrlCreateCheckbox("enabled.", 118, -3)
        GUICtrlSetTip(-1, $this_label)

        $butt_exclusions = GUICtrlCreateButton("&exclusions", -118, 28, 64, 22)
        GUICtrlSetTip(-1, " no audio will play while an excluded application is active - click here to setup the exclusions ")


    ; some context menus..

        ; why oh why did I stick with message loop mode for the prefs???

        $context_ex_alarms = GUICtrlCreateContextMenu($combo_alarm_presets)
        $ex_1 = GUICtrlCreateMenuitem("Export Alarm.."$context_ex_alarms)
        $ex_9 = GUICtrlCreateMenuitem("Export Alarm into Collection.."$context_ex_alarms)
        GUICtrlCreateMenuitem(""$context_ex_alarms)
        $ex_2 = GUICtrlCreateMenuitem("Export All Alarms.."$context_ex_alarms)

        $context_ex_alarms2 = GUICtrlCreateContextMenu($butt_del_alarm)
        $ex_3 = GUICtrlCreateMenuitem("Export Alarm.."$context_ex_alarms2)
        $ex_10 = GUICtrlCreateMenuitem("Export Alarm into Collection.."$context_ex_alarms2)
        GUICtrlCreateMenuitem(""$context_ex_alarms2)
        $ex_4 = GUICtrlCreateMenuitem("Export All Alarms.."$context_ex_alarms2)

        $context_ex_alarms3 = GUICtrlCreateContextMenu($butt_revert_alarm)
        $ex_5 = GUICtrlCreateMenuitem("Export Alarm.."$context_ex_alarms3)
        $ex_11 = GUICtrlCreateMenuitem("Export Alarm into Collection.."$context_ex_alarms3)
        GUICtrlCreateMenuitem(""$context_ex_alarms3)
        $ex_6 = GUICtrlCreateMenuitem("Export All Alarms.."$context_ex_alarms3)

        $context_ex_alarms4 = GUICtrlCreateContextMenu($butt_save_alarm)
        $ex_7 = GUICtrlCreateMenuitem("Export Alarm.."$context_ex_alarms4)
        $ex_12 = GUICtrlCreateMenuitem("Export Alarm into Collection.."$context_ex_alarms4)
        GUICtrlCreateMenuitem(""$context_ex_alarms4)
        $ex_8 = GUICtrlCreateMenuitem("Export All Alarms.."$context_ex_alarms4)

        $context_chimes_clear_list = GUICtrlCreateContextMenu($combo_chimes)
        $menu_chimes_clear_list = GUICtrlCreateMenuitem("Clear recent chimes list.."$combo_chimes)

        $context_msg_clear_list = GUICtrlCreateContextMenu($combo_message)
        $menu_msg_clear_list = GUICtrlCreateMenuitem("Clear recent messages list.."$combo_message)


    ; Second tab..
    ;
    $tab_prefs_title2 = GUICtrlCreateTabItem(" Schemes ")
    GUICtrlSetTip($tab_prefs_title" Visual and Other Preferences.. ")

    ; Colour Scheme Presets..

        GUISetCoord(5, 30)

        $group_scheme_presets = GUICtrlCreateGroup("Scheme Presets..", 0, 0, 218, 45)

        $ex_tip = @CRLF & " right-click for the schemes export menu "
        global $combo_scheme_presets = GUICtrlCreateCombo("", 5, 16, 115, 20, _
                BitOR($CBS_SORT$CBS_DROPDOWN$CBS_AUTOHSCROLL$WS_VSCROLL))
        GUICtrlSetTip(-1, " your clock schemes (bundled color, hands, pips and numerals settings) " & @CRLF & _
                          " you can add, update, and delete schemes from here " & $ex_tip)
        GUICtrlSetData($combo_scheme_presets"|")
        for $i = 1 to $scheme_names[0]
            GUICtrlSetData($combo_scheme_presets$scheme_names[$i])
        next
        GUICtrlSetData($combo_scheme_presets$current_scheme)
        GUICtrlSetState(-1, $GUI_DROPACCEPTED)

        $butt_del_scheme = GUICtrlCreateButton("x", 119, 0, 16, 20)
        GUICtrlSetTip(-1, " delete the current scheme" & $ex_tip)

        $butt_revert_scheme = GUICtrlCreateButton("&revert", 19, 0, 36, 20)
        GUICtrlSetTip(-1, " revert back to the last saved settings " & $ex_tip)

        $butt_save_scheme = GUICtrlCreateButton("&save", 38, 0, 32, 20)
        GUICtrlSetTip(-1, " save this scheme with all the current settings " & $ex_tip)

        $context_ex_schemes = GUICtrlCreateContextMenu($combo_scheme_presets)
        $exsc_1 = GUICtrlCreateMenuitem("Export Scheme.."$context_ex_schemes)
        $exsc_9 = GUICtrlCreateMenuitem("Export Scheme into Collection.."$context_ex_schemes)
        GUICtrlCreateMenuitem(""$context_ex_schemes)
        $exsc_2 = GUICtrlCreateMenuitem("Export All Schemes.."$context_ex_schemes)

        $context_ex_schemes2 = GUICtrlCreateContextMenu($butt_del_scheme)
        $exsc_3 = GUICtrlCreateMenuitem("Export Scheme.."$context_ex_schemes2)
        $exsc_10 = GUICtrlCreateMenuitem("Export Scheme into Collection.."$context_ex_schemes2)
        GUICtrlCreateMenuitem(""$context_ex_schemes2)
        $exsc_4 = GUICtrlCreateMenuitem("Export All Schemes.."$context_ex_schemes2)

        $context_ex_schemes3 = GUICtrlCreateContextMenu($butt_revert_scheme)
        $exsc_5 = GUICtrlCreateMenuitem("Export Scheme.."$context_ex_schemes3)
        $exsc_11 = GUICtrlCreateMenuitem("Export Scheme into Collection.."$context_ex_schemes3)
        GUICtrlCreateMenuitem(""$context_ex_schemes3)
        $exsc_6 = GUICtrlCreateMenuitem("Export All Schemes.."$context_ex_schemes3)

        $context_ex_schemes4 = GUICtrlCreateContextMenu($butt_save_scheme)
        $exsc_7 = GUICtrlCreateMenuitem("Export Scheme.."$context_ex_schemes4)
        $exsc_12 = GUICtrlCreateMenuitem("Export Scheme into Colection.."$context_ex_schemes4)
        GUICtrlCreateMenuitem(""$context_ex_schemes4)
        $exsc_8 = GUICtrlCreateMenuitem("Export All Schemes.."$context_ex_schemes4)


        ; 2do - disable desktop compositioning temporarily (inside cpc)
        $check_disable_cpc = ""
        if $vista then
            GUISetCoord(230, 33)
            $tip_vista_warn = " The Aero drawing routines in Vista are not compatible with the color pickin chooser's magnifier. " & @CRLF & _
                              " Check this box to disable the color pickin chooser, and use the system color picker, instead. "
            $check_disable_cpc = GUICtrlCreateCheckbox("DISABLE COLOR PICKIN CHOOSER", 0, 0, 200, 20)
            GUICtrlSetTip(-1, $tip_vista_warn)
            GUICtrlSetState(-1, $disable_cpc)
            $label_color_clock_face = GUICtrlCreateLabel("..handy if you are using an 'Aero' theme", 11, 21, 190, 50)
            GUICtrlSetTip(-1, $tip_vista_warn)
        endif

        ; clock face colours..
        GUISetCoord(5, 80)

        GUICtrlCreateGroup("Colors..", 0, 0, 218, 215)
        $revert_tip = @CRLF & "(click here to revert the value back to its last saved setting) "

        $label_color_clock_face = GUICtrlCreateLabel("Clock Face: ", 8, 25, 69, 20)
        GUICtrlSetTip(-1, " the color of the clock face " & $revert_tip)
        $butt_color_clock_face = GUICtrlCreateButton("", 91, -2, 62, 16)
        GUICtrlSetTip(-1, " click here to choose the color for the face of the clock ")

        $label_numerals_color = GUICtrlCreateLabel("Numerals: ", -91, 25, 69, 20)
        $tiny_add = ""
        if $size < 150 then $tiny_add = "(tiny) "
        GUICtrlSetTip(-1, " the color of the " & $tiny_add & "numbers around the clock face " & $revert_tip)
        $butt_numerals_color = GUICtrlCreateButton("", 91, -2, 62, 16)
        GUICtrlSetTip(-1, " click here to choose the color for numbers around the clock face ")

        $label_hour_pen = GUICtrlCreateLabel("Hour Hand: ", -91, 25, 69, 20)
        GUICtrlSetTip(-1, " the color of the Hour hand (the thick one!)" & $revert_tip)
        $butt_hour_pen = GUICtrlCreateButton("", 91, -2, 62, 16)
        GUICtrlSetTip(-1, " click here to choose the color for hour hand ")

        $label_minute_pen = GUICtrlCreateLabel("Minute Hand: ", -91, 25, 69, 20)
        GUICtrlSetTip(-1, " the color of the Minute hand (the thin one!) " & $revert_tip)
        $butt_minute_pen = GUICtrlCreateButton("", 91, -2, 62, 16)
        GUICtrlSetTip(-1, " click here to choose the color for minute hand ")

        $label_second_hand_color = GUICtrlCreateLabel("Second Hand: ", -91, 25, 69, 20)
        GUICtrlSetTip(-1, " the color of the thin hand that moves each second " & $revert_tip)
        $butt_second_hand_color = GUICtrlCreateButton("", 91, -2, 62, 16)
        GUICtrlSetTip(-1, " click here to choose the color for second hand ")

        $label_big_pips_pen = GUICtrlCreateLabel("Hour Pips: ", -91, 25, 69, 20)
        GUICtrlSetTip(-1, " the color of big pips at each hour " & $revert_tip)
        $butt_big_pips_pen = GUICtrlCreateButton("", 91, -2, 62, 16)
        GUICtrlSetTip(-1, " click here to choose the color for hour pips ")

        $label_pips_pen = GUICtrlCreateLabel("Minute Pips: ", -91, 25, 69, 20)
        GUICtrlSetTip(-1, " the color of wee minute pips around the clock " & $revert_tip & @CRLF & _
                            " (to make them disappear, set them to the face color) ")
        $butt_pips_pen = GUICtrlCreateButton("", 91, -2, 62, 16)
        GUICtrlSetTip(-1, " click here to choose the color for minute pips ")

        $label_prefs_trans = GUICtrlCreateLabel("Transparency: ", -91, 25, 69, 20)
        GUICtrlSetTip(-1, " the opaquenessnessness of your clock " & $revert_tip)
        $slider_prefs_trans = GUICtrlCreateSlider(85, -2, 75, 20, $TBS_NOTICKS)
        GUICtrlSetLimit(-1, 99, 0)
        $tip_trans = "%" & @CRLF & " use can use the arrow keys and PgUp/PgDn to adjust this "
        GUICtrlSetTip(-1, " currently " & $WinTrans & $tip_trans)
        GUICtrlSetData($slider_prefs_trans$WinTrans; needs to be set now for live update


        $handy_tip_01 = GUICtrlCreateLabel("Tip: To switch schemes quickly, use F10 and F11.", -80, 45, 350, 40)

    ; Pips and Numerals prefs..

        GUISetCoord(228, 80)

        GUICtrlCreateGroup("Pips and Numerals..", 0, 0, 207, 120)

        $check_draw_numerals = GUICtrlCreateCheckbox("Draw Numerals", 10, 20)
        GUICtrlSetTip(-1, " you can choose to not draw the numerals. " & @CRLF & _
                            " the pips will move out to the edge, and you can control them. ")
        GUICtrlSetState(-1, $draw_numerals)

        $check_draw_pips = GUICtrlCreateCheckbox("Draw Pips", 100, 0)
        GUICtrlSetTip(-1, " you can choose to not draw the Pips. this is the same as setting them to zero, but quicker) ")
        GUICtrlSetState(-1, $draw_pips)

        $rev_tip = " [click this label to revert to the last saved setting. shift-click to get back the master default setting] "
        $label_pips_rim = GUICtrlCreateLabel("Pips outer rim", -100, 25, 75, 20)
        GUICtrlSetTip(-1, " this enables you to shift the outer rim inwards. depending on the length of the pips, they could be inside or outside the rim. " & @CRLF & $rev_tip)
        $tip_pips_rim = " the distance between the pips rim and the outer edge of the clock (or numerals, if enabled) " & @CRLF & " [default is 2, currently "
        $slider_pips_rim = GUICtrlCreateSlider(80, 0, 115, 20, $TBS_NOTICKS)
        GUICtrlSetTip(-1, $tip_pips_rim  & $pips_outer_rim & "] ")
        GUICtrlSetLimit(-1, 50, 0)
        GUICtrlSetData(-1, $pips_outer_rim)


        $label_minute_pips_size = GUICtrlCreateLabel("Minute pips size", -80, 20, 75, 20)
        GUICtrlSetTip(-1, " the length of the minute pips. set this to zero (or rim) to make them invisible. other effects are possible. " _
                                                                                                            & @CRLF & $rev_tip)
        $tip_minute_pips = " the length of the minute pips " & @CRLF & " [default is 6, currently "
        $slider_minute_pips_size = GUICtrlCreateSlider(80, 0, 115, 20, $TBS_NOTICKS)
        GUICtrlSetTip(-1, $tip_minute_pips & $minute_pips_size & "] ")
        GUICtrlSetLimit(-1, 50, 0)
        GUICtrlSetData(-1, $minute_pips_size)


        $label_hour_pips_size = GUICtrlCreateLabel("Hour pips size", -80, 20, 75, 20)
        GUICtrlSetTip(-1, " the length of the hour pips. set this to zero (or rim) to make them invisible. other effects are possible. " _
                                                                                                            & @CRLF & $rev_tip)
        $tip_hour_pips = " the length of the hour pips " & @CRLF & " [default is 10, currently "
        $slider_hour_pips_size = GUICtrlCreateSlider(80, 0, 115, 20, $TBS_NOTICKS)
        GUICtrlSetTip(-1, $tip_hour_pips & $hour_pips_size & "] ")
        GUICtrlSetLimit(-1, 50, 0)
        GUICtrlSetData(-1, $hour_pips_size)

        if $draw_pips = $GUI_UNCHECKED then
            for $i = $label_pips_rim to $slider_hour_pips_size
                GUICtrlSetState($i$GUI_HIDE)
            next
        endif

    ; Hands..

        GUISetCoord(228, 205)

        GUICtrlCreateGroup("Hands..", 0, 0, 207, 90)

        $label_size_second_hand = GUICtrlCreateLabel("Second hand size", 10, 18, 85, 20)
        GUICtrlSetTip(-1, " the length of the second hand (% of radius) " & @CRLF & $rev_tip)
        $tip_second_hand = " the length of the second hand " & @CRLF & " [default is 75, currently "
        $slider_size_second_hand = GUICtrlCreateSlider(85, 0, 110, 20, $TBS_NOTICKS)
        GUICtrlSetTip(-1, $tip_second_hand & $second_hand_size & "] ")
        GUICtrlSetLimit(-1, 100, 0)
        GUICtrlSetData(-1, $second_hand_size)


        $label_size_minute_hand = GUICtrlCreateLabel("Minute hand size", -85, 20, 85, 20)
        GUICtrlSetTip(-1, " the length of the minute hand (% of radius) " & @CRLF & $rev_tip)
        $tip_minute_hand = " the length of the minute hand " & @CRLF & " [default is 67, currently "
        $slider_size_minute_hand = GUICtrlCreateSlider(85, 0, 110, 20, $TBS_NOTICKS)
        GUICtrlSetTip(-1, $tip_minute_hand & $minute_hand_size & "] ")
        GUICtrlSetLimit(-1, 100, 0)
        GUICtrlSetData(-1, $minute_hand_size)


        $label_size_hour_hand = GUICtrlCreateLabel("Hour hand size", -85, 20, 85, 20)
        GUICtrlSetTip(-1, " the length of the hour hand (% of radius) " & @CRLF & $rev_tip)
        $tip_hour_hand = " the length of the hour hand " & @CRLF & " [default is 50, currently "
        $slider_size_hour_hand = GUICtrlCreateSlider(85, 0, 110, 20, $TBS_NOTICKS)
        GUICtrlSetTip(-1, $tip_hour_hand & $hour_hand_size & "] ")
        GUICtrlSetLimit(-1, 100, 0)
        GUICtrlSetData(-1, $hour_hand_size)

    ; Third tab..
    ;
    $tab_prefs_title3 = GUICtrlCreateTabItem( " Audio " )
    GUICtrlSetTip($tab_prefs_title" Audio Preferences.. ")

    ; Alerts..

        GUISetCoord(5, 30)

        $group_alert_presets = GUICtrlCreateGroup("Alert Presets..", 0, 0, 220, 45)

        $ex_tip = @CRLF & " right-click for the alerts export menu "
        global $combo_alert_presets = GUICtrlCreateCombo("", 5, 16, 115, 20, _
                BitOR($CBS_SORT$CBS_DROPDOWN$CBS_AUTOHSCROLL$WS_VSCROLL))
        GUICtrlSetTip(-1, " your alerts " & $ex_tip)
        GUICtrlSetState(-1, $GUI_DROPACCEPTED)

        $butt_del_alert = GUICtrlCreateButton("x", 119, 0, 16, 20)
        GUICtrlSetTip(-1, " delete the current alert" & $ex_tip)

        $butt_revert_alert = GUICtrlCreateButton("&revert", 19, 0, 36, 20)
        GUICtrlSetTip(-1, " revert back to the last saved settings " & $ex_tip)

        $butt_save_alert = GUICtrlCreateButton("&save", 38, 0, 32, 20)
        GUICtrlSetTip(-1, " save this alert with all the current settings " & $ex_tip)


        $context_ex_alerts = GUICtrlCreateContextMenu($combo_alert_presets)
        $exst_1 = GUICtrlCreateMenuitem("Export Alert.."$context_ex_alerts)
        $exst_9 = GUICtrlCreateMenuitem("Export Alert into Collection.."$context_ex_alerts)
        GUICtrlCreateMenuitem(""$context_ex_alerts)
        $exst_2 = GUICtrlCreateMenuitem("Export All Alerts.."$context_ex_alerts)

        $context_ex_alerts2 = GUICtrlCreateContextMenu($butt_del_alert)
        $exst_3 = GUICtrlCreateMenuitem("Export Alert.."$context_ex_alerts2)
        $exst_10 = GUICtrlCreateMenuitem("Export Alert into Collection.."$context_ex_alerts2)
        GUICtrlCreateMenuitem(""$context_ex_alerts2)
        $exst_4 = GUICtrlCreateMenuitem("Export All Alerts.."$context_ex_alerts2)

        $context_ex_alerts3 = GUICtrlCreateContextMenu($butt_revert_alert)
        $exst_5 = GUICtrlCreateMenuitem("Export Alert.."$context_ex_alerts3)
        $exst_11 = GUICtrlCreateMenuitem("Export Alert into Collection.."$context_ex_alerts3)
        GUICtrlCreateMenuitem(""$context_ex_alerts3)
        $exst_6 = GUICtrlCreateMenuitem("Export All Alerts.."$context_ex_alerts3)

        $context_ex_alerts4 = GUICtrlCreateContextMenu($butt_save_alert)
        $exst_7 = GUICtrlCreateMenuitem("Export Alert.."$context_ex_alerts4)
        $exst_12 = GUICtrlCreateMenuitem("Export Alert into Collection.."$context_ex_alerts4)
        GUICtrlCreateMenuitem(""$context_ex_alerts4)
        $exst_8 = GUICtrlCreateMenuitem("Export All Alerts.."$context_ex_alerts4)



        GUISetCoord(5, 80)

        $radio_alert_switch_beep = GUICtrlCreateRadio("Beep Style", 0, 0, 80, 22, BitOr($BS_PUSHLIKE$BS_VCENTER$BS_CENTER))
        GUICtrlSetTip(-1, " use a beep synth sound for this alert preset ")
        $radio_alert_switch_wavs = GUICtrlCreateRadio("Wav File", 85, 0, 80, 22, BitOr($BS_PUSHLIKE$BS_VCENTER$BS_CENTER))
        GUICtrlSetTip(-1, " use a wav file for this alert preset ")

    ; beeps..

        GUISetCoord(5, 108)

        $tip_beep_label = " click this label to revert the setting back to its last saved value"
        $group_alert_params = GUICtrlCreateGroup("Beep Synth ;o)..", 0, 0, 350, 125)

        $label_alert_repeat = GUICtrlCreateLabel("repeat: ", 10, 25, 83)
        GUICtrlSetTip(-1, $tip_beep_label)
        $input_alert_repeat = GUICtrlCreateInput("", 85, -3, 45, 20, BitOr($ES_LEFT$ES_NUMBER))

        $label_alert_beep_len = GUICtrlCreateLabel("beep length: ", -85, 27, 83)
        GUICtrlSetTip(-1, $tip_beep_label)
        $input_alert_beep_len = GUICtrlCreateInput("", 85, -3, 45, 20, BitOr($ES_LEFT$ES_NUMBER))

        $label_alert_sleep = GUICtrlCreateLabel("sleep length: ", -85, 27, 83)
        GUICtrlSetTip(-1, $tip_beep_label)
        $input_alert_sleep = GUICtrlCreateInput("", 85, -3, 45, 20, BitOr($ES_LEFT$ES_NUMBER))

        $label_alert_beeps = GUICtrlCreateLabel("no. of beeps: ", -85, 27, 83)
        GUICtrlSetTip(-1, $tip_beep_label)
        $input_alert_beeps = GUICtrlCreateInput("", 85, -3, 45, 20, BitOr($ES_LEFT$ES_NUMBER))


        GUISetCoord(170, 108)

        $label_alert_bottom = GUICtrlCreateLabel("bottom: ", 10, 25, 83)
        GUICtrlSetTip(-1, $tip_beep_label)
        $input_alert_bottom = GUICtrlCreateInput("", 85, -3, 45, 20)

        $label_alert_step =  GUICtrlCreateLabel("step: ", -85, 27, 83)
        GUICtrlSetTip(-1, $tip_beep_label)
        $input_alert_step =  GUICtrlCreateInput("", 85, -3, 45, 20, BitOr($ES_LEFT$ES_NUMBER))

        $label_alert_scaler = GUICtrlCreateLabel("scaler: ", -85, 27, 83)
        GUICtrlSetTip(-1, $tip_beep_label)
        $input_alert_scaler = GUICtrlCreateInput("", 85, -3, 45, 20, BitOr($ES_LEFT$ES_NUMBER))

        $check_alert_and_down = GUICtrlCreateCheckbox(" play second loop", -85, 25, 120, 20, BitOr($ES_LEFT$ES_NUMBER))
        GUICtrlSetTip(-1, " also play the down scale ")

        global $icon_beepalert_test = GUICtrlCreateIcon("shell32.dll", 246, 152, 7, 16, 16)
        GUICtrlSetTip(-1, " test this alert ")
        GUICtrlSetImage(-1, "shell32.dll", 246, 0)

    ; wavs..

        GUISetCoord(5, 108)

        $group_wav_file_params = GUICtrlCreateGroup("Wav File Parameters..", 0, 0, 350, 125)

        $label_alert_wavname = GUICtrlCreateLabel("wav file: ", 10, 25, 83)
        GUICtrlSetState(-1, $GUI_HIDE)
        GUICtrlSetTip(-1, " click this label to get back the last saved setting " & @CRLF & _
                        " if you mess up, and save it as a Beep Style by mistake, you can click here to get back the last wav file path " )
        $input_alert_wavname = GUICtrlCreateInput("", 75, -3, 212)
        GUICtrlSetState(-1, $GUI_HIDE)

        $icon_alert_wav_in = GUICtrlCreateIcon("shell32.dll", 4, 220, 2, 16, 16)
        GUICtrlSetTip(-1, " browse for a WAV file to use as an alarm ")
        GUICtrlSetState(-1, $GUI_HIDE)

        global $icon_alert_wav_play = GUICtrlCreateIcon("shell32.dll", 246, 20, 1, 16, 16)
        GUICtrlSetTip(-1, " click here to play the currently selected WAV file ")
        GUICtrlSetState(-1, $GUI_HIDE)


        $label_alert_pause = GUICtrlCreateLabel("pause: ", -315, 25, 83)
        GUICtrlSetState(-1, $GUI_HIDE)
        GUICtrlSetTip(-1, " click this label to get back the last saved setting ")

        $input_alert_pause = GUICtrlCreateInput("", 75, -3, 40, 20, BitOr($ES_LEFT$ES_NUMBER))
        GUICtrlSetState(-1, $GUI_HIDE)

    ; Master Speech prefs..

        GUISetCoord(5, 238)

            $group_master_speech_params = GUICtrlCreateGroup("Master Speech Settings..", 0, 0, 350, 98)

            $label_master_volume = GUICtrlCreateLabel("Speech Volume: ", 10, 25, 80, 20)
            $vtip = " adjust the volume of the speech , from 0 (silent) to 100 (loud) "
            $slider_master_volume = GUICtrlCreateSlider(80, -4, 133, 35)
            GUICtrlSetTip(-1, $vtip & @CRLF & " [current volume: " & $speech_volume & "] ")
            GUICtrlSetLimit(-1, 100, 0)
            GUICtrlSetData(-1, $speech_volume)

            $label_master_rate = GUICtrlCreateLabel("Speech Rate: ", -80, 40, 75, 20)
            GUICtrlSetTip(-1, " adjust the rate of the speech (this setting affects all spoken messages and chimes) ")
            $rtip = " adjust the rate of the speech, from -10 (slow) to 10 (fast) "
            $slider_master_rate = GUICtrlCreateSlider(80, -4, 133, 35)
            GUICtrlSetTip(-1, $rtip  & @CRLF & " [current rate: " & $speech_rate & "] ")
            GUICtrlSetLimit(-1, 10, -10)
            GUICtrlSetData(-1, $speech_rate)

            $label_master_voice = GUICtrlCreateLabel("Voice: ", 150, -31, 32, 20)
            $s_tip = " choose which voice to use for spoken messages and chimes. the default is 'Sam', but you may have others "
            GUICtrlSetTip(-1, $s_tip)
            $input_master_voice = GUICtrlCreateInput($speech_voice, 40, -3, 64, 20)
            GUICtrlSetTip(-1, $s_tip)


    ; Help system

        GUISetCoord(230, 30)
        $group_help_box = GUICtrlCreateGroup("Help..", 0, 0, 200, 75)
        $help_default_tip = "Hover over a control to receive help with the item. Click any of the labels to set that parameter back to its last saved value. aka. 'revert' "
        $label_help_box = GUICtrlCreateLabel($help_default_tip, 5, 17, 190, 53)


    ; let's do it..

    ; a dll fade-in sometimes causes controls to not be drawn properly (see FadeIn() for a better way), so here's a slide..
    DllCall("user32.dll""int""AnimateWindow""hwnd"$prefs_dialog"int", 200, "long", 0x00040004 )

    GUISetState()

    HotKeySet("{PAUSE}""SoundOff"; for some reason, setting this here has no effect
    HotKeySet("^+{TAB}""PreviousTab")
    HotKeySet("^{TAB}""NextTab")
    HotKeySet("{F10}""SchemeSwitchMsg")
    HotKeySet("{F11}""SchemeSwitchMsg")
    HotKeySet("{ESC}""KillPrefs")

    while $show_prefs ; yeah, I guess we could use $prefs_open :/

        if not $init_prefs then  ; activate the first (or previously selected) alarm, etc..

            ; always init first tab regardless..
            UpdateAlertCombos()
            ControlCommand($prefs_dialog""$combo_alarm_presets"SelectString"$current_preset)

            ; which tab to jump to?
            for $i = 2 to $choose_tab
                ControlCommand($prefs_dialog""$tab_prefs"TabRight""")
            next
            $init_prefs = 1
        endif

        $msg = GUIGetMsg()
        $cpc = ""

        ; thank God for code-folding! (also the reason for the group indentations throughout)
        switch $msg

            ; update tab when clicked
            case $tab_prefs
                ; if there have been changes, don't update the tab, otherwise load the current preset.
                ; this ensures it gets updated at least one time, to load the preset's values into the controls.
                if not HasChanged(1, 20) then ControlCommand($prefs_dialog""$combo_scheme_presets"SelectString"$current_scheme)
                if not HasChanged(41, 49) then ControlCommand($prefs_dialog""$combo_alert_presets"SelectString"$current_alert)
                $lc = 50 ; update titlebar immediately

            case $GUI_EVENT_CLOSE
                GUIDelete($prefs_dialog)
                exitloop

            case $GUI_EVENT_DROPPED
                if @GUI_DRAGID = -1 then
                    if not StringInStr(FileGetAttrib(@GUI_DRAGFILE), "D") then
                        $import_file = @GUI_DRAGFILE
                        switch GetExtension($import_file)
                            case "wav"
                                $new_alert = @GUI_DRAGFILE
                                AddAlert($new_alert)
                                ControlClick($prefs_dialog""$icon_alert_in; only activates if first tab is active. handy.
                            case "ini"
                                ImportIniFile(@GUI_DRAGFILE)
                        endswitch
                    endif
                endif

            ; Alarms & Chimes..

                ; this always gets called at least once, automatically (see above)
                case $combo_alarm_presets

                    $current_preset = GUICtrlRead($combo_alarm_presets)
                    RememberComboSelection($previous_combo_alarms$current_preset)
                    $index = AlarmIndex($current_preset)

                    $current_alarm_freq = $my_alarms[$index][0] ; the text, ie. "Weekends"
                    GUICtrlSetData($combo_frequency$current_alarm_freq)

                    $current_alarm_hour = $my_alarms[$index][1]
                    GUICtrlSetData($Alarm_Hour$current_alarm_hour)
                    $current_alarm_min = $my_alarms[$index][2]
                    GUICtrlSetData($prefs_dialog_Min$current_alarm_min)
                    $current_alarm_ampm = $my_alarms[$index][3]
                    GUICtrlSetData($Alarm_AMPM$current_alarm_ampm)

                    $current_alarm_month = $my_alarms[$index][4]    ; load even when "Daily", or whatever,
                    $current_alarm_day = $my_alarms[$index][5]        ; in case they switch back to "One Date"
                    $current_alarm_year = $my_alarms[$index][6]        ; etc.

                    global $current_custom_type = $my_alarms[$index][14]
                    global $current_custom_period = $my_alarms[$index][15]

                    if $current_alarm_freq = "One Date" or $current_alarm_freq = "Custom" then
                        GUICtrlSetData($Alarm_Cal$current_alarm_year & "/" & $current_alarm_month & "/" & $current_alarm_day)
                        GUICtrlSetState($Alarm_Cal$GUI_ENABLE)
                    else
                        GUICtrlSetData($Alarm_Cal, @YEAR & "/" & @MON & "/" & @MDAY) ; set back to today's date
                        GUICtrlSetState($Alarm_Cal$GUI_DISABLE)
                    endif

                    if $current_alarm_freq = "Custom" then
                        for $i = $label_custom_frequency to $combo_interval_type
                            GUICtrlSetState($i$GUI_SHOW)
                        next
                        GUICtrlSetData($combo_interval_period$current_custom_period)
                        GUICtrlSetData($combo_interval_type$current_custom_type)
                    else
                        for $i = $label_custom_frequency to $combo_interval_type
                            GUICtrlSetState($i$GUI_HIDE)
                        next
                    endif

                    global $current_alarm_status = IniReadCheckboxValue($ini_path_alarms$alarm_names[$index], "active", 1)

                    if $current_alarm_status = 1 then
                        GUICtrlSetData($check_alarm_enabled"enabled.")
                        GUICtrlSetState($check_alarm_enabled$GUI_CHECKED)
                    else
                        GUICtrlSetData($check_alarm_enabled"disabled.")
                        GUICtrlSetState($check_alarm_enabled$GUI_UNCHECKED)
                    endif

                    if $AlarmStatus[2] = 1 then
                        GUICtrlSetData($check_master_enabled"enabled.")
                        GUICtrlSetState($check_master_enabled$GUI_CHECKED)
                    else
                        GUICtrlSetData($check_master_enabled"disabled.")
                        GUICtrlSetState($check_master_enabled$GUI_UNCHECKED)
                    endif

                    $current_input_message = $my_alarms[$index][8]
                    if $current_input_message then GUICtrlSetData($combo_message$current_input_message)
                    ControlCommand($prefs_dialog""$combo_message"SelectString"$current_input_message)

                    GUICtrlSetBkColor($butt_flash_color"0x" & $my_alarms[$index][9])
                    $current_flash_color = $my_alarms[$index][9]

                    $current_alert = $my_alarms[$index][10]
                    if $current_alert <> "" then GUICtrlSetData($combo_alert$current_alert)

                    global $current_speech_volume = $my_alarms[$index][11]
                    global $current_speech_voice = $my_alarms[$index][12]
                    global $current_speech_rate = $my_alarms[$index][13]

                    IniWrite($ini_path$my_shortname"current_preset", GUICtrlRead($combo_alarm_presets))
                    $lc = 50

                    ; reset scheme changed flags..
                    ResetChanges(21, 40)

                    ControlFocus($prefs_dialog""$combo_alarm_presets )

                case $butt_del_alarm

                    if ce_IsPressed(10) then
                        RecoverBackup($ini_path_alarms)
                        GetAlarms()
                        continueloop
                    endif

                    StoreBackup($ini_path_alarms)
                    IniDelete($ini_path_alarms, GUICtrlRead($combo_alarm_presets))
                    $occ = ControlCommand($prefs_dialog""$combo_alarm_presets"FindString", GUICtrlRead($combo_alarm_presets))
                    ControlCommand($prefs_dialog""$combo_alarm_presets"DelString"$occ)
                    GetAlarms()

                    $previous_alarm = GetLastComboSelection($previous_combo_alarms$alarm_names)
                    ControlCommand($prefs_dialog""$combo_alarm_presets"SelectString"$previous_alarm)

                case $butt_revert_alarm
                    GetAlarms()
                    ControlCommand($prefs_dialog""$combo_alarm_presets"SelectString", GUICtrlRead($combo_alarm_presets))

                case $butt_save_alarm

                    RemoveBackup($ini_path_alarms)

                    global $new_alarm = StringReplace(GUICtrlRead($combo_alarm_presets), "[""{")
                    $new_alarm = StringReplace($new_alarm"]""}")
                    if not InArray($alarm_names$new_alarm) then ; create an (almost) empty preset..
                        IniWrite($ini_path_alarms$new_alarm"alert", GUICtrlRead($combo_alert)) ; or whatever
                        ControlCommand($prefs_dialog""$combo_alarm_presets"AddString"$new_alarm)
                        GetAlarms()
                    endif

                    $index = AlarmIndex($new_alarm)

                    if Number(GUICtrlRead($Alarm_Hour)) > 0 and Number(GUICtrlRead($Alarm_Hour)) < 13 then
                        $my_alarms[$index][1] = GUICtrlRead($Alarm_Hour)
                    else
                        $my_alarms[$index][1] = 12
                        GUICtrlSetData($Alarm_Hour"12")
                    endif
                    if Number(GUICtrlRead($prefs_dialog_Min)) >= 0 and Number(GUICtrlRead($prefs_dialog_Min)) < 60 then
                        $my_alarms[$index][2] = GUICtrlRead($prefs_dialog_Min)
                    else
                        $my_alarms[$index][2] = 00
                        GUICtrlSetData($prefs_dialog_Min"00")
                    endif
                    if StringLower(GUICtrlRead($Alarm_AMPM)) = "am" or StringLower(GUICtrlRead($Alarm_AMPM)) = "pm" then
                        $my_alarms[$index][3] = GUICtrlRead($Alarm_AMPM)
                    else
                        $my_alarms[$index][3] = "am"
                        GUICtrlSetData($Alarm_AMPM"am")
                    endif

                    $my_alarms[$index][0] = GUICtrlRead($combo_frequency)

                    ; we don't care if these apply, it's user information (date of alarm creation/update), and so we'll store it..
                    ; you can check that date in the prefs, by switching to 'One Date', or 'Custom'. In short, why not?
                    $prefs_dialog_MonthCalDate = StringSplit(GUICtrlRead($Alarm_Cal), "/")
                    $my_alarms[$index][4] = $prefs_dialog_MonthCalDate[2]
                    $my_alarms[$index][5] = $prefs_dialog_MonthCalDate[3]
                    $my_alarms[$index][6] = $prefs_dialog_MonthCalDate[1]

                    $my_alarms[$index][14] = GUICtrlRead($combo_interval_type; yup, this came later, hence 14/15
                    $my_alarms[$index][15] = GUICtrlRead($combo_interval_period)

                    ; for new alarms, this is hidden, so they always begin disabled..
                    if GUICtrlRead($check_alarm_enabled) = 1 then
                        $my_alarms[$index][7] = 1
                    else
                        $my_alarms[$index][7] = 0
                    endif

                    $my_alarms[$index][8] = GUICtrlRead($combo_message)
                    $my_alarms[$index][9] = $current_flash_color ; enables new alarms to pick up current color
                    $my_alarms[$index][10] = GUICtrlRead($combo_alert)

                    ; copy voice settings to new preset..
                    $my_alarms[$index][11] = $current_speech_volume
                    $my_alarms[$index][12] = $current_speech_voice
                    $my_alarms[$index][13] = $current_speech_rate


                    $primed[$index] = 1
                    $current_preset = $new_alarm
                    SaveAlarm($index)

                    AddMessageToList()

                    ; this will also reset $changes for this group..
                    ControlCommand($prefs_dialog""$combo_alarm_presets"SelectString"$current_preset)

                ; where we try and make up for all the extra bytes in the GUI creation
                case $ex_1$ex_3$ex_5$ex_7
                    ExportAlarm()

                case $ex_2$ex_4$ex_6$ex_8
                    ExportAllAlarms()

                case $ex_9 to $ex_12
                    ExportAlarmIntoCollection()

                case $Alarm_Hour
                    $changes[31] = 0
                    if GUICtrlRead($Alarm_Hour) <> $my_alarms[$index][1] then $changes[31] = 1 ; hour

                case $prefs_dialog_Min
                    $changes[32] = 0
                    if GUICtrlRead($Alarm_Hour) <> $my_alarms[$index][2] then $changes[32] = 1 ; hour

                case $Alarm_AMPM
                    $changes[33] = 0
                    if GUICtrlRead($Alarm_AMPM) <> $my_alarms[$index][3] then $changes[33] = 1 ; ampm

                case $butt_now
                    $this_hour = HourToHumanTime(@HOUR)
                    $current_alarm_hour = $this_hour[0]
                    GUICtrlSetData($Alarm_Hour$current_alarm_hour)
                    $current_alarm_min = @MIN
                    GUICtrlSetData($prefs_dialog_Min$current_alarm_min)
                    $current_alarm_ampm = $this_hour[1]
                    GUICtrlSetData($Alarm_AMPM$current_alarm_ampm)
                    $current_alarm_date = @YEAR & "/" & @MON & "/" & @MDAY
                    GUICtrlSetData($Alarm_Cal$current_alarm_date)
                    $current_alarm_month = @MON
                    $current_alarm_day = @MDAY
                    $current_alarm_year = @YEAR

                    if $current_alarm_hour <> $my_alarms[$index][1] then $changes[31] = 1 ; hour
                    if $current_alarm_min <> $my_alarms[$index][2] then $changes[32] = 1 ; minute
                    if $current_alarm_ampm <> $my_alarms[$index][3] then $changes[33] = 1 ; ampm
                    if $current_alarm_month <> $my_alarms[$index][4] then $changes[34] = 1 ; month
                    if $current_alarm_day <> $my_alarms[$index][5] then $changes[35] = 1 ; day
                    if $current_alarm_year <> $my_alarms[$index][6] then $changes[36] = 1 ; year

                    ControlFocus($prefs_dialog""$prefs_dialog_Min)

                case $Alarm_Cal

                    $prefs_dialog_MonthCalDate = StringSplit(GUICtrlRead($Alarm_Cal), "/")
                    $current_alarm_month = $prefs_dialog_MonthCalDate[2]
                    $current_alarm_day = $prefs_dialog_MonthCalDate[3]
                    $current_alarm_year = $prefs_dialog_MonthCalDate[1]
                    $changes[34] = 0
                    $changes[35] = 0
                    $changes[36] = 0
                    if $current_alarm_month <> $my_alarms[$index][4] then $changes[34] = 1
                    if $current_alarm_day <> $my_alarms[$index][5] then $changes[35] = 1
                    if $current_alarm_year <> $my_alarms[$index][6] then $changes[36] = 1


                case $combo_frequency

                    $current_alarm_freq = GUICtrlRead($combo_frequency)

                    if $current_alarm_freq = "One Date" or $current_alarm_freq = "Custom" then
                        GUICtrlSetData($Alarm_Cal$current_alarm_year & "/" & $current_alarm_month & "/" & $current_alarm_day)
                        GUICtrlSetState($Alarm_Cal$GUI_ENABLE)
                    else
                        GUICtrlSetData($Alarm_Cal, @YEAR & "/" & @MON & "/" & @MDAY)
                        GUICtrlSetState($Alarm_Cal$GUI_DISABLE)
                    endif

                    if $current_alarm_freq = "Custom" then
                        for $i = $label_custom_frequency to $combo_interval_type
                            GUICtrlSetState($i$GUI_SHOW)
                            GUICtrlSetData($combo_interval_period$current_custom_period)
                            GUICtrlSetData($combo_interval_type$current_custom_type)
                        next
                    else
                        for $i = $label_custom_frequency to $combo_interval_type
                            GUICtrlSetState($i$GUI_HIDE)
                        next
                    endif



                    $changes[21] = 1
                    if $current_alarm_freq = $my_alarms[$index][0] then $changes[21] = 0

                    switch $current_alarm_freq
                        case "Daily"
                            GUICtrlSetTip($combo_frequency" your alarm is set to play every day ")
                        case "One Date"
                            GUICtrlSetTip($combo_frequency" your alarm is set to play only at one specific date and time ")
                        case "Weekdays"
                            GUICtrlSetTip($combo_frequency" your alarm is set to play every Weekday (Mon-Fri) ")
                        case "Weekends"
                            GUICtrlSetTip($combo_frequency" your alarm is set to play only on Weekends (Sat-Sun) ")
                        case "Custom"
                            GUICtrlSetTip($combo_frequency" your alarm is set to recur at custom intervals, " & @CRLF & _
                                                                                    "either days, weeks, months, or years ")
                    endswitch


                case $combo_interval_type
                    $current_custom_type = GUICtrlRead($combo_interval_type)
                    if $current_custom_type <> $my_alarms[$index][14] then $changes[28] = 1

                case $combo_interval_period
                    $current_custom_period = GUICtrlRead($combo_interval_period)
                    if $current_custom_period <> $my_alarms[$index][15] then $changes[29] = 1


                case $label_flash_color
                    $current_flash_color = $my_alarms[$index][9]
                    GUICtrlSetBkColor($butt_flash_color"0x" & $current_flash_color)
                    $changes[22] = 0

                case $butt_flash_color
                    $cpc = GetPickedColor($current_flash_color$current_scheme, true)
                    if $cpc <> "" then
                        $changes[22] = 0
                        $index = AlarmIndex(GUICtrlRead($combo_alarm_presets))
                        if StringTrimLeft($cpc, 2) <> $my_alarms[$index][9] then $changes[22] = 1
                        $current_flash_color = StringTrimLeft($cpc, 2)
                        GUICtrlSetBkColor($butt_flash_color$cpc)
                    endif


                case $label_alert

                    if InArray($alert_names$my_alarms[$index][10]) then ; user may have deleted this alert
                        $current_alert = $my_alarms[$index][10]
                        ControlCommand($prefs_dialog""$combo_alert"SelectString"$current_alert)
                        $changes[23] = 0
                    endif

                case $combo_alert
                    $index = AlarmIndex(GUICtrlRead($combo_alarm_presets))
                    $changes[23] = 0
                    if GUICtrlRead($combo_alert) <> $my_alarms[$index][10] then $changes[23] = 1
                    $current_alert = GUICtrlRead($combo_alert)
                    UpdateAlertCombos()

                case $icon_alert_in
                    if $new_alert = "" then
                        PrefsFileDialogOpen()
                        $open_at = IniRead($ini_path$my_shortname"wavs_folder"$data_parent & "\alerts")
                        $tmp_open =  FileOpenDialog("Pick a WAV file to play as your alarm..", _
                            $open_at"WAV Files (*.wav)", 1, "alarm.wav")
                        if $tmp_open <> "" then
                            $new_alert = $tmp_open
                            IniWrite($ini_path$my_shortname"wavs_folder", GetParent($new_alert))
                        endif
                        PrefsFileDialogClose()
                        AddAlert($new_alert)
                    endif
                    $new_alert = ""


                case $icon_alert_test
                    switch $play_idx
                        case 2
                            SoundOff()
                        case 1 to 9
                            continueloop
                        case else
                            $play_idx = 2
                            if IniRead($ini_path_alerts$current_alert"wav""") = "" then $play_idx = 3 ; beep
                            SwitchIconsPLAYING()
                            IGuessItsAlarmTime(GUICtrlRead($combo_alert), true, $current_flash_color)
                    endswitch

                case $combo_message
                    if $current_input_message <> GUICtrlRead($combo_message) then
                        $changes[24] = 1
                    else
                        $changes[24] = 0
                    endif
                    AddMessageToList()


                case $menu_chimes_clear_list
                    IniDelete($ini_path$my_shortname"recent_chimes")
                    GUICtrlSetData($combo_chimes"")
                    GetChimesList()

                ;    GUICtrlSetData($combo_chimes$current_input_message)
                ;    ControlCommand($prefs_dialog""$combo_chimes"SelectString"$current_chimes)


                case $menu_msg_clear_list
                    IniDelete($ini_path$my_shortname"recent_messages")
                    GUICtrlSetData($combo_message"")
                    GUICtrlSetData($combo_message$current_input_message)
                    ControlCommand($prefs_dialog""$combo_message"SelectString"$current_input_message)

                case $icon_msg_test
                    switch $play_idx
                        case 6
                            SoundOff()
                        case 1 to 9
                            continueloop
                        case else
                            $play_idx = 6
                            SwitchIconsPLAYING()
                            TestMessage(GUICtrlRead($combo_message), $index$current_speech_volume$current_speech_voice$current_speech_rate)
                    endswitch
                    AddMessageToList()

                case $label_message
                    DialogSetVoice(AlarmIndex(GUICtrlRead($combo_alarm_presets)))

                case $label_alarm_enabled ; this means you can overlap them, too
                    ControlClick($prefs_dialog""$check_alarm_enabled)

                case $check_alarm_enabled
                    ToggleThisAlarm(AlarmIndex(GUICtrlRead($combo_alarm_presets)))
                    ControlFocus($prefs_dialog""$combo_alarm_presets )

                case $label_master_enabled
                    ControlClick($prefs_dialog""$check_master_enabled)
                    ControlFocus($prefs_dialog""$combo_alarm_presets)

                case $check_master_enabled
                    ToggleAlarm()

                case $butt_exclusions
                    EditExclusions()

                case $check_chimes

                    if $init_prefs = 1 then ToggleChime()

                    if $do_chime = 1 then
                        GUICtrlSetState($icon_chime_test$GUI_SHOW)
                        for $i = $combo_chime_minute to $combo_chimes
                            GUICtrlSetState($i$GUI_ENABLE)
                        next
                    else
                        GUICtrlSetState($icon_chime_test$GUI_HIDE)
                        for $i = $combo_chime_minute to $combo_chimes
                            GUICtrlSetState($i$GUI_DISABLE)
                        next
                    endif

                case $icon_chime_test
                    AddChimeToList()
                    switch $play_idx
                        case 7, 8, 9
                            SoundOff()
                        case 2 to 9
                            continueloop
                        case else
                            $play_idx = 9
                            SwitchIconsPLAYING()
                            DoChime(GUICtrlRead($combo_chime_minute))
                    endswitch

                case $label_chime
                    GUICtrlSetData($combo_chimes"4000")
                    continuecase

                case $combo_chimes
                    AddChimeToList()

                case $combo_chime_minute
                    $chime_minute = GUICtrlRead($combo_chime_minute; Number() <- letters get you "0", but fux! 07 -> 7
                    IniWrite($ini_path$my_shortname"chime_minute",  $chime_minute;allow 00
                    $chime_done = 0

            ; Scheme Prefs..

                ; we are working with the live clock, here..
                case $combo_scheme_presets

                    $current_scheme = GUICtrlRead($combo_scheme_presets)
                    RememberComboSelection($previous_combo_schemes$current_scheme)
                    SwitchScheme($current_scheme)

                    GUICtrlSetBkColor($butt_color_clock_face"0x" & $face_color)
                    GUICtrlSetBkColor($butt_numerals_color"0x" & $numerals_color)
                    GUICtrlSetBkColor($butt_second_hand_color"0x" & $second_hand_color)
                    GUICtrlSetBkColor($butt_hour_pen"0x" & $hour_pen)
                    GUICtrlSetBkColor($butt_minute_pen"0x" & $minute_pen)
                    GUICtrlSetBkColor($butt_pips_pen"0x" & $pips_pen)
                    GUICtrlSetBkColor($butt_big_pips_pen"0x" & $big_pips_pen)

                    GUICtrlSetData($slider_prefs_trans$WinTrans)
                    GUICtrlSetTip($slider_prefs_trans" currently " & $WinTrans & $tip_trans)

                    GUICtrlSetState($check_draw_numerals$draw_numerals)
                    GUICtrlSetState($check_draw_pips$draw_pips)

                    GUICtrlSetData($slider_pips_rim$pips_outer_rim)
                    GUICtrlSetTip($slider_pips_rim$tip_pips_rim  & $pips_outer_rim & "] ")
                    GUICtrlSetData($slider_minute_pips_size$minute_pips_size)
                    GUICtrlSetTip($slider_minute_pips_size$tip_minute_pips & $minute_pips_size & "] ")
                    GUICtrlSetData($slider_hour_pips_size$hour_pips_size)
                    GUICtrlSetTip($slider_hour_pips_size$tip_hour_pips & $hour_pips_size & "] ")

                    if $draw_pips = $GUI_CHECKED then
                        for $i = $label_pips_rim to $slider_hour_pips_size
                            GUICtrlSetState($i$GUI_SHOW)
                        next
                    else
                        for $i = $label_pips_rim to $slider_hour_pips_size
                            GUICtrlSetState($i$GUI_HIDE)
                        next
                    endif

                    GUICtrlSetData($slider_size_second_hand$second_hand_size)
                    GUICtrlSetTip($slider_size_second_hand$tip_second_hand & $second_hand_size & "] ")
                    GUICtrlSetData($slider_size_minute_hand$minute_hand_size)
                    GUICtrlSetTip($slider_size_minute_hand$tip_minute_hand & $minute_hand_size & "] ")
                    GUICtrlSetData($slider_size_hour_hand$hour_hand_size)
                    GUICtrlSetTip($slider_size_hour_hand$tip_hour_hand & $hour_hand_size & "] ")
                    UpdateHandSizes()
                    ResetChanges(1, 20)
                    $lc = 50

                ControlFocus($prefs_dialog""$combo_scheme_presets)

                case $butt_del_scheme

                    if ce_IsPressed(10) then
                        RecoverBackup($ini_path_schemes)
                        continueloop
                    endif

                    StoreBackup($ini_path_schemes)
                    IniDelete($ini_path_schemes, GUICtrlRead($combo_scheme_presets))
                    GetSchemeNames()

                    $previous_scheme = GetLastComboSelection($previous_combo_schemes$scheme_names)
                    $current_scheme = $previous_scheme

                    SwitchScheme($current_scheme)
                    UpdateSchemesCombo()

                    ControlCommand($prefs_dialog""$combo_scheme_presets"SelectString"$current_scheme)

                case $butt_revert_scheme
                    SwitchScheme(GUICtrlRead($combo_scheme_presets))
                    ControlCommand($prefs_dialog""$combo_scheme_presets"SelectString", GUICtrlRead($combo_scheme_presets))

                case $butt_save_scheme

                    RemoveBackup($ini_path_schemes)
                    $current_scheme = StringReplace(GUICtrlRead($combo_scheme_presets), "[""{")
                    $current_scheme = StringReplace($current_scheme"]""}")

                    SaveSchemePref($current_scheme"face_colour"$face_color)
                    SaveSchemePref($current_scheme"numerals_color"$numerals_color)
                    SaveSchemePref($current_scheme"second_hand_color"$second_hand_color)
                    SaveSchemePref($current_scheme"hour_pen"$hour_pen)
                    SaveSchemePref($current_scheme"minute_pen"$minute_pen)
                    SaveSchemePref($current_scheme"pips_pen"$pips_pen)
                    SaveSchemePref($current_scheme"big_pips_pen"$big_pips_pen)
                    SaveSchemePref($current_scheme"transparency"$WinTrans)

                    SaveSchemePref($current_scheme"draw_numerals"$draw_numerals, 1) ; checkbox flag set to true
                    SaveSchemePref($current_scheme"draw_pips"$draw_pips, 1)
                    SaveSchemePref($current_scheme"pips_outer_rim"$pips_outer_rim)
                    SaveSchemePref($current_scheme"minute_pips_size"$minute_pips_size)
                    SaveSchemePref($current_scheme"hour_pips_size"$hour_pips_size)

                    SaveSchemePref($current_scheme"second_hand_size"$second_hand_size)
                    SaveSchemePref($current_scheme"minute_hand_size"$minute_hand_size)
                    SaveSchemePref($current_scheme"hour_hand_size"$hour_hand_size)

                    SwitchScheme($current_scheme)
                    UpdateSchemesCombo()

                    ControlCommand($prefs_dialog""$combo_scheme_presets"SelectString"$current_scheme)

                case $exsc_1$exsc_3$exsc_5$exsc_7
                    ExportScheme()

                case $exsc_2$exsc_4$exsc_6$exsc_8
                    ExportAllSchemes()

                case $exsc_9 to $exsc_12
                    ExportSchemeIntoCollection()

                case $check_disable_cpc
                    $disable_cpc = GUICtrlRead($check_disable_cpc)
                    IniWriteCheckboxValue($ini_path_schemes$current_scheme"disable_cpc"$disable_cpc)

                case $label_color_clock_face
                    $face_color = IniRead($ini_path_schemes$current_scheme"face_colour""FFFFFF")
                    GUICtrlSetBkColor($butt_color_clock_face"0x" & $face_color)
                    AllThatGoodStuff(1)
                    $changes[2] = 0

                case $butt_color_clock_face
                    $cpc = GetPickedColor($face_color$current_scheme)
                    if $cpc <> "" then
                        $changes[2] = 0
                        if $cpc <> IniRead($ini_path_schemes$current_scheme"face_colour""FFFFFF") then $changes[2] = 1
                        $face_color = $cpc
                        GUICtrlSetBkColor($butt_color_clock_face"0x" & $face_color)
                        AllThatGoodStuff(1)
                    endif

                case $label_numerals_color
                    $numerals_color = IniRead($ini_path_schemes$current_scheme"numerals_color""FF0000")
                    GUICtrlSetBkColor($butt_numerals_color"0x" & $numerals_color)
                    AllThatGoodStuff(1)
                    $changes[3] = 0

                case $butt_numerals_color
                    $cpc = GetPickedColor($numerals_color$current_scheme)
                    if $cpc <> "" then
                        $changes[3] = 0
                        if $cpc <> IniRead($ini_path_schemes$current_scheme"numerals_color""FF0000") then $changes[3] = 1
                        $numerals_color = $cpc
                        GUICtrlSetBkColor($butt_numerals_color"0x" & $numerals_color)
                        AllThatGoodStuff(1)
                    endif

                case $label_second_hand_color
                    $second_hand_color = IniRead($ini_path_schemes$current_scheme"second_hand_color""FF0000")
                    GUICtrlSetBkColor($butt_second_hand_color"0x" & $second_hand_color)
                    AllThatGoodStuff(1)
                    $changes[4] = 0

                case $butt_second_hand_color
                    $cpc = GetPickedColor($second_hand_color$current_scheme)
                    if $cpc <> "" then
                        $changes[4] = 0
                        if $cpc <> IniRead($ini_path_schemes$current_scheme"second_hand_color""FF0000") then $changes[4] = 1
                        $second_hand_color = $cpc
                        GUICtrlSetBkColor($butt_second_hand_color"0x" & $second_hand_color)
                        AllThatGoodStuff(1)
                    endif

                case $label_hour_pen
                    $hour_pen = IniRead($ini_path_schemes$current_scheme"hour_pen""000000")
                    GUICtrlSetBkColor($butt_hour_pen"0x" & $hour_pen)
                    AllThatGoodStuff(1)
                    $changes[5] = 0

                case $butt_hour_pen
                    $cpc = GetPickedColor($hour_pen$current_scheme)
                    if $cpc <> "" then
                        $changes[5] = 0
                        if $cpc <> IniRead($ini_path_schemes$current_scheme"hour_pen""000000") then $changes[5] = 1
                        $hour_pen = $cpc
                        GUICtrlSetBkColor($butt_hour_pen"0x" & $hour_pen)
                        AllThatGoodStuff(1)
                    endif

                case $label_minute_pen
                    $minute_pen = IniRead($ini_path_schemes$current_scheme"minute_pen""000000")
                    GUICtrlSetBkColor($butt_minute_pen"0x" & $minute_pen)
                    AllThatGoodStuff(1)
                    $changes[6] = 0

                case $butt_minute_pen
                    $cpc = GetPickedColor($minute_pen$current_scheme)
                    if $cpc <> "" then
                        $changes[6] = 0
                        if $cpc <> IniRead($ini_path_schemes$current_scheme"minute_pen""000000") then $changes[6] = 1
                        $minute_pen = $cpc
                        GUICtrlSetBkColor($butt_minute_pen"0x" & $minute_pen)
                        AllThatGoodStuff(1)
                    endif

                case $label_pips_pen
                    $pips_pen = IniRead($ini_path_schemes$current_scheme"pips_pen""000000")
                    GUICtrlSetBkColor($butt_pips_pen"0x" & $pips_pen)
                    AllThatGoodStuff(1)
                    $changes[7] = 0

                case $butt_pips_pen
                    $cpc = GetPickedColor($pips_pen$current_scheme)
                    if $cpc <> "" then
                        $changes[7] = 0
                        if $cpc <> IniRead($ini_path_schemes$current_scheme"pips_pen""000000") then $changes[7] = 1
                        $pips_pen = $cpc
                        GUICtrlSetBkColor($butt_pips_pen"0x" & $pips_pen)
                        AllThatGoodStuff(1)
                    endif

                case $label_big_pips_pen
                    $big_pips_pen = IniRead($ini_path_schemes$current_scheme"big_pips_pen""000000")
                    GUICtrlSetBkColor($butt_big_pips_pen"0x" & $big_pips_pen)
                    AllThatGoodStuff(1)
                    $changes[8] = 0

                case $butt_big_pips_pen
                    $cpc = GetPickedColor($big_pips_pen$current_scheme)
                    if $cpc <> "" then
                        $changes[8] = 0
                        if $cpc <> IniRead($ini_path_schemes$current_scheme"big_pips_pen""000000") then $changes[8] = 1
                        $big_pips_pen = $cpc
                        GUICtrlSetBkColor($butt_big_pips_pen"0x" & $big_pips_pen)
                        AllThatGoodStuff(1)
                    endif

                case $label_prefs_trans
                    $WinTrans = IniRead($ini_path_schemes$current_scheme"transparency", 0)
                    GUICtrlSetData($slider_prefs_trans$WinTrans)
                    UpdateTrans()
                    $changes[9] = 0
                    continuecase
                case $slider_prefs_trans
                    GUICtrlSetTip($slider_prefs_trans" currently " & $WinTrans & "%" & _
                        @CRLF & " use can use the arrow keys and PgUp/PgDn to adjust this ")

            ; Pips and Numerals..

                case $check_draw_numerals
                    $draw_numerals = GUICtrlRead($check_draw_numerals)
                    $changes[10] = 0
                    if $draw_numerals <> IniReadCheckboxValue($ini_path_schemes$current_scheme"draw_numerals", 1) then $changes[10] = 1
                    UpdateColors()
                    AllThatGoodStuff(1)

                case $check_draw_pips
                    $draw_pips = GUICtrlRead($check_draw_pips)

                    if $draw_pips = $GUI_CHECKED then
                        for $i = $label_pips_rim to $slider_hour_pips_size
                            GUICtrlSetState($i$GUI_SHOW)
                        next
                    else
                        for $i = $label_pips_rim to $slider_hour_pips_size
                            GUICtrlSetState($i$GUI_HIDE)
                        next
                    endif

                    $changes[11] = 0
                    if $draw_pips <> IniReadCheckboxValue($ini_path_schemes$current_scheme"draw_pips", 1) then $changes[11] = 1
                    UpdateColors()
                    AllThatGoodStuff(1)

                case $label_pips_rim
                    if ce_IsPressed(10) then ; master default setting
                        GUICtrlSetData($slider_pips_rim, 2)
                    else
                        GUICtrlSetData($slider_pips_rim, IniRead($ini_path_schemes$current_scheme"pips_outer_rim", 2))
                    endif
                    continuecase
                case $slider_pips_rim
                    $pips_outer_rim = GUICtrlRead($slider_pips_rim)
                    GUICtrlSetTip($slider_pips_rim$tip_pips_rim  & $pips_outer_rim & "] ")
                    AllThatGoodStuff(1)
                    $changes[12] = 0
                    if $pips_outer_rim <> IniRead($ini_path_schemes$current_scheme"pips_outer_rim", 2) then $changes[12] = 1

                case $label_minute_pips_size
                    if ce_IsPressed(10) then
                        GUICtrlSetData($slider_minute_pips_size, 6)
                    else
                        GUICtrlSetData($slider_minute_pips_size, IniRead($ini_path_schemes$current_scheme"minute_pips_size", 6))
                    endif
                    continuecase
                case $slider_minute_pips_size
                    $minute_pips_size = GUICtrlRead($slider_minute_pips_size)
                    GUICtrlSetTip($slider_minute_pips_size$tip_minute_pips & $minute_pips_size & "] ")
                    AllThatGoodStuff(1)
                    $changes[13] = 0
                    if $minute_pips_size <> IniRead($ini_path_schemes$current_scheme"minute_pips_size", 6) then $changes[13] = 1

                case $label_hour_pips_size
                    if ce_IsPressed(10) then
                        GUICtrlSetData($slider_hour_pips_size, 10)
                    else
                        GUICtrlSetData($slider_hour_pips_size, IniRead($ini_path_schemes$current_scheme"hour_pips_size", 11))
                    endif
                    continuecase
                case $slider_hour_pips_size
                    $hour_pips_size = GUICtrlRead($slider_hour_pips_size)
                        GUICtrlSetTip($slider_hour_pips_size$tip_hour_pips & $hour_pips_size & "] ")
                    AllThatGoodStuff(1)
                    $changes[14] = 0
                    if $hour_pips_size <> IniRead($ini_path_schemes$current_scheme"hour_pips_size", 10) then $changes[14] = 1

            ; Hands

                case $label_size_second_hand
                    if ce_IsPressed(10) then
                        GUICtrlSetData($slider_size_second_hand, 75)
                    else
                        GUICtrlSetData($slider_size_second_hand, IniRead($ini_path_schemes$current_scheme"second_hand_size", 75))
                    endif
                    continuecase
                case $slider_size_second_hand
                    $second_hand_size = GUICtrlRead($slider_size_second_hand)
                    $changes[16] = 0
                    if $second_hand_size <> IniRead($ini_path_schemes$current_scheme"second_hand_size", 75) then $changes[16] = 1
                    GUICtrlSetTip($slider_size_second_hand$tip_second_hand & $second_hand_size & "] ")
                    UpdateHandSizes()
                    AllThatGoodStuff(1)

                case $label_size_minute_hand
                    if ce_IsPressed(10) then
                        GUICtrlSetData($slider_size_minute_hand, 67)
                    else
                        GUICtrlSetData($slider_size_minute_hand, IniRead($ini_path_schemes$current_scheme"minute_hand_size", 67))
                    endif
                    continuecase
                case $slider_size_minute_hand
                    $minute_hand_size = GUICtrlRead($slider_size_minute_hand)
                    $changes[17] = 0
                    if $minute_hand_size <> IniRead($ini_path_schemes$current_scheme"minute_hand_size", 67) then $changes[17] = 1
                    GUICtrlSetTip($slider_size_minute_hand$tip_minute_hand & $minute_hand_size & "] ")
                    UpdateHandSizes()
                    AllThatGoodStuff(1)

                case $label_size_hour_hand
                    if ce_IsPressed(10) then
                        GUICtrlSetData($slider_size_hour_hand, 50)
                    else
                        GUICtrlSetData($slider_size_hour_hand, IniRead($ini_path_schemes$current_scheme"hour_hand_size", 50))
                    endif
                    continuecase
                case $slider_size_hour_hand

                    $hour_hand_size = GUICtrlRead($slider_size_hour_hand)
                    $changes[18] = 0
                    if $hour_hand_size <> IniRead($ini_path_schemes$current_scheme"hour_hand_size", 50) then $changes[18] = 1

                    GUICtrlSetTip($slider_size_hour_hand$tip_hour_hand & $hour_hand_size & "] ")
                    UpdateHandSizes()
                    AllThatGoodStuff(1)

            ; Alerts..

                case $combo_alert_presets

                    $current_alert = GUICtrlRead($combo_alert_presets)
                    RememberComboSelection($previous_combo_alerts$current_alert)

                    if IniRead($ini_path_alerts$current_alert"wav""") <> "" then
                        $alert_is_wav = true
                        ControlClick($prefs_dialog""$radio_alert_switch_wavs)
                        GUICtrlSetState($combo_alert_presets$GUI_FOCUS)
                    else
                        $alert_is_wav = false
                        ControlClick($prefs_dialog""$radio_alert_switch_beep)
                        GUICtrlSetState($combo_alert_presets$GUI_FOCUS)
                    endif
                    ResetChanges(41, 49)
                    $lc = 50

                    ControlFocus($prefs_dialog""$combo_alert_presets)

                case $butt_del_alert

                    if ce_IsPressed(10) then
                        RecoverBackup($ini_path_alerts)
                        continueloop
                    endif

                    $del_alert = GUICtrlRead($combo_alert_presets)
                    StoreBackup($ini_path_alerts)
                    IniDelete($ini_path_alerts$del_alert)

                    GetAlertNames()
                    $previous_alert = GetLastComboSelection($previous_combo_alerts$alert_names)
                    $current_alert = $previous_alert

                    UpdateAlertCombos()
                    ControlCommand($prefs_dialog""$combo_alert_presets"SelectString"$current_alert)

                    if $del_alert = $my_alarms[$index][10] then
                        $changes[23] = 1
                        IniWrite($ini_path_alarms$alarm_names[$index], "alert""")
                        GUICtrlSetData($combo_alert"<missing>"; you can't actually choose this, though
                        ControlCommand($prefs_dialog""$combo_alert"SelectString""<missing>")
                    endif

                case $butt_revert_alert
                    ControlCommand($prefs_dialog""$combo_alert_presets"SelectString", GUICtrlRead($combo_alert_presets))

                case $butt_save_alert

                    RemoveBackup($ini_path_alerts)
                    $preset_name = StringReplace(GUICtrlRead($combo_alert_presets), "[""{")
                    $preset_name = StringReplace($preset_name"]""}")

                    if $alert_is_wav then
                        local $save_alert[3] = [    $preset_name, _
                                                    GUICtrlRead($input_alert_wavname), _
                                                    GUICtrlRead($input_alert_pause)    ]
                        SaveAlert($save_alert"wav")
                    else
                        if GUICtrlRead($input_alert_step) < 1 then GUICtrlSetData($input_alert_step, 1)
                        local $save_alert[9] = [    $preset_name, _
                                                    GUICtrlRead($input_alert_repeat), _
                                                    GUICtrlRead($input_alert_beep_len), _
                                                    GUICtrlRead($input_alert_sleep), _
                                                    GUICtrlRead($input_alert_beeps), _
                                                    GUICtrlRead($input_alert_bottom), _
                                                    GUICtrlRead($input_alert_step), _
                                                    GUICtrlRead($input_alert_scaler), _
                                                    GUICtrlRead($check_alert_and_down)    ]

                        $remember_wav = GUICtrlRead($input_alert_wavname; in case they fuxdup, we'll remember this
                        SaveAlert($save_alert)
                    endif

                    UpdateAlertCombos()
                    ControlCommand($prefs_dialog""$combo_alert_presets"SelectString"$save_alert[0])


                case $exst_1$exst_3$exst_5$exst_7
                    ExportAlert()

                case $exst_2$exst_4$exst_6$exst_8
                    ExportAllAlerts()

                case $exst_9 to $exst_12
                    ExportAlertIntoCollection()


                case $radio_alert_switch_beep
                    $alert_is_wav = false

                    ; The AutoIt documentation doesn't do enough to explain that the creation of a GUI Control
                    ; returns the ID of the control, that is, A NUMBER. If folk realised, there wouldn't be
                    ; crazy forum questions along the lines of "how to I disable groups of controls?"
                    ; Put them into arrays? Guys! Numbers work like this..

                    for $i = $group_wav_file_params to $input_alert_pause ; just numbers, see.
                        GUICtrlSetState($i$GUI_HIDE)
                    next

                    ; TADA! Not exactly rocket science. I use this all over.
                    ; But it's so obscure, it could almost be called a "trick" :/
                    ; Arrays of controls have their place, sure, but not here.
                    ; here it goes again..

                    for $i = $group_alert_params to $icon_beepalert_test
                        GUICtrlSetState($i$GUI_SHOW)
                    next
                    ; you can also use "step 2" to affect only alternate controls,
                    ; leaving labels, but disabling their sliders, or whatever. handy.

                    $current_repeat = IniRead($ini_path_alerts$current_alert"repeat", 4)
                    GUICtrlSetData($input_alert_repeat$current_repeat)
                    $current_beep_len = IniRead($ini_path_alerts$current_alert"beep_len", 500)
                    GUICtrlSetData($input_alert_beep_len$current_beep_len)
                    $current_sleep = IniRead($ini_path_alerts$current_alert"sleep", 500)
                    GUICtrlSetData($input_alert_sleep$current_sleep)
                    $current_beeps = IniRead($ini_path_alerts$current_alert"beeps", 1)
                    GUICtrlSetData($input_alert_beeps$current_beeps)
                    $current_bottom = IniRead($ini_path_alerts$current_alert"bottom", 1)
                    GUICtrlSetData($input_alert_bottom$current_bottom)
                    $current_step = IniRead($ini_path_alerts$current_alert"step", 1)
                    if $current_step < 1 then $current_step = 1
                    GUICtrlSetData($input_alert_step$current_step)
                    $current_scaler = IniRead($ini_path_alerts$current_alert"scaler", 3000)
                    GUICtrlSetData($input_alert_scaler$current_scaler)
                    $current_and_down = IniReadCheckBoxValue($ini_path_alerts$current_alert"and_down", 4)
                    GUICtrlSetState($check_alert_and_down$current_and_down)


                case $radio_alert_switch_wavs

                    $alert_is_wav = true
                    for $i = $group_alert_params to $icon_beepalert_test
                        GUICtrlSetState($i$GUI_HIDE)
                    next
                    for $i = $group_wav_file_params to  $input_alert_pause
                        GUICtrlSetState($i$GUI_SHOW)
                    next
                    GUICtrlSetData($input_alert_wavname, IniRead($ini_path_alerts$current_alert"wav"""))
                    GUICtrlSetData($input_alert_pause, IniRead($ini_path_alerts$current_alert"pause", 250))

                ; click labels to revert parameters..
                case $label_alert_repeat
                    GUICtrlSetData($input_alert_repeat$current_repeat)
                    $changes[41] = 0
                case $input_alert_repeat
                    if GUICtrlRead($input_alert_repeat) <> $current_repeat then $changes[41] = 1

                case $label_alert_beep_len
                    GUICtrlSetData($input_alert_beep_len$current_beep_len)
                    $changes[42] = 0
                case $input_alert_beep_len
                    if GUICtrlRead($input_alert_beep_len) <> $current_beep_len then $changes[42] = 1

                case $label_alert_sleep
                    GUICtrlSetData($input_alert_sleep$current_sleep)
                    $changes[43] = 0
                case $input_alert_sleep
                    if GUICtrlRead($input_alert_sleep) <> $current_sleep then $changes[43] = 1

                case $label_alert_beeps
                    GUICtrlSetData($input_alert_beeps$current_beeps)
                    $changes[44] = 0
                case $input_alert_beeps
                    if GUICtrlRead($input_alert_beeps) <> $current_beeps then $changes[44] = 1

                case $label_alert_bottom
                    GUICtrlSetData($input_alert_bottom$current_bottom)
                    $changes[45] = 0
                case $input_alert_bottom
                    if GUICtrlRead($input_alert_bottom) <> $current_bottom then $changes[45] = 1

                case $label_alert_step
                    GUICtrlSetData($input_alert_step$current_step)
                    $changes[46] = 0
                case $input_alert_step
                    if GUICtrlRead($input_alert_step) <> $current_step then $changes[46] = 1

                case $label_alert_scaler
                    GUICtrlSetData($input_alert_scaler$current_scaler)
                    $changes[47] = 0
                case $input_alert_scaler
                    if GUICtrlRead($input_alert_scaler) <> $current_scaler then $changes[47] = 1

                case $check_alert_and_down
                    if GUICtrlRead($check_alert_and_down) <> $current_and_down then
                        $changes[48] = 1
                    else
                        $changes[48] = 0
                    endif


                case $icon_beepalert_test
                    $play_idx = 5
                    SwitchIconsPLAYING()

                    if GUICtrlRead($input_alert_step) < 1 then GUICtrlSetData($input_alert_step, 1)

                    local $save_alert[9] = [    "corz-clock-temp-alert", _
                                                GUICtrlRead($input_alert_repeat), _
                                                GUICtrlRead($input_alert_beep_len), _
                                                GUICtrlRead($input_alert_sleep), _
                                                GUICtrlRead($input_alert_beeps), _
                                                GUICtrlRead($input_alert_bottom), _
                                                GUICtrlRead($input_alert_step), _
                                                GUICtrlRead($input_alert_scaler), _
                                                GUICtrlRead($check_alert_and_down)    ]
                    SaveAlert($save_alert)
                    IGuessItsAlarmTime("corz-clock-temp-alert", true, "-")
                    IniDelete($ini_path_alerts"corz-clock-temp-alert")

                case $label_alert_wavname
                    if IniRead($ini_path_alerts$current_alert"wav""") <> "" then
                        GUICtrlSetData($input_alert_wavname, IniRead($ini_path_alerts$current_alert"wav"""))
                    else
                        GUICtrlSetData($input_alert_wavname$remember_wav)
                    endif

                case $label_alert_pause
                    GUICtrlSetData($input_alert_pause, IniRead($ini_path_alerts$current_alert"pause", 250))

                case $icon_alert_wav_in
                    PrefsFileDialogOpen()
                    $open_at = IniRead($ini_path$my_shortname"wavs_folder"$data_parent & "\alerts")
                    $tmp_open =  FileOpenDialog("Pick a WAV file to use for this alert..", _
                        $open_at"WAV Files (*.wav)", 1, "alarm.wav")
                    if $tmp_open <> "" then GUICtrlSetData($input_alert_wavname$tmp_open)
                    IniWrite($ini_path$my_shortname"wavs_folder", GetParent($new_alert))
                    PrefsFileDialogClose()

                case $icon_alert_wav_play
                    switch $play_idx
                        case 4
                            SoundOff()
                        case 1 to 9
                            continueloop
                        case else
                            $play_idx = 4
                            SwitchIconsPLAYING()
                            PlaySound(GUICtrlRead($input_alert_wavname))
                    endswitch

            ; Master Speech Setings..

                case $label_master_volume
                    GUICtrlSetData($slider_master_volume, 50)
                    continuecase
                case $slider_master_volume ; update instantly
                    $speech_volume = GUICtrlRead($slider_master_volume)
                    GUICtrlSetTip($slider_master_volume$vtip & @CRLF & " [current volume: " & GUICtrlRead($slider_master_volume) & "] ")
                    IniWrite($ini_path$my_shortname"speech_volume"$speech_volume)

                case $label_master_rate
                    GUICtrlSetData($slider_master_rate, 0)
                    continuecase
                case $slider_master_rate
                    $speech_rate = GUICtrlRead($slider_master_rate)
                    GUICtrlSetTip($slider_master_rate$rtip & @CRLF & " [current rate: " & GUICtrlRead($slider_master_rate) & "] ")
                    IniWrite($ini_path$my_shortname"speech_rate"$speech_rate)

                case $label_master_voice
                    GUICtrlSetData($input_master_voice"Sam")
                    continuecase
                case $input_master_voice
                    $speech_voice = GUICtrlRead($input_master_voice)
                    IniWrite($ini_path$my_shortname"speech_voice"$speech_voice)

            ; All done!
                case $butt_done
                    if DontDiscardChanges() then continuecase

                    AddChimeToList()
                    $chime_minute = GUICtrlRead($combo_chime_minute)
                    IniWrite($ini_path$my_shortname"chime_minute",  $chime_minute)
                    $chime_done = 0
                    $size_array = WinGetPos($prefs_dialog)
                    if IsArray($size_array) then
                        IniWrite($ini_path$my_shortname"prefs_x"$size_array[0])
                        IniWrite($ini_path$my_shortname"prefs_y"$size_array[1])
                    endif

                DllCall("user32.dll""int""AnimateWindow""hwnd"$prefs_dialog"int", 200, "long", 0x00050008)
                GUIDelete($prefs_dialog)
                exitloop

            case else ; for the above continuecase, saves messing around
        endswitch


        ; better here, for live effect..
        if $WinTrans <> GUICtrlRead($slider_prefs_trans) then
            $WinTrans = GUICtrlRead($slider_prefs_trans)
            UpdateTrans()
        endif
        $changes[9] = 0
        if $WinTrans <> IniRead($ini_path_schemes$current_scheme"transparency", 0) then $changes[9] = 1


        ; irregular gui events (every x cycles, to avoid flicker)
        ; update the title bar, help text, etc.
        $lc += 1
        if $lc >= 30 then

            $tab_index = ControlCommand($prefs_dialog""$tab_prefs"CurrentTab""")

            ; we will do these updates, even if the user is mousing outside the GUI..
            switch $tab_index
                case 1
                    $this_hour = HourToHumanTime(@HOUR)
                    WinSetTitle($prefs_dialog , """ Alarms And Chimes..          [" & $this_hour[0] & _
                                            "." & @MIN & " " & StringLower($this_hour[1]) & "]" )
                case 2
                    WinSetTitle($prefs_dialog , """ Schemes..          [current scheme: " & $current_scheme & "]")
                case 3
                    WinSetTitle($prefs_dialog , """ Audio Preferences..")
            endswitch

            ; but these only occur when the mouse is inside the GUI..
            local $mouse_info = GUIGetCursorInfo($prefs_dialog)
            if IsArray($mouse_info) and $mouse_info[4] <> 0 then

                switch $tab_index
                    case 1
                        ; switch the text of the "save" buttons, to "add", as required..
                        if not InArray($alarm_names, GUICtrlRead($combo_alarm_presets)) then
                            GUICtrlSetData($butt_save_alarm"&add")
                            GUICtrlSetTip($butt_save_alarm" save this alarm preset with the current settings " & @CRLF & _
                                                            " new alarms will be disabled until you enable them (below) ")
                            for $i = $label_alarm_enabled to $check_alarm_enabled
                                GUICtrlSetState($i$GUI_UNCHECKED)
                                GUICtrlSetState($i$GUI_HIDE)
                            next
                        else
                            GUICtrlSetData($butt_save_alarm"&save")
                            GUICtrlSetTip($butt_save_alarm" save this alarm preset with the current ghsettings " )
                            for $i = $label_alarm_enabled to $check_alarm_enabled
                                GUICtrlSetState($i$GUI_SHOW)
                            next
                        endif
                    case 2
                        if not InArray($scheme_names, GUICtrlRead($combo_scheme_presets)) then
                            GUICtrlSetData($butt_save_scheme"&add")
                        else
                            GUICtrlSetData($butt_save_scheme"&save")
                        endif
                    case 3
                        if not InArray($alert_names , GUICtrlRead($combo_alert_presets)) then
                            GUICtrlSetData($butt_save_alert"&add")
                        else
                            GUICtrlSetData($butt_save_alert"&save")
                        endif

                        ; alerts help system..
                        switch $mouse_info[4]

                            ; quickly! enable word-wrap! ...
                            case $group_alert_presets to $combo_alert_presets
                                GUICtrlSetData($label_help_box"Select and create alerts from here. You can drop WAVs and preset (ini) files onto this combo box to automatically import them.")

                            case $butt_del_alert
                                GUICtrlSetData($label_help_box"Delete the currently selected alert from the list.")

                            case $butt_revert_alert
                                GUICtrlSetData($label_help_box"Revert this alert back to its last saved settings")

                            case $butt_save_alert
                                GUICtrlSetData($label_help_box"Save or add alerts. Note: Alerts can be either Beep or Wav, NOT BOTH! Saving a beep alert as a Wav destroys the beep settings, and vica-versa")


                            case $radio_alert_switch_beep
                                GUICtrlSetData($label_help_box"A beep alert is basically two loops of beeps that you can play with. ")

                            case $radio_alert_switch_wavs
                                GUICtrlSetData($label_help_box"Rather than using the built-in beep synth, you can use a WAV file for your alert - remember to have the sound on, and the volume UP!")


                            case $group_alert_params
                                GUICtrlSetData($label_help_box"The first loop has the potential to increase pitch with every beep, and the second (optional) loop has the potential to decrease pitch with every beep.")


                            case $label_alert_repeat
                                GUICtrlSetData($label_help_box"This sets the total number of overall (outer) loops. Whatever wonderful noise you create, it will be repeated *this* many times..")

                            case $input_alert_repeat
                                GUICtrlSetData($label_help_box"Yes, sometimes the help is split over two controls. Watch for that!")

                            case $label_alert_beep_len to $input_alert_beep_len
                                GUICtrlSetData($label_help_box"This sets the length of the actual beeps, in milliseconds. The default is 500. For special effects, sirens, etc. use much shorter lengths.")

                            case $label_alert_sleep to $input_alert_sleep
                                GUICtrlSetData($label_help_box"This defines the gap between individual beeps, again, in milliseconds. You can set this to zero if you want. The default is 500.")

                            case $label_alert_beeps
                                GUICtrlSetData($label_help_box"The number of beeps in the loop. The default is 1..")

                            case $input_alert_beeps
                                GUICtrlSetData($label_help_box"Set to larger numbers for special effects (basically, lots of short beeps, as opposed to one long beep)")

                            case $label_alert_bottom to $input_alert_bottom
                                GUICtrlSetData($label_help_box"Where the pitch slide begins. Generally it's set to 1, but you might want to begin your scale further up the audio spectrum")

                            case $label_alert_step
                                GUICtrlSetData($label_help_box"The value of the steps in pitch. Set to any number equal or smaller than the value of 'beeps'. The default is 1 (play every beep). Step cannot be zero..")

                            case $input_alert_step
                                GUICtrlSetData($label_help_box"e.g., if you have 10 beeps, with a step value of 2, you will only hear five beeps; 1,3,5,7,9. It's generally best to keep the step value quite low.")

                            case $label_alert_scaler
                                GUICtrlSetData($label_help_box"The multiplier for the beep pitch. The value of the pitch is beeps*scaler. If 'no. of beeps' is 1, the pitch won't change, and this becomes a simple Hz value..")

                            case  $input_alert_scaler
                                GUICtrlSetData($label_help_box"If 'no. of beeps' is NOT 1, the pitch will start at  1*scaler and finish at beeps*scaler, increasing in pitch all the way. ")


                            case $check_alert_and_down
                                GUICtrlSetData($label_help_box"This instructs clock to perform a second inner loop, this time decreasing the pitch, enabling the creation of 'siren' like effects, lots of fun. ")


                            case $icon_beepalert_test
                                GUICtrlSetData($label_help_box"Test the current Beep Alert. Note: Like native WAVs and spoken messages, Beep Alerts can be stopped mid-stream with the Pause (Break) key.")


                            case $group_wav_file_params
                                GUICtrlSetData($label_help_box"Native WAV files and Spoken messages can be stopped while playing. Some imported WAV files cannot; you get a 'NO ENTRY' icon, and must wait for them.")

                            case $label_alert_wavname to $input_alert_wavname
                                GUICtrlSetData($label_help_box"To use a WAV file for this alert, enter the full path to a WAV file (or use the browse button)")

                            case $icon_alert_wav_in
                                GUICtrlSetData($label_help_box"Click here to browse for a WAV file to use for this alert.")

                            case $icon_alert_wav_play
                                GUICtrlSetData($label_help_box"Test the current WAV file." & @CRLF & @CRLF & "Note: If you get the 'NO ENTRY' icon, it means the sound cannot be stopped mid-stream.")

                            case $label_alert_pause to $input_alert_pause
                                GUICtrlSetData($label_help_box"This is the delay between the alarm sound and any spoken messages that may follow. Usually 250ms but some WAVs like more of a pause after them.")


                            case $group_master_speech_params
                                GUICtrlSetData($label_help_box"These settings affect all spoken chimes, and alarms without speech settings of their own. Master speech settings take effect immediately.")

                            case $label_master_volume to $slider_master_volume
                                GUICtrlSetData($label_help_box"Set the MASTER speech volume from here. This setting affects all spoken chimes, and alarms without speech volume settings.")

                            case $label_master_rate to $slider_master_rate
                                GUICtrlSetData($label_help_box"Set the MASTER speech rate from here. This setting affects all spoken chimes, and alarms without speech rate settings.")

                            case $label_master_voice to $input_master_voice
                                GUICtrlSetData($label_help_box"Which voice to use for speech? This setting affects all spoken chimes, and alarms with no voice selection. Sam, Mike, and Mary are good choices.")

                            case else
                                GUICtrlSetData($label_help_box$help_default_tip)
                        endswitch
                endswitch
            endif

            ; update sound play icons..
            if CheckSound() then
                SwitchIconsPLAYING()
            else
                SwitchIconsREADY()
            endif

            if $mouse_info[4] <> 0 then
                ; enable/disable export context menus..
                if $alarm_names[0] > 1 or ($alarm_names[0] = 1 and $alarm_names[1] <> "unsaved alarm") then
                    if $prefs_open then
                        for $i = $context_ex_alarms to $ex_8
                            GUICtrlSetState($i$GUI_ENABLE)
                        next
                    endif
                elseif $prefs_open then
                    for $i = $context_ex_alarms to $ex_8
                        GUICtrlSetState($i$GUI_DISABLE)
                    next
                endif

                if $scheme_names[0] > 1 or ($scheme_names[0] = 1 and $scheme_names[1] <> "default") then
                    if $prefs_open then
                        for $i = $context_ex_schemes to $exsc_8
                            GUICtrlSetState($i$GUI_ENABLE)
                        next
                    endif
                elseif $prefs_open then
                    for $i = $context_ex_schemes to $exsc_8
                        GUICtrlSetState($i$GUI_DISABLE)
                    next
                endif

                if $alert_names[0] > 1 or ($alert_names[0] = 1 and $alert_names[1] <> "simple") then
                    if $prefs_open then
                        for $i = $context_ex_alerts to $exst_8
                            GUICtrlSetState($i$GUI_ENABLE)
                        next
                    endif
                elseif $prefs_open then
                    for $i = $context_ex_alerts to $exst_8
                        GUICtrlSetState($i$GUI_DISABLE)
                    next
                endif
            endif
            HotKeySet("{PAUSE}""SoundOff")
            HotKeySet("{ESC}""KillPrefs")                ; in case cpc has run, and unset it
            HotKeySet("{F10}""F10SchemeSwitchMsg")    ; simply because setting them earlier
            HotKeySet("{F11}""F11SchemeSwitchMsg")    ; seems to have no effect. hmm.
            $lc = 0
        endif

        sleep(20)
        CheckClockStuff(2)
    wend

    ; this is a highly effective reset!
    RestartClock()
endfunc


; My very simple, yet highly effective changes tracker..
;
; Basically, it's an array of zeros. If anything gets changed, some unique element is set to 1
; If the setting is reverted, or manually goes back to previous setting, the element is set to 0
; Then, when we need to check for changes, we simply run through the array, or any part of it,
; and look for ones. Different areas of the preferences are split into "ranges"..
;
; changes ranges..
;
; schemes: 1-20        ; I just happened to do these first, is all.
; alarms: 21-40
; alerts: 41-49
$changes[0] is reserved (possibly for fuzzy option - ignore single changes, maybe) ;2do
;

func HasChanged($start$end)
    for $i = $start to $end
        if $changes[$i] = 1 then return true
    next
endfunc

func ResetChanges($start$end)
    for $i = $start to $end
        $changes[$i] = 0
    next
endfunc

func DontDiscardChanges()
    $made_changes = false
    for $i in $changes
        if $i = 1 then $made_changes = true
    next
    if $made_changes then
        $made_changes = false
        if LoseUnsavedChanges() then
            return false
        else
            return true
        endif
    endif
endfunc

func LoseUnsavedChanges()
    $dont_bug_me = IniReadCheckBoxValue($ini_path$my_shortname"dont_bug_me_about_unsaved_changes"$GUI_UNCHECKED)
    if $dont_bug_me = $GUI_CHECKED then return true

    $size_array = WinGetPos($prefs_dialog)
    if IsArray($size_array) then
        $vx = $size_array[0] + 110
        $vy = $size_array[1] + 120
    else
        $vx = -1
        $vy = -1
    endif
    PrefsDialogOpen()

    $gui_unsaved_changes = GUICreate(" Unsaved Chages!", 223, 100, $vx$vy, -1, $WS_EX_TOOLWINDOW)
    WinSetOnTop($gui_unsaved_changes"", 1)

    $label_unsaved = GUICtrlCreateLabel("There are unsaved changes " & @CRLF & _
                                        "Do you still wish to close the preferences?", 10, 10, 203)

    $butt_yes = GUICtrlCreateButton("Yes", 0, 40, 42, 22)
    GUICtrlSetTip(-1, " ignore the changes you made, and close the preferences" )

    $butt_no = GUICtrlCreateButton("No", 44, 0, 42, 22)
    GUICtrlSetTip(-1, " go back to the preferences " )

    $check_dont_bug_me = GUICtrlCreateCheckBox("don't bug me again about this", -40, 28)
    GUICtrlSetTip(-1, " if you check this, corz clock will stop reminding you about unsaved changes " )

    GUISetState()
    $lose_changes = false

    while 1
        $msg = GUIGetMsg()
        switch $msg
            case $GUI_EVENT_CLOSE
                exitloop

            case $butt_yes
                $lose_changes = true
                exitloop

            case $butt_no
                exitloop

            case $check_dont_bug_me
                if GUICtrlRead($check_dont_bug_me) = $GUI_CHECKED then
                    IniWrite($ini_path$my_shortname"dont_bug_me_about_unsaved_changes""true")
                else
                    IniWrite($ini_path$my_shortname"dont_bug_me_about_unsaved_changes""false")
                endif
        endswitch
    wend
    GUIDelete($gui_unsaved_changes)
    PrefsDialogClose()
    return $lose_changes
endfunc


func F10SchemeSwitchMsg()
    if WinActive($prefs_dialog) then
        SchemeSwitchMsg()
    else
        HotKeyset("{F10}")
        Send("{F10}")
        HotKeySet("{F10}""F10SchemeSwitchMsg")
    endif
endfunc

func F11SchemeSwitchMsg()
    if WinActive($prefs_dialog) then
        SchemeSwitchMsg()
    else
        HotKeyset("{F11}")
        Send("{F11}")
        HotKeySet("{F11}""F11SchemeSwitchMsg")
    endif
endfunc

func SchemeSwitchMsg()
    if $seen_switch_msg then return
    ToolTip(" You can use the mouse and arrow keys in here."$prefs_x$prefs_y"Not when the preferences are open! ", 2)
    AdlibEnable("SwitchOffTip", 3333)
    $seen_switch_msg = true
endfunc


func KillPrefs()
    if WinActive($prefs_dialog) then
        $show_prefs = false
    else
        HotKeyset("{ESC}")
        Send("{ESC}")
        HotKeySet("{ESC}""KillPrefs")
    endif
endfunc


func GetPickedColor($start_color$load_scheme$autoitval=false)
    PrefsDialogOpen()
    if $disable_cpc = $GUI_CHECKED then
        $foo = cpc__ChooseColor(2, "0x" & $start_color, 2, $gui)
        if not @error then
            $cpc = StringTrimLeft($foo, 2)
        else
            $cpc = $start_color
        endif
    else
        $cpc = ColorPickinChooser($start_color$load_scheme$autoitval"CheckClockStuff")
    endif
    PrefsDialogClose()
    return $cpc
endfunc


func PreviousTab()
    if WinActive(" Alarms And") or WinActive(" Schemes") or WinActive(" Audio") then
        ControlCommand($prefs_dialog""$tab_prefs"TabLeft""")
    else
        HotKeySet("^+{TAB}")
        Send("^+{TAB}")
        HotKeySet( "^+{TAB}" , "NextTab")
    endif
endfunc

func NextTab()
    if WinActive(" Alarms And") or WinActive(" Schemes") or WinActive(" Audio") then
        ControlCommand($prefs_dialog""$tab_prefs"TabRight""")
    else
        HotKeySet("^{TAB}")
        Send("^{TAB}")
        HotKeySet( "^{TAB}" , "NextTab")
    endif
endfunc


; set speech options for this alarm..
;
func DialogSetVoice($index)

    $size_array = WinGetPos($prefs_dialog)
    if IsArray($size_array) then
        $vx = $size_array[0] + 110
        $vy = $size_array[1] + 120
    else
        $vx = -1
        $vy = -1
    endif
    PrefsDialogOpen()

    $gui_speech = GUICreate(" Spoken Message Settings..", 223, 118, $vx$vy, -1, $WS_EX_TOOLWINDOW)
    WinSetOnTop($gui_speech"", 1)

    $label_speech_volume = GUICtrlCreateLabel("Speech Volume: ", 10, 15, 80, 20)
    GUICtrlSetTip(-1, " click here to revert the speech volume back to the last saved setting for this alarm ")

    $vtip = " adjust the volume of the speech , from 0 (silent) to 100 (loud) "
    $slider_speech_volume = GUICtrlCreateSlider(80, -4, 133, 35)
    GUICtrlSetTip(-1, $vtip & @CRLF & " [current volume: " & $current_speech_volume & "] ")
    GUICtrlSetLimit(-1, 100, 0)
    GUICtrlSetData(-1, $current_speech_volume)

    $label_speech_rate = GUICtrlCreateLabel("Speech Rate: ", -80, 40, 75, 20)
    GUICtrlSetTip(-1, " click here to revert the speech rate back to the last saved setting for this alarm ")
    $rtip = " adjust the rate of the speech, from -10 (slow) to 10 (fast) "
    $slider_speech_rate = GUICtrlCreateSlider(80, -4, 133, 35)
    GUICtrlSetTip(-1, $rtip  & @CRLF & " [current rate: " & $current_speech_rate & "] ")
    GUICtrlSetLimit(-1, 10, -10)
    GUICtrlSetData(-1, $current_speech_rate)

    $label_voice = GUICtrlCreateLabel("Voice: ", -79, 43, 32, 20)
    GUICtrlSetTip(-1, " click here to revert the voice back to the last voice selected for this alarm ")
    $input_speech_voice = GUICtrlCreateInput($current_speech_voice, 45, -3, 64, 20)
    GUICtrlSetTip(-1, " choose which voice to use for this spoken message ")

    $butt_ok = GUICtrlCreateButton("Save", 112, 2, 50, 25)
    GUICtrlSetTip(-1, " save the changes you made, and close this dialog " & @CRLF & _
                      " note: these changes won't be permanent until you save the alarm " )
    GUISetState()

    while 1
        $msg = GUIGetMsg()
        switch $msg
            case $GUI_EVENT_CLOSE
                exitloop

            case $label_speech_volume
                if ce_IsPressed(10) then
                    GUICtrlSetData($slider_speech_volume, 50)
                else
                    GUICtrlSetData($slider_speech_volume$my_alarms[$index][11])
                endif
                continuecase
            case $slider_speech_volume
                GUICtrlSetTip($slider_speech_volume$vtip & @CRLF & " [current volume: " & GUICtrlRead($slider_speech_volume) & "] ")

            case $label_voice
                if ce_IsPressed(10) then
                    GUICtrlSetData($input_speech_voice"Sam")
                else
                    GUICtrlSetData($input_speech_voice$my_alarms[$index][12])
                endif

            case $label_speech_rate
                if ce_IsPressed(10) then ; master default setting
                    GUICtrlSetData($slider_speech_rate, 0)
                else
                    GUICtrlSetData($slider_speech_rate$my_alarms[$index][13])
                endif
                continuecase
            case $slider_speech_rate
                GUICtrlSetTip($slider_speech_rate$rtip & @CRLF & " [current rate: " & GUICtrlRead($slider_speech_rate) & "] ")

            case $butt_ok
                $changes[25] = 0
                $changes[26] = 0
                $changes[27] = 0
                if $my_alarms[$index][11] <> GUICtrlRead($slider_speech_volume) then $changes[25] = 1
                if $my_alarms[$index][12] <> GUICtrlRead($input_speech_voice) then $changes[26] = 1
                if $my_alarms[$index][13] <> GUICtrlRead($slider_speech_rate) then $changes[27] = 1
                $current_speech_volume = GUICtrlRead($slider_speech_volume)
                $current_speech_voice = GUICtrlRead($input_speech_voice)
                $current_speech_rate = GUICtrlRead($slider_speech_rate)
                exitloop
        endswitch
    wend
    GUIDelete($gui_speech)
    PrefsDialogClose()
endfunc


func GetChimesList()
    global $chime = IniRead($ini_path$my_shortname"chime", 4000)
    if $chime = "" then $chime = 4000 ; in the gui, out-of-range Hz values are not possible
    ; but we allow folk to hack out-of-range values into the ini, for their own devious purposes.
    global $recent_chimes = IniRead($ini_path$my_shortname"recent_chimes""HO? HO? HO!|and all is well!|")
    ; we don't store Hz values in the "recent chimes", but we still need to load them if they have been previously set..
    GUICtrlSetData($combo_chimes"|")
    if not StringInStr($recent_chimes$chime) then
        ControlCommand($prefs_dialog""$combo_chimes"AddString"$chime)
    endif
    GUICtrlSetData($combo_chimes$recent_chimes)
    GUICtrlSetData($combo_chimes$chime)
endfunc


func AddChimeToList()
    $bad_chimes = false
    $new_chime = GUICtrlRead($combo_chimes)
    if $new_chime = "" or $new_chime = "0" then $bad_chimes = true
    if Number($new_chime) > 19999 then $bad_chimes = true
    if Number($new_chime) > 0 and Number($new_chime) < 37 then $bad_chimes = true
    if $bad_chimes then
        if $chime <> "" then GUICtrlSetData($combo_chimes$chime)
        return
    endif

    $chime = $new_chime
    IniWrite($ini_path$my_shortname"chime"$chime; add to list or not, it's now the default.

    if not StringInStr($recent_chimes$chime) and Number($chime) = 0 and $chime <> "" then
        $recent_chimes &= $chime & "|"
        $recent_chimes_array = StringSplit($recent_chimes"|")
        $recent_chimes = ""
        $keep = 50 ; remember the last (up to) 50 spoken chimes..
        if $recent_chimes_array[0] < 50 then $keep = $recent_chimes_array[0]-1
        for $i = $recent_chimes_array[0]-$keep to $recent_chimes_array[0]-1
            if $recent_chimes_array[$i] <> "" then $recent_chimes &= $recent_chimes_array[$i] & "|"
        next
        IniWrite($ini_path$my_shortname"recent_chimes"$recent_chimes)
        ControlCommand($prefs_dialog""$combo_chimes"AddString"$chime)
    endif
endfunc


func GetMessagesList()
    global $recent_messages = IniRead($ini_path$my_shortname"recent_messages""Now is the time!|WAKE UP!|")
    GUICtrlSetData($combo_message"|")
    GUICtrlSetData($combo_message$recent_messages)
endfunc


func AddMessageToList()

    $message = GUICtrlRead($combo_message)
    if $message = "" or Number($message) then return

    if not StringInStr($recent_messages$message) then
        $recent_messages &= $message & "|"
        $recent_messages_array = StringSplit($recent_messages"|")
        $recent_messages = ""
        $keep = 50
        if $recent_messages_array[0] < 50 then $keep = $recent_messages_array[0]-1
        for $i = $recent_messages_array[0]-$keep to $recent_messages_array[0]-1
            if $recent_messages_array[$i] <> "" then $recent_messages &= $recent_messages_array[$i] & "|"
        next
        IniWrite($ini_path$my_shortname"recent_messages"$recent_messages)
        ControlCommand($prefs_dialog""$combo_message"AddString"$message)
    endif
endfunc


func EditExclusions()

    $size_array = WinGetPos($prefs_dialog)
    if IsArray($size_array) then
        $vx = $size_array[0] - 24
        $vy = $size_array[1] - 24
        if $vx < 0 then $vx = 0
        if $vy < 0 then $vy = 0
    else
        $vx = -1
        $vy = -1
    endif
    PrefsDialogOpen()

    global $gui_exclusions = GUICreate(" Application Exclusion list", 322, 277, $vx$vy, -1, $WS_EX_TOOLWINDOW)
    WinSetOnTop($gui_exclusions"", 1)

    $label_info = GUICtrlCreateLabel("No audio will sound while the following applications are active..", 9, 9, 300)
    $label_info2 = GUICtrlCreateLabel("corz clock will match the application's window title with whatever " & _
                            "you enter here, so please be as specific as possible..", 0, 18, 312, 32)

    GetExclusionsList() ; get it fresh, every time.
    global $list_exlusions = GUICtrlCreateList("", -3, 32, 250, 200);, BitOr($LBS_SORT$WS_BORDER$WS_VSCROLL$LBS_NOTIFY))
    GUICtrlSetData(-1, $exclusion_list)
    GUICtrlSetTip(-1, " you can enter more than just the application's name, if it will help make the match " )

    $butt_delete = GUICtrlCreateButton("&remove", 258, 2, 54, 22)
    GUICtrlSetTip(-1, " permanently remove the selected item from the exclusion list " )

    $butt_edit = GUICtrlCreateButton("&edit", 0, 28, 54, 22)
    GUICtrlSetTip(-1, " edit this item (this removes it from the exclusion list until you add it again)" )

    global $input_appname = GUICtrlCreateInput("", -258, 162, 200, 22)
    GUICtrlSetTip(-1, " enter the name of the application, as appears in its window's TITLE BAR " & @CRLF & _
                        " be as specific as you can, eg. 'Adobe Audition', rather than just plain 'Audition' " & @CRLF & _
                        " which would match, for example, you editing a text file called 'Audition Notes'")
    if $last_exclusion then GUICtrlSetData(-1, $last_exclusion)

    $butt_add = GUICtrlCreateButton("&add", 205, 1, 46, 22)
    GUICtrlSetTip(-1, " add your text to the exclusion list " )

    $butt_done = GUICtrlCreateButton("all &done", 54, 0, 54, 22)
    GUICtrlSetTip(-1, " close this dialog " )


    GUISetState()

    $sel = ""
    global $clicked = 0

    while 1

        $msg = GUIGetMsg()
        ; do this here - we may re-use the functions eleswhere..
        $selected = ControlCommand($gui_exclusions""$list_exlusions"GetCurrentSelection""")


        switch $msg

            case $GUI_EVENT_CLOSE
                exitloop

            case $butt_add
                AddExclusion(GUICtrlRead($input_appname))


            case $list_exlusions

                ; a wee trick to get the list to register a proper (fast) double-click
                $mousepos = MouseGetPos()
                if IsArray($mousepos) then
                    MouseMove($mousepos[0]+3, $mousepos[1])
                    ; the movement must be at or beyond their system double-click rectangle setting (/2)
                    ; in XP, the default is 4, so we'd need to move the mouse at least 2 pixels. 3 is safer,
                    ; but obviously more preceptible to the user.
                endif

                ; where is the double-click event?
                select
                    case $sel = $selected
                        if $clicked then
                            EditThisExclusion($selected)
                            $clicked = 0
                        endif

                    case $sel <> $selected
                        $clicked = 1
                        $sel = $selected
                        continueloop
                endselect
                ; at any rate, the double-click to edit exclusions is an undocumented feature!

            case $butt_edit
                if $selected then EditThisExclusion($selected)

            case $butt_delete
                if $selected then RemoveExclusion($selected)

            case $butt_done
                $last_exclusion = GUICtrlRead($input_appname)
                exitloop
        endswitch

        CheckClockStuff()
    wend

    GUIDelete($gui_exclusions)
    PrefsDialogClose()
endfunc


#cs
                switch $clicked
                    case 0 ; first click
                        if $sel <> $selected then
                            $sel = $selected
                            $clicked = 1
                            continueloop
                        else
                            continuecase
                        endif
                    case else
                        if $sel = $selected then
                            EditThisExclusion($selected)
                            $clicked = 0
                            $sel = ""
                        else
                            $sel = $selected
                            $clicked = 1
                            continueloop
                        endif
                endswitch
#ce


func GetExclusionsList()
    global $exclusion_list = IniRead($ini_path$my_shortname"exclusions""Adobe Audition|AudioMulch|")
endfunc

func UpdateExclusionsList()
    GUICtrlSetData($list_exlusions"")
    GUICtrlSetData($list_exlusions$exclusion_list)
endfunc

func AddExclusion($new_ex)
    if not StringInStr($exclusion_list$new_ex & "|") and $new_ex <> "" then
        $exclusion_list &= $new_ex & "|"
        IniWrite($ini_path$my_shortname"exclusions"$exclusion_list)
    endif
    GUICtrlSetData($input_appname"")
    GetExclusionsList()
    UpdateExclusionsList()
endfunc

func EditThisExclusion($ex)
    if not $ex then return
    $curr_ex = GUICtrlRead($input_appname)
    AddExclusion($curr_ex)
    RemoveExclusion($ex)
    GUICtrlSetData($input_appname$ex)
endfunc

func RemoveExclusion($appname)
    if not $appname then return "0" is sent if nothing selected, prevents removing all items!
    $tmp_array = StringSplit($exclusion_list"|")
    $exclusion_list = ""
    for $i = 1 to $tmp_array[0]
        if $tmp_array[$i] <> "" and $tmp_array[$i] <> $appname then
            $exclusion_list &= $tmp_array[$i] & "|"
        endif
    next
    IniWrite($ini_path$my_shortname"exclusions"$exclusion_list)
    GetExclusionsList()
    UpdateExclusionsList()
endfunc

func CheckActiveExclusions()
    GetExclusionsList()
    $ex_apps = StringSplit(StringTrimRight($exclusion_list, 1), "|")
    $old_matchmode = AutoItSetOption("WinTitleMatchMode", 2)
    for $i = 1 to $ex_apps[0]
        if WinActive($ex_apps[$i]) then
            return $ex_apps[$i]
        endif
    next
    AutoItSetOption("WinTitleMatchMode"$old_matchmode)
endfunc



; alarms..
;

; feed it the alarm name..
; returns the index number of that alarm.
;
func AlarmIndex($alarm_name)
    for $i = 1 to $alarm_names[0]
        if $alarm_names[$i] = $alarm_name then
            return $i
        endif
    next
endfunc

func GetAlarmNames()
    global $alarm_names = IniReadSectionNames($ini_path_alarms)
    if not IsArray($alarm_names) then
        global $alarm_names = MakeDummyArray("unsaved alarm")
        global $my_alarms[2][17] = [[1]]
    else
        global $my_alarms[$alarm_names[0]+1][17] = [[$alarm_names[0]]] ; set [0][0] to $alarm_names[0] (total)
    endif
    global $primed[$alarm_names[0]+1]
endfunc


func GetAlarms()
    GetAlarmNames()
    for $index = 1 to $alarm_names[0]
        $primed[$index] = 1 ; could check for a primed=0 (for active alarms)
        $my_alarms[$index][0] = IniRead($ini_path_alarms$alarm_names[$index], "Frequency""Daily")
        $my_alarms[$index][1] = IniRead($ini_path_alarms$alarm_names[$index], "Hour""12")
        $my_alarms[$index][2] = IniRead($ini_path_alarms$alarm_names[$index], "Min""00")
        $my_alarms[$index][3] = IniRead($ini_path_alarms$alarm_names[$index], "AMPM""pm")

        if $my_alarms[$index][0] <> "Daily" and $my_alarms[$index][0] <> "Weekdays" and _
            $my_alarms[$index][0] <> "Weekends" and $my_alarms[$index][0] <> "One Date" _
            and $my_alarms[$index][0] <> "Custom" then $my_alarms[$index][0] = "Daily"
        if $my_alarms[$index][1] < 1 or $my_alarms[$index][1] > 12 then $my_alarms[$index][1] = "12"
        if $my_alarms[$index][2] < 0 or $my_alarms[$index][2] > 59 then $my_alarms[$index][2] = "00"
        if StringLower($my_alarms[$index][3]) <> "am" and StringLower($my_alarms[$index][3]) <> "pm" _
                                                                        then $my_alarms[$index][3] = "am"

        $my_alarms[$index][4] = IniRead($ini_path_alarms$alarm_names[$index], "Month""")
        if Number($my_alarms[$index][4]) < 1 or Number($my_alarms[$index][4]) > 12 then $my_alarms[$index][4] = ""
        $my_alarms[$index][5] = IniRead($ini_path_alarms$alarm_names[$index], "Day""")
        if Number($my_alarms[$index][5]) < 1 or Number($my_alarms[$index][5]) > 31 then $my_alarms[$index][5] = ""
        $my_alarms[$index][6] = IniRead($ini_path_alarms$alarm_names[$index], "Year""")
        if Number($my_alarms[$index][6]) < Number(@YEAR) then $my_alarms[$index][6] = "" ; in the past

        $my_alarms[$index][7] = IniRead($ini_path_alarms$alarm_names[$index], "active""1")
        $my_alarms[$index][8] = IniRead($ini_path_alarms$alarm_names[$index], "message""")
        $my_alarms[$index][9] = IniRead($ini_path_alarms$alarm_names[$index], "flash_color""FF0000")
        $my_alarms[$index][10] = IniRead($ini_path_alarms$alarm_names[$index], "alert""simple")

        ; use defaults if none set..
        $my_alarms[$index][11] = IniRead($ini_path_alarms$alarm_names[$index], "speech_volume"$speech_volume)
        $my_alarms[$index][12] = IniRead($ini_path_alarms$alarm_names[$index], "speech_voice"$speech_voice)
        $my_alarms[$index][13] = IniRead($ini_path_alarms$alarm_names[$index], "speech_rate"$speech_rate)

        $my_alarms[$index][14] = IniRead($ini_path_alarms$alarm_names[$index], "custom_type""Years")
        $my_alarms[$index][15] = IniRead($ini_path_alarms$alarm_names[$index], "custom_period", 1)

        $my_alarms[$index][16] = IniRead($ini_path_alarms$alarm_names[$index], "missed", 0)

    next
endfunc

; hmm. getting kinda long.
func SaveAlarm($index)
    IniWrite($ini_path_alarms$alarm_names[$index], "Frequency"$my_alarms[$index][0])
    IniWrite($ini_path_alarms$alarm_names[$index], "Hour"$my_alarms[$index][1])
    IniWrite($ini_path_alarms$alarm_names[$index], "Min"$my_alarms[$index][2])
    IniWrite($ini_path_alarms$alarm_names[$index], "AMPM"$my_alarms[$index][3])
    IniWrite($ini_path_alarms$alarm_names[$index], "Month"$my_alarms[$index][4])
    IniWrite($ini_path_alarms$alarm_names[$index], "Day"$my_alarms[$index][5])
    IniWrite($ini_path_alarms$alarm_names[$index], "Year"$my_alarms[$index][6])
    IniWrite($ini_path_alarms$alarm_names[$index], "active"$my_alarms[$index][7])
    IniWrite($ini_path_alarms$alarm_names[$index], "message"$my_alarms[$index][8])
    IniWrite($ini_path_alarms$alarm_names[$index], "flash_color"$my_alarms[$index][9])
    IniWrite($ini_path_alarms$alarm_names[$index], "alert"$my_alarms[$index][10])
    IniWrite($ini_path_alarms$alarm_names[$index], "speech_volume"$my_alarms[$index][11])
    IniWrite($ini_path_alarms$alarm_names[$index], "speech_voice"$my_alarms[$index][12])
    IniWrite($ini_path_alarms$alarm_names[$index], "speech_rate"$my_alarms[$index][13])
    IniWrite($ini_path_alarms$alarm_names[$index], "custom_type"$my_alarms[$index][14])
    IniWrite($ini_path_alarms$alarm_names[$index], "custom_period"$my_alarms[$index][15])
    IniDelete($ini_path_alarms$alarm_names[$index], "missed")

    if $prefs_open then IniWrite($ini_path$my_shortname"current_preset"$new_alarm)
endfunc


; master alarm switch..
;
func ToggleAlarm()
    if $AlarmStatus[2] = 1 then
        $AlarmStatus[2] = 0
        GUICtrlSetState($check_master_enabled$GUI_UNCHECKED)
        if $prefs_open then GUICtrlSetData($check_master_enabled"disabled")
    else
        $AlarmStatus[2] = 1
        GUICtrlSetState($check_master_enabled$GUI_CHECKED)
        if $prefs_open then GUICtrlSetData($check_master_enabled"enabled")
    endif
    TrayItemSetText($TrayItemAlarmStatus"Alarms are " & $AlarmStatus[$AlarmStatus[2]])
    IniWrite($ini_path$my_shortname"alarms_active"$AlarmStatus[2])
endfunc

func ToggleThisAlarm($index)
    if $current_alarm_status = 1 then
        $current_alarm_status = 0
        GUICtrlSetData($check_alarm_enabled"disabled")
        GUICtrlSetState($check_alarm_enabled$GUI_UNCHECKED; it should be anyway, but this is a back-up
    else
        $current_alarm_status = 1
        GUICtrlSetData($check_alarm_enabled"enabled")
        GUICtrlSetState($check_alarm_enabled$GUI_CHECKED; ditto
    endif
    IniWrite($ini_path_alarms$alarm_names[$index], "active"$current_alarm_status)
endfunc


; schemes..
;

func SchemeIndex($scheme_name)
    for $i = 1 to $scheme_names[0]
        if $scheme_names[$i] = $scheme_name then
            return $i
        endif
    next
endfunc

; you want those colours right now, sir?
; as you wish..
func MenuSwitchScheme()
    for $s = 1 to $scheme_names[0]
        select
            case @GUI_CtrlId = $scheme_menu_items[$s]
                $current_scheme = $scheme_names[$s]
                CheckUncheckScheme($GUI_UNCHECKED$uncheck_item)
                CheckUncheckScheme($GUI_CHECKED$s)
                SwitchScheme($current_scheme)
                $uncheck_item = $s
        endselect
    next
endfunc

func F10SwitchPreviousScheme()
    CheckUncheckScheme($GUI_UNCHECKED)
    $new_idx = SchemeIndex($current_scheme) - 1
    if $new_idx < 1 then $new_idx = $scheme_names[0]
    $current_scheme = $scheme_names[$new_idx]
    CheckUncheckScheme($GUI_CHECKED)
    SwitchScheme($current_scheme)
endfunc

func F11SwitchNextScheme()
    CheckUncheckScheme($GUI_UNCHECKED)
    $new_idx = SchemeIndex($current_scheme) + 1
    if $new_idx > $scheme_names[0] then $new_idx = 1
    $current_scheme = $scheme_names[$new_idx]
    CheckUncheckScheme($GUI_CHECKED)
    SwitchScheme($current_scheme)
endfunc

func CheckUncheckScheme($action$item="")
    if $item then
        $s_idx = $item
    else
        $s_idx = SchemeIndex($current_scheme)
    endif

    GUICtrlSetState($scheme_menu_items[$s_idx], $action)
endfunc

func SwitchScheme($my_scheme)
    LoadScheme($my_scheme)
    AllThatGoodStuff(1)
    UpdateNumeralLabels()
    UpdatePips()
    IniWrite($ini_path$my_shortname"scheme",  $my_scheme; set as current scheme
endfunc


func GetSchemeNames()
    if not FileExists($ini_path_schemes) then FileInstall(".\stuff\default-schemes.ini"$ini_path_schemes, 0)
    global $scheme_names = IniReadSectionNames($ini_path_schemes)
    if not IsArray($scheme_names) then $scheme_names = MakeDummyArray("default")
    BubbleSort($scheme_names)
endfunc


; load a colour scheme..
;
func LoadScheme($my_scheme)

    GetSchemeNames()

    if not InArray($scheme_names$my_scheme) then
        $my_scheme = "default"
        $current_scheme = $my_scheme
    endif

    global $face_color = IniRead($ini_path_schemes$my_scheme"face_colour""FFFFFF")
    global $numerals_color = IniRead($ini_path_schemes$my_scheme"numerals_color""FF0000")
    global $second_hand_color = IniRead($ini_path_schemes$my_scheme"second_hand_color""FF0000")
    global $hour_pen = IniRead($ini_path_schemes$my_scheme"hour_pen""000000")
    global $minute_pen = IniRead($ini_path_schemes$my_scheme"minute_pen""000000")
    global $pips_pen = IniRead($ini_path_schemes$my_scheme"pips_pen""000000")
    global $big_pips_pen = IniRead($ini_path_schemes$my_scheme"big_pips_pen""000000")

    global $WinTrans = IniRead($ini_path_schemes$my_scheme"transparency", 0)
    if $WinTrans >= 100 then $WinTrans = 99
    if $WinTrans < 0 then $WinTrans = 0

    global $draw_numerals = IniReadCheckboxValue($ini_path_schemes$my_scheme"draw_numerals", 1)
    global $draw_pips = IniReadCheckboxValue($ini_path_schemes$my_scheme"draw_pips", 1)

    global $pips_outer_rim = IniRead($ini_path_schemes$my_scheme"pips_outer_rim", 2)
    global $minute_pips_size = IniRead($ini_path_schemes$my_scheme"minute_pips_size", 6)
    global $hour_pips_size = IniRead($ini_path_schemes$my_scheme"hour_pips_size", 10)

    global $second_hand_size = IniRead($ini_path_schemes$my_scheme"second_hand_size", 75)
    global $minute_hand_size = IniRead($ini_path_schemes$my_scheme"minute_hand_size", 67)
    global $hour_hand_size = IniRead($ini_path_schemes$my_scheme"hour_hand_size", 50)

    UpdateHandSizes()

endfunc


func UpdateSchemesCombo()
    GetSchemeNames()
    GUICtrlSetData($combo_scheme_presets"|")
    for $i = 1 to $scheme_names[0]
        GUICtrlSetData($combo_scheme_presets$scheme_names[$i])
    next
    GUICtrlSetData($combo_scheme_presets$current_scheme)
endfunc


func SaveSchemePref($this_scheme$prefname$val$checkbox=false)
    if $checkbox then
        IniWriteCheckboxValue($ini_path_schemes$this_scheme$prefname$val)
    else
        IniWrite($ini_path_schemes$this_scheme$prefname$val)
    endif
endfunc



; alerts..
;

func AlertIndex($alert_name)
    for $i = 1 to $alert_names[0]
        if $alert_names[$i] = $alert_name then
            return $i
        endif
    next
    return 1
endfunc

func GetAlertNames()
    if not FileExists($ini_path_alerts) then FileInstall(".\stuff\default-alerts.ini"$ini_path_alerts, 0)
    global $alert_names = IniReadSectionNames($ini_path_alerts)
    if not IsArray($alert_names) then $alert_names = MakeDummyArray("simple")
endfunc

func AddAlert($new_alert)
    if $new_alert <> "" then
        ; if not already in list.. (could also add automatically from wavs folder ;2do)
        $base_new_alert = BaseName($new_alert)
        if not FileExists(IniRead($ini_path_alerts$new_alert"wav""")) then
            ControlCommand($prefs_dialog""$combo_alert"AddString"$base_new_alert)
            ControlCommand($prefs_dialog""$combo_alert"SelectString"$base_new_alert)
            ControlCommand($prefs_dialog""$combo_alert_presets"AddString"$base_new_alert)
            ControlCommand($prefs_dialog""$combo_alert_presets"SelectString"$base_new_alert)
            IniWrite($ini_path_alerts$base_new_alert"wav"$new_alert)
            IniWrite($ini_path_alerts$base_new_alert"pause", 250)
        endif
    endif
    ; if it was thrown into the currently selected alarm, that counts as a change..
    $tab_index = ControlCommand($prefs_dialog""$tab_prefs"CurrentTab""")
    $current_alert = $new_alert
endfunc

; there can be only one..
func SaveAlert($alert_array$alert_type="beep")
    IniDelete($ini_path_alerts$alert_array[0])
    if $alert_type = "wav" then
        IniWrite($ini_path_alerts$alert_array[0], "wav"$alert_array[1])
        IniWrite($ini_path_alerts$alert_array[0], "pause"$alert_array[2])
    else
        IniWrite($ini_path_alerts$alert_array[0], "repeat"$alert_array[1])
        IniWrite($ini_path_alerts$alert_array[0], "beep_len"$alert_array[2])
        IniWrite($ini_path_alerts$alert_array[0], "sleep"$alert_array[3])
        IniWrite($ini_path_alerts$alert_array[0], "beeps"$alert_array[4])
        IniWrite($ini_path_alerts$alert_array[0], "bottom"$alert_array[5])
        if $alert_array[6] < 1 then $alert_array[6] = 1
        IniWrite($ini_path_alerts$alert_array[0], "step"$alert_array[6])
        IniWrite($ini_path_alerts$alert_array[0], "scaler"$alert_array[7])
        IniWriteCheckBoxValue($ini_path_alerts$alert_array[0], "and_down"$alert_array[8])
    endif
endfunc

func UpdateAlertCombos()
    GetAlertNames()
    GUICtrlSetData($combo_alert"|")
    GUICtrlSetData($combo_alert_presets"|")
    for $i = 1 to $alert_names[0]
        if $alert_names[$i] <> "" then
            GUICtrlSetData($combo_alert$alert_names[$i])
            GUICtrlSetData($combo_alert_presets$alert_names[$i])
        endif
    next
    if AlertIndex($current_alert) = 0 then
        $current_alert = $alert_names[$alert_names[0]]
    endif
    GUICtrlSetData($combo_alert$current_alert)
    GUICtrlSetData($combo_alert_presets$current_alert)
endfunc

func DeleteAlert($this_alert)
    IniDelete($ini_path_alerts$this_alert)
endfunc



; import/export functions..
;

func ImportIniFile($import_file)
    if $import_file <> "" then

        $ini_sections = IniReadSectionNames($import_file)
        if not IsArray($ini_sections) then return

        ; the quick and dirty method..
        ;for $i = 1 to $ini_sections[0]
        ;    if not InArray($alarm_names$ini_sections[$i]) then
        ;        IniWriteSection($ini_path_alarms$ini_sections[$i], IniReadSection($import_file$ini_sections[$i]))
        ;        ControlCommand($prefs_dialog""$combo_alarm_presets"AddString"$ini_sections[$i])
        ;    endif
        ;next

        ; A more thorough method..
        ;
        ; This method enables dragging of *any* type of preset file. It interrogates the file, and
        ; adds whatever presets it finds to the correct ini. This even works if the presets are all
        ; mixed up in a single file, a-la "collection".
        ;
        local $alarm_score$scheme_score$wav_score$beep_score$got_alarms$got_schemes
        for $i = 1 to $ini_sections[0]

            $ini_section = IniReadSection($import_file$ini_sections[$i])
            if not IsArray($ini_section) then continueloop

            ; run through each ini setting, see what we have..
            for $j = 0 to uBound($ini_section)-1

                switch $ini_section[$j][0]

                    ; To be valid, an alarm MUST have at least..
                    ; Frequency, Hour, Min, and AMPM
                    case "Dates" ; drag&drop legacy "analog clock" alarm conversion
                        $ini_section[$j][0] = "Frequency"
                        continuecase
                    case "Frequency"
                        $alarm_score += 1
                    case "Hour"
                        $alarm_score += 1
                    case "Min"
                        $alarm_score += 1
                    case "AMPM"
                        $alarm_score += 1

                    ; any one of these settings is enough to make a scheme..
                    case "face_colour"
                        $scheme_score += 1
                    case "numerals_color"
                        $scheme_score += 1
                    case "second_hand_color"
                        $scheme_score += 1
                    case "hour_pen"
                        $scheme_score += 1
                    case "minute_pen"
                        $scheme_score += 1
                    case "pips_pen"
                        $scheme_score += 1
                    case "big_pips_pen"
                        $scheme_score += 1
                    case "transparency"
                        $scheme_score += 1
                    case "draw_numerals"
                        $scheme_score += 1
                    case "draw_pips"
                        $scheme_score += 1
                    case "pips_outer_rim"
                        $scheme_score += 1
                    case "minute_pips_size"
                        $scheme_score += 1
                    case "hour_pips_size"
                        $scheme_score += 1
                    case "second_hand_size"
                        $scheme_score += 1
                    case "minute_hand_size"
                        $scheme_score += 1
                    case "hour_hand_size"
                        $scheme_score += 1

                    ; again, a single setting is enough (a simple override)..
                    case "repeat"
                        $beep_score += 1
                    case "beep_len"
                        $beep_score += 1
                    case "sleep"
                        $beep_score += 1
                    case "beeps"
                        $beep_score += 1
                    case "bottom"
                        $beep_score += 1
                    case "step"
                        $beep_score += 1
                    case "scaler"
                        $beep_score += 1
                    case "and_down"
                        $beep_score += 1

                    ; you get nothing for just a "pause" setting..
                    case "wav"
                        $wav_score += 1
                endswitch
            next

            ; now check the totals..
            select
                case $alarm_score = 4 ; four criteria satisfied
                    if not InArray($alarm_names$ini_sections[$i]) then

                        IniWriteSection($ini_path_alarms$ini_sections[$i], $ini_section)
                        ControlCommand($prefs_dialog""$combo_alarm_presets"AddString"$ini_sections[$i])
                        ControlCommand($prefs_dialog""$combo_alarm_presets"SelectString"$ini_sections[$i])
                        $got_alarms = true
                    endif

                case $scheme_score >= 1
                    if not InArray($scheme_names$ini_sections[$i]) then
                        IniWriteSection($ini_path_schemes$ini_sections[$i], $ini_section)
                        ControlCommand($prefs_dialog""$combo_scheme_presets"AddString"$ini_sections[$i])
                        ControlCommand($prefs_dialog""$combo_scheme_presets"SelectString"$ini_sections[$i])
                        $got_schemes = true
                    endif

                case $wav_score >= 1 or $beep_score >= 1 ; we may add more criteria later
                    ; we don't check for the wav's existence, assuming the user probably knows what they are doing.
                    if not InArray($alert_names$ini_sections[$i]) and $ini_sections[$i] <> $my_shortname then
                        IniWriteSection($ini_path_alerts$ini_sections[$i], $ini_section)
                        ControlCommand($prefs_dialog""$combo_alert_presets"AddString"$ini_sections[$i])
                        ControlCommand($prefs_dialog""$combo_alert_presets"SelectString"$ini_sections[$i])
                    endif
            endselect
            $alarm_score = 0
            $scheme_score = 0
            $wav_score = 0
            $beep_score = 0
        next
        if $got_alarms then GetAlarms()
        if $got_schemes then GetSchemeNames()
    endif
endfunc


func ExportAlarm()
    ExportSettings($ini_path_alarms"save_alarms", GUICtrlRead($combo_alarm_presets))
endfunc
func ExportAlarmIntoCollection()
    ExportSettings($ini_path_alarms"save_collections", GUICtrlRead($combo_alarm_presets), """", true)
endfunc
func ExportAllAlarms()
    ExportSettings($ini_path_alarms"save_alarms""""Alarms", true)
endfunc

func ExportScheme()
    ExportSettings($ini_path_schemes"save_schemes", GUICtrlRead($combo_scheme_presets))
endfunc
func ExportSchemeIntoCollection()
    ExportSettings($ini_path_schemes"save_collections", GUICtrlRead($combo_scheme_presets), """", true)
endfunc
func ExportAllSchemes()
    ExportSettings($ini_path_schemes"save_schemes""""Schemes", true)
endfunc

func ExportAlert()
    ExportSettings($ini_path_alerts"save_alerts", GUICtrlRead($combo_alert_presets))
endfunc
func ExportAlertIntoCollection()
    ExportSettings($ini_path_alerts"save_collections", GUICtrlRead($combo_alert_presets), """", true)
endfunc
func ExportAllAlerts()
    ExportSettings($ini_path_alerts"save_alerts""""Alerts", true)
endfunc

func ExportSettings($ini_file$default_save_to="save_inis"$preset=""$title="Settings"$all_sections=false, $collect=false)

    $save_to = IniRead($ini_path$my_shortname$default_save_to, @MyDocumentsDir)
    $old_section = IniReadSection($ini_file$preset)

    $label = $preset
    $save_name = $preset
    $opt = 16
    $thingie = " as.."

    if $collect then
        $opt = 0 ; don't prompt for overwrite
        $thingie = " into a new or existing collection.."
        $save_name =  $recent_collection
    endif

    ; technically, these should never action, but the user may be *really* quick, and
    ; grab a menu item before it is greyed out. They also serve as a fall-back check.
    if not $all_sections and not IsArray($old_section) then return
    if $all_sections and not FileExists($ini_file) then return

    PrefsFileDialogOpen()
    if $all_sections then
        $label = "All " & $title
        $save_name = $title & " [" &@YEAR & "-" & @MON & "-" & @MDAY & "]"
    endif
    $save_file = FileSaveDialog( "Export " & $label & $thingie$save_to"ini files (*.ini)" , $opt$save_name & ".ini")

    if $save_file then
        IniWrite($ini_path$my_shortname$default_save_to, GetParent($save_file))
        if $all_sections then
            ; simple is best, this way we also get the comments..
            FileCopy($ini_file$save_file)
        else
            IniWriteSection($save_file$preset$old_section; you can add to existing ini files, make collections
        endif
        $recent_collection = CleanName($save_file)
        IniWrite($ini_path$my_shortname"recent_collection"$recent_collection)
    endif
    PrefsFileDialogClose()
endfunc


; backup preset deletions in case they change their mind..
;
func StoreBackup($inifile_path)
    FileCopy($inifile_path, @TempDir & "\" & Basename($inifile_path) & ".backup.ini", 1)
endfunc

func RecoverBackup($inifile_path)
    FileCopy($inifile_path, @TempDir & "\" & Basename($inifile_path) & ".backupTMP", 1)
    ImportIniFile(@TempDir & "\" & Basename($inifile_path) & ".backup.ini"; whole lotta free energy here
    FileMove(@TempDir & "\" & Basename($inifile_path) & ".backupTMP", @TempDir & "\" & Basename($inifile_path) & ".backup.ini", 1)

    ToolTip(" Your " & CleanName($inifile_path) & " have been successfully recovered"$prefs_x$prefs_y, _
                                                                        "Backup recovered ", 1)
    AdlibEnable("SwitchOffTip", 4000)
endfunc

func RemoveBackup($inifile_path)
    FileDelete(@TempDir & "\" & Basename($inifile_path) & ".backup.ini")
endfunc



func DoChime($do_min="")

    if CheckActiveExclusions() then return

    if $do_chime = 1 then
        StopSound()
        $chime = IniRead($ini_path$my_shortname"chime", 4000)
        if $chime = "" then $chime = 4000
        if not $do_min then $do_min = @MIN

        if Int($chime) <> 0 then
            if @HOUR = 00 then ; double-pips at midnight, for human-time calibration when no clocks are visible
                Beep($chime, 133)
                Sleep(5)
                Beep($chime, 133)
            else
                Beep($chime, 333)
            endif
            if $play_idx <> 0 then SwitchIconsREADY()

        elseif GetExtension($chime) = "wav" and FileExists($chime) then
            $play_idx = 12
            if $prefs_open then $play_idx = 8
            PlaySound($chime)
        else
            $play_idx = 13
            if $prefs_open then $play_idx = 7
            $ampm_add = ", A. M. " ; punctuate for correct speech
            $hour_array = HourToHumanTime(@HOUR)
            $hour = $hour_array[0]
            if $hour_array[1] = "pm" then $ampm_add = ", P. M. "

            $chime = TransformMessage($chime)
            $speech_voice = IniRead($ini_path$my_shortname"speech_voice""Sam")

            if $do_min = 0 then
                Say(String($hour) & " O clock " & $ampm_add & ", " &  $chime$speech_volume$speech_voice$speech_rate; string() isn't strictly necessary
            else
                if $do_min < 10 then $do_min = StringReplace(String($do_min), "0""O ")
                Say(String($hour) & " " & $do_min & $ampm_add & ", " & $chime$speech_volume$speech_voice$speech_rate)
            endif
        endif
    endif

    ; on-top status tends to be lost over time, so thios would be nice..
    ;if $on_top = $GUI_CHECKED then WinSetOnTop($gui"", 1)
    ; but we'd have to check that no movies/games/etc were playing - how to check the overlay status? hmm.

endfunc

func MenuToggleChime()
    ToggleChime()
endfunc

func ToggleChime($flip=0)
    if $do_chime = $GUI_CHECKED then
        $do_chime = $GUI_UNCHECKED
    else
        $do_chime = $GUI_CHECKED
    endif
    if not $flip then
        TrayItemSetText($TrayItemChimeStatus"Chimes are " & $chimes_status[$do_chime])
        GUICtrlSetState($check_chimes$do_chime)
        IniWriteCheckBoxValue($ini_path$my_shortname"do_chime"$do_chime)
    endif
endfunc



func TestMessage($t_string$t_index$t_volume$t_voice$t_rate)
    if $t_string = "" then return
        if GetExtension($t_string) = "wav" and FileExists($t_string) then
            PlaySound($t_string)
        else
            $t_string = TransformMessage($t_string)
            Say($t_string$t_volume$t_voice$t_rate)
        endif
endfunc


; somewhat enhanced..
;
func IGuessItsAlarmTime($index=0, $test=false, $flash_col="FF0000")

    if CheckActiveExclusions() then
        ToolTip(" Audio disabled by exclusion list ", @DesktopWidth/2-100, 1, "ALARM: " & $alarm_names[$index], 2)
        AdlibEnable("SwitchOffTip", 3333)
        ; do not unset the primed status
        ; if they switch to a non-excluded app within a minute, they still get the alarm
        return
    endif


    $do_flash = true

    if not $test then
        if $my_alarms[$index][7] <> 1 then return ; alarm is disabled
        if $AlarmStatus[2] <> 1 then return ; alarms master disabled
        $primed[$index] = 0
        $last_alarm_min = @MIN

        ; grab these again, in case they are playing around, editing their ini..
        $flash_color = "0x" & IniRead($ini_path_alarms$alarm_names[$index], "flash_color""FF0000")
        $alert = IniRead($ini_path$my_shortname"alert""simple")
        ; override with alarm-specific alert (or not)..
        $alert = IniRead($ini_path_alarms$alarm_names[$index], "alert"$alert)
        IniWrite($ini_path_alarms$alarm_names[$index], "missed""no")
    else
        $alert = $index
        if $flash_col = "-" then
            $do_flash = false
        else
            $flash_color = "0x" & $flash_col
        endif
    endif

    if FileExists($alert) then
        $play_wav = $alert            ; useful legacy functionality: [c:\path\to\file.wav]
    else                            ; they might simply enter the path to a wav in the input, you see.
        $play_wav = IniRead($ini_path_alerts$alert"wav""")
    endif

    if FileExists($play_wav) then
        if $do_flash then GUISetBkColor($flash_color$gui)
        if not $test then $play_idx = 13
        PlaySound($play_wav)
        Sleep(IniRead($ini_path_alerts$alert"pause", 250)) ; alarm specific
        if $do_flash then GUISetBkColor("0x" & $face_color$gui)
        AllThatGoodStuff(2)
    else

        ; load the default alert values first..
        $and_down = 0
        $beep_len = 500
        $beeps = 1
        $bottom = 1
        $repeat = 6
        $scaler = 3000
        $sleep = 500
        $step = 1

        ; then the default built-in alert values..
        select
            case $alert = "siren"
                $and_down = 1
                $beep_len = 5
                $beeps = 66
                $repeat = 10
                $scaler = 50
                $sleep = 0
                $step = 2

            case $alert = "beeper"
                $beep_len = 50
                $beeps = 20
                $repeat = 3
                $scaler = 400
                $sleep = 50

            case $alert = "simple"
                $repeat = 7
        endselect

        ; the user may have been toying around (and may still be!), let's override..
        $sections = IniReadSectionNames($ini_path_alerts)
        if IsArray($sections) then ; Damn! AutoIt is STRONG in the ini department!
            $repeat =  IniRead($ini_path_alerts$alert"repeat"$repeat)
            $beep_len = IniRead($ini_path_alerts$alert"beep_len"$beep_len)
            $sleep =  IniRead($ini_path_alerts$alert"sleep"$sleep)
            $beeps =  IniRead($ini_path_alerts$alert"beeps"$beeps)
            $bottom = IniRead($ini_path_alerts$alert"bottom"$bottom)
            $step =  IniRead($ini_path_alerts$alert"step"$step)
            if $step < 1 then $step = 1
            $scaler =  IniRead($ini_path_alerts$alert"scaler"$scaler)
            $and_down =  IniRead($ini_path_alerts$alert"and_down"$and_down)
        endif

        ; wait for previous alarm (if any) to finish.
        if Checksound() then
            while CheckSound()
                sleep(500)
                CheckClockStuff()
            wend
        endif

        ; let's beep!
        global $interrupt = 0
        for $a = 1 to $repeat
            if $do_flash then GUISetBkColor($flash_color$gui)
            for $i = $bottom to $beeps step $step
                if $interrupt then exitloop 2
                Beep($scaler * $i$beep_len)
                Sleep($sleep)
            next
            if $do_flash then GUISetBkColor("0x" & $face_color$gui)
            if $and_down = 1 then
                for $i = $beeps to $bottom step - $step
                    if $interrupt then exitloop 2
                    Beep($scaler * $i$beep_len)
                    Sleep($sleep)
                next
            endif
        next
        AllThatGoodStuff(2)
        $interrupt = 0
        if $do_flash then GUISetBkColor("0x" & $face_color$gui; in case of interrupt
    endif

    ; if there's a spoken message for this alarm..
    if not $test then
        if Checksound() then
            while CheckSound()
                sleep(500)
                CheckClockStuff()
            wend
        endif
        ; the following is an undocumented feature; you can enter the path to a wav file
        ; into the spoken message input and basically use two wav files for your alarm..
        if GetExtension($my_alarms[$index][8]) = "wav" and FileExists($my_alarms[$index][8]) then
            $play_idx = 13
            if $prefs_open then $play_idx = 6
            PlaySound($my_alarms[$index][8])
        else
            $play_idx = 13
            if $my_alarms[$index][8] <> "" then
                $spoken = TransformMessage($my_alarms[$index][8])
                Say($spoken$my_alarms[$index][11], $my_alarms[$index][12], $my_alarms[$index][13])
            endif
        endif
    SwitchScheme($current_scheme; in case there are any color artefacts from the flashing
    endif
endfunc



; Speak some text out loud..
;
; saving to a temporary WAV file works better than speaking directly, because
; you always hear the whole message without timing worries, messing with
; sleep()ing and shit. Using my custom PlaySound routine also enables us to
; stop the speech mid-stream, which is often useful.
;
func Say($text$volume$my_voice="Sam"$rate=0)
    if FileExists($text) then $text = FileRead($text)
    global $voice = ObjCreate("Sapi.SpVoice")
    if SpeakToWAV($text, @tempdir & "\clocktmp.wav"$volume$my_voice$rate) = 1 then
        PlaySound(@tempdir & "\clocktmp.wav")
    endif
endfunc

; is you specify the wrong voice, sapi continues with the default voice (on XP, that's Sam)
func SpeakToWAV($text$file$volume$my_voice="Sam"$rate=0)
    if StringLen($my_voice) < 5 then $my_voice = "Name=Microsoft " & $my_voice ; works so far!
    $MyObjectError = ObjEvent("AutoIt.Error""MyDummyErrFunc")
    $file_obj=ObjCreate("SAPI.SpFileStream.1")
    if Isobj($voice) and Isobj($file_obj) then
        $file_obj.Open($file,3)
        $voice.AudioOutputStream = $file_obj
        $voice.Voice = $voice.GetVoices($my_voice).Item(0) ; language is optional, you see
        $voice.Volume = $volume
        $voice.Rate = $rate
        $voice.Speak($text)
        $voice = ObjCreate("Sapi.SpVoice"; stop
        return 1
    endif
endfunc

; prevents errers..
func MyDummyErrFunc()
    ; if you specify "LH Michael", speech will still work.
    ; btw; get "LH Michelle" and "LH Michael" by installing Microsoft Reader and the TTS add-on.
endfunc


; decide whether the text provided is a string, a URL, or a real local file,
; and if it's the latter, decide if it's HTML or not. Once we know what we have,
; return the plain text of whatever-it-is for speaking.
;
func TransformMessage($string)
    select
        case FileExists($string)
            $inner = FileRead($string)
                ; I started checking for "<!doc", <html, etc. but this makes more sense..
                if StringLeft(StringStripWS($inner, 1), 1) = "<" then ; an html file
                return UrlToText($string)
            else
                return FileRead($string)
            endif
        case StringLeft($string, 4) = "http"
            return UrlToText($string)
        case else
            return $string
    endselect
endfunc


func PlaySound($file)

    DllCall("winmm.dll""int""mciSendString""str""close waveaudio""str""""int", 0, "int", 0)
    $foo = DllCall("winmm.dll""int""mciSendString""str""open waveaudio!" & $file _
                                        & " alias sample""str""""int", 255, "int", 0)

    if $foo[2] <> 1 then
        ; backup for wavs that winmm.dll won't play, somehow SoundPlay() can.
        ; however, the user cannot stop this sound in mid-stream.
        ;
        ; setting an hourglass cursor here would be great, but for some reason
        ; it won't properly unset afterwards, perhaps something to do with the
        ; dll call. The buttons change to "NO ENTRY", so that will have to do.
debug(@ScriptLineNumber & ": " & "PlaySound: FALL-BACK " & "->" & $file & "<-" & @CRLF)
        SwitchIconsWAIT()
        SoundPlay($file, 1) ; it's too dodgy to give back control while the sound is playing
        SwitchIconsREADY()
        ; As well as a backup for sounds that winmm.dll can't handle, it serves as a fall-back for
        ; any occasions when the sound system/temp wav gets stuck; this kicks in and you still get audio.
        return
    endif
    DllCall("winmm.dll""int""mciSendString""str""play sample""str""""int", 0, "int", 0)
endfunc


; sound still playing?
; although it sounds groovy if you're stoned, we don't actually want sounds playing over the top of each other.
func CheckSound()
    if not $play_idx then return 0
    $status = DllCall("winmm.dll""int""mciSendString""str""status sample mode""str""""int", 255, "int", 0)
    switch $status[2]
        case "stopped"
            SoundOff()
            return 0
        case ""
            $play_idx = 0
            return 0
        case else
            return 1
    endswitch
endfunc

; we have CONTROL!
func SoundOff()
    StopSound()
    $play_idx = 0
    SwitchIconsREADY()
endfunc
func StopSound()
    $interrupt = 1 ; hit it with everything..
    DllCall("winmm.dll""int""mciSendString""str""seek sample to start""str","""int", 0, "int", 0)
    DllCall("winmm.dll""int""mciSendString""str""stop sample""str","""int", 0, "int", 0)
    DllCall("winmm.dll""int""mciSendString""str""close sample""str","""int", 0, "int", 0)
    ; I realise that the above isn't strictly necessary, but it was added while hunting
    ; a curious bug, and I can't think of any good reason to remove it again!
    DllCall("winmm.dll""int""mciSendString""str""close waveaudio""str""""int", 0, "int", 0)
    FileDelete(@tempdir & "\clocktmp.wav")
endfunc


func SwitchIconsPLAYING()
    switch $play_idx
        case 2 ; alert test (wav)
            GUICtrlSetImage($icon_alert_test"shell32.dll", 28, 0)
        case 3 ; alert test (beep)
            GUICtrlSetImage($icon_alert_test"shell32.dll", 200, 0)
        case 4 ; audio tab wav test
            GUICtrlSetImage($icon_alert_wav_play"shell32.dll", 28, 0)
        case 5 ; audio tab beep test
            GUICtrlSetImage($icon_beepalert_test"shell32.dll", 200, 0)
        case 6 ; spoken message test
            GUICtrlSetImage($icon_msg_test"shell32.dll", 28, 0)
        case 7 ; spoken chime
            GUICtrlSetImage($icon_chime_test"shell32.dll", 28, 0)
        case 8 ; chime test (wav)
            GUICtrlSetImage($icon_chime_test"shell32.dll", 28, 0)
        case 9 ; chime test (beep)
            GUICtrlSetImage($icon_chime_test"shell32.dll", 200, 0)
    endswitch
endfunc

; for some reason, you cannot interrupt this sound..
func SwitchIconsWAIT()
    switch $play_idx
        case 2
            GUICtrlSetImage($icon_alert_test"shell32.dll", 200, 0)
        case 4
            GUICtrlSetImage($icon_alert_wav_play"shell32.dll", 200, 0)
        case 8
            GUICtrlSetImage($icon_chime_test"shell32.dll", 200, 0)
    endswitch
endfunc

; the normal state..
func SwitchIconsREADY()
    if not $prefs_open then return
    GUICtrlSetImage($icon_chime_test"shell32.dll", 246, 0)
    GUICtrlSetImage($icon_alert_test"shell32.dll", 246, 0)
    GUICtrlSetImage($icon_msg_test"shell32.dll", 246, 0)
    GUICtrlSetImage($icon_beepalert_test"shell32.dll", 246, 0)
    GUICtrlSetImage($icon_alert_wav_play"shell32.dll", 246, 0)
endfunc



func F9ToggleClickDrag()
    ToggleClickDrag()
endfunc

func MenuToggleClickDrag()
    ToggleClickDrag()
endfunc

func ToggleClickDrag($flip=0) ; a "flip" is when we toggle and back very quickly, as a handy reset mechanism
    if $click_drag_to_move <> $GUI_CHECKED then
        $click_drag_to_move = $GUI_CHECKED
        GUICtrlSetState($MenuItemClickDrag$GUI_CHECKED)
    else
        $click_drag_to_move = 0
        GUICtrlSetState($MenuItemClickDrag$GUI_UNCHECKED)
    endif
    if not $flip then IniWriteCheckBoxValue($ini_path$my_shortname"click_drag_to_move"$click_drag_to_move)
endfunc


func _DateToDayOfWeekSpecial($iYear$iMonth$iDay)
    local $i_aFactor$i_yFactor$i_mFactor$i_dFactor
    $i_aFactor = Int((14 - $iMonth) / 12)
    $i_yFactor = $iYear - $i_aFactor
    $i_mFactor = $iMonth + (12 * $i_aFactor) - 2
    $i_dFactor = Mod($iDay + $i_yFactor + Int($i_yFactor / 4) - Int($i_yFactor / 100) _
                            + Int($i_yFactor / 400) + Int((31 * $i_mFactor) / 12), 7)
    if $i_dFactor >= 1 then return $i_dFactor - 1
    return 6
endfunc; _DateToDayOfWeekISO all-in-one ;



; HourToHumanTime()
;
; returns a 1-dimensional array with two values..
;
;    [0] = hour (integer in 12-hour clock format)
;    [1] = am/pm (string)
;
func HourToHumanTime($24hour)
    local $human_hour[2]
        $human_hour[0] = Number($24hour; 02 -> 2
        $human_hour[1] = "am"
        if $24hour > 11 then $human_hour[1] = "pm"
        if $24hour = 00 then $human_hour[0] = 12
        if $24hour > 12 then $human_hour[0] -= 12
        $human_hour[0] = int($human_hour[0])
    return $human_hour
endfunc


; And the reverse..
;
; Feed it the twelve-hour-clock format hour, and the am/pm string ("am" or "pm")
; Returns an integer (the hour, in 24 hour clock format, padded with a zero, if
; necessary), e.g..
;
;        HumanTimeToHour(3, "am") = 03
;        HumanTimeToHour(3, "pm") = 15
;
; I use two variables here because a) it's clearer, and b)
; I've been gagging to use the word "puter" in a variable for ages.
;
func HumanTimeToHour($12hour$am_pm)
    switch $am_pm
        case "am"
            if $12hour = 12 then
                $puter_hours = 0
            else
                $puter_hours = $12hour
            endif
        case "pm"
            if $12hour = 12 then
                $puter_hours = 12
            else
                $puter_hours = $12hour + 12
            endif
    endswitch
    return StringFormat("%02d"$puter_hours)
endfunc




func DoAbout()
    DialogOpen()
    $last_event_mode = AutoItSetOption("GUIOnEventMode", 0)
    $last_coord_mode = AutoItSetOption("GUICoordMode", 1)
    $GUI_About = GUICreate(" About " & $my_shortname & "..", 230, 100, -1, -1, $WS_CAPTION$WS_EX_TOPMOST)
    GUICtrlCreateLabel(" " & $my_shortname & " v" & $my_version & @CRLF & " by cor + greenmachine", 60, 8)
    GUICtrlCreateIcon("shell32.dll", 274, 10, 10)

    GUICtrlCreateLabel(" do you want to visit the " & @CRLF & " corz clock web page at this time? ", 60, 40)

    $gui_about_NO = GUICtrlCreateButton("No, not right now", 10, 74, 85, 22)
    $gui_about_OK = GUICtrlCreateButton("Yes, let's do it!", 138, 74, 85, 22)
    GUICtrlSetState($gui_about_OK$GUI_FOCUS)

    GUISetState()
    while 1
        $msg = GUIGetMsg()
        switch $msg
            case $GUI_EVENT_CLOSE$gui_about_NO
                GUIDelete($gui_about)
                exitloop
            case $gui_about_OK
                VisitURL('http://corz.org/windows/software/clock/')
                GUIDelete($gui_about)
                exitloop
        endswitch
        CheckClockStuff(2)
    wend
    AutoItSetOption("GUIOnEventMode"$last_event_mode)
    AutoItSetOption("GUICoordMode"$last_coord_mode)
    DialogClose()
    WinActivate($gui)
endfunc


func ShowTips()
    DialogOpen()
    corz_TipsSystem($tips_file$gui$ini_path$my_shortname"corz clock tips""", 380, "CheckClockStuff""""""right")
    DialogClose()
endfunc


; fade-in..
;
; you get to see the clock at max opacity for a moment, then dropping to the
; current transparency setting, which I enjoy; it's like a wee startup pulse.
func FadeIn()
    if $fade_in = $GUI_CHECKED then
        WinSetTrans($gui"", 0)
        GUISetState(@SW_SHOW, $gui)
        $step = 5
        $i = 100
        ;while $i >= $WinTrans+3 ; use this to only fade-in to the clock's current transparency level
        while $i >= 3
            WinSetTrans($gui"", (100 - $i) * 2.55)
            Sleep(5)
            $step = $i / 9
            $i -= $step
        wend
    else
        GUISetState(@SW_SHOW, $gui)
    endif
    WinActivate($gui)    ; bonus! heh. seriously, in startup items it sometimes doesn't draw completely - try 1. ;2do
                        ; I only restart the XP box about once a month, so I'll come back to this.
endfunc


; handy as functions..
func DialogOpen()
    GUISetState(@SW_DISABLE, $gui)
    AutoItSetOption("TrayIconHide" , 1)
    UnsetHotKeys()
endfunc
func DialogClose()
    AutoItSetOption("TrayIconHide" , 0)
    GUISetState(@SW_ENABLE, $gui)
    WinActivate($gui)
    SetHotKeys()
endfunc


; mix-and-match, depending on whether it's a system file dialog or not..
func PrefsFileDialogOpen()
    PrefsDialogOpen()
    ; on top status is only disabled for file dialogs, else gui paint issues
    WinSetOnTop($prefs_dialog"", 0)
endfunc
func PrefsFileDialogClose()
    GUISetState(@SW_ENABLE, $prefs_dialog)
    WinSetOnTop($prefs_dialog"", 1)
    WinActivate($prefs_dialog)
endfunc
func PrefsDialogOpen()
    GUISetState(@SW_DISABLE, $prefs_dialog)
endfunc
func PrefsDialogClose()
    ; if you move the dialog (say, the exclusions list), it leaves black areas in the prefs window.
    ; However, after some trial and error, I discovered a way to force the window to re-paint..
    GUISetState(@SW_UNLOCK, $prefs_dialog)    ; even though it was never locked, Boom! Instant re-paint!
    ; before or after the @SW_ENABLE, it dunt matter, but don't use it for system file dialogs.
    PrefsFileDialogClose()
endfunc

func SwitchOffTip()
    ToolTip("")
    AdlibDisable()
endfunc


func MenuToggleStartWithWindows()
    ToggleStartWithWindows()
endfunc

func ToggleStartWithWindows($flip=0)
    if $start_with_windows = $GUI_CHECKED then
        $start_with_windows = $GUI_UNCHECKED
    else
        $start_with_windows = $GUI_CHECKED
    endif
    TrayItemSetState($TrayItemStartWithWindows$start_with_windows)
    if not $flip then
        IniWriteCheckboxValue($ini_path$my_shortname"start_with_windows"$start_with_windows)
        CheckStartupLink()
    endif
endfunc

func MenuToggleFadeAtStartup()
    ToggleFadeAtStartup()
endfunc

func ToggleFadeAtStartup($flip=0)
    if $fade_in = $GUI_CHECKED then
        $fade_in = $GUI_UNCHECKED
    else
        $fade_in = $GUI_CHECKED
    endif
    TrayItemSetState($TrayItemFadeAtStartup$fade_in)
    if not $flip then IniWriteCheckboxValue($ini_path$my_shortname"fade_in"$fade_in)
endfunc


func MenuToggleOnTop()
    ToggleOnTop()
endfunc

func ToggleOnTop($flip=0)
    if $on_top <> $GUI_CHECKED then    ; 1
        WinSetOnTop($gui"", 1)
        $on_top = $GUI_CHECKED
        GUICtrlSetState($MenuItemOnTop$GUI_CHECKED)
    else
        WinSetOnTop($gui"", 0)
        $on_top = $GUI_UNCHECKED ; 4
        GUICtrlSetState($MenuItemOnTop$GUI_UNCHECKED)
    endif
    if not $flip then IniWriteCheckBoxValue($ini_path$my_shortname"always_on_top"$on_top)
endfunc


func RefreshClock()
    ToggleWindow(1)
    ToggleWindow(1)
endfunc

; left-click system tray action..
func MenuToggleWindow()
    ToggleWindow()
endfunc

func ToggleWindow($flip=0)
    $winstate = WinGetState($gui)
    if BitAnd($winstate, 2) then
        GUISetState(@SW_HIDE, $gui)
        if not $flip then UnsetHotKeys()
    else
        GUISetState(@SW_SHOW, $gui)
        if not $flip then SetHotKeys()
        if $on_top = $GUI_CHECKED then WinSetOnTop($gui"", 1) ; after a time, this ca get unset somehow. hmm
    endif
endfunc

; a bit dodgy, but fun..
func Drag()
    if $click_drag_to_move <> 1 then return
    dllcall("user32.dll","int","ReleaseCapture")
    dllcall("user32.dll","int","SendMessage","hWnd"$gui ,"int",$WM_NCLBUTTONDOWN,"int"$HTCAPTION,"int", 0)
endfunc


; hot-keys..
;
; this was a back-up system that was convenient to leave intact
; now it's the main system. I like it.
;
func SetHotKeys()
    HotKeySet("{PAUSE}""SoundOff")
    HotKeySet("!{F4}""AltF4DoQuit")
    HotKeySet("{Esc}""AltF4DoQuit")
    HotKeySet("{F1}""ShowTips")
    HotKeySet("{F2}""F2ResizeTheClock")
    HotKeySet("{F3}""F3MoveTheClock")
    HotKeySet("{F4}""F4DialogSetTrans")
    HotKeySet("{F5}""AlarmPrefs")
    HotKeySet("{F6}""ColorPrefs")
    HotKeySet("{F7}""LaunchAudioPrefs")
    HotKeySet("{F8}""GoColorPickinChooser")
    HotKeySet("{F9}""F9ToggleClickDrag")
    HotKeySet("{F10}""F10SwitchPreviousScheme")
    HotKeySet("{F11}""F11SwitchNextScheme")
    HotKeySet("{UP}""TransUp")
    HotKeySet("{DOWN}""TransDown")
    HotKeySet("{PGUP}""BigTransUp")
    HotKeySet("{PGDN}""BigTransDown")
endfunc
func UnsetHotKeys()
    HotKeySet("{PAUSE}")
    HotKeySet("!{F4}")
    HotKeySet("{Esc}")
    HotKeySet("{F1}")
    HotKeySet("{F2}")
    HotKeySet("{F3}")
    HotKeySet("{F4}")
    HotKeySet("{F5}")
    HotKeySet("{F6}")
    HotKeySet("{F7}")
    HotKeySet("{F8}")
    HotKeySet("{F9}")
    HotKeySet("{F10}")
    HotKeySet("{F11}")
    HotKeySet("{UP}")
    HotKeySet("{DOWN}")
    HotKeySet("{PGUP}")
    HotKeySet("{PGDN}")
endfunc

func OpenDataFolder()
    ShellExecute("Explorer.exe"$data_parent)
endfunc

func GoColorPickinChooser()
    DialogOpen()
    ColorPickinChooser("""""""CheckClockStuff")
    DialogClose()
endfunc

func CheckStartupLink()
    if $start_with_windows = $GUI_CHECKED then
        if not FileExists(@StartupDir & "\corz clock.lnk") then
            FileCreateShortcut(@ScriptFullPath, @StartupDir & "\corz clock.lnk""" , "startup" , _
                "A clock and a half! Multiple alarm presets, spoken alarms and chimes, colour schemes and much more!")
        endif
    else
        FileDelete(@StartupDir & "\corz clock.lnk")
    endif
endfunc


; save the width/height prefs..
;
func SaveXYPrefs()
    $size_array = WinGetPos($gui)
    if IsArray($size_array) then
        IniWrite($ini_path$my_shortname"x"$size_array[0])
        IniWrite($ini_path$my_shortname"y"$size_array[1])
    endif
    CheckStartupLink()
endfunc


func AltF4DoQuit()
    DoQuit()
endfunc

func DoQuit()
    SaveXYPrefs()
    FileDelete(@tempdir & "\clocktmp.wav"; just in case
    DllClose($gdi_dll; these are closed automatically, but it shouldn't hurt to do it manually here, too.
    DllClose($user32_dll)
    exit
endfunc

func RestartClock()
    SaveXYPrefs()
    if @Compiled = 1 then
        Run("""" & @ScriptFullPath & """" & " restart"; command line switch tells clock to not fade-in.
    else
        Run(FileGetShortName(@AutoItExe) & " " & """" & @ScriptFullPath & """" & " restart")
    endif
    exit(@AutoItPID) ; will try something later ;2do
endfunc

func OnAutoItExit()
    ; closing dll's in here can sometimes throw up an error (already closed automatically?).
    ; don't do it.
endfunc


#cs

    changes

    2.6

    *    The Vista work-around release.

        If you are running Vista, clock will give you the option to disable the
        color pickin chooser, and instead, you'll get the system color picker.

        This is a stop-gap measure until I can make the time to figure out how
        to disable desktop compositioning for the duration of the chooser's
        activity. The fix will probably be in cpc itself.

        I don't think the Vista GetPixel bug will ever be fixed, in fact, in all
        fairness to Microsoft, I don't believe it's a bug at all. On closer
        investigation, it turns out (I am so out of the OS hype-loop!) Vista
        uses a vector-based window manager, like Mac OS X (good!), and rendering
        all those layers as a bitmap is always gonna take time, no matter how
        brilliant your code is. In a tight loop, it's inevitable that this will
        equate to "a LOT of time".

        However, I do believe that the PixelGetColor() AutoIt manual page should
        fully detail this issue, and provide a working code example of how to
        disable/enable desktop compositioning, using dllcall + dwmapi.dll (I'm
        guessing), something I'm gonna have to figure out, when I get a chance -
        and I have a mental block with DLL calls, as it is!

        It would prolly take those clever AutoIt dudes SECONDS. Och well.


    2.5.2

    *    fixed a bug where dragging wav files onto alert inputs was saving only
        the basename of the wav, and not the entire path, so when you tried to
        play them, it would fail.


    2.5.1

    *    maintenance release - non-code improvements only.

        There are still issues with mag speed under Vista with Aero running - if
        you want to use the color chooser, you need to be running a classic or
        "standard" theme.


    2.5

    *    fixes to color pickin chooser incorporated into clock.


    2.4.8.1 - 2.4.8.3

    *    bugfixing vista troubles (in the dark!)
        fixed a couple of unchecked GetPos() commands

        only color chooser is causing issues now, I think.

        I'm now developing clock from the exact same folder that I put out as
        the source pack, so anything that works for me, should also work for
        you!


    2.4.8

        [first release]

#ce


; compiler directives..
;
#Region
; AutoIt3Wrapper settings..
#AutoIt3Wrapper_Icon = img\clock.ico
#AutoIt3Wrapper_Res_Icon_Add = img\icons\grad.ico
#AutoIt3Wrapper_Res_Icon_Add = img\icons\mag.ico
#AutoIt3Wrapper_Res_Icon_Add = img\icons\hex.ico
#AutoIt3Wrapper_Res_Icon_Add = img\chooser.ico
; free-form resource fields (max 15)..
#AutoIt3Wrapper_Res_Field = Author|(or
#AutoIt3Wrapper_Res_Field = Compiled|%date% - %time%
;  resource info..
#AutoIt3Wrapper_Res_Comment = initially developed from 'analog clock' by greenmachine, with bits by Larry, neogia, and Valuater. Many thanks.
#AutoIt3Wrapper_Res_Description = corz clock
#AutoIt3Wrapper_Res_Fileversion = 2.6
#EndRegion
back to the source menu
test

Welcome to corz.org!

I'm always messing around with the back-end.. See a bug? Wait a minute and try again. Still see a bug? Mail Me!