/*
 *  fmenuhandler.c
 *  PeekIt
 *
 *  Created by C.K. Haun on Sat Feb 08 2003.
 *  Copyright (c) 2003 Ravenware Software. All rights reserved.
 *
 */
#define __FMENUHANDLER__
// open recent is 700
// notes is 
#include "PeekIt.h"
UInt16 gSavesPending;
Boolean gStopQuitting= false;
extern void DoAbout(void);
void InstallCommandHandler(void);
void         DoNoWindowMenuSetup(void);
void InstallMenuHandler(void);
void InitPeekItMenus(void)
{    MenuRef     iii,theMenu;
    EnableMenuCommand( NULL, kHICommandPreferences );

    InstallCommandHandler();
    InstallMenuHandler();
         iii= GetMenuRef(kFileMenu);

    GetMenuItemHierarchicalMenu(
                                iii,
                                kRecentSubMenuPosition,
                                &theMenu) ;
    DeleteMenuItems(theMenu, 1, CountMenuItems(theMenu));

}
Boolean MyQuitter(short how)
{Boolean retVal = true;
    switch(how){
        case kInitialQuit:

            gQuitting = true;

            gStopQuitting = false;


            RunWindows(kQuitting);
            if(gSavesPending)retVal = false;    
 //   if(gStopQuitting)doCallThru = false;
            break;

        case kRunWindowsReturn:
            break;
    }
    return(retVal);            

}
OSStatus CommandEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
{OSErr myErr = noErr;
// get the mouse location
    Boolean doCallThru = true;
    HICommand commandStruct;
    WindowRef theWindow = FrontWindow();
    GetEventParameter (inEvent, kEventParamDirectObject,
                       typeHICommand, NULL, sizeof(HICommand),
                       NULL, &commandStruct);

    switch(commandStruct.commandID){

        case kHICommandOpen:
            PeekItWindowOpenFile();
            break;
        case kHICommandQuit:
//            doCallThru = false;
            doCallThru = MyQuitter(kInitialQuit);
            break;

        case kHICommandAbout:
            doCallThru = false;

            DoAbout();
            break;
        case 'FIFI':
// send a generic general find
//            void GenPIMainWIND(WindowRef theWindow, UShort selector, void *theData)

            if(theWindow != 0 && IsAppWindow(theWindow)){
                WCH tempWC = (WCH)GetWRefCon(theWindow);
                if(*tempWC != 0xffffffff && (*tempWC)->generalMe){
                    ((*tempWC)->generalMe)(theWindow,kGenFindCommand,0);
                }}                    
            
            break;
            case 'FIAG':
                // find again
                if(theWindow != 0 && IsAppWindow(theWindow)){
                    WCH tempWC = (WCH)GetWRefCon(theWindow);
                    if(*tempWC != 0xffffffff && (*tempWC)->generalMe){
                        ((*tempWC)->generalMe)(theWindow,kFindAgainCommand,0);
                    }}          
                break;
        case 'FIAF':
        {  SInt16 outItemHit;
            StandardAlert(
                          kAlertStopAlert,
                          "\pTeasing!!!",
                          "\pFinding will be in the next release of PeekIt!",
                          0,                          &outItemHit)   ;

        }
            break;
            // font menu
            case 'FTCH':
                            if(theWindow != 0 && IsAppWindow(theWindow)){
                    WCH tempWC = (WCH)GetWRefCon(theWindow);
                    if(*tempWC != 0xffffffff && (*tempWC)->generalMe){
                        ((*tempWC)->generalMe)(theWindow,kChooseFontCommand,0);
                    }}   
                break;

            case 'FTBG':
                if(theWindow != 0 && IsAppWindow(theWindow)){
                    WCH tempWC = (WCH)GetWRefCon(theWindow);
                    if(*tempWC != 0xffffffff && (*tempWC)->generalMe){
                        ((*tempWC)->generalMe)(theWindow,kFontBiggerCommand,0);
                    }}   
                    break;

                case 'FTSM':
                    if(theWindow != 0 && IsAppWindow(theWindow)){
                        WCH tempWC = (WCH)GetWRefCon(theWindow);
                        if(*tempWC != 0xffffffff && (*tempWC)->generalMe){
                            ((*tempWC)->generalMe)(theWindow,kFontSmallerCommand,0);
                        }}   
                    break;
        case 'PISC':
        {

            extern WindowRef CreateOrShowPISourceWIND(FileTrackerPtr theFile, Boolean vis,Boolean newWindow);
            CreateOrShowPISourceWIND(0,true,false);
        }

            break;
        case 'PIRN':
        {

            extern WindowRef CreateOrShowPIReleaseNWIND(FileTrackerPtr theFile, Boolean vis,Boolean newWindow);
            CreateOrShowPIReleaseNWIND(0,true,false);
        }
            
            break;
        case kHICommandPreferences:
        {extern
            void DoPrefs(void);
            doCallThru = false;

            DoPrefs();




        }
            break;
        default:
            
// default value calls through to the embedded command ahndler if it is
        {WindowRef theWindow = FrontWindow();
            if(theWindow){
            if(IsAppWindow(theWindow)){
                if(theWindow != 0){
                    WCH tempWC = (WCH)GetWRefCon(theWindow);
                    if( (*tempWC)->commandMe){

                        ((*tempWC)->commandMe)( theWindow,  inEvent,inUserData,&commandStruct);

                    }}}
            } else {
            // no window.  Do it yourself, babycakes
                if(commandStruct.menu.menuRef){
                    // parse out by specific menus
                    UInt16 theID= GetMenuID(commandStruct.menu.menuRef);

                    switch(theID){
                        case 700:
                            OpenOpenRecent(commandStruct.menu.menuItemIndex);
                            break;
                        case 802:  // files with notes
                            DoBookMarkedFileMenu(commandStruct.menu.menuItemIndex);
                            
                            break;
                            
                        default:
                            break;
                    }                            
                }                    
            }
        
        }

            break;

    }




    if(doCallThru){
        myErr = CallNextEventHandler(
                                     inHandlerCallRef,
                                     inEvent);
    }
    return(myErr);
}


