1 #include "win32\win32guts.h"
2 #include <ole2.h>
3 #ifndef _APRICOT_H_
4 #include "apricot.h"
5 #endif
6 #include "guts.h"
7 #include "Window.h"
8 #include "Application.h"
9 #include "Menu.h"
10
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14
15
16 #define sys (( PDrawableData)(( PComponent) self)-> sysData)->
17 #define dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)->
18 #define var (( PWidget) self)->
19 #define HANDLE sys handle
20 #define DHANDLE(x) dsys(x) handle
21
22 WinGuts guts;
23 DWORD rc;
24 PHash stylusMan = NULL; // pen & brush manager
25 PHash stylusGpMan = NULL; // pen & brush manager for GDI+
26 PHash fontMan = NULL; // font manager
27 PHash patMan = NULL; // pattern resource manager
28 PHash menuMan = NULL; // HMENU manager
29 PHash imageMan = NULL; // HBITMAP manager
30 PHash regnodeMan = NULL; // cache for apc_widget_user_profile
31 PHash myfontMan = NULL; // hash of calls to apc_font_load
32 PHash menuBitmapMan = NULL; // HBITMAP manager for SetMenuItemBitmaps
33 PHash scriptCacheMan = NULL; // SCRIPT_CACHE entries per font/script
34 HPEN hPenHollow;
35 HBRUSH hBrushHollow;
36 HCURSOR arrowCursor;
37 PatResource hPatHollow;
38 DIBMONOBRUSH bmiHatch = {
39 { sizeof( BITMAPINFOHEADER), 8, 8, 1, 1, BI_RGB, 0, 0, 0, 2, 2},
40 {{0,0,0,0}, {0,0,0,0}}
41 };
42 int FONTSTRUCSIZE;
43 Handle lastMouseOver = NULL_HANDLE;
44 MusClkRec musClk = {0};
45 char * keyLayouts[] = { "0409", "0403", "0405", "0406", "0407",
46 "0807","0809","080A","080C","0C0C","100C","0810","0814","0816",
47 "040A","040B","040C","040E","040F","0410","0413","0414","0415","0416",
48 "0417","0418","041A","041D"
49 };
50 WCHAR lastDeadKey = 0;
51 int timeDefsCount = 0;
52 PItemRegRec timeDefs = NULL;
53 Bool debug = false;
54 HBITMAP uncheckedBitmap = NULL;
55
56 BOOL APIENTRY
DllMain(HINSTANCE hInstance,DWORD reason,LPVOID reserved)57 DllMain( HINSTANCE hInstance, DWORD reason, LPVOID reserved)
58 {
59 if ( reason == DLL_PROCESS_ATTACH) {
60 memset( &guts, 0, sizeof( guts));
61 guts. instance = hInstance;
62 guts. cmdShow = SW_SHOWDEFAULT;
63 }
64 return TRUE;
65 }
66
67 typedef enum _PROCESS_DPI_AWARENESS {
68 PROCESS_DPI_UNAWARE = 0,
69 PROCESS_SYSTEM_DPI_AWARE = 1,
70 PROCESS_PER_MONITOR_DPI_AWARE = 2
71 } PROCESS_DPI_AWARENESS;
72
73 typedef enum _MONITOR_DPI_TYPE {
74 MDT_EFFECTIVE_DPI = 0,
75 MDT_ANGULAR_DPI = 1,
76 MDT_RAW_DPI = 2
77 } MONITOR_DPI_TYPE;
78
79 #ifndef MONITOR_DEFAULTTONEAREST
80 #define MONITOR_DEFAULTTONULL 0
81 #define MONITOR_DEFAULTTOPRIMARY 1
82 #define MONITOR_DEFAULTTONEAREST 2
83 #endif
84
85 static HRESULT (__stdcall *SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS) = NULL;
86 static HRESULT (__stdcall *GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*) = NULL;
87 static HRESULT (__stdcall *DwmIsCompositionEnabled)(BOOL *pfEnabled) = NULL;
88 static BOOL (__stdcall *GetUserPreferredUILanguages)(DWORD dwFlags, PULONG pulNumLanguages, PZZWSTR pwszLanguagesBuffer, PULONG pcchLanguagesBuffer) = NULL;
89
90 BOOL
my_GetUserPreferredUILanguages(DWORD dwFlags,PULONG pulNumLanguages,PZZWSTR pwszLanguagesBuffer,PULONG pcchLanguagesBuffer)91 my_GetUserPreferredUILanguages(
92 DWORD dwFlags, PULONG pulNumLanguages,
93 PZZWSTR pwszLanguagesBuffer, PULONG pcchLanguagesBuffer
94 ) {
95 if ( GetUserPreferredUILanguages == NULL)
96 return false;
97 return GetUserPreferredUILanguages(dwFlags, pulNumLanguages, pwszLanguagesBuffer, pcchLanguagesBuffer);
98 }
99
100
101 void
dpi_change(void)102 dpi_change(void)
103 {
104 UINT dx, dy;
105 POINT pt = {1,1};
106 HMONITOR m = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
107 if ( GetDpiForMonitor && (GetDpiForMonitor( m, MDT_EFFECTIVE_DPI, &dx, &dy) == S_OK )) {
108 guts. displayResolution. x = dx;
109 guts. displayResolution. y = dy;
110 }
111 }
112
113 Bool
is_dwm_enabled(void)114 is_dwm_enabled( void )
115 {
116 if ( DwmIsCompositionEnabled ) {
117 BOOL b;
118 if ( DwmIsCompositionEnabled(&b) != S_OK) goto NOPE;
119 return b;
120 } else {
121 HKEY hKey;
122 DWORD valSize = 256, valType = REG_SZ, dw = 0;
123 NOPE:
124 if ( LOBYTE(LOWORD(guts.version)) > 5 )
125 return 1;
126 valType = REG_DWORD;
127 valSize = sizeof(DWORD);
128 if ( RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\DWM", 0, KEY_READ, &hKey) == 0 ) {
129 if ( RegQueryValueEx( hKey, "CompositionPolicy", NULL, &valType, ( LPBYTE)&dw, &valSize) != 0 )
130 dw = 1;
131 RegCloseKey( hKey);
132 return dw == 0;
133 } else
134 return 0;
135 }
136 }
137
138 static void
load_function(HMODULE module,void ** ptr,const char * name)139 load_function(HMODULE module, void ** ptr, const char * name)
140 {
141 (*ptr) = (void*) GetProcAddress(module, name);
142 }
143
144 Bool
window_subsystem_init(char * error_buf)145 window_subsystem_init( char * error_buf)
146 {
147 WNDCLASSW wc;
148 HDC dc;
149 HBITMAP hbm;
150 OSVERSIONINFO os = { sizeof( OSVERSIONINFO)};
151 GdiplusStartupInput gdiplusStartupInputDef = { 1, NULL, FALSE, FALSE };
152
153 guts. version = GetVersion();
154 GetVersionEx( &os);
155 guts. utf8_prepend_0x202D =
156 (( os.dwMajorVersion > 5) || (os.dwMajorVersion == 5 && os.dwMinorVersion > 1)) ?
157 1 : 0;
158 guts. alloc_utf8_to_wchar_visual =
159 guts. utf8_prepend_0x202D ?
160 alloc_utf8_to_wchar_visual :
161 alloc_utf8_to_wchar;
162 guts. mainThreadId = GetCurrentThreadId();
163 guts. errorMode = SetErrorMode( SEM_FAILCRITICALERRORS);
164 guts. desktopWindow = GetDesktopWindow();
165 arrowCursor = LoadCursor( NULL, IDC_ARROW);
166
167 memset( &wc, 0, sizeof( wc));
168 wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
169 wc.lpfnWndProc = ( WNDPROC) generic_app_handler;
170 wc.cbClsExtra = 0;
171 wc.cbWndExtra = 0;
172 wc.hInstance = guts. instance;
173 wc.hIcon = LoadIcon( guts. instance, IDI_APPLICATION);
174 wc.hCursor = LoadCursor( NULL, IDC_ARROW);
175 wc.hbrBackground = (HBRUSH)NULL;
176 wc.lpszClassName = L"GenericApp";
177 RegisterClassW( &wc);
178
179 memset( &wc, 0, sizeof( wc));
180 wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
181 wc.lpfnWndProc = ( WNDPROC) generic_frame_handler;
182 wc.cbClsExtra = 0;
183 wc.cbWndExtra = 0;
184 wc.hInstance = guts. instance;
185 wc.hIcon = LoadIcon( guts. instance, IDI_APPLICATION);
186 wc.hCursor = arrowCursor;
187 wc.hbrBackground = (HBRUSH)NULL;
188 wc.lpszClassName = L"GenericFrame";
189 RegisterClassW( &wc);
190
191 memset( &wc, 0, sizeof( wc));
192 wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
193 wc.lpfnWndProc = ( WNDPROC) layered_frame_handler;
194 wc.cbClsExtra = 0;
195 wc.cbWndExtra = 0;
196 wc.hInstance = guts. instance;
197 wc.hIcon = LoadIcon( guts. instance, IDI_APPLICATION);
198 wc.hCursor = arrowCursor;
199 wc.hbrBackground = (HBRUSH)NULL;
200 wc.lpszClassName = L"LayeredFrame";
201 RegisterClassW( &wc);
202
203 memset( &wc, 0, sizeof( wc));
204 wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
205 wc.lpfnWndProc = ( WNDPROC) generic_view_handler;
206 wc.cbClsExtra = 0;
207 wc.cbWndExtra = 0;
208 wc.hInstance = guts. instance;
209 wc.hIcon = LoadIcon( guts. instance, IDI_APPLICATION);
210 wc.hCursor = NULL; // LoadCursor( NULL, IDC_ARROW);
211 wc.hbrBackground = (HBRUSH)NULL;
212 wc.lpszClassName = L"Generic";
213 RegisterClassW( &wc);
214
215 stylusMan = hash_create();
216 stylusGpMan= hash_create();
217 fontMan = hash_create();
218 patMan = hash_create();
219 menuMan = hash_create();
220 imageMan = hash_create();
221 regnodeMan = hash_create();
222 myfontMan = hash_create();
223 menuBitmapMan = hash_create();
224 scriptCacheMan = hash_create();
225 create_font_hash();
226 {
227 LOGBRUSH b = { BS_HOLLOW, 0, 0};
228 Font f;
229 hPenHollow = CreatePen( PS_NULL, 0, 0);
230 hBrushHollow = CreateBrushIndirect( &b);
231 hPatHollow. dotsCount = 0;
232 hPatHollow. dotsPtr = NULL;
233 FONTSTRUCSIZE = (char *)(&(f. name)) - (char *)(&f);
234 }
235
236 if (!( dc = dc_alloc())) return false;
237 guts. displayResolution. x = GetDeviceCaps( dc, LOGPIXELSX);
238 guts. displayResolution. y = GetDeviceCaps( dc, LOGPIXELSY);
239
240 /* Win7 DWM */
241 #define LOAD_FUNC(m,f) load_function(m, (void**) &f, #f)
242 if ( os.dwMajorVersion >= 5) {
243 HMODULE mod = LoadLibrary("DWMAPI.DLL");
244 if ( mod ) {
245 LOAD_FUNC(mod, DwmIsCompositionEnabled);
246 }
247 mod = LoadLibrary("KERNEL32.DLL");
248 if ( mod ) {
249 LOAD_FUNC(mod, GetUserPreferredUILanguages);
250 }
251 }
252
253 /* Win8 - high dpi awareness stuff */
254 if (( os.dwMajorVersion > 5) || (os.dwMajorVersion == 5 && os.dwMinorVersion > 1)) {
255 HMODULE shcore = LoadLibrary("SHCORE.DLL");
256 if ( shcore ) {
257 LOAD_FUNC(shcore, SetProcessDpiAwareness);
258 LOAD_FUNC(shcore, GetDpiForMonitor);
259 }
260 if (
261 SetProcessDpiAwareness && GetDpiForMonitor &&
262 (SetProcessDpiAwareness( PROCESS_PER_MONITOR_DPI_AWARE) == S_OK )
263 )
264 dpi_change();
265 }
266 #undef LOAD_FUNC
267
268 {
269 LOGFONT lf;
270 HFONT sfont;
271
272 // getting most common font name
273 memset( &lf, 0, sizeof( lf));
274 lf. lfCharSet = OEM_CHARSET;
275 lf. lfOutPrecision = OUT_DEFAULT_PRECIS;
276 lf. lfClipPrecision = CLIP_DEFAULT_PRECIS;
277 lf. lfQuality = PROOF_QUALITY;
278 lf. lfPitchAndFamily = DEFAULT_PITCH;
279 sfont = SelectObject( dc, CreateFontIndirect( &lf));
280 GetTextFace( dc, 256, guts. defaultSystemFont);
281
282 // getting common fixed font name
283 lf. lfHeight = 320;
284 lf. lfPitchAndFamily = FIXED_PITCH;
285 DeleteObject( SelectObject( dc, CreateFontIndirect( &lf)));
286 GetTextFace( dc, 256, guts. defaultFixedFont);
287
288 // getting common variable font name
289 lf. lfPitchAndFamily = VARIABLE_PITCH;
290 DeleteObject( SelectObject( dc, CreateFontIndirect( &lf)));
291 GetTextFace( dc, 256, guts. defaultVariableFont);
292 DeleteObject( SelectObject( dc, sfont));
293
294 // getting system font presets
295 reset_system_fonts();
296 register_mapper_fonts();
297 }
298
299 memset( &guts. displayBMInfo, 0, sizeof( guts. displayBMInfo));
300 guts. displayBMInfo. bmiHeader. biSize = sizeof( BITMAPINFO);
301 if ( !( hbm = GetCurrentObject( dc, OBJ_BITMAP))) {
302 apiErr;
303 dc_free();
304 return false;
305 }
306
307 if ( !GetDIBits( dc, hbm, 0, 0, NULL, &guts. displayBMInfo, DIB_PAL_COLORS)) {
308 guts. displayBMInfo. bmiHeader. biBitCount = GetDeviceCaps( dc, BITSPIXEL);
309 guts. displayBMInfo. bmiHeader. biPlanes = GetDeviceCaps( dc, PLANES);
310 }
311
312 dc_free();
313 guts. insertMode = true;
314 guts. iconSizeSmall. x = GetSystemMetrics( SM_CXSMICON);
315 guts. iconSizeSmall. y = GetSystemMetrics( SM_CYSMICON);
316 guts. iconSizeLarge. x = GetSystemMetrics( SM_CXICON);
317 guts. iconSizeLarge. y = GetSystemMetrics( SM_CYICON);
318 guts. pointerSize. x = GetSystemMetrics( SM_CXCURSOR);
319 guts. pointerSize. y = GetSystemMetrics( SM_CYCURSOR);
320 list_create( &guts. transp, 8, 8);
321 list_create( &guts. files, 8, 8);
322 list_create( &guts. sockets, 8, 8);
323
324 // selecting locale layout, more or less latin-like
325
326 {
327 char buf[ KL_NAMELENGTH * 2] = "";
328 HKL current = GetKeyboardLayout( 0);
329 int i, j, size = GetKeyboardLayoutList( 0, NULL);
330 HKL * kl = ( HKL *) malloc( sizeof( HKL) * size);
331
332 guts. keyLayout = NULL;
333 if ( !GetKeyboardLayoutName( buf)) apiErr;
334 for ( j = 0; j < ( sizeof( keyLayouts) / sizeof( char*)); j++) {
335 if ( strncmp( buf + 4, keyLayouts[ j], 4) == 0) {
336 guts. keyLayout = current;
337 goto found_1;
338 }
339 }
340
341 if ( kl) {
342 GetKeyboardLayoutList( size, kl);
343 for ( i = 0; i < size; i++) {
344 ActivateKeyboardLayout( kl[ i], 0);
345 if ( !GetKeyboardLayoutName( buf)) apiErr;
346 for ( j = 0; j < ( sizeof( keyLayouts) / sizeof( char*)); j++) {
347 if ( strncmp( buf + 4, keyLayouts[ j], 4) == 0) {
348 guts. keyLayout = kl[ i];
349 goto found_2;
350 }
351 }
352 }
353 found_2:;
354 ActivateKeyboardLayout( current, 0);
355 }
356 found_1:;
357 free( kl);
358 }
359 guts. currentKeyState = guts. keyState;
360 memset( guts. emptyKeyState, 0, sizeof( guts. emptyKeyState));
361 guts. smDblClk. x = GetSystemMetrics( SM_CXDOUBLECLK);
362 guts. smDblClk. y = GetSystemMetrics( SM_CYDOUBLECLK);
363
364 GdiplusStartup(&guts.gdiplusToken, &gdiplusStartupInputDef, NULL);
365 {
366 HRESULT r = OleInitialize(NULL);
367 guts. ole_initialized = (r == S_OK || r == S_FALSE );
368 }
369
370 return true;
371 }
372
373 Bool
window_subsystem_get_options(int * argc,char *** argv)374 window_subsystem_get_options( int * argc, char *** argv)
375 {
376 static char * win32_argv[] = {
377 "debug", "turns on debugging"
378 };
379 *argv = win32_argv;
380 *argc = sizeof( win32_argv) / sizeof( char*);
381 return true;
382 }
383
384 Bool
window_subsystem_set_option(char * option,char * value)385 window_subsystem_set_option( char * option, char * value)
386 {
387 if ( strcmp( option, "debug") == 0) {
388 debug = value ? *value != '0' : true;
389 return true;
390 }
391 return false;
392 }
393
394 static Bool
myfont_cleaner(void * value,int keyLen,void * key,void * dummy)395 myfont_cleaner( void * value, int keyLen, void * key, void * dummy)
396 {
397 RemoveFontResource((LPCTSTR)key);
398 return false;
399 }
400
401 static Bool
menu_bitmap_cleaner(void * value,int keyLen,void * key,void * dummy)402 menu_bitmap_cleaner( void * value, int keyLen, void * key, void * dummy)
403 {
404 DeleteObject((HBITMAP) value);
405 return false;
406 }
407
408 void
window_subsystem_done()409 window_subsystem_done()
410 {
411 if (guts. ole_initialized)
412 OleUninitialize();
413 free( timeDefs);
414 timeDefs = NULL;
415 list_destroy( &guts. files);
416
417 if ( guts. socketMutex) {
418 // appDead must be TRUE for this moment!
419 appDead = true;
420 CloseHandle( guts. socketMutex);
421 }
422
423 list_destroy( &guts. sockets);
424 list_destroy( &guts. transp);
425 destroy_font_hash();
426
427 font_clean();
428 stylus_clean();
429
430 stylus_gp_clean();
431 GdiplusShutdown(guts.gdiplusToken);
432
433 hash_destroy( imageMan, false);
434 hash_destroy( menuMan, false);
435 hash_destroy( patMan, true);
436 hash_destroy( fontMan, true);
437 hash_destroy( stylusGpMan,true);
438 hash_destroy( stylusMan, true);
439 hash_destroy( regnodeMan, false);
440
441 hash_first_that( menuBitmapMan, menu_bitmap_cleaner, NULL, NULL, NULL);
442 hash_destroy( menuBitmapMan, false);
443 hash_destroy( scriptCacheMan, true);
444
445 hash_first_that( myfontMan, myfont_cleaner, NULL, NULL, NULL);
446 hash_destroy( myfontMan, false);
447 DeleteObject( hPenHollow);
448 DeleteObject( hBrushHollow);
449 if ( uncheckedBitmap && uncheckedBitmap != (HBITMAP)-1)
450 DeleteObject( uncheckedBitmap);
451 SetErrorMode( guts. errorMode);
452 }
453
454 void
window_subsystem_cleanup()455 window_subsystem_cleanup()
456 {
457 while ( guts. appLock > 0) apc_application_unlock( application);
458 while ( guts. pointerLock < 0) {
459 ShowCursor( 1);
460 guts. pointerLock++;
461 }
462 }
463
464 static char err_buf[ 256] = "";
err_msg(DWORD errId,char * buffer)465 char * err_msg( DWORD errId, char * buffer)
466 {
467 LPVOID lpMsgBuf;
468 int len;
469 if ( buffer == NULL) buffer = err_buf;
470 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errId,
471 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
472 ( LPTSTR) &lpMsgBuf, 0, NULL);
473 if ( lpMsgBuf)
474 strncpy( buffer, ( const char *) lpMsgBuf, 256);
475 else
476 buffer[0] = 0;
477 buffer[ 255] = 0;
478 LocalFree( lpMsgBuf);
479
480 /* chomp! */
481 len = strlen(buffer);
482 while ( len > 0) {
483 len--;
484 if ( buffer[len] != '\xD' && buffer[len] != '\xA' && buffer[len] != '.')
485 break;
486 buffer[len] = 0;
487 }
488
489 return buffer;
490 }
491
err_msg_gplus(GpStatus errId,char * buffer)492 char * err_msg_gplus( GpStatus errId, char * buffer)
493 {
494 if ( buffer == nil) buffer = err_buf;
495 switch(errId) {
496 case Ok : strcpy(buffer, "Ok"); break;
497 case GenericError : strcpy(buffer, "GDI+ generic error"); break;
498 case InvalidParameter : strcpy(buffer, "GDI+ invalid parameter"); break;
499 case OutOfMemory : strcpy(buffer, "GDI+ out of memory"); break;
500 case ObjectBusy : strcpy(buffer, "GDI+ object busy"); break;
501 case InsufficientBuffer : strcpy(buffer, "GDI+ insufficient buffer"); break;
502 case NotImplemented : strcpy(buffer, "GDI+ not implemented"); break;
503 case Win32Error : strcpy(buffer, "GDI+ Win32 error"); break;
504 case WrongState : strcpy(buffer, "GDI+ Wrong state"); break;
505 case Aborted : strcpy(buffer, "GDI+ aborted"); break;
506 case FileNotFound : strcpy(buffer, "GDI+ file not found"); break;
507 case ValueOverflow : strcpy(buffer, "GDI+ value overflow"); break;
508 case AccessDenied : strcpy(buffer, "GDI+ access denied"); break;
509 case UnknownImageFormat : strcpy(buffer, "GDI+ unknown image format"); break;
510 case FontFamilyNotFound : strcpy(buffer, "GDI+ font family not found"); break;
511 case FontStyleNotFound : strcpy(buffer, "GDI+ font style not found"); break;
512 case NotTrueTypeFont : strcpy(buffer, "GDI+ not a TrueType font"); break;
513 case UnsupportedGdiplusVersion : strcpy(buffer, "GDI+ unsipported Gdiplus version"); break;
514 case GdiplusNotInitialized : strcpy(buffer, "GDI+ not initialized"); break;
515 case PropertyNotFound : strcpy(buffer, "GDI+ property not found"); break;
516 case PropertyNotSupported : strcpy(buffer, "GDI+ property not supported"); break;
517 case ProfileNotFound : strcpy(buffer, "GDI+ profile not found"); break;
518 default : strcpy(buffer, "GDI+ unknown error");
519 }
520 return buffer;
521 }
522
523 char *
apc_last_error(void)524 apc_last_error(void)
525 {
526 switch (apcError) {
527 case errApcError : return err_buf;
528 case errOk : return NULL;
529 case errInvObject : return "Bad object";
530 case errInvParams : return "Bad parameters";
531 case errInvWindowIcon : return "Bad window icon";
532 case errInvClipboardData : return "Bad clipboard request";
533 case errInvPrinter : return "Bad printer request";
534 case errNoPrinters : return "No printers";
535 case errUserCancelled : return "User cancelled";
536 default : return "Unknown error";
537 }
538 }
539
move_back(PWidget self,PWidget child,int * delta)540 static Bool move_back( PWidget self, PWidget child, int * delta)
541 {
542 RECT r;
543 int oStage = child-> stage;
544
545 if ( !dsys( child) options. aptClipOwner) return false;
546
547 child-> stage = csFrozen;
548 GetWindowRect( DHANDLE( child), &r);
549 if ( dsys( child) options. aptClipOwner)
550 MapWindowPoints( NULL, ( HWND) self-> handle, ( LPPOINT)&r, 2);
551 SetWindowPos( DHANDLE( child), 0, r. left, r. top + *delta, 0, 0,
552 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
553 child-> stage = oStage;
554
555 return false;
556 }
557
558
559 static Bool
local_wnd(HWND who,HWND client)560 local_wnd( HWND who, HWND client)
561 {
562 PComponent v;
563 Handle self;
564 if ( who == client)
565 return true;
566 self = GetWindowLongPtr( client, GWLP_USERDATA);
567 v = (PComponent) hwnd_to_view( who);
568 while (v && ( Handle) v != application)
569 {
570 if ( (Handle)v == self) return true;
571 v = ( PComponent) ( v-> owner);
572 }
573 return false;
574 }
575
576 extern Handle ctx_kb2VK[];
577 extern Handle ctx_kb2VK2[];
578 extern Handle ctx_kb2VK3[];
579
580 static Bool
find_oid(PAbstractMenu menu,PMenuItemReg m,int id)581 find_oid( PAbstractMenu menu, PMenuItemReg m, int id)
582 {
583 return m-> down && ( m-> down-> id == id);
584 }
585
586 Handle ctx_deadkeys[] = {
587 0x5E, 0x302, // Circumflex accent
588 0x60, 0x300, // Grave accent
589 0xA8, 0x308, // Diaeresis
590 0xB4, 0x301, // Acute accent
591 0xB8, 0x327, // Cedilla
592 endCtx
593 };
594
595 static void
zorder_sync(Handle self,HWND me,LPWINDOWPOS lp)596 zorder_sync( Handle self, HWND me, LPWINDOWPOS lp)
597 {
598 if ( lp-> hwndInsertAfter == HWND_TOP ||
599 lp-> hwndInsertAfter == HWND_NOTOPMOST ||
600 lp-> hwndInsertAfter == HWND_TOPMOST) {
601 me = GetNextWindow( me, GW_HWNDPREV);
602 if ( me)
603 PostMessage( me, WM_ZORDERSYNC, 0, 0);
604 } else if ( lp-> hwndInsertAfter == HWND_BOTTOM) {
605 me = GetNextWindow( me, GW_HWNDNEXT);
606 if ( me)
607 PostMessage( me, WM_ZORDERSYNC, 0, 0);
608 }
609 }
610
611 static Bool
id_match(Handle self,PMenuItemReg m,void * params)612 id_match( Handle self, PMenuItemReg m, void * params)
613 {
614 return m-> id == *(( int*) params);
615 }
616
generic_view_handler(HWND win,UINT msg,WPARAM mp1,LPARAM mp2)617 LRESULT CALLBACK generic_view_handler( HWND win, UINT msg, WPARAM mp1, LPARAM mp2)
618 {
619 LRESULT ret = 0;
620 Handle self = GetWindowLongPtr( win, GWLP_USERDATA);
621 PWidget v = ( PWidget) self;
622 UINT orgMsg = msg;
623 Event ev;
624 Bool hiStage = false;
625 Bool message_result = true;
626
627 if ( !self || appDead)
628 return DefWindowProcW( win, msg, mp1, mp2);
629
630 memset( &ev, 0, sizeof (ev));
631 ev. gen. source = self;
632
633 switch ( msg) {
634 case WM_NCACTIVATE:
635 // if activation or deactivation is concerned with declipped window ( e.g.self),
636 // notify its top level frame so that it will have the chance to redraw itself correspondingly
637 if ( is_declipped_child( self) && !Widget_is_child( hwnd_to_view(( HWND) mp2), hwnd_top_level( self))) {
638 Handle x = hwnd_top_level( self);
639 if ( x) SendMessage( DHANDLE( x), WM_NCACTIVATE, mp1, mp2);
640 }
641 break;
642 case WM_MOUSEACTIVATE:
643 // if pointing to non-active frame, but its declipped child is active at the moment,
644 // cancel activation - it could produce unwilling focus changes
645 if ( sys className == WC_FRAME) {
646 Handle x = hwnd_to_view( GetActiveWindow());
647 if ( is_declipped_child(x) && Widget_is_child( x, self))
648 return MA_NOACTIVATE;
649 }
650 break;
651 case WM_CLOSE:
652 if ( guts. focSysDialog) return 0;
653 if ( sys className != WC_FRAME)
654 return 0;
655 break;
656 case WM_COMMAND:
657 if (( HIWORD( mp1) == 0 /* menu source */) && ( mp2 == 0)) {
658 if ( LOWORD( mp1) <= MENU_ID_AUTOSTART) {
659 HWND active = GetFocus();
660 if ( active != NULL) SendMessage( active, LOWORD( mp1), 0, 0);
661 } else if ( sys lastMenu) {
662 PAbstractMenu a = ( PAbstractMenu) sys lastMenu;
663 if ( a-> stage <= csNormal)
664 a-> self-> sub_call_id(( Handle) a, LOWORD( mp1) - MENU_ID_AUTOSTART);
665 }
666 }
667 break;
668 case WM_CONTEXTMENU:
669 {
670 POINT a;
671 a. x = ( short)LOWORD( mp2);
672 a. y = ( short)HIWORD( mp2);
673 ev. cmd = cmPopup;
674 // mouse event
675 ev. gen. B = ( GetKeyState( VK_LBUTTON) < 0) | ( GetKeyState( VK_RBUTTON) < 0);
676 if ( !ev. gen. B && GetSystemMetrics( SM_MOUSEPRESENT))
677 GetCursorPos(( POINT*) &a);
678
679 MapWindowPoints( NULL, win, &a, 1);
680 ev. gen. P. x = a. x;
681 ev. gen. P. y = sys lastSize. y - a. y - 1;
682 }
683 break;
684 case WM_DRAG_RESPONSE:
685 SetCursor( sys pointer );
686 break;
687 case WM_DRAWITEM:
688 {
689 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT*) mp2;
690 if ( dis-> CtlType == ODT_MENU && dis-> itemData != 0) {
691 RECT r;
692 self = (Handle) dis-> itemData;
693 v = (PWidget) self;
694 GetClientRect(WindowFromDC(dis->hDC), &r);
695 ev.cmd = cmMenuItemPaint;
696 ev.gen.i = (Handle) dis-> itemID - MENU_ID_AUTOSTART;
697 ev.gen.p = (void*) dis->hDC;
698 ev.gen.B = ((dis-> itemState & ODS_SELECTED) != 0);
699 ev.gen.P.x = r.right;
700 ev.gen.P.y = r.bottom;
701 ev.gen.R.left = dis-> rcItem.left;
702 ev.gen.R.bottom = r.bottom - dis-> rcItem.bottom;
703 ev.gen.R.right = dis-> rcItem.right - 1;
704 ev.gen.R.top = r.bottom - dis-> rcItem.top - 1;
705 }
706 }
707 break;
708 case WM_ENABLE:
709 ev. cmd = mp1 ? cmEnable : cmDisable;
710 hiStage = true;
711 break;
712 case WM_ERASEBKGND:
713 return 1;
714 case WM_FORCEFOCUS:
715 if ( mp2)
716 ((( PWidget) mp2)-> self)-> set_selected(( Handle) mp2, 1);
717 return 0;
718 case WM_HASMATE:
719 *(( Handle*) mp2) = self;
720 return HASMATE_MAGIC;
721 case WM_IME_CHAR:
722 if ( apc_widget_is_responsive( self)) {
723 ev. cmd = cmKeyDown;
724 ev. key. mod = kmUnicode;
725 ev. key. key = kbNoKey;
726 ev. key. code = mp1;
727 }
728 break;
729 case WM_SYSKEYDOWN:
730 case WM_SYSKEYUP:
731 if ( mp2 & ( 1 << 29)) ev. key. mod = kmAlt;
732 case WM_KEYDOWN:
733 case WM_KEYUP:
734 if ( apc_widget_is_responsive( self)) {
735 BYTE * keyState;
736 Bool up = ( msg == WM_KEYUP) || ( msg == WM_SYSKEYUP);
737 Bool extended = mp2 & ( 1 << 24);
738 UINT scan = ( HIWORD( mp2) & 0xFF) | ( up ? 0x80000000 : 0);
739 int deadPollCount = 0;
740 HKL kl = GetKeyboardLayout(0);
741
742 // basic assignments
743 ev. cmd = up ? cmKeyUp : cmKeyDown;
744 ev. key. key = ctx_remap_def( mp1, ctx_kb2VK, false, kbNoKey);
745 ev. key. code = mp1;
746 ev. key. repeat = mp2 & 0x000000FF;
747
748 // VK validations
749 if ( extended) {
750 int ks = ev. key. key;
751 ev. key. key = ctx_remap_def( ks, ctx_kb2VK3, true, ks);
752 if ( ev. key. key != ks)
753 extended = false; // avoid (Ctrl|Alt)R+KeyPad combinations
754 } else if ( mp1 >= VK_NUMPAD0 && mp1 <= VK_DIVIDE)
755 extended = true; // include numpads
756
757 ev. key. mod = 0 |
758 ( extended ? kmKeyPad : 0) |
759 (( GetKeyState( VK_SHIFT) < 0) ? kmShift : 0) |
760 (( GetKeyState( VK_CONTROL) < 0) ? kmCtrl : 0) |
761 (( GetKeyState( VK_MENU) < 0) ? kmAlt : 0);
762
763 keyState = guts. keyState;
764 AGAIN:
765 if ( PApplication(application)-> wantUnicodeInput) {
766 WCHAR keys[ 2];
767 // unicode mapping
768 switch ( ToUnicodeEx( mp1, scan, keyState, keys, 2, 0, kl)) {
769 case 1: // char
770 if ( lastDeadKey ) {
771 WCHAR wcBuffer[3];
772 WCHAR out[3];
773 wcBuffer[0] = keys[0];
774 wcBuffer[1] = lastDeadKey;
775 wcBuffer[2] = '\0';
776 if ( FoldStringW(MAP_PRECOMPOSED, (LPWSTR) wcBuffer, 3, (LPWSTR) out, 3) )
777 keys[0] = out[0];
778 }
779 if ( !deadPollCount && ( GetKeyState( VK_MENU) < 0) && ( GetKeyState( VK_SHIFT) >= 0)) {
780 WCHAR keys2[2];
781 if (( ToUnicodeEx( mp1, scan, guts. emptyKeyState, keys2, 2, 0, kl) == 1) &&
782 ( keys2[0] != keys[0])) {
783 /* example - (AltGr+2) == '@' on danish keyboard.
784 this hack is to tell whether the key without mods
785 will give same character code ... */
786 ev. key. mod &= ~(kmAlt|kmCtrl|kmShift);
787 }
788 }
789 if (!up) lastDeadKey = 0;
790 break;
791 case 2: { // dead key
792 lastDeadKey = ctx_remap_def( keys[0], ctx_deadkeys, true, keys[0]);
793 keys[ 0] = 0;
794 ev. key. mod |= kmDeadKey;
795 }
796 break;
797 case 0: // virtual key
798 if ( deadPollCount == 0) {
799 /* can't have character code - maybe fish out without mods? */
800 keyState = guts. emptyKeyState;
801 deadPollCount = 1;
802 goto AGAIN;
803 } else {
804 /* same meaning without mods, no code anyway */
805 keys[ 0] = 0;
806 }
807 if (!up) lastDeadKey = 0;
808 break;
809 default:
810 ev. key. mod |= kmDeadKey;
811 if (!up) lastDeadKey = 0;
812 }
813 ev. key. code = keys[ 0];
814 ev. key. mod |= kmUnicode;
815 } else {
816 BYTE keys[ 4];
817 switch ( ToAsciiEx( mp1, scan, keyState, (LPWORD) keys, 0, kl)) {
818 case 1: // char
819 if ( lastDeadKey ) {
820 BYTE cBuffer[3];
821 BYTE out[3];
822 cBuffer[0] = keys[0];
823 cBuffer[1] = lastDeadKey;
824 cBuffer[2] = '\0';
825 if ( FoldStringA(MAP_PRECOMPOSED, (LPSTR) cBuffer, 3, (LPSTR) out, 3) )
826 keys[0] = out[0];
827 }
828 if ( !deadPollCount && ( GetKeyState( VK_MENU) < 0) && ( GetKeyState( VK_SHIFT) >= 0)) {
829 BYTE keys2[4];
830 if (( ToAsciiEx( mp1, scan, guts. emptyKeyState, (LPWORD) keys2, 0, kl) == 1) &&
831 ( keys2[0] != keys[0])) {
832 /* example - (AltGr+2) == '@' on danish keyboard.
833 this hack is to tell whether the key without mods
834 will give same character code ... */
835 ev. key. mod &= ~(kmAlt|kmCtrl|kmShift);
836 }
837 }
838 break;
839 case 2: // dead key
840 lastDeadKey = keys[0];
841 keys[ 0] = 0;
842 ev. key. mod |= kmDeadKey;
843 break;
844 case 0: // virtual key
845 if ( deadPollCount == 0) {
846 /* can't have character code - maybe fish out without mods? */
847 keyState = guts. emptyKeyState;
848 deadPollCount = 1;
849 goto AGAIN;
850 } else {
851 /* same meaning without mods, no code anyway */
852 keys[ 0] = 0;
853 }
854 if (!up) lastDeadKey = 0;
855 break;
856 default:
857 ev. key. mod |= kmDeadKey;
858 if (!up) lastDeadKey = 0;
859 }
860 ev. key. code = keys[ 0];
861 }
862
863 // simulated key codes
864 if ( ev. key. key == kbTab && ( ev. key. mod & kmShift))
865 ev. key. key = kbBackTab;
866
867 if ( ev. key. code >= 'A' && ev. key. code <= 'z' && ev. key. mod & kmCtrl) {
868 ev. key. code = toupper(ev. key. code & 0xFF) - '@';
869 if (!( ev. key. mod & kmShift)) ev. key. code = tolower( ev. key. code);
870 }
871 }
872 break;
873 case WM_INITMENUPOPUP:
874 if ( HIWORD( mp2)) break; // do not use system popup
875 case WM_INITMENU:
876 {
877 PMenuWndData mwd = ( PMenuWndData) hash_fetch( menuMan, &mp1, sizeof( void*));
878 PMenuItemReg m = NULL;
879 sys lastMenu = mwd ? mwd-> menu : NULL_HANDLE;
880 if ( mwd && mwd-> menu && ( PAbstractMenu(mwd-> menu)->stage <= csNormal)) {
881 m = ( PMenuItemReg) AbstractMenu_first_that( mwd-> menu, find_oid, INT2PTR(void*,mwd->id), true);
882 hiStage = true;
883 ev. cmd = cmMenu;
884 ev. gen. H = mwd-> menu;
885 ev. gen. i = m ? m-> id : 0;
886 }
887 if (( msg == WM_INITMENUPOPUP) && ( m == NULL))
888 ev. cmd = 0;
889 }
890 break;
891 case WM_KILLFOCUS:
892 if (( HWND) mp1 != win) {
893 ev. cmd = cmReleaseFocus;
894 hiStage = true;
895 apt_assign( aptFocused, 0);
896 DestroyCaret();
897 }
898 break;
899 case WM_LBUTTONDOWN:
900 ev. pos. button = mbLeft;
901 goto MB_DOWN;
902 case WM_RBUTTONDOWN:
903 ev. pos. button = mbRight;
904 goto MB_DOWN;
905 case WM_MBUTTONDOWN:
906 ev. pos. button = mbMiddle;
907 goto MB_DOWN;
908 case WM_XBUTTONDOWN:
909 ev. pos. button = (HIWORD(mp1) == XBUTTON1) ? mb4 : mb5;
910 goto MB_DOWN;
911 case WM_LBUTTONUP:
912 ev. pos. button = mbLeft;
913 goto MB_UP;
914 case WM_RBUTTONUP:
915 ev. pos. button = mbRight;
916 goto MB_UP;
917 case WM_MBUTTONUP:
918 ev. pos. button = mbMiddle;
919 goto MB_UP;
920 case WM_XBUTTONUP:
921 ev. pos. button = (HIWORD(mp1) == XBUTTON1) ? mb4 : mb5;
922 goto MB_UP;
923 case WM_LBUTTONDBLCLK:
924 ev. pos. button = mbLeft;
925 goto MB_DBLCLK;
926 case WM_RBUTTONDBLCLK:
927 ev. pos. button = mbRight;
928 goto MB_DBLCLK;
929 case WM_MBUTTONDBLCLK:
930 ev. pos. button = mbMiddle;
931 goto MB_DBLCLK;
932 case WM_XBUTTONDBLCLK:
933 ev. pos. button = (HIWORD(mp1) == XBUTTON1) ? mb4 : mb5;
934 goto MB_DBLCLK;
935 case WM_LMOUSECLICK:
936 ev. pos. button = mbLeft;
937 goto MB_CLICK;
938 case WM_RMOUSECLICK:
939 ev. pos. button = mbRight;
940 goto MB_CLICK;
941 case WM_MMOUSECLICK:
942 ev. pos. button = mbMiddle;
943 goto MB_CLICK;
944 case WM_XMOUSECLICK:
945 ev. pos. button = (HIWORD(mp1) == XBUTTON1) ? mb4 : mb5;
946 goto MB_CLICK;
947 case WM_MOUSEWHEEL:
948 {
949 POINT p;
950 p. x = (short)LOWORD( mp2);
951 p. y = (short)HIWORD( mp2);
952 ev. cmd = cmMouseWheel;
953 ev. pos. button = ( short) HIWORD( mp1);
954 MapWindowPoints( NULL, win, &p, 1);
955 ev. pos. where. x = p. x;
956 ev. pos. where. y = sys lastSize. y - p. y - 1;
957 }
958 goto MB_MAIN_NOPOS;
959 case WM_MOUSEMOVE:
960 ev. cmd = cmMouseMove;
961 if ( self != lastMouseOver) {
962 Handle old = lastMouseOver;
963 lastMouseOver = self;
964 if ( old && ( PWidget( old)-> stage == csNormal))
965 SendMessage(( HWND)(( PWidget) old)-> handle, WM_MOUSEEXIT, mp1, mp2);
966 SendMessage( win, WM_MOUSEENTER, mp1, mp2);
967 if ( !guts. mouseTimer) {
968 guts. mouseTimer = 1;
969 if ( !SetTimer( dsys(application)handle, TID_USERMAX, 100, NULL)) apiErr;
970 }
971 }
972 goto MB_MAIN;
973 case WM_MOUSEENTER:
974 ev. cmd = cmMouseEnter;
975 goto MB_MAIN;
976 case WM_MOUSEEXIT:
977 ev. cmd = cmMouseLeave;
978 goto MB_MAIN;
979 MB_DOWN:
980 ev. cmd = cmMouseDown;
981 goto MB_MAINACT;
982 MB_UP:
983 ev. cmd = cmMouseUp;
984 goto MB_MAINACT;
985 MB_DBLCLK:
986 ev. pos. dblclk = 1;
987 MB_CLICK:
988 ev. cmd = cmMouseClick;
989 goto MB_MAINACT;
990 MB_MAINACT:
991 if ( !is_apt( aptEnabled) || !apc_widget_is_responsive( self))
992 {
993 if ( ev. cmd == cmMouseDown || (ev. cmd == cmMouseClick && ev. pos. dblclk))
994 MessageBeep( MB_OK);
995 return 0;
996 }
997 goto MB_MAIN;
998 MB_MAIN:
999 if ( ev. cmd == cmMouseDown && !is_apt( aptFirstClick)) {
1000 Handle x = self;
1001 while ( dsys(x) className != WC_FRAME && ( x != application)) x = (( PWidget) x)-> owner;
1002 if ( x != application && !local_wnd( GetActiveWindow(), DHANDLE( x)))
1003 {
1004 ev. cmd = 0; // yes, we abandon mousedown but we should force selection:
1005 if ((( PApplication) application)-> hintUnder == self) v-> self-> set_hintVisible( self, 0);
1006 if (( v-> options. optSelectable) && ( v-> selectingButtons & ev. pos. button))
1007 apc_widget_set_focused( self);
1008 }
1009 }
1010 ev. pos. where. x = (short)LOWORD( mp2);
1011 ev. pos. where. y = sys lastSize. y - (short)HIWORD( mp2) - 1;
1012 MB_MAIN_NOPOS:
1013 ev. pos. mod = 0 |
1014 (( mp1 & MK_CONTROL ) ? kmCtrl : 0) |
1015 (( mp1 & MK_SHIFT ) ? kmShift : 0) |
1016 (( GetKeyState( VK_MENU) < 0) ? kmAlt : 0) |
1017 apc_pointer_get_state(self)
1018 ;
1019 break;
1020 case WM_MEASUREITEM: {
1021 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT*) mp2;
1022 if ( mis-> CtlType == ODT_MENU && mis-> itemData != 0) {
1023 ev.cmd = cmMenuItemMeasure;
1024 self = (Handle) mis-> itemData;
1025 v = (PWidget) self;
1026 ev.gen.i = (Handle) mis-> itemID - MENU_ID_AUTOSTART;
1027 ev.gen.P.x = ev.gen.P.y = 0;
1028 }
1029 break;
1030 }
1031 case WM_MENUCHAR: {
1032 int key;
1033 PMenuWndData mwd;
1034 ev. key. key = ctx_remap_def( mp1, ctx_kb2VK2, false, kbNoKey);
1035 ev. key. code = LOWORD(mp1);
1036 ev. key. mod |=
1037 (( GetKeyState( VK_SHIFT) < 0) ? kmShift : 0) |
1038 (( GetKeyState( VK_CONTROL) < 0) ? kmCtrl : 0) |
1039 (( GetKeyState( VK_MENU) < 0) ? kmAlt : 0);
1040 if (( ev. key. mod & kmCtrl) && ( ev. key. code <= 'z'))
1041 ev. key. code += 'A' - 1;
1042 key = CAbstractMenu-> translate_key( NULL_HANDLE, ev. key. code, ev. key. key, ev. key. mod);
1043 if ( v-> self-> process_accel( self, key))
1044 return MAKELONG( 0, MNC_CLOSE);
1045
1046 ev.key.code = tolower(ev.key.code);
1047 if (( mwd = (MenuWndData*) hash_fetch(menuMan, &mp2, sizeof(mp2))) != NULL) {
1048 int pos = 0;
1049 PMenuItemReg m = CAbstractMenu(mwd->menu)-> first_that(mwd->menu, (void*)id_match, &mwd->id, false);
1050 while ( m != NULL ) {
1051 if ( m-> flags.custom_draw && m-> text != NULL ) {
1052 char * t = m-> text;
1053 while (*t) {
1054 if ( t[0] == '~' && tolower(t[1]) == ev.key.code )
1055 return MAKELONG( pos, MNC_EXECUTE);
1056 t++;
1057 }
1058 }
1059 m = m-> next;
1060 pos++;
1061 }
1062 }
1063 break;
1064 }
1065 case WM_SYNCMOVE: {
1066 Handle parent = v-> self-> get_parent(( Handle) v);
1067 if ( parent) {
1068 Point pos = var self-> get_origin( self);
1069 ev. cmd = cmMove;
1070 ev. gen. P = pos;
1071 if ( pos. x == var pos. x && pos. y == var pos. y) ev. cmd = 0;
1072 }
1073 break;
1074 }
1075 case WM_MOVE: {
1076 Handle parent = v-> self-> get_parent(( Handle) v);
1077 if ( parent) {
1078 Point sz = CWidget(parent)-> get_size( parent);
1079 ev. cmd = cmMove;
1080 ev. gen . P. x = ( short) LOWORD( mp2);
1081 ev. gen . P. y = sz. y - ( short) HIWORD( mp2) - sys yOverride;
1082 if ( is_apt( aptTransparent))
1083 InvalidateRect( win, NULL, false);
1084 }
1085 break;
1086 }
1087 case WM_NCHITTEST:
1088 if ( guts. focSysDialog) return HTERROR;
1089 // dlg protect code - protecting from user actions
1090 if ( !guts. focSysDisabled && ( Application_map_focus( application, self) != self))
1091 return HTERROR;
1092 break;
1093 case WM_PAINT:
1094 ev. cmd = cmPaint;
1095 if (
1096 ( sys className == WC_CUSTOM) &&
1097 ( var stage == csNormal) &&
1098 ( list_index_of( &guts. transp, self) >= 0)
1099 )
1100 return 0;
1101
1102 if (
1103 ( var self->get_locked(self) > 0) || /* or WM_PAINT bashing occurs */
1104 is_apt( aptLayered ) ||
1105 ( opt_InPaint && !is_apt(aptWM_PAINT) )
1106 ) {
1107 PAINTSTRUCT ps;
1108 BeginPaint(win, &ps);
1109 EndPaint(win, &ps);
1110 return 0;
1111 }
1112
1113 break;
1114 case WM_QUERYNEWPALETTE:
1115 return palette_change( self);
1116 case WM_PALETTECHANGED:
1117 if (( HWND) mp1 != win) {
1118 Handle mp = hwnd_to_view(( HWND) mp1);
1119 if ( mp && ( hwnd_top_level( mp) == hwnd_top_level( self)))
1120 return 0;
1121 palette_change( self);
1122 }
1123 break;
1124 case WM_POSTAL:
1125 ev. cmd = cmPost;
1126 ev. gen. H = ( Handle) mp1;
1127 ev. gen. p = ( void *) mp2;
1128 break;
1129 case WM_PRIMA_CREATE:
1130 ev. cmd = cmSetup;
1131 break;
1132 case WM_REPAINT_LAYERED:
1133 if ( var stage == csNormal )
1134 hwnd_repaint_layered( self, true );
1135 break;
1136 case WM_SETFOCUS:
1137 if ( guts. focSysDialog) return 1;
1138 // dlg protect code - general case
1139 if ( !guts. focSysDisabled && !guts. focSysGranted) {
1140 Handle hf = Application_map_focus( application, self);
1141 if ( hf != self) {
1142 PostMessage( win, WM_FORCEFOCUS, 0, ( LPARAM) hf);
1143 return 1;
1144 }
1145 }
1146 if (( HWND) mp1 != win) {
1147 ev. cmd = cmReceiveFocus;
1148 hiStage = true;
1149 apt_assign( aptFocused, 1);
1150 cursor_update( self);
1151 }
1152 break;
1153 case WM_SETVISIBLE:
1154 if ( list_index_of( &guts. transp, self) < 0) {
1155 if ( v-> stage <= csNormal) ev. cmd = mp1 ? cmShow : cmHide;
1156 hiStage = true;
1157 apt_assign( aptVisible, mp1);
1158 }
1159 break;
1160 case WM_SIZE:
1161 ev. cmd = cmSize;
1162 ev. gen. R. left = sys lastSize. x;
1163 ev. gen. R. bottom = sys lastSize. y;
1164 sys lastSize. x = ev. gen. R. right = ev. gen . P. x = ( short) LOWORD( mp2);
1165 sys lastSize. y = ev. gen. R. top = ev. gen . P. y = ( short) HIWORD( mp2);
1166 if ( ev. gen. R. top != ev. gen. R. bottom) {
1167 int delta = ev. gen. R. top - ev. gen. R. bottom;
1168 Widget_first_that( self, move_back, &delta);
1169 if ( is_apt( aptFocused)) cursor_update(( Handle) self);
1170 }
1171 if ( sys sizeLockLevel == 0 && var stage <= csNormal)
1172 var virtualSize = sys lastSize;
1173 break;
1174 case WM_WINDOWPOSCHANGING: {
1175 LPWINDOWPOS l = ( LPWINDOWPOS) mp2;
1176 if ( sys className == WC_CUSTOM) {
1177 if (( l-> flags & SWP_NOSIZE) == 0) {
1178 ev. cmd = cmCalcBounds;
1179 ev. gen. R. right = l-> cx;
1180 ev. gen. R. top = l-> cy;
1181 }
1182 }
1183 if (( l-> flags & SWP_NOZORDER) == 0)
1184 zorder_sync( self, win, l);
1185 break;
1186 }
1187 case WM_WINDOWPOSCHANGED: {
1188 LPWINDOWPOS l = ( LPWINDOWPOS) mp2;
1189 if (( l-> flags & SWP_NOZORDER) == 0)
1190 PostMessage( win, WM_ZORDERSYNC, 0, 0);
1191 if (( l-> flags & SWP_NOSIZE) == 0) {
1192 sys yOverride = l-> cy;
1193 SendMessage( win, WM_SYNCMOVE, 0, 0);
1194 }
1195 if ( l-> flags & SWP_HIDEWINDOW) SendMessage( win, WM_SETVISIBLE, 0, 0);
1196 if ( l-> flags & SWP_SHOWWINDOW) SendMessage( win, WM_SETVISIBLE, 1, 0);
1197 break;
1198 }
1199 case WM_ZORDERSYNC:
1200 ev. cmd = cmZOrderChanged;
1201 break;
1202 }
1203
1204 if ( hiStage)
1205 ret = DefWindowProcW( win, msg, mp1, mp2);
1206
1207 if ( ev. cmd)
1208 message_result = v-> self-> message( self, &ev);
1209 else
1210 ev. cmd = orgMsg;
1211
1212 if ( v-> stage > csNormal) orgMsg = 0; // protect us from dead body
1213
1214 switch ( orgMsg) {
1215 case WM_DRAWITEM: {
1216 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT*) mp2;
1217 if ( dis-> CtlType == ODT_MENU && dis-> itemData != 0)
1218 return (LRESULT) 1;
1219 break;
1220 }
1221 case WM_DESTROY:
1222 v-> handle = NULL_HANDLE; // tell apc not to kill this HWND
1223 SetWindowLongPtr( win, GWLP_USERDATA, 0);
1224 Object_destroy(( Handle) v);
1225 break;
1226 case WM_PAINT:
1227 return 0;
1228 case WM_SYSKEYDOWN:
1229 if ( !message_result)
1230 guts. dont_xlate_message = true;
1231 break;
1232 case WM_SYSKEYUP:
1233 // ev. cmd = 1; // forced call DefWindowProc superseded for test reasons
1234 break;
1235 case WM_MEASUREITEM: {
1236 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT*) mp2;
1237 if ( mis-> CtlType == ODT_MENU && mis-> itemData != 0) {
1238 mis-> itemWidth = ev.gen.P.x;
1239 mis-> itemHeight = ev.gen.P.y;
1240 return (LRESULT) 1;
1241 }
1242 break;
1243 }
1244 case WM_MOUSEMOVE:
1245 SetCursor( is_apt( aptEnabled) ? sys pointer : arrowCursor);
1246 break;
1247 case WM_MOUSEWHEEL:
1248 return ( LRESULT)1;
1249 case WM_WINDOWPOSCHANGING: {
1250 LPWINDOWPOS l = ( LPWINDOWPOS) mp2;
1251 if ( sys className == WC_CUSTOM) {
1252 if (( l-> flags & SWP_NOSIZE) == 0) {
1253 int dy = l-> cy - ev. gen. R. top;
1254 l-> cx = ev. gen. R. right;
1255 l-> cy = ev. gen. R. top;
1256 l-> y += dy;
1257 }
1258 return false;
1259 }
1260 if (( l-> flags & SWP_NOZORDER) == 0)
1261 zorder_sync( self, win, l);
1262 break;
1263 }
1264 }
1265
1266 if ( ev. cmd && !hiStage)
1267 ret = DefWindowProcW( win, msg, mp1, mp2);
1268
1269 return ret;
1270 }
1271
generic_frame_handler(HWND win,UINT msg,WPARAM mp1,LPARAM mp2)1272 LRESULT CALLBACK generic_frame_handler( HWND win, UINT msg, WPARAM mp1, LPARAM mp2)
1273 {
1274 LRESULT ret = 0;
1275 Handle self = GetWindowLongPtr( win, GWLP_USERDATA);
1276 PWidget v = ( PWidget) self;
1277 UINT orgMsg = msg;
1278 Event ev;
1279 Bool hiStage = false;
1280
1281 if ( !self)
1282 return DefWindowProcW( win, msg, mp1, mp2);
1283
1284 memset( &ev, 0, sizeof (ev));
1285 ev. gen. source = self;
1286
1287 switch ( msg) {
1288 case WM_ACTIVATE:
1289 if ( guts. focSysDialog) return 1;
1290 // dlg protect code - protecting from window activation
1291 if ( LOWORD( mp1) && !guts. focSysDisabled) {
1292 Handle hf = Application_map_focus( application, self);
1293 if ( hf != self) {
1294 guts. focSysDisabled = 1;
1295 Application_popup_modal( application);
1296 PostMessage( win, msg, 0, 0);
1297 guts. focSysDisabled = 0;
1298 return 1;
1299 }
1300 }
1301 ev. cmd = ( LOWORD( mp1) != WA_INACTIVE) ? cmActivate : cmDeactivate;
1302 hiStage = true;
1303 break;
1304 case WM_CLOSE:
1305 if ( guts. focSysDialog) return 0;
1306 ev. cmd = cmClose;
1307 break;
1308 case WM_COMMAND:
1309 case WM_DRAWITEM:
1310 case WM_INITMENUPOPUP:
1311 case WM_INITMENU:
1312 case WM_MEASUREITEM:
1313 case WM_MENUCHAR:
1314 case WM_KEYDOWN:
1315 case WM_KEYUP:
1316 case WM_SETVISIBLE:
1317 case WM_ENABLE:
1318 case WM_FORCEFOCUS:
1319 case WM_MOUSEWHEEL:
1320 case WM_ZORDERSYNC:
1321 return generic_view_handler(( HWND) v-> handle, msg, mp1, mp2);
1322 case WM_QUERYNEWPALETTE:
1323 return generic_view_handler(( HWND) v-> handle, msg, mp1, mp2);
1324 case WM_PALETTECHANGED:
1325 if (( HWND) mp1 == win) return 0;
1326 return generic_view_handler(( HWND) v-> handle, msg, mp1, mp2);
1327 case WM_SYSKEYDOWN:
1328 case WM_SYSKEYUP:
1329 if ( generic_view_handler(( HWND) v-> handle, msg, mp1, mp2) == 0)
1330 return 0;
1331 hiStage = true;
1332 break;
1333 case WM_DLGENTERMODAL:
1334 ev. cmd = mp1 ? cmExecute : cmEndModal;
1335 break;
1336 case WM_ERASEBKGND:
1337 return 1;
1338 case WM_NCACTIVATE:
1339 if ( guts. focSysDialog) return 1;
1340
1341 if (( mp1 == 0) && ( mp2 != 0)) {
1342 Handle x = hwnd_to_view(( HWND) mp2);
1343 if ( is_declipped_child( x) && Widget_is_child( x, self)) {
1344 return 1;
1345 }
1346 }
1347 // dlg protect code - protecting from window activation
1348 if ( mp1 && !guts. focSysDisabled) {
1349 Handle hf = Application_map_focus( application, self);
1350 if ( hf != self) {
1351 guts. focSysDisabled = 1;
1352 Application_popup_modal( application);
1353 PostMessage( win, msg, 0, 0);
1354 guts. focSysDisabled = 0;
1355 return 1;
1356 }
1357 }
1358 break;
1359 case WM_NCHITTEST:
1360 if ( guts. focSysDialog) return HTERROR;
1361 // dlg protect code - protecting from user actions
1362 if ( !guts. focSysDisabled) {
1363 Handle foc = Application_map_focus( application, self);
1364 if ( foc != self) {
1365 return ( foc == apc_window_get_active()) ? HTERROR : HTCLIENT;
1366 }
1367 }
1368 break;
1369 case WM_SETFOCUS:
1370 if ( guts. focSysDialog) return 1;
1371
1372 // dlg protect code - general case
1373 if ( !guts. focSysDisabled && !guts. focSysGranted) {
1374 Handle hf = Application_map_focus( application, self);
1375 if ( hf != self) {
1376 PostMessage( win, WM_FORCEFOCUS, 0, ( LPARAM) hf);
1377 return 1;
1378 }
1379 }
1380
1381 // This code is about to protect frame events when set_selected would
1382 // grant SetFocus() call to another frame.
1383 {
1384 Handle x = var self-> get_selectee( self);
1385 Handle w = x;
1386 Bool hasCO = w == self;
1387 while ( w && w != self) {
1388 if ( !dsys( w) options. aptClipOwner) {
1389 hasCO = true;
1390 break;
1391 }
1392 w = (( PWidget) w)-> owner;
1393 }
1394 if ( !hasCO) {
1395 var self-> set_selected( self, true);
1396 }
1397 // else we do not select any widget, but still have a chance to resize frame :)
1398 }
1399 break;
1400 case WM_SIZE: {
1401 int state = wsNormal;
1402 Bool doWSChange = false;
1403 if (( int) mp1 == SIZE_RESTORED) {
1404 state = wsNormal;
1405 if ( sys s. window. state != state) doWSChange = true;
1406 } else if (( int) mp1 == SIZE_MAXIMIZED) {
1407 state = wsMaximized;
1408 doWSChange = true;
1409 } else if (( int) mp1 == SIZE_MINIMIZED) {
1410 state = wsMinimized;
1411 doWSChange = true;
1412 }
1413 if ( doWSChange) {
1414 ev. gen. i = sys s. window. state = state;
1415 ev. cmd = cmWindowState;
1416 }
1417 break;
1418 }
1419 case WM_SYNCMOVE: {
1420 Handle parent = v-> self-> get_parent(( Handle) v);
1421 if ( parent) {
1422 Point pos = var self-> get_origin( self);
1423 ev. cmd = cmMove;
1424 ev. gen. P = pos;
1425 if ( pos. x == var pos. x && pos. y == var pos. y) ev. cmd = 0;
1426 }
1427 break;
1428 }
1429 case WM_MOVE: {
1430 Handle parent = v-> self-> get_parent(( Handle) v);
1431 if ( parent) {
1432 Point sz = CWidget(parent)-> get_size( parent);
1433 ev. cmd = cmMove;
1434 ev. gen . P. x = ( short) LOWORD( mp2);
1435 ev. gen . P. y = sz. y - ( short) HIWORD( mp2) - sys yOverride;
1436 }
1437 break;
1438 }
1439 // case WM_SYSCHAR:return 1;
1440 case WM_TIMER:
1441 if ( mp1 == TID_USERMAX) {
1442 POINT p;
1443 HWND wp;
1444 if ( lastMouseOver && !GetCapture() && ( PObject( lastMouseOver)-> stage == csNormal)) {
1445 HWND desktop = HWND_DESKTOP;
1446 GetCursorPos( &p);
1447 wp = WindowFromPoint( p);
1448 if ( wp) {
1449 POINT xp = p;
1450 MapWindowPoints( desktop, wp, &xp, 1);
1451 wp = ChildWindowFromPointEx( wp, xp, CWP_SKIPINVISIBLE);
1452 } else
1453 wp = ChildWindowFromPointEx( wp, p, CWP_SKIPINVISIBLE);
1454 if ( wp != ( HWND)(( PWidget) lastMouseOver)-> handle)
1455 {
1456 HWND old = ( HWND)(( PWidget) lastMouseOver)-> handle;
1457 Handle s;
1458 lastMouseOver = NULL_HANDLE;
1459 SendMessage( old, WM_MOUSEEXIT, 0, 0);
1460 s = hwnd_to_view( wp);
1461 if ( s && ( HWND)(( PWidget) s)-> handle == wp)
1462 {
1463 MapWindowPoints( desktop, wp, &p, 1);
1464 SendMessage( wp, WM_MOUSEENTER, 0, MAKELPARAM( p. x, p. y));
1465 lastMouseOver = s;
1466 } else if ( guts. mouseTimer) {
1467 guts. mouseTimer = 0;
1468 if ( !KillTimer( dsys(application)handle, TID_USERMAX)) apiErr;
1469 }
1470 }
1471 }
1472 return 0;
1473 } else {
1474 int id = mp1 - 1;
1475 if ( id >= 0 && id < timeDefsCount) {
1476 ev. gen. H = ( Handle) timeDefs[ id]. item;
1477 if ( ev. gen. H) {
1478 v = ( PWidget)( self = ev. gen. H);
1479 ev. cmd = cmTimer;
1480 }
1481 }
1482 }
1483 break;
1484 case WM_GETMINMAXINFO: {
1485 LPMINMAXINFO l = ( LPMINMAXINFO) mp2;
1486 Point min = var self-> get_sizeMin( self);
1487 Point max = var self-> get_sizeMax( self);
1488 Point bor = get_window_borders( sys s. window. borderStyle);
1489 int dy = 0 +
1490 (( sys s. window. borderIcons & biTitleBar) ? GetSystemMetrics( SM_CYCAPTION) : 0) +
1491 ( PWindow(self)-> menu ? GetSystemMetrics( SM_CYMENU) : 0);
1492 l-> ptMinTrackSize. x = min. x + bor.x * 2;
1493 l-> ptMinTrackSize. y = min. y + bor.y * 2 + dy;
1494 l-> ptMaxTrackSize. x = max. x + bor.x * 2;
1495 l-> ptMaxTrackSize. y = max. y + bor.y * 2 + dy;
1496 break;
1497 }
1498 case WM_WINDOWPOSCHANGED:
1499 if ( !is_apt(aptIgnoreSizeMessages)) {
1500 LPWINDOWPOS l = ( LPWINDOWPOS) mp2;
1501 if (( l-> flags & SWP_NOZORDER) == 0)
1502 PostMessage( win, WM_ZORDERSYNC, 0, 0);
1503 if (( l-> flags & SWP_NOSIZE) == 0) {
1504 RECT r;
1505 GetClientRect( win, &r);
1506 sys yOverride = r. bottom - r. top;
1507 SendMessage( win, WM_SYNCMOVE, 0, 0);
1508 }
1509 if ( l-> flags & SWP_HIDEWINDOW) SendMessage( win, WM_SETVISIBLE, 0, 0);
1510 if ( l-> flags & SWP_SHOWWINDOW) SendMessage( win, WM_SETVISIBLE, 1, 0);
1511 {
1512 RECT r;
1513 GetClientRect( win, &r);
1514 SetWindowPos(( HWND) var handle, 0, 0, 0, r. right, r.bottom, SWP_NOZORDER);
1515 }
1516 }
1517 break;
1518 }
1519
1520 if ( hiStage)
1521 ret = DefWindowProcW( win, msg, mp1, mp2);
1522
1523 if ( ev. cmd) v-> self-> message( self, &ev); else ev. cmd = orgMsg;
1524
1525 if ( var stage == csDead) orgMsg = 0;
1526
1527 switch ( orgMsg) {
1528 case WM_CLOSE:
1529 if ( ev. cmd) {
1530 if ( sys className == WC_FRAME && PWindow(self)->modal) {
1531 CWindow( self)-> cancel( self);
1532 return 0;
1533 } else {
1534 SetWindowLongPtr( win, GWLP_USERDATA, 0);
1535 Object_destroy(( Handle) v);
1536 }
1537 break;
1538 } else
1539 return 0;
1540 }
1541
1542 if ( ev. cmd && !hiStage)
1543 ret = DefWindowProcW( win, msg, mp1, mp2);
1544 return ret;
1545 }
1546
1547 static void
update_layered_frame(Handle self)1548 update_layered_frame(Handle self)
1549 {
1550 HRGN r1, r2;
1551 RECT frame, client;
1552 POINT frame_size, client_size;
1553 Point delta_upper_left, delta_lower_right, move;
1554 HWND win = HANDLE;
1555
1556 delta_lower_right = get_window_borders( sys s. window. borderStyle);
1557 GetWindowRect(win, &frame);
1558 GetClientRect(win, &client);
1559 frame_size. x = frame. right - frame. left;
1560 frame_size. y = frame. bottom - frame. top;
1561 client_size. x = client. right - client. left;
1562 client_size. y = client. bottom - client. top;
1563 r2 = CreateRectRgn( 0, 0, frame_size.x, frame_size.y);
1564 r1 = CreateRectRgn( 0, 0, client_size.x, client_size.y);
1565 delta_upper_left.x = frame_size.x - client_size.x - delta_lower_right.x;
1566 delta_upper_left.y = frame_size.y - client_size.y - delta_lower_right.y;
1567 OffsetRgn( r1, delta_upper_left.x, delta_upper_left.y);
1568 CombineRgn( r2, r2, r1, RGN_XOR);
1569 if (!SetWindowRgn( win, r2, true)) apiErr;
1570 DeleteObject(r1);
1571 DeleteObject(r2);
1572
1573 move.x = frame.left + delta_upper_left.x;
1574 move.y = frame.top + delta_upper_left.y;
1575 if ( !SetWindowPos(( HWND ) var handle, win,
1576 client.left + move.x, client.top + move.y, client_size.x, client_size.y,
1577 SWP_NOACTIVATE)) apiErr;
1578 hwnd_repaint_layered( self, false );
1579 }
1580
layered_frame_handler(HWND win,UINT msg,WPARAM mp1,LPARAM mp2)1581 LRESULT CALLBACK layered_frame_handler( HWND win, UINT msg, WPARAM mp1, LPARAM mp2)
1582 {
1583 Handle self = GetWindowLongPtr( win, GWLP_USERDATA);
1584
1585 if ( !self)
1586 return DefWindowProcW( win, msg, mp1, mp2);
1587
1588 switch ( msg) {
1589 case WM_NCACTIVATE:
1590 case WM_NCHITTEST:
1591 case WM_SETFOCUS:
1592 return DefWindowProcW( win, msg, mp1, mp2);
1593
1594 case WM_SIZE:
1595 case WM_MOVE:
1596 update_layered_frame(self);
1597 return DefWindowProcW( win, msg, mp1, mp2);
1598
1599 case WM_WINDOWPOSCHANGED: {
1600 LPWINDOWPOS l = ( LPWINDOWPOS) mp2;
1601 Bool updated = false;
1602
1603 if (( l-> flags & SWP_NOSIZE) == 0) {
1604 RECT r;
1605 update_layered_frame(self);
1606 updated = true;
1607
1608 GetClientRect( win, &r);
1609 sys yOverride = r. bottom - r. top;
1610 SendMessage( win, WM_SYNCMOVE, 0, 0);
1611 }
1612 if (( l-> flags & SWP_NOMOVE) == 0) {
1613 if ( !updated ) {
1614 update_layered_frame(self);
1615 updated = true;
1616 }
1617 }
1618 if (( l-> flags & SWP_NOZORDER) == 0) {
1619 PostMessage( win, WM_ZORDERSYNC, 0, 0);
1620 if ( !updated ) {
1621 update_layered_frame(self);
1622 updated = true;
1623 }
1624 }
1625 if ( l-> flags & SWP_HIDEWINDOW) {
1626 ShowWindow((HWND) var handle, SW_HIDE);
1627 SendMessage( win, WM_SETVISIBLE, 0, 0);
1628 }
1629 if ( l-> flags & SWP_SHOWWINDOW) {
1630 ShowWindow((HWND) var handle, SW_SHOW);
1631 SendMessage( win, WM_SETVISIBLE, 1, 0);
1632 }
1633 return DefWindowProcW( win, msg, mp1, mp2);
1634 }
1635
1636 }
1637
1638 return generic_frame_handler( win, msg, mp1, mp2 );
1639 }
1640
kill_img_cache(Handle self,int keyLen,void * key,void * killDBM)1641 static Bool kill_img_cache( Handle self, int keyLen, void * key, void * killDBM)
1642 {
1643 if ( is_apt( aptDeviceBitmap)) {
1644 if ( killDBM) dbm_recreate( self);
1645 } else
1646 image_destroy_cache( self);
1647 return false;
1648 }
1649
generic_app_handler(HWND win,UINT msg,WPARAM mp1,LPARAM mp2)1650 LRESULT CALLBACK generic_app_handler( HWND win, UINT msg, WPARAM mp1, LPARAM mp2)
1651 {
1652 switch ( msg) {
1653 case WM_DISPLAYCHANGE: {
1654 HDC dc = dc_alloc();
1655 int oldBPP = guts. displayBMInfo. bmiHeader. biBitCount;
1656 HBITMAP hbm;
1657
1658 if ( dc) {
1659 guts. displayBMInfo. bmiHeader. biBitCount = 0;
1660 guts. displayBMInfo. bmiHeader. biSize = sizeof( BITMAPINFO);
1661 if ( !( hbm = GetCurrentObject( dc, OBJ_BITMAP))) apiErr;
1662
1663 if ( !GetDIBits( dc, hbm, 0, 0, NULL, &guts. displayBMInfo, DIB_PAL_COLORS)) {
1664 guts. displayBMInfo. bmiHeader. biBitCount = ( int) mp1;
1665 guts. displayBMInfo. bmiHeader. biPlanes = GetDeviceCaps( dc, PLANES);
1666 };
1667 }
1668 dsys( application) lastSize. x = ( short) LOWORD( mp2);
1669 dsys( application) lastSize. y = ( short) HIWORD( mp2);
1670 if ( dc) {
1671 if ( oldBPP != guts. displayBMInfo. bmiHeader. biBitCount)
1672 hash_first_that( imageMan, kill_img_cache, (void*)1, NULL, NULL);
1673 dc_free();
1674 }
1675 break;
1676 }
1677 case WM_FONTCHANGE:
1678 destroy_font_hash();
1679 break;
1680 case WM_DPICHANGED: {
1681 Event ev = {cmFontChanged};
1682 dpi_change();
1683 reset_system_fonts();
1684 destroy_font_hash();
1685 font_clean();
1686 PComponent(application)-> self-> message( application, &ev);
1687 break;
1688 }
1689 case WM_COMPACTING:
1690 stylus_clean();
1691 stylus_gp_clean();
1692 font_clean();
1693 destroy_font_hash();
1694 hash_first_that( imageMan, kill_img_cache, NULL, NULL, NULL);
1695 hash_destroy( regnodeMan, false);
1696 regnodeMan = hash_create();
1697 break;
1698 case WM_QUERYNEWPALETTE:
1699 case WM_PALETTECHANGED:
1700 return 0;
1701 }
1702 return generic_frame_handler( win, msg, mp1, mp2);
1703 }
1704
1705 #ifdef __cplusplus
1706 }
1707 #endif
1708