gecko-dev/cmd/winfe/javaio.cpp

442 строки
9.8 KiB
C++
Executable File

/* -*- 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( j<len ) {
if( pbuf[i] == '\n' ) {
buffer[j++] = '\r';
}
buffer[j++] = pbuf[i++];
}
buffer[j] = '\0';
size -= i;
pbuf += i;
// Truncate the edit box text if it is reaching its limit
len = m_pEdit->GetWindowTextLength();
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 */