void InstallCommandHandler(void)
{
    OSStatus myErr = noErr;

    EventTypeSpec  eventList[1]={{
        kEventClassCommand,
        kEventCommandProcess}};
    myErr =InstallEventHandler(
                               GetApplicationEventTarget(),
                               NewEventHandlerUPP(CommandEventHandler),
                               1,
                               &eventList,
                               0, // theWindow, //  void *                 inUserData,
                               0 //  EventHandlerRef *      outRef);          /* can be NULL */
                               );
                               
}

// all this handler handles is the disablement/enablement message
OSStatus MenuEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
{
    OSStatus myErr = noErr;
// check the front winder
    WindowRef theWindow = FrontWindow();
    MenuID theID;
    MenuRef theMenu;

    UInt32 inEventKind =         GetEventKind(inEvent);
    
 // see if it's ours
    switch (inEventKind){
        case kEventMenuEnableItems:
            GetEventParameter (inEvent, kEventParamDirectObject, typeMenuRef,
                               NULL, sizeof(MenuRef), NULL, &theMenu);
            theID = GetMenuID(theMenu);
            switch (theID){
                case kEditMenu:
                case kFileMenu:
                case kNotesMenu:
                    DisableAllMenuItems( theMenu);

                    break;
            }
                if(theWindow != 0 && IsAppWindow(theWindow)){
                    WCH tempWC = (WCH)GetWRefCon(theWindow);
                    if(*tempWC != 0xffffffff && (*tempWC)->generalMe){
                        ((*tempWC)->generalMe)(theWindow,kwmgSetUpMenus,theID);
                        DrawDevNum(theID);

                    }
                } else {
                    DoNoWindowMenuSetup();
                }

                break;
        default:
            break;
    }
    myErr = CallNextEventHandler(
                                 inHandlerCallRef,
                                 inEvent);

    return(myErr);


}


