Back to index

lightning-sunbird  0.9+nobinonly
winevent.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039 ** File:        winevent.c
00040 ** Description: Test functions in plevent.c using Windows
00041 **
00042 ** The winevent test exercises the PLEvent library in a maner
00043 ** similar to how the Mozilla (or NGLayout) Client will use
00044 ** it in a Windows environment.
00045 **
00046 ** This test is based on ideas taken from Charles Petzold's
00047 ** book "Programming Windows 3.1". License to use is in the
00048 ** book. It has been ported to Win32.
00049 **
00050 ** Operation:
00051 ** The initialization is a standard Windows GUI application
00052 ** setup. When the main window receives its WM_CREATE
00053 ** message, a child window is created, a edit control is
00054 ** instantiated in that window.
00055 **
00056 ** A thread is created; this thread runs in the function:
00057 ** TimerThread(). The new thread sends a message every second
00058 ** via the PL_PostEvent() function. The event handler
00059 ** HandlePadEvent() sends a windows message to the edit
00060 ** control window; these messages are WM_CHAR messages that
00061 ** cause the edit control to place a single '.' character in
00062 ** the edit control. 
00063 **
00064 ** After a deterministic number of '.' characters, the
00065 ** TimerThread() function is notified via a global variable
00066 ** that it's quitting time.
00067 ** 
00068 ** TimerThread() callse TestEvents(), an external function
00069 ** that tests additional function of PLEvent.
00070 **
00071 */
00072 
00073 #include "nspr.h"
00074 #include "plevent.h"
00075 
00076 #include <windows.h>
00077 #include <commdlg.h>
00078 
00079 #define ID_EDIT     1
00080 
00081 /* 
00082 ** Declarations for NSPR customization
00083 ** 
00084 */
00085 typedef struct PadEvent
00086 {
00087     PLEvent plEvent;
00088     int     unused;    
00089 } PadEvent;
00090 
00091 static void PR_CALLBACK TimerThread( void *arg);
00092 static void PR_CALLBACK HandlePadEvent( PadEvent *padEvent );
00093 static void PR_CALLBACK DestroyPadEvent( PadEvent *padevent );
00094 
00095 static PRThread *tThread;
00096 static PLEventQueue *padQueue; 
00097 static long ThreadSleepTime = 1000; /* in milli-seconds */
00098 static long timerCount = 0;
00099 static HWND hDlgModeless ;
00100 static HWND hwndEdit ;
00101 static PRBool testFinished = PR_FALSE;
00102 static HWND     hwnd ;
00103 
00104 LRESULT CALLBACK WinProc (HWND, UINT, WPARAM, LPARAM);
00105 
00106 TCHAR appName[] = TEXT ("WinEvent") ;
00107 
00108 int WINAPI WinMain(
00109     HINSTANCE hInstance, 
00110     HINSTANCE hPrevInstance,
00111     PSTR szCmdLine, 
00112     int iCmdShow
00113     )
00114 {
00115     MSG      msg ;
00116     WNDCLASS wndclass ;
00117     HANDLE   hAccel ;
00118     
00119     PR_Init(0, 0, 0);
00120 
00121     wndclass.style = CS_HREDRAW | CS_VREDRAW;
00122     wndclass.lpfnWndProc = WinProc;
00123     wndclass.cbClsExtra = 0;
00124     wndclass.cbWndExtra = 0;
00125     wndclass.hInstance = hInstance;
00126     wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
00127     wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
00128     wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
00129     wndclass.lpszMenuName = NULL;
00130     wndclass.lpszClassName = appName;
00131      
00132     if ( !RegisterClass( &wndclass ))
00133     {
00134         MessageBox( NULL, 
00135             TEXT( "This program needs Win32" ),
00136             appName, 
00137             MB_ICONERROR );
00138         return 0; 
00139     }
00140      
00141     hwnd = CreateWindow( appName, 
00142         appName,
00143         WS_OVERLAPPEDWINDOW,
00144         CW_USEDEFAULT, 
00145         CW_USEDEFAULT,
00146         CW_USEDEFAULT, 
00147         CW_USEDEFAULT,
00148         NULL, 
00149         NULL, 
00150         hInstance, 
00151         NULL);
00152      
00153      ShowWindow( hwnd, iCmdShow );
00154      UpdateWindow( hwnd ); 
00155      
00156      for(;;)
00157      {
00158         if ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE  ))
00159         {
00160             if ( GetMessage( &msg, NULL, 0, 0 ))
00161             {
00162                 if ( hDlgModeless == NULL || !IsDialogMessage( hDlgModeless, &msg ))
00163                 {
00164                     if ( !TranslateAccelerator( hwnd, hAccel, &msg ))
00165                     {
00166                         TranslateMessage( &msg );
00167                         DispatchMessage( &msg );
00168                     } /* end if !TranslateAccelerator */
00169                 } 
00170             }
00171             else
00172             {
00173                 break;    
00174             } /* end if GetMessage() */
00175         } 
00176         else /* !PeekMessage */
00177         {
00178             PR_Sleep(50);
00179         }/* end if PeekMessage() */
00180      } /* end for() */
00181 
00182      PR_JoinThread( tThread );
00183      PL_DestroyEventQueue( padQueue );
00184      PR_Cleanup();
00185      return msg.wParam ;
00186 }
00187 
00188 LRESULT CALLBACK WinProc(
00189     HWND hwnd, 
00190     UINT message, 
00191     WPARAM wParam, 
00192     LPARAM lParam
00193 )
00194 {
00195      switch (message)
00196      {
00197      case WM_CREATE :
00198           hwndEdit = CreateWindow(
00199                         TEXT( "edit" ), 
00200                         NULL,
00201                         WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | 
00202                             WS_BORDER | ES_LEFT | ES_MULTILINE |
00203                             ES_AUTOHSCROLL | ES_AUTOVSCROLL,
00204                          0, 0, 0, 0, 
00205                          hwnd, 
00206                          (HMENU)ID_EDIT,
00207                          ((LPCREATESTRUCT)lParam)->hInstance, 
00208                          NULL);
00209      
00210           /* Initialize Event Processing for NSPR
00211           ** Retrieve the event queue just created
00212           ** Create the TimerThread
00213           */
00214 
00215 /*
00216           PL_InitializeEventsLib( "someName" );
00217           padQueue = PL_GetMainEventQueue();
00218 */
00219           padQueue = PL_CreateEventQueue("MainQueue", PR_GetCurrentThread());
00220                 PR_ASSERT( padQueue != NULL );
00221           tThread = PR_CreateThread( PR_USER_THREAD,
00222                     TimerThread,
00223                     NULL,
00224                     PR_PRIORITY_NORMAL,
00225                     PR_LOCAL_THREAD,
00226                     PR_JOINABLE_THREAD,
00227                     0 );
00228           return 0 ;
00229           
00230      case WM_SETFOCUS :
00231           SetFocus( hwndEdit );
00232           return 0;
00233           
00234      case WM_SIZE : 
00235           MoveWindow( hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE );
00236           return 0 ;
00237           
00238      case WM_COMMAND :
00239           if ( LOWORD(wParam) == ID_EDIT )
00240                if ( HIWORD(wParam ) == EN_ERRSPACE || 
00241                          HIWORD( wParam ) == EN_MAXTEXT )
00242 
00243                     MessageBox( hwnd, TEXT( "Edit control out of space." ),
00244                         appName, MB_OK | MB_ICONSTOP );
00245           return 0;
00246                
00247      case WM_DESTROY :
00248           PostQuitMessage(0);
00249           return 0;
00250      }
00251      return DefWindowProc( hwnd, message, wParam, lParam );
00252 }
00253 
00254 
00255 
00256 /*
00257 ** TimerThread() -- The Main function of the timer pop thread
00258 **
00259 */
00260 static void PR_CALLBACK TimerThread( void *arg )
00261 {
00262     PRIntn  rc;
00263 
00264     do {
00265         PadEvent   *ev;
00266         
00267         /*
00268         ** Create and Post the event the event
00269         */
00270         PL_ENTER_EVENT_QUEUE_MONITOR( padQueue );
00271         ev = (PadEvent *) PR_NEW( PadEvent );
00272         PL_InitEvent( &ev->plEvent, NULL, 
00273                 (PLHandleEventProc)HandlePadEvent, 
00274                 (PLDestroyEventProc)DestroyPadEvent );
00275         PL_PostEvent( padQueue, &ev->plEvent );
00276         PL_EXIT_EVENT_QUEUE_MONITOR( padQueue );
00277             
00278         PR_Sleep( PR_MillisecondsToInterval(ThreadSleepTime) );
00279     } while( testFinished == PR_FALSE );
00280 
00281     PR_Sleep( PR_SecondsToInterval(4) );
00282 
00283     /*
00284     ** All done now. This thread can kill the main thread by sending 
00285     ** WM_DESTROY message to the main window.
00286     */
00287     SendMessage( hwnd, WM_DESTROY, 0, 0 );
00288     return;
00289 }    
00290 
00291 static char *startMessage = "Poppad: NSPR Windows GUI and event test program.\n"
00292                             "Every 1 second gets a '.'.\n"
00293                             "The test self terminates in less than a minute\n"
00294                             "You should be able to type in the window.\n\n";
00295 
00296 static char *stopMessage = "\n\nIf you saw a series of dots being emitted in the window\n"
00297                            " at one second intervals, the test worked.\n\n";
00298 
00299 /*
00300 ** HandlePadEvent() -- gets called because of PostEvent
00301 */
00302 static void PR_CALLBACK HandlePadEvent( PadEvent *padEvent )
00303 {
00304     char *cp;
00305     static const long lineLimit = 10;   /* limit on number of '.' per line */
00306     static const long timerLimit = 25;  /* limit on timer pop iterations */
00307 
00308     if ( timerCount++ == 0 )
00309     {
00310         
00311         for ( cp = startMessage; *cp != 0 ; cp++ )
00312         {
00313             SendMessage( hwndEdit, WM_CHAR, *cp, 1 );
00314         }
00315     }
00316     /* 
00317     ** Send a WM_CHAR event the edit Window
00318     */
00319     SendMessage( hwndEdit, WM_CHAR, '.', 1 );
00320     
00321     /*
00322     ** Limit the number of characters sent via timer pop to lineLimit
00323     */
00324     if ( (timerCount % lineLimit) == 0)
00325     {
00326         SendMessage( hwndEdit, WM_CHAR, '\n', 1 );
00327     }
00328 
00329     if ( timerCount >= timerLimit )
00330     {
00331         for ( cp = stopMessage; *cp != 0 ; cp++ )
00332         {
00333             SendMessage( hwndEdit, WM_CHAR, *cp, 1 );
00334         }
00335         testFinished = PR_TRUE;
00336     }
00337 
00338     return;
00339 }
00340 
00341 /*
00342 ** DestroyPadEvent() -- Called after HandlePadEvent()
00343 */
00344 static void PR_CALLBACK DestroyPadEvent( PadEvent *padevent )
00345 {
00346    PR_Free( padevent );
00347    return;
00348 }