RamCDev.c

#define __DebugVersion  0
/*
**  Apple Macintosh Developer Technical Support
**
**  RamCDev.c: Ram Disk Control Panel code
**
**  by Gordon Sheridan and Jim Luther
**  modified incessantly by Brian Bechtel
**  and even more so by Quinn "The Eskimo!"
**
**  File:       RamCDev.c
**
**  Copyright © 1992-1996 Apple Computer, Inc.
**  All rights reserved.
**
**  You may incorporate this sample code into your applications without
**  restriction, though the sample code has been provided "AS IS" and the
**  responsibility for its operation is 100% yours.  However, what you are
**  not permitted to do is to redistribute the source as "DTS Sample 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 Code, but that you've made changes.
**
**  Change History (most recent first):
**
**  Change History (most recent first):
**
**      <1.4>   19970207    Quinn   Reworked to use new file layout and bring generally
**                                  up-to-date.
**       <3>     06/10/94   BL¡B    Converted to work with Metrowerks & Symantec
**       <2>     6/13/93    gs      Additional Cleanup
**       <1>     6/13/93    gs      Clean up format.
**      <0+>     10/2/92    gs      Clean up format.
**/
 
#ifdef __MWERKS__
#include <A4Stuff.h>
#endif
#ifdef THINK_C
#include <SetupA4.h>
#endif
 
#include <LowMem.h>
#include <Resources.h>
#include <TextUtils.h>
 
#include "RamDiskCommon.h"
 
///////////////////////////////////////////////////////////////////////////
 
typedef struct
{
    ConfigRecHandle config;
    DialogPtr       dlgPtr;
    short           dlgItems;
    long            sizepos;
    long            cursize;
    long            maxsize;
    PicHandle       sizePict;
    Str15           curStr;
    Str15           maxStr;
} RDataStorage, *RDataPtr, **RDataHdl;
 
 
///////////////////////////////////////////////////////////////////////////
//
// Resource IDs
 
 
enum{
    // DITL
    // cdev's always have the same DITL ID, namely -4064
        iCheckBox = 1, 
        iEditText, 
        iSizeBar, 
        iPict, 
        iMaxSize, 
        iCurSize,
    
    // PICT
    rCDevSizeBarPICT = -4034
};
 
///////////////////////////////////////////////////////////////////////////
//
// Simple dialog utilites
 
static Handle IGetHand(RDataHdl cdevGlobalsHdl, short item)
{
    Handle  itemHand;
    Rect    itemRect;
    short   itemType;
    
    GetDialogItem( (**cdevGlobalsHdl).dlgPtr, item + (**cdevGlobalsHdl).dlgItems,
                &itemType, &itemHand, &itemRect);
    return itemHand;
}
 
static void IGetRect(RDataHdl cdevGlobalsHdl, short item, Rect *itemRect)
{
    short   itemType;
    Handle  itemHand;
    
    GetDialogItem( (**cdevGlobalsHdl).dlgPtr, item + (**cdevGlobalsHdl).dlgItems,
                &itemType, &itemHand, itemRect);
}
 
///////////////////////////////////////////////////////////////////////////
 
static short UpdateSysz(ConfigRecHandle config)
{
    Handle  sysz;
    short   err = 0;
    
    sysz = Get1Resource ('sysz', 0);
    if (sysz == nil)
    {
        err = ResError();
        if (err == resNotFound || err == 0) // then make a new one
        {
            sysz = NewHandle(sizeof(long));
            if (sysz == nil)
                return -1;
            
            **(long **)sysz = 0;
                
            AddResource(sysz, 'sysz', 0, "\p");
            err =  ResError();
            if (err)
                return err;
        }
        else
            DebugStr("\pGet1Resource('sysz',0) returned nil...");
    }
    
    if ( (**config).install)
        **(long **)sysz = (16 + (**config).size) * 1024;
    else
        **(long **)sysz = 16 * 1024;
    ChangedResource(sysz);
    WriteResource(sysz);
    ReleaseResource(sysz);
    
    return err;
}
 
///////////////////////////////////////////////////////////////////////////
 
