/*
 *  diffdrawer.pi.c
 *  PeekIt
 *
 *  Created by C.K. Haun on 7/17/07.
 *  Copyright 2007 Ravenware Software. All rights reserved.
 *
 */




// Drawer out
#define kDiffDWindSig 'DIFD'
enum{
  kDiffDRawButt = 1000,
   kDiffDHexButt
};

enum{
kIAmADrawer=0,
    kIAmFloating
};
void HitDiffDWIND(WindowRef theWindow, Point *thePoint);

struct DiffDWindData {
    WindowRef mommy;
    UInt16 whatAmI;
    UInt32 largest;
    short buddy;
    HIObjectRef compareRawPane;
    HIObjectRef compareTransPane;
    diffByteRangePtr theDifferences;
};

typedef struct DiffDWindData DiffDWindData;
typedef DiffDWindData *DiffDWDataP; // , **DiffDWDataP;
/* protos */

 #include  "diffview.pi.c"
static void ReArrangeDiffDWControls(WindowRef theWindow, DiffDWDataP nowCD);
static void SizeDiffDWINDControls(WindowRef theWindow);

OSStatus DiffDWindowDrawingCode(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
{
    OSStatus myStatus = noErr;
    CallNextEventHandler(
                         inHandlerCallRef,
                         inEvent);

    return(myStatus);

}
OSStatus DiffDWindowClickCode(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
{
    OSStatus myStatus = noErr;
// extract the mouse
    Point theMouse;
    mPushPort((WindowRef)inUserData)

        GetEventParameter (inEvent, kEventParamMouseLocation, typeQDPoint,
                           NULL, sizeof(Point), NULL, &theMouse);
    
// now hand off
// TEST TEMP get the mouse
// GetMouse(&theMouse);  // I should not have to get the mouse again
    mPullPort

        CallNextEventHandler(
                             inHandlerCallRef,
                             inEvent);

    return(myStatus);

}
OSStatus DiffDWindowStateChangeCode(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
{
    OSStatus myStatus = noErr;
    UInt32 theKind;
    WindowRef theWindow=(WindowRef)inUserData;
    WCH tempWC = (WCH)GetWRefCon((WindowRef)inUserData);
    DiffDWDataP nowCD = (DiffDWDataP)(*tempWC)->dataStore;
    
    
    theKind = GetEventKind(inEvent);

//    ZapPort((WindowRef)inUserData);
    switch(theKind){

        case        kEventWindowActivated:
/*
            SetKeyboardFocus(
                             theWindow,
                             SnatchCRef(theWindow,kDiffDWindSig,kByteEditBox),
                             kControlFocusNoPart);
            SetKeyboardFocus(
                             theWindow,
                             SnatchCRef(theWindow,kDiffDWindSig,kByteEditBox),
                             kControlFocusNextPart);
 */  
 
            break;
       case kEventWindowDeactivated:

           break;
           }
    CallNextEventHandler(
                         inHandlerCallRef,
                         inEvent);

    return(myStatus);

}
OSStatus DiffDWindowSizeCode(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
{
    OSStatus myStatus = noErr;

    SizeDiffDWINDControls((WindowRef) inUserData);

    CallNextEventHandler(
                         inHandlerCallRef,
                         inEvent);

    return(myStatus);

}
OSStatus DiffDWindowCloseCode(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
{
    OSStatus myStatus = noErr;
// just hide the window


    HideWindow((WindowRef)inUserData);

    return(myStatus);

}

OSStatus DiffDWindowSpecialCode(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
{
    OSStatus myStatus = noErr;

    HICommand commandStruct;
    GetEventParameter (inEvent, kEventParamDirectObject,
                       kEventClassWindow, NULL, sizeof(HICommand),
                       NULL, &commandStruct);

    CallNextEventHandler(
                         inHandlerCallRef,
                         inEvent);

    return(myStatus);

}








OSStatus InstallDiffDWindowHandlers(
                                     WindowRef theWindow,
                                     void * refCon,
                                     ULong flags)

{
    OSStatus myErr = noErr;
    long realRefCon = 0;
    EventHandlerRef windowOutRef;
    EventTypeSpec  windowDrawEventList[1]={{kEventClassWindow,kEventWindowDrawContent}};

    EventTypeSpec  windowStateEventList[2]={{kEventClassWindow,kEventWindowActivated},{kEventClassWindow,kEventWindowDeactivated}};

    EventTypeSpec  windowSizeEventList[1]={{kEventClassWindow,kEventWindowBoundsChanged}};

    EventTypeSpec  windowCloseEventList[1]={{kEventClassWindow,kEventWindowClose}};
    
//    EventTypeSpec  windowSpecialEventList[1]={{kEventClassWindow,kEventWindowContextualMenuSelect}};

    EventTypeSpec  windowClickEventList[1]={   {kEventClassWindow,kEventWindowHandleContentClick}};

    if(refCon == NULL)realRefCon = (long)theWindow;
// we should collect all these event refs in the window data struct
    myErr = InstallEventHandler (GetWindowEventTarget (theWindow), NewEventHandlerUPP(DiffDWindowDrawingCode),     sizeof(windowDrawEventList)/sizeof(EventTypeSpec),  (EventTypeSpec *)  &windowDrawEventList,     (void *)theWindow,   &windowOutRef);

    myErr = InstallEventHandler (GetWindowEventTarget (theWindow), NewEventHandlerUPP(DiffDWindowClickCode),     sizeof(windowClickEventList)/sizeof(EventTypeSpec),    (EventTypeSpec *)&windowClickEventList, (void *)theWindow,      &windowOutRef);

    myErr = InstallEventHandler (GetWindowEventTarget (theWindow), NewEventHandlerUPP(DiffDWindowStateChangeCode),     sizeof(windowStateEventList)/sizeof(EventTypeSpec),    (EventTypeSpec *)&windowStateEventList, (void *)theWindow,      &windowOutRef);

    myErr = InstallEventHandler (GetWindowEventTarget (theWindow), NewEventHandlerUPP(DiffDWindowSizeCode),     sizeof(windowSizeEventList)/sizeof(EventTypeSpec),   (EventTypeSpec *) &windowSizeEventList, (void *)theWindow,      &windowOutRef);

    myErr = InstallEventHandler (GetWindowEventTarget (theWindow), NewEventHandlerUPP(DiffDWindowCloseCode),     sizeof(windowCloseEventList)/sizeof(EventTypeSpec),    (EventTypeSpec *)&windowCloseEventList, (void *)theWindow,      &windowOutRef);
    
// taking the special out for a miunutes
// myErr = InstallEventHandler (GetWindowEventTarget (theWindow), NewEventHandlerUPP(DiffDWindowSpecialCode),     sizeof(windowSpecialEventList)/sizeof(EventTypeSpec),
// &windowSizeEventList, (void *)theWindow,      &windowOutRef);
    myErr = InstallStandardEventHandler(GetWindowEventTarget (theWindow));



    return(myErr);

}





// ****************************
// pascal void Contdevloop(short depth, short deviceFlags, GDHandle targetDevice, long userData)
// going back through and removing all the offscreen stuff in this.


void DrawDiffDWIND(WindowRef theWindow, EventRecord *theEvent)
{
}






void SizeDiffDWIND(WindowRef theWindow, EventRecord *theEvent, short how)
{
#pragma unused (theEvent )
    WCH tempWC = (WCH)GetWRefCon(theWindow);
    DiffDWDataP nowCD = (DiffDWDataP)(*tempWC)->dataStore;

    mPushPort(theWindow)
        SizeDiffDWINDControls(theWindow);
    mPullPort
}


OSStatus diffTextDrawEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
{
    OSStatus myErr = noErr;
    WindowRef theWindow=(WindowRef)inUserData;
    WCH tempWC = (WCH)GetWRefCon((WindowRef)inUserData);
    DiffDWDataP nowCD = (DiffDWDataP)(*tempWC)->dataStore;
    WindowRef parentWindow = nowCD->mommy;
    WCH parentTempWC = (WCH)GetWRefCon(parentWindow);
    PIMainWDataP parentNowCD = (PIMainWDataP)(*parentTempWC)->dataStore;
    ControlRef theCont;
    Rect theRect,ookRect;
    ControlID theID;
    UInt32 theKind;
    HIRect theHIRect,innerHIRect;
    CGContextRef cgContext ;
    short oldFontSize;
    SInt16 outItemHit;
    
    
    
    if(nowCD){
        GetEventParameter( inEvent, kEventParamCGContextRef, typeCGContextRef,
                           NULL, sizeof( CGContextRef ), NULL, &cgContext );
        
        theKind = GetEventKind(inEvent);
        HIViewGetFrame(
                       theCont,
                       &theHIRect);
        theHIRect.origin.x=theHIRect.origin.y=0;
        // works	 PaintCGRectWithRGBColorPtr(cgContext,theHIRect,&gBlack);
        
        innerHIRect = theHIRect;
        GetControlBounds(theCont,&theRect);
        
        switch(theKind){
            case kEventControlHit:
            case kEventControlClick:
                
                break;
            case kEventControlDraw:
            {Str255 fish = "\pComparing with file:  ";
                CGContextSelectFont(cgContext, "Lucida Grande", parentNowCD->fontSize, kCGEncodingMacRoman);
                CGContextSetTextDrawingMode (cgContext,  kCGTextFill);          
                CGContextScaleCTM (cgContext, 1,-1);// -1.0);
                    CGDrawStringAt(cgContext,fish,theRect.left,theRect.top-14);
   // and the file name
                    
                    if(parentNowCD->comparingWithFile->fsSpecIsValid){
                        CGContextShowText( cgContext, &parentNowCD->comparingWithFile->fsSpec->name[1],parentNowCD->comparingWithFile->fsSpec->name[0]);  
                    } else           {
                        Str255 thisone;
                        FSRefMakeFSSpec(parentNowCD->comparingWithFile->fsRef,& thisone);

                        CGContextShowText( cgContext, & thisone,parentNowCD->comparingWithFile->fsSpec->name[0]);  
                    }
                    
                // warn them if the file sizes are different
                    if((parentNowCD->comparingWithFile->dataForkLen !=parentNowCD->theFT->dataForkLen )){
                        CGDrawCFString(cgContext,CFSTR("  -   data fork"));
                    }
                    if((parentNowCD->comparingWithFile->resForkLen !=parentNowCD->theFT->resForkLen )){
                        CGDrawCFString(cgContext,CFSTR(" and res fork"));
                    }
                    if(((parentNowCD->comparingWithFile->dataForkLen !=parentNowCD->theFT->dataForkLen ))||((parentNowCD->comparingWithFile->resForkLen !=parentNowCD->theFT->resForkLen ))){
                        CGDrawCFString(cgContext,CFSTR(" sizes are different"));

                    }
            }
                
                break;
        }
    }        
    return(myErr);
    
}



#pragma mark creation

WindowRef AddDiffDWIND(WindowRef theWindow)
{
#pragma unused (theFile )
    LoopVar qq;
    WindowPrefStructHdl thePrefs=nil;
    EventTypeSpec	aboutlControlEvents[] =
    {
    {kEventClassControl,    kEventControlHit}
    };
    EventTypeSpec	posControlEvents[] =    {    {kEventClassControl,    kEventControlDraw}    };
    
    WCH tempWC;
    DiffDWDataP nowCD;
    OSErr myErr = 0;
    Rect globalBounds;
    AliasHandle theA;
    WindowRef DiffDWINDWindow = nil;
    

    WCH parentTempWC = (WCH)GetWRefCon(theWindow);
    PIMainWDataP parentNowCD = (PIMainWDataP)(*parentTempWC)->dataStore;
    Rect leftRect = parentNowCD->rawTargetRect;
    tempWC = (WCH)NewHandleClear(sizeof(windowControl));
    nowCD = (DiffDWDataP)calloc(1,sizeof(DiffDWindData));
    
    
    // see if it exists yet
//  gAddPrefs.diffWindowWhere=kDiffWindowAsFloat;
    switch( gAddPrefs.diffWindowWhere){
        case kDiffWindowAsDrawer:
            myErr = CreateWindowFromNib(gNibRef, CFSTR("DiffDrawer"), &DiffDWINDWindow);
            nowCD->whatAmI = kIAmADrawer;
            break;
        case kDiffWindowAsFloat:
            myErr = CreateWindowFromNib(gNibRef, CFSTR("DiffFloat"), &DiffDWINDWindow);
            nowCD->whatAmI = kIAmFloating;
// if I'm floating, size myself to the hiview
            GetWindowBounds(
                            DiffDWINDWindow,
                            kWindowGlobalPortRgn,
                            &globalBounds);
            globalBounds.right = globalBounds.left + (leftRect.right - leftRect.left);
            globalBounds.bottom = globalBounds.top + (leftRect.bottom - leftRect.top);

            SetWindowBounds(
                            DiffDWINDWindow,
                            kWindowStructureRgn,
                            &globalBounds);
            
            break;
    }
    
    
// NEW
    InstallDiffDWindowHandlers(
                                DiffDWINDWindow,
                                0,
                                0);
// moved up
#if 0    
    tempWC = (WCH)NewHandleClear(sizeof(windowControl));
    nowCD = (DiffDWDataP)calloc(1,sizeof(DiffDWindData));
#endif    
    nowCD->mommy= theWindow;
    SetWRefCon(DiffDWINDWindow, (long)tempWC);

        (*tempWC)->dataStore = (Ptr)nowCD;
    AddWindowID(DiffDWINDWindow);
    
    // set up the initial rects, either defaulted or saved
    SizeDiffDWINDControls(DiffDWINDWindow);
//   InstallControlEventHandler(  SnatchCRef(DiffDWINDWindow,kDiffDWindSig,kDiffDyteButt),  GTBGoToEventHandlerProc , GetEventTypeCount(aboutlControlEvents), aboutlControlEvents, DiffDWINDWindow, NULL );
//   InstallControlEventHandler( SnatchCRef(DiffDWINDWindow,kDiffDWindSig,kCancelButt),  GTBCancelEventHandlerProc , GetEventTypeCount(aboutlControlEvents), aboutlControlEvents, DiffDWINDWindow, NULL );
    InstallControlEventHandler(   SnatchCRef(DiffDWINDWindow,kDiffDWindSig,2000),  diffPaneDrawEventHandlerProc , GetEventTypeCount(posControlEvents), posControlEvents, DiffDWINDWindow, NULL );
    InstallControlEventHandler(   SnatchCRef(DiffDWINDWindow,kDiffDWindSig,2001),  diffPaneDrawEventHandlerProc , GetEventTypeCount(posControlEvents), posControlEvents, DiffDWINDWindow, NULL );
    InstallControlEventHandler(   SnatchCRef(DiffDWINDWindow,kDiffDWindSig,2100),  diffTextDrawEventHandlerProc , GetEventTypeCount(posControlEvents), posControlEvents, DiffDWINDWindow, NULL );



//    SetDrawerParent(DiffDWINDWindow, theWindow);
//    SetDrawerPreferredEdge(DiffDWINDWindow,kWindowEdgeBottom);
// SetDrawerOffsets (DiffDWINDWindow, 10.0, 10.0);

 nowCD->mommy = theWindow;



 switch( gAddPrefs.diffWindowWhere){
     case kDiffWindowAsDrawer:
         SetDrawerParent (
                          DiffDWINDWindow,
                          theWindow
                          );
         SetDrawerPreferredEdge(
                                DiffDWINDWindow,
                                kWindowEdgeBottom);
         break;
     case kDiffWindowAsFloat:
     {Str255 things;
         Str255 rest="\p differences";
         mCopyString(parentNowCD->theFT->fsSpec->name,things);
         mCopyString(rest,things);
         SetWTitle(DiffDWINDWindow,things);
     }
         break;
 }
 
 return(DiffDWINDWindow);
}


void UpdateCompareFileInfoDrawer(WindowRef theWindow)
{
    WCH tempWC = (WCH)GetWRefCon(theWindow);
    DiffDWDataP nowCD = (DiffDWDataP)(*tempWC)->dataStore;

}

// size scroll bar and text area
static void SizeDiffDWINDControls(WindowRef theWindow)
{
    Rect curRect;
    UInt16 heightOfText = 16;
    WCH tempWC = (WCH)GetWRefCon(theWindow);
    DiffDWDataP nowCD = (DiffDWDataP)(*tempWC)->dataStore;
    GetWindowPortBounds(theWindow,&curRect );
// 2100
    UInt16 gap;
    WindowRef parentWindow = nowCD->mommy;
    WCH parentTempWC = (WCH)GetWRefCon(parentWindow);
    PIMainWDataP parentNowCD = (PIMainWDataP)(*parentTempWC)->dataStore;
    Rect leftRect = parentNowCD->rawTargetRect;
    Rect rightRect = parentNowCD->transTargetRect;
    gap = rightRect.left - leftRect.right;
    
    Rect topRect = leftRect;

    topRect.right = 1500;
    topRect.top = 8;

    switch ( nowCD->whatAmI){
        case kIAmADrawer:
    topRect.bottom = heightOfText+topRect.top;
    SetControlBounds(
                     SnatchCRef(theWindow,kDiffDWindSig,2100),
                     &topRect);
    
    OffsetRect(&leftRect,-8,0/* heightOfText+2*/);
 rightRect = parentNowCD->transTargetRect;
    OffsetRect(&rightRect,-8,0 /*heightOfText+2*/);

    SetControlBounds(
                    SnatchCRef(theWindow,kDiffDWindSig,2000),
                     &leftRect);
    SetControlBounds(
                    SnatchCRef(theWindow,kDiffDWindSig,2001),
                     &rightRect);

            
        break;
    case   kIAmFloating:

        RectToZeroZero(&leftRect);
        SetControlBounds(
                         SnatchCRef(theWindow,kDiffDWindSig,2000),
                         &leftRect);
         rightRect = parentNowCD->transTargetRect;
         RectToZeroZero(&rightRect);
        OffsetRect(&rightRect,leftRect.right+gap,0 /*heightOfText+2*/);

        SetControlBounds(
                         SnatchCRef(theWindow,kDiffDWindSig,2001),
                         &rightRect);
        break;
    
}



}


















void ReArrangeDiffDWControls(WindowRef theWindow, DiffDWDataP nowCD)
{

}








void DoDiffDWindMenu(short which)
{

    WindowRef theW = FindWindowByKind(kDiffDWINDWindow);
    WCH tempWC = (WCH)GetWRefCon(theW);
    DiffDWDataP nowCD = (DiffDWDataP)(*tempWC)->dataStore;


}

void             UpdateDiffViews(PIMainWDataP parentNowCD,WindowRef theWindow)
{
           HIViewSetNeedsDisplay(   SnatchCRef(theWindow,kDiffDWindSig,2000),true);
            HIViewSetNeedsDisplay(   SnatchCRef(theWindow,kDiffDWindSig,2001),true);

}
#define kCompFileBufferSize    100000
OSStatus BuildDifferencesList(WindowRef theWindow)
{
    diffByteRangePtr theDataList = 0;
    diffByteRangePtr theResList = 0;
    diffByteRangePtr currentBase = 0;
    diffByteRangePtr currentHook = 0;
    diffByteRangePtr currentRange = 0;
 OSStatus myErr=0;
Boolean doIt, doingDataFork;
SInt16 forkRef1,forkRef2;
    Boolean inAnRange=false;
    SInt64 shortestFileLen = 0;
    SInt64 currentFilePosition = 0;
    UInt32 amountToRead=0;
    UInt32 posInBuffer = 0;
    Ptr buffer1,buffer2;
    SInt64 theOffsetStart = 0;
    FileTrackerPtr file1,file2;

    WCH tempWC = (WCH)GetWRefCon(theWindow);
    PIMainWDataP nowCD = (PIMainWDataP)(*tempWC)->dataStore;
    doIt= doingDataFork=false;
    buffer1 = malloc(kCompFileBufferSize);
    buffer2 = malloc(kCompFileBufferSize);
// open both files for reading
        if(nowCD->theFT->fsSpecIsValid)
                file1 = NewFileTrackerWith(nowCD->theFT->fsSpec,0);
            else           
                file1 = NewFileTrackerWith(0,nowCD->theFT->fsRef);
                
        file1->openDataFork = true;
        file1->dataForkPerm=fsRdPerm; //read it only
        file1->openResFork = true;
        file1->resForkPerm=fsRdPerm;
         myErr = OpenFile(file1);
         if(nowCD->comparingWithFile->fsSpecIsValid)
                file2 = NewFileTrackerWith(nowCD->comparingWithFile->fsSpec,0);
            else           
                file2 = NewFileTrackerWith(0,nowCD->comparingWithFile->fsRef);
    
            file2->openDataFork = true;
            file2->dataForkPerm=fsRdPerm; //read it only
            file2->openResFork = true;
            file2->resForkPerm=fsRdPerm;
            myErr |= OpenFile(file2);
            if(myErr){
            // •••• EXIT POINT
                free(buffer1);
                free(buffer2);
                nowCD->diffingActive = false;
                return(myErr);
            }



            doingDataFork = true;           

            do{   
                doIt = false;
                shortestFileLen = 0;
                currentFilePosition = 0;
                posInBuffer = 0;
                theOffsetStart=0;
                if(doingDataFork){
                    if(file1->dataForkRef && file2->dataForkRef ){
                        doIt = true;
                        forkRef1 = file1->dataForkRef;
                        forkRef2 = file2->dataForkRef;
                        if(file1->dataForkLen < file2->dataForkLen)
                            shortestFileLen  = file1->dataForkLen;
                        else
                            shortestFileLen = file2->dataForkLen;
                    } 
                } else {
                    if(file1->resForkRef && file2->resForkRef ){
                        doIt = true;
                        forkRef1 = file1->resForkRef;
                        forkRef2 = file2->resForkRef;
                        if(file1->resForkLen < file2->resForkLen)
                            shortestFileLen  = file1->resForkLen;
                        else
                            shortestFileLen = file2->resForkLen;
                        
                        
                    } 
                    
                    
                }
                if(doIt){
                do{
                    amountToRead = MIN(kCompFileBufferSize,(shortestFileLen - currentFilePosition));
                    // read 'em both
                    if(amountToRead){
                    theOffsetStart = currentFilePosition;                    
                    myErr=    FSReadFork ( forkRef1,fsFromStart,  currentFilePosition,amountToRead, buffer1, 0);                    
                    myErr|=    FSReadFork ( forkRef2,fsFromStart,  currentFilePosition,amountToRead, buffer2, 0);                    
                    posInBuffer = 0;

                    if(myErr ){                        break;                    }
                    currentFilePosition += amountToRead;
                    // now run through and find diffs
                    do{
                    if(*(buffer1+posInBuffer) != *(buffer2+posInBuffer)){
                        if(inAnRange){
                            currentRange->rangeEnd++;
                        } else {
                        // start a new one
                            inAnRange = true;
                            currentRange = calloc(1,sizeof(diffByteRange));
                            currentRange->rangeStart=currentRange->rangeEnd = theOffsetStart+posInBuffer;
                            // and see if we need to hook in
                            if(currentHook){
                                currentHook->next = currentRange;
                                currentHook = currentRange;
                            } else {
                            // no hook, you are the hook
                                currentBase = currentHook = currentRange;
                            }
                        }
                    } else {
                    // see if we are marking a range already, if so, terminate
                        inAnRange = false;
                        currentRange = 0;
                    }
                        posInBuffer++;

                    }while(posInBuffer!=amountToRead);
                    } else {
                    // amount to read was zero.  WTF?   break
                        break;
                    }
                }while(currentFilePosition < shortestFileLen);
                }
                if(doingDataFork){
                    doingDataFork = false;
                    if(currentBase){
                        nowCD->dataForkDiffs = currentBase;
                        currentBase=0;
                    }
                } else {
                    if(currentBase){
                        nowCD->resForkDiffs = currentBase;
                    currentBase = 0;

                    }
                    break;
                }
            }while(true);
            free(buffer1);
    free(buffer2);
    nowCD->diffingActive = false;

}
#define  kCompareMenuPosition 13
void BuildCompareMenu(CompareMenuItemData * thisData,Size numBytes)
{
    
    UInt16 numItems = numBytes/sizeof(CompareMenuItemData);
    UInt16 nowItem;
    MenuRef theMenu;
    OSStatus myErr = 0;
    MenuRef     iii= GetMenuRef(kToolsMenu);
    UInt16 index=1;
    HFSUniStr255 outName;
    CFStringRef theString;
    RecentMenuItemData * current=thisData;
    GetMenuItemHierarchicalMenu(
                                iii,
                                kCompareMenuPosition,
                                &theMenu) ;
    DeleteMenuItems(theMenu, 1, CountMenuItems(theMenu));
    if(numBytes){
        while(index <= numItems){
            myErr= FSGetCatalogInfo(                           &current->theRef,                            kFSCatInfoGettableInfo,
                                                               0,       /* can be NULL */
                                                               &outName,                      /* can be NULL */
                                                               0,            /* can be NULL */
                                                               0);
            if(myErr == noErr){
                theString= CFStringCreateWithCharacters(0, &outName.unicode, outName.length);
                
                
                AppendMenuItemTextWithCFString (
                                                theMenu,
                                                theString,
                                                0,0,&nowItem
                                                );
                mSafeCFRelease(theString);
                
                SetMenuItemProperty(
                                    theMenu,
                                    nowItem,
                                    'PEEK',
                                    'FREF',
                                    sizeof(CompareMenuItemData),
                                    current) ;
                
            }
            
            current=current +1;
            
            index++; 
        }
        
    }
    AppendMenuItemTextWithCFString( theMenu, NULL, kMenuItemAttrSeparator,
                                    0, NULL );
    AppendMenuItemTextWithCFString( theMenu, CFSTR("Clear Menu"), 0,
                                    0, NULL );
    
    
}
Ptr CollectCompareItems(Size * compareMenuDataSize)
{
    
    
    Ptr theData = 0;   
    Ptr returnPtr = 0;
    MenuRef     iii= GetMenuRef(kToolsMenu);
    MenuRef theMenu;
    UInt16 index=1;
    short count;
    Size actualSize;
    *compareMenuDataSize = 0;
    
    GetMenuItemHierarchicalMenu(
                                iii,
                                kCompareMenuPosition,  // I think
                                &theMenu) ;
    count = CountMenuItems(theMenu);
    theData = malloc((sizeof(CompareMenuItemData)) * count);
    returnPtr = theData;
    *compareMenuDataSize=(sizeof(CompareMenuItemData)) * count;
    while(count){
        count--;
        GetMenuItemProperty(
                            theMenu,
                            index,
                            'PEEK',
                            'FREF',
                            sizeof(CompareMenuItemData),
                            &actualSize,
                            theData) ;
        index++;
        theData = theData +sizeof(CompareMenuItemData);
    }
    
    
    
    
    
    
    return(returnPtr);
    
    
    
    
    
    
}


void ClearCompareMenu(MenuRef theMenu)
{    DeleteMenuItems(theMenu, 1, CountMenuItems(theMenu));
    
    AppendMenuItemTextWithCFString( theMenu, NULL, kMenuItemAttrSeparator,
                                    0, NULL );
    AppendMenuItemTextWithCFString( theMenu, CFSTR("Clear Menu"), 0,
                                    0, NULL );
    
    
}
void RemoveOldCompareItem(theMenu)
{
    // so we want the smallest number
    CFAbsoluteTime theSmallest;
    UInt16 index,numItems,smallItem;
    UInt32 actualSize;
    numItems = 1;
    RecentMenuItemData *   thisData = malloc(sizeof(CompareMenuItemData));
    GetMenuItemProperty(
                        theMenu,
                        numItems,
                        'PEEK',
                        'FREF',
                        sizeof(CompareMenuItemData),
                        &actualSize,
                        thisData) ;
    theSmallest = thisData->added;
    smallItem = 1;
    for(index = 2;index<11;index++){
        GetMenuItemProperty(
                            theMenu,
                            index,
                            'PEEK',
                            'FREF',
                            sizeof(RecentMenuItemData),
                            &actualSize,
                            thisData) ;
        if(thisData->added < theSmallest){
            smallItem = index;
        }
        
    }
    RemoveMenuItemProperty(
                           theMenu,
                           smallItem,
                           'PEEK',
                           'FREF') ;
    DeleteMenuItem    (theMenu,smallItem);
    free(thisData);
    {short ii=CountMenuItems(theMenu); 
        if(ii>10)
            RemoveOldRecentItem(theMenu);
    }
}

Boolean FileInCompareMenuNow(FileTrackerPtr theFT)
{Boolean retVal = false;
    MenuRef iii,theMenu;
    short count,index;
    Size actualSize;
    RecentMenuItemData thisData;
    iii= GetMenuRef(kToolsMenu);
    GetMenuItemHierarchicalMenu(
                                iii,
                                kCompareMenuPosition,
                                &theMenu) ;
    count = CountMenuItems(theMenu);
    count -=2;
    index = 1;
    while(count){
        GetMenuItemProperty( 
                             theMenu,
                             index,
                             'PEEK',
                             'FREF',
                             sizeof(CompareMenuItemData),
                             &actualSize,
                             &thisData) ;
        if( FSCompareFSRefs( 
                             theFT->fsRef,
                             & thisData.theRef) == noErr){
            return(true);
            
        }
        
        count--;
        index++;
        
    }
    
    return(retVal);
}

void AddToCompareMenu(FileTrackerPtr theFT)
{RecentMenuItemData * thisData=malloc(sizeof(CompareMenuItemData));;
MenuRef iii,theMenu;
iii= GetMenuRef(kToolsMenu);
UInt16 numItems;
CFStringRef theString;
Str255 holder;
HFSUniStr255         outName;
//find it
if(FileInCompareMenuNow(theFT))return;   // ••• exit point
GetMenuItemHierarchicalMenu(
                            iii,
                            kCompareMenuPosition,
                            &theMenu) ;
numItems = CountMenuItems(theMenu);
// take the two bottom ones off
if(numItems){
    DeleteMenuItem    (theMenu,numItems);
    numItems--;
    DeleteMenuItem    (theMenu,numItems);
    numItems--;
}
if(numItems > 9)RemoveOldCompareItem(theMenu);
// just add it baby

thisData->added=CFAbsoluteTimeGetCurrent();
BlockMoveData(theFT->fsRef,&thisData->theRef,sizeof(FSRef));
FSGetCatalogInfo(                             theFT->fsRef,                            kFSCatInfoGettableInfo,
                                              0,       /* can be NULL */
                                              &outName,                      /* can be NULL */
                                              0,            /* can be NULL */
                                              0);
theString= CFStringCreateWithCharacters(0, &outName.unicode, outName.length);


AppendMenuItemTextWithCFString (
                                theMenu,
                                theString,
                                0,0,&numItems
                                );
mSafeCFRelease(theString);

SetMenuItemProperty(
                    theMenu,
                    numItems,
                    'PEEK',
                    'FREF',
                    sizeof(CompareMenuItemData),
                    thisData) ;
free(thisData);
AppendMenuItemTextWithCFString( theMenu, NULL, kMenuItemAttrSeparator,
                                0, NULL );
AppendMenuItemTextWithCFString( theMenu, CFSTR("Clear Menu"), 0,
                                0, NULL );

}
void OpenOpenCompare(UInt16 index,WindowRef theWindow)
{
    UInt32 actualSize;
    short count,compIndex;
    RecentMenuItemData *   thisData = malloc(sizeof(CompareMenuItemData));
    MenuRef iii,theMenu;
    iii= GetMenuRef(kToolsMenu);
    GetMenuItemHierarchicalMenu(
                                iii,
                                kCompareMenuPosition,
                                &theMenu) ;
    actualSize = 0;
    count = CountMenuItems(theMenu);
    if(index < (count -1)){
        GetMenuItemProperty( 
                             theMenu,
                             index,
                             'PEEK',
                             'FREF',
                             sizeof(CompareMenuItemData),
                             &actualSize,
                             thisData) ;
        if(actualSize){
            FileTrackerPtr theFile =NewFileTrackerWith(0,&thisData->theRef);
            Boolean gotIt;
            gotIt = DoesFileExist(theFile,0);
            
            if(   gotIt){
//                CreateOrShowPIMainWIND(theFile,true,true,0);
extern                void PIMainCompareFileStart(WindowRef theWindow,PIMainWDataP nowCD,FileTrackerPtr withThis);
                {                WCH tempWC = (WCH)GetWRefCon(theWindow);
                PIMainWDataP nowCD = (PIMainWDataP)(*tempWC)->dataStore;
                PIMainCompareFileStart( theWindow, nowCD,theFile);
                }
            } else {
                // tel em something
                //            DebugStr("\pdeathfish");
                short outItemHit;
                DeleteMenuItem(theMenu,index);
                StandardAlert(
                              kAlertStopAlert,
                              "\pCould not open file.",
                              "\pThe file may not exist, moved somewhere I can't find it, or something else.  Sorry.",
                              0,                          &outItemHit)   ;
            }
        }
    } else {
        if(index == count){
            ClearRecentMenu(theMenu);
        }
    }
    
}

void DrawDiffDataQuartz(   CGContextRef cgContext, WindowRef theWindow,UInt16 which){
    WCH tempWC = (WCH)GetWRefCon(theWindow);
    PIMainWDataP nowCD = (PIMainWDataP)(*tempWC)->dataStore;
    Rect lilRect,lilRect2,winRect;
    Byte hexen;
    diffByteRangePtr theDiffs = nowCD->currentDiffs;
    diffByteRangePtr activeDiff=theDiffs;

//    UInt16 howManyLilBytes = 0;
    Ptr realPtr = nowCD->comparing.fileBuffer;
    Boolean noModDisplay = false;
    Str31 theS;
    Boolean                             noReallyBreak = false;
    SInt64 tempVar1, tempVar2,tempVar1PlusLilCounter;
    CGContextRef context;
    float incer = nowCD->columnWidth;
    float incer2 = nowCD->columnWidth*2;
    float lilFast1,lilFast2;
    Ptr moddedPtr = nowCD->modBuffer;
    Byte lilByte,modCheckByte; 
    float hi = nowCD->cellHi;
    float numCols=nowCD->numColumns;
    LoopVar qq,ii;
    float numRows=    nowCD->numRows ;

    
    SInt64 lilCounter = nowCD->comparing.offsetInBuffer;
    static        char raw[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    HIRect theHIRect;
    lilFast2 = nowCD->fontSize+2;  // ??? 
    lilFast1 = 0;
    mCGSetColor(cgContext,gTheColors[kColTextColor]);
if(nowCD->forkShowing == kPIMainShowingNoFork)
    noModDisplay = true;
    switch(which){
        short newID;
        case kDrawRawData:
            tempVar1=nowCD->comparing.bufStartInFile;
                
                switch(nowCD->forkShowing){	
                    case kPIMainShowingDataFork:
                        tempVar2 =nowCD->comparingWithFile->dataForkLen; 
                        break;
                    case kPIMainShowingResFork:
                        tempVar2 =nowCD->comparingWithFile->resForkLen; 
                        break;  
                    case    kPIMainShowingNoFork:
                        tempVar2 = kFileBufferSize;
                        break;
                };	
            
                
                
                
            while(activeDiff){
                if( (tempVar1+lilCounter) >  activeDiff->rangeEnd){
                    activeDiff = activeDiff->next;                        
                } else {
                    break;
                }
            }  
                
                
                for(ii=0;ii<numRows;ii++){        
                    for(qq=0;qq<numCols;qq++){
                        tempVar1PlusLilCounter = tempVar1 + lilCounter;



#if 0
••••                        change this 
                        if(noModDisplay)
                            modCheckByte = 0;
                        else
                        modCheckByte = *(moddedPtr + lilCounter);
            
            
            if(modCheckByte){
                
                mCGSetColor(cgContext,gTheColors[kModdedTextColor]);
            }
#endif                        
                        /***************************/
                        if(activeDiff){
                            if( tempVar1PlusLilCounter >= activeDiff->rangeStart  &&  tempVar1PlusLilCounter <= activeDiff->rangeEnd){
                                CGRGBColor pppp=gCGDiffRangeColor;
                                pppp.alpha=.3;
//                                pppp.red=.9;
                                Rect theR;
                                HIRect theIt;
                                theIt.origin.x= lilFast1-2; // theR.left;
                                theIt.origin.y = ( lilFast2 -nowCD->fontSize)*-1;
                                theIt.size.width =  (nowCD->columnWidth);// theR.right-theR.left;
                                    theIt.size.height = lilFast2 -( lilFast2 -nowCD->fontSize)+4;
                                    
                                    theIt.origin.y -=theIt.size.height;
                                    
                                    PaintCGRectWithCGRGBColorPtr(cgContext,theIt,&pppp);
                                    
                                    
                                    
                                    mCGSetColor(cgContext,gTheColors[kColTextColor]);
                                                                     
                                    
                            }
                            // see if it's time to move on
                            if( tempVar1PlusLilCounter+1 >  activeDiff->rangeEnd)activeDiff = activeDiff->next;

                        }
                        
                        /**********************/
                        
                        
                        if(modCheckByte){
                            mCGSetColor(cgContext,gTheColors[kColTextColor]);                
                        }  
                        
            CGContextShowTextAtPoint (cgContext,lilFast1 , lilFast2  * -1  ,(realPtr+lilCounter), 1); 
//            howManyLilBytes++;

                        
            lilCounter++;
            if((lilCounter+tempVar1) >= tempVar2){  // 6.2.06 less than or equal tried
                noReallyBreak = true;
                break;
            }
            lilFast1+=incer;
            
        }
        lilFast1=2; // bigRect.left+2; // plus 2, dammit
        lilFast2+=hi;
        if(noReallyBreak == true)break;
        
    }
    // reset the notes
                nowCD->comparing.bytesShowing = numRows * numCols; // howManyLilBytes;
    noReallyBreak = false;
    
    break;
            /***************/
            
        case kDrawTransData:
            tempVar1=nowCD->comparing.bufStartInFile;
                switch(nowCD->forkShowing){	
                    case kPIMainShowingDataFork:
                        tempVar2 =nowCD->comparingWithFile->dataForkLen; 
                        break;
                    case kPIMainShowingResFork:
                        tempVar2 =nowCD->comparingWithFile->resForkLen; 
                        break;  
                    case    kPIMainShowingNoFork:
                        tempVar2 = kFileBufferSize;
                        break;
                };	
            
                
            if(nowCD->showingHex){
                lilCounter=nowCD->comparing.offsetInBuffer;
                // reset nextnoteisat based on lilpointer
                while(activeDiff){
                    if( (tempVar1+lilCounter) >  activeDiff->rangeEnd){
                        activeDiff = activeDiff->next;                        
                    } else {
                        break;
                    }
                }  
                
                
                lilFast1 = 4 ;  // not 2;
                for(ii=0;ii<numRows;ii++){                    
                    for(qq=0;qq<numCols;qq++){
                        // now the hex of it
                        tempVar1PlusLilCounter = tempVar1 + lilCounter;
                        lilByte = *(realPtr+lilCounter);
                        theS[1]   = raw[(lilByte>>4)&0xf];
                        theS[2] = raw[lilByte&0xf];
                        
                        
                        
                        //  here will be added the rectangle surrounding noted byes

                        
                        
                        
// make range marks.  OK, now look to see if we're in range, too
                        if( tempVar1PlusLilCounter >= nowCD->rangeStart  &&  tempVar1PlusLilCounter <= nowCD->rangeEnd){
                            // this is to keep from marking 0/0
                            
                            
                        }
                        /***************************/
                        if(activeDiff){
                            if( tempVar1PlusLilCounter >= activeDiff->rangeStart  &&  tempVar1PlusLilCounter <= activeDiff->rangeEnd){
                                CGRGBColor pppp=gCGDiffRangeColor;
                                pppp.alpha=.3;
//                                pppp.red=.9;
                                
                                Rect theR;
                                HIRect theIt;
                                theIt.origin.x= lilFast1-2; // theR.left;
                                theIt.origin.y = ( lilFast2 -nowCD->fontSize)*-1;
                                theIt.size.width =  (nowCD->columnWidth)*2;// theR.right-theR.left;
                                    theIt.size.height = lilFast2 -( lilFast2 -nowCD->fontSize)+4;
                                    
                                    theIt.origin.y -=theIt.size.height;
                                    
                                    PaintCGRectWithCGRGBColorPtr(cgContext,theIt,&pppp);
                                    
                                    
                                    
                                    mCGSetColor(cgContext,gTheColors[kColTextColor]);
                                    // see if it's time to move on
                                    
                                    
                            }
                            if( tempVar1PlusLilCounter+1 >  activeDiff->rangeEnd)
                                activeDiff = activeDiff->next;

                        }
                        
                        
                        /**********************/
                        
                        
                        
                        // moving this one now    
                        // changing this so liFast 1 and 2 are not being modified here.  Let them be modified in the non-regulr cases
                                                CGContextShowTextAtPoint (cgContext,lilFast1/* +2*/ ,  lilFast2*-1/* ook*/,&theS[1], 2); 
                        
                        
                        if(modCheckByte){
                            mCGSetColor(cgContext,gTheColors[kColTextColor]);
                            
                        }
                        
                        
                        lilCounter++;
                        
                        if((lilCounter+ tempVar1 /* nowCD->displaying.bufStartInFile*/ )  >= tempVar2 /* nowCD->theFT->dataForkLen*/ ){   
                            noReallyBreak = true;
                            break;
                        }
                        
                        lilFast1 +=incer2;
                        
                    }
                    
                    
                     lilFast1=4;
                    lilFast2+=hi;
                    if(noReallyBreak == true)break;
                    
                }
            }
                // reset the notes
                
                
                
                break;
            
            
            
            /****************/
    
    
    }

}



OSStatus diffPaneDrawEventHandlerProc ( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
{
    OSStatus myErr = noErr;
    WindowRef theWindow=(WindowRef)inUserData;
    WCH tempWC = (WCH)GetWRefCon((WindowRef)inUserData);
    DiffDWDataP nowCD = (DiffDWDataP)(*tempWC)->dataStore;
    WindowRef parentWindow = nowCD->mommy;
    WCH parentTempWC = (WCH)GetWRefCon(parentWindow);
    PIMainWDataP parentNowCD = (PIMainWDataP)(*parentTempWC)->dataStore;
    


if(nowCD){
    ControlRef theCont;
    Rect theRect,ookRect;
    ControlID theID;
    UInt32 theKind;
    HIRect theHIRect,innerHIRect;
    CGContextRef cgContext ;
    short oldFontSize;
    SInt16 outItemHit;
    GetEventParameter( inEvent, kEventParamCGContextRef, typeCGContextRef,
                       NULL, sizeof( CGContextRef ), NULL, &cgContext );
    
    
//    mPushPort((WindowRef)inUserData);
    GetEventParameter (inEvent, kEventParamDirectObject, typeControlRef,
                       NULL, sizeof(ControlRef), NULL, &theCont);
    theKind = GetEventKind(inEvent);
    HIViewGetFrame(
                   theCont,
                   &theHIRect);
    theHIRect.origin.x=theHIRect.origin.y=0;
    // works	 PaintCGRectWithRGBColorPtr(cgContext,theHIRect,&gBlack);
    
    innerHIRect = theHIRect;
    GetControlBounds(theCont,&theRect);
    
    switch(theKind){
        case kEventControlHit:
        case kEventControlClick:
            
            break;
        case kEventControlDraw:
        if(parentNowCD->diffingActive == false){
            ColDrawRectQuartz(cgContext,kForTransData,parentNowCD);
                            CGContextSetRGBFillColor (cgContext, 0, 0, 0, 1); 
            {OSStatus ik=0;
                theHIRect.origin.x=0;
                theHIRect.origin.y=0;
                CGContextBeginPath(cgContext);
                CGContextAddRect(cgContext, theHIRect);		// current path now represents cgRect
                CGContextDrawPath(cgContext, kCGPathStroke);
            }
                
            CGContextSelectFont(cgContext, "Lucida Grande", parentNowCD->fontSize, kCGEncodingMacRoman);
            CGContextSetTextDrawingMode (cgContext,  kCGTextFill);          
            CGContextScaleCTM (cgContext, 1,-1);// -1.0);
            short willy;
            GetControlID(
                         theCont,
                         &theID);
            if(            theID.id == 2000)
                willy = kDrawRawData;
                else
                willy = kDrawTransData;
            DrawDiffDataQuartz( cgContext, parentWindow,willy);

         } else {
             CGContextSelectFont(cgContext, "Lucida Grande", parentNowCD->fontSize, kCGEncodingMacRoman);
             CGContextSetTextDrawingMode (cgContext,  kCGTextFill);          
             CGContextScaleCTM (cgContext, 1,-1);// -1.0);
                 CGDrawStringAt(cgContext,"\p Processing file differences",20,-20);
//                      CGDrawStringAt(cgContext,"\p Please wait....",20,-40);
         }
            break;



    }


// mPullPort;
    }
return(myErr);

}
