DialogStuff.c

/*
    File:       DialogStuff.c
 
    Contains:   Handle application's dialogs
 
    Written by: Chris White 
 
    Copyright:  Copyright © 1995-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/5/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
 
#include <Types.h>
#include <Quickdraw.h>
#include <QDOffscreen.h>
#include <Devices.h>
#include <LowMem.h>
#include <TextUtils.h>
#include <Dialogs.h>
//#include <stddef.h>
#include <CodeFragments.h>
#include <StandardFile.h>
#include <Folders.h>
 
#include "FragmentTool.h"
#include "FragmentStuff.h"
#include "DialogStuff.h"
#include "Streams.h"
#include "Utilities.h"
#include "Prototypes.h"
 
static OSErr CreateContentList ( WindowRef theWindow, tContentsProcPtr contentsProc, void* refCon );
static void AddContentsToList ( WindowRef theWindow );
static int8 GetStageFromItem ( int16 theItem );
static int16 GetItemFromStage ( int8 theStage );
void GetNameFromDialog ( DialogRef theDialog, StringPtr theName );
 
 
 
 
 
//
// Creates a simple dialog with a single list. A routine pointer is passed
// as an argument which add the list contents.
//
OSErr CreateListDialog ( DialogRef* dialogRef, int16 dialogID, StringPtr dialogTitle,
                            tContentsProcPtr contentsProc, void* refCon )
{
    int16           theType;
    OSErr           theErr;
    GrafPtr         savePort;
    DialogRef       theDialog = nil;
    ListRef         theList = nil;
    Handle          theHandle;
    Point           cellSize = {0, 0};
    Cell            firstCell = {0, 0};
    Rect            dataRect = {0, 0, 0, 1};
    Rect            theRect;
    
    
    
    theDialog = GetNewDialog ( dialogID, nil, (WindowRef) -1L );
    if ( theDialog == nil )
        return kGenericError;
    
    // Creates the data structure assigned to the window's refCon field
    theErr = CreateWindowInfo ( theDialog, sizeof ( tDialogInfo ) );
    if ( theErr )
    {
        // Don't forget to free any storage we've used so far
        DestroyDialog ( theDialog );
        return theErr;
    }
    
    GetPort ( &savePort );
    SetPortWindowPort ( theDialog );
    TextFont ( kFontIDGeneva );
    TextFace ( normal );
    TextSize ( 9 );
    
    SetWindowType ( theDialog, kListWindowType );
    SetWTitle ( theDialog, dialogTitle );
    
    GetDialogItem ( theDialog, kListUserItem, &theType, &theHandle, &theRect );
    SetDialogItem ( theDialog, kListUserItem, theType, (Handle) gOutlineUserItemUPP, &theRect );
    
    theRect.right -= 15;
    theList = LNew ( &theRect, &dataRect, cellSize, 0, theDialog, 
                        false, false, false, true );
    if ( theList )
    {
        tDialogInfoPtr  theInfo;
        
        theInfo = (tDialogInfoPtr) GetWRefCon ( theDialog );
        theInfo->listRef = theList;
        (*theList)->selFlags = lOnlyOne;
        
        // Since the calling routine is always in the same architecture type as
        // the callback routine, we don't need to worry about any Mixed Mode
        // complications. We just treat it as a straight forward routine pointer.
        
        theErr = (*contentsProc) ( theList, refCon );
        if ( theErr )
        {
            // Don't forget to free any storage we've used so far
            DestroyDialog ( theDialog );
            SetPort ( savePort );
            return theErr;
        }
        
        LSetSelect ( true, firstCell, theList );
 
        // Now the list has been fully prepared, turn the drawing mode on. This
        // isn't srictly necessary since the window isn't supposed to visible.
        LSetDrawingMode ( true, theList );
    }
    
    SetPort ( savePort );
    
    SelectWindow ( theDialog );
    ShowWindow ( theDialog );
 
    *dialogRef = theDialog;
    
    return noErr;
}
 
 
 
//
// Creates the dialog used for the GetInfo command. Displays information about
// the code fragment. This is the stuff contained within the 'cfrg' resource
//
OSErr CreateInfoDialog ( DialogRef* dialogRef, StringPtr dialogTitle, WindowRef theWindow, int16 theIndex )
{
    OSErr           theErr;
    GrafPtr         savePort = nil;
    DialogRef       theDialog = nil;
    TEHandle        textH;
    tDialogInfoPtr  theInfo;
    tStreamRef      theStream = nil;
    tItemPtr        theItem;
    FontInfo        theFontInfo;
 
    
    theDialog = GetNewDialog ( 2002, nil, (WindowRef) -1L );
    if ( theDialog == nil )
        return kGenericError;
    
    theErr = CreateWindowInfo ( theDialog, sizeof ( tDialogInfo ) );
    if ( theErr )
        goto CleanupAndBail;
    
    GetPort ( &savePort );
    SetPortWindowPort ( theDialog );
    TextFont ( kFontIDGeneva );
    TextFace ( normal );
    TextSize ( 9 );
    
    // We're using a different font than the standard, so we need to
    // change the fields in the textedit record. Otherwise, any text
    // that is being edited will be display in the standard font.
    GetFontInfo ( &theFontInfo );
    textH = ((DialogPeek) theDialog)->textH;
    (*textH)->txFont = kFontIDGeneva;
    (*textH)->txFace = normal;
    (*textH)->txSize = 9;
    (*textH)->lineHeight = theFontInfo.ascent + theFontInfo.descent + theFontInfo.leading;
    (*textH)->fontAscent = theFontInfo.ascent;
    
    SetWindowType ( theDialog, kGetInfoWindowType );
    SetWTitle ( theDialog, dialogTitle );
    
    
    // The window is needed to make the document dirty if the user makes
    // a change. The item points to the information displayed in the dialog.
    
    theErr = NewStream ( &theStream, sizeof ( WindowRef ) + sizeof ( int16 ) );
    if ( theErr ) goto CleanupAndBail;
    
    theErr = SetStreamData ( theStream, (Ptr) &theWindow, sizeof ( WindowRef ) );
    if ( theErr ) goto CleanupAndBail;
    
    theErr = SetStreamData ( theStream, (Ptr) &theIndex, sizeof ( int16 ) );
    if ( theErr ) goto CleanupAndBail;
 
    theErr = CompactStream ( theStream );
    if ( theErr ) goto CleanupAndBail;
    
    theInfo = (tDialogInfoPtr) GetWRefCon ( theDialog );
    theInfo->refCon = (int32) theStream;
    
    // Set up the dialog with the information from the selected item 
    theItem = GetNthWindowItem ( theWindow, theIndex );
    theErr = SetDialogValues ( theDialog, theItem );
    if ( theErr ) goto CleanupAndBail;
    
    SetPort ( savePort );
    
    SelectWindow ( theDialog );
    ShowWindow ( theDialog );
    
    *dialogRef = theDialog;
    
    return noErr;
    
CleanupAndBail:
    // Don't forget to free any storage we've used so far. goto's are very useful
    // for things like error recovery. That's how many of the exception stack
    // implementations work in class frameworks.
    
    if ( theStream )
        DisposeStream ( theStream );
    if ( theDialog )
        DestroyDialog ( theDialog );
    if ( savePort )
        SetPort ( savePort );
        
    return theErr;
}
 
 
 
//
// Our one-fits-all routine to free up everything
// to do with a  dialog.
//
DialogRef DestroyDialog ( DialogRef theDialog )
{
    if ( theDialog )
    {
        tDialogInfoPtr  theInfo;
        
        theInfo = (tDialogInfoPtr) GetWRefCon ( theDialog );
        if ( theInfo )
        {
            if ( theInfo->listRef )
                LDispose ( theInfo->listRef );
            DisposePtr ( (Ptr) theInfo );
        }
        
        DisposeDialog ( theDialog );
    }
    
    // We'll return nil so the result can assigned to
    // the dialog reference that was passed in.
    return nil;
}
 
 
 
//
// This routine's pointer is passed into CreateListDialog
// to add the contents to a newly created list.
//
OSErr AddFragmentExports ( ListRef theList, void* refCon )
{
    int                     i;
    int32                   theCount;
    OSErr                   theErr = noErr;
    CFragLoadOptions        theFlags = kLoadCFrag;
    tItemPtr                theItem;
    Ptr                     mainAddr, symAddr;
    CFragConnectionID       theConnID;
    CFragSymbolClass        symClass;
    tAddFragmentExportsRec* theRec;
    Str255                  symName;
    static Str255           errName;
    
    
    theRec = (tAddFragmentExportsRec*) refCon;
    theItem = theRec->u.out.theItem;
    if ( theItem == nil )
        return kGenericError;
    
    
    // Since 'errName' must be valid after the routine has
    // gone out of scope, the variable is declaired static.
    
    
    // The fragment may not exist in the document yet. If this is the
    // case, we'll need to get the fragment from the temporary file. 
    if ( theItem->bExistsInDocument )
        theErr = GetDiskFragment ( theRec->u.out.theSpecPtr, theItem->codeOffset, theItem->codeLength,
                                    theItem->name, theFlags, &theConnID, &mainAddr, errName );
    else
        theErr = GetDiskFragment ( GetTempSpecPtr ( theItem ), 0, 0, theItem->name, theFlags, &theConnID, &mainAddr, errName );
    
    if ( theErr )
    {
        theRec->bIn = true;
        theRec->u.in.theErrorStr = errName;
        return theErr;
    }
    
    theErr = CountSymbols ( theConnID, &theCount );
    if ( theErr ) goto CleanupAndBail;
    
    for ( i = 0; i < theCount; i++ )
    {
        theErr = GetIndSymbol ( theConnID, i, symName, &symAddr, &symClass );
        if ( theErr ) goto CleanupAndBail;
        
        AddToList ( theList, symName );
    }
    
    
CleanupAndBail:
    
    CloseConnection ( &theConnID );
    
    return theErr;
}
 
 
 
//
// This routine's pointer is passed into CreateListDialog
// to add the names of each document, except the front-most.
//
OSErr AddDocuments ( ListRef theList, void* refCon )
{
    #pragma unused(refCon)
    int         theIndex = 0;
    WindowRef   theWindow;
    
    
    
    // By structuring the routines this way, we can ensure that the index we
    // retrive from the List Manager (as the selected item) can be passed into
    // the GetIndexedDocumentWindow routine to get the correct window. This
    // minimizes any logical dependencies between different routines. Most
    // of the logic is contained within the GetIndexedDocumentWindow routine.
    
    while ( 0 != (theWindow = GetIndexedDocumentWindow(theIndex++)))
    {
        Str255  theText;
        
        GetWTitle ( theWindow, theText );
        AddToList ( theList, theText );
    }
    
    return noErr;
}
 
 
 
// This routine is called to setup all the dialog items with the information
// from a fragment. We pass in a pointer to its data structure.
OSErr SetDialogValues ( DialogRef theDialog, tItemPtr theItem )
{
    int16   itemType;
    int16   tmpNum;
    Handle  theHandle;
    Rect    theRect;
    Str255  tmpString = "\p";
    
    // Name of the fragment
    GetDialogItem ( theDialog, kNameEditText, &itemType, &theHandle, &theRect );
    SetDialogItemText ( theHandle, theItem->name );
    
    // The fragment's arichtecture. For example, m68k
    GetDialogItem ( theDialog, kArchitectureStaticText, &itemType, &theHandle, &theRect );
    OSTypeToPStr ( theItem->archType, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    // The update level. We use a popup menu for this information
    GetDialogItem ( theDialog, kUpdateLevelPopup, &itemType, &theHandle, &theRect );
    SetControlValue ( (ControlHandle) theHandle, theItem->updateLevel + 1 );
    
    // Current Version
    GetDialogItem ( theDialog, kCurrentMajorEditText, &itemType, &theHandle, &theRect );
    NumToString ( (*(NumVersion*)&theItem->currVersion).majorRev, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    GetDialogItem ( theDialog, kCurrentMinorEditText, &itemType, &theHandle, &theRect );
    NumToString ( (*(NumVersion*)&theItem->currVersion).minorAndBugRev & 0xF0, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    GetDialogItem ( theDialog, kCurrentBugRevEditText, &itemType, &theHandle, &theRect );
    NumToString ( (*(NumVersion*)&theItem->currVersion).minorAndBugRev & 0x0F, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    GetDialogItem ( theDialog, kCurrentStagePopup, &itemType, &theHandle, &theRect );
    tmpNum = GetItemFromStage ( (*(NumVersion*)&theItem->currVersion).stage );
    SetControlValue ( (ControlHandle) theHandle, tmpNum );
 
    GetDialogItem ( theDialog, kCurrentNonRelEditText, &itemType, &theHandle, &theRect );
    NumToString ( (*(NumVersion*)&theItem->currVersion).nonRelRev, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    // Old Version
    GetDialogItem ( theDialog, kOldMajorEditText, &itemType, &theHandle, &theRect );
    NumToString ( (*(NumVersion*)&theItem->oldDefVersion).majorRev, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    GetDialogItem ( theDialog, kOldMinorEditText, &itemType, &theHandle, &theRect );
    NumToString ( (*(NumVersion*)&theItem->oldDefVersion).minorAndBugRev & 0xF0, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    GetDialogItem ( theDialog, kOldBugRevEditText, &itemType, &theHandle, &theRect );
    NumToString ( (*(NumVersion*)&theItem->oldDefVersion).minorAndBugRev & 0x0F, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    GetDialogItem ( theDialog, kOldStagePopup, &itemType, &theHandle, &theRect );
    tmpNum = GetItemFromStage ( (*(NumVersion*)&theItem->oldDefVersion).stage );
    SetControlValue ( (ControlHandle) theHandle, tmpNum );
    
    GetDialogItem ( theDialog, kOldNonRelEditText, &itemType, &theHandle, &theRect );
    NumToString ( (*(NumVersion*)&theItem->oldDefVersion).nonRelRev, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    // Stack size. Only relevant if this thing's an application
    GetDialogItem ( theDialog, kStackSizeEditText, &itemType, &theHandle, &theRect );
    NumToString ( theItem->appStackSize / 1024, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    // Resource ID of an alias record to look for fragments. We don't do much with this.
    GetDialogItem ( theDialog, kSubFolderIDEditText, &itemType, &theHandle, &theRect );
    NumToString ( theItem->appStackSize, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    // Usage. Is this an application, library, or what.
    GetDialogItem ( theDialog, kUsagePopup, &itemType, &theHandle, &theRect );
    SetControlValue ( (ControlHandle) theHandle, theItem->usage + 1 );
    
    // This is currently "hard-coded" in the dialog resource. We'll leave it alone.
    GetDialogItem ( theDialog, kLocationStaticText, &itemType, &theHandle, &theRect );
    // NumToString ( theItem->location, tmpString );
    // SetDialogItemText ( theHandle, tmpString );
    
    // Offset to the fragment in the data fork.
    if ( theItem->bExistsInDocument ) // Has it been saved? We don't know the offset otherwise
    {
        GetDialogItem ( theDialog, kOffsetStaticText, &itemType, &theHandle, &theRect );
        NumToString ( theItem->codeOffset, tmpString );
        SetDialogItemText ( theHandle, tmpString );
    }
    
    // Length of the fragment in the data fork
    GetDialogItem ( theDialog, kLengthStaticText, &itemType, &theHandle, &theRect );
    NumToString ( theItem->codeLength, tmpString );
    SetDialogItemText ( theHandle, tmpString );
    
    return noErr;
}
 
 
 
//
// The opposite of the above routine. This one gets the values from the dialog
// fields and puts them in the fragment's data structure
//
OSErr GetDialogValues ( DialogRef theDialog, tItemPtr theItem )
{
    int16   itemType;
    int32   tmpNum;
    Handle  theHandle;
    Rect    theRect;
    Str255  tmpString = "\p";
    
 
 
    // Name of the fragment
    GetDialogItem ( theDialog, kNameEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, theItem->name );
    
    // The update level. We use a popup menu for this information
    GetDialogItem ( theDialog, kUpdateLevelPopup, &itemType, &theHandle, &theRect );
    theItem->updateLevel = GetControlValue ( (ControlHandle) theHandle ) - 1;
    
    // Current Version
    GetDialogItem ( theDialog, kCurrentMajorEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, tmpString );
    StringToNum ( tmpString, &tmpNum );
    (*(NumVersion*)&theItem->currVersion).majorRev = tmpNum;
    
    GetDialogItem ( theDialog, kCurrentMinorEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, tmpString );
    StringToNum ( tmpString, &tmpNum );
    (*(NumVersion*)&theItem->currVersion).minorAndBugRev = tmpNum << 4;
    
    GetDialogItem ( theDialog, kCurrentBugRevEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, tmpString );
    StringToNum ( tmpString, &tmpNum );
    (*(NumVersion*)&theItem->currVersion).minorAndBugRev += tmpNum;
    
    GetDialogItem ( theDialog, kCurrentStagePopup, &itemType, &theHandle, &theRect );
    tmpNum = GetControlValue ( (ControlHandle) theHandle );
    (*(NumVersion*)&theItem->currVersion).stage = GetStageFromItem ( tmpNum );
    
    GetDialogItem ( theDialog, kCurrentNonRelEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, tmpString );
    StringToNum ( tmpString, &tmpNum );
    (*(NumVersion*)&theItem->currVersion).nonRelRev = tmpNum;
    
    // Old Version
    GetDialogItem ( theDialog, kOldMajorEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, tmpString );
    StringToNum ( tmpString, &tmpNum );
    (*(NumVersion*)&theItem->oldDefVersion).majorRev = tmpNum;
    
    GetDialogItem ( theDialog, kOldMinorEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, tmpString );
    StringToNum ( tmpString, &tmpNum );
    (*(NumVersion*)&theItem->oldDefVersion).minorAndBugRev = tmpNum << 4;
    
    GetDialogItem ( theDialog, kOldBugRevEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, tmpString );
    StringToNum ( tmpString, &tmpNum );
    (*(NumVersion*)&theItem->oldDefVersion).minorAndBugRev += tmpNum;
    
    GetDialogItem ( theDialog, kOldStagePopup, &itemType, &theHandle, &theRect );
    tmpNum = GetControlValue ( (ControlHandle) theHandle );
    (*(NumVersion*)&theItem->oldDefVersion).stage = GetStageFromItem ( tmpNum );
    
    GetDialogItem ( theDialog, kOldNonRelEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, tmpString );
    StringToNum ( tmpString, &tmpNum );
    (*(NumVersion*)&theItem->oldDefVersion).nonRelRev = tmpNum;
    
    // Stack size. Only relevant if this thing's an application
    GetDialogItem ( theDialog, kStackSizeEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, tmpString );
    StringToNum ( tmpString, &theItem->appStackSize );
    
    // Resource ID of an alias record to look for fragments. We don't do much with this.
    GetDialogItem ( theDialog, kSubFolderIDEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, tmpString );
    StringToNum ( tmpString, &theItem->appStackSize );
    
    // Usage. Is this an application, library, or what.
    GetDialogItem ( theDialog, kUsagePopup, &itemType, &theHandle, &theRect );
    theItem->usage = GetControlValue ( (ControlHandle) theHandle ) - 1;
    
    
    return noErr;
}
 
 
 
void GetNameFromDialog ( DialogRef theDialog, StringPtr theName )
{
    int16   itemType;
    Handle  theHandle;
    Rect    theRect;
    
    // Just the name of the fragment
    GetDialogItem ( theDialog, kNameEditText, &itemType, &theHandle, &theRect );
    GetDialogItemText ( theHandle, theName );
}
 
 
 
//
// Convert between the popup item number and what it means
//
int8 GetStageFromItem ( int16 theItem )
{
    int8 theStage = 0;
    
    switch ( theItem )
    {
        case 1:
            theStage = 0x20;
        break;
        
        case 2:
            theStage = 0x40;
        break;
        
        case 3:
            theStage = 0x60;
        break;
        
        case 4:
            theStage = 0x80;
        break;
    }
    
    return theStage;
}
 
 
 
//
// Convert between the popup item number and what it means
//
int16 GetItemFromStage ( int8 theStage )
{
    int16 theItem = 0;
    
    switch ( theStage )
    {
        case 0x20:
            theItem = 1;
        break;
        
        case 0x40:
            theItem = 2;
        break;
        
        case 0x60:
            theItem = 3;
        break;
        
        case 0x80:
            theItem = 4;
        break;
    }
    
    return theItem;
}
 
 
 
//
// Handle a click in a dialog
//
void DoDialogContentClick ( DialogRef theDialog, EventRecord* theEvent )
{
    SInt16 itemHit;
    
    
    SetPort ( theDialog );
    
    if ( DialogSelect ( theEvent, &theDialog, &itemHit ) )
        DoDialogItemHit ( theDialog, itemHit );
    else
    {
        if ( GetWindowType ( theDialog ) == kListWindowType )
        {
            ListRef         theList;
            tDialogInfoPtr  theInfo;
            Point           localPt;
            
            
            theInfo = (tDialogInfoPtr) GetWRefCon ( theDialog );
            theList = theInfo->listRef;
            
            localPt = theEvent->where;
            GlobalToLocal ( &localPt );
            
            if ( LClick ( localPt, theEvent->modifiers, theList ) )     /* double clicked? */
                DoDialogItemHit ( theDialog, kStdOkItemIndex );
        }   
    }
    
    
    return;
}
 
 
 
