/*  Project leowl_2
	 xor@frognet.net
	 Copyright © 1996. Andrey B. Yastrebov. All Rights Reserved.

	 SUBSYSTEM:    leowl_2.exe Application
	 FILE:         leowl_2.cpp
	 AUTHOR:       Andrey B. Yastrebov


	 OVERVIEW
	 ========
	 Source file for implementation of leowl_2 (TApplication).
*/


#include <owl\owlpch.h>
#pragma hdrstop

#include <dir.h>

#include "leowl_2.h"
#include "leowl_2c.h"
#include "leowl_2z.h"                        // Definition of about dialog.

// Name of desktop file
const char DesktopFile[] = "LEOWL_2.DSK";

// Drag / Drop support:
TFileDrop::TFileDrop (char* fileName, TPoint& p, BOOL inClient, TModule*)
{
    char    exePath[MAXPATH];

    exePath[0] = 0;
    FileName = strcpy(new char[strlen(fileName) + 1], fileName);
    Point = p;
    InClientArea = inClient;
}

TFileDrop::~TFileDrop ()
{
    delete FileName;
}

const char *TFileDrop::WhoAmI ()
{
  return FileName;
}


//{{leowl_2 Implementation}}


//
// Build a response table for all messages/commands handled
// by the application.
//
DEFINE_RESPONSE_TABLE1(leowl_2, TApplication)
//{{leowl_2RSP_TBL_BEGIN}}
    EV_COMMAND(CM_HELPABOUT, CmHelpAbout),
    EV_WM_DROPFILES,
    EV_COMMAND(CM_DESKTOPRESTORE, CmDesktopRestore),
    EV_COMMAND(CM_DESKTOPSAVE, CmDesktopSave),
//{{leowl_2RSP_TBL_END}}
END_RESPONSE_TABLE;

IMPLEMENT_STREAMABLE1(leowl_2, TApplication);
//////////////////////////////////////////////////////////
// leowl_2
// =====
//
leowl_2::leowl_2 () : TApplication("leowl_2")
{
}


leowl_2::~leowl_2 ()
{
}

//////////////////////////////////////////////////////////
// leowl_2
// =====
// Application intialization.
//
void leowl_2::InitMainWindow ()
{
    if (nCmdShow != SW_HIDE)
        nCmdShow = (nCmdShow != SW_SHOWMINNOACTIVE) ? SW_SHOWNORMAL : nCmdShow;

    mdiClient = new leowl_2MDIClient;
    TDecoratedMDIFrame* frame =
      new TDecoratedMDIFrame(Name, MDI_MENU, *mdiClient, TRUE);

    // Set the client area to the application workspace color.
    frame->SetBkgndColor(::GetSysColor(COLOR_APPWORKSPACE));

    //
    // Assign ICON w/ this application.
    //
    frame->SetIcon(this, IDI_MDIAPPLICATION);

    //
    // Menu associated with window and accelerator table associated with table.
    //
    frame->AssignMenu(MDI_MENU);

    //
    // Associate with the accelerator table.
    //
    frame->Attr.AccelTable = MDI_MENU;

    //
    // Insert Control Bar
    //
	 TControlBar* cb = new TControlBar(frame);
	 cb->Insert(*new TButtonGadget(CM_MDIFILENEW, CM_MDIFILENEW));
	 cb->Insert(*new TButtonGadget(CM_MDIFILEOPEN, CM_MDIFILEOPEN));
    cb->Insert(*new TButtonGadget(CM_FILESAVE, CM_FILESAVE));
    cb->Insert(*new TButtonGadget(CM_FILESAVEAS, CM_FILESAVEAS));
    cb->Insert(*new TSeparatorGadget(6));
    cb->Insert(*new TButtonGadget(CM_EDITCUT, CM_EDITCUT));
    cb->Insert(*new TButtonGadget(CM_EDITCOPY, CM_EDITCOPY));
    cb->Insert(*new TButtonGadget(CM_EDITPASTE, CM_EDITPASTE));
    cb->Insert(*new TSeparatorGadget(6));
    cb->Insert(*new TButtonGadget(CM_EDITUNDO, CM_EDITUNDO));
    cb->Insert(*new TButtonGadget(CM_EDITREDO, CM_EDITREDO));
    cb->Insert(*new TSeparatorGadget(6));
    cb->Insert(*new TButtonGadget(CM_EDITFIND, CM_EDITFIND));
    cb->Insert(*new TButtonGadget(CM_EDITREPLACE, CM_EDITREPLACE));
    cb->Insert(*new TButtonGadget(CM_EDITFINDNEXT, CM_EDITFINDNEXT));

    // Add fly-over help hints.
    cb->SetHintMode(TGadgetWindow::EnterHints);

    frame->Insert(*cb, TDecoratedFrame::Top);

    //
    // Insert Status Bar
    //
    TStatusBar* sb = new TStatusBar(frame, TGadget::Recessed,
    	TStatusBar::CapsLock | TStatusBar::NumLock | TStatusBar::ScrollLock
    	| TStatusBar::Overtype);
    frame->Insert(*sb, TDecoratedFrame::Bottom);

    mdiClient->sB = sb;

	 SetMainWindow(frame);

	 frame->SetMenuDescr(TMenuDescr(MDI_MENU,1,2,1,0,1,1));
}


