349 lines
10 KiB
C
349 lines
10 KiB
C
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||
|
*
|
||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||
|
* the License. You may obtain a copy of the License at
|
||
|
* http://www.mozilla.org/MPL/
|
||
|
*
|
||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||
|
* for the specific language governing rights and limitations under the
|
||
|
* License.
|
||
|
*
|
||
|
* The Original Code is the Netscape Portable Runtime (NSPR).
|
||
|
*
|
||
|
* The Initial Developer of the Original Code is
|
||
|
* Netscape Communications Corporation.
|
||
|
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
||
|
* the Initial Developer. All Rights Reserved.
|
||
|
*
|
||
|
* Contributor(s):
|
||
|
*
|
||
|
* Alternatively, the contents of this file may be used under the terms of
|
||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||
|
* of those above. If you wish to allow use of your version of this file only
|
||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||
|
* use your version of this file under the terms of the MPL, indicate your
|
||
|
* decision by deleting the provisions above and replace them with the notice
|
||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||
|
* the provisions above, a recipient may use your version of this file under
|
||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||
|
*
|
||
|
* ***** END LICENSE BLOCK ***** */
|
||
|
|
||
|
/*
|
||
|
** File: winevent.c
|
||
|
** Description: Test functions in plevent.c using Windows
|
||
|
**
|
||
|
** The winevent test exercises the PLEvent library in a maner
|
||
|
** similar to how the Mozilla (or NGLayout) Client will use
|
||
|
** it in a Windows environment.
|
||
|
**
|
||
|
** This test is based on ideas taken from Charles Petzold's
|
||
|
** book "Programming Windows 3.1". License to use is in the
|
||
|
** book. It has been ported to Win32.
|
||
|
**
|
||
|
** Operation:
|
||
|
** The initialization is a standard Windows GUI application
|
||
|
** setup. When the main window receives its WM_CREATE
|
||
|
** message, a child window is created, a edit control is
|
||
|
** instantiated in that window.
|
||
|
**
|
||
|
** A thread is created; this thread runs in the function:
|
||
|
** TimerThread(). The new thread sends a message every second
|
||
|
** via the PL_PostEvent() function. The event handler
|
||
|
** HandlePadEvent() sends a windows message to the edit
|
||
|
** control window; these messages are WM_CHAR messages that
|
||
|
** cause the edit control to place a single '.' character in
|
||
|
** the edit control.
|
||
|
**
|
||
|
** After a deterministic number of '.' characters, the
|
||
|
** TimerThread() function is notified via a global variable
|
||
|
** that it's quitting time.
|
||
|
**
|
||
|
** TimerThread() callse TestEvents(), an external function
|
||
|
** that tests additional function of PLEvent.
|
||
|
**
|
||
|
*/
|
||
|
|
||
|
#include "nspr.h"
|
||
|
#include "plevent.h"
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <commdlg.h>
|
||
|
|
||
|
#define ID_EDIT 1
|
||
|
|
||
|
/*
|
||
|
** Declarations for NSPR customization
|
||
|
**
|
||
|
*/
|
||
|
typedef struct PadEvent
|
||
|
{
|
||
|
PLEvent plEvent;
|
||
|
int unused;
|
||
|
} PadEvent;
|
||
|
|
||
|
static void PR_CALLBACK TimerThread( void *arg);
|
||
|
static void PR_CALLBACK HandlePadEvent( PadEvent *padEvent );
|
||
|
static void PR_CALLBACK DestroyPadEvent( PadEvent *padevent );
|
||
|
|
||
|
static PRThread *tThread;
|
||
|
static PLEventQueue *padQueue;
|
||
|
static long ThreadSleepTime = 1000; /* in milli-seconds */
|
||
|
static long timerCount = 0;
|
||
|
static HWND hDlgModeless ;
|
||
|
static HWND hwndEdit ;
|
||
|
static PRBool testFinished = PR_FALSE;
|
||
|
static HWND hwnd ;
|
||
|
|
||
|
LRESULT CALLBACK WinProc (HWND, UINT, WPARAM, LPARAM);
|
||
|
|
||
|
TCHAR appName[] = TEXT ("WinEvent") ;
|
||
|
|
||
|
int WINAPI WinMain(
|
||
|
HINSTANCE hInstance,
|
||
|
HINSTANCE hPrevInstance,
|
||
|
PSTR szCmdLine,
|
||
|
int iCmdShow
|
||
|
)
|
||
|
{
|
||
|
MSG msg ;
|
||
|
WNDCLASS wndclass ;
|
||
|
HANDLE hAccel ;
|
||
|
|
||
|
PR_Init(0, 0, 0);
|
||
|
|
||
|
wndclass.style = CS_HREDRAW | CS_VREDRAW;
|
||
|
wndclass.lpfnWndProc = WinProc;
|
||
|
wndclass.cbClsExtra = 0;
|
||
|
wndclass.cbWndExtra = 0;
|
||
|
wndclass.hInstance = hInstance;
|
||
|
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
|
||
|
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
|
||
|
wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
|
||
|
wndclass.lpszMenuName = NULL;
|
||
|
wndclass.lpszClassName = appName;
|
||
|
|
||
|
if ( !RegisterClass( &wndclass ))
|
||
|
{
|
||
|
MessageBox( NULL,
|
||
|
TEXT( "This program needs Win32" ),
|
||
|
appName,
|
||
|
MB_ICONERROR );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
hwnd = CreateWindow( appName,
|
||
|
appName,
|
||
|
WS_OVERLAPPEDWINDOW,
|
||
|
CW_USEDEFAULT,
|
||
|
CW_USEDEFAULT,
|
||
|
CW_USEDEFAULT,
|
||
|
CW_USEDEFAULT,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
hInstance,
|
||
|
NULL);
|
||
|
|
||
|
ShowWindow( hwnd, iCmdShow );
|
||
|
UpdateWindow( hwnd );
|
||
|
|
||
|
for(;;)
|
||
|
{
|
||
|
if ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ))
|
||
|
{
|
||
|
if ( GetMessage( &msg, NULL, 0, 0 ))
|
||
|
{
|
||
|
if ( hDlgModeless == NULL || !IsDialogMessage( hDlgModeless, &msg ))
|
||
|
{
|
||
|
if ( !TranslateAccelerator( hwnd, hAccel, &msg ))
|
||
|
{
|
||
|
TranslateMessage( &msg );
|
||
|
DispatchMessage( &msg );
|
||
|
} /* end if !TranslateAccelerator */
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
} /* end if GetMessage() */
|
||
|
}
|
||
|
else /* !PeekMessage */
|
||
|
{
|
||
|
PR_Sleep(50);
|
||
|
}/* end if PeekMessage() */
|
||
|
} /* end for() */
|
||
|
|
||
|
PR_JoinThread( tThread );
|
||
|
PL_DestroyEventQueue( padQueue );
|
||
|
PR_Cleanup();
|
||
|
return msg.wParam ;
|
||
|
}
|
||
|
|
||
|
LRESULT CALLBACK WinProc(
|
||
|
HWND hwnd,
|
||
|
UINT message,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
switch (message)
|
||
|
{
|
||
|
case WM_CREATE :
|
||
|
hwndEdit = CreateWindow(
|
||
|
TEXT( "edit" ),
|
||
|
NULL,
|
||
|
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
|
||
|
WS_BORDER | ES_LEFT | ES_MULTILINE |
|
||
|
ES_AUTOHSCROLL | ES_AUTOVSCROLL,
|
||
|
0, 0, 0, 0,
|
||
|
hwnd,
|
||
|
(HMENU)ID_EDIT,
|
||
|
((LPCREATESTRUCT)lParam)->hInstance,
|
||
|
NULL);
|
||
|
|
||
|
/* Initialize Event Processing for NSPR
|
||
|
** Retrieve the event queue just created
|
||
|
** Create the TimerThread
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
PL_InitializeEventsLib( "someName" );
|
||
|
padQueue = PL_GetMainEventQueue();
|
||
|
*/
|
||
|
padQueue = PL_CreateEventQueue("MainQueue", PR_GetCurrentThread());
|
||
|
PR_ASSERT( padQueue != NULL );
|
||
|
tThread = PR_CreateThread( PR_USER_THREAD,
|
||
|
TimerThread,
|
||
|
NULL,
|
||
|
PR_PRIORITY_NORMAL,
|
||
|
PR_LOCAL_THREAD,
|
||
|
PR_JOINABLE_THREAD,
|
||
|
0 );
|
||
|
return 0 ;
|
||
|
|
||
|
case WM_SETFOCUS :
|
||
|
SetFocus( hwndEdit );
|
||
|
return 0;
|
||
|
|
||
|
case WM_SIZE :
|
||
|
MoveWindow( hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE );
|
||
|
return 0 ;
|
||
|
|
||
|
case WM_COMMAND :
|
||
|
if ( LOWORD(wParam) == ID_EDIT )
|
||
|
if ( HIWORD(wParam ) == EN_ERRSPACE ||
|
||
|
HIWORD( wParam ) == EN_MAXTEXT )
|
||
|
|
||
|
MessageBox( hwnd, TEXT( "Edit control out of space." ),
|
||
|
appName, MB_OK | MB_ICONSTOP );
|
||
|
return 0;
|
||
|
|
||
|
case WM_DESTROY :
|
||
|
PostQuitMessage(0);
|
||
|
return 0;
|
||
|
}
|
||
|
return DefWindowProc( hwnd, message, wParam, lParam );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
** TimerThread() -- The Main function of the timer pop thread
|
||
|
**
|
||
|
*/
|
||
|
static void PR_CALLBACK TimerThread( void *arg )
|
||
|
{
|
||
|
PRIntn rc;
|
||
|
|
||
|
do {
|
||
|
PadEvent *ev;
|
||
|
|
||
|
/*
|
||
|
** Create and Post the event the event
|
||
|
*/
|
||
|
PL_ENTER_EVENT_QUEUE_MONITOR( padQueue );
|
||
|
ev = (PadEvent *) PR_NEW( PadEvent );
|
||
|
PL_InitEvent( &ev->plEvent, NULL,
|
||
|
(PLHandleEventProc)HandlePadEvent,
|
||
|
(PLDestroyEventProc)DestroyPadEvent );
|
||
|
PL_PostEvent( padQueue, &ev->plEvent );
|
||
|
PL_EXIT_EVENT_QUEUE_MONITOR( padQueue );
|
||
|
|
||
|
PR_Sleep( PR_MillisecondsToInterval(ThreadSleepTime) );
|
||
|
} while( testFinished == PR_FALSE );
|
||
|
|
||
|
PR_Sleep( PR_SecondsToInterval(4) );
|
||
|
|
||
|
/*
|
||
|
** All done now. This thread can kill the main thread by sending
|
||
|
** WM_DESTROY message to the main window.
|
||
|
*/
|
||
|
SendMessage( hwnd, WM_DESTROY, 0, 0 );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static char *startMessage = "Poppad: NSPR Windows GUI and event test program.\n"
|
||
|
"Every 1 second gets a '.'.\n"
|
||
|
"The test self terminates in less than a minute\n"
|
||
|
"You should be able to type in the window.\n\n";
|
||
|
|
||
|
static char *stopMessage = "\n\nIf you saw a series of dots being emitted in the window\n"
|
||
|
" at one second intervals, the test worked.\n\n";
|
||
|
|
||
|
/*
|
||
|
** HandlePadEvent() -- gets called because of PostEvent
|
||
|
*/
|
||
|
static void PR_CALLBACK HandlePadEvent( PadEvent *padEvent )
|
||
|
{
|
||
|
char *cp;
|
||
|
static const long lineLimit = 10; /* limit on number of '.' per line */
|
||
|
static const long timerLimit = 25; /* limit on timer pop iterations */
|
||
|
|
||
|
if ( timerCount++ == 0 )
|
||
|
{
|
||
|
|
||
|
for ( cp = startMessage; *cp != 0 ; cp++ )
|
||
|
{
|
||
|
SendMessage( hwndEdit, WM_CHAR, *cp, 1 );
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
** Send a WM_CHAR event the edit Window
|
||
|
*/
|
||
|
SendMessage( hwndEdit, WM_CHAR, '.', 1 );
|
||
|
|
||
|
/*
|
||
|
** Limit the number of characters sent via timer pop to lineLimit
|
||
|
*/
|
||
|
if ( (timerCount % lineLimit) == 0)
|
||
|
{
|
||
|
SendMessage( hwndEdit, WM_CHAR, '\n', 1 );
|
||
|
}
|
||
|
|
||
|
if ( timerCount >= timerLimit )
|
||
|
{
|
||
|
for ( cp = stopMessage; *cp != 0 ; cp++ )
|
||
|
{
|
||
|
SendMessage( hwndEdit, WM_CHAR, *cp, 1 );
|
||
|
}
|
||
|
testFinished = PR_TRUE;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** DestroyPadEvent() -- Called after HandlePadEvent()
|
||
|
*/
|
||
|
static void PR_CALLBACK DestroyPadEvent( PadEvent *padevent )
|
||
|
{
|
||
|
PR_Free( padevent );
|
||
|
return;
|
||
|
}
|