void InstallMenuHandler(void)
{
    OSStatus myErr = noErr;

    EventTypeSpec  eventList[1]={{
        kEventClassMenu,
        kEventMenuEnableItems}};
    myErr =InstallEventHandler(
                               GetApplicationEventTarget(),
                               NewEventHandlerUPP(MenuEventHandler),
                               1,
                               &eventList,
                               0, // theWindow, //  void *                 inUserData,
                               0 //  EventHandlerRef *      outRef);          /* can be NULL */
                               );
                               
}


void         DoNoWindowMenuSetup(void)
{
// MenuRef fMenu =    GetMenuHandle(980);

    EnableMenuCommand(0,kHICommandOpen);
    EnableMenuItem(
                   GetMenuRef(kFileMenu),
                   kRecentSubMenuPosition);
    EnableMenuItem(GetMenuRef(kNotesMenu),8);

    

}

typedef struct RecentMenuItemData{
    CFAbsoluteTime added;

    FSRef theRef;
}RecentMenuItemData;

Ptr CollectRecentItems(Size *size)
{
    Ptr theData = 0;   
    Ptr returnPtr = 0;
    MenuRef     iii= GetMenuRef(kFileMenu);
    MenuRef theMenu;
    UInt16 index=1;
    short count;
    Size actualSize;
    *size = 0;

    GetMenuItemHierarchicalMenu(
                                iii,
                                kRecentSubMenuPosition,
                                &theMenu) ;
count = CountMenuItems(theMenu);
theData = malloc((sizeof(RecentMenuItemData)) * count);
returnPtr = theData;
*size=(sizeof(RecentMenuItemData)) * count;
while(count){
    count--;
    GetMenuItemProperty(
                        theMenu,
                        index,
                        'PEEK',
                        'FREF',
                        sizeof(RecentMenuItemData),
                        &actualSize,
                        theData) ;
    index++;
    theData = theData +sizeof(RecentMenuItemData);
}
    
    
    
    
    
    
    return(returnPtr);
}
void RemoveOldRecentItem(theMenu)
{
 // so we want the smallest number
    CFAbsoluteTime theSmallest;
    UInt16 index,numItems,smallItem;
    UInt32 actualSize;
    numItems = 1;
    RecentMenuItemData *   thisData = malloc(sizeof(RecentMenuItemData));
    GetMenuItemProperty(
                        theMenu,
                        numItems,
                        'PEEK',
                        'FREF',
                        sizeof(RecentMenuItemData),
                        &actualSize,
                        thisData) ;
    theSmallest = thisData->added;
    
    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);
}

// called from prefs 
void CreateRecentMenu(RecentMenuItemData * thisData,Size numBytes)
{
    UInt16 numItems = numBytes/sizeof(RecentMenuItemData);
    UInt16 nowItem;
    MenuRef theMenu;
    OSStatus myErr = 0;
    MenuRef     iii= GetMenuRef(kFileMenu);
    UInt16 index=1;
    HFSUniStr255 outName;
    CFStringRef theString;
    RecentMenuItemData * current=thisData;
    GetMenuItemHierarchicalMenu(
                                iii,
                                3,
                                &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
                                        );
        CFRelease(theString);
        
        SetMenuItemProperty(
                            theMenu,
                            nowItem,
                            'PEEK',
                            'FREF',
                            sizeof(RecentMenuItemData),
                            current) ;
        }
    
        current=current +1;
        
        index++; 
    }
    
    }
}
void AddToRecentMenu(FileTrackerPtr theFT)
{RecentMenuItemData * thisData=malloc(sizeof(RecentMenuItemData));;
    MenuRef iii,theMenu;
    iii= GetMenuRef(kFileMenu);
    UInt16 numItems;
    CFStringRef theString;
    Str255 holder;
    HFSUniStr255         outName;
    //find it
    GetMenuItemHierarchicalMenu(
                                iii,
                                3,
                                &theMenu) ;
    numItems = CountMenuItems(theMenu);
    if(numItems > 10)RemoveOldRecentItem(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
                        );
    CFRelease(theString);
 
        SetMenuItemProperty(
                            theMenu,
                            numItems,
                            'PEEK',
                            'FREF',
                           sizeof(RecentMenuItemData),
                            thisData) ;
    
    
    
}


