Script Info

Name: Freeze/Thaw Group
Author: Five Speed Software
Description:
This script will freeze or thaw a group of packages. It takes a list of packages, and prompts the user whether to freeze or thaw them. This example works with a group of Internet-related apps, but it is easy to duplicate the script and create your own custom scripts that freeze or thaw the group of packages that you want. All you need to do is change the groupName variable to a name that describes your group, and change the pkgNameList array to contain a list of the package names for the packages you want to include in your group. (To get a list of package names of packages installed on your Newton, see the Get Package Names List script).
Last Modified: Tuesday, March 2, 1999
Download:   The example scripts are now included as part of every Dash Board download.


This example script is copyright © 1998, 1999 by the author listed above, and may be freely used, modified, and distributed, provided that it is distributed free of charge.

Script Code

local groupName := "Internet Apps";




local pkgNameList :=
    [
        //add package names one per line
        //enclosed in quotes and
        //separated by commas
        "Newton Internet Enabler",
        "NIE Ethernet Module",
        "NIE LocalTalk Module",
        "NIE Modem & Serial Module",
        "NetHopper:ALLPEN",
        "NewtFTP Prefs",
        "NewtFTP Transport:Tactile",
        "NewtFTP:Tactile",
        "NewtFTPConnection:Tactile",
        "Email:QUALCOMM",
        "EnRoute  Core",
        "EudoraMail:QUALCOMM",
        "PT100:Scrawl",
        "inet Text Encoding",
        "InkSpot:DejaVu",
        "Internet Setup"        
    ];
    
local extrasWasOpen;
if GetRoot().extrasDrawer.viewCObject then
    begin
        extrasWasOpen := TRUE;
        GetRoot().extrasDrawer:Close();
    end
else
    extrasWasOpen := NIL;
    
local freezeOrThaw := ModalConfirm("Do you want to freeze all of the programs in the \"" & groupName & 
    "\" group, or thaw them?", ["Freeze", "Thaw", "Cancel"]);

local statusMessage;
if freezeOrThaw = 0 then
    statusMessage := "Freezing " & groupName & " Packages..."
else if freezeOrThaw = 1 then
    statusMessage := "Thawing " & groupName & " Packages..."
else if freezeOrThaw = 2 then
    return NIL;  //quit right here because user cancelled
    
local currentPkgRef;
local gaugeNow := 0;    
local gaugeTotal := Length(pkgNameList) * Length(GetStores());
local incrementAmt := 100 / gaugeTotal;
    
local statusSlipOptions := 
    {
        closebox: NIL,
        gauge: 0,
        statusText: statusMessage,
    };
    
local workFunction := func(statusSlip)
    begin
        foreach store in GetStores() do
            begin
                foreach pkgName in pkgNameList do
                    begin
                        currentPkgRef := GetPkgRef(pkgName, store);
                        if freezeOrThaw = 0 then  //then we should freeze
                            begin
                                if currentPkgRef and IsPackageActive(currentPkgRef) then
                                    SafeFreezePackage(currentPkgRef);
                            end
                        else if freezeOrThaw = 1 then //then we should thaw
                            begin
                                if currentPkgRef and not IsPackageActive(currentPkgRef) then
                                    ThawPackage(currentPkgRef);
                            end;
                        gaugeNow := Floor(gaugeNow + incrementAmt);
                        statusSlip:SetStatus('vGauge, {kind: 'vGauge, gauge: gaugeNow, statusText: statusMessage, titleText: pkgName});
                    end;
            
            end;
    end;
    
