netscape-revival
sun-java/awt/windows/awtapp.cpp
/*
* @(#)awtapp.cpp 1.40 95/12/08
*
* Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies. Please refer to the file "copyright.html"
* for further important copyright and licensing information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
/*-
* awtapp.cpp : Defines the class behaviors for the application.
*/
#include "stdafx.h"
#include "awt.h"
#include "awtapp.h"
#include "awt_button.h"
#include "awt_comp.h"
#include "awt_edit.h"
#include "awt_event.h"
#include "awt_filedlg.h"
#include "awt_font.h"
#include "awt_fontmetrics.h"
#include "awt_graphics.h"
#include "awt_label.h"
#include "awt_list.h"
#include "awt_optmenu.h"
#include "awt_mainfrm.h"
#include "awt_menu.h"
#include "awt_sbar.h"
#include "awt_window.h"
extern "C" {
#include "javaThreads.h"
#include "exceptions.h"
#if defined(NETSCAPE)
extern _declspec(dllexport) int sysAtexit(void (*func)(void));
#define GET_APP_PALETTE_API "GetApplicationPalette"
typedef HPALETTE (*GetApplicationPalette)(void);
#else
extern int sysAtexit(void (*func)(void));
#endif /* NETSCAPE */
}
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#ifdef ENABLE_CALLINGWINDOWS
CallingWindowsStruct CallingWindows[CALLINGWINDOWS_QUEUESIZE];
#endif
/////////////////////////////////////////////////////////////////////////////
// CAwtApp
BEGIN_MESSAGE_MAP(CAwtApp, CWinApp)
//{{AFX_MSG_MAP(CAwtApp)
//}}AFX_MSG_MAP
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
// Standard print setup command
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
// AWT message routing
// ON_AWT_MESSAGE(WM_AWT_DISPATCH_EVENT, OnAwtDispatchEvent)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// DllMain entry point
// This code is derived from DllMain in winmain.cpp. There may
// be missing code.
extern "C" BOOL WINAPI
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
{
CAwtApp* pApp = (CAwtApp *)AfxGetApp();
if (dwReason == DLL_PROCESS_ATTACH) {
// initialize DLL instance
if (!AfxWinInit(hInstance, NULL, &afxChNil, 0)) {
AfxWinTerm();
return FALSE;
}
// initialize application instance
if (pApp != NULL && !pApp->InitInstance()) {
pApp->ExitInstance();
AfxWinTerm();
return FALSE;
}
} else if (dwReason == DLL_PROCESS_DETACH) {
AfxWinTerm();
#if defined(NETSCAPE) && defined(DEBUG)
AwtCList *ptr;
ptr = (AwtCList *)__AllAwtObjects.next;
PR_LOG(AWT, out, ("Dumping remaining AwtObjects:"));
while (ptr != &__AllAwtObjects) {
PR_LOG(AWT, out, (" %s", ptr->name));
ptr = (AwtCList *)ptr->next;
}
#endif
}
return TRUE;
}
void handleExit(void)
{
(CAwtApp *)AfxGetApp()->ExitInstance();
}
/////////////////////////////////////////////////////////////////////////////
// CAwtApp construction
extern "C" ClassClass *GetThreadClassBlock();
CAwtApp::CAwtApp()
{
// Initialize the list of all AWT objects (debug only)
INITIALIZE_AWT_LIST;
// Add the new object to the list of all AWT objects (debug only)
INITIALIZE_AWT_LIST_LINK("AwtApp");
OSVERSIONINFO osVersionInfo;
m_hBtnFont = NULL;
m_hBtnFontBold = NULL;
m_bInMonitor = FALSE;
m_hReadyEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
m_bWin95UI = (BYTE)::GetVersion() >= 4;
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
VERIFY(::GetVersionEx(&osVersionInfo));
m_bWin95OS = osVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT;
m_cleanupList = new CMapPtrToPtr;
bTraceAwt = FALSE;
// Awt message pool.
::InitializeCriticalSection(&m_csAwtMsgPool);
}
CAwtApp::~CAwtApp()
{
AwtImage::DisposePalette();
if (m_hBtnFont != NULL) {
VERIFY(::DeleteObject(m_hBtnFont));
}
if (m_hBtnFontBold != NULL) {
VERIFY(::DeleteObject(m_hBtnFontBold));
}
if (m_hReadyEvent != NULL) {
::CloseHandle(m_hReadyEvent);
}
// Awt brush cache.
POSITION pos = brushCache.GetStartPosition();
while (pos != NULL) {
void *key;
BrushCacheRec* pRec;
void *p;
brushCache.GetNextAssoc(pos, key, p);
pRec = (BrushCacheRec*)p;
::DeleteObject(pRec->m_hBrush);
delete pRec;
}
brushCache.RemoveAll();
// Awt message pool.
::DeleteCriticalSection(&m_csAwtMsgPool);
while (!m_AwtMsgPool.IsEmpty()) {
AwtMsg *pMsg = (AwtMsg*)m_AwtMsgPool.RemoveHead();
VERIFY(::CloseHandle(pMsg->hEvent));
delete pMsg;
}
CAwtApp *pApp = (CAwtApp*)AfxGetApp();
while (!pApp->m_pCallbackThreadQ->IsEmpty()) {
CallbackThreadMsg *pMsg =
(CallbackThreadMsg *)pApp->m_pCallbackThreadQ->RemoveHead();
AWT_TRACE(("deleting callback msg %s\n", pMsg->m_pzMethodName));
delete pMsg;
}
delete pApp->m_pCallbackThreadQ;
::CloseHandle(pApp->m_hCallbackThreadEvent);
::CloseHandle(pApp->m_hCallbackThreadQMutex);
// Remove the object from the list of all AWT objects (debug only)
REMOVE_AWT_LIST_LINK;
}
/////////////////////////////////////////////////////////////////////////////
// CAwtApp initialization
BOOL CAwtApp::InitInstance()
{
HDC hDC = ::CreateCompatibleDC(NULL);
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
//Enable3dControls();
//LoadStdProfileSettings(); // Load standard INI file options (including MRU)
// this variable is used by the app framework which assumes this is not NULL.
// An app typically has at least one window open so this is justified.
// However, this is not true in our case so we create a fake window and
// have it point to it.
m_pMainWnd = new CWnd();
#if !defined(NETSCAPE)
// Check for at least 8-bit color
if (::GetDeviceCaps(hDC, SIZEPALETTE) > 0 && ::GetDeviceCaps(hDC, SIZEPALETTE) < 256) {
::MessageBox(NULL, "Sorry, but you must have at least 256 colors for this alpha release of HotJava/NT",
"Error", MB_APPLMODAL);
return FALSE;
}
AwtImage::InitializePalette(hDC);
#else
// Check for at least 8-bit color
if (::GetDeviceCaps(hDC, SIZEPALETTE) > 0 && ::GetDeviceCaps(hDC, SIZEPALETTE) < 256) {
::MessageBox(NULL, "Sorry, but you must have at least 256 colors to display java applets",
"Error", MB_APPLMODAL);
return FALSE;
// The Palette is initialized in CAwtApp::MainLoop()
}
#endif // NETSCAPE
// Create the button fonts used by buttons created in AWT
LOGFONT logfont;
UINT cyPixelsPerInch = ::GetDeviceCaps(hDC, LOGPIXELSY);
memset(&logfont, 0, sizeof(logfont));
logfont.lfHeight = -MulDiv(10, cyPixelsPerInch, 72);
logfont.lfWeight = FW_NORMAL;
logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
lstrcpy(logfont.lfFaceName, _T("MS Sans Serif"));
m_hBtnFont = ::CreateFontIndirect(&logfont);
//m_hBtnFont = NULL;
if (m_hBtnFont == NULL) {
TRACE0("Warning: Using system font for button text.\n");
m_hBtnFontBold = (HFONT)::GetStockObject(SYSTEM_FONT);
}
logfont.lfWeight = FW_BOLD;
if (m_hBtnFont != NULL) {
m_hBtnFontBold = ::CreateFontIndirect(&logfont);
}
if (m_hBtnFontBold == NULL) {
TRACE0("Warning: Using system font for button text.\n");
m_hBtnFontBold = (HFONT)::GetStockObject(SYSTEM_FONT);
}
// Get DLU for button font
::SelectObject(hDC, m_hBtnFontBold);
::GetTextExtentPoint(hDC, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 52, &m_aveSize);
::SelectObject(hDC, ::GetStockObject(SYSTEM_FONT));
::DeleteDC(hDC);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CAwtApp object
CAwtApp theApp;
/////////////////////////////////////////////////////////////////////////////
// Operations
void CAwtApp::Init(Hsun_awt_win32_MToolkit *pJavaObject, Hjava_lang_Thread *pParentObject) {
Classjava_lang_Thread *pParent = (Classjava_lang_Thread*)unhand(pParentObject);
// Start callback thread
m_hCallbackThreadQMutex = CreateMutex(NULL, FALSE, NULL);
m_pCallbackThreadQ = new CPtrList();
m_hCallbackThreadEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
}
void CAwtApp::MainLoop(Hsun_awt_win32_MToolkit *pJavaObject)
{
MSG msg;
char *pAwtEnv = getenv("AWT_DEBUG");
int i;
#ifdef _DEBUG
printf("DEBUG version of awt.dll\n");
#endif
//GdiSetBatchLimit(1);
if (pAwtEnv) {
printf("AWT_DEBUG=%s\n", pAwtEnv);
for (i=0; i<(int)strlen(pAwtEnv); i++) {
if (pAwtEnv[i] == 't') {
bTraceAwt = TRUE;
AWT_TRACE(("tracing all awt calls\n"));
}
}
}
// Create the message queue and then signal ready.
::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
m_pJavaObject = pJavaObject;
m_threadID = GetCurrentThreadId();
#ifdef ENABLE_CALLINGWINDOWS
CallingWindows[0].msgLoopThread = m_threadID;
CallingWindows[0].msgLoopMonitor = (int *)obj_monitor(m_pJavaObject);
#endif
sysAtexit(handleExit);
#ifdef NETSCAPE
//
// Call back to the Application to query the default palette via the
// exported GetApplicationPalette() call
//
HPALETTE hPal;
GetApplicationPalette pfGetAppPalette = (GetApplicationPalette)
::GetProcAddress( ::GetModuleHandle(NULL),
GET_APP_PALETTE_API);
if( pfGetAppPalette ) {
hPal = (*pfGetAppPalette)();
}
if( hPal ) {
AwtImage::InitializePalette(hPal);
} else {
HDC hDC = ::CreateCompatibleDC(NULL);
AwtImage::InitializePalette(hDC);
::DeleteDC(hDC);
}
#endif // NETSCAPE
MonitorEnter();
monitorNotify(obj_monitor(m_pJavaObject));
//MonitorExit();
Run();
MonitorExit();
}
BOOL CAwtApp::PumpMessage()
{
ASSERT_VALID(this);
#ifdef _DEBUG
if (m_nDisablePumpCount != 0)
{
TRACE0("Error: CWinThread::PumpMessage called when not permitted.\n");
ASSERT(FALSE);
}
#endif
// Release the AWT lock before blocking in GetMessage(...)
MonitorExit();
if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
{
MonitorEnter();
#ifdef _DEBUG
if (afxTraceFlags & traceAppMsg)
TRACE0("CWinThread::PumpMessage - Received WM_QUIT.\n");
m_nDisablePumpCount++; // application must die
// Note: prevents calling message loop things in 'ExitInstance'
// will never be decremented
#endif
return FALSE;
}
// Get the AWT lock
MonitorEnter();
#ifdef _DEBUG
#ifndef MSVC4
if (afxTraceFlags & traceAppMsg)
_AfxTraceMsg(_T("PumpMessage"), &m_msgCur);
#endif
#endif
// process this message
if (!PreTranslateMessage(&m_msgCur) && (m_msgCur.message != WM_NULL) )
{
::TranslateMessage(&m_msgCur);
::DispatchMessage(&m_msgCur);
}
return TRUE;
}
BOOL CAwtApp::OnIdle(LONG lCount)
{
MonitorExit();
CALLINGWINDOWS(0);
VERIFY(::WaitMessage());
MonitorEnter();
return 1;
}
void CAwtApp::CallbackLoop(Hsun_awt_win32_MToolkit *pJavaObject)
{
CallbackThreadMsg *pMsg;
CAwtApp *pApp = (CAwtApp*)AfxGetApp();
EE();
while (TRUE) {
::WaitForSingleObject(pApp->m_hCallbackThreadEvent, INFINITE);
// check the queue for any items
while (TRUE) {
pMsg = NULL;
::WaitForSingleObject(pApp->m_hCallbackThreadQMutex, INFINITE);
if (!pApp->m_pCallbackThreadQ->IsEmpty()) {
pMsg = (CallbackThreadMsg *)pApp->m_pCallbackThreadQ->RemoveHead();
}
::ReleaseMutex(pApp->m_hCallbackThreadQMutex);
if (pMsg == NULL) {
break;
} else {
// Copy msg, as pMsg needs to be freed before msg is
// executed, as it may exit.
CallbackThreadMsg msg;
memcpy(&msg, pMsg, sizeof(CallbackThreadMsg));
delete pMsg;
AWT_TRACE(("CB %s %s\n",
msg.m_pzMethodName, msg.m_pzMethodSig));
pApp->DoCallback2(EE(), msg.m_pJavaObject,
msg.m_pzMethodName, msg.m_pzMethodSig,
msg.m_nParamCount, msg.p1, msg.p2,
msg.p3, msg.p4, msg.p5, msg.p6, msg.p7);
}
}
}
}
void CAwtApp::MonitorExit()
{
monitorExit(obj_monitor(m_pJavaObject));
}
void CAwtApp::MonitorEnter()
{
monitorEnter(obj_monitor(m_pJavaObject));
}
CRect CAwtApp::ComputeRect(char *pzString, int nAdditionalChars) {
CRect result(0, 0, 0, 0);
CSize stringSize(0, 0);
if (pzString == NULL || strlen(pzString) == 0) {
pzString = "M";
}
stringSize = AwtFontMetrics::StringWidth(CFont::FromHandle(m_hBtnFontBold), pzString);
// Surround the text with 3 DLU's
result.right = (6 + nAdditionalChars * 4) * m_aveSize.cx;
result.right /= 4 * 52;
result.right += stringSize.cx;
result.bottom = 6 * m_aveSize.cy;
result.bottom /= 8;
result.bottom += stringSize.cy;
return result;
}
void CAwtApp::CreateBrush(COLORREF color)
{
void *p;
BrushCacheRec *pRec;
if (brushCache.Lookup((void*)color, p)) {
pRec = (BrushCacheRec*)p;
pRec->m_nRefCount++;
return;
}
pRec = new BrushCacheRec;
pRec->m_nRefCount = 1;
pRec->m_hBrush = ::CreateSolidBrush(color);
brushCache[(void*)color] = pRec;
}
HBRUSH CAwtApp::GetBrush(COLORREF color)
{
void *p;
BrushCacheRec *pRec;
if (brushCache.Lookup((void*)color, p)) {
pRec = (BrushCacheRec*)p;
return pRec->m_hBrush;
}
ASSERT(FALSE);
return NULL;
}
void CAwtApp::ReleaseBrush(COLORREF color)
{
BrushCacheRec *pRec;
void *p;
if (brushCache.Lookup((void*)color, p)) {
pRec = (BrushCacheRec*)p;
pRec->m_nRefCount--;
if (pRec->m_nRefCount == 0) {
::DeleteObject(pRec->m_hBrush);
delete pRec;
VERIFY(brushCache.RemoveKey((void*)color));
}
return;
}
ASSERT(FALSE);
}
HICON CAwtApp::GetAwtIcon(void)
{
#ifdef NETSCAPE
return LoadIcon( "AWT_ICON" );
#else
HMODULE h = GetModuleHandle("AWT");
if (h == NULL) {
h = GetModuleHandle("AWT_G");
}
if (h != NULL) {
return ::LoadIcon(h, "AWT_ICON");
}
return NULL;
#endif
}
BOOL CAwtApp::IsServerThread() {
return ::GetCurrentThreadId() == m_threadID;
}
AwtMsg *CAwtApp::GetAwtMsgPool()
{
AwtMsg *pMsg;
::EnterCriticalSection(&m_csAwtMsgPool);
if (m_AwtMsgPool.IsEmpty()) {
pMsg = new AwtMsg;
pMsg->hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
} else {
pMsg = (AwtMsg*)m_AwtMsgPool.RemoveHead();
}
::LeaveCriticalSection(&m_csAwtMsgPool);
return pMsg;
}
void CAwtApp::PutAwtMsgPool(AwtMsg *pMsg)
{
::EnterCriticalSection(&m_csAwtMsgPool);
m_AwtMsgPool.AddHead(pMsg);
::LeaveCriticalSection(&m_csAwtMsgPool);
}
BOOL CAwtApp::PostServerQ(UINT uMsg, WPARAM wParam, LPARAM lParam) {
//printf("post([%x], %x, %x)", ::GetCurrentThreadId(), uMsg, lParam);
return ::PostThreadMessage(m_threadID, uMsg, wParam, lParam);
}
void CAwtApp::ShowWnd(HWND hWnd, UINT nFlags, BOOL bBringToTop)
{
PostAwtMsg(AWT_SHOWWND, 0, (long)hWnd, nFlags, bBringToTop);
}
void CAwtApp::PostAwtMsg(UINT nClass, UINT nMsg, long p1, long p2, long p3,
long p4, long p5, long p6, long p7)
{
//printf("post(%x, %x)", nClass, nMsg);
if (IsServerThread()) {
//MonitorExit();
HandleMsg(nClass, nMsg, p1, p2, p3, p4, p5, p6, p7);
//MonitorEnter();
} else {
AwtMsg *pMsg = GetAwtMsgPool();
pMsg->nClass = nClass;
pMsg->nMsg = nMsg;
pMsg->p1 = p1;
pMsg->p2 = p2;
pMsg->p3 = p3;
pMsg->p4 = p4;
pMsg->p5 = p5;
pMsg->p6 = p6;
pMsg->p7 = p7;
pMsg->bSignalEvent = FALSE;
VERIFY(PostServerQ(nClass, 0, (LPARAM)pMsg));
}
}
long CAwtApp::SendAwtMsg(UINT nClass, UINT nMsg, long p1, long p2, long p3,
long p4, long p5, long p6, long p7, long p8)
{
//printf("send(%x, %x)", nClass, nMsg);
long nResult;
if (IsServerThread()) {
//MonitorExit();
nResult = HandleMsg(nClass, nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
//MonitorEnter();
} else {
AwtMsg *pMsg = GetAwtMsgPool();
pMsg->nClass = nClass;
VERIFY(::ResetEvent(pMsg->hEvent));
pMsg->nMsg = nMsg;
pMsg->p1 = p1;
pMsg->p2 = p2;
pMsg->p3 = p3;
pMsg->p4 = p4;
pMsg->p5 = p5;
pMsg->p6 = p6;
pMsg->p7 = p7;
pMsg->p8 = p8;
pMsg->bSignalEvent = TRUE;
VERIFY(PostServerQ(nClass, 0, (LPARAM)pMsg));
MonitorExit();
#if 1
AWT_TRACE(("SendAwtMsg - Entering wait loop\n"));
while( ::WaitForSingleObject(pMsg->hEvent, 250) == WAIT_TIMEOUT ) {
MSG msg;
::PeekMessage( &msg, NULL, NULL, NULL, PM_NOREMOVE );
AWT_TRACE(("SendAwtMsg - wait timeout...\n"));
}
AWT_TRACE(("SendAwtMsg - Finished wait loop\n"));
#else
::WaitForSingleObject(pMsg->hEvent, INFINITE);
#endif
MonitorEnter();
nResult = pMsg->nResult;
PutAwtMsgPool(pMsg);
}
return nResult;
}
BOOL CAwtApp::PreTranslateMessage(MSG* pMsg)
{
#ifdef ENABLE_CALLINGWINDOWS
CALLINGWINDOWS(pMsg->hwnd);
CallingWindows[0].lastMsg = *pMsg;
#endif
if (pMsg->hwnd == NULL && pMsg->message >= AWT_CLASS_FIRST && pMsg->message <= AWT_CLASS_LAST) {
AwtMsg *pAwtMsg = (AwtMsg*)pMsg->lParam;
long nResult;
nResult = HandleMsg(pMsg->message, pAwtMsg->nMsg, pAwtMsg->p1, pAwtMsg->p2, pAwtMsg->p3,
pAwtMsg->p4, pAwtMsg->p5, pAwtMsg->p6, pAwtMsg->p7, pAwtMsg->p8);
if (pAwtMsg->bSignalEvent) {
pAwtMsg->nResult = nResult;
VERIFY(::SetEvent((HANDLE)pAwtMsg->hEvent));
} else {
PutAwtMsgPool(pAwtMsg);
}
return TRUE;
}
CALLINGWINDOWS(pMsg->hwnd);
if (pMsg->message == WM_AWT_DISPATCH_EVENT &&
pMsg->wParam == FILTER_SIGNATURE) {
// Dispatch the message posted by DispatchInputEvent().
MSG* pEventMsg = (MSG*)(pMsg->lParam);
::TranslateMessage(pEventMsg);
::DispatchMessage(pEventMsg);
free(pEventMsg); // allocated in DispatchInputEvent()
return TRUE;
}
if (::HandleInputEvent(pMsg) == TRUE) {
return TRUE;
}
return CWinApp::PreTranslateMessage(pMsg);
}
long CAwtApp::HandleMsg(UINT nClass, UINT nMsg, long p1, long p2, long p3,
long p4, long p5, long p6, long p7, long p8)
{
long nResult;
switch (nClass) {
case AWT_SHOWWND:
CALLINGWINDOWS((HWND)p1);
::ShowWindow((HWND)p1, (BOOL)p2);
if ((BOOL)p3) {
:: BringWindowToTop((HWND)p1);
}
break;
case AWT_CLEANUP:
cleanup();
break;
case AWT_COMP:
nResult = AwtComp::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_FRAME:
nResult = MainFrame::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_GRAPHICS:
nResult = AwtGraphics::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_MENU:
nResult = AwtMenu::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_WINDOW:
nResult = AwtWindow::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_BUTTON:
nResult = AwtButton::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_LIST:
nResult = AwtList::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_OPTIONMENU:
nResult = AwtOptionMenu::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_SCROLLBAR:
nResult = AwtScrollbar::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_EDIT:
nResult = AwtEdit::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_LABEL:
nResult = AwtLabel::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_FILEDIALOG:
nResult = AwtFileDialog::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
case AWT_FONT:
nResult = AwtFont::HandleMsg(nMsg, p1, p2, p3, p4, p5, p6, p7, p8);
break;
default:
return FALSE;
}
return nResult;
}
// Callback Thread
void CAwtApp::DoCallback(void *pJavaObject, char *pzMethodName, char *pzMethodSig,
int nParamCount, long p1, long p2, long p3, long p4, long p5, long p6, long p7)
{
CallbackThreadMsg *pMsg;
::WaitForSingleObject(m_hCallbackThreadQMutex, INFINITE);
if (pzMethodName != 0 && !m_pCallbackThreadQ->IsEmpty()) {
if (strcmp(pzMethodName, "handleRepaint") == 0) {
pMsg = (CallbackThreadMsg *) m_pCallbackThreadQ->GetTail();
if (pMsg && pMsg->m_pJavaObject == pJavaObject
&& strcmp(pMsg->m_pzMethodName, pzMethodName) == 0) {
if (p1 < pMsg->p1) {
pMsg->p3 += pMsg->p1 - p1;
pMsg->p1 = p1;
}
if (p2 < pMsg->p2) {
pMsg->p4 += pMsg->p2 - p2;
pMsg->p2 = p2;
}
if (p1 + p3 > pMsg->p1 + pMsg->p3) {
pMsg->p3 = p1 + p3 - pMsg->p1;
}
if (p2 + p4 > pMsg->p2 + pMsg->p4) {
pMsg->p4 = p2 + p4 - pMsg->p2;
}
::ReleaseMutex(m_hCallbackThreadQMutex);
AWT_TRACE(("collapsed repaint\n"));
return;
}
} else if (strcmp(pzMethodName, "handleMouseMoved") == 0
|| strcmp(pzMethodName, "handleMouseDrag") == 0) {
pMsg = (CallbackThreadMsg *) m_pCallbackThreadQ->GetTail();
if (pMsg && pMsg->m_pJavaObject == pJavaObject
&& strcmp(pMsg->m_pzMethodName, pzMethodName) == 0) {
if (pMsg->p5 == p5) {
pMsg->p1 = p1;
pMsg->p2 = p2;
pMsg->p3 = p3;
pMsg->p4 = p4;
::ReleaseMutex(m_hCallbackThreadQMutex);
AWT_TRACE(("collapsed mouse event\n"));
return;
}
}
}
}
// need to eventually use a pool
pMsg = new CallbackThreadMsg();
pMsg->m_pJavaObject = pJavaObject;
pMsg->m_pzMethodName = pzMethodName;
pMsg->m_pzMethodSig = pzMethodSig;
pMsg->m_nParamCount = nParamCount;
pMsg->p1 = p1;
pMsg->p2 = p2;
pMsg->p3 = p3;
pMsg->p4 = p4;
pMsg->p5 = p5;
pMsg->p6 = p6;
pMsg->p7 = p7;
m_pCallbackThreadQ->AddTail(pMsg);
::SetEvent((HANDLE)m_hCallbackThreadEvent);
::ReleaseMutex(m_hCallbackThreadQMutex);
}
void CAwtApp::DoCallback2(ExecEnv *ee, void *pJavaObject, char *pzMethodName, char *pzMethodSig,
int nParamCount, long p1, long p2, long p3, long p4, long p5, long p6, long p7)
{
Hjava_lang_Object *pPeer = (Hjava_lang_Object*)
(unhand((Hjava_awt_Component *)pJavaObject)->peer);
if (pPeer == NULL) { // this might be true during create of some awt objects
return;
}
switch (nParamCount) { // is there a better way?
case 0:
execute_java_dynamic_method(ee, pPeer, pzMethodName, pzMethodSig);
break;
case 1:
execute_java_dynamic_method(ee, pPeer, pzMethodName, pzMethodSig,
p1);
break;
case 2:
execute_java_dynamic_method(ee, pPeer, pzMethodName, pzMethodSig,
p1, p2);
break;
case 3:
execute_java_dynamic_method(ee, pPeer, pzMethodName, pzMethodSig,
p1, p2, p3);
break;
case 4:
execute_java_dynamic_method(ee, pPeer, pzMethodName, pzMethodSig,
p1, p2, p3, p4);
break;
case 5:
execute_java_dynamic_method(ee, pPeer, pzMethodName, pzMethodSig,
p1, p2, p3, p4, p5);
break;
case 6:
execute_java_dynamic_method(ee, pPeer, pzMethodName, pzMethodSig,
p1, p2, p3, p4, p5, p6);
break;
case 7:
execute_java_dynamic_method(ee, pPeer, pzMethodName, pzMethodSig,
p1, p2, p3, p4, p5, p6, p7);
break;
default:
VERIFY(FALSE);
}
GdiFlush();
if (exceptionOccurred(EE())) {
exceptionDescribe(EE());
exceptionClear(EE());
}
}
void CAwtApp::cleanupListAdd(CObject *pObj)
{
m_cleanupList->SetAt(pObj, pObj);
}
void CAwtApp::cleanupListRemove(CObject *pObj)
{
if (m_cleanupList != NULL) {
m_cleanupList->RemoveKey(pObj);
}
}
void CAwtApp::cleanup()
{
AwtComp::Cleanup();
AwtFont::Cleanup();
AwtGraphics::Cleanup();
POSITION pos = m_cleanupList->GetStartPosition();
while (pos != NULL) {
CObject *pObj;
void *key, *p;
m_cleanupList->GetNextAssoc(pos, key, p);
pObj = (CObject*)p;
if (pObj->IsKindOf(RUNTIME_CLASS(AwtMenu))) {
delete ((AwtMenu*)pObj);
} else if (pObj->IsKindOf(RUNTIME_CLASS(AwtWindow))) {
delete ((AwtWindow*)pObj);
} else {
delete pObj;
}
}
m_cleanupList->RemoveAll();
delete m_cleanupList;
m_cleanupList = NULL;
}
int CAwtApp::ExitInstance()
{
// Delete any outstanding resources.
if (m_cleanupList != NULL) {
SendAwtMsg(AWT_CLEANUP, 0);
}
// free MFC memory leaks
if (m_pszExeName != NULL) {
free((void*)m_pszExeName);
m_pszExeName = NULL;
}
if (m_pszAppName != NULL) {
free((void*)m_pszAppName);
m_pszAppName = NULL;
}
if (m_pszHelpFilePath != NULL) {
free((void*)m_pszHelpFilePath);
m_pszHelpFilePath = NULL;
}
if (m_pszProfileName != NULL) {
free((void*)m_pszProfileName);
m_pszProfileName = NULL;
}
delete m_pMainWnd;
return CWinApp::ExitInstance();
}