| Current Path : /var/www/html/prashantkr/TurboC/TCWIN45/SOURCE/OWL/ |
| Current File : /var/www/html/prashantkr/TurboC/TCWIN45/SOURCE/OWL/APPLICAT.CPP |
//----------------------------------------------------------------------------
// ObjectWindows
// (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
//
// Implementation of class TApplication. This defines the basic behavior
// for ObjectWindows applications.
//----------------------------------------------------------------------------
#pragma hdrignore SECTION
#include <owl/owlpch.h>
#include <owl/applicat.h>
#include <owl/framewin.h>
#include <owl/docmanag.h>
#include <owl/appdict.h>
#if defined(SECTION) && SECTION != 1
DIAG_DECLARE_GROUP(OwlApp); // General Application diagnostic group
#endif
#if !defined(SECTION) || SECTION == 1
DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlApp, 1, 0);
//
// Static members for initialization
//
HINSTANCE TApplication::InitHInstance;
HINSTANCE TApplication::InitHPrevInstance;
string TApplication::InitCmdLine;
int TApplication::InitCmdShow;
//
// Global GetWindowPtr() message id used for registered message
//
uint _OWLDATA GetWindowPtrMsgId = 0;
//
// Constructor for use in OwlMain(). Gets members from statics set earlier by
// a call to InitWinMainParams() in Owl's WinMain.
//
TApplication::TApplication(const char far* name, TModule*& gModule,
TAppDictionary* appDict)
:
TModule(name, InitHInstance, InitCmdLine.c_str()),
XBase(0), XState(0), DocManager(0),
Dictionary(appDict ? appDict : &::OwlAppDictionary)
{
// Copy over values that were stashed in static members before this instance
// was constructed.
//
hPrevInstance = InitHPrevInstance;
nCmdShow = InitCmdShow;
MainWindow = 0;
HAccTable = 0;
BreakMessageLoop = false;
BWCCOn = Ctl3dOn = false;
BWCCModule = Ctl3dModule = 0;
Running = false;
CondemnedWindows = 0;
CmdLine = InitCmdLine;
Dictionary->Add(this);
gModule = this;
}
//
// Constructor for use in user defined WinMain() when all the args are
// available
//
TApplication::TApplication(const char far* name,
HINSTANCE instance,
HINSTANCE prevInstance,
const char far* cmdLine,
int cmdShow,
TModule*& gModule,
TAppDictionary* appDict)
:
TModule(name, instance, cmdLine),
XBase(0), XState(0), DocManager(0),
Dictionary(appDict ? appDict : &::OwlAppDictionary)
{
hPrevInstance = prevInstance;
nCmdShow = cmdShow;
MainWindow = 0;
HAccTable = 0;
BreakMessageLoop = false;
BWCCOn = Ctl3dOn = false;
BWCCModule = Ctl3dModule = 0;
Running = false;
CondemnedWindows = 0;
CmdLine = cmdLine;
Dictionary->Add(this);
gModule = this;
}
//
//
//
TApplication::~TApplication()
{
DeleteCondemned();
// Unregister ourselves from the Ctl3d DLL and/or the BWCC DLL if they are
// loaded.
//
if (Ctl3dModule) {
bool FAR PASCAL(*Ctl3dUnregister)(HANDLE);
(FARPROC)Ctl3dUnregister = Ctl3dModule->GetProcAddress("Ctl3dUnregister");
if (Ctl3dUnregister)
Ctl3dUnregister(*this);
delete Ctl3dModule;
}
if (BWCCModule) {
bool FAR PASCAL(*bwccIntlTerm)(void);
(FARPROC)bwccIntlTerm = BWCCModule->GetProcAddress("BWCCIntlTerm");
if (bwccIntlTerm)
bwccIntlTerm();
delete BWCCModule;
}
// Delete the main window if still present, may be destroyed but not deleted
// Set MainWindow to 0 to prevent calling ::PostQuitMessage
//
TWindow* mainWindow = SetMainWindow(0);
if (mainWindow) {
mainWindow->Destroy();
delete mainWindow;
}
delete (TStreamableBase*)DocManager;// cast to avoid ref to docmgr if not used
// Remove ourselves from the application dictionary that we are in
//
Dictionary->Remove(this);
delete XBase; // remove any exception copy
}
//
// Handle initialization for the first executing instance of the OWL
// application
//
void
TApplication::InitApplication()
{
}
//
// Handle initialization for each executing instance of the OWL
// application
//
// This implementation creates and displays the main window
//
void
TApplication::InitInstance()
{
InitMainWindow();
if (MainWindow) {
MainWindow->SetFlag(wfMainWindow);
MainWindow->Create();
MainWindow->Show(nCmdShow);
}
else
THROW( TXInvalidMainWindow() );
}
//
// Initialize the application's main window
//
// Default main window title is the same as the applications
//
void
TApplication::InitMainWindow()
{
SetMainWindow(new TFrameWindow(0, GetName()));
}
//
// Handle termination for each executing instance of the application
//
int
TApplication::TermInstance(int status)
{
return status;
}
//
// Set (or reset) the main window. Returns, but does not destroy the
// previous main window.
//
TFrameWindow*
TApplication::SetMainWindow(TFrameWindow* window)
{
if (MainWindow)
MainWindow->ClearFlag(wfMainWindow);
TFrameWindow* oldMainWindow = MainWindow;
MainWindow = window;
if (MainWindow)
MainWindow->SetFlag(wfMainWindow);
return oldMainWindow;
}
//
// Sets (or resets) the document manager, returns the previous one if present
//
TDocManager*
TApplication::SetDocManager(TDocManager* docManager)
{
TDocManager* oldDocManager = DocManager;
DocManager = docManager;
return oldDocManager;
}
#if defined(BI_PLAT_WIN32)
//
// overrides TEventHandler::Dispatch() to handle multi-thread synchonization
//
LRESULT TApplication::Dispatch(TEventInfo& info, WPARAM wp, LPARAM lp)
{
TApplication::TAppLock Lock(*this);
return TModule::Dispatch(info, wp, lp);
}
int TApplication::TAppMutex::NotWIN32s =
!( (::GetVersion()&0x80000000) && (::GetVersion()&0xFF) < 4);
#endif
//
// default idle action is to forward the action to the main window.
//
bool
TApplication::IdleAction(long idleCount)
{
if (MainWindow)
return MainWindow->IdleAction(idleCount);
return 0;
}
//
// Run this application, return when finished
//
// Initializes instances, creating and displaying their main window (calls
// InitApplication for the first executing instance and calls InitInstance for
// all instances). Runs the application's message loop. Each of the virtual
// functions called are expected to throw an exception if there is an error.
//
int
TApplication::Run()
{
int status;
TRY {
if (!MainWindow) {
if (!hPrevInstance)
InitApplication();
InitInstance();
}
Running = true;
status = MessageLoop();
}
CATCH( (TXOwl& x) {status = x.Unhandled(this, 0);})
CATCH( (xmsg& x) {status = Error(x, 0);})
CATCH( (Bad_cast& x) {status = Error(xmsg(string(typeid(x).name())), 0);} )
CATCH( (Bad_typeid& x) {status = Error(xmsg(string(typeid(x).name())), 0);} )
MSG msg;
while (::PeekMessage(&msg,0,0,0,PM_NOYIELD|PM_REMOVE)
&& msg.message != WM_PAINT) ; // flush queue
Running = false;
return TermInstance(status);
}
//
// Start this application and return immediately
//
// Initializes instances, creating and displaying their main window (calls
// InitApplication for the first executing instance and calls InitInstance for
// all instances). Each of the virtual functions called are expected to throw an
// exception if there is an error. Does not run message loop.
//
int
TApplication::Start()
{
int status = 0;
TRY {
if (!hPrevInstance)
InitApplication();
InitInstance();
}
CATCH( (TXOwl& x) {status = x.Unhandled(this, 0);})
CATCH( (xmsg& x) {status = Error(x, 0);})
CATCH( (Bad_cast& x) {status = Error(xmsg(string(typeid(x).name())), 0);} )
CATCH( (Bad_typeid& x) {status = Error(xmsg(string(typeid(x).name())), 0);} )
return status;
}
//
// Called after each message is pulled from the queue, and before it is
// dispatched. Return true if the message was handled completely here.
//
bool
TApplication::ProcessAppMsg(MSG& msg)
{
// start with the window that the event was destined for and allow it
// and its parent (and its parent...) an opportunity to preprocess the
// event
//
for (HWND hWnd = msg.hwnd; hWnd; hWnd = ::GetParent(hWnd)) {
TWindow* win = GetWindowPtr(hWnd);
if (win && win->PreProcessMsg(msg))
return true;
}
// for compatability with OWL 1.0, check the application's accelerator
// table if it is being used
//
// NOTE: we should only support this for one rev...
//
if (HAccTable && MainWindow)
return ::TranslateAccelerator(MainWindow->HWindow, HAccTable, &msg);
return false;
}
//
// Called after each message dispatch when TApplication's message loop is not
// being used.
//
void
TApplication::PostDispatchAction()
{
DeleteCondemned();
ResumeThrow();
MSG msg;
if (!::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE))
IdleAction(0);
}
//
// Lowlevel message loop: retrieves and processes messages from the OWL
// application's message queue until it is empty
//
// calls ProcessAppMsg() to allow special pre-handling of the message
//
bool
TApplication::PumpWaitingMessages()
{
MSG msg;
bool foundOne = false;
while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
foundOne = true;
if (msg.message == WM_QUIT) {
BreakMessageLoop = true;
MessageLoopResult = msg.wParam;
::PostQuitMessage(msg.wParam); // make sure all loops exit
break;
}
// Let the app preprocess the message. If it is not eaten, then translate
// it, & dispatch it. If no hwnd, then first find/dispatch it directly to
// the app (for PostAppMessage() functionality)
//
if (!ProcessAppMsg(msg)) {
::TranslateMessage(&msg);
if (!msg.hwnd) {
TEventInfo cmdEventInfo(msg.message, msg.wParam);
if (Find(cmdEventInfo)) {
Dispatch(cmdEventInfo, msg.wParam, msg.lParam);
return true;
}
else {
TEventInfo eventInfo(msg.message);
if (Find(eventInfo)) {
Dispatch(eventInfo, msg.wParam, msg.lParam);
return true;
}
}
}
::DispatchMessage(&msg);
DeleteCondemned();
ResumeThrow();
}
}
return foundOne;
}
//
// Suspend throw functions store away a caught exception to allow foreign code
// to be re-entered. Call ResumeThrow() to rethrow the exception, if any, upon
// return from the foreign code.
//
void
TApplication::SuspendThrow(xalloc& x)
{
XString = x.why();
XSize = x.requested();
XState |= xsAlloc;
}
void
TApplication::SuspendThrow(xmsg& x)
{
XString = x.why();
XState |= xsMsg;
}
void
TApplication::SuspendThrow(TXBase& x)
{
delete XBase; // remove any previous exception
XBase = x.Clone();
XState |= xsBase;
}
void
TApplication::SuspendThrow(int flag)
{
XState |= (flag & (xsBadCast | xsBadTypeid | xsUnknown));
}
void
TApplication::ResumeThrow()
{
if (XState) {
if (XState & xsBase) {
XState &= ~xsBase;
XBase->Throw(); // must be deleted later
}
if (XState & xsAlloc) {
XState &= ~xsAlloc;
THROW( xalloc(XString,XSize) );
}
if (XState & xsMsg) {
XState &= ~xsMsg;
THROW( xmsg(XString) );
}
if (XState & xsUnknown) {
XState &= ~xsUnknown;
THROW( xmsg(string()) );
}
if (XState & xsBadCast) {
XState &= ~xsBadCast;
THROW( Bad_cast() );
}
if (XState & xsBadTypeid) {
XState &= ~xsBadTypeid;
THROW( Bad_typeid() );
}
}
}
//
// General message loop: retrieves and processes messages from the OWL
// application's message queue until BreakMessageLoop becomes true
//
// Calls IdleAction() when there are no messages
//
int
TApplication::MessageLoop()
{
long idleCount = 0;
MessageLoopResult = 0;
while (!BreakMessageLoop) {
TRY {
if (!IdleAction(idleCount++))
::WaitMessage(); // allow system to go idle
if (PumpWaitingMessages()) // pumps any waiting messages
idleCount = 0;
}
CATCH( (TXOwl& x) {
MessageLoopResult = x.Unhandled(this, IDS_OKTORESUME);
if (MessageLoopResult != 0) {
::PostQuitMessage(MessageLoopResult);
break;
}
})
CATCH( (xmsg& x) {
MessageLoopResult = Error(x, 0, IDS_OKTORESUME);
if (MessageLoopResult != 0) {
::PostQuitMessage(MessageLoopResult);
break;
}
})
CATCH( (Bad_cast& x) {
MessageLoopResult = Error(xmsg(string(typeid(x).name())), 0, IDS_OKTORESUME);
if (MessageLoopResult != 0) {
::PostQuitMessage(MessageLoopResult);
break;
}
})
CATCH( (Bad_typeid& x) {
MessageLoopResult = Error(xmsg(string(typeid(x).name())), 0, IDS_OKTORESUME);
if (MessageLoopResult != 0) {
::PostQuitMessage(MessageLoopResult);
break;
}
})
}
BreakMessageLoop = false;
return MessageLoopResult;
}
//
// Default event handling simply defers to the DocManager if it has been
// installed
//
bool
TApplication::Find(TEventInfo &eventInfo, TEqualOperator equal)
{
return DocManager ? DocManager->Find(eventInfo, equal) : false;
}
//
// Determines whether the application can be closed.
// Makes sure the MainWindow can close & doc manager can close.
//
bool
TApplication::CanClose()
{
TEventInfo eventInfo(WM_OWLCANCLOSE);
return (!MainWindow || MainWindow->CanClose())
&& (!DocManager ||!DocManager->Find(eventInfo)
|| DocManager->Dispatch(eventInfo, 0, 0));
}
//
// Oportunity to preprocess the main window's menubar before it is installed.
// Normally delegated to the doc manager to install a file menu as needed
//
void
TApplication::PreProcessMenu(HMENU fmenu)
{
TEventInfo eventInfo(WM_OWLPREPROCMENU);
if (DocManager && DocManager->Find(eventInfo)) {
DocManager->Dispatch(eventInfo, (WPARAM)fmenu, 0);
MainWindow->DrawMenuBar();
}
}
//
// Condemn a window to be deleted the at the next available safe time.
// Adds the window to a normal single linked list
//
// Condemned windows should be removed if they are destructed in the mean time
// thru some other mechanism (i.e. stack, aggregate, etc)
//
void
TApplication::Condemn(TWindow* win)
{
TRACEX(OwlApp, 1, "Condemning window: " << *win);
win->SetParent(0);
win->SetNext(CondemnedWindows);
CondemnedWindows = win;
}
//
// Remove a condemned window from the list.
//
void
TApplication::Uncondemn(TWindow* win)
{
if (win && CondemnedWindows) {
TWindow* w = 0;
if (CondemnedWindows != win)
for (w = CondemnedWindows; w->Next() != win; w = w->Next())
if (!w->Next())
return;
TRACEX(OwlApp, 1, "Uncondemning window: " << *win);
if (w)
w->SetNext(win->Next());
else
CondemnedWindows = win->Next();
}
}
//
// Walk the condemned window list & delete each window. Assumes that the
// windows were constructed using 'new'
//
void
TApplication::DeleteCondemned()
{
while (CondemnedWindows) {
TRACEX(OwlApp, 1, "Deleting condemned window: " << *CondemnedWindows);
TWindow* next = CondemnedWindows->Next();
delete CondemnedWindows;
CondemnedWindows = next;
}
}
TApplication::TXInvalidMainWindow::TXInvalidMainWindow()
:
TXOwl(IDS_INVALIDMAINWINDOW)
{
}
TApplication::TXInvalidMainWindow::~TXInvalidMainWindow()
{
}
TApplication::TXInvalidMainWindow*
TApplication::TXInvalidMainWindow::Clone()
{
return new TXInvalidMainWindow(*this);
}
void
TApplication::TXInvalidMainWindow::Throw()
{
THROW( *this );
}
#endif
//----------------------------------------------------------------------------
#if !defined(SECTION) || SECTION == 2
struct TEnumInfo {
HWND ModalWnd; // The window being made modal if needed
short Count; // Count of windows in Wnds below
HWND* Wnds; // list of windows that were disabled
};
static TEnumInfo* stackTop = 0; // points to topmost enuminfo in BeginModal calls
//
// Enum[Thread/Task]Windows callback. Counts or disables given window based on
// whether or not window list has been allocated yet.
//
bool CALLBACK __export
DisableWnds(HWND wnd, TEnumInfo far* ei)
{
if (!(::GetWindowLong(wnd, GWL_STYLE) & WS_CHILD)) {
if (wnd != ei->ModalWnd && ::IsWindowEnabled(wnd)) {
if (!ei->Wnds) {
ei->Count++; // no buffer yet, we are just counting
}
else {
*(ei->Wnds++) = wnd;
::EnableWindow(wnd, false);
}
}
}
return true;
}
//
// Terminate the modal state initiated by BeginModal. Needs topmost ei block,
// and cleans the block up as needed inorder to be safe to be called twice.
//
static void termModal(TEnumInfo& ei)
{
//
// Re-enable window(s) that are disabled in BeginModal()
//
if (ei.Wnds) {
for (HWND* wnd = ei.Wnds; *wnd; wnd++)
::EnableWindow(*wnd, true);
delete[] ei.Wnds;
ei.Wnds = 0;
}
else {
if (ei.ModalWnd && IsWindow(ei.ModalWnd)) {
::EnableWindow(ei.ModalWnd, true);
ei.ModalWnd = 0;
}
}
}
//
// Go modal and enter a message loop until a quit message goes by.
// the flag values determine how window is used:
// MB_APPLMODAL - window is the owner to disable (if 0, none are disabled)
// MB_TASKMODAL - window is the window to make modal,
// all other top level windows are disabled
// MB_SYSTEMMODAL - window is the window to make system modal
// returns -1 on errors
//
int
TApplication::BeginModal(TWindow* window, int flags)
{
TEnumInfo ei = { 0, 0, 0 };
TEnumInfo* lastStackTop = stackTop; // keep last stackTop to restore later
stackTop = &ei; // point stackTop to topmost ei
// Set modal state
//
if (flags & MB_TASKMODAL) {
if (window)
ei.ModalWnd = window->HWindow; // don't disable the modal window if exists
// count windows to disable
//
#if defined(BI_PLAT_WIN32)
if (!EnumThreadWindows(GetCurrentThreadId(), (WNDENUMPROC)DisableWnds,
(LPARAM)(TEnumInfo far*)&ei))
return -1;
#else
if (!EnumTaskWindows(GetCurrentTask(), (WNDENUMPROC)DisableWnds,
(LPARAM)(TEnumInfo far*)&ei))
return -1;
#endif
// Allocate list of windows to disable, disable windows that are
// enabled and then stuff them into the list.
//
HWND* wnds = ei.Wnds = new HWND[ei.Count + 1];
memset(ei.Wnds, 0, sizeof(HWND)*(ei.Count + 1));
#if defined(BI_PLAT_WIN32)
EnumThreadWindows(GetCurrentThreadId(), (WNDENUMPROC)DisableWnds,
(LPARAM)(TEnumInfo far*)&ei);
#else
EnumTaskWindows(GetCurrentTask(), (WNDENUMPROC)DisableWnds,
(LPARAM)(TEnumInfo far*)&ei);
#endif
ei.Wnds = wnds; // restore alloc'd pointer since enumerator bumps it
}
#if defined(BI_PLAT_WIN16)
else if (flags & MB_SYSTEMMODAL)
window->SetSysModalWindow();
#endif
else if (window) {
ei.ModalWnd = window->HWindow; // remember who to re-enable later
window->EnableWindow(false);
}
// Enter message loop, saving & restoring the current status & getting the
// returned result.
//
int result;
TRY {
result = MessageLoop();
}
CATCH( (...) {
termModal(ei);
stackTop = lastStackTop;
RETHROW;
})
stackTop = lastStackTop;
termModal(ei); // just in case termModal was missed in EndModal
// return the result from the modal window's EndModal call
//
return result;
}
//
// Cause the current modal message loop to break and have it return a result
// Re-enable the disabled windows here, if the EnumInfo is available.
//
void
TApplication::EndModal(int result)
{
MessageLoopResult = result;
BreakMessageLoop = true;
if (stackTop)
termModal(*stackTop);
}
#endif
//----------------------------------------------------------------------------
#if !defined(SECTION) || SECTION == 3
//
// Predefined DLLs that TApplication knows how to find.
//
#if defined(BI_PLAT_WIN32)
const char BwccDllName[] = "BWCC32.DLL";
const char Ctl3dDllName[] = "CTL3D32.DLL";
#elif defined(BI_PLAT_WIN16)
const char BwccDllName[] = "BWCC.DLL";
const char Ctl3dDllName[] = "CTL3DV2.DLL";
#endif
//
// Load the BWCC DLL if needed & set the BWCC on flag according to 'enable'
// Library is not free'd on disable to reduce re-loads if enabling on the fly
//
void
TApplication::EnableBWCC(bool enable, uint language)
{
if (enable) {
if (!BWCCModule) {
BWCCModule = new TModule(BwccDllName, true);
bool FAR PASCAL(*bwccIntlInit)(uint);
(FARPROC)bwccIntlInit = BWCCModule->GetProcAddress("BWCCIntlInit");
if (bwccIntlInit)
bwccIntlInit(language);
bool FAR PASCAL(*bwccRegister)(HINSTANCE);
(FARPROC)bwccRegister = BWCCModule->GetProcAddress("BWCCRegister");
if (bwccRegister)
bwccRegister(GetInstance());
}
BWCCOn = true;
}
else
BWCCOn = false;
}
//
// enable or disable the use of the CTL3D DLL. Loads it if needed.
//
void
TApplication::EnableCtl3d(bool enable)
{
//
// If we are running Win4.0 or greater, then ctl3d is unnecessary
//
#if defined(BI_PLAT_WIN32)
if ((::GetVersion()&0xFF) >= 4)
#else
if ((::GetVersion()&0xFF) >= 3 && ((::GetVersion()>>8)&0xFF) >= 95)
#endif
return;
//
// Load the Ctl3d DLL if needed & register our instance
//
if (enable) {
if (!Ctl3dModule) {
Ctl3dModule = new TModule(Ctl3dDllName, true);
bool FAR PASCAL(*ctl3dRegister)(HANDLE);
(FARPROC)ctl3dRegister = Ctl3dModule->GetProcAddress("Ctl3dRegister");
if (ctl3dRegister)
ctl3dRegister(*this);
else {
delete Ctl3dModule;
Ctl3dModule = 0;
return; // could not register--don't change Ctl3dOn flag
}
}
}
Ctl3dOn = enable;
}
//
// enable or disable CTL3D's use of auto-subclassing. Turn on autosubclassing
// before creating a non-owl dialog to make it 3d, & turn it off immediatly
// after.
//
void
TApplication::EnableCtl3dAutosubclass(bool enable)
{
if (Ctl3dEnabled()) {
if (enable) {
bool FAR PASCAL(*ctl3dRegister)(HANDLE);
(FARPROC)ctl3dRegister = Ctl3dModule->GetProcAddress("Ctl3dRegister");
if (ctl3dRegister) {
ctl3dRegister(*this);
bool FAR PASCAL(*ctl3dAutoSubclass)(HANDLE);
(FARPROC)ctl3dAutoSubclass = Ctl3dModule->GetProcAddress("Ctl3dAutoSubclass");
if (ctl3dAutoSubclass)
ctl3dAutoSubclass(*this);
}
}
else {
bool FAR PASCAL(*Ctl3dUnregister)(HANDLE);
(FARPROC)Ctl3dUnregister = Ctl3dModule->GetProcAddress("Ctl3dUnregister");
if (Ctl3dUnregister)
Ctl3dUnregister(*this);
}
}
}
#endif
//----------------------------------------------------------------------------
#if !defined(SECTION) || SECTION == 4
IMPLEMENT_STREAMABLE1(TApplication, TModule);
void*
TApplication::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
TApplication* o = GetObject();
if (o != ::Module)
is >> *::Module; // set reference to OWL module
return o;
}
void
TApplication::Streamer::Write(opstream& os) const
{
TApplication* o = GetObject();
if (o != ::Module)
os << *::Module; // write out reference to OWL module, no data written
}
#endif // SECTION