/*
* TinyFinder.c - 21-Feb-85
*
* This program is an alternative Finder that is very fast and small,
* and limited in its abilities compared to the real Finder.  It is
* written in Aztec 68000 C (version 1.06D).
*
* copyright (c) 1985 by:
*   Kent Kersten
*   Harrison Systems
*   437 Atlas Drive
*   Nashville, TN  37211
*   (615) 834-1366
*   CompuServe CIS [72277,2726]
*
* To compile & link this file:
*       cc TinyFinder.c
*       ln -m TinyFinder.o sys:lib/sacroot.o -lc
*/

#include  <quickdraw.h>
#include  <window.h>
#include  <event.h>
#include  <menu.h>
#include  <desk.h>
#include  <dialog.h>
#include  <resource.h>
#include  <segment.h>
#include  <packages.h>
#include  <pb.h>
#include  <syserr.h>
#include  <inits.h>

#define   nil                   (long) 0
#define   NUM_MENUS             4

#define   AppleMenu             256
#define   FileMenu              257
#define   EditMenu              258
#define   SpecialMenu           259

#define   ABOUT_DLOG            256     /* resource id # of our 'About...' box */
#define   GENERAL_ERROR_ALRT    500

MenuHandle TFMenu[NUM_MENUS];
Point      whereOpen    = { 80, 80 };           /* where to put the SF dialog */

Boolean  DoCommand(), ProcessEvents();


main()
{
    InitGraf(&thePort);
    InitFonts();
    InitWindows();
    InitMenus();
    InitDialogs(nil);
    TEInit();

    FlushEvents(everyEvent, 0);        /* flush ALL events */
    FormMenuBar();

    CheckForFinder();

    InitCursor();
    LaunchAppl();

    while(ProcessEvents())
         ;
}


/*
* Get events and process them.  Return FALSE to exit.
*/

Boolean ProcessEvents()
{
    char         theChar;
    Boolean      NoQuitFlag = TRUE;
    WindowPtr    whichWindow;
    EventRecord  TFEvent;
    GrafPtr      savePort;

    HiliteMenu(0);                     /* turn off any highlighting in menu bar */
    SystemTask();

    GetNextEvent(everyEvent, &TFEvent);
    switch(TFEvent.what) {
         case mouseDown:
              switch(FindWindow(pass(TFEvent.where), &whichWindow)) {  /* major Aztec C68K hack-ack (pass) */
                   case inMenuBar:
                        NoQuitFlag = DoCommand(MenuSelect(pass(TFEvent.where)));       /* Aztec hack */
                        break;
                   case inSysWindow:
                        SystemClick(&TFEvent,whichWindow);
                        break;
              }
              break;
         case keyDown:
         case autoKey:
              theChar = TFEvent.message % 256;
              if((TFEvent.modifiers & cmdKey) != 0)            /* command key pressed */
                   NoQuitFlag = DoCommand(MenuKey(theChar));
              break;
         case updateEvt:
              GetPort(&savePort);
              SetPort(TFEvent.message);
              BeginUpdate(TFEvent.message);
              EndUpdate(TFEvent.message);
              SetPort(savePort);
              break;
    }

    return NoQuitFlag;
}


/*
* Decipher menu commands here.  Return FALSE to quit.
*/

Boolean DoCommand(command)
long command;
{
    char     name[256];
    short    MenuNum, ItemNum;
    Boolean  NoQuitFlag = TRUE;

    InitCursor();
    MenuNum = HiWord(command);
    ItemNum = LoWord(command);

    switch(MenuNum) {
         case AppleMenu:
              if(ItemNum == 1)
                   AboutTinyFinder();          /* do our "About..." box */
              else {
                   GetItem(TFMenu[0], ItemNum, name);
                   OpenDeskAcc(name);
              }
              break;
         case FileMenu:
              switch(ItemNum) {
                   case 1:
                        LaunchAppl();
                        break;
                   case 2:
                        GoFinder();
                        break;
                   case 4:
                        NoQuitFlag = FALSE;
                        break;
              }
              break;
         case EditMenu:
              switch(ItemNum) {
                   case 1:
                        SystemEdit(undoCmd);
                        break;
                   case 3:
                        SystemEdit(cutCmd);
                        break;
                   case 4:
                        SystemEdit(copyCmd);
                        break;
                   case 5:
                        SystemEdit(pasteCmd);
                        break;
                   case 6:
                        SystemEdit(clearCmd);
                        break;
              }
              break;
         case SpecialMenu:
              switch(ItemNum) {
                   case 1:
                        ShutDown();
                        break;
              }
    }

    return NoQuitFlag;
}