//
// Handle a dialog item hit
//
void DoDialogItemHit ( DialogRef theDialog, int16 theItem )
{
    switch ( theItem )
    {
        case kStdOkItemIndex:
        {
            int16   theSubType;
            
            theSubType = GetWindowSubType ( theDialog );
            switch ( theSubType )
            {
                case kMoveFragmentWindowSubType:
                    MoveCopySelectedFragments ( theDialog, true );
                break;
                
                case kCopyFragmentWindowSubType:
                    MoveCopySelectedFragments ( theDialog, false );
                break;
                
                default:
                    if ( GetWindowType ( theDialog ) == kGetInfoWindowType )
                    {
                        tDialogInfoPtr  theInfo;
                        tStreamRef      theStream;
                        
                        
                        theInfo = (tDialogInfoPtr) GetWRefCon ( theDialog );
                        theStream = (tStreamRef) theInfo->refCon;
                        if ( theStream )
                        {
                            OSErr       theErr;
                            int16       theIndex;
                            WindowRef   theWindow;
                            tItemPtr    theItem;
                            Str255      theName;
                            
                            
                            ResetStreamCursor ( theStream );
                            theErr = GetStreamData ( theStream, (Ptr) &theWindow, sizeof ( WindowRef ) );
                            theErr = GetStreamData ( theStream, (Ptr) &theIndex, sizeof ( int16 ) );
                            DisposeStream ( theStream );
                            
                            theItem = GetNthWindowItem ( theWindow, theIndex );
                            GetNameFromDialog ( theDialog, theName );
                            UpdateFragInList ( theWindow, theIndex, theName );
                            GetDialogValues ( theDialog, theItem );
                            
                            SetDocumentDirty ( theWindow, true );
                        }
                    }
                break;
            }
            DestroyDialog ( theDialog );
        }
        break;
        
        case kStdCancelItemIndex:
            DestroyDialog ( theDialog );
        break;
    }
    return;
    
} // DoDialogItemHit
 
 
 
