home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / APPLICAT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  23.4 KB  |  900 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Implementation of class TApplication. This defines the basic behavior
  6. //   for ObjectWindows applications.
  7. //----------------------------------------------------------------------------
  8. #pragma hdrignore SECTION
  9. #include <owl/owlpch.h>
  10. #include <owl/applicat.h>
  11. #include <owl/framewin.h>
  12. #include <owl/docmanag.h>
  13. #include <owl/appdict.h>
  14.  
  15. #if defined(SECTION) && SECTION != 1
  16. DIAG_DECLARE_GROUP(OwlApp);        // General Application diagnostic group
  17. #endif
  18.  
  19. #if !defined(SECTION) || SECTION == 1
  20.  
  21. DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlApp, 1, 0);
  22.  
  23. //
  24. // Static members for initialization
  25. //
  26. HINSTANCE  TApplication::InitHInstance;
  27. HINSTANCE  TApplication::InitHPrevInstance;
  28. string     TApplication::InitCmdLine;
  29. int        TApplication::InitCmdShow;
  30.  
  31. //
  32. // Global GetWindowPtr() message id used for registered message
  33. //
  34. uint _OWLDATA GetWindowPtrMsgId = 0;
  35.  
  36. //
  37. // Constructor for use in OwlMain(). Gets members from statics set earlier by
  38. // a call to InitWinMainParams() in Owl's WinMain.
  39. //
  40. TApplication::TApplication(const char far* name, TModule*& gModule,
  41.                            TAppDictionary* appDict)
  42. :
  43.   TModule(name, InitHInstance, InitCmdLine.c_str()),
  44.   XBase(0), XState(0), DocManager(0),
  45.   Dictionary(appDict ? appDict : &::OwlAppDictionary)
  46. {
  47.   // Copy over values that were stashed in static members before this instance
  48.   // was constructed.
  49.   //
  50.   hPrevInstance = InitHPrevInstance;
  51.   nCmdShow = InitCmdShow;
  52.  
  53.   MainWindow = 0;
  54.   HAccTable = 0;
  55.   BreakMessageLoop = false;
  56.   BWCCOn = Ctl3dOn = false;
  57.   BWCCModule = Ctl3dModule = 0;
  58.   Running = false;
  59.   CondemnedWindows = 0;
  60.   CmdLine = InitCmdLine;
  61.  
  62.   Dictionary->Add(this);
  63.   gModule = this;
  64. }
  65.  
  66. //
  67. // Constructor for use in user defined WinMain() when all the args are
  68. // available
  69. //
  70. TApplication::TApplication(const char far* name,
  71.                            HINSTANCE       instance,
  72.                            HINSTANCE       prevInstance,
  73.                            const char far* cmdLine,
  74.                            int             cmdShow,
  75.                            TModule*&       gModule,
  76.                            TAppDictionary* appDict)
  77. :
  78.   TModule(name, instance, cmdLine),
  79.   XBase(0), XState(0), DocManager(0),
  80.   Dictionary(appDict ? appDict : &::OwlAppDictionary)
  81. {
  82.   hPrevInstance = prevInstance;
  83.   nCmdShow = cmdShow;
  84.   MainWindow = 0;
  85.   HAccTable = 0;
  86.   BreakMessageLoop = false;
  87.   BWCCOn = Ctl3dOn = false;
  88.   BWCCModule = Ctl3dModule = 0;
  89.   Running = false;
  90.   CondemnedWindows = 0;
  91.   CmdLine = cmdLine;
  92.   
  93.   Dictionary->Add(this);
  94.   gModule = this;
  95. }
  96.  
  97. //
  98. //
  99. //
  100. TApplication::~TApplication()
  101. {
  102.   DeleteCondemned();
  103.   
  104.   // Unregister ourselves from the Ctl3d DLL and/or the BWCC DLL if they are
  105.   // loaded.
  106.   //
  107.   if (Ctl3dModule) {
  108.     bool FAR PASCAL(*Ctl3dUnregister)(HANDLE);
  109.     (FARPROC)Ctl3dUnregister = Ctl3dModule->GetProcAddress("Ctl3dUnregister");
  110.     if (Ctl3dUnregister)
  111.       Ctl3dUnregister(*this);
  112.     delete Ctl3dModule;
  113.   }
  114.   if (BWCCModule) {
  115.     bool FAR PASCAL(*bwccIntlTerm)(void);
  116.     (FARPROC)bwccIntlTerm = BWCCModule->GetProcAddress("BWCCIntlTerm");
  117.     if (bwccIntlTerm)
  118.       bwccIntlTerm();
  119.     delete BWCCModule;
  120.   }
  121.  
  122.   // Delete the main window if still present, may be destroyed but not deleted
  123.   // Set MainWindow to 0 to prevent calling ::PostQuitMessage
  124.   //
  125.   TWindow* mainWindow = SetMainWindow(0);
  126.   if (mainWindow) {
  127.     mainWindow->Destroy();
  128.     delete mainWindow;
  129.   }
  130.  
  131.   delete (TStreamableBase*)DocManager;// cast to avoid ref to docmgr if not used
  132.  
  133.   // Remove ourselves from the application dictionary that we are in
  134.   //
  135.   Dictionary->Remove(this);
  136.   delete XBase;   // remove any exception copy
  137. }
  138.  
  139. //
  140. // Handle initialization for the first executing instance of the OWL
  141. // application
  142. //
  143. void
  144. TApplication::InitApplication()
  145. {
  146. }
  147.  
  148. //
  149. // Handle initialization for each executing instance of the OWL
  150. // application
  151. //
  152. // This implementation creates and displays the main window
  153. //
  154. void
  155. TApplication::InitInstance()
  156. {
  157.   InitMainWindow();
  158.  
  159.   if (MainWindow) {
  160.     MainWindow->SetFlag(wfMainWindow);
  161.     MainWindow->Create();
  162.     MainWindow->Show(nCmdShow);
  163.   }
  164.   else
  165.     THROW( TXInvalidMainWindow() );
  166. }
  167.  
  168. //
  169. // Initialize the application's main window
  170. //
  171. // Default main window title is the same as the applications
  172. //
  173. void
  174. TApplication::InitMainWindow()
  175. {
  176.   SetMainWindow(new TFrameWindow(0, GetName()));
  177. }
  178.  
  179. //
  180. // Handle termination for each executing instance of the application
  181. //
  182. int
  183. TApplication::TermInstance(int status)
  184. {
  185.   return status;
  186. }
  187.  
  188. //
  189. // Set (or reset) the main window. Returns, but does not destroy the
  190. // previous main window.
  191. //
  192. TFrameWindow*
  193. TApplication::SetMainWindow(TFrameWindow* window)
  194. {
  195.   if (MainWindow)
  196.     MainWindow->ClearFlag(wfMainWindow);
  197.   TFrameWindow* oldMainWindow = MainWindow;
  198.   MainWindow = window;
  199.   if (MainWindow)
  200.     MainWindow->SetFlag(wfMainWindow);
  201.   return oldMainWindow;
  202. }
  203.  
  204. //
  205. // Sets (or resets) the document manager, returns the previous one if present
  206. //
  207. TDocManager*
  208. TApplication::SetDocManager(TDocManager* docManager)
  209. {
  210.   TDocManager* oldDocManager = DocManager;
  211.   DocManager = docManager;
  212.   return oldDocManager;
  213. }
  214.  
  215. #if defined(BI_PLAT_WIN32)
  216. //
  217. // overrides TEventHandler::Dispatch() to handle multi-thread synchonization
  218. //
  219. LRESULT TApplication::Dispatch(TEventInfo& info, WPARAM wp, LPARAM lp)
  220. {
  221.   TApplication::TAppLock Lock(*this);
  222.   return TModule::Dispatch(info, wp, lp);
  223. }
  224.  
  225. int TApplication::TAppMutex::NotWIN32s =
  226.     !( (::GetVersion()&0x80000000) && (::GetVersion()&0xFF) < 4);
  227. #endif
  228.  
  229. //
  230. // default idle action is to forward the action to the main window.
  231. //
  232. bool
  233. TApplication::IdleAction(long idleCount)
  234. {
  235.   if (MainWindow)
  236.     return MainWindow->IdleAction(idleCount);
  237.   return 0;
  238. }
  239.  
  240. //
  241. // Run this application, return when finished
  242. //
  243. // Initializes instances, creating and displaying their main window (calls
  244. // InitApplication for the first executing instance and calls InitInstance for
  245. // all instances). Runs the application's message loop. Each of the virtual
  246. // functions called are expected to throw an exception if there is an error.
  247. //
  248. int
  249. TApplication::Run()
  250. {
  251.   int status;
  252.   TRY {
  253.     if (!MainWindow) {
  254.       if (!hPrevInstance)
  255.         InitApplication();
  256.       InitInstance();
  257.     }
  258.     Running = true;
  259.     status = MessageLoop();
  260.   }
  261.   CATCH( (TXOwl& x) {status = x.Unhandled(this, 0);})
  262.   CATCH( (xmsg& x) {status = Error(x, 0);})
  263.   CATCH( (Bad_cast& x) {status = Error(xmsg(string(typeid(x).name())), 0);} )
  264.   CATCH( (Bad_typeid& x) {status = Error(xmsg(string(typeid(x).name())), 0);} )
  265.  
  266.   MSG msg;
  267.   while (::PeekMessage(&msg,0,0,0,PM_NOYIELD|PM_REMOVE)
  268.          && msg.message != WM_PAINT) ; // flush queue
  269.  
  270.   Running = false;
  271.   return TermInstance(status);
  272. }
  273.  
  274. //
  275. // Start this application and return immediately
  276. //
  277. // Initializes instances, creating and displaying their main window (calls
  278. // InitApplication for the first executing instance and calls InitInstance for
  279. // all instances). Each of the virtual functions called are expected to throw an
  280. // exception if there is an error. Does not run message loop.
  281. //
  282. int
  283. TApplication::Start()
  284. {
  285.   int status = 0;
  286.   TRY {
  287.     if (!hPrevInstance)
  288.       InitApplication();
  289.     InitInstance();
  290.   }
  291.   CATCH( (TXOwl& x) {status = x.Unhandled(this, 0);})
  292.   CATCH( (xmsg& x) {status = Error(x, 0);})
  293.   CATCH( (Bad_cast& x) {status = Error(xmsg(string(typeid(x).name())), 0);} )
  294.   CATCH( (Bad_typeid& x) {status = Error(xmsg(string(typeid(x).name())), 0);} )
  295.  
  296.   return status;
  297. }
  298.  
  299. //
  300. // Called after each message is pulled from the queue, and before it is
  301. // dispatched. Return true if the message was handled completely here.
  302. //
  303. bool
  304. TApplication::ProcessAppMsg(MSG& msg)
  305. {
  306.   // start with the window that the event was destined for and allow it
  307.   // and its parent (and its parent...) an opportunity to preprocess the
  308.   // event
  309.   //
  310.   for (HWND hWnd = msg.hwnd; hWnd; hWnd = ::GetParent(hWnd)) {
  311.     TWindow*  win = GetWindowPtr(hWnd);
  312.  
  313.     if (win && win->PreProcessMsg(msg))
  314.       return true;
  315.   }
  316.  
  317.   // for compatability with OWL 1.0, check the application's accelerator
  318.   // table if it is being used
  319.   //
  320.   // NOTE: we should only support this for one rev...
  321.   //
  322.   if (HAccTable && MainWindow)
  323.     return ::TranslateAccelerator(MainWindow->HWindow, HAccTable, &msg);
  324.  
  325.   return false;
  326. }
  327.  
  328. //
  329. // Called after each message dispatch when TApplication's message loop is not
  330. // being used.
  331. //
  332. void
  333. TApplication::PostDispatchAction()
  334. {
  335.   DeleteCondemned();
  336.   ResumeThrow();
  337.  
  338.   MSG msg;
  339.   if (!::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE))
  340.     IdleAction(0);
  341. }
  342.  
  343. //
  344. // Lowlevel message loop: retrieves and processes messages from the OWL
  345. // application's message queue until it is empty
  346. //
  347. // calls ProcessAppMsg() to allow special pre-handling of the message
  348. //
  349. bool
  350. TApplication::PumpWaitingMessages()
  351. {
  352.   MSG  msg;
  353.   bool foundOne = false;
  354.  
  355.   while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
  356.     foundOne = true;
  357.     if (msg.message == WM_QUIT) {
  358.       BreakMessageLoop = true;
  359.       MessageLoopResult = msg.wParam;
  360.       ::PostQuitMessage(msg.wParam);  // make sure all loops exit
  361.       break;
  362.     }
  363.  
  364.     // Let the app preprocess the message. If it is not eaten, then translate
  365.     // it, & dispatch it. If no hwnd, then first find/dispatch it directly to
  366.     // the app (for PostAppMessage() functionality)
  367.     //
  368.     if (!ProcessAppMsg(msg)) {
  369.       ::TranslateMessage(&msg);
  370.       if (!msg.hwnd) {
  371.         TEventInfo cmdEventInfo(msg.message, msg.wParam);
  372.         if (Find(cmdEventInfo)) {
  373.           Dispatch(cmdEventInfo, msg.wParam, msg.lParam);
  374.           return true;
  375.         }
  376.         else {
  377.           TEventInfo eventInfo(msg.message);
  378.           if (Find(eventInfo)) {
  379.             Dispatch(eventInfo, msg.wParam, msg.lParam);
  380.             return true;
  381.           }
  382.         }
  383.       }
  384.       ::DispatchMessage(&msg);
  385.       DeleteCondemned();
  386.       ResumeThrow();
  387.     }
  388.   }
  389.   return foundOne;
  390. }
  391.  
  392. //
  393. // Suspend throw functions store away a caught exception to allow foreign code
  394. // to be re-entered. Call ResumeThrow() to rethrow the exception, if any, upon
  395. // return from the foreign code.
  396. //
  397. void
  398. TApplication::SuspendThrow(xalloc& x)
  399. {
  400.   XString = x.why();
  401.   XSize   = x.requested();
  402.   XState |= xsAlloc;
  403. }
  404.  
  405. void
  406. TApplication::SuspendThrow(xmsg& x)
  407. {
  408.   XString = x.why();
  409.   XState |= xsMsg;
  410. }
  411.  
  412. void
  413. TApplication::SuspendThrow(TXBase& x)
  414. {
  415.   delete XBase;       // remove any previous exception
  416.   XBase = x.Clone();
  417.   XState |= xsBase;
  418. }
  419.  
  420. void
  421. TApplication::SuspendThrow(int flag)
  422. {
  423.   XState |= (flag & (xsBadCast | xsBadTypeid | xsUnknown));
  424. }
  425.  
  426. void
  427. TApplication::ResumeThrow()
  428. {
  429.   if (XState) {
  430.     if (XState & xsBase) {
  431.       XState &= ~xsBase;
  432.       XBase->Throw();  // must be deleted later
  433.     }
  434.     if (XState & xsAlloc) {
  435.       XState &= ~xsAlloc;
  436.       THROW( xalloc(XString,XSize) );
  437.     }
  438.     if (XState & xsMsg) {
  439.       XState &= ~xsMsg;
  440.       THROW( xmsg(XString) );
  441.     }
  442.     if (XState & xsUnknown) {
  443.       XState &= ~xsUnknown;
  444.       THROW( xmsg(string()) );
  445.     }
  446.     if (XState & xsBadCast) {
  447.       XState &= ~xsBadCast;
  448.       THROW( Bad_cast() );
  449.     }
  450.     if (XState & xsBadTypeid) {
  451.       XState &= ~xsBadTypeid;
  452.       THROW( Bad_typeid() );
  453.     }
  454.   }
  455. }
  456.  
  457. //
  458. // General message loop: retrieves and processes messages from the OWL
  459. // application's message queue until BreakMessageLoop becomes true
  460. //
  461. // Calls IdleAction() when there are no messages
  462. //
  463. int
  464. TApplication::MessageLoop()
  465. {
  466.   long idleCount = 0;
  467.  
  468.   MessageLoopResult = 0;
  469.   while (!BreakMessageLoop) {
  470.     TRY {
  471.       if (!IdleAction(idleCount++))
  472.         ::WaitMessage();             // allow system to go idle
  473.       if (PumpWaitingMessages())     // pumps any waiting messages
  474.         idleCount = 0;
  475.     }
  476.     CATCH( (TXOwl& x) {
  477.       MessageLoopResult = x.Unhandled(this, IDS_OKTORESUME);
  478.       if (MessageLoopResult != 0) {
  479.         ::PostQuitMessage(MessageLoopResult);
  480.         break;
  481.       }
  482.     })
  483.     CATCH( (xmsg& x) {
  484.       MessageLoopResult = Error(x, 0, IDS_OKTORESUME);
  485.       if (MessageLoopResult != 0) {
  486.         ::PostQuitMessage(MessageLoopResult);
  487.         break;
  488.       }
  489.     })
  490.     CATCH( (Bad_cast& x) {
  491.       MessageLoopResult = Error(xmsg(string(typeid(x).name())), 0, IDS_OKTORESUME);
  492.       if (MessageLoopResult != 0) {
  493.         ::PostQuitMessage(MessageLoopResult);
  494.         break;
  495.       }
  496.     })
  497.     CATCH( (Bad_typeid& x) {
  498.       MessageLoopResult = Error(xmsg(string(typeid(x).name())), 0, IDS_OKTORESUME);
  499.       if (MessageLoopResult != 0) {
  500.         ::PostQuitMessage(MessageLoopResult);
  501.         break;
  502.       }
  503.     })
  504.   }
  505.   BreakMessageLoop = false;
  506.   return MessageLoopResult;
  507. }
  508.  
  509. //
  510. // Default event handling simply defers to the DocManager if it has been
  511. // installed
  512. //
  513. bool
  514. TApplication::Find(TEventInfo &eventInfo, TEqualOperator equal)
  515. {
  516.   return DocManager ? DocManager->Find(eventInfo, equal) : false;
  517. }
  518.  
  519. //
  520. // Determines whether the application can be closed.
  521. // Makes sure the MainWindow can close & doc manager can close.
  522. //
  523. bool
  524. TApplication::CanClose()
  525. {
  526.   TEventInfo eventInfo(WM_OWLCANCLOSE);
  527.   return (!MainWindow || MainWindow->CanClose())
  528.       && (!DocManager ||!DocManager->Find(eventInfo)
  529.                       || DocManager->Dispatch(eventInfo, 0, 0));
  530. }
  531.  
  532. //
  533. // Oportunity to preprocess the main window's menubar before it is installed.
  534. // Normally delegated to the doc manager to install a file menu as needed
  535. //
  536. void
  537. TApplication::PreProcessMenu(HMENU fmenu)
  538. {
  539.   TEventInfo eventInfo(WM_OWLPREPROCMENU);
  540.   if (DocManager && DocManager->Find(eventInfo)) {
  541.     DocManager->Dispatch(eventInfo, (WPARAM)fmenu, 0);
  542.     MainWindow->DrawMenuBar();
  543.   }
  544. }
  545.  
  546. //
  547. // Condemn a window to be deleted the at the next available safe time.
  548. // Adds the window to a normal single linked list
  549. //
  550. // Condemned windows should be removed if they are destructed in the mean time
  551. // thru some other mechanism (i.e. stack, aggregate, etc)
  552. //
  553. void
  554. TApplication::Condemn(TWindow* win)
  555. {
  556.   TRACEX(OwlApp, 1, "Condemning window: " << *win);
  557.   win->SetParent(0);
  558.   win->SetNext(CondemnedWindows);
  559.   CondemnedWindows = win;
  560. }
  561.  
  562. //
  563. // Remove a condemned window from the list.
  564. //
  565. void
  566. TApplication::Uncondemn(TWindow* win)
  567. {
  568.   if (win && CondemnedWindows) {
  569.     TWindow* w = 0;
  570.     if (CondemnedWindows != win)
  571.       for (w = CondemnedWindows; w->Next() != win; w = w->Next())
  572.         if (!w->Next())
  573.           return;
  574.            
  575.     TRACEX(OwlApp, 1, "Uncondemning window: " << *win);
  576.     if (w)
  577.       w->SetNext(win->Next());
  578.     else
  579.       CondemnedWindows = win->Next();
  580.   }
  581. }
  582.  
  583. //
  584. // Walk the condemned window list & delete each window. Assumes that the
  585. // windows were constructed using 'new'
  586. //
  587. void
  588. TApplication::DeleteCondemned()
  589. {
  590.   while (CondemnedWindows) {
  591.     TRACEX(OwlApp, 1, "Deleting condemned window: " << *CondemnedWindows);
  592.     TWindow* next = CondemnedWindows->Next();
  593.     delete CondemnedWindows;
  594.     CondemnedWindows = next;
  595.   }
  596. }
  597.  
  598. TApplication::TXInvalidMainWindow::TXInvalidMainWindow()
  599. :
  600.   TXOwl(IDS_INVALIDMAINWINDOW)
  601. {
  602. }
  603.  
  604. TApplication::TXInvalidMainWindow::~TXInvalidMainWindow()
  605. {
  606. }
  607.  
  608. TApplication::TXInvalidMainWindow*
  609. TApplication::TXInvalidMainWindow::Clone()
  610. {
  611.   return new TXInvalidMainWindow(*this);
  612. }
  613.  
  614. void
  615. TApplication::TXInvalidMainWindow::Throw()
  616. {
  617.   THROW( *this );
  618. }
  619.  
  620. #endif
  621. //----------------------------------------------------------------------------
  622. #if !defined(SECTION) || SECTION == 2
  623.  
  624. struct TEnumInfo {
  625.   HWND      ModalWnd; // The window being made modal if needed
  626.   short     Count;    // Count of windows in Wnds below
  627.   HWND*     Wnds;     // list of windows that were disabled
  628. };
  629. static TEnumInfo* stackTop = 0; // points to topmost enuminfo in BeginModal calls
  630.  
  631. //
  632. // Enum[Thread/Task]Windows callback. Counts or disables given window based on
  633. // whether or not window list has been allocated yet.
  634. //
  635. bool CALLBACK __export
  636. DisableWnds(HWND wnd, TEnumInfo far* ei)
  637. {
  638.   if (!(::GetWindowLong(wnd, GWL_STYLE) & WS_CHILD)) {
  639.     if (wnd != ei->ModalWnd && ::IsWindowEnabled(wnd)) {
  640.       if (!ei->Wnds) {
  641.         ei->Count++;  // no buffer yet, we are just counting
  642.       }
  643.       else {
  644.         *(ei->Wnds++) = wnd;
  645.         ::EnableWindow(wnd, false);
  646.       }
  647.     }
  648.   }
  649.   return true;
  650. }
  651.  
  652. //
  653. // Terminate the modal state initiated by BeginModal. Needs topmost ei block,
  654. // and cleans the block up as needed inorder to be safe to be called twice.
  655. //
  656. static void termModal(TEnumInfo& ei)
  657. {
  658.   //
  659.   // Re-enable window(s) that are disabled in BeginModal()
  660.   //
  661.   if (ei.Wnds) {
  662.     for (HWND* wnd = ei.Wnds; *wnd; wnd++)
  663.       ::EnableWindow(*wnd, true);
  664.     delete[] ei.Wnds;
  665.     ei.Wnds = 0;
  666.   }
  667.   else {
  668.     if (ei.ModalWnd && IsWindow(ei.ModalWnd)) {
  669.       ::EnableWindow(ei.ModalWnd, true);
  670.       ei.ModalWnd = 0;
  671.     }
  672.   }
  673. }
  674.  
  675. //
  676. // Go modal and enter a message loop until a quit message goes by.
  677. // the flag values determine how window is used:
  678. //   MB_APPLMODAL -   window is the owner to disable (if 0, none are disabled)
  679. //   MB_TASKMODAL -   window is the window to make modal,
  680. //                    all other top level windows are disabled
  681. //   MB_SYSTEMMODAL - window is the window to make system modal
  682. // returns -1 on errors
  683. //
  684. int
  685. TApplication::BeginModal(TWindow* window, int flags)
  686. {
  687.   TEnumInfo  ei = { 0, 0, 0 };
  688.   TEnumInfo* lastStackTop = stackTop; // keep last stackTop to restore later
  689.   stackTop = &ei;                     // point stackTop to topmost ei
  690.  
  691.   // Set modal state
  692.   //
  693.   if (flags & MB_TASKMODAL) {
  694.  
  695.     if (window)
  696.       ei.ModalWnd = window->HWindow;  // don't disable the modal window if exists
  697.  
  698.     // count windows to disable
  699.     //
  700. #if defined(BI_PLAT_WIN32)
  701.     if (!EnumThreadWindows(GetCurrentThreadId(), (WNDENUMPROC)DisableWnds,
  702.                            (LPARAM)(TEnumInfo far*)&ei))
  703.       return -1;
  704. #else
  705.     if (!EnumTaskWindows(GetCurrentTask(), (WNDENUMPROC)DisableWnds,
  706.                          (LPARAM)(TEnumInfo far*)&ei))
  707.       return -1;
  708. #endif
  709.  
  710.     // Allocate list of windows to disable, disable windows that are
  711.     // enabled and then stuff them into the list.
  712.     //
  713.     HWND* wnds = ei.Wnds = new HWND[ei.Count + 1];
  714.     memset(ei.Wnds, 0, sizeof(HWND)*(ei.Count + 1));
  715.  
  716. #if defined(BI_PLAT_WIN32)
  717.     EnumThreadWindows(GetCurrentThreadId(), (WNDENUMPROC)DisableWnds,
  718.                       (LPARAM)(TEnumInfo far*)&ei);
  719. #else
  720.     EnumTaskWindows(GetCurrentTask(), (WNDENUMPROC)DisableWnds,
  721.                     (LPARAM)(TEnumInfo far*)&ei);
  722. #endif
  723.  
  724.     ei.Wnds = wnds;  // restore alloc'd pointer since enumerator bumps it
  725.   }
  726. #if defined(BI_PLAT_WIN16)
  727.   else if (flags & MB_SYSTEMMODAL)
  728.     window->SetSysModalWindow();
  729. #endif
  730.   else if (window) {
  731.     ei.ModalWnd = window->HWindow;  // remember who to re-enable later
  732.     window->EnableWindow(false);
  733.   }
  734.  
  735.   // Enter message loop, saving & restoring the current status & getting the
  736.   // returned result.
  737.   //
  738.   int result;
  739.   TRY {
  740.     result = MessageLoop();
  741.   }
  742.   CATCH( (...) {
  743.     termModal(ei);
  744.     stackTop = lastStackTop;
  745.     RETHROW;
  746.   })
  747.   stackTop = lastStackTop;
  748.   termModal(ei);            // just in case termModal was missed in EndModal
  749.  
  750.   // return the result from the modal window's EndModal call
  751.   //
  752.   return result;
  753. }
  754.  
  755. //
  756. // Cause the current modal message loop to break and have it return a result
  757. // Re-enable the disabled windows here, if the EnumInfo is available.
  758. //
  759. void
  760. TApplication::EndModal(int result)
  761. {
  762.   MessageLoopResult = result;
  763.   BreakMessageLoop = true;
  764.   if (stackTop)
  765.     termModal(*stackTop);
  766. }
  767.  
  768. #endif
  769. //----------------------------------------------------------------------------
  770. #if !defined(SECTION) || SECTION == 3
  771.  
  772. //
  773. // Predefined DLLs that TApplication knows how to find.
  774. //
  775. #if defined(BI_PLAT_WIN32)
  776.   const char BwccDllName[]  = "BWCC32.DLL";
  777.   const char Ctl3dDllName[] = "CTL3D32.DLL";
  778. #elif defined(BI_PLAT_WIN16)
  779.   const char BwccDllName[]  = "BWCC.DLL";
  780.   const char Ctl3dDllName[] = "CTL3DV2.DLL";
  781. #endif
  782.  
  783. //
  784. // Load the BWCC DLL if needed & set the BWCC on flag according to 'enable'
  785. // Library is not free'd on disable to reduce re-loads if enabling on the fly
  786. //
  787. void
  788. TApplication::EnableBWCC(bool enable, uint language)
  789. {
  790.   if (enable) {
  791.     if (!BWCCModule) {
  792.       BWCCModule = new TModule(BwccDllName, true);
  793.  
  794.       bool FAR PASCAL(*bwccIntlInit)(uint);
  795.       (FARPROC)bwccIntlInit = BWCCModule->GetProcAddress("BWCCIntlInit");
  796.       if (bwccIntlInit)
  797.         bwccIntlInit(language);
  798.  
  799.       bool FAR PASCAL(*bwccRegister)(HINSTANCE);
  800.       (FARPROC)bwccRegister = BWCCModule->GetProcAddress("BWCCRegister");
  801.       if (bwccRegister)
  802.         bwccRegister(GetInstance());
  803.     }
  804.     BWCCOn = true;
  805.   }
  806.   else
  807.     BWCCOn = false;
  808. }
  809.  
  810. //
  811. // enable or disable the use of the CTL3D DLL. Loads it if needed.
  812. //
  813. void
  814. TApplication::EnableCtl3d(bool enable)
  815. {
  816.   //
  817.   // If we are running Win4.0 or greater, then ctl3d is unnecessary
  818.   //
  819. #if defined(BI_PLAT_WIN32)
  820.   if ((::GetVersion()&0xFF) >= 4)
  821. #else
  822.   if ((::GetVersion()&0xFF) >= 3 && ((::GetVersion()>>8)&0xFF) >= 95)
  823. #endif
  824.     return;
  825.  
  826.   //
  827.   // Load the Ctl3d DLL if needed & register our instance
  828.   //
  829.   if (enable) {
  830.     if (!Ctl3dModule) {
  831.       Ctl3dModule = new TModule(Ctl3dDllName, true);
  832.       bool FAR PASCAL(*ctl3dRegister)(HANDLE);
  833.       (FARPROC)ctl3dRegister = Ctl3dModule->GetProcAddress("Ctl3dRegister");
  834.       if (ctl3dRegister)
  835.         ctl3dRegister(*this);
  836.       else {
  837.         delete Ctl3dModule;
  838.         Ctl3dModule = 0;
  839.         return;   // could not register--don't change Ctl3dOn flag
  840.       }
  841.     }
  842.   }
  843.   Ctl3dOn = enable;
  844. }
  845.  
  846. //
  847. // enable or disable CTL3D's use of auto-subclassing. Turn on autosubclassing
  848. // before creating a non-owl dialog to make it 3d, & turn it off immediatly
  849. // after.
  850. //
  851. void
  852. TApplication::EnableCtl3dAutosubclass(bool enable)
  853. {
  854.   if (Ctl3dEnabled()) {
  855.     if (enable) {
  856.       bool FAR PASCAL(*ctl3dRegister)(HANDLE);
  857.       (FARPROC)ctl3dRegister = Ctl3dModule->GetProcAddress("Ctl3dRegister");
  858.       if (ctl3dRegister) {
  859.         ctl3dRegister(*this);
  860.  
  861.         bool FAR PASCAL(*ctl3dAutoSubclass)(HANDLE);
  862.         (FARPROC)ctl3dAutoSubclass = Ctl3dModule->GetProcAddress("Ctl3dAutoSubclass");
  863.         if (ctl3dAutoSubclass)
  864.           ctl3dAutoSubclass(*this);
  865.       }
  866.     }
  867.     else {
  868.       bool FAR PASCAL(*Ctl3dUnregister)(HANDLE);
  869.       (FARPROC)Ctl3dUnregister = Ctl3dModule->GetProcAddress("Ctl3dUnregister");
  870.       if (Ctl3dUnregister)
  871.         Ctl3dUnregister(*this);
  872.     }
  873.   }
  874. }
  875.  
  876. #endif
  877. //----------------------------------------------------------------------------
  878. #if !defined(SECTION) || SECTION == 4
  879.  
  880. IMPLEMENT_STREAMABLE1(TApplication, TModule);
  881.  
  882. void*
  883. TApplication::Streamer::Read(ipstream& is, uint32 /*version*/) const
  884. {
  885.   TApplication* o = GetObject();
  886.   if (o != ::Module)
  887.     is >> *::Module;   // set reference to OWL module
  888.   return o;
  889. }
  890.  
  891. void
  892. TApplication::Streamer::Write(opstream& os) const
  893. {
  894.   TApplication* o = GetObject();
  895.   if (o != ::Module)
  896.     os << *::Module;    // write out reference to OWL module, no data written
  897. }
  898.  
  899. #endif  // SECTION
  900.