/*
* This pops up a dialog for our 'About...' box.
*/

AboutTinyFinder()
{
    int         type, ItemHit;
    Handle      hdl;
    DialogPtr   DPtr;
    Rect        tBox;

    InitCursor();

    DPtr = GetNewDialog(ABOUT_DLOG, nil, (long) -1);
    SetPort(DPtr);

    GetDItem(DPtr, 2, &type, &hdl, &tBox);             /* icon */
    PlotIcon(&tBox, GetIcon(256));

    PenPat(&gray);
    GetDItem(DPtr, 6, &type, &hdl, &tBox);             /* dividing line */
    MoveTo(tBox.left, tBox.top);
    LineTo(tBox.right, tBox.top);

    GetDItem(DPtr, 7, &type, &hdl, &tBox);             /* dividing line */
    MoveTo(tBox.left, tBox.top);
    LineTo(tBox.right, tBox.top);
    PenPat(&black);

    while(1) {
         ModalDialog(nil, &ItemHit);
         if(ItemHit == 1) {
              CloseDialog(DPtr);                       /* 'OK' */
              break;
         }
    }
}


/*
* Check to see if the file named 'Finder' exists on the default volume.
* If not, then disable the command in the 'File' menu that allows the user to
* launch the Apple Finder.  Note that this is fairly dumb, in that if it
* finds ANY file named 'Finder' it thinks it is the one.  Could be made
* smarter by checking the type and creator bytes for the file, but I
* didn't feel that I should, in case there is an application by that name.
*/

CheckForFinder()
{
    Finfo fndrInfo;

    if(GetFInfo("\006Finder", 0, &fndrInfo) < 0)       /* use default volume */
         DisableItem(TFMenu[1], 2);
}


/*
* Create our menu bar.
*/

FormMenuBar()
{
    int  i;

    TFMenu[0] = GetMenu(AppleMenu);
    TFMenu[1] = GetMenu(FileMenu);
    TFMenu[2] = GetMenu(EditMenu);
    TFMenu[3] = GetMenu(SpecialMenu);
    AddResMenu(TFMenu[0], 'DRVR');

    for(i = 0;i < NUM_MENUS;++i)
         InsertMenu(TFMenu[i], 0);

    DrawMenuBar();
}


/*
* This alert takes care of our general error messages.  We can
* pass up to four Str255 types (pointers to them, that is), and
* they are combined end to end with a single space between them.
*/

GeneralError(str1, str2, str3, str4)
char *str1, *str2, *str3, *str4;                        /* Pascal format */
{
    InitCursor();
    ParamText("\000", "\000", "\000", "\000");
    ParamText(str1, str2, str3, str4);
    StopAlert(GENERAL_ERROR_ALRT, nil);
}


/*
* Launch the Apple Finder.  This command is disabled in the menu bar
* if the program does not find the Finder on the default disk when
* we boot up and begin execution.
*/

GoFinder()
{
    long zeroes = 0;

    Launch("\006Finder", &zeroes);
}


/*
* Come here when the 'Launch' menu command is given.
*/

LaunchAppl()
{
    long        zeroes = 0;
    short       numTypes = 1;
    Ptr         prompt = nil;
    Ptr         fileFilter = nil;
    Handle      hdl;
    SFReply     rec;
    SFTypeList  typeList;

    typeList[0] = 'APPL';              /* filter out all but 'APPL' types */

    SFGetFile(pass(whereOpen), prompt, fileFilter, numTypes, typeList, nil, &rec);

    if(rec.good == 0)                          /* 'Cancel' button hit */
         return;

    if(SetVol(nil, rec.vRefNum) < 0) {         /* set the new default volume */
         hdl = GetString(256);
         GeneralError(*hdl, nil, nil, nil);
         return;
    }

    Launch(rec.fName, &zeroes);
}


/*
* This is the equivalent of Apple Finder v4.1's 'Shut Down' command,
* in which the diskettes are ejected from the internal & external
* drives and a system reset is issued.  Any other volumes that happen
* to be mounted will NOT be handled.
*/

ShutDown()
{
    int  vRefNum;
    long freeBytes;
    char volName[256];

    GetVInfo(1, volName, &vRefNum, &freeBytes);        /* internal drive */
    Eject(volName, vRefNum);

    if(GetVInfo(2, volName, &vRefNum, &freeBytes) != ParamErr) /* external */
         Eject(volName, vRefNum);


               /* pulse the 68000's RESET pin via a direct assembler call */
#asm

    Reset

#endasm
}