DoProgress('vGauge, statusSlipOptions, workFunction);
if extrasWasOpen then GetRoot().extrasDrawer:Open();

Discussion

The first line just names the group of packages that this script operates on. This name is used when prompting the user. The following line of code sets the groupName variable to the text string "Internet Apps".

local groupName := "Internet Apps";

Next we set the pkgNameList variable to an array of package names. Package names are the unique names for packages used by the system, NOT the name you see in the Extras Drawer (though in some cases they may be the same). To get a list of packages names for the packages installed on your Newton device, use the Get Package Names List script. You should customize the list to match the packages you want your version of this script to freeze or thaw. Enclose the package names in quotes, separate them by commas, and put one on each line for easier readability. The following code creates an array containing package names for the group of packages that this script will work on.

local pkgNameList :=
    [
        //add package names one per line
        //enclosed in quotes and
        //separated by commas
        "Newton Internet Enabler",
        "NIE Ethernet Module",
        "NIE LocalTalk Module",
        "NIE Modem & Serial Module",
        "NetHopper:ALLPEN",
        "NewtFTP Prefs",
        "NewtFTP Transport:Tactile",
        "NewtFTP:Tactile",
        "NewtFTPConnection:Tactile",
        "Email:QUALCOMM",
        "EnRoute  Core",
        "EudoraMail:QUALCOMM",
        "PT100:Scrawl",
        "inet Text Encoding",
        "InkSpot:DejaVu",
        "Internet Setup"        
    ];

Next, we declare a new variable, extrasWasOpen. We are going to close the Extras Drawer, because it slows down our script by updating the icons one at a time, and also uses a fairly hefty chunk of memory. Closing it makes our script run faster and decreases the risk that we might run out of memory on a 1MB MP2000 machine. However, if the Extras Drawer is open when we start our script, it is only polite to reopen it for the user when our script finishes. So the following code checks if the Extras Drawer is open. If it is, we set the extrasWasOpen variable to TRUE and then close it, otherwise we set it to NIL. We'll check this variable at the end of our script.

local extrasWasOpen;
if GetRoot().extrasDrawer.viewCObject then
    begin
        extrasWasOpen := TRUE;
        GetRoot().extrasDrawer:Close();
    end
else
    extrasWasOpen := NIL;

Next, we ask the user what to do. The choices are Freeze, Thaw, or Cancel. We set the value of a new variable, freezeOrThaw, to the user's response. We use the ModalConfirm() global function to ask the user. This function presents a modal dialog to the user, with buttons. The first parameter is the message shown to the user. The second parameter is an array of text strings. Each string in this array will be the title of a button in the dialog. The ModalConfirm() function will return the index number of the button chosen (starting with 0 as the first). We will set the freezeOrThaw variable to this number, so that our script knows what to do later.

local freezeOrThaw := ModalConfirm("Do you want to freeze all of the programs in the \"" & groupName & 
    "\" group, or thaw them?", ["Freeze", "Thaw", "Cancel"]);

Now freezeOrThaw is set to the index number of the button that the user tapped. If it is 0, we should freeze. If it is 1, we should thaw. And if it is 2, that means the user tapped "Cancel", so we should stop the script. Since we are going to show the user a progress dialog, we also want to set a text string to tell the user what is happening. So we declare a new variable, statusMessage. Then check the value of the freezeOrThaw variable, and set the value of statusMessage accordingly. If freezeOrThaw is 2, however, the user tapped Cancel so we use the return keyword to return right here and stop the script.

local statusMessage;
if freezeOrThaw = 0 then
    statusMessage := "Freezing " & groupName & " Packages..."
else if freezeOrThaw = 1 then
    statusMessage := "Thawing " & groupName & " Packages..."
else if freezeOrThaw = 2 then
    return NIL;  //quit right here because user cancelled

Next, we want to set a couple variables that will help us display accurate progress info to the user. The currentPkgRef variable will be used later; we just declare it now. The gaugeNow variable will be used to track the current percentage complete, to set the progress gauge. The gaugeTotal variable is the number of package names to check, times the number of stores available. This is because we check each store for each package. The incrementAmt variable is set to the amount we should increment the gauge for each package we check. Since the gauge display is percentage based, we divide 100 by the number of package names we will check. This yields the amount we should update the gauge for each package name we check.

local currentPkgRef;
local gaugeNow := 0;    
local gaugeTotal := Length(pkgNameList) * Length(GetStores());
local incrementAmt := 100 / gaugeTotal;

Next we create an options frame to control how our progress slip looks. We are going to use the global function DoProgress() to generate a standard progress slip. This function takes a frame of options as one of its parameters. We create that frame now.

local statusSlipOptions := 
    {
        closebox: NIL,
        gauge: 0,
        statusText: statusMessage,
    };

The next part is the heart of our script. The other parameter to the DoProgress() function is a function object. This function object is the function that will be executed while the progress slip is displayed. The function has one parameter, which is the status slip view itself. The following code creates a function object which goes through our list of package names, once for each store. For each package name, it gets a reference to the package (using the GetPkgRef() global function) and then it checks if the package is active (using the IsPackageActive() global function). It then checks the value of the freezeOrThaw variable we set before, and if necessary, freezes or thaws the package, as appropriate. At the end of the loop, once for each package, it updates the value of the gaugeNow variable, setting it to the current percent complete. Then we send the SetStatus() message to our progress slip to update the display. Note that we must use the Floor() global function to make sure that we get an integer number (no decimals), because that is what the SetStatus() method requires. (The Newton Programmer's Reference has more information on using the DoProgress() global function.)

local workFunction := func(statusSlip)
    begin
        foreach store in GetStores() do
            begin
                foreach pkgName in pkgNameList do
                    begin
                        currentPkgRef := GetPkgRef(pkgName, store);
                        if freezeOrThaw = 0 then  //then we should freeze
                            begin
                                if currentPkgRef and IsPackageActive(currentPkgRef) then
                                    SafeFreezePackage(currentPkgRef);
                            end
                        else if freezeOrThaw = 1 then //then we should thaw
                            begin
                                if currentPkgRef and not IsPackageActive(currentPkgRef) then
                                    ThawPackage(currentPkgRef);
                            end;
                        gaugeNow := Floor(gaugeNow + incrementAmt);
                        statusSlip:SetStatus('vGauge, {kind: 'vGauge, gauge: gaugeNow, statusText: statusMessage, titleText: pkgName});
                    end;
            
            end;
    end;

Now that we have set everything up, it is time to call the DoProgress() global function, with the options and function object that we have created. The DoProgress() function displays the progress slip, and executes the workFunction function object that we created above.

DoProgress('vGauge, statusSlipOptions, workFunction);

Now we are done! The only thing left to do is check the value of the extrasWasOpen variable. If it is set to TRUE, that means that the Extras Drawer was open, and so we should open it up again for the user.

if extrasWasOpen then GetRoot().extrasDrawer:Open();

And that is the end of our script.

 


Contents copyright © 1997-2004, Five Speed Software, Inc.