/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "stdafx.h" #ifdef JAVA_WIN32 // javaio.cpp : implementation file // #include "mainfrm.h" #include "javaio.h" #include "io.h" #include "prthread.h" #include "prmon.h" #include "prfile.h" #include "prdump.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif // Maximun number of characters in the edit box before truncation occurs... #define MAX_JAVA_OUTPUT_SIZE 10000 #define JAVA_IO_THREAD_STACK_SIZE 16768 ///////////////////////////////////////////////////////////////////////////// // CNSPRStream PRIOMethods CNSPRStream::IOMethods = { CNSPRStream::InitMethod, CNSPRStream::CloseMethod, CNSPRStream::ReadMethod, CNSPRStream::WriteMethod }; CNSPRStream::CNSPRStream(void) { } void CNSPRStream::MapFileDescriptor( PROSFD fd ) { PR_MapFileHandle( fd, (CNSPRStream *)this, &IOMethods ); } int32 CNSPRStream::InitMethod(PRFileDesc * fd) { int32 ret = -1; if( fd->instance ) { ret = ((CNSPRStream *)(fd->instance))->Init(fd); } return( ret ); } int32 CNSPRStream::CloseMethod(PRFileDesc * fd) { int32 ret = -1; if( fd->instance ) { ret = ((CNSPRStream *)(fd->instance))->Close(fd); } return( ret ); } int32 CNSPRStream::ReadMethod (PRFileDesc * fd, void *buf, int32 amount) { int32 ret = -1; if( fd->instance ) { ret = ((CNSPRStream *)(fd->instance))->Read(fd, buf, amount); } return( ret ); } int32 CNSPRStream::WriteMethod(PRFileDesc * fd, const void *buf, int32 amount) { int32 ret = -1; if( fd->instance ) { ret = ((CNSPRStream *)(fd->instance))->Write(fd, buf, amount); } return( ret ); } ///////////////////////////////////////////////////////////////////////////// // CJavaStdError CJavaStdError::CJavaStdError(void) { } int32 CJavaStdError::Init(PRFileDesc *fd) { return( fd->osfd ); } int32 CJavaStdError::Close(PRFileDesc *fd) { /* Never close stderr */ return( -1 ); } int32 CJavaStdError::Read(PRFileDesc *fd, void *buf, int32 amount) { /* Cannot read from stderr */ return( -1 ); } int32 CJavaStdError::Write(PRFileDesc *fd, const void *buf, int32 amount) { char buffer[1024]; int32 size; int len; size = amount; while (size) { len = size > 1023 ? 1023 : size; strncpy( buffer, (const char *)buf, len ); buffer[len] = '\0'; size -= len; // // Calling MFC's MessageBox causes a deadlock if the calling thread is NOT the // main UI thread of the navigator. In practice, this is ALWAYS the case :-( // //AfxGetApp()->GetMainWnd()->MessageBox( buffer, "Java Error" ); (void)::MessageBox(NULL, buffer, "Java Error", MB_SETFOREGROUND | MB_OK); } return(amount); } ///////////////////////////////////////////////////////////////////////////// // CJavaStdOutput #ifdef __BORLANDC__ static int64 SleepForever = 0x7fffffffffffffff; #else static int64 SleepForever = LL_MAXINT; #endif CJavaStdOutput::CJavaStdOutput(void) { m_bAutoDelete = TRUE; m_pOwnThread = 0; m_ThreadId = 0; m_pWnd = 0; m_pOutputMon = PR_NewNamedMonitor("output-monitor"); m_msgWrite = ::RegisterWindowMessage("NSPR_ConsoleWrite"); } CJavaStdOutput::~CJavaStdOutput() { if( m_pOutputMon ) { PR_DestroyMonitor( m_pOutputMon ); m_pOutputMon = NULL; } } BOOL CJavaStdOutput::PreTranslateMessage(MSG* pMsg) { BOOL bResult; if( (pMsg->hwnd == 0) && (pMsg->message == m_msgWrite) ) { m_pWnd->Display( (const char *)pMsg->lParam, (int32)pMsg->wParam ); bResult = TRUE; } else { bResult = CWinThread::PreTranslateMessage(pMsg); } return bResult; } BOOL CJavaStdOutput::InitInstance(void) { PRThreadStack *ts; BOOL bRet = FALSE; CWinThread::InitInstance(); /* Set up the thread stack information */ ts = (PRThreadStack*) calloc(1, sizeof(PRThreadStack)); if( ts ) { ts->stackSize = JAVA_IO_THREAD_STACK_SIZE; m_pOwnThread = PR_AttachThread("Java IO", 15, ts); m_pOwnThread->flags |= _PR_NO_SUSPEND; m_ThreadId = ::GetCurrentThreadId(); if( m_pWnd = new CJavaOutputWnd() ) { bRet = m_pWnd->Initialize( m_pOutputMon ); } } return(bRet); } int CJavaStdOutput::ExitInstance(void) { if( m_pWnd ) { delete m_pWnd; m_pWnd = NULL; } if( m_pOwnThread ) { PR_DetachThread( m_pOwnThread ); m_pOwnThread = NULL; } return CWinThread::ExitInstance(); } BOOL CJavaStdOutput::ToggleVisible(void) { BOOL bRet = m_pWnd->IsWindowVisible(); m_pWnd->ShowWindow( bRet ? SW_HIDE : SW_SHOW ); return( ! bRet ); } BOOL CJavaStdOutput::IsVisible(void) { return m_pWnd->IsWindowVisible(); } int32 CJavaStdOutput::Init(PRFileDesc *fd) { int32 ret = fd->osfd; if(! CreateThread(0, JAVA_IO_THREAD_STACK_SIZE, 0)) { ret = -1; } return ret; } int32 CJavaStdOutput::Close(PRFileDesc *fd) { ::PostThreadMessage( m_ThreadId, WM_QUIT, 0, 0 ); return 0; } int32 CJavaStdOutput::Read(PRFileDesc *fd, void *buf, int32 amount) { /* Cannot read from stdout */ return( -1 ); } int32 CJavaStdOutput::Write(PRFileDesc *fd, const void *buf, int32 amount) { if( PR_CurrentThread() == m_pOwnThread ) { m_pWnd->Display((const char *)buf, amount); } else { PR_EnterMonitor( m_pOutputMon ); ::PostThreadMessage( m_ThreadId, m_msgWrite, (WPARAM)amount, (LPARAM)buf ); PR_Wait( m_pOutputMon, SleepForever ); PR_ExitMonitor( m_pOutputMon); } return( amount ); } ///////////////////////////////////////////////////////////////////////////// // CJavaOutputWnd CJavaOutputWnd::CJavaOutputWnd() { m_pEdit = 0; m_pOutputMon = 0; } CJavaOutputWnd::~CJavaOutputWnd() { if( m_pEdit ) { delete m_pEdit; m_pEdit = NULL; } } BOOL CJavaOutputWnd::Initialize(PRMonitor *pMon) { BOOL bRet; RECT rect; m_pOutputMon = pMon; // Create the Frame Window bRet = CFrameWnd::Create( NULL, "Java Output", WS_OVERLAPPEDWINDOW | WS_VISIBLE ); if( bRet ) { GetClientRect( &rect ); // Create the Child Edit control used to display the text m_pEdit = new CGenericEdit(); bRet = m_pEdit->Create( WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY, rect, this, 100 ); // Initialize the font for the edit control... /// pContext = CMainFrame::GetLastActiveFrame()->GetMainContext()->GetContext(); /// if (INTL_CharSetType(pContext) == SINGLEBYTE) { m_pEdit->SetFont(CFont::FromHandle((HFONT)GetStockObject(ANSI_FIXED_FONT))); /// } else { // For multibyte, we can not use ANSI font /// m_pEdit->SetFont(CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FIXED_FONT))); /// } } return(bRet); } void CJavaOutputWnd::Display( const char *buf, int32 amount ) { char buffer[90]; const char *pbuf; int32 size; int i, j, len; PR_EnterMonitor( m_pOutputMon ); size = amount; pbuf = (const char *)buf; while (size) { len = size > 79 ? 79 : size; i = j = 0; // Translate \n to \r\n for the edit box while( jGetWindowTextLength(); if( len > MAX_JAVA_OUTPUT_SIZE ) { len -= (MAX_JAVA_OUTPUT_SIZE/2); i = j = 0; while ( len > 0) { int k = m_pEdit->LineLength(j++); len -= k; i += k; } m_pEdit->SetSel( 0, i, TRUE ); m_pEdit->ReplaceSel( "" ); } // Append the new text into the edit box m_pEdit->SetSel( m_pEdit->GetWindowTextLength(), -1, TRUE ); m_pEdit->ReplaceSel( buffer ); } PR_Notify( m_pOutputMon ); PR_ExitMonitor( m_pOutputMon ); } afx_msg void CJavaOutputWnd::OnSize(UINT type, int cx, int cy) { if( m_pEdit ) { m_pEdit->MoveWindow(0, 0, cx, cy, TRUE); } } afx_msg void CJavaOutputWnd::OnSysCommand(UINT nId, LPARAM lParam) { if( nId == SC_CLOSE ) { ShowWindow(SW_HIDE); } else { CFrameWnd::OnSysCommand(nId, lParam); } } afx_msg void CJavaOutputWnd::OnKeyUp(UINT nChar, UINT nRep, UINT nFlags) { #ifdef DEBUG if( nChar == VK_F1 ) { MessageBeep(0); PR_DumpThreads(); PR_DumpMonitors(); } #endif } #ifndef _AFXDLL #undef new #endif IMPLEMENT_DYNCREATE(CJavaOutputWnd, CFrameWnd) #ifndef _AFXDLL #define new DEBUG_NEW #endif BEGIN_MESSAGE_MAP(CJavaOutputWnd, CFrameWnd) ON_WM_SIZE ( ) ON_WM_SYSCOMMAND ( ) ON_WM_KEYUP ( ) END_MESSAGE_MAP() #endif /* JAVA_WIN32 */