//////////////////////////////////////////////////////////
// leowl_2
// ===========
// Menu Help About leowl_2.exe command
void leowl_2::CmHelpAbout ()
{
    //
    // Show the modal dialog.
    //
    leowl_2z(MainWindow).Execute();
}


void leowl_2::InitInstance ()
{
    TApplication::InitInstance();

    //
    // Attempt to load desktop from the stream.
    //
    ifpstream is(DesktopFile);
    if (!is.bad())
      {
	is.close();
	CmDesktopRestore();
      }

    // Accept files via drag/drop in the frame window.
    GetMainWindow()->DragAcceptFiles(TRUE);

    if (_argc > 1) for (int i = 1; i < _argc; i++)
      mdiClient->OpenFile(_argv[i]);
}


void leowl_2::EvDropFiles (TDropInfo drop)
{
    // Number of files dropped.
    int totalNumberOfFiles = drop.DragQueryFileCount();

    TFileList* files = new TFileList;

    for (int i = 0; i < totalNumberOfFiles; i++)
      {
        // Tell DragQueryFile the file interested in (i)
        // and the length of your buffer.
        int     fileLength = drop.DragQueryFileNameLen(i) + 1;
        char    *fileName = new char[fileLength];

        drop.DragQueryFile(i, fileName, fileLength);

        // Getting the file dropped. The location is relative to your
        // client coordinates, and will have negative values if dropped in
        // the non client parts of the window.
        // DragQueryPoint copies that point where the file was dropped and
        // returns whether or not the point is in the client area.
        // Regardless of whether or not the file is dropped in the client or
        // non-client area of the window, you will still receive
        // the file name.
        TPoint  point;
        BOOL    inClientArea = drop.DragQueryPoint(point);
        files->Add(new TFileDrop(fileName, point, inClientArea, this));
    }

    // Open the files that were dropped.
    AddFiles(files);

    // Release the memory allocated for this handle with DragFinish.
    drop.DragFinish();
}


void leowl_2::AddFiles (TFileList* files)
{
    // Open all files dragged in.
    TFileListIter fileIter(*files);

    TFrameWindow *tfw = GetMainWindow();
    if (tfw)
      {
        leowl_2MDIClient *theClient =
          TYPESAFE_DOWNCAST(tfw->GetClientWindow(), leowl_2MDIClient);

        if (theClient)
            while (fileIter)
              {
                theClient->OpenFile(fileIter.Current()->WhoAmI());
                fileIter++;
              }
    }
}

void leowl_2::CmDesktopRestore ()
{
         //
         // Close all existing children
         //
         mdiClient->CloseChildren();

	 //
	 // Restore Desktop from the stream
	 //
	 ifpstream is(DesktopFile);
	 if (!is.bad())
		{
		  is >> *this;
		  is.close();
		}
}


void leowl_2::CmDesktopSave ()
{
	 //
	 // Save Desktop into the stream
	 //
	 ofpstream os(DesktopFile);
	 if (!os.bad())
		{
		  os.flush();
		  os << *this;
		  os.close();
		}
}

BOOL leowl_2::CanClose ()
{
	 BOOL result = TApplication::CanClose();

    if (result)
      CmDesktopSave();

    return result;
}

void *
leowl_2::Streamer::Read(ipstream& is, uint32) const
{
  leowl_2* Obj = GetObject();
  ReadBaseObject((TApplication*) Obj, is);
  int X,Y,W,H;
  is >> X;
  is >> Y;
  is >> W;
  is >> H;
  is >> *(Obj->mdiClient);
  TMDIChild* active;
  is >> active;

  // Finally, create the interface objects for our children,
  // restoring the active window.
  Obj->mdiClient->CreateChildren();
  if (active)
     Obj->mdiClient->HandleMessage(WM_MDIACTIVATE,(UINT)active->HWindow);

  Obj->MainWindow->MoveWindow(X,Y,W,H,TRUE);
  return Obj;
}

void
leowl_2::Streamer::Write(opstream& os) const
{
  leowl_2* Obj = GetObject();
  WriteBaseObject((TApplication*) Obj, os);
  TFrameWindow* fW = Obj->GetMainWindow();
  os << fW->Attr.X;
  os << fW->Attr.Y;
  os << fW->Attr.W;
  os << fW->Attr.H;
  os << *(Obj->mdiClient);
  os << Obj->mdiClient->GetActiveMDIChild();
}


//
// Main procedure
//
int OwlMain (int , char* [])
{
    try {
        leowl_2    app;
        return app.Run();
    }
    catch (xmsg& x) {
        ::MessageBox(0, x.why().c_str(), "Exception", MB_OK);
    }

    return -1;
}



