Password.c

/*
    File:       Password.c
 
    Contains:   This file contains all the interesting password stuff
 
    Written by: Tim Dierks  
 
    Copyright:  Copyright © 1991-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                8/9/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
 
#include <Types.h>
#include <Memory.h>
#include <Resources.h>
#include <OSUtils.h>
#include <Quickdraw.h>
#include <Fonts.h>
#include <Events.h>
#include <OSEvents.h>
#include <Windows.h>
#include <Menus.h>
#include <Dialogs.h>
#include <TextEdit.h>
 
#include "Sample.h"
#include "Password.h"
 
void DisplayPassword (ConstStr255Param password)
{   DialogPtr   dlog;
    short       item;
    //short     rDisplayPasswordDialog;
    
    dlog = GetNewDialog(rDisplayPasswordDialog,0L,(WindowPtr) -1L);
    
    ParamText((ConstStr255Param)password,0L,0L,0L);
    
    do
    {   ModalDialog(0L,&item);
    } while (item != 1);            // Until the OK button gets hit
    
    DisposeDialog(dlog);
}
 
void TwoItemDialog (StringPtr password)
{
    DialogPtr       dlog;
    Handle          itemH;
    ControlHandle   chkBox;
    short           item,itemType,chkVal;
    Rect            box;
    Point           size;
 
    static ModalFilterUPP twoItemFilterUPP;
    
    /* set up a UPP for the dialog filter */
 
    if (!twoItemFilterUPP)
        twoItemFilterUPP = NewModalFilterProc(TwoItemFilter);
    
    dlog = GetNewDialog(rTwoItemDialog,0L,(WindowPtr) -1L);
    
    if (dlog)
    {
        do
        {   ModalDialog(twoItemFilterUPP,&item);
            if (item == 4)                                          // Hide/show checkbox
            {   GetDialogItem(dlog,4,&itemType,(Handle*)&chkBox,&box);  // Get check value
                chkVal = !GetControlValue(chkBox);
                SetControlValue(chkBox,chkVal);                         // Invert it
                size.v = dlog->portRect.bottom - dlog->portRect.top;
                size.h = dlog->portRect.right - dlog->portRect.left;
                if (chkVal)
                    size.v += 35;
                else
                    size.v -= 35;
                
                SizeWindow(dlog,size.h,size.v,true);        // Resize window
            }
        } while (item != 1);            // Until the OK button is hit
    
        GetDialogItem(dlog,3,&itemType,&itemH,&box);        // Get text from hidden dialog item
        GetDialogItemText(itemH, password);
        
        DisposeDialog(dlog);
    }
}
 
pascal Boolean
TwoItemFilter(DialogPtr dlog,EventRecord *event,short *itemHit)
{   DialogPtr   evtDlog;
    short       selStart,selEnd;
    
    if (event->what == keyDown || event->what == autoKey)
    {   switch (event->message & charCodeMask)
        {   case '\n':          // Return  (hitting return or enter is the same as hitting the OK button)
            case '\003':        // Enter
                *itemHit = 1;       // OK Button
                return true;        // We handled the event
            case '\t':          // Tab
                event->what = nullEvent;    // Do nothing (don't let the user tab to the hidden field)
                return false;
            case '\034':        // Left arrow  (Keys that just change the selection)
            case '\035':        // Right arrow
            case '\036':        // Up arrow
            case '\037':        // Down arrow
                return false;           // Let ModalDialog handle them
            default:
                selStart = (**((DialogPeek)dlog)->textH).selStart;      // Get the selection in the visible item
                selEnd = (**((DialogPeek)dlog)->textH).selEnd;
                SelectDialogItemText(dlog,3,selStart,selEnd);               // Select text in invisible item
                DialogSelect(event,&evtDlog,itemHit);           // Input key
                SelectDialogItemText(dlog,2,selStart,selEnd);               // Select same area in visible item
                if ((event->message & charCodeMask) != '\010')  // If it's not a backspace (backspace is the only key that can affect both the text and the selection- thus we need to process it in both fields, but not change it for the hidden field.
                    event->message = '¥';                       // Replace with character to use
                DialogSelect(event,&evtDlog,itemHit);           // Put in fake character
                return true;
        }
    }
    
    return false;           // For all non-keyDown events
}
 
