home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / lib / ds / plevent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  18.0 KB  |  735 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. #if defined(WIN16)
  19. #include <windows.h>
  20. #endif
  21. #include "plevent.h"
  22. #include "prmem.h"
  23. #include "prcmon.h"
  24. #include "prlog.h"
  25. #if !defined(WIN32)
  26. #include <errno.h>
  27. #include <stddef.h>
  28. #if !defined(OS2)
  29. #include <unistd.h>
  30. #endif
  31. #endif
  32.  
  33. #if defined(XP_MAC)
  34. #include <AppleEvents.h>
  35. #include "pprthred.h"
  36. #include "primpl.h"
  37. #else
  38. #include "private/pprthred.h"
  39. #include "private/primpl.h"
  40. #endif
  41.  
  42. static PRLogModuleInfo *event_lm = NULL;
  43.  
  44. /*******************************************************************************
  45.  * Private Stuff
  46.  ******************************************************************************/
  47.  
  48. struct PLEventQueue {
  49.     char*        name;
  50.     PRCList        queue;
  51.     PRMonitor*        monitor;
  52.     PRThread*        handlerThread;
  53. #ifdef XP_UNIX
  54.     PRInt32        eventPipe[2];
  55.     PRPackedBool    nativeNotifier;
  56.     int notifyCount;
  57. #endif
  58. };
  59.  
  60. #define PR_EVENT_PTR(_qp) \
  61.     ((PLEvent*) ((char*) (_qp) - offsetof(PLEvent, link)))
  62.  
  63. static PRStatus    _pl_SetupNativeNotifier(PLEventQueue* self);
  64. static void    _pl_CleanupNativeNotifier(PLEventQueue* self);
  65. static PRStatus    _pl_NativeNotify(PLEventQueue* self);
  66. static PRStatus    _pl_AcknowledgeNativeNotify(PLEventQueue* self);
  67.  
  68.  
  69. #if defined(_WIN32) || defined(WIN16)
  70. PLEventQueue * _pr_main_event_queue;
  71. UINT _pr_PostEventMsgId;
  72. HWND _pr_eventReceiverWindow;
  73. static char *_pr_eventWindowClass = "NSPR:EventWindow";
  74. #endif
  75.  
  76. /*******************************************************************************
  77.  * Event Queue Operations
  78.  ******************************************************************************/
  79.  
  80. PR_IMPLEMENT(PLEventQueue*)
  81. PL_CreateEventQueue(char* name, PRThread* handlerThread)
  82. {
  83.     PRStatus err;
  84.     PLEventQueue* self = NULL;
  85.     PRMonitor* mon = NULL;
  86.  
  87.     if (event_lm == NULL)
  88.         event_lm = PR_LOG_DEFINE("event");
  89.  
  90.     self = PR_NEWZAP(PLEventQueue);
  91.     if (self == NULL) return NULL;
  92.  
  93.     mon = PR_NewNamedMonitor(name);
  94.     if (mon == NULL) goto error;
  95.  
  96.     self->name = name;
  97.     self->monitor = mon;
  98.     self->handlerThread = handlerThread;
  99.     PR_INIT_CLIST(&self->queue);
  100.     err = _pl_SetupNativeNotifier(self);
  101.     if (err) goto error;
  102.  
  103.     return self;
  104.  
  105.   error:
  106.     if (mon != NULL)
  107.     PR_DestroyMonitor(mon);
  108.     PR_DELETE(self);
  109.     return NULL;
  110. }
  111.  
  112. PR_IMPLEMENT(PRMonitor*)
  113. PL_GetEventQueueMonitor(PLEventQueue* self)
  114. {
  115.     return self->monitor;
  116. }
  117.  
  118. static void PR_CALLBACK
  119. _pl_destroyEvent(PLEvent* event, void* data, PLEventQueue* queue)
  120. {
  121. #ifdef XP_MAC
  122. #pragma unused (data, queue)
  123. #endif
  124.     PL_DequeueEvent(event, queue);
  125.     PL_DestroyEvent(event);
  126. }
  127.  
  128. PR_IMPLEMENT(void)
  129. PL_DestroyEventQueue(PLEventQueue* self)
  130. {
  131.     PR_EnterMonitor(self->monitor);
  132.  
  133.     /* destroy undelivered events */
  134.     PL_MapEvents(self, _pl_destroyEvent, NULL);
  135.  
  136.     _pl_CleanupNativeNotifier(self);
  137.  
  138.     /* destroying the monitor also destroys the name */
  139.     PR_ExitMonitor(self->monitor);
  140.     PR_DestroyMonitor(self->monitor);
  141.     PR_DELETE(self);
  142.  
  143. }
  144.  
  145. PR_IMPLEMENT(PRStatus)
  146. PL_PostEvent(PLEventQueue* self, PLEvent* event)
  147. {
  148.     PRStatus err;
  149.     PRMonitor* mon;
  150.  
  151.     if (self == NULL)
  152.     return PR_FAILURE;
  153.  
  154.     mon = self->monitor;
  155.     PR_EnterMonitor(mon);
  156.  
  157.     /* insert event into thread's event queue: */
  158.     if (event != NULL) {
  159.     PR_APPEND_LINK(&event->link, &self->queue);
  160.     }
  161.  
  162.     /* notify even if event is NULL */
  163.     err = _pl_NativeNotify(self);
  164.     if (err != PR_SUCCESS) goto done;
  165.  
  166.     /*
  167.      * This may fall on deaf ears if we're really notifying the native 
  168.      * thread, and no one has called PL_WaitForEvent (or PL_EventLoop):
  169.      */
  170.     err = PR_Notify(mon);
  171.  
  172.   done:
  173.     PR_ExitMonitor(mon);
  174.     return err;
  175. }
  176.  
  177. PR_IMPLEMENT(void*)
  178. PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event)
  179. {
  180.     void* result;
  181.  
  182.     if (self == NULL)
  183.     return NULL;
  184.  
  185.     PR_ASSERT(event != NULL);
  186.     PR_CEnterMonitor(event);
  187.  
  188.     if (PR_CurrentThread() == self->handlerThread) {
  189.     /* Handle the case where the thread requesting the event handling
  190.        is also the thread that's supposed to do the handling. */
  191.     result = event->handler(event);
  192.     }
  193.     else {
  194.     int inEventQueueMon = PR_GetMonitorEntryCount(self->monitor);
  195.     int i, entryCount = self->monitor->entryCount;
  196.  
  197.     event->synchronousResult = (void*)PR_TRUE;
  198.     PR_PostEvent(self, event);
  199.     /* We need to temporarily give up our event queue monitor if
  200.        we're holding it, otherwise, the thread we're going to wait
  201.        for notification from won't be able to enter it to process
  202.        the event. */
  203.     if (inEventQueueMon) {
  204.         for (i = 0; i < entryCount; i++)
  205.         PR_ExitMonitor(self->monitor);
  206.     }
  207.     PR_CWait(event, PR_INTERVAL_NO_TIMEOUT);    /* wait for event to be handled or destroyed */
  208.     if (inEventQueueMon) {
  209.         for (i = 0; i < entryCount; i++)
  210.         PR_EnterMonitor(self->monitor);
  211.     }
  212.     result = event->synchronousResult;
  213.     event->synchronousResult = NULL;
  214.     }
  215.  
  216.     PR_CExitMonitor(event);
  217.  
  218.     /* For synchronous events, they're destroyed here on the caller's
  219.        thread before the result is returned. See PL_HandleEvent. */
  220.     PL_DestroyEvent(event);
  221.  
  222.     return result;
  223. }
  224.  
  225. PR_IMPLEMENT(PLEvent*)
  226. PL_GetEvent(PLEventQueue* self)
  227. {
  228.     PLEvent* event = NULL;
  229.     PRStatus err;
  230.     PRMonitor* mon;
  231.  
  232.     if (self == NULL)
  233.     return NULL;
  234.  
  235.     mon = self->monitor;
  236.     PR_EnterMonitor(mon);
  237.  
  238.     err = _pl_AcknowledgeNativeNotify(self);
  239.     if (err) goto done;
  240.  
  241.     if (!PR_CLIST_IS_EMPTY(&self->queue)) {
  242.     /* then grab the event and return it: */
  243.     event = PR_EVENT_PTR(self->queue.next);
  244.     PR_REMOVE_AND_INIT_LINK(&event->link);
  245.     }
  246.  
  247.   done:
  248.     PR_ExitMonitor(mon);
  249.     return event;
  250. }
  251.  
  252. PR_IMPLEMENT(PRBool)
  253. PL_EventAvailable(PLEventQueue* self)
  254. {
  255.     PRBool result = PR_FALSE;
  256.  
  257.     if (self == NULL)
  258.     return PR_FALSE;
  259.  
  260.     PR_EnterMonitor(self->monitor);
  261.  
  262.     if (!PR_CLIST_IS_EMPTY(&self->queue)) 
  263.     result = PR_TRUE;
  264.  
  265.     PR_ExitMonitor(self->monitor);
  266.     return result;
  267. }
  268.  
  269. PR_IMPLEMENT(void)
  270. PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data)
  271. {
  272.     PRCList* qp;
  273.  
  274.     if (self == NULL)
  275.     return;
  276.  
  277.     PR_EnterMonitor(self->monitor);
  278.     qp = self->queue.next;
  279.     while (qp != &self->queue) {
  280.     PLEvent* event = PR_EVENT_PTR(qp);
  281.     qp = qp->next;
  282.     (*fun)(event, data, self);
  283.     }
  284.     PR_ExitMonitor(self->monitor);
  285. }
  286.  
  287. static void PR_CALLBACK
  288. _pl_DestroyEventForOwner(PLEvent* event, void* owner, PLEventQueue* queue)
  289. {
  290.     PR_ASSERT(PR_GetMonitorEntryCount(queue->monitor) > 0);
  291.     if (event->owner == owner) {
  292.     PR_LOG(event_lm, PR_LOG_DEBUG,
  293.            ("$$$ \tdestroying event %0x for owner %0x", event, owner));
  294.     PL_DequeueEvent(event, queue);
  295.     if (event->synchronousResult == (void*)PR_TRUE) {
  296.         PR_CEnterMonitor(event);
  297.         event->synchronousResult = NULL;
  298.         PR_CNotify(event);
  299.         PR_CExitMonitor(event);
  300.     }
  301.     else {
  302.         PL_DestroyEvent(event);
  303.     }
  304.     }
  305.     else {
  306.     PR_LOG(event_lm, PR_LOG_DEBUG,
  307.            ("$$$ \tskipping event %0x for owner %0x", event, owner));
  308.     }
  309. }
  310.  
  311. PR_IMPLEMENT(void)
  312. PL_RevokeEvents(PLEventQueue* self, void* owner)
  313. {
  314.     if (self == NULL)
  315.     return;
  316.  
  317.     PR_LOG_BEGIN(event_lm, PR_LOG_DEBUG,
  318.          ("$$$ revoking events for owner %0x", owner));
  319.  
  320.     /*
  321.     ** First we enter the monitor so that no one else can post any events
  322.     ** to the queue:
  323.     */
  324.     PR_EnterMonitor(self->monitor);
  325.     PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ owner %0x, entered monitor", owner));
  326.  
  327.     /*
  328.     ** Discard any pending events for this owner:
  329.     */
  330.     PL_MapEvents(self, _pl_DestroyEventForOwner, owner);
  331.  
  332. #ifdef DEBUG
  333.     {
  334.     PRCList* qp = self->queue.next;
  335.     while (qp != &self->queue) {
  336.         PREvent* event = PR_EVENT_PTR(qp);
  337.         qp = qp->next;
  338.         PR_ASSERT(event->owner != owner);
  339.     }
  340.     }
  341. #endif /* DEBUG */
  342.  
  343.     PR_ExitMonitor(self->monitor);
  344.  
  345.     PR_LOG_END(event_lm, PR_LOG_DEBUG,
  346.            ("$$$ revoking events for owner %0x", owner));
  347. }
  348.  
  349. PR_IMPLEMENT(void)
  350. PL_ProcessPendingEvents(PLEventQueue* self)
  351. {
  352.     if (self == NULL)
  353.     return;
  354.  
  355.     while (PR_TRUE) {
  356.     PLEvent* event = PL_GetEvent(self);
  357.         if (event == NULL) return;
  358.  
  359.     PR_LOG_BEGIN(event_lm, PR_LOG_DEBUG, ("$$$ processing event"));
  360.     PL_HandleEvent(event);
  361.     PR_LOG_END(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
  362.     }
  363. }
  364.  
  365. /*******************************************************************************
  366.  * Event Operations
  367.  ******************************************************************************/
  368.  
  369. PR_IMPLEMENT(void)
  370. PL_InitEvent(PLEvent* self, void* owner,
  371.          PLHandleEventProc handler,
  372.          PLDestroyEventProc destructor)
  373. {
  374.     PR_INIT_CLIST(&self->link);
  375.     self->handler = handler;
  376.     self->destructor = destructor;
  377.     self->owner = owner;
  378.     self->synchronousResult = NULL;
  379. }
  380.  
  381. PR_IMPLEMENT(void*)
  382. PL_GetEventOwner(PLEvent* self)
  383. {
  384.     return self->owner;
  385. }
  386.  
  387. PR_IMPLEMENT(void)
  388. PL_HandleEvent(PLEvent* self)
  389. {
  390.     void* result;
  391.  
  392.     if (self == NULL)
  393.         return;
  394.  
  395.     /* This event better not be on an event queue anymore. */
  396.     PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link));
  397.  
  398.     result = (*self->handler)(self);
  399.     if (NULL != self->synchronousResult) {
  400.     PR_CEnterMonitor(self);
  401.     self->synchronousResult = result;
  402.     PR_CNotify(self);    /* wake up the guy waiting for the result */
  403.     PR_CExitMonitor(self);
  404.     }
  405.     else {
  406.     /* For asynchronous events, they're destroyed by the event-handler
  407.        thread. See PR_PostSynchronousEvent. */
  408.     PL_DestroyEvent(self);
  409.     }
  410. }
  411.  
  412. PR_IMPLEMENT(void)
  413. PL_DestroyEvent(PLEvent* self)
  414. {
  415.     if (self == NULL)
  416.     return;
  417.  
  418.     /* This event better not be on an event queue anymore. */
  419.     PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link));
  420.  
  421.     (*self->destructor)(self);
  422. }
  423.  
  424. PR_IMPLEMENT(void)
  425. PL_DequeueEvent(PLEvent* self, PLEventQueue* queue)
  426. {
  427. #ifdef XP_MAC
  428. #pragma unused (queue)
  429. #endif
  430.     if (self == NULL)
  431.     return;
  432.  
  433.     /* Only the owner is allowed to dequeue events because once the 
  434.        client has put it in the queue, they have no idea whether it's 
  435.        been processed and destroyed or not. */
  436. /*    PR_ASSERT(queue->handlerThread == PR_CurrentThread());*/
  437.  
  438.     PR_EnterMonitor(queue->monitor);
  439.  
  440.     PR_ASSERT(!PR_CLIST_IS_EMPTY(&self->link));
  441.     PR_REMOVE_AND_INIT_LINK(&self->link);
  442.  
  443.     PR_ExitMonitor(queue->monitor);
  444. }
  445.  
  446. /*******************************************************************************
  447.  * Pure Event Queues
  448.  *
  449.  * For when you're only processing PLEvents and there is no native
  450.  * select, thread messages, or AppleEvents.
  451.  ******************************************************************************/
  452.  
  453. PR_IMPLEMENT(PLEvent*)
  454. PL_WaitForEvent(PLEventQueue* self)
  455. {
  456.     PLEvent* event;
  457.     PRMonitor* mon;
  458.  
  459.     if (self == NULL)
  460.     return NULL;
  461.  
  462.     mon = self->monitor;
  463.     PR_EnterMonitor(mon);
  464.  
  465.     while ((event = PL_GetEvent(self)) == NULL) {
  466.         PRStatus err;
  467.         PR_LOG_END(event_lm, PR_LOG_DEBUG, ("$$$ waiting for event"));
  468.         err = PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
  469.         if ((err == PR_FAILURE)
  470.             && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break;
  471.     }
  472.  
  473.     PR_ExitMonitor(mon);
  474.     return event;
  475. }
  476.  
  477. PR_IMPLEMENT(void)
  478. PL_EventLoop(PLEventQueue* self)
  479. {
  480.     if (self == NULL)
  481.     return;
  482.  
  483.     while (PR_TRUE) {
  484.     PLEvent* event = PL_WaitForEvent(self);
  485.     if (event == NULL) {
  486.         /* This can only happen if the current thread is interrupted */
  487.         return;
  488.     }
  489.  
  490.         PR_LOG_BEGIN(event_lm, PR_LOG_DEBUG, ("$$$ processing event"));
  491.     PL_HandleEvent(event);
  492.     PR_LOG_END(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
  493.     }
  494. }
  495.  
  496. /*******************************************************************************
  497.  * Native Event Queues
  498.  *
  499.  * For when you need to call select, or WaitNextEvent, and yet also want
  500.  * to handle PLEvents.
  501.  ******************************************************************************/
  502.  
  503. static PRStatus
  504. _pl_SetupNativeNotifier(PLEventQueue* self)
  505. {
  506. #if defined(XP_MAC)
  507. #pragma unused (self)
  508. #endif
  509.  
  510.     PRInt32 err = 0;
  511. #if defined(XP_UNIX)
  512.     err = pipe(self->eventPipe);
  513. #endif
  514.     return err == 0 ? PR_SUCCESS : PR_FAILURE;
  515. }
  516.  
  517. static void
  518. _pl_CleanupNativeNotifier(PLEventQueue* self)
  519. {
  520. #if defined(XP_MAC)
  521. #pragma unused (self)
  522. #endif
  523.  
  524. #if defined(XP_UNIX)
  525.     close(self->eventPipe[0]);
  526.     close(self->eventPipe[1]);
  527. #endif
  528. }
  529.  
  530. static PRStatus
  531. _pl_NativeNotify(PLEventQueue* self)
  532. {
  533. #if defined(XP_UNIX)
  534.  
  535. #   define NOTIFY_TOKEN    0xFA
  536.     PRInt32 count;
  537.     unsigned char buf[] = { NOTIFY_TOKEN };
  538.  
  539.     count = write(self->eventPipe[1], buf, 1);
  540.     self->notifyCount++;
  541.     return (count == 1) ? PR_SUCCESS : PR_FAILURE;
  542.  
  543. #elif defined(XP_PC) && ( defined(WINNT) || defined(WIN95) || defined(WIN16))
  544.     /*
  545.     ** Post a message to the NSPR window on the main thread requesting 
  546.     ** it to process the pending events. This is only necessary for the
  547.     ** main event queue, since the main thread is waiting for OS events.
  548.     */
  549.     if (self == _pr_main_event_queue) {
  550.        PostMessage( _pr_eventReceiverWindow, _pr_PostEventMsgId,
  551.                       (WPARAM)0, (LPARAM)self);
  552.     }
  553.     return PR_SUCCESS;
  554.  
  555. #elif defined(XP_MAC)
  556.  
  557. #pragma unused (self)
  558.     return PR_SUCCESS;    /* XXX can fail? */
  559.  
  560. #endif
  561. }
  562.  
  563. static PRStatus
  564. _pl_AcknowledgeNativeNotify(PLEventQueue* self)
  565. {
  566. #if defined(XP_UNIX)
  567.  
  568.     PRInt32 count;
  569.     unsigned char c;
  570.  
  571.     if (self->notifyCount <= 0) return PR_SUCCESS;
  572.     /* consume the byte NativeNotify put in our pipe: */
  573.     count = read(self->eventPipe[0], &c, 1);
  574.     self->notifyCount--;
  575.     return ((count == 1 && c == NOTIFY_TOKEN) || count == 0)
  576.     ? PR_SUCCESS : PR_FAILURE;
  577.  
  578. #else
  579.  
  580. #if defined(XP_MAC)
  581. #pragma unused (self)
  582. #endif
  583.  
  584.     /* nothing to do on the other platforms */
  585.     return PR_SUCCESS;
  586. #endif
  587. }
  588.  
  589. PR_IMPLEMENT(PRInt32)
  590. PL_GetEventQueueSelectFD(PLEventQueue* self)
  591. {
  592.     if (self == NULL)
  593.     return -1;
  594.  
  595. #if defined(XP_UNIX)
  596.     return self->eventPipe[0];
  597. #else
  598.     return -1;    /* other platforms don't handle this (yet) */
  599. #endif
  600. }
  601.  
  602.  
  603.  
  604. #if defined(WIN16) || defined(_WIN32)
  605. /*
  606. ** Global Instance handle...
  607. ** In Win32 this is the module handle of the DLL.
  608. **
  609. */
  610. HINSTANCE _pr_hInstance;
  611. #endif
  612.  
  613. #if defined(WIN16)
  614. /*
  615. ** Function LibMain() is required by Win16
  616. **
  617. */
  618. int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg, 
  619.                       WORD cbHeapSize, LPSTR lpszCmdLine )
  620. {
  621.     _pr_hInstance = hInst;
  622.     return TRUE;
  623. }
  624. #endif /* WIN16 */
  625.  
  626. #if defined(_WIN32)
  627.  
  628. /*
  629. ** Initialization routine for the NSPR DLL...
  630. */
  631.  
  632. BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
  633. {
  634.   switch (dwReason)
  635.   {
  636.     case DLL_PROCESS_ATTACH:
  637.       _pr_hInstance = hDLL;
  638.       break;
  639.  
  640.     case DLL_THREAD_ATTACH:
  641.       break;
  642.  
  643.     case DLL_THREAD_DETACH:
  644.       break;
  645.  
  646.     case DLL_PROCESS_DETACH:
  647.       _pr_hInstance = NULL;
  648.       break;
  649.   }
  650.  
  651.     return TRUE;
  652. }
  653. #endif
  654.  
  655.  
  656. #if defined(WIN16) || defined(_WIN32)
  657. PR_IMPLEMENT(PLEventQueue *)
  658. PL_GetMainEventQueue()
  659. {
  660.    PR_ASSERT(_pr_main_event_queue);
  661.  
  662.    return _pr_main_event_queue;
  663. }
  664.  
  665. LRESULT CALLBACK 
  666. #if defined(WIN16)
  667. __loadds
  668. #endif
  669. _md_EventReceiverProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  670. {
  671.     if (_pr_PostEventMsgId == uMsg )
  672.     {
  673.         PREventQueue *queue = (PREventQueue *)lParam;
  674.  
  675.         PR_ASSERT(queue == PL_GetMainEventQueue());
  676.         if (queue == PL_GetMainEventQueue()) 
  677.         {
  678.             PR_ProcessPendingEvents(queue);
  679.             return TRUE;
  680.         }
  681.     } 
  682.     return DefWindowProc(hwnd, uMsg, wParam, lParam);
  683. }
  684.  
  685. PR_IMPLEMENT(void)
  686. PL_InitializeEventsLib(char *name)
  687. {
  688.     WNDCLASS wc;
  689.  
  690.     _pr_main_event_queue = PL_CreateEventQueue(name, PR_GetCurrentThread());
  691.  
  692.     /* Register the windows message for NSPR Event notification */
  693.     _pr_PostEventMsgId = RegisterWindowMessage("NSPR_PostEvent");
  694.  
  695.     /* Register the class for the event receiver window */
  696.     if (!GetClassInfo(_pr_hInstance, _pr_eventWindowClass, &wc)) {
  697.         wc.style         = 0;
  698.         wc.lpfnWndProc   = _md_EventReceiverProc;
  699.         wc.cbClsExtra    = 0;
  700.         wc.cbWndExtra    = 0;
  701.         wc.hInstance     = _pr_hInstance;
  702.         wc.hIcon         = NULL;
  703.         wc.hCursor       = NULL;
  704.         wc.hbrBackground = (HBRUSH) NULL;
  705.         wc.lpszMenuName  = (LPCSTR) NULL;
  706.         wc.lpszClassName = _pr_eventWindowClass;
  707.         RegisterClass(&wc);
  708.         }
  709.         
  710.     /* Create the event receiver window */
  711.     _pr_eventReceiverWindow = CreateWindow(_pr_eventWindowClass,
  712.                                            "NSPR:EventReceiver",
  713.                                             0, 0, 0, 10, 10,
  714.                                             NULL, NULL, _pr_hInstance,
  715.                                             NULL);
  716.     PR_ASSERT(_pr_eventReceiverWindow);
  717. }
  718. #endif
  719.  
  720. #if defined(_WIN32) || defined(WIN16)
  721. PR_IMPLEMENT(HWND)
  722. PR_GetEventReceiverWindow()
  723. {
  724.     if(_pr_eventReceiverWindow != NULL)
  725.     {
  726.     return _pr_eventReceiverWindow;
  727.     }
  728.  
  729.     return NULL;
  730.  
  731. }
  732. #endif
  733.  
  734. /******************************************************************************/
  735.