void                         OpenOpenRecent(short index)
{
    CFAbsoluteTime theSmallest;
    UInt16 numItems,smallItem;
    UInt32 actualSize;
    RecentMenuItemData *   thisData = malloc(sizeof(RecentMenuItemData));
    MenuRef iii,theMenu;
    iii= GetMenuRef(kFileMenu);
    GetMenuItemHierarchicalMenu(
                                iii,
                                3,
                                &theMenu) ;
    actualSize = 0;
    GetMenuItemProperty(
                        theMenu,
                        index,
                        'PEEK',
                        'FREF',
                        sizeof(RecentMenuItemData),
                        &actualSize,
                        thisData) ;
    if(actualSize){
        FileTrackerPtr theFile =NewFileTrackerWith(0,&thisData->theRef);
        Boolean gotIt;
        gotIt = DoesFileExist(theFile,0);

        if(   gotIt){
        CreateOrShowPIMainWIND(theFile,true);
        } else {
        // tel em something
//            DebugStr("\pdeathfish");
            short outItemHit;
            StandardAlert(
                          kAlertStopAlert,
                          "\pCould not open file.",
                          "\pThe file may not exist.",
                          0,                          &outItemHit)   ;
        }
    }
}

#if 0
kHICommandOK                  = 'ok  ',

/*
 * The Cancel button in a dialog or alert.
 */
kHICommandCancel              = 'not!',

/*
 * The application should quit.
 */
kHICommandQuit                = 'quit',

/*
 * The last editing operation should be undone.
 */
kHICommandUndo                = 'undo',

/*
 * The last editing operation should be redone.
 */
kHICommandRedo                = 'redo',

/*
 * The selected items should be cut.
 */
kHICommandCut                 = 'cut ',

/*
 * The selected items should be copied.
 */
kHICommandCopy                = 'copy',

/*
 * The contents of the clipboard should be pasted.
 */
kHICommandPaste               = 'past',

/*
 * The selected items should be deleted.
 */
kHICommandClear               = 'clea',

/*
 * All items in the active window should be selected.
 */
kHICommandSelectAll           = 'sall',

/*
 * The application should be hidden. The Menu Manager will respond to
 * this command automatically; your application does not need to
 * handle it.
 */
kHICommandHide                = 'hide',

/*
 * Other applications should be hidden. The Menu Manager will respond
 * to this command automatically; your application does not need to
 * handle it.
 */
kHICommandHideOthers          = 'hido',

/*
 * All applications should become visible. The Menu Manager will
 * respond to this command automatically; your application does not
 * need to handle it.
 */
kHICommandShowAll             = 'shal',

/*
 * The Preferences menu item has been selected.
 */
kHICommandPreferences         = 'pref',

/*
 * The active window should be zoomed in or out. The Window Manager
 * will respond to this event automatically; your application does
 * not need to handle it, but you may want to install a Carbon event
 * handler for kEventWindowGetIdealSize to return the ideal size for
 * your document windows.
 */
kHICommandZoomWindow          = 'zoom',

/*
 * The active window should be minimized. The Window Manager will
 * respond to this event automatically; your application does not
 * need to handle it.
 */
kHICommandMinimizeWindow      = 'mini',

/*
 * All windows of the same class as the active window that have
 * collapse boxes should be minimized. The Window Manager will
 * respond to this event automatically; your application does not
 * need to handle it.
 */
kHICommandMinimizeAll         = 'mina',

/*
 * The active window should be maximized. Only sent on Mac OS 9. The
 * Window Manager will respond to this event automatically; your
 * application does not need to handle it.
 */
kHICommandMaximizeWindow      = 'maxi',

/*
 * All windows of the same class as the active window that have
 * collapse boxes should be maximized. The Window Manager will
 * respond to this event automatically; your application does not
 * need to handle it.
 */