static RDataHdl  DoInit(DialogPtr CPDialog, short numItems)
{
    short   err;
    Rect    r;
    short   height;
    long    myBufPtr;
    
    RDataHdl    cdevGlobalsHdl = (RDataHdl)NewHandle(sizeof(RDataStorage));
    if (cdevGlobalsHdl == nil)  return cdevGlobalsHdl;
 
    HLock((Handle)cdevGlobalsHdl);
    (**cdevGlobalsHdl).config   = (ConfigRecHandle)Get1Resource ('RDcf', 0);
    err = ResError();
    if ((**cdevGlobalsHdl).config == nil)
    {
        if (err == resNotFound || err == 0) // then make a new one
        {
            (**cdevGlobalsHdl).config = (ConfigRecHandle)NewHandle(sizeof(ConfigRec));
            // check config
            (**(**cdevGlobalsHdl).config).install = false;
            (**(**cdevGlobalsHdl).config).size   = 0;
            GetIndString((**(**cdevGlobalsHdl).config).volumeName, rStringList, strDefaultNameStr);
            if (ResError() != noErr)
                BlockMoveData("\pRamDisk",(**(**cdevGlobalsHdl).config).volumeName,8);
            AddResource((Handle)(**cdevGlobalsHdl).config, 'RDcf', 0, "\p");
            // check ResError();
        }
        else
            DebugStr("\pGet1Resource('RDcf',0) returned nil...");
    }
    HLock((Handle)(**cdevGlobalsHdl).config);
 
    (**cdevGlobalsHdl).dlgPtr   = CPDialog;
    (**cdevGlobalsHdl).dlgItems = numItems;
 
    // initialize with config rsrc
    SetControlValue((ControlHandle)IGetHand(cdevGlobalsHdl,iCheckBox),
                (**(**cdevGlobalsHdl).config).install);
    (**cdevGlobalsHdl).cursize = (**(**cdevGlobalsHdl).config).size;
    SetDialogItemText(IGetHand(cdevGlobalsHdl,iEditText),(**(**cdevGlobalsHdl).config).volumeName);
    SelectDialogItemText(CPDialog, numItems + iEditText, 0, 999); /* make caret show up */
 
    myBufPtr = (long)LMGetBufPtr();
    (**cdevGlobalsHdl).maxsize  = ( myBufPtr / (1024L*1024L)) * 1024L;
    if ((**cdevGlobalsHdl).maxsize < 0) (**cdevGlobalsHdl).maxsize = 0;
    NumToString((**cdevGlobalsHdl).maxsize,(**cdevGlobalsHdl).maxStr);
    (**cdevGlobalsHdl).maxStr[++(**cdevGlobalsHdl).maxStr[0]] = 'K';
    
    NumToString((**cdevGlobalsHdl).cursize,(**cdevGlobalsHdl).curStr);
    (**cdevGlobalsHdl).curStr[++(**cdevGlobalsHdl).curStr[0]] = 'K';
 
    IGetRect(cdevGlobalsHdl, iSizeBar, &r);
    height = r.bottom - r.top - 4;
    (**cdevGlobalsHdl).sizepos  = 
        (**cdevGlobalsHdl).cursize/(double)(**cdevGlobalsHdl).maxsize * height;
 
    (**cdevGlobalsHdl).sizePict = GetPicture (rCDevSizeBarPICT);
    if ((**cdevGlobalsHdl).sizePict == nil)
        DebugStr("\pGetPicture returned nil!");
        
    HUnlock((Handle)(**cdevGlobalsHdl).config);
    HUnlock((Handle)cdevGlobalsHdl);
    
    return cdevGlobalsHdl;
}
 
///////////////////////////////////////////////////////////////////////////
 
static RDataHdl DoNul(RDataHdl cdevGlobalsHdl)
{
    HLock((Handle)cdevGlobalsHdl);
    HLock((Handle)(**cdevGlobalsHdl).config);
 
    (**(**cdevGlobalsHdl).config).install = 
            GetControlValue((ControlHandle)IGetHand(cdevGlobalsHdl,iCheckBox));
    
    (**(**cdevGlobalsHdl).config).size = (**cdevGlobalsHdl).cursize;
 
    GetDialogItemText( IGetHand(cdevGlobalsHdl,iEditText),
            (**(**cdevGlobalsHdl).config).volumeName);
 
    HUnlock((Handle)(**cdevGlobalsHdl).config);
    HUnlock((Handle)cdevGlobalsHdl);
    
    return cdevGlobalsHdl;
}
 
///////////////////////////////////////////////////////////////////////////
 
