Byte Works / Ordering / Apple IIGS / Apple ][ / APDA / HyperStudio / Books / System Software
This stack shows a simple password protection dialog.
The dialog has several cool features.
Copyright 2000, Byte Works, Inc.
You may read or print this page for your own use in any way you like, but it cannot be reproduced for anything except your personal use without the written permission of the publisher. Please feel free to point other people to this resource so they can get their own copy!
The stacks and scripts that accompany this project are public domain. You may use the scripts any way you like, including using them in your own HyperStudio projects.
Download the Stack
Uses
Use this dialog to make sure the stack user is really authorized to use the stack!
Please keep in mind that this is a relatively simple mechanism. It is great for casual protection, say the level of protection of a suitcase lock, but it can be broken easily by anyone who has a good knowledge of HyperStudio.
The script in this stack uses the following commands:
CHAR DOALERT HIDEITEM IF LOCAL LOCKSCREEN MAKE NOT OUTPUT QUIT REPEAT SETFIELDTEXT SHOWITEM STOP TO WHILE UNLOCKSCREEN UPPERCASE
You will see how these commands are used while working throughout the project. It will also be helpful to refer to the HyperLogo Reference Manual for detailed descriptions of these commands.
We'll use the same technique to examine this script that was used to write it: A top down approach. This technique starts with an overall view of the task. Major ideas are placed in procedures, which are written after the overall ideas are in place.
The task at hand is to enter a password. This process starts by creating the visual elements of the password dialog. The sample stack uses four elements:
The completed dialog looks like this:

The graphic used for the dialog's outline is named DialogBox. The three text items, from top to bottom, are named Instructions, PasswordCaption and Password.
The script itself is a series of procedures. The topmost procedure is EnterPassword, and that's the procedure that the script actually calls to do all of the work.
TO EnterPassword ; Enter and check a password Local "ch ShowPasswordDialog Make "password '' Make "ch ReadChar While not DoneChar :ch [UseCh :ch Make "ch ReadChar] CheckPassword END EnterPassword
The first step is to define a local variable called ch to hold the characters we read from the keyboard. While it isn't required in Logo, we always group local variable declarations at the top of the procedure where they are easy to find.
The procedure itself starts by showing the password dialog. This is a multistep procedure, so we'll just create a procedure to do the work and deal with it later. Next we set up two variables. The variable password is a global variable that will hold the password the user types. ch is used to hold the characters actually typed; we fill in an initial value using READCHAR.
The next line is the real meat of the procedure. The WHILE loop checks the current character to see if it indicates that the password has been completely typed. The work is done by a function named DoneChar that we'll define later. DoneChar needs the character to check, so we pass that as a parameter. Inside the loop, UseCh is another procedure that takes the character typed and does whatever we need done with the character; once again, that's a detail we'll leave for later. Finally, once we've processed the character, we read a new one.
After the password is entered, we have one last step: checking to make sure the password is correct. We'll defer the details to another procedure, CheckPassword.
With the main logic of the script in place, it's time to go back and fill in the details. We'll start with DoneChar, one of the two procedures that form the nuts and bolts of the main loop in EnterPassword.
TO DoneChar :ch ; Check to see if the user pressed the enter key. Output :ch = char 13 END
This is a pretty simple procedure. It returns TRUE if the enter (or return) key was pressed, and false for any other key. It works because the numeric value for the enter key is 13; CHAR is a Logo function that takes a number and returns the equivalent character.
It might seem odd to use a procedure in this situation, since we're really only executing a single line. In fact, we get two very important benefits from using a procedure here. First, by moving the check to a procedure, we're able to use a meaningful name for the operation in EnterPassword, making the main program easier to understand. At some point we hay want to add other characters, too, like the esc key. Placing the check in a procedure makes it easy to add additional characters without effecting the rest of the script.
UseCh is the procedure that actually processes a password character.
TO UseCh :ch ; Add a password character to the password. Local "display Make "password Word :password :ch Make "display '' Repeat Count :password [Make "display Word :display '*'] SetFieldText [] "Password :display END
One of the goals for our password entry program is to have it display an asterisk rather than the character actually typed. READCHAR just reads the character typed on the keyboard without displaying it, so we're halfway there. To display the character, we'll build a Logo word containing the right number of asterisk characters and place this word in the text field named Password. Note that this field, like all of them in our dialog, is a read-only field. The stack user can't type anything in the field even if they want to! The first line of the script defines a variable named display to hold the Logo word containing the asterisks.
The line
Make "password Word :password :ch
adds the character in ch to the old contents of password, building the password character by character as UseCh is called. The next two lines place one asterisk in the variable display for each character in the variable password. The last line puts the asterisks into the text field. The net effect is that the stack user sees one more asterisk each time he types a character.
We left the job of checking the password to the procedure CheckPassword.
TO CheckPassword ; See if the password is correct; quit if not. if (Uppercase :password) = 'ADDY' [HidePasswordDialog Stop] Ignore DoAlert 3 "Stop 'The password you entered is not correct. The program will now stop.' "^OK Quit END
The condition on the IF statement is
(Uppercase :password) = 'ADDY'
This condition converts the password typed to uppercase letters, then compares the result to the password string--in this case, ADDY. You can change the password to anything you like, of course.
The parenthesis are very important. Without them, the = compare has precedence. The operation would start by comparing the contents of the variable password to the word ADDY, then convert the result, which would be TRUE or FALSE, to uppercase. That's not even close to what we want!
If the password is, indeed, ADDY, CheckPassword does two things. First is calls yet another procedure we'll have to define; this one is named HidePasswordDialog. It is similar to its cousin ShowPasswordDialog that we used earlier in EnterPassword, but HidePasswordDialog hides all of the visual elements we used in the password dialog. The next step is to use STOP, a Logo command that stops the procedure. That means the rest of the procedure won't be executed if the password is correct.
If the password is not correct, the next two lines are executed. The first displays an alert telling the user they goofed and informing them of the consequences. The next line carries out the consequences. It uses Logo's QUIT command to exit HyperStudio.
DOALERT always returns a value. It returns the number of the button that the user selected. In this case we don't care; there is only one button anyway. We'll use a short procedure called Ignore that takes a parameter and does nothing with it. It's a handy way to get rid of the unneeded value returned by DOALERT.
TO Ignore :stuff ; Ignore a value returned by a function. END
The two remaining procedures are HidePasswordDialog and ShowPasswordDialog.
TO HidePasswordDialog ; Hide the password dialog. LockScreen HideItem [] "Password "text HideItem [] "PasswordCaption "text HideItem [] "Instructions "text HideItem [] "DialogBox "graphic UnlockScreen END TO ShowPasswordDialog ; Hide the password dialog. LockScreen ShowItem [] "Password "text ShowItem [] "PasswordCaption "text ShowItem [] "Instructions "text ShowItem [] "DialogBox "graphic SetFieldText [] "Password '' UnlockScreen END
Each starts with LOCKSCREEN, which tells HyperStudio to stop updating the card while we hide or show more than one object. It can take quite a while to redraw a complicated card, and the card is normally redrawn for every HIDEITEM or SHOWITEM command. LOCKSCREEN stops this process so we don't have to watch the card redraw four times. Next comes the hide or show commands to actually do the work, followed by UNLOCKSCREEN. UNLOCKSCREEN tells HyperStudio to start updating the card in the normal way, and also tells it to redraw the card once to show all the changes we made.
You may want to add an audible beep if the user selects an incorrect password. One way to do this is to add a TOOT command to the CheckPassword procedure, like this:
TO CheckPassword ; See if the password is correct; quit if not. if (Uppercase :password) = 'ADDY' [HidePasswordDialog Stop] Toot 60 60 Ignore DoAlert 3 "Stop 'The password you entered is not correct. The program will now stop.' "^OK Quit END
This routine is rather draconian: If the password is typed incorrectly, it stops HyperStudio. You could allow the user to try as many times as they like by changing the DOALERT call to display two buttons, and to take further action based on the result, like this:
TO CheckPassword ; See if the password is correct; quit if not. Local "button if (Uppercase :password) = 'ADDY' [HidePasswordDialog Stop] Make "button DoAlert 3 "Stop 'The password you entered is not correct.' [Try\ Again ^Quit] if :button = 1 [Quit] EnterPassword END