We make software for humans. Custom Mac, Windows, iOS and Android solutions in HyperCard, MetaCard, and RunRev LiveCode
Both the title card and the timer card of the Tech Support TimeSaver stack use an idle handler; in the first case to implement the repeated sound of a watch ticking, and in the second to update a timer display showing elapsed seconds. We will change both of these.
Go to the title card of the stack and open its card script. Delete or comment out the idle handler. Enter this handler in its place:
Now comment out the line in the openCard handler that sets the idleRate, and comment out or delete the entire closeCard handler as well. Insert the command doTicks just before the pass openCard command in the openCard handler. Finally, add a new closeCard handler:on doTicks play "Tick.rev" send "doTicks" to me in 1 second end doTicks
The entire script of the title card should now look like this (changes are in red):on closeCard repeat for each line l in the pendingmessages if "rev" is not in item 3 of l then cancel item 1 of l end repeat pass closeCard end closeCard
Close the script editor. If you leave the card and then return, you will hear a steady ticking about once per second. What did we do?on openCard global gShowDialog -- set the idleRate to 800 if gShowDialog is "Yes" then put "No" into gShowDialog -- play "Bell" answer "This program is $5 shareware." & return & return & \ "NOTICE: Do not distribute this stack except in its original," \ && "unaltered form as a HyperCard file. See the About card" && \ "for details." with "More Info" or "OK" if it is "More Info" then lock screen go next card set scroll of card field "Info" to 0 unlock screen with visual effect dissolve fast end if end if doTicks pass openCard end openCard
on doTicks play "Tick.rev" send "doTicks" to me in 1 second end doTicks
-- on idle play "Tick.rev" pass idle end idle
on closeCard repeat for each line l in the pendingmessages if "rev" is not in item 3 of l then cancel item 1 of l end repeat pass closeCard end closeCard
The doTicks handler simply plays the sound and then instructs itself to call its own handler name again 1 second later. The doTicks command we inserted into the openCard script is the trigger that starts the process initially; after that, doTicks repeats itself on its own. When the card is closed, the closeCard handler examines the pendingMessages, which is a list of messages that are queued up waiting to be sent, and it loops through the list, canceling each one that is not one of LiveCode's own internal messages. All of LiveCode's internal messages begin with "rev", and it is important to test for the existence of that string before a script cancels any pending message. If it doesn't, the stack will error whenever LiveCode's own handlers are running. The loop could optionally test for any other condition too, if there were several different handlers queueing up lots of different kinds of pending messages, but in this case our stack has only one type of pending message so we just cancel them all.
The advantage to using this approach instead of idle is that while pending messages are being sent and executed, LiveCode continues to be fully operational; the user has full control of the mouse and keyboard, other messages are sent normally, and there is no slowdown while the system waits for an idle handler to finish before moving on to the next task.
Go to the Timer2 card now and open its script. Change every instance of the word idle to checkTime. Delete the pass idle line in the idle script completely. Insert the line send checkTime to me in 200 milliseconds at the end of the checkTime handler, and insert the command checkTime just before the pass openCard command in the openCard handler.
In addition, add the same closeCard handler we used before so that all pending messages will be canceled when the user leaves the Timer card.
The revised card script looks like this:
Leave the card and return again to trigger the openCard handler. Then try the timer.on openCard global gTimerOpenOrClosed put "Open" into gTimerOpenOrClosed checkTime pass openCard end openCard
on checkTime global gStartTime,gTimerOn,gTemp get gTimerOn if it is empty then put "0:00" into card field "Elapsed Time" if it is "yes" then put (the seconds - gStartTime) into gTemp put gTemp div 60 into wholeMinutes put gTemp mod 60 into remainingSeconds if remainingSeconds < 10 then put "0" before remainingSeconds if wholeMinutes > 59 then put (wholeMinutes div 60) into wholeHours put (wholeMinutes mod 60) into wholeMinutes if wholeMinutes < 10 then put "0" before wholeMinutes put wholeHours &":"& wholeMinutes & ":" & remainingSeconds \ into card field "Elapsed Time" exit checkTime end if put wholeMinutes &":"& remainingSeconds into cd fld "Elapsed Time" end if send "checkTime" to me in 200 milliseconds end checkTime
on closeCard repeat for each line l in the pendingMessages if "rev" is not in item 3 of l then cancel item 1 of l end repeat end closeCard