void DifferentFontDialog (StringPtr password)
{
    DialogPtr       dlog;
    Handle          itemH;
    short           item,itemType,font;
    Rect            box;
    UserItemUPP     chicagoTextItemUPP;
    //short             rDifferentFontDialog;
    
    /* create the UPP for our ChicagoTextItem userItem */
    chicagoTextItemUPP = NewUserItemProc(ChicagoTextItem);
    
    GetFNum("\p.Pwd",&font);        // Get the font number for our password font (it begins with a period, so AppendResMenu won't add it)
    SetDialogFont(font);                // Use this font for static and edit text items in further dialogs
    
    dlog = GetNewDialog(rDifferentFontDialog,0L,(WindowPtr) -1L);
    
    GetDialogItem(dlog,3,&itemType,&itemH,&box);            // Because SetDialogFont affects static items, too, we've got to use user items to draw our prompts
    SetDialogItem(dlog,3,itemType,(Handle)chicagoTextItemUPP,&box);
    GetDialogItem(dlog,4,&itemType,&itemH,&box);
    SetDialogItem(dlog,4,itemType,(Handle)chicagoTextItemUPP,&box);
    
    do
    {   ModalDialog(0L,&item);
    } while (item != 1);            // Until the OK button is hit
    
    GetDialogItem(dlog,2,&itemType,&itemH,&box);        // Get text from TE item
    GetDialogItemText(itemH, password);
    
    DisposeDialog(dlog);
    
    SetDialogFont(0);       // Set the dialog font back to the System font
    
    DisposeRoutineDescriptor(chicagoTextItemUPP);
}
 
pascal void
ChicagoTextItem(WindowPtr wind,short item)
{   short       fontStore,sizeStore;
    Handle      itemH;
    short       itemType;
    Rect        box;
    char        *text;
    
    SetPort(wind);
    
    fontStore = wind->txFont;   // Remember the current font & size
    sizeStore = wind->txSize;
    
    TextFont(0);        // Set to default System font & size
    TextSize(0);
    
    GetDialogItem(wind,item,&itemType,&itemH,&box);
    
    if (item == 3)          // These strings would probably be in a resource or somesuch in an actual program.
        (ConstStr255Param) text = "\pPlease enter your password:";
    if (item == 4)
        (ConstStr255Param) text = "\pSpecial Font Password Dialog";
    
    TETextBox(text+1,*text,&box,teJustLeft);    // Draw the prompt
    
    TextFont(fontStore);        // Restore the font & size
    TextSize(sizeStore);
}
 
void InternalBufferDialog (StringPtr password)
{
    DialogPtr       dlog;
    short           item;
    ModalFilterUPP  internalBufferFilterUPP;
    //short         rInternalBufferDialog;
    
    /* create the UPP for the InternalBufferFilter */
    internalBufferFilterUPP = NewModalFilterProc(InternalBufferFilter);
    
    dlog = GetNewDialog(rInternalBufferDialog,0L,(WindowPtr) -1L);
    
    *password = '\0';                   // Zero out the buffered password
    SetWRefCon(dlog,(long)password);    // Stash the buffer's address
    
    do
    {   ModalDialog(internalBufferFilterUPP,&item);
    } while (item != 1);            // Until the OK button is hit
    
    DisposeDialog(dlog);
    
    DisposeRoutineDescriptor(internalBufferFilterUPP);
}
 
pascal Boolean
InternalBufferFilter(DialogPtr dlog,EventRecord *event,short *itemHit)
{   char    key;
    short   start,end;
    char    *buffer;
    
    if (event->what != keyDown && event->what != autoKey)
        return false;               // We don't want to deal with them
    
    key = event->message & charCodeMask;
    
    switch (key)
    {   case '\n':          // Return
        case '\003':        // Enter
            *itemHit = 1;       // OK Button
            return true;        // We handled the event
        case '\t':          // Tab
        case '\034':        // Left arrow
        case '\035':        // Right arrow
        case '\036':        // Up arrow
        case '\037':        // Down arrow
            return false;       // Let ModalDialog handle them
        default:            // Everything else falls through to be dealt with
            break;          //  below
    }
    
    start = (**((DialogPeek)dlog)->textH).selStart; // Get the current selection
    end = (**((DialogPeek)dlog)->textH).selEnd;
    
    buffer = (char*)GetWRefCon(dlog);       // Get the buffer's address
    
    if (start != end)                   // If there's a selection, delete it
        DeleteRange(buffer,start,end);
    
    if (key == '\010')  // Backspace
    {   if (start != 0)
            DeleteRange(buffer,start-1,start);  // Delete the character to the left
    }
    else
    {   InsertChar(buffer,start,key);       // Insert the real key into the buffer
        event->message = '*';               // Character to use in field
    }
    
    return false;       // Let ModalDialog insert the fake char
}
 
void
DeleteRange(char *buffer,short start,short end)
{   register char   *src,*dest,*last;
    
    last = buffer + *buffer;
    
    src = buffer + end + 1;
    dest = buffer + start + 1;
    
    while (src <= last)         // Shift character to the left over the removed characters
        *(dest++) = *(src++);
    
    (*buffer) -= (end-start);   // Adjust the buffer's length
}
 
void
InsertChar(char *buffer,short pos,char c)
{   register short  index,len;
    
    len = *buffer;
    
    if (len == 0xFF)        // if the string is full, return
        return;
    
    for (index = len;index > pos;index--)   // Shift characters to the right to make room
        buffer[index+1] = buffer[index];
    
    buffer[pos+1] = c;      // Fill in the new character
    
    (*buffer)++;            // Add one to the length of the string
}