static void DrawItem(RDataHdl cdevGlobalsHdl, short item)
{
    Rect        itemRect,r;
    long        len;
    RgnHandle   rgn = NewRgn();
    
    IGetRect(cdevGlobalsHdl, item, &itemRect);
    SetPort( (**cdevGlobalsHdl).dlgPtr);
    GetClip(rgn);
 
    TextMode(srcCopy);
 
    switch(item)
    {
        case iSizeBar:
            r = itemRect;
            FrameRect(&r);
            r.bottom = r.bottom - (**cdevGlobalsHdl).sizepos;
            ClipRect(&r);
            DrawPicture((**cdevGlobalsHdl).sizePict,&itemRect);
            SetClip(rgn);
            InsetRect(&itemRect,2,2);
            itemRect.top = itemRect.bottom - (**cdevGlobalsHdl).sizepos;
            PaintRect(&itemRect);
            break;
        case iMaxSize:
            NumToString((**cdevGlobalsHdl).maxsize,(**cdevGlobalsHdl).maxStr);
            (**cdevGlobalsHdl).maxStr[++(**cdevGlobalsHdl).maxStr[0]] = 'K';
            len = (**cdevGlobalsHdl).maxStr[0];
            TETextBox (&(**cdevGlobalsHdl).maxStr[1], len, &itemRect, teJustRight);                     
            break;
        case iCurSize:  
            NumToString((**cdevGlobalsHdl).cursize,(**cdevGlobalsHdl).curStr);
            (**cdevGlobalsHdl).curStr[++(**cdevGlobalsHdl).curStr[0]] = 'K';
            len = (**cdevGlobalsHdl).curStr[0];
            TETextBox (&(**cdevGlobalsHdl).curStr[1], len, &itemRect, teJustRight);                     
            break;
    }
    
    TextMode(srcOr);
}
 
///////////////////////////////////////////////////////////////////////////
 
static RDataHdl DoHit(RDataHdl cdevGlobalsHdl, short item)
{
    short   value,oldSize,newSize, barHeight;
    Point   mouse;
    Rect    r;
    
    switch(item)
    {
        case iCheckBox:
            value = GetControlValue((ControlHandle)IGetHand(cdevGlobalsHdl,item));
            SetControlValue((ControlHandle)IGetHand(cdevGlobalsHdl,item),!value);
            (**(**cdevGlobalsHdl).config).install = !value;
            break;
        case iSizeBar:
            oldSize = (**cdevGlobalsHdl).sizepos;
            IGetRect(cdevGlobalsHdl,iSizeBar,&r);
            barHeight = r.bottom - r.top - 4;
            while(StillDown())
            {
                GetMouse(&mouse);
                IGetRect(cdevGlobalsHdl,iSizeBar,&r);
                InsetRect(&r,0,2);
                if (PtInRect(mouse,&r))
                {
                    newSize = r.bottom - mouse.v;
                    if ((newSize < (**cdevGlobalsHdl).sizepos) ||
                        (newSize > (**cdevGlobalsHdl).sizepos))
                    {
                        (**cdevGlobalsHdl).sizepos = newSize;
                        (**cdevGlobalsHdl).cursize =
                            newSize/ (double)barHeight * 
                            (**cdevGlobalsHdl).maxsize;
                        (**cdevGlobalsHdl).cursize =
                            ((**cdevGlobalsHdl).cursize/32) * 32;
                        DrawItem(cdevGlobalsHdl,iSizeBar);
                        DrawItem(cdevGlobalsHdl,iCurSize);
                    }
                }
                else
                {
                    if ((**cdevGlobalsHdl).sizepos != oldSize)
                    {
                        (**cdevGlobalsHdl).sizepos = oldSize;
                        (**cdevGlobalsHdl).cursize =
                            oldSize / (double)barHeight * 
                            (**cdevGlobalsHdl).maxsize;
                        (**cdevGlobalsHdl).cursize =
                            ((**cdevGlobalsHdl).cursize/32) * 32;
                        DrawItem(cdevGlobalsHdl,iSizeBar);
                        DrawItem(cdevGlobalsHdl,iCurSize);
                    }
                }
            }
            break;
    }
    return cdevGlobalsHdl;
}
 
///////////////////////////////////////////////////////////////////////////
 