kHICommandMaximizeAll         = 'maxa',

/*
 * All document-class windows should be arranged in a stack. The
 * Window Manager will respond to this event automatically; your
 * application does not need to handle it.
 */
kHICommandArrangeInFront      = 'frnt',

/*
 * All windows of this application should be brought in front of
 * windows from other applications. Only sent on Mac OS X. The Window
 * Manager will respond to this event automatically; your application
 * does not need to handle it.
 */
kHICommandBringAllToFront     = 'bfrt',

/*
 * This command ID is used as a placeholder to mark the separator
 * item dividing the Zoom/Minimize/Maximize/Arrange menu items in the
 * standard Window menu from the menu items listing the visible
 * windows. If you need to add your own menu items to the standard
 * Window menu before the window list section, you can look for the
 * menu item with this command ID using GetIndMenuItemWithCommandID,
 * and insert your menu items before the item with this ID.
 */
kHICommandWindowListSeparator = 'wldv',

/*
 * This command ID is used as a placeholder to mark the end of the
 * window list section of the standard Window menu. If you need to
 * add your own menu items to the standard Window menu after the
 * window list section, you can look for the menu item with this
 * command ID using GetIndMenuItemWithCommandID, and insert your
 * items after the item with this ID.
 */
kHICommandWindowListTerminator = 'wlst',

/*
 * A window in the standard Window menu has been selected and should
 * be activated. The Window Manager will respond to this event
 * automatically; your application does not need to handle it.
 */
kHICommandSelectWindow        = 'swin',

/*
 * The Rotate Windows hotkey (cmd-~ by default) has been pressed, and
 * non-floating windows should be rotated so that the window after
 * the active window is activated. The Window Manager will respond to
 * this event automatically; your application does not need to handle
 * it.
 */
kHICommandRotateWindowsForward = 'rotw',

/*
 * The Rotate Windows hotkey (cmd-~ by default) has been pressed, and
 * non-floating windows should be rotated so that the window before
 * the active window is activated. The Window Manager will respond to
 * this event automatically; your application does not need to handle
 * it.
 */
kHICommandRotateWindowsBackward = 'rotb',

/*
 * The floating window focus hotkey (ctl-F6 by default) has been
 * pressed, and floating windows should be rotated so that the window
 * after the focused window is activated. The Window Manager will
 * respond to this event automatically; your application does not
 * need to handle it.
 */
kHICommandRotateFloatingWindowsForward = 'rtfw',

/*
 * The floating window focus hotkey (ctl-F6 by default) has been
 * pressed, and floating windows should be rotated so that the window
 * before the focused window is activated. The Window Manager will
 * respond to this event automatically; your application does not
 * need to handle it.
 */
kHICommandRotateFloatingWindowsBackward = 'rtfb',

/*
 * The About menu item has been selected.
 */
kHICommandAbout               = 'abou',

/*
 * A new document or item should be created.
 */
kHICommandNew                 = 'new ',

/*
 * The user wants to open an existing document.
 */
kHICommandOpen                = 'open',

/*
 * The active window should be closed.
 */
kHICommandClose               = 'clos',

/*
 * The active document should be saved.
 */
kHICommandSave                = 'save',

/*
 * The user wants to save the active document under a new name.
 */
kHICommandSaveAs              = 'svas',

/*
 * The contents of the active document should be reverted to the last
 * saved version.
 */
kHICommandRevert              = 'rvrt',

/*
 * The active window should be printed.
 */
kHICommandPrint               = 'prnt',

/*
 * The user wants to configure the current page margins, formatting,
 * and print options.
 */
kHICommandPageSetup           = 'page',

/*
 * The application's help book should be displayed. Used by the Help
 * Manager when it adds the "<AppName> Help" menu item to the Help
 * menu. The Help Manager will respond to this event automatically;
 * your application does not need to handle it.
 */
kHICommandAppHelp             = 'ahlp'

#endif

#undef __FMENUHANDLER__