//
// Perform's the copy/move after the user selects a traget document
// from the dialog.
//
void MoveCopySelectedFragments ( DialogRef theDialog, Boolean bMove )
{
    int16           theIndex = 0;
    tDialogInfoPtr  theInfo;
    
    
    theInfo = (tDialogInfoPtr) GetWRefCon ( theDialog );
    if ( GetSelection ( theInfo->listRef, &theIndex ) )
    {
        OSErr           theErr;
        int             theCount, i;
        WindowRef       sourceWindow, targetWindow;
        tStreamRef      theStream;
        
        
        
        // All the information is passed in a data stream
        // built by the PackageWindowData routine. It consists of the source
        // window reference, the number of fragments to copy or move, and
        // then an array of index values.
        
        targetWindow = GetIndexedDocumentWindow ( theIndex );
        if ( targetWindow == nil )
        {
            AlertUser ( kGenericErrorStr, 0, nil );
            return;
        }
        
        theStream = (tStreamRef) theInfo->refCon;
        ResetStreamCursor ( theStream );
        theErr = GetStreamData ( theStream, (Ptr) &sourceWindow, sizeof ( WindowRef ) );
        theErr = GetStreamData ( theStream, (Ptr) &theCount, sizeof ( int ) );
        
        for ( i = 0; i < theCount; i++ )
        {
            theErr = GetStreamData ( theStream, (Ptr) &theIndex, sizeof ( int16 ) );
            if ( bMove )
                theErr = MoveWindowFragment ( sourceWindow, theIndex, targetWindow );
            else
                theErr = CopyWindowFragment ( sourceWindow, theIndex, targetWindow );
        }
        
        DisposeStream ( theStream );
        
    }
    
    return;
}