/*- * Copyright (c) 1997-2002 The Protein Laboratory, University of Copenhagen * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: os2guts.c,v 1.27 2004/05/07 10:03:24 dk Exp $ */ /* Created by: Dmitry Karasik Anton Berezin */ #include #define INCL_GPI #include "os2/os2guts.h" #include "Application.h" #include "Component.h" #include "Menu.h" #include "Widget.h" #include "Window.h" #include #include #define sys (( PDrawableData)(( PComponent) self)-> sysData)-> #define dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)-> #define HANDLE (( sys className == WC_FRAME) ? WinQueryWindow( v->handle, QW_PARENT) : v->handle) #define DHANDLE( view) (((( PDrawableData)(( PComponent) view)-> sysData)->className == WC_FRAME) ? WinQueryWindow((( PWidget) view)->handle, QW_PARENT) : (( PWidget) view)->handle) OS2Guts guts; ERRORID rc = 0; Handle lastMouseOver = nilHandle; extern Handle hwnd_to_view( HWND win); extern Bool single_color_notify ( Handle self, Handle child, void * color); extern Bool font_notify ( Handle self, Handle child, void * font); void sigh ( int sig); static unsigned long dllModHandle = 0; unsigned long _DLL_InitTerm( unsigned long modhandle, unsigned long flag) { dllModHandle = flag ? 0 : modhandle; return 1; } Bool window_subsystem_init( char * error_buf) { ULONG minor; PPIB ppib; PTIB ptib; DosGetInfoBlocks( &ptib, &ppib); DosQuerySysInfo( QSV_VERSION_MINOR, QSV_VERSION_MINOR, &minor, sizeof( minor)); memset( &guts, 0, sizeof( guts)); guts. pid = ppib-> pib_ulpid; guts. appTypePM = 1; ppib-> pib_ultype = 3; /* nasty hack - but that way stdout and PM can coexist */ if ( !( guts. anchor = WinInitialize( 0))) { sprintf( error_buf, "WinIntialize(0) error"); return false; } if ( !( guts. queue = WinCreateMsgQueue( guts. anchor, minor <= 30 ? 256 : 0))) { rc = WinGetLastError(guts. anchor); WinTerminate( guts. anchor); if ( rc == 0x81051) { sprintf( error_buf, "WinCreateMsgQueue: not a PM program"); guts. appTypePM = 0; } else { sprintf( error_buf, "WinCreateMsgQueue: error %03x", (int)rc); } return false; } _fpreset(); create_font_hash(); { // make Prima.dll accessible for other modules char buf[2048]; DosQueryModuleName(dllModHandle, 2048, buf); apc_dl_export( buf); } if ( !WinRegisterClass( guts. anchor, "GeNeRiC", generic_view_handler, CS_MOVENOTIFY, 4)) apiErrRet; { ULONG cps; guts. codePage = 0; rc = DosQueryCp( sizeof( guts. codePage), &guts. codePage, &cps); if ( rc != 0 && rc != 473 /*ERROR_CPLIST_TOO_SMALL*/) { sprintf( error_buf, "DosQueryCp: error %03x", (int)rc); return false; } } WinGetLastError( guts. anchor); { HDC dc = DevOpenDC( guts. anchor, OD_MEMORY, "*", 0, nil, nilHandle); SIZEL s = {0, 0}; ULONG lFmts[ 256]; int i; if ( dc == nilHandle) apiErrRet; if ( !( guts. ps = GpiCreatePS( guts. anchor, dc, &s, PU_PELS | GPIT_MICRO | GPIA_ASSOC))) { rc = WinGetLastError(guts. anchor); sprintf( error_buf, "GpiCreatePS: error %03x", (int)rc); DevCloseDC( dc); return false; } if ( !GpiCreateLogColorTable( guts. ps, 0, LCOLF_RGB, 0, 0, nil)) { rc = WinGetLastError(guts. anchor); sprintf( error_buf, "GpiCreateLogColorTable: error %03x", (int)rc); GpiDestroyPS( guts. ps); DevCloseDC( dc); return false; } GpiQueryCharBox( guts. ps, &guts. defFontBox); guts. fontId = 0; if ( !( guts. fontHash = create_fontid_hash())) { sprintf( error_buf, "no memory"); GpiDestroyPS( guts. ps); DevCloseDC( dc); return false; } DevQueryCaps( dc, CAPS_HORIZONTAL_FONT_RES, 1, ( PLONG) &guts. displayResolution. x); DevQueryCaps( dc, CAPS_VERTICAL_FONT_RES, 1, ( PLONG) &guts. displayResolution. y); DevQueryCaps( dc, CAPS_BITMAP_FORMATS, 1, ( PLONG) &guts. bmfCount); WinGetLastError( guts. anchor); if ( !GpiQueryDeviceBitmapFormats( guts. ps, 2 * guts. bmfCount, lFmts)) { rc = WinGetLastError(guts. anchor); sprintf( error_buf, "GpiQueryDeviceBitmapFormats: error %03x", (int)rc); GpiDestroyPS( guts. ps); DevCloseDC( dc); return false; }; if ( !( guts. bmf = malloc( guts. bmfCount * sizeof( int) * 2))) { sprintf( error_buf, "no memory"); GpiDestroyPS( guts. ps); DevCloseDC( dc); return false; } for ( i = 0; i < guts. bmfCount * 2; i++) guts. bmf[ i] = lFmts[ i]; gp_get_font( guts. ps, &guts. sysDefFont, guts. displayResolution); apc_font_pick( nilHandle, &guts. sysDefFont, &guts. sysDefFont); guts. monoBitsOk = ( WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN) == 350 && guts. bmf[ 1] == 4); } list_create( &guts. transp, 8, 8); list_create( &guts. psList, 8, 8); list_create( &guts. winPsList, 8, 8); list_create( &guts. eventHooks, 1, 1); list_create( &guts. files, 8, 8); guts. appLock = 0; guts. pointerLock = 0; signal( SIGSEGV, sigh); signal( SIGTERM, sigh); signal( SIGFPE , sigh); return true; } Bool window_subsystem_get_options( int * argc, char *** argv) { *argc = 0; return true; } Bool window_subsystem_set_option( char * option, char * value) { return false; } Bool freePS( HPS ps, void * dummy) { WinEndPaint ( ps); return false; } Bool freeWinPS( HPS ps, void * dummy) { WinReleasePS( ps); return false; } void window_subsystem_cleanup( void) { list_first_that( &guts. psList, freePS, nil); list_first_that( &guts. winPsList, freeWinPS, nil); guts. psList. count = 0; guts. winPsList. count = 0; while ( guts. appLock > 0) apc_application_unlock( application); while ( guts. pointerLock < 0) { WinShowPointer( HWND_DESKTOP, 1); guts. pointerLock++; } { QMSG msg; for(;;) { if ( WinPeekMsg( guts. anchor, &msg, 0, WM_QUIT, WM_QUIT, PM_REMOVE)) continue; if ( WinPeekMsg( guts. anchor, &msg, 0, WM_CLOSE, WM_CLOSE, PM_REMOVE)) continue; break; } } } void sigh( int sig) { if ( sig == SIGSEGV || sig == SIGTERM || sig == SIGFPE) { list_first_that( &guts. psList, freePS, nil); list_first_that( &guts. winPsList, freeWinPS, nil); } signal( sig, SIG_ACK); } void window_subsystem_done( void) { HDC dc = GpiQueryDevice( guts. ps); if ( guts. socketMutex) { // appDead must be TRUE for this moment! appDead = true; DosCloseMutexSem( guts. socketMutex); } list_destroy( &guts. files); list_destroy( &guts. eventHooks); list_destroy( &guts. transp); list_first_that( &guts. psList, freePS, nil); list_first_that( &guts. winPsList, freeWinPS, nil); list_destroy( &guts. psList); list_destroy( &guts. winPsList); free( guts. bmf); GpiDestroyPS( guts. ps); guts. fontId = 0; destroy_fontid_hash( guts. fontHash); DevCloseDC( dc); destroy_font_hash(); WinDestroyMsgQueue( guts. queue); WinTerminate( guts. anchor); guts. anchor = guts. queue = nilHandle; } Bool apc_register_hook( int hookType, void * hookProc) { if ( hookType != HOOK_EVENT_LOOP) return false; list_add( &guts. eventHooks, ( Handle) hookProc); return true; } Bool apc_deregister_hook( int hookType, void * hookProc) { if ( hookType != HOOK_EVENT_LOOP) return false; list_delete( &guts. eventHooks, ( Handle) hookProc); return true; } Bool apc_register_event( void * sysMessage) { UINT i; for ( i = 0; i < WM_LAST_USER_MESSAGE - WM_FIRST_USER_MESSAGE; i++) { if (( guts. msgMask[ i >> 3] & (1 << (i & 7))) == 0) { guts. msgMask[ i >> 3] |= 1 << (i & 7); *(( UINT*) sysMessage) = WM_FIRST_USER_MESSAGE + i; return true; } } return false; } Bool apc_deregister_event( void * sysMessage) { UINT i = *((UINT*) sysMessage); if (( guts. msgMask[ i >> 3] & (1 << (i & 7))) == 0) return false; guts. msgMask[ i >> 3] &= ~(1 << (i & 7)); return true; } static Bool local_wnd( HWND who, HWND client) { HWND parent = WinQueryWindow( who, QW_PARENT); HWND owner = WinQueryWindow( who, QW_OWNER); HWND frame = WinQueryWindow( client, QW_PARENT); PComponent v; Handle self; if ( who == client || parent == client || owner == client || parent == frame || owner == frame) return true; self = WinQueryWindowULong( client, QWL_USER); v = (PComponent)hwnd_to_view( who); if (!v && WinQueryWindowPtr( who, QWP_PFNWP) == generic_menu_handler) v = (PComponent)(( PMenuWndData) WinQueryWindowULong( who, QWL_USER))-> menu; while (v && ( Handle) v != application) { if ((Handle)v == self) return true; ( Handle) v = v-> owner; } return false; } MRESULT EXPENTRY generic_view_handler( HWND w, ULONG msg, MPARAM mp1, MPARAM mp2) { Handle view; PWidget v; PWidget orgv; Event ev; MRESULT toReturn = 0; ULONG orgMsg; int i, orgCmd; Handle self; PFNWP fnwp; Bool hiStage = false; #define flow(cm) ev.cmd = (cm); ( PWidget) v = ctrl; ( PWidget) view = ctrl; #define flowb(cm) flow(cm) break; view = WinQueryWindowULong( w, QWL_USER); if (( view == nilHandle) || appDead) return WinDefWindowProc( w, msg, mp1, mp2); for ( i = 0; i < guts. eventHooks. count; i++) { QMSG ms = { w, msg, mp1, mp2, 0}; if ((( PrimaHookProc *)( guts. eventHooks. items[i]))((void*) &ms)) return 0; } // Here we (fortunately) have all we need to parse events v = ( PWidget) view; self = view; ( ApiHandle) fnwp = sys handle2; orgv = v; orgMsg = msg; memset( &ev, 0, sizeof (ev)); ev. gen. source = view; switch ( msg) { case WM_BUTTON1DBLCLK: ev. pos. button = mbLeft; goto _GenEvDoubleC; case WM_BUTTON2DBLCLK: ev. pos. button = mbRight; goto _GenEvDoubleC; case WM_BUTTON3DBLCLK: ev. pos. button = mbMiddle; goto _GenEvDoubleC; case WM_BUTTON1CLICK: ev. pos. button = mbLeft; goto _GenEvClick; case WM_BUTTON2CLICK: ev. pos. button = mbRight; goto _GenEvClick; case WM_BUTTON3CLICK: ev. pos. button = mbMiddle; goto _GenEvClick; case WM_BUTTON1UP: ev. pos. button = mbLeft; goto _GenEvUpC; case WM_BUTTON2UP: ev. pos. button = mbRight; goto _GenEvUpC; case WM_BUTTON3UP: ev. pos. button = mbMiddle; goto _GenEvUpC; case WM_BUTTON1DOWN: ev. pos. button = mbLeft; goto _GenEvDnC; case WM_BUTTON2DOWN: ev. pos. button = mbRight; goto _GenEvDnC; case WM_BUTTON3DOWN: ev. pos. button = mbMiddle; goto _GenEvDnC; case WM_MOUSEMOVE: ev. cmd = cmMouseMove; goto _GenEvC; case WM_MOUSEENTER: ev. cmd = cmMouseEnter; goto _GenEvC; case WM_MOUSELEAVE: ev. cmd = cmMouseLeave; goto _GenEvC; _GenEvDoubleC: ev. pos. dblclk = TRUE; _GenEvClick: ev. cmd = cmMouseClick; goto _GenEvC; _GenEvUpC: ev. cmd = cmMouseUp; goto _GenEvC; _GenEvDnC: ev. cmd = cmMouseDown; goto _GenEvC; _GenEvC: if ((short)SHORT1FROMMP( mp2) == HT_DISCARD) return 0; if ( !is_apt( aptEnabled)) { if (( ev. cmd != cmMouseMove) && ( ev. cmd != cmMouseEnter) && ( ev. cmd != cmMouseLeave)) { if ( ev. cmd == cmMouseDown || (ev. cmd == cmMouseClick && ev. pos. dblclk)) WinAlarm( HWND_DESKTOP, WA_WARNING); return 0; } } if ( ev.cmd == cmMouseMove && self != lastMouseOver) { Handle old = lastMouseOver; lastMouseOver = self; if ( old) WinSendMsg((( PWidget) old)-> handle, WM_MOUSELEAVE, mp1, mp2); WinSendMsg( w, WM_MOUSEENTER, mp1, mp2); } else if ( ev. cmd == cmMouseDown && !is_apt( aptFirstClick)) { Handle x = self; while ( dsys(x) className != WC_FRAME && ( x != application)) x = (( PWidget) x)-> owner; // possible bug with toplevel non-windows if ( x != application && !local_wnd( WinQueryActiveWindow( HWND_DESKTOP), (( PWidget) x)-> handle)) { ev. cmd = 0; // yes, we abandon mousedown but we should force selection: if ((( PApplication) application)-> hintUnder == self) v-> self-> set_hintVisible( self, 0); if (( v-> options. optSelectable) && ( v-> selectingButtons & ev. pos. button)) apc_widget_set_focused( self); } } ev. pos. where. x = (short)SHORT1FROMMP( mp1); ev. pos. where. y = (short)SHORT2FROMMP( mp1); if ( SHORT2FROMMP( mp2) & KC_SHIFT) { ev. pos. mod |= kmShift; } if ( SHORT2FROMMP( mp2) & KC_ALT ) { ev. pos. mod |= kmAlt; } if ( SHORT2FROMMP( mp2) & KC_CTRL ) { ev. pos. mod |= kmCtrl; } break; case WM_ACTIVATEMENU: { hiStage = true; ev. cmd = cmMenu; ev. gen. H = ( Handle) mp1; ev. gen. i = ( int) mp2; } break; case WM_ADJUSTWINDOWPOS: if ( sys className != WC_FRAME) { int fl = (( PSWP) mp1) -> fl; if (fl & ( SWP_SIZE | SWP_MOVE | SWP_MAXIMIZE | SWP_RESTORE | SWP_HIDE)) { ev. cmd = cmCalcBounds; ev. gen. R. left = (( PSWP) mp1) -> x; ev. gen. R. bottom = (( PSWP) mp1) -> y; ev. gen. R. right = (( PSWP) mp1) -> cx; ev. gen. R. top = (( PSWP) mp1) -> cy; } } break; case WM_CALCVALIDRECTS: if ( v-> self-> custom_paint( self)) return MPFROMLONG( CVR_REDRAW); else return MPFROMLONG( CVR_ALIGNLEFT | CVR_ALIGNBOTTOM); case WM_CHAR: if ( apc_widget_is_responsive( self)) { ev. cmd = ( SHORT1FROMMP( mp1) & KC_KEYUP) ? cmKeyUp : cmKeyDown; ev. key. code = SHORT1FROMMP( mp2) & 0xFF; ev. key. key = ctx_remap_def( SHORT2FROMMP( mp2), ctx_kb2VK, false, kbNoKey); ev. key. repeat = CHAR3FROMMP( mp1); ev. key. mod = 0; if ( SHORT1FROMMP( mp1) & KC_SHIFT) { ev. key. mod |= kmShift; } if ( SHORT1FROMMP( mp1) & KC_ALT ) { ev. key. mod |= kmAlt; } if ( SHORT1FROMMP( mp1) & KC_CTRL ) { ev. key. mod |= kmCtrl; if ( isalpha( ev. key. code)) ev. key. code = toupper( ev. key. code) - '@'; } if ( SHORT1FROMMP( mp1) & KC_DEADKEY) { ev. key. mod |= kmDeadKey; } } break; case WM_CLOSE: ev. cmd = cmClose; break; case WM_COMMAND: { switch ( SHORT1FROMMP( mp2)) { case CMDSRC_MENU: if ( SHORT1FROMMP( mp1) <= MENU_ID_AUTOSTART) { HWND active = WinQueryFocus( HWND_DESKTOP); if ( active != nilHandle) WinSendMsg ( active, SHORT1FROMMP( mp1), 0, 0); } break; } // end source case } break; case WM_CONTEXTMENU : ev. cmd = cmPopup; ev. gen. B = !SHORT2FROMMP( mp2); // mouse event ev. gen. P. x = SHORT1FROMMP( mp1); ev. gen. P. y = SHORT2FROMMP( mp1); break; case WM_DESTROY: if ( v-> stage <= csNormal) { v-> handle = nilHandle; // tell apc not to kill this HWND WinSetWindowULong( w, QWL_USER, 0); Object_destroy(( Handle) v); } break; case WM_ENABLE: ev. cmd = SHORT1FROMMP( mp1) ? cmEnable : cmDisable; hiStage = true; break; case WM_FOCUSCHANGE: if ( !guts. focSysDisabled && !guts. focSysGranted) { Handle hf = Application_map_focus( application, self); if ( hf && hf != self) { WinPostMsg( w, WM_FORCEFOCUS, ( MPARAM) (( PWidget) hf)-> handle, ( MPARAM) hf); return ( MPARAM) 0; } } break; case WM_FORCEFOCUS: if ( mp2 && WinIsWindow( guts. anchor, ( HWND) mp1)) ((( PWidget) mp2)-> self)-> set_selected(( Handle) mp2, 1); return 0; case WM_FONTCHANGED: ev. cmd = cmFontChanged; break; case WM_HELP: if ( apc_widget_is_responsive( self)) { ev. cmd = cmKeyDown; ev. key. key = kbF1; } break; case WM_MENUCOMMAND: ev. gen. i = SHORT1FROMMP( mp1); ev. gen. H = ev. gen. source = LONGFROMMP( mp2); ev. cmd = cmMenuCmd; break; case WM_MENUSELECT: { PMenuWndData menu = ( PMenuWndData) WinQueryWindowULong(( HWND) mp2, QWL_USER); if ( menu && SHORT2FROMMP( mp1) && ( SHORT1FROMMP( mp1) > MENU_ID_AUTOSTART)) { if (( ev. gen. source = menu-> menu) != nilHandle) WinPostMsg( w, WM_MENUCOMMAND, mp1, MPFROMLONG( menu-> menu)); } } break; case WM_MOVE: ev. cmd = cmMove; ev. gen. P = v-> self-> get_origin( self); if ( ev. gen. P. x == v-> pos. x && ev. gen. P. y == v-> pos. y) ev. cmd = 0; break; case WM_REPAINT: ev. cmd = cmRepaint; break; case WM_PAINT: { PWidget vv = ( PWidget)( v-> owner); Bool ok = true; if ( v-> stage == csNormal) { while ( vv) { if ( vv-> stage < csNormal) { ok = false; break; } vv = ( PWidget) vv-> owner; } } if ( !ok) { WinPostMsg( w, WM_REPAINT, 0, 0); break; } ev. cmd = cmPaint; switch (( int) sys className) { case WC_FRAME: break; case WC_CUSTOM: if ( v-> stage == csNormal && list_index_of( &guts. transp, self) >= 0) return 0; break; default: ev. cmd = 0; } break; } case WM_PRESPARAMMENU: ev. cmd = LONGFROMMP( mp1); ev. gen. source = ( Handle) mp2; if ( ev. cmd == cmFontChanged) hiStage = true; break; case WM_MENUCOLORCHANGED: ev. cmd = cmColorChanged; ev. gen. source = ( Handle) mp2; ev. gen. i = LONGFROMMP( mp1); hiStage = true; break; case WM_PRESPARAMCHANGED: if ( v-> stage == csNormal) switch ( LONGFROMMP( mp1)) { case PP_FOREGROUNDCOLOR: case PP_FOREGROUNDCOLORINDEX: ev. gen. i = ciFore; opt_clear( optOwnerColor); goto SETCMD; case PP_BACKGROUNDCOLOR: case PP_BACKGROUNDCOLORINDEX: ev. gen. i = ciBack; opt_clear( optOwnerBackColor); goto SETCMD; case PP_HILITEFOREGROUNDCOLOR: case PP_HILITEFOREGROUNDCOLORINDEX: ev. gen. i = ciHiliteText; goto SETCMD; case PP_HILITEBACKGROUNDCOLOR: case PP_HILITEBACKGROUNDCOLORINDEX: ev. gen. i = ciHilite; goto SETCMD; case PP_DISABLEDFOREGROUNDCOLOR: case PP_DISABLEDFOREGROUNDCOLORINDEX: ev. gen. i = ciDisabledText; goto SETCMD; case PP_DISABLEDBACKGROUNDCOLOR: case PP_DISABLEDBACKGROUNDCOLORINDEX: ev. gen. i = ciDisabled; SETCMD: { SingleColor s = { apc_widget_get_color( self, ev. gen. i), ev. gen. i}; v-> self-> first_that( self, single_color_notify, &s); } if ( ev. gen. i == ciFore) opt_clear( optOwnerColor); else if ( ev. gen. i == ciBack) opt_clear( optOwnerBackColor); ev. cmd = cmColorChanged; hiStage = true; break; case PP_FONTNAMESIZE: case PP_FONTHANDLE: view_get_font( view, &v-> font); v-> self-> first_that( self, font_notify, &v-> font); opt_clear( optOwnerFont); ev. cmd = cmFontChanged; hiStage = true; break; } break; case WM_PRIMA_CREATE: ev. cmd = cmSetup; break; case WM_SETFOCUS: ev. cmd = SHORT1FROMMP( mp2) ? cmReceiveFocus : cmReleaseFocus; ev. gen. source = LONGFROMMP( mp1); hiStage = true; apt_assign( aptFocused, ev. cmd == cmReceiveFocus); cursor_update( self); WinShowCursor( w, is_apt( aptFocused) && is_apt( aptCursorVis)); break; case WM_SHOW: if ( list_index_of( &guts. transp, self) < 0) { if ( v-> stage <= csNormal) ev. cmd = SHORT1FROMMP( mp1) ? cmShow : cmHide; hiStage = true; apt_assign( aptVisible, SHORT1FROMMP( mp1)); } break; case WM_TIMER: { int id = SHORT1FROMMP( mp1) - 1; if ( id + 1 == TID_USERMAX-1) // application local timer { POINTL p; HWND wp; // checking for WM_MOUSEENTER if ( lastMouseOver && !WinQueryCapture( HWND_DESKTOP)) { WinQueryPointerPos( HWND_DESKTOP, &p); wp = WinWindowFromPoint( HWND_DESKTOP, &p, true); if ( wp != (( PWidget) lastMouseOver)-> handle) { HWND old = (( PWidget) lastMouseOver)-> handle; Handle s; lastMouseOver = nilHandle; WinSendMsg( old, WM_MOUSELEAVE, 0, 0); s = hwnd_to_view( wp); if (s && (( PWidget) s)-> handle == wp) { WinMapWindowPoints( HWND_DESKTOP, wp, &p, 1); WinSendMsg( wp, WM_MOUSEENTER, MPFROM2SHORT( p. x, p. y), 0); lastMouseOver = s; } } } return 0; } if ( id >= 0 && id < sys timeDefsCount) ev. gen. H = ( Handle) sys timeDefs[ id]. item; if ( ev. gen. H) { v = ( PWidget)view = ev. gen. H; ev. cmd = cmTimer; } } break; case WM_POSTAL: ev. cmd = cmPost; ev. gen. H = ( Handle) mp1; ev. gen. p = ( void *) mp2; break; case WM_WINDOWPOSCHANGED: if (( v-> stage <= csNormal) && ( sys className != WC_FRAME)) { PSWP New = PVOIDFROMMP( mp1); PSWP Old = New + 1; int fl = New-> fl; if ( fl & SWP_ZORDER) WinPostMsg( w, WM_ZORDERSYNC, 0, 0); if ( fl & SWP_MOVE) { ev. cmd = cmMove; ev. gen . P. x = New-> x; ev. gen . P. y = New-> y; if ( fl & (SWP_SIZE|SWP_RESTORE|SWP_MAXIMIZE)) { New->fl &= ~SWP_MOVE; WinSendMsg( w, WM_WINDOWPOSCHANGED, mp1, mp2); New->fl |= SWP_MOVE; } if ( ev. gen. P. x == v-> pos. x && ev. gen. P. y == v-> pos. y) ev. cmd = 0; } else if ( fl & (SWP_SIZE|SWP_RESTORE|SWP_MAXIMIZE)) { ev. cmd = cmSize; ev. gen. R. right = ev. gen . P. x = New-> cx; ev. gen. R. top = ev. gen . P. y = New-> cy; ev. gen. R. left = Old-> cx; ev. gen. R. bottom = Old-> cy; if (( sys sizeLockLevel == 0) && ( v-> stage <= csNormal)) v-> virtualSize = ev. gen. P; } if ( is_apt( aptTransparent)) WinInvalidateRect( w, nil, false); } break; case WM_ZORDERSYNC: ev. cmd = cmZOrderChanged; break; } if ( hiStage && WinIsWindow( guts. anchor, w)) toReturn = fnwp ? fnwp( w, orgMsg, mp1, mp2) : WinDefWindowProc( w, msg, mp1, mp2); orgCmd = ev. cmd; if ( ev. cmd) v-> self-> message( view, &ev); else ev. cmd = orgMsg; if ( v-> stage <= csDestroying) switch ( orgMsg) { case WM_ADJUSTWINDOWPOS: if ( ev. cmd) { (( PSWP) mp1) -> x = ev. gen. R. left; (( PSWP) mp1) -> y = ev. gen. R. bottom; (( PSWP) mp1) -> cx = ev. gen. R. right; (( PSWP) mp1) -> cy = ev. gen. R. top; } break; case WM_BUTTON1DOWN: case WM_BUTTON1UP: case WM_BUTTON1CLICK: case WM_BUTTON1DBLCLK: case WM_BUTTON2DOWN: case WM_BUTTON2UP: case WM_BUTTON2CLICK: case WM_BUTTON2DBLCLK: case WM_BUTTON3DOWN: case WM_BUTTON3UP: case WM_BUTTON3CLICK: case WM_BUTTON3DBLCLK: return ( MRESULT)1; case WM_CHAR: if ( ev. cmd == 0 || WinIsWindowEnabled( w)) { // this is to avoid default send to owner hwnd return ( MRESULT)1; } break; case WM_CLOSE: if ( ev. cmd) { if ( sys className == WC_FRAME && PWindow(self)->modal) { CWindow(self)-> cancel( self); return 0; } else Object_destroy(( Handle) v); break; } else { return 0; } case WM_HELP: if ( !ev. cmd) WinSendMsg( w, WM_VIEWHELP, 0, 0); break; case WM_COMMAND: return toReturn; case WM_PRESPARAMCHANGED: WinInvalidateRect ( w, nil, true); break; case WM_MOUSEMOVE: if ( WinIsWindowEnabled( w)) WinSetPointer( HWND_DESKTOP, sys pointer); return MRFROMLONG(1); } if ( ev. cmd && !hiStage) { if ( !WinIsWindow( guts. anchor, w)) return 0; toReturn = fnwp ? fnwp( w, orgMsg, mp1, mp2) : WinDefWindowProc( w, msg, mp1, mp2); } return toReturn; } MRESULT EXPENTRY generic_frame_handler( HWND win, ULONG msg, MPARAM mp1, MPARAM mp2) { HWND client = WinWindowFromID( win, FID_CLIENT); PFNWP fProc = ( PFNWP) WinQueryWindowULong( win, QWL_USER); Event ev; Handle self = WinQueryWindowULong( client, QWL_USER); PWidget v = ( PWidget) self; MPARAM toReturn = 0; Bool hiStage = false; Point dPoint; int i; if ( !self) return fProc ? fProc( win, msg, mp1, mp2) : WinDefWindowProc( win, msg, mp1, mp2); for ( i = 0; i < guts. eventHooks. count; i++) { QMSG ms = { win, msg, mp1, mp2, 0}; if ((( PrimaHookProc *)( guts. eventHooks. items[i]))((void*) &ms)) return 0; } memset( &ev, 0, sizeof (ev)); ev. gen. source = self; switch ( msg) { case WM_ACTIVATE: ev. cmd = SHORT1FROMMP(mp1) ? cmActivate : cmDeactivate; break; case WM_ADJUSTWINDOWPOS: { int fl = (( PSWP) mp1) -> fl; if ( fl & SWP_ZORDER) { Handle hf = Application_map_focus( application, self); if ( hf && hf != self) (( PSWP) mp1)-> fl &= ~SWP_ZORDER; } if (fl & ( SWP_SIZE | SWP_MAXIMIZE | SWP_RESTORE)) // if (fl & ( SWP_SIZE | SWP_MAXIMIZE)) { Point p; ev. cmd = cmCalcBounds; ev. gen. R. left = (( PSWP) mp1) -> x; ev. gen. R. bottom = (( PSWP) mp1) -> y; p = frame2client( self, ( Point){ (( PSWP) mp1) -> cx, (( PSWP) mp1) -> cy }, true); dPoint = ( Point){ (( PSWP) mp1) -> cx - p. x, (( PSWP) mp1) -> cy - p. y }; ev. gen. R. right = p. x; ev. gen. R. top = p. y; } if ( fl & SWP_MINIMIZE) { sys s. window. lastFrameSize = ( Point){(( PSWP) mp1) -> cx, (( PSWP) mp1) -> cy}; sys s. window. lastClientSize = frame2client( self, sys s. window. lastFrameSize, true ); } } break; case WM_CHAR: WinSendMsg( v-> handle, msg, mp1, mp2); break; case WM_HITTEST: if ( !guts. focSysDisabled && ( Application_map_focus( application, self) != self)) return ( MRESULT) HT_ERROR; break; case WM_DLGENTERMODAL: WinSendMsg( win, WM_ACTIVATE, MPFROMLONG( 1), 0); ev. cmd = cmExecute; break; case WM_FOCUSCHANGE: if ( !guts. focSysDisabled && !guts. focSysGranted) { if ( SHORT1FROMMP( mp2)) { Handle hf = Application_map_focus( application, self); if ( hf && hf != self) { WinPostMsg( win, WM_FORCEFOCUS, ( MPARAM) (( PWidget) hf)-> handle, ( MPARAM) hf); return ( MPARAM) 0; } } else if ( PWindow( self)-> modal) { PID xpid; TID xtid; WinQueryWindowProcess(( HWND) mp1, &xpid, &xtid); if ( xpid != guts. pid) return 0; } hiStage = true; } break; case WM_WINDOWPOSCHANGED: { PSWP new = PVOIDFROMMP( mp1); PSWP old = new + 1; #define wspush(d) \ if ( v) \ { \ Event xev; \ xev. cmd = cmWindowState; \ xev. gen.source = self; \ xev. gen. i = d; \ v-> self-> message( self, &xev); \ } if ( new-> fl & SWP_ZORDER) WinPostMsg( client, WM_ZORDERSYNC, 0, 0); if ( new-> fl & ( SWP_SIZE | SWP_MAXIMIZE | SWP_RESTORE | SWP_HIDE)) { Point pOld = frame2client( self, ( Point){old->cx, old->cy}, true); Point pNew = frame2client( self, ( Point){new->cx, new->cy}, true); ev. gen. R. left = pOld. x; ev. gen. R. bottom = pOld. y; ev. gen. P. x = ev. gen. R. right = pNew. x; ev. gen. P. y = ev. gen. R. top = pNew. y; ev. cmd = cmSize; if (( sys sizeLockLevel == 0) && ( v-> stage <= csNormal)) v-> virtualSize = ev. gen. P; hiStage = true; } if (( new-> fl & SWP_RESTORE) && ( sys s. window. state == wsMinimized)) { Point p = frame2client( self, sys s. window. hiddenSize, false); wspush( wsNormal); sys s. window. state = wsNormal; WinSetWindowPos( win, 0, sys s. window. hiddenPos. x, sys s. window. hiddenPos. y, p.x, p.y, SWP_SIZE|SWP_MOVE ); } if (( new-> fl & SWP_RESTORE) && ( sys s. window. state == wsMaximized)) { wspush( wsNormal); sys s. window. state = wsNormal; } if (( new-> fl & SWP_MINIMIZE) && !( old-> fl & SWP_MINIMIZE)) { sys s. window. hiddenPos. x = old-> x; sys s. window. hiddenPos. y = old-> y; sys s. window. hiddenSize = sys s. window. lastClientSize; wspush( wsMinimized); sys s. window. state = wsMinimized; } if (( new-> fl & SWP_MAXIMIZE) && !( old-> fl & SWP_MAXIMIZE)) { wspush( wsMaximized); sys s. window. state = wsMaximized; } if ( new-> fl & ( SWP_SHOW | SWP_HIDE)) WinSendMsg( client, WM_SHOW, MPFROMLONG((new-> fl & SWP_SHOW)!=0), 0); } break; } if ( hiStage) toReturn = fProc ? fProc( win, msg, mp1, mp2) : WinDefWindowProc( win, msg, mp1, mp2); if (( ev. cmd != 0) && ( v != nil)) { v-> self-> message( self, &ev); } if ( v-> stage <= csDestroying) switch ( msg) { case WM_ADJUSTWINDOWPOS: if ( ev. cmd) { (( PSWP) mp1)-> x = ev. gen. R. left; (( PSWP) mp1)-> y = ev. gen. R. bottom; (( PSWP) mp1)-> cx = ev. gen. R. right + dPoint. x; (( PSWP) mp1)-> cy = ev. gen. R. top + dPoint. y; } break; case WM_FOCUSCHANGE: break; case WM_WINDOWPOSCHANGED: { PSWP new = PVOIDFROMMP( mp1); if ( is_apt( aptSyncPaint) && ( new-> fl & ( SWP_MAXIMIZE|SWP_RESTORE))) apc_widget_invalidate_rect( self, nil); } break; } if ( !WinIsWindow( guts. anchor, win)) return 0; if ( !hiStage) toReturn = fProc ? fProc( win, msg, mp1, mp2) : WinDefWindowProc( win, msg, mp1, mp2); return toReturn; } static Bool locate_accel( PAbstractMenu menu, PMenuItemReg m, int * key) { return menu-> self-> translate_accel(( Handle) menu, m-> text) == *key; } static Bool find_oid( PAbstractMenu menu, PMenuItemReg m, int id) { return m-> down && ( m-> down-> id == id); } MRESULT EXPENTRY generic_menu_handler( HWND win, ULONG msg, MPARAM mp1, MPARAM mp2) { PMenuWndData md = ( PMenuWndData) WinQueryWindowULong( win, QWL_USER); MPARAM ret; if (( md == nil) || ( md-> menu == nilHandle)) return WinDefWindowProc( win, msg, mp1, mp2); if ( !appDead) switch ( msg) { case WM_CHAR: if (( SHORT1FROMMP( mp1) & KC_KEYUP) == 0) { int code, key, flags = SHORT1FROMMP( mp1), mod = 0; code = SHORT1FROMMP( mp2); key = ctx_remap_def( SHORT2FROMMP( mp2), ctx_kb2VK, false, kbNoKey); if ( flags & KC_SHIFT) { mod |= kmShift; } if ( flags & KC_ALT ) { mod |= kmAlt; } if ( flags & KC_CTRL ) { mod |= kmCtrl; } switch ( SHORT2FROMMP( mp2)) { case VK_ESC: case VK_SPACE: case VK_END: case VK_HOME: case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN: case VK_ENTER: break; default: { PAbstractMenu menu = ( PAbstractMenu)( md-> menu); PWidget owner = ( PWidget)( menu-> owner); int xkey = menu-> self-> translate_key(( Handle) menu, key, code, mod); if ( menu-> self-> first_that(( Handle) menu, locate_accel, &xkey, false)) break; // suspect that menu shortcut found. Do not touch it. if ( menu-> self-> sub_call_key(( Handle) menu, xkey) || owner-> self-> process_accel(( Handle) owner, xkey)) { WinSendMsg( menu-> handle, MM_ENDMENUMODE, MPFROMLONG( true), 0); return ( MPARAM)1; } } } } break; case WM_DESTROY: { PFNWP f = md-> fnwp; WinSetWindowULong( win, QWL_USER, 0); free( md); if ( !WinIsWindow( guts. anchor, win)) return 0; return f ? f( win, msg, mp1, mp2) : WinDefWindowProc( win, msg, mp1, mp2); } break; case WM_INITMENU: { PMenuItemReg m; PMenuWndData mwd = ( PMenuWndData) WinQueryWindowULong(( HWND) mp2, QWL_USER); if ( mwd) { PComponent owner = ( PComponent)(( PComponent)( md-> menu))-> owner; m = AbstractMenu_first_that( mwd-> menu, find_oid, (void*)mwd->id, true); if ( m) WinSendMsg( owner-> handle, WM_ACTIVATEMENU, MPFROMLONG( md-> menu), ( MPARAM) m-> id); else WinSendMsg( owner-> handle, WM_ACTIVATEMENU, MPFROMLONG( md-> menu), ( MPARAM) 0); } } break; case WM_PRESPARAMCHANGED: switch ( LONGFROMMP( mp1)) { int i; case PP_MENUFOREGROUNDCOLOR: case PP_MENUFOREGROUNDCOLORINDEX: i = ciFore; goto SETCMD; case PP_MENUBACKGROUNDCOLOR: case PP_MENUBACKGROUNDCOLORINDEX: i = ciBack; goto SETCMD; case PP_MENUHILITEFGNDCOLOR: case PP_MENUHILITEFGNDCOLORINDEX: i = ciHiliteText; goto SETCMD; case PP_MENUHILITEBGNDCOLOR: case PP_MENUHILITEBGNDCOLORINDEX: i = ciHilite; goto SETCMD; case PP_MENUDISABLEDFGNDCOLOR: case PP_MENUDISABLEDFGNDCOLORINDEX: i = ciDisabledText; goto SETCMD; case PP_MENUDISABLEDBGNDCOLOR: case PP_MENUDISABLEDBGNDCOLORINDEX: i = ciDisabled; SETCMD: { PComponent owner = ( PComponent)(( PComponent)( md-> menu))-> owner; WinSendMsg( owner-> handle, WM_MENUCOLORCHANGED, MPFROMSHORT(i), MPFROMLONG( md-> menu)); } break; case PP_FONTNAMESIZE: case PP_FONTHANDLE: { PComponent owner = ( PComponent)(( PComponent)( md-> menu))-> owner; WinSendMsg( owner-> handle, WM_PRESPARAMMENU, MPFROMLONG( cmFontChanged), MPFROMLONG( md-> menu)); } break; } break; } if ( !WinIsWindow( guts. anchor, win)) return 0; ret = md-> fnwp ? md-> fnwp( win, msg, mp1, mp2) : WinDefWindowProc( win, msg, mp1, mp2); return ret; }