1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
---|
2 | /* ***** BEGIN LICENSE BLOCK *****
|
---|
3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
---|
4 | *
|
---|
5 | * The contents of this file are subject to the Mozilla Public License Version
|
---|
6 | * 1.1 (the "License"); you may not use this file except in compliance with
|
---|
7 | * the License. You may obtain a copy of the License at
|
---|
8 | * http://www.mozilla.org/MPL/
|
---|
9 | *
|
---|
10 | * Software distributed under the License is distributed on an "AS IS" basis,
|
---|
11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
---|
12 | * for the specific language governing rights and limitations under the
|
---|
13 | * License.
|
---|
14 | *
|
---|
15 | * The Original Code is the Netscape Portable Runtime (NSPR).
|
---|
16 | *
|
---|
17 | * The Initial Developer of the Original Code is
|
---|
18 | * Netscape Communications Corporation.
|
---|
19 | * Portions created by the Initial Developer are Copyright (C) 1998-2000
|
---|
20 | * the Initial Developer. All Rights Reserved.
|
---|
21 | *
|
---|
22 | * Contributor(s):
|
---|
23 | *
|
---|
24 | * Alternatively, the contents of this file may be used under the terms of
|
---|
25 | * either the GNU General Public License Version 2 or later (the "GPL"), or
|
---|
26 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
---|
27 | * in which case the provisions of the GPL or the LGPL are applicable instead
|
---|
28 | * of those above. If you wish to allow use of your version of this file only
|
---|
29 | * under the terms of either the GPL or the LGPL, and not to allow others to
|
---|
30 | * use your version of this file under the terms of the MPL, indicate your
|
---|
31 | * decision by deleting the provisions above and replace them with the notice
|
---|
32 | * and other provisions required by the GPL or the LGPL. If you do not delete
|
---|
33 | * the provisions above, a recipient may use your version of this file under
|
---|
34 | * the terms of any one of the MPL, the GPL or the LGPL.
|
---|
35 | *
|
---|
36 | * ***** END LICENSE BLOCK ***** */
|
---|
37 |
|
---|
38 | /*
|
---|
39 | ** File: winevent.c
|
---|
40 | ** Description: Test functions in plevent.c using Windows
|
---|
41 | **
|
---|
42 | ** The winevent test exercises the PLEvent library in a maner
|
---|
43 | ** similar to how the Mozilla (or NGLayout) Client will use
|
---|
44 | ** it in a Windows environment.
|
---|
45 | **
|
---|
46 | ** This test is based on ideas taken from Charles Petzold's
|
---|
47 | ** book "Programming Windows 3.1". License to use is in the
|
---|
48 | ** book. It has been ported to Win32.
|
---|
49 | **
|
---|
50 | ** Operation:
|
---|
51 | ** The initialization is a standard Windows GUI application
|
---|
52 | ** setup. When the main window receives its WM_CREATE
|
---|
53 | ** message, a child window is created, a edit control is
|
---|
54 | ** instantiated in that window.
|
---|
55 | **
|
---|
56 | ** A thread is created; this thread runs in the function:
|
---|
57 | ** TimerThread(). The new thread sends a message every second
|
---|
58 | ** via the PL_PostEvent() function. The event handler
|
---|
59 | ** HandlePadEvent() sends a windows message to the edit
|
---|
60 | ** control window; these messages are WM_CHAR messages that
|
---|
61 | ** cause the edit control to place a single '.' character in
|
---|
62 | ** the edit control.
|
---|
63 | **
|
---|
64 | ** After a deterministic number of '.' characters, the
|
---|
65 | ** TimerThread() function is notified via a global variable
|
---|
66 | ** that it's quitting time.
|
---|
67 | **
|
---|
68 | ** TimerThread() callse TestEvents(), an external function
|
---|
69 | ** that tests additional function of PLEvent.
|
---|
70 | **
|
---|
71 | */
|
---|
72 |
|
---|
73 | #include "nspr.h"
|
---|
74 | #include "plevent.h"
|
---|
75 |
|
---|
76 | #include <windows.h>
|
---|
77 | #include <commdlg.h>
|
---|
78 |
|
---|
79 | #define ID_EDIT 1
|
---|
80 |
|
---|
81 | /*
|
---|
82 | ** Declarations for NSPR customization
|
---|
83 | **
|
---|
84 | */
|
---|
85 | typedef struct PadEvent
|
---|
86 | {
|
---|
87 | PLEvent plEvent;
|
---|
88 | int unused;
|
---|
89 | } PadEvent;
|
---|
90 |
|
---|
91 | static void PR_CALLBACK TimerThread( void *arg);
|
---|
92 | static void PR_CALLBACK HandlePadEvent( PadEvent *padEvent );
|
---|
93 | static void PR_CALLBACK DestroyPadEvent( PadEvent *padevent );
|
---|
94 |
|
---|
95 | static PRThread *tThread;
|
---|
96 | static PLEventQueue *padQueue;
|
---|
97 | static long ThreadSleepTime = 1000; /* in milli-seconds */
|
---|
98 | static long timerCount = 0;
|
---|
99 | static HWND hDlgModeless ;
|
---|
100 | static HWND hwndEdit ;
|
---|
101 | static PRBool testFinished = PR_FALSE;
|
---|
102 | static HWND hwnd ;
|
---|
103 |
|
---|
104 | LRESULT CALLBACK WinProc (HWND, UINT, WPARAM, LPARAM);
|
---|
105 |
|
---|
106 | TCHAR appName[] = TEXT ("WinEvent") ;
|
---|
107 |
|
---|
108 | int WINAPI WinMain(
|
---|
109 | HINSTANCE hInstance,
|
---|
110 | HINSTANCE hPrevInstance,
|
---|
111 | PSTR szCmdLine,
|
---|
112 | int iCmdShow
|
---|
113 | )
|
---|
114 | {
|
---|
115 | MSG msg ;
|
---|
116 | WNDCLASS wndclass ;
|
---|
117 | HANDLE hAccel ;
|
---|
118 |
|
---|
119 | PR_Init(0, 0, 0);
|
---|
120 |
|
---|
121 | wndclass.style = CS_HREDRAW | CS_VREDRAW;
|
---|
122 | wndclass.lpfnWndProc = WinProc;
|
---|
123 | wndclass.cbClsExtra = 0;
|
---|
124 | wndclass.cbWndExtra = 0;
|
---|
125 | wndclass.hInstance = hInstance;
|
---|
126 | wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
|
---|
127 | wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
|
---|
128 | wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
|
---|
129 | wndclass.lpszMenuName = NULL;
|
---|
130 | wndclass.lpszClassName = appName;
|
---|
131 |
|
---|
132 | if ( !RegisterClass( &wndclass ))
|
---|
133 | {
|
---|
134 | MessageBox( NULL,
|
---|
135 | TEXT( "This program needs Win32" ),
|
---|
136 | appName,
|
---|
137 | MB_ICONERROR );
|
---|
138 | return 0;
|
---|
139 | }
|
---|
140 |
|
---|
141 | hwnd = CreateWindow( appName,
|
---|
142 | appName,
|
---|
143 | WS_OVERLAPPEDWINDOW,
|
---|
144 | CW_USEDEFAULT,
|
---|
145 | CW_USEDEFAULT,
|
---|
146 | CW_USEDEFAULT,
|
---|
147 | CW_USEDEFAULT,
|
---|
148 | NULL,
|
---|
149 | NULL,
|
---|
150 | hInstance,
|
---|
151 | NULL);
|
---|
152 |
|
---|
153 | ShowWindow( hwnd, iCmdShow );
|
---|
154 | UpdateWindow( hwnd );
|
---|
155 |
|
---|
156 | for(;;)
|
---|
157 | {
|
---|
158 | if ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ))
|
---|
159 | {
|
---|
160 | if ( GetMessage( &msg, NULL, 0, 0 ))
|
---|
161 | {
|
---|
162 | if ( hDlgModeless == NULL || !IsDialogMessage( hDlgModeless, &msg ))
|
---|
163 | {
|
---|
164 | if ( !TranslateAccelerator( hwnd, hAccel, &msg ))
|
---|
165 | {
|
---|
166 | TranslateMessage( &msg );
|
---|
167 | DispatchMessage( &msg );
|
---|
168 | } /* end if !TranslateAccelerator */
|
---|
169 | }
|
---|
170 | }
|
---|
171 | else
|
---|
172 | {
|
---|
173 | break;
|
---|
174 | } /* end if GetMessage() */
|
---|
175 | }
|
---|
176 | else /* !PeekMessage */
|
---|
177 | {
|
---|
178 | PR_Sleep(50);
|
---|
179 | }/* end if PeekMessage() */
|
---|
180 | } /* end for() */
|
---|
181 |
|
---|
182 | PR_JoinThread( tThread );
|
---|
183 | PL_DestroyEventQueue( padQueue );
|
---|
184 | PR_Cleanup();
|
---|
185 | return msg.wParam ;
|
---|
186 | }
|
---|
187 |
|
---|
188 | LRESULT CALLBACK WinProc(
|
---|
189 | HWND hwnd,
|
---|
190 | UINT message,
|
---|
191 | WPARAM wParam,
|
---|
192 | LPARAM lParam
|
---|
193 | )
|
---|
194 | {
|
---|
195 | switch (message)
|
---|
196 | {
|
---|
197 | case WM_CREATE :
|
---|
198 | hwndEdit = CreateWindow(
|
---|
199 | TEXT( "edit" ),
|
---|
200 | NULL,
|
---|
201 | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
|
---|
202 | WS_BORDER | ES_LEFT | ES_MULTILINE |
|
---|
203 | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
|
---|
204 | 0, 0, 0, 0,
|
---|
205 | hwnd,
|
---|
206 | (HMENU)ID_EDIT,
|
---|
207 | ((LPCREATESTRUCT)lParam)->hInstance,
|
---|
208 | NULL);
|
---|
209 |
|
---|
210 | /* Initialize Event Processing for NSPR
|
---|
211 | ** Retrieve the event queue just created
|
---|
212 | ** Create the TimerThread
|
---|
213 | */
|
---|
214 |
|
---|
215 | /*
|
---|
216 | PL_InitializeEventsLib( "someName" );
|
---|
217 | padQueue = PL_GetMainEventQueue();
|
---|
218 | */
|
---|
219 | padQueue = PL_CreateEventQueue("MainQueue", PR_GetCurrentThread());
|
---|
220 | PR_ASSERT( padQueue != NULL );
|
---|
221 | tThread = PR_CreateThread( PR_USER_THREAD,
|
---|
222 | TimerThread,
|
---|
223 | NULL,
|
---|
224 | PR_PRIORITY_NORMAL,
|
---|
225 | PR_LOCAL_THREAD,
|
---|
226 | PR_JOINABLE_THREAD,
|
---|
227 | 0 );
|
---|
228 | return 0 ;
|
---|
229 |
|
---|
230 | case WM_SETFOCUS :
|
---|
231 | SetFocus( hwndEdit );
|
---|
232 | return 0;
|
---|
233 |
|
---|
234 | case WM_SIZE :
|
---|
235 | MoveWindow( hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE );
|
---|
236 | return 0 ;
|
---|
237 |
|
---|
238 | case WM_COMMAND :
|
---|
239 | if ( LOWORD(wParam) == ID_EDIT )
|
---|
240 | if ( HIWORD(wParam ) == EN_ERRSPACE ||
|
---|
241 | HIWORD( wParam ) == EN_MAXTEXT )
|
---|
242 |
|
---|
243 | MessageBox( hwnd, TEXT( "Edit control out of space." ),
|
---|
244 | appName, MB_OK | MB_ICONSTOP );
|
---|
245 | return 0;
|
---|
246 |
|
---|
247 | case WM_DESTROY :
|
---|
248 | PostQuitMessage(0);
|
---|
249 | return 0;
|
---|
250 | }
|
---|
251 | return DefWindowProc( hwnd, message, wParam, lParam );
|
---|
252 | }
|
---|
253 |
|
---|
254 |
|
---|
255 |
|
---|
256 | /*
|
---|
257 | ** TimerThread() -- The Main function of the timer pop thread
|
---|
258 | **
|
---|
259 | */
|
---|
260 | static void PR_CALLBACK TimerThread( void *arg )
|
---|
261 | {
|
---|
262 | PRIntn rc;
|
---|
263 |
|
---|
264 | do {
|
---|
265 | PadEvent *ev;
|
---|
266 |
|
---|
267 | /*
|
---|
268 | ** Create and Post the event the event
|
---|
269 | */
|
---|
270 | PL_ENTER_EVENT_QUEUE_MONITOR( padQueue );
|
---|
271 | ev = (PadEvent *) PR_NEW( PadEvent );
|
---|
272 | PL_InitEvent( &ev->plEvent, NULL,
|
---|
273 | (PLHandleEventProc)HandlePadEvent,
|
---|
274 | (PLDestroyEventProc)DestroyPadEvent );
|
---|
275 | PL_PostEvent( padQueue, &ev->plEvent );
|
---|
276 | PL_EXIT_EVENT_QUEUE_MONITOR( padQueue );
|
---|
277 |
|
---|
278 | PR_Sleep( PR_MillisecondsToInterval(ThreadSleepTime) );
|
---|
279 | } while( testFinished == PR_FALSE );
|
---|
280 |
|
---|
281 | PR_Sleep( PR_SecondsToInterval(4) );
|
---|
282 |
|
---|
283 | /*
|
---|
284 | ** All done now. This thread can kill the main thread by sending
|
---|
285 | ** WM_DESTROY message to the main window.
|
---|
286 | */
|
---|
287 | SendMessage( hwnd, WM_DESTROY, 0, 0 );
|
---|
288 | return;
|
---|
289 | }
|
---|
290 |
|
---|
291 | static char *startMessage = "Poppad: NSPR Windows GUI and event test program.\n"
|
---|
292 | "Every 1 second gets a '.'.\n"
|
---|
293 | "The test self terminates in less than a minute\n"
|
---|
294 | "You should be able to type in the window.\n\n";
|
---|
295 |
|
---|
296 | static char *stopMessage = "\n\nIf you saw a series of dots being emitted in the window\n"
|
---|
297 | " at one second intervals, the test worked.\n\n";
|
---|
298 |
|
---|
299 | /*
|
---|
300 | ** HandlePadEvent() -- gets called because of PostEvent
|
---|
301 | */
|
---|
302 | static void PR_CALLBACK HandlePadEvent( PadEvent *padEvent )
|
---|
303 | {
|
---|
304 | char *cp;
|
---|
305 | static const long lineLimit = 10; /* limit on number of '.' per line */
|
---|
306 | static const long timerLimit = 25; /* limit on timer pop iterations */
|
---|
307 |
|
---|
308 | if ( timerCount++ == 0 )
|
---|
309 | {
|
---|
310 |
|
---|
311 | for ( cp = startMessage; *cp != 0 ; cp++ )
|
---|
312 | {
|
---|
313 | SendMessage( hwndEdit, WM_CHAR, *cp, 1 );
|
---|
314 | }
|
---|
315 | }
|
---|
316 | /*
|
---|
317 | ** Send a WM_CHAR event the edit Window
|
---|
318 | */
|
---|
319 | SendMessage( hwndEdit, WM_CHAR, '.', 1 );
|
---|
320 |
|
---|
321 | /*
|
---|
322 | ** Limit the number of characters sent via timer pop to lineLimit
|
---|
323 | */
|
---|
324 | if ( (timerCount % lineLimit) == 0)
|
---|
325 | {
|
---|
326 | SendMessage( hwndEdit, WM_CHAR, '\n', 1 );
|
---|
327 | }
|
---|
328 |
|
---|
329 | if ( timerCount >= timerLimit )
|
---|
330 | {
|
---|
331 | for ( cp = stopMessage; *cp != 0 ; cp++ )
|
---|
332 | {
|
---|
333 | SendMessage( hwndEdit, WM_CHAR, *cp, 1 );
|
---|
334 | }
|
---|
335 | testFinished = PR_TRUE;
|
---|
336 | }
|
---|
337 |
|
---|
338 | return;
|
---|
339 | }
|
---|
340 |
|
---|
341 | /*
|
---|
342 | ** DestroyPadEvent() -- Called after HandlePadEvent()
|
---|
343 | */
|
---|
344 | static void PR_CALLBACK DestroyPadEvent( PadEvent *padevent )
|
---|
345 | {
|
---|
346 | PR_Free( padevent );
|
---|
347 | return;
|
---|
348 | }
|
---|