static RDataHdl DoClose(RDataHdl cdevGlobalsHdl)
{
    short   err;
    
    if (cdevGlobalsHdl)
    {
        if ( (**cdevGlobalsHdl).config)
        {
            err = UpdateSysz((**cdevGlobalsHdl).config);
        
            HLock((Handle)cdevGlobalsHdl);
            ChangedResource((Handle)(**cdevGlobalsHdl).config);
            WriteResource((Handle)(**cdevGlobalsHdl).config);
            ReleaseResource((Handle)(**cdevGlobalsHdl).config);
            // check for ResError()!!!
            HUnlock((Handle)cdevGlobalsHdl);
        }
    
        DisposeHandle((Handle)cdevGlobalsHdl);
        cdevGlobalsHdl = nil;
    }
    return cdevGlobalsHdl;
}
 
///////////////////////////////////////////////////////////////////////////
 
static RDataHdl DoUpdate(RDataHdl cdevGlobalsHdl)
{
    DrawItem(cdevGlobalsHdl, iSizeBar);
    DrawItem(cdevGlobalsHdl, iMaxSize);
    DrawItem(cdevGlobalsHdl, iCurSize);
    
    return cdevGlobalsHdl;
}
 
///////////////////////////////////////////////////////////////////////////
 
static RDataHdl DoActive(RDataHdl cdevGlobalsHdl)
{
    return cdevGlobalsHdl;
}
 
static RDataHdl DoDeactive(RDataHdl cdevGlobalsHdl)
{
    return cdevGlobalsHdl;
}
 
///////////////////////////////////////////////////////////////////////////
 
static RDataHdl DoKeyEvent(RDataHdl cdevGlobalsHdl,
                 DialogPtr CPDialog,
                 EventRecord *event)
{
    char    tempChar;
    
    tempChar = event->message & charCodeMask;   // get the character, and check
    if (event->modifiers & cmdKey)              //  status of command key
    {           
        event->what = nullEvent;                // and empty event type
        
        switch (tempChar)                       // set appropriate message
        {
            case 'X':
            case 'x':   DialogCut(CPDialog);    break;
            
            case 'C':
            case 'c':   DialogCopy(CPDialog);   break;
            
            case 'V':
            case 'v':   DialogPaste(CPDialog);  break;
        }
    }
    return cdevGlobalsHdl;
}
 
///////////////////////////////////////////////////////////////////////////
 
extern pascal RDataHdl main (short message, short item, short numItems, short CPanelID,
                         EventRecord *theEvent, RDataHdl cdevGlobalsHdl, DialogPtr CPDialog);
 
extern pascal RDataHdl main (short message, short item, short numItems, short CPanelID,
                         EventRecord *theEvent, RDataHdl cdevGlobalsHdl, DialogPtr CPDialog)
{
#pragma unused (CPanelID)       /* unused formal parameters */
 
#ifdef THINK_C
    RememberA0();
    SetUpA4();
#endif
#ifdef __MWERKS__
    long oldA4=SetCurrentA4();
#endif
 
    if (message == macDev) return((RDataHdl) 1);                /* we work on every machine */
    else if (cdevGlobalsHdl != nil)
    {
        switch(message)
        {
            case nulDev:    cdevGlobalsHdl = DoNul(cdevGlobalsHdl);
                            break;
                            
            case initDev:   cdevGlobalsHdl = DoInit(CPDialog,numItems);
                            break;
                            
            case closeDev:  cdevGlobalsHdl = DoClose(cdevGlobalsHdl);
                            break;
 
            case hitDev:    cdevGlobalsHdl = DoHit(cdevGlobalsHdl,item - numItems);
                            break;
                            
            case updateDev: cdevGlobalsHdl = DoUpdate(cdevGlobalsHdl);
                            break;
            
            case activDev:  cdevGlobalsHdl = DoActive(cdevGlobalsHdl);
                            break;
            
            case deactivDev:    
                            cdevGlobalsHdl = DoDeactive(cdevGlobalsHdl);
                            break;
            
            case keyEvtDev:
                            cdevGlobalsHdl = DoKeyEvent(cdevGlobalsHdl,CPDialog,theEvent);
                            break;
                            
            case undoDev:   /* not supported */     break;
            case cutDev:    DialogCut(CPDialog);        break;
            case copyDev:   DialogCopy(CPDialog);       break;
            case pasteDev:  DialogPaste(CPDialog);      break;
            case clearDev:  DialogDelete(CPDialog); break;
            
            default:        // DebugStr("\pdefault:");
                            break;
        }
    }
 
#ifdef THINK_C
    RestoreA4();
#endif
#ifdef __MWERKS__
    SetA4(oldA4);
#endif
    return cdevGlobalsHdl;
}